--- Makefile.orig	Mon Apr 23 15:20:25 2001
+++ Makefile	Mon Apr 23 15:24:51 2001
@@ -7,6 +7,8 @@
 # to use cleartext passwords (a bad idea on production systems) add
 # -DCLEARTEXTPASSWD to the LDAPFLAGS
 LDAPFLAGS=-DQLDAP_CLUSTER
+RBLTAGON=-DRBLTAG
+
 
 # Perhaps you have different ldap libraries, change them here
 LDAPLIBS=-L/usr/local/lib -lldap -llber
@@ -1578,11 +1580,12 @@
 load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \
 date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \
 getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \
-str.a fs.a auto_qmail.o
+str.a fs.a auto_qmail.o dns.o ipalloc.o
 	./load qmail-qmtpd rcpthosts.o control.o constmap.o \
 	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
 	datetime.a open.a getln.a sig.a case.a env.a stralloc.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o 
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+	dns.o ipalloc.o ip.o `cat dns.lib`
 
 qmail-qmtpd.0: \
 qmail-qmtpd.8
@@ -1592,7 +1595,7 @@
 compile qmail-qmtpd.c stralloc.h gen_alloc.h substdio.h qmail.h \
 substdio.h now.h datetime.h str.h fmt.h env.h sig.h rcpthosts.h \
 auto_qmail.h readwrite.h control.h received.h
-	./compile qmail-qmtpd.c
+	./compile ${RBLTAGON} qmail-qmtpd.c
 
 qmail-qread: \
 load qmail-qread.o fmtqfn.o readsubdir.o date822fmt.o datetime.a \
@@ -1790,7 +1793,7 @@
 error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
 substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
 exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
-	./compile ${TLSON} ${TLSINCLUDES} qmail-smtpd.c
+	./compile ${RBLTAGON} ${TLSON} ${TLSINCLUDES} qmail-smtpd.c
 
 qmail-start: \
 load qmail-start.o prot.o fd.a auto_uids.o
--- qmail-showctl.c.orig	Mon Apr 23 15:27:51 2001
+++ qmail-showctl.c	Mon Apr 23 15:28:31 2001
@@ -300,6 +300,7 @@
   do_lst("badrcptto","Any RCPT TO is allowed.",""," not accepted in RCPT TO");
   do_lst("relaymailfrom","Relaymailfrom not enabled.","Envelope senders allowed to relay: ",".");
   do_lst("rbllist","No RBL listed.","RBL to check: ",".");
+  do_lst("rbltags","No RBL listed.","RBL to check: ",".");
 
   substdio_puts(subfdout,"\n");
   
--- qmail-smtpd.c.orig	Mon Apr 23 15:29:23 2001
+++ qmail-smtpd.c	Mon Apr 23 11:47:09 2001
@@ -186,6 +186,9 @@
 char *relayok;
 char *denymail;
 char *rblenabled;
+#ifdef RBLTAG
+  char *rbltagenabled;
+#endif
 int  spamflag = 0;
 
 stralloc helohost = {0};
@@ -207,6 +210,10 @@
 struct constmap maprmf;
 int rblok = 0;
 stralloc rbl = {0};
+#ifdef RBLTAG
+int rbltagok = 0;
+stralloc rbltag = {0};
+#endif
 int tarpitcount = 0;
 int tarpitdelay = 5;
 int maxrcptcount = 0;
@@ -263,7 +270,14 @@
   if (rblok == -1) die_control();
   if (rblok)
     rblenabled = env_get("RBL");
