view dccd/dccd_defs.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 source

/* Distributed Checksum Clearinghouse
 *
 * server daemon definitions
 *
 * 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.221 $Revision$
 */

#ifndef DCCD_DEFS_H
#define DCCD_DEFS_H

#include "srvr_defs.h"
#include "dcc_xhdr.h"

extern DCC_EMSG dcc_emsg;

extern u_char grey;
extern u_char background;
extern int stopint;

extern DCC_SRVR_ID my_srvr_id;

extern const char *brand;		/* our brand name */


extern u_char use_ipv6;
extern u_int16_t def_port;
typedef struct srvr_soc {
    struct srvr_soc *fwd;
    DCC_SOCKU	su;
    union {
	struct dcc_in6_addr in6;
	struct in_addr	    in4;
    } arg_addr;
    int		udp;
    int		listen;
    u_int16_t	arg_port;
    u_char	arg_family;
    u_char	flags;
#    define	 SRVR_SOC_ADDR	    0x01    /* explicit IP address */
#    define	 SRVR_SOC_IF	    0x02    /* port on all interfaces */
#    define	 SRVR_SOC_LISTEN    0x04    /* need a listen socket for port */
#    define	 SRVR_SOC_MARK	    0X08
#    define	 SRVR_SOC_NEW	    0X10
} SRVR_SOC;
extern SRVR_SOC *srvr_socs;
extern int srvr_rcvbuf;


#define MAX_CMD_CLOCK_SKEW (DCC_MAX_RETRANS_DELAY_SECS*2)
#define MAX_FLOD_CLOCK_SKEW (4*60*60)	/* refuse reports this far in advance */


extern char our_hostname[MAXHOSTNAMELEN];
extern DCC_SUM host_id_sum;		/* advertised with our server-ID */
extern time_t host_id_next, host_id_last;
#define DCC_SRVR_ID_SECS    (24*60*60)	/* defend server-IDs this often */
#define DCC_SRVR_ID_SECS_ST (5*60)	/* defend after daemon starts */

extern int flod_trace_gen;		/* unsuppress tracing */

/* keepalive intervals
 *	An idle flooding link is kept alive, or known to be healthy, by the
 *	receiving server repeating its current position.  If the link is
 *	broken, the receiving server's transmissions of its position will fail
 *	and the	transmitting server will hear silence on the link. */
#define	KEEPALIVE_IN	    (10*60)
#define	KEEPALIVE_OUT	    (KEEPALIVE_IN+FLODS_CK_SECS)
/* Things should be quicker while we are shutting down flooding
 *	Some TCP/IP implementations have retransmission delays that can
 *	totals 7 seconds, so we must not be too quick */
#define KEEPALIVE_IN_STOP   30
#define	KEEPALIVE_OUT_STOP  (KEEPALIVE_IN_STOP+FLODS_CK_SECS)
/* be really quick if stopping the daemon */
#define SHUTDOWN_DELAY	    2

#define IFP_DEAD(p,secs)  DB_IS_TIME((p)->iflod_alive+(secs), secs)
#define OFP_DEAD(p,secs)  DB_IS_TIME((p)->oflod_alive+(secs), secs)


/* Delay our reports and summaries of our reports by this much.
 * It should be long enough to allow us to generate useful summaries, but
 * it cannot be so long that we won't flood the summary when we make it. */
extern int summarize_delay_secs;


extern int queue_max;

extern u_char anon_off;			/* turn off anonymous access */
extern u_char query_only;		/* 1=treat reports as queries */

extern time_t anon_delay_us;		/* anonymous client delay */
extern u_int anon_delay_inflate;

extern struct timeval wake_time;	/* when we awoke from select() */
extern struct timeval req_recv_time;	/* when request arrived */

extern u_char grey_weak_body;		/* 1=ignore bodies for greylisting */
extern u_char grey_weak_ip;		/* 1=one good triple whitelists addr */

extern int grey_embargo;
extern int grey_window;
extern int grey_white;


/* rate limiting
 *	One of these structures is maintained for every recent client,
 *	where "recent" is at least one day */
