File ucspi-tcp-0.88-ipv6.patch of Package ucspi-tcp

(C) 2012 Peter Conrad <conrad@quisquis.de>

Licensed under the terms and conditions of the GNU General Public License
(version 2). See http://www.gnu.org/licenses/old-licenses/gpl-2.0 .

--- ucspi-tcp-0.88/dns_dfd.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_dfd.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,69 +0,0 @@
-#include "error.h"
-#include "alloc.h"
-#include "byte.h"
-#include "dns.h"
-
-int dns_domain_fromdot(char **out,char *buf,unsigned int n)
-{
-  char label[63];
-  unsigned int labellen = 0; /* <= sizeof label */
-  char name[255];
-  unsigned int namelen = 0; /* <= sizeof name */
-  char ch;
-  char *x;
-
-  errno = error_proto;
-
-  for (;;) {
-    if (!n) break;
-    ch = *buf++; --n;
-    if (ch == '.') {
-      if (labellen) {
-	if (namelen + labellen + 1 > sizeof name) return 0;
-	name[namelen++] = labellen;
-	byte_copy(name + namelen,labellen,label);
-	namelen += labellen;
-	labellen = 0;
-      }
-      continue;
-    }
-    if (ch == '\\') {
-      if (!n) break;
-      ch = *buf++; --n;
-      if ((ch >= '0') && (ch <= '7')) {
-	ch -= '0';
-	if (n && (*buf >= '0') && (*buf <= '7')) {
-	  ch <<= 3;
-	  ch += *buf - '0';
-	  ++buf; --n;
-	  if (n && (*buf >= '0') && (*buf <= '7')) {
-	    ch <<= 3;
-	    ch += *buf - '0';
-	    ++buf; --n;
-	  }
-	}
-      }
-    }
-    if (labellen >= sizeof label) return 0;
-    label[labellen++] = ch;
-  }
-
-  if (labellen) {
-    if (namelen + labellen + 1 > sizeof name) return 0;
-    name[namelen++] = labellen;
-    byte_copy(name + namelen,labellen,label);
-    namelen += labellen;
-    labellen = 0;
-  }
-
-  if (namelen + 1 > sizeof name) return 0;
-  name[namelen++] = 0;
-
-  x = alloc(namelen);
-  if (!x) return 0;
-  byte_copy(x,namelen,name);
-
-  if (*out) alloc_free(*out);
-  *out = x;
-  return 1;
-}
diff -rNU3 ucspi-tcp-0.88/dns_dtda.c ucspi-tcp-0.88.ipv6/dns_dtda.c
--- ucspi-tcp-0.88/dns_dtda.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_dtda.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,35 +0,0 @@
-#include "stralloc.h"
-#include "dns.h"
-
-int dns_domain_todot_cat(stralloc *out,char *d)
-{
-  char ch;
-  char ch2;
-  unsigned char ch3;
-  char buf[4];
-
-  if (!*d)
-    return stralloc_append(out,".");
-
-  for (;;) {
-    ch = *d++;
-    while (ch--) {
-      ch2 = *d++;
-      if ((ch2 >= 'A') && (ch2 <= 'Z'))
-	ch2 += 32;
-      if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_')) {
-        if (!stralloc_append(out,&ch2)) return 0;
-      }
-      else {
-	ch3 = ch2;
-	buf[3] = '0' + (ch3 & 7); ch3 >>= 3;
-	buf[2] = '0' + (ch3 & 7); ch3 >>= 3;
-	buf[1] = '0' + (ch3 & 7);
-	buf[0] = '\\';
-	if (!stralloc_catb(out,buf,4)) return 0;
-      }
-    }
-    if (!*d) return 1;
-    if (!stralloc_append(out,".")) return 0;
-  }
-}
diff -rNU3 ucspi-tcp-0.88/dns.h ucspi-tcp-0.88.ipv6/dns.h
--- ucspi-tcp-0.88/dns.h	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns.h	2012-02-17 14:06:29.000000000 +0100
@@ -2,83 +2,15 @@
 #define DNS_H
 
 #include "stralloc.h"
-#include "iopause.h"
-#include "taia.h"
 
 #define DNS_C_IN "\0\1"
-#define DNS_C_ANY "\0\377"
 
-#define DNS_T_A "\0\1"
-#define DNS_T_NS "\0\2"
-#define DNS_T_CNAME "\0\5"
-#define DNS_T_SOA "\0\6"
-#define DNS_T_PTR "\0\14"
-#define DNS_T_HINFO "\0\15"
-#define DNS_T_MX "\0\17"
 #define DNS_T_TXT "\0\20"
-#define DNS_T_RP "\0\21"
-#define DNS_T_SIG "\0\30"
-#define DNS_T_KEY "\0\31"
-#define DNS_T_AAAA "\0\34"
-#define DNS_T_AXFR "\0\374"
-#define DNS_T_ANY "\0\377"
-
-struct dns_transmit {
-  char *query; /* 0, or dynamically allocated */
-  unsigned int querylen;
-  char *packet; /* 0, or dynamically allocated */
-  unsigned int packetlen;
-  int s1; /* 0, or 1 + an open file descriptor */
-  int tcpstate;
-  unsigned int udploop;
-  unsigned int curserver;
-  struct taia deadline;
-  unsigned int pos;
-  char *servers;
-  char localip[4];
-  char qtype[2];
-} ;
 
-extern void dns_random_init(char *);
-extern unsigned int dns_random(unsigned int);
-
-extern void dns_sortip(char *,unsigned int);
-
-extern void dns_domain_free(char **);
 extern int dns_domain_copy(char **,char *);
-extern unsigned int dns_domain_length(char *);
-extern int dns_domain_equal(char *,char *);
-extern char *dns_domain_suffix(char *,char *);
-extern int dns_domain_fromdot(char **,char *,unsigned int);
-extern int dns_domain_todot_cat(stralloc *,char *);
-
 extern unsigned int dns_packet_copy(char *,unsigned int,unsigned int,char *,unsigned int);
-extern unsigned int dns_packet_getname(char *,unsigned int,unsigned int,char **);
 extern unsigned int dns_packet_skipname(char *,unsigned int,unsigned int);
-extern int dns_packet_nameequal(char *,unsigned int,unsigned int,char *,unsigned int,unsigned int);
 
-extern int dns_transmit_start(struct dns_transmit *,char *,int,char *,char *,char *);
-extern void dns_transmit_free(struct dns_transmit *);
-extern void dns_transmit_io(struct dns_transmit *,iopause_fd *,struct taia *);
-extern int dns_transmit_get(struct dns_transmit *,iopause_fd *,struct taia *);
-
-extern int dns_resolvconfip(char *);
-extern int dns_resolve(char *,char *);
-extern struct dns_transmit dns_resolve_tx;
-
-extern int dns_ip4_packet(stralloc *,char *,unsigned int);
-extern int dns_ip4(stralloc *,stralloc *);
-extern int dns_name_packet(stralloc *,char *,unsigned int);
-extern void dns_name4_domain(char *,char *);
-#define DNS_NAME4_DOMAIN 31
-extern int dns_name4(stralloc *,char *);
-extern int dns_txt_packet(stralloc *,char *,unsigned int);
 extern int dns_txt(stralloc *,stralloc *);
-extern int dns_mx_packet(stralloc *,char *,unsigned int);
-extern int dns_mx(stralloc *,stralloc *);
-
-extern int dns_resolvconfrewrite(stralloc *);
-extern int dns_ip4_qualify_rules(stralloc *,stralloc *,stralloc *,stralloc *);
-extern int dns_ip4_qualify(stralloc *,stralloc *,stralloc *);
 
 #endif
diff -rNU3 ucspi-tcp-0.88/dns_ip.c ucspi-tcp-0.88.ipv6/dns_ip.c
--- ucspi-tcp-0.88/dns_ip.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_ip.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,75 +0,0 @@
-#include "stralloc.h"
-#include "uint16.h"
-#include "byte.h"
-#include "dns.h"
-
-int dns_ip4_packet(stralloc *out,char *buf,unsigned int len)
-{
-  unsigned int pos;
-  char header[12];
-  uint16 numanswers;
-  uint16 datalen;
-
-  if (!stralloc_copys(out,"")) return -1;
-
-  pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
-  uint16_unpack_big(header + 6,&numanswers);
-  pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
-  pos += 4;
-
-  while (numanswers--) {
-    pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
-    pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
-    uint16_unpack_big(header + 8,&datalen);
-    if (byte_equal(header,2,DNS_T_A))
-      if (byte_equal(header + 2,2,DNS_C_IN))
-        if (datalen == 4) {
-	  if (!dns_packet_copy(buf,len,pos,header,4)) return -1;
-	  if (!stralloc_catb(out,header,4)) return -1;
-	}
-    pos += datalen;
-  }
-
-  dns_sortip(out->s,out->len);
-  return 0;
-}
-
-static char *q = 0;
-
-int dns_ip4(stralloc *out,stralloc *fqdn)
-{
-  unsigned int i;
-  char code;
-  char ch;
-
-  if (!stralloc_copys(out,"")) return -1;
-  code = 0;
-  for (i = 0;i <= fqdn->len;++i) {
-    if (i < fqdn->len)
-      ch = fqdn->s[i];
-    else
-      ch = '.';
-
-    if ((ch == '[') || (ch == ']')) continue;
-    if (ch == '.') {
-      if (!stralloc_append(out,&code)) return -1;
-      code = 0;
-      continue;
-    }
-    if ((ch >= '0') && (ch <= '9')) {
-      code *= 10;
-      code += ch - '0';
-      continue;
-    }
-
-    if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
-    if (dns_resolve(q,DNS_T_A) == -1) return -1;
-    if (dns_ip4_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
-    dns_transmit_free(&dns_resolve_tx);
-    dns_domain_free(&q);
-    return 0;
-  }
-
-  out->len &= ~3;
-  return 0;
-}
diff -rNU3 ucspi-tcp-0.88/dns_ipq.c ucspi-tcp-0.88.ipv6/dns_ipq.c
--- ucspi-tcp-0.88/dns_ipq.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_ipq.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,71 +0,0 @@
-#include "stralloc.h"
-#include "case.h"
-#include "byte.h"
-#include "str.h"
-#include "dns.h"
-
-static int doit(stralloc *work,char *rule)
-{
-  char ch;
-  unsigned int colon;
-  unsigned int prefixlen;
-
-  ch = *rule++;
-  if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1;
-  colon = str_chr(rule,':');
-  if (!rule[colon]) return 1;
-
-  if (work->len < colon) return 1;
-  prefixlen = work->len - colon;
-  if ((ch == '=') && prefixlen) return 1;
-  if (case_diffb(rule,colon,work->s + prefixlen)) return 1;
-  if (ch == '?') {
-    if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1;
-    if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1;
-    if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1;
-  }
-
-  work->len = prefixlen;
-  if (ch == '-') work->len = 0;
-  return stralloc_cats(work,rule + colon + 1);
-}
-
-int dns_ip4_qualify_rules(stralloc *out,stralloc *fqdn,stralloc *in,stralloc *rules)
-{
-  unsigned int i;
-  unsigned int j;
-  unsigned int plus;
-  unsigned int fqdnlen;
-
-  if (!stralloc_copy(fqdn,in)) return -1;
-
-  for (j = i = 0;j < rules->len;++j)
-    if (!rules->s[j]) {
-      if (!doit(fqdn,rules->s + i)) return -1;
-      i = j + 1;
-    }
-
-  fqdnlen = fqdn->len;
-  plus = byte_chr(fqdn->s,fqdnlen,'+');
-  if (plus >= fqdnlen)
-    return dns_ip4(out,fqdn);
-
-  i = plus + 1;
-  for (;;) {
-    j = byte_chr(fqdn->s + i,fqdnlen - i,'+');
-    byte_copy(fqdn->s + plus,j,fqdn->s + i);
-    fqdn->len = plus + j;
-    if (dns_ip4(out,fqdn) == -1) return -1;
-    if (out->len) return 0;
-    i += j;
-    if (i >= fqdnlen) return 0;
-    ++i;
-  }
-}
-
-int dns_ip4_qualify(stralloc *out,stralloc *fqdn,stralloc *in)
-{
-  static stralloc rules;
-  if (dns_resolvconfrewrite(&rules) == -1) return -1;
-  return dns_ip4_qualify_rules(out,fqdn,in,&rules);
-}
diff -rNU3 ucspi-tcp-0.88/dns_name.c ucspi-tcp-0.88.ipv6/dns_name.c
--- ucspi-tcp-0.88/dns_name.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_name.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,48 +0,0 @@
-#include "stralloc.h"
-#include "uint16.h"
-#include "byte.h"
-#include "dns.h"
-
-static char *q = 0;
-
-int dns_name_packet(stralloc *out,char *buf,unsigned int len)
-{
-  unsigned int pos;
-  char header[12];
-  uint16 numanswers;
-  uint16 datalen;
-
-  if (!stralloc_copys(out,"")) return -1;
-
-  pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
-  uint16_unpack_big(header + 6,&numanswers);
-  pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
-  pos += 4;
-
-  while (numanswers--) {
-    pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
-    pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
-    uint16_unpack_big(header + 8,&datalen);
-    if (byte_equal(header,2,DNS_T_PTR))
-      if (byte_equal(header + 2,2,DNS_C_IN)) {
-	if (!dns_packet_getname(buf,len,pos,&q)) return -1;
-	if (!dns_domain_todot_cat(out,q)) return -1;
-	return 0;
-      }
-    pos += datalen;
-  }
-
-  return 0;
-}
-
-int dns_name4(stralloc *out,char ip[4])
-{
-  char name[DNS_NAME4_DOMAIN];
-
-  dns_name4_domain(name,ip);
-  if (dns_resolve(name,DNS_T_PTR) == -1) return -1;
-  if (dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
-  dns_transmit_free(&dns_resolve_tx);
-  dns_domain_free(&q);
-  return 0;
-}
diff -rNU3 ucspi-tcp-0.88/dns_nd.c ucspi-tcp-0.88.ipv6/dns_nd.c
--- ucspi-tcp-0.88/dns_nd.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_nd.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,24 +0,0 @@
-#include "byte.h"
-#include "fmt.h"
-#include "dns.h"
-
-void dns_name4_domain(char name[DNS_NAME4_DOMAIN],char ip[4])
-{
-  unsigned int namelen;
-  unsigned int i;
-
-  namelen = 0;
-  i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[3]);
-  name[namelen++] = i;
-  namelen += i;
-  i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[2]);
-  name[namelen++] = i;
-  namelen += i;
-  i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[1]);
-  name[namelen++] = i;
-  namelen += i;
-  i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[0]);
-  name[namelen++] = i;
-  namelen += i;
-  byte_copy(name + namelen,14,"\7in-addr\4arpa\0");
-}
diff -rNU3 ucspi-tcp-0.88/dns_packet.c ucspi-tcp-0.88.ipv6/dns_packet.c
--- ucspi-tcp-0.88/dns_packet.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_packet.c	2012-02-17 14:00:31.000000000 +0100
@@ -2,6 +2,7 @@
 DNS should have used LZ77 instead of its own sophomoric compression algorithm.
 */
 