-  
+
+#ifdef RBLTAG
+  rbltagok = control_readfile(&rbltag,"control/rbltags",0);
+  if (rbltagok == -1) die_control();
+  if (rbltagok)
+    rbltagenabled = "1";
+#endif
+   
   if (control_readint(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
   if (x) { scan_ulong(x,&u); databytes = u; }
@@ -388,6 +402,9 @@
 /* RBL */
 
 stralloc ip_reverse;
+#ifdef RBLTAG
+stralloc tagrblid;
+#endif
 
 void rbl_init()
 {
@@ -470,6 +487,41 @@
   return r;
 }
 
+#ifdef RBLTAG
+int rblcheck_tag()
+{
+  int r;
+  char *p; 
+  rbl_init();
+
+  p = &rbltag.s[0];
+  while(p < &rbltag.s[0]+rbltag.len)
+  {  
+    logpid(2); logstring(2,"RBL check with '"); logstring(2,p); logstring(2,"':");
+    r = rbl_lookup(p);
+     switch(r) { 
+       case 2:
+         logstring(2,"temporary DNS error");
+		  break;
+       case 1:
+         logstring(2,"found match");
+         if ( 0 != tagrblid.len ) if (!stralloc_cats(&tagrblid," ")) die_nomem();
+         if (!stralloc_cats(&tagrblid,p)) die_nomem();
+         break;
+       default:
+         logstring(2, "no match");
+	 	  break;
+    }
+    /* continue */
+    logflush();
+    p = p+strlen(p);
+    p++;
+  }
+  if ( 0 != tagrblid.len ) tagrblid.s[tagrblid.len]='\0'; 
+  return r;
+}
+#endif
+
 /* RBL */
 
 int sizelimit(arg)
@@ -638,7 +690,14 @@
     logline(3,"RBL checking completed without match");
     }
   }
-
+#ifdef RBLTAG
+  if (rbltagenabled && !relayclient)
+  {
+    logline(3,"RBL TAGGING enabled, going through list of RBLs");
+    rblcheck_tag();
+  }
+#endif
+   
   /* DENYMAIL is set for this session from this client, so heavy checking
    * of mailfrom is done. If one of the following is set:
    * SPAM     -> refuse all mail
@@ -865,6 +924,37 @@
   return r;
 }
 
+#ifdef RBLTAG
+void rblcheckfmt(qqt, rblid)
+struct qmail *qqt;
+char *rblid;
+{
+ unsigned int j,k;
+ 
+ if (!rblid) return;
+ 
+ j=0;
+ while ('\0'!=rblid[j] && ' '==rblid[j]) j++;           /* eat up whitespace */
+ k=j;
+ while ('\0' != rblid[j]) {
+   if (' ' == rblid[j]) {
+     rblid[j] = '\0';
+     qmail_puts(qqt,"X-RBL-Check: ");
+     qmail_puts(qqt,rblid+k);
+     qmail_puts(qqt,"\n");
+     rblid[j] = ' ';
+     while (' ' == rblid[++j]);         /* eat up whitespace */
+     k=j;
+   } else j++;
+ }
+ if (j!=k) {
+   qmail_puts(qqt,"X-RBL-Check: ");
+   qmail_puts(qqt,rblid+k);
+   qmail_puts(qqt,"\n");
+ }
+}
+#endif
+
 char ssinbuf[1024];
 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
 
@@ -992,6 +1082,9 @@
 #else 
   received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo,mailfrom.s,&rcptto.s[1]);
 #endif
+#ifdef RBLTAG  
+  rblcheckfmt(&qqt, tagrblid.s);
+#endif 
   blast(&hops);
 
   receivedbytes[fmt_ulong(receivedbytes,(unsigned long) bytesreceived)] = 0;
--- qmail-qmtpd.c.orig	Mon Apr 23 15:29:38 2001
+++ qmail-qmtpd.c	Mon Apr 23 12:20:25 2001
@@ -12,6 +12,11 @@
 #include "control.h"
 #include "received.h"
 
+#ifdef RBLTAG
+  #include "ipalloc.h"
+  #include "dns.h"
+#endif
+
 void badproto() { _exit(100); }
 void resources() { _exit(111); }
 
@@ -73,6 +78,129 @@
 
 char *relayclient;
 int relayclientlen;
