## diffname ip/iproute.c 1998/0306 ## diff -e /dev/null /n/emeliedump/1998/0306/sys/src/brazil/ip/iproute.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "ip.h" enum { Lroot = 10, }; Route *v4root[1<left = nil; r->right = nil; if(r->type & Rv4) l = &v4freelist; else l = &v6freelist; r->mid = *l; *l = r; } static Route* allocroute(int type) { Route *r; int n; Route **l; if(type & Rv4){ n = sizeof(RouteTree) + sizeof(V4route); l = &v4freelist; } else { n = sizeof(RouteTree) + sizeof(V6route); l = &v6freelist; } r = *l; if(r != nil){ *l = r->mid; } else { r = malloc(n); if(r == nil) panic("out of routing nodes"); } memset(r, 0, n); r->type = type; r->ifc = nil; return r; } static void addqueue(Route **q, Route *r) { Route *l; if(r == nil) return; l = allocroute(r->type); l->mid = *q; *q = l; l->left = r; } /* * compare 2 v6 addresses */ static int lcmp(ulong *a, ulong *b) { int i; for(i = 0; i < IPllen; i++){ if(a[i] > b[i]) return 1; if(a[i] < b[i]) return -1; } return 0; } /* * compare 2 v4 or v6 ranges */ enum { Rpreceeds, Rfollows, Requals, Rcontains, Rcontained, }; static int rangecompare(Route *a, Route *b) { if(a->type & Rv4){ if(a->v4.endaddress < b->v4.address) return Rpreceeds; if(a->v4.address > b->v4.endaddress) return Rfollows; if(a->v4.address <= b->v4.address && a->v4.endaddress >= b->v4.endaddress){ if(a->v4.address == b->v4.address && a->v4.endaddress == b->v4.endaddress) return Requals; return Rcontains; } return Rcontained; } if(lcmp(a->v6.endaddress, b->v6.address) < 0) return Rpreceeds; if(lcmp(a->v6.address, b->v6.endaddress) > 0) return Rfollows; if(lcmp(a->v6.address, b->v6.address) <= 0 && lcmp(a->v6.endaddress, b->v6.endaddress) >= 0){ if(lcmp(a->v6.address, b->v6.address) == 0 && lcmp(a->v6.endaddress, b->v6.endaddress) == 0) return Requals; return Rcontains; } return Rcontained; } static void copygate(Route *old, Route *new) { if(new->type & Rv4) memmove(old->v4.gate, new->v4.gate, IPv4addrlen); else memmove(old->v6.gate, new->v6.gate, IPaddrlen); } /* * walk down a tree adding nodes back in */ static void walkadd(Route **root, Route *p) { Route *l, *r; l = p->left; r = p->right; p->left = 0; p->right = 0; addnode(root, p); if(l) walkadd(root, l); if(r) walkadd(root, r); } /* * calculate depth */ static void calcd(Route *p) { Route *q; int d; if(p) { d = 0; q = p->left; if(q) d = q->depth; q = p->right; if(q && q->depth > d) d = q->depth; q = p->mid; if(q && q->depth > d) d = q->depth; p->depth = d+1; } } /* * balance the tree at the current node */ static void balancetree(Route **cur) { Route *p, *l, *r; int dl, dr; /* * if left and right are * too out of balance, * rotate tree node */ p = *cur; dl = 0; if(l = p->left) dl = l->depth; dr = 0; if(r = p->right) dr = r->depth; if(dl > dr+1) { p->left = l->right; l->right = p; *cur = l; calcd(p); calcd(l); } else if(dr > dl+1) { p->right = r->left; r->left = p; *cur = r; calcd(p); calcd(r); } else calcd(p); } /* * add a new node to the tree */ static void addnode(Route **cur, Route *new) { Route *p; p = *cur; if(p == 0) { *cur = new; new->depth = 1; return; } switch(rangecompare(new, p)){ case Rpreceeds: addnode(&p->left, new); break; case Rfollows: addnode(&p->right, new); break; case Rcontains: /* * if new node is superset * of tree node, * replace tree node and * queue tree node to be * merged into root. */ *cur = new; new->depth = 1; addqueue(&queue, p); break; case Requals: copygate(p, new); freeroute(new); break; case Rcontained: addnode(&p->mid, new); break; } balancetree(cur); } #define V4H(a) ((a&0x07ffffff)>>(32-Lroot-5)) void v4addroute(char *tag, uchar *a, uchar *mask, uchar *gate, int type) { Route *p; ulong sa; ulong m; ulong ea; int h, eh; m = nhgetl(mask); sa = nhgetl(a) & m; ea = sa | ~m; eh = V4H(ea); for(h=V4H(sa); h<=eh; h++) { p = allocroute(Rv4 | type); p->v4.address = sa; p->v4.endaddress = ea; memmove(p->v4.gate, gate, sizeof(p->v4.gate)); memmove(p->tag, tag, sizeof(p->tag)); wlock(&routelock); addnode(&v4root[h], p); while(p = queue) { queue = p->mid; walkadd(&v4root[h], p->left); freeroute(p); } wunlock(&routelock); } ipifcaddroute(Rv4, a, mask, gate, type); } #define V6H(a) (((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5)) void v6addroute(char *tag, uchar *a, uchar *mask, uchar *gate, int type) { Route *p; ulong sa[IPllen], ea[IPllen]; ulong x, y; int h, eh; for(h = 0; h < IPllen; h++){ x = nhgetl(a+4*h); y = nhgetl(mask+4*h); sa[h] = x & y; ea[h] = x | ~y; } eh = V6H(ea); for(h = V6H(sa); h <= eh; h++) { p = allocroute(type); memmove(p->v6.address, sa, IPaddrlen); memmove(p->v6.endaddress, ea, IPaddrlen); memmove(p->v6.gate, gate, IPaddrlen); memmove(p->tag, tag, sizeof(p->tag)); wlock(&routelock); addnode(&v6root[h], p); while(p = queue) { queue = p->mid; walkadd(&v6root[h], p->left); freeroute(p); } wunlock(&routelock); } ipifcaddroute(0, a, mask, gate, type); } Route** looknode(Route **cur, Route *r) { Route *p; for(;;){ p = *cur; if(p == 0) return 0; switch(rangecompare(r, p)){ case Rcontains: return 0; case Rpreceeds: cur = &p->left; break; case Rfollows: cur = &p->right; break; case Rcontained: cur = &p->mid; break; case Requals: return cur; } } } void v4delroute(uchar *a, uchar *mask) { Route **r, *p; Route rt; int h, eh; ulong m; m = nhgetl(mask); rt.v4.address = nhgetl(a) & m; rt.v4.endaddress = rt.v4.address | ~m; rt.type = Rv4; eh = V4H(rt.v4.endaddress); for(h=V4H(rt.v4.address); h<=eh; h++) { wlock(&routelock); r = looknode(&v4root[h], &rt); if(r) { p = *r; *r = 0; addqueue(&queue, p->left); addqueue(&queue, p->mid); addqueue(&queue, p->right); freeroute(p); while(p = queue) { queue = p->mid; walkadd(&v4root[h], p->left); freeroute(p); } } wunlock(&routelock); } ipifcremroute(Rv4, a, mask); } void v6delroute(uchar *a, uchar *mask) { Route **r, *p; Route rt; int h, eh; ulong x, y; for(h = 0; h < IPllen; h++){ x = nhgetl(a+4*h); y = nhgetl(mask+4*h); rt.v6.address[h] = x & y; rt.v6.endaddress[h] = x | ~y; } rt.type = 0; eh = V6H(rt.v6.endaddress); for(h=V6H(rt.v6.address); h<=eh; h++) { wlock(&routelock); r = looknode(&v6root[h], &rt); if(r) { p = *r; *r = 0; addqueue(&queue, p->left); addqueue(&queue, p->mid); addqueue(&queue, p->right); freeroute(p); while(p = queue) { queue = p->mid; walkadd(&v6root[h], p->left); freeroute(p); } } wunlock(&routelock); } ipifcremroute(0, a, mask); } Route* v4lookup(uchar *a) { Route *p, *q; ulong la; uchar gate[IPaddrlen]; la = nhgetl(a); q = nil; for(p=v4root[V4H(la)]; p;) if(la >= p->v4.address) { if(la <= p->v4.endaddress) { q = p; p = p->mid; } else p = p->right; } else p = p->left; if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){ v4tov6(gate, q->v4.gate); q->ifc = findipifc(gate, q->type); if(q->ifc == nil) return nil; q->ifcid = q->ifc->ifcid; } return q; } Route* v6lookup(uchar *a) { Route *p, *q; ulong la[IPllen]; int h; ulong x, y; if(memcmp(a, v4prefix, 12) == 0){ q = v4lookup(a+12); if(q != nil) return q; } for(h = 0; h < IPllen; h++) la[h] = nhgetl(a+4*h); q = 0; for(p=v6root[V6H(la)]; p;){ for(h = 0; h < IPllen; h++){ x = la[h]; y = p->v6.address[h]; if(x == y) continue; if(x < y){ p = p->left; goto next; } break; } for(h = 0; h < IPllen; h++){ x = la[h]; y = p->v6.endaddress[h]; if(x == y) continue; if(x > y){ p = p->right; goto next; } break; } q = p; p = p->mid; next: ; } if(q && q->ifc == nil){ q->ifc = findipifc(q->v6.gate, q->type); if(q->ifc == nil) return nil; if(q->ifcid != q->ifc->ifcid) return nil; } return q; } enum { Rlinelen= 89, }; char *rformat = "%-24.24I %-24.24M %-24.24I %4.4s %4.4s %3s\n"; void convroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc) { int i; char *p = t; if(r->type & Rv4){ memmove(addr, v4prefix, IPv4off); hnputl(addr+IPv4off, r->v4.address); memset(mask, 0xff, IPv4off); hnputl(mask+IPv4off, ~(r->v4.endaddress ^ r->v4.address)); memmove(gate, v4prefix, IPv4off); memmove(gate+IPv4off, r->v4.gate, IPv4addrlen); } else { for(i = 0; i < IPllen; i++){ hnputl(addr + 4*i, r->v6.address[i]); hnputl(mask + 4*i, ~(r->v6.endaddress[i] ^ r->v6.address[i])); } memmove(gate, r->v6.gate, IPaddrlen); } memset(t, ' ', 4); t[4] = 0; if(r->type & Rv4) *p++ = '4'; else *p++ = '6'; if(r->type & Rifc) *p++ = 'i'; if(r->type & Runi) *p++ = 'u'; else if(r->type & Rbcast) *p++ = 'b'; else if(r->type & Rmulti) *p++ = 'm'; if(r->type & Rptpt) *p = 'p'; if(r->ifc) *nifc = r->ifc->conv->x; else *nifc = -1; } /* * this code is not in rr to reduce stack size */ static void sprintroute(Route *r, Routewalk *rw) { int nifc; char t[5], *iname, ifbuf[5]; uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen]; if(rw->o >= 0) { convroute(r, addr, mask, gate, t, &nifc); iname = "-"; if(nifc != -1) { iname = ifbuf; sprint(ifbuf, "%d", nifc); } sprint(rw->p, rformat, addr, mask, gate, t, r->tag, iname); rw->p += Rlinelen; } rw->o++; } /* * recurse descending tree, applying the function in Routewalk */ static int rr(Route *r, Routewalk *rw) { int h; if(rw->n <= rw->o) return 0; if(r == nil) return 1; if(rr(r->left, rw) == 0) return 0; if(r->type & Rv4) h = V4H(r->v4.address); else h = V6H(r->v6.address); if(h == rw->h) rw->walk(r, rw); if(rr(r->mid, rw) == 0) return 0; return rr(r->right, rw); } void ipwalkroutes(Routewalk *rw) { rlock(&routelock); if(rw->n > rw->o) { for(rw->h = 0; rw->h < nelem(v4root); rw->h++) if(rr(v4root[rw->h], rw) == 0) break; } if(rw->n > rw->o) { for(rw->h = 0; rw->h < nelem(v6root); rw->h++) if(rr(v6root[rw->h], rw) == 0) break; } runlock(&routelock); } long routeread(char *p, ulong offset, int n) { Routewalk rw; if(offset % Rlinelen) return 0; rw.p = p; rw.n = n/Rlinelen; rw.o = -(offset/Rlinelen); rw.walk = sprintroute; ipwalkroutes(&rw); if(rw.o < 0) rw.o = 0; return rw.o*Rlinelen; } /* * this code is not in routeflush to reduce stack size */ void delroute(Route *r) { uchar addr[IPaddrlen]; uchar mask[IPaddrlen]; uchar gate[IPaddrlen]; char t[5]; int nifc; convroute(r, addr, mask, gate, t, &nifc); if(r->type & Rv4) v4delroute(addr+IPv4off, mask+IPv4off); else v6delroute(addr, mask); } /* * recurse until one route is deleted * returns 0 if nothing is deleted, 1 otherwise */ int routeflush(Route *r) { if(r == nil) return 0; if(routeflush(r->mid)) return 1; if(routeflush(r->left)) return 1; if(routeflush(r->right)) return 1; if((r->type & Rifc) == 0){ delroute(r); return 1; } return 0; } long routewrite(Chan *c, char *p, int n) { int h; char *tag; Cmdbuf *cb; uchar addr[IPaddrlen]; uchar mask[IPaddrlen]; uchar gate[IPaddrlen]; cb = parsecmd(p, n); if(waserror()){ free(cb); nexterror(); } if(strcmp(cb->f[0], "flush") == 0){ wlock(&routelock); for(h = 0; h < nelem(v4root); h++) while(routeflush(v4root[h]) == 1) ; for(h = 0; h < nelem(v6root); h++) while(routeflush(v6root[h]) == 1) ; wunlock(&routelock); } else if(strcmp(cb->f[0], "remove") == 0){ if(cb->nf < 3) error(Ebadarg); parseip(addr, cb->f[1]); parseipmask(mask, cb->f[2]); if(memcmp(addr, v4prefix, IPv4off) == 0) v4delroute(addr+IPv4off, mask+IPv4off); else v6delroute(addr, mask); } else if(strcmp(cb->f[0], "add") == 0){ if(cb->nf < 4) error(Ebadarg); parseip(addr, cb->f[1]); parseipmask(mask, cb->f[2]); parseip(gate, cb->f[3]); tag = "none"; if(c != nil) tag = c->tag; if(memcmp(addr, v4prefix, IPv4off) == 0) v4addroute(tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); else v6addroute(tag, addr, mask, gate, 0); } else if(strcmp(cb->f[0], "tag") == 0) { if(cb->nf < 2) error(Ebadarg); h = strlen(cb->f[1]); if(h > sizeof(c->tag)) h = sizeof(c->tag); strncpy(c->tag, cb->f[1], h); if(h < 4) memset(c->tag+h, ' ', sizeof(c->tag)-h); } poperror(); free(cb); return n; } . ## diffname ip/iproute.c 1998/0310 ## diff -e /n/emeliedump/1998/0306/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0310/sys/src/brazil/ip/iproute.c 575,590c routetype(r->type, t); . 558d 546a void routetype(int type, char *p) { memset(p, ' ', 4); p[4] = 0; if(type & Rv4) *p++ = '4'; else *p++ = '6'; if(type & Rifc) *p++ = 'i'; if(type & Runi) *p++ = 'u'; else if(type & Rbcast) *p++ = 'b'; else if(type & Rmulti) *p++ = 'm'; if(type & Rptpt) *p = 'p'; } . ## diffname ip/iproute.c 1998/0313 ## diff -e /n/emeliedump/1998/0310/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0313/sys/src/brazil/ip/iproute.c 781c v6addroute(f, tag, addr, mask, gate, 0); . 779c v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); . 768c v6delroute(f, addr, mask); . 766c v4delroute(f, addr+IPv4off, mask+IPv4off); . 756,757c for(h = 0; h < nelem(f->v6root); h++) while(routeflush(f, f->v6root[h]) == 1) . 753,754c for(h = 0; h < nelem(f->v4root); h++) while(routeflush(f, f->v4root[h]) == 1) . 736c routewrite(Fs *f, Chan *c, char *p, int n) . 729c delroute(f, r); . 726c if(routeflush(f, r->right)) . 724c if(routeflush(f, r->left)) . 722c if(routeflush(f, r->mid)) . 718c routeflush(Fs *f, Route *r) . 710c v6delroute(f, addr, mask); . 708c v4delroute(f, addr+IPv4off, mask+IPv4off); . 698c delroute(Fs *f, Route *r) . 686c ipwalkroutes(f, &rw); . 674c routeread(Fs *f, char *p, ulong offset, int n) . 666,667c for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++) if(rr(f->v6root[rw->h], rw) == 0) . 661,662c for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++) if(rr(f->v4root[rw->h], rw) == 0) . 657c ipwalkroutes(Fs *f, Routewalk *rw) . 537c q->ifc = findipifc(f, q->v6.gate, q->type); . 508c for(p=f->v6root[V6H(la)]; p;){ . 499c q = v4lookup(f, a+12); . 491c v6lookup(Fs *f, uchar *a) . 481c q->ifc = findipifc(f, gate, q->type); . 469c for(p=f->v4root[V4H(la)]; p;) . 461c v4lookup(Fs *f, uchar *a) . 457c ipifcremroute(f, 0, a, mask); . 448,450c while(p = f->queue) { f->queue = p->mid; walkadd(f, &f->v6root[h], p->left); . 444,446c addqueue(&f->queue, p->left); addqueue(&f->queue, p->mid); addqueue(&f->queue, p->right); . 440c r = looknode(&f->v6root[h], &rt); . 422c v6delroute(Fs *f, uchar *a, uchar *mask) . 418c ipifcremroute(f, Rv4, a, mask); . 409,411c while(p = f->queue) { f->queue = p->mid; walkadd(f, &f->v4root[h], p->left); . 405,407c addqueue(&f->queue, p->left); addqueue(&f->queue, p->mid); addqueue(&f->queue, p->right); . 401c r = looknode(&f->v4root[h], &rt); . 386c v4delroute(Fs *f, uchar *a, uchar *mask) . 354c ipifcaddroute(f, 0, a, mask, gate, type); . 345,348c addnode(f, &f->v6root[h], p); while(p = f->queue) { f->queue = p->mid; walkadd(f, &f->v6root[h], p->left); . 322c v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type) . 316c ipifcaddroute(f, Rv4, a, mask, gate, type); . 307,310c addnode(f, &f->v4root[h], p); while(p = f->queue) { f->queue = p->mid; walkadd(f, &f->v4root[h], p->left); . 286c v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type) . 276c addnode(f, &p->mid, new); . 269c addqueue(&f->queue, p); . 257c addnode(f, &p->right, new); . 254c addnode(f, &p->left, new); . 241c addnode(Fs *f, Route **cur, Route *new) . 175c walkadd(f, root, r); . 173c walkadd(f, root, l); . 171c addnode(f, root, p); . 163c walkadd(Fs *f, Route **root, Route *p) . 20a /* these are used for all instances of IP */ . 10,18c static void walkadd(Fs*, Route**, Route*); static void addnode(Fs*, Route**, Route*); . ## diffname ip/iproute.c 1998/0316 ## diff -e /n/emeliedump/1998/0313/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0316/sys/src/brazil/ip/iproute.c 534,535c q->ifcid = q->ifc->ifcid; . 530,531c if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){ if(q->type & Rifc) { hnputl(gate, q->v6.gate[0]); hnputl(gate+4, q->v6.gate[1]); hnputl(gate+8, q->v6.gate[2]); hnputl(gate+12, q->v6.gate[3]); q->ifc = findipifc(f, gate, q->type); } else q->ifc = findipifc(f, q->v6.gate, q->type); . 490a uchar gate[IPaddrlen]; . 474c if(q->type & Rifc) { hnputl(gate+IPv4off, q->v4.address); memmove(gate, v4prefix, IPv4off); } else v4tov6(gate, q->v4.gate); . 266c /* * supercede the old entry if the old one isn't * a local interface. */ if((p->type & Rifc) == 0){ p->type = new->type; p->ifcid = -1; copygate(p, new); } . ## diffname ip/iproute.c 1998/0630 ## diff -e /n/emeliedump/1998/0316/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0630/sys/src/brazil/ip/iproute.c 781c v6delroute(f, addr, mask, 1); . 779c v4delroute(f, addr+IPv4off, mask+IPv4off, 1); . 770,772c for(changed = 1; changed;){ wlock(&routelock); changed = routeflush(f, f->v6root[h], tag); wunlock(&routelock); } . 767,768c for(changed = 1; changed;){ wlock(&routelock); changed = routeflush(f, f->v4root[h], tag); wunlock(&routelock); } . 765c tag = cb->f[1]; . 751c int h, changed; . 742c if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0) delroute(f, r, 0); . 739c if(routeflush(f, r->right, tag)) . 737c if(routeflush(f, r->left, tag)) . 735c if(routeflush(f, r->mid, tag)) . 731c routeflush(Fs *f, Route *r, char *tag) . 723c v6delroute(f, addr, mask, dolock); . 721c v4delroute(f, addr+IPv4off, mask+IPv4off, dolock); . 711c delroute(Fs *f, Route *r, int dolock) . 456c if(dolock) wunlock(&routelock); . 441c if(dolock) wlock(&routelock); . 424c v6delroute(Fs *f, uchar *a, uchar *mask, int dolock) . 417c if(dolock) wunlock(&routelock); . 402c if(dolock) wlock(&routelock); . 388c v4delroute(Fs *f, uchar *a, uchar *mask, int dolock) . ## diffname ip/iproute.c 1998/0701 ## diff -e /n/emeliedump/1998/0630/sys/src/brazil/ip/iproute.c /n/emeliedump/1998/0701/sys/src/brazil/ip/iproute.c 748c return 1; } . 746c if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0){ . ## diffname ip/iproute.c 2001/0405 ## diff -e /n/emeliedump/1998/0701/sys/src/brazil/ip/iproute.c /n/emeliedump/2001/0405/sys/src/9/ip/iproute.c 810,815c a = c->aux; na = newipaux(a->owner, cb->f[1]); c->aux = na; free(a); . 800,801c if(c != nil){ a = c->aux; tag = a->tag; } . 762a IPaux *a, *na; . ## diffname ip/iproute.c 2001/0710 ## diff -e /n/emeliedump/2001/0405/sys/src/9/ip/iproute.c /n/emeliedump/2001/0710/sys/src/9/ip/iproute.c 456a while(p = f->queue) { f->queue = p->mid; walkadd(f, &f->v6root[h], p->left); freeroute(p); } . 448,455c if(--(p->ref) == 0){ *r = 0; addqueue(&f->queue, p->left); addqueue(&f->queue, p->mid); addqueue(&f->queue, p->right); . 415a while(p = f->queue) { f->queue = p->mid; walkadd(f, &f->v4root[h], p->left); freeroute(p); } . 407,414c if(--(p->ref) == 0){ *r = 0; addqueue(&f->queue, p->left); addqueue(&f->queue, p->mid); addqueue(&f->queue, p->right); . 274c } else if(new->type & Rifc) p->ref++; . 59a r->ref = 1; . ## diffname ip/iproute.c 2001/1120 ## diff -e /n/emeliedump/2001/0710/sys/src/9/ip/iproute.c /n/emeliedump/2001/1120/sys/src/9/ip/iproute.c 818a case RWtag: . 800,817c break; . 791,793c break; case RWremove: . 777c ct = lookupcmd(cb, routecmd, nelem(routecmd)); switch(ct->index){ case RWadd: parseip(addr, cb->f[1]); parseipmask(mask, cb->f[2]); parseip(gate, cb->f[3]); tag = "none"; if(c != nil){ a = c->aux; tag = a->tag; } if(memcmp(addr, v4prefix, IPv4off) == 0) v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); else v6addroute(f, tag, addr, mask, gate, 0); break; case RWflush: . 765a Cmdtab *ct; . 18a enum { RWadd, RWflush, RWremove, RWtag, }; static Cmdtab routecmd[] = { RWadd, "add", 4, RWflush, "flush", 2, RWremove, "remove", 3, RWtag, "tag", 2, }; . ## diffname ip/iproute.c 2002/0507 ## diff -e /n/emeliedump/2001/1120/sys/src/9/ip/iproute.c /n/emeliedump/2002/0507/sys/src/9/ip/iproute.c 837d 835c } else if(strcmp(cb->f[0], "add") == 0){ if(cb->nf < 4) error(Ebadarg); parseip(addr, cb->f[1]); parseipmask(mask, cb->f[2]); parseip(gate, cb->f[3]); tag = "none"; if(c != nil){ a = c->aux; tag = a->tag; } if(memcmp(addr, v4prefix, IPv4off) == 0) v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0); else v6addroute(f, tag, addr, mask, gate, 0); } else if(strcmp(cb->f[0], "tag") == 0) { if(cb->nf < 2) error(Ebadarg); . 826,828c } else if(strcmp(cb->f[0], "remove") == 0){ if(cb->nf < 3) error(Ebadarg); . 794,812c if(strcmp(cb->f[0], "flush") == 0){ . 782d 612c char *rformat = "%-40.40I %-40.40M %-40.40I %4.4s %4.4s %3s\n"; . 609c Rlinelen= 137, . 571,574c for(h = 0; h < IPllen; h++) hnputl(gate+4*h, q->v6.address[h]); . 531,532c if(memcmp(a, v4prefix, IPv4off) == 0){ q = v4lookup(f, a+IPv4off); . 348a /* if(ISDFLT(a, mask, tag)) f->v6p->cdrouter = -1; */ . 339a #define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0)) . 19,34d ## diffname ip/iproute.c 2003/0308 ## diff -e /n/emeliedump/2002/0507/sys/src/9/ip/iproute.c /n/emeliedump/2003/0308/sys/src/9/ip/iproute.c 569a } if(c != nil){ c->r = q; c->rgen = v6routegeneration; . 527a if(c != nil && c->r != nil && c->rgen == v6routegeneration) return c->r; . 523c q = v4lookup(f, a+IPv4off, c); . 514c v6lookup(Fs *f, uchar *a, Conv *c) . 508a if(c != nil){ c->r = q; c->rgen = v4routegeneration; } . 485a if(c != nil && c->r != nil && c->rgen == v4routegeneration) return c->r; . 480c v4lookup(Fs *f, uchar *a, Conv *c) . 474a v6routegeneration++; . 431a v4routegeneration++; . 363a v6routegeneration++; . 318a v4routegeneration++; . 17a ulong v4routegeneration, v6routegeneration; . ## diffname ip/iproute.c 2003/0314 ## diff -e /n/emeliedump/2003/0308/sys/src/9/ip/iproute.c /n/emeliedump/2003/0314/sys/src/9/ip/iproute.c 584c q->ifc = ifc; q->ifcid = ifc->ifcid; . 581,582c ifc = findipifc(f, q->v6.gate, q->type); if(ifc == nil) . 579c ifc = findipifc(f, gate, q->type); . 540c if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration) . 532a Ipifc *ifc; . 516a . 515c q->ifc = ifc; q->ifcid = ifc->ifcid; . 512,513c ifc = findipifc(f, gate, q->type); if(ifc == nil) . 491c if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration) . 489a Ipifc *ifc; . ## diffname ip/iproute.c 2003/0404 ## diff -e /n/emeliedump/2003/0314/sys/src/9/ip/iproute.c /n/emeliedump/2003/0404/sys/src/9/ip/iproute.c 740,743c return rw.p - p; . 734,735c rw.e = p+n; rw.o = -offset; . 730,732d 717c if(rw->e > rw->p) { . 712c if(rw->e > rw->p) { . 686c if(rw->e <= rw->p) . 675c p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname); if(rw->o < 0){ n = p - rw->p; if(n > -rw->o){ memmove(rw->p, rw->p-rw->o, n+rw->o); rw->p = p + rw->o; } rw->o += n; } else rw->p = p; . 665,673c convroute(r, addr, mask, gate, t, &nifc); iname = "-"; if(nifc != -1) { iname = ifbuf; sprint(ifbuf, "%d", nifc); . 663a char *p; . 661c int nifc, n; . 625,626d 620,623c char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n"; .