📄 iproute.c
字号:
#include "all.h"#include "../ip/ip.h"#define DEBUG if(cons.flags&ralloc.flag)printenum{ Version= 1, /* * definitions that are innately tied to BSD */ AF_INET= 2, AF_UNSPEC= 0, /* * Packet types. */ Request= 1, Response= 2, Traceon= 3, Traceoff= 4, Infinity= 16, /* infinite hop count */ Maxpacket= 488, /* largest packet body */};/* * network info */typedef struct Rip Rip;struct Rip{ uchar family[2]; uchar port[2]; uchar addr[Pasize]; uchar pad[8]; uchar metric[4];};typedef struct Ripmsg Ripmsg;struct Ripmsg{ uchar type; uchar vers; uchar pad[2]; Rip rip[1]; /* the rest of the packet consists of routes */};enum{ Maxroutes= (Maxpacket-4)/sizeof(Ripmsg),};/* * internal route info */enum{ Nroute = 2*1024, Nhash = 256, /* routing hash buckets */ Nifc = 16,};typedef struct Route Route;struct Route{ Route *next; uchar dest[Pasize]; uchar mask[Pasize]; uchar gate[Pasize]; int metric; int inuse; Timet time;};struct{ Lock; Route route[Nroute]; Route *hash[Nhash]; int nroute; ulong flag; int dorip;} ralloc;uchar classmask[4][4] ={ 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,};#define CLASS(p) ((*(uchar*)(p))>>6)static void considerroute(Route*);static void deleteroute(Route*);static void printroute(Route*);static void printroutes(void);static void installroute(Route*);static void getmask(uchar*, uchar*);static void maskip(uchar*, uchar*, uchar*);static int equivip(uchar*, uchar*);static void cmd_route(int, char*[]);static ulong rhash(uchar*);voidiprouteinit(void){ cmd_install("route", "subcommand -- ip routes", cmd_route); ralloc.flag = flag_install("route", "-- verbose"); if(!conf.ripoff) ralloc.dorip = 1;}static voidcmd_route(int argc, char *argv[]){ Route r; if(argc < 2) {usage: print("route add dest gate [mask] -- add a route\n"); print("route delete dest -- remote a route\n"); print("route print [dest] -- print routes\n"); print("route ripon -- listen to RIP packets\n"); print("route ripoff -- ignore RIP packets\n"); return; } if(strcmp(argv[1], "ripoff") == 0) ralloc.dorip = 0; else if(strcmp(argv[1], "ripon") == 0) ralloc.dorip = 1; else if(strcmp(argv[1], "add") == 0) { switch(argc){ default: goto usage; case 4: memmove(r.mask, classmask[CLASS(r.dest)], Pasize); break; case 5: if(chartoip(r.mask, argv[4])) goto usage; break; } if(chartoip(r.dest, argv[2]) || chartoip(r.gate, argv[3])) goto usage; r.metric = 0; /* rip can't nuke these */ deleteroute(&r); considerroute(&r); } else if(strcmp(argv[1], "delete") == 0) { if(argc != 3 || chartoip(r.dest, argv[2])) goto usage; deleteroute(&r); } else if(strcmp(argv[1], "print") == 0) { if(argc == 3) { if(chartoip(r.dest, argv[2])) goto usage; printroute(&r); } else printroutes(); }}/* * consider installing a route. Do so only if it is better than what * we have. */static voidconsiderroute(Route *r){ ulong h, i; ulong m, nm; Route *hp, **l; r->next = 0; r->time = time(); r->inuse = 1; lock(&ralloc); h = rhash(r->dest); for(hp = ralloc.hash[h]; hp; hp = hp->next) { if(equivip(hp->dest, r->dest) && equivip(hp->mask, r->mask)) { /* * found a match, replace if better (or much newer) */ if(r->metric < hp->metric || time()-hp->time > 10*60) { memmove(hp->gate, r->gate, Pasize); hp->metric = r->metric; DEBUG("route: replacement %I & %I -> %I (%d)\n", hp->dest, hp->mask, hp->dest, hp->metric); } if(equivip(r->gate, hp->gate)) hp->time = time(); goto done; } } /* * no match, look for space */ for(hp = ralloc.route; hp < &ralloc.route[Nroute]; hp++) if(hp->inuse == 0) break; if(hp == &ralloc.route[Nroute]) hp = 0; /* * look for an old entry */ for(i = 0; hp == 0 && i < Nhash; i++) { l = &ralloc.hash[i]; for(hp = *l; hp; hp = *l) { if(time() - hp->time > 10*60 && hp->metric > 0){ *l = hp->next; break; } l = &hp->next; } } if(hp == 0) { print("no more routes"); goto done; } memmove(hp, r, sizeof(Route)); /* * insert largest mask first */ m = nhgetl(hp->mask); for(l = &ralloc.hash[h]; *l; l = &(*l)->next){ nm = nhgetl((*l)->mask); if(nm < m) break; } hp->next = *l; *l = hp; DEBUG("route: new %I & %I -> %I (%d)\n", hp->dest, hp->mask, hp->dest, hp->metric);done: unlock(&ralloc);}static voiddeleteroute(Route *r){ int h; Route *hp, **l; lock(&ralloc); for(h = 0; h < Nhash; h++) { l = &ralloc.hash[h]; for(hp = *l; hp; hp = *l){ if(equivip(r->dest, hp->dest)) { *l = hp->next; hp->next = 0; hp->inuse = 0; break; } l = &hp->next; } } unlock(&ralloc);}static voidprintroutes(void){ Ifc *i; int h; Route *hp; uchar mask[Pasize]; lock(&ralloc); for(h = 0; h < Nhash; h++) for(hp = ralloc.hash[h]; hp; hp = hp->next) print("%I & %I -> %I\n", hp->dest, hp->mask, hp->gate); unlock(&ralloc); print("\nifc's\n"); for(i = enets; i; i = i->next) { hnputl(mask, i->mask); print("addr %I mask %I defgate %I\n", i->ipa, mask, i->netgate); }}static voidprintroute(Route *r){ int h; Route *hp; uchar net[Pasize]; h = rhash(r->dest); for(hp = ralloc.hash[h]; hp; hp = hp->next){ maskip(r->dest, hp->mask, net); if(equivip(hp->dest, net)){ print("%I & %I -> %I\n", hp->dest, hp->mask, hp->gate); return; } } print("default * -> %I\n", enets[0].netgate);}voidiproute(uchar *to, uchar *dst, uchar *def){ int h; Route *hp; uchar net[Pasize]; h = rhash(dst); for(hp = ralloc.hash[h]; hp; hp = hp->next) { maskip(dst, hp->mask, net); if(equivip(hp->dest, net)) { def = hp->gate; break; } } memmove(to, def, Pasize);}voidriprecv(Msgbuf *mb, Ifc*){ int n; Rip *r; Ripmsg *m; Udppkt *uh; Route route; if(ralloc.dorip == 0) goto drop; uh = (Udppkt*)mb->data; m = (Ripmsg*)(mb->data + Ensize + Ipsize + Udpsize); if(m->type != Response || m->vers != Version) goto drop; n = nhgets(uh->udplen); n -= Udpsize; n = n/sizeof(Rip); DEBUG("%d routes from %I\n", n, uh->src); memmove(route.gate, uh->src, Pasize); for(r = m->rip; r < &m->rip[n]; r++){ getmask(route.mask, r->addr); maskip(r->addr, route.mask, route.dest); route.metric = nhgetl(r->metric) + 1; if(route.metric < 1) continue; considerroute(&route); }drop: mbfree(mb);}/* * route's hashed by net, not subnet */static ulongrhash(uchar *d){ ulong h; uchar net[Pasize]; maskip(d, classmask[CLASS(d)], net); h = net[0] + net[1] + net[2]; return h % Nhash;}/* * figure out what mask to use, if we have a direct connected network * with the same class net use its subnet mask. */static voidgetmask(uchar *mask, uchar *dest){ Ifc *i; long ip; ip = nhgetl(dest); for(i = enets; i; i = i->next) if((i->ipaddr & i->cmask) == (ip & i->cmask)) { hnputl(mask, i->mask); return; } memmove(mask, classmask[CLASS(dest)], Pasize);}static voidmaskip(uchar *a, uchar *m, uchar *n){ int i; for(i = 0; i < 4; i++) n[i] = a[i] & m[i];}static intequivip(uchar *a, uchar *b){ int i; for(i = 0; i < 4; i++) if(a[i] != b[i]) return 0; return 1;}longipclassmask(uchar *ip){ return nhgetl(classmask[CLASS(ip)]);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -