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