Only in netqmail-1.05.patched: CHANGES.spamthrottle
Only in netqmail-1.05.patched: CHANGES.spamthrottle.orig
diff -ur netqmail-1.05/FILES netqmail-1.05.patched/FILES
--- netqmail-1.05/FILES	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/FILES	2008-06-04 19:35:18.000000000 +0200
@@ -136,6 +136,8 @@
 dnsip.c
 dnsmxip.c
 dnsptr.c
+dnstxt.c
+spfquery.c
 hostname.c
 ipmeprint.c
 tcp-env.c
@@ -336,13 +338,16 @@
 byte.h
 byte_chr.c
 byte_copy.c
+byte_cspn.c
 byte_cr.c
 byte_diff.c
 byte_rchr.c
+byte_rcspn.c
 byte_zero.c
 str.h
 str_chr.c
 str_cpy.c
+str_cpyb.c
 str_diff.c
 str_diffn.c
 str_len.c
@@ -402,6 +407,8 @@
 date822fmt.c
 dns.h
 dns.c
+spf.h
+spf.c
 trylsock.c
 tryrsolv.c
 ip.h
@@ -432,3 +439,25 @@
 tcp-environ.5
 constmap.h
 constmap.c
+README.spamthrottle
+CHANGES.spamthrottle
+OTHERS.spamthrottle
+fmt_2long.c
+fmt_2long0.c
+fmt_ulong0.c
+time.c
+time.h
+control_time.c
+lock_exfcntl.c
+lock_unfcntl.c
+spam.c
+spam.h
+spam_get.c
+tryltai.c
+trytai.c
+open_rw.c
+qmail-newst.c
+qmail-newst.9
+qmail-spamt.9
+qmail-spamthrottle.9
+scan_2long.c
Only in netqmail-1.05.patched: FILES.auth
Only in netqmail-1.05.patched: FILES.auth.orig
diff -ur netqmail-1.05/FILES.orig netqmail-1.05.patched/FILES.orig
--- netqmail-1.05/FILES.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/FILES.orig	2008-06-04 19:35:18.000000000 +0200
@@ -10,6 +10,7 @@
 INSTALL.ids
 INSTALL.maildir
 INSTALL.mbox
+INSTALL-1.03
 INSTALL.vsm
 REMOVE.sendmail
 REMOVE.binmail
diff -ur netqmail-1.05/Makefile netqmail-1.05.patched/Makefile
--- netqmail-1.05/Makefile	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/Makefile	2008-06-04 19:35:18.000000000 +0200
@@ -2,6 +2,10 @@
 
 SHELL=/bin/sh
 
+VPOPMAIL_HOME=/home/vpopmail
+SMTPD_CHKUSER_OBJ=chkuser.o
+VPOPMAIL_LIBS=`head -1 $(VPOPMAIL_HOME)/etc/lib_deps`
+
 default: it
 
 addresses.0: \
@@ -136,6 +140,10 @@
 compile auto_usera.c
 	./compile auto_usera.c
 
+base64.o: \
+compile base64.c base64.h stralloc.h substdio.h str.h
+	./compile base64.c
+
 binm1: \
 binm1.sh conf-qmail
 	cat binm1.sh \
@@ -203,6 +211,10 @@
 compile byte_cr.c byte.h
 	./compile byte_cr.c
 
+byte_cspn.o: \
+compile byte_cspn.c byte.h
+	./compile byte_cspn.c
+
 byte_diff.o: \
 compile byte_diff.c byte.h
 	./compile byte_diff.c
@@ -211,6 +223,10 @@
 compile byte_rchr.c byte.h
 	./compile byte_rchr.c
 
+byte_rcspn.o: \
+compile byte_rcspn.c byte.h
+	./compile byte_rcspn.c
+
 byte_zero.o: \
 compile byte_zero.c byte.h
 	./compile byte_zero.c
@@ -300,6 +316,10 @@
 exit.h auto_spawn.h
 	./compile chkspawn.c
 
+chkuser.o: \
+compile chkuser.c chkuser.h chkuser_settings.h
+	./compile chkuser.c
+
 clean: \
 TARGETS
 	rm -f `cat TARGETS`
@@ -358,9 +378,14 @@
 
 control.o: \
 compile control.c readwrite.h open.h getln.h stralloc.h gen_alloc.h \
-substdio.h error.h control.h alloc.h scan.h
+substdio.h error.h control.h alloc.h scan.h fmt.h
 	./compile control.c
 
+control_time.o: \
+compile control_time.c readwrite.h open.h stralloc.h gen_alloc.h \
+substdio.h error.h control.h alloc.h time.h hastai.h
+	./compile control_time.c
+
 date822fmt.o: \
 compile date822fmt.c datetime.h fmt.h date822fmt.h
 	./compile date822fmt.c
@@ -393,84 +418,96 @@
 	rm -f trydrent.o
 
 dns.lib: \
-tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \
-alloc.a error.a fs.a str.a
+tryrsolv.c compile load socket.lib dns.o ipalloc.o strsalloc.o ip.o \
+stralloc.a alloc.a error.a fs.a str.a
 	( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \
-	ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
+	ipalloc.o strsalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
 	-lresolv `cat socket.lib` ) >/dev/null 2>&1 \
 	&& echo -lresolv || exit 0 ) > dns.lib
 	rm -f tryrsolv.o tryrsolv
 
 dns.o: \
-compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \
-stralloc.h gen_alloc.h dns.h case.h
+compile dns.c ip.h ipalloc.h strsalloc.h gen_alloc.h fmt.h alloc.h \
+str.h stralloc.h dns.h case.h
 	./compile dns.c
 
 dnscname: \
-load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
 substdio.a error.a str.a fs.a dns.lib socket.lib
-	./load dnscname dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	./load dnscname dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
 	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
 	socket.lib`
 
 dnscname.o: \
-compile dnscname.c substdio.h subfd.h substdio.h stralloc.h \
+compile dnscname.c substdio.h subfd.h stralloc.h \
 gen_alloc.h dns.h dnsdoe.h readwrite.h exit.h
 	./compile dnscname.c
 
 dnsdoe.o: \
-compile dnsdoe.c substdio.h subfd.h substdio.h exit.h dns.h dnsdoe.h
+compile dnsdoe.c substdio.h subfd.h exit.h dns.h dnsdoe.h
 	./compile dnsdoe.c
 
 dnsfq: \
-load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
 substdio.a error.a str.a fs.a dns.lib socket.lib
-	./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
 	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
 	socket.lib`
 
 dnsfq.o: \
-compile dnsfq.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
-dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+compile dnsfq.c substdio.h subfd.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h exit.h
 	./compile dnsfq.c
 
 dnsip: \
-load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
 substdio.a error.a str.a fs.a dns.lib socket.lib
-	./load dnsip dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	./load dnsip dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
 	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
 	socket.lib`
 
 dnsip.o: \
-compile dnsip.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
-dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+compile dnsip.c substdio.h subfd.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h exit.h
 	./compile dnsip.c
 
 dnsmxip: \
-load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o now.o stralloc.a alloc.a \
-substdio.a error.a str.a fs.a dns.lib socket.lib
-	./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o now.o \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o now.o stralloc.a \
+alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o now.o \
 	stralloc.a alloc.a substdio.a error.a str.a fs.a  `cat \
 	dns.lib` `cat socket.lib`
 
 dnsmxip.o: \
-compile dnsmxip.c substdio.h subfd.h substdio.h stralloc.h \
-gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h \
+compile dnsmxip.c substdio.h subfd.h stralloc.h \
+gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h \
 now.h datetime.h exit.h
 	./compile dnsmxip.c
 
 dnsptr: \
-load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
 substdio.a error.a str.a fs.a dns.lib socket.lib
-	./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
 	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
 	socket.lib`
 
 dnsptr.o: \
-compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+compile dnsptr.c substdio.h subfd.h stralloc.h gen_alloc.h \
 str.h scan.h dns.h dnsdoe.h ip.h exit.h
 	./compile dnsptr.c
 
+dnstxt: \
+load dnstxt.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnstxt dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnstxt.o: \
+compile dnstxt.c substdio.h subfd.h stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+	./compile dnstxt.c
+
 dot-qmail.0: \
 dot-qmail.5
 	nroff -man dot-qmail.5 > dot-qmail.0
@@ -557,6 +594,14 @@
 	cat auto-ccld.sh find-systype.sh > find-systype
 	chmod 755 find-systype
 
+fmt_2long.o: \
+compile fmt_2long.c fmt.h
+	./compile fmt_2long.c
+
+fmt_2long0.o: \
+compile fmt_2long0.c fmt.h
+	./compile fmt_2long0.c
+
 fmt_str.o: \
 compile fmt_str.c fmt.h
 	./compile fmt_str.c
@@ -577,6 +622,10 @@
 compile fmt_ulong.c fmt.h
 	./compile fmt_ulong.c
 
+fmt_ulong0.o: \
+compile fmt_ulong0.c fmt.h
+	./compile fmt_ulong0.c
+
 fmtqfn.o: \
 compile fmtqfn.c fmtqfn.h fmt.h auto_split.h
 	./compile fmtqfn.c
@@ -608,10 +657,11 @@
 	./compile forward.c
 
 fs.a: \
-makelib fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o \
-scan_ulong.o scan_8long.o
-	./makelib fs.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o \
-	fmt_ulong.o scan_ulong.o scan_8long.o
+makelib fmt_2long.o fmt_2long0.o fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o \
+fmt_ulong.o fmt_ulong0.o scan_ulong.o scan_2long.o scan_8long.o
+	./makelib fs.a fmt_2long.o fmt_2long0.o fmt_str.o fmt_strn.o \
+	fmt_uint.o fmt_uint0.o fmt_ulong.o fmt_ulong0.o scan_ulong.o \
+	scan_2long.o scan_8long.o
 
 getln.a: \
 makelib getln.o getln2.o
@@ -685,6 +735,13 @@
 	hasshsgr.h
 	rm -f tryshsgr.o tryshsgr
 
+hastai.h: \
+trytai.c compile load
+	( ( ./compile trytai.c && ./load trytai -ltai ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASTAI 1 || exit 0 ) > hastai.h
+	rm -f trytai.o trytai
+
 haswaitp.h: \
 trywaitp.c compile load
 	( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null \
@@ -777,38 +834,38 @@
 	./compile ip.c
 
 ipalloc.o: \
-compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \
+compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h \
 gen_alloc.h
 	./compile ipalloc.c
 
 ipme.o: \
-compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \
-stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h
+compile ipme.c hassalen.h byte.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h \
+stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.h
 	./compile ipme.c
 
 ipmeprint: \
-load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \
-error.a str.a fs.a socket.lib
-	./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \
-	substdio.a error.a str.a fs.a  `cat socket.lib`
+load ipmeprint.o ipme.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a socket.lib
+	./load ipmeprint ipme.o ip.o ipalloc.o strsalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a `cat socket.lib`
 
 ipmeprint.o: \
 compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \
-ipalloc.h ip.h gen_alloc.h exit.h
+ipalloc.h strsalloc.h ip.h gen_alloc.h exit.h
 	./compile ipmeprint.c
 
 it: \
 qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \
 qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \
-predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \
+predate datemail mailsubj qmail-upq qmail-showctl qmail-newst qmail-newu \
 qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \
 qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \
 qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \
-dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \
+dnsptr dnsip dnsmxip dnsfq dnstxt hostname ipmeprint qreceipt qsmhook qbiff \
 forward preline condredirect bouncesaying except maildirmake \
 maildir2mbox maildirwatch qail elq pinq idedit install-big install \
 instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
-binm3 binm3+df
+binm3 binm3+df spfquery update_tmprsadh
 
 load: \
 make-load warn-auto.sh systype
@@ -816,8 +873,8 @@
 	chmod 755 load
 
 lock.a: \
-makelib lock_ex.o lock_exnb.o lock_un.o
-	./makelib lock.a lock_ex.o lock_exnb.o lock_un.o
+makelib lock_ex.o lock_exnb.o lock_un.o lock_exfcntl.o lock_unfcntl.o
+	./makelib lock.a lock_ex.o lock_exnb.o lock_un.o lock_exfcntl.o lock_unfcntl.o
 
 lock_ex.o: \
 compile lock_ex.c hasflock.h lock.h
@@ -831,6 +888,14 @@
 compile lock_un.c hasflock.h lock.h
 	./compile lock_un.c
 
+lock_exfcntl.o: \
+compile lock_exfcntl.c lock.h
+	./compile lock_exfcntl.c
+
+lock_unfcntl.o: \
+compile lock_unfcntl.c lock.h
+	./compile lock_unfcntl.c
+
 maildir.0: \
 maildir.5
 	nroff -man maildir.5 > maildir.0
@@ -890,6 +955,38 @@
 readwrite.h open.h headerbody.h maildir.h strerr.h
 	./compile maildirwatch.c
 
+maildirgetquota.o: \
+compile maildirgetquota.c maildirgetquota.h maildirmisc.h
+	./compile maildirgetquota.c
+
+maildirflags.o: \
+compile maildirflags.c
+	./compile maildirflags.c
+
+maildiropen.o: \
+compile maildiropen.c maildirmisc.h
+	./compile maildiropen.c
+
+maildirparsequota.o: \
+compile maildirparsequota.c
+	./compile maildirparsequota.c
+
+maildirquota.o: \
+compile maildirquota.c maildirquota.h maildirmisc.h numlib.h
+	./compile maildirquota.c
+
+overmaildirquota.o: \
+compile overmaildirquota.c 
+	./compile overmaildirquota.c
+
+strtimet.o: \
+compile strtimet.c 
+	./compile strtimet.c
+
+strpidt.o: \
+compile strpidt.c 
+	./compile strpidt.c
+
 mailsubj: \
 warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
 	cat warn-auto.sh mailsubj.sh \
@@ -927,7 +1024,7 @@
 man: \
 qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \
 qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \
-qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \
+qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newst.0 qmail-newu.0 \
 qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \
 qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \
 qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \
@@ -935,7 +1032,7 @@
 maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \
 qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \
 qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 \
-envelopes.0 forgeries.0
+envelopes.0 forgeries.0 qmail-spamt.0 qmail-spamthrottle.0
 
 mbox.0: \
 mbox.5
@@ -968,9 +1065,9 @@
 
 open.a: \
 makelib open_append.o open_excl.o open_read.o open_trunc.o \
-open_write.o
+open_write.o open_rw.o
 	./makelib open.a open_append.o open_excl.o open_read.o \
-	open_trunc.o open_write.o
+	open_trunc.o open_write.o open_rw.o
 
 open_append.o: \
 compile open_append.c open.h
@@ -984,6 +1081,10 @@
 compile open_read.c open.h
 	./compile open_read.c
 
+open_rw.o: \
+compile open_rw.c open.h
+	./compile open_rw.c
+
 open_trunc.o: \
 compile open_trunc.c open.h
 	./compile open_trunc.c
@@ -1174,12 +1275,15 @@
 load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
 slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
 wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
-fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib
+fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \
+maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \
+strtimet.o strpidt.o
 	./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
 	slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
 	lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
 	substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
-	auto_patrn.o  `cat socket.lib`
+	auto_patrn.o  `cat socket.lib` maildirquota.o maildirgetquota.o \
+    maildiropen.o maildirparsequota.o overmaildirquota.o strtimet.o strpidt.o
 
 qmail-local.0: \
 qmail-local.8
@@ -1241,6 +1345,31 @@
 uint32.h substdio.h
 	./compile qmail-newmrh.c
 
+qmail-newst: \
+load qmail-newst.o cdbmss.o ip.o getln.a open.a seek.a cdbmake.a case.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o
+	./load qmail-newst cdbmss.o ip.o getln.a open.a seek.a cdbmake.a \
+	case.a stralloc.a alloc.a substdio.a error.a str.a fs.a \
+	auto_qmail.o
+
+qmail-newst.0: \
+qmail-newst.8
+	nroff -man qmail-newst.8 > qmail-newst.0
+
+qmail-newst.8: \
+qmail-newst.9 conf-break conf-spawn
+	cat qmail-newst.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-newst.8
+
+qmail-newst.o: \
+compile qmail-newst.c stralloc.h gen_alloc.h subfd.h substdio.h \
+getln.h substdio.h cdbmss.h cdbmake.h uint32.h substdio.h exit.h \
+readwrite.h open.h error.h case.h ip.h fmt.h auto_qmail.h
+	./compile qmail-newst.c
+
 qmail-newu: \
 load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \
 stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o
@@ -1269,11 +1398,13 @@
 qmail-pop3d: \
 load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
 maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
-stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib
+stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \
+maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
 	./load qmail-pop3d commands.o case.a timeoutread.o \
 	timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
 	open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
-	fs.a  `cat socket.lib`
+	fs.a  `cat socket.lib` maildirquota.o maildirgetquota.o \
+    maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
 
 qmail-pop3d.0: \
 qmail-pop3d.8
@@ -1439,12 +1570,13 @@
 
 qmail-remote: \
 load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
-timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
+timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o strsalloc.o ipme.o quote.o \
 ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
 substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
 	./load qmail-remote control.o constmap.o timeoutread.o \
 	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
-	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
+	tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
+	ipalloc.o strsalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
 	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
 	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
 
@@ -1455,7 +1587,7 @@
 qmail-remote.o: \
 compile qmail-remote.c sig.h stralloc.h gen_alloc.h substdio.h \
 subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \
-alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \
+alloc.h quote.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.h \
 gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \
 tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h
 	./compile qmail-remote.c
@@ -1513,10 +1645,10 @@
 
 qmail-showctl: \
 load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \
-alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_break.o \
+alloc.a substdio.a error.a str.a fs.a spam_get.o cdb.a auto_qmail.o auto_break.o \
 auto_patrn.o auto_spawn.o auto_split.o
 	./load qmail-showctl auto_uids.o control.o open.a getln.a \
-	stralloc.a alloc.a substdio.a error.a str.a fs.a \
+	stralloc.a alloc.a substdio.a error.a str.a fs.a spam_get.o cdb.a \
 	auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \
 	auto_split.o 
 
@@ -1528,34 +1660,60 @@
 compile qmail-showctl.c substdio.h subfd.h substdio.h exit.h fmt.h \
 str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \
 auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \
-auto_split.h
+auto_split.h spf.h
 	./compile qmail-showctl.c
 
 qmail-smtpd: \
-load qmail-smtpd.o 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 socket.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 \
+load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \
+timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o control_time.o time.o constmap.o \
+received.o date822fmt.o now.o qmail.o spf.o dns.o spam.o spam_get.o cdb.a fd.a wait.a \
+datetime.a getln.a open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a \
+error.a str.a fs.a auto_uids.o tai.lib lock.a auto_qmail.o base64.o socket.lib \
+$(SMTPD_CHKUSER_OBJ) dns.lib
+	./load qmail-smtpd $(SMTPD_CHKUSER_OBJ) qregex.o rcpthosts.o commands.o timeoutread.o \
+	timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o control_time.o time.o \
+    constmap.o tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
+	received.o date822fmt.o now.o qmail.o spf.o spam.o spam_get.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`
+	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o base64.o  `cat \
+	socket.lib tai.lib dns.lib` dns.o lock.a $(VPOPMAIL_LIBS)
 
 qmail-smtpd.0: \
 qmail-smtpd.8
 	nroff -man qmail-smtpd.8 > qmail-smtpd.0
 
 qmail-smtpd.o: \
-compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \
+compile qmail-smtpd.c chkuser.h sig.h readwrite.h stralloc.h gen_alloc.h \
 substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
-error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
+error.h ipme.h ip.h ipalloc.h strsalloc.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
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h spam.h base64.h spf.h
 	./compile qmail-smtpd.c
 
+qmail-spamt.0: \
+qmail-spamt.5
+	nroff -man qmail-spamt.5 > qmail-spamt.0
+
+qmail-spamt.5: \
+qmail-spamt.9 conf-break conf-spawn
+	cat qmail-spamt.9 \
+      | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+      | sed s}BREAK}"`head -1 conf-break`"}g \
+      | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+      > qmail-spamt.5
+
+qmail-spamthrottle.0: \
+qmail-spamthrottle.5
+	nroff -man qmail-spamthrottle.5 > qmail-spamthrottle.0
+
+qmail-spamthrottle.5: \
+qmail-spamthrottle.9 conf-break conf-spawn
+	cat qmail-spamthrottle.9 \
+      | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+      | sed s}BREAK}"`head -1 conf-break`"}g \
+      | sed s}SPAWN}"`head -1 conf-spawn`"}g \
+      > qmail-spamthrottle.5
+
 qmail-start: \
 load qmail-start.o prot.o fd.a auto_uids.o
 	./load qmail-start prot.o fd.a auto_uids.o 
@@ -1681,6 +1839,10 @@
 constmap.h stralloc.h gen_alloc.h rcpthosts.h
 	./compile rcpthosts.c
 
+qregex.o: \
+compile qregex.c qregex.h
+	./compile qregex.c
+
 readsubdir.o: \
 compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
 auto_split.h
@@ -1696,6 +1858,10 @@
 timeoutread.h timeoutwrite.h remoteinfo.h
 	./compile remoteinfo.c
 
+scan_2long.o: \
+compile scan_2long.c scan.h
+	./compile scan_2long.c
+
 scan_8long.o: \
 compile scan_8long.c scan.h
 	./compile scan_8long.c
@@ -1779,7 +1945,7 @@
 qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \
 qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \
 qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \
-dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \
+dnsip.c dnsmxip.c dnsptr.c dnstxt.c hostname.c ipmeprint.c tcp-env.c \
 sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \
 except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \
 maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \
@@ -1813,21 +1979,25 @@
 trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c \
 sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c \
 trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c \
-byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h \
-str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c \
-str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 \
+byte_copy.c byte_cr.c byte_cspn.c byte_diff.c byte_rchr.c byte_rcspn.c \
+byte_zero.c str.h spf.c spf.h spfquery.c \
+str_chr.c str_cpy.c str_cpyb.c str_diff.c str_diffn.c str_len.c str_rchr.c \
+str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c lock_exfcntl.c lock_unfcntl.c getln.3 \
 getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c \
 subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 \
 error.h error.c error_str.c error_temp.c fmt.h fmt_str.c fmt_strn.c \
-fmt_uint.c fmt_uint0.c fmt_ulong.c scan.h scan_ulong.c scan_8long.c \
+fmt_uint.c fmt_uint0.c fmt_ulong.c fmt_ulong0.c scan.h scan_ulong.c scan_2long.c scan_8long.c \
 slurpclose.h slurpclose.c quote.h quote.c hfield.h hfield.c \
 headerbody.h headerbody.c token822.h token822.c control.h control.c \
 datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c \
 date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c \
-ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
+ipalloc.h strsalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
 ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
 prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
-maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c
+maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c \
+README.spamthrottle time.c time.h control_time.c lock_exfcntl.c \
+lock_unfcntl.c spam.c spam_get.c tryltai.c trytai.c open_rw.c qmail-spamt.9 \
+qmail-spamthrottle.9 update_tmprsadh
 	shar -m `cat FILES` > shar
 	chmod 400 shar
 
@@ -1890,6 +2060,16 @@
 	&& echo -lsocket -lnsl || exit 0 ) > socket.lib
 	rm -f trylsock.o trylsock
 
+spam.o: \
+compile spam.c auto_uids.h lock.h stralloc.h gen_alloc.h control.h \
+open.h fmt.h timeoutread.h error.h time.h hastai.h ip.h env.h cdb.h \
+uint32.h spam.h substdio.h
+	./compile spam.c
+
+spam_get.o: \
+compile spam_get.c stralloc.h gen_alloc.h spam.h substdio.h
+	./compile spam_get.c
+
 spawn.o: \
 compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \
 stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \
@@ -1897,6 +2077,23 @@
 	./chkspawn
 	./compile spawn.c
 
+spf.o: \
+compile spf.c stralloc.h gen_alloc.h alloc.h ipme.h ip.h ipalloc.h \
+strsalloc.h str.h fmt.h scan.h byte.h now.h case.h
+	./compile spf.c
+
+spfquery: \
+load spfquery.o spf.o ip.o ipme.o ipalloc.o strsalloc.o now.o dns.o \
+datetime.a stralloc.a alloc.a str.a substdio.a error.a fs.a case.a dns.lib
+	./load spfquery spf.o ip.o ipme.o ipalloc.o strsalloc.o \
+	now.o dns.o datetime.a stralloc.a alloc.a str.a substdio.a \
+	case.a error.a fs.a `cat dns.lib` `cat socket.lib`
+
+spfquery.o: \
+compile spfquery.c substdio.h subfd.h stralloc.h gen_alloc.h alloc.h \
+spf.h exit.h
+	./compile spfquery.c
+
 splogger: \
 load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib
 	./load splogger substdio.a error.a str.a fs.a  `cat \
@@ -1912,12 +2109,12 @@
 	./compile splogger.c
 
 str.a: \
-makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \
-str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \
-byte_cr.o byte_zero.o
-	./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \
-	str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \
-	byte_diff.o byte_copy.o byte_cr.o byte_zero.o
+makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_cpyb.o str_chr.o \
+str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_cspn.o byte_rcspn.o \
+byte_diff.o byte_copy.o byte_cr.o byte_zero.o
+	./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o str_cpyb.o \
+	str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_cspn.o \
+	byte_rcspn.o byte_diff.o byte_copy.o byte_cr.o byte_zero.o
 
 str_chr.o: \
 compile str_chr.c str.h
@@ -1927,6 +2124,10 @@
 compile str_cpy.c str.h
 	./compile str_cpy.c
 
+str_cpyb.o: \
+compile str_cpyb.c str.h
+	./compile str_cpyb.c
+
 str_diff.o: \
 compile str_diff.c str.h
 	./compile str_diff.c
@@ -2006,6 +2207,11 @@
 compile strerr_sys.c error.h strerr.h
 	./compile strerr_sys.c
 
+strsalloc.o: \
+compile strsalloc.c alloc.h gen_allocdefs.h stralloc.h strsalloc.h \
+gen_alloc.h
+	./compile strsalloc.c
+
 subfderr.o: \
 compile subfderr.c readwrite.h substdio.h subfd.h substdio.h
 	./compile subfderr.c
@@ -2064,13 +2270,20 @@
 find-systype trycpp.c
 	./find-systype > systype
 
+tai.lib: \
+tryltai.c compile load
+	( ( ./compile tryltai.c && \
+	./load tryltai -ltai ) >/dev/null 2>&1 \
+	&& echo -ltai || exit 0 ) > tai.lib
+	rm -f tryltai.o tryltai
+
 tcp-env: \
 load tcp-env.o dns.o remoteinfo.o timeoutread.o timeoutwrite.o \
-timeoutconn.o ip.o ipalloc.o case.a ndelay.a sig.a env.a getopt.a \
-stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
+timeoutconn.o ip.o ipalloc.o strsalloc.o case.a ndelay.a sig.a env.a \
+getopt.a stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
 	./load tcp-env dns.o remoteinfo.o timeoutread.o \
-	timeoutwrite.o timeoutconn.o ip.o ipalloc.o case.a ndelay.a \
-	sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \
+	timeoutwrite.o timeoutconn.o ip.o ipalloc.o strsalloc.o case.a \
+	ndelay.a sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \
 	str.a fs.a  `cat dns.lib` `cat socket.lib`
 
 tcp-env.0: \
@@ -2095,6 +2308,10 @@
 compile tcpto_clean.c tcpto.h open.h substdio.h readwrite.h
 	./compile tcpto_clean.c
 
+time.o: \
+compile time.c time.h stralloc.h gen_alloc.h fmt.h scan.h hastai.h
+	./compile time.c
+
 timeoutconn.o: \
 compile timeoutconn.c ndelay.h select.h error.h readwrite.h ip.h \
 byte.h timeoutconn.h
@@ -2108,6 +2325,19 @@
 compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
 	./compile timeoutwrite.c
 
+qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
+qmail-remote: tls.o ssl_timeoutio.o
+qmail-smtpd.o: tls.h ssl_timeoutio.h
+qmail-remote.o: tls.h ssl_timeoutio.h
+
+tls.o: \
+compile tls.c exit.h error.h
+	./compile tls.c
+
+ssl_timeoutio.o: \
+compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
+	./compile ssl_timeoutio.c
+
 token822.o: \
 compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
 gen_alloc.h gen_allocdefs.h
@@ -2139,3 +2369,26 @@
 wait_pid.o: \
 compile wait_pid.c error.h haswaitp.h
 	./compile wait_pid.c
+
+cert cert-req: \
+Makefile-cert
+	@$(MAKE) -sf $< $@
+
+Makefile-cert: \
+conf-qmail conf-users conf-groups Makefile-cert.mk
+	@cat Makefile-cert.mk \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> $@
+
+update_tmprsadh: \
+conf-qmail conf-users conf-groups update_tmprsadh.sh
+	@cat update_tmprsadh.sh\
+	| sed s}UGQMAILD}"`head -2 conf-users|tail -1`:`head -1 conf-groups`"}g \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> $@
+	chmod 755 update_tmprsadh 
+
+tmprsadh: \
+update_tmprsadh
+	echo "Creating new temporary RSA and DH parameters"
+	./update_tmprsadh
Only in netqmail-1.05.patched: Makefile-cert.mk
Only in netqmail-1.05.patched: Makefile-cert.mk.orig
diff -ur netqmail-1.05/Makefile.orig netqmail-1.05.patched/Makefile.orig
--- netqmail-1.05/Makefile.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/Makefile.orig	2008-06-04 19:35:18.000000000 +0200
@@ -263,7 +263,7 @@
 	cdbmake_add.o
 
 cdbmake_add.o: \
