diff options
author | John Denker <jsd@av8n.com> | 2012-07-31 22:34:58 -0700 |
---|---|---|
committer | John Denker <jsd@av8n.com> | 2012-07-31 22:36:28 -0700 |
commit | ef6722750b4518fcb29bf983755b5f02451ef224 (patch) | |
tree | 966e94ffd01cd8abb59e16a6992e142db345aa9f | |
parent | b95f5ec1d83519c603f6e2145865c14932c4a813 (diff) |
a bunch of files added by the ipv6 patch
33 files changed, 2169 insertions, 0 deletions
diff --git a/ucspi-tcp-0.88/ip6_fmt.c b/ucspi-tcp-0.88/ip6_fmt.c new file mode 100644 index 0000000..d7c010a --- /dev/null +++ b/ucspi-tcp-0.88/ip6_fmt.c @@ -0,0 +1,64 @@ +#include "fmt.h" +#include "byte.h" +#include "ip4.h" +#include "ip6.h" + +unsigned int ip6_fmt(char *s,char ip[16]) +{ + unsigned long len,temp, k, pos0=0,len0=0, pos1=0, compr=0; + + for (k=0; k<16; k+=2) { + if (ip[k]==0 && ip[k+1]==0) { + if (!compr) { + compr=1; + pos1=k; + } + if (k==14) { k=16; goto last; } + } else if (compr) { + last: + if ((temp=k-pos1) > len0) { + len0=temp; + pos0=pos1; + } + compr=0; + } + } + + for (len=0,k=0; k<16; k+=2) { + if (k==12 && ip6_isv4mapped(ip)) { + len += ip4_fmt(s,ip+12); + break; + } + if (pos0==k && len0) { + if (k==0) { ++len; if (s) *s++ = ':'; } + ++len; if (s) *s++ = ':'; + k += len0-2; + continue; + } + temp = ((unsigned long) (unsigned char) ip[k] << 8) + + (unsigned long) (unsigned char) ip[k+1]; + temp = fmt_xlong(s,temp); len += temp; if (s) s += temp; + if (k<14) { ++len; if (s) *s++ = ':'; } + } + + 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 --git a/ucspi-tcp-0.88/mconnect.1 b/ucspi-tcp-0.88/mconnect.1 new file mode 100644 index 0000000..6648367 --- /dev/null +++ b/ucspi-tcp-0.88/mconnect.1 @@ -0,0 +1,36 @@ +.TH mconnect 1 +.SH NAME +mconnect \- connect to the SMTP server on a host +.SH SYNTAX +.B mconnect +[ +.I host +[ +.I port +] +] +.SH DESCRIPTION +.B mconnect +connects to +.I port +on +.IR host . +It sends its input to +.IR host , +adding a CR to each line. +Meanwhile it prints anything it receives from +.IR host . + +If +.I port +is not supplied, +.B mconnect +uses port 25 (SMTP). + +If +.I host +is not supplied, +.B mconnect +connects to the local host. +.SH "SEE ALSO" +tcpclient(1) diff --git a/ucspi-tcp-0.88/old-rules.c b/ucspi-tcp-0.88/old-rules.c new file mode 100644 index 0000000..7225115 --- /dev/null +++ b/ucspi-tcp-0.88/old-rules.c @@ -0,0 +1,101 @@ +#include "alloc.h" +#include "stralloc.h" +#include "open.h" +#include "cdb.h" +#include "rules.h" + +stralloc rules_name = {0}; + +static struct cdb c; + +static int dorule(void (*callback)(char *,unsigned int)) +{ + char *data; + unsigned int datalen; + + switch(cdb_find(&c,rules_name.s,rules_name.len)) { + case -1: return -1; + case 0: return 0; + } + + datalen = cdb_datalen(&c); + data = alloc(datalen); + if (!data) return -1; + if (cdb_read(&c,data,datalen,cdb_datapos(&c)) == -1) { + alloc_free(data); + return -1; + } + + callback(data,datalen); + alloc_free(data); + return 1; +} + +static int doit(void (*callback)(char *,unsigned int),char *ip,char *host,char *info) +{ + int r; + + 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; + r = dorule(callback); + if (r) return r; + + if (host) { + if (!stralloc_copys(&rules_name,info)) return -1; + if (!stralloc_cats(&rules_name,"@=")) return -1; + if (!stralloc_cats(&rules_name,host)) return -1; + r = dorule(callback); + if (r) return r; + } + } + + if (!stralloc_copys(&rules_name,ip)) return -1; + r = dorule(callback); + if (r) return r; + + if (host) { + if (!stralloc_copys(&rules_name,"=")) return -1; + if (!stralloc_cats(&rules_name,host)) return -1; + r = dorule(callback); + if (r) return r; + } + + if (!stralloc_copys(&rules_name,ip)) return -1; + while (rules_name.len > 0) { + if (ip[rules_name.len - 1] == '.' || + (ip[rules_name.len-1]==':' && rules_name.len>1)) { + r = dorule(callback); + if (r) return r; + } + --rules_name.len; + } + + if (host) { + while (*host) { + if (*host == '.') { + if (!stralloc_copys(&rules_name,"=")) return -1; + if (!stralloc_cats(&rules_name,host)) return -1; + r = dorule(callback); + if (r) return r; + } + ++host; + } + if (!stralloc_copys(&rules_name,"=")) return -1; + r = dorule(callback); + if (r) return r; + } + + rules_name.len = 0; + return dorule(callback); +} + +int rules(void (*callback)(char *,unsigned int),int fd,char *ip,char *host,char *info) +{ + int r; + cdb_init(&c,fd); + r = doit(callback,ip,host,info); + cdb_free(&c); + return r; +} diff --git a/ucspi-tcp-0.88/recordio.1 b/ucspi-tcp-0.88/recordio.1 new file mode 100644 index 0000000..e056776 --- /dev/null +++ b/ucspi-tcp-0.88/recordio.1 @@ -0,0 +1,75 @@ +.TH recordio 1 +.SH NAME +recordio \- record the input and output of a program +.SH SYNTAX +.B recordio +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B recordio +runs +.I program +with the given arguments. +It prints lines to stderr +showing the input and output of +.IR program . + +At the beginning of each line on stderr, +.B recordio +inserts the +.I program +process ID, +along with +.B < +for input or +.B > +for output. +At the end of each line it inserts a space, a plus sign, or [EOF]; +a space indicates that there was a newline in the input or output, +and [EOF] indicates the end of input or output. + +.B recordio +prints every packet of input and output immediately. +It does not attempt to combine packets into coherent stderr lines. +For example, + +.EX + recordio sh -c 'cat /dev/fd/8 2>&1' > /dev/null +.EE + +could produce + +.EX + 5135 > cat: /dev/fd/8: Bad file descriptor +.br + 5135 > [EOF] +.EE + +or + +.EX + 5135 > cat: + +.br + 5135 > /dev/fd/8+ +.br + 5135 > : + +.br + 5135 > Bad file descriptor +.br + 5135 > [EOF] +.EE + +.B recordio +uses several lines for long packets +to guarantee that each line is printed atomically to stderr. + +.B recordio +runs as a child of +.IR program . +It exits when it sees the end of +.IR program 's +output. +.SH "SEE ALSO" +tcpserver(1) diff --git a/ucspi-tcp-0.88/remoteinfo6.c b/ucspi-tcp-0.88/remoteinfo6.c new file mode 100644 index 0000000..cf3b7c1 --- /dev/null +++ b/ucspi-tcp-0.88/remoteinfo6.c @@ -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 --git a/ucspi-tcp-0.88/scan_ip6.c b/ucspi-tcp-0.88/scan_ip6.c new file mode 100644 index 0000000..ee239fd --- /dev/null +++ b/ucspi-tcp-0.88/scan_ip6.c @@ -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<suffixlen; i++) + ip[16-suffixlen+i] = suffix[i]; + return len; +} diff --git a/ucspi-tcp-0.88/scan_xlong.c b/ucspi-tcp-0.88/scan_xlong.c new file mode 100644 index 0000000..6e46d74 --- /dev/null +++ b/ucspi-tcp-0.88/scan_xlong.c @@ -0,0 +1,23 @@ +#include "scan.h" + +static int fromhex(unsigned char c) { + if (c>='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(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 --git a/ucspi-tcp-0.88/socket_accept6.c b/ucspi-tcp-0.88/socket_accept6.c new file mode 100644 index 0000000..a8a9a07 --- /dev/null +++ b/ucspi-tcp-0.88/socket_accept6.c @@ -0,0 +1,44 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#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 --git a/ucspi-tcp-0.88/socket_bind6.c b/ucspi-tcp-0.88/socket_bind6.c new file mode 100644 index 0000000..8a5a7cd --- /dev/null +++ b/ucspi-tcp-0.88/socket_bind6.c @@ -0,0 +1,45 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#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 --git a/ucspi-tcp-0.88/socket_conn6.c b/ucspi-tcp-0.88/socket_conn6.c new file mode 100644 index 0000000..0ad886d --- /dev/null +++ b/ucspi-tcp-0.88/socket_conn6.c @@ -0,0 +1,38 @@ +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <errno.h> +#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 --git a/ucspi-tcp-0.88/socket_getifidx.c b/ucspi-tcp-0.88/socket_getifidx.c new file mode 100644 index 0000000..452d6d7 --- /dev/null +++ b/ucspi-tcp-0.88/socket_getifidx.c @@ -0,0 +1,8 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <net/if.h> +#include "socket.h" + +uint32 socket_getifidx(const char* ifname) { + return if_nametoindex(ifname); +} diff --git a/ucspi-tcp-0.88/socket_getifname.c b/ucspi-tcp-0.88/socket_getifname.c new file mode 100644 index 0000000..77edff9 --- /dev/null +++ b/ucspi-tcp-0.88/socket_getifname.c @@ -0,0 +1,14 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <net/if.h> +#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 --git a/ucspi-tcp-0.88/socket_ip4loopback.c b/ucspi-tcp-0.88/socket_ip4loopback.c new file mode 100644 index 0000000..1bbbe95 --- /dev/null +++ b/ucspi-tcp-0.88/socket_ip4loopback.c @@ -0,0 +1,2 @@ + +const char ip4loopback[4] = {127,0,0,1}; diff --git a/ucspi-tcp-0.88/socket_local6.c b/ucspi-tcp-0.88/socket_local6.c new file mode 100644 index 0000000..23427c3 --- /dev/null +++ b/ucspi-tcp-0.88/socket_local6.c @@ -0,0 +1,39 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#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 --git a/ucspi-tcp-0.88/socket_recv6.c b/ucspi-tcp-0.88/socket_recv6.c new file mode 100644 index 0000000..a86ca96 --- /dev/null +++ b/ucspi-tcp-0.88/socket_recv6.c @@ -0,0 +1,44 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#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 --git a/ucspi-tcp-0.88/socket_remote6.c b/ucspi-tcp-0.88/socket_remote6.c new file mode 100644 index 0000000..e60a539 --- /dev/null +++ b/ucspi-tcp-0.88/socket_remote6.c @@ -0,0 +1,39 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#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 --git a/ucspi-tcp-0.88/socket_send6.c b/ucspi-tcp-0.88/socket_send6.c new file mode 100644 index 0000000..4b2d1e8 --- /dev/null +++ b/ucspi-tcp-0.88/socket_send6.c @@ -0,0 +1,40 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#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 --git a/ucspi-tcp-0.88/socket_tcp6.c b/ucspi-tcp-0.88/socket_tcp6.c new file mode 100644 index 0000000..74099e2 --- /dev/null +++ b/ucspi-tcp-0.88/socket_tcp6.c @@ -0,0 +1,44 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <errno.h> +#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 --git a/ucspi-tcp-0.88/socket_udp6.c b/ucspi-tcp-0.88/socket_udp6.c new file mode 100644 index 0000000..3769b1d --- /dev/null +++ b/ucspi-tcp-0.88/socket_udp6.c @@ -0,0 +1,38 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <errno.h> +#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 --git a/ucspi-tcp-0.88/socket_v4mappedprefix.c b/ucspi-tcp-0.88/socket_v4mappedprefix.c new file mode 100644 index 0000000..dbed824 --- /dev/null +++ b/ucspi-tcp-0.88/socket_v4mappedprefix.c @@ -0,0 +1,2 @@ + +const unsigned char V4mappedprefix[12]={0,0,0,0,0,0,0,0,0,0,0xff,0xff}; diff --git a/ucspi-tcp-0.88/socket_v6any.c b/ucspi-tcp-0.88/socket_v6any.c new file mode 100644 index 0000000..c6d0cbb --- /dev/null +++ b/ucspi-tcp-0.88/socket_v6any.c @@ -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 --git a/ucspi-tcp-0.88/socket_v6loopback.c b/ucspi-tcp-0.88/socket_v6loopback.c new file mode 100644 index 0000000..b81ee65 --- /dev/null +++ b/ucspi-tcp-0.88/socket_v6loopback.c @@ -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 --git a/ucspi-tcp-0.88/tcp-environ.5 b/ucspi-tcp-0.88/tcp-environ.5 new file mode 100644 index 0000000..fecad70 --- /dev/null +++ b/ucspi-tcp-0.88/tcp-environ.5 @@ -0,0 +1,66 @@ +.TH tcp-environ 5 +.SH NAME +tcp-environ \- TCP-related environment variables +.SH DESCRIPTION +The following environment variables +describe a TCP connection. +They are set up by +.BR tcp-env , +.BR tcpclient , +and +.BR tcpserver . +Note that +.BR TCPLOCALHOST , +.BR TCPREMOTEHOST , +and +.B TCPREMOTEINFO +can contain arbitrary characters. +.TP 5 +PROTO +The string +.BR TCP . +.TP 5 +TCPLOCALHOST +The domain name of the local host, +with uppercase letters converted to lowercase. +If there is no currently available domain name +for the local IP address, +.B TCPLOCALHOST +is not set. +.TP 5 +TCPLOCALIP +The IP address of the local host, in dotted-decimal form. +.TP 5 +TCPLOCALPORT +The local TCP port number, in decimal. +.TP 5 +TCPREMOTEHOST +The domain name of the remote host, +with uppercase letters converted to lowercase. +If there is no currently available domain name +for the remote IP address, +.B TCPREMOTEHOST +is not set. +.TP 5 +TCPREMOTEINFO +A connection-specific string, perhaps a username, +supplied by the remote host +via 931/1413/IDENT/TAP. +If the remote host did not supply connection information, +.B TCPREMOTEINFO +is not set. +.TP 5 +TCPREMOTEIP +The IP address of the remote host. +.TP 5 +TCPREMOTEPORT +The remote TCP port number. +.TP 5 +TCPINTERFACE +The interface name ("eth0") for IPv6 connections using link-local +addresses. +.SH "SEE ALSO" +tcpclient(1), +tcpserver(1), +tcp-env(1), +tcp(4) diff --git a/ucspi-tcp-0.88/tcpcat.1 b/ucspi-tcp-0.88/tcpcat.1 new file mode 100644 index 0000000..4c51ed5 --- /dev/null +++ b/ucspi-tcp-0.88/tcpcat.1 @@ -0,0 +1,20 @@ +.TH tcpcat 1 +.SH NAME +tcpcat \- print data from a TCP port +.SH SYNTAX +.B tcpcat +.I host +.I port +.SH DESCRIPTION +.B tcpcat +connects to +.I port +on +.I host +and prints any data it receives. + +.B tcpcat +can be used to transfer binary data. +It does no conversions. +.SH "SEE ALSO" +tcpclient(1) diff --git a/ucspi-tcp-0.88/tcpclient.1 b/ucspi-tcp-0.88/tcpclient.1 new file mode 100644 index 0000000..f82f6b3 --- /dev/null +++ b/ucspi-tcp-0.88/tcpclient.1 @@ -0,0 +1,173 @@ +.TH tcpclient 1 +.SH NAME +tcpclient \- create an outgoing TCP connection +.SH SYNOPSIS +.B tcpclient +[ +.B \-46hHrRdDqQv +] +[ +.B \-i\fIlocalip +] +[ +.B \-p\fIlocalport +] +[ +.B \-T\fItimeoutconn +] +[ +.B \-l\fIlocalname +] +[ +.B \-t\fItimeoutinfo +] +[ +.B \-I\fIinterface +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpclient +attempts to connect to a TCP server. +If it is successful, it runs +.I program +with the given arguments, +with descriptor 6 reading from the network +and descriptor 7 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +may be 0, referring to the local machine, +or a dotted-decimal IP address, +or a host name; +if a host has several IP addresses, +.B tcpclient +tries each in turn. +.I port +may be a numeric port number +or a port name. + +.B tcpclient +sets up several environment variables, +as described in +.B tcp-environ(5). +.SH OPTIONS +.TP +.B \-i\fIlocalip +Use +.I localip +as the IP address for the local side of the connection; +quit if +.I localip +is not available. +.TP +.B \-p\fIlocalport +Use +.I localport +as the port number for the local side of the connection; +quit if +.I localport +is not available. +.TP +.B \-I\fIinterface +Use +.I interface +as the local network interface. This is only defined for IPv6 sockets +and needed if you use link-local IPv6 addresses. +.TP +.B \-T\fItimeoutconn +Give up on the +connection attempt +after +.I timeoutconn +seconds. Default: 60. +This timeout applies to each IP address tried. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-v +Verbose. +Print all available messages. +.SH "DATA-GATHERING OPTIONS" +.TP +.B \-h +(Default.) +Look up the remote host name for +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name; +unset +.BR TCPREMOTEHOST . +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeoutinfo +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeoutinfo +seconds. Default: 26. +.TP +.B \-4 +Fall back to IPv4 sockets. This is necessary for terminally broken +systems like OpenBSD which will not let IPv6 sockets connect to +V4-mapped IPv6 addresses. Please note that this also applies to DNS +lookups, so you will have to use an DNS resolver with an IPv6 address to +connect to IPv6 systems. Use \fBDNSCACHEIP\fR to set the DNS resolver +IP dynamically. +.TP +.B \-6 +Force IPv6 mode in UCSPI environment variables, even for +IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put +IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. +.SH "SEE ALSO" +date@(1), +finger@(1), +http@(1), +mconnect(1), +tcpcat(1), +tcpserver(1), +who@(1), +tcp-environ(5) diff --git a/ucspi-tcp-0.88/tcprules.1 b/ucspi-tcp-0.88/tcprules.1 new file mode 100644 index 0000000..084165b --- /dev/null +++ b/ucspi-tcp-0.88/tcprules.1 @@ -0,0 +1,221 @@ +.TH tcprules 1 +.SH NAME +tcprules \- compile rules for tcpserver +.SH SYNOPSIS +.B tcprules +.I rules.cdb +.I rules.tmp +.SH OVERVIEW +.B tcpserver +optionally follows rules to decide whether a TCP connection is acceptable. +For example, a rule of + +.EX + 18.23.0.32:deny +.EE + +prohibits connections from IP address 18.23.0.32. + +.B tcprules +reads rules from its standard input +and writes them into +.I rules.cdb +in a binary format suited +for quick access by +.BR tcpserver . + +.B tcprules +can be used while +.B tcpserver +is running: +it ensures that +.I rules.cdb +is updated atomically. +It does this by first writing the rules to +.I rules.tmp +and then moving +.I rules.tmp +on top of +.IR rules.cdb . +If +.I rules.tmp +already exists, it is destroyed. +The directories containing +.I rules.cdb +and +.I rules.tmp +must be writable to +.BR tcprules ; +they must also be on the same filesystem. + +If there is a problem with the input, +.B tcprules +complains and leaves +.I rules.cdb +alone. + +The binary +.I rules.cdb +format is portable across machines. +.SH "RULE FORMAT" +A rule takes up one line. +A file containing rules +may also contain comments: lines beginning with # are ignored. + +Each rule contains an +.BR address , +a colon, +and a list of +.BR instructions , +with no extra spaces. +When +.B tcpserver +receives a connection from that address, +it follows the instructions. +.SH "ADDRESSES" +.B tcpserver +starts by looking for a rule with address +.IR TCPREMOTEINFO\fB@\fITCPREMOTEIP . +If it doesn't find one, or if +.I TCPREMOTEINFO +is not set, it tries the address +.IR TCPREMOTEIP . +If that doesn't work, it tries shorter and shorter prefixes of +.I TCPREMOTEIP +ending with a dot. +If none of them work, it tries the empty string. + +For example, here are some rules: + +.EX + joe@127.0.0.1:first +.br + 18.23.0.32:second +.br + 127.:third +.br + :fourth +.br + ::1:fifth +.EE + +If +.I TCPREMOTEIP +is +.BR 10.119.75.38 , +.B tcpserver +will follow the +.B fourth +instructions. + +If +.I TCPREMOTEIP +is +.BR ::1 , +.B tcpserver +will follow the +.B fifth +instructions. Note that you cannot detect IPv4 mapped addresses by +matching "::ffff", as those addresses will be converted to IPv4 before +looking at the rules. + +If +.I TCPREMOTEIP +is +.BR 18.23.0.32 , +.B tcpserver +will follow the +.B second +instructions. + +If +.I TCPREMOTEINFO +is +.B bill +and +.I TCPREMOTEIP +is +.BR 127.0.0.1 , +.B tcpserver +will follow the +.B third +instructions. + +If +.I TCPREMOTEINFO +is +.B joe +and +.I TCPREMOTEIP +is +.BR 127.0.0.1 , +.B tcpserver +will follow the +.B first +instructions. +.SH "ADDRESS RANGES" +.B tcprules +treats +.B 1.2.3.37-53:ins +as an abbreviation +for the rules +.BR 1.2.3.37:ins , +.BR 1.2.3.38:ins , +and so on up through +.BR 1.2.3.53:ins . +Similarly, +.BR 10.2-3.:ins +is an abbreviation for +.B 10.2.:ins +and +.BR 10.3.:ins . +.SH "INSTRUCTIONS" +The instructions in a rule must begin with either +.B allow +or +.BR deny . +.B deny +tells +.B tcpserver +to drop the connection without running anything. +For example, the rule + +.EX + :deny +.EE + +tells +.B tcpserver +to drop all connections that aren't handled by more specific rules. + +The instructions may continue with some environment variables, +in the format +.IR ,VAR="VALUE" . +.B tcpserver +adds +.I VAR=VALUE +to the current environment. +For example, + +.EX + 10.0.:allow,RELAYCLIENT="@fix.me" +.EE + +adds +.B RELAYCLIENT=@fix.me +to the environment. +The quotes here may be replaced by any repeated character: + +.EX + 10.0.:allow,RELAYCLIENT=/@fix.me/ +.EE + +Any number of variables may be listed: + +.EX + 127.0.0.1:allow,RELAYCLIENT="",TCPLOCALHOST="movie.edu" +.EE +.SH "SEE ALSO" +tcprulescheck(1), +tcpserver(1), +tcp-environ(5) diff --git a/ucspi-tcp-0.88/tcprulescheck.1 b/ucspi-tcp-0.88/tcprulescheck.1 new file mode 100644 index 0000000..3f0de24 --- /dev/null +++ b/ucspi-tcp-0.88/tcprulescheck.1 @@ -0,0 +1,25 @@ +.TH tcprulescheck 1 +.SH NAME +tcprulescheck \- try out rules for tcpserver +.SH SYNTAX +.B tcprulescheck +.I rules.cdb +.I tcpremoteip +[ +.I tcpremoteinfo +] +.SH DESCRIPTION +.B tcprulescheck +says what +.B tcpserver +will do with a connection from +IP address +.IR tcpremoteip , +following the rules compiled into +.I rules.cdb +by +.BR tcprules . +.SH "SEE ALSO" +tcprules(1), +tcpserver(1), +tcp-environ(5) diff --git a/ucspi-tcp-0.88/tcpserver.1 b/ucspi-tcp-0.88/tcpserver.1 new file mode 100644 index 0000000..72c5ca0 --- /dev/null +++ b/ucspi-tcp-0.88/tcpserver.1 @@ -0,0 +1,266 @@ +.TH tcpserver 1 +.SH NAME +tcpserver \- accept incoming TCP connections +.SH SYNOPSIS +.B tcpserver +[ +.B \-146jpPhHrRoOdDqQv +] +[ +.B \-c\fIlimit +] +[ +.B \-x\fIrules.cdb +] +[ +.B \-B\fIbanner +] +[ +.B \-g\fIgid +] +[ +.B \-u\fIuid +] +[ +.B \-b\fIbacklog +] +[ +.B \-l\fIlocalname +] +[ +.B \-t\fItimeout +] +[ +.B \-I\fIinterface +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpserver +waits for connections from TCP clients. +For each connection, it runs +.I program +with the given arguments, +with descriptor 0 reading from the network +and descriptor 1 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +can be 0, allowing connections from any host; +or a particular IP address, +allowing connections only to that address; +or a host name, allowing connections to the first IP address +for that host. +.I port +may be a numeric port number +or a port name. +If +.I port +is 0, +.B tcpserver +will choose a free port. + +.B tcpserver +sets up several environment variables, +as described in +.B tcp-environ(5). + +.B tcpserver +exits when it receives SIGTERM. +.SH "OPTIONS" +.TP +.B \-c\fIlimit +Do not handle more than +.I limit +simultaneous connections. +If there are +.I limit +simultaneous copies of +.I program +running, defer acceptance of a new connection +until one copy finishes. +.I limit +must be a positive integer. +Default: 40. +.TP +.B \-x\fIrules.cdb +Follow the rules compiled into +.I rules.cdb +by +.BR tcprules . +These rules may specify setting environment variables +or rejecting connections from bad sources. + +.B tcpserver +does not read +.I rules.cdb +into memory; +you can rerun +.B tcprules +to change +.BR tcpserver 's +behavior on the fly. +.TP +.B \-B\fIbanner +Write +.I banner +to the network immediately after each connection is made. +.B tcpserver +writes +.I banner +before looking up +.BR TCPREMOTEHOST , +before looking up +.BR TCPREMOTEINFO , +and before checking +.IR rules.cdb . + +This feature can be used to reduce latency in protocols +where the client waits for a greeting from the server. +.TP +.B \-g\fIgid +Switch group ID to +.I gid +after preparing to receive connections. +.I gid +must be a positive integer. +.TP +.B \-u\fIuid +Switch user ID to +.I uid +after preparing to receive connections. +.I uid +must be a positive integer. +.TP +.B \-1 +After preparing to receive connections, +print the local port number to standard output. +.TP +.B \-4 +Fall back to IPv4 sockets. This is necessary for terminally broken +systems like OpenBSD which will not let IPv6 sockets connect to +V4-mapped IPv6 addresses. Please note that this also applies to DNS +lookups, so you will have to use an DNS resolver with an IPv6 address to +accept IPv6 connections. Use \fBDNSCACHEIP\fR to set the DNS resolver +IP dynamically. +.TP +.B \-6 +Force IPv6 mode in UCSPI environment variables, even for +IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put +IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. +.TP +.B \-I\fIinterface +Bind to the network interface +.I interface +("eth0" on Linux, for example). This is only defined and needed for +IPv6 link-local addresses. +.TP +.B \-b\fIbacklog +Allow up to +.I backlog +simultaneous SYN_RECEIVEDs. +Default: 20. +On some systems, +.I backlog +is silently limited to 5. +See +.BR listen (2) +for more details. +.TP +.B \-o +Leave IP options alone. +If the client is sending packets along an IP source route, +send packets back along the same route. +.TP +.B \-O +(Default.) +Kill IP options. +A client can still use source routing to connect and to send data, +but packets will be sent back along the default route. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-v +Verbose. +Print all available messages. +.SH "DATA-GATHERING OPTIONS" +.TP +.B \-p +Paranoid. +After looking up the remote host name, +look up the IP addresses for that name, +and make sure one of them matches +.BR TCPREMOTEIP . +If none of them do, +unset +.BR TCPREMOTEHOST . +.TP +.B \-P +(Default.) +Not paranoid. +.TP +.B \-h +(Default.) +Look up the remote host name and set +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name. +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeout +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeout +seconds. Default: 26. +.SH "SEE ALSO" +argv0(1), +fixcr(1), +recordio(1), +tcpclient(1), +tcprules(1), +listen(2), +tcp-environ(5) diff --git a/ucspi-tcp-0.88/timeoutconn6.c b/ucspi-tcp-0.88/timeoutconn6.c new file mode 100644 index 0000000..75e9f5a --- /dev/null +++ b/ucspi-tcp-0.88/timeoutconn6.c @@ -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 --git a/ucspi-tcp-0.88/tryip6.c b/ucspi-tcp-0.88/tryip6.c new file mode 100644 index 0000000..e0d7cfb --- /dev/null +++ b/ucspi-tcp-0.88/tryip6.c @@ -0,0 +1,8 @@ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +main() { + struct sockaddr_in6 sa; + sa.sin6_family = PF_INET6; +} diff --git a/ucspi-tcp-0.88/usr/local/man/man1/tcpclient.1 b/ucspi-tcp-0.88/usr/local/man/man1/tcpclient.1 new file mode 100644 index 0000000..f82f6b3 --- /dev/null +++ b/ucspi-tcp-0.88/usr/local/man/man1/tcpclient.1 @@ -0,0 +1,173 @@ +.TH tcpclient 1 +.SH NAME +tcpclient \- create an outgoing TCP connection +.SH SYNOPSIS +.B tcpclient +[ +.B \-46hHrRdDqQv +] +[ +.B \-i\fIlocalip +] +[ +.B \-p\fIlocalport +] +[ +.B \-T\fItimeoutconn +] +[ +.B \-l\fIlocalname +] +[ +.B \-t\fItimeoutinfo +] +[ +.B \-I\fIinterface +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpclient +attempts to connect to a TCP server. +If it is successful, it runs +.I program +with the given arguments, +with descriptor 6 reading from the network +and descriptor 7 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +may be 0, referring to the local machine, +or a dotted-decimal IP address, +or a host name; +if a host has several IP addresses, +.B tcpclient +tries each in turn. +.I port +may be a numeric port number +or a port name. + +.B tcpclient +sets up several environment variables, +as described in +.B tcp-environ(5). +.SH OPTIONS +.TP +.B \-i\fIlocalip +Use +.I localip +as the IP address for the local side of the connection; +quit if +.I localip +is not available. +.TP +.B \-p\fIlocalport +Use +.I localport +as the port number for the local side of the connection; +quit if +.I localport +is not available. +.TP +.B \-I\fIinterface +Use +.I interface +as the local network interface. This is only defined for IPv6 sockets +and needed if you use link-local IPv6 addresses. +.TP +.B \-T\fItimeoutconn +Give up on the +connection attempt +after +.I timeoutconn +seconds. Default: 60. +This timeout applies to each IP address tried. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-v +Verbose. +Print all available messages. +.SH "DATA-GATHERING OPTIONS" +.TP +.B \-h +(Default.) +Look up the remote host name for +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name; +unset +.BR TCPREMOTEHOST . +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeoutinfo +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeoutinfo +seconds. Default: 26. +.TP +.B \-4 +Fall back to IPv4 sockets. This is necessary for terminally broken +systems like OpenBSD which will not let IPv6 sockets connect to +V4-mapped IPv6 addresses. Please note that this also applies to DNS +lookups, so you will have to use an DNS resolver with an IPv6 address to +connect to IPv6 systems. Use \fBDNSCACHEIP\fR to set the DNS resolver +IP dynamically. +.TP +.B \-6 +Force IPv6 mode in UCSPI environment variables, even for +IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put +IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. +.SH "SEE ALSO" +date@(1), +finger@(1), +http@(1), +mconnect(1), +tcpcat(1), +tcpserver(1), +who@(1), +tcp-environ(5) diff --git a/ucspi-tcp-0.88/usr/local/man/man1/tcpserver.1 b/ucspi-tcp-0.88/usr/local/man/man1/tcpserver.1 new file mode 100644 index 0000000..72c5ca0 --- /dev/null +++ b/ucspi-tcp-0.88/usr/local/man/man1/tcpserver.1 @@ -0,0 +1,266 @@ +.TH tcpserver 1 +.SH NAME +tcpserver \- accept incoming TCP connections +.SH SYNOPSIS +.B tcpserver +[ +.B \-146jpPhHrRoOdDqQv +] +[ +.B \-c\fIlimit +] +[ +.B \-x\fIrules.cdb +] +[ +.B \-B\fIbanner +] +[ +.B \-g\fIgid +] +[ +.B \-u\fIuid +] +[ +.B \-b\fIbacklog +] +[ +.B \-l\fIlocalname +] +[ +.B \-t\fItimeout +] +[ +.B \-I\fIinterface +] +.I host +.I port +.I program +[ +.I arg ... +] +.SH DESCRIPTION +.B tcpserver +waits for connections from TCP clients. +For each connection, it runs +.I program +with the given arguments, +with descriptor 0 reading from the network +and descriptor 1 writing to the network. + +The server's address is given by +.I host +and +.IR port . +.I host +can be 0, allowing connections from any host; +or a particular IP address, +allowing connections only to that address; +or a host name, allowing connections to the first IP address +for that host. +.I port +may be a numeric port number +or a port name. +If +.I port +is 0, +.B tcpserver +will choose a free port. + +.B tcpserver +sets up several environment variables, +as described in +.B tcp-environ(5). + +.B tcpserver +exits when it receives SIGTERM. +.SH "OPTIONS" +.TP +.B \-c\fIlimit +Do not handle more than +.I limit +simultaneous connections. +If there are +.I limit +simultaneous copies of +.I program +running, defer acceptance of a new connection +until one copy finishes. +.I limit +must be a positive integer. +Default: 40. +.TP +.B \-x\fIrules.cdb +Follow the rules compiled into +.I rules.cdb +by +.BR tcprules . +These rules may specify setting environment variables +or rejecting connections from bad sources. + +.B tcpserver +does not read +.I rules.cdb +into memory; +you can rerun +.B tcprules +to change +.BR tcpserver 's +behavior on the fly. +.TP +.B \-B\fIbanner +Write +.I banner +to the network immediately after each connection is made. +.B tcpserver +writes +.I banner +before looking up +.BR TCPREMOTEHOST , +before looking up +.BR TCPREMOTEINFO , +and before checking +.IR rules.cdb . + +This feature can be used to reduce latency in protocols +where the client waits for a greeting from the server. +.TP +.B \-g\fIgid +Switch group ID to +.I gid +after preparing to receive connections. +.I gid +must be a positive integer. +.TP +.B \-u\fIuid +Switch user ID to +.I uid +after preparing to receive connections. +.I uid +must be a positive integer. +.TP +.B \-1 +After preparing to receive connections, +print the local port number to standard output. +.TP +.B \-4 +Fall back to IPv4 sockets. This is necessary for terminally broken +systems like OpenBSD which will not let IPv6 sockets connect to +V4-mapped IPv6 addresses. Please note that this also applies to DNS +lookups, so you will have to use an DNS resolver with an IPv6 address to +accept IPv6 connections. Use \fBDNSCACHEIP\fR to set the DNS resolver +IP dynamically. +.TP +.B \-6 +Force IPv6 mode in UCSPI environment variables, even for +IPv4 connections. This will set \fB$PROTO\fR to \fBTCP6\fR and put +IPv4-mapped IPv6 addresses in \fBTCPLOCALIP\fR and \fBTCPREMOTEIP\fR. +.TP +.B \-I\fIinterface +Bind to the network interface +.I interface +("eth0" on Linux, for example). This is only defined and needed for +IPv6 link-local addresses. +.TP +.B \-b\fIbacklog +Allow up to +.I backlog +simultaneous SYN_RECEIVEDs. +Default: 20. +On some systems, +.I backlog +is silently limited to 5. +See +.BR listen (2) +for more details. +.TP +.B \-o +Leave IP options alone. +If the client is sending packets along an IP source route, +send packets back along the same route. +.TP +.B \-O +(Default.) +Kill IP options. +A client can still use source routing to connect and to send data, +but packets will be sent back along the default route. +.TP +.B \-d +(Default.) +Delay sending data for a fraction of a second whenever the +remote host is responding slowly, +to make better use of the network. +.TP +.B \-D +Never delay sending data; +enable TCP_NODELAY. +This is appropriate for interactive connections. +.TP +.B \-q +Quiet. +Do not print any messages. +.TP +.B \-Q +(Default.) +Print error messages. +.TP +.B \-v +Verbose. +Print all available messages. +.SH "DATA-GATHERING OPTIONS" +.TP +.B \-p +Paranoid. +After looking up the remote host name, +look up the IP addresses for that name, +and make sure one of them matches +.BR TCPREMOTEIP . +If none of them do, +unset +.BR TCPREMOTEHOST . +.TP +.B \-P +(Default.) +Not paranoid. +.TP +.B \-h +(Default.) +Look up the remote host name and set +.BR TCPREMOTEHOST . +.TP +.B \-H +Do not look up the remote host name. +.TP +.B \-l\fIlocalname +Do not look up the local host name; +use +.I localname +for +.BR TCPLOCALHOST . +.TP +.B \-r +(Default.) +Attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-R +Do not attempt to obtain +.B TCPREMOTEINFO +from the remote host. +.TP +.B \-t\fItimeout +Give up on the +.B TCPREMOTEINFO +connection attempt +after +.I timeout +seconds. Default: 26. +.SH "SEE ALSO" +argv0(1), +fixcr(1), +recordio(1), +tcpclient(1), +tcprules(1), +listen(2), +tcp-environ(5) diff --git a/ucspi-tcp-0.88/who@.1 b/ucspi-tcp-0.88/who@.1 new file mode 100644 index 0000000..0c13f84 --- /dev/null +++ b/ucspi-tcp-0.88/who@.1 @@ -0,0 +1,32 @@ +.TH who@ 1 +.SH NAME +who@ \- print list of active users on a host +.SH SYNTAX +.B who@ +[ +.I host +] +.SH DESCRIPTION +.B who@ +connects to TCP port 11 (Systat) on +.I host +and prints any data it receives. +It removes CR and converts unprintable characters to a visible format. + +If +.I host +is not supplied, +.B who@ +connects to the local host. + +Some computers respond to port 11 with a list of active users. +For example, they may be running + +.EX + tcpserver 0 11 who & +.EE +.SH "SEE ALSO" +cat(1), +delcr(1), +tcpclient(1), +tcpserver(1) |