|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <signal.h> ! 3: #include <errno.h> ! 4: #include <sys/param.h> ! 5: #include <sys/types.h> ! 6: #include <sgtty.h> ! 7: #include <sys/inet/in.h> ! 8: #include <sys/inet/ip_var.h> ! 9: #include <sys/inet/udp_user.h> ! 10: #include "config.h" ! 11: ! 12: #define IPDEVICE "/dev/ip16" /* device for getting ip info from */ ! 13: #define RPORT 520 ! 14: ! 15: int udpfd, ipfd, verbose, trace, quiet; ! 16: extern errno; ! 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: ! 31: for(i = 1; i < argc; i++){ ! 32: if(strcmp(argv[i], "-v") == 0) ! 33: verbose++; ! 34: else if(strcmp(argv[i], "-q") == 0) ! 35: quiet++; ! 36: else if(strcmp(argv[i], "-t") == 0) ! 37: trace++; ! 38: else ! 39: recsafe(argv[i]); ! 40: } ! 41: ! 42: if ((udpfd = udp_datagram(RPORT)) < 0) { ! 43: printf("udp route daemon: no connection\n"); ! 44: exit(1); ! 45: } ! 46: if ((ipfd = open(IPDEVICE, 2)) < 0) { ! 47: perror(IPDEVICE); ! 48: exit(1); ! 49: } ! 50: ! 51: readgateways(); ! 52: timer(); ! 53: ! 54: again: ! 55: while((n = read(udpfd, &packet, sizeof(struct udppacket))) > 0) { ! 56: if(packet.addr.port == RPORT) ! 57: routed(&packet, n - sizeof(struct udpaddr)); ! 58: else ! 59: fprintf(stderr, "routed: %s %s masquerading as routed\n", ! 60: in_host(packet.addr.host), packet.addr.port); ! 61: } ! 62: if(n < 0 && errno == EINTR) ! 63: goto again; ! 64: } ! 65: ! 66: ! 67: /* protocol.h 4.10 83/08/11 */ ! 68: /* ! 69: * Routing Information Protocol ! 70: * ! 71: * Derived from Xerox NS Routing Information Protocol ! 72: * by changing 32-bit net numbers to sockaddr's and ! 73: * padding stuff to 32-bit boundaries. ! 74: */ ! 75: #define RIPVERSION 1 ! 76: #define AF_INET 2 ! 77: ! 78: struct sockaddr{ ! 79: short sin_family; ! 80: u_short sin_port; ! 81: u_long sin_addr; ! 82: char sin_zero[8]; ! 83: }; ! 84: struct netinfo { ! 85: struct sockaddr rip_dst; /* destination net/host */ ! 86: int rip_metric; /* cost of route */ ! 87: }; ! 88: ! 89: struct rip { ! 90: u_char rip_cmd; /* request/response */ ! 91: u_char rip_vers; /* protocol version # */ ! 92: u_char rip_res1[2]; /* pad to 32-bit boundary */ ! 93: union { ! 94: struct netinfo ru_nets[1]; /* variable length... */ ! 95: char ru_tracefile[1]; /* ditto ... */ ! 96: } ripun; ! 97: #define rip_nets ripun.ru_nets ! 98: #define rip_tracefile ripun.ru_tracefile ! 99: }; ! 100: ! 101: /* ! 102: * Packet types. ! 103: */ ! 104: #define RIPCMD_REQUEST 1 /* want info */ ! 105: #define RIPCMD_RESPONSE 2 /* responding to request */ ! 106: #define RIPCMD_TRACEON 3 /* turn tracing on */ ! 107: #define RIPCMD_TRACEOFF 4 /* turn it off */ ! 108: ! 109: #define RIPCMD_MAX 5 ! 110: #ifdef RIPCMDS ! 111: char *ripcmds[RIPCMD_MAX] = ! 112: { "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" }; ! 113: #endif ! 114: ! 115: #define HOPCNT_INFINITY 16 /* per Xerox NS */ ! 116: #define MAXPACKETSIZE 512 /* max broadcast size */ ! 117: #define MAXROUTESPERPACKET (MAXPACKETSIZE-4)/sizeof(struct netinfo) ! 118: ! 119: /* ! 120: * Timer values used in managing the routing table. ! 121: * Every update forces an entry's timer to be reset. After ! 122: * EXPIRE_TIME without updates, the entry is marked invalid, ! 123: * but held onto until GARBAGE_TIME so that others may ! 124: * see it "be deleted". ! 125: */ ! 126: #define TIMER_RATE 30 /* alarm clocks every 30 seconds */ ! 127: ! 128: #define SUPPLY_INTERVAL 30 /* time to supply tables */ ! 129: ! 130: #define EXPIRE_TIME 180 /* time to mark entry invalid */ ! 131: #define GARBAGE_TIME 240 /* time to garbage collect */ ! 132: ! 133: #define NIFS 20 ! 134: u_long ifs[2*NIFS]; /* interface network/address pairs */ ! 135: ! 136: routed(up, len) ! 137: struct udppacket *up; ! 138: u_int len; ! 139: { ! 140: struct rip *rip; ! 141: struct sockaddr *sin; ! 142: struct netinfo *np; ! 143: ! 144: rip = (struct rip *)(up->buf); ! 145: if(rip->rip_cmd != RIPCMD_RESPONSE || rip->rip_vers != RIPVERSION) ! 146: return; ! 147: if(myaddr(up->addr.host)) ! 148: return; ! 149: np = rip->rip_nets; ! 150: if(trace) ! 151: printf("%s\n", in_ntoa(up->addr.host)); ! 152: while(np < (struct netinfo *)(&(up->buf[len]))){ ! 153: sin = &(np->rip_dst); ! 154: np->rip_metric = ntohl(np->rip_metric); ! 155: sin->sin_port = ntohs(sin->sin_port); ! 156: sin->sin_addr = ntohl(sin->sin_addr); ! 157: if(trace) { ! 158: printf(" %s %d\n", in_ntoa(sin->sin_addr), np->rip_metric); ! 159: fflush(stdout); ! 160: } ! 161: if (np->rip_metric > 0 && saferoute(sin->sin_addr) == 0) ! 162: rtinstall(sin->sin_addr, up->addr.host, np->rip_metric, 0); ! 163: np++; ! 164: } ! 165: } ! 166: ! 167: struct route{ ! 168: u_long dst; ! 169: u_long gate; ! 170: int metric; ! 171: int age; ! 172: }; ! 173: #define NROUTES 150 ! 174: struct route routes[NROUTES]; ! 175: ! 176: rtinstall(dst, gate, metric, age) ! 177: u_long dst, gate; ! 178: { ! 179: struct route *rp, *save = 0; ! 180: ! 181: if(metric >= HOPCNT_INFINITY) ! 182: return; ! 183: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 184: if(rp->dst == dst) ! 185: break; ! 186: if(rp->dst == 0 && save == 0) ! 187: save = rp; ! 188: } ! 189: if(rp >= &routes[NROUTES] && (rp = save) == 0){ ! 190: printf("routed: out of routes?\n"); ! 191: return; ! 192: } ! 193: if(rp->dst == 0) ! 194: rp->metric = HOPCNT_INFINITY + 1; ! 195: if(gate != rp->gate && rp->age > 1){ ! 196: /* let it age some more to avoid loops */ ! 197: return; ! 198: } ! 199: if(metric < rp->metric ! 200: || (gate == rp->gate && metric != rp->metric) ! 201: || (gate == rp->gate && age != rp->age)){ ! 202: rp->metric = metric; ! 203: rp->age = age; ! 204: if(rp->dst != dst || rp->gate != gate){ ! 205: if(verbose){ ! 206: printf("%s ", in_host(gate)); ! 207: printf("installing as route to %s, metric %d\n", ! 208: in_host(dst), metric); ! 209: fflush(stdout); ! 210: } ! 211: rp->dst = dst; ! 212: rp->gate = gate; ! 213: if(ioctl(ipfd, IPIOROUTE, rp) < 0) ! 214: perror("IPIOROUTE"); ! 215: } else { ! 216: if(verbose > 1){ ! 217: printf("%s ", in_host(gate)); ! 218: printf("confirmed as route to %s, metric %d\n", ! 219: in_host(dst), metric); ! 220: fflush(stdout); ! 221: } ! 222: rp->dst = dst; ! 223: rp->gate = gate; ! 224: } ! 225: } ! 226: } ! 227: ! 228: /* ! 229: * keep a list of routes ! 230: * that belong to us; ! 231: * don't let anyone claim them ! 232: */ ! 233: ! 234: #define NSAFE 20 ! 235: ! 236: u_long safer[NSAFE]; ! 237: int nsafe = 0; ! 238: ! 239: recsafe(s) ! 240: char *s; ! 241: { ! 242: if (nsafe < NSAFE) ! 243: safer[nsafe++] = in_address(s); ! 244: } ! 245: ! 246: saferoute(dst) ! 247: u_long dst; ! 248: { ! 249: register int i; ! 250: ! 251: for (i = 0; i < nsafe; i++) ! 252: if (dst == safer[i]) ! 253: return (1); ! 254: return (0); ! 255: } ! 256: ! 257: readgateways() ! 258: { ! 259: FILE *fp; ! 260: char buf[512]; ! 261: char net[32], gateway[32], which[32]; ! 262: u_long dst, gate; ! 263: int metric; ! 264: ! 265: if((fp = fopen(GATEWAYS, "r")) == 0) ! 266: return; ! 267: while(fgets(buf, sizeof(buf), fp)){ ! 268: if(sscanf(buf, "%s %s gateway %s metric %d", ! 269: which, net, gateway, &metric) != 4) ! 270: continue; ! 271: dst = in_address(net); ! 272: gate = in_address(gateway); ! 273: rtinstall(dst, gate, metric, -1); ! 274: } ! 275: } ! 276: ! 277: ! 278: timer() ! 279: { ! 280: int i,j; ! 281: struct route *rp; ! 282: struct ipif ipif; ! 283: ! 284: signal(SIGALRM, SIG_IGN); ! 285: alarm(0); ! 286: ! 287: for(j=i=0; j<2*NIFS; i++){ ! 288: *(int *)&ipif = i; ! 289: if(ioctl(ipfd, IPIOGETIFS, &ipif) < 0) ! 290: break; ! 291: if(ipif.flags&IFF_UP) { ! 292: ifs[j++] = ipif.that; ! 293: ifs[j++] = ipif.thishost; ! 294: } ! 295: } ! 296: ifs[j]=0; ! 297: for(i = 0; ifs[i]; i+= 2) ! 298: if(ifs[i] != ifs[i+1] && ifs[i] != 0x7f000000) ! 299: rtinstall(in_netof(ifs[i]), in_netof(ifs[i]), 0, 0); ! 300: ! 301: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 302: if(rp->dst == 0) ! 303: continue; ! 304: if(rp->age > 0 && rp->metric < HOPCNT_INFINITY) ! 305: rp->metric = HOPCNT_INFINITY - 1; ! 306: } ! 307: ! 308: broadcast(); ! 309: ! 310: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 311: if(rp->dst == 0) ! 312: continue; ! 313: if(rp->age > 10){ ! 314: rtdelete(rp); ! 315: } else if(rp->age >= 0){ ! 316: rp->age++; ! 317: } ! 318: } ! 319: ! 320: fflush(stdout); ! 321: alarm(60); ! 322: signal(SIGALRM, timer); ! 323: } ! 324: ! 325: broadcast() ! 326: { ! 327: struct route *rp; ! 328: struct rip *rip; ! 329: struct netinfo *np; ! 330: struct sockaddr *sin; ! 331: struct udppacket p; ! 332: ! 333: rip = (struct rip *)p.buf; ! 334: rip->rip_cmd = RIPCMD_RESPONSE; ! 335: rip->rip_vers = RIPVERSION; ! 336: np = rip->rip_nets; ! 337: if(trace) ! 338: printf("BROADCAST:\n"); ! 339: ! 340: /* first send info about directly connected networks */ ! 341: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 342: if(rp->dst == 0 || rp->metric > 0) ! 343: continue; ! 344: bzero(np, sizeof(struct netinfo)); ! 345: sin = &(np->rip_dst); ! 346: np->rip_metric = htonl(rp->metric + 1); ! 347: sin->sin_port = 0; ! 348: sin->sin_addr = htonl(rp->dst); ! 349: sin->sin_family = htons((u_short)AF_INET); ! 350: if(trace) ! 351: printf(" %s %d\n", ! 352: in_ntoa(ntohl(sin->sin_addr)), ntohl(np->rip_metric)); ! 353: np++; ! 354: if (np-rip->rip_nets == MAXROUTESPERPACKET) { ! 355: pbroadcast(&p, (char *)np); ! 356: np = rip->rip_nets; ! 357: } ! 358: } ! 359: ! 360: /* now send info about the rest */ ! 361: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 362: if(rp->dst==0 || rp->metric>=HOPCNT_INFINITY || rp->metric<=0) ! 363: continue; ! 364: bzero(np, sizeof(struct netinfo)); ! 365: sin = &(np->rip_dst); ! 366: np->rip_metric = htonl(rp->metric + 1); ! 367: sin->sin_port = 0; ! 368: sin->sin_addr = htonl(rp->dst); ! 369: sin->sin_family = htons((u_short)AF_INET); ! 370: if(trace) ! 371: printf(" %s %d\n", ! 372: in_ntoa(ntohl(sin->sin_addr)), ntohl(np->rip_metric)); ! 373: np++; ! 374: if (np-rip->rip_nets == MAXROUTESPERPACKET) { ! 375: pbroadcast(&p, (char *)np); ! 376: np = rip->rip_nets; ! 377: } ! 378: } ! 379: if (np > rip->rip_nets) ! 380: pbroadcast(&p, (char *)np); ! 381: } ! 382: ! 383: /* broadcast one routing packet everywhere */ ! 384: pbroadcast(pp, cp) ! 385: struct udppacket *pp; ! 386: char *cp; ! 387: { ! 388: int len=sizeof(struct udpaddr)+cp-(char *)pp; ! 389: int i; ! 390: ! 391: if(quiet) ! 392: return; ! 393: pp->addr.port = 520; ! 394: for(i = 0; ifs[i]; i += 2){ ! 395: if (trace) { ! 396: printf("on ifs[%d]\n", i); ! 397: fflush(stdout); ! 398: } ! 399: if(ifs[i]!=0 && ifs[i]!=ifs[i+1] && ifs[i]!=0x7f000000) { ! 400: pp->addr.host = ifs[i]; ! 401: if (write(udpfd, pp, len) !=len) ! 402: perror("udp write"); ! 403: } ! 404: } ! 405: } ! 406: ! 407: myaddr(x) ! 408: u_long x; ! 409: { ! 410: int i; ! 411: ! 412: for(i = 0; ifs[i]; i += 2) ! 413: if(ifs[i+1] == x) ! 414: return(1); ! 415: return(0); ! 416: } ! 417: ! 418: rtdelete(rp) ! 419: struct route *rp; ! 420: { ! 421: if(verbose) { ! 422: printf("deleting %s %d\n", in_ntoa(rp->dst), rp->metric); ! 423: fflush(stdout); ! 424: } ! 425: if(rp->gate != rp->dst){ ! 426: rp->gate = 0; ! 427: if(ioctl(ipfd, IPIOROUTE, rp) < 0) ! 428: perror("IPIOROUTE"); ! 429: } ! 430: rp->gate = rp->dst = 0; ! 431: rp->age = rp->metric = 0; ! 432: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.