typedef u_int16_t RL_DATA_FG;
#    define	 RL_FG_MARKED	0x0001	/* seen during `cdcc clients` */
#    define	 RL_FG_CK_BL	0x0002	/* 0=need to check list of addresses */
#    define	 RL_FG_TRACE	0x0004
#    define	 RL_FG_BL_ADDR	0x0008	/* blacklisted client or flood peer */
#    define	 RL_FG_BL_ID	0x0010	/* blacklisted client ID */
#    define	 RL_FG_BL_BAD	0x0020	/* ignored for bad behavior */
#    define	 RL_FG_BLS (RL_FG_BL_ADDR | RL_FG_BL_ID | RL_FG_BL_BAD)
#    define	 RL_FG_PASSWD	0x0040	/* bad password */
#    define	 RL_FG_UKN_ID	0x0080	/* bad ID */
#    define	 RL_FG_ANON	0x0100	/* clnt_id=DCC_ID_ANON or bad */
typedef struct {
    u_int64_t	requests;
    u_int64_t	requests_old;
    u_int64_t	nops;
    u_int64_t	nops_old;
    time_t	last_used;
    time_t	requests_avg_start;	/* effective start of averaging */
#    define	 RL_AVG_TERM	(60*60 * 48)
    time_t	requests_avg_aged;	/* when last updated */
#    define	 RL_AVG_UPDATE	(10*60)
    u_int	requests_avg_total;
    u_int	requests_avg;
    u_int	nops_avg_total;
    u_int	nops_avg;
#    define	 RL_REQUESTS_AVG(d) max((d)->requests_avg, (d)->requests)
#    define	 RL_NOPS_AVG(d)	    max((d)->nops_avg, (d)->nops)
    int		request_credits;	/* limit operations */
    int		bug_credits;		/* limit complaints about this client */
    DCC_CLNT_ID	clnt_id;
    struct in6_addr clnt_addr;
    u_char	pkt_vers;		/* recent protocol version */
    RL_DATA_FG	flags;
} RL_DATA;
typedef struct rl {
    struct rl	*hfwd, *hbak, **bin;	/* neighbors in hash chain & the bin */
    struct rl	*older, *newer;		/* global recently used chain */
    RL_DATA	d;
    short	ref_cnt;		/* in use by an entry in job queue */
} RL;


/* rate-limit parameters
 *	Decrease request_credits by RL_SCALE for each event.
 *	Increase request_credits by .per_sec for every second.
 *	When request_credits <= 0, there have been too many events.
 *	Clamp request_credits at .lo to limit the duration of a penalty.
 *	Clamp request_credits at .hi to limit the duration over which
 *	    the rate is averaged.
 */
typedef struct {
    float   penalty_secs;		/* drop excess events for this long */
    int	    per_sec;			/* allowed events/second * RL_SCALE */
    int	    lo;				/* clamp credit count at this */
    int	    hi;				/* reset credit count to this */
} RL_RATE;

extern RL_RATE rl_sub_rate;		/* X/sec/paying customer */
extern RL_RATE rl_anon_rate;		/* X/sec/freeloader */
extern RL_RATE rl_all_anon_rate;	/* X/sec for all freeloaders */
extern RL_RATE rl_bugs_rate;		/* X complaints/sec */

#if defined(RL_MIN_MAX)
#if RL_MIN_MAX<1000 || RL_MIN_MAX>1000000
#undef RL_MIN_MAX
#endif
#endif
#define RL_MIN_MAX_DEF	(10*1000)
#define RL_MIN_MAX_MAX	(1000*1000)	/* fix ./configure if this changes */
#define RL_AVG_SECS	10		/* average for this many seconds */
#define	RL_LIFE_SECS    (RL_AVG_SECS*2)	/* lifetime of rate limit block */

#define RL_OVF_CREDITS	0x7fffffff	/* fit {bug,request}_credits */
#define RL_SCALE	10
#define RL_MAX_CREDITS	(RL_OVF_CREDITS/RL_AVG_SECS/RL_SCALE/2)


extern time_t clients_cleared;


/* file containing rate limit blocks */
#define CLIENTS_NM()	    (grey_on ? "grey_clients" : "dccd_clients")
#define BAD_CLIENTS_NM()    (grey_on ? "grey_clients-bad" : "dccd_clients-bad")