+#include "byte.h"
 #include "error.h"
 #include "dns.h"
 
diff -rNU3 ucspi-tcp-0.88/dns_random.c ucspi-tcp-0.88.ipv6/dns_random.c
--- ucspi-tcp-0.88/dns_random.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_random.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,65 +0,0 @@
-#include "dns.h"
-#include "taia.h"
-#include "uint32.h"
-#include <sys/types.h>
-#include <unistd.h>
-
-
-static uint32 seed[32];
-static uint32 in[12];
-static uint32 out[8];
-static int outleft = 0;
-
-#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
-#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
-
-static void surf(void)
-{
-  uint32 t[12]; uint32 x; uint32 sum = 0;
-  int r; int i; int loop;
-
-  for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
-  for (i = 0;i < 8;++i) out[i] = seed[24 + i];
-  x = t[11];
-  for (loop = 0;loop < 2;++loop) {
-    for (r = 0;r < 16;++r) {
-      sum += 0x9e3779b9;
-      MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
-      MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
-      MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
-    }
-    for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
-  }
-}
-
-void dns_random_init(char data[128])
-{
-  int i;
-  struct taia t;
-  char tpack[16];
-
-  for (i = 0;i < 32;++i)
-    uint32_unpack(data + 4 * i,seed + i);
-
-  taia_now(&t);
-  taia_pack(tpack,&t);
-  for (i = 0;i < 4;++i)
-    uint32_unpack(tpack + 4 * i,in + 4 + i);
-
-  in[8] = getpid();
-  in[9] = getppid();
-  /* more space in 10 and 11, but this is probably enough */
-}
-
-unsigned int dns_random(unsigned int n)
-{
-  if (!n) return 0;
-
-  if (!outleft) {
-    if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
-    surf();
-    outleft = 8;
-  }
-
-  return out[--outleft] % n;
-}
diff -rNU3 ucspi-tcp-0.88/dns_rcip.c ucspi-tcp-0.88.ipv6/dns_rcip.c
--- ucspi-tcp-0.88/dns_rcip.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_rcip.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,82 +0,0 @@
-#include "taia.h"
-#include "openreadclose.h"
-#include "byte.h"
-#include "ip4.h"
-#include "env.h"
-#include "dns.h"
-
-static stralloc data = {0};
-
-static int init(char ip[64])
-{
-  int i;
-  int j;
-  int iplen = 0;
-  char *x;
-
-  x = env_get("DNSCACHEIP");
-  if (x)
-    while (iplen <= 60)
-      if (*x == '.')
-	++x;
-      else {
-        i = ip4_scan(x,ip + iplen);
-	if (!i) break;
-	x += i;
-	iplen += 4;
-      }
-
-  if (!iplen) {
-    i = openreadclose("/etc/resolv.conf",&data,64);
-    if (i == -1) return -1;
-    if (i) {
-      if (!stralloc_append(&data,"\n")) return -1;
-      i = 0;
-      for (j = 0;j < data.len;++j)
-        if (data.s[j] == '\n') {
-          if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) {
-            i += 10;
-            while ((data.s[i] == ' ') || (data.s[i] == '\t'))
-              ++i;
-            if (iplen <= 60)
-              if (ip4_scan(data.s + i,ip + iplen))
-                iplen += 4;
-          }
-          i = j + 1;
-        }
-    }
-  }
-
-  if (!iplen) {
-    byte_copy(ip,4,"\177\0\0\1");
-    iplen = 4;
-  }
-  byte_zero(ip + iplen,64 - iplen);
-  return 0;
-}
-
-static int ok = 0;
-static unsigned int uses;
-static struct taia deadline;
-static char ip[64]; /* defined if ok */
-
-int dns_resolvconfip(char s[64])
-{
-  struct taia now;
-
-  taia_now(&now);
-  if (taia_less(&deadline,&now)) ok = 0;
-  if (!uses) ok = 0;
-
-  if (!ok) {
-    if (init(ip) == -1) return -1;
-    taia_uint(&deadline,600);
-    taia_add(&deadline,&now,&deadline);
-    uses = 10000;
-    ok = 1;
-  }
-
-  --uses;
-  byte_copy(s,64,ip);
-  return 0;
-}
diff -rNU3 ucspi-tcp-0.88/dns_rcrw.c ucspi-tcp-0.88.ipv6/dns_rcrw.c
--- ucspi-tcp-0.88/dns_rcrw.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_rcrw.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,131 +0,0 @@
-#include "taia.h"
-#include "env.h"
-#include "byte.h"
-#include "str.h"
-#include "openreadclose.h"
-#include "dns.h"
-#include <unistd.h>
-
-static stralloc data = {0};
-
-static int init(stralloc *rules)
-{
-  char host[256];
-  char *x;
-  int i;
-  int j;
-  int k;
-
-  if (!stralloc_copys(rules,"")) return -1;
-
-  x = env_get("DNSREWRITEFILE");
-  if (!x) x = "/etc/dnsrewrite";
-
-  i = openreadclose(x,&data,64);
-  if (i == -1) return -1;
-
-  if (i) {
-    if (!stralloc_append(&data,"\n")) return -1;
-    i = 0;
-    for (j = 0;j < data.len;++j)
-      if (data.s[j] == '\n') {
-        if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
-        while (rules->len) {
-          if (rules->s[rules->len - 1] != ' ')
-          if (rules->s[rules->len - 1] != '\t')
-          if (rules->s[rules->len - 1] != '\r')
-            break;
-          --rules->len;
-        }
-        if (!stralloc_0(rules)) return -1;
-        i = j + 1;
-      }
-    return 0;
-  }
-
-  x = env_get("LOCALDOMAIN");
-  if (x) {
-    if (!stralloc_copys(&data,x)) return -1;
-    if (!stralloc_append(&data," ")) return -1;
-    if (!stralloc_copys(rules,"?:")) return -1;
-    i = 0;
-    for (j = 0;j < data.len;++j)
-      if (data.s[j] == ' ') {
-        if (!stralloc_cats(rules,"+.")) return -1;
-        if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
-        i = j + 1;
-      }
-    if (!stralloc_0(rules)) return -1;
-    if (!stralloc_cats(rules,"*.:")) return -1;
-    if (!stralloc_0(rules)) return -1;
-    return 0;
-  }
-
-  i = openreadclose("/etc/resolv.conf",&data,64);
-  if (i == -1) return -1;
-
-  if (i) {
-    if (!stralloc_append(&data,"\n")) return -1;
-    i = 0;
-    for (j = 0;j < data.len;++j)
-      if (data.s[j] == '\n') {
-        if (byte_equal("search ",7,data.s + i) || byte_equal("search\t",7,data.s + i) || byte_equal("domain ",7,data.s + i) || byte_equal("domain\t",7,data.s + i)) {
-          if (!stralloc_copys(rules,"?:")) return -1;
-          i += 7;
-          while (i < j) {
-            k = byte_chr(data.s + i,j - i,' ');
-            k = byte_chr(data.s + i,k,'\t');
-            if (!k) { ++i; continue; }
-            if (!stralloc_cats(rules,"+.")) return -1;
-            if (!stralloc_catb(rules,data.s + i,k)) return -1;
-            i += k;
-          }
-          if (!stralloc_0(rules)) return -1;
-          if (!stralloc_cats(rules,"*.:")) return -1;
-          if (!stralloc_0(rules)) return -1;
-          return 0;
-        }
-        i = j + 1;
-      }
-  }
-
-  host[0] = 0;
-  if (gethostname(host,sizeof host) == -1) return -1;
-  host[(sizeof host) - 1] = 0;
-  i = str_chr(host,'.');
-  if (host[i]) {
-    if (!stralloc_copys(rules,"?:")) return -1;
-    if (!stralloc_cats(rules,host + i)) return -1;
-    if (!stralloc_0(rules)) return -1;
-  }
-  if (!stralloc_cats(rules,"*.:")) return -1;
-  if (!stralloc_0(rules)) return -1;
-
-  return 0;
-}
-
-static int ok = 0;
-static unsigned int uses;
-static struct taia deadline;
-static stralloc rules = {0}; /* defined if ok */
-
-int dns_resolvconfrewrite(stralloc *out)
-{
-  struct taia now;
-
-  taia_now(&now);
-  if (taia_less(&deadline,&now)) ok = 0;
-  if (!uses) ok = 0;
-
-  if (!ok) {
-    if (init(&rules) == -1) return -1;
-    taia_uint(&deadline,600);
-    taia_add(&deadline,&now,&deadline);
-    uses = 10000;
-    ok = 1;
-  }
-
-  --uses;
-  if (!stralloc_copy(out,&rules)) return -1;
-  return 0;
-}
diff -rNU3 ucspi-tcp-0.88/dns_resolve.c ucspi-tcp-0.88.ipv6/dns_resolve.c
--- ucspi-tcp-0.88/dns_resolve.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_resolve.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,29 +0,0 @@
-#include "iopause.h"
-#include "taia.h"
-#include "byte.h"
-#include "dns.h"
-
-struct dns_transmit dns_resolve_tx = {0};
-
-int dns_resolve(char *q,char qtype[2])
-{
-  struct taia stamp;
-  struct taia deadline;
-  char servers[64];
-  iopause_fd x[1];
-  int r;
-
-  if (dns_resolvconfip(servers) == -1) return -1;
-  if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,"\0\0\0\0") == -1) return -1;
-
-  for (;;) {
-    taia_now(&stamp);
-    taia_uint(&deadline,120);
-    taia_add(&deadline,&deadline,&stamp);
-    dns_transmit_io(&dns_resolve_tx,x,&deadline);
-    iopause(x,1,&deadline,&stamp);
-    r = dns_transmit_get(&dns_resolve_tx,x,&stamp);
-    if (r == -1) return -1;
-    if (r == 1) return 0;
-  }
-}
diff -rNU3 ucspi-tcp-0.88/dns_sortip.c ucspi-tcp-0.88.ipv6/dns_sortip.c
--- ucspi-tcp-0.88/dns_sortip.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_sortip.c	2012-02-17 12:55:08.000000000 +0100
@@ -1,20 +0,0 @@
-#include "byte.h"
-#include "dns.h"
-
-/* XXX: sort servers by configurable notion of closeness? */
-/* XXX: pay attention to competence of each server? */
-
-void dns_sortip(char *s,unsigned int n)
-{
-  unsigned int i;
-  char tmp[4];
-
-  n >>= 2;
-  while (n > 1) {
-    i = dns_random(n);
-    --n;
-    byte_copy(tmp,4,s + (i << 2));
-    byte_copy(s + (i << 2),4,s + (n << 2));
-    byte_copy(s + (n << 2),4,tmp);
-  }
-}
diff -rNU3 ucspi-tcp-0.88/dns_transmit.c ucspi-tcp-0.88.ipv6/dns_transmit.c
--- ucspi-tcp-0.88/dns_transmit.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_transmit.c	2012-02-17 12:55:13.000000000 +0100
@@ -1,366 +0,0 @@
-#include "socket.h"
-#include "alloc.h"
-#include "error.h"
-#include "byte.h"
-#include <unistd.h>
-#include "uint16.h"
-#include "dns.h"
-#include <sys/types.h>
-#include <sys/socket.h>
-
-static int serverwantstcp(char *buf,unsigned int len)
-{
-  char out[12];
-
-  if (!dns_packet_copy(buf,len,0,out,12)) return 1;
-  if (out[2] & 2) return 1;
-  return 0;
-}
-
-static int serverfailed(char *buf,unsigned int len)
-{
-  char out[12];
-  unsigned int rcode;
-
-  if (!dns_packet_copy(buf,len,0,out,12)) return 1;
-  rcode = out[3];
-  rcode &= 15;
-  if (rcode && (rcode != 3)) { errno = error_again; return 1; }
-  return 0;
-}
-
-static int irrelevant(struct dns_transmit *d,char *buf,unsigned int len)
-{
-  char out[12];
-  char *dn;
-  unsigned int pos;
-
-  pos = dns_packet_copy(buf,len,0,out,12); if (!pos) return 1;
-  if (byte_diff(out,2,d->query + 2)) return 1;
-  if (out[4] != 0) return 1;
-  if (out[5] != 1) return 1;
-
-  dn = 0;
-  pos = dns_packet_getname(buf,len,pos,&dn); if (!pos) return 1;
-  if (!dns_domain_equal(dn,d->query + 14)) { alloc_free(dn); return 1; }
-  alloc_free(dn);
-
-  pos = dns_packet_copy(buf,len,pos,out,4); if (!pos) return 1;
-  if (byte_diff(out,2,d->qtype)) return 1;
-  if (byte_diff(out + 2,2,DNS_C_IN)) return 1;
-
-  return 0;
-}
-
-static void packetfree(struct dns_transmit *d)
-{
-  if (!d->packet) return;
-  alloc_free(d->packet);
-  d->packet = 0;
-}
-
-static void queryfree(struct dns_transmit *d)
-{
-  if (!d->query) return;
-  alloc_free(d->query);
-  d->query = 0;
-}
-
-static void socketfree(struct dns_transmit *d)
-{
-  if (!d->s1) return;
-  close(d->s1 - 1);
-  d->s1 = 0;
-}
-
-void dns_transmit_free(struct dns_transmit *d)
-{
-  queryfree(d);
-  socketfree(d);
-  packetfree(d);
-}
-
-static int randombind(struct dns_transmit *d)
-{
-  int j;
-
-  for (j = 0;j < 10;++j)
-    if (socket_bind4(d->s1 - 1,d->localip,1025 + dns_random(64510)) == 0)
-      return 0;
-  if (socket_bind4(d->s1 - 1,d->localip,0) == 0)
-    return 0;
-  return -1;
-}
-
-static const int timeouts[4] = { 1, 3, 11, 45 };
-
-static int thisudp(struct dns_transmit *d)
-{
-  char *ip;
-
-  socketfree(d);
-
-  while (d->udploop < 4) {
-    for (;d->curserver < 16;++d->curserver) {
-      ip = d->servers + 4 * d->curserver;
-      if (byte_diff(ip,4,"\0\0\0\0")) {
-	d->query[2] = dns_random(256);
-	d->query[3] = dns_random(256);
-  
-        d->s1 = 1 + socket_udp();
-        if (!d->s1) { dns_transmit_free(d); return -1; }
-	if (randombind(d) == -1) { dns_transmit_free(d); return -1; }
-
-        if (socket_connect4(d->s1 - 1,ip,53) == 0)
-          if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) {
-            struct taia now;
-            taia_now(&now);
-            taia_uint(&d->deadline,timeouts[d->udploop]);
-            taia_add(&d->deadline,&d->deadline,&now);
-            d->tcpstate = 0;
-            return 0;
-          }
-  
-        socketfree(d);
-      }
-    }
-
-    ++d->udploop;
-    d->curserver = 0;
-  }
-
-  dns_transmit_free(d); return -1;
-}
-
-static int firstudp(struct dns_transmit *d)
-{
-  d->curserver = 0;
-  return thisudp(d);
-}
-
-static int nextudp(struct dns_transmit *d)
-{
-  ++d->curserver;
-  return thisudp(d);
-}
-
-static int thistcp(struct dns_transmit *d)
-{
-  struct taia now;
-  char *ip;
-
-  socketfree(d);
-  packetfree(d);
-
-  for (;d->curserver < 16;++d->curserver) {
-    ip = d->servers + 4 * d->curserver;
-    if (byte_diff(ip,4,"\0\0\0\0")) {
-      d->query[2] = dns_random(256);
-      d->query[3] = dns_random(256);
-
-      d->s1 = 1 + socket_tcp();
-      if (!d->s1) { dns_transmit_free(d); return -1; }
-      if (randombind(d) == -1) { dns_transmit_free(d); return -1; }
-  
-      taia_now(&now);
-      taia_uint(&d->deadline,10);
-      taia_add(&d->deadline,&d->deadline,&now);
-      if (socket_connect4(d->s1 - 1,ip,53) == 0) {
-        d->tcpstate = 2;
-        return 0;
-      }
-      if ((errno == error_inprogress) || (errno == error_wouldblock)) {
-        d->tcpstate = 1;
-        return 0;
-      }
-  
-      socketfree(d);
-    }
-  }
-
-  dns_transmit_free(d); return -1;
-}
-
-static int firsttcp(struct dns_transmit *d)
-{
-  d->curserver = 0;
-  return thistcp(d);
-}
-
-static int nexttcp(struct dns_transmit *d)
-{
-  ++d->curserver;
-  return thistcp(d);
-}
-
-int dns_transmit_start(struct dns_transmit *d,char servers[64],int flagrecursive,char *q,char qtype[2],char localip[4])
-{
-  unsigned int len;
-
-  dns_transmit_free(d);
-  errno = error_io;
-
-  len = dns_domain_length(q);
-  d->querylen = len + 18;
-  d->query = alloc(d->querylen);
-  if (!d->query) return -1;
-
-  uint16_pack_big(d->query,len + 16);
-  byte_copy(d->query + 2,12,flagrecursive ? "\0\0\1\0\0\1\0\0\0\0\0\0" : "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround");
-  byte_copy(d->query + 14,len,q);
-  byte_copy(d->query + 14 + len,2,qtype);
-  byte_copy(d->query + 16 + len,2,DNS_C_IN);
-
-  byte_copy(d->qtype,2,qtype);
-  d->servers = servers;
-  byte_copy(d->localip,4,localip);
-
-  d->udploop = flagrecursive ? 1 : 0;
-
-  if (len + 16 > 512) return firsttcp(d);
-  return firstudp(d);
-}
-
-void dns_transmit_io(struct dns_transmit *d,iopause_fd *x,struct taia *deadline)
-{
-  x->fd = d->s1 - 1;
-
-  switch(d->tcpstate) {
-    case 0: case 3: case 4: case 5:
-      x->events = IOPAUSE_READ;
-      break;
-    case 1: case 2:
-      x->events = IOPAUSE_WRITE;
-      break;
-  }
-
-  if (taia_less(&d->deadline,deadline))
-    *deadline = d->deadline;
-}
-
-int dns_transmit_get(struct dns_transmit *d,iopause_fd *x,struct taia *when)
-{
-  char udpbuf[513];
-  unsigned char ch;
-  int r;
-  int fd;
-
-  errno = error_io;
-  fd = d->s1 - 1;
-
-  if (!x->revents) {
-    if (taia_less(when,&d->deadline)) return 0;
-    errno = error_timeout;
-    if (d->tcpstate == 0) return nextudp(d);
-    return nexttcp(d);
-  }
-
-  if (d->tcpstate == 0) {
-/*
-have attempted to send UDP query to each server udploop times
-have sent query to curserver on UDP socket s
-*/
-    r = recv(fd,udpbuf,sizeof udpbuf,0);
-    if (r <= 0) {
-      if (d->udploop == 2) return 0;
-      return nextudp(d);
-    }
-    if (r + 1 > sizeof udpbuf) return 0;
-
-    if (irrelevant(d,udpbuf,r)) return 0;
-    if (serverwantstcp(udpbuf,r)) return firsttcp(d);
-    if (serverfailed(udpbuf,r)) {
-      if (d->udploop == 2) return 0;
-      return nextudp(d);
-    }
-    socketfree(d);
-
-    d->packetlen = r;
-    d->packet = alloc(d->packetlen);
-    if (!d->packet) { dns_transmit_free(d); return -1; }
-    byte_copy(d->packet,d->packetlen,udpbuf);
-    queryfree(d);
-    return 1;
-  }
-
-  if (d->tcpstate == 1) {
-/*
-have sent connection attempt to curserver on TCP socket s
-pos not defined
-*/
-    if (!socket_connected(fd)) return nexttcp(d);
-    d->pos = 0;
-    d->tcpstate = 2;
-    return 0;
-  }
-
-  if (d->tcpstate == 2) {
-/*
-have connection to curserver on TCP socket s
-have sent pos bytes of query
-*/
-    r = write(fd,d->query + d->pos,d->querylen - d->pos);
-    if (r <= 0) return nexttcp(d);
-    d->pos += r;
-    if (d->pos == d->querylen) {
-      struct taia now;
-      taia_now(&now);
-      taia_uint(&d->deadline,10);
-      taia_add(&d->deadline,&d->deadline,&now);
-      d->tcpstate = 3;
-    }
-    return 0;
-  }
-
-  if (d->tcpstate == 3) {
-/*
-have sent entire query to curserver on TCP socket s
-pos not defined
-*/
-    r = read(fd,&ch,1);
-    if (r <= 0) return nexttcp(d);
-    d->packetlen = ch;
-    d->tcpstate = 4;
-    return 0;
-  }
-
-  if (d->tcpstate == 4) {
-/*
-have sent entire query to curserver on TCP socket s
-pos not defined
-have received one byte of packet length into packetlen
-*/
-    r = read(fd,&ch,1);
-    if (r <= 0) return nexttcp(d);
-    d->packetlen <<= 8;
-    d->packetlen += ch;
-    d->tcpstate = 5;
-    d->pos = 0;
-    d->packet = alloc(d->packetlen);
-    if (!d->packet) { dns_transmit_free(d); return -1; }
-    return 0;
-  }
-
-  if (d->tcpstate == 5) {
-/*
-have sent entire query to curserver on TCP socket s
-have received entire packet length into packetlen
-packet is allocated
-have received pos bytes of packet
-*/
-    r = read(fd,d->packet + d->pos,d->packetlen - d->pos);
-    if (r <= 0) return nexttcp(d);
-    d->pos += r;
-    if (d->pos < d->packetlen) return 0;
-
-    socketfree(d);
-    if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d);
-    if (serverwantstcp(d->packet,d->packetlen)) return nexttcp(d);
-    if (serverfailed(d->packet,d->packetlen)) return nexttcp(d);
-
-    queryfree(d);
-    return 1;
-  }
-
-  return 0;
-}
diff -rNU3 ucspi-tcp-0.88/dns_txt.c ucspi-tcp-0.88.ipv6/dns_txt.c
--- ucspi-tcp-0.88/dns_txt.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/dns_txt.c	2012-02-17 14:42:23.000000000 +0100
@@ -1,8 +1,13 @@
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
 #include "stralloc.h"
 #include "uint16.h"
 #include "byte.h"
 #include "dns.h"
 
