Просмотр исходного кода

Merge branch 'rbl-lookup'

* rbl-lookup: (24 commits)
  * Fix set 'realname' ordering
  * Don't check RBL until all m->userip[]'s are populated from the dns lookup, or else the KICKs wont occur
  * Remove flush overload from do_mask
  * Show RBL in kick/ban reason
  * Cleanup memory leaks in rbl/+r code
  * Optimize lookups more, apply the ban to the botnet/chan right away on matching result and kick all matching users based on cached m->userip
  * Fix memory leak in RBL checking: Free up r->servers after a successful lookup
  * Move debugging notice
  * Optimize RBL checking slightly
  * Only send the +b if opped, otherwise add it temporarily to the botnet
  * Fix RBL lookup ignoring clients with userips
  * Update doc/UPDATES about new rbl features
  * No need to do RBL lookups on self or users
  * Add +rbl to help::chaninfo
  * Support multiple servers for RBL lookups
  src/mod/irc.mod/chan.c
  * Add set 'rbl-servers' with defaults
  * Only need to lookup the A record when checking RBL lists
  * Remove unused 'ps'
  * Fix user matching in resolve/rbl callbacks
  ...
Bryan Drewery 16 лет назад
Родитель
Сommit
ecaad589df

+ 1 - 0
doc/UPDATES

@@ -43,6 +43,7 @@
 * Cleanup all string parsing to trim excess whitespaces (fixes #268)
 * Cleanup all string parsing to trim excess whitespaces (fixes #268)
 * No longer bundling Openssl code; It is now required to be installed to compile.
 * No longer bundling Openssl code; It is now required to be installed to compile.
 * Cleanup cmd_botcmd restrictions.
 * Cleanup cmd_botcmd restrictions.
+* Add 'chanset +rbl' which uses list of servers from 'set rbl-servers'. Only +r bots will enforce this.
 
 
 1.2.16 - http://wraith.botpack.net/milestone/1.2.16
 1.2.16 - http://wraith.botpack.net/milestone/1.2.16
 * Add 'set altchars' so that alternative characters used for nicks can be changed. (fixes #418)
 * Add 'set altchars' so that alternative characters used for nicks can be changed. (fixes #418)

+ 8 - 4
doc/help.txt

@@ -467,6 +467,8 @@ See also: link
                        Users who lose access to a channel because of this setting
                        Users who lose access to a channel because of this setting
                        will see no reference to it over the botnet in any place.
                        will see no reference to it over the botnet in any place.
                        The +o restriction goes for +v as well.
                        The +o restriction goes for +v as well.
+        $brbl$b             Do RBL lookups on clients and ban on matches.
+                       Uses 'rbl-servers'. See also '%dhelp set'
         $btake$b           Once a bot is opped, it will mass op all other bots
         $btake$b           Once a bot is opped, it will mass op all other bots
                        in the channel. After that, they will all attempt to 
                        in the channel. After that, they will all attempt to 
                        mass deop in hopes 'taking' the channel. :)
                        mass deop in hopes 'taking' the channel. :)
@@ -1530,12 +1532,12 @@ See also: reload, backup
    $uB$u:    Boolean (0/1/true/on/false/off)
    $uB$u:    Boolean (0/1/true/on/false/off)
    $uS$u:    String
    $uS$u:    String
    $uN$u:    Number
    $uN$u:    Number
-   $uL$u:    List capable
+   $uL$u:    List
    $uR$u:    Rate. Set as 'number:interval', ie, '1:5'
    $uR$u:    Rate. Set as 'number:interval', ie, '1:5'
    $uD$u:    Detected vars have the folloing options: $bignore$b/0, $bwarn$b/1, $breject$b/2, 
    $uD$u:    Detected vars have the folloing options: $bignore$b/0, $bwarn$b/1, $breject$b/2, 
                                                       $bdie$b/3, $bsuicide$b/4
                                                       $bdie$b/3, $bsuicide$b/4
  
  
-[SL] $balias$b           List of dcc aliases in format '<alias> <cmd> [parms]'. First
+[L] $balias$b            List of dcc aliases in format '<alias> <cmd> [parms]'. First
                           matching alias is used. Normal flag checking is done
                           matching alias is used. Normal flag checking is done
                           after the alias is expanded. 
                           after the alias is expanded. 
                           $bAliases may not reference other aliases.$b
                           $bAliases may not reference other aliases.$b
@@ -1571,8 +1573,10 @@ See also: reload, backup
 [D]  $bpromisc$b         How to handle when an interface is set to promiscuous mode.
 [D]  $bpromisc$b         How to handle when an interface is set to promiscuous mode.
 [D]  $bhijack$b          How to handle when a commonly used hijack method attempt is detected. 
 [D]  $bhijack$b          How to handle when a commonly used hijack method attempt is detected. 
  
  
-[SL] $bservers$b         Comma-separated list of servers the bot will use.
-[SL] $bservers6$b        Comma-separated list of servers the bot will use (FOR IPv6).
+[L]  $bservers$b         Comma-separated list of servers the bot will use.
+[L]  $bservers6$b        Comma-separated list of servers the bot will use (FOR IPv6).
+
+[L]  $brbl-servers$b     Servers to use for RBL checking in channels that are +rbl.
  
  
 [S]  $brealname$b        The bot's "real name" when connecting. (supports '$n' expansion)
 [S]  $brealname$b        The bot's "real name" when connecting. (supports '$n' expansion)
 [S]  $busermode$b        The bot's usermode on IRC. (Set on connect/rehash)
 [S]  $busermode$b        The bot's usermode on IRC. (Set on connect/rehash)

+ 10 - 0
doc/settings.txt

@@ -62,4 +62,14 @@ irc.ipv6.homelien.no
 irc.ipv6.inter.net.il
 irc.ipv6.inter.net.il
 irc.paraphysics.net
 irc.paraphysics.net
 
 
+:rbl
+cbl.abuseat.org
+dnsbl.ahbl.org
+dnsbl.proxybl.org
+rbl.efnetrbl.org
+tor.efnet.org
+dnsbl.swiftbl.net
+xbl.spamhaus.org
+rbl.efnetpro.com
+
 :end
 :end

+ 27 - 22
src/adns.c

@@ -166,7 +166,6 @@ const char *dns_ip = NULL;
 
 
 static int make_header(char *buf, int id);
 static int make_header(char *buf, int id);
 static int cut_host(const char *host, char *query);
 static int cut_host(const char *host, char *query);
-static int reverse_ip(const char *host, char *reverse);
 static int read_resolv(char *fname);
 static int read_resolv(char *fname);
 static void read_hosts(char *fname);
 static void read_hosts(char *fname);
 static int get_dns_idx();
 static int get_dns_idx();
@@ -394,33 +393,39 @@ dns_query_t *find_query(const char *host)
   return NULL;
   return NULL;
 }
 }
 
 
