Logo Search packages:      
Sourcecode: dcc version File versions

dccd_defs.h

/* Distributed Checksum Clearinghouse
 *
 * server daemon definitions
 *
 * Copyright (c) 2005 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 for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * Parties not eligible to receive a license under this agreement can
 * obtain a commercial license to use DCC and permission to use
 * U.S. Patent 6,330,590 by contacting Commtouch at http://www.commtouch.com/
 * or by email to nospam@commtouch.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.42-1.147 $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;

extern DB_RCD host_id_rcd;          /* our host's globally unique ID */
extern time_t host_id_next, host_id_last;
#define DCC_SRVR_ID_SEC     (24*60*60)    /* defend server-IDs this often */
#define DCC_SRVR_ID_SEC0    (5*60)  /* defend after daemon is running */

extern time_t boot_ok_time;         /* suppress flooding errors at first */

/* normal keepalive interval */
#define     KEEPALIVE_IN          (60*15)
#define     KEEPALIVE_OUT         (KEEPALIVE_IN+FLODS_CK_SECS)
/* things should be quicker while we are shutting down flooding */
#define KEEPALIVE_IN_STOP   15
#define     KEEPALIVE_OUT_STOP  (KEEPALIVE_IN_STOP+FLODS_CK_SECS)
/* be really quick if stopping the daemon */
#define SHUTDOWN_DELAY      2


extern int summarize_delay_secs;    /* delay summaries by this */
#define MAX_SUMMARIZE_DELAY_SECS (DCC_NEW_SPAM_SECS/2)


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 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 struct rl {
    struct rl     *fwd, *bak, **hash;
    struct rl     *older, *newer;
    DCC_CLNT_ID   clnt_id;
    struct in6_addr clnt_addr;
    time_t  last_used;
    time_t  requests_avg_date;      /* end of "today" for averaging */
#    define  RL_AVG_DAY (24*60*60 - 30*60)
    int           requests_cur_avg; /* yesterday's total */
    int           nops_cur_avg;
    int           requests_next_avg;      /* growing total for tomorrow */
    int           nops_next_avg;
#    define  RL_REQUESTS_AVG(rl) max((rl)->requests_cur_avg,      \
                               (rl)->requests+(rl)->requests_next_avg)
#    define  RL_NOPS_AVG(rl) max((rl)->nops_cur_avg,        \
                             (rl)->nops+(rl)->nops_next_avg)
    int           requests;
    int           nops;
    int           request_credits;  /* operations */
    int           bug_credits;            /* complaints about this client */
    short   ref_cnt;          /* in use by entry in queue */
    u_char  vers;             /* recent protocol version */
    u_char  flags;
#    define  RL_CK_BLACKLIST    0x01    /* 0=need the check blacklist */
#    define  RL_BLACKLIST         0x02    /* 1=blacklisted client */
#    define  RL_TRACE       0x04
#    define  RL_MARKED      0x08
} RL;


typedef struct {
    float   penalty_secs;
    int         sec, lo, hi;
} 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 */

#define     RL_MIN_MAX  10000       /* freely create this many blocks */
#define RL_MAX_MAX      (RL_MIN_MAX*8)    /* absolute limit */
#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;


/* 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;
    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;          /* validated client-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_FLG_RPT_OK     0x01  /* override dccd -Q */
    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         val;
    int         limit;
} FLOD_LIMCNT;
#define FLOD_CNTERR(lc) (++(lc)->val - ((lc)->limit + 10))
#define FLOD_LIM_CLEAR_SECS   (60*60)

typedef struct {
    u_int   flags;
#    define  FLOD_OPT_OFF           0x0001
#    define  FLOD_OPT_DEL_OK  0x0002
#    define  FLOD_OPT_DEL_SET 0x0004
#    define  FLOD_OPT_NO_LOG_DEL    0x0008
#    define  FLOD_OPT_TRAPS         0x0010
#    define  FLOD_OPT_PASSIVE 0x0020
#    define  FLOD_OPT_SOCKS         0x0040
#    define  FLOD_OPT_IPv4          0x0080
#    define  FLOD_OPT_IPv6          0x0100
#    define  FLOD_OPT_NO_REP  0x0200
    OFLOD_SRVR_ID_MAP srvr_map[10];
    u_char  num_maps;
    u_char  path_len;
} OFLOD_OPTS;

