diff -urN qmail-1.03.orig/Makefile qmail-1.03-smtpd/Makefile
--- qmail-1.03.orig/Makefile	Mon Jun 15 04:53:16 1998
+++ qmail-1.03-smtpd/Makefile	Wed Oct  1 11:04:16 2003
@@ -1536,13 +1536,13 @@
 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
 date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
 open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
-fs.a auto_qmail.o socket.lib
+fs.a auto_qmail.o socket.lib dns.o dns.lib
 	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
 	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
 	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
 	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
 	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
-	socket.lib`
+	socket.lib` dns.o `cat dns.lib`
 
 qmail-smtpd.0: \
 qmail-smtpd.8
diff -urN qmail-1.03.orig/qmail-smtpd.c qmail-1.03-smtpd/qmail-smtpd.c
--- qmail-1.03.orig/qmail-smtpd.c	Mon Jun 15 04:53:16 1998
+++ qmail-1.03-smtpd/qmail-smtpd.c	Wed Oct  1 13:09:55 2003
@@ -23,10 +23,13 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "dns.h"
 
 #define MAXHOPS 100
 unsigned int databytes = 0;
+unsigned int mfchk = 1;
 int timeout = 1200;
+#define BADIP -4
 
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
@@ -38,9 +41,26 @@
 
 char ssoutbuf[512];
 substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
+char sserrbuf[512];
+substdio sserr = SUBSTDIO_FDBUF(safewrite,2,sserrbuf,sizeof sserrbuf);
 
 void flush() { substdio_flush(&ssout); }
 void out(s) char *s; { substdio_puts(&ssout,s); }
+void log1(s1) char *s1; {
+ substdio_putsflush(&sserr,s1); }
+void log2(s1,s2) char *s1; char *s2; {
+ substdio_putsflush(&sserr,s1);
+ substdio_putsflush(&sserr,s2); }
+void log3(s1,s2,s3) char *s1; char *s2; char *s3; {
+ substdio_putsflush(&sserr,s1);
+ substdio_putsflush(&sserr,s2);
+ substdio_putsflush(&sserr,s3); }
+void log5(s1,s2,s3,s4,s5) char *s1; char *s2; char *s3; char *s4; char *s5; {
+ substdio_putsflush(&sserr,s1);
+ substdio_putsflush(&sserr,s2);
+ substdio_putsflush(&sserr,s3);
+ substdio_putsflush(&sserr,s4);
+ substdio_putsflush(&sserr,s5); }
 
 void die_read() { _exit(1); }
 void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); }
@@ -49,8 +69,8 @@
 void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
 void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
 
-void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
-void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
+void err_mailrefused() { out("553 sorry, mail refused (#5.7.1)\r\n"); }
+void err_mailrefusedtemp() { out("451 sorry, mail refused due to temporary error (#4.3.0)\r\n"); }
 void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
 void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
 void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
@@ -96,6 +116,10 @@
 int bmfok = 0;
 stralloc bmf = {0};
 struct constmap mapbmf;