typedef struct {
    char    magic[80];
    char    pad[40];
    time_t  now;
    time_t  cleared;
    int32_t anon_delay_us;
    u_int32_t anon_delay_inflate;
    int	    hash_len;
} CLIENTS_HEADER;
#define CLIENTS_MAGIC_VERSION	"7"
#define CLIENTS_MAGIC_STR	" client rate limit blocks version "
#define CLIENTS_MAGIC_BASE(g)	((g) ? "greylist" CLIENTS_MAGIC_STR	\
				 : "dccd" CLIENTS_MAGIC_STR)
#define CLIENTS_MAGIC_V(g,v)	((g) ? "greylist" CLIENTS_MAGIC_STR v	\
				 : "dccd" CLIENTS_MAGIC_STR v)
#define CLIENTS_MAGIC(g)	CLIENTS_MAGIC_V(g,CLIENTS_MAGIC_VERSION)



/* report cache used to detect duplicate reports
 *	One of these structures is maintained for every current operation */
typedef struct ridc {
    struct ridc *fwd, *bak, **hash;
    struct ridc *older, *newer;
    time_t	last_used;
    DCC_HDR	hdr;
    u_int16_t	clnt_port;
    int		len;
    u_char	op;
    u_char	bad;
    union {
	DCC_ANSWER_BODY_CKS b;
	DCC_ADMN_RESP_ANON_DELAY anon_delay;
	char		msg[DCC_ERROR_MSG_LEN];
    } result;
} RIDC;

/* entry in main job queue */
typedef struct dccd_queue {
    struct dccd_queue *later, *earlier;
    RL		*rl;
    RIDC	*ridc;
    SRVR_SOC	*sp;
    DCC_CLNT_ID	clnt_id;
    DCC_SOCKU	clnt_su;		/* send answer here */
    u_int	pkt_len;
    time_t	delay_us;		/* how long to delay the answer */
    struct timeval answer;		/* when it should be answered */
    u_char	flags;
#    define	 Q_FG_RPT_OK	    0x01    /* override dccd -Q */
#    define	 Q_FG_UNTRUSTED	    0x02
#    define	 Q_FG_UKN_ID	    0x04
#    define	 Q_FG_BAD_PASSWD    0x08
    DCC_PASSWD	passwd;			/* sign answers with this */
    union {
	DCC_HDR	    hdr;
	DCC_REPORT  r;
	DCC_DELETE  d;
	DCC_GREY_SPAM gs;
	DCC_ADMN_REQ ad;
    } pkt;
} QUEUE;


typedef struct iflod_info IFLOD_INFO;

typedef struct {
    DCC_SRVR_ID from_lo;
    DCC_SRVR_ID from_hi;
    u_char	result;
} OFLOD_SRVR_ID_MAP;
typedef enum {
    ID_MAP_NO, ID_MAP_REJ, ID_MAP_SELF
} ID_MAP_RESULT;

typedef struct {
    int	    cur, lim;			/* signed because lim can be <0 */
} FLOD_LIMCNT;
#define FLOD_LIM_CLEAR_SECS	(5*60)
#define FLOD_LIM_COMPLAINTS	10

typedef u_int OPT_FLAGS;
typedef struct {
    OPT_FLAGS	flags;
#    define	 FLOD_OPT_OFF		0x0001
#    define	 FLOD_OPT_TRACE		0x0002
#    define	 FLOD_OPT_TRACE2	0x0004
#    define	 FLOD_OPT_ROGUE		0x0008
#     define	  IFLOD_OPT_OFF_ROGUE(o) (((o)->i_opts.flags & FLOD_OPT_OFF)  \
					  | ((o)->o_opts.flags&FLOD_OPT_ROGUE))
#     define	  OFLOD_OPT_OFF_ROGUE(o) ((o)->o_opts.flags & (FLOD_OPT_OFF \
							| FLOD_OPT_ROGUE))
#    define	 FLOD_OPT_IPv4		0x0010
#    define	 FLOD_OPT_IPv6		0x0020
#    define	 FLOD_OPT_PASSIVE	0x0040
#    define	 FLOD_OPT_SOCKS		0x0080
#    define	 FLOD_OPT_NAT		0x0100
#    define	 FLOD_OPT_DEL_OK	0x0200
#    define	 FLOD_OPT_DEL_SET	0x0400
#    define	 FLOD_OPT_NO_LOG_DEL	0x0800
#    define	 FLOD_OPT_TRAPS		0x1000
#    define	 FLOD_OPT_SIMPLE	0x2000
    OFLOD_SRVR_ID_MAP srvr_map[10];
    u_char	num_maps;
    u_char	path_len;
} OFLOD_OPTS;

