## diffname port/deviproute.c 1991/0330 ## diff -e /dev/null /n/bootesdump/1991/0330/sys/src/9/port/deviproute.c 0a #include #include typedef struct Iproute Iproute; typedef struct Iprtab Iprtab; enum { Nroutes= 256, }; /* * Standard ip masks for the 3 classes */ uchar classmask[4][4] = { 0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0, }; #define CLASSMASK(x) classmask[(*x>>6) & 3] /* * routes */ struct Iproute { uchar dst[4]; uchar gate[4]; uchar mask[4]; Iproute *next; int inuse; }; struct Iprtab { /* Lock; */ Iproute *first; Iproute r[Nroutes]; /* routings */ }; Iprtab iprtab; #define lock(x) #define unlock(x) void printroute(void) { Iproute *r; print("\n"); for(r = iprtab.first; r; r = r->next) print("%d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d\n", r->dst[0], r->dst[1], r->dst[2], r->dst[3], r->mask[0], r->mask[1], r->mask[2], r->mask[3], r->gate[0], r->gate[1], r->gate[2], r->gate[3]); print("\n"); } /* * The chosen route is the one obeys the constraint * r->mask[x] & dst[x] == r->dst[x] for x in 0 1 2 3 * * If there are several matches, the one whose mask has the most * leading ones (and hence is the most specific) wins. * * If there is no match, the default gateway is chosen. */ void iproute(uchar *dst, uchar *gate) { Iproute *r; /* * first check routes */ lock(&iprtab); for(r = iprtab.first; r; r = r->next){ if((r->mask[0]&dst[0]) == r->dst[0] && (r->mask[1]&dst[1]) == r->dst[1] && (r->mask[2]&dst[2]) == r->dst[2] && (r->mask[3]&dst[3]) == r->dst[3]){ memmove(gate, r->gate, 4); unlock(&iprtab); return; } } unlock(&iprtab); /* * else just return what we got */ memmove(gate, dst, 4); } /* * Compares 2 subnet masks and returns an integer less than, equal to, * or greater than 0, according as m1 is numericly less than, * equal to, or greater than m2. */ ipmaskcmp(uchar *m1, uchar *m2) { int a, i; for(i = 0; i < 4; i++){ if(a = *m1++ - *m2++) return a; } return 0; } /* * Add a route, create a mask if the first mask is 0. * * All routes are stored sorted by the length of leading * ones in the mask. * * NOTE: A default route has an all zeroes mask and dst. */ void ipaddroute(uchar *dst, uchar *mask, uchar *gate) { Iproute *r, *e, *free; int i; if(mask==0) mask = CLASSMASK(dst); /* * filter out impossible requests */ for(i = 0; i < 4; i++) if((dst[i]&mask[i]) != dst[i]) return; /* * see if we already have a route for * the destination */ lock(&iprtab); free = 0; for(r = iprtab.r; r < &iprtab.r[Nroutes]; r++){ if(r->inuse == 0){ free = r; continue; } if(memcmp(dst, r->dst, 4)==0 && memcmp(mask, r->mask, 4)==0){ memmove(r->gate, gate, 4); unlock(&iprtab); return; } } /* * add the new route in sorted order */ memmove(free->dst, dst, 4); memmove(free->mask, mask, 4); memmove(free->gate, gate, 4); free->inuse = 1; for(r = iprtab.first; r; r = r->next){ if(ipmaskcmp(free->mask, r->mask) > 0) break; e = r; } free->next = r; if(r == iprtab.first) iprtab.first = free; else e->next = free; unlock(&iprtab); } /* * remove a route */ void ipremroute(uchar *dst, uchar *mask) { Iproute *r, *e; lock(&iprtab); for(r = iprtab.first; r; r = r->next){ if(memcmp(dst, r->dst, 4)==0 && memcmp(mask, r->mask, 4)==0){ if(r == iprtab.first) iprtab.first = r->next; else e->next = r->next; r->inuse = 0; break; } e = r; } unlock(&iprtab); } /* * remove all routes */ void ipflushroute(void) { Iproute *r; lock(&iprtab); for(r = iprtab.first; r; r = r->next) r->inuse = 0; iprtab.first = 0; unlock(&iprtab); } . ## diffname port/deviproute.c 1991/0331 ## diff -e /n/bootesdump/1991/0330/sys/src/9/port/deviproute.c /n/bootesdump/1991/0331/sys/src/9/port/deviproute.c 206a } /* * device interface */ enum{ Qdir, Qdata, }; Dirtab iproutetab[]={ "iproute", Qdata, 0, 0600, }; #define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) void iproutereset(void) { } void iprouteinit(void) { } Chan * iprouteattach(char *spec) { return devattach('R', spec); } Chan * iprouteclone(Chan *c, Chan *nc) { return devclone(c, nc); } int iproutewalk(Chan *c, char *name) { return devwalk(c, name, iproutetab, (long)Niproutetab, devgen); } void iproutestat(Chan *c, char *db) { devstat(c, db, iproutetab, (long)Niproutetab, devgen); } Chan * iprouteopen(Chan *c, int omode) { if(c->qid.path == CHDIR){ if(omode != OREAD) error(Eperm); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void iproutecreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void iprouteremove(Chan *c) { error(Eperm); } void iproutewstat(Chan *c, char *dp) { error(Eperm); } void iprouteclose(Chan *c) { } #define IPR_ENTRYLEN 54 #define PAD " " long iprouteread(Chan *c, void *a, long n) { char buf[IPR_ENTRYLEN*2]; Iproute *r; int part, bytes, size; switch((int)(c->qid.path&~CHDIR)){ case Qdir: return devdirread(c, a, n, iproutetab, Niproutetab, devgen); case Qdata: lock(&iprtab); part = c->offset/IPR_ENTRYLEN; for(r = iprtab.first; part && r; r = r->next) ; bytes = c->offset; while(bytes < iprtab.n*IPR_ENTRYLEN && n){ part = bytes%IPR_ENTRYLEN; sprint(buf,"%d.%d.%d.%d & %d.%d.%d.%d -> %d.%d.%d.%d%s", r->dst[0], r->dst[1], r->dst[2], r->dst[3], r->mask[0], r->mask[1], r->mask[2], r->mask[3], r->gate[0], r->gate[1], r->gate[2], r->gate[3], PAD); buf[IPR_ENTRYLEN-1] = '\n'; size = IPR_ENTRYLEN - part; size = MIN(n, size); memmove(a, buf+part, size); a = (void *)((int)a + size); n -= size; bytes += size; } unlock(&iprtab); return bytes - c->offset; break; default: n=0; break; } return n; } long iproutewrite(Chan *c, char *a, long n) { char buf[IPR_ENTRYLEN]; char *field[4]; uchar mask[4], dst[4], gate[4]; int m; switch((int)(c->qid.path&~CHDIR)){ case Qdata: strncpy(buf, a, sizeof buf); m = getfields(buf, field, 4, ' '); if(strncmp(field[0], "flush", 5) == 0) ipflushroute(); else if(strcmp(field[0], "add") == 0){ switch(m){ case 4: strtoip(field[1], dst); strtoip(field[2], mask); strtoip(field[3], gate); ipaddroute(dst, mask, gate); break; case 3: strtoip(field[1], dst); strtoip(field[2], gate); ipaddroute(dst, 0, gate); break; default: error(Ebadarg); } } else if(strcmp(field[0], "delete") == 0){ switch(m){ case 3: strtoip(field[1], dst); strtoip(field[2], mask); ipremroute(dst, mask); break; case 2: strtoip(field[1], dst); ipremroute(dst, 0); break; default: error(Ebadarg); } } break; default: error(Ebadusefd); } return n; . 205a iprtab.n = 0; . 186a iprtab.n--; . 167a iprtab.n++; . 149a if(free == 0) errors("no free ip routes"); . 131c errors("bad ip route"); . 48,54c /* convert the bytes */ for(i = 0; i<4 & *rptr; i++) addr[i] = strtoul(rptr, &rptr, 0); /* move host bytes to the right place */ first = NETBYTES(addr); off = 4 - i; if(off) while(i != first){ --i; addr[i+off] = addr[i]; } . 46c int i, off, first; char *rptr = s; . 44c strtoip(char *s, uchar *addr) . 40,42c /* * Convert string to ip address. This is rediculously difficult because * the designers of ip decided to allow any leading zero bytes in the * host part to be left out. */ . 34,36c Lock; int n; /* number of valid routes */ Iproute *first; /* list of valid routes */ Iproute r[Nroutes]; /* all routes */ . 22a uchar netbytes[4] = { 1, 1, 2, 3 }; #define NETBYTES(x) netbytes[(*x>>6) & 3] . 3a #include "devtab.h" . 1,2c #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" . ## diffname port/deviproute.c 1991/0401 ## diff -e /n/bootesdump/1991/0331/sys/src/9/port/deviproute.c /n/bootesdump/1991/0401/sys/src/9/port/deviproute.c 401,402c dst = ipparse(field[1]); ipremroute(dst, classmask[dst>>30]); . 396,397c dst = ipparse(field[1]); mask = ipparse(field[2]); . 386,388c dst = ipparse(field[1]); gate = ipparse(field[2]); ipaddroute(dst, classmask[dst>>30], gate); . 380,382c dst = ipparse(field[1]); mask = ipparse(field[2]); gate = ipparse(field[3]); . 367c Ipaddr mask, dst, gate; . 350a r = r->next; . 345c if(size > n) size = n; . 337,339c dst[0], dst[1], dst[2], dst[3], mask[0], mask[1], mask[2], mask[3], gate[0], gate[1], gate[2], gate[3], . 335a hnputl(dst, r->dst); hnputl(mask, r->mask); hnputl(gate, r->gate); . 333c while(r && bytes < iprtab.n*IPR_ENTRYLEN && n){ . 331c part--; . 322a uchar dst[4], mask[4], gate[4]; . 320c char buf[IPR_ENTRYLEN*3]; . 201,202c for(r = e = iprtab.first; r; r = r->next){ if(dst==r->dst && mask==r->mask){ . 196c ipremroute(ulong dst, ulong mask) . 178,179c for(r = e = iprtab.first; r; r = r->next){ if(mask > r->mask) . 174,176c free->dst = dst; free->mask = mask; free->gate = gate; . 169a } . 168c if(free == 0){ unlock(&iprtab); . 162,163c if(dst==r->dst && mask==r->mask){ r->gate = gate; . 147,149c if((dst&mask) != dst) errors("bad ip route"); . 141,143d 136c ipaddroute(ulong dst, ulong mask, ulong gate) . 112,127d 106c * else just return the same address . 103d 94,99c if((r->mask&udst) == r->dst){ hnputl(gate, r->gate); . 92d 88a udst = nhgetl(dst); if((udst&Mymask) == (Myip&Mymask)){ memmove(gate, dst, 4); return; } . 87a ulong udst; . 80,82c * leading ones (and hence is the most specific) wins. This is * forced by storing the routes in decreasing number of ones order * and returning the first match. The default gateway has no ones * in the mask and is thus the last matched. . 77c * r->mask & dst == r->dst . 51,75d 36,38c ulong dst; ulong gate; ulong mask; . 19,32d 9a /* * All ip numbers and masks are stored as ulongs. * All interfaces to this code uses the standard byte * string representation. */ . 6a #include "arp.h" #include "ipdat.h" . ## diffname port/deviproute.c 1991/0411 ## diff -e /n/bootesdump/1991/0401/sys/src/9/port/deviproute.c /n/bootesdump/1991/0411/sys/src/9/port/deviproute.c 322c iproutewrite(Chan *c, char *a, long n, ulong offset) . 312c return bytes - offset; . 286c bytes = offset; . 283c part = offset/IPR_ENTRYLEN; . 271c iprouteread(Chan *c, void *a, long n, ulong offset) . ## diffname port/deviproute.c 1991/0418 ## diff -e /n/bootesdump/1991/0411/sys/src/9/port/deviproute.c /n/bootesdump/1991/0418/sys/src/9/port/deviproute.c 210c return devattach('P', spec); . ## diffname port/deviproute.c 1991/0419 ## diff -e /n/bootesdump/1991/0418/sys/src/9/port/deviproute.c /n/bootesdump/1991/0419/sys/src/9/port/deviproute.c 222a } Chan* iprouteclwalk(Chan *c, char *name) { return devclwalk(c, name); . 193c "iproute", {Qdata}, 0, 0600, . ## diffname port/deviproute.c 1991/0427 ## diff -e /n/bootesdump/1991/0419/sys/src/9/port/deviproute.c /n/bootesdump/1991/0427/sys/src/9/port/deviproute.c 225,230d ## diffname port/deviproute.c 1991/0629 ## diff -e /n/bootesdump/1991/0427/sys/src/9/port/deviproute.c /n/bootesdump/1991/0629/sys/src/9/port/deviproute.c 193c "iproute", {Qdata}, 0, 0666, . ## diffname port/deviproute.c 1991/0705 ## diff -e /n/bootesdump/1991/0629/sys/src/9/port/deviproute.c /n/bootesdump/1991/0705/sys/src/9/port/deviproute.c 193c "iproute", {Qdata}, 0, 0600, . ## diffname port/deviproute.c 1991/1112 ## diff -e /n/bootesdump/1991/0705/sys/src/9/port/deviproute.c /n/bootesdump/1991/1112/sys/src/9/port/deviproute.c 193c "iproute", {Qdata}, 0, 0666, . ## diffname port/deviproute.c 1991/1115 ## diff -e /n/bootesdump/1991/1112/sys/src/9/port/deviproute.c /n/bootesdump/1991/1115/sys/src/9/port/deviproute.c 264a USED(c); . 258a USED(c, dp); . 252a USED(c); . 246a USED(c, name, omode, perm); . ## diffname port/deviproute.c 1992/0111 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/deviproute.c /n/bootesdump/1992/0111/sys/src/9/port/deviproute.c 6c #include "../port/error.h" . ## diffname port/deviproute.c 1992/0112 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/deviproute.c /n/bootesdump/1992/0112/sys/src/9/port/deviproute.c 121c error(Enoroute); . 100c error(Ebadaddr); . ## diffname port/deviproute.c 1992/0114 ## diff -e /n/bootesdump/1992/0112/sys/src/9/port/deviproute.c /n/bootesdump/1992/0114/sys/src/9/port/deviproute.c 121c exhausted("routes"); . 100c error(Enetaddr); . ## diffname port/deviproute.c 1992/0213 ## diff -e /n/bootesdump/1992/0114/sys/src/9/port/deviproute.c /n/bootesdump/1992/0213/sys/src/9/port/deviproute.c 61c if((udst&Mymask) == (Myip[Myself]&Mymask)){ . ## diffname port/deviproute.c 1992/0304 ## diff -e /n/bootesdump/1992/0213/sys/src/9/port/deviproute.c /n/bootesdump/1992/0304/sys/src/9/port/deviproute.c 61c if((udst&Mynetmask) == (Myip[Myself]&Mynetmask)){ . ## diffname port/deviproute.c 1992/0321 ## diff -e /n/bootesdump/1992/0304/sys/src/9/port/deviproute.c /n/bootesdump/1992/0321/sys/src/9/port/deviproute.c 2c #include "../port/lib.h" . ## diffname port/deviproute.c 1992/0711 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/deviproute.c /n/bootesdump/1992/0711/sys/src/9/port/deviproute.c 331a USED(offset); . 94d ## diffname port/deviproute.c 1993/0804 # deleted ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/deviproute.c /n/fornaxdump/1993/0804/sys/src/brazil/port/deviproute.c 1,377d