add ip6 support to drawterm Reference: /n/atom/patch/applied/dtip6 Date: Sat Mar 22 18:41:01 CET 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/unix/drawterm/Makefile Sat Mar 22 18:39:48 2014 +++ /sys/src/cmd/unix/drawterm/Makefile Sat Mar 22 18:39:49 2014 @@ -23,6 +23,7 @@ libdraw/libdraw.a\ gui-$(GUI)/libgui.a\ libc/libc.a\ + libip/libip.a\ # stupid gcc LIBS=$(LIBS1) $(LIBS1) $(LIBS1) libmachdep.a @@ -66,6 +67,9 @@ libc/libc.a: (cd libc; $(MAKE)) + +libip/libip.a: + (cd libip; $(MAKE)) gui-$(GUI)/libgui.a: (cd gui-$(GUI); $(MAKE)) --- /sys/src/cmd/unix/drawterm/include/ip.h Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/unix/drawterm/include/ip.h Sat Mar 22 18:39:53 2014 @@ -0,0 +1,38 @@ +enum +{ + IPaddrlen= 16, + IPv4addrlen= 4, + IPv4off= 12, +}; + +uchar* defmask(uchar*); +void maskip(uchar*, uchar*, uchar*); +int eipfmt(Fmt*); +int isv4(uchar*); +vlong parseip(uchar*, char*); +vlong parseipmask(uchar*, char*); +char* v4parseip(uchar*, char*); +char* v4parsecidr(uchar*, uchar*, char*); + +void hnputv(void*, uvlong); +void hnputl(void*, uint); +void hnputs(void*, ushort); +uvlong nhgetv(void*); +uint nhgetl(void*); +ushort nhgets(void*); + +int v6tov4(uchar*, uchar*); +void v4tov6(uchar*, uchar*); + +#define ipcmp(x, y) memcmp(x, y, IPaddrlen) +#define ipmove(x, y) memmove(x, y, IPaddrlen) + +extern uchar IPv4bcast[IPaddrlen]; +extern uchar IPv4bcastobs[IPaddrlen]; +extern uchar IPv4allsys[IPaddrlen]; +extern uchar IPv4allrouter[IPaddrlen]; +extern uchar IPnoaddr[IPaddrlen]; +extern uchar v4prefix[IPaddrlen]; +extern uchar IPallbits[IPaddrlen]; + +#define CLASS(p) ((*(uchar*)(p))>>6) --- /sys/src/cmd/unix/drawterm/kern/devip-posix.c Sat Mar 22 18:39:55 2014 +++ /sys/src/cmd/unix/drawterm/kern/devip-posix.c Sat Mar 22 18:39:55 2014 @@ -3,12 +3,14 @@ #include #include #include +#include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" +#include "ip.h" #include "devip.h" @@ -16,6 +18,26 @@ #undef accept #undef bind +static int +family(unsigned char *addr) +{ + if(isv4(addr)) + return AF_INET; + return AF_INET6; +} + +static int +addrlen(struct sockaddr_storage *ss) +{ + switch(ss->ss_family){ + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + } + return 0; +} + void osipinit(void) { @@ -26,7 +48,7 @@ } int -so_socket(int type) +so_socket(int type, unsigned char *addr) { int fd, one; @@ -41,7 +63,7 @@ break; } - fd = socket(AF_INET, type, 0); + fd = socket(family(addr), type, 0); if(fd < 0) oserror(); @@ -54,36 +76,52 @@ return fd; } - void -so_connect(int fd, unsigned long raddr, unsigned short rport) +so_connect(int fd, unsigned char *raddr, unsigned short rport) { - struct sockaddr_in sin; + struct sockaddr_storage ss; + + memset(&ss, 0, sizeof(ss)); + + ss.ss_family = family(raddr); - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, rport); - hnputl(&sin.sin_addr.s_addr, raddr); + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport); + v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport); + memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr)); + break; + } - if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } void -so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) +so_getsockname(int fd, unsigned char *laddr, unsigned short *lport) { socklen_t len; - struct sockaddr_in sin; + struct sockaddr_storage ss; - len = sizeof(sin); - if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) + len = sizeof(ss); + if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *laddr = nhgetl(&sin.sin_addr.s_addr); - *lport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } } void @@ -94,30 +132,37 @@ } int -so_accept(int fd, unsigned long *raddr, unsigned short *rport) +so_accept(int fd, unsigned char *raddr, unsigned short *rport) { int nfd; socklen_t len; - struct sockaddr_in sin; + struct sockaddr_storage ss; - len = sizeof(sin); - nfd = accept(fd, (struct sockaddr*)&sin, &len); + len = sizeof(ss); + nfd = accept(fd, (struct sockaddr*)&ss, &len); if(nfd < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *raddr = nhgetl(&sin.sin_addr.s_addr); - *rport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } return nfd; } void -so_bind(int fd, int su, unsigned short port) +so_bind(int fd, int su, unsigned short port, unsigned char *addr) { int i, one; - struct sockaddr_in sin; + struct sockaddr_storage ss; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ @@ -127,21 +172,37 @@ if(su) { for(i = 600; i < 1024; i++) { - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = i; + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); + + switch(ss.ss_family){ + case AF_INET: + ((struct sockaddr_in*)&ss)->sin_port = i; + break; + case AF_INET6: + ((struct sockaddr_in6*)&ss)->sin6_port = i; + break; + } - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0) return; } oserror(); } - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, port); + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, port); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port); + break; + } + + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } @@ -170,16 +231,28 @@ char* hostlookup(char *host) { - char buf[100]; + char buf[INET6_ADDRSTRLEN]; uchar *p; struct hostent *he; + struct addrinfo *result; he = gethostbyname(host); if(he != 0 && he->h_addr_list[0]) { p = (uchar*)he->h_addr_list[0]; sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); + } else if(getaddrinfo(host, NULL, NULL, &result) == 0) { + switch (result->ai_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in*)result->ai_addr)->sin_addr, buf, sizeof(buf)); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, buf, sizeof(buf)); + break; + default: + return nil; + } } else - strcpy(buf, host); + return nil; return strdup(buf); } --- /sys/src/cmd/unix/drawterm/kern/devip-win32.c Sat Mar 22 18:39:57 2014 +++ /sys/src/cmd/unix/drawterm/kern/devip-win32.c Sat Mar 22 18:39:57 2014 @@ -1,9 +1,11 @@ #include +#include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" +#include "ip.h" #include "devip.h" @@ -15,6 +17,26 @@ #undef accept #undef bind +static int +family(unsigned char *addr) +{ + if(isv4(addr)) + return AF_INET; + return AF_INET6; +} + +static int +addrlen(struct sockaddr_storage *ss) +{ + switch(ss->ss_family){ + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + } + return 0; +} + void osipinit(void) { @@ -29,7 +51,7 @@ } int -so_socket(int type) +so_socket(int type, unsigned char *addr) { int fd, one; @@ -44,7 +66,7 @@ break; } - fd = socket(AF_INET, type, 0); + fd = socket(family(addr), type, 0); if(fd < 0) oserror(); @@ -59,34 +81,51 @@ void -so_connect(int fd, unsigned long raddr, unsigned short rport) +so_connect(int fd, unsigned char *raddr, unsigned short rport) { - struct sockaddr_in sin; + struct sockaddr_storage ss; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, rport); - hnputl(&sin.sin_addr.s_addr, raddr); + memset(&ss, 0, sizeof(ss)); - if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + ss.ss_family = family(raddr); + + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport); + v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport); + memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr)); + break; + } + + if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } void -so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) +so_getsockname(int fd, unsigned char *laddr, unsigned short *lport) { int len; - struct sockaddr_in sin; + struct sockaddr_storage ss; - len = sizeof(sin); - if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) + len = sizeof(ss); + if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *laddr = nhgetl(&sin.sin_addr.s_addr); - *lport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } } void @@ -97,53 +136,77 @@ } int -so_accept(int fd, unsigned long *raddr, unsigned short *rport) +so_accept(int fd, unsigned char *raddr, unsigned short *rport) { - int nfd, len; - struct sockaddr_in sin; + int nfd; + int len; + struct sockaddr_storage ss; - len = sizeof(sin); - nfd = accept(fd, (struct sockaddr*)&sin, &len); + len = sizeof(ss); + nfd = accept(fd, (struct sockaddr*)&ss, &len); if(nfd < 0) oserror(); - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *raddr = nhgetl(&sin.sin_addr.s_addr); - *rport = nhgets(&sin.sin_port); + switch(ss.ss_family){ + case AF_INET: + v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr); + *rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port); + break; + case AF_INET6: + memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr)); + *rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port); + break; + default: + error("not AF_INET or AF_INET6"); + } return nfd; } void -so_bind(int fd, int su, unsigned short port) +so_bind(int fd, int su, unsigned short port, unsigned char *addr) { int i, one; - struct sockaddr_in sin; + struct sockaddr_storage ss; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ oserrstr(); - print("setsockopt: %s", up->errstr); + print("setsockopt: %r"); } if(su) { for(i = 600; i < 1024; i++) { - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = i; + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); + + switch(ss.ss_family){ + case AF_INET: + ((struct sockaddr_in*)&ss)->sin_port = i; + break; + case AF_INET6: + ((struct sockaddr_in6*)&ss)->sin6_port = i; + break; + } - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0) return; } oserror(); } - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, port); + memset(&ss, 0, sizeof(ss)); + ss.ss_family = family(addr); + + switch(ss.ss_family){ + case AF_INET: + hnputs(&((struct sockaddr_in*)&ss)->sin_port, port); + break; + case AF_INET6: + hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port); + break; + } - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) + if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0) oserror(); } @@ -174,7 +237,7 @@ { char buf[100]; uchar *p; - HOSTENT *he; + struct hostent *he; he = gethostbyname(host); if(he != 0 && he->h_addr_list[0]) { --- /sys/src/cmd/unix/drawterm/kern/devip.c Sat Mar 22 18:39:59 2014 +++ /sys/src/cmd/unix/drawterm/kern/devip.c Sat Mar 22 18:40:00 2014 @@ -3,14 +3,10 @@ #include "dat.h" #include "fns.h" #include "error.h" +#include "ip.h" #include "devip.h" -void hnputl(void *p, unsigned long v); -void hnputs(void *p, unsigned short v); -unsigned long nhgetl(void *p); -unsigned short nhgets(void *p); -unsigned long parseip(char *to, char *from); void csclose(Chan*); long csread(Chan*, void*, long, vlong); long cswrite(Chan*, void*, long, vlong); @@ -37,6 +33,7 @@ #define CONV(x) ((int)(((x).path >> 4)&0xfff)) #define PROTO(x) ((int)(((x).path >> 16)&0xff)) #define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y)) +#define ipzero(x) memset(x, 0, IPaddrlen) typedef struct Proto Proto; typedef struct Conv Conv; @@ -48,9 +45,9 @@ int perm; char owner[KNAMELEN]; char* state; - ulong laddr; + uchar laddr[IPaddrlen]; ushort lport; - ulong raddr; + uchar raddr[IPaddrlen]; ushort rport; int restricted; char cerr[KNAMELEN]; @@ -71,7 +68,6 @@ static int np; static Proto proto[MAXPROTO]; -int eipfmt(Fmt*); static Conv* protoclone(Proto*, char*, int); static void setladdr(Conv*); @@ -222,7 +218,7 @@ ipopen(Chan *c, int omode) { Proto *p; - ulong raddr; + uchar raddr[IPaddrlen]; ushort rport; int perm, sfd; Conv *cv, *lcv; @@ -286,13 +282,13 @@ case Qlisten: p = &proto[PROTO(c->qid)]; lcv = p->conv[CONV(c->qid)]; - sfd = so_accept(lcv->sfd, &raddr, &rport); + sfd = so_accept(lcv->sfd, raddr, &rport); cv = protoclone(p, up->user, sfd); if(cv == 0) { close(sfd); error(Enodev); } - cv->raddr = raddr; + ipmove(cv->raddr, raddr); cv->rport = rport; setladdr(cv); cv->state = "Established"; @@ -324,8 +320,8 @@ strcpy(cc->owner, "network"); cc->perm = 0666; cc->state = "Closed"; - cc->laddr = 0; - cc->raddr = 0; + ipzero(cc->laddr); + ipzero(cc->raddr); cc->lport = 0; cc->rport = 0; close(cc->sfd); @@ -339,7 +335,7 @@ int r; Conv *c; Proto *x; - uchar ip[4]; + uchar ip[IPaddrlen]; char buf[128], *p; /*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/ @@ -358,12 +354,12 @@ return readstr(offset, p, n, buf); case Qremote: c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; - hnputl(ip, c->raddr); + ipmove(ip, c->raddr); sprint(buf, "%I!%d\n", ip, c->rport); return readstr(offset, p, n, buf); case Qlocal: c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; - hnputl(ip, c->laddr); + ipmove(ip, c->laddr); sprint(buf, "%I!%d\n", ip, c->lport); return readstr(offset, p, n, buf); case Qstatus: @@ -386,7 +382,7 @@ static void setladdr(Conv *c) { - so_getsockname(c->sfd, &c->laddr, &c->lport); + so_getsockname(c->sfd, c->laddr, &c->lport); } static void @@ -395,23 +391,27 @@ if(c->restricted == 0 && c->lport == 0) return; - so_bind(c->sfd, c->restricted, c->lport); + if(c->sfd == -1) + c->sfd = so_socket(c->p->stype, c->laddr); + + so_bind(c->sfd, c->restricted, c->lport, c->laddr); } static void setladdrport(Conv *c, char *str) { - char *p, addr[4]; + char *p; + uchar addr[IPaddrlen]; p = strchr(str, '!'); if(p == 0) { p = str; - c->laddr = 0; + ipzero(c->laddr); } else { *p++ = 0; parseip(addr, str); - c->laddr = nhgetl((uchar*)addr); + ipmove(c->laddr, addr); } if(*p == '*') c->lport = 0; @@ -424,14 +424,15 @@ static char* setraddrport(Conv *c, char *str) { - char *p, addr[4]; + char *p; + uchar addr[IPaddrlen]; p = strchr(str, '!'); if(p == 0) return "malformed address"; *p++ = 0; parseip(addr, str); - c->raddr = nhgetl((uchar*)addr); + ipmove(c->raddr, addr); c->rport = atoi(p); p = strchr(p, '!'); if(p) { @@ -480,6 +481,8 @@ setlport(c); break; } + if(c->sfd == -1) + c->sfd = so_socket(c->p->stype, c->raddr); so_connect(c->sfd, c->raddr, c->rport); setladdr(c); c->state = "Established"; @@ -565,13 +568,11 @@ c->perm = 0660; c->state = "Closed"; c->restricted = 0; - c->laddr = 0; - c->raddr = 0; + ipzero(c->laddr); + ipzero(c->raddr); c->lport = 0; c->rport = 0; c->sfd = nfd; - if(nfd == -1) - c->sfd = so_socket(p->stype); unlock(&c->r.lk); unlock(&p->l); @@ -579,145 +580,6 @@ return c; } -enum -{ - Isprefix= 16, -}; - -uchar prefixvals[256] = -{ -/*0x00*/ 0 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x80*/ 1 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xC0*/ 2 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xE0*/ 3 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xF0*/ 4 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, -/*0xF8*/ 5 | Isprefix, - 0, 0, 0, -/*0xFC*/ 6 | Isprefix, - 0, -/*0xFE*/ 7 | Isprefix, -/*0xFF*/ 8 | Isprefix, -}; - -int -eipfmt(Fmt *f) -{ - char buf[5*8]; - static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; - static char *ifmt = "%d.%d.%d.%d"; - uchar *p, ip[16]; - ulong ul; - - switch(f->r) { - case 'E': /* Ethernet address */ - p = va_arg(f->args, uchar*); - snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); - return fmtstrcpy(f, buf); - - case 'I': - ul = va_arg(f->args, ulong); - hnputl(ip, ul); - snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]); - return fmtstrcpy(f, buf); - } - return fmtstrcpy(f, "(eipfmt)"); -} - -void -hnputl(void *p, unsigned long v) -{ - unsigned char *a; - - a = p; - a[0] = v>>24; - a[1] = v>>16; - a[2] = v>>8; - a[3] = v; -} - -void -hnputs(void *p, unsigned short v) -{ - unsigned char *a; - - a = p; - a[0] = v>>8; - a[1] = v; -} - -unsigned long -nhgetl(void *p) -{ - unsigned char *a; - a = p; - return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); -} - -unsigned short -nhgets(void *p) -{ - unsigned char *a; - a = p; - return (a[0]<<8)|(a[1]<<0); -} - -#define CLASS(p) ((*(unsigned char*)(p))>>6) - -unsigned long -parseip(char *to, char *from) -{ - int i; - char *p; - - p = from; - memset(to, 0, 4); - for(i = 0; i < 4 && *p; i++){ - to[i] = strtoul(p, &p, 10); - if(*p != '.' && *p != 0){ - memset(to, 0, 4); - return 0; - } - if(*p == '.') - p++; - } - switch(CLASS(to)){ - case 0: /* class A - 1 byte net */ - case 1: - if(i == 3){ - to[3] = to[2]; - to[2] = to[1]; - to[1] = 0; - } else if (i == 2){ - to[3] = to[1]; - to[1] = 0; - } - break; - case 2: /* class B - 2 byte net */ - if(i == 3){ - to[3] = to[2]; - to[2] = 0; - } - break; - } - return nhgetl(to); -} - void csclose(Chan *c) { @@ -856,23 +718,17 @@ return 0; } -static ulong -lookuphost(char *s) +static int +lookuphost(char *s, uchar *to) { - char to[4]; - ulong ip; - - memset(to, 0, sizeof to); - parseip(to, s); - ip = nhgetl(to); - if(ip != 0) - return ip; - if((s = hostlookup(s)) == nil) + ipzero(to); + if(parseip(to, s) != -1) return 0; + if((s = hostlookup(s)) == nil) + return -1; parseip(to, s); - ip = nhgetl(to); free(s); - return ip; + return 0; } long @@ -880,7 +736,7 @@ { char *f[4]; char *s, *ns; - ulong ip; + uchar ip[IPaddrlen]; int nf, port; s = malloc(n+1); @@ -900,8 +756,7 @@ if(port <= 0) error("no translation for port found"); - ip = lookuphost(f[1]); - if(ip == 0) + if(lookuphost(f[1], ip) < 0) error("no translation for host found"); ns = smprint("/net/%s/clone %I!%d", f[0], ip, port); --- /sys/src/cmd/unix/drawterm/kern/devip.h Sat Mar 22 18:40:01 2014 +++ /sys/src/cmd/unix/drawterm/kern/devip.h Sat Mar 22 18:40:02 2014 @@ -4,14 +4,14 @@ S_UDP }; -int so_socket(int type); -void so_connect(int, unsigned long, unsigned short); -void so_getsockname(int, unsigned long*, unsigned short*); -void so_bind(int, int, unsigned short); +int so_socket(int, unsigned char*); +void so_connect(int, unsigned char*, unsigned short); +void so_getsockname(int, unsigned char*, unsigned short*); +void so_bind(int, int, unsigned short, unsigned char*); void so_listen(int); int so_send(int, void*, int, int); int so_recv(int, void*, int, int); -int so_accept(int, unsigned long*, unsigned short*); +int so_accept(int, unsigned char*, unsigned short*); int so_getservbyname(char*, char*, char*); int so_gethostbyname(char*, char**, int); --- /sys/src/cmd/unix/drawterm/kern/fns.h Sat Mar 22 18:40:03 2014 +++ /sys/src/cmd/unix/drawterm/kern/fns.h Sat Mar 22 18:40:04 2014 @@ -375,12 +375,6 @@ Segment* dupseg(Segment**, int, int); Segment* newseg(int, ulong, ulong); Segment* seg(Proc*, ulong, int); -void hnputv(void*, vlong); -void hnputl(void*, ulong); -void hnputs(void*, ushort); -vlong nhgetv(void*); -ulong nhgetl(void*); -ushort nhgets(void*); ulong ticks(void); void osproc(Proc*); void osnewproc(Proc*); --- /sys/src/cmd/unix/drawterm/libip/Makefile Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/Makefile Sat Mar 22 18:40:05 2014 @@ -0,0 +1,19 @@ +ROOT=.. +include ../Make.config +LIB=libip.a + +OFILES=\ + eipfmt.$O\ + parseip.$O\ + classmask.$O\ + bo.$O\ + ipaux.$O\ + +default: $(LIB) +$(LIB): $(OFILES) + $(AR) r $(LIB) $(OFILES) + $(RANLIB) $(LIB) + +%.$O: %.c + $(CC) $(CFLAGS) $*.c + --- /sys/src/cmd/unix/drawterm/libip/bo.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/bo.c Sat Mar 22 18:40:05 2014 @@ -0,0 +1,77 @@ +#include +#include +#include + +void +hnputv(void *p, uvlong v) +{ + uchar *a; + + a = p; + a[0] = v>>56; + a[1] = v>>48; + a[2] = v>>40; + a[3] = v>>32; + a[4] = v>>24; + a[5] = v>>16; + a[6] = v>>8; + a[7] = v; +} + +void +hnputl(void *p, uint v) +{ + uchar *a; + + a = p; + a[0] = v>>24; + a[1] = v>>16; + a[2] = v>>8; + a[3] = v; +} + +void +hnputs(void *p, ushort v) +{ + uchar *a; + + a = p; + a[0] = v>>8; + a[1] = v; +} + +uvlong +nhgetv(void *p) +{ + uchar *a; + uvlong v; + + a = p; + v = (uvlong)a[0]<<56; + v |= (uvlong)a[1]<<48; + v |= (uvlong)a[2]<<40; + v |= (uvlong)a[3]<<32; + v |= a[4]<<24; + v |= a[5]<<16; + v |= a[6]<<8; + v |= a[7]<<0; + return v; +} + +uint +nhgetl(void *p) +{ + uchar *a; + + a = p; + return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); +} + +ushort +nhgets(void *p) +{ + uchar *a; + + a = p; + return (a[0]<<8)|(a[1]<<0); +} --- /sys/src/cmd/unix/drawterm/libip/classmask.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/classmask.c Sat Mar 22 18:40:06 2014 @@ -0,0 +1,86 @@ +#include +#include +#include + +static uchar classmask[4][16] = { + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0x00,0x00, + 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0x00, +}; + +static uchar v6loopback[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01 +}; + +static uchar v6linklocal[IPaddrlen] = { + 0xfe, 0x80, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static uchar v6linklocalmask[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static int v6llpreflen = 8; /* link-local prefix length in bytes */ + +static uchar v6multicast[IPaddrlen] = { + 0xff, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static uchar v6multicastmask[IPaddrlen] = { + 0xff, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; +static int v6mcpreflen = 1; /* multicast prefix length */ + +static uchar v6solicitednode[IPaddrlen] = { + 0xff, 0x02, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x01, + 0xff, 0, 0, 0 +}; +static uchar v6solicitednodemask[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0, 0x0, 0x0 +}; +static int v6snpreflen = 13; + +uchar* +defmask(uchar *ip) +{ + if(isv4(ip)) + return classmask[ip[IPv4off]>>6]; + else { + if(ipcmp(ip, v6loopback) == 0) + return IPallbits; + else if(memcmp(ip, v6linklocal, v6llpreflen) == 0) + return v6linklocalmask; + else if(memcmp(ip, v6solicitednode, v6snpreflen) == 0) + return v6solicitednodemask; + else if(memcmp(ip, v6multicast, v6mcpreflen) == 0) + return v6multicastmask; + return IPallbits; + } +} + +void +maskip(uchar *from, uchar *mask, uchar *to) +{ + int i; + + for(i = 0; i < IPaddrlen; i++) + to[i] = from[i] & mask[i]; +} --- /sys/src/cmd/unix/drawterm/libip/eipfmt.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/eipfmt.c Sat Mar 22 18:40:06 2014 @@ -0,0 +1,109 @@ +#include +#include +#include + +enum +{ + Isprefix= 16, +}; + +uchar prefixvals[256] = +{ +[0x00] 0 | Isprefix, +[0x80] 1 | Isprefix, +[0xC0] 2 | Isprefix, +[0xE0] 3 | Isprefix, +[0xF0] 4 | Isprefix, +[0xF8] 5 | Isprefix, +[0xFC] 6 | Isprefix, +[0xFE] 7 | Isprefix, +[0xFF] 8 | Isprefix, +}; + +int +eipfmt(Fmt *f) +{ + char buf[5*8]; + static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux"; + static char *ifmt = "%d.%d.%d.%d"; + uchar *p, ip[16]; + ulong *lp; + ushort s; + int i, j, n, eln, eli; + + switch(f->r) { + case 'E': /* Ethernet address */ + p = va_arg(f->args, uchar*); + snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); + return fmtstrcpy(f, buf); + + case 'I': /* Ip address */ + p = va_arg(f->args, uchar*); +common: + if(memcmp(p, v4prefix, 12) == 0){ + snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]); + return fmtstrcpy(f, buf); + } + + /* find longest elision */ + eln = eli = -1; + for(i = 0; i < 16; i += 2){ + for(j = i; j < 16; j += 2) + if(p[j] != 0 || p[j+1] != 0) + break; + if(j > i && j - i > eln){ + eli = i; + eln = j - i; + } + } + + /* print with possible elision */ + n = 0; + for(i = 0; i < 16; i += 2){ + if(i == eli){ + n += sprint(buf+n, "::"); + i += eln; + if(i >= 16) + break; + } else if(i != 0) + n += sprint(buf+n, ":"); + s = (p[i]<<8) + p[i+1]; + n += sprint(buf+n, "%ux", s); + } + return fmtstrcpy(f, buf); + + case 'i': /* v6 address as 4 longs */ + lp = va_arg(f->args, ulong*); + for(i = 0; i < 4; i++) + hnputl(ip+4*i, *lp++); + p = ip; + goto common; + + case 'V': /* v4 ip address */ + p = va_arg(f->args, uchar*); + snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]); + return fmtstrcpy(f, buf); + + case 'M': /* ip mask */ + p = va_arg(f->args, uchar*); + + /* look for a prefix mask */ + for(i = 0; i < 16; i++) + if(p[i] != 0xff) + break; + if(i < 16){ + if((prefixvals[p[i]] & Isprefix) == 0) + goto common; + for(j = i+1; j < 16; j++) + if(p[j] != 0) + goto common; + n = 8*i + (prefixvals[p[i]] & ~Isprefix); + } else + n = 8*16; + + /* got one, use /xx format */ + snprint(buf, sizeof buf, "/%d", n); + return fmtstrcpy(f, buf); + } + return fmtstrcpy(f, "(eipfmt)"); +} --- /sys/src/cmd/unix/drawterm/libip/ipaux.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/ipaux.c Sat Mar 22 18:40:07 2014 @@ -0,0 +1,102 @@ +#include +#include +#include + +/* + * well known IP addresses + */ +uchar IPv4bcast[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff +}; +uchar IPv4allsys[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0xe0, 0, 0, 0x01 +}; +uchar IPv4allrouter[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0xe0, 0, 0, 0x02 +}; +uchar IPallbits[IPaddrlen] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff +}; +uchar IPnoaddr[IPaddrlen]; + +/* + * prefix of all v4 addresses + */ +uchar v4prefix[IPaddrlen] = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff, + 0, 0, 0, 0 +}; + +int +isv4(uchar *ip) +{ + return memcmp(ip, v4prefix, IPv4off) == 0; +} + +/* + * the following routines are unrolled with no memset's to speed + * up the usual case + */ +void +v4tov6(uchar *v6, uchar *v4) +{ + v6[0] = 0; + v6[1] = 0; + v6[2] = 0; + v6[3] = 0; + v6[4] = 0; + v6[5] = 0; + v6[6] = 0; + v6[7] = 0; + v6[8] = 0; + v6[9] = 0; + v6[10] = 0xff; + v6[11] = 0xff; + v6[12] = v4[0]; + v6[13] = v4[1]; + v6[14] = v4[2]; + v6[15] = v4[3]; +} + +int +v6tov4(uchar *v4, uchar *v6) +{ + if(v6[0] == 0 + && v6[1] == 0 + && v6[2] == 0 + && v6[3] == 0 + && v6[4] == 0 + && v6[5] == 0 + && v6[6] == 0 + && v6[7] == 0 + && v6[8] == 0 + && v6[9] == 0 + && v6[10] == 0xff + && v6[11] == 0xff) + { + v4[0] = v6[12]; + v4[1] = v6[13]; + v4[2] = v6[14]; + v4[3] = v6[15]; + return 0; + } else { + memset(v4, 0, 4); + if(memcmp(v6, IPnoaddr, IPaddrlen) == 0) + return 0; + return -1; + } +} --- /sys/src/cmd/unix/drawterm/libip/parseip.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/unix/drawterm/libip/parseip.c Sat Mar 22 18:40:07 2014 @@ -0,0 +1,185 @@ +#include +#include +#include +#include + +char* +v4parseip(uchar *to, char *from) +{ + int i; + char *p; + + p = from; + for(i = 0; i < 4 && *p; i++){ + to[i] = strtoul(p, &p, 0); + if(*p == '.') + p++; + } + switch(CLASS(to)){ + case 0: /* class A - 1 uchar net */ + case 1: + if(i == 3){ + to[3] = to[2]; + to[2] = to[1]; + to[1] = 0; + } else if (i == 2){ + to[3] = to[1]; + to[1] = 0; + } + break; + case 2: /* class B - 2 uchar net */ + if(i == 3){ + to[3] = to[2]; + to[2] = 0; + } + break; + } + return p; +} + +static int +ipcharok(int c) +{ + return c == '.' || c == ':' || (isascii(c) && isxdigit(c)); +} + +static int +delimchar(int c) +{ + if(c == '\0') + return 1; + if(c == '.' || c == ':' || (isascii(c) && isalnum(c))) + return 0; + return 1; +} + +/* + * `from' may contain an address followed by other characters, + * at least in /boot, so we permit whitespace (and more) after the address. + * we do ensure that "delete" cannot be parsed as "de::". + * + * some callers don't check the return value for errors, so + * set `to' to something distinctive in the case of a parse error. + */ +vlong +parseip(uchar *to, char *from) +{ + int i, elipsis = 0, v4 = 1; + ulong x; + char *p, *op; + + memset(to, 0, IPaddrlen); + p = from; + for(i = 0; i < IPaddrlen && ipcharok(*p); i+=2){ + op = p; + x = strtoul(p, &p, 16); + if((*p == '.' && i <= IPaddrlen-4) || (*p == 0 && i == 0)){ + /* ends with v4 */ + p = v4parseip(to+i, op); + i += 4; + break; + } + /* v6: at most 4 hex digits, followed by colon or delim */ + if(x != (ushort)x || (*p != ':' && !delimchar(*p))) { + memset(to, 0, IPaddrlen); + return -1; /* parse error */ + } + to[i] = x>>8; + to[i+1] = x; + if(*p == ':'){ + v4 = 0; + if(*++p == ':'){ /* :: is elided zero short(s) */ + if (elipsis) { + memset(to, 0, IPaddrlen); + return -1; /* second :: */ + } + elipsis = i+2; + p++; + } + } else if (p == op) /* strtoul made no progress? */ + break; + } + if (p == from || !delimchar(*p)) { + memset(to, 0, IPaddrlen); + return -1; /* parse error */ + } + if(i < IPaddrlen){ + memmove(&to[elipsis+IPaddrlen-i], &to[elipsis], i-elipsis); + memset(&to[elipsis], 0, IPaddrlen-i); + } + if(v4){ + to[10] = to[11] = 0xff; + return nhgetl(to + IPv4off); + } else + return 6; +} + +/* + * hack to allow ip v4 masks to be entered in the old + * style + */ +vlong +parseipmask(uchar *to, char *from) +{ + int i, w; + vlong x; + uchar *p; + + if(*from == '/'){ + /* as a number of prefix bits */ + i = atoi(from+1); + if(i < 0) + i = 0; + if(i > 128) + i = 128; + w = i; + memset(to, 0, IPaddrlen); + for(p = to; i >= 8; i -= 8) + *p++ = 0xff; + if(i > 0) + *p = ~((1<<(8-i))-1); + x = nhgetl(to+IPv4off); + /* + * identify as ipv6 if the mask is inexpressible as a v4 mask + * (because it has too few mask bits). Arguably, we could + * always return 6 here. + */ + if (w < 8*(IPaddrlen-IPv4addrlen)) + return 6; + } else { + /* as a straight v4 bit mask */ + x = parseip(to, from); + if (x != -1) + x = (ulong)nhgetl(to + IPv4off); + if(memcmp(to, v4prefix, IPv4off) == 0) + memset(to, 0xff, IPv4off); + } + return x; +} + +/* + * parse a v4 ip address/mask in cidr format + */ +char* +v4parsecidr(uchar *addr, uchar *mask, char *from) +{ + int i; + char *p; + uchar *a; + + p = v4parseip(addr, from); + + if(*p == '/'){ + /* as a number of prefix bits */ + i = strtoul(p+1, &p, 0); + if(i > 32) + i = 32; + memset(mask, 0, IPv4addrlen); + for(a = mask; i >= 8; i -= 8) + *a++ = 0xff; + if(i > 0) + *a = ~((1<<(8-i))-1); + } else + memcpy(mask, defmask(addr), IPv4addrlen); + return p; +}