+#define MAX_ANSWER 1024
+
 int dns_txt_packet(stralloc *out,char *buf,unsigned int len)
 {
   unsigned int pos;
@@ -46,14 +51,25 @@
   return 0;
 }
 
-static char *q = 0;
-
 int dns_txt(stralloc *out,stralloc *fqdn)
 {
-  if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
-  if (dns_resolve(q,DNS_T_TXT) == -1) return -1;
-  if (dns_txt_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
-  dns_transmit_free(&dns_resolve_tx);
-  dns_domain_free(&q);
-  return 0;
+static int was_initialized = 0;
+static stralloc tmp = {0};
+int l;
+
+  if (!was_initialized) {
+    if (res_init())
+      return -1;
+    was_initialized = 1;
+  }
+
+  if (!stralloc_ready(&tmp, MAX_ANSWER))
+    return -1;
+  if (!stralloc_catb(fqdn, "", 1))
+    return -1;
+
+  l = res_query(fqdn->s, C_IN, T_TXT, tmp.s, tmp.a);
+  if (l < 0)
+    return -1;
+  return dns_txt_packet(out, tmp.s, l);
 }
diff -rNU3 ucspi-tcp-0.88/ip4.h ucspi-tcp-0.88.ipv6/ip4.h
--- ucspi-tcp-0.88/ip4.h	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/ip4.h	2012-02-17 13:47:34.000000000 +0100
@@ -1,9 +1,19 @@
 #ifndef IP4_H
 #define IP4_H
 
-extern unsigned int ip4_scan(char *,char *);
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
 extern unsigned int ip4_fmt(char *,char *);
 
 #define IP4_FMT 20
 
+typedef union {
+    struct sockaddr_in  sa4;
+    struct sockaddr_in6	sa6;
+} socket_address;
+
+extern const char V6_MAPPED_PREFIX[];
+
 #endif
diff -rNU3 ucspi-tcp-0.88/ip4_scan.c ucspi-tcp-0.88.ipv6/ip4_scan.c
--- ucspi-tcp-0.88/ip4_scan.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/ip4_scan.c	2012-02-17 13:47:38.000000000 +0100
@@ -1,19 +1,4 @@
 #include "scan.h"
 #include "ip4.h"
 
-unsigned int ip4_scan(char *s,char ip[4])
-{
-  unsigned int i;
-  unsigned int len;
-  unsigned long u;
- 
-  len = 0;
-  i = scan_ulong(s,&u); if (!i) return 0; ip[0] = u; s += i; len += i;
-  if (*s != '.') return 0; ++s; ++len;
-  i = scan_ulong(s,&u); if (!i) return 0; ip[1] = u; s += i; len += i;
-  if (*s != '.') return 0; ++s; ++len;
-  i = scan_ulong(s,&u); if (!i) return 0; ip[2] = u; s += i; len += i;
-  if (*s != '.') return 0; ++s; ++len;
-  i = scan_ulong(s,&u); if (!i) return 0; ip[3] = u; s += i; len += i;
-  return len;
-}
+const char V6_MAPPED_PREFIX[] = "\0\0\0\0\0\0\0\0\0\0\377\377";
diff -rNU3 ucspi-tcp-0.88/Makefile ucspi-tcp-0.88.ipv6/Makefile
--- ucspi-tcp-0.88/Makefile	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/Makefile	2012-02-17 14:08:30.000000000 +0100
@@ -179,87 +179,19 @@
 	./compile delcr.c
 
 dns.a: \
-makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o \
-dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
-dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o
-	./makelib dns.a dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o \
-	dns_ipq.o dns_name.o dns_nd.o dns_packet.o dns_random.o \
-	dns_rcip.o dns_rcrw.o dns_resolve.o dns_sortip.o \
-	dns_transmit.o dns_txt.o
-
-dns_dfd.o: \
-compile dns_dfd.c error.h alloc.h byte.h dns.h stralloc.h gen_alloc.h \
-iopause.h taia.h tai.h uint64.h taia.h
-	./compile dns_dfd.c
+makelib dns_domain.o dns_packet.o dns_txt.o
+	./makelib dns.a dns_domain.o dns_packet.o dns_txt.o
 
 dns_domain.o: \
 compile dns_domain.c error.h alloc.h case.h byte.h dns.h stralloc.h \
 gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
 	./compile dns_domain.c
 
-dns_dtda.o: \
-compile dns_dtda.c stralloc.h gen_alloc.h dns.h stralloc.h iopause.h \
-taia.h tai.h uint64.h taia.h
-	./compile dns_dtda.c
-
-dns_ip.o: \
-compile dns_ip.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
-stralloc.h iopause.h taia.h tai.h uint64.h taia.h
-	./compile dns_ip.c
-
-dns_ipq.o: \
-compile dns_ipq.c stralloc.h gen_alloc.h case.h byte.h str.h dns.h \
-stralloc.h iopause.h taia.h tai.h uint64.h taia.h
-	./compile dns_ipq.c
-
-dns_name.o: \
-compile dns_name.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
-stralloc.h iopause.h taia.h tai.h uint64.h taia.h
-	./compile dns_name.c
-
-dns_nd.o: \
-compile dns_nd.c byte.h fmt.h dns.h stralloc.h gen_alloc.h iopause.h \
-taia.h tai.h uint64.h taia.h
-	./compile dns_nd.c
-
 dns_packet.o: \
 compile dns_packet.c error.h dns.h stralloc.h gen_alloc.h iopause.h \
 taia.h tai.h uint64.h taia.h
 	./compile dns_packet.c
 
-dns_random.o: \
-compile dns_random.c dns.h stralloc.h gen_alloc.h iopause.h taia.h \
-tai.h uint64.h taia.h taia.h uint32.h
-	./compile dns_random.c
-
-dns_rcip.o: \
-compile dns_rcip.c taia.h tai.h uint64.h openreadclose.h stralloc.h \
-gen_alloc.h byte.h ip4.h env.h dns.h stralloc.h iopause.h taia.h \
-taia.h
-	./compile dns_rcip.c
-
-dns_rcrw.o: \
-compile dns_rcrw.c taia.h tai.h uint64.h env.h byte.h str.h \
-openreadclose.h stralloc.h gen_alloc.h dns.h stralloc.h iopause.h \
-taia.h taia.h
-	./compile dns_rcrw.c
-
-dns_resolve.o: \
-compile dns_resolve.c iopause.h taia.h tai.h uint64.h taia.h byte.h \
-dns.h stralloc.h gen_alloc.h iopause.h taia.h
-	./compile dns_resolve.c
-
-dns_sortip.o: \
-compile dns_sortip.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \
-taia.h tai.h uint64.h taia.h
-	./compile dns_sortip.c
-
-dns_transmit.o: \
-compile dns_transmit.c socket.h uint16.h alloc.h error.h byte.h \
-readwrite.h uint16.h dns.h stralloc.h gen_alloc.h iopause.h taia.h \
-tai.h uint64.h taia.h
-	./compile dns_transmit.c
-
 dns_txt.o: \
 compile dns_txt.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
 stralloc.h iopause.h taia.h tai.h uint64.h taia.h
@@ -472,7 +404,7 @@
 rblsmtpd: \
 load rblsmtpd.o commands.o dns.a time.a unix.a byte.a socket.lib
 	./load rblsmtpd commands.o dns.a time.a unix.a byte.a  \
-	`cat socket.lib`
+	`cat socket.lib` -lresolv
 
 rblsmtpd.o: \
 compile rblsmtpd.c byte.h str.h scan.h fmt.h env.h exit.h sig.h \
@@ -556,14 +488,6 @@
 	&& echo -lsocket -lnsl || exit 0 ) > socket.lib
 	rm -f trylsock.o trylsock
 