typedef struct {
    FLOD_MMAP     *mp;
    int           s;                /* 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[MAXHOSTNAMELEN];
    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  out_try_again;          /* don't connect() before then */
    int           out_try_secs;           /*    backoff */
    time_t  in_try_again;           /* no SOCKS connect() before then */
    int           in_try_secs;            /*    backoff */
    time_t  limit_reset;            /* when to reset complaint limits */
    time_t  keep_out_time;          /* last sent to peer */
    time_t  keep_in_time;           /* last heard from peer */
    struct {
      time_t          saved;        /* last wrote counts to file */
      int       out_reports;  /* total reports sent */
      int       total;        /* total reports received */
      int       accepted;           /* acceptable received reports */
      FLOD_LIMCNT stale;            /* bad timestamp */
      FLOD_LIMCNT dup;        /* already received */
      FLOD_LIMCNT ok2;        /* 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 */
    } cnts;
    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 */
    u_int   ibuf_len;
    union {
      DCC_FLOD_POS pos;
      FLOD_END    end;
      FLOD_NOTE   note;
      u_char          b[sizeof(DCC_FLOD_POS)*2+DCC_FLOD_MAX_RESP+1];
    } ibuf;
    u_int   obuf_reports, obuf_len, obuf_off;
    union {
      DCC_FLOD_VERSION_HDR vers;
      DCC_FLOD    f[3];
#      define          FLOD_BUF_SIZE 2048
      char      c[FLOD_BUF_SIZE];
    } obuf;
    OFLOD_OPTS    i_opts;
    OFLOD_OPTS    o_opts;
    time_t  ids_mtime;
    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_PASSWD_NEXT   0x0010      /* have a 2nd password */
#    define  OFLOD_FG_TOO_BUSY      0x0020      /* stopped filling buffer */
#    define  OFLOD_FG_EAGAIN  0x0040      /* recent bogus EAGAIN */
    u_char  iversion, oversion;
} OFLOD_INFO;

typedef struct {
    int           total;
    int           active;
    OFLOD_INFO  infos[DCCD_MAX_FLOODS];
} OFLODS;
extern OFLODS oflods;
extern DB_PTR oflods_max_pos;

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

extern DB_FLOD_THOLDS flod_tholds;

struct iflod_info {
    int           s;                /* incoming socket */
    DCC_SOCKU     su;               /* sender of the flood */
    char    hostname[sizeof(flod_mmaps->mmaps[0].rem_hostname)];
    DCC_FLOD_POS pos, pos_sent;
    OFLOD_INFO    *ofp;
    time_t  quit_connect;           /* when to stop waiting for password */
#    define  IFLOD_CONNECT_SECS KEEPALIVE_IN
    u_int   ibuf_len, ibuf_off;
    u_char  flags;
#    define  IFLOD_FG_CONNECTED     0x01
#    define  IFLOD_FG_VERS_CK 0x02
#    define  IFLOD_FG_END_REQ 0x04
#    define  IFLOD_FG_FAST_LINGER   0x08
#    define  IFLOD_FG_PEER_REP_OFF  0x10  /* peer rejects reputations */
    union {
      DCC_FLOD_VERSION_HDR vers;
      DCC_FLOD    f[3];
      char      c[FLOD_BUF_SIZE];
    } ibuf;
};

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

extern int flods_off;               /* # of reasons flooding is off */
extern int flod_db_sick;            /* # of flooding DB sicknesses */
extern u_int complained_many_iflods;

extern u_char too_busy;             /* too busy to flood */
extern time_t next_flods_ck;
#define FLODS_CK_SECS       5
#define GREY_FLODS_CK_SECS  5
#define MISC_CK_SECS        (FLODS_CK_SECS-1)

#define FLOD_RETRY_SECS       (60*5)      /* try to connect once in 5 minutes */
#define FLOD_SLOW_RETRY_SECS (60*60*4)    /* 4 hours after bad authentication */

extern time_t got_hosts;
#define FLOD_NAMES_RESOLVE_SECS     (60*15)     /* resolve hostnames once/15 minutes */
extern pid_t resolve_hosts_pid;

extern const char *need_del_dbclean;
extern time_t del_dbclean_next;
#define DEL_DBCLEAN_SECS      (60*30)     /* 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(t,p) do {                          \
      if (DCC_TRACE_##t##_BIT & dccd_tracemask) \
            dcc_trace_msg(p);} while (0)
#define TMSG1(t,p,arg) do {                     \
      if (DCC_TRACE_##t##_BIT & dccd_tracemask) \
            dcc_trace_msg(p,arg);} while (0)
#define TMSG2(t,p,arg1,arg2) do {               \
      if (DCC_TRACE_##t##_BIT & dccd_tracemask) \
            dcc_trace_msg(p,arg1,arg2);} while (0)