typedef struct {
    FLOD_MMAP	*mp;
    int		soc;			/* outgoing socket */
    int		lno;
    char	rem_portname[sizeof(flod_mmaps->mmaps[0].rem_portname)];
    char	rem_hostname[sizeof(flod_mmaps->mmaps[0].rem_hostname)];
    char	loc_hostname[DCC_MAXDOMAINLEN];
    DCC_SRVR_ID	rem_id, in_passwd_id, out_passwd_id;
    u_int16_t	rem_port, loc_port;
    DCC_SOCKU	rem_su;			/* target of the flood */
    time_t	limit_reset;		/* when to reset complaint limits */
    time_t	oflod_alive;		/* when last active */
    struct {
	time_t	    saved;		/* last wrote counts to file */
	u_int	    out_reports;	/* total reports sent */
	u_int	    total;		/* total reports received */
	u_int	    accepted;		/* acceptable received reports */
    } cnts;
    struct {
	FLOD_LIMCNT stale;		/* bad timestamp */
	FLOD_LIMCNT dup;		/* already received */
	FLOD_LIMCNT wlist;		/* whitelisted */
	FLOD_LIMCNT not_deleted;	/* delete commands ignored */
	FLOD_LIMCNT bad_id;		/* unrecognized server-IDs */
	FLOD_LIMCNT complaint;		/* output complaint from peer */
	FLOD_LIMCNT iflod_bad;		/* generic bad report */
    } lc;
    DB_PTR	xmit_pos;		/* last transmitted position */
    DB_PTR	recv_pos;		/* heard this from target */
    DB_PTR	cur_pos;		/* completed to here */
    DB_PTR	rewind_pos;		/* will have rewound by here */
    int		ibuf_len;
    union {
	DCC_FLOD_RESP r;
	u_char	    b[sizeof(DCC_FLOD_RESP)*2];
    } ibuf;
    u_int	obuf_len;
    union {
	DCC_FLOD_STREAM s;
#	 define	     FLOD_BUF_SIZE 2048
	u_char	    b[FLOD_BUF_SIZE];
    } obuf;
    OFLOD_OPTS	i_opts;
    OFLOD_OPTS	o_opts;
    IFLOD_INFO	*ifp;
    u_int	flags;
#    define	 OFLOD_FG_CONNECTED	0x0001	/* connect() complete */
#    define	 OFLOD_FG_NEW		0x0002	/* new connection */
#    define	 OFLOD_FG_SHUTDOWN	0x0004	/* brakes applied */
#    define	 OFLOD_FG_SHUTDOWN_REQ	0x0008
#    define	 OFLOD_FG_HAVE_2PASSWD	0x0010	/* have a 2nd password */
#    define	 OFLOD_FG_I_USED_2PASSWD 0x020	/* used the 2nd password */
#    define	 OFLOD_FG_O_USED_2PASSWD 0x040
#    define	 OFLOD_FG_EAGAIN	0x0080	/* recent bogus EAGAIN */
	u_char	oversion;
} OFLOD_INFO;

typedef struct {
    int		total;			/* known peers */
    int		open;			/* active outgoing streams */
    OFLOD_INFO  infos[DCCD_MAX_FLOODS];
} OFLODS;
extern OFLODS oflods;
extern DB_PTR oflods_max_cur_pos;

extern enum FLODS_ST {
	FLODS_ST_OFF, FLODS_ST_RESTART, FLODS_ST_ON
} flods_st;

extern DCC_TGTS flod_tholds[DCC_DIM_CKS];