-compile cdbmake_add.c cdbmake.h uint32.h
+compile cdbmake_add.c cdbmake.h alloc.h uint32.h
 	./compile cdbmake_add.c
 
 cdbmake_hash.o: \
@@ -1483,12 +1483,12 @@
 trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
 datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
 lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-auto_split.o
+auto_split.o env.a
 	./load qmail-send qsutil.o control.o constmap.o newfield.o \
 	prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
 	qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
 	wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
-	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o 
+	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
 
 qmail-send.0: \
 qmail-send.8
@@ -1892,7 +1892,7 @@
 
 spawn.o: \
 compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \
-stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \
+stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \
 auto_qmail.h auto_uids.h auto_spawn.h
 	./chkspawn
 	./compile spawn.c
Only in netqmail-1.05.patched: OTHERS.spamthrottle
Only in netqmail-1.05.patched: OTHERS.spamthrottle.orig
Only in netqmail-1.05.patched: README.auth
Only in netqmail-1.05.patched: README.auth.orig
Only in netqmail-1.05.patched: README.qregex
Only in netqmail-1.05.patched: README.qregex.orig
Only in netqmail-1.05.patched: README.spamthrottle
Only in netqmail-1.05.patched: README.spamthrottle.orig
diff -ur netqmail-1.05/TARGETS netqmail-1.05.patched/TARGETS
--- netqmail-1.05/TARGETS	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/TARGETS	2008-06-04 19:35:18.000000000 +0200
@@ -10,11 +10,20 @@
 qmail.o
 quote.o
 now.o
+base64.o
 gfrom.o
 myctime.o
 slurpclose.o
 make-makelib
 makelib
+maildirflags.o
+maildirparsequota.o
+maildiropen.o
+maildirgetquota.o
+maildirquota.o
+overmaildirquota.o
+strtimet.o
+strpidt.o
 case_diffb.o
 case_diffs.o
 case_lowerb.o
@@ -100,11 +109,14 @@
 str_diff.o
 str_diffn.o
 str_cpy.o
+str_cpyb.o
 str_chr.o
 str_rchr.o
 str_start.o
 byte_chr.o
 byte_rchr.o
+byte_cspn.o
+byte_rcspn.o
 byte_diff.o
 byte_copy.o
 byte_cr.o
@@ -168,11 +180,15 @@
 constmap.o
 timeoutread.o
 timeoutwrite.o
+tls.o
+ssl_timeoutio.o
 timeoutconn.o
 tcpto.o
 dns.o
+spf.o
 ip.o
 ipalloc.o
+strsalloc.o
 hassalen.h
 ipme.o
 ndelay.o
@@ -212,6 +228,9 @@
 headerbody.o
 hfield.o
 token822.o
+spf.o
+spfquery.o
+spfquery
 qmail-inject
 predate.o
 predate
@@ -252,6 +271,7 @@
 qmail-qmtpd
 qmail-smtpd.o
 qmail-smtpd
+qregex.o
 sendmail.o
 sendmail
 tcp-env.o
@@ -270,6 +290,8 @@
 dnsip
 dnsmxip.o
 dnsmxip
+dnstxt.o
+dnstxt
 dnsfq.o
 dnsfq
 hostname.o
@@ -320,6 +342,7 @@
 binm2+df
 binm3
 binm3+df
+Makefile-cert
 it
 qmail-local.0
 qmail-lspawn.0
@@ -385,3 +408,24 @@
 man
 setup
 check
+update_tmprsadh
+spam.o
+spam_get.o
+open_rw.o
+lock_exfcntl.o
+lock_unfcntl.o
+fmt_2long.o
+fmt_2long0.o
+fmt_ulong0.o
+scan_2long.o
+control_time.o
+hastai.h
+time.o
+tai.lib
+qmail-newst.o
+qmail-newst
+qmail-spamt.5
+qmail-spamt.0
+qmail-spamthrottle.5
+qmail-spamthrottle.0
+chkuser.o
Only in netqmail-1.05.patched: TARGETS.orig
Only in netqmail-1.05.patched: auth.log
Only in netqmail-1.05.patched: auth.log.orig
Only in netqmail-1.05.patched: base64.c
Only in netqmail-1.05.patched: base64.c.orig
Only in netqmail-1.05.patched: base64.h
Only in netqmail-1.05.patched: base64.h.orig
diff -ur netqmail-1.05/byte.h netqmail-1.05.patched/byte.h
--- netqmail-1.05/byte.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/byte.h	2008-06-04 19:35:18.000000000 +0200
@@ -3,6 +3,8 @@
 
 extern unsigned int byte_chr();
 extern unsigned int byte_rchr();
+extern unsigned int byte_cspn();
+extern unsigned int byte_rcspn();
 extern void byte_copy();
 extern void byte_copyr();
 extern int byte_diff();
Only in netqmail-1.05.patched: byte.h.orig
Only in netqmail-1.05.patched: byte_cspn.c
Only in netqmail-1.05.patched: byte_cspn.c.orig
Only in netqmail-1.05.patched: byte_rcspn.c
Only in netqmail-1.05.patched: byte_rcspn.c.orig
Only in netqmail-1.05.patched: case_startb.c
Only in netqmail-1.05.patched: case_startb.c.orig
diff -ur netqmail-1.05/chkspawn.c netqmail-1.05.patched/chkspawn.c
--- netqmail-1.05/chkspawn.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/chkspawn.c	2008-06-04 19:35:18.000000000 +0200
@@ -22,8 +22,8 @@
     _exit(1);
   }
 
-  if (auto_spawn > 255) {
-    substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 255.\n");
+  if (auto_spawn > 65000) {
+    substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 65000.\n");
     substdio_flush(subfderr);
     _exit(1);
   }
Only in netqmail-1.05.patched: chkspawn.c.orig
Only in netqmail-1.05.patched: chkuser.c
Only in netqmail-1.05.patched: chkuser.c.orig
Only in netqmail-1.05.patched: chkuser.h
Only in netqmail-1.05.patched: chkuser.h.orig
Only in netqmail-1.05.patched: chkuser_settings.h
Only in netqmail-1.05.patched: chkuser_settings.h.orig
diff -ur netqmail-1.05/conf-cc netqmail-1.05.patched/conf-cc
--- netqmail-1.05/conf-cc	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/conf-cc	2008-06-04 19:35:18.000000000 +0200
@@ -1,3 +1,3 @@
-cc -O2
+cc -O2 -DINET6 -DTLS=20060104 -I/usr/local/ssl/include -I/home/vpopmail/include
 
 This will be used to compile .c files.
Only in netqmail-1.05.patched: conf-cc.orig
diff -ur netqmail-1.05/conf-spawn netqmail-1.05.patched/conf-spawn
--- netqmail-1.05/conf-spawn	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/conf-spawn	2008-06-04 19:35:18.000000000 +0200
@@ -1,4 +1,4 @@
-120
+509
 
 This is a silent concurrency limit. You can't set it above 255. On some
 systems you can't set it above 125. qmail will refuse to compile if the
Only in netqmail-1.05.patched: conf-spawn.orig
diff -ur netqmail-1.05/control.c netqmail-1.05.patched/control.c
--- netqmail-1.05/control.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/control.c	2008-06-04 19:35:18.000000000 +0200
@@ -7,8 +7,10 @@
 #include "control.h"
 #include "alloc.h"
 #include "scan.h"
+#include "fmt.h"
 
 static char inbuf[64];
+static char outbuf[64];
 static stralloc line = {0};
 static stralloc me = {0};
 static int meok = 0;
@@ -128,3 +130,25 @@
  close(fd);
  return -1;
 }
+
+
+int control_writeint(i,fn)
+int *i;
+char *fn;
+{
+ substdio ss;
+ int fd;
+ char num[FMT_ULONG];
+
+ fd = open_write(fn);
+ if (fd == -1) { if (errno == error_noent) return 0; return -1; }
+ 
+ substdio_fdbuf(&ss,write,fd,outbuf,sizeof(outbuf));
+
+ substdio_putflush(&ss,num,fmt_ulong(num,*i));
+ substdio_putsflush(&ss,"\n");
+
+ close(fd);
+
+ return 1;
+}
Only in netqmail-1.05.patched: control.c.orig
diff -ur netqmail-1.05/control.h netqmail-1.05.patched/control.h
--- netqmail-1.05/control.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/control.h	2008-06-04 19:35:18.000000000 +0200
@@ -6,5 +6,9 @@
 extern int control_rldef();
 extern int control_readint();
 extern int control_readfile();
+extern int control_writeint();
+
+extern int control_readtime();
+extern int control_writetime();
 
 #endif
Only in netqmail-1.05.patched: control.h.orig
Only in netqmail-1.05.patched: control_time.c
Only in netqmail-1.05.patched: control_time.c.orig
diff -ur netqmail-1.05/dns.c netqmail-1.05.patched/dns.c
--- netqmail-1.05/dns.c	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/dns.c	2008-06-04 19:35:18.000000000 +0200
@@ -3,12 +3,14 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
+#include <sys/socket.h>
 #include <resolv.h>
 #include <errno.h>
 extern int res_query();
 extern int res_search();
 #include "ip.h"
 #include "ipalloc.h"
+#include "strsalloc.h"
 #include "fmt.h"
 #include "alloc.h"
 #include "str.h"
@@ -19,14 +21,20 @@
 static unsigned short getshort(c) unsigned char *c;
 { unsigned short u; u = c[0]; return (u << 8) + c[1]; }
 
-static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static struct { unsigned char *buf; } response;
+static int responsebuflen = 0;
 static int responselen;
 static unsigned char *responseend;
 static unsigned char *responsepos;
+static u_long saveresoptions;
 
 static int numanswers;
 static char name[MAXDNAME];
 static struct ip_address ip;
+#ifdef INET6
+static struct ip6_address ip6;
+#endif
+static stralloc txt = {0};
 unsigned short pref;
 
 static stralloc glue = {0};
@@ -43,18 +51,33 @@
  errno = 0;
  if (!stralloc_copy(&glue,domain)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
- responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response));
+ if (!responsebuflen)
+  if (response.buf = (unsigned char *)alloc(PACKETSZ+1))
+   responsebuflen = PACKETSZ+1;
+  else return DNS_MEM;
+
+ responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+ if ((responselen >= responsebuflen) ||
+     (responselen > 0 && (((HEADER *)response.buf)->tc)))
+  {
+   if (responsebuflen < 65536)
+    if (alloc_re(&response.buf, responsebuflen, 65536))
+     responsebuflen = 65536;
+    else return DNS_MEM;
+    saveresoptions = _res.options;
+    _res.options |= RES_USEVC;
+    responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+    _res.options = saveresoptions;
+  }
  if (responselen <= 0)
   {
    if (errno == ECONNREFUSED) return DNS_SOFT;
    if (h_errno == TRY_AGAIN) return DNS_SOFT;
    return DNS_HARD;
   }
- if (responselen >= sizeof(response))
-   responselen = sizeof(response);
  responseend = response.buf + responselen;
  responsepos = response.buf + sizeof(HEADER);
- n = ntohs(response.hdr.qdcount);
+ n = ntohs(((HEADER *)response.buf)->qdcount);
  while (n-- > 0)
   {
    i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
@@ -64,7 +87,7 @@
    if (i < QFIXEDSZ) return DNS_SOFT;
    responsepos += QFIXEDSZ;
   }
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
  return 0;
 }
 
@@ -140,6 +163,43 @@
  return 0;
 }
 
+#ifdef INET6
+static int findip6(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+   
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+  {
+   if (rrdlen < 16)
+     return DNS_SOFT;
+   bcopy(&responsepos[0], &ip6.d, 16);
+   responsepos += rrdlen;
+   return 1;
+  }
+   
+ responsepos += rrdlen;
+ return 0;
+}
+#endif
+
 static int findmx(wanttype)
 int wanttype;
 {
@@ -177,6 +237,49 @@
  return 0;
 }
 
+static int findtxt(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+   
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+  {
+   unsigned short txtpos;
+   unsigned char txtlen;
+
+   txt.len = 0;
+   for (txtpos = 0;txtpos < rrdlen;txtpos += txtlen)
+    {
+     txtlen = responsepos[txtpos++];
+     if (txtlen > rrdlen-txtpos) txtlen = rrdlen-txtpos;
+     if (!stralloc_catb(&txt,&responsepos[txtpos],txtlen)) return DNS_MEM;
+    }
+
+   responsepos += rrdlen;
+   return 1;
+ }
+
+ responsepos += rrdlen;
+ return 0;
+}
+
 void dns_init(flagsearch)
 int flagsearch;
 {
@@ -235,15 +338,89 @@
  return len;
 }
 
-int dns_ptr(sa,ip)
-stralloc *sa;
+static int dns_ptrplus(ssa,ip)
+strsalloc *ssa;
 struct ip_address *ip;
 {
+ stralloc sa = {0};
  int r;
 
- if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM;
- sa->len = iaafmt(sa->s,ip);
- switch(resolve(sa,T_PTR))
+ if (!stralloc_ready(&sa,iaafmt((char *) 0,ip))) return DNS_MEM;
+ sa.len = iaafmt(sa.s,ip);
+ r = resolve(&sa,T_PTR);
+ alloc_free(sa.s);
+ switch(r)
+  {
+   case DNS_MEM: return DNS_MEM;
+   case DNS_SOFT: return DNS_SOFT;
+   case DNS_HARD: return DNS_HARD;
+  }
+ while ((r = findname(T_PTR)) != 2)
+  {
+   if (r == DNS_SOFT) return DNS_SOFT;
+   if (r == 1)
+    {
+     stralloc sa2 = {0};
+     if (!stralloc_copys(&sa2,name)) return DNS_MEM;
+     if (!strsalloc_append(ssa,&sa2)) return DNS_MEM;
+    }
+  }
+ if (ssa->len) return 0;
+ return DNS_HARD;
+}
+
+int dns_ptr(ssa,ip)
+strsalloc *ssa;
+struct ip_address *ip;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_ptrplus(ssa,ip);
+ if (r < 0)
+  {
+   for (j = 0;j < ssa->len;++j)
+    alloc_free(ssa->sa[j].s);
+   ssa->len = 0;
+  }
+ return r;
+}
+
+#ifdef INET6
+static int iaafmt6(s,ip)
+char *s;
+struct ip6_address *ip;
+{
+ unsigned int i;
+ int j;
+ unsigned int len;
+ static char data[] = "0123456789abcdef";
+ len = 0;
+
+ if (s) {
+   for (j = 15; j >= 0; j--) {
+     *s++ = data[ip->d[j] & 0x0f];
+     *s++ = '.';
+     *s++ = data[(ip->d[j] >> 4) & 0x0f];
+     *s++ = '.';
+   }
+   strcpy(s, "ip6.int");
+ }
+ return 71;
+ /* 1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.int */
+}
+
+int dns_ptr6(sa,ip)
+stralloc *sa;
+struct ip6_address *ip;
+{
+ int r;
+
+ if (!stralloc_ready(sa,iaafmt6((char *) 0,ip))) return DNS_MEM;
+ sa->len = iaafmt6(sa->s,ip);
+ switch(resolve(sa,T_PTR)) 
   {
    case DNS_MEM: return DNS_MEM;
    case DNS_SOFT: return DNS_SOFT;
@@ -260,6 +437,7 @@
   }
  return DNS_HARD;
 }
+#endif
 
 static int dns_ipplus(ia,sa,pref)
 ipalloc *ia;
@@ -267,34 +445,73 @@
 int pref;
 {
  int r;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
+ int err4 = 0, err6 = 0;
 
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
-   if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
+   ix.af = AF_INET;
+   if (!glue.s[ip_scan(glue.s,&ix.addr.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.addr.ip)])
     {
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
      return 0;
     }
  }
 
- switch(resolve(sa,T_A))
+#ifdef INET6
+ switch(resolve(sa,T_AAAA))
   {
-   case DNS_MEM: return DNS_MEM;
-   case DNS_SOFT: return DNS_SOFT;
-   case DNS_HARD: return DNS_HARD;
+   case DNS_MEM: err6 = DNS_MEM; break;
+   case DNS_SOFT: err6 = DNS_SOFT; break;
+   case DNS_HARD: err6 = DNS_HARD; break;
+   default:
+     while ((r = findip6(T_AAAA)) != 2)
+       {
+         ix.af = AF_INET6;
+         ix.addr.ip6 = ip6;
+         ix.pref = pref;
+	 if (r == DNS_SOFT) { err6 = DNS_SOFT; break; }
+	 if (r == 1)
+	   if (!ipalloc_append(ia,&ix)) { err6 = DNS_MEM; break; }
+       }
+     break;
   }
+#endif
+
+ switch(resolve(sa,T_A))
+  {
+   case DNS_MEM: err4 = DNS_MEM; break;
+   case DNS_SOFT: err4 = DNS_SOFT; break;
+   case DNS_HARD: err4 = DNS_HARD; break;
+    default:
  while ((r = findip(T_A)) != 2)
   {
-   ix.ip = ip;
+   //ix.ip = ip;
+   ix.addr.ip = ip;
    ix.pref = pref;
-   if (r == DNS_SOFT) return DNS_SOFT;
-   if (r == 1)
-     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
-  }
+   if (r == DNS_SOFT) { err4 = DNS_SOFT; break;}
+   if (r == 1) {
+#ifdef IX_FQDN
+     ix.fqdn = glue.s;
+#endif
+     if (!ipalloc_append(ia,&ix)) {err4 = DNS_MEM;  break;}
+  }
+  }
+ break;
+  }
+#ifdef IX_FQDN
+ glue.s = 0;
+#endif
+
+#ifdef INET6
+ if (err4 != 0 && err6 != 0) {
+   return err4;
+ }
  return 0;
+#else
+ return err4;
+#endif
 }
 
 int dns_ip(ia,sa)
@@ -313,7 +530,7 @@
 {
  int r;
  struct mx { stralloc sa; unsigned short p; } *mx;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
  int nummx;
  int i;
  int j;
@@ -325,9 +542,10 @@
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
-   if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
+   //if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
+   if (!glue.s[ip_scan(glue.s,&ix.addr.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.addr.ip)])
     {
+     ix.af = AF_INET;
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
      return 0;
     }
@@ -396,3 +614,49 @@
  alloc_free(mx);
  return flagsoft;
 }
