diff -ur qmail-1.03/conf-cc qmail-1.03v6/conf-cc
--- qmail-1.03/conf-cc	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/conf-cc	Tue Apr 20 13:32:54 1999
@@ -1,3 +1,4 @@
+cc -O2 -DINET6
 cc -O2
 
 This will be used to compile .c files.
diff -ur qmail-1.03/dns.c qmail-1.03v6/dns.c
--- qmail-1.03/dns.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/dns.c	Wed Jul  1 21:53:10 1998
@@ -3,6 +3,7 @@
 #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();
@@ -29,6 +30,9 @@
 static int numanswers;
 static char name[MAXDNAME];
 static struct ip_address ip;
+#ifdef INET6
+static struct ip6_address ip6;
+#endif
 unsigned short pref;
 
 static stralloc glue = {0};
@@ -142,6 +146,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;
 {
@@ -263,6 +304,57 @@
  return DNS_HARD;
 }
 
+#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;
+   case DNS_HARD: return DNS_HARD;
+  }
+ while ((r = findname(T_PTR)) != 2)
+  {
+   if (r == DNS_SOFT) return DNS_SOFT;
+   if (r == 1)
+    {
+     if (!stralloc_copys(sa,name)) return DNS_MEM;
+     return 0;
+    }
+  }
+ return DNS_HARD;
+}
+#endif
+
 static int dns_ipplus(ia,sa,pref)
 ipalloc *ia;
 stralloc *sa;
@@ -270,33 +362,66 @@
 {
  int r;
  struct ip_mx ix;
+ 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;
   }
- while ((r = findip(T_A)) != 2)
+#endif
+
+ switch(resolve(sa,T_A))
   {
-   ix.ip = ip;
-   ix.pref = pref;
-   if (r == DNS_SOFT) return DNS_SOFT;
-   if (r == 1)
-     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
+   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.af = AF_INET;
+         ix.addr.ip = ip;
+         ix.pref = pref;
+	 if (r == DNS_SOFT) { err4 = DNS_SOFT; break; }
+	 if (r == 1)
+	   if (!ipalloc_append(ia,&ix)) { err4 = DNS_MEM; break; }
+       }
+     break;
   }
+
+#ifdef INET6
+ if (err4 != 0 && err6 != 0) {
+   return err4;
+ }
  return 0;
+#else
+ return err4;
+#endif
 }
 
 int dns_ip(ia,sa)
@@ -328,8 +453,9 @@
  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.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;
     }
diff -ur qmail-1.03/dnsfq.c qmail-1.03v6/dnsfq.c
--- qmail-1.03/dnsfq.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/dnsfq.c	Wed Jul  1 21:53:11 1998
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/socket.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "stralloc.h"
@@ -25,7 +27,12 @@
   {
    substdio_putsflush(subfderr,"no IP addresses\n"); _exit(100);
   }
- dnsdoe(dns_ptr(&sa,&ia.ix[0].ip));
+ if (ia.ix[0].af == AF_INET)
+	dnsdoe(dns_ptr(&sa,&ia.ix[0].addr.ip));
+#ifdef INET6
+ else
+	dnsdoe(dns_ptr6(&sa,&ia.ix[0].addr.ip6));
+#endif
  substdio_putflush(subfdout,sa.s,sa.len);
  substdio_putsflush(subfdout,"\n");
  _exit(0);
diff -ur qmail-1.03/dnsip.c qmail-1.03v6/dnsip.c
--- qmail-1.03/dnsip.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/dnsip.c	Wed Jul  1 21:53:11 1998
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/socket.h>
 #include "substdio.h"
 #include "subfd.h"
 #include "stralloc.h"
@@ -27,7 +29,19 @@
  dnsdoe(dns_ip(&ia,&sa));
  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_putsflush(subfdout,"\n");
   }
  _exit(0);
diff -ur qmail-1.03/dnsmxip.c qmail-1.03v6/dnsmxip.c
--- qmail-1.03/dnsmxip.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/dnsmxip.c	Wed Jul  1 21:53:12 1998
@@ -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");
diff -ur qmail-1.03/ip.c qmail-1.03v6/ip.c
--- qmail-1.03/ip.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/ip.c	Mon Apr 17 22:48:11 2000
@@ -51,3 +51,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
diff -ur qmail-1.03/ip.h qmail-1.03v6/ip.h
--- qmail-1.03/ip.h	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/ip.h	Wed Jul  1 21:53:13 1998
@@ -2,10 +2,20 @@
 #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 ip_scan();
 extern unsigned int ip_scanbracket();
