|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: #include "arp.h" ! 8: #include "../port/ipdat.h" ! 9: ! 10: #include "devtab.h" ! 11: ! 12: /* ! 13: * All ip numbers and masks are stored as ulongs. ! 14: * All interfaces to this code uses the standard byte ! 15: * string representation. ! 16: */ ! 17: ! 18: typedef struct Iproute Iproute; ! 19: typedef struct Iprtab Iprtab; ! 20: ! 21: enum ! 22: { ! 23: Nroutes= 1024, ! 24: }; ! 25: ! 26: /* ! 27: * routes ! 28: */ ! 29: struct Iproute { ! 30: ulong dst; ! 31: ulong gate; ! 32: ulong mask; ! 33: Iproute *next; ! 34: int inuse; ! 35: }; ! 36: struct Iprtab { ! 37: Lock; ! 38: int n; /* number of valid routes */ ! 39: Iproute *first; /* list of valid routes */ ! 40: Iproute r[Nroutes]; /* all routes */ ! 41: }; ! 42: Iprtab iprtab; ! 43: ! 44: /* ! 45: * The chosen route is the one obeys the constraint ! 46: * r->mask & dst == r->dst ! 47: * ! 48: * If there are several matches, the one whose mask has the most ! 49: * leading ones (and hence is the most specific) wins. This is ! 50: * forced by storing the routes in decreasing number of ones order ! 51: * and returning the first match. The default gateway has no ones ! 52: * in the mask and is thus the last matched. ! 53: */ ! 54: Ipdevice* ! 55: iproute(uchar *dst, uchar *gate) ! 56: { ! 57: Iproute *r; ! 58: Ipdevice *p; ! 59: ulong udst; ! 60: ! 61: udst = nhgetl(dst); ! 62: for(p = ipd; p < &ipd[Nipd]; p++){ ! 63: if(p->q == 0) ! 64: continue; ! 65: if((udst&p->Mynetmask) == p->Remip){ ! 66: memmove(gate, dst, 4); ! 67: return p; ! 68: } ! 69: } ! 70: ! 71: /* ! 72: * first check routes ! 73: */ ! 74: for(r = iprtab.first; r; r = r->next){ ! 75: if((r->mask&udst) == r->dst){ ! 76: hnputl(gate, r->gate); ! 77: for(p = ipd; p < &ipd[Nipd]; p++){ ! 78: if(p->q == 0) ! 79: break; ! 80: if((r->gate&p->Mynetmask) == p->Remip) ! 81: return p; ! 82: } ! 83: return ipd; ! 84: } ! 85: } ! 86: ! 87: /* ! 88: * else just return the same address and first interface ! 89: */ ! 90: memmove(gate, dst, 4); ! 91: return ipd; ! 92: } ! 93: ! 94: /* ! 95: * Add a route, create a mask if the first mask is 0. ! 96: * ! 97: * All routes are stored sorted by the length of leading ! 98: * ones in the mask. ! 99: * ! 100: * NOTE: A default route has an all zeroes mask and dst. ! 101: */ ! 102: void ! 103: ipaddroute(ulong dst, ulong mask, ulong gate) ! 104: { ! 105: Iproute *r, *e, *free; ! 106: ! 107: /* ! 108: * filter out impossible requests ! 109: */ ! 110: if((dst&mask) != dst) ! 111: error(Enetaddr); ! 112: ! 113: /* ! 114: * see if we already have a route for ! 115: * the destination ! 116: */ ! 117: lock(&iprtab); ! 118: free = 0; ! 119: for(r = iprtab.r; r < &iprtab.r[Nroutes]; r++){ ! 120: if(r->inuse == 0){ ! 121: free = r; ! 122: continue; ! 123: } ! 124: if(dst==r->dst && mask==r->mask){ ! 125: r->gate = gate; ! 126: unlock(&iprtab); ! 127: return; ! 128: } ! 129: } ! 130: if(free == 0){ ! 131: unlock(&iprtab); ! 132: exhausted("routes"); ! 133: } ! 134: ! 135: /* ! 136: * add the new route in sorted order ! 137: */ ! 138: free->dst = dst; ! 139: free->mask = mask; ! 140: free->gate = gate; ! 141: free->inuse = 1; ! 142: for(r = e = iprtab.first; r; r = r->next){ ! 143: if(mask > r->mask) ! 144: break; ! 145: e = r; ! 146: } ! 147: free->next = r; ! 148: if(r == iprtab.first) ! 149: iprtab.first = free; ! 150: else ! 151: e->next = free; ! 152: iprtab.n++; ! 153: unlock(&iprtab); ! 154: } ! 155: ! 156: /* ! 157: * remove a route ! 158: */ ! 159: void ! 160: ipremroute(ulong dst, ulong mask) ! 161: { ! 162: Iproute *r, *e; ! 163: ! 164: lock(&iprtab); ! 165: for(r = e = iprtab.first; r; r = r->next){ ! 166: if(dst==r->dst && (mask == 0 || mask==r->mask)){ ! 167: if(r == iprtab.first) ! 168: iprtab.first = r->next; ! 169: else ! 170: e->next = r->next; ! 171: r->inuse = 0; ! 172: iprtab.n--; ! 173: break; ! 174: } ! 175: e = r; ! 176: } ! 177: unlock(&iprtab); ! 178: } ! 179: ! 180: /* ! 181: * remove all routes ! 182: */ ! 183: void ! 184: ipflushroute(void) ! 185: { ! 186: Iproute *r; ! 187: ! 188: lock(&iprtab); ! 189: for(r = iprtab.first; r; r = r->next) ! 190: r->inuse = 0; ! 191: iprtab.first = 0; ! 192: iprtab.n = 0; ! 193: unlock(&iprtab); ! 194: } ! 195: ! 196: /* ! 197: * device interface ! 198: */ ! 199: enum{ ! 200: Qdir, ! 201: Qdata, ! 202: Qipifc, ! 203: }; ! 204: Dirtab iproutetab[]={ ! 205: "iproute", {Qdata}, 0, 0666, ! 206: "ipifc", {Qipifc}, 0, 0666, ! 207: }; ! 208: #define Niproutetab (sizeof(iproutetab)/sizeof(Dirtab)) ! 209: ! 210: void ! 211: iproutereset(void) ! 212: { ! 213: } ! 214: ! 215: void ! 216: iprouteinit(void) ! 217: { ! 218: } ! 219: ! 220: Chan * ! 221: iprouteattach(char *spec) ! 222: { ! 223: return devattach('P', spec); ! 224: } ! 225: ! 226: Chan * ! 227: iprouteclone(Chan *c, Chan *nc) ! 228: { ! 229: return devclone(c, nc); ! 230: } ! 231: ! 232: int ! 233: iproutewalk(Chan *c, char *name) ! 234: { ! 235: return devwalk(c, name, iproutetab, (long)Niproutetab, devgen); ! 236: } ! 237: ! 238: void ! 239: iproutestat(Chan *c, char *db) ! 240: { ! 241: devstat(c, db, iproutetab, (long)Niproutetab, devgen); ! 242: } ! 243: ! 244: Chan * ! 245: iprouteopen(Chan *c, int omode) ! 246: { ! 247: if(c->qid.path == CHDIR){ ! 248: if(omode != OREAD) ! 249: error(Eperm); ! 250: } ! 251: c->mode = openmode(omode); ! 252: c->flag |= COPEN; ! 253: c->offset = 0; ! 254: return c; ! 255: } ! 256: ! 257: void ! 258: iproutecreate(Chan *c, char *name, int omode, ulong perm) ! 259: { ! 260: USED(c, name, omode, perm); ! 261: error(Eperm); ! 262: } ! 263: ! 264: void ! 265: iprouteremove(Chan *c) ! 266: { ! 267: USED(c); ! 268: error(Eperm); ! 269: } ! 270: ! 271: void ! 272: iproutewstat(Chan *c, char *dp) ! 273: { ! 274: USED(c, dp); ! 275: error(Eperm); ! 276: } ! 277: ! 278: void ! 279: iprouteclose(Chan *c) ! 280: { ! 281: USED(c); ! 282: } ! 283: ! 284: /* sprint an ip address right justified into a 16 char field */ ! 285: char* ! 286: ipformat(char *to, ulong ip) ! 287: { ! 288: uchar hip[4]; ! 289: char buf[17]; ! 290: int n; ! 291: ! 292: hnputl(hip, ip); ! 293: n = sprint(buf, "%d.%d.%d.%d", hip[0], hip[1], hip[2], hip[3]); ! 294: memset(to, ' ', 16 - n); ! 295: memmove(to+16-n, buf, n); ! 296: to[16] = 0; ! 297: return to; ! 298: } ! 299: ! 300: long ! 301: iprouteread(Chan *c, void *a, long n, ulong offset) ! 302: { ! 303: Iproute *r; ! 304: Ipdevice *p; ! 305: char *va = a; ! 306: char *e; ! 307: int part, bytes, size; ! 308: char dst[17], mask[17], gate[17]; ! 309: char buf[128]; ! 310: ! 311: switch((int)(c->qid.path&~CHDIR)){ ! 312: case Qdir: ! 313: return devdirread(c, a, n, iproutetab, Niproutetab, devgen); ! 314: case Qdata: ! 315: lock(&iprtab); ! 316: bytes = 0; ! 317: e = va + n; ! 318: for(r = iprtab.first; r && va < e; r = r->next){ ! 319: size = sprint(buf, "%s & %s -> %s\n", ipformat(dst, r->dst), ! 320: ipformat(mask, r->mask), ipformat(gate, r->gate)); ! 321: if(bytes + size <= offset){ ! 322: bytes += size; ! 323: continue; ! 324: } ! 325: ! 326: if(va == a){ ! 327: part = offset - bytes; ! 328: size -= part; ! 329: } else ! 330: part = 0; ! 331: if(size > n) ! 332: size = n; ! 333: ! 334: memmove(va, buf + part, size); ! 335: va += size; ! 336: } ! 337: unlock(&iprtab); ! 338: n = va - (char*)a; ! 339: break; ! 340: case Qipifc: ! 341: bytes = 0; ! 342: e = va + n; ! 343: for(p = ipd; p < &ipd[Nipd] && va < e; p++){ ! 344: if(p->q == 0) ! 345: continue; ! 346: size = sprint(buf, " #%C%d %5d %s %s %s\n", ! 347: devchar[p->type], p->dev, p->maxmtu, ! 348: ipformat(dst, p->Myip[0]), ! 349: ipformat(mask, p->Mynetmask), ! 350: ipformat(gate, p->Remip)); ! 351: if(bytes + size <= offset){ ! 352: bytes += size; ! 353: continue; ! 354: } ! 355: ! 356: if(va == a){ ! 357: part = offset - bytes; ! 358: size -= part; ! 359: } else ! 360: part = 0; ! 361: if(size > n) ! 362: size = n; ! 363: ! 364: memmove(va, buf + part, size); ! 365: va += size; ! 366: } ! 367: n = va - (char*)a; ! 368: break; ! 369: default: ! 370: n=0; ! 371: break; ! 372: } ! 373: return n; ! 374: } ! 375: ! 376: long ! 377: iproutewrite(Chan *c, char *a, long n, ulong offset) ! 378: { ! 379: char buf[128]; ! 380: char *field[4]; ! 381: Ipaddr mask, dst, gate; ! 382: int m; ! 383: ! 384: USED(offset); ! 385: ! 386: switch((int)(c->qid.path&~CHDIR)){ ! 387: case Qdata: ! 388: strncpy(buf, a, sizeof buf); ! 389: m = getfields(buf, field, 4, " "); ! 390: ! 391: if(strncmp(field[0], "flush", 5) == 0) ! 392: ipflushroute(); ! 393: else if(strncmp(field[0], "add", 3) == 0){ ! 394: switch(m){ ! 395: case 4: ! 396: dst = ipparse(field[1]); ! 397: mask = ipparse(field[2]); ! 398: gate = ipparse(field[3]); ! 399: ipaddroute(dst, mask, gate); ! 400: break; ! 401: case 3: ! 402: dst = ipparse(field[1]); ! 403: gate = ipparse(field[2]); ! 404: ipaddroute(dst, classmask[dst>>30], gate); ! 405: break; ! 406: default: ! 407: error(Ebadarg); ! 408: } ! 409: } else if(strncmp(field[0], "delete", 6) == 0){ ! 410: switch(m){ ! 411: case 3: ! 412: dst = ipparse(field[1]); ! 413: mask = ipparse(field[2]); ! 414: ipremroute(dst, mask); ! 415: break; ! 416: case 2: ! 417: dst = ipparse(field[1]); ! 418: ipremroute(dst, 0); ! 419: break; ! 420: default: ! 421: error(Ebadarg); ! 422: } ! 423: } ! 424: else ! 425: error(Ebadctl); ! 426: break; ! 427: default: ! 428: error(Ebadusefd); ! 429: } ! 430: return n; ! 431: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.