#define TMSG3(t,p,arg1,arg2,arg3) do {                \
      if (DCC_TRACE_##t##_BIT & dccd_tracemask) \
            dcc_trace_msg(p,arg1,arg2,arg3);} while (0)
#define TMSG4(t,p,arg1,arg2,arg3,arg4) do {           \
      if (DCC_TRACE_##t##_BIT & dccd_tracemask) \
            dcc_trace_msg(p,arg1,arg2,arg3,arg4);} while (0)
#define TMSG5(t,p,arg1,arg2,arg3,arg4,arg5) do {      \
      if (DCC_TRACE_##t##_BIT & dccd_tracemask) \
            dcc_trace_msg(p,arg1,arg2,arg3,arg4,arg5);} while (0)
#define TMSG6(t,p,arg1,arg2,arg3,arg4,arg5,arg6) do { \
      if (DCC_TRACE_##t##_BIT & dccd_tracemask) \
            dcc_trace_msg(p,arg1,arg2,arg3,arg4,arg5,arg6);} while (0)

#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));
}



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

/* iflod.c */
const char *flod_stats_str(int *, int, enum FLOD_ERR_OP);
extern void rpt_err(LAST_ERROR *, u_char, enum FLOD_ERR_OP, int,
                const char *, ...) PATTRIB(5,6);
extern u_char set_flod_socket(int, const char *, const DCC_SOCKU *, u_char);
extern u_char flod_names_resolve_ck(void);
extern u_char flod_names_resolve_start(void);
extern ID_MAP_RESULT id_map(DCC_SRVR_ID, const OFLOD_OPTS *);
extern void iflod_stop(IFLOD_INFO *, const char *);
extern void iflods_stop(const char *, u_char);
extern void iflod_start(SRVR_SOC *);
extern void iflods_start(void);
extern void iflod_socks_start(OFLOD_INFO *);
extern u_char dccd_db_open(u_char);
extern void iflod_close(IFLOD_INFO *, u_char, enum FLOD_ERR_OP, int,
                  const char *, ...)  PATTRIB(5,6);
extern void iflod_read(IFLOD_INFO *);
extern u_char 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);
extern void new_peer(OFLOD_INFO *);

/* oflod.c */
extern void oflod_open(OFLOD_INFO *);
extern void oflods_unmap(void);
extern u_char oflods_load(void);
extern void save_flod_cnts(OFLOD_INFO *);
extern void oflod_close(OFLOD_INFO *, u_char, enum FLOD_ERR_OP, int);
extern void oflod_read(OFLOD_INFO *);
extern void oflod_write(OFLOD_INFO *);
extern void oflods_stop(u_char);
extern const char *version_str(const OFLOD_INFO *);
extern u_char oflod_connect_fin(OFLOD_INFO *);
extern void PATTRIB(3,4) db_broken(int, const char *, const char *, ...);
extern void flods_restart(const char *);
extern void flods_ck(u_char);
extern void flods_init(void);

/* rl.c */
extern void clients_get_id(DCC_ADMN_RESP_VAL *, int *, const QUEUE *,
                     u_int, int, u_char,
                     const struct in6_addr *, const struct in6_addr *);
extern int clients_get(DCC_ADMN_RESP_VAL *, int *, const QUEUE *,
                   u_int, int, u_char,
                   const struct in6_addr *, const struct in6_addr *);
#ifdef DCC_PKT_VERSION6
extern void clients_get_idv6(DCC_ADMN_RESP_VAL *, int *, u_int, int, u_char);
#endif
#define CLIENTS_AGE (24*60*60)
extern void clients_clear(u_char);
extern u_char ck_sign(ID_TBL **, DCC_PASSWD, DCC_CLNT_ID, const void *, u_int);
extern u_char ck_id(QUEUE *, DCC_CLNT_ID);
extern u_char ck_clnt_srvr_id(QUEUE *);
extern u_char ck_clnt_id(QUEUE *);
extern void check_blacklist_file(void);

/* trace.c */
extern u_long dccd_tracemask;
extern void vanon_msg(const char *, va_list);
extern void anon_msg(const char *, ...) PATTRIB(1,2);
extern void clnt_msg(const QUEUE *, const char *, ...) PATTRIB(2,3);

/* work.c */
extern u_char ridc_get(QUEUE *);
extern void update_q_delay(QUEUE *);
extern void cycle_q_delay(void);
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 *);
extern void discard_error(const QUEUE *, const char *, ...) PATTRIB(2,3);
extern void send_ok(QUEUE *);


#endif /* DCCD_DEFS_H */

Generated by  Doxygen 1.6.0   Back to index