+
+#define HOSTNAMELEN	1025
 
 #endif
diff -ur qmail-1.03/ipalloc.h qmail-1.03v6/ipalloc.h
--- qmail-1.03/ipalloc.h	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/ipalloc.h	Wed Jul  1 21:53:14 1998
@@ -3,7 +3,16 @@
 
 #include "ip.h"
 
-struct ip_mx { struct ip_address ip; int pref; } ;
+struct ip_mx {
+  unsigned short af;
+  union {
+    struct ip_address ip;
+#ifdef INET6
+    struct ip6_address ip6;
+#endif
+    } addr;
+  int pref;
+};
 
 #include "gen_alloc.h"
 
diff -ur qmail-1.03/ipme.c qmail-1.03v6/ipme.c
--- qmail-1.03/ipme.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/ipme.c	Tue Oct 10 17:32:21 2000
@@ -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;
@@ -71,11 +87,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)
@@ -83,9 +110,18 @@
         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;
   }
diff -ur qmail-1.03/ipmeprint.c qmail-1.03v6/ipmeprint.c
--- qmail-1.03/ipmeprint.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/ipmeprint.c	Wed Jul  1 21:53:15 1998
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/socket.h>
 #include "subfd.h"
 #include "substdio.h"
 #include "ip.h"
@@ -16,7 +18,19 @@
   }
  for (j = 0;j < ipme.len;++j)
   {
-   substdio_put(subfdout,temp,ip_fmt(temp,&ipme.ix[j].ip));
+   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);
diff -ur qmail-1.03/qmail-remote.c qmail-1.03v6/qmail-remote.c
--- qmail-1.03/qmail-remote.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/qmail-remote.c	Wed Jul  1 21:53:16 1998
@@ -46,7 +46,7 @@
 
 saa reciplist = {0};
 
-struct ip_address partner;
+struct ip_mx partner;
 
 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 +89,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;
@@ -326,6 +334,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 +429,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 +448,18 @@
     perm_ambigmx();
  
   for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) {
-    if (tcpto(&ip.ix[i].ip)) continue;
+    if (tcpto(&ip.ix[i])) continue;
  
-    smtpfd = socket(AF_INET,SOCK_STREAM,0);
+    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;
+
+    if (timeoutconn46(smtpfd,&ip.ix[i],(unsigned int) port,timeoutconnect) == 0)
+	{
+      tcpto_err(&ip.ix[i],0);
+      partner = ip.ix[i];
       smtp(); /* does not return */
     }
-    tcpto_err(&ip.ix[i].ip,errno == error_timeout);
+    tcpto_err(&ip.ix[i],errno == error_timeout);
     close(smtpfd);
   }
   
diff -ur qmail-1.03/remoteinfo.c qmail-1.03v6/remoteinfo.c
--- qmail-1.03/remoteinfo.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/remoteinfo.c	Wed Jul  1 21:53:16 1998
@@ -23,33 +23,62 @@
   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;
diff -ur qmail-1.03/tcp-env.c qmail-1.03v6/tcp-env.c
--- qmail-1.03/tcp-env.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/tcp-env.c	Mon Oct  9 00:20:33 2000
@@ -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"
@@ -15,20 +16,50 @@
 #include "remoteinfo.h"
 #include "exit.h"
 #include "case.h"
+#include "hassalen.h"
 
 void die() { _exit(111); }
 
-struct sockaddr_in salocal;
+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};
 
-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
 
 void main(argc,argv)
 int argc;
@@ -39,6 +70,7 @@
  int opt;
  int flagremoteinfo;
  unsigned long timeout;
+ struct sockaddr_in *v4;
 
  sig_pipeignore();
 
@@ -65,59 +97,108 @@
 
    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();
-
-   switch(dns_ptr(&localname,&iplocal))
-    {
-     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();
-    }
+   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();
+   }
 
    dummy = sizeof(saremote);
    if (getpeername(0,(struct sockaddr *) &saremote,&dummy) == -1) die();
+   mappedtov4(&saremote);
 
-   remoteport = ntohs(saremote.sin_port);
-   temp[fmt_ulong(temp,remoteport)] = 0;
-   if (!env_put2("TCPREMOTEPORT",temp)) die();
-
-   byte_copy(&ipremote,4,&saremote.sin_addr);
-   temp[ip_fmt(temp,&ipremote)] = 0;
-   if (!env_put2("TCPREMOTEIP",temp)) die();
-
-   switch(dns_ptr(&remotename,&ipremote))
-    {
-     case DNS_MEM: die();
-     case DNS_SOFT:
-       if (!stralloc_copys(&remotename,"softdnserror")) die();
-     case 0:
-       if (!stralloc_0(&remotename)) die();
-       case_lowers(remotename.s);
-       if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
-       break;
-     default:
-       if (!env_unset("TCPREMOTEHOST")) die();
-    }
+   switch(saremote.sa.sa_family) {
+   case AF_INET:
+	remoteport = ntohs(saremote.sa4.sin_port);
+        temp[fmt_ulong(temp,remoteport)] = 0;
+        if (!env_put2("TCPREMOTEPORT",temp)) die();
+	temp[ip_fmt(temp, &saremote.sa4.sin_addr)] = 0;
+	if (!env_put2("TCPREMOTEIP",temp)) die();
+	switch(dns_ptr(&remotename,&saremote.sa4.sin_addr)) {
+	case DNS_MEM: die();
+	case DNS_SOFT:
+	  if (!stralloc_copys(&remotename,"softdnserror")) die();
+	case 0:
+	  if (!stralloc_0(&remotename)) die();
+	  case_lowers(remotename.s);
+	  if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
+	  break;
+	default:
+	  if (!env_unset("TCPREMOTEHOST")) die();
+	}
+	break;
+#ifdef INET6
+   case AF_INET6:
+	remoteport = ntohs(saremote.sa6.sin6_port);
+        temp[fmt_ulong(temp,remoteport)] = 0;
+	if (!env_put2("TCPREMOTEPORT",temp)) die();
+	temp[ip6_fmt(temp, &saremote.sa6.sin6_addr)] = 0;
+	if (!env_put2("TCPREMOTEIP",temp)) die();
+	switch(dns_ptr6(&remotename,&saremote.sa6.sin6_addr)) {
+	case DNS_MEM: die();
+	case DNS_SOFT:
+	  if (!stralloc_copys(&remotename,"softdnserror")) die();
+	case 0:
+	  if (!stralloc_0(&remotename)) die();
+	  case_lowers(remotename.s);
+	  if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
+	  break;
+	default:
+	  if (!env_unset("TCPREMOTEHOST")) die();
+	}
+	break;
+#endif
+   default:
+	die();
+   }
 
    if (!env_unset("TCPREMOTEINFO")) die();
+
    if (flagremoteinfo)
     {
      char *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();
     }
diff -ur qmail-1.03/tcpto.c qmail-1.03v6/tcpto.c
--- qmail-1.03/tcpto.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/tcpto.c	Wed Jul  1 21:53:17 1998
@@ -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*/
   }
 
diff -ur qmail-1.03/tcpto_clean.c qmail-1.03v6/tcpto_clean.c
--- qmail-1.03/tcpto_clean.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/tcpto_clean.c	Wed Jul  1 21:53:18 1998
@@ -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 */
 {
diff -ur qmail-1.03/timeoutconn.c qmail-1.03v6/timeoutconn.c
--- qmail-1.03/timeoutconn.c	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/timeoutconn.c	Wed Jul  1 21:53:18 1998
@@ -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
diff -ur qmail-1.03/timeoutconn.h qmail-1.03v6/timeoutconn.h
--- qmail-1.03/timeoutconn.h	Mon Jun 15 19:53:16 1998
+++ qmail-1.03v6/timeoutconn.h	Wed Jul  1 21:53:19 1998
@@ -2,5 +2,6 @@
 #define TIMEOUTCONN_H
 
 extern int timeoutconn();
+extern int timeoutconn6();
 
 #endif