-socket_accept.o: \
-compile socket_accept.c byte.h socket.h uint16.h
-	./compile socket_accept.c
-
-socket_bind.o: \
-compile socket_bind.c byte.h socket.h uint16.h
-	./compile socket_bind.c
-
 socket_conn.o: \
 compile socket_conn.c readwrite.h byte.h socket.h uint16.h
 	./compile socket_conn.c
@@ -576,26 +500,10 @@
 compile socket_listen.c socket.h uint16.h
 	./compile socket_listen.c
 
-socket_local.o: \
-compile socket_local.c byte.h socket.h uint16.h
-	./compile socket_local.c
-
 socket_opts.o: \
 compile socket_opts.c socket.h uint16.h
 	./compile socket_opts.c
 
-socket_remote.o: \
-compile socket_remote.c byte.h socket.h uint16.h
-	./compile socket_remote.c
-
-socket_tcp.o: \
-compile socket_tcp.c ndelay.h socket.h uint16.h
-	./compile socket_tcp.c
-
-socket_udp.o: \
-compile socket_udp.c ndelay.h socket.h uint16.h
-	./compile socket_udp.c
-
 str_chr.o: \
 compile str_chr.c str.h
 	./compile str_chr.c
@@ -710,9 +618,9 @@
 	chmod 755 tcpcat
 
 tcpclient: \
-load tcpclient.o remoteinfo.o timeoutconn.o dns.a time.a unix.a \
+load tcpclient.o remoteinfo.o timeoutconn.o time.a unix.a \
 byte.a socket.lib
-	./load tcpclient remoteinfo.o timeoutconn.o dns.a time.a \
+	./load tcpclient remoteinfo.o timeoutconn.o time.a \
 	unix.a byte.a  `cat socket.lib`
 
 tcpclient.o: \
@@ -742,10 +650,10 @@
 	./compile tcprulescheck.c
 
 tcpserver: \
-load tcpserver.o rules.o remoteinfo.o timeoutconn.o cdb.a dns.a \
+load tcpserver.o rules.o remoteinfo.o timeoutconn.o cdb.a \
 time.a unix.a byte.a socket.lib
 	./load tcpserver rules.o remoteinfo.o timeoutconn.o cdb.a \
-	dns.a time.a unix.a byte.a  `cat socket.lib`
+	time.a unix.a byte.a  `cat socket.lib`
 
 tcpserver.o: \
 compile tcpserver.c uint16.h str.h byte.h fmt.h scan.h ip4.h fd.h \
@@ -801,9 +709,9 @@
 fd_copy.o fd_move.o getln.o getln2.o ndelay_off.o ndelay_on.o \
 open_read.o open_trunc.o open_write.o openreadclose.o pathexec_env.o \
 pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o sig.o \
-sig_block.o sig_catch.o sig_pause.o socket_accept.o socket_bind.o \
-socket_conn.o socket_delay.o socket_listen.o socket_local.o \
-socket_opts.o socket_remote.o socket_tcp.o socket_udp.o \
+sig_block.o sig_catch.o sig_pause.o \
+socket_conn.o socket_delay.o socket_listen.o \
+socket_opts.o \
 stralloc_cat.o stralloc_catb.o stralloc_cats.o stralloc_copy.o \
 stralloc_eady.o stralloc_opyb.o stralloc_opys.o stralloc_pend.o \
 strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o wait_pid.o
@@ -813,10 +721,10 @@
 	getln.o getln2.o ndelay_off.o ndelay_on.o open_read.o \
 	open_trunc.o open_write.o openreadclose.o pathexec_env.o \
 	pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o \
-	sig.o sig_block.o sig_catch.o sig_pause.o socket_accept.o \
-	socket_bind.o socket_conn.o socket_delay.o socket_listen.o \
-	socket_local.o socket_opts.o socket_remote.o socket_tcp.o \
-	socket_udp.o stralloc_cat.o stralloc_catb.o stralloc_cats.o \
+	sig.o sig_block.o sig_catch.o sig_pause.o \
+	socket_conn.o socket_delay.o socket_listen.o \
+	socket_opts.o \
+	stralloc_cat.o stralloc_catb.o stralloc_cats.o \
 	stralloc_copy.o stralloc_eady.o stralloc_opyb.o \
 	stralloc_opys.o stralloc_pend.o strerr_die.o strerr_sys.o \
 	subgetopt.o wait_nohang.o wait_pid.o
diff -rNU3 ucspi-tcp-0.88/rblsmtpd.c ucspi-tcp-0.88.ipv6/rblsmtpd.c
--- ucspi-tcp-0.88/rblsmtpd.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/rblsmtpd.c	2012-02-17 21:33:50.000000000 +0100
@@ -13,9 +13,14 @@
 #include "commands.h"
 #include "pathexec.h"
 #include "dns.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 
 #define FATAL "rblsmtpd: fatal: "
 
