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/tcpserver.c | 112 +++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 35 deletions(-) (limited to 'ucspi-tcp-0.88/tcpserver.c') diff --git a/ucspi-tcp-0.88/tcpserver.c b/ucspi-tcp-0.88/tcpserver.c index 979a0be..aab637f 100644 --- a/ucspi-tcp-0.88/tcpserver.c +++ b/ucspi-tcp-0.88/tcpserver.c @@ -7,6 +7,7 @@ #include "fmt.h" #include "scan.h" #include "ip4.h" +#include "ip6.h" #include "fd.h" #include "exit.h" #include "env.h" @@ -28,6 +29,7 @@ #include "sig.h" #include "dns.h" +int forcev6 = 0; int verbosity = 1; int flagkillopts = 1; int flagdelay = 1; @@ -36,20 +38,21 @@ int flagremoteinfo = 1; int flagremotehost = 1; int flagparanoid = 0; unsigned long timeout = 26; +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; 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; @@ -96,12 +99,12 @@ void safecats(char *s) if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; if (ch == '%') ch = '?'; /* logger stupidity */ - if (ch == ':') ch = '?'; +/* if (ch == ':') ch = '?'; */ append(&ch); } cats("..."); } -void env(char *s,char *t) +void env(const char *s,const char *t) { if (!pathexec_env(s,t)) drop_nomem(); } @@ -135,9 +138,16 @@ void found(char *data,unsigned int datalen) void doit(int t) { + int fakev4=0; int j; + 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; @@ -155,30 +165,40 @@ void doit(int t) strerr_die2sys(111,DROP,"unable to print banner: "); } - 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; } - env("PROTO","TCP"); + env("PROTO",fakev4?"TCP":"TCP6"); env("TCPLOCALIP",localipstr); + localipstr[ip6_fmt(localipstr,localip)]=0; + 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) - if (dns_ip4(&tmp,&remotehostsa) == 0) - for (j = 0;j + 4 <= tmp.len;j += 4) - if (byte_equal(remoteip,4,tmp.s + j)) { + 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; } @@ -188,15 +208,20 @@ void doit(int t) } } env("TCPREMOTEIP",remoteipstr); + remoteipstr[ip6_fmt(remoteipstr,remoteip)]=0; + 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("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + env("TCP6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (fnrules) { int fdrules; @@ -206,7 +231,15 @@ void doit(int t) 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); } } @@ -240,7 +273,7 @@ void usage(void) { strerr_warn1("\ tcpserver: usage: tcpserver \ -[ -1UXpPhHrRoOdDqQv ] \ +[ -461UXpPhHrRoOdDqQv ] \ [ -c limit ] \ [ -x rules.cdb ] \ [ -B banner ] \ @@ -249,6 +282,7 @@ tcpserver: usage: tcpserver \ [ -b backlog ] \ [ -l localname ] \ [ -t timeout ] \ +[ -I interface ] \ host port program",0); _exit(100); } @@ -299,8 +333,8 @@ main(int argc,char **argv) unsigned long u; int s; int t; - - while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof) + + while ((opt = getopt(argc,argv,"46dDvqQhHrR1UXx:t:u:g:l:b:B:c:I:pPoO")) != opteof) switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; @@ -325,7 +359,10 @@ main(int argc,char **argv) 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 'I': netif=socket_getifidx(optarg); break; case '1': flag1 = 1; break; + case '4': noipv6 = 1; break; + case '6': forcev6 = 1; break; case 'l': localhost = optarg; break; default: usage(); } @@ -337,8 +374,7 @@ main(int argc,char **argv) 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(); @@ -348,7 +384,7 @@ main(int argc,char **argv) 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 (!*argv) usage(); @@ -358,20 +394,26 @@ main(int argc,char **argv) 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 (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_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: "); @@ -399,7 +441,7 @@ main(int argc,char **argv) 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; -- cgit v1.2.3