|
|
1.1 ! root 1: #include <sys/param.h> ! 2: #include <fio.h> ! 3: #include <signal.h> ! 4: #include <errno.h> ! 5: #include <sys/filio.h> ! 6: #include <sys/inet/in.h> ! 7: #include <sys/inet/ip_var.h> ! 8: #include <sys/inet/udp_user.h> ! 9: #include "config.h" ! 10: ! 11: #define IPDEVICE "/dev/ip16" /* device for getting ip info from */ ! 12: #define RPORT 520 ! 13: ! 14: int udpfd, ipfd, verbose, trace, quiet, traceinput, hopoffset; ! 15: extern errno; ! 16: extern int buf_ld; ! 17: extern char *in_ntoa(); ! 18: extern u_short cksum(); ! 19: ! 20: struct udppacket { ! 21: struct udpaddr addr; ! 22: char buf[4096]; ! 23: }; ! 24: ! 25: main(argc, argv) ! 26: char *argv[]; ! 27: { ! 28: int n, i; ! 29: struct udppacket packet; ! 30: char *cp; ! 31: ! 32: for(i = 1; i < argc; i++){ ! 33: if(argv[i][0] == '-'){ ! 34: for(cp = argv[i]+1; *cp; cp++){ ! 35: switch(*cp){ ! 36: case 'v': ! 37: verbose++; ! 38: break; ! 39: case 'q': ! 40: quiet++; ! 41: break; ! 42: case 't': ! 43: trace++; ! 44: break; ! 45: case 'T': ! 46: traceinput++; ! 47: break; ! 48: default: ! 49: if((*cp >= '0' && *cp <= '9') || *cp == '-') { ! 50: hopoffset = atoi(cp); ! 51: while(*cp >= '0' && *cp <= '9') ! 52: cp++; ! 53: cp--; ! 54: } else { ! 55: fprint(2, "usage: routed [-qtvT#]\n"); exit(1); ! 56: } ! 57: break; ! 58: } ! 59: } ! 60: } else ! 61: recsafe(argv[i]); ! 62: } ! 63: ! 64: if(verbose || traceinput || trace) { ! 65: if(hopoffset) ! 66: fprint(2, "%s: adding %d to each metric\n", argv[0], hopoffset); ! 67: } ! 68: ! 69: if((udpfd = udp_datagram(RPORT)) < 0) { ! 70: perror("udp route daemon: no connection"); ! 71: exit(1); ! 72: } ! 73: ! 74: /* ! 75: * try pushing bufld, complain but don't exit if unable ! 76: */ ! 77: /* ! 78: if(ioctl(udpfd, FIOPUSHLD, &buf_ld)<0){ ! 79: perror("pushing buf_ld"); ! 80: } ! 81: if(ioctl(udpfd, FIOPUSHLD, &buf_ld)<0){ ! 82: perror("pushing buf_ld"); ! 83: } ! 84: if(ioctl(udpfd, FIOPUSHLD, &buf_ld)<0){ ! 85: perror("pushing buf_ld"); ! 86: } ! 87: */ ! 88: ! 89: if((ipfd = open(IPDEVICE, 2)) < 0) { ! 90: perror(IPDEVICE); ! 91: exit(1); ! 92: } ! 93: ! 94: readgateways(); ! 95: if(!(verbose || traceinput || trace)) { ! 96: detach("routed"); ! 97: nice(-20); ! 98: } ! 99: timer(); ! 100: ! 101: again: ! 102: while((n = read(udpfd, &packet, sizeof(struct udppacket))) > 0) { ! 103: routed(&packet, n - sizeof(struct udpaddr)); ! 104: } ! 105: if(n < 0 && errno == EINTR) ! 106: goto again; ! 107: } ! 108: ! 109: ! 110: /* protocol.h 4.10 83/08/11 */ ! 111: /* ! 112: * Routing Information Protocol ! 113: * ! 114: * Derived from Xerox NS Routing Information Protocol ! 115: * by changing 32-bit net numbers to sockaddr's and ! 116: * padding stuff to 32-bit boundaries. ! 117: */ ! 118: #define RIPVERSION 1 ! 119: #define AF_INET 2 ! 120: #define AF_UNSPEC 0 ! 121: ! 122: struct sockaddr{ ! 123: short sin_family; ! 124: u_short sin_port; ! 125: u_long sin_addr; ! 126: char sin_zero[8]; ! 127: }; ! 128: struct netinfo { ! 129: struct sockaddr rip_dst; /* destination net/host */ ! 130: int rip_metric; /* cost of route */ ! 131: }; ! 132: ! 133: struct rip { ! 134: u_char rip_cmd; /* request/response */ ! 135: u_char rip_vers; /* protocol version # */ ! 136: u_char rip_res1[2]; /* pad to 32-bit boundary */ ! 137: union { ! 138: struct netinfo ru_nets[1]; /* variable length... */ ! 139: char ru_tracefile[1]; /* ditto ... */ ! 140: } ripun; ! 141: #define rip_nets ripun.ru_nets ! 142: #define rip_tracefile ripun.ru_tracefile ! 143: }; ! 144: ! 145: /* ! 146: * Packet types. ! 147: */ ! 148: #define RIPCMD_REQUEST 1 /* want info */ ! 149: #define RIPCMD_RESPONSE 2 /* responding to request */ ! 150: #define RIPCMD_TRACEON 3 /* turn tracing on */ ! 151: #define RIPCMD_TRACEOFF 4 /* turn it off */ ! 152: ! 153: #define RIPCMD_MAX 5 ! 154: #ifdef RIPCMDS ! 155: char *ripcmds[RIPCMD_MAX] = ! 156: { "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" }; ! 157: #endif ! 158: ! 159: #define HOPCNT_INFINITY 16 /* per Xerox NS */ ! 160: #define MAXPACKETSIZE 488 /* max broadcast size */ ! 161: #define MAXROUTESPERPACKET (MAXPACKETSIZE-4)/sizeof(struct netinfo) ! 162: ! 163: /* ! 164: * Timer values used in managing the routing table. ! 165: * Every update forces an entry's timer to be reset. After ! 166: * EXPIRE_TIME without updates, the entry is marked invalid, ! 167: * but held onto until GARBAGE_TIME so that others may ! 168: * see it "be deleted". ! 169: */ ! 170: #define TIMER_RATE 60 /* interval in seconds over which we bcast to all ! 171: * directly connected interfaces */ ! 172: ! 173: #define EXPIRE_TIME 180 /* time to mark entry invalid */ ! 174: #define GARBAGE_TIME 240 /* time to garbage collect */ ! 175: ! 176: #define NIFS TIMER_RATE ! 177: struct ipif ifs[NIFS]; ! 178: int nextifs; /* next interface to broadcast to */ ! 179: int nifs; /* number of functioning interfaces */ ! 180: ! 181: routed(up, len) ! 182: struct udppacket *up; ! 183: u_int len; ! 184: { ! 185: struct rip *rip; ! 186: ! 187: if(traceinput) ! 188: logevent("from %s\n", in_ntoa(up->addr.host)); ! 189: rip = (struct rip *)(up->buf); ! 190: if(rip->rip_vers != RIPVERSION) ! 191: return; ! 192: switch(rip->rip_cmd){ ! 193: case RIPCMD_RESPONSE: ! 194: if(up->addr.port != RPORT) ! 195: logevent("routed: %s %d masquerading as routed\n", ! 196: in_host(up->addr.host), up->addr.port); ! 197: else ! 198: response(up, len); ! 199: break; ! 200: case RIPCMD_REQUEST: ! 201: request(up, len); ! 202: break; ! 203: default: ! 204: logevent("routed: %s %d sent strange command %d\n", ! 205: in_host(up->addr.host), up->addr.port, rip->rip_cmd); ! 206: return; ! 207: } ! 208: } ! 209: ! 210: /* ! 211: * don't believe responses from this host. no use infinitely ! 212: * recursing. ! 213: */ ! 214: response(up, len) ! 215: struct udppacket *up; ! 216: u_int len; ! 217: { ! 218: struct rip *rip; ! 219: struct sockaddr *sin; ! 220: struct netinfo *np; ! 221: ! 222: rip = (struct rip *)(up->buf); ! 223: if(myaddr(up->addr.host)) ! 224: return; ! 225: np = rip->rip_nets; ! 226: while(np < (struct netinfo *)(&(up->buf[len]))){ ! 227: sin = &(np->rip_dst); ! 228: np->rip_metric = ntohl(np->rip_metric); ! 229: sin->sin_port = ntohs(sin->sin_port); ! 230: sin->sin_addr = ntohl(sin->sin_addr); ! 231: if(traceinput) { ! 232: logevent(" %s %d\n", in_ntoa(sin->sin_addr), np->rip_metric); ! 233: } ! 234: if (np->rip_metric > 0 && saferoute(sin->sin_addr) == 0) ! 235: rtinstall(sin->sin_addr, up->addr.host, np->rip_metric, 0, -1); ! 236: np++; ! 237: } ! 238: } ! 239: ! 240: /* ! 241: * Only accept requests for all routes or for internet routes. ! 242: * In all cases send back everything. ! 243: */ ! 244: request(up, len) ! 245: struct udppacket *up; ! 246: u_int len; ! 247: { ! 248: struct rip *rip; ! 249: struct sockaddr *sin; ! 250: struct netinfo *np; ! 251: ! 252: rip = (struct rip *)(up->buf); ! 253: np = rip->rip_nets; ! 254: if(traceinput) ! 255: logevent("request from %s\n", in_ntoa(up->addr.host)); ! 256: ! 257: sin = &(np->rip_dst); ! 258: np->rip_metric = ntohl(np->rip_metric); ! 259: sin->sin_family = ntohs(sin->sin_family); ! 260: if((sin->sin_family == AF_UNSPEC && np->rip_metric == HOPCNT_INFINITY) ! 261: || sin->sin_family == AF_INET) ! 262: send(up); ! 263: } ! 264: ! 265: struct route{ ! 266: u_long dst; ! 267: u_long gate; ! 268: int metric; ! 269: int age; ! 270: int nif; ! 271: }; ! 272: #define NROUTES 360 ! 273: struct route routes[NROUTES]; ! 274: ! 275: rtinstall(dst, gate, metric, age, nif) ! 276: u_long dst, gate; ! 277: { ! 278: struct route *rp, *save = 0; ! 279: char hname[128]; ! 280: ! 281: /* ! 282: * don't let a default route get set unless we are quiet ! 283: */ ! 284: if(dst==0 && !quiet) ! 285: return; ! 286: ! 287: /* ! 288: * ignore any route with inifinite hop counts ! 289: */ ! 290: if(metric >= HOPCNT_INFINITY) ! 291: return; ! 292: ! 293: /* ! 294: * look up the route in our local tables (not the kernel's) ! 295: */ ! 296: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 297: if(rp->dst == dst) ! 298: break; ! 299: if(rp->dst == 0 && save == 0) ! 300: save = rp; ! 301: } ! 302: if(rp >= &routes[NROUTES] && (rp = save) == 0){ ! 303: logevent("routed: out of routes?\n"); ! 304: return; ! 305: } ! 306: ! 307: /* ! 308: * if this is a new route, make sure the new count is smaller ! 309: */ ! 310: if(rp->dst == 0) ! 311: rp->metric = HOPCNT_INFINITY + 1; ! 312: ! 313: /* ! 314: * if new route is closer than the old route ! 315: * or the gate is the same but the distance has changed ! 316: * or the gate is the same but the age has changed, ! 317: * then use the new gate ! 318: */ ! 319: if(metric < rp->metric ! 320: || (gate == rp->gate && metric != rp->metric) ! 321: || (gate == rp->gate && age != rp->age)){ ! 322: rp->metric = metric; ! 323: rp->age = age; ! 324: if(rp->dst != dst || rp->gate != gate){ ! 325: if(verbose){ ! 326: strcpy(hname, in_host(gate)); ! 327: logevent("%s installing as route to %s, metric %d\n", ! 328: hname, in_host(dst), metric); ! 329: } ! 330: rp->dst = dst; ! 331: rp->gate = gate; ! 332: rp->nif = nif; ! 333: if(ioctl(ipfd, IPIOROUTE, rp) < 0) ! 334: logevent("can't install routed %s\n", in_ntoa(rp->gate)); ! 335: } else { ! 336: if(verbose > 1){ ! 337: strcpy(hname, in_host(gate)); ! 338: logevent("%s confirmed as route to %s, metric %d\n", ! 339: hname, in_host(dst), metric); ! 340: } ! 341: rp->dst = dst; ! 342: rp->gate = gate; ! 343: } ! 344: } ! 345: } ! 346: ! 347: /* ! 348: * keep a list of routes ! 349: * that belong to us; ! 350: * don't let anyone claim them ! 351: */ ! 352: ! 353: #define NSAFE 20 ! 354: ! 355: u_long safer[NSAFE]; ! 356: int nsafe = 0; ! 357: ! 358: recsafe(s) ! 359: char *s; ! 360: { ! 361: if (nsafe < NSAFE) ! 362: safer[nsafe++] = in_address(s); ! 363: } ! 364: ! 365: saferoute(dst) ! 366: u_long dst; ! 367: { ! 368: register int i; ! 369: ! 370: for (i = 0; i < nsafe; i++) ! 371: if (dst == safer[i]) ! 372: return (1); ! 373: return (0); ! 374: } ! 375: ! 376: readgateways() ! 377: { ! 378: int fd; ! 379: char *cp; ! 380: char net[32], gateway[32], which[32]; ! 381: u_long dst, gate; ! 382: int metric; ! 383: ! 384: if((fd = open(GATEWAYS, 0)) == 0) ! 385: return; ! 386: Finit(fd, 0); ! 387: while(cp=Frdline(fd)){ ! 388: if(sscanf(cp, "%s %s gateway %s metric %d", ! 389: which, net, gateway, &metric) != 4) ! 390: continue; ! 391: dst = in_address(net); ! 392: gate = in_address(gateway); ! 393: rtinstall(dst, gate, metric, -1, -1); ! 394: } ! 395: } ! 396: ! 397: timer() ! 398: { ! 399: int i; ! 400: struct route *rp; ! 401: struct ipif ipif; ! 402: u_long net; ! 403: char haddr1[32], haddr2[322]; ! 404: ! 405: if(nextifs == 0){ ! 406: /* ! 407: * get interfaces from kernel. ignore interfaces that are down, ! 408: * interfaces that are loop place holders (this==that), and the ! 409: * loop-back network ! 410: */ ! 411: for(i = nifs = 0; nifs < NIFS; i++){ ! 412: *(int *)&ipif = i; ! 413: if(ioctl(ipfd, IPIOGETIFS, &ipif) < 0) ! 414: break; ! 415: if((ipif.flags&IFF_UP) && ipif.thishost != ipif.that && ! 416: ipif.that != 0x7f000000) { ! 417: if(ipif.bcast[0] == 0) ! 418: ipif.bcast[0] = ipif.that; ! 419: ifs[nifs++] = ipif; ! 420: if(trace){ ! 421: strcpy(haddr1, in_ntoa(ipif.that)); ! 422: strcpy(haddr2, in_ntoa(ipif.thishost)); ! 423: logevent("ifs[%d] %s %s %s\n", nifs, haddr1, ! 424: haddr2, in_ntoa(ipif.bcast[0])); ! 425: } ! 426: rtinstall(ipif.that, ipif.that, 0, 0, nifs - 1); ! 427: } ! 428: } ! 429: } ! 430: ! 431: if(!quiet) ! 432: broadcast(); ! 433: ! 434: /* ! 435: * age routes && get rid of too old routes ! 436: */ ! 437: if(nextifs == 0) ! 438: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 439: if(rp->dst == 0) ! 440: continue; ! 441: if(rp->age > 10){ ! 442: rtdelete(rp); ! 443: } else if(rp->age >= 0){ ! 444: rp->age++; ! 445: } ! 446: } ! 447: ! 448: /* ! 449: * post alarm for broadcast to next interface ! 450: */ ! 451: signal(SIGALRM, timer); ! 452: i = nifs>0 ? TIMER_RATE/nifs : TIMER_RATE; ! 453: alarm(i+1); ! 454: } ! 455: ! 456: /* ! 457: * Send a broadcast to the next interface. This happens once every TIMER_RATE/nifs ! 458: * seconds so that n TIMER_RATE seconds we shoulc hit every interface. ! 459: */ ! 460: broadcast() ! 461: { ! 462: static long last; ! 463: long now; ! 464: int reps; ! 465: struct udppacket p; ! 466: ! 467: /* ! 468: * broadcast to interfaces. approximate one broadcast every ! 469: * TIMER_RATE/nifs seconds. ! 470: */ ! 471: now = time((long *)0); ! 472: reps = nifs ? (now-last)/(TIMER_RATE/nifs) : 0; ! 473: if(reps > nifs) ! 474: reps = nifs; ! 475: for(; reps>0; reps--){ ! 476: if(++nextifs >= nifs) ! 477: nextifs = 0; ! 478: ! 479: p.addr.host = ifs[nextifs].bcast[0]; ! 480: p.addr.port = RPORT; ! 481: send(&p); ! 482: } ! 483: last = now; ! 484: } ! 485: ! 486: /* ! 487: * put an entry into the bradcast message ! 488: */ ! 489: struct netinfo * ! 490: insert(rp, up, np, rip) ! 491: struct udppacket *up; ! 492: struct route *rp; ! 493: struct netinfo *np; ! 494: struct rip *rip; ! 495: { ! 496: struct sockaddr *sin; ! 497: char haddr[32]; ! 498: ! 499: /* ! 500: * don't send routes back onto the network from which they ! 501: * came ! 502: */ ! 503: if((rp->gate & ifs[nextifs].mask) == ifs[nextifs].that) ! 504: return np; ! 505: ! 506: /* ! 507: * put the routing entry into the message. ! 508: */ ! 509: bzero(np, sizeof(struct netinfo)); ! 510: sin = &(np->rip_dst); ! 511: np->rip_metric = htonl(rp->metric + 1 + hopoffset); ! 512: sin->sin_port = 0; ! 513: ! 514: /* ! 515: * don't send information about one network's subnets to other networks ! 516: */ ! 517: if(in_netof(rp->dst) == in_netof(ifs[nextifs].that)) ! 518: sin->sin_addr = htonl(rp->dst); ! 519: else ! 520: sin->sin_addr = htonl(in_netof(rp->dst)); ! 521: ! 522: sin->sin_family = htons((u_short)AF_INET); ! 523: if(trace){ ! 524: strcpy(haddr, in_ntoa(ntohl(sin->sin_addr))); ! 525: logevent(" %s %s %d\n", ! 526: haddr, ! 527: in_ntoa(rp->dst), ! 528: ntohl(np->rip_metric)); ! 529: } ! 530: np++; ! 531: ! 532: /* ! 533: * if the message is at maximum size, send it and start a new one ! 534: */ ! 535: if (np-rip->rip_nets == MAXROUTESPERPACKET) { ! 536: psend(up, (char *)np); ! 537: np = rip->rip_nets; ! 538: } ! 539: return np; ! 540: } ! 541: ! 542: /* ! 543: * send info about all routes ! 544: */ ! 545: send(up) ! 546: struct udppacket *up; ! 547: { ! 548: struct route *rp; ! 549: struct rip *rip; ! 550: struct netinfo *np; ! 551: long net; ! 552: ! 553: net = in_netof(ifs[nextifs].bcast[0]); ! 554: rip = (struct rip *)up->buf; ! 555: rip->rip_cmd = RIPCMD_RESPONSE; ! 556: rip->rip_vers = RIPVERSION; ! 557: np = rip->rip_nets; ! 558: if(trace) ! 559: logevent("BROADCAST:\n"); ! 560: ! 561: /* ! 562: * first send info about directly connected networks ! 563: */ ! 564: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 565: if(rp->dst == 0 || rp->metric > 0) ! 566: continue; ! 567: if(rp->metric + hopoffset + 1 >= HOPCNT_INFINITY) ! 568: continue; ! 569: np = insert(rp, up, np, rip); ! 570: } ! 571: ! 572: /* ! 573: * now send info about the rest ! 574: */ ! 575: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 576: if(rp->dst==0 || rp->metric<=0) ! 577: continue; ! 578: if(rp->metric + hopoffset + 1 >= HOPCNT_INFINITY) ! 579: continue; ! 580: np = insert(rp, up, np, rip); ! 581: } ! 582: if (np > rip->rip_nets) ! 583: psend(up, (char *)np); ! 584: } ! 585: ! 586: /* send one routing packet to one network */ ! 587: psend(pp, cp) ! 588: struct udppacket *pp; ! 589: char *cp; ! 590: { ! 591: int len=cp-(char *)pp; ! 592: int i; ! 593: ! 594: if(trace) ! 595: logevent("to %s %d\n", in_ntoa(pp->addr.host), len); ! 596: if (write(udpfd, pp, len) !=len) ! 597: logevent("udp write error\n"); ! 598: } ! 599: ! 600: myaddr(x) ! 601: u_long x; ! 602: { ! 603: int i; ! 604: ! 605: for(i = 0; i < nifs; i ++) ! 606: if(ifs[i].thishost == x) ! 607: return(1); ! 608: return(0); ! 609: } ! 610: ! 611: rtdelete(rp) ! 612: struct route *rp; ! 613: { ! 614: if(verbose) { ! 615: logevent("deleting %s %d\n", in_ntoa(rp->dst), rp->metric); ! 616: } ! 617: if(rp->gate != rp->dst){ ! 618: rp->gate = 0; ! 619: if(ioctl(ipfd, IPIOROUTE, rp) < 0) ! 620: logevent("can't remove route %s\n", in_ntoa(rp->gate)); ! 621: } ! 622: rp->gate = rp->dst = 0; ! 623: rp->age = rp->metric = 0; ! 624: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.