diff -Naur ucspi-ssl-0.70.orig/package/files ucspi-ssl-0.70/package/files --- ucspi-ssl-0.70.orig/package/files 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/package/files 2009-08-03 10:16:12.000000000 -0500 @@ -323,3 +323,24 @@ src/warn-auto.sh src/warn-shsgr src/x86cpuid.c +src/dns_ip6.c +src/dns_ipq6.c +src/dns_nd6.c +src/dns_sortip6.c +src/fmt_xlong.c +src/ip6_fmt.c +src/ip6_scan.c +src/scan_0x.c +src/socket_accept6.c +src/socket_bind6.c +src/socket_conn6.c +src/socket_local6.c +src/socket_recv6.c +src/socket_remote6.c +src/socket_send6.c +src/socket_tcp6.c +src/timeoutconn6.c +src/tryip6.c +src/haveip6.h2 +src/haveip6.h1 +src/remoteinfo6.c diff -Naur ucspi-ssl-0.70.orig/src/Makefile ucspi-ssl-0.70/src/Makefile --- ucspi-ssl-0.70.orig/src/Makefile 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/Makefile 2009-08-03 10:16:12.000000000 -0500 @@ -36,7 +36,13 @@ tai_pack.o taia_add.o taia_approx.o taia_frac.o taia_less.o taia_now.o \ taia_pack.o taia_sub.o taia_uint.o timeoutconn.o uint16_pack.o \ uint16_unpack.o uint32.h uint32_pack.o uint32_unpack.o uint64.h unix.a \ - wait_nohang.o wait_pid.o + wait_nohang.o wait_pid.o dns_ip6.o dns_ipq6.o dns_nd6.o dns_sortip6.o \ + fmt_xlong.o ip6_fmt.o ip6_scan.o scan_0x.o socket_accept6.o socket_bind6.o \ + socket_conn6.o socket_local6.o socket_recv6.o socket_remote6.o \ + socket_send6.o socket_tcp6.o timeoutconn6.o haveip6.h remoteinfo6.o \ + socket_getifidx.o socket_getifname.o scan_ip6.o scan_xlong.o \ + socket_ip4loopback.o socket_udp6.o socket_v4mappedprefix.o \ + socket_v6any.o socket_v6loopback.o tryssl.o alloc.o: compile alloc.c alloc.h error.h ./compile alloc.c @@ -219,7 +225,7 @@ uint64.h ./compile dns_random.c -dns_rcip.o: compile dns_rcip.c taia.h openreadclose.h byte.h ip4.h env.h \ +dns_rcip.o: compile dns_rcip.c taia.h openreadclose.h byte.h ip4.h ip6.h env.h \ dns.h tai.h stralloc.h stralloc.h iopause.h taia.h uint64.h gen_alloc.h \ gen_alloc.h taia.h tai.h tai.h uint64.h uint64.h ./compile dns_rcip.c @@ -240,7 +246,7 @@ dns_transmit.o: compile dns_transmit.c socket.h alloc.h error.h byte.h \ uint16.h dns.h uint16.h stralloc.h iopause.h taia.h gen_alloc.h taia.h \ -tai.h tai.h uint64.h uint64.h +tai.h tai.h uint32.h uint64.h ./compile dns_transmit.c dns_txt.o: compile dns_txt.c stralloc.h uint16.h byte.h dns.h gen_alloc.h \ @@ -372,9 +378,14 @@ remoteinfo.o: compile remoteinfo.c fmt.h buffer.h socket.h error.h \ iopause.h timeoutconn.h remoteinfo.h uint16.h taia.h uint16.h stralloc.h \ -uint16.h tai.h gen_alloc.h uint64.h +uint16.h tai.h gen_alloc.h uint32.h uint64.h ./compile remoteinfo.c +remoteinfo6.o: compile remoteinfo6.c fmt.h buffer.h socket.h error.h \ +iopause.h timeoutconn.h remoteinfo.h uint16.h taia.h stralloc.h \ +tai.h gen_alloc.h uint32.h uint64.h + ./compile remoteinfo6.c + rules.o: compile rules.c alloc.h stralloc.h open.h cdb.h rules.h \ gen_alloc.h uint32.h stralloc.h gen_alloc.h ./compile rules.c @@ -412,34 +423,34 @@ && 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 +socket_accept.o: compile socket_accept.c byte.h socket.h uint16.h uint32.h ./compile socket_accept.c -socket_bind.o: compile socket_bind.c byte.h socket.h uint16.h +socket_bind.o: compile socket_bind.c byte.h socket.h uint16.h uint32.h ./compile socket_bind.c -socket_conn.o: compile socket_conn.c byte.h socket.h uint16.h +socket_conn.o: compile socket_conn.c byte.h socket.h uint16.h uint32.h ./compile socket_conn.c -socket_delay.o: compile socket_delay.c socket.h uint16.h +socket_delay.o: compile socket_delay.c socket.h uint16.h uint32.h ./compile socket_delay.c -socket_listen.o: compile socket_listen.c socket.h uint16.h +socket_listen.o: compile socket_listen.c socket.h uint16.h uint32.h ./compile socket_listen.c -socket_local.o: compile socket_local.c byte.h socket.h uint16.h +socket_local.o: compile socket_local.c byte.h socket.h uint16.h uint32.h ./compile socket_local.c -socket_opts.o: compile socket_opts.c socket.h uint16.h +socket_opts.o: compile socket_opts.c socket.h uint16.h uint32.h ./compile socket_opts.c -socket_remote.o: compile socket_remote.c byte.h socket.h uint16.h +socket_remote.o: compile socket_remote.c byte.h socket.h uint16.h uint32.h ./compile socket_remote.c -socket_tcp.o: compile socket_tcp.c ndelay.h socket.h uint16.h +socket_tcp.o: compile socket_tcp.c ndelay.h socket.h uint16.h uint32.h ./compile socket_tcp.c -socket_udp.o: compile socket_udp.c ndelay.h socket.h uint16.h +socket_udp.o: compile socket_udp.c ndelay.h socket.h uint16.h uint32.h ./compile socket_udp.c ssl.a: makelib ssl.o ssl_io.o ssl_context.o ssl_new.o ssl_timeoutconn.o \ @@ -503,18 +514,18 @@ > sslcat chmod 755 sslcat -sslclient: load sslclient.o remoteinfo.o timeoutconn.o ssl.a unix.a \ +sslclient: load sslclient.o remoteinfo6.o timeoutconn6.o ssl.a unix.a \ auto_cafile.o auto_cadir.o auto_ciphers.o socket.lib ssl.lib - ./load sslclient remoteinfo.o timeoutconn.o ssl.a unix.a auto_cafile.o \ + ./load sslclient remoteinfo6.o timeoutconn6.o ssl.a unix.a auto_cafile.o \ auto_cadir.o auto_ciphers.o `cat socket.lib` `cat ssl.lib` sslclient.o: compile sslclient.c ssl.h sig.h exit.h sgetopt.h uint16.h \ -fmt.h scan.h str.h ip4.h uint16.h socket.h fd.h stralloc.h buffer.h \ +fmt.h scan.h str.h ip4.h ip6.h uint16.h socket.h fd.h stralloc.h buffer.h \ getln.h error.h strerr.h pathexec.h timeoutconn.h remoteinfo.h dns.h \ auto_cafile.h auto_cadir.h auto_ciphers.h byte.h ndelay.h wait.h \ stralloc.h subgetopt.h uint16.h gen_alloc.h buffer.h stralloc.h uint16.h \ stralloc.h uint16.h stralloc.h iopause.h taia.h gen_alloc.h gen_alloc.h \ -gen_alloc.h gen_alloc.h taia.h tai.h tai.h uint64.h uint64.h +gen_alloc.h gen_alloc.h taia.h tai.h tai.h uint32.h uint64.h uint64.h ./compile sslclient.c sslconnect: home warn-auto.sh sslconnect.sh @@ -526,7 +537,7 @@ chmod 755 sslconnect sslhandle.o: compile sslhandle.c ssl.h uint16.h str.h byte.h fmt.h scan.h \ -ip4.h fd.h exit.h env.h prot.h open.h wait.h stralloc.h alloc.h buffer.h \ +ip4.h ip6.h fd.h exit.h env.h prot.h open.h wait.h stralloc.h alloc.h buffer.h \ getln.h error.h strerr.h sgetopt.h socket.h ndelay.h remoteinfo.h rules.h \ sig.h dns.h auto_cafile.h auto_cadir.h auto_ccafile.h auto_dhfile.h \ auto_certfile.h auto_keyfile.h auto_ciphers.h iopause.h coe.h lock.h \ @@ -562,20 +573,20 @@ sslserver: load sslserver.o auto_cafile.o auto_ccafile.o auto_cadir.o \ auto_dhfile.o auto_certfile.o auto_keyfile.o auto_ciphers.o rules.o \ -remoteinfo.o timeoutconn.o cdb.a ssl.a unix.a socket.lib ssl.lib +remoteinfo6.o timeoutconn6.o cdb.a ssl.a unix.a socket.lib ssl.lib ./load sslserver auto_cafile.o auto_ccafile.o auto_cadir.o auto_dhfile.o \ - auto_certfile.o auto_keyfile.o auto_ciphers.o rules.o remoteinfo.o \ - timeoutconn.o cdb.a ssl.a unix.a `cat socket.lib` `cat ssl.lib` + auto_certfile.o auto_keyfile.o auto_ciphers.o rules.o remoteinfo6.o \ + timeoutconn6.o cdb.a ssl.a unix.a `cat socket.lib` `cat ssl.lib` sslserver.o: compile sslserver.c ssl.h uint16.h str.h byte.h fmt.h scan.h \ -ip4.h fd.h exit.h env.h prot.h open.h wait.h stralloc.h alloc.h buffer.h \ +ip4.h ip6.h fd.h exit.h env.h prot.h open.h wait.h stralloc.h alloc.h buffer.h \ getln.h error.h strerr.h sgetopt.h pathexec.h socket.h ndelay.h \ remoteinfo.h rules.h sig.h dns.h auto_cafile.h auto_cadir.h \ auto_ccafile.h auto_dhfile.h auto_certfile.h auto_keyfile.h \ auto_ciphers.h stralloc.h gen_alloc.h buffer.h stralloc.h subgetopt.h \ uint16.h stralloc.h uint16.h stralloc.h stralloc.h iopause.h taia.h \ gen_alloc.h gen_alloc.h gen_alloc.h gen_alloc.h gen_alloc.h taia.h tai.h \ -tai.h uint64.h uint64.h +tai.h uint32.h uint64.h ./compile sslserver.c str_chr.o: compile str_chr.c str.h @@ -671,9 +682,13 @@ ./compile taia_uint.c timeoutconn.o: compile timeoutconn.c ndelay.h socket.h iopause.h error.h \ -timeoutconn.h uint16.h taia.h uint16.h tai.h uint64.h +timeoutconn.h uint16.h taia.h uint16.h tai.h uint32.h uint64.h ./compile timeoutconn.c +timeoutconn6.o: compile timeoutconn6.c ndelay.h socket.h iopause.h error.h \ +timeoutconn.h uint16.h taia.h uint16.h tai.h uint32.h uint64.h + ./compile timeoutconn6.c + uint16_pack.o: compile uint16_pack.c uint16.h ./compile uint16_pack.c @@ -711,7 +726,12 @@ taia_sub.o taia_uint.o 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 lock_ex.o \ -lock_un.o coe.o +lock_un.o coe.o socket_conn6.o socket_bind6.o socket_accept6.o socket_recv6.o \ +socket_send6.o socket_local6.o socket_remote6.o socket_tcp6.o \ +socket_getifname.o socket_getifidx.o socket_v4mappedprefix.o \ +socket_ip4loopback.o socket_v6any.o socket_v6loopback.o \ +socket_udp6.o scan_ip6.o ip6_fmt.o scan_xlong.o fmt_xlong.o \ +dns_ip6.o dns_sortip6.o dns_nd6.o dns_ipq6.o ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o \ buffer_2.o buffer_get.o buffer_put.o buffer_copy.o buffer_read.o \ buffer_write.o env.o error.o error_str.o fd_copy.o fd_move.o fmt_ulong.o \ @@ -731,10 +751,119 @@ taia_sub.o taia_uint.o 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 lock_ex.o \ - lock_un.o coe.o + lock_un.o coe.o socket_conn6.o socket_bind6.o socket_accept6.o socket_recv6.o \ + socket_send6.o socket_local6.o socket_remote6.o socket_tcp6.o \ + socket_getifname.o socket_getifidx.o socket_v4mappedprefix.o \ + socket_ip4loopback.o socket_v6any.o socket_v6loopback.o \ + socket_udp6.o scan_ip6.o ip6_fmt.o scan_xlong.o fmt_xlong.o \ + dns_ip6.o dns_sortip6.o dns_nd6.o dns_ipq6.o wait_nohang.o: compile wait_nohang.c haswaitp.h ./compile wait_nohang.c wait_pid.o: compile wait_pid.c error.h haswaitp.h ./compile wait_pid.c + +socket_conn6.o: \ +compile socket_conn6.c socket.h uint16.h haveip6.h error.h ip6.h \ +uint32.h + ./compile socket_conn6.c + +socket_bind6.o: \ +compile socket_bind6.c socket.h uint16.h haveip6.h error.h ip6.h \ +uint32.h + ./compile socket_bind6.c + +socket_accept6.o: \ +compile socket_accept6.c socket.h uint16.h haveip6.h error.h ip6.h \ +uint32.h + ./compile socket_accept6.c + +socket_recv6.o: \ +compile socket_recv6.c socket.h uint16.h haveip6.h error.h ip6.h \ +uint32.h + ./compile socket_recv6.c + +socket_send6.o: \ +compile socket_send6.c socket.h uint16.h haveip6.h error.h uint32.h + ./compile socket_send6.c + +socket_local6.o: \ +compile socket_local6.c socket.h uint16.h haveip6.h error.h uint32.h + ./compile socket_local6.c + +socket_remote6.o: \ +compile socket_remote6.c socket.h uint16.h haveip6.h error.h uint32.h + ./compile socket_remote6.c + +dns_sortip6.o: \ +compile dns_sortip6.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \ +taia.h tai.h uint64.h taia.h + ./compile dns_sortip6.c + +dns_nd6.o: \ +compile dns_nd6.c byte.h fmt.h dns.h stralloc.h gen_alloc.h iopause.h \ +taia.h tai.h uint64.h taia.h + ./compile dns_nd6.c + +dns_ipq6.o: \ +compile dns_ipq6.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 ip6.h + ./compile dns_ipq6.c + +dns_ip6.o: \ +compile dns_ip6.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_ip6.c + +fmt_xlong.o: \ +compile fmt_xlong.c scan.h + ./compile fmt_xlong.c + +scan_xlong.o: \ +compile scan_xlong.c scan.h + ./compile scan_xlong.c + +ip6_fmt.o: \ +compile ip6_fmt.c fmt.h ip6.h + ./compile ip6_fmt.c + +scan_ip6.o: \ +compile scan_ip6.c scan.h ip6.h + ./compile scan_ip6.c + +socket_tcp6.o: \ +compile socket_tcp6.c ndelay.h socket.h uint16.h haveip6.h uint32.h + ./compile socket_tcp6.c + +socket_udp6.o: \ +compile socket_udp6.c ndelay.h socket.h uint16.h haveip6.h uint32.h + ./compile socket_udp6.c + +haveip6.h: \ +tryip6.c choose compile haveip6.h1 haveip6.h2 + ./choose c tryip6 haveip6.h1 haveip6.h2 > haveip6.h + +socket_getifname.o: \ +compile socket_getifname.c socket.h uint16.h uint32.h + ./compile socket_getifname.c + +socket_getifidx.o: \ +compile socket_getifidx.c socket.h uint16.h uint32.h + ./compile socket_getifidx.c + +socket_ip4loopback.o: \ +compile socket_ip4loopback.c + ./compile socket_ip4loopback.c + +socket_v4mappedprefix.o: \ +compile socket_v4mappedprefix.c + ./compile socket_v4mappedprefix.c + +socket_v6any.o: \ +compile socket_v6any.c + ./compile socket_v6any.c + +socket_v6loopback.o: \ +compile socket_v6loopback.c + ./compile socket_v6loopback.c diff -Naur ucspi-ssl-0.70.orig/src/dns.h ucspi-ssl-0.70/src/dns.h --- ucspi-ssl-0.70.orig/src/dns.h 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/dns.h 2009-08-03 10:16:12.000000000 -0500 @@ -35,7 +35,8 @@ struct taia deadline; unsigned int pos; const char *servers; - char localip[4]; + char localip[16]; + unsigned int scope_id; char qtype[2]; } ; @@ -43,6 +44,7 @@ extern unsigned int dns_random(unsigned int); extern void dns_sortip(char *,unsigned int); +extern void dns_sortip6(char *,unsigned int); extern void dns_domain_free(char **); extern int dns_domain_copy(char **,const char *); @@ -68,6 +70,8 @@ extern int dns_ip4_packet(stralloc *,const char *,unsigned int); extern int dns_ip4(stralloc *,const stralloc *); +extern int dns_ip6_packet(stralloc *,const char *,unsigned int); +extern int dns_ip6(stralloc *,stralloc *); extern int dns_name_packet(stralloc *,const char *,unsigned int); extern void dns_name4_domain(char *,const char *); #define DNS_NAME4_DOMAIN 31 @@ -80,5 +84,10 @@ extern int dns_resolvconfrewrite(stralloc *); extern int dns_ip4_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *); extern int dns_ip4_qualify(stralloc *,stralloc *,const stralloc *); +extern int dns_ip6_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *); +extern int dns_ip6_qualify(stralloc *,stralloc *,const stralloc *); + +extern int dns_name6_domain(char*,char *); +#define DNS_NAME6_DOMAIN (4*16+11) #endif diff -Naur ucspi-ssl-0.70.orig/src/dns_ip6.c ucspi-ssl-0.70/src/dns_ip6.c --- ucspi-ssl-0.70.orig/src/dns_ip6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/dns_ip6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,103 @@ +#include "stralloc.h" +#include "uint16.h" +#include "byte.h" +#include "dns.h" +#include "ip4.h" +#include "ip6.h" + +static int dns_ip6_packet_add(stralloc *out,const char *buf,unsigned int len) +{ + unsigned int pos; + char header[16]; + uint16 numanswers; + uint16 datalen; + + 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_AAAA)) { + if (byte_equal(header + 2,2,DNS_C_IN)) + if (datalen == 16) { + if (!dns_packet_copy(buf,len,pos,header,16)) return -1; + if (!stralloc_catb(out,header,16)) return -1; + } + } else if (byte_equal(header,2,DNS_T_A)) + if (byte_equal(header + 2,2,DNS_C_IN)) + if (datalen == 4) { + byte_copy(header,12,V4mappedprefix); + if (!dns_packet_copy(buf,len,pos,header+12,4)) return -1; + if (!stralloc_catb(out,header,16)) return -1; + } + pos += datalen; + } + + dns_sortip6(out->s,out->len); + return 0; +} + +int dns_ip6_packet(stralloc *out,const char *buf,unsigned int len) { + if (!stralloc_copys(out,"")) return -1; + return dns_ip6_packet_add(out,buf,len); +} + +static char *q = 0; + +int dns_ip6(stralloc *out,stralloc *fqdn) +{ + unsigned int i; + char code; + char ch; + char ip[16]; + + if (!stralloc_copys(out,"")) return -1; + if (!stralloc_readyplus(fqdn,1)) return -1; + fqdn->s[fqdn->len]=0; + if ((i=scan_ip6(fqdn->s,ip))) { + if (fqdn->s[i]) return -1; + stralloc_copyb(out,ip,16); + return 0; + } + 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 (!stralloc_copys(out,"")) return -1; + if (dns_resolve(q,DNS_T_AAAA) != -1) + if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) { + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + } + if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1; + if (dns_resolve(q,DNS_T_A) != -1) + if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) { + dns_transmit_free(&dns_resolve_tx); + dns_domain_free(&q); + } + return out->a>0?0:-1; + } + + out->len &= ~3; + return 0; +} diff -Naur ucspi-ssl-0.70.orig/src/dns_ipq6.c ucspi-ssl-0.70/src/dns_ipq6.c --- ucspi-ssl-0.70.orig/src/dns_ipq6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/dns_ipq6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,72 @@ +#include "stralloc.h" +#include "case.h" +#include "byte.h" +#include "str.h" +#include "dns.h" + +static int doit(stralloc *work,const 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; + 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_ip6_qualify_rules(stralloc *out,stralloc *fqdn,const stralloc *in,const 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_ip6(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_ip6(out,fqdn) == -1) return -1; + if (out->len) return 0; + i += j; + if (i >= fqdnlen) return 0; + ++i; + } +} + +int dns_ip6_qualify(stralloc *out,stralloc *fqdn,const stralloc *in) +{ + static stralloc rules; + if (dns_resolvconfrewrite(&rules) == -1) return -1; + return dns_ip6_qualify_rules(out,fqdn,in,&rules); +} diff -Naur ucspi-ssl-0.70.orig/src/dns_name.c ucspi-ssl-0.70/src/dns_name.c --- ucspi-ssl-0.70.orig/src/dns_name.c 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/dns_name.c 2009-08-03 10:16:12.000000000 -0500 @@ -2,6 +2,7 @@ #include "uint16.h" #include "byte.h" #include "dns.h" +#include "ip6.h" static char *q = 0; @@ -46,3 +47,17 @@ dns_domain_free(&q); return 0; } + +int dns_name6(stralloc *out,char ip[16]) +{ + char name[DNS_NAME6_DOMAIN]; + + if (ip6_isv4mapped(ip)) + return dns_name4(out,ip+12); + dns_name6_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 -Naur ucspi-ssl-0.70.orig/src/dns_nd6.c ucspi-ssl-0.70/src/dns_nd6.c --- ucspi-ssl-0.70.orig/src/dns_nd6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/dns_nd6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,28 @@ +#include "byte.h" +#include "fmt.h" +#include "dns.h" + +/* RFC1886: + * 4321:0:1:2:3:4:567:89ab + * -> + * b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.INT. + */ + +static inline char tohex(char c) { + return c>=10?c-10+'a':c+'0'; +} + +int dns_name6_domain(char name[DNS_NAME6_DOMAIN],char ip[16]) +{ + unsigned int j; + + for (j=0; j<16; j++) { + name[j*4]=1; + name[j*4+1]=tohex(ip[15-j] & 15); + name[j*4+2]=1; + name[j*4+3]=tohex((unsigned char)ip[15-j] >> 4); + } + byte_copy(name + 4*16,10,"\3ip6\4arpa\0"); + return 4*16+10; +} + diff -Naur ucspi-ssl-0.70.orig/src/dns_rcip.c ucspi-ssl-0.70/src/dns_rcip.c --- ucspi-ssl-0.70.orig/src/dns_rcip.c 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/dns_rcip.c 2009-08-03 11:53:06.000000000 -0500 @@ -2,12 +2,13 @@ #include "openreadclose.h" #include "byte.h" #include "ip4.h" +#include "ip6.h" #include "env.h" #include "dns.h" static stralloc data = {0}; -static int init(char ip[64]) +static int init(char ip[256]) { int i; int j; @@ -20,10 +21,10 @@ if (*x == '.') ++x; else { - i = ip4_scan(x,ip + iplen); + i = scan_ip6(x,ip + iplen); if (!i) break; x += i; - iplen += 4; + iplen += 16; } } @@ -40,10 +41,8 @@ while ((data.s[i] == ' ') || (data.s[i] == '\t')) ++i; if (iplen <= 60) - if (ip4_scan(data.s + i,ip + iplen)) { - if (byte_equal(ip + iplen,4,"\0\0\0\0")) - byte_copy(ip + iplen,4,"\177\0\0\1"); - iplen += 4; + if (scan_ip6(data.s + i,ip + iplen)) { + iplen += 16; } } i = j + 1; @@ -52,19 +51,19 @@ } if (!iplen) { - byte_copy(ip,4,"\177\0\0\1"); - iplen = 4; + byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"); + iplen = 16; } - byte_zero(ip + iplen,64 - iplen); + byte_zero(ip + iplen,256 - iplen); return 0; } static int ok = 0; static unsigned int uses; static struct taia deadline; -static char ip[64]; /* defined if ok */ +static char ip[256]; /* defined if ok */ -int dns_resolvconfip(char s[64]) +int dns_resolvconfip(char s[256]) { struct taia now; @@ -81,6 +80,6 @@ } --uses; - byte_copy(s,64,ip); + byte_copy(s,256,ip); return 0; } diff -Naur ucspi-ssl-0.70.orig/src/dns_resolve.c ucspi-ssl-0.70/src/dns_resolve.c --- ucspi-ssl-0.70.orig/src/dns_resolve.c 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/dns_resolve.c 2009-08-03 10:16:12.000000000 -0500 @@ -2,6 +2,7 @@ #include "taia.h" #include "byte.h" #include "dns.h" +#include "ip6.h" struct dns_transmit dns_resolve_tx = {0}; @@ -9,12 +10,12 @@ { struct taia stamp; struct taia deadline; - char servers[64]; + char servers[256]; 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; + if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,V6any) == -1) return -1; for (;;) { taia_now(&stamp); diff -Naur ucspi-ssl-0.70.orig/src/dns_sortip6.c ucspi-ssl-0.70/src/dns_sortip6.c --- ucspi-ssl-0.70.orig/src/dns_sortip6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/dns_sortip6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,20 @@ +#include "byte.h" +#include "dns.h" + +/* XXX: sort servers by configurable notion of closeness? */ +/* XXX: pay attention to competence of each server? */ + +void dns_sortip6(char *s,unsigned int n) +{ + unsigned int i; + char tmp[16]; + + n >>= 4; + while (n > 1) { + i = dns_random(n); + --n; + byte_copy(tmp,16,s + (i << 4)); + byte_copy(s + (i << 4),16,s + (n << 4)); + byte_copy(s + (n << 4),16,tmp); + } +} diff -Naur ucspi-ssl-0.70.orig/src/dns_transmit.c ucspi-ssl-0.70/src/dns_transmit.c --- ucspi-ssl-0.70.orig/src/dns_transmit.c 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/dns_transmit.c 2009-08-03 10:16:12.000000000 -0500 @@ -7,6 +7,7 @@ #include "byte.h" #include "uint16.h" #include "dns.h" +#include "ip6.h" static int serverwantstcp(const char *buf,unsigned int len) { @@ -85,9 +86,9 @@ int j; for (j = 0;j < 10;++j) - if (socket_bind4(d->s1 - 1,d->localip,1025 + dns_random(64510)) == 0) + if (socket_bind6(d->s1 - 1,d->localip,1025 + dns_random(64510),d->scope_id) == 0) return 0; - if (socket_bind4(d->s1 - 1,d->localip,0) == 0) + if (socket_bind6(d->s1 - 1,d->localip,0,d->scope_id) == 0) return 0; return -1; } @@ -102,16 +103,16 @@ 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")) { + ip = d->servers + 16 * d->curserver; + if (byte_diff(ip,16,V6any)) { d->query[2] = dns_random(256); d->query[3] = dns_random(256); - d->s1 = 1 + socket_udp(); + d->s1 = 1 + socket_udp6(); 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 (socket_connect6(d->s1 - 1,ip,53,d->scope_id) == 0) if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) { struct taia now; taia_now(&now); @@ -153,19 +154,19 @@ packetfree(d); for (;d->curserver < 16;++d->curserver) { - ip = d->servers + 4 * d->curserver; - if (byte_diff(ip,4,"\0\0\0\0")) { + ip = d->servers + 16 * d->curserver; + if (byte_diff(ip,16,V6any)) { d->query[2] = dns_random(256); d->query[3] = dns_random(256); - d->s1 = 1 + socket_tcp(); + d->s1 = 1 + socket_tcp6(); 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) { + if (socket_connect6(d->s1 - 1,ip,53,d->scope_id) == 0) { d->tcpstate = 2; return 0; } @@ -193,7 +194,7 @@ return thistcp(d); } -int dns_transmit_start(struct dns_transmit *d,const char servers[64],int flagrecursive,const char *q,const char qtype[2],const char localip[4]) +int dns_transmit_start(struct dns_transmit *d,const char servers[256],int flagrecursive,const char *q,const char qtype[2],const char localip[16]) { unsigned int len; @@ -213,7 +214,7 @@ byte_copy(d->qtype,2,qtype); d->servers = servers; - byte_copy(d->localip,4,localip); + byte_copy(d->localip,16,localip); d->udploop = flagrecursive ? 1 : 0; diff -Naur ucspi-ssl-0.70.orig/src/fmt_xlong.c ucspi-ssl-0.70/src/fmt_xlong.c --- ucspi-ssl-0.70.orig/src/fmt_xlong.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/fmt_xlong.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,22 @@ +#include "fmt.h" + +char tohex(char num) { + if (num<10) + return num+'0'; + else if (num<16) + return num-10+'a'; + else + return -1; +} + +unsigned int fmt_xlong(register char *s,register unsigned long u) +{ + register unsigned int len; register unsigned long q; + len = 1; q = u; + while (q > 15) { ++len; q /= 16; } + if (s) { + s += len; + do { *--s = tohex(u % 16); u /= 16; } while(u); /* handles u == 0 */ + } + return len; +} diff -Naur ucspi-ssl-0.70.orig/src/haveip6.h1 ucspi-ssl-0.70/src/haveip6.h1 --- ucspi-ssl-0.70.orig/src/haveip6.h1 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/haveip6.h1 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1 @@ + diff -Naur ucspi-ssl-0.70.orig/src/haveip6.h2 ucspi-ssl-0.70/src/haveip6.h2 --- ucspi-ssl-0.70.orig/src/haveip6.h2 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/haveip6.h2 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1 @@ +#define LIBC_HAS_IP6 1 diff -Naur ucspi-ssl-0.70.orig/src/ip4.h ucspi-ssl-0.70/src/ip4.h --- ucspi-ssl-0.70.orig/src/ip4.h 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/ip4.h 2009-08-03 10:16:12.000000000 -0500 @@ -6,4 +6,6 @@ #define IP4_FMT 20 +extern const char ip4loopback[4]; /* = {127,0,0,1}' */ + #endif diff -Naur ucspi-ssl-0.70.orig/src/ip6.h ucspi-ssl-0.70/src/ip6.h --- ucspi-ssl-0.70.orig/src/ip6.h 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/ip6.h 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,28 @@ +#ifndef IP6_H +#define IP6_H + +#include "byte.h" + +extern unsigned int scan_ip6(const char *src,char *ip); +extern unsigned int fmt_ip6(char *dest,const char *ip); + +extern unsigned int scan_ip6_flat(const char *src,char *); +extern unsigned int fmt_ip6_flat(char *dest,const char *); + +/* + ip6 address syntax: (h = hex digit), no leading '0' required + 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh + 2. any number of 0000 may be abbreviated as "::", but only once + flat ip6 address syntax: + hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh + */ + +#define IP6_FMT 40 + +extern const unsigned char V4mappedprefix[12]; /*={0,0,0,0,0,0,0,0,0,0,0xff,0xff}; */ +extern const unsigned char V6loopback[16]; /*={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; */ +extern const unsigned char V6any[16]; /*={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; */ + +#define ip6_isv4mapped(ip) (byte_equal(ip,12,V4mappedprefix)) + +#endif diff -Naur ucspi-ssl-0.70.orig/src/ip6_fmt.c ucspi-ssl-0.70/src/ip6_fmt.c --- ucspi-ssl-0.70.orig/src/ip6_fmt.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/ip6_fmt.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,62 @@ +#include "fmt.h" +#include "byte.h" +#include "ip4.h" +#include "ip6.h" + +unsigned int ip6_fmt(char *s,char ip[16]) +{ + unsigned int len; + unsigned int i; + unsigned int temp; + unsigned int compressing; + int j; + + len = 0; compressing = 0; + for (j=0; j<16; j+=2) { + if (j==12 && ip6_isv4mapped(ip)) { + temp=ip4_fmt(s,ip+12); + len+=temp; + s+=temp; + break; + } + temp = ((unsigned long) (unsigned char) ip[j] << 8) + + (unsigned long) (unsigned char) ip[j+1]; + if (temp == 0) { + if (!compressing) { + compressing=1; + if (j==0) { + *s=':'; s+=1; ++len; + } + } + } else { + if (compressing) { + compressing=0; + *s=':'; s+=1; ++len; + } + i = fmt_xlong(s,temp); len += i; if (s) s += i; + if (s && j<14) { *s++ = ':'; ++len; } + } + } + + if (s) *s=0; + return len; +} + +static char tohex(char num) { + if (num<10) + return num+'0'; + else if (num<16) + return num-10+'a'; + else + return -1; +} + +unsigned int ip6_fmt_flat(char *s,char ip[16]) +{ + int i; + for (i=0; i<16; i++) { + *s++=tohex((unsigned char)ip[i] >> 4); + *s++=tohex((unsigned char)ip[i] & 15); + } + return 32; +} diff -Naur ucspi-ssl-0.70.orig/src/remoteinfo.h ucspi-ssl-0.70/src/remoteinfo.h --- ucspi-ssl-0.70.orig/src/remoteinfo.h 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/remoteinfo.h 2009-08-03 10:16:12.000000000 -0500 @@ -5,5 +5,6 @@ #include "uint16.h" extern int remoteinfo(stralloc *,char *,uint16,char *,uint16,unsigned int); +extern int remoteinfo6(stralloc *,char *,uint16,char *,uint16,unsigned int,uint32); #endif diff -Naur ucspi-ssl-0.70.orig/src/remoteinfo6.c ucspi-ssl-0.70/src/remoteinfo6.c --- ucspi-ssl-0.70.orig/src/remoteinfo6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/remoteinfo6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,98 @@ +#include "fmt.h" +#include "buffer.h" +#include "socket.h" +#include "error.h" +#include "iopause.h" +#include "timeoutconn.h" +#include "remoteinfo.h" + +static struct taia now; +static struct taia deadline; + +static int mywrite(int fd,char *buf,int len) +{ + iopause_fd x; + + x.fd = fd; + x.events = IOPAUSE_WRITE; + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; + if (taia_less(&deadline,&now)) { + errno = error_timeout; + return -1; + } + } + return write(fd,buf,len); +} + +static int myread(int fd,char *buf,int len) +{ + iopause_fd x; + + x.fd = fd; + x.events = IOPAUSE_READ; + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; + if (taia_less(&deadline,&now)) { + errno = error_timeout; + return -1; + } + } + return read(fd,buf,len); +} + +static int doit(stralloc *out,int s,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) +{ + buffer b; + char bspace[128]; + char strnum[FMT_ULONG]; + int numcolons; + char ch; + + if (socket_bind6(s,iplocal,0,netif) == -1) return -1; + if (timeoutconn6(s,ipremote,113,timeout,netif) == -1) return -1; + + buffer_init(&b,mywrite,s,bspace,sizeof bspace); + buffer_put(&b,strnum,fmt_ulong(strnum,portremote)); + buffer_put(&b," , ",3); + buffer_put(&b,strnum,fmt_ulong(strnum,portlocal)); + buffer_put(&b,"\r\n",2); + if (buffer_flush(&b) == -1) return -1; + + buffer_init(&b,myread,s,bspace,sizeof bspace); + numcolons = 0; + for (;;) { + if (buffer_get(&b,&ch,1) != 1) return -1; + if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue; + if (ch == '\n') return 0; + if (numcolons < 3) { + if (ch == ':') ++numcolons; + } + else { + if (!stralloc_append(out,&ch)) return -1; + if (out->len > 256) return 0; + } + } +} + +int remoteinfo6(stralloc *out,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) +{ + int s; + int r; + + if (!stralloc_copys(out,"")) return -1; + + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + + s = socket_tcp6(); + if (s == -1) return -1; + r = doit(out,s,ipremote,portremote,iplocal,portlocal,timeout,netif); + close(s); + return r; +} diff -Naur ucspi-ssl-0.70.orig/src/rules.c ucspi-ssl-0.70/src/rules.c --- ucspi-ssl-0.70.orig/src/rules.c 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/rules.c 2009-08-03 10:16:12.000000000 -0500 @@ -64,7 +64,7 @@ if (!stralloc_copys(&rules_name,ip)) return -1; while (rules_name.len > 0) { - if (ip[rules_name.len - 1] == '.') { + if (ip[rules_name.len - 1] == '.' || ip[rules_name.len - 1] == ':') { r = dorule(callback); if (r) return r; } diff -Naur ucspi-ssl-0.70.orig/src/scan_ip6.c ucspi-ssl-0.70/src/scan_ip6.c --- ucspi-ssl-0.70.orig/src/scan_ip6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/scan_ip6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,87 @@ +#include "scan.h" +#include "ip4.h" +#include "ip6.h" + +/* + * IPv6 addresses are really ugly to parse. + * Syntax: (h = hex digit) + * 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh + * 2. any number of 0000 may be abbreviated as "::", but only once + * 3. The last two words may be written as IPv4 address + */ + +unsigned int scan_ip6(const char *s,char ip[16]) +{ + unsigned int i; + unsigned int len=0; + unsigned long u; + + char suffix[16]; + int prefixlen=0; + int suffixlen=0; + + if ((i=ip4_scan((char*)s,ip+12))) { + for (len=0; len<12; ++len) ip[len]=V4mappedprefix[len]; + return i; + } + for (i=0; i<16; i++) ip[i]=0; + for (;;) { + if (*s == ':') { + len++; + if (s[1] == ':') { /* Found "::", skip to part 2 */ + s+=2; + len++; + break; + } + s++; + } + i = scan_xlong((char*)s,&u); + if (!i) return 0; + if (prefixlen==12 && s[i]=='.') { + /* the last 4 bytes may be written as IPv4 address */ + i=ip4_scan((char*)s,ip+12); + if (i) + return i+len; + else + return 0; + } + ip[prefixlen++] = (u >> 8); + ip[prefixlen++] = (u & 255); + s += i; len += i; + if (prefixlen==16) + return len; + } + +/* part 2, after "::" */ + for (;;) { + if (*s == ':') { + if (suffixlen==0) + break; + s++; + len++; + } else if (suffixlen!=0) + break; + i = scan_xlong((char*)s,&u); + if (!i) { + len--; + break; + } + if (suffixlen+prefixlen<=12 && s[i]=='.') { + int j=ip4_scan((char*)s,suffix+suffixlen); + if (j) { + suffixlen+=4; + len+=j; + break; + } else + prefixlen=12-suffixlen; /* make end-of-loop test true */ + } + suffix[suffixlen++] = (u >> 8); + suffix[suffixlen++] = (u & 255); + s += i; len += i; + if (prefixlen+suffixlen==16) + break; + } + for (i=0; i='0' && c<='9') + return c-'0'; + else if (c>='A' && c<='F') + return c-'A'+10; + else if (c>='a' && c<='f') + return c-'a'+10; + return -1; +} + +unsigned int scan_xlong(const char *src,unsigned long *dest) { + register const char *tmp=src; + register int l=0; + register unsigned char c; + while ((c=fromhex(*tmp))<16) { + l=(l<<4)+c; + ++tmp; + } + *dest=l; + return tmp-src; +} diff -Naur ucspi-ssl-0.70.orig/src/socket.h ucspi-ssl-0.70/src/socket.h --- ucspi-ssl-0.70.orig/src/socket.h 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/socket.h 2009-08-03 10:16:12.000000000 -0500 @@ -2,23 +2,53 @@ #define SOCKET_H #include "uint16.h" +#include "uint32.h" extern int socket_tcp(void); extern int socket_udp(void); +extern int socket_tcp6(void); +extern int socket_udp6(void); extern int socket_connect4(int,const char *,uint16); +extern int socket_connect6(int s,const char *ip,uint16 port,uint32 scope_id); extern int socket_connected(int); extern int socket_bind4(int,char *,uint16); extern int socket_bind4_reuse(int,char *,uint16); +extern int socket_bind6(int s,const char *ip,uint16 port,uint32 scope_id); +extern int socket_bind6_reuse(int s,const char *,uint16 port,uint32 scope_id); extern int socket_listen(int,int); extern int socket_accept4(int,char *,uint16 *); +extern int socket_accept6(int s,char *ip,uint16 *port,uint32 *scope_id); extern int socket_recv4(int,char *,int,char *,uint16 *); extern int socket_send4(int,const char *,int,const char *,uint16); +extern int socket_recv6(int s,char *buf,unsigned int len,char *ip,uint16 *port,uint32 *scope_id); +extern int socket_send6(int s,const char *buf,unsigned int len,const char *ip,uint16 port,uint32 scope_id); extern int socket_local4(int,char *,uint16 *); extern int socket_remote4(int,char *,uint16 *); +extern int socket_local6(int s,char *ip,uint16 *port,uint32 *scope_id); +extern int socket_remote6(int s,char *ip,uint16 *port,uint32 *scope_id); extern int socket_tcpnodelay(int); extern int socket_ipoptionskill(int); +/* enable sending udp packets to the broadcast address */ +extern int socket_broadcast(int); +/* join a multicast group on the given interface */ +extern int socket_mcjoin4(int,char *,char *); +extern int socket_mcjoin6(int,char *,int); +/* leave a multicast group on the given interface */ +extern int socket_mcleave4(int,char *); +extern int socket_mcleave6(int,char *); +/* set multicast TTL/hop count for outgoing packets */ +extern int socket_mcttl4(int,char); +extern int socket_mcttl6(int,char); +/* enable multicast loopback */ +extern int socket_mcloop4(int,char); +extern int socket_mcloop6(int,char); + +extern const char* socket_getifname(uint32 interface); +extern uint32 socket_getifidx(const char *ifname); + extern void socket_tryreservein(int,int); +extern int noipv6; #endif diff -Naur ucspi-ssl-0.70.orig/src/socket_accept6.c ucspi-ssl-0.70/src/socket_accept6.c --- ucspi-ssl-0.70.orig/src/socket_accept6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_accept6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip6.h" +#include "haveip6.h" +#include "error.h" + +int socket_accept6(int s,char ip[16],uint16 *port,uint32 *scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 sa; +#else + struct sockaddr_in sa; +#endif + unsigned int dummy = sizeof sa; + int fd; + + fd = accept(s,(struct sockaddr *) &sa,&dummy); + if (fd == -1) return -1; + +#ifdef LIBC_HAS_IP6 + if (sa.sin6_family==AF_INET) { + struct sockaddr_in *sa4=(struct sockaddr_in*)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa4->sin_addr); + uint16_unpack_big((char *) &sa4->sin_port,port); + return fd; + } + byte_copy(ip,16,(char *) &sa.sin6_addr); + uint16_unpack_big((char *) &sa.sin6_port,port); + if (scope_id) *scope_id=sa.sin6_scope_id; + + return fd; +#else + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa.sin_addr); + uint16_unpack_big((char *) &sa.sin_port,port); + if (scope_id) *scope_id=0; + return fd; +#endif +} diff -Naur ucspi-ssl-0.70.orig/src/socket_bind6.c ucspi-ssl-0.70/src/socket_bind6.c --- ucspi-ssl-0.70.orig/src/socket_bind6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_bind6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip6.h" +#include "haveip6.h" +#include "error.h" + +int socket_bind6(int s,const char ip[16],uint16 port,uint32 scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 sa; + + if (noipv6) { +#endif + int i; + for (i=0; i<16; i++) + if (ip[i]!=0) break; + if (i==16 || ip6_isv4mapped(ip)) + return socket_bind4(s,ip+12,port); +#ifdef LIBC_HAS_IP6 + } + byte_zero(&sa,sizeof sa); + sa.sin6_family = AF_INET6; + uint16_pack_big((char *) &sa.sin6_port,port); +/* implicit: sa.sin6_flowinfo = 0; */ + byte_copy((char *) &sa.sin6_addr,16,ip); + sa.sin6_scope_id=scope_id; + + return bind(s,(struct sockaddr *) &sa,sizeof sa); +#else + errno=error_proto; + return -1; +#endif +} + +int socket_bind6_reuse(int s,const char ip[16],uint16 port,uint32 scope_id) +{ + int opt = 1; + setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt); + return socket_bind6(s,ip,port,scope_id); +} + diff -Naur ucspi-ssl-0.70.orig/src/socket_conn6.c ucspi-ssl-0.70/src/socket_conn6.c --- ucspi-ssl-0.70.orig/src/socket_conn6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_conn6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip6.h" +#include "haveip6.h" +#include "uint32.h" +#include "ip4.h" + +int socket_connect6(int s,const char ip[16],uint16 port,uint32 scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 sa; + + if (noipv6) { +#endif + if (ip6_isv4mapped(ip)) + return socket_connect4(s,ip+12,port); + if (byte_equal(ip,16,V6loopback)) + return socket_connect4(s,ip4loopback,port); +#ifdef LIBC_HAS_IP6 + } + byte_zero(&sa,sizeof sa); + sa.sin6_family = PF_INET6; + uint16_pack_big((char *) &sa.sin6_port,port); + sa.sin6_flowinfo = 0; + sa.sin6_scope_id = scope_id; + byte_copy((char *) &sa.sin6_addr,16,ip); + + return connect(s,(struct sockaddr *) &sa,sizeof sa); +#else + errno=EPROTONOSUPPORT; + return -1; +#endif +} diff -Naur ucspi-ssl-0.70.orig/src/socket_getifidx.c ucspi-ssl-0.70/src/socket_getifidx.c --- ucspi-ssl-0.70.orig/src/socket_getifidx.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_getifidx.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,8 @@ +#include +#include +#include +#include "socket.h" + +uint32 socket_getifidx(const char* ifname) { + return if_nametoindex(ifname); +} diff -Naur ucspi-ssl-0.70.orig/src/socket_getifname.c ucspi-ssl-0.70/src/socket_getifname.c --- ucspi-ssl-0.70.orig/src/socket_getifname.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_getifname.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,14 @@ +#include +#include +#include +#include "socket.h" + +static char ifname[IFNAMSIZ]; + +const char* socket_getifname(uint32 interface) { + char *tmp=if_indextoname(interface,ifname); + if (tmp) + return tmp; + else + return "[unknown]"; +} diff -Naur ucspi-ssl-0.70.orig/src/socket_ip4loopback.c ucspi-ssl-0.70/src/socket_ip4loopback.c --- ucspi-ssl-0.70.orig/src/socket_ip4loopback.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_ip4loopback.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,2 @@ + +const char ip4loopback[4] = {127,0,0,1}; diff -Naur ucspi-ssl-0.70.orig/src/socket_local6.c ucspi-ssl-0.70/src/socket_local6.c --- ucspi-ssl-0.70.orig/src/socket_local6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_local6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip6.h" +#include "haveip6.h" +#include "error.h" + +int socket_local6(int s,char ip[16],uint16 *port,uint32 *scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 sa; +#else + struct sockaddr_in sa; +#endif + unsigned int dummy = sizeof sa; + + if (getsockname(s,(struct sockaddr *) &sa,&dummy) == -1) return -1; +#ifdef LIBC_HAS_IP6 + if (sa.sin6_family==AF_INET) { + struct sockaddr_in *sa4=(struct sockaddr_in*)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa4->sin_addr); + uint16_unpack_big((char *) &sa4->sin_port,port); + return 0; + } + byte_copy(ip,16,(char *) &sa.sin6_addr); + uint16_unpack_big((char *) &sa.sin6_port,port); + if (scope_id) *scope_id=sa.sin6_scope_id; +#else + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa.sin_addr); + uint16_unpack_big((char *) &sa.sin_port,port); + if (scope_id) *scope_id=0; +#endif + return 0; +} diff -Naur ucspi-ssl-0.70.orig/src/socket_recv6.c ucspi-ssl-0.70/src/socket_recv6.c --- ucspi-ssl-0.70.orig/src/socket_recv6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_recv6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip6.h" +#include "haveip6.h" +#include "error.h" + +int socket_recv6(int s,char *buf,unsigned int len,char ip[16],uint16 *port,uint32 *scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 sa; +#else + struct sockaddr_in sa; +#endif + unsigned int dummy = sizeof sa; + int r; + + byte_zero(&sa,dummy); + r = recvfrom(s,buf,len,0,(struct sockaddr *) &sa,&dummy); + if (r == -1) return -1; + +#ifdef LIBC_HAS_IP6 + if (noipv6) { + struct sockaddr_in *sa4=(struct sockaddr_in *)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa4->sin_addr); + uint16_unpack_big((char *) &sa4->sin_port,port); + return r; + } + byte_copy(ip,16,(char *) &sa.sin6_addr); + uint16_unpack_big((char *) &sa.sin6_port,port); + if (scope_id) *scope_id=sa.sin6_scope_id; +#else + byte_copy(ip,12,(char *)V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa.sin_addr); + uint16_unpack_big((char *) &sa.sin_port,port); + if (scope_id) *scope_id=0; +#endif + + return r; +} diff -Naur ucspi-ssl-0.70.orig/src/socket_remote6.c ucspi-ssl-0.70/src/socket_remote6.c --- ucspi-ssl-0.70.orig/src/socket_remote6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_remote6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip6.h" +#include "haveip6.h" +#include "error.h" + +int socket_remote6(int s,char ip[16],uint16 *port,uint32 *scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 sa; +#else + struct sockaddr_in sa; +#endif + unsigned int dummy = sizeof sa; + + if (getpeername(s,(struct sockaddr *) &sa,&dummy) == -1) return -1; +#ifdef LIBC_HAS_IP6 + if (sa.sin6_family==AF_INET) { + struct sockaddr_in *sa4=(struct sockaddr_in*)&sa; + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa4->sin_addr); + uint16_unpack_big((char *) &sa4->sin_port,port); + return 0; + } + byte_copy(ip,16,(char *) &sa.sin6_addr); + uint16_unpack_big((char *) &sa.sin6_port,port); + if (scope_id) *scope_id=sa.sin6_scope_id; +#else + byte_copy(ip,12,V4mappedprefix); + byte_copy(ip+12,4,(char *) &sa.sin_addr); + uint16_unpack_big((char *) &sa.sin_port,port); + if (scope_id) *scope_id=0; +#endif + return 0; +} diff -Naur ucspi-ssl-0.70.orig/src/socket_send6.c ucspi-ssl-0.70/src/socket_send6.c --- ucspi-ssl-0.70.orig/src/socket_send6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_send6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include "byte.h" +#include "socket.h" +#include "ip4.h" +#include "ip6.h" +#include "haveip6.h" +#include "error.h" + +int socket_send6(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id) +{ +#ifdef LIBC_HAS_IP6 + struct sockaddr_in6 sa; +#else + struct sockaddr_in sa; +#endif + + byte_zero(&sa,sizeof sa); +#ifdef LIBC_HAS_IP6 + if (noipv6) { +#endif + if (ip6_isv4mapped(ip)) + return socket_send4(s,buf,len,ip+12,port); + if (byte_equal(ip,16,V6loopback)) + return socket_send4(s,buf,len,ip4loopback,port); +#ifdef LIBC_HAS_IP6 + errno=error_proto; + return -1; + } + sa.sin6_family = AF_INET6; + uint16_pack_big((char *) &sa.sin6_port,port); + byte_copy((char *) &sa.sin6_addr,16,ip); + return sendto(s,buf,len,0,(struct sockaddr *) &sa,sizeof sa); +#else + errno=error_proto; + return -1; +#endif +} diff -Naur ucspi-ssl-0.70.orig/src/socket_tcp6.c ucspi-ssl-0.70/src/socket_tcp6.c --- ucspi-ssl-0.70.orig/src/socket_tcp6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_tcp6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include "ndelay.h" +#include "socket.h" +#include "haveip6.h" +#include "error.h" + +#ifdef LIBC_HAS_IP6 +int noipv6=0; +#else +int noipv6=1; +#endif + +int socket_tcp6(void) +{ +#ifdef LIBC_HAS_IP6 + int s; + + if (noipv6) goto compat; + s = socket(PF_INET6,SOCK_STREAM,0); + if (s == -1) { + if (errno == EINVAL || errno == EAFNOSUPPORT) { +compat: + s=socket(AF_INET,SOCK_STREAM,0); + noipv6=1; + if (s==-1) return -1; + } else + return -1; + } + if (ndelay_on(s) == -1) { close(s); return -1; } +#ifdef IPV6_V6ONLY + { + int zero=0; + setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&zero,sizeof(zero)); + } +#endif + return s; +#else + return socket_tcp(); +#endif +} diff -Naur ucspi-ssl-0.70.orig/src/socket_udp6.c ucspi-ssl-0.70/src/socket_udp6.c --- ucspi-ssl-0.70.orig/src/socket_udp6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_udp6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include "haveip6.h" +#include "socket.h" + +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT EINVAL +#endif + +int socket_udp6(void) +{ +#ifdef LIBC_HAS_IP6 + int s; + + if (noipv6) goto compat; + s = socket(PF_INET6,SOCK_DGRAM,0); + if (s == -1) { + if (errno == EINVAL || errno == EAFNOSUPPORT) { +compat: + s=socket(AF_INET,SOCK_DGRAM,0); + noipv6=1; + if (s==-1) return -1; + } else + return -1; + } +#ifdef IPV6_V6ONLY + { + int zero=0; + setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&zero,sizeof(zero)); + } +#endif + return s; +#else + return socket_udp(); +#endif +} diff -Naur ucspi-ssl-0.70.orig/src/socket_v4mappedprefix.c ucspi-ssl-0.70/src/socket_v4mappedprefix.c --- ucspi-ssl-0.70.orig/src/socket_v4mappedprefix.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_v4mappedprefix.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,2 @@ + +const unsigned char V4mappedprefix[12]={0,0,0,0,0,0,0,0,0,0,0xff,0xff}; diff -Naur ucspi-ssl-0.70.orig/src/socket_v6any.c ucspi-ssl-0.70/src/socket_v6any.c --- ucspi-ssl-0.70.orig/src/socket_v6any.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_v6any.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,2 @@ + +const unsigned char V6any[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; diff -Naur ucspi-ssl-0.70.orig/src/socket_v6loopback.c ucspi-ssl-0.70/src/socket_v6loopback.c --- ucspi-ssl-0.70.orig/src/socket_v6loopback.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/socket_v6loopback.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,2 @@ + +const unsigned char V6loopback[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; diff -Naur ucspi-ssl-0.70.orig/src/sslclient.c ucspi-ssl-0.70/src/sslclient.c --- ucspi-ssl-0.70.orig/src/sslclient.c 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/sslclient.c 2009-08-03 10:16:12.000000000 -0500 @@ -13,6 +13,7 @@ #include "scan.h" #include "str.h" #include "ip4.h" +#include "ip6.h" #include "uint16.h" #include "socket.h" #include "fd.h" @@ -48,12 +49,13 @@ } void usage(void) { strerr_die1x(100,"sslclient: usage: sslclient \ -[ -3hHrRdDqQveEsSnNxX ] \ +[ -463hHrRdDqQveEsSnNxX ] \ [ -i localip ] \ [ -p localport ] \ [ -T timeoutconn ] \ [ -l localname ] \ [ -t timeoutinfo ] \ +[ -I interface ] \ [ -a cafile ] \ [ -A cadir ] \ [ -c certfile ] \ @@ -64,6 +66,7 @@ host port program"); } +int forcev6 = 0; int verbosity = 1; int flagdelay = 0; int flagremoteinfo = 1; @@ -74,12 +77,13 @@ unsigned long itimeout = 26; unsigned long ctimeout[2] = { 2, 58 }; unsigned int progtimeout = 3600; +uint32 netif = 0; -char iplocal[4] = { 0,0,0,0 }; +char iplocal[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; uint16 portlocal = 0; const char *forcelocal = 0; -char ipremote[4]; +char ipremote[16]; uint16 portremote; const char *hostname; @@ -91,7 +95,7 @@ static stralloc tmp; static stralloc fqdn; char strnum[FMT_ULONG]; -char ipstr[IP4_FMT]; +char ipstr[IP6_FMT]; char seed[128]; @@ -131,6 +135,7 @@ } int main(int argc,char * const *argv) { + int fakev4=0; unsigned long u; int opt; const char *x; @@ -146,8 +151,10 @@ close(7); sig_ignore(sig_pipe); - while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:a:A:c:C:k:V:3eEsSnN0xXw:")) != opteof) + while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:a:A:c:C:k:V:463eEsSnN0xXw:I:")) != opteof) switch(opt) { + case '4': noipv6 = 1; break; + case '6': forcev6 = 1; break; case 'd': flagdelay = 1; break; case 'D': flagdelay = 0; break; case 'v': verbosity = 2; break; @@ -164,7 +171,8 @@ scan_ulong(optarg + j,&ctimeout[1]); break; case 'w': scan_uint(optarg,&progtimeout); break; - case 'i': if (!ip4_scan(optarg,iplocal)) usage(); break; + case 'i': if (!scan_ip6(optarg,iplocal)) usage(); break; + case 'I': netif=socket_getifidx(optarg); break; case 'p': scan_ulong(optarg,&u); portlocal = u; break; case 'a': cafile = optarg; break; case 'A': cadir = optarg; break; @@ -190,8 +198,8 @@ hostname = *argv; if (!hostname) usage(); - if (str_equal(hostname,"")) hostname = "127.0.0.1"; - if (str_equal(hostname,"0")) hostname = "127.0.0.1"; + if (!hostname[0] || str_equal(hostname, "0")) + hostname = (noipv6?"127.0.0.1":"::1"); x = *++argv; if (!x) usage(); @@ -217,12 +225,12 @@ if (!*++argv) usage(); if (!stralloc_copys(&tmp,hostname)) nomem(); - if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1) + if (dns_ip6_qualify(&addresses,&fqdn,&tmp) == -1) strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": "); - if (addresses.len < 4) + if (addresses.len < 16) strerr_die3x(111,FATAL,"no IP address for ",hostname); - if (addresses.len == 4) { + if (addresses.len == 16) { ctimeout[0] += ctimeout[1]; ctimeout[1] = 0; } @@ -230,21 +238,24 @@ s = -1; 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;j + 16 <= addresses.len;j += 4) { + s = socket_tcp6(); if (s == -1) strerr_die2sys(111,FATAL,"unable to create socket: "); - if (socket_bind4(s,iplocal,portlocal) == -1) + if (socket_bind6(s,iplocal,portlocal,netif) == -1) strerr_die2sys(111,FATAL,"unable to bind socket: "); - if (timeoutconn(s,addresses.s + j,portremote,ctimeout[cloop]) == 0) + if (timeoutconn6(s,addresses.s + j,portremote,ctimeout[cloop],netif) == 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,addresses.s + j,16)) nomem(); } else { strnum[fmt_ulong(strnum,portremote)] = 0; - ipstr[ip4_fmt(ipstr,addresses.s + j)] = 0; + if (ip6_isv4mapped(addresses.s+j)) + ipstr[ip4_fmt(ipstr,addresses.s + j + 12)] = 0; + else + ipstr[ip6_fmt(ipstr,addresses.s + j)] = 0; strerr_warn5(CONNECT,ipstr," port ",strnum,": ",&strerr_sys); } } @@ -255,34 +266,44 @@ CONNECTED: - env("PROTO","SSL"); - if (socket_local4(s,iplocal,&portlocal) == -1) + if (socket_local6(s,iplocal,&portlocal,&netif) == -1) strerr_die2sys(111,FATAL,"unable to get local address: "); + if (!forcev6 && (ip6_isv4mapped(iplocal) || byte_equal(iplocal,16,V6any))) + fakev4=1; + + env("PROTO",fakev4?"SSL":"SSL6"); + strnum[fmt_ulong(strnum,portlocal)] = 0; env("SSLLOCALPORT",strnum); if (flagtcpenv) env("TCPLOCALPORT",strnum); - ipstr[ip4_fmt(ipstr,iplocal)] = 0; + if (fakev4) + ipstr[ip4_fmt(ipstr,iplocal+12)] = 0; + else + ipstr[ip6_fmt(ipstr,iplocal)] = 0; env("SSLLOCALIP",ipstr); if (flagtcpenv) env("TCPLOCALIP",ipstr); x = forcelocal; if (!x) - if (dns_name4(&tmp,iplocal) == 0) { + if (dns_name6(&tmp,iplocal) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } env("SSLLOCALHOST",x); if (flagtcpenv) env("TCPLOCALHOST",x); - if (socket_remote4(s,ipremote,&portremote) == -1) + if (socket_remote6(s,ipremote,&portremote,&netif) == -1) strerr_die2sys(111,FATAL,"unable to get remote address: "); strnum[fmt_ulong(strnum,portremote)] = 0; env("SSLREMOTEPORT",strnum); if (flagtcpenv) env("TCPREMOTEPORT",strnum); - ipstr[ip4_fmt(ipstr,ipremote)] = 0; + if (fakev4) + ipstr[ip4_fmt(ipstr,ipremote+12)] = 0; + else + ipstr[ip6_fmt(ipstr,ipremote)] = 0; env("SSLREMOTEIP",ipstr); if (flagtcpenv) env("TCPREMOTEIP",ipstr); if (verbosity >= 2) @@ -290,7 +311,7 @@ x = 0; if (flagremotehost) - if (dns_name4(&tmp,ipremote) == 0) { + if (dns_name6(&tmp,ipremote) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } @@ -299,7 +320,7 @@ x = 0; if (flagremoteinfo) - if (remoteinfo(&tmp,ipremote,portremote,iplocal,portlocal,itimeout) == 0) { + if (remoteinfo6(&tmp,ipremote,portremote,iplocal,portlocal,itimeout,netif) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } diff -Naur ucspi-ssl-0.70.orig/src/sslserver.c ucspi-ssl-0.70/src/sslserver.c --- ucspi-ssl-0.70.orig/src/sslserver.c 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/sslserver.c 2009-08-03 11:54:22.000000000 -0500 @@ -12,6 +12,7 @@ #include "fmt.h" #include "scan.h" #include "ip4.h" +#include "ip6.h" #include "fd.h" #include "exit.h" #include "env.h" @@ -40,6 +41,7 @@ #include "auto_keyfile.h" #include "auto_ciphers.h" +int forcev6 = 0; int verbosity = 1; int flagkillopts = 1; int flagafter = 0; @@ -54,20 +56,21 @@ unsigned long timeout = 26; unsigned long ssltimeout = 26; unsigned int progtimeout = 3600; +uint32 netif = 0; static stralloc tcpremoteinfo; uint16 localport; char localportstr[FMT_ULONG]; -char localip[4]; -char localipstr[IP4_FMT]; +char localip[16]; +char localipstr[IP6_FMT]; static stralloc localhostsa; const char *localhost = 0; uint16 remoteport; char remoteportstr[FMT_ULONG]; -char remoteip[4]; -char remoteipstr[IP4_FMT]; +char remoteip[16]; +char remoteipstr[IP6_FMT]; static stralloc remotehostsa; char *remotehost = 0; char *verifyhost = 0; @@ -137,7 +140,7 @@ if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; if (ch == '%') ch = '?'; /* logger stupidity */ - if (ch == ':') ch = '?'; +/* if (ch == ':') ch = '?'; */ append(&ch); } cats("..."); @@ -177,75 +180,113 @@ } void doit(int t) { + int fakev4=0; int j; SSL *ssl; int wstat; + uint32 scope_id; - remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; + if (!forcev6 && ip6_isv4mapped(remoteip)) + fakev4=1; + if (fakev4) + remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0; + else + remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn4("sslserver: pid ",strnum," from ",remoteipstr,0); } - if (socket_local4(t,localip,&localport) == -1) + if (socket_local6(t,localip,&localport,&scope_id) == -1) strerr_die2sys(111,DROP,"unable to get local address: "); - - localipstr[ip4_fmt(localipstr,localip)] = 0; + + if (fakev4) + localipstr[ip4_fmt(localipstr,localip+12)] = 0; + else + localipstr[ip6_fmt(localipstr,localip)] = 0; remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; if (!localhost) - if (dns_name4(&localhostsa,localip) == 0) + if (dns_name6(&localhostsa,localip) == 0) if (localhostsa.len) { - if (!stralloc_0(&localhostsa)) drop_nomem(); - localhost = localhostsa.s; + if (!stralloc_0(&localhostsa)) drop_nomem(); + localhost = localhostsa.s; } - env("PROTO","SSL"); + + env("PROTO",fakev4?"SSL":"SSL6"); env("SSLLOCALIP",localipstr); + if (flagtcpenv) { + env("TCPLOCALIP",localipstr); + } + localipstr[ip6_fmt(localipstr,localip)]=0; + env("SSL6LOCALIP",localipstr); + env("SSLLOCALPORT",localportstr); + env("SSL6LOCALPORT",localportstr); env("SSLLOCALHOST",localhost); + env("SSL6LOCALHOST",localhost); + if (!fakev4 && scope_id) + env("SSL6INTERFACE",socket_getifname(scope_id)); + if (flagtcpenv) { - env("TCPLOCALIP",localipstr); + env("TCP6LOCALIP",localipstr); env("TCPLOCALPORT",localportstr); + env("TCP6LOCALPORT",localportstr); env("TCPLOCALHOST",localhost); + env("TCP6LOCALHOST",localhost); + if (!fakev4 && scope_id) + env("TCP6INTERFACE",socket_getifname(scope_id)); } if (flagremotehost) - if (dns_name4(&remotehostsa,remoteip) == 0) + if (dns_name6(&remotehostsa,remoteip) == 0) if (remotehostsa.len) { - if (flagparanoid) { - verifyhost = remoteipstr; - if (dns_ip4(&tmp,&remotehostsa) == 0) - for (j = 0;j + 4 <= tmp.len;j += 4) - if (byte_equal(remoteip,4,tmp.s + j)) { - flagparanoid = 0; - break; - } - } - if (!flagparanoid) { - if (!stralloc_0(&remotehostsa)) drop_nomem(); - remotehost = remotehostsa.s; - verifyhost = remotehostsa.s; - } + if (flagparanoid) { + verifyhost = remoteipstr; + if (dns_ip6(&tmp,&remotehostsa) == 0) + for (j = 0;j + 16 <= tmp.len;j += 16) + if (byte_equal(remoteip,16,tmp.s + j)) { + flagparanoid = 0; + break; + } + } + if (!flagparanoid) { + if (!stralloc_0(&remotehostsa)) drop_nomem(); + remotehost = remotehostsa.s; + verifyhost = remotehostsa.s; + } } env("SSLREMOTEIP",remoteipstr); + if (flagtcpenv) { + env("TCPREMOTEIP",remoteipstr); + } + remoteipstr[ip6_fmt(remoteipstr,remoteip)]=0; + env("SSL6REMOTEIP",remoteipstr); env("SSLREMOTEPORT",remoteportstr); + env("SSL6REMOTEPORT",remoteportstr); env("SSLREMOTEHOST",remotehost); + env("SSL6REMOTEHOST",remotehost); if (flagtcpenv) { - env("TCPREMOTEIP",remoteipstr); + env("TCP6REMOTEIP",remoteipstr); env("TCPREMOTEPORT",remoteportstr); + env("TCP6REMOTEPORT",remoteportstr); env("TCPREMOTEHOST",remotehost); + env("TCP6REMOTEHOST",remotehost); } if (flagremoteinfo) { - if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout) == -1) + if (remoteinfo6(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1) flagremoteinfo = 0; if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); } env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); - if (flagtcpenv) + env("SSL6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + if (flagtcpenv) { env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); - + env("TCP6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + } + if (fnrules) { int fdrules; fdrules = open_read(fnrules); @@ -254,8 +295,16 @@ if (!flagallownorules) drop_rules(); } else { - if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) - drop_rules(); + int fakev4 = 0; + char* temp; + if (!forcev6 && ip6_isv4mapped(remoteip)) + fakev4=1; + if (fakev4) + temp=remoteipstr+7; + else + temp=remoteipstr; + if (rules(found,fdrules,temp,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) + drop_rules(); close(fdrules); } } @@ -371,7 +420,7 @@ { strerr_warn1("\ sslserver: usage: sslserver \ -[ -13UXpPhHrRoOdDqQviIeEsS ] \ +[ -4613UXpPhHrRoOdDqQviIeEsS ] \ [ -c limit ] \ [ -x rules.cdb ] \ [ -B banner ] \ @@ -380,6 +429,7 @@ [ -b backlog ] \ [ -l localname ] \ [ -t timeout ] \ +[ -N interface ] \ [ -T ssltimeout ] \ [ -w progtimeout ] \ host port program",0); @@ -449,7 +499,7 @@ int s; int t; - while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:pPoO3IiEeSsaAw:")) != opteof) + while ((opt = getopt(argc,argv,"46dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:N:pPoO3iIEeSsaAw:")) != opteof) switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; @@ -476,9 +526,12 @@ x = env_get("GID"); if (x) scan_ulong(x,&gid); break; case 'u': scan_ulong(optarg,&uid); break; case 'g': scan_ulong(optarg,&gid); break; + case 'N': netif=socket_getifidx(optarg); break; case '1': flag1 = 1; break; case 'l': localhost = optarg; break; case '3': flag3 = 1; break; + case '4': noipv6 = 1; break; + case '6': forcev6 = 1; break; case 'I': flagclientcert = 0; break; case 'i': flagclientcert = 1; break; case 'S': flagsslenv = 0; break; @@ -497,8 +550,7 @@ 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 = "0"; x = *argv++; if (!x) usage(); @@ -510,7 +562,7 @@ se = getservbyname(x,"tcp"); if (!se) strerr_die3x(111,FATAL,"unable to figure out port number for ",x); - localport = ntohs(se->s_port); + uint16_unpack_big((char *)&se->s_port,&localport); } if (x = env_get("VERIFYDEPTH")) { @@ -545,22 +597,28 @@ 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); + if (str_equal(hostname,"0")) { + byte_zero(localip,sizeof localip); + } else { + if (!stralloc_copys(&tmp,hostname)) + strerr_die2x(111,FATAL,"out of memory"); + if (dns_ip6_qualify(&addresses,&fqdn,&tmp) == -1) + strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": "); + if (addresses.len < 16) + strerr_die3x(111,FATAL,"no IP address for ",hostname); + byte_copy(localip,16,addresses.s); + if(ip6_isv4mapped(localip)) + noipv6=1; + } - s = socket_tcp(); + s = socket_tcp6(); if (s == -1) strerr_die2sys(111,FATAL,"unable to create socket: "); - if (socket_bind4_reuse(s,localip,localport) == -1) + if (socket_bind6_reuse(s,localip,localport,netif) == -1) strerr_die2sys(111,FATAL,"unable to bind: "); - if (socket_local4(s,localip,&localport) == -1) + if (socket_local6(s,localip,&localport,&netif) == -1) strerr_die2sys(111,FATAL,"unable to get local address: "); if (socket_listen(s,backlog) == -1) strerr_die2sys(111,FATAL,"unable to listen: "); @@ -632,7 +690,7 @@ while (numchildren >= limit) sig_pause(); sig_unblock(sig_child); - t = socket_accept4(s,remoteip,&remoteport); + t = socket_accept6(s,remoteip,&remoteport,&netif); sig_block(sig_child); if (t == -1) continue; diff -Naur ucspi-ssl-0.70.orig/src/timeoutconn.h ucspi-ssl-0.70/src/timeoutconn.h --- ucspi-ssl-0.70.orig/src/timeoutconn.h 2009-08-03 10:15:47.000000000 -0500 +++ ucspi-ssl-0.70/src/timeoutconn.h 2009-08-03 10:16:12.000000000 -0500 @@ -2,7 +2,9 @@ #define TIMEOUTCONN_H #include "uint16.h" +#include "uint32.h" extern int timeoutconn(int,char *,uint16,unsigned int); +extern int timeoutconn6(int,char *,uint16,unsigned int,uint32); #endif diff -Naur ucspi-ssl-0.70.orig/src/timeoutconn6.c ucspi-ssl-0.70/src/timeoutconn6.c --- ucspi-ssl-0.70.orig/src/timeoutconn6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/timeoutconn6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,34 @@ +#include "ndelay.h" +#include "socket.h" +#include "iopause.h" +#include "error.h" +#include "timeoutconn.h" + +int timeoutconn6(int s,char ip[16],uint16 port,unsigned int timeout,uint32 netif) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + + if (socket_connect6(s,ip,port,netif) == -1) { + if ((errno != error_wouldblock) && (errno != error_inprogress)) return -1; + x.fd = s; + x.events = IOPAUSE_WRITE; + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + for (;;) { + taia_now(&now); + iopause(&x,1,&deadline,&now); + if (x.revents) break; + if (taia_less(&deadline,&now)) { + errno = error_timeout; /* note that connect attempt is continuing */ + return -1; + } + } + if (!socket_connected(s)) return -1; + } + + if (ndelay_off(s) == -1) return -1; + return 0; +} diff -Naur ucspi-ssl-0.70.orig/src/tryip6.c ucspi-ssl-0.70/src/tryip6.c --- ucspi-ssl-0.70.orig/src/tryip6.c 1969-12-31 18:00:00.000000000 -0600 +++ ucspi-ssl-0.70/src/tryip6.c 2009-08-03 10:16:12.000000000 -0500 @@ -0,0 +1,8 @@ +#include +#include +#include + +main() { + struct sockaddr_in6 sa; + sa.sin6_family = PF_INET6; +}