|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)route.c 5.9 (Berkeley) 12/26/87";
15: #endif not lint
16:
17: #include <sys/param.h>
18: #include <sys/socket.h>
19: #include <sys/ioctl.h>
20: #include <sys/mbuf.h>
21:
22: #include <net/route.h>
23: #include <netinet/in.h>
24: #include <netns/ns.h>
25:
26: #include <stdio.h>
27: #include <errno.h>
28: #include <ctype.h>
29: #include <netdb.h>
30:
31: struct rtentry route;
32: int s;
33: int forcehost, forcenet, doflush, nflag;
34: struct sockaddr_in sin = { AF_INET };
35: struct in_addr inet_makeaddr();
36: char *malloc();
37:
38: main(argc, argv)
39: int argc;
40: char *argv[];
41: {
42:
43: if (argc < 2)
44: printf("usage: route [ -n ] [ -f ] [ cmd [ net | host ] args ]\n"),
45: exit(1);
46: s = socket(AF_INET, SOCK_RAW, 0);
47: if (s < 0) {
48: perror("route: socket");
49: exit(1);
50: }
51: argc--, argv++;
52: for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
53: for (argv[0]++; *argv[0]; argv[0]++)
54: switch (*argv[0]) {
55: case 'f':
56: doflush++;
57: break;
58: case 'n':
59: nflag++;
60: break;
61: }
62: }
63: if (doflush)
64: flushroutes();
65: if (argc > 0) {
66: if (strcmp(*argv, "add") == 0)
67: newroute(argc, argv);
68: else if (strcmp(*argv, "delete") == 0)
69: newroute(argc, argv);
70: else if (strcmp(*argv, "change") == 0)
71: changeroute(argc-1, argv+1);
72: else
73: printf("%s: huh?\n", *argv);
74: }
75: }
76:
77: /*
78: * Purge all entries in the routing tables not
79: * associated with network interfaces.
80: */
81: #include <nlist.h>
82:
83: struct nlist nl[] = {
84: #define N_RTHOST 0
85: { "_rthost" },
86: #define N_RTNET 1
87: { "_rtnet" },
88: #define N_RTHASHSIZE 2
89: { "_rthashsize" },
90: "",
91: };
92:
93: flushroutes()
94: {
95: struct mbuf mb;
96: register struct rtentry *rt;
97: register struct mbuf *m;
98: struct mbuf **routehash;
99: int rthashsize, i, doinghost = 1, kmem;
100: char *routename(), *netname();
101:
102: nlist("/vmunix", nl);
103: if (nl[N_RTHOST].n_value == 0) {
104: printf("route: \"rthost\", symbol not in namelist\n");
105: exit(1);
106: }
107: if (nl[N_RTNET].n_value == 0) {
108: printf("route: \"rtnet\", symbol not in namelist\n");
109: exit(1);
110: }
111: if (nl[N_RTHASHSIZE].n_value == 0) {
112: printf("route: \"rthashsize\", symbol not in namelist\n");
113: exit(1);
114: }
115: kmem = open("/dev/kmem", 0);
116: if (kmem < 0) {
117: perror("route: /dev/kmem");
118: exit(1);
119: }
120: lseek(kmem, nl[N_RTHASHSIZE].n_value, 0);
121: read(kmem, &rthashsize, sizeof (rthashsize));
122: routehash = (struct mbuf **)malloc(rthashsize*sizeof (struct mbuf *));
123:
124: lseek(kmem, nl[N_RTHOST].n_value, 0);
125: read(kmem, routehash, rthashsize*sizeof (struct mbuf *));
126: printf("Flushing routing tables:\n");
127: again:
128: for (i = 0; i < rthashsize; i++) {
129: if (routehash[i] == 0)
130: continue;
131: m = routehash[i];
132: while (m) {
133: lseek(kmem, m, 0);
134: read(kmem, &mb, sizeof (mb));
135: rt = mtod(&mb, struct rtentry *);
136: if (rt->rt_flags & RTF_GATEWAY) {
137: printf("%-20.20s ", doinghost ?
138: routename(&rt->rt_dst) :
139: netname(&rt->rt_dst));
140: printf("%-20.20s ", routename(&rt->rt_gateway));
141: if (ioctl(s, SIOCDELRT, (caddr_t)rt) < 0)
142: error("delete");
143: else
144: printf("done\n");
145: }
146: m = mb.m_next;
147: }
148: }
149: if (doinghost) {
150: lseek(kmem, nl[N_RTNET].n_value, 0);
151: read(kmem, routehash, rthashsize*sizeof (struct mbuf *));
152: doinghost = 0;
153: goto again;
154: }
155: close(kmem);
156: free(routehash);
157: }
158:
159: char *
160: routename(sa)
161: struct sockaddr *sa;
162: {
163: register char *cp;
164: static char line[50];
165: struct hostent *hp;
166: static char domain[MAXHOSTNAMELEN + 1];
167: static int first = 1;
168: char *index();
169: char *ns_print();
170:
171: if (first) {
172: first = 0;
173: if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
174: (cp = index(domain, '.')))
175: (void) strcpy(domain, cp + 1);
176: else
177: domain[0] = 0;
178: }
179: switch (sa->sa_family) {
180:
181: case AF_INET:
182: { struct in_addr in;
183: in = ((struct sockaddr_in *)sa)->sin_addr;
184:
185: cp = 0;
186: if (in.s_addr == INADDR_ANY)
187: cp = "default";
188: if (cp == 0 && !nflag) {
189: hp = gethostbyaddr(&in, sizeof (struct in_addr),
190: AF_INET);
191: if (hp) {
192: if ((cp = index(hp->h_name, '.')) &&
193: !strcmp(cp + 1, domain))
194: *cp = 0;
195: cp = hp->h_name;
196: }
197: }
198: if (cp)
199: strcpy(line, cp);
200: else {
201: #define C(x) ((x) & 0xff)
202: in.s_addr = ntohl(in.s_addr);
203: (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
204: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
205: }
206: break;
207: }
208:
209: case AF_NS:
210: return (ns_print((struct sockaddr_ns *)sa));
211:
212: default:
213: { u_short *s = (u_short *)sa->sa_data;
214:
215: (void)sprintf(line, "af %d: %x %x %x %x %x %x %x",
216: sa->sa_family, s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
217: break;
218: }
219: }
220: return (line);
221: }
222:
223: /*
224: * Return the name of the network whose address is given.
225: * The address is assumed to be that of a net or subnet, not a host.
226: */
227: char *
228: netname(sa)
229: struct sockaddr *sa;
230: {
231: char *cp = 0;
232: static char line[50];
233: struct netent *np = 0;
234: u_long net, mask;
235: register u_long i;
236: int subnetshift;
237: char *ns_print();
238:
239: switch (sa->sa_family) {
240:
241: case AF_INET:
242: { struct in_addr in;
243: in = ((struct sockaddr_in *)sa)->sin_addr;
244:
245: i = in.s_addr = ntohl(in.s_addr);
246: if (in.s_addr == 0)
247: cp = "default";
248: else if (!nflag) {
249: if (IN_CLASSA(i)) {
250: mask = IN_CLASSA_NET;
251: subnetshift = 8;
252: } else if (IN_CLASSB(i)) {
253: mask = IN_CLASSB_NET;
254: subnetshift = 8;
255: } else {
256: mask = IN_CLASSC_NET;
257: subnetshift = 4;
258: }
259: /*
260: * If there are more bits than the standard mask
261: * would suggest, subnets must be in use.
262: * Guess at the subnet mask, assuming reasonable
263: * width subnet fields.
264: */
265: while (in.s_addr &~ mask)
266: mask = (long)mask >> subnetshift;
267: net = in.s_addr & mask;
268: while ((mask & 1) == 0)
269: mask >>= 1, net >>= 1;
270: np = getnetbyaddr(net, AF_INET);
271: if (np)
272: cp = np->n_name;
273: }
274: if (cp)
275: strcpy(line, cp);
276: else if ((in.s_addr & 0xffffff) == 0)
277: (void)sprintf(line, "%u", C(in.s_addr >> 24));
278: else if ((in.s_addr & 0xffff) == 0)
279: (void)sprintf(line, "%u.%u", C(in.s_addr >> 24),
280: C(in.s_addr >> 16));
281: else if ((in.s_addr & 0xff) == 0)
282: (void)sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
283: C(in.s_addr >> 16), C(in.s_addr >> 8));
284: else
285: (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
286: C(in.s_addr >> 16), C(in.s_addr >> 8),
287: C(in.s_addr));
288: break;
289: }
290:
291: case AF_NS:
292: return (ns_print((struct sockaddr_ns *)sa));
293: break;
294:
295: default:
296: { u_short *s = (u_short *)sa->sa_data;
297:
298: (void)sprintf(line, "af %d: %x %x %x %x %x %x %x",
299: sa->sa_family, s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
300: break;
301: }
302: }
303: return (line);
304: }
305:
306: newroute(argc, argv)
307: int argc;
308: char *argv[];
309: {
310: struct sockaddr_in *sin;
311: char *cmd, *dest, *gateway;
312: int ishost, metric = 0, ret, attempts, oerrno;
313: struct hostent *hp;
314: extern int errno;
315:
316: cmd = argv[0];
317: if ((strcmp(argv[1], "host")) == 0) {
318: forcehost++;
319: argc--, argv++;
320: } else if ((strcmp(argv[1], "net")) == 0) {
321: forcenet++;
322: argc--, argv++;
323: }
324: if (*cmd == 'a') {
325: if (argc != 4) {
326: printf("usage: %s destination gateway metric\n", cmd);
327: printf("(metric of 0 if gateway is this host)\n");
328: return;
329: }
330: metric = atoi(argv[3]);
331: } else {
332: if (argc < 3) {
333: printf("usage: %s destination gateway\n", cmd);
334: return;
335: }
336: }
337: sin = (struct sockaddr_in *)&route.rt_dst;
338: ishost = getaddr(argv[1], &route.rt_dst, &hp, &dest, forcenet);
339: if (forcehost)
340: ishost = 1;
341: if (forcenet)
342: ishost = 0;
343: sin = (struct sockaddr_in *)&route.rt_gateway;
344: (void) getaddr(argv[2], &route.rt_gateway, &hp, &gateway, 0);
345: route.rt_flags = RTF_UP;
346: if (ishost)
347: route.rt_flags |= RTF_HOST;
348: if (metric > 0)
349: route.rt_flags |= RTF_GATEWAY;
350: for (attempts = 1; ; attempts++) {
351: errno = 0;
352: if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT,
353: (caddr_t)&route)) == 0)
354: break;
355: if (errno != ENETUNREACH && errno != ESRCH)
356: break;
357: if (hp && hp->h_addr_list[1]) {
358: hp->h_addr_list++;
359: bcopy(hp->h_addr_list[0], (caddr_t)&sin->sin_addr,
360: hp->h_length);
361: } else
362: break;
363: }
364: oerrno = errno;
365: printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net",
366: dest, gateway);
367: if (attempts > 1 && ret == 0)
368: printf(" (%s)",
369: inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
370: if (ret == 0)
371: printf("\n");
372: else {
373: printf(": ");
374: fflush(stdout);
375: errno = oerrno;
376: error(0);
377: }
378: }
379:
380: changeroute(argc, argv)
381: int argc;
382: char *argv[];
383: {
384: printf("not supported\n");
385: }
386:
387: error(cmd)
388: char *cmd;
389: {
390: extern int errno;
391:
392: switch(errno) {
393: case ESRCH:
394: fprintf(stderr, "not in table\n");
395: break;
396: case EBUSY:
397: fprintf(stderr, "entry in use\n");
398: break;
399: case ENOBUFS:
400: fprintf(stderr, "routing table overflow\n");
401: break;
402: default:
403: perror(cmd);
404: }
405: }
406:
407: char *
408: savestr(s)
409: char *s;
410: {
411: char *sav;
412:
413: sav = malloc(strlen(s) + 1);
414: if (sav == NULL) {
415: fprintf("route: out of memory\n");
416: exit(1);
417: }
418: strcpy(sav, s);
419: return (sav);
420: }
421:
422: /*
423: * Interpret an argument as a network address of some kind,
424: * returning 1 if a host address, 0 if a network address.
425: */
426: getaddr(s, sin, hpp, name, isnet)
427: char *s;
428: struct sockaddr_in *sin;
429: struct hostent **hpp;
430: char **name;
431: int isnet;
432: {
433: struct hostent *hp;
434: struct netent *np;
435: u_long val;
436:
437: *hpp = 0;
438: if (strcmp(s, "default") == 0) {
439: sin->sin_family = AF_INET;
440: sin->sin_addr = inet_makeaddr(0, INADDR_ANY);
441: *name = "default";
442: return(0);
443: }
444: sin->sin_family = AF_INET;
445: if (isnet == 0) {
446: val = inet_addr(s);
447: if (val != -1) {
448: sin->sin_addr.s_addr = val;
449: *name = s;
450: return(inet_lnaof(sin->sin_addr) != INADDR_ANY);
451: }
452: }
453: val = inet_network(s);
454: if (val != -1) {
455: sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
456: *name = s;
457: return(0);
458: }
459: np = getnetbyname(s);
460: if (np) {
461: sin->sin_family = np->n_addrtype;
462: sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
463: *name = savestr(np->n_name);
464: return(0);
465: }
466: hp = gethostbyname(s);
467: if (hp) {
468: *hpp = hp;
469: sin->sin_family = hp->h_addrtype;
470: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
471: *name = savestr(hp->h_name);
472: return(1);
473: }
474: fprintf(stderr, "%s: bad value\n", s);
475: exit(1);
476: }
477:
478: short ns_nullh[] = {0,0,0};
479: short ns_bh[] = {-1,-1,-1};
480:
481: char *
482: ns_print(sns)
483: struct sockaddr_ns *sns;
484: {
485: struct ns_addr work;
486: union { union ns_net net_e; u_long long_e; } net;
487: u_short port;
488: static char mybuf[50], cport[10], chost[25];
489: char *host = "";
490: register char *p; register u_char *q; u_char *q_lim;
491:
492: work = sns->sns_addr;
493: port = ntohs(work.x_port);
494: work.x_port = 0;
495: net.net_e = work.x_net;
496: if (ns_nullhost(work) && net.long_e == 0) {
497: if (port ) {
498: (void)sprintf(mybuf, "*.%xH", port);
499: upHex(mybuf);
500: } else
501: (void)sprintf(mybuf, "*.*");
502: return (mybuf);
503: }
504:
505: if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
506: host = "any";
507: } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
508: host = "*";
509: } else {
510: q = work.x_host.c_host;
511: (void)sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
512: q[0], q[1], q[2], q[3], q[4], q[5]);
513: for (p = chost; *p == '0' && p < chost + 12; p++);
514: host = p;
515: }
516: if (port)
517: (void)sprintf(cport, ".%xH", htons(port));
518: else
519: *cport = 0;
520:
521: (void)sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
522: upHex(mybuf);
523: return(mybuf);
524: }
525:
526: upHex(p0)
527: char *p0;
528: {
529: register char *p = p0;
530: for (; *p; p++) switch (*p) {
531:
532: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
533: *p += ('A' - 'a');
534: }
535: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.