commit d7094239263eac816ebb3af32641079b7924c666 from: rsc date: Sun Nov 23 18:23:20 2003 UTC add libip commit - 99947423b136903263513b9022aab6586c8c6cc5 commit + d7094239263eac816ebb3af32641079b7924c666 blob - /dev/null blob + 54675d8cb7e0c51700c422cce7b0c6017c2d8ae4 (mode 644) --- /dev/null +++ src/libip/bo.c @@ -0,0 +1,44 @@ +#include +#include +#include + + +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; +} + +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); +} blob - /dev/null blob + 5932f878f0ed10027479542fbac99f6a88d22f34 (mode 644) --- /dev/null +++ src/libip/classmask.c @@ -0,0 +1,25 @@ +#include +#include +#include + +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, +}; + +uchar* +defmask(uchar *ip) +{ + return classmask[ip[IPv4off]>>6]; +} + +void +maskip(uchar *from, uchar *mask, uchar *to) +{ + int i; + + for(i = 0; i < IPaddrlen; i++) + to[i] = from[i] & mask[i]; +} blob - /dev/null blob + 8333225a5fa52e14630e47514a29ab26be06d132 (mode 644) --- /dev/null +++ src/libip/eipfmt.c @@ -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 = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; + 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)"); +} blob - /dev/null blob + 858bc1ca684a8d35e888578aa1df7c47764c19fb (mode 644) --- /dev/null +++ src/libip/equivip.c @@ -0,0 +1,13 @@ +#include +#include + +int +equivip(uchar *a, uchar *b) +{ + int i; + + for(i = 0; i < 4; i++) + if(a[i] != b[i]) + return 0; + return 1; +} blob - /dev/null blob + aae565c0fc66ef9500b61fdfadc0810c2c4a28fd (mode 644) --- /dev/null +++ src/libip/ip.h @@ -0,0 +1,77 @@ +#pragma src "/sys/src/libip" +#pragma lib "libip.a" + +enum +{ + IPaddrlen= 16, + IPv4addrlen= 4, + IPv4off= 12, + IPllen= 4, +}; + +/* + * for reading /net/ipifc + */ +typedef struct Ipifc Ipifc; +typedef struct Ipifcs Ipifcs; + +struct Ipifc +{ + char dev[64]; + uchar ip[IPaddrlen]; + uchar mask[IPaddrlen]; + uchar net[IPaddrlen]; /* ip & mask */ + Ipifc *next; +}; + +struct Ipifcs +{ + Ipifc *first; + Ipifc *last; +}; + +/* + * user level udp headers + */ +enum +{ + Udphdrsize= 36, /* size of a Udphdr */ +}; + +typedef struct Udphdr Udphdr; +struct Udphdr +{ + uchar raddr[IPaddrlen]; /* remote address and port */ + uchar laddr[IPaddrlen]; /* local address and port */ + uchar rport[2]; + uchar lport[2]; +}; + +uchar* defmask(uchar*); +void maskip(uchar*, uchar*, uchar*); +int eipconv(va_list*, Fconv*); +ulong parseip(uchar*, char*); +ulong parseipmask(uchar*, char*); +int parseether(uchar*, char*); +int myipaddr(uchar*, char*); +int myetheraddr(uchar*, char*); + +void readipifc(char*, Ipifcs*); + +void hnputl(void*, uint); +void hnputs(void*, ushort); +uint nhgetl(void*); +ushort nhgets(void*); + +#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) blob - /dev/null blob + 215b37ee94195b194df726d344a15902560fcb26 (mode 644) --- /dev/null +++ src/libip/ipaux.c @@ -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; + } +} blob - /dev/null blob + d6995b7a0fa797cd5ce8c4b0b826c6b48d86e51a (mode 644) --- /dev/null +++ src/libip/myetheraddr.c @@ -0,0 +1,41 @@ +#include +#include +#include + +int +myetheraddr(uchar *to, char *dev) +{ + int n, fd; + char buf[256], *ptr; + + /* Make one exist */ + if(*dev == '/') + sprint(buf, "%s/clone", dev); + else + sprint(buf, "/net/%s/clone", dev); + fd = open(buf, ORDWR); + if(fd >= 0) + close(fd); + + if(*dev == '/') + sprint(buf, "%s/0/stats", dev); + else + sprint(buf, "/net/%s/0/stats", dev); + fd = open(buf, OREAD); + if(fd < 0) + return -1; + + n = read(fd, buf, sizeof(buf)-1); + close(fd); + if(n <= 0) + return -1; + buf[n] = 0; + + ptr = strstr(buf, "addr: "); + if(!ptr) + return -1; + ptr += 6; + + parseether(to, ptr); + return 0; +} blob - /dev/null blob + d9b692017ef9950cefd58f14c8959044e9625d9c (mode 644) --- /dev/null +++ src/libip/myipaddr.c @@ -0,0 +1,21 @@ +#include +#include +#include + +int +myipaddr(uchar *ip, char *net) +{ + Ipifc *nifc; + Iplifc *lifc; + static Ipifc *ifc; + + ifc = readipifc(net, ifc, -1); + for(nifc = ifc; nifc; nifc = nifc->next) + for(lifc = nifc->lifc; lifc; lifc = lifc->next) + if(ipcmp(lifc->ip, IPnoaddr) != 0){ + ipmove(ip, lifc->ip); + return 0; + } + ipmove(ip, IPnoaddr); + return -1; +} blob - /dev/null blob + f199eb6f11cf7eb33aaad325143d69cbb71aba77 (mode 644) --- /dev/null +++ src/libip/parseether.c @@ -0,0 +1,25 @@ +#include +#include + +int +parseether(uchar *to, char *from) +{ + char nip[4]; + char *p; + int i; + + p = from; + for(i = 0; i < 6; i++){ + if(*p == 0) + return -1; + nip[0] = *p++; + if(*p == 0) + return -1; + nip[1] = *p++; + nip[2] = 0; + to[i] = strtoul(nip, 0, 16); + if(*p == ':') + p++; + } + return 0; +} blob - /dev/null blob + c0dd55ccdc549f37abffb024b7926360873dbbe7 (mode 644) --- /dev/null +++ src/libip/parseip.c @@ -0,0 +1,135 @@ +#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; +} + +ulong +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 < 16 && *p; i+=2){ + op = p; + x = strtoul(p, &p, 16); + if(*p == '.' || (*p == 0 && i == 0)){ + p = v4parseip(to+i, op); + i += 4; + break; + } + to[i] = x>>8; + to[i+1] = x; + if(*p == ':'){ + v4 = 0; + if(*++p == ':'){ + elipsis = i+2; + p++; + } + } + } + if(i < 16){ + memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis); + memset(&to[elipsis], 0, 16-i); + } + if(v4){ + to[10] = to[11] = 0xff; + return nhgetl(to+12); + } else + return 6; +} + +/* + * hack to allow ip v4 masks to be entered in the old + * style + */ +ulong +parseipmask(uchar *to, char *from) +{ + ulong x; + int i; + uchar *p; + + if(*from == '/'){ + /* as a number of prefix bits */ + i = atoi(from+1); + if(i < 0) + i = 0; + if(i > 128) + i = 128; + 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); + } else { + /* as a straight bit mask */ + x = parseip(to, from); + 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; +} blob - /dev/null blob + d87815bce5fe02415748b98011da58bd533cb2a2 (mode 644) --- /dev/null +++ src/libip/ptclbsum.c @@ -0,0 +1,68 @@ +#include +#include +#include + +static short endian = 1; +static uchar* aendian = (uchar*)&endian; +#define LITTLE *aendian + +ushort +ptclbsum(uchar *addr, int len) +{ + ulong losum, hisum, mdsum, x; + ulong t1, t2; + + losum = 0; + hisum = 0; + mdsum = 0; + + x = 0; + if((ulong)addr & 1) { + if(len) { + hisum += addr[0]; + len--; + addr++; + } + x = 1; + } + while(len >= 16) { + t1 = *(ushort*)(addr+0); + t2 = *(ushort*)(addr+2); mdsum += t1; + t1 = *(ushort*)(addr+4); mdsum += t2; + t2 = *(ushort*)(addr+6); mdsum += t1; + t1 = *(ushort*)(addr+8); mdsum += t2; + t2 = *(ushort*)(addr+10); mdsum += t1; + t1 = *(ushort*)(addr+12); mdsum += t2; + t2 = *(ushort*)(addr+14); mdsum += t1; + mdsum += t2; + len -= 16; + addr += 16; + } + while(len >= 2) { + mdsum += *(ushort*)addr; + len -= 2; + addr += 2; + } + if(x) { + if(len) + losum += addr[0]; + if(LITTLE) + losum += mdsum; + else + hisum += mdsum; + } else { + if(len) + hisum += addr[0]; + if(LITTLE) + hisum += mdsum; + else + losum += mdsum; + } + + losum += hisum >> 8; + losum += (hisum & 0xff) << 8; + while(hisum = losum>>16) + losum = hisum + (losum & 0xffff); + + return losum & 0xffff; +} blob - /dev/null blob + b28b3b0cf7ad426450b0bf65bcf5298d34c5cb0d (mode 644) --- /dev/null +++ src/libip/readipifc.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include + +static Ipifc** +_readoldipifc(char *buf, Ipifc **l, int index) +{ + char *f[200]; + int i, n; + Ipifc *ifc; + Iplifc *lifc, **ll; + + /* allocate new interface */ + *l = ifc = mallocz(sizeof(Ipifc), 1); + if(ifc == nil) + return l; + l = &ifc->next; + ifc->index = index; + + n = tokenize(buf, f, nelem(f)); + if(n < 2) + return l; + + strncpy(ifc->dev, f[0], sizeof ifc->dev); + ifc->dev[sizeof(ifc->dev) - 1] = 0; + ifc->mtu = strtoul(f[1], nil, 10); + + ll = &ifc->lifc; + for(i = 2; n-i >= 7; i += 7){ + /* allocate new local address */ + *ll = lifc = mallocz(sizeof(Iplifc), 1); + ll = &lifc->next; + + parseip(lifc->ip, f[i]); + parseipmask(lifc->mask, f[i+1]); + parseip(lifc->net, f[i+2]); + ifc->pktin = strtoul(f[i+3], nil, 10); + ifc->pktout = strtoul(f[i+4], nil, 10); + ifc->errin = strtoul(f[i+5], nil, 10); + ifc->errout = strtoul(f[i+6], nil, 10); + } + return l; +} + +static char* +findfield(char *name, char **f, int n) +{ + int i; + + for(i = 0; i < n-1; i++) + if(strcmp(f[i], name) == 0) + return f[i+1]; + return ""; +} + +static Ipifc** +_readipifc(char *file, Ipifc **l, int index) +{ + int i, n, fd, lines; + char buf[4*1024]; + char *line[32]; + char *f[64]; + Ipifc *ifc; + Iplifc *lifc, **ll; + + /* read the file */ + fd = open(file, OREAD); + if(fd < 0) + return l; + n = 0; + while((i = read(fd, buf+n, sizeof(buf)-1-n)) > 0 && n < sizeof(buf) - 1) + n += i; + buf[n] = 0; + close(fd); + + if(strncmp(buf, "device", 6) != 0) + return _readoldipifc(buf, l, index); + + /* allocate new interface */ + *l = ifc = mallocz(sizeof(Ipifc), 1); + if(ifc == nil) + return l; + l = &ifc->next; + ifc->index = index; + + lines = getfields(buf, line, nelem(line), 1, "\n"); + + /* pick off device specific info(first line) */ + n = tokenize(line[0], f, nelem(f)); + strncpy(ifc->dev, findfield("device", f, n), sizeof(ifc->dev)); + ifc->dev[sizeof(ifc->dev)-1] = 0; + if(ifc->dev[0] == 0){ + free(ifc); + return l; + } + ifc->mtu = strtoul(findfield("maxmtu", f, n), nil, 10); + ifc->sendra6 = atoi(findfield("sendra", f, n)); + ifc->recvra6 = atoi(findfield("recvra", f, n)); + ifc->rp.mflag = atoi(findfield("mflag", f, n)); + ifc->rp.oflag = atoi(findfield("oflag", f, n)); + ifc->rp.maxraint = atoi(findfield("maxraint", f, n)); + ifc->rp.minraint = atoi(findfield("minraint", f, n)); + ifc->rp.linkmtu = atoi(findfield("linkmtu", f, n)); + ifc->rp.reachtime = atoi(findfield("reachtime", f, n)); + ifc->rp.rxmitra = atoi(findfield("rxmitra", f, n)); + ifc->rp.ttl = atoi(findfield("ttl", f, n)); + ifc->rp.routerlt = atoi(findfield("routerlt", f, n)); + ifc->pktin = strtoul(findfield("pktin", f, n), nil, 10); + ifc->pktout = strtoul(findfield("pktout", f, n), nil, 10); + ifc->errin = strtoul(findfield("errin", f, n), nil, 10); + ifc->errout = strtoul(findfield("errout", f, n), nil, 10); + + /* now read the addresses */ + ll = &ifc->lifc; + for(i = 1; i < lines; i++){ + n = tokenize(line[i], f, nelem(f)); + if(n < 5) + break; + + /* allocate new local address */ + *ll = lifc = mallocz(sizeof(Iplifc), 1); + ll = &lifc->next; + + parseip(lifc->ip, f[0]); + parseipmask(lifc->mask, f[1]); + parseip(lifc->net, f[2]); + + lifc->validlt = strtoul(f[3], nil, 10); + lifc->preflt = strtoul(f[4], nil, 10); + } + + return l; +} + +static void +_freeifc(Ipifc *ifc) +{ + Ipifc *next; + Iplifc *lnext, *lifc; + + if(ifc == nil) + return; + for(; ifc; ifc = next){ + next = ifc->next; + for(lifc = ifc->lifc; lifc; lifc = lnext){ + lnext = lifc->next; + free(lifc); + } + free(ifc); + } +} + +Ipifc* +readipifc(char *net, Ipifc *ifc, int index) +{ + int fd, i, n; + Dir *dir; + char directory[128]; + char buf[128]; + Ipifc **l; + + _freeifc(ifc); + + l = &ifc; + ifc = nil; + + if(net == 0) + net = "/net"; + snprint(directory, sizeof(directory), "%s/ipifc", net); + + if(index >= 0){ + snprint(buf, sizeof(buf), "%s/%d/status", directory, index); + _readipifc(buf, l, index); + } else { + fd = open(directory, OREAD); + if(fd < 0) + return nil; + n = dirreadall(fd, &dir); + close(fd); + + for(i = 0; i < n; i++){ + if(strcmp(dir[i].name, "clone") == 0) + continue; + if(strcmp(dir[i].name, "stats") == 0) + continue; + snprint(buf, sizeof(buf), "%s/%s/status", directory, dir[i].name); + l = _readipifc(buf, l, atoi(dir[i].name)); + } + free(dir); + } + + return ifc; +} blob - /dev/null blob + aa57120c8e938500322e8d07596ea6ade4bdbf8d (mode 644) --- /dev/null +++ src/libip/testreadipifc.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void +main(void) +{ + Ipifc *ifc, *list; + Iplifc *lifc; + int i; + + fmtinstall('I', eipfmt); + fmtinstall('M', eipfmt); + + list = readipifc("/net", nil, -1); + for(ifc = list; ifc; ifc = ifc->next){ + print("ipifc %s %d\n", ifc->dev, ifc->mtu); + for(lifc = ifc->lifc; lifc; lifc = lifc->next) + print("\t%I %M %I\n", lifc->ip, lifc->mask, lifc->net); + } +}