struct iflod_info {
    int		soc;			/* incoming socket */
    DCC_SOCKU	rem_su;			/* sender of the flood */
    char	rem_hostname[sizeof(flod_mmaps->mmaps[0].rem_hostname)];
    DCC_FLOD_POS pos, pos_sent;
    OFLOD_INFO	*ofp;
    time_t	iflod_alive;		/* when last active */
    int		ibuf_len;
    u_char	flags;
#    define	 IFLOD_FG_CONNECTED	0x01
#    define	 IFLOD_FG_CLIENT	0x02	/* outgoing connection */
#    define	 IFLOD_FG_VERS_CK	0x04
#    define	 IFLOD_FG_END_REQ	0x08
#    define	 IFLOD_FG_FAST_LINGER	0x10
    union {
	DCC_FLOD_STREAM	s;
	u_char		b[FLOD_BUF_SIZE];
    } ibuf;
};

typedef struct {
    int		open;
    IFLOD_INFO	infos[DCCD_MAX_FLOODS];
} IFLODS;
extern IFLODS iflods;

extern int flods_off;			/* # of reasons flooding is off */
#define FLODS_OK()	(!flods_off && !db_minimum_map)
#define FLODS_OK_ON()	(FLODS_OK() && flods_st == FLODS_ST_ON)
extern u_int complained_many_iflods;

typedef enum {
    WFIX_DELAY,				/* waiting for window overflow */
    WFIX_BUSY,				/* measuring active load */
    WFIX_QUIET,				/* waiting for clients to flee */
    WFIX_CHECK,				/* counting clients that stayed */
} DBCLEAN_WFIX_STATE;
extern DBCLEAN_WFIX_STATE dbclean_wfix_state;

extern u_char stop_mode;		/* 0=normal 1=reboot 2=with/DB clean */
extern time_t next_flods_ck;
#define FLODS_CK_SECS	    5
#define RUSH_NEXT_FLODS_CK() {if (next_flods_ck > db_time.tv_sec + 1)	\
	next_flods_ck = db_time.tv_sec + 1;}
#define MISC_CK_SECS	    FLODS_CK_SECS
#define CLIENTS_SAVE_SECS   (30*60)

extern time_t flod_mtime;

#define FLOD_RETRY_SECS		(5*60)	/* retry connection no sooner */
#define FLOD_SUBMAX_RETRY_SECS	(60*60)	/* retry when peer can't poke us */
#define FLOD_MAX_RETRY_SECS (24*60*60)	/* maximum backoff */
#define	FLOD_SOCKS_SOCKS_IRETRY	30

#define	FLOD_IN_COMPLAIN    (24*60*60)  /* complain daily about input */
#define	FLOD_IN_COMPLAIN1   (2*60*60)	/* 1st normal input complaint */
#define	FLOD_IN_COMPLAIN_NOW	(5*60)	/* complain as soon as possible */

extern time_t iflods_ok_timer;		/* incoming flooding ok since then */
#define IFLODS_OK_SECS	    (5*60)	/* 5 minutes to catch up */

extern time_t need_clients_save;

extern time_t got_hosts;		/* resolve hostnames */
#define FLOD_NAMES_RESOLVE_SECS	(5*60)	/*	at most every 5 minutes */
extern pid_t resolve_hosts_pid;

extern const char *need_del_dbclean;
extern time_t del_dbclean_next;
#define DEL_DBCLEAN_SECS	(30*60)	/* limit dbclean if not urgent */
extern time_t dbclean_limit;
#define DBCLEAN_LIMIT_SECS	15	/* not too often for any reason */
extern time_t dbclean_limit_secs;

extern DCCD_STATS dccd_stats;


/* Avoid the costs of generating and passing the args to syslog() by
 * checking bits in the caller.
 * If the server ran only on modern Unix, we could use gcc's macro varargs. */
#define TMSG_BIT(t) (DCC_TRACE_##t##_BIT & dccd_tracemask)
#define TMSG_BLOCK(t,args) do {if TMSG_BIT(t) dcc_trace_msg args;} while (0)
#define TMSG(t,p)	TMSG_BLOCK(t,(p))
#define TMSG1(t,p,arg)	TMSG_BLOCK(t,(p,arg))
#define TMSG2(t,p,arg1,arg2) TMSG_BLOCK(t,(p,arg1,arg2))
#define TMSG3(t,p,arg1,arg2,arg3) TMSG_BLOCK(t,(p,arg1,arg2,arg3))
#define TMSG4(t,p,arg1,arg2,arg3,arg4) TMSG_BLOCK(t,(p,arg1,arg2,arg3,arg4))
#define TMSG5(t,p,arg1,arg2,arg3,arg4,arg5)				\
		TMSG_BLOCK(t,(p,arg1,arg2,arg3,arg4,arg5))