+
+
+static int dns_txtplus(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+
+ switch(resolve(sa,T_TXT)) 
+  {
+   case DNS_MEM: return DNS_MEM;
+   case DNS_SOFT: return DNS_SOFT;
+   case DNS_HARD: return DNS_HARD;
+  }
+ while ((r = findtxt(T_TXT)) != 2)
+  {
+   if (r == DNS_SOFT) return DNS_SOFT;
+   if (r == 1)
+    {
+     stralloc sa = {0};
+     if (!stralloc_copy(&sa,&txt)) return DNS_MEM;
+     if (!strsalloc_append(ssa,&sa)) return DNS_MEM;
+    }
+  }
+ if (ssa->len) return 0;
+ return DNS_HARD;
+}
+
+int dns_txt(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_txtplus(ssa,sa);
+ if (r < 0)
+  {
+   for (j = 0;j < ssa->len;++j)
+    alloc_free(ssa->sa[j].s);
+   ssa->len = 0;
+  }
+ return r;
+}
diff -ur netqmail-1.05/dns.c.orig netqmail-1.05.patched/dns.c.orig
--- netqmail-1.05/dns.c.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/dns.c.orig	2008-06-04 19:35:18.000000000 +0200
@@ -7,10 +7,9 @@
 #include <errno.h>
 extern int res_query();
 extern int res_search();
-extern int errno;
-extern int h_errno;
 #include "ip.h"
 #include "ipalloc.h"
+#include "strsalloc.h"
 #include "fmt.h"
 #include "alloc.h"
 #include "str.h"
@@ -21,14 +20,17 @@
 static unsigned short getshort(c) unsigned char *c;
 { unsigned short u; u = c[0]; return (u << 8) + c[1]; }
 
-static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static struct { unsigned char *buf; } response;
+static int responsebuflen = 0;
 static int responselen;
 static unsigned char *responseend;
 static unsigned char *responsepos;
+static u_long saveresoptions;
 
 static int numanswers;
 static char name[MAXDNAME];
 static struct ip_address ip;
+static stralloc txt = {0};
 unsigned short pref;
 
 static stralloc glue = {0};
@@ -45,18 +47,33 @@
  errno = 0;
  if (!stralloc_copy(&glue,domain)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
- responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response));
+ if (!responsebuflen)
+  if (response.buf = (unsigned char *)alloc(PACKETSZ+1))
+   responsebuflen = PACKETSZ+1;
+  else return DNS_MEM;
+
+ responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+ if ((responselen >= responsebuflen) ||
+     (responselen > 0 && (((HEADER *)response.buf)->tc)))
+  {
+   if (responsebuflen < 65536)
+    if (alloc_re(&response.buf, responsebuflen, 65536))
+     responsebuflen = 65536;
+    else return DNS_MEM;
+    saveresoptions = _res.options;
+    _res.options |= RES_USEVC;
+    responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+    _res.options = saveresoptions;
+  }
  if (responselen <= 0)
   {
    if (errno == ECONNREFUSED) return DNS_SOFT;
    if (h_errno == TRY_AGAIN) return DNS_SOFT;
    return DNS_HARD;
   }
- if (responselen >= sizeof(response))
-   responselen = sizeof(response);
  responseend = response.buf + responselen;
  responsepos = response.buf + sizeof(HEADER);
- n = ntohs(response.hdr.qdcount);
+ n = ntohs(((HEADER *)response.buf)->qdcount);
  while (n-- > 0)
   {
    i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
@@ -66,7 +83,7 @@
    if (i < QFIXEDSZ) return DNS_SOFT;
    responsepos += QFIXEDSZ;
   }
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
  return 0;
 }
 
@@ -179,6 +196,49 @@
  return 0;
 }
 
+static int findtxt(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+   
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+  {
+   unsigned short txtpos;
+   unsigned char txtlen;
+
+   txt.len = 0;
+   for (txtpos = 0;txtpos < rrdlen;txtpos += txtlen)
+    {
+     txtlen = responsepos[txtpos++];
+     if (txtlen > rrdlen-txtpos) txtlen = rrdlen-txtpos;
+     if (!stralloc_catb(&txt,&responsepos[txtpos],txtlen)) return DNS_MEM;
+    }
+
+   responsepos += rrdlen;
+   return 1;
+ }
+
+ responsepos += rrdlen;
+ return 0;
+}
+
 void dns_init(flagsearch)
 int flagsearch;
 {
@@ -237,15 +297,18 @@
  return len;
 }
 
-int dns_ptr(sa,ip)
-stralloc *sa;
+static int dns_ptrplus(ssa,ip)
+strsalloc *ssa;
 struct ip_address *ip;
 {
+ stralloc sa = {0};
  int r;
 
- if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM;
- sa->len = iaafmt(sa->s,ip);
- switch(resolve(sa,T_PTR))
+ if (!stralloc_ready(&sa,iaafmt((char *) 0,ip))) return DNS_MEM;
+ sa.len = iaafmt(sa.s,ip);
+ r = resolve(&sa,T_PTR);
+ alloc_free(sa.s);
+ switch(r)
   {
    case DNS_MEM: return DNS_MEM;
    case DNS_SOFT: return DNS_SOFT;
@@ -256,25 +319,46 @@
    if (r == DNS_SOFT) return DNS_SOFT;
    if (r == 1)
     {
-     if (!stralloc_copys(sa,name)) return DNS_MEM;
-     return 0;
+     stralloc sa2 = {0};
+     if (!stralloc_copys(&sa2,name)) return DNS_MEM;
+     if (!strsalloc_append(ssa,&sa2)) return DNS_MEM;
     }
   }
+ if (ssa->len) return 0;
  return DNS_HARD;
 }
 
+int dns_ptr(ssa,ip)
+strsalloc *ssa;
+struct ip_address *ip;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_ptrplus(ssa,ip);
+ if (r < 0)
+  {
+   for (j = 0;j < ssa->len;++j)
+    alloc_free(ssa->sa[j].s);
+   ssa->len = 0;
+  }
+ return r;
+}
+
+
 static int dns_ipplus(ia,sa,pref)
 ipalloc *ia;
 stralloc *sa;
 int pref;
 {
  int r;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
 
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
    if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
     {
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
@@ -293,9 +377,16 @@
    ix.ip = ip;
    ix.pref = pref;
    if (r == DNS_SOFT) return DNS_SOFT;
-   if (r == 1)
+   if (r == 1) {
+#ifdef IX_FQDN
+     ix.fqdn = glue.s;
+#endif
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
   }
+  }
+#ifdef IX_FQDN
+ glue.s = 0;
+#endif
  return 0;
 }
 
@@ -315,7 +406,7 @@
 {
  int r;
  struct mx { stralloc sa; unsigned short p; } *mx;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
  int nummx;
  int i;
  int j;
@@ -327,7 +418,6 @@
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
    if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
     {
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
@@ -398,3 +488,49 @@
  alloc_free(mx);
  return flagsoft;
 }
+
+
+static int dns_txtplus(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+
+ switch(resolve(sa,T_TXT)) 
+  {
+   case DNS_MEM: return DNS_MEM;
+   case DNS_SOFT: return DNS_SOFT;
+   case DNS_HARD: return DNS_HARD;
+  }
+ while ((r = findtxt(T_TXT)) != 2)
+  {
+   if (r == DNS_SOFT) return DNS_SOFT;
+   if (r == 1)
+    {
+     stralloc sa = {0};
+     if (!stralloc_copy(&sa,&txt)) return DNS_MEM;
+     if (!strsalloc_append(ssa,&sa)) return DNS_MEM;
+    }
+  }
+ if (ssa->len) return 0;
+ return DNS_HARD;
+}
+
+int dns_txt(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_txtplus(ssa,sa);
+ if (r < 0)
+  {
+   for (j = 0;j < ssa->len;++j)
+    alloc_free(ssa->sa[j].s);
+   ssa->len = 0;
+  }
+ return r;
+}
diff -ur netqmail-1.05/dns.h netqmail-1.05.patched/dns.h
--- netqmail-1.05/dns.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/dns.h	2008-06-04 19:35:18.000000000 +0200
@@ -10,5 +10,6 @@
 int dns_mxip();
 int dns_ip();
 int dns_ptr();
+int dns_txt();
 
 #endif
Only in netqmail-1.05.patched: dns.h.orig
diff -ur netqmail-1.05/dnsfq.c netqmail-1.05.patched/dnsfq.c
--- netqmail-1.05/dnsfq.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/dnsfq.c	2008-06-04 19:35:18.000000000 +0200
@@ -5,15 +5,19 @@
 #include "dnsdoe.h"
 #include "ip.h"
 #include "ipalloc.h"
+#include "strsalloc.h"
 #include "exit.h"
 
 stralloc sa = {0};
+strsalloc ssa = {0};
 ipalloc ia = {0};
 
 void main(argc,argv)
 int argc;
 char **argv;
 {
+ int j;
+
  if (!argv[1]) _exit(100);
 
  if (!stralloc_copys(&sa,argv[1]))
@@ -25,8 +29,11 @@
   {
    substdio_putsflush(subfderr,"no IP addresses\n"); _exit(100);
   }
- dnsdoe(dns_ptr(&sa,&ia.ix[0].ip));
- substdio_putflush(subfdout,sa.s,sa.len);
- substdio_putsflush(subfdout,"\n");
+ dnsdoe(dns_ptr(&ssa,&ia.ix[0].addr.ip));
+ for(j = 0;j < ssa.len;++j)
+  {
+   substdio_putflush(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+   substdio_putsflush(subfdout,"\n");
+  }
  _exit(0);
 }
Only in netqmail-1.05.patched: dnsfq.c.orig
diff -ur netqmail-1.05/dnsip.c netqmail-1.05.patched/dnsip.c
--- netqmail-1.05/dnsip.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/dnsip.c	2008-06-04 19:35:18.000000000 +0200
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/socket.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "stralloc.h"
@@ -27,7 +29,20 @@
  dnsdoe(dns_ip(&ia,&sa));
  for (j = 0;j < ia.len;++j)
   {
-   substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip));
+ //  substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip));
+    switch(ia.ix[j].af) {
+   case AF_INET:
+      substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].addr.ip));
+      break;
+#ifdef INET6
+   case AF_INET6:
+      substdio_put(subfdout,temp,ip6_fmt(temp,&ia.ix[j].addr.ip6));
+      break;
+#endif
+   default:
+      substdio_puts(subfdout,"Unknown address family = ");
+      substdio_put(subfdout,temp,fmt_ulong(temp,ia.ix[j].af));
+   }
    substdio_putsflush(subfdout,"\n");
   }
  _exit(0);
Only in netqmail-1.05.patched: dnsip.c.orig
diff -ur netqmail-1.05/dnsmxip.c netqmail-1.05.patched/dnsmxip.c
--- netqmail-1.05/dnsmxip.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/dnsmxip.c	2008-06-04 19:35:18.000000000 +0200
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/socket.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "stralloc.h"
@@ -31,7 +33,19 @@
  dnsdoe(dns_mxip(&ia,&sa,r));
  for (j = 0;j < ia.len;++j)
   {
-   substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip));
+   switch(ia.ix[j].af) {
+   case AF_INET:
+      substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].addr.ip));
+      break;
+#ifdef INET6
+   case AF_INET6:
+      substdio_put(subfdout,temp,ip6_fmt(temp,&ia.ix[j].addr.ip6));
+      break;
+#endif
+   default:
+      substdio_puts(subfdout,"Unknown address family = ");
+      substdio_put(subfdout,temp,fmt_ulong(temp,ia.ix[j].af));
+   }
    substdio_puts(subfdout," ");
    substdio_put(subfdout,temp,fmt_ulong(temp,(unsigned long) ia.ix[j].pref));
    substdio_putsflush(subfdout,"\n");
Only in netqmail-1.05.patched: dnsmxip.c.orig
diff -ur netqmail-1.05/dnsptr.c netqmail-1.05.patched/dnsptr.c
--- netqmail-1.05/dnsptr.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/dnsptr.c	2008-06-04 19:35:18.000000000 +0200
@@ -6,22 +6,28 @@
 #include "dns.h"
 #include "dnsdoe.h"
 #include "ip.h"
+#include "strsalloc.h"
 #include "exit.h"
 
-stralloc sa = {0};
+strsalloc ssa = {0};
 struct ip_address ip;
 
 void main(argc,argv)
 int argc;
 char **argv;
 {
+ int j;
+
  if (!argv[1]) _exit(100);
 
  ip_scan(argv[1],&ip);
 
  dns_init(0);
- dnsdoe(dns_ptr(&sa,&ip));
- substdio_putflush(subfdout,sa.s,sa.len);
- substdio_putsflush(subfdout,"\n");
+ dnsdoe(dns_ptr(&ssa,&ip));
+ for(j = 0;j < ssa.len;++j)
+  {
+   substdio_putflush(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+   substdio_putsflush(subfdout,"\n");
+  }
  _exit(0);
 }
Only in netqmail-1.05.patched: dnsptr.c.orig
Only in netqmail-1.05.patched: dnstxt.c
Only in netqmail-1.05.patched: dnstxt.c.orig
diff -ur netqmail-1.05/fmt.h netqmail-1.05.patched/fmt.h
--- netqmail-1.05/fmt.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/fmt.h	2008-06-04 19:35:18.000000000 +0200
@@ -2,6 +2,7 @@
 #define FMT_H
 
 #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
+#define FMT_2LONG 129 /* same, but in binary */
 #define FMT_LEN ((char *) 0) /* convenient abbreviation */
 
 extern unsigned int fmt_uint();
@@ -12,8 +13,11 @@
 extern unsigned int fmt_xshort();
 extern unsigned int fmt_nbbshort();
 extern unsigned int fmt_ulong();
+extern unsigned int fmt_ulong0();
 extern unsigned int fmt_xlong();
 extern unsigned int fmt_nbblong();
+extern unsigned int fmt_2long();
+extern unsigned int fmt_2long0();
 
 extern unsigned int fmt_plusminus();
 extern unsigned int fmt_minus();
Only in netqmail-1.05.patched: fmt.h.orig
Only in netqmail-1.05.patched: fmt_2long.c
Only in netqmail-1.05.patched: fmt_2long.c.orig
Only in netqmail-1.05.patched: fmt_2long0.c
Only in netqmail-1.05.patched: fmt_2long0.c.orig
Only in netqmail-1.05.patched: fmt_ulong0.c
Only in netqmail-1.05.patched: fmt_ulong0.c.orig
diff -ur netqmail-1.05/hier.c netqmail-1.05.patched/hier.c
--- netqmail-1.05/hier.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/hier.c	2008-06-04 19:35:18.000000000 +0200
@@ -47,6 +47,7 @@
   d(auto_qmail,"man/man8",auto_uido,auto_gidq,0755);
 
   d(auto_qmail,"alias",auto_uida,auto_gidq,02755);
+  d(auto_qmail,"spam",auto_uidd,auto_gidn,02700);
 
   d(auto_qmail,"queue",auto_uidq,auto_gidq,0750);
   d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700);
@@ -76,6 +77,7 @@
   c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
 
   c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
@@ -109,6 +111,7 @@
   c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-newst",auto_uido,auto_gidq,0700);
   c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700);
   c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700);
   c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711);
@@ -143,6 +146,9 @@
   c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
   c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
+#ifdef TLS
+  c(auto_qmail,"bin","update_tmprsadh",auto_uido,auto_gidq,0755);
+#endif
 
   c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
@@ -164,6 +170,10 @@
   c(auto_qmail,"man/cat5","qmail-users.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man5","tcp-environ.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","tcp-environ.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","qmail-spamt.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","qmail-spamt.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","qmail-spamthrottle.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","qmail-spamthrottle.0",auto_uido,auto_gidq,0644);
 
   c(auto_qmail,"man/man7","forgeries.7",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat7","forgeries.0",auto_uido,auto_gidq,0644);
@@ -223,6 +233,8 @@
   c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-newst.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-newst.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat8","qmail-newu.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man8","qmail-pw2u.8",auto_uido,auto_gidq,0644);
Only in netqmail-1.05.patched: hier.c.orig
diff -ur netqmail-1.05/install-big.c netqmail-1.05.patched/install-big.c
--- netqmail-1.05/install-big.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/install-big.c	2008-06-04 19:35:18.000000000 +0200
@@ -76,6 +76,7 @@
   c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
 
   c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","README.qregex",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
Only in netqmail-1.05.patched: install-big.c.orig
Only in netqmail-1.05.patched: install_auth.sh
Only in netqmail-1.05.patched: install_auth.sh.orig
diff -ur netqmail-1.05/ip.c netqmail-1.05.patched/ip.c
--- netqmail-1.05/ip.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/ip.c	2008-06-04 19:35:18.000000000 +0200
@@ -1,6 +1,7 @@
 #include "fmt.h"
 #include "scan.h"
 #include "ip.h"
+#include "byte.h"
 
 unsigned int ip_fmt(s,ip)
 char *s;
@@ -20,6 +21,44 @@
   return len;
 }
 
+unsigned int fmt_ipn(s,ip,n)
+char *s;
+struct ip_address *ip;
+unsigned int n;
+{
+  struct ip_address ipn;
+  unsigned long uip = 0;
+
+  uip += ip->d[0]; uip <<= 8;
+  uip += ip->d[1]; uip <<= 8;
+  uip += ip->d[2]; uip <<= 8;
+  uip += ip->d[3];
+
+  uip &= ~((1<<(32-n))-1);
+
+  ipn.d[3] = uip & 0xff; uip >>= 8;
+  ipn.d[2] = uip & 0xff; uip >>= 8;
+  ipn.d[1] = uip & 0xff; uip >>= 8;
+  ipn.d[0] = uip;
+
+  return ip_fmt(s,&ipn);
+}
+
+unsigned int fmt_2ip0(s,ip)
+char *s;
+struct ip_address *ip;
+{
+  unsigned long uip = 0;
+
+  uip += ip->d[0]; uip <<= 8;
+  uip += ip->d[1]; uip <<= 8;
+  uip += ip->d[2]; uip <<= 8;
+  uip += ip->d[3];
+
+  return fmt_2long0(s,uip,32);
+}
+
+
 unsigned int ip_scan(s,ip)
 char *s;
 struct ip_address *ip;
@@ -51,3 +90,32 @@
   if (s[len + 1] != ']') return 0;
   return len + 2;
 }
+
+#ifdef INET6
+int fmt_hexbyte(char *s, unsigned char byte)
+{
+  static char data[] = "0123456789abcdef";
+
+  if (s) {
+    *s++ = data[(byte >> 4) & 0xf];
+    *s = data[byte & 0xf];
+  }
+  return 2;
+}
+
+unsigned int ip6_fmt(s,ip6)
+char *s;
+struct ip6_address *ip6;
+{
+  unsigned int len;
+  unsigned int i, j, k;
+ 
+  len = 0;
+  for (j = 0, len = 0, k = 0; j < 8; j++) {
+    i = fmt_hexbyte(s, ip6->d[k++]); len += i; if (s) s += i;
+    i = fmt_hexbyte(s, ip6->d[k++]); len += i; if (s) s += i;
+    i = fmt_str(s,":"); len += i; if (s) s += i;
+  }
+  return len-1;
+}
+#endif
Only in netqmail-1.05.patched: ip.c.orig
diff -ur netqmail-1.05/ip.h netqmail-1.05.patched/ip.h
--- netqmail-1.05/ip.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/ip.h	2008-06-04 19:35:18.000000000 +0200
@@ -2,10 +2,24 @@
 #define IP_H
 
 struct ip_address { unsigned char d[4]; } ;
+#ifdef INET6
+struct ip6_address { unsigned char d[16]; } ;
+#endif
 
 extern unsigned int ip_fmt();
+#ifdef INET6
+extern unsigned int ip6_fmt();
+#define IPFMT 72
+#else
 #define IPFMT 19
+#endif
+
+extern unsigned int fmt_ipn();		/* to n-bit masked ip address */
+extern unsigned int fmt_2ip0();		/* to a binary string with leading zeroes */
+#define FMT_2IP 33
 extern unsigned int ip_scan();
 extern unsigned int ip_scanbracket();
 
+#define HOSTNAMELEN	1025
+
 #endif
Only in netqmail-1.05.patched: ip.h.orig
diff -ur netqmail-1.05/ipalloc.h netqmail-1.05.patched/ipalloc.h
--- netqmail-1.05/ipalloc.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/ipalloc.h	2008-06-04 19:35:18.000000000 +0200
@@ -3,7 +3,32 @@
 
 #include "ip.h"
 
-struct ip_mx { struct ip_address ip; int pref; } ;
+#ifdef TLS
+# define IX_FQDN 1
+#endif
+
+#ifdef IX_FQDN
+struct ip_mx { 
+  unsigned short af;
+  union {
+    struct ip_address ip;
+#ifdef INET6
+    struct ip6_address ip6;
+#endif
+    } addr;
+  int pref; 
+  char *fqdn; } ;
+#else
+struct ip_mx { 
+  unsigned short af;
+  union {
+    struct ip_address ip;
+#ifdef INET6
+    struct ip6_address ip6;
+#endif
+    } addr;
+    int pref; } ;
+#endif
 
 #include "gen_alloc.h"
 
Only in netqmail-1.05.patched: ipalloc.h.orig
diff -ur netqmail-1.05/ipme.c netqmail-1.05.patched/ipme.c
--- netqmail-1.05/ipme.c	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/ipme.c	2008-06-04 19:35:18.000000000 +0200
@@ -24,11 +24,24 @@
   int i;
   if (ipme_init() != 1) return -1;
   for (i = 0;i < ipme.len;++i)
-    if (byte_equal(&ipme.ix[i].ip,4,ip))
+    if (ipme.ix[i].af == AF_INET && byte_equal(&ipme.ix[i].addr.ip,4,ip))
       return 1;
   return 0;
 }
 
+#ifdef INET6
+int ipme_is6(ip)
+struct ip6_address *ip;
+{
+  int i;
+  if (ipme_init() != 1) return -1;
+  for (i = 0;i < ipme.len;++i)
+    if (ipme.ix[i].af == AF_INET6 && byte_equal(&ipme.ix[i].addr.ip6,16,ip))
+      return 1;
+  return 0;
+}
+#endif
+
 static stralloc buf = {0};
 
 int ipme_init()
@@ -37,6 +50,9 @@
   char *x;
   struct ifreq *ifr;
   struct sockaddr_in *sin;
+  #ifdef INET6
+  struct sockaddr_in6 *sin6;
+  #endif
   int len;
   int s;
   struct ip_mx ix;
@@ -49,7 +65,7 @@
   /* 0.0.0.0 is a special address which always refers to 
    * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a.
   */
-  byte_copy(&ix.ip,4,"\0\0\0\0");
+    byte_copy(&ix.addr.ip,4,"\0\0\0\0");
   if (!ipalloc_append(&ipme,&ix)) { return 0; }
   if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
  
@@ -76,11 +92,22 @@
       len = sizeof(*ifr);
     if (ifr->ifr_addr.sa_family == AF_INET) {
       sin = (struct sockaddr_in *) &ifr->ifr_addr;
-      byte_copy(&ix.ip,4,&sin->sin_addr);
+      byte_copy(&ix.addr.ip,4,&sin->sin_addr);
+      ix.af = AF_INET;
       if (ioctl(s,SIOCGIFFLAGS,x) == 0)
         if (ifr->ifr_flags & IFF_UP)
           if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
     }
+#ifdef INET6
+	else if (ifr->ifr_addr.sa_family == AF_INET6) {
+      sin6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
+      byte_copy(&ix.addr.ip6,16,&sin6->sin6_addr);
+      ix.af = AF_INET6;
+      if (ioctl(s,SIOCGIFFLAGS,x) == 0)
+        if (ifr->ifr_flags & IFF_UP)
+          if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
+    }
+#endif
 #else
     len = sizeof(*ifr);
     if (ioctl(s,SIOCGIFFLAGS,x) == 0)