+#ifdef RBLTAG
+char *rbltagenabled;
+int rbltagok = 0;
+stralloc rbltag = {0};
+#endif
+
+/* RBL */
+
+stralloc ip_reverse;
+#ifdef RBLTAG
+stralloc tagrblid;
+
+void rbl_init()
+{
+  unsigned int i;
+  unsigned int j;
+  char *ip_env;
+
+  ip_env = remoteip;
+  if (!ip_env) ip_env = "";
+
+  if (!stralloc_copys(&ip_reverse,"")) resources();
+
+  i = str_len(ip_env);
+  while (i) {
+    for (j = i;j > 0;--j) if (ip_env[j - 1] == '.') break;
+    if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) resources();
+    if (!stralloc_cats(&ip_reverse,".")) resources();
+    if (!j) break;
+    i = j - 1;
+  }
+}
+
+stralloc rbl_tmp;
+
+int rbl_lookup(char *base)
+{
+  ipalloc rblsa = {0};
+
+  if (!*base) return 2;
+
+  if (!stralloc_copys(&rbl_tmp,"")) resources();
+
+  if (!stralloc_copy(&rbl_tmp,&ip_reverse)) resources();
+  if (!stralloc_cats(&rbl_tmp,base)) resources();
+
+  switch (dns_ip(&rblsa,&rbl_tmp))
+  {
+    case DNS_MEM:
+    case DNS_SOFT:
+         return 2; /* soft error */
+         break;
+
+    case DNS_HARD:
+         return 0; /* found no match */
+         break;
+
+    default:
+         return 1; /* found match */
+         break;
+  }
+}
+
+int rblcheck_tag()
+{
+  int r;
+  char *p; 
+  rbl_init();
+
+  p = &rbltag.s[0];
+  while(p < &rbltag.s[0]+rbltag.len)
+  {  
+    r = rbl_lookup(p);
+     switch(r) { 
+       case 2:
+		 break;
+       case 1:
+         if ( 0 != tagrblid.len ) if (!stralloc_cats(&tagrblid," ")) resources();
+         if (!stralloc_cats(&tagrblid,p)) resources();
+         break;
+       default:
+	 break;
+    }
+    /* continue */
+    p = p+strlen(p);
+    p++;
+  }
+  if ( 0 != tagrblid.len ) tagrblid.s[tagrblid.len]='\0'; 
+  return r;
+}
+
+void rblcheckfmt(qqt, rblid)
+struct qmail *qqt;
+char *rblid;
+{
+ unsigned int j,k;
+ 
+ if (!rblid) return;
+ 
+ j=0;
+ while ('\0'!=rblid[j] && ' '==rblid[j]) j++;           /* eat up whitespace */
+ k=j;
+ while ('\0' != rblid[j]) {
+   if (' ' == rblid[j]) {
+     rblid[j] = '\0';
+     qmail_puts(qqt,"X-RBL-Check: ");
+     qmail_puts(qqt,rblid+k);
+     qmail_puts(qqt,"\n");
+     rblid[j] = ' ';
+     while (' ' == rblid[++j]);         /* eat up whitespace */
+     k=j;
+   } else j++;
+ }
+ if (j!=k) {
+   qmail_puts(qqt,"X-RBL-Check: ");
+   qmail_puts(qqt,rblid+k);
+   qmail_puts(qqt,"\n");
+ }
+}
+#endif
+/* RBL */
+
+
 
 main()
 {
@@ -112,6 +240,14 @@
   local = env_get("TCPLOCALHOST");
   if (!local) local = env_get("TCPLOCALIP");
   if (!local) local = "unknown";
+#ifdef RBLTAG
+  rbltagok = control_readfile(&rbltag,"control/rbltags",0);
+  if (rbltagok == -1) resources();
+  if (rbltagok)
+  {
+    rblcheck_tag();
+  }
+#endif
  
   for (;;) {
     if (!stralloc_copys(&failure,"")) resources();
@@ -131,6 +267,9 @@
     else badproto();
  
     received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0,(char *) 0,(char *) 0);
+#ifdef RBLTAG  
+    rblcheckfmt(&qq, tagrblid.s);
+#endif 
  
     /* XXX: check for loops? only if len is big? */
  