+static char *HEX = "0123456789abcdef";
+
 void nomem(void)
 {
   strerr_die2x(111,FATAL,"out of memory");
@@ -31,7 +36,7 @@
 void ip_init(void)
 {
   unsigned int i;
-  unsigned int j;
+  unsigned int j, haveDot=0, haveColon=0;
 
   ip_env = env_get("TCPREMOTEIP");
   if (!ip_env) ip_env = "";
@@ -40,12 +45,33 @@
 
   i = str_len(ip_env);
   while (i) {
-    for (j = i;j > 0;--j) if (ip_env[j - 1] == '.') break;
+    for (j = i;j > 0;--j) {
+      if (ip_env[j - 1] == '.') { haveDot++; break; }
+      if (ip_env[j - 1] == ':') { haveColon = 1; break; }
+    }
     if (!stralloc_catb(&ip_reverse,ip_env + j,i - j)) nomem();
     if (!stralloc_cats(&ip_reverse,".")) nomem();
-    if (!j) break;
+    if (!j || haveColon) break;
     i = j - 1;
   }
+  if (!haveDot && ip_reverse.len) { /* assume IPv6 */
+    struct addrinfo *res, hints={0};
+    hints.ai_family = AF_INET6;
+    hints.ai_flags = AI_NUMERICHOST;
+    if (!getaddrinfo(ip_env, NULL, &hints, &res) && res != NULL) {
+      if (res->ai_family == AF_INET6) {
+	if (!stralloc_copys(&ip_reverse,"")) nomem();
+	for (j = 16; j > 0; j--) {
+	  unsigned int tmp = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr[j-1];
+	  if (!stralloc_catb(&ip_reverse, HEX + (tmp & 0xf), 1)) nomem();
+	  if (!stralloc_catb(&ip_reverse, ".", 1)) nomem();
+	  if (!stralloc_catb(&ip_reverse, HEX + ((tmp >> 4) & 0xf), 1)) nomem();
+	  if (!stralloc_catb(&ip_reverse, ".", 1)) nomem();
+	}
+      }
+      freeaddrinfo(res);
+    }
+  }
 }
 
 unsigned long timeout = 60;
@@ -61,6 +87,7 @@
 
 void rbl(char *base)
 {
+  struct addrinfo *res;
   int i;
   char *altreply = 0;
   if (decision) return;
@@ -72,7 +99,8 @@
   }
   if (!stralloc_cats(&tmp,base)) nomem();
   if (altreply) {
-    if (dns_ip4(&text,&tmp) == -1) {
+    if (!stralloc_catb(&tmp, "", 1)) nomem();
+    if (getaddrinfo(tmp.s, NULL, NULL, &res)) {
       flagmustnotbounce = 1;
       if (flagfailclosed) {
         if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem();
@@ -80,7 +108,8 @@
       }
       return;
     }
-    if (text.len) {
+    if (res) {
+      freeaddrinfo(res);
       if(!stralloc_copys(&text, "")) nomem();
       while(*altreply) {
         char *x;
@@ -119,17 +148,21 @@
 
 void antirbl(char *base)
 {
+  struct addrinfo *res;
   if (decision) return;
   if (!stralloc_copy(&tmp,&ip_reverse)) nomem();
   if (!stralloc_cats(&tmp,base)) nomem();
-  if (dns_ip4(&text,&tmp) == -1) {
+  if (!stralloc_catb(&tmp, "", 1)) nomem();
+  if (getaddrinfo(tmp.s, NULL, NULL, &res)) {
     flagmustnotbounce = 1;
     if (!flagfailclosed)
       decision = 1;
     return;
   }
-  if (text.len)
+  if (res) {
+    freeaddrinfo(res);
     decision = 1;
+  }
 }
 
 char strnum[FMT_ULONG];
@@ -139,18 +172,18 @@
 char outspace[1]; buffer out = BUFFER_INIT(write,1,outspace,sizeof outspace);
 
 void reject() { buffer_putflush(&out,message.s,message.len); }
-void accept() { buffer_putsflush(&out,"250 rblsmtpd.local\r\n"); }
+void smtp_accept() { buffer_putsflush(&out,"250 rblsmtpd.local\r\n"); }
 void greet()  { buffer_putsflush(&out,"220 rblsmtpd.local\r\n"); }
 void quit()   { buffer_putsflush(&out,"221 rblsmtpd.local\r\n"); _exit(0); }
 void drop()   { _exit(0); }
 
 struct commands smtpcommands[] = {
   { "quit", quit, 0 }
-, { "helo", accept, 0 }
-, { "ehlo", accept, 0 }
-, { "mail", accept, 0 }
-, { "rset", accept, 0 }
-, { "noop", accept, 0 }
+, { "helo", smtp_accept, 0 }
+, { "ehlo", smtp_accept, 0 }
+, { "mail", smtp_accept, 0 }
+, { "rset", smtp_accept, 0 }
+, { "noop", smtp_accept, 0 }
 , { 0, reject, 0 }
 } ;
 
diff -rNU3 ucspi-tcp-0.88/remoteinfo.c ucspi-tcp-0.88.ipv6/remoteinfo.c
--- ucspi-tcp-0.88/remoteinfo.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/remoteinfo.c	2012-02-06 16:53:41.000000000 +0100
@@ -1,3 +1,4 @@
+#include "byte.h"
 #include "fmt.h"
 #include "buffer.h"
 #include "socket.h"
@@ -6,6 +7,7 @@
 #include "timeoutconn.h"
 #include "remoteinfo.h"
 #include <unistd.h>
+#include "ip4.h"
 
 static struct taia now;
 static struct taia deadline;
@@ -46,21 +48,34 @@
   return read(fd,buf,len);
 }
 
-static int doit(stralloc *out,int s,char ipremote[4],uint16 portremote,char iplocal[4],uint16 portlocal,unsigned int timeout)
+static int doit(stralloc *out,int s,socket_address *remote,socket_address *local,unsigned int timeout)
 {
   buffer b;
   char bspace[128];
   char strnum[FMT_ULONG];
   int numcolons;
   char ch;
+  socket_address iplocal, ipremote;
 
-  if (socket_bind4(s,iplocal,0) == -1) return -1;
-  if (timeoutconn(s,ipremote,113,timeout) == -1) return -1;
+  byte_copy(&iplocal,sizeof(iplocal),local);
+  if (iplocal.sa6.sin6_family == AF_INET6) {
+    iplocal.sa6.sin6_port = 0;
+  } else {
+    iplocal.sa4.sin_port = 0;
+  }
+  if (bind(s,(struct sockaddr *) &iplocal.sa4,iplocal.sa4.sin_family == AF_INET ? sizeof(iplocal.sa4) : sizeof(iplocal.sa6)) == -1) return -1;
+  byte_copy(&ipremote,sizeof(ipremote),remote);
+  if (ipremote.sa6.sin6_family == AF_INET6) {
+    ipremote.sa6.sin6_port = htons(113);
+  } else {
+    ipremote.sa4.sin_port = htons(113);
+  }
+  if (timeoutconn(s,&ipremote,timeout) == -1) return -1;
 
   buffer_init(&b,mywrite,s,bspace,sizeof bspace);
-  buffer_put(&b,strnum,fmt_ulong(strnum,portremote));
+  buffer_put(&b,strnum,fmt_ulong(strnum,ntohs(remote->sa4.sin_family == AF_INET ? remote->sa4.sin_port : remote->sa6.sin6_port)));
   buffer_put(&b," , ",3);
-  buffer_put(&b,strnum,fmt_ulong(strnum,portlocal));
+  buffer_put(&b,strnum,fmt_ulong(strnum,ntohs(local->sa4.sin_family == AF_INET ? local->sa4.sin_port : local->sa6.sin6_port)));
   buffer_put(&b,"\r\n",2);
   if (buffer_flush(&b) == -1) return -1;
 
@@ -80,7 +95,7 @@
   }
 }
 
-int remoteinfo(stralloc *out,char ipremote[4],uint16 portremote,char iplocal[4],uint16 portlocal,unsigned int timeout)
+int remoteinfo(stralloc *out,socket_address *remote,socket_address *local,unsigned int timeout)
 {
   int s;
   int r;
@@ -91,9 +106,9 @@
   taia_uint(&deadline,timeout);
   taia_add(&deadline,&now,&deadline);
 
-  s = socket_tcp();
+  s = socket(remote->sa4.sin_family, SOCK_STREAM, 0);
   if (s == -1) return -1;
-  r = doit(out,s,ipremote,portremote,iplocal,portlocal,timeout);
+  r = doit(out,s,remote,local,timeout);
   close(s);
   return r;
 }
diff -rNU3 ucspi-tcp-0.88/remoteinfo.h ucspi-tcp-0.88.ipv6/remoteinfo.h
--- ucspi-tcp-0.88/remoteinfo.h	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/remoteinfo.h	2012-02-06 11:49:08.000000000 +0100
@@ -3,7 +3,8 @@
 
 #include "stralloc.h"
 #include "uint16.h"
+#include "ip4.h"
 
-extern int remoteinfo(stralloc *,char *,uint16,char *,uint16,unsigned int);
+extern int remoteinfo(stralloc *,socket_address *,socket_address *,unsigned int);
 
 #endif
diff -rNU3 ucspi-tcp-0.88/rts.exp ucspi-tcp-0.88.ipv6/rts.exp
--- ucspi-tcp-0.88/rts.exp	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/rts.exp	2012-02-18 22:02:53.000000000 +0100
@@ -1,8 +1,8 @@
 --- tcpclient prints usage message without enough arguments
-tcpclient: usage: tcpclient [ -hHrRdDqQv ] [ -i localip ] [ -p localport ] [ -T timeoutconn ] [ -l localname ] [ -t timeoutinfo ] host port program
+tcpclient: usage: tcpclient [ -hHrRdDqQv46 ] [ -i localip ] [ -p localport ] [ -T timeoutconn ] [ -l localname ] [ -t timeoutinfo ] host port program
 100
 --- tcpclient prints error message with unknown port name
-tcpclient: fatal: unable to figure out port number for nonexistentport
+tcpclient: fatal: no IP address for 127.0.0.1/nonexistentport
 111
 --- tcpclient prints error message when connection fails
 tcpclient: unable to connect to 127.0.0.1 port 16: connection refused
@@ -18,14 +18,20 @@
 --- tcpclient understands bracketed IP address
 tcpclient: unable to connect to 127.0.0.1 port 16: connection refused
 111
+--- tcpclient understands unbracketed IP6 address
+tcpclient: unable to connect to ::1 port 16: connection refused
+111
+--- tcpclient understands bracketed IP6 address
+tcpclient: unable to connect to ::1 port 16: connection refused
+111
 --- tcpclient prints error message with unknown host name
-tcpclient: fatal: no IP address for nonexistent.local.
+tcpclient: fatal: no IP address for nonexistent.local./016
 111
 --- tcpclient prints error message with unresolvable host name
-tcpclient: fatal: temporarily unable to figure out IP address for thislabelistoolongbecausednshasalimitof63charactersinasinglelabel.: protocol error
+tcpclient: fatal: no IP address for thislabelistoolongbecausednshasalimitof63charactersinasinglelabel./016
 111
 --- tcpserver prints usage message without enough arguments
-tcpserver: usage: tcpserver [ -1UXpPhHrRoOdDqQv ] [ -c limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] [ -u uid ] [ -b backlog ] [ -l localname ] [ -t timeout ] host port program
+tcpserver: usage: tcpserver [ -1UXpPhHrRoOdDqQv46 ] [ -c limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] [ -u uid ] [ -b backlog ] [ -l localname ] [ -t timeout ] host port program
 100
 --- tcpserver -u 1 attempts to set uid to 1
 tcpserver: fatal: unable to set uid: permission denied
@@ -40,13 +46,13 @@
 tcpserver: fatal: unable to set gid: permission denied
 111
 --- tcpserver prints error message with unknown port name
-tcpserver: fatal: unable to figure out port number for nonexistentport
+tcpserver: fatal: no IP address for ''/nonexistentport
 111
 --- tcpserver prints error message with unknown host name
-tcpserver: fatal: no IP address for nonexistent.local.
+tcpserver: fatal: no IP address for nonexistent.local./016
 111
 --- tcpserver prints error message with unresolvable host name
-tcpserver: fatal: temporarily unable to figure out IP address for thislabelistoolongbecausednshasalimitof63charactersinasinglelabel.: protocol error
+tcpserver: fatal: no IP address for thislabelistoolongbecausednshasalimitof63charactersinasinglelabel./016
 111
 --- tcpserver prints error message with non-local host name
 tcpserver: fatal: unable to bind: address not available
@@ -61,6 +67,16 @@
 TCPREMOTEPORT=50017
 TCPREMOTEINFO=unset
 0
+--- tcpserver sets basic environment variables
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=::1
+TCPLOCALPORT=50015
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=::1
+TCPREMOTEPORT=50017
+TCPREMOTEINFO=unset
+0
 --- tcpclient recognizes -D, -i, -r, -h, -t
 bannerPROTO=TCP
 TCPLOCALHOST=Local
@@ -71,6 +87,16 @@
 TCPREMOTEPORT=50018
 TCPREMOTEINFO=unset
 0
+--- tcpclient recognizes -D, -i, -r, -h, -t
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=::1
+TCPLOCALPORT=50015
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=::1
+TCPREMOTEPORT=50018
+TCPREMOTEINFO=unset
+0
 --- tcpclient sets basic environment variables
 PROTO=TCP
 TCPLOCALHOST=Local
@@ -81,6 +107,16 @@
 TCPREMOTEPORT=50016
 TCPREMOTEINFO=unset
 0
+--- tcpclient sets basic environment variables
+PROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=::1
+TCPLOCALPORT=50019
+TCPREMOTEHOST=unset
+TCPREMOTEIP=::1
+TCPREMOTEPORT=50015
+TCPREMOTEINFO=unset
+0
 --- tcpclient looks up host names properly
 PROTO=TCP
 TCPLOCALHOST=localhost
@@ -91,10 +127,36 @@
 TCPREMOTEPORT=50016
 TCPREMOTEINFO=unset
 0
+--- tcpclient looks up host names properly
+PROTO=TCP
+TCPLOCALHOST=localhost
+TCPLOCALIP=::1
+TCPLOCALPORT=50020
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=::1
+TCPREMOTEPORT=50015
+TCPREMOTEINFO=unset
+0
 --- tcpclient -v works
 tcpclient: connected to 127.0.0.1 port 50016
 ok
 0
+--- tcpclient -v works
+tcpclient: connected to ::1 port 50015
+ok
+0
+--- tcpclient -4 works
+tcpclient: unable to connect to 127.0.0.1 port 50015: connection refused
+111
+tcpclient: connected to 127.0.0.1 port 50016
+ok
+0
+--- tcpclient -6 works
+tcpclient: connected to ::1 port 50015
+ok
+0
+tcpclient: unable to connect to ::1 port 50016: connection refused
+111
 --- tcpserver prints error message with used port
 tcpserver: fatal: unable to bind: address already used
 111
@@ -107,6 +169,15 @@
 TCPREMOTEIP=127.0.0.1
 TCPREMOTEINFO=unset
 0
+--- tcpcat works
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=::1
+TCPLOCALPORT=50015
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=::1
+TCPREMOTEINFO=unset
+0
 --- mconnect works
 bannerPROTO=TCP
 TCPLOCALHOST=Local
@@ -116,6 +187,15 @@
 TCPREMOTEIP=127.0.0.1
 TCPREMOTEINFO=unset
 0
+--- mconnect works
+bannerPROTO=TCP
+TCPLOCALHOST=Local
+TCPLOCALIP=::1
+TCPLOCALPORT=50015
+TCPREMOTEHOST=localhost
+TCPREMOTEIP=::1
+TCPREMOTEINFO=unset
+0
 --- tcprules prints usage message without enough arguments
 tcprules: usage: tcprules rules.cdb rules.tmp
 100
@@ -208,6 +288,24 @@
 deny connection
 rule =.abuser.edu:
 deny connection
+--- tcprules handles IPv6
+0
+rule 20014ba0fff100bfc0011337d00ddead:
+set environment variable which=full
+allow connection
+rule 20014ba0fff100bfc001:
+set environment variable which=part
+allow connection
+rule 00000000000000000000000000000001:
+set environment variable which=full
+allow connection
+rule 0:
+deny connection
+rule 0:
+deny connection
+rule :
+set environment variable which=anybody
+allow connection
 --- tcprulescheck searches for rules in the proper order
 0
 rule xyz@86.75.30.9:
@@ -354,12 +452,24 @@
 --- rblsmtpd does not find 127.0.0.1 on the RBL
 ok
 0
+--- rblsmtpd does not find ::ffff:127.0.0.1 on the RBL
+ok
+0
+--- rblsmtpd does not find ::1 on the RBL
+ok
+0
 --- rblsmtpd finds 127.0.0.2 on the RBL
 rblsmtpd: 127.0.0.2 pid x: 451 http://www.spamhaus.org/SBL/sbl.lasso?query=SBL233http://www.spamhaus.org/query/bl?ip=127.0.0.2
 220 rblsmtpd.local^M
 451 http://www.spamhaus.org/SBL/sbl.lasso?query=SBL233http://www.spamhaus.org/query/bl?ip=127.0.0.2^M
 221 rblsmtpd.local^M
 0
+--- rblsmtpd finds ::ffff:127.0.0.2 on the RBL
+rblsmtpd: ::ffff:127.0.0.2 pid x: 451 http://www.spamhaus.org/SBL/sbl.lasso?query=SBL233http://www.spamhaus.org/query/bl?ip=127.0.0.2
+220 rblsmtpd.local^M
+451 http://www.spamhaus.org/SBL/sbl.lasso?query=SBL233http://www.spamhaus.org/query/bl?ip=127.0.0.2^M
+221 rblsmtpd.local^M
+0
 --- rblsmtpd -b uses a permanent error code
 rblsmtpd: 127.0.0.2 pid x: 553 http://www.spamhaus.org/SBL/sbl.lasso?query=SBL233http://www.spamhaus.org/query/bl?ip=127.0.0.2
 220 rblsmtpd.local^M
@@ -433,3 +543,51 @@
 tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
 tcpserver: end x status 0
 tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from 127.0.0.1
+tcpserver: ok x Local:127.0.0.1:50016 localhost:127.0.0.1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+--- tcpserver -1v prints proper messages
+50015
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
+tcpserver: status: 1/2
+tcpserver: pid x from ::1
+tcpserver: ok x Local:??1:50015 localhost:??1::x
+tcpserver: end x status 0
+tcpserver: status: 0/2
diff -rNU3 ucspi-tcp-0.88/rts.tests ucspi-tcp-0.88.ipv6/rts.tests
--- ucspi-tcp-0.88/rts.tests	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/rts.tests	2012-02-18 21:56:13.000000000 +0100
@@ -37,6 +37,16 @@
 
 supervise 50016 >log 2>&1 &
 
+mkdir 50015
+echo '#!/bin/sh
+exec tcpserver \
+-c 2 -Bbanner -vo -D -1 -Xx rules.cdb -Rt5 -hp -l Local -b 2 \
+::1 50015 ../print
+' > 50015/run
+chmod 755 50015/run
+
+supervise 50015 >log2 2>&1 &
+
 echo '--- tcpclient prints usage message without enough arguments'
 tcpclient 0 0; echo $?
 
@@ -58,6 +68,12 @@
 echo '--- tcpclient understands bracketed IP address'
 tcpclient '[127.000.000.001]' 016 echo wrong; echo $?
 
+echo '--- tcpclient understands unbracketed IP6 address'
+tcpclient '::1' 016 echo wrong; echo $?
+
+echo '--- tcpclient understands bracketed IP6 address'
+tcpclient '[::1]' 016 echo wrong; echo $?
+
 echo '--- tcpclient prints error message with unknown host name'
 tcpclient nonexistent.local. 016 echo wrong; echo $?
 
@@ -96,38 +112,87 @@
 echo $?
 sleep 1
 
+echo '--- tcpserver sets basic environment variables' 
+tcpclient -p 50017 -R -H -T 10 -l Local ::1 50015 sh -c 'cat <&6'
+echo $?
+sleep 1
+
 echo '--- tcpclient recognizes -D, -i, -r, -h, -t'
 tcpclient -Di 127.0.0.1 -p 50018 -hrt1 -l Local \
 127.0.0.1 50016 sh -c 'cat <&6'
 echo $?
 sleep 1
 
+echo '--- tcpclient recognizes -D, -i, -r, -h, -t'
+tcpclient -Di ::1 -p 50018 -hrt1 -l Local \
+::1 50015 sh -c 'cat <&6'
+echo $?
+sleep 1
+
 echo '--- tcpclient sets basic environment variables' 
 tcpclient -p 50019 -R -H -l Local 0 50016 ./print
 echo $?
 sleep 1
 
+echo '--- tcpclient sets basic environment variables' 
+tcpclient -p 50019 -R -H -l Local ::1 50015 ./print
+echo $?
+sleep 1
+
 echo '--- tcpclient looks up host names properly'
 tcpclient -p 50020 -R 0 50016 ./print
 echo $?
 sleep 1
 
+echo '--- tcpclient looks up host names properly'
+tcpclient -p 50020 -R ::1 50015 ./print
+echo $?
+sleep 1
+
 echo '--- tcpclient -v works' 
 tcpclient -v -R -H -l Local 0 50016 sh -c 'echo ok; sleep 1'
 echo $?
 sleep 1
 
+echo '--- tcpclient -v works' 
+tcpclient -v -R -H -l Local ::1 50015 sh -c 'echo ok; sleep 1'
+echo $?
+sleep 1
+
+echo '--- tcpclient -4 works' 
+tcpclient -v -R -H -l Local -4 localhost 50015 sh -c 'echo wrong; sleep 1'
+echo $?
+tcpclient -v -R -H -l Local -4 localhost 50016 sh -c 'echo ok; sleep 1'
+echo $?
+sleep 1
+
+echo '--- tcpclient -6 works' 
+tcpclient -v -R -H -l Local -6 localhost 50015 sh -c 'echo ok; sleep 1'
+echo $?
+tcpclient -v -R -H -l Local -6 localhost 50016 sh -c 'echo wrong; sleep 1'
+echo $?
+sleep 1
+
 echo '--- tcpserver prints error message with used port'
 tcpserver -R -H -l Local 127.0.0.1 50016 echo wrong
 echo $?
 
 echo '--- tcpcat works'
-tcpcat 0 50016 | grep -v TCPREMOTEPORT
+tcpcat 127.0.0.1 50016 | grep -v TCPREMOTEPORT
 echo $?
 sleep 1
 
+echo '--- tcpcat works'
+tcpcat ::1 50015 | grep -v TCPREMOTEPORT
+echo $?
+sleep 1
+
+echo '--- mconnect works'
+mconnect 127.0.0.1 50016 </dev/null | grep -v TCPREMOTEPORT
+echo $?
+
 echo '--- mconnect works'
-mconnect 0 50016 </dev/null | grep -v TCPREMOTEPORT
+mconnect ::1 50015 </dev/null | grep -v TCPREMOTEPORT
 echo $?
 
 echo '--- tcprules prints usage message without enough arguments'
@@ -191,6 +256,19 @@
 env TCPREMOTEIP=1.2.3.4 TCPREMOTEHOST=x.abuser.edu tcprulescheck test.cdb
 env TCPREMOTEIP=1.2.3.4 TCPREMOTEHOST=x.y.abuser.edu tcprulescheck test.cdb
 
+echo '--- tcprules handles IPv6'
+echo '20014ba0fff100bfc0011337d00ddead:allow,which=/full/
+20014ba0fff100bfc001:allow,which=/part/
+00000000000000000000000000000001:allow,which=/full/
+0:deny
+:allow,which=/anybody/' | tcprules test.cdb test.tmp; echo $?
+env TCPREMOTEIP=2001:4ba0:fff1:bf:c001:1337:d00d:dead tcprulescheck test.cdb
+env TCPREMOTEIP=2001:4ba0:fff1:bf:c001::1 tcprulescheck test.cdb
+env TCPREMOTEIP=::1 tcprulescheck test.cdb
+env TCPREMOTEIP=::2 tcprulescheck test.cdb
+env TCPREMOTEIP=1::1 tcprulescheck test.cdb
+env TCPREMOTEIP=fe80::212:37ff:fe8c:c886 tcprulescheck test.cdb
+
 echo '--- tcprulescheck searches for rules in the proper order'
 echo 'xyz@86.75.30.9:allow,which=/first/
 xyz@=one.two.three:allow,which=/second/
@@ -298,11 +376,26 @@
 | ( TCPREMOTEIP=127.0.0.1 rblsmtpd -r zen.spamhaus.org echo ok 2>&1; echo $? ) \
 | sed 's/pid [0-9]*/pid x/'
 
+echo '--- rblsmtpd does not find ::ffff:127.0.0.1 on the RBL'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=::ffff:127.0.0.1 rblsmtpd -r zen.spamhaus.org echo ok 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
+echo '--- rblsmtpd does not find ::1 on the RBL'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=::1 rblsmtpd -r zen.spamhaus.org echo ok 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
 echo '--- rblsmtpd finds 127.0.0.2 on the RBL'
 ( echo help; echo quit ) \
 | ( TCPREMOTEIP=127.0.0.2 rblsmtpd -r zen.spamhaus.org echo whoops 2>&1; echo $? ) \
 | sed 's/pid [0-9]*/pid x/'
 
+echo '--- rblsmtpd finds ::ffff:127.0.0.2 on the RBL'
+( echo help; echo quit ) \
+| ( TCPREMOTEIP=::ffff:127.0.0.2 rblsmtpd -r zen.spamhaus.org echo whoops 2>&1; echo $? ) \
+| sed 's/pid [0-9]*/pid x/'
+
 echo '--- rblsmtpd -b uses a permanent error code'
 ( echo help; echo quit ) \
 | ( TCPREMOTEIP=127.0.0.2 rblsmtpd -b -r zen.spamhaus.org echo whoops 2>&1; echo $? ) \
@@ -345,10 +438,14 @@
 
 
 svc -dx 50016
+svc -dx 50015
 wait
 
 echo '--- tcpserver -1v prints proper messages'
 sed -e 's/::.*/::x/' -e 's/ [0-9]* / x /' < log
 
+echo '--- tcpserver -1v prints proper messages'
+sed -e 's/::[02-9]$/::x/;s/::[0-9][0-9][0-9]*$/::x/' -e 's/ [0-9]* / x /' < log2
+
 
 exit 0
diff -rNU3 ucspi-tcp-0.88/rules.c ucspi-tcp-0.88.ipv6/rules.c
--- ucspi-tcp-0.88/rules.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/rules.c	2012-02-17 16:58:00.000000000 +0100
@@ -1,13 +1,17 @@
 #include "alloc.h"
+#include "byte.h"
 #include "stralloc.h"
 #include "open.h"
 #include "cdb.h"
 #include "rules.h"
 
 stralloc rules_name = {0};
+static stralloc remote = {0};
 
 static struct cdb c;
 
+static const char HEX[] = "0123456789abcdef";
+
 static int dorule(void (*callback)(char *,unsigned int))
 {
   char *data;
@@ -31,14 +35,29 @@
   return 1;
 }
 
-static int doit(void (*callback)(char *,unsigned int),char *ip,char *host,char *info)
+static int doit(void (*callback)(char *,unsigned int),socket_address *ip,char *host,char *info)
 {
-  int r;
+  int r, v6=0;
 
+  if (ip->sa4.sin_family == AF_INET) {
+    if (stralloc_ready(&remote, IP4_FMT) == -1) return -1;
+    remote.len = ip4_fmt(remote.s, (char*) &ip->sa4.sin_addr.s_addr);
+  } else if (byte_equal(ip->sa6.sin6_addr.s6_addr, 12, V6_MAPPED_PREFIX)) {
+    if (stralloc_ready(&remote, IP4_FMT) == -1) return -1;
+    remote.len = ip4_fmt(remote.s, ip->sa6.sin6_addr.s6_addr+12);
+  } else {
+    v6 = 1;
+    if (stralloc_ready(&remote, 16*2 + 1) == -1) return -1;
+    stralloc_copys(&remote, "");
+    for (r = 0; r < 16; r++) {
+      remote.s[remote.len++] = HEX[(ip->sa6.sin6_addr.s6_addr[r] >> 4) & 0xf];
+      remote.s[remote.len++] = HEX[ip->sa6.sin6_addr.s6_addr[r] & 0xf];
+    }
+  }
   if (info) {
     if (!stralloc_copys(&rules_name,info)) return -1;
     if (!stralloc_cats(&rules_name,"@")) return -1;
-    if (!stralloc_cats(&rules_name,ip)) return -1;
+    if (!stralloc_cat(&rules_name,&remote)) return -1;
     r = dorule(callback);
     if (r) return r;
 
@@ -51,7 +70,7 @@
     }
   }
 
-  if (!stralloc_copys(&rules_name,ip)) return -1;
+  if (!stralloc_copy(&rules_name, &remote)) return -1;
   r = dorule(callback);
   if (r) return r;
 
@@ -62,9 +81,9 @@
     if (r) return r;
   }
 
-  if (!stralloc_copys(&rules_name,ip)) return -1;
+  if (!stralloc_copy(&rules_name, &remote)) return -1;
   while (rules_name.len > 0) {
-    if (ip[rules_name.len - 1] == '.') {
+    if (v6 || rules_name.s[rules_name.len - 1] == '.') {
       r = dorule(callback);
       if (r) return r;
     }
@@ -90,7 +109,7 @@
   return dorule(callback);
 }
 
-int rules(void (*callback)(char *,unsigned int),int fd,char *ip,char *host,char *info)
+int rules(void (*callback)(char *,unsigned int),int fd,socket_address *ip,char *host,char *info)
 {
   int r;
   cdb_init(&c,fd);
diff -rNU3 ucspi-tcp-0.88/rules.h ucspi-tcp-0.88.ipv6/rules.h
--- ucspi-tcp-0.88/rules.h	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/rules.h	2012-02-06 14:40:35.000000000 +0100
@@ -2,8 +2,9 @@
 #define RULES_H
 
 #include "stralloc.h"
+#include "ip4.h"
 
 extern stralloc rules_name;
-extern int rules(void (*)(char *,unsigned int),int,char *,char *,char *);
+extern int rules(void (*)(char *,unsigned int),int,socket_address *,char *,char *);
 
 #endif
diff -rNU3 ucspi-tcp-0.88/socket_accept.c ucspi-tcp-0.88.ipv6/socket_accept.c
--- ucspi-tcp-0.88/socket_accept.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket_accept.c	2012-02-17 10:58:34.000000000 +0100
@@ -1,21 +0,0 @@
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "byte.h"
-#include "socket.h"
-
-int socket_accept4(int s,char ip[4],uint16 *port)
-{
-  struct sockaddr_in sa;
-  int dummy = sizeof sa;
-  int fd;
-
-  fd = accept(s,(struct sockaddr *) &sa,&dummy);
-  if (fd == -1) return -1;
-
-  byte_copy(ip,4,(char *) &sa.sin_addr);
-  uint16_unpack_big((char *) &sa.sin_port,port);
-
-  return fd;
-}
diff -rNU3 ucspi-tcp-0.88/socket_bind.c ucspi-tcp-0.88.ipv6/socket_bind.c
--- ucspi-tcp-0.88/socket_bind.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket_bind.c	2012-02-17 13:42:53.000000000 +0100
@@ -1,33 +0,0 @@
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "byte.h"
-#include "socket.h"
-
-int socket_bind4(int s,char ip[4],uint16 port)
-{
-  struct sockaddr_in sa;
-
-  byte_zero(&sa,sizeof sa);
-  sa.sin_family = AF_INET;
-  uint16_pack_big((char *) &sa.sin_port,port);
-  byte_copy((char *) &sa.sin_addr,4,ip);
-
-  return bind(s,(struct sockaddr *) &sa,sizeof sa);
-}
-
-int socket_bind4_reuse(int s,char ip[4],uint16 port)
-{
-  int opt = 1;
-  setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);
-  return socket_bind4(s,ip,port);
-}
-
-void socket_tryreservein(int s,int size)
-{
-  while (size >= 1024) {
-    if (setsockopt(s,SOL_SOCKET,SO_RCVBUF,&size,sizeof size) == 0) return;
-    size -= (size >> 5);
-  }
-}
diff -rNU3 ucspi-tcp-0.88/socket_conn.c ucspi-tcp-0.88.ipv6/socket_conn.c
--- ucspi-tcp-0.88/socket_conn.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket_conn.c	2012-02-17 13:43:15.000000000 +0100
@@ -5,22 +5,11 @@
 #include <unistd.h>
 #include "byte.h"
 #include "socket.h"
-
-int socket_connect4(int s,char ip[4],uint16 port)
-{
-  struct sockaddr_in sa;
-
-  byte_zero(&sa,sizeof sa);
-  sa.sin_family = AF_INET;
-  uint16_pack_big((char *) &sa.sin_port,port);
-  byte_copy((char *) &sa.sin_addr,4,ip);
-
-  return connect(s,(struct sockaddr *) &sa,sizeof sa);
-}
+#include "ip4.h"
 
 int socket_connected(int s)
 {
-  struct sockaddr_in sa;
+  socket_address sa;
   int dummy;
   char ch;
 
diff -rNU3 ucspi-tcp-0.88/socket.h ucspi-tcp-0.88.ipv6/socket.h
--- ucspi-tcp-0.88/socket.h	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket.h	2012-02-17 13:43:41.000000000 +0100
@@ -3,20 +3,7 @@
 
 #include "uint16.h"
 
-extern int socket_tcp(void);
-extern int socket_udp(void);
-
-extern int socket_connect4(int,char *,uint16);
 extern int socket_connected(int);
-extern int socket_bind4(int,char *,uint16);
-extern int socket_bind4_reuse(int,char *,uint16);
 extern int socket_listen(int,int);
-extern int socket_accept4(int,char *,uint16 *);
-extern int socket_recv4(int,char *,int,char *,uint16 *);
-extern int socket_send4(int,char *,int,char *,uint16);
-extern int socket_local4(int,char *,uint16 *);
-extern int socket_remote4(int,char *,uint16 *);
-
-extern void socket_tryreservein(int,int);
 
 #endif
diff -rNU3 ucspi-tcp-0.88/socket_local.c ucspi-tcp-0.88.ipv6/socket_local.c
--- ucspi-tcp-0.88/socket_local.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket_local.c	2012-02-17 10:58:44.000000000 +0100
@@ -1,17 +0,0 @@
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "byte.h"
-#include "socket.h"
-
-int socket_local4(int s,char ip[4],uint16 *port)
-{
-  struct sockaddr_in sa;
-  int dummy = sizeof sa;
-
-  if (getsockname(s,(struct sockaddr *) &sa,&dummy) == -1) return -1;
-  byte_copy(ip,4,(char *) &sa.sin_addr);
-  uint16_unpack_big((char *) &sa.sin_port,port);
-  return 0;
-}
diff -rNU3 ucspi-tcp-0.88/socket_remote.c ucspi-tcp-0.88.ipv6/socket_remote.c
--- ucspi-tcp-0.88/socket_remote.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket_remote.c	2012-02-17 10:58:39.000000000 +0100
@@ -1,17 +0,0 @@
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "byte.h"
-#include "socket.h"
-
-int socket_remote4(int s,char ip[4],uint16 *port)
-{
-  struct sockaddr_in sa;
-  int dummy = sizeof sa;
-
-  if (getpeername(s,(struct sockaddr *) &sa,&dummy) == -1) return -1;
-  byte_copy(ip,4,(char *) &sa.sin_addr);
-  uint16_unpack_big((char *) &sa.sin_port,port);
-  return 0;
-}
diff -rNU3 ucspi-tcp-0.88/socket_tcp.c ucspi-tcp-0.88.ipv6/socket_tcp.c
--- ucspi-tcp-0.88/socket_tcp.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket_tcp.c	2012-02-17 13:43:27.000000000 +0100
@@ -1,17 +0,0 @@
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "ndelay.h"
-#include "socket.h"
-#include <unistd.h>
-
-int socket_tcp(void)
-{
-  int s;
-
-  s = socket(AF_INET,SOCK_STREAM,0);
-  if (s == -1) return -1;
-  if (ndelay_on(s) == -1) { close(s); return -1; }
-  return s;
-}
diff -rNU3 ucspi-tcp-0.88/socket_udp.c ucspi-tcp-0.88.ipv6/socket_udp.c
--- ucspi-tcp-0.88/socket_udp.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/socket_udp.c	2012-02-17 13:43:30.000000000 +0100
@@ -1,17 +0,0 @@
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "ndelay.h"
-#include "socket.h"
-#include <unistd.h>
-
-int socket_udp(void)
-{
-  int s;
-
-  s = socket(AF_INET,SOCK_DGRAM,0);
-  if (s == -1) return -1;
-  if (ndelay_on(s) == -1) { close(s); return -1; }
-  return s;
-}
diff -rNU3 ucspi-tcp-0.88/strerr_die.c ucspi-tcp-0.88.ipv6/strerr_die.c
--- ucspi-tcp-0.88/strerr_die.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/strerr_die.c	2012-02-06 16:50:16.000000000 +0100
@@ -2,7 +2,7 @@
 #include "exit.h"
 #include "strerr.h"
 
-void strerr_warn(char *x1,char *x2,char *x3,char *x4,char *x5,char *x6,struct strerr *se)
+void strerr_warn(const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,struct strerr *se)
 {
   strerr_sysinit();
  
@@ -24,7 +24,7 @@
   buffer_flush(buffer_2);
 }
 
-void strerr_die(int e,char *x1,char *x2,char *x3,char *x4,char *x5,char *x6,struct strerr *se)
+void strerr_die(int e,const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,struct strerr *se)
 {
   strerr_warn(x1,x2,x3,x4,x5,x6,se);
   _exit(e);
diff -rNU3 ucspi-tcp-0.88/strerr.h ucspi-tcp-0.88.ipv6/strerr.h
--- ucspi-tcp-0.88/strerr.h	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/strerr.h	2012-02-06 16:50:27.000000000 +0100
@@ -12,8 +12,8 @@
 extern void strerr_sysinit(void);
 
 extern char *strerr(struct strerr *);
-extern void strerr_warn(char *,char *,char *,char *,char *,char *,struct strerr *);
-extern void strerr_die(int,char *,char *,char *,char *,char *,char *,struct strerr *);
+extern void strerr_warn(const char *,const char *,const char *,const char *,const char *,const char *,struct strerr *);
+extern void strerr_die(int,const char *,const char *,const char *,const char *,const char *,const char *,struct strerr *);
 
 #define STRERR(r,se,a) \
 { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; }
diff -rNU3 ucspi-tcp-0.88/tcpclient.c ucspi-tcp-0.88.ipv6/tcpclient.c
--- ucspi-tcp-0.88/tcpclient.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/tcpclient.c	2012-02-17 16:36:51.000000000 +0100
@@ -19,7 +19,8 @@
 #include "pathexec.h"
 #include "timeoutconn.h"
 #include "remoteinfo.h"
-#include "dns.h"
+#include "ip4.h"
+#include "byte.h"
 
 #define FATAL "tcpclient: fatal: "
 #define CONNECT "tcpclient: unable to connect to "
@@ -31,7 +32,7 @@
 void usage(void)
 {
   strerr_die1x(100,"tcpclient: usage: tcpclient \
-[ -hHrRdDqQv ] \
+[ -hHrRdDqQv46 ] \
 [ -i localip ] \
 [ -p localport ] \
 [ -T timeoutconn ] \
@@ -47,19 +48,14 @@
 unsigned long itimeout = 26;
 unsigned long ctimeout[2] = { 2, 58 };
 
-char iplocal[4] = { 0,0,0,0 };
-uint16 portlocal = 0;
 char *forcelocal = 0;
 
-char ipremote[4];
-uint16 portremote;
+socket_address local, remote;
 
 char *hostname;
-static stralloc addresses;
 static stralloc moreaddresses;
 
 static stralloc tmp;
-static stralloc fqdn;
 char strnum[FMT_ULONG];
 char ipstr[IP4_FMT];
 
@@ -67,20 +65,20 @@
 
 main(int argc,char **argv)
 {
-  unsigned long u;
   int opt;
-  char *x;
+  char *x, *portname, *localname = NULL, *portlocal = NULL;
   int j;
   int s;
   int cloop;
-
-  dns_random_init(seed);
+  struct addrinfo *to_bind = NULL, *to_connect = NULL, hints = {0}, *bindme;
+  socklen_t addrlen = sizeof(local);
 
   close(6);
   close(7);
   sig_ignore(sig_pipe);
- 
-  while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:")) != opteof)
+
+  hints.ai_family = AF_UNSPEC; 
+  while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:46")) != opteof)
     switch(opt) {
       case 'd': flagdelay = 1; break;
       case 'D': flagdelay = 0; break;
@@ -97,8 +96,10 @@
 		if (optarg[j] == '+') ++j;
 		scan_ulong(optarg + j,&ctimeout[1]);
 		break;
-      case 'i': if (!ip4_scan(optarg,iplocal)) usage(); break;
-      case 'p': scan_ulong(optarg,&u); portlocal = u; break;
+      case 'i': localname = optarg; break;
+      case 'p': portlocal = optarg; break;
+      case '4': hints.ai_family = AF_INET; break;
+      case '6': hints.ai_family = AF_INET6; break;
       default: usage();
     }
   argv += optind;
@@ -110,54 +111,70 @@
   if (!hostname) usage();
   if (str_equal(hostname,"")) hostname = "127.0.0.1";
   if (str_equal(hostname,"0")) hostname = "127.0.0.1";
-
-  x = *++argv;
-  if (!x) usage();
-  if (!x[scan_ulong(x,&u)])
-    portremote = u;
-  else {
-    struct servent *se;
-    se = getservbyname(x,"tcp");
-    if (!se)
-      strerr_die3x(111,FATAL,"unable to figure out port number for ",x);
-    portremote = ntohs(se->s_port);
-    /* i continue to be amazed at the stupidity of the s_port interface */
+  j = strlen(hostname);
+  if (*hostname == '[' && hostname[j-1] == ']') {
+    hostname[j-1] = 0;
+    hostname++;
   }
 
+  portname = *++argv;
+  if (!portname) usage();
+
   if (!*++argv) usage();
 
-  if (!stralloc_copys(&tmp,hostname)) nomem();
-  if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1)
-    strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": ");
-  if (addresses.len < 4)
-    strerr_die3x(111,FATAL,"no IP address for ",hostname);
+  hints.ai_socktype = SOCK_STREAM;
+  if (hints.ai_family == AF_UNSPEC) {
+    hints.ai_flags |= AI_ADDRCONFIG | AI_V4MAPPED;
+  }
+  if (localname || portlocal) {
+    errno = getaddrinfo(localname, portlocal, &hints, &to_bind);
+    if (errno == EAI_NODATA || !to_bind)
+      strerr_die5x(111,FATAL,"no IP address for ",localname?localname:"''","/",portlocal?portlocal:"0");
+    if (errno)
+      strerr_die5x(111,FATAL,"temporarily unable to figure out IP address for ",localname,": ",gai_strerror(errno));
+  }
+
+  errno = getaddrinfo(hostname, portname, &hints, &to_connect);
+  if (errno == EAI_NODATA || !to_connect)
+    strerr_die5x(111,FATAL,"no IP address for ",hostname,"/",portname);
+  if (errno)
+    strerr_die5x(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": ",gai_strerror(errno));
 
-  if (addresses.len == 4) {
+  if (!to_connect->ai_next) {
     ctimeout[0] += ctimeout[1];
     ctimeout[1] = 0;
   }
 
+  if (!stralloc_copys(&moreaddresses,"")) nomem();
   for (cloop = 0;cloop < 2;++cloop) {
-    if (!stralloc_copys(&moreaddresses,"")) nomem();
-    for (j = 0;j + 4 <= addresses.len;j += 4) {
-      s = socket_tcp();
+    for (j=0, hints.ai_next = to_connect; hints.ai_next; hints.ai_next = hints.ai_next->ai_next, j++) {
+      bindme = to_bind;
+      while (bindme && bindme->ai_family != hints.ai_next->ai_family)
+	bindme = bindme->ai_next;
+      if (!bindme && to_bind) { continue; }
+      if (cloop && !moreaddresses.s[j]) { continue; }
+      s = socket(hints.ai_next->ai_family, hints.ai_next->ai_socktype | SOCK_NONBLOCK,
+		 hints.ai_next->ai_protocol);
       if (s == -1)
         strerr_die2sys(111,FATAL,"unable to create socket: ");
-      if (socket_bind4(s,iplocal,portlocal) == -1)
+      if (bindme && bind(s, bindme->ai_addr, bindme->ai_addrlen) == -1)
         strerr_die2sys(111,FATAL,"unable to bind socket: ");
-      if (timeoutconn(s,addresses.s + j,portremote,ctimeout[cloop]) == 0)
+      byte_copy(&remote, hints.ai_next->ai_addrlen, hints.ai_next->ai_addr);
+      if (timeoutconn(s, &remote, ctimeout[cloop]) == 0)
         goto CONNECTED;
       close(s);
       if (!cloop && ctimeout[1] && (errno == error_timeout)) {
-	if (!stralloc_catb(&moreaddresses,addresses.s + j,4)) nomem();
+	if (!stralloc_catb(&moreaddresses, "\001", 1)) nomem();
       }
       else {
-        strnum[fmt_ulong(strnum,portremote)] = 0;
-        ipstr[ip4_fmt(ipstr,addresses.s + j)] = 0;
+	if (!stralloc_catb(&moreaddresses, "", 1)) nomem();
+	if (getnameinfo(hints.ai_next->ai_addr, hints.ai_next->ai_addrlen, ipstr, sizeof(ipstr),
+			strnum, sizeof(strnum), NI_NUMERICHOST|NI_NUMERICSERV)) {
+	  strerr_die2sys(111, FATAL, "unable to get local host + port: ");
+	}
         strerr_warn5(CONNECT,ipstr," port ",strnum,": ",&strerr_sys);
       }
     }
-    if (!stralloc_copy(&addresses,&moreaddresses)) nomem();
   }
 
   _exit(111);
@@ -171,43 +188,52 @@
 
   if (!pathexec_env("PROTO","TCP")) nomem();
 
-  if (socket_local4(s,iplocal,&portlocal) == -1)
+  if (getsockname(s,(struct sockaddr *) &local, &addrlen))
     strerr_die2sys(111,FATAL,"unable to get local address: ");
 
-  strnum[fmt_ulong(strnum,portlocal)] = 0;
+  if (getnameinfo((struct sockaddr *) &local, sizeof(local), ipstr, sizeof(ipstr),
+		  strnum, sizeof(strnum), NI_NUMERICHOST|NI_NUMERICSERV)) {
+    strerr_die2sys(111, FATAL, "unable to get local host + port: ");
+  }
+
   if (!pathexec_env("TCPLOCALPORT",strnum)) nomem();
-  ipstr[ip4_fmt(ipstr,iplocal)] = 0;
   if (!pathexec_env("TCPLOCALIP",ipstr)) nomem();
 
+  if (!stralloc_ready(&tmp, 1024)) nomem();
   x = forcelocal;
-  if (!x)
-    if (dns_name4(&tmp,iplocal) == 0) {
-      if (!stralloc_0(&tmp)) nomem();
-      x = tmp.s;
-    }
+  if (!x) {
+    stralloc_copyb(&tmp, "", 1);
+    if (getnameinfo((struct sockaddr *) &local, sizeof(local), tmp.s,
+		    tmp.a, NULL, 0, NI_NAMEREQD) == 0)
+      if (tmp.s[0]) {
+        x = tmp.s;
+      }
+  }
   if (!pathexec_env("TCPLOCALHOST",x)) nomem();
 
-  if (socket_remote4(s,ipremote,&portremote) == -1)
+  opt = sizeof(remote);
+  if (getpeername(s, &remote.sa4, &opt))
     strerr_die2sys(111,FATAL,"unable to get remote address: ");
 
-  strnum[fmt_ulong(strnum,portremote)] = 0;
+  if (getnameinfo((struct sockaddr *) &remote, sizeof(remote), ipstr, sizeof(ipstr),
+                  strnum, sizeof(strnum), NI_NUMERICHOST|NI_NUMERICSERV))
+    strerr_die2sys(111, FATAL, "unable to get remote host + port: ");
   if (!pathexec_env("TCPREMOTEPORT",strnum)) nomem();
-  ipstr[ip4_fmt(ipstr,ipremote)] = 0;
   if (!pathexec_env("TCPREMOTEIP",ipstr)) nomem();
   if (verbosity >= 2)
     strerr_warn4("tcpclient: connected to ",ipstr," port ",strnum,0);
 
   x = 0;
-  if (flagremotehost)
-    if (dns_name4(&tmp,ipremote) == 0) {
-      if (!stralloc_0(&tmp)) nomem();
-      x = tmp.s;
-    }
+  if (flagremotehost
+      && getnameinfo((struct sockaddr *) &remote, sizeof(remote), tmp.s,
+                     tmp.a, NULL, 0, NI_NAMEREQD) == 0) {
+    x = tmp.s;
+  }
   if (!pathexec_env("TCPREMOTEHOST",x)) nomem();
 
   x = 0;
   if (flagremoteinfo)
-    if (remoteinfo(&tmp,ipremote,portremote,iplocal,portlocal,itimeout) == 0) {
+    if (remoteinfo(&tmp, &remote, &local, itimeout) == 0) {
       if (!stralloc_0(&tmp)) nomem();
       x = tmp.s;
     }
diff -rNU3 ucspi-tcp-0.88/tcprulescheck.c ucspi-tcp-0.88.ipv6/tcprulescheck.c
--- ucspi-tcp-0.88/tcprulescheck.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/tcprulescheck.c	2012-02-17 10:47:00.000000000 +0100
@@ -5,7 +5,9 @@
 #include "rules.h"
 #include <unistd.h>
 #include "open.h"
-
+#include "ip4.h"
+#include <netdb.h>
+#include "error.h"
 
 void found(char *data,unsigned int datalen)
 {
@@ -41,6 +43,8 @@
   char *ip;
   char *info;
   char *host;
+  struct addrinfo *sockaddr = NULL, hints = {0};
+  socket_address address;
 
   fnrules = argv[1];
   if (!fnrules)
@@ -51,8 +55,14 @@
   info = env_get("TCPREMOTEINFO");
   host = env_get("TCPREMOTEHOST");
 
+  if (getaddrinfo(ip, NULL, &hints, &sockaddr) || sockaddr == NULL)
+    strerr_die2x(100,"tcprulescheck: fatal: couldn't parse TCPREMOTEIP: ",
+		 gai_strerror(errno));
+  byte_copy(&address, sockaddr->ai_addrlen, sockaddr->ai_addr);
+  freeaddrinfo(sockaddr);
+
   fd = open_read(fnrules);
-  if ((fd == -1) || (rules(found,fd,ip,host,info) == -1))
+  if ((fd == -1) || (rules(found, fd, &address, host, info) == -1))
     strerr_die3sys(111,"tcprulescheck: fatal: unable to read ",fnrules,": ");
 
   buffer_putsflush(buffer_1,"default:\nallow connection\n");
diff -rNU3 ucspi-tcp-0.88/tcpserver.c ucspi-tcp-0.88.ipv6/tcpserver.c
--- ucspi-tcp-0.88/tcpserver.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/tcpserver.c	2012-02-17 16:41:01.000000000 +0100
@@ -4,6 +4,8 @@
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 #include <netdb.h>
 #include <stdlib.h>
 #ifdef NO_GETLOADAVG
@@ -59,26 +61,22 @@
 
 static stralloc tcpremoteinfo;
 
-uint16 localport;
-char localportstr[FMT_ULONG];
-char localip[4];
-char localipstr[IP4_FMT];
+char localportstr[40];
+char localipstr[48];
 static stralloc localhostsa;
 char *localhost = 0;
 
-uint16 remoteport;
-char remoteportstr[FMT_ULONG];
-char remoteip[4];
-char remoteipstr[IP4_FMT];
+char remoteportstr[40];
+char remoteipstr[48];
 static stralloc remotehostsa;
 char *remotehost = 0;
 
+static socket_address local, remote;
+
 char strnum[FMT_ULONG];
 char strnum2[FMT_ULONG];
 
 static stralloc tmp;
-static stralloc fqdn;
-static stralloc addresses;
 static stralloc diemsg_buf;
 
 char bspace[16];
@@ -87,7 +87,7 @@
 
 typedef struct
 {
-  char ip[4];
+  char ip[16];
   pid_t pid;
 } baby;
 
@@ -221,10 +221,14 @@
 
 void doit(int t)
 {
-  int j;
   unsigned long curload = 0;
+  socklen_t addrlen = sizeof(local);
 
-  remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0;
+  if (getnameinfo((struct sockaddr *) &remote, sizeof(remote), remoteipstr, sizeof(remoteipstr),
+		  remoteportstr, sizeof(remoteportstr),
+		  NI_NUMERICHOST|NI_NUMERICSERV)) {
+    strerr_die2sys(111,DROP,"unable to get remote host + port: ");
+  }
 
   if (verbosity >= 2) {
     strnum[fmt_ulong(strnum,getpid())] = 0;
@@ -242,44 +247,69 @@
       strerr_die2sys(111,DROP,"unable to print banner: ");
   }
 
-  if (socket_local4(t,localip,&localport) == -1)
+  if (getsockname(t,(struct sockaddr *) &local, &addrlen))
     strerr_die2sys(111,DROP,"unable to get local address: ");
 
-  localipstr[ip4_fmt(localipstr,localip)] = 0;
-  remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;
+  if (getnameinfo((struct sockaddr *) &local, sizeof(local), localipstr, sizeof(localipstr),
+		  localportstr, sizeof(localportstr),
+		  NI_NUMERICHOST|NI_NUMERICSERV)) {
+    strerr_die2sys(111,DROP,"unable to get local host + port: ");
+  }
 
-  if (!localhost)
-    if (dns_name4(&localhostsa,localip) == 0)
-      if (localhostsa.len) {
-	if (!stralloc_0(&localhostsa)) drop_nomem();
+  if (!localhost) {
+    if (!stralloc_ready(&localhostsa, 1024)) drop_nomem();
+    stralloc_copyb(&localhostsa, "", 1);
+    if (getnameinfo((struct sockaddr *) &local, sizeof(local), localhostsa.s,
+		    localhostsa.a, NULL, 0, NI_NAMEREQD) == 0)
+      if (localhostsa.s[0]) {
 	localhost = localhostsa.s;
       }
+  }
   env("PROTO","TCP");
   env("TCPLOCALIP",localipstr);
   env("TCPLOCALPORT",localportstr);
   env("TCPLOCALHOST",localhost);
 
-  if (flagremotehost)
-    if (dns_name4(&remotehostsa,remoteip) == 0)
-      if (remotehostsa.len) {
-	if (flagparanoid)
-	  if (dns_ip4(&tmp,&remotehostsa) == 0)
-	    for (j = 0;j + 4 <= tmp.len;j += 4)
-	      if (byte_equal(remoteip,4,tmp.s + j)) {
+  if (flagremotehost) {
+    if (!stralloc_ready(&remotehostsa, 1024)) drop_nomem();
+    if (getnameinfo((struct sockaddr *) &remote, sizeof(remote),remotehostsa.s,
+		    remotehostsa.a, NULL, 0, NI_NAMEREQD) == 0)
+      if (remotehostsa.s[0]) {
+	if (flagparanoid) {
+	  struct addrinfo *reverse, hints = {0};
+	  hints.ai_family = remote.sa4.sin_family;
+	  if (remote.sa6.sin6_family == AF_INET6) {
+	    hints.ai_flags = AI_V4MAPPED | AI_ALL;
+	  }
+	  if (getaddrinfo(remotehostsa.s, NULL, &hints, &reverse) == 0) {
+	    hints.ai_next = reverse;
+	    while (hints.ai_next) {
+	      if (hints.ai_next->ai_family == AF_INET
+		  && remote.sa4.sin_family == AF_INET
+		  && byte_equal(&remote.sa4.sin_addr, 4, &((struct sockaddr_in*) hints.ai_next->ai_addr)->sin_addr)
+		  || hints.ai_next->ai_family == AF_INET6
+		     && remote.sa6.sin6_family == AF_INET6
+		     && byte_equal(remote.sa6.sin6_addr.s6_addr, 16,
+				   &((struct sockaddr_in6*) hints.ai_next->ai_addr)->sin6_addr.s6_addr)) {
 		flagparanoid = 0;
 		break;
 	      }
+	      hints.ai_next = hints.ai_next->ai_next;
+	    }
+	    freeaddrinfo(reverse);
+	  }
+	}
 	if (!flagparanoid) {
-	  if (!stralloc_0(&remotehostsa)) drop_nomem();
 	  remotehost = remotehostsa.s;
 	}
       }
+  }
   env("TCPREMOTEIP",remoteipstr);
   env("TCPREMOTEPORT",remoteportstr);
   env("TCPREMOTEHOST",remotehost);
 
   if (flagremoteinfo) {
-    if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout) == -1)
+    if (remoteinfo(&tcpremoteinfo,&remote,&local,timeout) == -1)
       flagremoteinfo = 0;
     if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
   }
@@ -293,7 +323,7 @@
       if (!flagallownorules) drop_rules();
     }
     else {
-      if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules();
+      if (rules(found,fdrules,&remote,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules();
       close(fdrules);
     }
   }
@@ -306,13 +336,22 @@
   if (!flagdeny && (maxconnip != -1 || maxconnc != -1)) {
   	unsigned long u;
   	long c1=0, cc=0;
-  	for (u=0; u < limit; u++) if (child[u].pid != 0) { 
-  		if ((child[u].ip[0] == remoteip[0]) &&
-  		    (child[u].ip[1] == remoteip[1]) &&
-  		    (child[u].ip[2] == remoteip[2]) ) {
+  	for (u=0; u < limit; u++) if (child[u].pid != 0) {
+	    if (byte_equal(child[u].ip,12,V6_MAPPED_PREFIX)) {
+	        if (remote.sa4.sin_family == AF_INET6) {
+		    if (byte_equal(child[u].ip+12,3,remote.sa6.sin6_addr.s6_addr+12)) {
+  			cc++;
+			if (child[u].ip[15] == remote.sa6.sin6_addr.s6_addr[15]) c1++;
+		    }
+		} else if (byte_equal(child[u].ip+12,3,&remote.sa4.sin_addr)) {
   		    cc++;
-  		    if (child[u].ip[3] == remoteip[3]) c1++;
+  		    if (byte_equal(child[u].ip+12,4,&remote.sa4.sin_addr)) c1++;
   		}
+	    } else if (remote.sa4.sin_family == AF_INET6
+		       && byte_equal(child[u].ip,8,remote.sa6.sin6_addr.s6_addr)) {
+  		cc++;
+		if (byte_equal(child[u].ip+8,8,remote.sa6.sin6_addr.s6_addr+8)) c1++;
+	    }
   	}
 	if (maxconnc != -1 && (cc >= maxconnc)) flagdeny = 4;
 	if (maxconnip != -1 && (c1 >= maxconnip)) flagdeny = 3;
@@ -371,7 +410,7 @@
 {
   strerr_warn1("\
 tcpserver: usage: tcpserver \
-[ -1UXpPhHrRoOdDqQv ] \
+[ -1UXpPhHrRoOdDqQv46 ] \
 [ -c limit ] \
 [ -x rules.cdb ] \
 [ -B banner ] \
@@ -427,14 +466,16 @@
   char *hostname;
   char *portname;
   int opt;
-  struct servent *se;
+  struct addrinfo *to_bind = NULL, hints = {0};
   char *x;
   unsigned long u;
   int s;
   int t;
   pid_t pid;
- 
-  while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof)
+  socklen_t addrlen = sizeof(local);
+
+  hints.ai_family = AF_UNSPEC; 
+  while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO46")) != opteof)
     switch(opt) {
       case 'b': scan_ulong(optarg,&backlog); break;
       case 'c': scan_ulong(optarg,&limit); break;
@@ -460,6 +501,8 @@
       case 'g': scan_ulong(optarg,&gid); break;
       case '1': flag1 = 1; break;
       case 'l': localhost = optarg; break;
+      case '4': hints.ai_family = AF_INET; break;
+      case '6': hints.ai_family = AF_INET6; break;
       default: usage();
     }
   argc -= optind;
@@ -475,19 +518,13 @@
  
   hostname = *argv++;
   if (!hostname) usage();
-  if (str_equal(hostname,"")) hostname = "0.0.0.0";
-  if (str_equal(hostname,"0")) hostname = "0.0.0.0";
+  if (str_equal(hostname,"")) hostname = NULL;
+  if (hostname && str_equal(hostname,"0")) hostname = NULL;
+  if (hostname && str_equal(hostname,"0.0.0.0")) hostname = NULL;
+  if (hostname && str_equal(hostname,"::")) hostname = NULL;
 
-  x = *argv++;
-  if (!x) usage();
-  if (!x[scan_ulong(x,&u)])
-    localport = u;
-  else {
-    se = getservbyname(x,"tcp");
-    if (!se)
-      strerr_die3x(111,FATAL,"unable to figure out port number for ",x);
-    localport = ntohs(se->s_port);
-  }
+  portname = *argv++;
+  if (!portname) usage();
 
   if (!*argv) usage();
   
@@ -499,21 +536,38 @@
   sig_catch(sig_child,sigchld);
   sig_catch(sig_term,sigterm);
   sig_ignore(sig_pipe);
- 
-  if (!stralloc_copys(&tmp,hostname))
-    strerr_die2x(111,FATAL,"out of memory");
-  if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1)
-    strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": ");
-  if (addresses.len < 4)
-    strerr_die3x(111,FATAL,"no IP address for ",hostname);
-  byte_copy(localip,4,addresses.s);
-
-  s = socket_tcp();
-  if (s == -1)
-    strerr_die2sys(111,FATAL,"unable to create socket: ");
-  if (socket_bind4_reuse(s,localip,localport) == -1)
-    strerr_die2sys(111,FATAL,"unable to bind: ");
-  if (socket_local4(s,localip,&localport) == -1)
+
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_PASSIVE;
+  if (hints.ai_family == AF_UNSPEC) {
+    hints.ai_flags |= AI_ADDRCONFIG | AI_V4MAPPED;
+  }
+  errno = getaddrinfo(hostname, portname, &hints, &to_bind);
+  if (errno == EAI_NODATA || !to_bind)
+    strerr_die5x(111,FATAL,"no IP address for ",hostname?hostname:"''","/",portname);
+  if (errno)
+    strerr_die5x(111,FATAL,"temporarily unable to figure out IP address for ",hostname?hostname:"''",": ",gai_strerror(errno));
+  hints.ai_next = to_bind;
+  do {
+    s = socket(to_bind->ai_family, to_bind->ai_socktype, to_bind->ai_protocol);
+    if (s == -1) {
+      if (!hints.ai_next->ai_next)
+	strerr_die2sys(111,FATAL,"unable to create socket: ");
+    } else if (ndelay_on(s)) {
+	close(s);
+	strerr_die2sys(111,FATAL,"unable to make socket nonblocking: ");
+    } else {
+      opt = 1;
+      setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);
+      if (bind(s, hints.ai_next->ai_addr, hints.ai_next->ai_addrlen)
+	  && !hints.ai_next->ai_next)
+	strerr_die2sys(111,FATAL,"unable to bind: ");
+    }
+    hints.ai_next = hints.ai_next->ai_next;
+  } while (s < 0 && hints.ai_next);
+  freeaddrinfo(to_bind);
+
+  if (getsockname(s, (struct sockaddr *) &local, &addrlen))
     strerr_die2sys(111,FATAL,"unable to get local address: ");
   if (socket_listen(s,backlog) == -1)
     strerr_die2sys(111,FATAL,"unable to listen: ");
@@ -525,7 +577,11 @@
     strerr_die2sys(111,FATAL,"unable to set uid: ");
 
  
-  localportstr[fmt_ulong(localportstr,localport)] = 0;
+  if (getnameinfo((struct sockaddr *) &local, sizeof(local), NULL, 0,
+		  localportstr, sizeof(localportstr),
+		  NI_NUMERICHOST|NI_NUMERICSERV)) {
+    strerr_die2sys(111,DROP,"unable to get local name: ");
+  }
   if (flag1) {
     buffer_init(&b,write,1,bspace,sizeof bspace);
     buffer_puts(&b,localportstr);
@@ -543,8 +599,9 @@
   for (;;) {
     while (numchildren >= limit) sig_pause();
 
+    addrlen = sizeof(remote);
     sig_unblock(sig_child);
-    t = socket_accept4(s,remoteip,&remoteport);
+    t = accept(s, (struct sockaddr *) &remote, &addrlen);
     sig_block(sig_child);
 
     if (t == -1) continue;
@@ -567,7 +624,14 @@
         --numchildren; printstatus();
         break;
       default:
-        for (u=0; u < limit; u++) if (child[u].pid == 0) { byte_copy(child[u].ip,4,remoteip); child[u].pid = pid; break; }
+        for (u=0; u < limit; u++) if (child[u].pid == 0) {
+	  if (remote.sa4.sin_family == AF_INET) {
+	    byte_copy(child[u].ip, 12, V6_MAPPED_PREFIX);
+	    byte_copy(child[u].ip+12, 4, (char*) &remote.sa4.sin_addr.s_addr);
+	  } else
+	    byte_copy(child[u].ip, 16, remote.sa6.sin6_addr.s6_addr);
+	  child[u].pid = pid; break;
+	}
 	if (u == limit) strerr_die1x(111,"tcpserver: ERROR: no empty space for new child?!"); /* never happens */
     }
     close(t);
Binärdateien ucspi-tcp-0.88/test.cdb and ucspi-tcp-0.88.ipv6/test.cdb sind verschieden.
diff -rNU3 ucspi-tcp-0.88/timeoutconn.c ucspi-tcp-0.88.ipv6/timeoutconn.c
--- ucspi-tcp-0.88/timeoutconn.c	2012-02-20 12:18:21.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/timeoutconn.c	2012-02-06 12:01:14.000000000 +0100
@@ -4,13 +4,13 @@
 #include "error.h"
 #include "timeoutconn.h"
 
-int timeoutconn(int s,char ip[4],uint16 port,unsigned int timeout)
+int timeoutconn(int s,socket_address *remote,unsigned int timeout)
 {
   struct taia now;
   struct taia deadline;
   iopause_fd x;
 
-  if (socket_connect4(s,ip,port) == -1) {
+  if (connect(s, (struct sockaddr *) &remote->sa4, remote->sa4.sin_family == AF_INET ? sizeof(remote->sa4) : sizeof(remote->sa6)) == -1) {
     if ((errno != error_wouldblock) && (errno != error_inprogress)) return -1;
     x.fd = s;
     x.events = IOPAUSE_WRITE;
diff -rNU3 ucspi-tcp-0.88/timeoutconn.h ucspi-tcp-0.88.ipv6/timeoutconn.h
--- ucspi-tcp-0.88/timeoutconn.h	2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.ipv6/timeoutconn.h	2012-02-06 11:56:23.000000000 +0100
@@ -2,7 +2,8 @@
 #define TIMEOUTCONN_H
 
 #include "uint16.h"
+#include "ip4.h"
 
-extern int timeoutconn(int,char *,uint16,unsigned int);
+extern int timeoutconn(int,socket_address *,unsigned int);
 
 #endif
--- ucspi-tcp-0.88/Makefile.orig	2012-10-04 14:32:31.000000000 +0200
+++ ucspi-tcp-0.88/Makefile	2012-10-04 14:32:33.000000000 +0200
@@ -638,7 +638,7 @@
 scan.h str.h ip4.h uint16.h socket.h uint16.h fd.h stralloc.h \
 gen_alloc.h buffer.h error.h strerr.h pathexec.h timeoutconn.h \
 uint16.h remoteinfo.h stralloc.h uint16.h dns.h stralloc.h iopause.h \
-taia.h tai.h uint64.h taia.h
+taia.h tai.h uint64.h taia.h ndelay.h
 	./compile tcpclient.c
 
 tcprules: \
--- ucspi-tcp-0.88/tcpclient.c.orig	2012-10-04 14:31:00.000000000 +0200
+++ ucspi-tcp-0.88/tcpclient.c	2012-10-04 14:32:13.000000000 +0200
@@ -21,6 +21,7 @@
 #include "remoteinfo.h"
 #include "ip4.h"
 #include "byte.h"
+#include "ndelay.h"
 
 #define FATAL "tcpclient: fatal: "
 #define CONNECT "tcpclient: unable to connect to "
@@ -150,10 +151,14 @@
 	bindme = bindme->ai_next;
       if (!bindme && to_bind) { continue; }
       if (cloop && !moreaddresses.s[j]) { continue; }
-      s = socket(hints.ai_next->ai_family, hints.ai_next->ai_socktype | SOCK_NONBLOCK,
+      s = socket(hints.ai_next->ai_family, hints.ai_next->ai_socktype,
 		 hints.ai_next->ai_protocol);
       if (s == -1)
         strerr_die2sys(111,FATAL,"unable to create socket: ");
+      if (ndelay_on(s)) {
+	s = -1;
+        strerr_die2sys(111,FATAL,"unable to create nonblocking socket: ");
+      }
       if (bindme && bind(s, bindme->ai_addr, bindme->ai_addrlen) == -1)
         strerr_die2sys(111,FATAL,"unable to bind socket: ");
       byte_copy(&remote, hints.ai_next->ai_addrlen, hints.ai_next->ai_addr);
openSUSE Build Service is sponsored by