|
|
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.