@@ -88,10 +115,19 @@
         if (ioctl(s,SIOCGIFADDR,x) == 0)
 	  if (ifr->ifr_addr.sa_family == AF_INET) {
 	    sin = (struct sockaddr_in *) &ifr->ifr_addr;
-	    byte_copy(&ix.ip,4,&sin->sin_addr);
+	    ix.af = AF_INET;
+	    byte_copy(&ix.addr.ip,4,&sin->sin_addr);
+	    if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
+	  }
+#ifdef INET6
+      else if (ifr->ifr_addr.sa_family == AF_INET6) {
+	    sin6 = (struct sockaddr_in6 *) &ifr->ifr_addr;
+        ix.af = AF_INET6;
+	    byte_copy(&ix.addr.ip6,16,&sin6->sin6_addr);
 	    if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; }
 	  }
 #endif
+#endif
     x += len;
   }
   close(s);
diff -ur netqmail-1.05/ipme.c.orig netqmail-1.05.patched/ipme.c.orig
--- netqmail-1.05/ipme.c.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/ipme.c.orig	2008-06-04 19:35:18.000000000 +0200
@@ -46,6 +46,11 @@
   ipme.len = 0;
   ix.pref = 0;
  
+  /* 0.0.0.0 is a special address which always refers to 
+   * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a.
+  */
+  byte_copy(&ix.ip,4,"\0\0\0\0");
+  if (!ipalloc_append(&ipme,&ix)) { return 0; }
   if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
  
   len = 256;
diff -ur netqmail-1.05/ipmeprint.c netqmail-1.05.patched/ipmeprint.c
--- netqmail-1.05/ipmeprint.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/ipmeprint.c	2008-06-04 19:35:18.000000000 +0200
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/socket.h>
 #include "subfd.h"
 #include "substdio.h"
 #include "ip.h"
@@ -16,8 +18,20 @@
   }
  for (j = 0;j < ipme.len;++j)
   {
-   substdio_put(subfdout,temp,ip_fmt(temp,&ipme.ix[j].ip));
-   substdio_puts(subfdout,"\n");
+   switch(ipme.ix[j].af) {
+   case AF_INET:
+      substdio_put(subfdout,temp,ip_fmt(temp,&ipme.ix[j].addr.ip));
+      break;
+#ifdef INET6
+   case AF_INET6:
+      substdio_put(subfdout,temp,ip6_fmt(temp,&ipme.ix[j].addr.ip6));
+      break;
+#endif
+   default:
+      substdio_puts(subfdout,"Unknown address family = ");
+      substdio_put(subfdout,temp,fmt_ulong(temp,ipme.ix[j].af));
+   }
+   substdio_puts(subfdout,"\n");   
   }
  substdio_flush(subfdout);
  _exit(0);
Only in netqmail-1.05.patched: ipmeprint.c.orig
diff -ur netqmail-1.05/lock.h netqmail-1.05.patched/lock.h
--- netqmail-1.05/lock.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/lock.h	2008-06-04 19:35:18.000000000 +0200
@@ -5,4 +5,7 @@
 extern int lock_un();
 extern int lock_exnb();
 
+extern int lock_exfcntl();
+extern int lock_unfcntl();
+
 #endif
Only in netqmail-1.05.patched: lock.h.orig
Only in netqmail-1.05.patched: lock_exfcntl.c
Only in netqmail-1.05.patched: lock_exfcntl.c.orig
Only in netqmail-1.05.patched: lock_unfcntl.c
Only in netqmail-1.05.patched: lock_unfcntl.c.orig
Only in netqmail-1.05.patched: maildirflags.c
Only in netqmail-1.05.patched: maildirflags.c.orig
Only in netqmail-1.05.patched: maildirgetquota.c
Only in netqmail-1.05.patched: maildirgetquota.c.orig
Only in netqmail-1.05.patched: maildirgetquota.h
Only in netqmail-1.05.patched: maildirgetquota.h.orig
Only in netqmail-1.05.patched: maildirmisc.h
Only in netqmail-1.05.patched: maildirmisc.h.orig
Only in netqmail-1.05.patched: maildiropen.c
Only in netqmail-1.05.patched: maildiropen.c.orig
Only in netqmail-1.05.patched: maildirparsequota.c
Only in netqmail-1.05.patched: maildirparsequota.c.orig
Only in netqmail-1.05.patched: maildirquota.c
Only in netqmail-1.05.patched: maildirquota.c.orig
Only in netqmail-1.05.patched: maildirquota.h
Only in netqmail-1.05.patched: maildirquota.h.orig
Only in netqmail-1.05.patched: numlib.h
Only in netqmail-1.05.patched: numlib.h.orig
diff -ur netqmail-1.05/open.h netqmail-1.05.patched/open.h
--- netqmail-1.05/open.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/open.h	2008-06-04 19:35:18.000000000 +0200
@@ -6,5 +6,6 @@
 extern int open_append();
 extern int open_trunc();
 extern int open_write();
+extern int open_rw();
 
 #endif
Only in netqmail-1.05.patched: open.h.orig
Only in netqmail-1.05.patched: open_rw.c
Only in netqmail-1.05.patched: open_rw.c.orig
Only in netqmail-1.05.patched: overmaildirquota.c
Only in netqmail-1.05.patched: overmaildirquota.c.orig
diff -ur netqmail-1.05/qmail-control.9 netqmail-1.05.patched/qmail-control.9
--- netqmail-1.05/qmail-control.9	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-control.9	2008-06-04 19:35:18.000000000 +0200
@@ -20,7 +20,11 @@
 
 Comments are allowed
 in
+.IR badhelo ,
 .IR badmailfrom ,
+.IR badmailfromnorelay ,
+.IR badmailto ,
+.IR badmailtonorelay ,
 .IR locals ,
 .IR percenthack ,
 .IR qmqpservers ,
@@ -40,14 +44,22 @@
 .ta 5c 10c
 control	default	used by
 
+.I badhelo	\fR(none)	\fRqmail-smtpd
 .I badmailfrom	\fR(none)	\fRqmail-smtpd
+.I badmailfromnorelay	\fR(none)	\fRqmail-smtpd
+.I badmailto	\fR(none)	\fRqmail-smtpd
+.I badmailtonorelay	\fR(none)	\fRqmail-smtpd
 .I bouncefrom	\fRMAILER-DAEMON	\fRqmail-send
 .I bouncehost	\fIme	\fRqmail-send
+.I clientca.pem	\fR(none)	\fRqmail-smtpd
+.I clientcert.pem	\fR(none)	\fRqmail-remote
 .I concurrencylocal	\fR10	\fRqmail-send
 .I concurrencyremote	\fR20	\fRqmail-send
 .I defaultdomain	\fIme	\fRqmail-inject
 .I defaulthost	\fIme	\fRqmail-inject
 .I databytes	\fR0	\fRqmail-smtpd
+.I dh1024.pem	\fR(none)	\fRqmail-smtpd
+.I dh512.pem	\fR(none)	\fRqmail-smtpd
 .I doublebouncehost	\fIme	\fRqmail-send
 .I doublebounceto	\fRpostmaster	\fRqmail-send
 .I envnoathost	\fIme	\fRqmail-send
@@ -61,11 +73,22 @@
 .I qmqpservers	\fR(none)	\fRqmail-qmqpc
 .I queuelifetime	\fR604800	\fRqmail-send
 .I rcpthosts	\fR(none)	\fRqmail-smtpd
+.I rsa512.pem	\fR(none)	\fRqmail-smtpd
+.I servercert.pem	\fR(none)	\fRqmail-smtpd
 .I smtpgreeting	\fIme	\fRqmail-smtpd
 .I smtproutes	\fR(none)	\fRqmail-remote
+.I spfbehavior        \fR0    \fRqmail-smtpd
+.I spfexp     \fR(default)    \fRqmail-smtpd
+.I spfguess   \fR(none)       \fRqmail-smtpd
+.I spfrules   \fR(none)       \fRqmail-smtpd
+.I spamt	\fR(none)	\fRqmail-smtpd
 .I timeoutconnect	\fR60	\fRqmail-remote
 .I timeoutremote	\fR1200	\fRqmail-remote
 .I timeoutsmtpd	\fR1200	\fRqmail-smtpd
+.I tlsclients	\fR(none)	\fRqmail-smtpd
+.I tlsclientciphers	\fR(none)	\fRqmail-remote
+.I tlshosts/FQDN.pem	\fR(none)	\fRqmail-remote
+.I tlsserverciphers	\fR(none)	\fRqmail-smtpd
 .I virtualdomains	\fR(none)	\fRqmail-send
 .fi
 .RE
Only in netqmail-1.05.patched: qmail-control.9.orig
diff -ur netqmail-1.05/qmail-local.c netqmail-1.05.patched/qmail-local.c
--- netqmail-1.05/qmail-local.c	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/qmail-local.c	2008-06-04 19:35:18.000000000 +0200
@@ -66,6 +66,7 @@
 
 char buf[1024];
 char outbuf[1024];
+#define QUOTABUFSIZE    256
 
 /* child process */
 
@@ -86,9 +87,15 @@
  int fd;
  substdio ss;
  substdio ssout;
+ char quotabuf[QUOTABUFSIZE];
 
  sig_alarmcatch(sigalrm);
  if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); }
+ if (maildir_getquota(dir, quotabuf) == 0) {
+  if (user_over_maildirquota(dir,quotabuf)==1) {
+   _exit(1);
+  }
+ }
  pid = getpid();
  host[0] = 0;
  gethostname(host,sizeof(host));
@@ -99,7 +106,10 @@
    s += fmt_str(s,"tmp/");
    s += fmt_ulong(s,time); *s++ = '.';
    s += fmt_ulong(s,pid); *s++ = '.';
-   s += fmt_strn(s,host,sizeof(host)); *s++ = 0;
+   s += fmt_strn(s,host,sizeof(host));
+   s += fmt_strn(s,",S=",sizeof(",S="));
+   if (fstat(0,&st) == -1) if (errno == error_noent) break;
+   s += fmt_ulong(s,st.st_size); *s++ = 0;
    if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
    /* really should never get to this point */
    if (loop == 2) _exit(1);
@@ -159,6 +169,7 @@
  switch(wait_exitcode(wstat))
   {
    case 0: break;
+   case 1: strerr_die1x(1, "User over quota. (#5.1.1)");
    case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
    case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
    case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
diff -ur netqmail-1.05/qmail-local.c.orig netqmail-1.05.patched/qmail-local.c.orig
--- netqmail-1.05/qmail-local.c.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-local.c.orig	2008-06-04 19:35:18.000000000 +0200
@@ -645,7 +645,7 @@
     {
      cmds.s[j] = 0;
      k = j;
-     while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))
+     while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
        cmds.s[--k] = 0;
      switch(cmds.s[i])
       {
Only in netqmail-1.05.patched: qmail-newst.0
Only in netqmail-1.05.patched: qmail-newst.0.orig
Only in netqmail-1.05.patched: qmail-newst.8
Only in netqmail-1.05.patched: qmail-newst.8.orig
Only in netqmail-1.05.patched: qmail-newst.9
Only in netqmail-1.05.patched: qmail-newst.9.orig
Only in netqmail-1.05.patched: qmail-newst.c
Only in netqmail-1.05.patched: qmail-newst.c.orig
diff -ur netqmail-1.05/qmail-pop3d.c netqmail-1.05.patched/qmail-pop3d.c
--- netqmail-1.05/qmail-pop3d.c	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/qmail-pop3d.c	2008-06-04 19:35:18.000000000 +0200
@@ -16,6 +16,11 @@
 #include "readwrite.h"
 #include "timeoutread.h"
 #include "timeoutwrite.h"
+#include <errno.h>
+#include "maildirquota.h"
+#include "maildirmisc.h"
+
+#define QUOTABUFSIZE 256
 
 void die() { _exit(0); }
 
@@ -45,19 +50,15 @@
 {
   substdio_put(&ssout,buf,len);
 }
-void puts(s) char *s;
-{
-  substdio_puts(&ssout,s);
-}
 void flush()
 {
   substdio_flush(&ssout);
 }
 void err(s) char *s;
 {
-  puts("-ERR ");
-  puts(s);
-  puts("\r\n");
+  substdio_puts(&ssout,"-ERR ");
+  substdio_puts(&ssout,s);
+  substdio_puts(&ssout,"\r\n");
   flush();
 }
 
@@ -73,7 +74,7 @@
 void err_nosuch() { err("unable to open that message"); }
 void err_nounlink() { err("unable to unlink all deleted messages"); }
 
-void okay(arg) char *arg; { puts("+OK \r\n"); flush(); }
+void okay() { substdio_puts(&ssout,"+OK \r\n"); flush(); }
 
 void printfn(fn) char *fn;
 {
@@ -153,11 +154,11 @@
  
   total = 0;
   for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
-  puts("+OK ");
+  substdio_puts(&ssout,"+OK ");
   put(strnum,fmt_uint(strnum,numm));
-  puts(" ");
+  substdio_puts(&ssout," ");
   put(strnum,fmt_ulong(strnum,total));
-  puts("\r\n");
+  substdio_puts(&ssout,"\r\n");
   flush();
 }
 
@@ -171,18 +172,41 @@
 
 void pop3_last(arg) char *arg;
 {
-  puts("+OK ");
+  substdio_puts(&ssout,"+OK ");
   put(strnum,fmt_uint(strnum,last));
-  puts("\r\n");
+  substdio_puts(&ssout,"\r\n");
   flush();
 }
 
 void pop3_quit(arg) char *arg;
 {
   int i;
+  char quotabuf[QUOTABUFSIZE];
+  int has_quota=maildir_getquota(".", quotabuf);
+
+  long deleted_bytes=0;
+  long deleted_messages=0;
+
   for (i = 0;i < numm;++i)
     if (m[i].flagdeleted) {
-      if (unlink(m[i].fn) == -1) err_nounlink();
+      unsigned long un=0;
+      const char *filename=m[i].fn;
+      if (has_quota == 0 && !MAILDIR_DELETED(filename)) {
+          if (maildir_parsequota(filename, &un)) {
+              struct stat stat_buf;
+
+              if (stat(filename, &stat_buf) == 0)
+                  un=stat_buf.st_size;
+          }
+      }
+      if (unlink(m[i].fn) == -1) {
+          err_nounlink();
+          un=0;
+      }
+      if (un) {
+          deleted_bytes -= un;
+          deleted_messages -= 1;
+      }
     }
     else
       if (str_start(m[i].fn,"new/")) {
@@ -192,6 +216,21 @@
 	if (!stralloc_0(&line)) die_nomem();
 	rename(m[i].fn,line.s); /* if it fails, bummer */
       }
+
+    if (deleted_messages < 0) {
+        int quotafd;
+
+        if (maildir_checkquota(".", &quotafd, quotabuf, deleted_bytes,
+                               deleted_messages) && errno != EAGAIN &&
+                               deleted_bytes >= 0)
+            {
+                if (quotafd >= 0) close (quotafd);
+            } else {
+                 maildir_addquota(".", quotafd, quotabuf,
+                                 deleted_bytes, deleted_messages);
+                 if (quotafd >= 0) close(quotafd);
+            }
+        }
   okay(0);
   die();
 }
@@ -222,10 +261,10 @@
 int flaguidl;
 {
   put(strnum,fmt_uint(strnum,i + 1));
-  puts(" ");
+  substdio_puts(&ssout," ");
   if (flaguidl) printfn(m[i].fn);
   else put(strnum,fmt_ulong(strnum,m[i].size));
-  puts("\r\n");
+  substdio_puts(&ssout,"\r\n");
 }
 
 void dolisting(arg,flaguidl) char *arg; int flaguidl;
@@ -234,7 +273,7 @@
   if (*arg) {
     i = msgno(arg);
     if (i == -1) return;
-    puts("+OK ");
+    substdio_puts(&ssout,"+OK ");
     list(i,flaguidl);
   }
   else {
@@ -242,7 +281,7 @@
     for (i = 0;i < numm;++i)
       if (!m[i].flagdeleted)
 	list(i,flaguidl);
-    puts(".\r\n");
+    substdio_puts(&ssout,".\r\n");
   }
   flush();
 }
diff -ur netqmail-1.05/qmail-pop3d.c.orig netqmail-1.05.patched/qmail-pop3d.c.orig
--- netqmail-1.05/qmail-pop3d.c.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-pop3d.c.orig	2008-06-04 19:35:18.000000000 +0200
@@ -66,14 +66,14 @@
 void die_scan() { err("unable to scan $HOME/Maildir"); die(); }
 
 void err_syntax() { err("syntax error"); }
-void err_unimpl() { err("unimplemented"); }
+void err_unimpl(arg) char *arg; { err("unimplemented"); }
 void err_deleted() { err("already deleted"); }
 void err_nozero() { err("messages are counted from 1"); }
 void err_toobig() { err("not that many messages"); }
 void err_nosuch() { err("unable to open that message"); }
 void err_nounlink() { err("unable to unlink all deleted messages"); }
 
-void okay() { puts("+OK \r\n"); flush(); }
+void okay(arg) char *arg; { puts("+OK \r\n"); flush(); }
 
 void printfn(fn) char *fn;
 {
@@ -146,7 +146,7 @@
   }
 }
 
-void pop3_stat()
+void pop3_stat(arg) char *arg;
 {
   int i;
   unsigned long total;
@@ -161,15 +161,15 @@
   flush();
 }
 
-void pop3_rset()
+void pop3_rset(arg) char *arg;
 {
   int i;
   for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
   last = 0;
-  okay();
+  okay(0);
 }
 
-void pop3_last()
+void pop3_last(arg) char *arg;
 {
   puts("+OK ");
   put(strnum,fmt_uint(strnum,last));
@@ -177,7 +177,7 @@
   flush();
 }
 
-void pop3_quit()
+void pop3_quit(arg) char *arg;
 {
   int i;
   for (i = 0;i < numm;++i)
@@ -192,7 +192,7 @@
 	if (!stralloc_0(&line)) die_nomem();
 	rename(m[i].fn,line.s); /* if it fails, bummer */
       }
-  okay();
+  okay(0);
   die();
 }
 
@@ -214,7 +214,7 @@
   if (i == -1) return;
   m[i].flagdeleted = 1;
   if (i + 1 > last) last = i + 1;
-  okay();
+  okay(0);
 }
 
 void list(i,flaguidl)
@@ -238,7 +238,7 @@
     list(i,flaguidl);
   }
   else {
-    okay();
+    okay(0);
     for (i = 0;i < numm;++i)
       if (!m[i].flagdeleted)
 	list(i,flaguidl);
@@ -267,7 +267,7 @@
  
   fd = open_read(m[i].fn);
   if (fd == -1) { err_nosuch(); return; }
-  okay();
+  okay(0);
   substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
   blast(&ssmsg,limit);
   close(fd);
@@ -299,7 +299,7 @@
  
   getlist();
 
-  okay();
+  okay(0);
   commands(&ssin,pop3commands);
   die();
 }
diff -ur netqmail-1.05/qmail-remote.8 netqmail-1.05.patched/qmail-remote.8
--- netqmail-1.05/qmail-remote.8	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-remote.8	2008-06-04 19:35:18.000000000 +0200
@@ -114,6 +114,10 @@
 always exits zero.
 .SH "CONTROL FILES"
 .TP 5
+.I clientcert.pem
+SSL certificate that is used to authenticate with the remote server
+during a TLS session.
+.TP 5
 .I helohost
 Current host name,
 for use solely in saying hello to the remote SMTP server.
@@ -123,6 +127,16 @@
 otherwise
 .B qmail-remote
 refuses to run.
+
+.TP 5
+.I notlshosts/<FQDN>
+.B qmail-remote
+will not try TLS on servers for which this file exists
+.RB ( <FQDN>
+is the fully-qualified domain name of the server). 
+.IR (tlshosts/<FQDN>.pem 
+takes precedence over this file however).
+
 .TP 5
 .I smtproutes
 Artificial SMTP routes.
@@ -156,6 +170,8 @@
 this tells
 .B qmail-remote
 to look up MX records as usual.
+.I port 
+value of 465 (deprecated smtps port) causes TLS session to be started.
 .I smtproutes
 may include wildcards:
 
@@ -195,6 +211,33 @@
 .B qmail-remote
 will wait for each response from the remote SMTP server.
 Default: 1200.
+
+.TP 5
+.I tlsclientciphers
+A set of OpenSSL client cipher strings. Multiple ciphers
+contained in a string should be separated by a colon.
+
+.TP 5
+.I tlshosts/<FQDN>.pem
+.B qmail-remote
+requires TLS authentication from servers for which this certificate exists
+.RB ( <FQDN>
+is the fully-qualified domain name of the server). One of the
+.I dNSName
+or the
+.I CommonName
+attributes have to match.
+
+.B WARNING:
+this option may cause mail to be delayed, bounced, doublebounced, or lost.
+
+.TP 5
+.I tlshosts/exhaustivelist
+if this file exists
+no TLS will be tried on hosts other than those for which a file
+.B tlshosts/<FQDN>.pem
+exists.
+
 .SH "SEE ALSO"
 addresses(5),
 envelopes(5),
Only in netqmail-1.05.patched: qmail-remote.8.orig
diff -ur netqmail-1.05/qmail-remote.c netqmail-1.05.patched/qmail-remote.c
--- netqmail-1.05/qmail-remote.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-remote.c	2008-06-04 19:35:18.000000000 +0200
@@ -46,7 +46,19 @@
 
 saa reciplist = {0};
 
-struct ip_address partner;
+//struct ip_address partner;
+struct ip_mx partner;
+
+#ifdef TLS
+# include <sys/stat.h>
+# include "tls.h"
+# include "ssl_timeoutio.h"
+# include <openssl/x509v3.h>
+# define EHLO 1
+
+int tls_init();
+const char *ssl_err_str = 0;
+#endif 
 
 void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
 void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
@@ -89,7 +101,15 @@
 void outhost()
 {
   char x[IPFMT];
-  if (substdio_put(subfdoutsmall,x,ip_fmt(x,&partner)) == -1) _exit(0);
+#ifdef INET6
+  if (partner.af == AF_INET) {
+#endif
+  if (substdio_put(subfdoutsmall,x,ip_fmt(x,&partner.addr.ip)) == -1) _exit(0);
+#ifdef INET6
+  } else {
+  if (substdio_put(subfdoutsmall,x,ip6_fmt(x,&partner.addr.ip6)) == -1) _exit(0);
+  }
+#endif
 }
 
 int flagcritical = 0;
@@ -99,6 +119,9 @@
   outhost();
   out(" but connection died. ");
   if (flagcritical) out("Possible duplicate! ");
+#ifdef TLS
+  if (ssl_err_str) { out(ssl_err_str); out(" "); }
+#endif
   out("(#4.4.2)\n");
   zerodie();
 }
