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