From 9aa998757a8736cef02fd92050eacbb2a6fb5180 Mon Sep 17 00:00:00 2001 From: John Denker Date: Thu, 26 Jul 2012 10:57:13 -0700 Subject: patch to support IPv6 in tcpserver --- ucspi-tcp-0.88/tcpclient.c | 73 +++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 26 deletions(-) (limited to 'ucspi-tcp-0.88/tcpclient.c') diff --git a/ucspi-tcp-0.88/tcpclient.c b/ucspi-tcp-0.88/tcpclient.c index 9f6d7f2..77b1ad5 100644 --- a/ucspi-tcp-0.88/tcpclient.c +++ b/ucspi-tcp-0.88/tcpclient.c @@ -9,6 +9,7 @@ #include "scan.h" #include "str.h" #include "ip4.h" +#include "ip6.h" #include "uint16.h" #include "socket.h" #include "fd.h" @@ -20,6 +21,7 @@ #include "timeoutconn.h" #include "remoteinfo.h" #include "dns.h" +#include "byte.h" #define FATAL "tcpclient: fatal: " #define CONNECT "tcpclient: unable to connect to " @@ -31,27 +33,30 @@ void nomem(void) void usage(void) { strerr_die1x(100,"tcpclient: usage: tcpclient \ -[ -hHrRdDqQv ] \ +[ -46hHrRdDqQv ] \ [ -i localip ] \ [ -p localport ] \ [ -T timeoutconn ] \ [ -l localname ] \ [ -t timeoutinfo ] \ +[ -I interface ] \ host port program"); } +int forcev6 = 0; int verbosity = 1; int flagdelay = 1; int flagremoteinfo = 1; int flagremotehost = 1; unsigned long itimeout = 26; unsigned long ctimeout[2] = { 2, 58 }; +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; char *forcelocal = 0; -char ipremote[4]; +char ipremote[16]; uint16 portremote; char *hostname; @@ -61,12 +66,13 @@ static stralloc moreaddresses; static stralloc tmp; static stralloc fqdn; char strnum[FMT_ULONG]; -char ipstr[IP4_FMT]; +char ipstr[IP6_FMT]; char seed[128]; main(int argc,char **argv) { + int fakev4=0; unsigned long u; int opt; char *x; @@ -80,8 +86,10 @@ main(int argc,char **argv) close(7); sig_ignore(sig_pipe); - while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:")) != opteof) + while ((opt = getopt(argc,argv,"46dDvqQhHrRi:p:t:T:l: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; @@ -97,7 +105,8 @@ main(int argc,char **argv) if (optarg[j] == '+') ++j; scan_ulong(optarg + j,&ctimeout[1]); 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; default: usage(); } @@ -108,8 +117,8 @@ main(int argc,char **argv) 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(); @@ -127,33 +136,36 @@ main(int argc,char **argv) 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; } 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); } } @@ -169,37 +181,46 @@ main(int argc,char **argv) if (!flagdelay) socket_tcpnodelay(s); /* if it fails, bummer */ - if (!pathexec_env("PROTO","TCP")) nomem(); - - 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; + + if (!pathexec_env("PROTO",fakev4?"TCP":"TCP6")) nomem(); + strnum[fmt_ulong(strnum,portlocal)] = 0; if (!pathexec_env("TCPLOCALPORT",strnum)) nomem(); - ipstr[ip4_fmt(ipstr,iplocal)] = 0; + if (fakev4) + ipstr[ip4_fmt(ipstr,iplocal+12)] = 0; + else + ipstr[ip6_fmt(ipstr,iplocal)] = 0; if (!pathexec_env("TCPLOCALIP",ipstr)) nomem(); x = forcelocal; if (!x) - if (dns_name4(&tmp,iplocal) == 0) { + if (dns_name6(&tmp,iplocal) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } if (!pathexec_env("TCPLOCALHOST",x)) nomem(); - 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; if (!pathexec_env("TCPREMOTEPORT",strnum)) nomem(); - ipstr[ip4_fmt(ipstr,ipremote)] = 0; + if (fakev4) + ipstr[ip4_fmt(ipstr,ipremote+12)] = 0; + else + ipstr[ip6_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 (dns_name6(&tmp,ipremote) == 0) { if (!stralloc_0(&tmp)) nomem(); x = tmp.s; } @@ -207,7 +228,7 @@ main(int argc,char **argv) 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; } -- cgit v1.2.3