|
|
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/udp_user.h> ! 8: #include "config.h" ! 9: ! 10: #define IPDEVICE "/dev/ip16" /* device for getting ip info from */ ! 11: ! 12: int udpfd, ipfd, verbose, trace, quiet; ! 13: struct in_service *servp; ! 14: extern errno; ! 15: extern char *in_ntoa(); ! 16: extern u_short cksum(); ! 17: ! 18: struct udppacket { ! 19: struct udpaddr addr; ! 20: char buf[4096]; ! 21: }; ! 22: ! 23: main(argc, argv) ! 24: char *argv[]; ! 25: { ! 26: int n, i; ! 27: struct udppacket packet; ! 28: ! 29: for(i = 1; i < argc; i++){ ! 30: if(strcmp(argv[i], "-v") == 0) ! 31: verbose++; ! 32: else if(strcmp(argv[i], "-q") == 0) ! 33: quiet++; ! 34: else if(strcmp(argv[i], "-t") == 0) ! 35: trace++; ! 36: } ! 37: ! 38: servp = in_service("route", "udp", 0); ! 39: if (servp == NULL) { ! 40: printf("route service not in table\n"); ! 41: exit(1); ! 42: } ! 43: if ((udpfd = udp_datagram(servp->port)) < 0) { ! 44: printf("udp route daemon: no connection\n"); ! 45: exit(1); ! 46: } ! 47: if ((ipfd = open(IPDEVICE, 2)) < 0) { ! 48: perror(IPDEVICE); ! 49: exit(1); ! 50: } ! 51: ! 52: readgateways(); ! 53: timer(); ! 54: ! 55: again: ! 56: while((n = read(udpfd, &packet, sizeof(struct udppacket))) > 0) { ! 57: if(packet.addr.port == servp->port) ! 58: routed(&packet, n - sizeof(struct udpaddr)); ! 59: else ! 60: fprintf(stderr, "routed: %s %s masquerading as routed\n", ! 61: in_host(packet.addr.host), packet.addr.port); ! 62: } ! 63: if(n < 0 && errno == EINTR) ! 64: goto again; ! 65: } ! 66: ! 67: ! 68: /* protocol.h 4.10 83/08/11 */ ! 69: /* ! 70: * Routing Information Protocol ! 71: * ! 72: * Derived from Xerox NS Routing Information Protocol ! 73: * by changing 32-bit net numbers to sockaddr's and ! 74: * padding stuff to 32-bit boundaries. ! 75: */ ! 76: #define RIPVERSION 1 ! 77: #define AF_INET 2 ! 78: ! 79: struct sockaddr{ ! 80: short sin_family; ! 81: u_short sin_port; ! 82: u_long sin_addr; ! 83: char sin_zero[8]; ! 84: }; ! 85: struct netinfo { ! 86: struct sockaddr rip_dst; /* destination net/host */ ! 87: int rip_metric; /* cost of route */ ! 88: }; ! 89: ! 90: struct rip { ! 91: u_char rip_cmd; /* request/response */ ! 92: u_char rip_vers; /* protocol version # */ ! 93: u_char rip_res1[2]; /* pad to 32-bit boundary */ ! 94: union { ! 95: struct netinfo ru_nets[1]; /* variable length... */ ! 96: char ru_tracefile[1]; /* ditto ... */ ! 97: } ripun; ! 98: #define rip_nets ripun.ru_nets ! 99: #define rip_tracefile ripun.ru_tracefile ! 100: }; ! 101: ! 102: /* ! 103: * Packet types. ! 104: */ ! 105: #define RIPCMD_REQUEST 1 /* want info */ ! 106: #define RIPCMD_RESPONSE 2 /* responding to request */ ! 107: #define RIPCMD_TRACEON 3 /* turn tracing on */ ! 108: #define RIPCMD_TRACEOFF 4 /* turn it off */ ! 109: ! 110: #define RIPCMD_MAX 5 ! 111: #ifdef RIPCMDS ! 112: char *ripcmds[RIPCMD_MAX] = ! 113: { "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" }; ! 114: #endif ! 115: ! 116: #define HOPCNT_INFINITY 16 /* per Xerox NS */ ! 117: #define MAXPACKETSIZE 512 /* max broadcast size */ ! 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: u_long ifs[50]; /* interface network/address pairs */ ! 134: ! 135: routed(up, len) ! 136: struct udppacket *up; ! 137: u_int len; ! 138: { ! 139: struct rip *rip; ! 140: struct sockaddr *sin; ! 141: struct netinfo *np; ! 142: ! 143: rip = (struct rip *)(up->buf); ! 144: if(rip->rip_cmd != RIPCMD_RESPONSE || rip->rip_vers != RIPVERSION) ! 145: return; ! 146: if(myaddr(up->addr.host)) ! 147: return; ! 148: np = rip->rip_nets; ! 149: if(trace) ! 150: printf("%s\n", in_ntoa(up->addr.host)); ! 151: while(np < (struct netinfo *)(&(up->buf[len]))){ ! 152: sin = &(np->rip_dst); ! 153: np->rip_metric = ntohl(np->rip_metric); ! 154: sin->sin_port = ntohs(sin->sin_port); ! 155: sin->sin_addr = ntohl(sin->sin_addr); ! 156: if(trace) { ! 157: printf(" %s %d\n", in_ntoa(sin->sin_addr), np->rip_metric); ! 158: fflush(stdout); ! 159: } ! 160: rtinstall(sin->sin_addr, up->addr.host, np->rip_metric, 0); ! 161: np++; ! 162: } ! 163: } ! 164: ! 165: struct route{ ! 166: u_long dst; ! 167: u_long gate; ! 168: int metric; ! 169: int age; ! 170: }; ! 171: #define NROUTES 50 ! 172: struct route routes[NROUTES]; ! 173: ! 174: rtinstall(dst, gate, metric, age) ! 175: u_long dst, gate; ! 176: { ! 177: struct route *rp, *save = 0; ! 178: ! 179: if(metric >= HOPCNT_INFINITY) ! 180: return; ! 181: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 182: if(rp->dst == dst) ! 183: break; ! 184: if(rp->dst == 0 && save == 0) ! 185: save = rp; ! 186: } ! 187: if(rp >= &routes[NROUTES] && (rp = save) == 0){ ! 188: printf("routed: out of routes?\n"); ! 189: return; ! 190: } ! 191: if(rp->dst == 0) ! 192: rp->metric = HOPCNT_INFINITY + 1; ! 193: if(gate != rp->gate && rp->age > 1){ ! 194: /* let it age some more to avoid loops */ ! 195: return; ! 196: } ! 197: if(metric < rp->metric ! 198: || (gate == rp->gate && metric != rp->metric) ! 199: || (gate == rp->gate && age != rp->age)){ ! 200: rp->metric = metric; ! 201: rp->age = age; ! 202: if(dst != gate ! 203: && (rp->dst != dst || rp->gate != gate)){ ! 204: if(verbose){ ! 205: printf("%s ", in_host(gate)); ! 206: printf("installing as route to %s, metric %d\n", ! 207: in_host(dst), metric); ! 208: fflush(stdout); ! 209: } ! 210: rp->dst = dst; ! 211: rp->gate = gate; ! 212: if(ioctl(ipfd, IPIOROUTE, rp) < 0) ! 213: perror("IPIOROUTE"); ! 214: } else { ! 215: if(verbose > 1){ ! 216: printf("%s ", in_host(gate)); ! 217: printf("confirmed as route to %s, metric %d\n", ! 218: in_host(dst), metric); ! 219: fflush(stdout); ! 220: } ! 221: rp->dst = dst; ! 222: rp->gate = gate; ! 223: } ! 224: } ! 225: } ! 226: ! 227: readgateways() ! 228: { ! 229: FILE *fp; ! 230: char buf[512]; ! 231: char net[32], gateway[32], which[32]; ! 232: u_long dst, gate; ! 233: int metric; ! 234: ! 235: if((fp = fopen(GATEWAYS, "r")) == 0) ! 236: return; ! 237: while(fgets(buf, sizeof(buf), fp)){ ! 238: if(sscanf(buf, "%s %s gateway %s metric %d", ! 239: which, net, gateway, &metric) != 4) ! 240: continue; ! 241: dst = in_address(net); ! 242: gate = in_address(gateway); ! 243: rtinstall(dst, gate, metric, -1); ! 244: } ! 245: } ! 246: ! 247: ! 248: timer() ! 249: { ! 250: int i; ! 251: struct route *rp; ! 252: ! 253: signal(SIGALRM, SIG_IGN); ! 254: alarm(0); ! 255: ! 256: ! 257: ifs[0] = 0; ! 258: if(ioctl(ipfd, IPIOGETIFS, ifs) < 0){ ! 259: perror("IPIOGETIFS"); ! 260: exit(1); ! 261: } ! 262: for(i = 0; ifs[i]; i+= 2) ! 263: if(ifs[i] != ifs[i+1] && ifs[i] != 0x7f000000) ! 264: rtinstall(ifs[i], ifs[i], 0, 0); ! 265: ! 266: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 267: if(rp->dst == 0) ! 268: continue; ! 269: if(rp->age > 0 && rp->metric < HOPCNT_INFINITY) ! 270: rp->metric = HOPCNT_INFINITY - 1; ! 271: } ! 272: ! 273: broadcast(); ! 274: ! 275: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 276: if(rp->dst == 0) ! 277: continue; ! 278: if(rp->age > 10){ ! 279: rtdelete(rp); ! 280: } else if(rp->age >= 0){ ! 281: rp->age++; ! 282: } ! 283: } ! 284: ! 285: fflush(stdout); ! 286: alarm(60); ! 287: signal(SIGALRM, timer); ! 288: } ! 289: ! 290: broadcast() ! 291: { ! 292: int i; ! 293: struct route *rp; ! 294: u_char buf[2000]; ! 295: struct rip *rip; ! 296: struct netinfo *np; ! 297: struct sockaddr *sin; ! 298: ! 299: rip = (struct rip *)buf; ! 300: rip->rip_cmd = RIPCMD_RESPONSE; ! 301: rip->rip_vers = RIPVERSION; ! 302: np = rip->rip_nets; ! 303: if(trace) ! 304: printf("BROADCAST:\n"); ! 305: for(rp = routes; rp < &routes[NROUTES]; rp++){ ! 306: if(rp->dst == 0 || rp->metric >= HOPCNT_INFINITY) ! 307: continue; ! 308: bzero(np, sizeof(struct netinfo)); ! 309: sin = &(np->rip_dst); ! 310: np->rip_metric = htonl(rp->metric + 1); ! 311: sin->sin_port = 0; ! 312: sin->sin_addr = htonl(rp->dst); ! 313: sin->sin_family = htons((u_short)AF_INET); ! 314: if(trace) ! 315: printf(" %s %d\n", ! 316: in_ntoa(ntohl(sin->sin_addr)), ntohl(np->rip_metric)); ! 317: np++; ! 318: } ! 319: if(quiet) ! 320: return; ! 321: for(i = 0; ifs[i]; i += 2){ ! 322: if (trace) { ! 323: printf("on ifs[%d]\n", i); ! 324: fflush(stdout); ! 325: } ! 326: if(ifs[i] != ifs[i+1] && ifs[i] != 0x7f000000) ! 327: udp_output(rip, (u_char *)np - (u_char *)rip, ! 328: ifs[i+1], 520, ifs[i], 520); ! 329: } ! 330: } ! 331: ! 332: udp_output(buf, len, src, sport, dst, dport) ! 333: u_char *buf; ! 334: u_long src, dst; ! 335: { ! 336: struct udppacket packet; ! 337: ! 338: if (dst == 0) ! 339: return; ! 340: bcopy(buf, packet.buf, len); ! 341: packet.addr.host = dst; ! 342: packet.addr.port = dport; ! 343: if (write(udpfd, &packet, sizeof(struct udpaddr) + len) < 0) ! 344: perror("udp write"); ! 345: } ! 346: ! 347: myaddr(x) ! 348: u_long x; ! 349: { ! 350: int i; ! 351: ! 352: for(i = 0; ifs[i]; i += 2) ! 353: if(ifs[i+1] == x) ! 354: return(1); ! 355: return(0); ! 356: } ! 357: ! 358: rtdelete(rp) ! 359: struct route *rp; ! 360: { ! 361: if(verbose) { ! 362: printf("deleting %s %d\n", in_ntoa(rp->dst), rp->metric); ! 363: fflush(stdout); ! 364: } ! 365: if(rp->gate != rp->dst){ ! 366: rp->gate = 0; ! 367: if(ioctl(ipfd, IPIOROUTE, rp) < 0) ! 368: perror("IPIOROUTE"); ! 369: } ! 370: rp->gate = rp->dst = 0; ! 371: rp->age = rp->metric = 0; ! 372: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.