@@ -110,6 +133,12 @@
 int saferead(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
+#ifdef TLS
+  if (ssl) {
+    r = ssl_timeoutread(timeout, smtpfd, smtpfd, ssl, buf, len);
+    if (r < 0) ssl_err_str = ssl_error_str();
+  } else
+#endif
   r = timeoutread(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
@@ -117,6 +146,12 @@
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
+#ifdef TLS
+  if (ssl) {
+    r = ssl_timeoutwrite(timeout, smtpfd, smtpfd, ssl, buf, len);
+    if (r < 0) ssl_err_str = ssl_error_str();
+  } else
+#endif 
   r = timeoutwrite(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
@@ -163,6 +198,65 @@
   return code;
 }
 
+#ifdef EHLO
+saa ehlokw = {0}; /* list of EHLO keywords and parameters */
+int maxehlokwlen = 0;
+
+unsigned long ehlo()
+{
+  stralloc *sa;
+  char *s, *e, *p;
+  unsigned long code;
+
+  if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len;
+  ehlokw.len = 0;
+
+# ifdef MXPS
+  if (type == 's') return 0;
+# endif
+
+  substdio_puts(&smtpto, "EHLO ");
+  substdio_put(&smtpto, helohost.s, helohost.len);
+  substdio_puts(&smtpto, "\r\n");
+  substdio_flush(&smtpto);
+
+  code = smtpcode();
+  if (code != 250) return code;
+
+  s = smtptext.s;
+  while (*s++ != '\n') ; /* skip the first line: contains the domain */
+
+  e = smtptext.s + smtptext.len - 6; /* 250-?\n */
+  while (s <= e)
+  {
+    int wasspace = 0;
+
+    if (!saa_readyplus(&ehlokw, 1)) temp_nomem();
+    sa = ehlokw.sa + ehlokw.len++;
+    if (ehlokw.len > maxehlokwlen) *sa = sauninit; else sa->len = 0;
+
+     /* smtptext is known to end in a '\n' */
+     for (p = (s += 4); ; ++p)
+       if (*p == '\n' || *p == ' ' || *p == '\t') {
+         if (!wasspace)
+           if (!stralloc_catb(sa, s, p - s) || !stralloc_0(sa)) temp_nomem();
+         if (*p == '\n') break;
+         wasspace = 1;
+       } else if (wasspace == 1) {
+         wasspace = 0;
+         s = p;
+       }
+    s = ++p;
+
+    /* keyword should consist of alpha-num and '-'
+     * broken AUTH might use '=' instead of space */
+    for (p = sa->s; *p; ++p) if (*p == '=') { *p = 0; break; }
+  }
+
+  return 250;
+}
+#endif
+
 void outsmtptext()
 {
   int i; 
@@ -179,6 +273,11 @@
 char *prepend;
 char *append;
 {
+#ifdef TLS
+  /* shouldn't talk to the client unless in an appropriate state */
+  int state = ssl ? ssl->state : SSL_ST_BEFORE;
+  if (state & SSL_ST_OK || (!smtps && state & SSL_ST_BEFORE))
+#endif
   substdio_putsflush(&smtpto,"QUIT\r\n");
   /* waiting for remote side is just too ridiculous */
   out(prepend);
@@ -186,6 +285,30 @@
   out(append);
   out(".\n");
   outsmtptext();
+
+#if defined(TLS) && defined(DEBUG)
+  if (ssl) {
+    X509 *peercert;
+
+    out("STARTTLS proto="); out(SSL_get_version(ssl));
+    out("; cipher="); out(SSL_get_cipher(ssl));
+
+    /* we want certificate details */
+    if (peercert = SSL_get_peer_certificate(ssl)) {
+      char *str;
+
+      str = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
+      out("; subject="); out(str); OPENSSL_free(str);
+
+      str = X509_NAME_oneline(X509_get_issuer_name(peercert), NULL, 0);
+      out("; issuer="); out(str); OPENSSL_free(str);
+
+      X509_free(peercert);
+    }
+    out(";\n");
+  }
+#endif
+
   zerodie();
 }
 
@@ -214,6 +337,194 @@
   substdio_flush(&smtpto);
 }
 
+#ifdef TLS
+char *partner_fqdn = 0;
+
+# define TLS_QUIT quit(ssl ? "; connected to " : "; connecting to ", "")
+void tls_quit(const char *s1, const char *s2)
+{
+  out(s1); if (s2) { out(": "); out(s2); } TLS_QUIT;
+}
+# define tls_quit_error(s) tls_quit(s, ssl_error())
+
+int match_partner(const char *s, int len)
+{
+  if (!case_diffb(partner_fqdn, len, s) && !partner_fqdn[len]) return 1;
+  /* we also match if the name is *.domainname */
+  if (*s == '*') {
+    const char *domain = partner_fqdn + str_chr(partner_fqdn, '.');
+    if (!case_diffb(domain, --len, ++s) && !domain[len]) return 1;
+  }
+  return 0;
+}
+
+/* don't want to fail handshake if certificate can't be verified */
+int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
+
+int tls_init()
+{
+  int i;
+  SSL *myssl;
+  SSL_CTX *ctx;
+  stralloc saciphers = {0};
+  const char *ciphers, *servercert = 0;
+
+  if (partner_fqdn) {
+    struct stat st;
+    stralloc tmp = {0};
+    if (!stralloc_copys(&tmp, "control/tlshosts/")
+      || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn))
+      || !stralloc_catb(&tmp, ".pem", 5)) temp_nomem();
+    if (stat(tmp.s, &st) == 0) 
+      servercert = tmp.s;
+    else {
+      if (!stralloc_copys(&tmp, "control/notlshosts/")
+        || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn)+1))
+        temp_nomem();
+      if ((stat("control/tlshosts/exhaustivelist", &st) == 0) ||
+	  (stat(tmp.s, &st) == 0)) {
+         alloc_free(tmp.s);
+         return 0;
+      }
+      alloc_free(tmp.s);
+    }
+  }
+ 
+  if (!smtps) {
+    stralloc *sa = ehlokw.sa;
+    unsigned int len = ehlokw.len;
+    /* look for STARTTLS among EHLO keywords */
+    for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ;
+    if (!len) {
+      if (!servercert) return 0;
+      out("ZNo TLS achieved while "); out(servercert);
+      out(" exists"); smtptext.len = 0; TLS_QUIT;
+    }
+  }
+
+  SSL_library_init();
+  ctx = SSL_CTX_new(SSLv23_client_method());
+  if (!ctx) {
+    if (!smtps && !servercert) return 0;
+    smtptext.len = 0;
+    tls_quit_error("ZTLS error initializing ctx");
+  }
+
+  if (servercert) {
+    if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) {
+      SSL_CTX_free(ctx);
+      smtptext.len = 0;
+      out("ZTLS unable to load "); tls_quit_error(servercert);
+    }
+    /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
+    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
+  }
+
+  /* let the other side complain if it needs a cert and we don't have one */
+# define CLIENTCERT "control/clientcert.pem"
+  if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT))
+    SSL_CTX_use_RSAPrivateKey_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM);
+# undef CLIENTCERT
+
+  myssl = SSL_new(ctx);
+  SSL_CTX_free(ctx);
+  if (!myssl) {
+    if (!smtps && !servercert) return 0;
+    smtptext.len = 0;
+    tls_quit_error("ZTLS error initializing ssl");
+  }
+
+  if (!smtps) substdio_putsflush(&smtpto, "STARTTLS\r\n");
+
+  /* while the server is preparing a responce, do something else */
+  if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1)
+    { SSL_free(myssl); temp_control(); }
+  if (saciphers.len) {
+    for (i = 0; i < saciphers.len - 1; ++i)
+      if (!saciphers.s[i]) saciphers.s[i] = ':';
+    ciphers = saciphers.s;
+  }
+  else ciphers = "DEFAULT";
+  SSL_set_cipher_list(myssl, ciphers);
+  alloc_free(saciphers.s);
+
+  /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */
+  SSL_set_fd(myssl, smtpfd);
+
+  /* read the responce to STARTTLS */
+  if (!smtps) {
+    if (smtpcode() != 220) {
+      SSL_free(myssl);
+      if (!servercert) return 0;
+      out("ZSTARTTLS rejected while ");
+      out(servercert); out(" exists"); TLS_QUIT;
+    }
+    smtptext.len = 0;
+  }
+
+  ssl = myssl;
+  if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0)
+    tls_quit("ZTLS connect failed", ssl_error_str());
+
+  if (servercert) {
+    X509 *peercert;
+    STACK_OF(GENERAL_NAME) *gens;
+
+    int r = SSL_get_verify_result(ssl);
+    if (r != X509_V_OK) {
+      out("ZTLS unable to verify server with ");
+      tls_quit(servercert, X509_verify_cert_error_string(r));
+    }
+    alloc_free(servercert);
+
+    peercert = SSL_get_peer_certificate(ssl);
+    if (!peercert) {
+      out("ZTLS unable to verify server ");
+      tls_quit(partner_fqdn, "no certificate provided");
+    }
+
+    /* RFC 2595 section 2.4: find a matching name
+     * first find a match among alternative names */
+    gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0);
+    if (gens) {
+      for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i)
+      {
+        const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
+        if (gn->type == GEN_DNS)
+          if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
+      }
+      sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    }
+
+    /* no alternative name matched, look up commonName */
+    if (!gens || i >= r) {
+      stralloc peer = {0};
+      X509_NAME *subj = X509_get_subject_name(peercert);
+      i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
+      if (i >= 0) {
+        const ASN1_STRING *s = X509_NAME_get_entry(subj, i)->value;
+        if (s) { peer.len = s->length; peer.s = s->data; }
+      }
+      if (peer.len <= 0) {
+        out("ZTLS unable to verify server ");
+        tls_quit(partner_fqdn, "certificate contains no valid commonName");
+      }
+      if (!match_partner(peer.s, peer.len)) {
+        out("ZTLS unable to verify server "); out(partner_fqdn);
+        out(": received certificate for "); outsafe(&peer); TLS_QUIT;
+      }
+    }
+
+    X509_free(peercert);
+  }
+
+  if (smtps) if (smtpcode() != 220)
+    quit("ZTLS Connected to "," but greeting failed");
+
+  return 1;
+}
+#endif
+
 stralloc recip = {0};
 
 void smtp()
@@ -222,14 +533,53 @@
   int flagbother;
   int i;
  
+#ifndef PORT_SMTP
+  /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */
+# define port smtp_port
+#endif
+
+#ifdef TLS
+# ifdef MXPS
+  if (type == 'S') smtps = 1;
+  else if (type != 's')
+# endif
+    if (port == 465) smtps = 1;
+  if (!smtps)
+#endif
+ 
   if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
  
+#ifdef EHLO
+# ifdef TLS
+  if (!smtps)
+# endif
+  code = ehlo();
+
+# ifdef TLS
+  if (tls_init())
+    /* RFC2487 says we should issue EHLO (even if we might not need
+     * extensions); at the same time, it does not prohibit a server
+     * to reject the EHLO and make us fallback to HELO */
+    code = ehlo();
+# endif
+
+  if (code == 250) {
+    /* add EHLO response checks here */
+
+    /* and if EHLO failed, use HELO */
+  } else {
+#endif
+ 
   substdio_puts(&smtpto,"HELO ");
   substdio_put(&smtpto,helohost.s,helohost.len);
   substdio_puts(&smtpto,"\r\n");
   substdio_flush(&smtpto);
   if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
  
+#ifdef EHLO
+  }
+#endif
+ 
   substdio_puts(&smtpto,"MAIL FROM:<");
   substdio_put(&smtpto,sender.s,sender.len);
   substdio_puts(&smtpto,">\r\n");
@@ -326,6 +676,33 @@
   }
 }
 
+#ifdef INET6
+int ipme_is46(mxip)
+struct ip_mx *mxip;
+{
+  switch(mxip->af) {
+  case AF_INET:
+    return ipme_is(&mxip->addr.ip);
+  case AF_INET6:
+    return ipme_is6(&mxip->addr.ip6);
+  }
+  return 0;
+}
+#endif
+
+int timeoutconn46(fd, ix, port, timeout)
+int fd;
+struct ip_mx *ix;
+int port;
+int timeout;
+{
+#ifdef INET6
+	if (ix->af == AF_INET6)
+		return timeoutconn6(fd, &ix->addr.ip6, port, timeout);
+#endif
+	return timeoutconn(fd, &ix->addr.ip, port, timeout);
+}
+
 void main(argc,argv)
 int argc;
 char **argv;
@@ -394,7 +771,11 @@
  
   prefme = 100000;
   for (i = 0;i < ip.len;++i)
-    if (ipme_is(&ip.ix[i].ip))
+#ifdef INET6
+   if (ipme_is46(&ip.ix[i]))
+#else
+   if (ipme_is(&ip.ix[i].addr.ip))
+#endif
       if (ip.ix[i].pref < prefme)
         prefme = ip.ix[i].pref;
  
@@ -409,17 +790,22 @@
     perm_ambigmx();
  
   for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) {
-    if (tcpto(&ip.ix[i].ip)) continue;
- 
-    smtpfd = socket(AF_INET,SOCK_STREAM,0);
+    if (tcpto(&ip.ix[i])) continue;
+
+    smtpfd = socket(ip.ix[i].af,SOCK_STREAM,0);
     if (smtpfd == -1) temp_oserr();
  
-    if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
-      tcpto_err(&ip.ix[i].ip,0);
-      partner = ip.ix[i].ip;
-      smtp(); /* does not return */
+    if (timeoutconn46(smtpfd,&ip.ix[i],(unsigned int) port,timeoutconnect) == 0)
+	{
+      tcpto_err(&ip.ix[i],0);
+      partner = ip.ix[i];
+#ifdef TLS
+      partner_fqdn = ip.ix[i].fqdn;
+#endif
+     smtp(); /* does not return */
     }
-    tcpto_err(&ip.ix[i].ip,errno == error_timeout);
+
+    tcpto_err(&ip.ix[i],errno == error_timeout);
     close(smtpfd);
   }
   
Only in netqmail-1.05.patched: qmail-remote.c.orig
diff -ur netqmail-1.05/qmail-send.c netqmail-1.05.patched/qmail-send.c
--- netqmail-1.05/qmail-send.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-send.c	2008-06-04 19:35:18.000000000 +0200
@@ -262,6 +262,8 @@
  while (!stralloc_copys(&comm_buf[c],"")) nomem();
  ch = delnum;
  while (!stralloc_append(&comm_buf[c],&ch)) nomem();
+ ch = delnum >> 8;
+ while (!stralloc_append(&comm_buf[c],&ch)) nomem();
  fnmake_split(id);
  while (!stralloc_cats(&comm_buf[c],fn.s)) nomem();
  while (!stralloc_0(&comm_buf[c])) nomem();
@@ -906,41 +908,42 @@
      dline[c].len = REPORTMAX;
      /* qmail-lspawn and qmail-rspawn are responsible for keeping it short */
      /* but from a security point of view, we don't trust rspawn */
-   if (!ch && (dline[c].len > 1))
+   if (!ch && (dline[c].len > 2))
     {
      delnum = (unsigned int) (unsigned char) dline[c].s[0];
+     delnum += (unsigned int) ((unsigned int) dline[c].s[1]) << 8;
      if ((delnum < 0) || (delnum >= concurrency[c]) || !d[c][delnum].used)
        log1("warning: internal error: delivery report out of range\n");
      else
       {
        strnum3[fmt_ulong(strnum3,d[c][delnum].delid)] = 0;
-       if (dline[c].s[1] == 'Z')
+       if (dline[c].s[2] == 'Z')
 	 if (jo[d[c][delnum].j].flagdying)
 	  {
-	   dline[c].s[1] = 'D';
+	   dline[c].s[2] = 'D';
 	   --dline[c].len;
 	   while (!stralloc_cats(&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
 	   while (!stralloc_0(&dline[c])) nomem();
 	  }
-       switch(dline[c].s[1])
+       switch(dline[c].s[2])
 	{
 	 case 'K':
 	   log3("delivery ",strnum3,": success: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
 	   markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
 	   --jo[d[c][delnum].j].numtodo;
 	   break;
 	 case 'Z':
 	   log3("delivery ",strnum3,": deferral: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
 	   break;
 	 case 'D':
 	   log3("delivery ",strnum3,": failure: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
-	   addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 2);
+	   addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 3);
 	   markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
 	   --jo[d[c][delnum].j].numtodo;
 	   break;
@@ -1544,7 +1547,7 @@
  numjobs = 0;
  for (c = 0;c < CHANNELS;++c)
   {
-   char ch;
+   char ch, ch1;
    int u;
    int r;
    do
@@ -1552,7 +1555,13 @@
    while ((r == -1) && (errno == error_intr));
    if (r < 1)
     { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); }
+   do
+     r = read(chanfdin[c],&ch1,1);
+   while ((r == -1) && (errno == error_intr));
+   if (r < 1)
+    { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); }
    u = (unsigned int) (unsigned char) ch;
+   u += (unsigned int) ((unsigned char) ch1) << 8;
    if (concurrency[c] > u) concurrency[c] = u;
    numjobs += concurrency[c];
   }
Only in netqmail-1.05.patched: qmail-send.c.orig
diff -ur netqmail-1.05/qmail-showctl.c netqmail-1.05.patched/qmail-showctl.c
--- netqmail-1.05/qmail-showctl.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-showctl.c	2008-06-04 19:35:18.000000000 +0200
@@ -9,12 +9,15 @@
 #include "constmap.h"
 #include "stralloc.h"
 #include "direntry.h"
+#include "spam.h"
+#include "uint32.h"
 #include "auto_uids.h"
 #include "auto_qmail.h"
 #include "auto_break.h"
 #include "auto_patrn.h"
 #include "auto_spawn.h"
 #include "auto_split.h"
+#include "spf.h"
 
 stralloc me = {0};
 int meok;
@@ -136,6 +139,130 @@
   }
 }
 
+void do_spam()
+{
+  struct stat st;
+  struct stat stcdb;
+  uint32 dlen;
+  stralloc data = {0};
+  int i;
+  int r;
+  int fd;
+  struct spam_t spamt = spam_t_init(0,0);
+  unsigned int uip;
+
+  substdio_puts(subfdout,"\nspamt/spamt.cdb: ");
+  if (stat("spamt",&st) == -1)
+    if (stat("spamt.cdb",&stcdb) == -1)
+      substdio_puts(subfdout,"(Default.) No effect.\n");
+    else
+      substdio_puts(subfdout,"Oops! spamt.cdb exists but spamt doesn't (Spam throttling active).\n");
+  else
+    if (stat("spamt.cdb",&stcdb) == -1)
+      substdio_puts(subfdout,"Oops! spamt exists but spamt.cdb doesn't (No effect).\n");
+    else
+      if (st.st_mtime > stcdb.st_mtime)
+        substdio_puts(subfdout,"Oops! spamt.cdb is older than spamt.\n");
+      else
+        substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n");
+
+  fd = open_read("spamt.cdb");
+  if (fd == -1) return;
+
+  substdio_puts(subfdout,"\nspamt.cdb (defaults): ");
+
+  r = cdb_seek(fd,"",0,&dlen);
+  if (r != 1)
+  {
+    substdio_puts(subfdout,"No default entry (Spam throttling inactive).\n");
+    return;
+  }
+
+  if (!stralloc_ready(&data,(unsigned int) dlen))
+  {
+    substdio_puts(subfdout,"Unknown (temporary error).\n");
+    return;
+  }
+  data.len = dlen;
+  if (cdb_bread(fd,data.s,data.len) == -1)
+  {
+    substdio_puts(subfdout,"Unknown (unknown error...try running qmail-newst).\n");
+    return;
+  }
+
+  /* get the ipbits block from this key */
+  byte_copy(&uip,4,data.s);
+  /* then populate the spam_t (defaults) */
+  if (spam_get(&spamt,data.s + 4,data.len - 4) == -1)
+  {
+    substdio_puts(subfdout,"Unknown (unknown error...try running qmail-newst).\n");
+    return;
+  }
+
+  substdio_puts(subfdout,"\n\tthrottle constant: ");
+  if (spamt.throttle) {
+    substdio_put(subfdout,num,fmt_uint(num,spamt.throttle));
+    substdio_puts(subfdout,"ms");
+  } else
+    substdio_puts(subfdout,"none (spam throttling not active)");
+
+  substdio_puts(subfdout,"\n\tthrottle max: ");
+  if (spamt.max) {
+    substdio_put(subfdout,num,fmt_uint(num,spamt.max));
+    substdio_puts(subfdout,"ms");
+  } else
+    substdio_puts(subfdout,"no maximum");
+
+  substdio_puts(subfdout,"\n\treasonable recipient count: ");
+  if (spamt.reasonablercpt)
+    substdio_put(subfdout,num,fmt_uint(num,spamt.reasonablercpt));
+  else
+    substdio_puts(subfdout,"unlimited");
+
+  substdio_puts(subfdout,"\n\tpre-DATA flush? ");
+  substdio_puts(subfdout,spamt.flush ? "yes" : "no");
+
+  substdio_puts(subfdout,"\n\tteergrubing periodicity: ");
+  if (spamt.tg) {
+    substdio_put(subfdout,num,fmt_uint(num,spamt.tg));
+    substdio_puts(subfdout,"s");
+  } else
+    substdio_puts(subfdout, "not active");
+
+  if (spamt.tg) {
+    substdio_puts(subfdout,"\n\tteergrube response: ");
+    if (spamt.tg_resp.s)
+      substdio_puts(subfdout,spamt.tg_resp.s);
+    else
+      substdio_puts(subfdout,"(Default.) please wait.");
+  }
+
+  substdio_puts(subfdout,"\n\tspam throttle (state) directory: ");
+  if (spamt.dir.s && spamt.dir.s[0] )
+    if (spamt.dir.s[0] == '/') {
+      substdio_puts(subfdout,"construct ");
+      substdio_puts(subfdout,spamt.dir.s+1);
+      substdio_puts(subfdout,"-bit directory from remote IP");
+    } else
+      substdio_puts(subfdout,spamt.dir.s);
+  else
+    substdio_puts(subfdout,"construct 32-bit directory from remote IP");
+
+  substdio_puts(subfdout,"\n\tother active network blocks (bits): ");
+  r = 0;
+  for (i = 32;i >= 1;--i)
+  {
+    if (!(uip & (1 << (i - 1)))) continue;
+    if (r++)
+      substdio_puts(subfdout,", ");
+    substdio_put(subfdout,num,fmt_uint(num,i));
+  }
+  if (!r)
+    substdio_puts(subfdout,"none");
+
+  substdio_puts(subfdout,"\n");
+}
+
 void main()
 {
   DIR *dir;
@@ -214,7 +341,11 @@
     _exit(111);
   }
 
-  do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM.");
+  do_lst("badhelo","Any HELO host name is allowed.",""," HELO host name denied if it matches this pattern.");
+  do_lst("badmailfrom","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern.");
+  do_lst("badmailfromnorelay","Any MAIL FROM is allowed.",""," MAIL FROM denied if it matches this pattern and RELAYCLIENT is not set.");
+  do_lst("badmailto","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern.");
+  do_lst("badmailtonorelay","No RCPT TO are specifically denied.",""," RCPT TO denied if it matches this pattern and RELAYCLIENT is not set.");
   do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is ");
   do_str("bouncehost",1,"bouncehost","Bounce host name is ");
   do_int("concurrencylocal","10","Local concurrency is ","");
@@ -257,6 +388,11 @@
 
   do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 ");
   do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ","");
+  do_int("spfbehavior","0","The SPF behavior is ","");
+  do_str("spfexp",0,SPF_DEFEXP,"The SPF default explanation is: 550 ");
+  do_str("spfguess",0,"","The guess SPF rules are: ");
+  do_str("spfrules",0,"","The local SPF rules are: ");
+  do_spam();
   do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds");
   do_int("timeoutremote","1200","SMTP client data timeout is "," seconds");
   do_int("timeoutsmtpd","1200","SMTP server data timeout is "," seconds");
@@ -267,7 +403,11 @@
     if (str_equal(d->d_name,"..")) continue;
     if (str_equal(d->d_name,"bouncefrom")) continue;
     if (str_equal(d->d_name,"bouncehost")) continue;
+    if (str_equal(d->d_name,"badhelo")) continue;
     if (str_equal(d->d_name,"badmailfrom")) continue;
+    if (str_equal(d->d_name,"badmailfromnorelay")) continue;
+    if (str_equal(d->d_name,"badmailto")) continue;
+    if (str_equal(d->d_name,"badmailtonorelay")) continue;
     if (str_equal(d->d_name,"bouncefrom")) continue;
     if (str_equal(d->d_name,"bouncehost")) continue;
     if (str_equal(d->d_name,"concurrencylocal")) continue;
@@ -292,6 +432,12 @@
     if (str_equal(d->d_name,"rcpthosts")) continue;
     if (str_equal(d->d_name,"smtpgreeting")) continue;
     if (str_equal(d->d_name,"smtproutes")) continue;
+    if (str_equal(d->d_name,"spfbehavior")) continue;
+    if (str_equal(d->d_name,"spfexp")) continue;
+    if (str_equal(d->d_name,"spfguess")) continue;
+    if (str_equal(d->d_name,"spfrules")) continue;
+    if (str_equal(d->d_name,"spamt")) continue;
+    if (str_equal(d->d_name,"spamt.cdb")) continue;
     if (str_equal(d->d_name,"timeoutconnect")) continue;
     if (str_equal(d->d_name,"timeoutremote")) continue;
     if (str_equal(d->d_name,"timeoutsmtpd")) continue;
Only in netqmail-1.05.patched: qmail-showctl.c.orig
diff -ur netqmail-1.05/qmail-smtpd.8 netqmail-1.05.patched/qmail-smtpd.8
--- netqmail-1.05/qmail-smtpd.8	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-smtpd.8	2008-06-04 19:35:18.000000000 +0200
@@ -14,6 +14,15 @@
 see
 .BR tcp-environ(5) .
 
+If the environment variable
+.B SMTPS
+is non-empty,
+.B qmail-smtpd
+starts a TLS session (to support the deprecated SMTPS protocol,
+normally on port 465). Otherwise,
+.B qmail-smtpd
+offers the STARTTLS extension to ESMTP.
+
 .B qmail-smtpd
 is responsible for counting hops.
 It rejects any message with 100 or more 
@@ -23,7 +32,30 @@
 header fields.
 
 .B qmail-smtpd
-supports ESMTP, including the 8BITMIME and PIPELINING options.
+supports ESMTP, including the 8BITMIME, DATA, PIPELINING, SIZE, and AUTH options.
+.B qmail-smtpd
+includes a \'MAIL FROM:\' parameter parser and obeys \'Auth\' and \'Size\' advertisements.
+.B qmail-smtpd
+can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types. It invokes
+.IR checkprogram ,
+which reads on file descriptor 3 the username, a 0 byte, the password
+or CRAM-MD5 digest/response derived from the SMTP client,
+another 0 byte, a CRAM-MD5 challenge (if applicable to the AUTH type),
+and a final 0 byte.
+.I checkprogram
+invokes
+.I subprogram
+upon successful authentication, which should in turn return 0 to
+.BR qmail-smtpd ,
+effectively setting the environment variables $RELAYCLIENT and $TCPREMOTEINFO
+(any supplied value replaced with the authenticated username).
+.B qmail-smtpd
+will reject the authentication attempt if it receives a nonzero return
+value from
+.I checkprogram
+or
+.IR subprogram .
+
 .SH TRANSPARENCY
 .B qmail-smtpd
 converts the SMTP newline convention into the UNIX newline convention
@@ -37,11 +69,26 @@
 even though such messages violate the SMTP protocol.
 .SH "CONTROL FILES"
 .TP 5
+.I badhelo
+Unacceptable HELO/EHLO host names.
+.B qmail-smtpd
+will reject every recipient address for a message if
+the host name is listed in, 
+or matches a POSIX regular expression pattern listed in,
+.IR badhelo .
+If the 
+.B NOBADHELO 
+environment variable is set, then the contents of 
+.IR badhelo 
+will be ignored.
+For more information, please have a look at doc/README.qregex.
+.TP 5
 .I badmailfrom
 Unacceptable envelope sender addresses.
 .B qmail-smtpd
 will reject every recipient address for a message
-if the envelope sender address is listed in
+if the envelope sender address is listed in, or matches a POSIX regular expression
+pattern listed in,
 .IR badmailfrom .
 A line in
 .I badmailfrom
@@ -49,6 +96,45 @@
 .BR @\fIhost ,
 meaning every address at
 .IR host .
+For more information, please have a look at doc/README.qregex.
+.TP 5
+.I badmailfromnorelay
+Functions the same as the
+.IR badmailfrom
+control file but is read only if the 
+.B RELAYCLIENT 
+environment variable is not set.
+For more information, please have a look at doc/README.qregex.
+.TP 5
+.I badmailto
+Unacceptable envelope recipient addresses.
+.B qmail-smtpd
+will reject every recipient address for a message if the recipient address
+is listed in,
+or matches a POSIX regular expression pattern listed in,
+.IR badmailto .
+For more information, please have a look at doc/README.qregex.
+.TP 5
+.I badmailtonorelay
+Functions the same as the
+.IR badmailto
+control file but is read only if the
+.B RELAYCLIENT
+environment variable is not set.
+For more information, please have a look at doc/README.qregex.
+
+.TP 5
+.I clientca.pem
+A list of Certifying Authority (CA) certificates that are used to verify
+the client-presented certificates during a TLS-encrypted session.
+
+.TP 5
+.I clientcrl.pem
+A list of Certificate Revocation Lists (CRLs). If present it
+should contain the CRLs of the CAs in 
+.I clientca.pem 
+and client certs will be checked for revocation.
+
 .TP 5
 .I databytes
 Maximum number of bytes allowed in a message,
@@ -76,6 +162,18 @@
 .B DATABYTES
 is set, it overrides
 .IR databytes .
+
+.TP 5
+.I dh1024.pem
+If these 1024 bit DH parameters are provided,
+.B qmail-smtpd
+will use them for TLS sessions instead of generating one on-the-fly 
+(which is very timeconsuming).
+.TP 5
+.I dh512.pem
+512 bit counterpart for 
+.B dh1024.pem. 
+
 .TP 5
 .I localiphost
 Replacement host name for local IP addresses.
@@ -151,6 +249,19 @@
 
 Envelope recipient addresses without @ signs are
 always allowed through.
+
+.TP 5
+.I rsa512.pem
+If this 512 bit RSA key is provided,
+.B qmail-smtpd
+will use it for TLS sessions instead of generating one on-the-fly.
+
+.TP 5
+.I servercert.pem
+SSL certificate to be presented to clients in TLS-encrypted sessions. 
+Should contain both the certificate and the private key. Certifying Authority
+(CA) and intermediate certificates can be added at the end of the file.
+
 .TP 5
 .I smtpgreeting
 SMTP greeting message.
@@ -169,11 +280,76 @@
 .B qmail-smtpd
 will wait for each new buffer of data from the remote SMTP client.
 Default: 1200.
+.TP 5
+.I spfbehavior
+Set to a value between 1 and 6 to enable SPF checks; 0 to disable.
+1 selects 'annotate-only' mode, where
+.B qmail-smtpd
+will annotate incoming email with
+.B Received-SPF
+fields, but will not reject any messages.  2 will produce temporary
+failures on DNS lookup problems so you can make sure you always have
+meaningful Received-SPF headers.  3 selects 'reject' mode,
+where incoming mail will be rejected if the SPF record says 'fail'.  4
+selects a more stricter rejection mode, which is like 'reject' mode,
+except that incoming mail will also be rejected when the SPF record
+says 'softfail'.  5 will also reject when the SPF record says 'neutral',
+and 6 if no SPF records are available at all (or a syntax error was
+encountered). The contents of this file are overridden by the value of
+the
+.B SPFBEHAVIOR
+environment variable, if set.
+Default: 0.
+.TP 5
+.I spfexp
+You can add a line with a an SPF explanation that will be shown to the
+sender in case of a reject. It will override the default one. You can
+use SPF macro expansion.
+.TP 5
+.I spfguess
+You can add a line with SPF rules that will be checked if a sender
+domain doesn't have a SPF record. The local rules will also be used
+in this case.
+.TP 5
+.I spfrules
+You can add a line with SPF rules that will be checked before other SPF
+rules would fail.  This can be used to always allow certain machines to
+send certain mails.
+.TP 5
+.I spamt
+The spam throttle parameters file.  See
+.BR qmail-newst (8)
+and
+.BR qmail-spamt (5)
+for details.
+
+
+
+.TP 5
+.I tlsclients
+A list of email addresses. When relay rules would reject an incoming message,
+.B qmail-smtpd
+can allow it if the client presents a certificate that can be verified against
+the CA list in
+.I clientca.pem
+and the certificate email address is in
+.IR tlsclients .
+
+.TP 5
+.I tlsserverciphers
+A set of OpenSSL cipher strings. Multiple ciphers contained in a
+string should be separated by a colon. If the environment variable
+.B TLSCIPHERS
+is set to such a string, it takes precedence.
+
 .SH "SEE ALSO"
 tcp-env(1),
 tcp-environ(5),
 qmail-control(5),
+qmail-spamt(5),
+qmail-spamthrottle(5)
 qmail-inject(8),
 qmail-newmrh(8),
+qmail-newst(8),
 qmail-queue(8),
 qmail-remote(8)
Only in netqmail-1.05.patched: qmail-smtpd.8.orig
diff -ur netqmail-1.05/qmail-smtpd.c netqmail-1.05.patched/qmail-smtpd.c
--- netqmail-1.05/qmail-smtpd.c	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/qmail-smtpd.c	2008-06-04 19:35:18.000000000 +0200
@@ -1,3 +1,14 @@
+
+/*
+ *
+ * includes chkuser v.2.0.8
+ * for qmail/netqmail > 1.0.3 and vpopmail > 5.3.x
+ *
+ * Author: Antonio Nati tonix@interazioni.it
+ * www.interazioni.it/opensource
+ *
+ */
+
 #include "sig.h"
 #include "readwrite.h"
 #include "stralloc.h"
@@ -23,14 +34,48 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "spam.h"
+#include "wait.h"
+#include "spf.h"
+
+#define CRAM_MD5
+#define AUTHSLEEP 5
+
+#include "qregex.h"
+#include "strerr.h"
+
+#define BMCHECK_BMF 0
+#define BMCHECK_BMFNR 1
+#define BMCHECK_BMT 2
+#define BMCHECK_BMTNR 3
+#define BMCHECK_BHELO 4
 
 #define MAXHOPS 100
 unsigned int databytes = 0;
 int timeout = 1200;
+unsigned int spfbehavior = 0;
+
+#ifdef TLS
+#include <sys/stat.h>
+#include "tls.h"
+#include "ssl_timeoutio.h"
+
+void tls_init();
+int tls_verify();
+void tls_nogateway();
+int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
+#endif
+
+#include "chkuser.h"
 
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
+#ifdef TLS
+  if (ssl && fd == ssl_wfd)
+    r = ssl_timeoutwrite(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
   r = timeoutwrite(timeout,fd,buf,len);
   if (r <= 0) _exit(1);
   return r;
@@ -49,8 +94,20 @@
 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_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
+void err_bmf() { out("553 sorry, your envelope sender has been denied (#5.7.1)\r\n"); }
+void err_bmt() { out("553 sorry, your envelope recipient has been denied (#5.7.1)\r\n"); }
+void err_bhelo() { out("553 sorry, your HELO host name has been denied (#5.7.1)\r\n"); }
+#ifndef TLS
 void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
+#else
+void err_nogateway()
+{
+  out("553 sorry, that domain isn't in my list of allowed rcpthosts");
+  tls_nogateway();
+  out(" (#5.7.1)\r\n");
+}
+#endif
 void err_unimpl(arg) char *arg; { 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"); }
@@ -59,8 +116,39 @@
 void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); }
 void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
 
+int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
+void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
+int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
+int err_authabrt() { out("501 auth exchange canceled (#5.0.0)\r\n"); return -1; }
+int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
+void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
+
+int saferead(fd,buf,len) int fd; char *buf; int len;
+{
+  int r;
+  flush();
+#ifdef TLS
+  if (ssl && fd == ssl_rfd)
+    r = ssl_timeoutread(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
+  r = timeoutread(timeout,fd,buf,len);
+  if (r == -1) if (errno == error_timeout) die_alarm();
+  if (r <= 0) die_read();
+  return r;
+}
+
+char ssinbuf[1024];
+substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
 
 stralloc greeting = {0};
+stralloc spflocal = {0};
+stralloc spfguess = {0};
+stralloc spfexp = {0};
 
 void smtp_greet(code) char *code;
 {
@@ -76,6 +164,7 @@
   smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
 }
 
+char *protocol;
 char *remoteip;
 char *remotehost;
 char *remoteinfo;
@@ -85,7 +174,9 @@
 stralloc helohost = {0};
 char *fakehelo; /* pointer into helohost, or 0 */
 
-void dohelo(arg) char *arg; {
+void dohelo(arg)
+char *arg;
+{
   if (!stralloc_copys(&helohost,arg)) die_nomem(); 
   if (!stralloc_0(&helohost)) die_nomem(); 
   fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0;
@@ -95,7 +186,20 @@
 stralloc liphost = {0};
 int bmfok = 0;
 stralloc bmf = {0};
-struct constmap mapbmf;
+
+int bmfnrok = 0;
+stralloc bmfnr = {0};
+
+int bmtok = 0;
+stralloc bmt = {0};
+
+int bmtnrok = 0;
+stralloc bmtnr = {0};
+
+int bhelook = 0;
+stralloc bhelo = {0};
+
+struct spam_t spamt = spam_t_init(&ssin,&ssout);
 
 void setup()
 {
@@ -109,19 +213,43 @@
   if (liphostok == -1) die_control();
   if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
   if (timeout <= 0) timeout = 1;
-
   if (rcpthosts_init() == -1) die_control();
 
   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();
- 
+
+  bmfnrok = control_readfile(&bmfnr,"control/badmailfromnorelay",0);
+  if (bmfnrok == -1) die_control();
+
+  bmtok = control_readfile(&bmt,"control/badmailto",0);
+  if (bmtok == -1) die_control();
+
+  bmtnrok = control_readfile(&bmtnr,"control/badmailtonorelay",0);
+  if (bmtnrok == -1) die_control();
+
+  bhelook = control_readfile(&bhelo, "control/badhelo",0);
+  if (bhelook == -1) die_control();
+  if (env_get("NOBADHELO")) bhelook = 0;
+
   if (control_readint(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
   if (x) { scan_ulong(x,&u); databytes = u; }
   if (!(databytes + 1)) --databytes;
  
+  if (control_readint(&spfbehavior,"control/spfbehavior") == -1)
+    die_control();
+  x = env_get("SPFBEHAVIOR");
+  if (x) { scan_ulong(x,&u); spfbehavior = u; }
+
+  if (control_readline(&spflocal,"control/spfrules") == -1) die_control();
+  if (spflocal.len && !stralloc_0(&spflocal)) die_nomem();
+  if (control_readline(&spfguess,"control/spfguess") == -1) die_control();
+  if (spfguess.len && !stralloc_0(&spfguess)) die_nomem();
+  if (control_rldef(&spfexp,"control/spfexp",0,SPF_DEFEXP) == -1)
+    die_control();
+  if (!stralloc_0(&spfexp)) die_nomem();
+
+  protocol = "SMTP";
   remoteip = env_get("TCPREMOTEIP");
   if (!remoteip) remoteip = "unknown";
   local = env_get("TCPLOCALHOST");
@@ -131,6 +259,14 @@
   if (!remotehost) remotehost = "unknown";
   remoteinfo = env_get("TCPREMOTEINFO");
   relayclient = env_get("RELAYCLIENT");
+
+#ifdef TLS
+  if (env_get("SMTPS")) { smtps = 1; tls_init(); }
+  else
+#endif
+
+  spam_control(&spamt);
+
   dohelo(remotehost);
 }
 
@@ -197,14 +333,48 @@
   return 1;
 }
 
-int bmfcheck()
+int bmcheck(which) int which;
 {
-  int j;
-  if (!bmfok) return 0;
-  if (constmap(&mapbmf,addr.s,addr.len - 1)) 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;
+  int i = 0;
+  int j = 0;
+  int x = 0;
+  int negate = 0;
+  static stralloc bmb = {0};
+  static stralloc curregex = {0};
+
+  if (which == BMCHECK_BMF) {
+    if (!stralloc_copy(&bmb,&bmf)) die_nomem();
+  } else if (which == BMCHECK_BMFNR) {
+    if (!stralloc_copy(&bmb,&bmfnr)) die_nomem();
+  } else if (which == BMCHECK_BMT) {
+    if (!stralloc_copy(&bmb,&bmt)) die_nomem();
+  } else if (which == BMCHECK_BMTNR) {
+    if (!stralloc_copy(&bmb,&bmtnr)) die_nomem();
+  } else if (which == BMCHECK_BHELO) {
+    if (!stralloc_copy(&bmb,&bhelo)) die_nomem();
+  } else {
+    die_control();
+  }
+
+  while (j < bmb.len) {
+    i = j;
+    while ((bmb.s[i] != '\0') && (i < bmb.len)) i++;
+    if (bmb.s[j] == '!') {
+      negate = 1;
+      j++;
+    }
+    if (!stralloc_copyb(&curregex,bmb.s + j,(i - j))) die_nomem();
+    if (!stralloc_0(&curregex)) die_nomem();
+    if (which == BMCHECK_BHELO) {
+      x = matchregex(helohost.s, curregex.s);
+    } else {
+      x = matchregex(addr.s, curregex.s);
+    }
+    if ((negate) && (x == 0)) return 1;
+    if (!(negate) && (x > 0)) return 1;
+    j = i + 1;
+    negate = 0;
+  }
   return 0;
 }
 
@@ -213,24 +383,115 @@
   int r;
   r = rcpthosts(addr.s,str_len(addr.s));
   if (r == -1) die_control();
+#ifdef TLS
+  if (r == 0) if (tls_verify()) r = -2;
+#endif
   return r;
 }
 
-
 int seenmail = 0;
-int flagbarf; /* defined if seenmail */
+int rcptcount;
+int flagbarfbmf; /* defined if seenmail */
+int flagbarfspf;
+stralloc spfbarfmsg = {0};
+int flagbarfbmt;
+int flagbarfbhelo;
+int flagsize;
 stralloc mailfrom = {0};
 stralloc rcptto = {0};
+stralloc fuser = {0};
+stralloc mfparms = {0};
+
+int mailfrom_size(arg) char *arg;
+{
+  long r;
+  unsigned long sizebytes = 0;
+
+  scan_ulong(arg,&r);
+  sizebytes = r;
+  if (databytes) if (sizebytes > databytes) return 1;
+  return 0;
+}
+
+void mailfrom_auth(arg,len) 
+char *arg; 
+int len;
+{
+  int j;
+
+  if (!stralloc_copys(&fuser,"")) die_nomem();
+  if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); }
+  else 
+    while (len) {
+      if (*arg == '+') {
+        if (case_starts(arg,"+3D")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"=")) die_nomem(); }
+        if (case_starts(arg,"+2B")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"+")) die_nomem(); }
+      }
+      else
+        if (!stralloc_catb(&fuser,arg,1)) die_nomem();
+      arg++; len--;
+    }
+  if(!stralloc_0(&fuser)) die_nomem();
+  if (!remoteinfo) {
+    remoteinfo = fuser.s;
+    if (!env_unset("TCPREMOTEINFO")) die_read();
+    if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+  }
+}
+
+void mailfrom_parms(arg) char *arg;
+{
+  int i;
+  int len;
+
+    len = str_len(arg);
+    if (!stralloc_copys(&mfparms,"")) die_nomem;
+    i = byte_chr(arg,len,'>');
+    if (i > 4 && i < len) {
+      while (len) {
+        arg++; len--; 
+        if (*arg == ' ' || *arg == '\0' ) {
+           if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
+           if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);  
+           if (!stralloc_copys(&mfparms,"")) die_nomem;
+        }
+        else
+          if (!stralloc_catb(&mfparms,arg,1)) die_nomem; 
+      }
+    }
+}
 
 void smtp_helo(arg) char *arg;
 {
   smtp_greet("250 "); out("\r\n");
   seenmail = 0; dohelo(arg);
+  if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
 }
+/* ESMTP extensions are published here */
 void smtp_ehlo(arg) char *arg;
 {
-  smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  char size[FMT_ULONG];
+#ifdef TLS
+  struct stat st;
+#endif
+  smtp_greet("250-"); 
+#ifdef TLS
+  if (!ssl && (stat("control/servercert.pem",&st) == 0))
+    out("\r\n250-STARTTLS");
+#endif
+  size[fmt_ulong(size,(unsigned int) databytes)] = 0;
+  if (!spamt.flush || !spamt.throttle) {
+   out("\r\n250-PIPELINING");
+  }
+  out("\r\n250-8BITMIME\r\n");
+  out("250-SIZE "); out(size); out("\r\n");
+#ifdef CRAM_MD5
+  out("250 AUTH LOGIN PLAIN CRAM-MD5\r\n");
+#else
+  out("250 AUTH LOGIN PLAIN\r\n");
+#endif
   seenmail = 0; dohelo(arg);
+  if (bhelook) flagbarfbhelo = bmcheck(BMCHECK_BHELO);
 }
 void smtp_rset(arg) char *arg;
 {
@@ -239,45 +500,121 @@
 }
 void smtp_mail(arg) char *arg;
 {
+  int r;
   if (!addrparse(arg)) { err_syntax(); return; }
-  flagbarf = bmfcheck();
+  flagsize = 0;
+  mailfrom_parms(arg);
+  if (flagsize) { err_size(); return; }
+  flagbarfbmf = 0; /* bmcheck is skipped for empty envelope senders */
+  if ((bmfok) && (addr.len != 1)) flagbarfbmf = bmcheck(BMCHECK_BMF);
+  if ((!flagbarfbmf) && (bmfnrok) && (addr.len != 1) && (!relayclient)) {
+    flagbarfbmf = bmcheck(BMCHECK_BMFNR);
+  }
+  if (chkuser_sender (&addr) != CHKUSER_OK) { return; }
+  flagbarfspf = 0;
+  if (spfbehavior && !relayclient)
+   { 
+    switch(r = spfcheck()) {
+    case SPF_OK: env_put2("SPFRESULT","pass"); break;
+    case SPF_NONE: env_put2("SPFRESULT","none"); break;
+    case SPF_UNKNOWN: env_put2("SPFRESULT","unknown"); break;
+    case SPF_NEUTRAL: env_put2("SPFRESULT","neutral"); break;
+    case SPF_SOFTFAIL: env_put2("SPFRESULT","softfail"); break;
+    case SPF_FAIL: env_put2("SPFRESULT","fail"); break;
+    case SPF_ERROR: env_put2("SPFRESULT","error"); break;
+    }
+    switch (r) {
+    case SPF_NOMEM:
+      die_nomem();
+    case SPF_ERROR:
+      if (spfbehavior < 2) break;
+      out("451 SPF lookup failure (#4.3.0)\r\n");
+      return;
+    case SPF_NONE:
+    case SPF_UNKNOWN:
+      if (spfbehavior < 6) break;
+    case SPF_NEUTRAL:
+      if (spfbehavior < 5) break;
+    case SPF_SOFTFAIL:
+      if (spfbehavior < 4) break;
+    case SPF_FAIL:
+      if (spfbehavior < 3) break;
+      if (!spfexplanation(&spfbarfmsg)) die_nomem();
+      if (!stralloc_0(&spfbarfmsg)) die_nomem();
+      flagbarfspf = 1;
+    }
+   } 
+  else
+   env_unset("SPFRESULT");
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
+  rcptcount = 0;
   out("250 ok\r\n");
 }