-void dns_send_query(dns_query_t *q)
+static void dns_send_query(dns_query_t *q, int type = (DNS_LOOKUP_A|DNS_LOOKUP_AAAA))
 {
 {
   char buf[512] = "";
   char buf[512] = "";
   int len;
   int len;
 
 
-  if (!q->ip) {
-    /* Send the ipv4 query. */
-    q->remaining = 1;
-    len = make_header(buf, q->id);
-    len += cut_host(q->query, buf + len);
-    buf[len] = 0; len++; buf[len] = DNS_A; len++;
-    buf[len] = 0; len++; buf[len] = 1; len++;
+  q->remaining = 0;
 
 
-    egg_dns_send(buf, len);
+  if (!q->ip) {
+    if (type & DNS_LOOKUP_A) {
+      /* Send the ipv4 query. */
+      q->remaining++;
+      len = make_header(buf, q->id);
+      len += cut_host(q->query, buf + len);
+      buf[len] = 0; len++; buf[len] = DNS_A; len++;
+      buf[len] = 0; len++; buf[len] = 1; len++;
+
+      egg_dns_send(buf, len);
+    }
 
 
 #ifdef USE_IPV6
 #ifdef USE_IPV6
-    /* Now send the ipv6 query. */
-    q->remaining++;
-    len = make_header(buf, q->id);
-    len += cut_host(q->query, buf + len);
-    buf[len] = 0; len++; buf[len] = DNS_AAAA; len++;
-    buf[len] = 0; len++; buf[len] = 1; len++;
-
-    egg_dns_send(buf, len);
+    if (type & DNS_LOOKUP_AAAA) {
+      /* Now send the ipv6 query. */
+      q->remaining++;
+      len = make_header(buf, q->id);
+      len += cut_host(q->query, buf + len);
+      buf[len] = 0; len++; buf[len] = DNS_AAAA; len++;
+      buf[len] = 0; len++; buf[len] = 1; len++;
+
+      egg_dns_send(buf, len);
+    }
 #endif
 #endif
   } else if (q->ip) {
   } else if (q->ip) {
-    q->remaining = 1;
+    q->remaining++;
     len = make_header(buf, q->id);
     len = make_header(buf, q->id);
     len += cut_host(q->ip, buf + len);
     len += cut_host(q->ip, buf + len);
     buf[len] = 0; len++; buf[len] = DNS_PTR; len++;
     buf[len] = 0; len++; buf[len] = DNS_PTR; len++;
@@ -460,7 +465,7 @@ void dns_create_timeout_timer(dns_query_t **qm, const char *query, int timeout)
 /* Perform an async dns lookup. This is host -> ip. For ip -> host, use
 /* Perform an async dns lookup. This is host -> ip. For ip -> host, use
  * egg_dns_reverse(). We return a dns id that you can use to cancel the
  * egg_dns_reverse(). We return a dns id that you can use to cancel the
  * lookup. */
  * lookup. */
-int egg_dns_lookup(const char *host, interval_t timeout, dns_callback_t callback, void *client_data)
+int egg_dns_lookup(const char *host, interval_t timeout, dns_callback_t callback, void *client_data, int type)
 {
 {
 	dns_query_t *q = NULL;
 	dns_query_t *q = NULL;
 	int i, cache_id;
 	int i, cache_id;
@@ -509,7 +514,7 @@ int egg_dns_lookup(const char *host, interval_t timeout, dns_callback_t callback
         q = alloc_query(client_data, callback, host);
         q = alloc_query(client_data, callback, host);
 
 
 	sdprintf("egg_dns_lookup(%s, %d) -> %d", host, timeout, q->id);
 	sdprintf("egg_dns_lookup(%s, %d) -> %d", host, timeout, q->id);
-        dns_send_query(q);
+        dns_send_query(q, type);
 
 
 //        /* setup a timer to detect dead ns */
 //        /* setup a timer to detect dead ns */
 //	dns_create_timeout_timer(&q, host, timeout);
 //	dns_create_timeout_timer(&q, host, timeout);
@@ -821,7 +826,7 @@ static int cut_host(const char *host, char *query)
 	return(query-orig);
 	return(query-orig);
 }
 }
 
 
-static int reverse_ip(const char *host, char *reverse)
+int reverse_ip(const char *host, char *reverse)
 {
 {
 	const char *period = NULL;
 	const char *period = NULL;
 	int offset, len;
 	int offset, len;

+ 5 - 1
src/adns.h

@@ -30,6 +30,9 @@ TXT             16 text strings
 #define DNS_PTR		12
 #define DNS_PTR		12
 #define DNS_AAAA	28
 #define DNS_AAAA	28
 
 
+#define DNS_LOOKUP_A    1
+#define DNS_LOOKUP_AAAA 2
+
 
 
 #define DNS_IPV4	1
 #define DNS_IPV4	1
 #define DNS_IPV6	2
 #define DNS_IPV6	2
@@ -43,12 +46,13 @@ int egg_dns_init(void);
 //int egg_dns_shutdown(void);
 //int egg_dns_shutdown(void);
 
 
 void egg_dns_send(char *query, int len);
 void egg_dns_send(char *query, int len);
-int egg_dns_lookup(const char *host, interval_t timeout, dns_callback_t callback, void *client_data);
+int egg_dns_lookup(const char *host, interval_t timeout, dns_callback_t callback, void *client_data, int type = (DNS_LOOKUP_A|DNS_LOOKUP_AAAA));
 int egg_dns_reverse(const char *ip, interval_t timeout, dns_callback_t callback, void *client_data);
 int egg_dns_reverse(const char *ip, interval_t timeout, dns_callback_t callback, void *client_data);
 int egg_dns_cancel(int id, int issue_callback);
 int egg_dns_cancel(int id, int issue_callback);
 void tell_dnsdebug(int);
 void tell_dnsdebug(int);
 void dns_cache_flush();
 void dns_cache_flush();
 bool valid_dns_id(int, int);
 bool valid_dns_id(int, int);
+int reverse_ip(const char *host, char *reverse);
 
 
 extern int		dns_sock, dns_idx;
 extern int		dns_sock, dns_idx;
 extern const char	*dns_ip;
 extern const char	*dns_ip;

+ 2 - 1
src/chan.h

@@ -231,7 +231,7 @@ struct chanset_t {
 #define CHAN_BOTBITCH       BIT7        /* only let bots be opped? */
 #define CHAN_BOTBITCH       BIT7        /* only let bots be opped? */
 #define CHAN_BACKUP         BIT8	/* Join the BOT_BACKUP bots when set */
 #define CHAN_BACKUP         BIT8	/* Join the BOT_BACKUP bots when set */
 #define CHAN_SECRET         BIT9	/* don't advertise channel on botnet  */
 #define CHAN_SECRET         BIT9	/* don't advertise channel on botnet  */
-#undef  CHAN_10		    /* BIT10        not used */
+#define CHAN_RBL            BIT10	/* Lookup users in RBL (requires +r) */
 #define CHAN_CYCLE          BIT11	/* cycle the channel if possible      */
 #define CHAN_CYCLE          BIT11	/* cycle the channel if possible      */
 #define CHAN_INACTIVE       BIT12	/* no irc support for this channel */
 #define CHAN_INACTIVE       BIT12	/* no irc support for this channel */
 #define CHAN_VOICE          BIT13	/* a bot +y|y will voice *, except +q */
 #define CHAN_VOICE          BIT13	/* a bot +y|y will voice *, except +q */
@@ -302,6 +302,7 @@ struct chanset_t *findchan_by_dname(const char *name);
 #define channel_nomassjoin(chan) (chan->status & CHAN_NOMASSJOIN)
 #define channel_nomassjoin(chan) (chan->status & CHAN_NOMASSJOIN)
 #define channel_knock(chan) (chan->status & CHAN_KNOCK)
 #define channel_knock(chan) (chan->status & CHAN_KNOCK)
 #define channel_meankicks(chan) (chan->status & CHAN_MEANKICKS)
 #define channel_meankicks(chan) (chan->status & CHAN_MEANKICKS)
+#define channel_rbl(chan) (chan->status & CHAN_RBL)
 /* Chanflag template
 /* Chanflag template
  *#define channel_temp(chan) (chan->status & CHAN_PRIVATE)
  *#define channel_temp(chan) (chan->status & CHAN_PRIVATE)
  */
  */

+ 2 - 0
src/mod/channels.mod/channels.c

@@ -886,6 +886,8 @@ void channels_report(int idx, int details)
           i += my_strcpy(s + i, "knock ");
           i += my_strcpy(s + i, "knock ");
         if (channel_meankicks(chan))
         if (channel_meankicks(chan))
           i += my_strcpy(s + i, "meankicks ");
           i += my_strcpy(s + i, "meankicks ");
+        if (channel_rbl(chan))
+          i += my_strcpy(s + i, "rbl ");
 /* Chanflag template
 /* Chanflag template
  *	if (channel_temp(chan))
  *	if (channel_temp(chan))
  *	  i += my_strcpy(s + i, "temp ");
  *	  i += my_strcpy(s + i, "temp ");

+ 1 - 1
src/mod/channels.mod/channels.h

@@ -43,7 +43,7 @@ void write_invites(bd::Stream&, int);
 bool expired_mask(struct chanset_t *, char *);
 bool expired_mask(struct chanset_t *, char *);
 void set_handle_laston(char *, struct userrec *, time_t);
 void set_handle_laston(char *, struct userrec *, time_t);
 int u_delmask(char type, struct chanset_t *c, char *who, int doit);
 int u_delmask(char type, struct chanset_t *c, char *who, int doit);
-bool u_addmask(char type, struct chanset_t *, char *, char *, char *, time_t, int);
+bool u_addmask(char type, struct chanset_t *, char *, const char *, const char *, time_t, int);
 int u_sticky_mask(maskrec *, char *);
 int u_sticky_mask(maskrec *, char *);
 int u_setsticky_mask(struct chanset_t *, maskrec *, char *, int, const char);
 int u_setsticky_mask(struct chanset_t *, maskrec *, char *, int, const char);
 int SplitList(char *, const char *, int *, const char ***);
 int SplitList(char *, const char *, int *, const char ***);

+ 3 - 2
src/mod/channels.mod/cmdschan.c

@@ -1242,13 +1242,14 @@ static void cmd_chaninfo(int idx, char *par)
     SHOW_FLAG("enforcebans", 	channel_enforcebans(chan));
     SHOW_FLAG("enforcebans", 	channel_enforcebans(chan));
     SHOW_FLAG("fastop",		channel_fastop(chan));
     SHOW_FLAG("fastop",		channel_fastop(chan));
     SHOW_FLAG("inactive",	channel_inactive(chan));
     SHOW_FLAG("inactive",	channel_inactive(chan));
+    SHOW_FLAG("knock",          channel_knock(chan));
     SHOW_FLAG("meankicks",	channel_meankicks(chan));
     SHOW_FLAG("meankicks",	channel_meankicks(chan));
     SHOW_FLAG("nodesynch",	channel_nodesynch(chan));
     SHOW_FLAG("nodesynch",	channel_nodesynch(chan));
     SHOW_FLAG("nomassjoin",	channel_nomassjoin(chan));
     SHOW_FLAG("nomassjoin",	channel_nomassjoin(chan));
     SHOW_FLAG("private",	channel_privchan(chan));
     SHOW_FLAG("private",	channel_privchan(chan));
-    SHOW_FLAG("knock",          channel_knock(chan));
-//    SHOW_FLAG("revenge",	channel_revenge(chan));
+    SHOW_FLAG("rbl",		channel_rbl(chan));
 //    SHOW_FLAG("revengebot",	channel_revengebot(chan));
 //    SHOW_FLAG("revengebot",	channel_revengebot(chan));
+//    SHOW_FLAG("revenge",	channel_revenge(chan));
     if (HAVE_TAKE)
     if (HAVE_TAKE)
       SHOW_FLAG("take",		channel_take(chan));
       SHOW_FLAG("take",		channel_take(chan));
     SHOW_FLAG("voice",		channel_voice(chan));
     SHOW_FLAG("voice",		channel_voice(chan));

+ 4 - 0
src/mod/channels.mod/tclchan.c

@@ -607,6 +607,10 @@ int channel_modify(char *result, struct chanset_t *chan, int items, char **item,
       chan->status |= CHAN_MEANKICKS;
       chan->status |= CHAN_MEANKICKS;
     else if (!strcmp(item[i], "-meankicks"))
     else if (!strcmp(item[i], "-meankicks"))
       chan->status &= ~CHAN_MEANKICKS;
       chan->status &= ~CHAN_MEANKICKS;
+    else if (!strcmp(item[i], "+rbl"))
+      chan->status |= CHAN_RBL;
+    else if (!strcmp(item[i], "-rbl"))
+      chan->status &= ~CHAN_RBL;
 /* Chanflag template
 /* Chanflag template
  *  else if (!strcmp(item[i], "+temp"))
  *  else if (!strcmp(item[i], "+temp"))
  *    chan->status |= CHAN_TEMP;
  *    chan->status |= CHAN_TEMP;

+ 3 - 2
src/mod/channels.mod/userchan.c

@@ -309,7 +309,7 @@ int u_delmask(char type, struct chanset_t *c, char *who, int doit)
 
 
 /* Note: If first char of note is '*' it's a sticky mask.
 /* Note: If first char of note is '*' it's a sticky mask.
  */
  */
-bool u_addmask(char type, struct chanset_t *chan, char *who, char *from, char *note, time_t expire_time, int flags)
+bool u_addmask(char type, struct chanset_t *chan, char *who, const char *from, const char *note, time_t expire_time, int flags)
 {
 {
   char host[UHOSTLEN] = "", s[UHOSTLEN] = "";
   char host[UHOSTLEN] = "", s[UHOSTLEN] = "";
   maskrec *p = NULL, *l = NULL, **u = NULL;
   maskrec *p = NULL, *l = NULL, **u = NULL;
@@ -735,7 +735,7 @@ flood-exempt %d flood-lock-time %d \
 %cmeankicks %cenforcebans %cdynamicbans %cuserbans %cbitch \
 %cmeankicks %cenforcebans %cdynamicbans %cuserbans %cbitch \
 %cprivate %ccycle %cinactive %cdynamicexempts %cuserexempts \
 %cprivate %ccycle %cinactive %cdynamicexempts %cuserexempts \
 %cdynamicinvites %cuserinvites %cnodesynch %cclosed %cvoice \
 %cdynamicinvites %cuserinvites %cnodesynch %cclosed %cvoice \
-%cfastop %cautoop %cbotbitch %cbackup %cnomassjoin %cknock %c%s}\n",
+%cfastop %cautoop %cbotbitch %cbackup %cnomassjoin %cknock %crbl %c%s}\n",
 	chan->dname,
 	chan->dname,
 	w,
 	w,
         chan->added_by,
         chan->added_by,
@@ -791,6 +791,7 @@ flood-exempt %d flood-lock-time %d \
         PLSMNS(channel_backup(chan)),
         PLSMNS(channel_backup(chan)),
         PLSMNS(channel_nomassjoin(chan)),
         PLSMNS(channel_nomassjoin(chan)),
         PLSMNS(channel_knock(chan)),
         PLSMNS(channel_knock(chan)),
+        PLSMNS(channel_rbl(chan)),
 	HAVE_TAKE ? PLSMNS(channel_take(chan)) : ' ',
 	HAVE_TAKE ? PLSMNS(channel_take(chan)) : ' ',
         HAVE_TAKE ? "take " : " "
         HAVE_TAKE ? "take " : " "
 /* Chanflag template
 /* Chanflag template

+ 131 - 31
src/mod/irc.mod/chan.c

@@ -29,6 +29,7 @@
  *
  *
  */
  */
 
 
+#include <bdlib/src/String.h>
 
 
 static time_t last_ctcp = (time_t) 0L;
 static time_t last_ctcp = (time_t) 0L;
 static int    count_ctcp = 0;
 static int    count_ctcp = 0;
@@ -37,49 +38,50 @@ static char   last_invchan[300] = "";
 
 
 typedef struct resolvstruct {
 typedef struct resolvstruct {
   struct chanset_t *chan;
   struct chanset_t *chan;
-  char *nick;
+  char *host;
+  bd::String* servers;
+  bd::String* server;
 } resolv_member;
 } resolv_member;
 
 
 static void resolv_member_callback(int id, void *client_data, const char *host, char **ips)
 static void resolv_member_callback(int id, void *client_data, const char *host, char **ips)
 {
 {
   resolv_member *r = (resolv_member *) client_data;
   resolv_member *r = (resolv_member *) client_data;
 
 
-  if (!r || !r->chan || !r->nick) {
-    if (r->nick) free(r->nick);
+  if (!r || !r->chan || !r->host || !ips || !ips[0]) {
+    if (r) {
+      if (r->host) free(r->host);
+      free(r);
+    }
     return;
     return;
   }
   }
 
 
   memberlist *m = NULL;
   memberlist *m = NULL;
-  char *ps = NULL, *pe = NULL, s[UHOSTLEN + 1];
-
-  if (ips && ips[0]) {
-    for (m = r->chan->channel.member; m && m->nick[0]; m = m->next) {
-      if (!rfc_casecmp(m->nick, r->nick)) {
-        if (!m->userip[0] && m->userhost[0]) {
-          ps = m->userhost;
-          pe = strchr(ps, '@');
-          if (pe) {
-            char user[15] = "";
-
-            strlcpy(user, m->userhost, pe - ps + 1);
-            simple_snprintf(m->userip, sizeof(m->userip), "%s@%s", user, ips[0]);
-            if (!m->user) {
-              simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userip);
-              m->user = get_user_by_host(s);
-
-              /* Act on this lookup */
-              if (m->user)
-                check_this_user(m->user->handle, 0, NULL);
-            }
-            free(r->nick);
-            return;
-          }
+  char *pe = NULL, s[UHOSTLEN + 1], user[15] = "";
+
+  /* Apply lookup results to all matching members by host */
+  for (m = r->chan->channel.member; m && m->nick[0]; m = m->next) {
+    if (!m->userip[0] && m->userhost[0]) {
+      pe = strchr(m->userhost, '@');
+      if (pe && !strcmp(pe + 1, r->host)) {
+        strlcpy(user, m->userhost, pe - m->userhost + 1);
+        simple_snprintf(m->userip, sizeof(m->userip), "%s@%s", user, ips[0]);
+        if (!m->user) {
+          simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userip);
+          m->user = get_user_by_host(s);
+
+          /* Act on this lookup */
+          if (m->user)
+            check_this_user(m->user->handle, 0, NULL);
         }
         }
       }
       }
     }
     }
   }
   }
 
 
-  free(r->nick);
+  if (channel_rbl(r->chan))
+    resolve_to_rbl(r->chan, ips[0]);
+
+  free(r->host);
+  free(r);
   return;
   return;
 }
 }
 
 
@@ -89,11 +91,102 @@ void resolve_to_member(struct chanset_t *chan, char *nick, char *host)
   resolv_member *r = (resolv_member *) my_calloc(1, sizeof(resolv_member));
   resolv_member *r = (resolv_member *) my_calloc(1, sizeof(resolv_member));
 
 
   r->chan = chan;
   r->chan = chan;
-  r->nick = strdup(nick);
+  r->host = strdup(host);
 
 
   egg_dns_lookup(host, 20, resolv_member_callback, (void *) r);
   egg_dns_lookup(host, 20, resolv_member_callback, (void *) r);
 }
 }
 
 
+/* RBL */
+static void resolve_rbl_callback(int id, void *client_data, const char *host, char **ips)
+{
+  resolv_member *r = (resolv_member *) client_data;
+
+  if (!r || !r->chan || !r->host || !ips || (ips && !ips[0])) {
+    if (r && r->chan && r->host) {
+      // Lookup from the next RBL
+      resolve_to_rbl(r->chan, r->host, r);
+    }
+    return;
+  }
+
+  sdprintf("RBL match for %s:%s: %s", r->chan->dname, r->host, ips[0]);
+
+  char s1[UHOSTLEN] = "";
+  simple_snprintf(s1, sizeof(s1), "*!*@%s", r->host);
+
+  bd::String reason = "Listed in RBL: " + *(r->server);
+
+  u_addmask('b', r->chan, s1, conf.bot->nick, reason.c_str(), now + (60 * (r->chan->ban_time ? r->chan->ban_time : 300)), 0);
+
+  if (me_op(r->chan)) {
+    do_mask(r->chan, r->chan->channel.ban, s1, 'b');
+
+    memberlist *m = NULL;
+    char *pe = NULL;
+
+    /* Apply lookup results to all matching members by host */
+    for (m = r->chan->channel.member; m && m->nick[0]; m = m->next) {
+      if (!m->user && !chan_sentkick(m) && m->userip[0]) {
+        pe = strchr(m->userip, '@');
+        if (pe && !strcmp(pe + 1, r->host)) {
+          m->flags |= SENTKICK;
+          dprintf(DP_MODE, "KICK %s %s :%s%s\n", r->chan->name, m->nick, bankickprefix, reason.c_str());
+        }
+      }
+    }
+  }
+
+  sdprintf("Done checking rbl (matched) for %s:%s", r->chan->dname, r->host);
+  delete r->servers;
+  delete r->server;
+  free(r->host);
+  free(r);
+  return;
+}
+
+
+void resolve_to_rbl(struct chanset_t *chan, char *host, resolv_member *r)
+{
+  if (!r) {
+    r = (resolv_member *) my_calloc(1, sizeof(resolv_member));
+
+    r->chan = chan;
+    r->host = strdup(host);
+    r->servers = new bd::String(rbl_servers);
+    r->server = new bd::String;
+  }
+
+  bd::String rbl_server = newsplit(*(r->servers), ',');
+
+  if (!rbl_server) {
+    sdprintf("Done checking rbl (no match) for %s:%s", chan->dname, host);
+    delete r->servers;
+    delete r->server;
+    free(r->host);
+    free(r);
+    return; //No more servers
+  }
+
+  *(r->server) = rbl_server;
+
+  size_t iplen = strlen(host) + 1 + rbl_server.length() + 1;
+  char *ip = (char *) my_calloc(1, iplen);
+  reverse_ip(host, ip);
+  strlcat(ip, ".", iplen);
+  strlcat(ip, rbl_server.c_str(), iplen);
+
+  if (egg_dns_lookup(ip, 20, resolve_rbl_callback, (void *) r, DNS_A) == -2) { //Already querying?
+    // Querying on clones will cause the callback to not be called and this nick will be ignored
+    // cleanup memory as this chain is not even starting.
+    delete r->servers;
+    delete r->server;
+    free(r->host);
+    free(r);
+  }
+
+  free(ip);
+}
+
 /* ID length for !channels.
 /* ID length for !channels.
  */
  */
 #define CHANNEL_ID_LEN 5
 #define CHANNEL_ID_LEN 5
@@ -1782,6 +1875,9 @@ static int got352or4(struct chanset_t *chan, char *user, char *host, char *nick,
   //This bot is set +r, so resolve.
   //This bot is set +r, so resolve.
   if (!m->userip[0] && doresolv(chan))
   if (!m->userip[0] && doresolv(chan))
     resolve_to_member(chan, nick, host);
     resolve_to_member(chan, nick, host);
+  else if (!me && !m->user && m->userip[0] && doresolv(chan) && channel_rbl(chan))
+    resolve_to_rbl(chan, host);
+
 
 
   get_user_flagrec(m->user, &fr, chan->dname, chan);
   get_user_flagrec(m->user, &fr, chan->dname, chan);
   
   
@@ -2475,9 +2571,11 @@ static int gotjoin(char *from, char *chname)
           m->tried_getuser = 1;
           m->tried_getuser = 1;
  
  
           if (!m->user && !m->userip[0] && doresolv(chan)) {
           if (!m->user && !m->userip[0] && doresolv(chan)) {
-            if (is_dotted_ip(host))
+            if (is_dotted_ip(host)) {
               strlcpy(m->userip, uhost, sizeof(m->userip));
               strlcpy(m->userip, uhost, sizeof(m->userip));
-            else
+              if (channel_rbl(chan))
+                resolve_to_rbl(chan, host);
+            } else
               resolve_to_member(chan, nick, host);
               resolve_to_member(chan, nick, host);
           }
           }
         }
         }
@@ -2498,6 +2596,8 @@ static int gotjoin(char *from, char *chname)
 
 
         if (!m->userip[0] && doresolv(chan))
         if (!m->userip[0] && doresolv(chan))
           resolve_to_member(chan, nick, host);
           resolve_to_member(chan, nick, host);
+        else if (!m->user && m->userip[0] && doresolv(chan) && channel_rbl(chan))
+          resolve_to_rbl(chan, host);
 
 
 //	m->flags |= STOPWHO;
 //	m->flags |= STOPWHO;
 
 

+ 1 - 0
src/mod/irc.mod/irc.c

@@ -28,6 +28,7 @@
 #include "src/common.h"
 #include "src/common.h"
 #define MAKING_IRC
 #define MAKING_IRC
 #include "irc.h"
 #include "irc.h"
+#include "src/adns.h"
 #include "src/match.h"
 #include "src/match.h"
 #include "src/settings.h"
 #include "src/settings.h"
 #include "src/tandem.h"
 #include "src/tandem.h"

+ 9 - 0
src/mod/irc.mod/irc.h

@@ -22,6 +22,10 @@ enum { BC_NOCOOKIE = 1, BC_SLACK, BC_HASH };
 
 
 #ifdef MAKING_IRC
 #ifdef MAKING_IRC
 
 
+namespace bd {
+  class String;
+}
+
 #ifdef CACHE
 #ifdef CACHE
 typedef struct cache_chan_b {
 typedef struct cache_chan_b {
   struct cache_chan_b *next;
   struct cache_chan_b *next;
@@ -94,6 +98,11 @@ static void send_chan_who(int queue, struct chanset_t* chan);
 #define newban(chan, mask, who)         new_mask((chan)->channel.ban, mask, who)
 #define newban(chan, mask, who)         new_mask((chan)->channel.ban, mask, who)
 #define newexempt(chan, mask, who)      new_mask((chan)->channel.exempt, mask, who)
 #define newexempt(chan, mask, who)      new_mask((chan)->channel.exempt, mask, who)
 #define newinvite(chan, mask, who)      new_mask((chan)->channel.invite, mask, who)
 #define newinvite(chan, mask, who)      new_mask((chan)->channel.invite, mask, who)
+void resolve_to_member(struct chanset_t *chan, char *nick, char *host);
+
+typedef struct resolvstruct resolv_member;
+void resolve_to_rbl(struct chanset_t *chan, char *host, struct resolvstruct *r = NULL);
+static void do_mask(struct chanset_t *chan, masklist *m, char *mask, char Mode);
 
 
 #endif /* MAKING_IRC */
 #endif /* MAKING_IRC */
 
 

+ 3 - 0
src/set.c

@@ -29,6 +29,7 @@ static bool parsing_botset = 0;
 
 
 char altchars[50] = "";
 char altchars[50] = "";
 char alias[1024] = "";
 char alias[1024] = "";
+char rbl_servers[1024] = "";
 bool auth_chan;
 bool auth_chan;
 char auth_key[51] = "";
 char auth_key[51] = "";
 char auth_prefix[2] = "";
 char auth_prefix[2] = "";
@@ -64,6 +65,7 @@ bool manop_warn;
 char homechan[51] = "";
 char homechan[51] = "";
 char usermode[15] = "";
 char usermode[15] = "";
 
 
+////// THIS MUST REMAIN SORTED
 // VAR("bad-process",	&badprocess,		VAR_INT|VAR_DETECTED,				0, 4, "ignore"),
 // VAR("bad-process",	&badprocess,		VAR_INT|VAR_DETECTED,				0, 4, "ignore"),
 // VAR("process-list",	process_list,		VAR_STRING|VAR_LIST,				0, 0, NULL),
 // VAR("process-list",	process_list,		VAR_STRING|VAR_LIST,				0, 0, NULL),
 static variable_t vars[] = {
 static variable_t vars[] = {
@@ -105,6 +107,7 @@ static variable_t vars[] = {
  VAR("op-bots",		&op_bots,		VAR_INT|VAR_NOLOC,				1, MAX_BOTS, "1"),
  VAR("op-bots",		&op_bots,		VAR_INT|VAR_NOLOC,				1, MAX_BOTS, "1"),
  VAR("op-requests",	&op_requests,		VAR_RATE|VAR_NOLOC,				0, 0, "2:5"),
  VAR("op-requests",	&op_requests,		VAR_RATE|VAR_NOLOC,				0, 0, "2:5"),
  VAR("promisc",		&promisc,		VAR_INT|VAR_DETECTED,				0, 4, "warn"),
  VAR("promisc",		&promisc,		VAR_INT|VAR_DETECTED,				0, 4, "warn"),
+ VAR("rbl-servers",	rbl_servers,		VAR_STRING|VAR_LIST|VAR_SHUFFLE|VAR_NOLHUB,	0, 0, DEFAULT_RBL),
  VAR("realname",	botrealname,		VAR_STRING|VAR_NOLHUB,				0, 0, "* I'm too lame to read BitchX.doc *"),
  VAR("realname",	botrealname,		VAR_STRING|VAR_NOLHUB,				0, 0, "* I'm too lame to read BitchX.doc *"),
  VAR("server-port",	&default_port,		VAR_INT|VAR_SHORT|VAR_NOLHUB,			0, 65535, "6667"),
  VAR("server-port",	&default_port,		VAR_INT|VAR_SHORT|VAR_NOLHUB,			0, 65535, "6667"),
  VAR("servers",		&serverlist,		VAR_SERVERS|VAR_LIST|VAR_SHUFFLE|VAR_NOLHUB|VAR_NOLDEF,	0, 0, DEFAULT_SERVERS),
  VAR("servers",		&serverlist,		VAR_SERVERS|VAR_LIST|VAR_SHUFFLE|VAR_NOLHUB|VAR_NOLDEF,	0, 0, DEFAULT_SERVERS),

+ 1 - 1
src/set.h

@@ -67,7 +67,7 @@ typedef struct rate_b {
  interval_t time;
  interval_t time;
 } rate_t;
 } rate_t;
 
 
-extern char		auth_key[], auth_prefix[2], motd[], *def_chanset, alias[],
+extern char		auth_key[], auth_prefix[2], motd[], *def_chanset, alias[], rbl_servers[1024],
 			msgident[], msginvite[], msgop[], msgpass[],
 			msgident[], msginvite[], msgop[], msgpass[],
                         homechan[], altchars[];
                         homechan[], altchars[];
 extern bool		dccauth, auth_obscure, manop_warn, auth_chan, oidentd, ident_botnick, irc_autoaway, link_cleartext;
 extern bool		dccauth, auth_obscure, manop_warn, auth_chan, oidentd, ident_botnick, irc_autoaway, link_cleartext;