+int bhok = 0;
+stralloc bh = {0};
+struct constmap mapbh;
+char mypid[FMT_ULONG];
 
 void setup()
 {
@@ -112,11 +136,21 @@
 
   if (rcpthosts_init() == -1) die_control();
 
+  x = env_get("NOMFCHECK");
+  if (x) { mfchk = 0; }
+
   bmfok = control_readfile(&bmf,"control/badmailfrom",0);
   if (bmfok == -1) die_control();
   if (bmfok)
     if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
  
+  bhok = control_readfile(&bh,"control/badhelo",0);
+  if (bhok == -1) die_control();
+  x = env_get("NOBADHELO");
+  if (x) { bhok = 0; }
+  if (bhok)
+    if (!constmap_init(&mapbh,bh.s,bh.len,0)) die_nomem();
+ 
   if (control_readint(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
   if (x) { scan_ulong(x,&u); databytes = u; }
@@ -132,6 +166,7 @@
   remoteinfo = env_get("TCPREMOTEINFO");
   relayclient = env_get("RELAYCLIENT");
   dohelo(remotehost);
+  mypid[fmt_ulong(mypid,getpid())] = 0;
 }
 
 
@@ -197,14 +232,70 @@
   return 1;
 }
 
+int helocheck()
+{
+  int j;
+  if (!bhok) return 0;
+  if (constmap(&mapbh,helohost.s,helohost.len - 1)) {
+    log5("pid ",mypid," badhelo ",helohost.s,"\n");
+    return 1;
+  }
+  return 0;
+}
+
 int bmfcheck()
 {
   int j;
   if (!bmfok) return 0;
-  if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1;
+  if (constmap(&mapbmf,addr.s,addr.len - 1)) {
+    log5("pid ",mypid," badmailfrom ",addr.s,"\n");
+    return 1;
+  }
   j = byte_rchr(addr.s,addr.len,'@');
   if (j < addr.len)
-    if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1;
+    if (constmap(&mapbmf,addr.s + j,addr.len - j - 1))  {
+      log5("pid ",mypid," badmailfrom ",addr.s,"\n");
+      return 1;
+    }
+  return 0;
+}
+
+int mfcheck()
+{
+  stralloc sa = {0};
+  ipalloc ia = {0};
+  unsigned int random;
+  int j;
+  char ipbuf[IPFMT];
+  unsigned char *o;
+  
+  if (!mfchk) return 0;
+  random = now() + (getpid() << 16);
+  j = byte_rchr(addr.s,addr.len,'@') + 1;
+  if (j < addr.len) {
+    stralloc_copys(&sa, addr.s + j);
+    dns_init(0);
+    j = dns_mxip(&ia,&sa,random);
+    if (j < 0) {
+      log3("pid ",mypid," mfcheck ");
+      switch(j) {
+        case DNS_HARD: log1("permanent "); break;
+        case DNS_SOFT: log1("temporary "); break;
+        case DNS_MEM: die_nomem();
+      }
+      log2(addr.s,"\n");
+      return j;
+    }
+    o = ia.ix->ip.d;
+    if ((*o == 127) || (*o == 10)
+      || ((*o == 192) && (*(o+1) == 168))
+      || ((*o == 172) && ((*(o+1) & 0xF0) == 0x10))) {
+      ipbuf[ip_fmt(ipbuf,o)] = 0;
+      log5("pid ",mypid," ",addr.s, " mfcheck MX nonrouteable IP ");
+      log2(ipbuf, "\n");
+      return BADIP;
+    }
+  }
   return 0;
 }
 
@@ -219,6 +310,8 @@
 
 int seenmail = 0;
 int flagbarf; /* defined if seenmail */
+int flagbarfhelo;
+int flagbarfmfcheck;
 stralloc mailfrom = {0};
 stralloc rcptto = {0};
 
@@ -226,11 +319,14 @@
 {
   smtp_greet("250 "); out("\r\n");
   seenmail = 0; dohelo(arg);
+  log5("pid ",mypid," helo ",arg, "\n");
+  flagbarfhelo = helocheck();
 }
 void smtp_ehlo(arg) char *arg;
 {
   smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
   seenmail = 0; dohelo(arg);
+  flagbarfhelo = helocheck();
 }
 void smtp_rset()
 {
@@ -241,26 +337,36 @@
 {
   if (!addrparse(arg)) { err_syntax(); return; }
   flagbarf = bmfcheck();
+  flagbarfmfcheck = mfcheck();
+  if (flagbarfmfcheck == DNS_MEM) die_nomem();
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
+  log5("pid ",mypid," mail from: ",arg, "\n");
   out("250 ok\r\n");
 }
 void smtp_rcpt(arg) char *arg; {
   if (!seenmail) { err_wantmail(); return; }
   if (!addrparse(arg)) { err_syntax(); return; }
-  if (flagbarf) { err_bmf(); return; }
+  if (flagbarfhelo) { err_mailrefused(); return; }
+  if (flagbarf) { err_mailrefused(); return; }
+  switch(flagbarfmfcheck()) {
+    case DNS_HARD: err_mailrefused(); return;
+    case DNS_SOFT: err_mailrefusedtemp(); return;
+    case BADIP: err_mailrefused(); return;
+  }
   if (relayclient) {
     --addr.len;
     if (!stralloc_cats(&addr,relayclient)) die_nomem();
     if (!stralloc_0(&addr)) die_nomem();
   }
   else
-    if (!addrallowed()) { err_nogateway(); return; }
+    if (!addrallowed()) { err_mailrefused(); return; }
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
+  log5("pid ",mypid," rcpt to: ",arg, "\n");
   out("250 ok\r\n");
 }
 