#define TMSG_FB(ofp) ((DCC_TRACE_FLOD_BIT & dccd_tracemask)		\
		      || ((ofp && (ofp->o_opts.flags & FLOD_OPT_TRACE))))
#define TMSG_Fsub(ofp,args) do {if (TMSG_FB(ofp)) dcc_trace_msg args;} while(0)
#define TMSG_FLOD(ofp,p) TMSG_Fsub(ofp,(p))
#define TMSG1_FLOD(ofp,p,arg) TMSG_Fsub(ofp,(p,arg))
#define TMSG2_FLOD(ofp,p,arg1,arg2) TMSG_Fsub(ofp,(p,arg1,arg2))
#define TMSG3_FLOD(ofp,p,arg1,arg2,arg3) TMSG_Fsub(ofp,(p,arg1,arg2,arg3))

#define TMSG_FB2(ofp) (((DCC_TRACE_FLOD_BIT				\
			 | DCC_TRACE_FLOD2_BIT) & dccd_tracemask)	\
		       || ((ofp && (ofp->o_opts.flags			\
				    & (FLOD_OPT_TRACE | FLOD_OPT_TRACE2)))))
#define TMSG_F2sub(ofp,args) do {if (TMSG_FB2(ofp))dcc_trace_msg args;} while(0)
#define TMSG_FLOD2(ofp,p) TMSG_F2sub(ofp,(p))
#define TMSG1_FLOD2(ofp,p,arg) TMSG_F2sub(ofp,(p,arg))
#define TMSG2_FLOD2(ofp,p,arg1,arg2) TMSG_F2sub(ofp,(p,arg1,arg2))
#define TMSG3_FLOD2(ofp,p,arg1,arg2,arg3) TMSG_F2sub(ofp,(p,arg1,arg2,arg3))


#define Q_CIP(q) dcc_su2str_err(&(q)->clnt_su)


static inline void
db_ptr2flod_pos(DCC_FLOD_POS bp, DB_PTR pos)
{
	bp[7] = pos;     bp[6] = pos>>8;
	bp[5] = pos>>16; bp[4] = pos>>24;
	bp[3] = pos>>32; bp[2] = pos>>40;
	bp[1] = pos>>48; bp[0] = pos>>56;
}


static inline DB_PTR
flod_pos2db_ptr(const DCC_FLOD_POS pos)
{
	return ((DB_PTR)pos[7]		 + (((DB_PTR)pos[6])<<8)
		+ (((DB_PTR)pos[5])<<16) + (((DB_PTR)pos[4])<<24)
		+ (((DB_PTR)pos[3])<<32) + (((DB_PTR)pos[2])<<40)
		+ (((DB_PTR)pos[1])<<48) + (((DB_PTR)pos[0])<<56));
}


/* multiplicative hash function after Knuth vol. 3 */
static inline u_int32_t
mhash(u_int32_t hashin, u_int nbins)
{
	u_int64_t v;

	v = 0x9ccf9319;
	v *= hashin;			/* v=(hashin * Knuth's 0.6125423371 */
	v &= 0xffffffff;		/* fractional part or modulo 1 */
	v *= nbins;
	return v >> 32;
}


/* dccd.c */
extern void free_q(QUEUE *);
extern void after_fork(void);
extern void set_dbclean_timer(void);
extern void bad_stop(const char *, ...) PATTRIB(1,2);

/* iflod.c */
extern ID_MAP_RESULT id_map(DCC_SRVR_ID, const OFLOD_OPTS *);
extern const char * ifp_rem_str(const IFLOD_INFO *);
#define CK_FLOD_CNTERR(lc) (++(lc)->cur <= ((lc)->lim + FLOD_LIM_COMPLAINTS))
extern void flod_cnterr(const FLOD_LIMCNT *, const char *, ...) PATTRIB(2,3);
extern const char * ofp_rem_str(const OFLOD_INFO *);
extern void rpt_err(OFLOD_INFO *, u_char, u_char,
		    const char *, ...) PATTRIB(4,5);
