Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:p_conrad:branches
ucspi-tcp
ucspi-tcp-0.88-ipv6.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
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);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor