diff include/dcc_proto.h @ 0:c7f6b056b673

First import of vendor version
author Peter Gervai <grin@grin.hu>
date Tue, 10 Mar 2009 13:49:58 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/dcc_proto.h	Tue Mar 10 13:49:58 2009 +0100
@@ -0,0 +1,612 @@
+/* Distributed Checksum Clearinghouse
+ *
+ * client-server and server-server protocols
+ *
+ * Copyright (c) 2008 by Rhyolite Software, LLC
+ *
+ * This agreement is not applicable to any entity which sells anti-spam
+ * solutions to others or provides an anti-spam solution as part of a
+ * security solution sold to other entities, or to a private network
+ * which employs the DCC or uses data provided by operation of the DCC
+ * but does not provide corresponding data to other users.
+ *
+ * Permission to use, copy, modify, and distribute this software without
+ * changes for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear in all
+ * copies and any distributed versions or copies are either unchanged
+ * or not called anything similar to "DCC" or "Distributed Checksum
+ * Clearinghouse".
+ *
+ * Parties not eligible to receive a license under this agreement can
+ * obtain a commercial license to use DCC by contacting Rhyolite Software
+ * at sales@rhyolite.com.
+ *
+ * A commercial license would be for Distributed Checksum and Reputation
+ * Clearinghouse software.  That software includes additional features.  This
+ * free license for Distributed ChecksumClearinghouse Software does not in any
+ * way grant permision to use Distributed Checksum and Reputation Clearinghouse
+ * software
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Rhyolite Software DCC 1.3.103-1.137 $Revision$
+ */
+
+#ifndef DCC_PROTO_H
+#define DCC_PROTO_H
+
+#define DCC_PKT_VERSION4    4
+#define	DCC_PKT_VERSION5    5
+#define	DCC_PKT_VERSION6    6
+#define	DCC_PKT_VERSION7    7
+#define	DCC_PKT_VERSION8    8
+#define	DCC_PKT_VERSION	    9		/* current */
+#define	DCC_PKT_VERSION_MIN	DCC_PKT_VERSION4    /* recognized */
+#define	DCC_PKT_VERSION_MAX	DCC_PKT_VERSION
+#define DCC_PKT_VERSION_MIN_VALID   DCC_PKT_VERSION_MIN	/* sanity check */
+#define	DCC_PKT_VERSION_MAX_VALID   0x7f
+
+
+#define DCC_SRVR_PORT	6277		/* default DCC server port # */
+#define DCC_GREY_PORT	6276		/* grey listing server port */
+
+
+/* types of checksums */
+typedef enum {
+    DCC_CK_INVALID	    =0,		/* deleted from database when seen */
+    DCC_CK_IP		    =1,		/* MD5 of binary source IPv6 address */
+    DCC_CK_ENV_FROM	    =2,		/*  "  "  envelope Mail From value */
+    DCC_CK_FROM		    =3,		/*  "  "  header From: line */
+    DCC_CK_SUB		    =4,		/*  "  "  substitute header line */
+    DCC_CK_MESSAGE_ID	    =5,		/*  "  "  header Message-ID: line */
+    DCC_CK_RECEIVED	    =6,		/*  "  "  last header Received: line */
+    DCC_CK_BODY		    =7,		/*  "  "  body */
+    DCC_CK_FUZ1		    =8,		/*  "  "  filtered body */
+    DCC_CK_FUZ2		    =9,		/*  "  "     "      "   */
+    DCC_CK_G_MSG_R_TOTAL    =10,
+#    define DCC_CK_GREY_MSG   DCC_CK_G_MSG_R_TOTAL
+#    define DCC_CK_REP_TOTAL  DCC_CK_G_MSG_R_TOTAL
+    DCC_CK_G_TRIPLE_R_BULK  =11,
+#    define DCC_CK_GREY3      DCC_CK_G_TRIPLE_R_BULK
+#    define DCC_CK_REP_BULK   DCC_CK_G_TRIPLE_R_BULK
+    DCC_CK_SRVR_ID	    =12,	/* hostname for server-ID check */
+    DCC_CK_ENV_TO	    =13		/* MD5 of envelope Rcpt To value */
+#    define DCC_CK_FLOD_PATH  DCC_CK_ENV_TO /* flooding path in server-IDs */
+} DCC_CK_TYPES;
+typedef u_char DCC_CK_TYPE_B;		/* big enough */
+#define DCC_CK_TYPE_FIRST   DCC_CK_IP
+#define DCC_CK_TYPE_LAST    DCC_CK_ENV_TO
+#define DCC_NUM_CKS	    DCC_CK_TYPE_LAST    /* # of valid types */
+
+/* DCC_DIM_CKS dimensions arrays of checksum types including DCC_CK_INVALID
+ * Beware that DCC_DIM_CKS is used in the database header. */
+#define DCC_DIM_CKS	    (DCC_CK_TYPE_LAST+1)
+
+/* record of path taken by a report */
+#define DCC_NUM_FLOD_PATH ((int)(sizeof(DCC_SUM)/sizeof(DCC_SRVR_ID)))
+typedef struct {
+    u_char	hi, lo;
+} DCC_FLOD_PATH_ID;
+/* DCC_MAX_FLOD_PATH assumes that among the maximum 14 possible slots for
+ * checksums in a flooded report (dimension of cks in a DB_RCD or DCC_DIM_CKS),
+ *	DCC_CK_INVALID is never used
+ *	DCC_CK_SRVR_ID is never used when any real checksums are present,
+ * is so there is always room for 2 extra DCC_CK_FLOD_PATH entries besides
+ * the natural DCC_CK_FLOD_PATH entry. */
+#define DCC_MAX_FLOD_PATH_CKSUMS 3
+/* This must not be too large lest reports become larger than DCC_DIM_CKS */
+#define DCC_MAX_FLOD_PATH (DCC_NUM_FLOD_PATH*DCC_MAX_FLOD_PATH_CKSUMS)
+
+
+/* checksums in client-server protocol */
+#define	DCC_QUERY_MAX DCC_DIM_CKS	/* even to prevent structure padding */
+
+/* Ensure that arrays of DCC_CKs contain an even number so that structures
+ * containing them will have no extra structure packing */
+#define DCC_COMP_DIM_CKS    ((((DCC_NUM_CKS+1)+1)/2)*2)	/* == DCC_DIM_CKS */
+
+/* keep some checksums in the database longer than others */
+#define DCC_CK_LONG_TERM(t) ((t) >= DCC_CK_FUZ1				\
+			     && (t) <= DCC_CK_G_TRIPLE_R_BULK)
+
+#define DCC_CK_IS_BODY(t) ((t) >= DCC_CK_BODY && (t) <= DCC_CK_FUZ2)
+
+/* MD5 of greylist msg+sender+target */
+#define DCC_CK_IS_GREY_MSG(g,t) ((g) && (t) == DCC_CK_G_MSG_R_TOTAL)
+/* MD5 of greylisted triple */
+#define DCC_CK_IS_GREY_TRIPLE(g,t) ((g) && (t) == DCC_CK_G_TRIPLE_R_BULK)
+#define DCC_CK_IS_GREY(g,t) (DCC_CK_IS_GREY_MSG(g,t)			\
+			     || DCC_CK_IS_GREY_TRIPLE(g,t))
+
+/* total messages sent by an IP address */
+#define DCC_CK_IS_REP_TOTAL_CMN(g,t) (!(g) && (t) == DCC_CK_G_MSG_R_TOTAL)
+/* bulk messages sent by an IP address */
+#define DCC_CK_IS_REP_BULK_CMN(g,t) (!(g) && (t) == DCC_CK_G_TRIPLE_R_BULK)
+#define DCC_CK_IS_REP_CMN(g,t) (DCC_CK_IS_REP_TOTAL_CMN(g,t)		\
+				|| DCC_CK_IS_REP_BULK_CMN(g,t))
+#define DCC_CK_IS_REP_TOTAL_OP(g,t) 0
+#define DCC_CK_IS_REP_BULK_OP(g,t)  0
+#define DCC_CK_IS_REP_OP(g,t)	    0
+
+
+
+typedef enum {
+    DCC_OP_INVALID	=0,
+    DCC_OP_NOP		=1,		/* see if the server is alive */
+    DCC_OP_REPORT	=2,		/* old client reporting and querying */
+    DCC_OP_QUERY	=3,		/* client querying */
+    DCC_OP_ANSWER	=4,		/* server responding */
+    DCC_OP_ADMN		=5,		/* control the server */
+    DCC_OP_OK		=6,		/* administrative operation ok */
+    DCC_OP_ERROR	=7,		/* server failing or complaining */
+    DCC_OP_DELETE	=8,		/* delete some checksums */
+    DCC_OP_GREY_REPORT	=9,		/* greylist report */
+    DCC_OP_GREY_QUERY	=10,		/*   "   "  query */
+    DCC_OP_GREY_SPAM	=11,		/* forget greylisted spammer */
+    DCC_OP_GREY_WHITE	=12		/* whitelisted greylist triple */
+} DCC_OPS;
+
+typedef u_int32_t DCC_CLNT_ID;
+#define DCC_ID_INVALID	    0
+#define DCC_ID_ANON	    1		/* anonymous (non-paying) client */
+#define DCC_ID_WHITE	    2		/* whitelisted */
+#define DCC_ID_COMP	    3		/* compressed */
+#define	DCC_ID_SRVR_SIMPLE  4		/* simple server */
+#define DCC_ID_SRVR_REP_OK  5		/* ok to use reputations */
+#define	DCC_ID_SRVR_IGNORE  6		/* ignore its flooded reports */
+#define	DCC_ID_SRVR_ROGUE   7		/* crazy server */
+#define DCC_ID_SRVR_TYPE(id) ((id) == DCC_ID_SRVR_SIMPLE		\
+			      || (id) == DCC_ID_SRVR_REP_OK		\
+			      || (id) == DCC_ID_SRVR_IGNORE		\
+			      || (id) == DCC_ID_SRVR_ROGUE)
+#define DCC_SRVR_ID_MIN	    100		/* below reserved for special uses */
+#define	DCC_SRVR_ID_MAX	    32767	/* below are servers--must be 2**n-1 */
+#define DCC_CLNT_ID_MIN	    (DCC_SRVR_ID_MAX+1)
+#define DCC_CLNT_ID_MAX	    16777215
+typedef u_int16_t DCC_SRVR_ID;
+#define	DCC_SRVR_ID_AUTH (DCC_SRVR_ID_MAX+1)	/* client was authenticated */
+
+/* client's identification of its transaction */
+typedef u_int32_t DCC_OP_NUM;
+typedef struct {
+    DCC_OP_NUM	h;			/* client host ID, e.g. IP address */
+    DCC_OP_NUM	p;			/* process ID, serial #, timestamp */
+    DCC_OP_NUM	r;			/* report ID */
+    DCC_OP_NUM	t;			/* client (re)transmission # */
+} DCC_OP_NUMS;
+
+/* The inter-DCC server flooding algorithm depends on unique-per-server
+ * timestamps to detect duplicates.  That imposes a requirement on
+ * timestamps that they have resolution enough to separate reports
+ * from clients arriving at any single server.
+ * The timestamps are 48 bits consisting of 17 bits of 8's of microseconds
+ * and 31 bits of seconds.  That's sufficient for the UNIX epoch.
+ * If the DCC is still around in the 2030's (and in the unlikely case that
+ * 8 microseconds are still fine enough), we can make the 31 bits be
+ * an offset in a bigger window.
+ */
+#define DCC_TS_US_RSHIFT    3
+#define DCC_TS_US_MULT	    (1<<DCC_TS_US_RSHIFT)
+#define DCC_TS_SECS_LSHIFT  17
+#define DCC_TS_US_MASK	    ((1<<DCC_TS_SECS_LSHIFT) - 1)
+typedef struct {
+    u_char  b[6];
+} DCC_TS;
+
+/* The start of any DCC packet.
+ *	The length and version are early, since they are the only fields
+ *	constrained in future versions. */
+typedef struct {
+    u_int16_t	len;			/* total DCC packet length */
+    u_char	pkt_vers;		/* packet protocol version */
+    u_char	op;			/* one of DCC_OPS */
+    /* Identify the transaction.
+     *	    Each client can have many hosts, each host can be multi-homed,
+     *	    and each host can be running many processes talking to the
+     *	    server.  Each packet needs to be uniquely numbered, so that the
+     *	    server can recognize as interchangable all of the (re)transmissions
+     *	    of a single report (rid) from a client process (pid) on a single
+     *	    host (hid), and the client can know which transmission (tid)
+     *	    produced a given server response to maintain the client's RTT
+     *	    value for the server. */
+    DCC_CLNT_ID	sender;			/* client-ID or server-ID */
+    DCC_OP_NUMS	op_nums;		/* op_num.t must be last */
+} DCC_HDR;
+
+typedef u_char DCC_SIGNATURE[16];
+
+typedef struct {
+    DCC_HDR	hdr;
+    DCC_SIGNATURE signature;
+} DCC_NOP;
+
+
+/* DCC_OP_ADMN administrative requests from localhost
+ *	Most of these can be changed, because the administrative tools
+ *	should match the daemon. */
+typedef enum {
+    DCC_AOP_OK		=-1,		/* never really sent */
+    DCC_AOP_STOP	= 1,		/* stop gracefully */
+    DCC_AOP_DB_UNLOAD	= 2,		/* flush cache */
+    DCC_AOP_FLOD	= 3,		/* start or stop flooding */
+    DCC_AOP_DB_CLEAN	= 4,		/* start cleaning */
+    DCC_AOP_DB_NEW	= 5,		/* finish switch to new database */
+    DCC_AOP_STATS	= 6,		/* return counters--val=buffer size */
+    DCC_AOP_STATS_CLEAR	= 7,		/* return and zero counters */
+    DCC_AOP_TRACE_ON	= 8,
+    DCC_AOP_TRACE_OFF	= 9,
+    DCC_AOP_unused1	= 10,		/*	was dcc1-1-36 clients command */
+    DCC_AOP_CLIENTS	= 11,		/* some client IP addresses */
+    DCC_AOP_CLIENTS_ID	= 12,		/* some client IDs */
+    DCC_AOP_ANON_DELAY	= 13,		/* anonymous delay parameters */
+    DCC_AOP_CLOCK_CHECK	= 14
+} DCC_AOPS;
+
+/* for DCC_AOP_FLOD */
+typedef enum {
+    DCC_AOP_FLOD_CHECK=0,
+    DCC_AOP_FLOD_SHUTDOWN,
+    DCC_AOP_FLOD_HALT,
+    DCC_AOP_FLOD_RESUME,
+    DCC_AOP_FLOD_REWIND,
+    DCC_AOP_FLOD_LIST,
+    DCC_AOP_FLOD_STATS,
+    DCC_AOP_FLOD_STATS_CLEAR,
+#    define DCC_AOP_FLOD_STATS_ID   " server-ID %u "
+    DCC_AOP_FLOD_FFWD_IN,
+    DCC_AOP_FLOD_FFWD_OUT
+} DCC_AOP_FLODS;
+
+typedef struct {			/* with operation DCC_OP_ADMN */
+    DCC_HDR	hdr;
+    int32_t	date;			/* seconds since epoch on caller */
+    u_int32_t	val1;			/* request type, buffer size, etc. */
+    u_char	aop;			/* one of DCC_AOPS */
+    u_char	val2;
+    u_char	val3;
+    u_char	val4;
+#    define	 MAX_DCC_ADMN_REQ_VAL5	64
+    u_char	val5[MAX_DCC_ADMN_REQ_VAL5];
+    DCC_SIGNATURE signature;
+} DCC_ADMN_REQ;
+#define DCC_ADMN_REQ_MIN_SIZE (ISZ(DCC_ADMN_REQ) - MAX_DCC_ADMN_REQ_VAL5)
+
+
+typedef u_char DCC_AOP_CLIENTS_CIDR[17];    /* IPv6 netmask and length */
+
+/* val2 for DCC_AOP_CLIENTS or DCC_AOP_CLIENTS_ID */
+#define DCC_AOP_CLIENTS_AVG		0x01	/* want averages */
+#define DCC_AOP_CLIENTS_VERS		0x02	/* want protocol version */
+#define DCC_AOP_CLIENTS_ANON		0x04	/* only anonymous clients */
+#define DCC_AOP_CLIENTS_NON_ANON	0x08	/* non-anonymous only */
+
+#define DCC_AOP_CLIENTS_MAX_OFFSET	((1<<24)-1)
+
+/* scale client's response buffer size in part of val1 by this */
+#define DCC_ADMIN_RESP_CLIENTS_SHIFT	5
+/* limit threshold in part of val1 */
+#define DCC_ADMIN_RESP_CLIENTS_MAX_THOLD    ((1<<16)-1)
+
+/* noisy response to DCC_AOP_CLIENTS or DCC_AOP_CLIENTS_ID */
+#define	DCC_ADMN_RESP_CLIENTS_BL	0x01	/* this client blacklisted */
+#define	DCC_ADMN_RESP_CLIENTS_IPV6	0x02	/* address is IPv6 */
+#define	DCC_ADMN_RESP_CLIENTS_SKIP	0x04	/* last_used=clients skipped */
+#define	DCC_ADMN_RESP_CLIENTS_ID1	0x08	/* suppressed ID=DCC_ID_ANON */
+#define DCC_ADMN_RESP_CLIENTS_VERS	0x10	/* protocol version # present */
+#define DCC_ADMN_RESP_CLIENTS_LAST	0x20
+#define DCC_ADMN_RESP_CLIENTS_BAD	0x40	/* naughty client */
+
+/* worst case bytes used to describe a client */
+#define DCC_ADMN_RESP_CLIENTS_MAX_SIZE	(1+1+4*4+16)
+
+#define DCC_ADMIN_RESP_MAX_CLIENTS	(10*1000)
+
+
+#ifdef DCC_PKT_VERSION6
+typedef struct {
+    u_char	clnt_id[4];
+    u_char	last_used[4];
+    u_char	requests[3];
+    u_char	nops[2];
+    u_char	flags;
+    union {
+	u_char	ipv6[16];
+	u_char	ipv4[4];
+    } addr;
+} DCC_ADMN_RESP_CLIENTSv6;
+#endif /* DCC_PKT_VERSION6 */
+
+typedef struct {
+    u_char	inflate[4];
+    u_char	delay[2];
+#    define	 DCC_ANON_DELAY_MAX	DCC_MAX_RTT
+#    define	 DCC_ANON_DELAY_FOREVER	((u_int16_t)-1)
+#    define	 DCC_NO_ANON_DELAY	((u_int16_t)-2)
+} DCC_ADMN_RESP_ANON_DELAY;
+typedef union {
+    char	string[80*22];
+    u_char	clients[1];
+#ifdef DCC_PKT_VERSION6
+    DCC_ADMN_RESP_CLIENTSv6 clientsV6[1];
+#endif
+    DCC_ADMN_RESP_ANON_DELAY anon_delay;
+} DCC_ADMN_RESP_VAL;
+typedef struct {
+    DCC_HDR	hdr;
+    DCC_ADMN_RESP_VAL val;
+    DCC_SIGNATURE signature;
+} DCC_ADMN_RESP;
+
+
+#define DCC_TRACE_ADMN_BIT  0x0001	/* administrative requests */
+#define DCC_TRACE_ANON_BIT  0x0002	/* anonymous client errors */
+#define DCC_TRACE_CLNT_BIT  0x0004	/* authenticated client errors */
+#define DCC_TRACE_RLIM_BIT  0x0008	/* rate limited messages */
+#define DCC_TRACE_QUERY_BIT 0x0010	/* all queries and reports */
+#define DCC_TRACE_RIDC_BIT  0x0020	/* RID cache messages */
+#define DCC_TRACE_FLOD_BIT  0x0040	/* general inter-server flooding */
+#define DCC_TRACE_FLOD2_BIT 0x0080	/* individual flooded reports */
+#define DCC_TRACE_IDS_BIT   0x0100	/* monitor client- and server-IDs */
+#define DCC_TRACE_BL_BIT    0x0200	/* blacklisted clients */
+#define DCC_TRACE_DB_BIT    0x0400	/* odd database events */
+#define DCC_TRACE_WLIST_BIT 0x0800	/* whitelisted checksums */
+#define DCC_TRACE_BITS  (DCC_TRACE_ADMN_BIT | DCC_TRACE_ANON_BIT	\
+			 | DCC_TRACE_CLNT_BIT | DCC_TRACE_RLIM_BIT	\
+			 | DCC_TRACE_QUERY_BIT | DCC_TRACE_RIDC_BIT	\
+			 | DCC_TRACE_FLOD_BIT | DCC_TRACE_FLOD2_BIT	\
+			 | DCC_TRACE_IDS_BIT | DCC_TRACE_BL_BIT		\
+			 | DCC_TRACE_DB_BIT | DCC_TRACE_WLIST_BIT)
+#define DCC_TRACE_ON_DEF_BITS (DCC_TRACE_ANON_BIT | DCC_TRACE_CLNT_BIT)
+#define DCC_TRACE_OFF_DEF_BITS (DCC_TRACE_BITS				\
+				& ~(DCC_TRACE_ANON_BIT | DCC_TRACE_CLNT_BIT))
+
+
+#define DCC_BRAND_MAXLEN 64
+typedef char DCC_BRAND[DCC_BRAND_MAXLEN];
+
+/* administrative or NOP ok */
+typedef struct {
+    DCC_HDR	hdr;
+    u_char	max_pkt_vers;		/* server can handle this version */
+    u_char	unused;
+    u_int16_t	qdelay_ms;
+    DCC_BRAND	brand;			/* identity or brandname of sender */
+    DCC_SIGNATURE signature;
+} DCC_OK;
+
+
+typedef u_int32_t DCC_TGTS;		/* database is limited to 24 bits */
+#define	DCC_TGTS_TOO_MANY   0x00fffff0	/* >= 16777200 targets */
+#define	DCC_TGTS_OK	    0x00fffff1	/* certified not spam */
+#define	DCC_TGTS_OK2	    0x00fffff2	/* half certified not spam */
+#define DCC_TGTS_GREY_WHITE DCC_TGTS_OK2    /* whitelisted for greylisting */
+#define	DCC_TGTS_DEL	    0x00fffff3	/* a deleted checksum */
+#define DCC_TGTS_REP_ADJ    0x00fffff4	/* scale a reputation */
+#define DCC_TGTS_OK_MX	    0x00fffff5	/* partly whitelist MX secondary */
+#define DCC_TGTS_OK_MXDCC   0x00fffff6	/*	MX secondary with DCC client */
+#define DCC_TGTS_SUBMIT_CLIENT 0x00fffff7   /* SMTP submission client */
+#define DCC_TGTS_MAX_DB	    DCC_TGTS_REP_ADJ
+#define DCC_TGTS_INVALID    0x01000000
+#define DCC_TGTS_SPAM	    DCC_TGTS_INVALID
+#define DCC_TGTS_REP_SPAM   0x02000000	/* reputation hit */
+#define DCC_TGTS_MASK	    0x00ffffff
+
+#define DCC_TGTS_RPT_MAX    2000
+#define DCC_TGTS_FLOD_RPT_MAX (DCC_TGTS_RPT_MAX*1000)
+#define BULK_THRESHOLD	    10
+#define	REFLOOD_THRESHOLD   300
+#define DCC_TGTS_REP_TOTAL_THOLD (BULK_THRESHOLD*2)
+#define DCC_TGTS_REP_TOTAL_EXPIRE BULK_THRESHOLD
+
+/* checksums kept by most servers */
+#define DCC_CK_IS_GREY_BODY(g,t) ((g) ? ((t)==DCC_CK_BODY) : DCC_CK_IS_BODY(t))
+#define DB_GLOBAL_NOKEEP(g,t) (!DCC_CK_IS_GREY_BODY(g,t)		\
+			       && (t) != DCC_CK_SRVR_ID			\
+			       && ((t) != DCC_CK_G_MSG_R_TOTAL || !(g))	\
+			       && ((t) != DCC_CK_G_TRIPLE_R_BULK || !(g)))
+
+/* checksums subject to thresholds */
+#define DCC_CK_THOLD_OK(t)  ((t) > DCC_CK_INVALID			\
+			     && (t) <= DCC_CK_G_TRIPLE_R_BULK)
+
+#define IS_ALL_CKSUM(t)	(DCC_CK_THOLD_OK(t) && !DCC_CK_IS_REP_CMN(0, t))
+#define IS_CMN_CKSUM(t)	DCC_CK_IS_BODY(t)
+
+
+/* a reported checksum from a client */
+typedef u_char DCC_SUM[16];		/* for now all have 16 bytes */
+typedef struct {
+    DCC_CK_TYPE_B type;
+    u_char	len;			/* total length of this checksum */
+    DCC_SUM	sum;
+} DCC_CK;
+
+/* most packets from client to server */
+typedef struct {
+    DCC_HDR	hdr;
+    DCC_TGTS	tgts;			/* # of addressees */
+    DCC_CK	cks[DCC_QUERY_MAX];	/* even to prevent structure padding */
+    DCC_SIGNATURE signature;
+} DCC_REPORT;
+
+/* most responses */
+typedef struct {
+    DCC_TGTS	c;			/* current value, with this report */
+    DCC_TGTS	p;			/* previous value, before this report */
+} DCC_ANSWER_BODY_CKS;
+typedef struct {
+    DCC_HDR	hdr;
+    DCC_ANSWER_BODY_CKS b[DCC_QUERY_MAX];
+    DCC_SIGNATURE signature;
+} DCC_ANSWER;
+
+#ifdef DCC_PKT_VERSION5
+typedef struct {
+    DCC_HDR	hdr;
+    DCC_TGTS	b[DCC_QUERY_MAX];	/* current values */
+    DCC_SIGNATURE signature;
+} DCC_ANSWERv5;
+#endif
+
+typedef struct {
+    DCC_HDR	hdr;
+    DCC_TGTS	msg;
+    DCC_TGTS	triple;
+    DCC_SIGNATURE signature;
+} DCC_GREY_ANSWER;
+
+
+/* DCC_OP_DELETE request to delete checksums */
+typedef struct {
+    DCC_HDR	hdr;
+    int32_t	date;			/* seconds since epoch on client */
+    DCC_CK	ck;
+    u_char	pad[2];
+    DCC_SIGNATURE signature;
+} DCC_DELETE;
+
+
+/* DCC_OP_GREY_SPAM restore greylist embargo */
+typedef struct {
+    DCC_HDR	hdr;
+    DCC_CK	ip;
+    DCC_CK	msg;
+    DCC_CK	triple;
+    DCC_SIGNATURE signature;
+} DCC_GREY_SPAM;
+
+
+/* error response from server to client */
+typedef struct {
+    DCC_HDR	hdr;
+#    define	 DCC_ERROR_MSG_LEN  128
+    char	msg[DCC_ERROR_MSG_LEN];
+    DCC_SIGNATURE signature;
+} DCC_ERROR;
+
+
+typedef union {
+    DCC_HDR	hdr;
+    DCC_ANSWER	ans;
+#ifdef DCC_PKT_VERSION5
+    DCC_ANSWERv5 ans5;
+#endif
+    DCC_GREY_ANSWER gans;
+    DCC_OK	ok;
+    DCC_ERROR	error;
+    DCC_ADMN_RESP resp;
+    int		w[6];
+} DCC_OP_RESP;
+
+
+
+
+/* ************** server-to-server flooding protocol ************ */
+
+/* This protocol is the sort of botch of a mess that results from assuming
+ * a considered protocol is not necessary and then extending it. */
+
+/* A flooding connection starts with the TCP client or connection originator
+ * sending an ASCII "magic" string including a version number, the connection
+ * originator's server-ID, whether SOCKS is involved, and a cryptographic
+ * hash of the fixed-length message.  In the common case, the connection
+ * orginator will send a flood of DCC reports.  If SOCKS is involved, the
+ * connection is immediately turned around. */
+#define DCC_FLOD_VERSION_STR_BASE	"DCC flod version "
+#define DCC_FLOD_VERSION7		7
+/* in the next version, add a length to DCC_FLOD_END */
+#define DCC_FLOD_VERSION7_STR		DCC_FLOD_VERSION_STR_BASE"7"
+#define DCC_FLOD_VERSION_DEF		0
+#define DCC_FLOD_VERSION_CUR		DCC_FLOD_VERSION7
+#define DCC_FLOD_VERSION_CUR_STR	DCC_FLOD_VERSION7_STR
+typedef struct {
+#    define DCC_FLOD_VERSION_STR_LEN 64
+    char	str[DCC_FLOD_VERSION_STR_LEN];
+    u_char	sender_srvr_id[sizeof(DCC_SRVR_ID)];
+    u_char	turn;			/* 1=turn connection around for SOCKS */
+    u_char	unused[3];
+} DCC_FLOD_VERSION_BODY;
+typedef struct {
+    DCC_FLOD_VERSION_BODY body;
+    char	pad[256-sizeof(DCC_FLOD_VERSION_BODY)-sizeof(DCC_SIGNATURE)];
+    DCC_SIGNATURE signature;
+} DCC_FLOD_VERSION_HDR;
+
+
+/* flood sender's position or serial number
+ *	Only the sender understands sender positions except for these
+ *	special values.  However, the special values imply that the position
+ *	must be big endian. */
+typedef u_char DCC_FLOD_POS[8];
+/* special cases sent by the receiver back to the sender */
+typedef enum {
+    DCC_FLOD_POS_END	    =0,		/* receiver closing with message */
+    DCC_FLOD_POS_END_REQ    =1,		/* receiver wants to stop */
+    DCC_FLOD_POS_NOTE	    =2,		/* receiver has a tracing message */
+    DCC_FLOD_POS_COMPLAINT  =3,		/* receiver has a problem message */
+    DCC_FLOD_POS_REWIND	    =4,		/* receiver's database emptied */
+    DCC_FLOD_POS_FFWD_IN    =5		/* receiver wants fast-forward */
+} DCC_FLOD_POS_OPS;
+#define DCC_FLOD_POS_MIN    10
+
+#define DCC_FLOD_OK_STR	    "DCC flod ok: "
+
+/* final result sent from flood receiver to flood sender
+ *	This structure always ends the TCP stream.  The length of the msg is
+ *	obtain from the number of buts to the end of the stream.  It should
+ *	have had an explicit length in the structure.  */
+typedef struct {
+    DCC_FLOD_POS pos;			/* one of DCC_FLOD_POS_* */
+#    define DCC_FLOD_MAX_RESP   200
+    char	msg[DCC_FLOD_MAX_RESP];	/* no '\0'; uses length to EOF */
+} DCC_FLOD_END;
+#define FLOD_END_OVHD ISZ(((DCC_FLOD_END*)0)->pos)
+
+/* report forwarded among servers */
+typedef struct {
+    DCC_FLOD_POS pos;
+    u_char	tgts[sizeof(DCC_TGTS)];
+    u_char	srvr_id_auth[sizeof(DCC_SRVR_ID)];  /* receiving server */
+    DCC_TS	ts;			/* date reported */
+    u_char	num_cks;
+    DCC_CK	cks[DCC_QUERY_MAX];
+} DCC_FLOD_RPT;
+#define DCC_FLOD_RPT_LEN(n) (ISZ(DCC_FLOD_RPT) - ISZ(DCC_CK)*DCC_QUERY_MAX  \
+			     + ISZ(DCC_CK)*(n))
+
+/* what can appear in the stream of flooded reports */
+typedef union {
+    DCC_FLOD_VERSION_HDR v;
+    DCC_FLOD_END    e;
+    DCC_FLOD_RPT    r;
+} DCC_FLOD_STREAM;
+
+
+/* a response to flooded reports */
+typedef union {
+    DCC_FLOD_POS    pos;
+    DCC_FLOD_END    end;		/* final result */
+    struct {
+	DCC_FLOD_POS    op;		/* one of DCC_FLOD_POS_* */
+	u_char		len;		/* total length */
+	char		str[DCC_FLOD_MAX_RESP]; /* includes trailing '\0' */
+    } note;
+} DCC_FLOD_RESP;
+#define FLOD_NOTE_OVHD (ISZ(((DCC_FLOD_RESP*)0)->note) - DCC_FLOD_MAX_RESP)
+
+
+/* parts of error messages sent between flooding peers */
+#define DCC_FLOD_BAD_VER_MSG	"unrecognized flod version"
+#define DCC_FLOD_BAD_ID_MSG	"unauthorized ID"
+#define DCC_FLOD_BAD_AUTH_MSG	"bad authentication for ID"
+#define DCC_FLOD_PASSWD_ID_MSG	"unknown passwd-ID"
+
+
+#endif /* DCC_PROTO_H	*/