19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier #include "ip.h"
99ef1f84bSDavid du Colombier
109ef1f84bSDavid du Colombier static void walkadd(Fs*, Route**, Route*);
119ef1f84bSDavid du Colombier static void addnode(Fs*, Route**, Route*);
129ef1f84bSDavid du Colombier static void calcd(Route*);
139ef1f84bSDavid du Colombier
149ef1f84bSDavid du Colombier /* these are used for all instances of IP */
159ef1f84bSDavid du Colombier static Route* v4freelist;
169ef1f84bSDavid du Colombier static Route* v6freelist;
179ef1f84bSDavid du Colombier static RWlock routelock;
189ef1f84bSDavid du Colombier static ulong v4routegeneration, v6routegeneration;
199ef1f84bSDavid du Colombier
209ef1f84bSDavid du Colombier static void
freeroute(Route * r)219ef1f84bSDavid du Colombier freeroute(Route *r)
229ef1f84bSDavid du Colombier {
239ef1f84bSDavid du Colombier Route **l;
249ef1f84bSDavid du Colombier
259ef1f84bSDavid du Colombier r->left = nil;
269ef1f84bSDavid du Colombier r->right = nil;
279ef1f84bSDavid du Colombier if(r->type & Rv4)
289ef1f84bSDavid du Colombier l = &v4freelist;
299ef1f84bSDavid du Colombier else
309ef1f84bSDavid du Colombier l = &v6freelist;
319ef1f84bSDavid du Colombier r->mid = *l;
329ef1f84bSDavid du Colombier *l = r;
339ef1f84bSDavid du Colombier }
349ef1f84bSDavid du Colombier
359ef1f84bSDavid du Colombier static Route*
allocroute(int type)369ef1f84bSDavid du Colombier allocroute(int type)
379ef1f84bSDavid du Colombier {
389ef1f84bSDavid du Colombier Route *r;
399ef1f84bSDavid du Colombier int n;
409ef1f84bSDavid du Colombier Route **l;
419ef1f84bSDavid du Colombier
429ef1f84bSDavid du Colombier if(type & Rv4){
439ef1f84bSDavid du Colombier n = sizeof(RouteTree) + sizeof(V4route);
449ef1f84bSDavid du Colombier l = &v4freelist;
459ef1f84bSDavid du Colombier } else {
469ef1f84bSDavid du Colombier n = sizeof(RouteTree) + sizeof(V6route);
479ef1f84bSDavid du Colombier l = &v6freelist;
489ef1f84bSDavid du Colombier }
499ef1f84bSDavid du Colombier
509ef1f84bSDavid du Colombier r = *l;
519ef1f84bSDavid du Colombier if(r != nil){
529ef1f84bSDavid du Colombier *l = r->mid;
539ef1f84bSDavid du Colombier } else {
549ef1f84bSDavid du Colombier r = malloc(n);
559ef1f84bSDavid du Colombier if(r == nil)
569ef1f84bSDavid du Colombier panic("out of routing nodes");
579ef1f84bSDavid du Colombier }
589ef1f84bSDavid du Colombier memset(r, 0, n);
599ef1f84bSDavid du Colombier r->type = type;
609ef1f84bSDavid du Colombier r->ifc = nil;
619ef1f84bSDavid du Colombier r->ref = 1;
629ef1f84bSDavid du Colombier
639ef1f84bSDavid du Colombier return r;
649ef1f84bSDavid du Colombier }
659ef1f84bSDavid du Colombier
669ef1f84bSDavid du Colombier static void
addqueue(Route ** q,Route * r)679ef1f84bSDavid du Colombier addqueue(Route **q, Route *r)
689ef1f84bSDavid du Colombier {
699ef1f84bSDavid du Colombier Route *l;
709ef1f84bSDavid du Colombier
719ef1f84bSDavid du Colombier if(r == nil)
729ef1f84bSDavid du Colombier return;
739ef1f84bSDavid du Colombier
749ef1f84bSDavid du Colombier l = allocroute(r->type);
759ef1f84bSDavid du Colombier l->mid = *q;
769ef1f84bSDavid du Colombier *q = l;
779ef1f84bSDavid du Colombier l->left = r;
789ef1f84bSDavid du Colombier }
799ef1f84bSDavid du Colombier
809ef1f84bSDavid du Colombier /*
819ef1f84bSDavid du Colombier * compare 2 v6 addresses
829ef1f84bSDavid du Colombier */
839ef1f84bSDavid du Colombier static int
lcmp(ulong * a,ulong * b)849ef1f84bSDavid du Colombier lcmp(ulong *a, ulong *b)
859ef1f84bSDavid du Colombier {
869ef1f84bSDavid du Colombier int i;
879ef1f84bSDavid du Colombier
889ef1f84bSDavid du Colombier for(i = 0; i < IPllen; i++){
899ef1f84bSDavid du Colombier if(a[i] > b[i])
909ef1f84bSDavid du Colombier return 1;
919ef1f84bSDavid du Colombier if(a[i] < b[i])
929ef1f84bSDavid du Colombier return -1;
939ef1f84bSDavid du Colombier }
949ef1f84bSDavid du Colombier return 0;
959ef1f84bSDavid du Colombier }
969ef1f84bSDavid du Colombier
979ef1f84bSDavid du Colombier /*
989ef1f84bSDavid du Colombier * compare 2 v4 or v6 ranges
999ef1f84bSDavid du Colombier */
1009ef1f84bSDavid du Colombier enum
1019ef1f84bSDavid du Colombier {
1029ef1f84bSDavid du Colombier Rpreceeds,
1039ef1f84bSDavid du Colombier Rfollows,
1049ef1f84bSDavid du Colombier Requals,
1059ef1f84bSDavid du Colombier Rcontains,
1069ef1f84bSDavid du Colombier Rcontained,
1079ef1f84bSDavid du Colombier };
1089ef1f84bSDavid du Colombier
1099ef1f84bSDavid du Colombier static int
rangecompare(Route * a,Route * b)1109ef1f84bSDavid du Colombier rangecompare(Route *a, Route *b)
1119ef1f84bSDavid du Colombier {
1129ef1f84bSDavid du Colombier if(a->type & Rv4){
1139ef1f84bSDavid du Colombier if(a->v4.endaddress < b->v4.address)
1149ef1f84bSDavid du Colombier return Rpreceeds;
1159ef1f84bSDavid du Colombier
1169ef1f84bSDavid du Colombier if(a->v4.address > b->v4.endaddress)
1179ef1f84bSDavid du Colombier return Rfollows;
1189ef1f84bSDavid du Colombier
1199ef1f84bSDavid du Colombier if(a->v4.address <= b->v4.address
1209ef1f84bSDavid du Colombier && a->v4.endaddress >= b->v4.endaddress){
1219ef1f84bSDavid du Colombier if(a->v4.address == b->v4.address
1229ef1f84bSDavid du Colombier && a->v4.endaddress == b->v4.endaddress)
1239ef1f84bSDavid du Colombier return Requals;
1249ef1f84bSDavid du Colombier return Rcontains;
1259ef1f84bSDavid du Colombier }
1269ef1f84bSDavid du Colombier return Rcontained;
1279ef1f84bSDavid du Colombier }
1289ef1f84bSDavid du Colombier
1299ef1f84bSDavid du Colombier if(lcmp(a->v6.endaddress, b->v6.address) < 0)
1309ef1f84bSDavid du Colombier return Rpreceeds;
1319ef1f84bSDavid du Colombier
1329ef1f84bSDavid du Colombier if(lcmp(a->v6.address, b->v6.endaddress) > 0)
1339ef1f84bSDavid du Colombier return Rfollows;
1349ef1f84bSDavid du Colombier
1359ef1f84bSDavid du Colombier if(lcmp(a->v6.address, b->v6.address) <= 0
1369ef1f84bSDavid du Colombier && lcmp(a->v6.endaddress, b->v6.endaddress) >= 0){
1379ef1f84bSDavid du Colombier if(lcmp(a->v6.address, b->v6.address) == 0
1389ef1f84bSDavid du Colombier && lcmp(a->v6.endaddress, b->v6.endaddress) == 0)
1399ef1f84bSDavid du Colombier return Requals;
1409ef1f84bSDavid du Colombier return Rcontains;
1419ef1f84bSDavid du Colombier }
1429ef1f84bSDavid du Colombier
1439ef1f84bSDavid du Colombier return Rcontained;
1449ef1f84bSDavid du Colombier }
1459ef1f84bSDavid du Colombier
1469ef1f84bSDavid du Colombier static void
copygate(Route * old,Route * new)1479ef1f84bSDavid du Colombier copygate(Route *old, Route *new)
1489ef1f84bSDavid du Colombier {
1499ef1f84bSDavid du Colombier if(new->type & Rv4)
1509ef1f84bSDavid du Colombier memmove(old->v4.gate, new->v4.gate, IPv4addrlen);
1519ef1f84bSDavid du Colombier else
1529ef1f84bSDavid du Colombier memmove(old->v6.gate, new->v6.gate, IPaddrlen);
1539ef1f84bSDavid du Colombier }
1549ef1f84bSDavid du Colombier
1559ef1f84bSDavid du Colombier /*
1569ef1f84bSDavid du Colombier * walk down a tree adding nodes back in
1579ef1f84bSDavid du Colombier */
1589ef1f84bSDavid du Colombier static void
walkadd(Fs * f,Route ** root,Route * p)1599ef1f84bSDavid du Colombier walkadd(Fs *f, Route **root, Route *p)
1609ef1f84bSDavid du Colombier {
1619ef1f84bSDavid du Colombier Route *l, *r;
1629ef1f84bSDavid du Colombier
1639ef1f84bSDavid du Colombier l = p->left;
1649ef1f84bSDavid du Colombier r = p->right;
1659ef1f84bSDavid du Colombier p->left = 0;
1669ef1f84bSDavid du Colombier p->right = 0;
1679ef1f84bSDavid du Colombier addnode(f, root, p);
1689ef1f84bSDavid du Colombier if(l)
1699ef1f84bSDavid du Colombier walkadd(f, root, l);
1709ef1f84bSDavid du Colombier if(r)
1719ef1f84bSDavid du Colombier walkadd(f, root, r);
1729ef1f84bSDavid du Colombier }
1739ef1f84bSDavid du Colombier
1749ef1f84bSDavid du Colombier /*
1759ef1f84bSDavid du Colombier * calculate depth
1769ef1f84bSDavid du Colombier */
1779ef1f84bSDavid du Colombier static void
calcd(Route * p)1789ef1f84bSDavid du Colombier calcd(Route *p)
1799ef1f84bSDavid du Colombier {
1809ef1f84bSDavid du Colombier Route *q;
1819ef1f84bSDavid du Colombier int d;
1829ef1f84bSDavid du Colombier
1839ef1f84bSDavid du Colombier if(p) {
1849ef1f84bSDavid du Colombier d = 0;
1859ef1f84bSDavid du Colombier q = p->left;
1869ef1f84bSDavid du Colombier if(q)
1879ef1f84bSDavid du Colombier d = q->depth;
1889ef1f84bSDavid du Colombier q = p->right;
1899ef1f84bSDavid du Colombier if(q && q->depth > d)
1909ef1f84bSDavid du Colombier d = q->depth;
1919ef1f84bSDavid du Colombier q = p->mid;
1929ef1f84bSDavid du Colombier if(q && q->depth > d)
1939ef1f84bSDavid du Colombier d = q->depth;
1949ef1f84bSDavid du Colombier p->depth = d+1;
1959ef1f84bSDavid du Colombier }
1969ef1f84bSDavid du Colombier }
1979ef1f84bSDavid du Colombier
1989ef1f84bSDavid du Colombier /*
1999ef1f84bSDavid du Colombier * balance the tree at the current node
2009ef1f84bSDavid du Colombier */
2019ef1f84bSDavid du Colombier static void
balancetree(Route ** cur)2029ef1f84bSDavid du Colombier balancetree(Route **cur)
2039ef1f84bSDavid du Colombier {
2049ef1f84bSDavid du Colombier Route *p, *l, *r;
2059ef1f84bSDavid du Colombier int dl, dr;
2069ef1f84bSDavid du Colombier
2079ef1f84bSDavid du Colombier /*
2089ef1f84bSDavid du Colombier * if left and right are
2099ef1f84bSDavid du Colombier * too out of balance,
2109ef1f84bSDavid du Colombier * rotate tree node
2119ef1f84bSDavid du Colombier */
2129ef1f84bSDavid du Colombier p = *cur;
2139ef1f84bSDavid du Colombier dl = 0; if(l = p->left) dl = l->depth;
2149ef1f84bSDavid du Colombier dr = 0; if(r = p->right) dr = r->depth;
2159ef1f84bSDavid du Colombier
2169ef1f84bSDavid du Colombier if(dl > dr+1) {
2179ef1f84bSDavid du Colombier p->left = l->right;
2189ef1f84bSDavid du Colombier l->right = p;
2199ef1f84bSDavid du Colombier *cur = l;
2209ef1f84bSDavid du Colombier calcd(p);
2219ef1f84bSDavid du Colombier calcd(l);
2229ef1f84bSDavid du Colombier } else
2239ef1f84bSDavid du Colombier if(dr > dl+1) {
2249ef1f84bSDavid du Colombier p->right = r->left;
2259ef1f84bSDavid du Colombier r->left = p;
2269ef1f84bSDavid du Colombier *cur = r;
2279ef1f84bSDavid du Colombier calcd(p);
2289ef1f84bSDavid du Colombier calcd(r);
2299ef1f84bSDavid du Colombier } else
2309ef1f84bSDavid du Colombier calcd(p);
2319ef1f84bSDavid du Colombier }
2329ef1f84bSDavid du Colombier
2339ef1f84bSDavid du Colombier /*
2349ef1f84bSDavid du Colombier * add a new node to the tree
2359ef1f84bSDavid du Colombier */
2369ef1f84bSDavid du Colombier static void
addnode(Fs * f,Route ** cur,Route * new)2379ef1f84bSDavid du Colombier addnode(Fs *f, Route **cur, Route *new)
2389ef1f84bSDavid du Colombier {
2399ef1f84bSDavid du Colombier Route *p;
2409ef1f84bSDavid du Colombier
2419ef1f84bSDavid du Colombier p = *cur;
2429ef1f84bSDavid du Colombier if(p == 0) {
2439ef1f84bSDavid du Colombier *cur = new;
2449ef1f84bSDavid du Colombier new->depth = 1;
2459ef1f84bSDavid du Colombier return;
2469ef1f84bSDavid du Colombier }
2479ef1f84bSDavid du Colombier
2489ef1f84bSDavid du Colombier switch(rangecompare(new, p)){
2499ef1f84bSDavid du Colombier case Rpreceeds:
2509ef1f84bSDavid du Colombier addnode(f, &p->left, new);
2519ef1f84bSDavid du Colombier break;
2529ef1f84bSDavid du Colombier case Rfollows:
2539ef1f84bSDavid du Colombier addnode(f, &p->right, new);
2549ef1f84bSDavid du Colombier break;
2559ef1f84bSDavid du Colombier case Rcontains:
2569ef1f84bSDavid du Colombier /*
2579ef1f84bSDavid du Colombier * if new node is superset
2589ef1f84bSDavid du Colombier * of tree node,
2599ef1f84bSDavid du Colombier * replace tree node and
2609ef1f84bSDavid du Colombier * queue tree node to be
2619ef1f84bSDavid du Colombier * merged into root.
2629ef1f84bSDavid du Colombier */
2639ef1f84bSDavid du Colombier *cur = new;
2649ef1f84bSDavid du Colombier new->depth = 1;
2659ef1f84bSDavid du Colombier addqueue(&f->queue, p);
2669ef1f84bSDavid du Colombier break;
2679ef1f84bSDavid du Colombier case Requals:
2689ef1f84bSDavid du Colombier /*
2699ef1f84bSDavid du Colombier * supercede the old entry if the old one isn't
2709ef1f84bSDavid du Colombier * a local interface.
2719ef1f84bSDavid du Colombier */
2729ef1f84bSDavid du Colombier if((p->type & Rifc) == 0){
2739ef1f84bSDavid du Colombier p->type = new->type;
2749ef1f84bSDavid du Colombier p->ifcid = -1;
2759ef1f84bSDavid du Colombier copygate(p, new);
2769ef1f84bSDavid du Colombier } else if(new->type & Rifc)
2779ef1f84bSDavid du Colombier p->ref++;
2789ef1f84bSDavid du Colombier freeroute(new);
2799ef1f84bSDavid du Colombier break;
2809ef1f84bSDavid du Colombier case Rcontained:
2819ef1f84bSDavid du Colombier addnode(f, &p->mid, new);
2829ef1f84bSDavid du Colombier break;
2839ef1f84bSDavid du Colombier }
2849ef1f84bSDavid du Colombier
2859ef1f84bSDavid du Colombier balancetree(cur);
2869ef1f84bSDavid du Colombier }
2879ef1f84bSDavid du Colombier
2889ef1f84bSDavid du Colombier #define V4H(a) ((a&0x07ffffff)>>(32-Lroot-5))
2899ef1f84bSDavid du Colombier
2909ef1f84bSDavid du Colombier void
v4addroute(Fs * f,char * tag,uchar * a,uchar * mask,uchar * gate,int type)2919ef1f84bSDavid du Colombier v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
2929ef1f84bSDavid du Colombier {
2939ef1f84bSDavid du Colombier Route *p;
2949ef1f84bSDavid du Colombier ulong sa;
2959ef1f84bSDavid du Colombier ulong m;
2969ef1f84bSDavid du Colombier ulong ea;
2979ef1f84bSDavid du Colombier int h, eh;
2989ef1f84bSDavid du Colombier
2999ef1f84bSDavid du Colombier m = nhgetl(mask);
3009ef1f84bSDavid du Colombier sa = nhgetl(a) & m;
3019ef1f84bSDavid du Colombier ea = sa | ~m;
3029ef1f84bSDavid du Colombier
3039ef1f84bSDavid du Colombier eh = V4H(ea);
3049ef1f84bSDavid du Colombier for(h=V4H(sa); h<=eh; h++) {
3059ef1f84bSDavid du Colombier p = allocroute(Rv4 | type);
3069ef1f84bSDavid du Colombier p->v4.address = sa;
3079ef1f84bSDavid du Colombier p->v4.endaddress = ea;
3089ef1f84bSDavid du Colombier memmove(p->v4.gate, gate, sizeof(p->v4.gate));
3099ef1f84bSDavid du Colombier memmove(p->tag, tag, sizeof(p->tag));
3109ef1f84bSDavid du Colombier
3119ef1f84bSDavid du Colombier wlock(&routelock);
3129ef1f84bSDavid du Colombier addnode(f, &f->v4root[h], p);
3139ef1f84bSDavid du Colombier while(p = f->queue) {
3149ef1f84bSDavid du Colombier f->queue = p->mid;
3159ef1f84bSDavid du Colombier walkadd(f, &f->v4root[h], p->left);
3169ef1f84bSDavid du Colombier freeroute(p);
3179ef1f84bSDavid du Colombier }
3189ef1f84bSDavid du Colombier wunlock(&routelock);
3199ef1f84bSDavid du Colombier }
3209ef1f84bSDavid du Colombier v4routegeneration++;
3219ef1f84bSDavid du Colombier
3229ef1f84bSDavid du Colombier ipifcaddroute(f, Rv4, a, mask, gate, type);
3239ef1f84bSDavid du Colombier }
3249ef1f84bSDavid du Colombier
3259ef1f84bSDavid du Colombier #define V6H(a) (((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5))
3269ef1f84bSDavid du Colombier #define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))
3279ef1f84bSDavid du Colombier
3289ef1f84bSDavid du Colombier void
v6addroute(Fs * f,char * tag,uchar * a,uchar * mask,uchar * gate,int type)3299ef1f84bSDavid du Colombier v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
3309ef1f84bSDavid du Colombier {
3319ef1f84bSDavid du Colombier Route *p;
3329ef1f84bSDavid du Colombier ulong sa[IPllen], ea[IPllen];
3339ef1f84bSDavid du Colombier ulong x, y;
3349ef1f84bSDavid du Colombier int h, eh;
3359ef1f84bSDavid du Colombier
3369ef1f84bSDavid du Colombier /*
3379ef1f84bSDavid du Colombier if(ISDFLT(a, mask, tag))
3389ef1f84bSDavid du Colombier f->v6p->cdrouter = -1;
3399ef1f84bSDavid du Colombier */
3409ef1f84bSDavid du Colombier
3419ef1f84bSDavid du Colombier
3429ef1f84bSDavid du Colombier for(h = 0; h < IPllen; h++){
3439ef1f84bSDavid du Colombier x = nhgetl(a+4*h);
3449ef1f84bSDavid du Colombier y = nhgetl(mask+4*h);
3459ef1f84bSDavid du Colombier sa[h] = x & y;
3469ef1f84bSDavid du Colombier ea[h] = x | ~y;
3479ef1f84bSDavid du Colombier }
3489ef1f84bSDavid du Colombier
3499ef1f84bSDavid du Colombier eh = V6H(ea);
3509ef1f84bSDavid du Colombier for(h = V6H(sa); h <= eh; h++) {
3519ef1f84bSDavid du Colombier p = allocroute(type);
3529ef1f84bSDavid du Colombier memmove(p->v6.address, sa, IPaddrlen);
3539ef1f84bSDavid du Colombier memmove(p->v6.endaddress, ea, IPaddrlen);
3549ef1f84bSDavid du Colombier memmove(p->v6.gate, gate, IPaddrlen);
3559ef1f84bSDavid du Colombier memmove(p->tag, tag, sizeof(p->tag));
3569ef1f84bSDavid du Colombier
3579ef1f84bSDavid du Colombier wlock(&routelock);
3589ef1f84bSDavid du Colombier addnode(f, &f->v6root[h], p);
3599ef1f84bSDavid du Colombier while(p = f->queue) {
3609ef1f84bSDavid du Colombier f->queue = p->mid;
3619ef1f84bSDavid du Colombier walkadd(f, &f->v6root[h], p->left);
3629ef1f84bSDavid du Colombier freeroute(p);
3639ef1f84bSDavid du Colombier }
3649ef1f84bSDavid du Colombier wunlock(&routelock);
3659ef1f84bSDavid du Colombier }
3669ef1f84bSDavid du Colombier v6routegeneration++;
3679ef1f84bSDavid du Colombier
3689ef1f84bSDavid du Colombier ipifcaddroute(f, 0, a, mask, gate, type);
3699ef1f84bSDavid du Colombier }
3709ef1f84bSDavid du Colombier
3719ef1f84bSDavid du Colombier Route**
looknode(Route ** cur,Route * r)3729ef1f84bSDavid du Colombier looknode(Route **cur, Route *r)
3739ef1f84bSDavid du Colombier {
3749ef1f84bSDavid du Colombier Route *p;
3759ef1f84bSDavid du Colombier
3769ef1f84bSDavid du Colombier for(;;){
3779ef1f84bSDavid du Colombier p = *cur;
3789ef1f84bSDavid du Colombier if(p == 0)
3799ef1f84bSDavid du Colombier return 0;
3809ef1f84bSDavid du Colombier
3819ef1f84bSDavid du Colombier switch(rangecompare(r, p)){
3829ef1f84bSDavid du Colombier case Rcontains:
3839ef1f84bSDavid du Colombier return 0;
3849ef1f84bSDavid du Colombier case Rpreceeds:
3859ef1f84bSDavid du Colombier cur = &p->left;
3869ef1f84bSDavid du Colombier break;
3879ef1f84bSDavid du Colombier case Rfollows:
3889ef1f84bSDavid du Colombier cur = &p->right;
3899ef1f84bSDavid du Colombier break;
3909ef1f84bSDavid du Colombier case Rcontained:
3919ef1f84bSDavid du Colombier cur = &p->mid;
3929ef1f84bSDavid du Colombier break;
3939ef1f84bSDavid du Colombier case Requals:
3949ef1f84bSDavid du Colombier return cur;
3959ef1f84bSDavid du Colombier }
3969ef1f84bSDavid du Colombier }
3979ef1f84bSDavid du Colombier }
3989ef1f84bSDavid du Colombier
3997356a45dSDavid du Colombier static void
del1route(Fs * f,Route ** root,Route * rtp,int h,int dolock)4007356a45dSDavid du Colombier del1route(Fs *f, Route **root, Route *rtp, int h, int dolock)
4019ef1f84bSDavid du Colombier {
4029ef1f84bSDavid du Colombier Route **r, *p;
4039ef1f84bSDavid du Colombier
4049ef1f84bSDavid du Colombier if(dolock)
4059ef1f84bSDavid du Colombier wlock(&routelock);
4067356a45dSDavid du Colombier r = looknode(&root[h], rtp);
4079ef1f84bSDavid du Colombier if(r) {
4089ef1f84bSDavid du Colombier p = *r;
4099ef1f84bSDavid du Colombier if(--(p->ref) == 0){
4109ef1f84bSDavid du Colombier *r = 0;
4119ef1f84bSDavid du Colombier addqueue(&f->queue, p->left);
4129ef1f84bSDavid du Colombier addqueue(&f->queue, p->mid);
4139ef1f84bSDavid du Colombier addqueue(&f->queue, p->right);
4149ef1f84bSDavid du Colombier freeroute(p);
4159ef1f84bSDavid du Colombier while(p = f->queue) {
4169ef1f84bSDavid du Colombier f->queue = p->mid;
4177356a45dSDavid du Colombier walkadd(f, &root[h], p->left);
4189ef1f84bSDavid du Colombier freeroute(p);
4199ef1f84bSDavid du Colombier }
4209ef1f84bSDavid du Colombier }
4219ef1f84bSDavid du Colombier }
4229ef1f84bSDavid du Colombier if(dolock)
4239ef1f84bSDavid du Colombier wunlock(&routelock);
4249ef1f84bSDavid du Colombier }
4257356a45dSDavid du Colombier
4267356a45dSDavid du Colombier void
v4delroute(Fs * f,uchar * a,uchar * mask,int dolock)4277356a45dSDavid du Colombier v4delroute(Fs *f, uchar *a, uchar *mask, int dolock)
4287356a45dSDavid du Colombier {
4297356a45dSDavid du Colombier Route rt;
4307356a45dSDavid du Colombier int h, eh;
4317356a45dSDavid du Colombier ulong m;
4327356a45dSDavid du Colombier
4337356a45dSDavid du Colombier m = nhgetl(mask);
4347356a45dSDavid du Colombier rt.v4.address = nhgetl(a) & m;
4357356a45dSDavid du Colombier rt.v4.endaddress = rt.v4.address | ~m;
4367356a45dSDavid du Colombier rt.type = Rv4;
4377356a45dSDavid du Colombier
4387356a45dSDavid du Colombier eh = V4H(rt.v4.endaddress);
4397356a45dSDavid du Colombier for(h=V4H(rt.v4.address); h<=eh; h++)
4407356a45dSDavid du Colombier del1route(f, f->v4root, &rt, h, dolock);
4419ef1f84bSDavid du Colombier v4routegeneration++;
4429ef1f84bSDavid du Colombier
4439ef1f84bSDavid du Colombier ipifcremroute(f, Rv4, a, mask);
4449ef1f84bSDavid du Colombier }
4459ef1f84bSDavid du Colombier
4469ef1f84bSDavid du Colombier void
v6delroute(Fs * f,uchar * a,uchar * mask,int dolock)4479ef1f84bSDavid du Colombier v6delroute(Fs *f, uchar *a, uchar *mask, int dolock)
4489ef1f84bSDavid du Colombier {
4499ef1f84bSDavid du Colombier Route rt;
4509ef1f84bSDavid du Colombier int h, eh;
4519ef1f84bSDavid du Colombier ulong x, y;
4529ef1f84bSDavid du Colombier
4539ef1f84bSDavid du Colombier for(h = 0; h < IPllen; h++){
4549ef1f84bSDavid du Colombier x = nhgetl(a+4*h);
4559ef1f84bSDavid du Colombier y = nhgetl(mask+4*h);
4569ef1f84bSDavid du Colombier rt.v6.address[h] = x & y;
4579ef1f84bSDavid du Colombier rt.v6.endaddress[h] = x | ~y;
4589ef1f84bSDavid du Colombier }
4599ef1f84bSDavid du Colombier rt.type = 0;
4609ef1f84bSDavid du Colombier
4619ef1f84bSDavid du Colombier eh = V6H(rt.v6.endaddress);
4627356a45dSDavid du Colombier for(h=V6H(rt.v6.address); h<=eh; h++)
4637356a45dSDavid du Colombier del1route(f, f->v6root, &rt, h, dolock);
4649ef1f84bSDavid du Colombier v6routegeneration++;
4659ef1f84bSDavid du Colombier
4669ef1f84bSDavid du Colombier ipifcremroute(f, 0, a, mask);
4679ef1f84bSDavid du Colombier }
4689ef1f84bSDavid du Colombier
4699ef1f84bSDavid du Colombier Route*
v4lookup(Fs * f,uchar * a,Conv * c)4709ef1f84bSDavid du Colombier v4lookup(Fs *f, uchar *a, Conv *c)
4719ef1f84bSDavid du Colombier {
4729ef1f84bSDavid du Colombier Route *p, *q;
4739ef1f84bSDavid du Colombier ulong la;
4749ef1f84bSDavid du Colombier uchar gate[IPaddrlen];
4759ef1f84bSDavid du Colombier Ipifc *ifc;
4769ef1f84bSDavid du Colombier
4779ef1f84bSDavid du Colombier if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration)
4789ef1f84bSDavid du Colombier return c->r;
4799ef1f84bSDavid du Colombier
4809ef1f84bSDavid du Colombier la = nhgetl(a);
481*55ba833bSDavid du Colombier again:
4829ef1f84bSDavid du Colombier q = nil;
4839ef1f84bSDavid du Colombier for(p=f->v4root[V4H(la)]; p;)
4849ef1f84bSDavid du Colombier if(la >= p->v4.address) {
4859ef1f84bSDavid du Colombier if(la <= p->v4.endaddress) {
4869ef1f84bSDavid du Colombier q = p;
4879ef1f84bSDavid du Colombier p = p->mid;
4889ef1f84bSDavid du Colombier } else
4899ef1f84bSDavid du Colombier p = p->right;
4909ef1f84bSDavid du Colombier } else
4919ef1f84bSDavid du Colombier p = p->left;
4929ef1f84bSDavid du Colombier
4939ef1f84bSDavid du Colombier if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
4949ef1f84bSDavid du Colombier if(q->type & Rifc) {
4959ef1f84bSDavid du Colombier hnputl(gate+IPv4off, q->v4.address);
4969ef1f84bSDavid du Colombier memmove(gate, v4prefix, IPv4off);
4979ef1f84bSDavid du Colombier } else
4989ef1f84bSDavid du Colombier v4tov6(gate, q->v4.gate);
4999ef1f84bSDavid du Colombier ifc = findipifc(f, gate, q->type);
500*55ba833bSDavid du Colombier if(ifc == nil){
501*55ba833bSDavid du Colombier /* find a direct attached route */
502*55ba833bSDavid du Colombier if(q->v4.address == 0 && q->v4.endaddress == ~0){
503*55ba833bSDavid du Colombier la = nhgetl(q->v4.gate);
504*55ba833bSDavid du Colombier goto again;
505*55ba833bSDavid du Colombier }
5069ef1f84bSDavid du Colombier return nil;
507*55ba833bSDavid du Colombier }
5089ef1f84bSDavid du Colombier q->ifc = ifc;
5099ef1f84bSDavid du Colombier q->ifcid = ifc->ifcid;
5109ef1f84bSDavid du Colombier }
5119ef1f84bSDavid du Colombier
5129ef1f84bSDavid du Colombier if(c != nil){
5139ef1f84bSDavid du Colombier c->r = q;
5149ef1f84bSDavid du Colombier c->rgen = v4routegeneration;
5159ef1f84bSDavid du Colombier }
5169ef1f84bSDavid du Colombier
5179ef1f84bSDavid du Colombier return q;
5189ef1f84bSDavid du Colombier }
5199ef1f84bSDavid du Colombier
5209ef1f84bSDavid du Colombier Route*
v6lookup(Fs * f,uchar * a,Conv * c)5219ef1f84bSDavid du Colombier v6lookup(Fs *f, uchar *a, Conv *c)
5229ef1f84bSDavid du Colombier {
5239ef1f84bSDavid du Colombier Route *p, *q;
5249ef1f84bSDavid du Colombier ulong la[IPllen];
5259ef1f84bSDavid du Colombier int h;
5269ef1f84bSDavid du Colombier ulong x, y;
5279ef1f84bSDavid du Colombier uchar gate[IPaddrlen];
5289ef1f84bSDavid du Colombier Ipifc *ifc;
5299ef1f84bSDavid du Colombier
5309ef1f84bSDavid du Colombier if(memcmp(a, v4prefix, IPv4off) == 0){
5319ef1f84bSDavid du Colombier q = v4lookup(f, a+IPv4off, c);
5329ef1f84bSDavid du Colombier if(q != nil)
5339ef1f84bSDavid du Colombier return q;
5349ef1f84bSDavid du Colombier }
5359ef1f84bSDavid du Colombier
5369ef1f84bSDavid du Colombier if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration)
5379ef1f84bSDavid du Colombier return c->r;
5389ef1f84bSDavid du Colombier
5399ef1f84bSDavid du Colombier for(h = 0; h < IPllen; h++)
5409ef1f84bSDavid du Colombier la[h] = nhgetl(a+4*h);
5419ef1f84bSDavid du Colombier
5429ef1f84bSDavid du Colombier q = 0;
5439ef1f84bSDavid du Colombier for(p=f->v6root[V6H(la)]; p;){
5449ef1f84bSDavid du Colombier for(h = 0; h < IPllen; h++){
5459ef1f84bSDavid du Colombier x = la[h];
5469ef1f84bSDavid du Colombier y = p->v6.address[h];
5479ef1f84bSDavid du Colombier if(x == y)
5489ef1f84bSDavid du Colombier continue;
5499ef1f84bSDavid du Colombier if(x < y){
5509ef1f84bSDavid du Colombier p = p->left;
5519ef1f84bSDavid du Colombier goto next;
5529ef1f84bSDavid du Colombier }
5539ef1f84bSDavid du Colombier break;
5549ef1f84bSDavid du Colombier }
5559ef1f84bSDavid du Colombier for(h = 0; h < IPllen; h++){
5569ef1f84bSDavid du Colombier x = la[h];
5579ef1f84bSDavid du Colombier y = p->v6.endaddress[h];
5589ef1f84bSDavid du Colombier if(x == y)
5599ef1f84bSDavid du Colombier continue;
5609ef1f84bSDavid du Colombier if(x > y){
5619ef1f84bSDavid du Colombier p = p->right;
5629ef1f84bSDavid du Colombier goto next;
5639ef1f84bSDavid du Colombier }
5649ef1f84bSDavid du Colombier break;
5659ef1f84bSDavid du Colombier }
5669ef1f84bSDavid du Colombier q = p;
5679ef1f84bSDavid du Colombier p = p->mid;
5689ef1f84bSDavid du Colombier next: ;
5699ef1f84bSDavid du Colombier }
5709ef1f84bSDavid du Colombier
5719ef1f84bSDavid du Colombier if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
5729ef1f84bSDavid du Colombier if(q->type & Rifc) {
5739ef1f84bSDavid du Colombier for(h = 0; h < IPllen; h++)
5749ef1f84bSDavid du Colombier hnputl(gate+4*h, q->v6.address[h]);
5759ef1f84bSDavid du Colombier ifc = findipifc(f, gate, q->type);
5769ef1f84bSDavid du Colombier } else
5779ef1f84bSDavid du Colombier ifc = findipifc(f, q->v6.gate, q->type);
5789ef1f84bSDavid du Colombier if(ifc == nil)
5799ef1f84bSDavid du Colombier return nil;
5809ef1f84bSDavid du Colombier q->ifc = ifc;
5819ef1f84bSDavid du Colombier q->ifcid = ifc->ifcid;
5829ef1f84bSDavid du Colombier }
5839ef1f84bSDavid du Colombier if(c != nil){
5849ef1f84bSDavid du Colombier c->r = q;
5859ef1f84bSDavid du Colombier c->rgen = v6routegeneration;
5869ef1f84bSDavid du Colombier }
5879ef1f84bSDavid du Colombier
5889ef1f84bSDavid du Colombier return q;
5899ef1f84bSDavid du Colombier }
5909ef1f84bSDavid du Colombier
5919ef1f84bSDavid du Colombier void
routetype(int type,char * p)5929ef1f84bSDavid du Colombier routetype(int type, char *p)
5939ef1f84bSDavid du Colombier {
5949ef1f84bSDavid du Colombier memset(p, ' ', 4);
5959ef1f84bSDavid du Colombier p[4] = 0;
5969ef1f84bSDavid du Colombier if(type & Rv4)
5979ef1f84bSDavid du Colombier *p++ = '4';
5989ef1f84bSDavid du Colombier else
5999ef1f84bSDavid du Colombier *p++ = '6';
6009ef1f84bSDavid du Colombier if(type & Rifc)
6019ef1f84bSDavid du Colombier *p++ = 'i';
6029ef1f84bSDavid du Colombier if(type & Runi)
6039ef1f84bSDavid du Colombier *p++ = 'u';
6049ef1f84bSDavid du Colombier else if(type & Rbcast)
6059ef1f84bSDavid du Colombier *p++ = 'b';
6069ef1f84bSDavid du Colombier else if(type & Rmulti)
6079ef1f84bSDavid du Colombier *p++ = 'm';
6089ef1f84bSDavid du Colombier if(type & Rptpt)
6099ef1f84bSDavid du Colombier *p = 'p';
6109ef1f84bSDavid du Colombier }
6119ef1f84bSDavid du Colombier
6129ef1f84bSDavid du Colombier static char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n";
6139ef1f84bSDavid du Colombier
6149ef1f84bSDavid du Colombier void
convroute(Route * r,uchar * addr,uchar * mask,uchar * gate,char * t,int * nifc)6159ef1f84bSDavid du Colombier convroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc)
6169ef1f84bSDavid du Colombier {
6179ef1f84bSDavid du Colombier int i;
6189ef1f84bSDavid du Colombier
6199ef1f84bSDavid du Colombier if(r->type & Rv4){
6209ef1f84bSDavid du Colombier memmove(addr, v4prefix, IPv4off);
6219ef1f84bSDavid du Colombier hnputl(addr+IPv4off, r->v4.address);
6229ef1f84bSDavid du Colombier memset(mask, 0xff, IPv4off);
6239ef1f84bSDavid du Colombier hnputl(mask+IPv4off, ~(r->v4.endaddress ^ r->v4.address));
6249ef1f84bSDavid du Colombier memmove(gate, v4prefix, IPv4off);
6259ef1f84bSDavid du Colombier memmove(gate+IPv4off, r->v4.gate, IPv4addrlen);
6269ef1f84bSDavid du Colombier } else {
6279ef1f84bSDavid du Colombier for(i = 0; i < IPllen; i++){
6289ef1f84bSDavid du Colombier hnputl(addr + 4*i, r->v6.address[i]);
6299ef1f84bSDavid du Colombier hnputl(mask + 4*i, ~(r->v6.endaddress[i] ^ r->v6.address[i]));
6309ef1f84bSDavid du Colombier }
6319ef1f84bSDavid du Colombier memmove(gate, r->v6.gate, IPaddrlen);
6329ef1f84bSDavid du Colombier }
6339ef1f84bSDavid du Colombier
6349ef1f84bSDavid du Colombier routetype(r->type, t);
6359ef1f84bSDavid du Colombier
6369ef1f84bSDavid du Colombier if(r->ifc)
6379ef1f84bSDavid du Colombier *nifc = r->ifc->conv->x;
6389ef1f84bSDavid du Colombier else
6399ef1f84bSDavid du Colombier *nifc = -1;
6409ef1f84bSDavid du Colombier }
6419ef1f84bSDavid du Colombier
6429ef1f84bSDavid du Colombier /*
6439ef1f84bSDavid du Colombier * this code is not in rr to reduce stack size
6449ef1f84bSDavid du Colombier */
6459ef1f84bSDavid du Colombier static void
sprintroute(Route * r,Routewalk * rw)6469ef1f84bSDavid du Colombier sprintroute(Route *r, Routewalk *rw)
6479ef1f84bSDavid du Colombier {
6489ef1f84bSDavid du Colombier int nifc, n;
6499ef1f84bSDavid du Colombier char t[5], *iname, ifbuf[5];
6509ef1f84bSDavid du Colombier uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];
6519ef1f84bSDavid du Colombier char *p;
6529ef1f84bSDavid du Colombier
6539ef1f84bSDavid du Colombier convroute(r, addr, mask, gate, t, &nifc);
6549ef1f84bSDavid du Colombier iname = "-";
6559ef1f84bSDavid du Colombier if(nifc != -1) {
6569ef1f84bSDavid du Colombier iname = ifbuf;
6579ef1f84bSDavid du Colombier snprint(ifbuf, sizeof ifbuf, "%d", nifc);
6589ef1f84bSDavid du Colombier }
6599ef1f84bSDavid du Colombier p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname);
6609ef1f84bSDavid du Colombier if(rw->o < 0){
6619ef1f84bSDavid du Colombier n = p - rw->p;
6629ef1f84bSDavid du Colombier if(n > -rw->o){
6639ef1f84bSDavid du Colombier memmove(rw->p, rw->p-rw->o, n+rw->o);
6649ef1f84bSDavid du Colombier rw->p = p + rw->o;
6659ef1f84bSDavid du Colombier }
6669ef1f84bSDavid du Colombier rw->o += n;
6679ef1f84bSDavid du Colombier } else
6689ef1f84bSDavid du Colombier rw->p = p;
6699ef1f84bSDavid du Colombier }
6709ef1f84bSDavid du Colombier
6719ef1f84bSDavid du Colombier /*
6729ef1f84bSDavid du Colombier * recurse descending tree, applying the function in Routewalk
6739ef1f84bSDavid du Colombier */
6749ef1f84bSDavid du Colombier static int
rr(Route * r,Routewalk * rw)6759ef1f84bSDavid du Colombier rr(Route *r, Routewalk *rw)
6769ef1f84bSDavid du Colombier {
6779ef1f84bSDavid du Colombier int h;
6789ef1f84bSDavid du Colombier
6799ef1f84bSDavid du Colombier if(rw->e <= rw->p)
6809ef1f84bSDavid du Colombier return 0;
6819ef1f84bSDavid du Colombier if(r == nil)
6829ef1f84bSDavid du Colombier return 1;
6839ef1f84bSDavid du Colombier
6849ef1f84bSDavid du Colombier if(rr(r->left, rw) == 0)
6859ef1f84bSDavid du Colombier return 0;
6869ef1f84bSDavid du Colombier
6879ef1f84bSDavid du Colombier if(r->type & Rv4)
6889ef1f84bSDavid du Colombier h = V4H(r->v4.address);
6899ef1f84bSDavid du Colombier else
6909ef1f84bSDavid du Colombier h = V6H(r->v6.address);
6919ef1f84bSDavid du Colombier
6929ef1f84bSDavid du Colombier if(h == rw->h)
6939ef1f84bSDavid du Colombier rw->walk(r, rw);
6949ef1f84bSDavid du Colombier
6959ef1f84bSDavid du Colombier if(rr(r->mid, rw) == 0)
6969ef1f84bSDavid du Colombier return 0;
6979ef1f84bSDavid du Colombier
6989ef1f84bSDavid du Colombier return rr(r->right, rw);
6999ef1f84bSDavid du Colombier }
7009ef1f84bSDavid du Colombier
7019ef1f84bSDavid du Colombier void
ipwalkroutes(Fs * f,Routewalk * rw)7029ef1f84bSDavid du Colombier ipwalkroutes(Fs *f, Routewalk *rw)
7039ef1f84bSDavid du Colombier {
7049ef1f84bSDavid du Colombier rlock(&routelock);
7059ef1f84bSDavid du Colombier if(rw->e > rw->p) {
7069ef1f84bSDavid du Colombier for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++)
7079ef1f84bSDavid du Colombier if(rr(f->v4root[rw->h], rw) == 0)
7089ef1f84bSDavid du Colombier break;
7099ef1f84bSDavid du Colombier }
7109ef1f84bSDavid du Colombier if(rw->e > rw->p) {
7119ef1f84bSDavid du Colombier for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++)
7129ef1f84bSDavid du Colombier if(rr(f->v6root[rw->h], rw) == 0)
7139ef1f84bSDavid du Colombier break;
7149ef1f84bSDavid du Colombier }
7159ef1f84bSDavid du Colombier runlock(&routelock);
7169ef1f84bSDavid du Colombier }
7179ef1f84bSDavid du Colombier
7189ef1f84bSDavid du Colombier long
routeread(Fs * f,char * p,ulong offset,int n)7199ef1f84bSDavid du Colombier routeread(Fs *f, char *p, ulong offset, int n)
7209ef1f84bSDavid du Colombier {
7219ef1f84bSDavid du Colombier Routewalk rw;
7229ef1f84bSDavid du Colombier
7239ef1f84bSDavid du Colombier rw.p = p;
7249ef1f84bSDavid du Colombier rw.e = p+n;
7259ef1f84bSDavid du Colombier rw.o = -offset;
7269ef1f84bSDavid du Colombier rw.walk = sprintroute;
7279ef1f84bSDavid du Colombier
7289ef1f84bSDavid du Colombier ipwalkroutes(f, &rw);
7299ef1f84bSDavid du Colombier
7309ef1f84bSDavid du Colombier return rw.p - p;
7319ef1f84bSDavid du Colombier }
7329ef1f84bSDavid du Colombier
7339ef1f84bSDavid du Colombier /*
7349ef1f84bSDavid du Colombier * this code is not in routeflush to reduce stack size
7359ef1f84bSDavid du Colombier */
7369ef1f84bSDavid du Colombier void
delroute(Fs * f,Route * r,int dolock)7379ef1f84bSDavid du Colombier delroute(Fs *f, Route *r, int dolock)
7389ef1f84bSDavid du Colombier {
7399ef1f84bSDavid du Colombier uchar addr[IPaddrlen];
7409ef1f84bSDavid du Colombier uchar mask[IPaddrlen];
7419ef1f84bSDavid du Colombier uchar gate[IPaddrlen];
7429ef1f84bSDavid du Colombier char t[5];
7439ef1f84bSDavid du Colombier int nifc;
7449ef1f84bSDavid du Colombier
7459ef1f84bSDavid du Colombier convroute(r, addr, mask, gate, t, &nifc);
7469ef1f84bSDavid du Colombier if(r->type & Rv4)
7479ef1f84bSDavid du Colombier v4delroute(f, addr+IPv4off, mask+IPv4off, dolock);
7489ef1f84bSDavid du Colombier else
7499ef1f84bSDavid du Colombier v6delroute(f, addr, mask, dolock);
7509ef1f84bSDavid du Colombier }
7519ef1f84bSDavid du Colombier
7529ef1f84bSDavid du Colombier /*
7539ef1f84bSDavid du Colombier * recurse until one route is deleted
7549ef1f84bSDavid du Colombier * returns 0 if nothing is deleted, 1 otherwise
7559ef1f84bSDavid du Colombier */
7569ef1f84bSDavid du Colombier int
routeflush(Fs * f,Route * r,char * tag)7579ef1f84bSDavid du Colombier routeflush(Fs *f, Route *r, char *tag)
7589ef1f84bSDavid du Colombier {
7599ef1f84bSDavid du Colombier if(r == nil)
7609ef1f84bSDavid du Colombier return 0;
7619ef1f84bSDavid du Colombier if(routeflush(f, r->mid, tag))
7629ef1f84bSDavid du Colombier return 1;
7639ef1f84bSDavid du Colombier if(routeflush(f, r->left, tag))
7649ef1f84bSDavid du Colombier return 1;
7659ef1f84bSDavid du Colombier if(routeflush(f, r->right, tag))
7669ef1f84bSDavid du Colombier return 1;
7679ef1f84bSDavid du Colombier if((r->type & Rifc) == 0){
7689ef1f84bSDavid du Colombier if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0){
7699ef1f84bSDavid du Colombier delroute(f, r, 0);
7709ef1f84bSDavid du Colombier return 1;
7719ef1f84bSDavid du Colombier }
7729ef1f84bSDavid du Colombier }
7739ef1f84bSDavid du Colombier return 0;
7749ef1f84bSDavid du Colombier }
7759ef1f84bSDavid du Colombier
7769ef1f84bSDavid du Colombier Route *
iproute(Fs * fs,uchar * ip)7779ef1f84bSDavid du Colombier iproute(Fs *fs, uchar *ip)
7789ef1f84bSDavid du Colombier {
7799ef1f84bSDavid du Colombier if(isv4(ip))
7809ef1f84bSDavid du Colombier return v4lookup(fs, ip+IPv4off, nil);
7819ef1f84bSDavid du Colombier else
7829ef1f84bSDavid du Colombier return v6lookup(fs, ip, nil);
7839ef1f84bSDavid du Colombier }
7849ef1f84bSDavid du Colombier
7859ef1f84bSDavid du Colombier static void
printroute(Route * r)7869ef1f84bSDavid du Colombier printroute(Route *r)
7879ef1f84bSDavid du Colombier {
7889ef1f84bSDavid du Colombier int nifc;
7899ef1f84bSDavid du Colombier char t[5], *iname, ifbuf[5];
7909ef1f84bSDavid du Colombier uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];
7919ef1f84bSDavid du Colombier
7929ef1f84bSDavid du Colombier convroute(r, addr, mask, gate, t, &nifc);
7939ef1f84bSDavid du Colombier iname = "-";
7949ef1f84bSDavid du Colombier if(nifc != -1) {
7959ef1f84bSDavid du Colombier iname = ifbuf;
7969ef1f84bSDavid du Colombier snprint(ifbuf, sizeof ifbuf, "%d", nifc);
7979ef1f84bSDavid du Colombier }
7989ef1f84bSDavid du Colombier print(rformat, addr, mask, gate, t, r->tag, iname);
7999ef1f84bSDavid du Colombier }
8009ef1f84bSDavid du Colombier
8019ef1f84bSDavid du Colombier long
routewrite(Fs * f,Chan * c,char * p,int n)8029ef1f84bSDavid du Colombier routewrite(Fs *f, Chan *c, char *p, int n)
8039ef1f84bSDavid du Colombier {
8049ef1f84bSDavid du Colombier int h, changed;
8059ef1f84bSDavid du Colombier char *tag;
8069ef1f84bSDavid du Colombier Cmdbuf *cb;
8079ef1f84bSDavid du Colombier uchar addr[IPaddrlen];
8089ef1f84bSDavid du Colombier uchar mask[IPaddrlen];
8099ef1f84bSDavid du Colombier uchar gate[IPaddrlen];
8109ef1f84bSDavid du Colombier IPaux *a, *na;
8119ef1f84bSDavid du Colombier Route *q;
812*55ba833bSDavid du Colombier uchar type;
8139ef1f84bSDavid du Colombier
8149ef1f84bSDavid du Colombier cb = parsecmd(p, n);
8159ef1f84bSDavid du Colombier if(waserror()){
8169ef1f84bSDavid du Colombier free(cb);
8179ef1f84bSDavid du Colombier nexterror();
8189ef1f84bSDavid du Colombier }
8199ef1f84bSDavid du Colombier
8209ef1f84bSDavid du Colombier if(strcmp(cb->f[0], "flush") == 0){
8219ef1f84bSDavid du Colombier tag = cb->f[1];
8229ef1f84bSDavid du Colombier for(h = 0; h < nelem(f->v4root); h++)
8239ef1f84bSDavid du Colombier for(changed = 1; changed;){
8249ef1f84bSDavid du Colombier wlock(&routelock);
8259ef1f84bSDavid du Colombier changed = routeflush(f, f->v4root[h], tag);
8269ef1f84bSDavid du Colombier wunlock(&routelock);
8279ef1f84bSDavid du Colombier }
8289ef1f84bSDavid du Colombier for(h = 0; h < nelem(f->v6root); h++)
8299ef1f84bSDavid du Colombier for(changed = 1; changed;){
8309ef1f84bSDavid du Colombier wlock(&routelock);
8319ef1f84bSDavid du Colombier changed = routeflush(f, f->v6root[h], tag);
8329ef1f84bSDavid du Colombier wunlock(&routelock);
8339ef1f84bSDavid du Colombier }
8349ef1f84bSDavid du Colombier } else if(strcmp(cb->f[0], "remove") == 0){
8359ef1f84bSDavid du Colombier if(cb->nf < 3)
8369ef1f84bSDavid du Colombier error(Ebadarg);
8379ef1f84bSDavid du Colombier if (parseip(addr, cb->f[1]) == -1)
8389ef1f84bSDavid du Colombier error(Ebadip);
8399ef1f84bSDavid du Colombier parseipmask(mask, cb->f[2]);
8409ef1f84bSDavid du Colombier if(memcmp(addr, v4prefix, IPv4off) == 0)
8419ef1f84bSDavid du Colombier v4delroute(f, addr+IPv4off, mask+IPv4off, 1);
8429ef1f84bSDavid du Colombier else
8439ef1f84bSDavid du Colombier v6delroute(f, addr, mask, 1);
8449ef1f84bSDavid du Colombier } else if(strcmp(cb->f[0], "add") == 0){
8459ef1f84bSDavid du Colombier if(cb->nf < 4)
8469ef1f84bSDavid du Colombier error(Ebadarg);
8479ef1f84bSDavid du Colombier if(parseip(addr, cb->f[1]) == -1 ||
8489ef1f84bSDavid du Colombier parseip(gate, cb->f[3]) == -1)
8499ef1f84bSDavid du Colombier error(Ebadip);
8509ef1f84bSDavid du Colombier parseipmask(mask, cb->f[2]);
8519ef1f84bSDavid du Colombier tag = "none";
8529ef1f84bSDavid du Colombier if(c != nil){
8539ef1f84bSDavid du Colombier a = c->aux;
8549ef1f84bSDavid du Colombier tag = a->tag;
8559ef1f84bSDavid du Colombier }
856*55ba833bSDavid du Colombier if(memcmp(addr, v4prefix, IPv4off) == 0){
857*55ba833bSDavid du Colombier type = 0;
858*55ba833bSDavid du Colombier if(ipcmp(mask, IPallbits) == 0)
859*55ba833bSDavid du Colombier type = Rbcast;
860*55ba833bSDavid du Colombier v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, type);
861*55ba833bSDavid du Colombier }else
8629ef1f84bSDavid du Colombier v6addroute(f, tag, addr, mask, gate, 0);
8639ef1f84bSDavid du Colombier } else if(strcmp(cb->f[0], "tag") == 0) {
8649ef1f84bSDavid du Colombier if(cb->nf < 2)
8659ef1f84bSDavid du Colombier error(Ebadarg);
8669ef1f84bSDavid du Colombier
8679ef1f84bSDavid du Colombier a = c->aux;
8689ef1f84bSDavid du Colombier na = newipaux(a->owner, cb->f[1]);
8699ef1f84bSDavid du Colombier c->aux = na;
8709ef1f84bSDavid du Colombier free(a);
8719ef1f84bSDavid du Colombier } else if(strcmp(cb->f[0], "route") == 0) {
8729ef1f84bSDavid du Colombier if(cb->nf < 2)
8739ef1f84bSDavid du Colombier error(Ebadarg);
8749ef1f84bSDavid du Colombier if (parseip(addr, cb->f[1]) == -1)
8759ef1f84bSDavid du Colombier error(Ebadip);
8769ef1f84bSDavid du Colombier
8779ef1f84bSDavid du Colombier q = iproute(f, addr);
8789ef1f84bSDavid du Colombier print("%I: ", addr);
8799ef1f84bSDavid du Colombier if(q == nil)
8809ef1f84bSDavid du Colombier print("no route\n");
8819ef1f84bSDavid du Colombier else
8829ef1f84bSDavid du Colombier printroute(q);
8839ef1f84bSDavid du Colombier }
8849ef1f84bSDavid du Colombier
8859ef1f84bSDavid du Colombier poperror();
8869ef1f84bSDavid du Colombier free(cb);
8879ef1f84bSDavid du Colombier return n;
8889ef1f84bSDavid du Colombier }
889