From 812b0290f086fad80c7f7b93bb311cb5f9bfb561 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 30 Mar 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-03-30 --- port/deviproute.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++ port/stnoether.c | 15 ++++ 2 files changed, 222 insertions(+) create mode 100644 port/deviproute.c diff --git a/port/deviproute.c b/port/deviproute.c new file mode 100644 index 0000000000000000000000000000000000000000..3213bf861dcf016c874b1da7bc1fb100b4da0cee --- /dev/null +++ b/port/deviproute.c @@ -0,0 +1,207 @@ +#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); +} diff --git a/port/stnoether.c b/port/stnoether.c index acbbe52c9560e57b792fd610eedfbec0d448dd43..bf210a10c39103985154829a2fd2df1f8e514e7c 100644 --- a/port/stnoether.c +++ b/port/stnoether.c @@ -267,10 +267,25 @@ noetheriput(Queue *q, Block *bp) static void etherparse(uchar *to, char *from) { + ulong ip; + uchar nip[4]; int tdig; int fdig; int i; +#ifdef MAGNUM + /* Dot means ip address */ + if(strchr(from, '.')) { + ip = ipparse(from); + if(ip == 0) + error(Ebadnet); + + hnputl(nip, ip); + if(arp_lookup(nip, to)) + return; + } +#endif + if(strlen(from) != 12) error(Ebadnet);