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 #include #include +#include #include #include 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 +#include #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 +#include #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 +#include #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 +#include #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 #include #include +#include #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 +#include #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