+
+void err_spf() {
+  int i,j;
+ 
+   for(i = 0; i < spfbarfmsg.len; i = j + 1) {
+     j = byte_chr(spfbarfmsg.s + i, spfbarfmsg.len - i, '\n') + i;
+     if (j < spfbarfmsg.len) {
+       out("550-");
+       spfbarfmsg.s[j] = 0;
+       out(spfbarfmsg.s);
+       spfbarfmsg.s[j] = '\n';
+       out("\r\n");
+     } else {
+       out("550 ");
+       out(spfbarfmsg.s);
+       out(" (#5.7.1)\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 (relayclient) {
+  if (flagbarfbhelo) {
+    strerr_warn4("qmail-smtpd: badhelo: <",helohost.s,"> at ",remoteip,0);
+    err_bhelo();
+    return;
+  }
+  if (flagbarfbmf) {
+    strerr_warn4("qmail-smtpd: badmailfrom: <",mailfrom.s,"> at ",remoteip,0);
+    err_bmf();
+    return;
+  }
+  if (bmtok) flagbarfbmt = bmcheck(BMCHECK_BMT);
+  if ((!flagbarfbmt) && (bmtnrok) && (!relayclient)) {
+    flagbarfbmt = bmcheck(BMCHECK_BMTNR);
+  }
+  if (flagbarfbmt) {
+    strerr_warn4("qmail-smtpd: badmailto: <",addr.s,"> at ",remoteip,0);
+    err_bmt();
+    return;
+  }
+  if (flagbarfspf) { err_spf(); return; }
+  switch (chkuser_realrcpt (&mailfrom, &addr)) {
+
+        case CHKUSER_KO:
+                return;
+                break;
+
+        case CHKUSER_RELAYING:
     --addr.len;
     if (!stralloc_cats(&addr,relayclient)) die_nomem();
     if (!stralloc_0(&addr)) die_nomem();
+                break;
   }
-  else
-    if (!addrallowed()) { err_nogateway(); return; }
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
+  ++rcptcount;
   out("250 ok\r\n");
 }
 
-
-int saferead(fd,buf,len) int fd; char *buf; int len;
-{
-  int r;
-  flush();
-  r = timeoutread(timeout,fd,buf,len);
-  if (r == -1) if (errno == error_timeout) die_alarm();
-  if (r <= 0) die_read();
-  return r;
-}
-
-char ssinbuf[1024];
-substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
-
 struct qmail qqt;
 unsigned int bytestooverflow = 0;
 
@@ -351,6 +688,25 @@
   }
 }
 
+void spfreceived()
+{
+  stralloc sa = {0};
+  stralloc rcvd_spf = {0};
+
+  if (!spfbehavior || relayclient) return;
+
+  if (!stralloc_copys(&rcvd_spf, "Received-SPF: ")) die_nomem();
+  if (!spfinfo(&sa)) die_nomem();
+  if (!stralloc_cat(&rcvd_spf, &sa)) die_nomem();
+  if (!stralloc_append(&rcvd_spf, "\n")) die_nomem();
+  if (bytestooverflow) {
+    bytestooverflow -= rcvd_spf.len;
+    if (bytestooverflow <= 0) qmail_fail(&qqt);
+  }
+  qmail_put(&qqt,rcvd_spf.s,rcvd_spf.len);
+}
+
+
 char accept_buf[FMT_ULONG];
 void acceptmessage(qp) unsigned long qp;
 {
@@ -376,9 +732,14 @@
   if (databytes) bytestooverflow = databytes + 1;
   if (qmail_open(&qqt) == -1) { err_qqt(); return; }
   qp = qmail_qp(&qqt);
+
+  spamt.rcptcount = rcptcount;
+  spam_wait(&spamt);
+
   out("354 go ahead\r\n");
  
-  received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
+  received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
+  spfreceived();
   blast(&hops);
   hops = (hops >= MAXHOPS);
   if (hops) qmail_fail(&qqt);
@@ -388,28 +749,496 @@
   qqx = qmail_close(&qqt);
   if (!*qqx) { acceptmessage(qp); return; }
   if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
-  if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
+  if (databytes) if (!bytestooverflow) { err_size(); return; }
   if (*qqx == 'D') out("554 "); else out("451 ");
   out(qqx + 1);
   out("\r\n");
 }
 
+/* this file is too long ----------------------------------------- SMTP AUTH */
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+static stralloc authin = {0};   /* input from SMTP client */
+static stralloc user = {0};     /* authorization user-id */
+static stralloc pass = {0};     /* plain passwd or digest */
+static stralloc resp = {0};     /* b64 response */
+#ifdef CRAM_MD5
+static stralloc chal = {0};     /* plain challenge */
+static stralloc slop = {0};     /* b64 challenge */
+#endif
+
+int flagauth = 0;
+char **childargs;
+char ssauthbuf[512];
+substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf));
+
+int authgetl(void) {
+  int i;
+
+  if (!stralloc_copys(&authin,"")) die_nomem();
+  for (;;) {
+    if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
+    i = substdio_get(&ssin,authin.s + authin.len,1);
+    if (i != 1) die_read();
+    if (authin.s[authin.len] == '\n') break;
+    ++authin.len;
+  }
+
+  if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
+  authin.s[authin.len] = 0;
+  if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
+  if (authin.len == 0) { return err_input(); }
+  return authin.len;
+}
+
+int authenticate(void)
+{
+  int child;
+  int wstat;
+  int pi[2];
+
+  if (!stralloc_0(&user)) die_nomem();
+  if (!stralloc_0(&pass)) die_nomem();
+#ifdef CRAM_MD5
+  if (!stralloc_0(&chal)) die_nomem();
+#endif
+
+  if (pipe(pi) == -1) return err_pipe();
+  switch(child = fork()) {
+    case -1:
+      return err_fork();
+    case 0:
+      close(pi[1]);
+      if(fd_copy(3,pi[0]) == -1) return err_pipe();
+      sig_pipedefault();
+        execvp(*childargs, childargs);
+      _exit(1);
+  }
+  close(pi[0]);
+
+  substdio_fdbuf(&ssauth,write,pi[1],ssauthbuf,sizeof ssauthbuf);
+  if (substdio_put(&ssauth,user.s,user.len) == -1) return err_write();
+  if (substdio_put(&ssauth,pass.s,pass.len) == -1) return err_write();
+#ifdef CRAM_MD5
+  if (substdio_put(&ssauth,chal.s,chal.len) == -1) return err_write();
+#endif
+  if (substdio_flush(&ssauth) == -1) return err_write();
+
+  close(pi[1]);
+#ifdef CRAM_MD5
+  if (!stralloc_copys(&chal,"")) die_nomem();
+  if (!stralloc_copys(&slop,"")) die_nomem();
+#endif
+  byte_zero(ssauthbuf,sizeof ssauthbuf);
+  if (wait_pid(&wstat,child) == -1) return err_child();
+  if (wait_crashed(wstat)) return err_child();
+  if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */
+  return 0; /* yes */
+}
+
+int auth_login(arg) char *arg;
+{
+  int r;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
+  }
+  else {
+    out("334 VXNlcm5hbWU6\r\n"); flush();       /* Username: */
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
+  }
+  if (r == -1) die_nomem();
+
+  out("334 UGFzc3dvcmQ6\r\n"); flush();         /* Password: */
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
+  if (r == -1) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+int auth_plain(arg) char *arg;
+{
+  int r, id = 0;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&resp) == 1) return err_input();
+  }
+  else {
+    out("334 \r\n"); flush();
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
+  }
+  if (r == -1 || !stralloc_0(&resp)) die_nomem();
+  while (resp.s[id]) id++;                       /* "authorize-id\0userid\0passwd\0" */
+
+  if (resp.len > id + 1)
+    if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem();
+  if (resp.len > id + user.len + 2)
+    if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+#ifdef CRAM_MD5
+int auth_cram()
+{
+  int i, r;
+  char *s;
+
+  s = unique;                                           /* generate challenge */
+  s += fmt_uint(s,getpid());
+  *s++ = '.';
+  s += fmt_ulong(s,(unsigned long) now());
+  *s++ = '@';
+  *s++ = 0;
+  if (!stralloc_copys(&chal,"<")) die_nomem();
+  if (!stralloc_cats(&chal,unique)) die_nomem();
+  if (!stralloc_cats(&chal,local)) die_nomem();
+  if (!stralloc_cats(&chal,">")) die_nomem();
+  if (b64encode(&chal,&slop) < 0) die_nomem();
+  if (!stralloc_0(&slop)) die_nomem();
+
+  out("334 ");                                          /* "334 base64_challenge \r\n" */
+  out(slop.s);
+  out("\r\n");
+  flush();
+
+  if (authgetl() < 0) return -1;                        /* got response */
+  if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
+  if (r == -1 || !stralloc_0(&resp)) die_nomem();
+
+  i = str_chr(resp.s,' ');
+  s = resp.s + i;
+  while (*s == ' ') ++s;
+  resp.s[i] = 0;
+  if (!stralloc_copys(&user,resp.s)) die_nomem();       /* userid */
+  if (!stralloc_copys(&pass,s)) die_nomem();            /* digest */
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+#endif
+
+struct authcmd {
+  char *text;
+  int (*fun)();
+} authcmds[] = {
+  { "login",auth_login }
+,  { "plain",auth_plain }
+#ifdef CRAM_MD5
+, { "cram-md5",auth_cram }
+#endif
+, { 0,err_noauth }
+};
+
+void smtp_auth(arg)
+char *arg;
+{
+  int i;
+  char *cmd = arg;
+
+  if (!*childargs) { out("503 auth not available (#5.3.3)\r\n"); return; }
+  if (flagauth) { err_authd(); return; }
+  if (seenmail) { err_authmail(); return; }
+
+  if (!stralloc_copys(&user,"")) die_nomem();
+  if (!stralloc_copys(&pass,"")) die_nomem();
+  if (!stralloc_copys(&resp,"")) die_nomem();
+#ifdef CRAM_MD5
+  if (!stralloc_copys(&chal,"")) die_nomem();
+#endif
+
+  i = str_chr(cmd,' ');
+  arg = cmd + i;
+  while (*arg == ' ') ++arg;
+  cmd[i] = 0;
+
+  for (i = 0;authcmds[i].text;++i)
+    if (case_equals(authcmds[i].text,cmd)) break;
+
+  switch (authcmds[i].fun(arg)) {
+    case 0:
+      if (!env_put2("SMTPAUTHMETHOD", authcmds[i].text)) die_nomem();
+      if (!env_put2("SMTPAUTHUSER",user.s)) die_nomem();
+      flagauth = 1;
+      protocol = "ESMTPA";
+      relayclient = "";
+      remoteinfo = user.s;
+      if (!env_unset("TCPREMOTEINFO")) die_read();
+      if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+      if (!env_put2("RELAYCLIENT",relayclient)) die_nomem();
+      out("235 ok, go ahead (#2.0.0)\r\n");
+      break;
+    case 1:
+      err_authfail(user.s,authcmds[i].text);
+  }
+}
+
+
+/* this file is too long --------------------------------------------- GO ON */
+
+#ifdef TLS
+stralloc proto = {0};
+int ssl_verified = 0;
+const char *ssl_verify_err = 0;
+
+void smtp_tls(char *arg)
+{
+  if (ssl) err_unimpl();
+  else if (*arg) out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
+  else tls_init();
+}
+
+RSA *tmp_rsa_cb(SSL *ssl, int export, int keylen)
+{
+  if (!export) keylen = 512;
+  if (keylen == 512) {
+    FILE *in = fopen("control/rsa512.pem", "r");
+    if (in) {
+      RSA *rsa = PEM_read_RSAPrivateKey(in, NULL, NULL, NULL);
+      fclose(in);
+      if (rsa) return rsa;
+    }
+  }
+  return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
+}
+
+DH *tmp_dh_cb(SSL *ssl, int export, int keylen)
+{
+  if (!export) keylen = 1024;
+  if (keylen == 512) {
+    FILE *in = fopen("control/dh512.pem", "r");
+    if (in) {
+      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+      fclose(in);
+      if (dh) return dh;
+    }
+  }
+  if (keylen == 1024) {
+    FILE *in = fopen("control/dh1024.pem", "r");
+    if (in) {
+      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+      fclose(in);
+      if (dh) return dh;
+    }
+  }
+  return DH_generate_parameters(keylen, DH_GENERATOR_2, NULL, NULL);
+} 
+
+/* don't want to fail handshake if cert isn't verifiable */
+int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
+
+void tls_nogateway()
+{
+  /* there may be cases when relayclient is set */
+  if (!ssl || relayclient) return;
+  out("; no valid cert for gatewaying");
+  if (ssl_verify_err) { out(": "); out(ssl_verify_err); }
+}
+void tls_out(const char *s1, const char *s2)
+{
+  out("454 TLS "); out(s1);
+  if (s2) { out(": "); out(s2); }
+  out(" (#4.3.0)\r\n"); flush();
+}
+void tls_err(const char *s) { tls_out(s, ssl_error()); if (smtps) die_read(); }
+
+# define CLIENTCA "control/clientca.pem"
+# define CLIENTCRL "control/clientcrl.pem"
+# define SERVERCERT "control/servercert.pem"
+
+int tls_verify()
+{
+  stralloc clients = {0};
+  struct constmap mapclients;
+
+  if (!ssl || relayclient || ssl_verified) return 0;
+  ssl_verified = 1; /* don't do this twice */
+
+  /* request client cert to see if it can be verified by one of our CAs
+   * and the associated email address matches an entry in tlsclients */
+  switch (control_readfile(&clients, "control/tlsclients", 0))
+  {
+  case 1:
+    if (constmap_init(&mapclients, clients.s, clients.len, 0)) {
+      /* if CLIENTCA contains all the standard root certificates, a
+       * 0.9.6b client might fail with SSL_R_EXCESSIVE_MESSAGE_SIZE;
+       * it is probably due to 0.9.6b supporting only 8k key exchange
+       * data while the 0.9.6c release increases that limit to 100k */
+      STACK_OF(X509_NAME) *sk = SSL_load_client_CA_file(CLIENTCA);
+      if (sk) {
+        SSL_set_client_CA_list(ssl, sk);
+        SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
+        break;
+      }
+      constmap_free(&mapclients);
+    }
+  case 0: alloc_free(clients.s); return 0;
+  case -1: die_control();
+  }
+
+  if (ssl_timeoutrehandshake(timeout, ssl_rfd, ssl_wfd, ssl) <= 0) {
+    const char *err = ssl_error_str();
+    tls_out("rehandshake failed", err); die_read();
+  }
+
+  do { /* one iteration */
+    X509 *peercert;
+    X509_NAME *subj;
+    stralloc email = {0};
+
+    int n = SSL_get_verify_result(ssl);
+    if (n != X509_V_OK)
+      { ssl_verify_err = X509_verify_cert_error_string(n); break; }
+    peercert = SSL_get_peer_certificate(ssl);
+    if (!peercert) break;
+
+    subj = X509_get_subject_name(peercert);
+    n = X509_NAME_get_index_by_NID(subj, NID_pkcs9_emailAddress, -1);
+    if (n >= 0) {
+      const ASN1_STRING *s = X509_NAME_get_entry(subj, n)->value;
+      if (s) { email.len = s->length; email.s = s->data; }
+    }
+
+    if (email.len <= 0)
+      ssl_verify_err = "contains no email address";
+    else if (!constmap(&mapclients, email.s, email.len))
+      ssl_verify_err = "email address not in my list of tlsclients";
+    else {
+      /* add the cert email to the proto if it helped allow relaying */
+      --proto.len;
+      if (!stralloc_cats(&proto, "\n  (cert ") /* continuation line */
+        || !stralloc_catb(&proto, email.s, email.len)
+        || !stralloc_cats(&proto, ")")
+        || !stralloc_0(&proto)) die_nomem();
+      relayclient = "";
+      protocol = proto.s;
+    }
+
+    X509_free(peercert);
+  } while (0);
+  constmap_free(&mapclients); alloc_free(clients.s);
+
+  /* we are not going to need this anymore: free the memory */
+  SSL_set_client_CA_list(ssl, NULL);
+  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
+
+  return relayclient ? 1 : 0;
+}
+
+void tls_init()
+{
+  SSL *myssl;
+  SSL_CTX *ctx;
+  const char *ciphers;
+  stralloc saciphers = {0};
+  X509_STORE *store;
+  X509_LOOKUP *lookup;
+
+  SSL_library_init();
+
+  /* a new SSL context with the bare minimum of options */
+  ctx = SSL_CTX_new(SSLv23_server_method());
+  if (!ctx) { tls_err("unable to initialize ctx"); return; }
+
+  if (!SSL_CTX_use_certificate_chain_file(ctx, SERVERCERT))
+    { SSL_CTX_free(ctx); tls_err("missing certificate"); return; }
+  SSL_CTX_load_verify_locations(ctx, CLIENTCA, NULL);
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+  /* crl checking */
+  store = SSL_CTX_get_cert_store(ctx);
+  if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) &&
+      (X509_load_crl_file(lookup, CLIENTCRL, X509_FILETYPE_PEM) == 1))
+    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
+                                X509_V_FLAG_CRL_CHECK_ALL);
+#endif
+
+  /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
+  SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb);
+
+  /* a new SSL object, with the rest added to it directly to avoid copying */
+  myssl = SSL_new(ctx);
+  SSL_CTX_free(ctx);
+  if (!myssl) { tls_err("unable to initialize ssl"); return; }
+
+  /* this will also check whether public and private keys match */
+  if (!SSL_use_RSAPrivateKey_file(myssl, SERVERCERT, SSL_FILETYPE_PEM))
+    { SSL_free(myssl); tls_err("no valid RSA private key"); return; }
+
+  ciphers = env_get("TLSCIPHERS");
+  if (!ciphers) {
+    if (control_readfile(&saciphers, "control/tlsserverciphers") == -1)
+      { SSL_free(myssl); die_control(); }
+    if (saciphers.len) { /* convert all '\0's except the last one to ':' */
+      int i;
+      for (i = 0; i < saciphers.len - 1; ++i)
+        if (!saciphers.s[i]) saciphers.s[i] = ':';
+      ciphers = saciphers.s;
+    }
+  }
+  if (!ciphers || !*ciphers) ciphers = "DEFAULT";
+  SSL_set_cipher_list(myssl, ciphers);
+  alloc_free(saciphers.s);
+
+  SSL_set_tmp_rsa_callback(myssl, tmp_rsa_cb);
+  SSL_set_tmp_dh_callback(myssl, tmp_dh_cb);
+  SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin));
+  SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout));
+
+  if (!smtps) { out("220 ready for tls\r\n"); flush(); }
+
+  if (ssl_timeoutaccept(timeout, ssl_rfd, ssl_wfd, myssl) <= 0) {
+    /* neither cleartext nor any other response here is part of a standard */
+    const char *err = ssl_error_str();
+    ssl_free(myssl); tls_out("connection failed", err); die_read();
+  }
+  ssl = myssl;
+
+  /* populate the protocol string, used in Received */
+  if (!stralloc_copys(&proto, "(")
+    || !stralloc_cats(&proto, SSL_get_cipher(ssl))
+    || !stralloc_cats(&proto, " encrypted) SMTP")) die_nomem();
+  if (!stralloc_0(&proto)) die_nomem();
+  protocol = proto.s;
+
+  /* have to discard the pre-STARTTLS HELO/EHLO argument, if any */
+  dohelo(remotehost);
+}
+
+# undef SERVERCERT
+# undef CLIENTCA
+
+#endif
+
 struct commands smtpcommands[] = {
   { "rcpt", smtp_rcpt, 0 }
 , { "mail", smtp_mail, 0 }
 , { "data", smtp_data, flush }
+, { "auth", smtp_auth, flush }
 , { "quit", smtp_quit, flush }
 , { "helo", smtp_helo, flush }
 , { "ehlo", smtp_ehlo, flush }
 , { "rset", smtp_rset, 0 }
 , { "help", smtp_help, flush }
+#ifdef TLS
+, { "starttls", smtp_tls, flush }
+#endif
 , { "noop", err_noop, flush }
 , { "vrfy", err_vrfy, flush }
 , { 0, err_unimpl, flush }
 } ;
 
-void main()
+void main(argc,argv)
+int argc;
+char **argv;
 {
+  childargs = argv + 1;
   sig_pipeignore();
   if (chdir(auto_qmail) == -1) die_control();
   setup();
diff -ur netqmail-1.05/qmail-smtpd.c.orig netqmail-1.05.patched/qmail-smtpd.c.orig
--- netqmail-1.05/qmail-smtpd.c.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/qmail-smtpd.c.orig	2008-06-04 19:35:18.000000000 +0200
@@ -51,12 +51,12 @@
 
 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_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
+void err_unimpl(arg) char *arg; { 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"); }
 void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
-void err_noop() { out("250 ok\r\n"); }
-void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }
+void err_noop(arg) char *arg; { out("250 ok\r\n"); }
+void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); }
 void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
 
 
@@ -67,11 +67,11 @@
   substdio_puts(&ssout,code);
   substdio_put(&ssout,greeting.s,greeting.len);
 }
-void smtp_help()
+void smtp_help(arg) char *arg;
 {
-  out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n");
+  out("214 netqmail home page: http://qmail.org/netqmail\r\n");
 }
-void smtp_quit()
+void smtp_quit(arg) char *arg;
 {
   smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
 }
@@ -232,7 +232,7 @@
   smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
   seenmail = 0; dohelo(arg);
 }
-void smtp_rset()
+void smtp_rset(arg) char *arg;
 {
   seenmail = 0;
   out("250 flushed\r\n");
@@ -316,8 +316,8 @@
         if (flagmaybex) if (pos == 7) ++*hops;
         if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0;
         if (flagmaybey) if (pos == 1) flaginheader = 0;
+	++pos;
       }
-      ++pos;
       if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; }
     }
     switch(state) {
@@ -365,7 +365,7 @@
   out("\r\n");
 }
 
-void smtp_data() {
+void smtp_data(arg) char *arg; {
   int hops;
   unsigned long qp;
   char *qqx;
Only in netqmail-1.05.patched: qmail-spamt.9
Only in netqmail-1.05.patched: qmail-spamt.9.orig
Only in netqmail-1.05.patched: qmail-spamthrottle.9
Only in netqmail-1.05.patched: qmail-spamthrottle.9.orig
Only in netqmail-1.05.patched: qregex.c
Only in netqmail-1.05.patched: qregex.c.orig
Only in netqmail-1.05.patched: qregex.h
Only in netqmail-1.05.patched: qregex.h.orig
diff -ur netqmail-1.05/remoteinfo.c netqmail-1.05.patched/remoteinfo.c
--- netqmail-1.05/remoteinfo.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/remoteinfo.c	2008-06-04 19:35:18.000000000 +0200
@@ -23,33 +23,63 @@
   return timeoutread(t,fd,buf,len);
 }
 
-char *remoteinfo_get(ipr,rp,ipl,lp,timeout)
-struct ip_address *ipr;
-unsigned long rp;
-struct ip_address *ipl;
-unsigned long lp;
+union sockunion {
+	struct sockaddr     sa;
+	struct sockaddr_in  sa4;
+#ifdef INET6
+	struct sockaddr_in6 sa6;
+#endif
+};
+
+char *remoteinfo_get(saremote, salocal, timeout)
+union sockunion *saremote, *salocal;
+
 int timeout;
 {
   char *x;
   int s;
-  struct sockaddr_in sin;
+  union sockunion sa;
   substdio ss;
   char buf[32];
-  unsigned int len;
+  unsigned int len, rp, lp;
   int numcolons;
   char ch;
 
   t = timeout;
  
-  s = socket(AF_INET,SOCK_STREAM,0);
+  s = socket(saremote->sa.sa_family,SOCK_STREAM,0);
   if (s == -1) return 0;
  
-  byte_zero(&sin,sizeof(sin));
-  sin.sin_family = AF_INET;
-  byte_copy(&sin.sin_addr,4,ipl);
-  sin.sin_port = 0;
-  if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; }
-  if (timeoutconn(s,ipr,113,timeout) == -1) { close(s); return 0; }
+  switch(saremote->sa.sa_family) {
+  case AF_INET:
+    rp = ntohs(saremote->sa4.sin_port);
+    lp = ntohs(salocal->sa4.sin_port);
+    byte_zero(&sa,sizeof(sa));
+    sa.sa4.sin_family = AF_INET;
+    byte_copy(&sa.sa4.sin_addr, 4, &salocal->sa4.sin_addr);
+    sa.sa4.sin_port = 0;
+    if (bind(s,(struct sockaddr *) &sa.sa,sizeof(sa.sa4)) == -1) { close(s); return 0; }
+    if (timeoutconn(s,&saremote->sa4.sin_addr,113,timeout) == -1) { close(s); return 0; }
+    break;
+#ifdef INET6
+  case AF_INET6:
+    rp = ntohs(saremote->sa6.sin6_port);
+    lp = ntohs(salocal->sa6.sin6_port);
+    s = socket(PF_INET6, SOCK_STREAM, 0);
+    if (s == -1) return 0;
+    byte_zero(&sa,sizeof(sa));
+    sa.sa6.sin6_family = AF_INET;
+    byte_copy(&sa.sa6.sin6_addr, 16, &salocal->sa6.sin6_addr);
+    sa.sa6.sin6_port = 0;
+    sa.sa6.sin6_flowinfo = 0;
+    if (bind(s,(struct sockaddr *) &sa.sa,sizeof(sa.sa6)) == -1) { close(s); return 0; }
+    if (timeoutconn6(s,&saremote->sa6.sin6_addr,113,timeout) == -1) { close(s); return 0; }
+    break;
+#endif
+  default:
+    return 0;
+  }
+  
   fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY);
  
   len = 0;