extern u_char set_flod_socket(OFLOD_INFO *, u_char, int,
			      const char *, const DCC_SOCKU *);
extern u_char flod_names_resolve_ck(void);
extern u_char flod_names_resolve_start(void);
extern void iflod_listen_close(SRVR_SOC *);
extern void iflods_stop(const char *, u_char);
extern void iflod_start(SRVR_SOC *);
extern void iflods_listen(void);
extern void iflod_socks_start(OFLOD_INFO *);
extern u_char dccd_db_open(u_char);
extern void iflod_close(IFLOD_INFO *, u_char, u_char, u_char,
			const char *, ...) PATTRIB(5,6);
extern u_char iflod_read(IFLOD_INFO *);
extern int iflod_send_pos(IFLOD_INFO *, u_char);
extern int flods_list(char *, int, u_char);
extern int flod_stats(char *, int, u_int32_t, u_char);

/* oflod.c */
extern void oflods_clear(void);
extern void oflod_open(OFLOD_INFO *);
extern u_char load_flod(u_char);
extern void save_flod_cnts(OFLOD_INFO *);
extern void oflod_close(OFLOD_INFO *, u_char);
extern int oflod_parse_eof(OFLOD_INFO *, u_char, const DCC_FLOD_END *, int);
extern void oflod_read(OFLOD_INFO *);
extern void oflod_write(OFLOD_INFO *);
extern void flods_stop(const char *, u_char);
extern const char *version_str(OFLOD_INFO *);
extern void flod_try_again(OFLOD_INFO *);
extern const char *flod_sign(OFLOD_INFO *, u_char, void *, int);
extern u_char oflod_connect_fin(OFLOD_INFO *);
extern void flods_restart(const char *, u_char);
extern int check_load_ids(u_char);
extern void flods_ck(u_char);
extern void flods_init(void);

/* rl.c */
extern void rl_inc(RL *, const RL_RATE *);
extern void clients_save(void);
extern void clients_load(void);
extern u_char ck_ip_bl(RL **, DCC_CLNT_ID, const struct in6_addr *);
extern void clients_get_id(DCC_ADMN_RESP_VAL *, int *, u_int, int, u_char,
			   const struct in6_addr *, const struct in6_addr *);
extern int clients_get(DCC_ADMN_RESP_VAL *, int *, u_int, int, u_char,
		       const struct in6_addr *, const struct in6_addr *);
#define CLIENTS_AGE	    (24*60*60)
#define CLIENTS_SAVE_AGE    (14*CLIENTS_AGE)
extern void clients_clear(void);
extern u_char ck_sign(const ID_TBL **, DCC_PASSWD, DCC_CLNT_ID,
		      const void *, u_int);
extern u_char ck_clnt_srvr_id(QUEUE *);
extern u_char ck_clnt_id(QUEUE *);
extern const char *qop2str(const QUEUE *);
extern void check_blacklist_file(void);

extern u_long dccd_tracemask;

extern const char *from_id_ip(const QUEUE *, u_char);
extern const char *op_id_ip(const QUEUE *);
extern void vanon_msg(const char *, va_list);
extern void anon_msg(const char *, ...) PATTRIB(1,2);
extern void vclnt_msg(const QUEUE *, const char *, va_list);
extern void clnt_msg(const QUEUE *, const char *, ...) PATTRIB(2,3);
extern void drop_msg(QUEUE *, const char *, ...) PATTRIB(2,3);

/* work.c */
extern int find_srvr_rcd(const DCC_SUM, const char *);
extern int find_srvr_rcd_type(DCC_SRVR_ID);
extern ID_TBL *find_srvr_type(DCC_SRVR_ID);
extern void refresh_srvr_rcd(const DCC_SUM, DCC_SRVR_ID, const char *);
extern void stats_clear(void);
extern u_char summarize_dly(void);
extern u_char add_dly_rcd(DB_RCD *, u_char);
extern void do_work(QUEUE *);
extern void do_grey(QUEUE *);
extern void do_grey_spam(QUEUE *);
extern void do_nop(QUEUE *);
extern void do_admn(QUEUE *);
extern void do_delete(QUEUE *);


#endif /* DCCD_DEFS_H */