X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/5a635333bcf52b34ca957d32af634071212b2e70..ddc4703926b3eabf3ee6344bfecf07453e24209d:/usr/src/sbin/route/route.c diff --git a/usr/src/sbin/route/route.c b/usr/src/sbin/route/route.c index 32e4453857..c00c6f1b83 100644 --- a/usr/src/sbin/route/route.c +++ b/usr/src/sbin/route/route.c @@ -1,11 +1,13 @@ #ifndef lint -static char sccsid[] = "@(#)route.c 4.5 82/11/15"; +static char sccsid[] = "@(#)route.c 4.9 (Berkeley) 84/05/11"; #endif #include #include #include +#include +#define KERNEL #include #include @@ -18,6 +20,7 @@ struct rtentry route; int options; int s; struct sockaddr_in sin = { AF_INET }; +struct in_addr inet_makeaddr(); main(argc, argv) int argc; @@ -25,21 +28,144 @@ main(argc, argv) { if (argc < 2) - printf("usage: route [ cmd ] [ args ]\n"), exit(1); + printf("usage: route [ -f ] [ cmd args ]\n"), exit(1); s = socket(AF_INET, SOCK_RAW, 0, 0); if (s < 0) { perror("route: socket"); exit(1); } argc--, argv++; - if (strcmp(*argv, "add") == 0) - newroute(argc, argv); - else if (strcmp(*argv, "delete") == 0) - newroute(argc, argv); - else if (strcmp(*argv, "change") == 0) - changeroute(argc-1, argv+1); - else - printf("%s: huh?\n", *argv); + if (strcmp(*argv, "-f") == 0) { + argc--, argv++; + flushroutes(); + } + if (argc > 0) { + if (strcmp(*argv, "add") == 0) + newroute(argc, argv); + else if (strcmp(*argv, "delete") == 0) + newroute(argc, argv); + else if (strcmp(*argv, "change") == 0) + changeroute(argc-1, argv+1); + else + printf("%s: huh?\n", *argv); + } +} + +/* + * Purge all entries in the routing tables not + * associated with network interfaces. + */ +#include + +struct nlist nl[] = { +#define N_RTHOST 0 + { "_rthost" }, +#define N_RTNET 1 + { "_rtnet" }, + "", +}; + +flushroutes() +{ + struct mbuf mb; + register struct rtentry *rt; + register struct mbuf *m; + struct mbuf *routehash[RTHASHSIZ]; + int i, doinghost = 1, kmem; + char *routename(); + + nlist("/vmunix", nl); + if (nl[N_RTHOST].n_value == 0) { + printf("route: \"rthost\", symbol not in namelist\n"); + exit(1); + } + if (nl[N_RTNET].n_value == 0) { + printf("route: \"rtnet\", symbol not in namelist\n"); + exit(1); + } + kmem = open("/dev/kmem", 0); + if (kmem < 0) { + perror("route: /dev/kmem"); + exit(1); + } + lseek(kmem, nl[N_RTHOST].n_value, 0); + read(kmem, routehash, sizeof (routehash)); + printf("Flushing routing tables:\n"); +again: + for (i = 0; i < RTHASHSIZ; i++) { + if (routehash[i] == 0) + continue; + m = routehash[i]; + while (m) { + lseek(kmem, m, 0); + read(kmem, &mb, sizeof (mb)); + rt = mtod(&mb, struct rtentry *); + if (rt->rt_flags & RTF_GATEWAY) { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)&rt->rt_dst; + printf("%-15.15s ", routename(sin->sin_addr)); + sin = (struct sockaddr_in *)&rt->rt_gateway; + printf("%-15.15s ", routename(sin->sin_addr)); + if (ioctl(s, SIOCDELRT, (caddr_t)rt) < 0) + error("delete"); + else + printf("done\n"); + } + m = mb.m_next; + } + } + if (doinghost) { + lseek(kmem, nl[N_RTNET].n_value, 0); + read(kmem, routehash, sizeof (routehash)); + doinghost = 0; + goto again; + } + close(kmem); +} + +char * +routename(in) + struct in_addr in; +{ + char *cp = 0; + static char line[50]; + struct hostent *hp; + struct netent *np; + int lna, net, subnet; + + net = inet_netof(in); + subnet = inet_subnetof(in); + lna = inet_lnaof(in); + if (lna == INADDR_ANY) { + np = getnetbyaddr(net, AF_INET); + if (np) + cp = np->n_name; + else if (net == 0) + cp = "default"; + } else if ((subnet != net) && ((lna & 0xff) == 0) && + (np = getnetbyaddr(subnet, AF_INET))) { + struct in_addr subnaddr, inet_makeaddr(); + + subnaddr = inet_makeaddr(subnet, INADDR_ANY); + if (bcmp(&in, &subnaddr, sizeof(in)) == 0) + cp = np->n_name; + } else { + hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET); + if (hp) + cp = hp->h_name; + } + if (cp) + strcpy(line, cp); + else { + u_char *ucp = (u_char *)∈ + if (lna == INADDR_ANY) + sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]); + else + sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1], + ucp[2], ucp[3]); + } + return (line); } newroute(argc, argv) @@ -48,23 +174,32 @@ newroute(argc, argv) { struct sockaddr_in *sin; char *cmd; + int ishost; - if (argc < 3 || argc > 4) { - printf("usage: %s destination gateway [ metric ]\n", argv[0]); - return; - } cmd = argv[0]; - getaddr(argv[1], &route.rt_dst); - getaddr(argv[2], &route.rt_gateway); + if (*cmd == 'a') { + if (argc != 4) { + printf("usage: %s destination gateway metric\n", cmd); + printf("(metric of 0 if gateway is this host)\n"); + return; + } + } else { + if (argc != 3) { + printf("usage: %s destination gateway\n", cmd); + return; + } + } + ishost = getaddr(argv[1], &route.rt_dst); + (void) getaddr(argv[2], &route.rt_gateway); sin = (struct sockaddr_in *)&route.rt_dst; route.rt_flags = RTF_UP; - if (inet_lnaof(sin->sin_addr) != 0) + if (ishost) route.rt_flags |= RTF_HOST; - if (argc > 3 && atoi(argv[3]) > 0) + if (atoi(argv[3]) > 0) route.rt_flags |= RTF_GATEWAY; - printf("%s %x: gateway %x, flags %x\n", cmd, sin->sin_addr, - ((struct sockaddr_in *)&route.rt_gateway)->sin_addr, - route.rt_flags); + printf("%s %s: gateway ", cmd, routename(sin->sin_addr)); + sin = (struct sockaddr_in *)&route.rt_gateway; + printf("%s, flags %x\n", routename(sin->sin_addr), route.rt_flags); if (ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, (caddr_t)&route)) error(cmd); } @@ -91,22 +226,74 @@ error(cmd) perror(cmd); } +/* + * Interpret an argument as a network address of some kind, + * returning 1 if a host address, 0 if a network address. + */ getaddr(s, sin) char *s; struct sockaddr_in *sin; { struct hostent *hp; + struct netent *np; + u_long val; - hp = gethostbyname(s); - if (hp == 0) { - sin->sin_addr.s_addr = inet_addr(s); - if (sin->sin_addr.s_addr == -1) { - fprintf(stderr, "%s: bad value\n", s); - exit(1); - } + if (strcmp(s, "default") == 0) { sin->sin_family = AF_INET; - return; + sin->sin_addr = inet_makeaddr(0, INADDR_ANY); + return(0); + } + hp = gethostbyname(s); + if (hp) { + sin->sin_family = hp->h_addrtype; + bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); + return(1); + } + np = getnetbyname(s); + if (np) { + sin->sin_family = np->n_addrtype; + sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); + return(0); + } + sin->sin_family = AF_INET; + val = inet_addr(s); + if (val != -1) { + sin->sin_addr.s_addr = val; + return(inet_lnaof(sin->sin_addr) != INADDR_ANY); } - sin->sin_family = hp->h_addrtype; - bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); + val = inet_network(s); + if (val != -1) { + sin->sin_addr = inet_makeaddr(val, INADDR_ANY); + return(0); + } + fprintf(stderr, "%s: bad value\n", s); + exit(1); +} + +/* + * Return the possible subnetwork number from an internet address. + * If the address is of the form of a subnet address (most significant + * bit of the host part is set), believe the subnet exists. + * Otherwise, return the network number. + * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING + * INSIDE OF THE HOST PART. We can only believe this if we have other + * information (e.g., we can find a name for this number). + */ +inet_subnetof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) { + if (IN_SUBNETA(i)) + return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT); + else + return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + } else if (IN_CLASSB(i)) { + if (IN_SUBNETB(i)) + return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT); + else + return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + } else + return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); }