Only in netqmail-1.05.patched: remoteinfo.c.orig
diff -ur netqmail-1.05/scan.h netqmail-1.05.patched/scan.h
--- netqmail-1.05/scan.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/scan.h	2008-06-04 19:35:18.000000000 +0200
@@ -10,6 +10,7 @@
 extern unsigned int scan_ulong();
 extern unsigned int scan_xlong();
 extern unsigned int scan_nbblong();
+extern unsigned int scan_2long();
 
 extern unsigned int scan_plusminus();
 extern unsigned int scan_0x();
Only in netqmail-1.05.patched: scan.h.orig
Only in netqmail-1.05.patched: scan_2long.c
Only in netqmail-1.05.patched: scan_2long.c.orig
Only in netqmail-1.05.patched: spam.c
Only in netqmail-1.05.patched: spam.c.orig
Only in netqmail-1.05.patched: spam.h
Only in netqmail-1.05.patched: spam.h.orig
Only in netqmail-1.05.patched: spam_get.c
Only in netqmail-1.05.patched: spam_get.c.orig
diff -ur netqmail-1.05/spawn.c netqmail-1.05.patched/spawn.c
--- netqmail-1.05/spawn.c	2008-06-04 19:35:29.000000000 +0200
+++ netqmail-1.05.patched/spawn.c	2008-06-04 19:35:18.000000000 +0200
@@ -64,7 +64,7 @@
 int flagreading = 1;
 char outbuf[1024]; substdio ssout;
 
-int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */
+int stage = 0; /* reading 0:delnum 1:delnum2 2:messid 3:sender 4:recip */
 int flagabort = 0; /* if 1, everything except delnum is garbage */
 int delnum;
 stralloc messid = {0};
@@ -74,6 +74,7 @@
 void err(s) char *s;
 {
  char ch; ch = delnum; substdio_put(&ssout,&ch,1);
+ ch = delnum >> 8; substdio_put(&ssout,&ch,1);
  substdio_puts(&ssout,s); substdio_putflush(&ssout,"",1);
 }
 
@@ -156,16 +157,19 @@
     {
      case 0:
        delnum = (unsigned int) (unsigned char) ch;
-       messid.len = 0; stage = 1; break;
+       stage = 1; break;
      case 1:
+       delnum += (unsigned int) ((unsigned int) ch) << 8;
+       messid.len = 0; stage = 2; break;
+     case 2:
        if (!stralloc_append(&messid,&ch)) flagabort = 1;
        if (ch) break;
-       sender.len = 0; stage = 2; break;
-     case 2:
+       sender.len = 0; stage = 3; break;
+     case 3:
        if (!stralloc_append(&sender,&ch)) flagabort = 1;
        if (ch) break;
-       recip.len = 0; stage = 3; break;
-     case 3:
+       recip.len = 0; stage = 4; break;
+     case 4:
        if (!stralloc_append(&recip,&ch)) flagabort = 1;
        if (ch) break;
        docmd();
@@ -202,7 +206,8 @@
 
  initialize(argc,argv);
 
- ch = auto_spawn; substdio_putflush(&ssout,&ch,1);
+ ch = auto_spawn; substdio_put(&ssout,&ch,1);
+ ch = auto_spawn >> 8; substdio_putflush(&ssout,&ch,1);
 
  for (i = 0;i < auto_spawn;++i) { d[i].used = 0; d[i].output.s = 0; }
 
@@ -237,7 +242,8 @@
 	   continue; /* read error on a readable pipe? be serious */
 	 if (r == 0)
 	  {
-           ch = i; substdio_put(&ssout,&ch,1);
+           char ch; ch = i; substdio_put(&ssout,&ch,1);
+           ch = i >> 8; substdio_put(&ssout,&ch,1);
 	   report(&ssout,d[i].wstat,d[i].output.s,d[i].output.len);
 	   substdio_put(&ssout,"",1);
 	   substdio_flush(&ssout);
diff -ur netqmail-1.05/spawn.c.orig netqmail-1.05.patched/spawn.c.orig
--- netqmail-1.05/spawn.c.orig	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/spawn.c.orig	2008-06-04 19:35:18.000000000 +0200
@@ -5,6 +5,7 @@
 #include "substdio.h"
 #include "byte.h"
 #include "str.h"
+#include "alloc.h"
 #include "stralloc.h"
 #include "select.h"
 #include "exit.h"
Only in netqmail-1.05.patched: spf.c
Only in netqmail-1.05.patched: spf.c.orig
Only in netqmail-1.05.patched: spf.h
Only in netqmail-1.05.patched: spf.h.orig
Only in netqmail-1.05.patched: spfquery.c
Only in netqmail-1.05.patched: spfquery.c.orig
Only in netqmail-1.05.patched: ssl_timeoutio.c
Only in netqmail-1.05.patched: ssl_timeoutio.c.orig
Only in netqmail-1.05.patched: ssl_timeoutio.h
Only in netqmail-1.05.patched: ssl_timeoutio.h.orig
diff -ur netqmail-1.05/str.h netqmail-1.05.patched/str.h
--- netqmail-1.05/str.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/str.h	2008-06-04 19:35:18.000000000 +0200
@@ -2,6 +2,7 @@
 #define STR_H
 
 extern unsigned int str_copy();
+extern unsigned int str_copyb();
 extern int str_diff();
 extern int str_diffn();
 extern unsigned int str_len();
Only in netqmail-1.05.patched: str.h.orig
Only in netqmail-1.05.patched: str_cpyb.c
Only in netqmail-1.05.patched: str_cpyb.c.orig
Only in netqmail-1.05.patched: strpidt.c
Only in netqmail-1.05.patched: strpidt.c.orig
Only in netqmail-1.05.patched: strsalloc.c
Only in netqmail-1.05.patched: strsalloc.c.orig
Only in netqmail-1.05.patched: strsalloc.h
Only in netqmail-1.05.patched: strsalloc.h.orig
Only in netqmail-1.05.patched: strtimet.c
Only in netqmail-1.05.patched: strtimet.c.orig
diff -ur netqmail-1.05/tcp-env.1 netqmail-1.05.patched/tcp-env.1
--- netqmail-1.05/tcp-env.1	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/tcp-env.1	2008-06-04 19:35:18.000000000 +0200
@@ -4,7 +4,10 @@
 .SH SYNOPSIS
 .B tcp-env
 [
-.B \-rR
+.B \-rRhH
+]
+[
+.B \-l\fIlocalname
 ]
 [
 .B \-t\fItimeout
@@ -55,6 +58,20 @@
 .B TCPREMOTEINFO
 from the remote host.
 .TP
+.B \-h
+(Default.)
+Look up the remote host name in DNS to set the environment variable
+.BR TCPREMOTEHOST .
+.TP
+.B \-H
+Do not look up the remote host name in DNS; remove the environment variable 
+.BR TCPREMOTEHOST .
+.TP
+.B \-l\fIlocalname
+Do not look up the local host name in DNS; use localname for the environment variable 
+.BR TCPLOCALHOST .
+A common choice for localname is 0.
+.TP
 .B \-t\fItimeout
 Give up on the
 .B TCPREMOTEINFO
Only in netqmail-1.05.patched: tcp-env.1.orig
diff -ur netqmail-1.05/tcp-env.c netqmail-1.05.patched/tcp-env.c
--- netqmail-1.05/tcp-env.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/tcp-env.c	2008-06-04 19:35:18.000000000 +0200
@@ -2,6 +2,7 @@
 #include <sys/socket.h>
 #include <sys/param.h>
 #include <netinet/in.h>
+#include <netdb.h>
 #include "sig.h"
 #include "stralloc.h"
 #include "str.h"
@@ -10,35 +11,73 @@
 #include "scan.h"
 #include "subgetopt.h"
 #include "ip.h"
+#include "strsalloc.h"
 #include "dns.h"
 #include "byte.h"
 #include "remoteinfo.h"
 #include "exit.h"
 #include "case.h"
+#include "hassalen.h"
 
 void die() { _exit(111); }
 
-struct sockaddr_in salocal;
+int flagremotehost = 1;
+
+union sockunion {
+	struct sockaddr     sa;
+	struct sockaddr_in  sa4;
+#ifdef INET6
+	struct sockaddr_in6 sa6;
+#endif
+};
+
+char temp[HOSTNAMELEN];
+
+union sockunion salocal;
 unsigned long localport;
-struct ip_address iplocal;
 stralloc localname = {0};
+char *localhost = 0;
 
-struct sockaddr_in saremote;
+union sockunion saremote;
 unsigned long remoteport;
-struct ip_address ipremote;
 stralloc remotename = {0};
 
-char temp[IPFMT + FMT_ULONG];
+#ifdef IN6_IS_ADDR_V4MAPPED
+void mappedtov4(union sockunion *sa)
+{
+	struct sockaddr_in sin;
+	struct sockaddr_in6 *sin6 = &sa->sa6;
+
+	bzero(&sin, sizeof(sin));
+	if (sin6->sin6_family == AF_INET6 &&
+	  IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ) {
+		memcpy(&sin.sin_addr, sin6->sin6_addr.s6_addr+12, sizeof(sin.sin_addr));
+		sin.sin_port = sin6->sin6_port;
+		sin.sin_family = AF_INET;
+#ifdef HASSALEN
+		sin.sin_len = sizeof(sin);
+#endif
+		memcpy(&sa->sa4, &sin, sizeof(sin));
+	}
+		
+}
+#else
+#define mappedtov4(A)
+#endif
+
+//char temp[IPFMT + FMT_ULONG];
 
 void main(argc,argv)
 int argc;
 char *argv[];
 {
+ strsalloc ssa = {0};
  int dummy;
  char *proto;
  int opt;
  int flagremoteinfo;
  unsigned long timeout;
+ struct sockaddr_in *v4;
 
  sig_pipeignore();
 
@@ -50,6 +89,9 @@
      case 'r': flagremoteinfo = 1; break;
      case 'R': flagremoteinfo = 0; break;
      case 't': scan_ulong(sgoptarg,&timeout); break;
+     case 'H': flagremotehost = 0; break;
+     case 'h': flagremotehost = 1; break;
+     case 'l': localhost = sgoptarg; break;
     }
 
  argv += sgoptind;
@@ -65,28 +107,77 @@
 
    dummy = sizeof(salocal);
    if (getsockname(0,(struct sockaddr *) &salocal,&dummy) == -1) die();
+   mappedtov4(&salocal);
 
-   localport = ntohs(salocal.sin_port);
-   temp[fmt_ulong(temp,localport)] = 0;
-   if (!env_put2("TCPLOCALPORT",temp)) die();
-
-   byte_copy(&iplocal,4,&salocal.sin_addr);
-   temp[ip_fmt(temp,&iplocal)] = 0;
-   if (!env_put2("TCPLOCALIP",temp)) die();
+   /* Problem start here */
+   switch(salocal.sa.sa_family) {
+   case AF_INET:
+	localport = ntohs(salocal.sa4.sin_port);
+        temp[fmt_ulong(temp,localport)] = 0;
+        if (!env_put2("TCPLOCALPORT",temp)) die();
+	temp[ip_fmt(temp, &salocal.sa4.sin_addr)] = 0;
+	if (!env_put2("TCPLOCALIP",temp)) die();
+	switch(dns_ptr(&localname,&salocal.sa4.sin_addr)) {
+	case DNS_MEM: die();
+	case DNS_SOFT:
+	  if (!stralloc_copys(&localname,"softdnserror")) die();
+	case 0:
+	  if (!stralloc_0(&localname)) die();
+	  case_lowers(localname.s);
+	  if (!env_put2("TCPLOCALHOST",localname.s)) die();
+	  break;
+	default:
+	  if (!env_unset("TCPLOCALHOST")) die();
+	}
+	break;
+#ifdef INET6
+   case AF_INET6:
+	localport = ntohs(salocal.sa6.sin6_port);
+        temp[fmt_ulong(temp,localport)] = 0;
+        if (!env_put2("TCPLOCALPORT",temp)) die();
+	temp[ip6_fmt(temp, &salocal.sa6.sin6_addr)] = 0;
+	if (!env_put2("TCPLOCALIP",temp)) die();
+	switch(dns_ptr6(&localname,&salocal.sa6.sin6_addr)) {
+	case DNS_MEM: die();
+	case DNS_SOFT:
+	  if (!stralloc_copys(&localname,"softdnserror")) die();
+	case 0:
+	  if (!stralloc_0(&localname)) die();
+	  case_lowers(localname.s);
+	  if (!env_put2("TCPLOCALHOST",localname.s)) die();
+	  break;
+	default:
+	  if (!env_unset("TCPLOCALHOST")) die();
+	}
+	break;
+#endif
+   default:
+	die();
+   }
+/* End new code */
 
-   switch(dns_ptr(&localname,&iplocal))
+/*switch statement differs from orginal 
+   if (!localhost)
+    {
+   switch(dns_ptr(&ssa,&iplocal))
     {
      case DNS_MEM: die();
      case DNS_SOFT:
        if (!stralloc_copys(&localname,"softdnserror")) die();
      case 0:
+       if (!stralloc_copy(&localname,&ssa.sa[0])) die();
        if (!stralloc_0(&localname)) die();
        case_lowers(localname.s);
-       if (!env_put2("TCPLOCALHOST",localname.s)) die();
+	 localhost = localname.s;
        break;
      default:
        if (!env_unset("TCPLOCALHOST")) die();
     }
+    }
+   if (localhost)
+    {
+     if (!env_put2("TCPLOCALHOST",localhost)) die();
+    }
 
    dummy = sizeof(saremote);
    if (getpeername(0,(struct sockaddr *) &saremote,&dummy) == -1) die();
@@ -99,26 +190,33 @@
    temp[ip_fmt(temp,&ipremote)] = 0;
    if (!env_put2("TCPREMOTEIP",temp)) die();
 
-   switch(dns_ptr(&remotename,&ipremote))
+   if (flagremotehost)
+    {
+   switch(dns_ptr(&ssa,&ipremote))
     {
      case DNS_MEM: die();
      case DNS_SOFT:
        if (!stralloc_copys(&remotename,"softdnserror")) die();
      case 0:
+       if (!stralloc_copy(&remotename,&ssa.sa[0])) die();
        if (!stralloc_0(&remotename)) die();
        case_lowers(remotename.s);
        if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
        break;
      default:
        if (!env_unset("TCPREMOTEHOST")) die();
+      }
     }
+    */
+/* End orignal switch code */
 
    if (!env_unset("TCPREMOTEINFO")) die();
    if (flagremoteinfo)
     {
      char *rinfo;
-     rinfo = remoteinfo_get(&ipremote,remoteport,&iplocal,localport,(int) timeout);
-     if (rinfo)
+     //rinfo = remoteinfo_get(&ipremote,remoteport,&iplocal,localport,(int) timeout);
+     rinfo = remoteinfo_get(&saremote, &salocal,(int) timeout);
+      if (rinfo)
        if (!env_put2("TCPREMOTEINFO",rinfo)) die();
     }
   }
Only in netqmail-1.05.patched: tcp-env.c.orig
diff -ur netqmail-1.05/tcpto.c netqmail-1.05.patched/tcpto.c
--- netqmail-1.05/tcpto.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/tcpto.c	2008-06-04 19:35:18.000000000 +0200
@@ -1,14 +1,17 @@
+#include <sys/types.h>
+#include <sys/socket.h>
 #include "tcpto.h"
 #include "open.h"
 #include "lock.h"
 #include "seek.h"
 #include "now.h"
 #include "ip.h"
+#include "ipalloc.h"
 #include "byte.h"
 #include "datetime.h"
 #include "readwrite.h"
 
-char tcpto_buf[1024];
+char tcpto_buf[2048];
 
 static int flagwasthere;
 static int fdlock;
@@ -26,13 +29,27 @@
  r = read(fd,tcpto_buf,sizeof(tcpto_buf));
  close(fd);
  if (r < 0) { close(fdlock); return 0; }
- r >>= 4;
+ r >>= 5;
  if (!r) close(fdlock);
  return r;
 }
 
-int tcpto(ip) struct ip_address *ip;
+/*
+  struct tcpto {  32bytes
+    char af;             +0
+    char nul[3];
+    char resason;        +4
+    char nul[3];
+    ulong when;          +8
+    char nul[4];
+    union { ip4, ip6 };  +16
+*/
+
+int tcpto(ix)
+struct ip_mx *ix;
 {
+ int af = ix->af;
+ struct ip_address *ip = &ix->addr.ip;
  int n;
  int i;
  char *record;
@@ -47,7 +64,7 @@
  record = tcpto_buf;
  for (i = 0;i < n;++i)
   {
-   if (byte_equal(ip->d,4,record))
+   if (af == record[0] && byte_equal(ip->d,af==AF_INET ? 4 : 16,record+16))
     {
      flagwasthere = 1;
      if (record[4] >= 2)
@@ -62,12 +79,14 @@
       }
      return 0;
     }
-   record += 16;
+   record += 32;
   }
  return 0;
 }
 
-void tcpto_err(ip,flagerr) struct ip_address *ip; int flagerr;
+void tcpto_err(af,ip,flagerr)
+int af;
+struct ip_address *ip; int flagerr;
 {
  int n;
  int i;
@@ -87,7 +106,7 @@
  record = tcpto_buf;
  for (i = 0;i < n;++i)
   {
-   if (byte_equal(ip->d,4,record))
+   if (af == record[0] && byte_equal(ip->d,af == AF_INET ? 4 : 16,record+16))
     {
      if (!flagerr)
        record[4] = 0;
@@ -107,13 +126,13 @@
        record[10] = when; when >>= 8;
        record[11] = when;
       }
-     if (seek_set(fdlock,i << 4) == 0)
-       if (write(fdlock,record,16) < 16)
+     if (seek_set(fdlock,i << 5) == 0)
+       if (write(fdlock,record,32) < 32)
          ; /*XXX*/
      close(fdlock);
      return;
     }
-   record += 16;
+   record += 32;
   }
 
  if (!flagerr) { close(fdlock); return; }
@@ -122,7 +141,7 @@
  for (i = 0;i < n;++i)
   {
    if (!record[4]) break;
-   record += 16;
+   record += 32;
   }
 
  if (i >= n)
@@ -141,23 +160,24 @@
        firstpos = i;
        firstwhen = when;
       }
-     record += 16;
+     record += 32;
     }
    i = firstpos;
   }
 
  if (i >= 0)
   {
-   record = tcpto_buf + (i << 4);
-   byte_copy(record,4,ip->d);
+   record = tcpto_buf + (i << 5);
+   record[0] = af;
+   byte_copy(record+16,16,&ip);
    when = now();
    record[8] = when; when >>= 8;
    record[9] = when; when >>= 8;
    record[10] = when; when >>= 8;
    record[11] = when;
    record[4] = 1;
-   if (seek_set(fdlock,i << 4) == 0)
-     if (write(fdlock,record,16) < 16)
+   if (seek_set(fdlock,i << 5) == 0)
+     if (write(fdlock,record,32) < 32)
        ; /*XXX*/
   }
 
Only in netqmail-1.05.patched: tcpto.c.orig
diff -ur netqmail-1.05/tcpto_clean.c netqmail-1.05.patched/tcpto_clean.c
--- netqmail-1.05/tcpto_clean.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/tcpto_clean.c	2008-06-04 19:35:18.000000000 +0200
@@ -3,7 +3,7 @@
 #include "substdio.h"
 #include "readwrite.h"
 
-char tcpto_cleanbuf[1024];
+char tcpto_cleanbuf[2048];
 
 void tcpto_clean() /* running from queue/mess */
 {
Only in netqmail-1.05.patched: tcpto_clean.c.orig
Only in netqmail-1.05.patched: time.c
Only in netqmail-1.05.patched: time.c.orig
Only in netqmail-1.05.patched: time.h
Only in netqmail-1.05.patched: time.h.orig
diff -ur netqmail-1.05/timeoutconn.c netqmail-1.05.patched/timeoutconn.c
--- netqmail-1.05/timeoutconn.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/timeoutconn.c	2008-06-04 19:35:18.000000000 +0200
@@ -57,3 +57,52 @@
   errno = error_timeout; /* note that connect attempt is continuing */
   return -1;
 }
+
+#ifdef INET6
+int timeoutconn6(s,ip,port,timeout)
+int s;
+struct ip6_address *ip;
+unsigned int port;
+int timeout;
+{
+  char ch;
+  struct sockaddr_in6 sin;
+  char *x;
+  fd_set wfds;
+  struct timeval tv;
+ 
+  byte_zero(&sin,sizeof(sin));
+  byte_copy(&sin.sin6_addr,16,ip);
+  sin.sin6_port = htons(port);;
+  sin.sin6_family = AF_INET6;
+ 
+  if (ndelay_on(s) == -1) return -1;
+ 
+  /* XXX: could bind s */
+ 
+  if (connect(s,(struct sockaddr *) &sin,sizeof(sin)) == 0) {
+    ndelay_off(s);
+    return 0;
+  }
+  if ((errno != error_inprogress) && (errno != error_wouldblock)) return -1;
+ 
+  FD_ZERO(&wfds);
+  FD_SET(s,&wfds);
+  tv.tv_sec = timeout; tv.tv_usec = 0;
+ 
+  if (select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1;
+  if (FD_ISSET(s,&wfds)) {
+    int dummy;
+    dummy = sizeof(sin);
+    if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) {
+      read(s,&ch,1);
+      return -1;
+    }
+    ndelay_off(s);
+    return 0;
+  }
+ 
+  errno = error_timeout; /* note that connect attempt is continuing */
+  return -1;
+}
+#endif
Only in netqmail-1.05.patched: timeoutconn.c.orig
diff -ur netqmail-1.05/timeoutconn.h netqmail-1.05.patched/timeoutconn.h
--- netqmail-1.05/timeoutconn.h	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05.patched/timeoutconn.h	2008-06-04 19:35:18.000000000 +0200
@@ -2,5 +2,6 @@
 #define TIMEOUTCONN_H
 
 extern int timeoutconn();
+extern int timeoutconn6();
 
 #endif
Only in netqmail-1.05.patched: timeoutconn.h.orig
Only in netqmail-1.05.patched: tls.c
Only in netqmail-1.05.patched: tls.c.orig
Only in netqmail-1.05.patched: tls.h
Only in netqmail-1.05.patched: tls.h.orig
Only in netqmail-1.05.patched: tryltai.c
Only in netqmail-1.05.patched: tryltai.c.orig
Only in netqmail-1.05.patched: trytai.c
Only in netqmail-1.05.patched: trytai.c.orig
Only in netqmail-1.05.patched: update_tmprsadh.sh
Only in netqmail-1.05.patched: update_tmprsadh.sh.orig
