|
|
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.6 (Berkeley) 6/5/86";
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: 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: sprintf(line, "af %d: %x %x %x %x %x %x %x", sa->sa_family,
216: 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 i;
236: int subnetshift;
237:
238: switch (sa->sa_family) {
239:
240: case AF_INET:
241: { struct in_addr in;
242: in = ((struct sockaddr_in *)sa)->sin_addr;
243:
244: in.s_addr = ntohl(in.s_addr);
245: if (in.s_addr == 0)
246: cp = "default";
247: else if (!nflag) {
248: if (IN_CLASSA(i)) {
249: mask = IN_CLASSA_NET;
250: subnetshift = 8;
251: } else if (IN_CLASSB(i)) {
252: mask = IN_CLASSB_NET;
253: subnetshift = 8;
254: } else {
255: mask = IN_CLASSC_NET;
256: subnetshift = 4;
257: }
258: /*
259: * If there are more bits than the standard mask
260: * would suggest, subnets must be in use.
261: * Guess at the subnet mask, assuming reasonable
262: * width subnet fields.
263: */
264: while (in.s_addr &~ mask)
265: mask = (long)mask >> subnetshift;
266: net = in.s_addr & mask;
267: while ((mask & 1) == 0)
268: mask >>= 1, net >>= 1;
269: np = getnetbyaddr(net, AF_INET);
270: if (np)
271: cp = np->n_name;
272: }
273: if (cp)
274: strcpy(line, cp);
275: else if ((in.s_addr & 0xffffff) == 0)
276: sprintf(line, "%u", C(in.s_addr >> 24));
277: else if ((in.s_addr & 0xffff) == 0)
278: sprintf(line, "%u.%u", C(in.s_addr >> 24),
279: C(in.s_addr >> 16));
280: else if ((in.s_addr & 0xff) == 0)
281: sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
282: C(in.s_addr >> 16), C(in.s_addr >> 8));
283: else
284: sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
285: C(in.s_addr >> 16), C(in.s_addr >> 8),
286: C(in.s_addr));
287: break;
288: }
289:
290: case AF_NS:
291: return (ns_print((struct sockaddr_ns *)sa));
292: break;
293:
294: default:
295: { u_short *s = (u_short *)sa->sa_data;
296:
297: sprintf(line, "af %d: %x %x %x %x %x %x %x", sa->sa_family,
298: s[0], s[1], s[2], s[3], s[4], s[5], s[6]);
299: break;
300: }
301: }
302: return (line);
303: }
304:
305: newroute(argc, argv)
306: int argc;
307: char *argv[];
308: {
309: struct sockaddr_in *sin;
310: char *cmd, *dest, *gateway;
311: int ishost, metric = 0, ret, attempts, oerrno;
312: struct hostent *hp;
313: extern int errno;
314:
315: cmd = argv[0];
316: if ((strcmp(argv[1], "host")) == 0) {
317: forcehost++;
318: argc--, argv++;
319: } else if ((strcmp(argv[1], "net")) == 0) {
320: forcenet++;
321: argc--, argv++;
322: }
323: if (*cmd == 'a') {
324: if (argc != 4) {
325: printf("usage: %s destination gateway metric\n", cmd);
326: printf("(metric of 0 if gateway is this host)\n");
327: return;
328: }
329: metric = atoi(argv[3]);
330: } else {
331: if (argc < 3) {
332: printf("usage: %s destination gateway\n", cmd);
333: return;
334: }
335: }
336: sin = (struct sockaddr_in *)&route.rt_dst;
337: ishost = getaddr(argv[1], &route.rt_dst, &hp, &dest, forcenet);
338: if (forcehost)
339: ishost = 1;
340: if (forcenet)
341: ishost = 0;
342: sin = (struct sockaddr_in *)&route.rt_gateway;
343: (void) getaddr(argv[2], &route.rt_gateway, &hp, &gateway, 0);
344: route.rt_flags = RTF_UP;
345: if (ishost)
346: route.rt_flags |= RTF_HOST;
347: if (metric > 0)
348: route.rt_flags |= RTF_GATEWAY;
349: for (attempts = 1; ; attempts++) {
350: errno = 0;
351: if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT,
352: (caddr_t)&route)) == 0)
353: break;
354: if (errno != ENETUNREACH && errno != ESRCH)
355: break;
356: if (hp && hp->h_addr_list[1]) {
357: hp->h_addr_list++;
358: bcopy(hp->h_addr_list[0], (caddr_t)&sin->sin_addr,
359: hp->h_length);
360: } else
361: break;
362: }
363: oerrno = errno;
364: printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net",
365: dest, gateway);
366: if (attempts > 1 && ret == 0)
367: printf(" (%s)",
368: inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
369: if (ret == 0)
370: printf("\n");
371: else {
372: printf(": ");
373: fflush(stdout);
374: errno = oerrno;
375: error(0);
376: }
377: }
378:
379: changeroute(argc, argv)
380: int argc;
381: char *argv[];
382: {
383: printf("not supported\n");
384: }
385:
386: error(cmd)
387: char *cmd;
388: {
389:
390: if (errno == ESRCH)
391: fprintf(stderr, "not in table\n");
392: else if (errno == EBUSY)
393: fprintf(stderr, "entry in use\n");
394: else if (errno == ENOBUFS)
395: fprintf(stderr, "routing table overflow\n");
396: else
397: perror(cmd);
398: }
399:
400: char *
401: savestr(s)
402: char *s;
403: {
404: char *sav;
405:
406: sav = malloc(strlen(s) + 1);
407: if (sav == NULL) {
408: fprintf("route: out of memory\n");
409: exit(1);
410: }
411: strcpy(sav, s);
412: return (sav);
413: }
414:
415: /*
416: * Interpret an argument as a network address of some kind,
417: * returning 1 if a host address, 0 if a network address.
418: */
419: getaddr(s, sin, hpp, name, isnet)
420: char *s;
421: struct sockaddr_in *sin;
422: struct hostent **hpp;
423: char **name;
424: int isnet;
425: {
426: struct hostent *hp;
427: struct netent *np;
428: u_long val;
429:
430: *hpp = 0;
431: if (strcmp(s, "default") == 0) {
432: sin->sin_family = AF_INET;
433: sin->sin_addr = inet_makeaddr(0, INADDR_ANY);
434: *name = "default";
435: return(0);
436: }
437: sin->sin_family = AF_INET;
438: if (isnet == 0) {
439: val = inet_addr(s);
440: if (val != -1) {
441: sin->sin_addr.s_addr = val;
442: *name = s;
443: return(inet_lnaof(sin->sin_addr) != INADDR_ANY);
444: }
445: }
446: val = inet_network(s);
447: if (val != -1) {
448: sin->sin_addr = inet_makeaddr(val, INADDR_ANY);
449: *name = s;
450: return(0);
451: }
452: np = getnetbyname(s);
453: if (np) {
454: sin->sin_family = np->n_addrtype;
455: sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
456: *name = savestr(np->n_name);
457: return(0);
458: }
459: hp = gethostbyname(s);
460: if (hp) {
461: *hpp = hp;
462: sin->sin_family = hp->h_addrtype;
463: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
464: *name = savestr(hp->h_name);
465: return(1);
466: }
467: fprintf(stderr, "%s: bad value\n", s);
468: exit(1);
469: }
470:
471: short ns_nullh[] = {0,0,0};
472: short ns_bh[] = {-1,-1,-1};
473:
474: char *
475: ns_print(sns)
476: struct sockaddr_ns *sns;
477: {
478: struct ns_addr work;
479: union { union ns_net net_e; u_long long_e; } net;
480: u_short port;
481: static char mybuf[50], cport[10], chost[25];
482: char *host = "";
483: register char *p; register u_char *q; u_char *q_lim;
484:
485: work = sns->sns_addr;
486: port = ntohs(work.x_port);
487: work.x_port = 0;
488: net.net_e = work.x_net;
489: if (ns_nullhost(work) && net.long_e == 0) {
490: if (port ) {
491: sprintf(mybuf, "*.%xH", port);
492: upHex(mybuf);
493: } else
494: sprintf(mybuf, "*.*");
495: return (mybuf);
496: }
497:
498: if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
499: host = "any";
500: } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
501: host = "*";
502: } else {
503: q = work.x_host.c_host;
504: sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
505: q[0], q[1], q[2], q[3], q[4], q[5]);
506: for (p = chost; *p == '0' && p < chost + 12; p++);
507: host = p;
508: }
509: if (port)
510: sprintf(cport, ".%xH", htons(port));
511: else
512: *cport = 0;
513:
514: sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
515: upHex(mybuf);
516: return(mybuf);
517: }
518:
519: upHex(p0)
520: char *p0;
521: {
522: register char *p = p0;
523: for (; *p; p++) switch (*p) {
524:
525: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
526: *p += ('A' - 'a');
527: }
528: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.