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.1 (Berkeley) 06/04/85"; 15 #endif not lint 16 17 #include <sys/types.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 25 #include <stdio.h> 26 #include <errno.h> 27 #include <ctype.h> 28 #include <netdb.h> 29 30 struct rtentry route; 31 int s; 32 int forcehost, forcenet; 33 struct sockaddr_in sin = { AF_INET }; 34 struct in_addr inet_makeaddr(); 35 36 main(argc, argv) 37 int argc; 38 char *argv[]; 39 { 40 41 if (argc < 2) 42 printf("usage: route [ -f ] [ [ -h ] [ -n ] cmd args ]\n"), 43 exit(1); 44 s = socket(AF_INET, SOCK_RAW, 0); 45 if (s < 0) { 46 perror("route: socket"); 47 exit(1); 48 } 49 argc--, argv++; 50 for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { 51 for (argv[0]++; *argv[0]; argv[0]++) 52 switch (*argv[0]) { 53 case 'f': 54 flushroutes(); 55 break; 56 case 'h': 57 forcehost++; 58 break; 59 case 'n': 60 forcenet++; 61 break; 62 } 63 } 64 if (forcehost && forcenet) { 65 fprintf(stderr, "-n and -h are incompatible\n"); 66 exit(1); 67 } 68 if (argc > 0) { 69 if (strcmp(*argv, "add") == 0) 70 newroute(argc, argv); 71 else if (strcmp(*argv, "delete") == 0) 72 newroute(argc, argv); 73 else if (strcmp(*argv, "change") == 0) 74 changeroute(argc-1, argv+1); 75 else 76 printf("%s: huh?\n", *argv); 77 } 78 } 79 80 /* 81 * Purge all entries in the routing tables not 82 * associated with network interfaces. 83 */ 84 #include <nlist.h> 85 86 struct nlist nl[] = { 87 #define N_RTHOST 0 88 { "_rthost" }, 89 #define N_RTNET 1 90 { "_rtnet" }, 91 #define N_RTHASHSIZE 2 92 { "_rthashsize" }, 93 "", 94 }; 95 96 flushroutes() 97 { 98 struct mbuf mb; 99 register struct rtentry *rt; 100 register struct mbuf *m; 101 struct mbuf **routehash; 102 int rthashsize, i, doinghost = 1, kmem; 103 char *routename(); 104 105 nlist("/vmunix", nl); 106 if (nl[N_RTHOST].n_value == 0) { 107 printf("route: \"rthost\", symbol not in namelist\n"); 108 exit(1); 109 } 110 if (nl[N_RTNET].n_value == 0) { 111 printf("route: \"rtnet\", symbol not in namelist\n"); 112 exit(1); 113 } 114 if (nl[N_RTHASHSIZE].n_value == 0) { 115 printf("route: \"rthashsize\", symbol not in namelist\n"); 116 exit(1); 117 } 118 kmem = open("/dev/kmem", 0); 119 if (kmem < 0) { 120 perror("route: /dev/kmem"); 121 exit(1); 122 } 123 lseek(kmem, nl[N_RTHASHSIZE].n_value, 0); 124 read(kmem, &rthashsize, sizeof (rthashsize)); 125 routehash = (struct mbuf **)malloc(rthashsize*sizeof (struct mbuf *)); 126 127 lseek(kmem, nl[N_RTHOST].n_value, 0); 128 read(kmem, routehash, rthashsize*sizeof (struct mbuf *)); 129 printf("Flushing routing tables:\n"); 130 again: 131 for (i = 0; i < rthashsize; i++) { 132 if (routehash[i] == 0) 133 continue; 134 m = routehash[i]; 135 while (m) { 136 lseek(kmem, m, 0); 137 read(kmem, &mb, sizeof (mb)); 138 rt = mtod(&mb, struct rtentry *); 139 if (rt->rt_flags & RTF_GATEWAY) { 140 struct sockaddr_in *sin; 141 142 sin = (struct sockaddr_in *)&rt->rt_dst; 143 printf("%-15.15s ", routename(sin->sin_addr)); 144 sin = (struct sockaddr_in *)&rt->rt_gateway; 145 printf("%-15.15s ", routename(sin->sin_addr)); 146 if (ioctl(s, SIOCDELRT, (caddr_t)rt) < 0) 147 error("delete"); 148 else 149 printf("done\n"); 150 } 151 m = mb.m_next; 152 } 153 } 154 if (doinghost) { 155 lseek(kmem, nl[N_RTNET].n_value, 0); 156 read(kmem, routehash, rthashsize*sizeof (struct mbuf *)); 157 doinghost = 0; 158 goto again; 159 } 160 close(kmem); 161 free(routehash); 162 } 163 164 char * 165 routename(in) 166 struct in_addr in; 167 { 168 char *cp = 0; 169 static char line[50]; 170 struct hostent *hp; 171 struct netent *np; 172 int lna, net; 173 174 net = inet_netof(in); 175 lna = inet_lnaof(in); 176 if (in.s_addr == INADDR_ANY) 177 cp = "default"; 178 if (cp == 0 && (lna == INADDR_ANY || forcenet)) { 179 np = getnetbyaddr(net, AF_INET); 180 if (np) 181 cp = np->n_name; 182 } 183 if (cp == 0) { 184 hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET); 185 if (hp) 186 cp = hp->h_name; 187 } 188 if (cp) 189 strcpy(line, cp); 190 else { 191 u_char *ucp = (u_char *)∈ 192 if (lna == INADDR_ANY) 193 sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]); 194 else 195 sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1], 196 ucp[2], ucp[3]); 197 } 198 return (line); 199 } 200 201 newroute(argc, argv) 202 int argc; 203 char *argv[]; 204 { 205 struct sockaddr_in *sin; 206 char *cmd; 207 int ishost, metric = 0; 208 209 cmd = argv[0]; 210 if (*cmd == 'a') { 211 if (argc != 4) { 212 printf("usage: %s destination gateway metric\n", cmd); 213 printf("(metric of 0 if gateway is this host)\n"); 214 return; 215 } 216 metric = atoi(argv[3]); 217 } else { 218 if (argc != 3) { 219 printf("usage: %s destination gateway\n", cmd); 220 return; 221 } 222 } 223 ishost = getaddr(argv[1], &route.rt_dst); 224 if (forcehost) 225 ishost = 1; 226 if (forcenet) 227 ishost = 0; 228 (void) getaddr(argv[2], &route.rt_gateway); 229 sin = (struct sockaddr_in *)&route.rt_dst; 230 route.rt_flags = RTF_UP; 231 if (ishost) 232 route.rt_flags |= RTF_HOST; 233 if (metric > 0) 234 route.rt_flags |= RTF_GATEWAY; 235 printf("%s %s: gateway ", cmd, routename(sin->sin_addr)); 236 sin = (struct sockaddr_in *)&route.rt_gateway; 237 printf("%s, flags %x\n", routename(sin->sin_addr), route.rt_flags); 238 if (ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, (caddr_t)&route)) 239 error(cmd); 240 } 241 242 changeroute(argc, argv) 243 int argc; 244 char *argv[]; 245 { 246 printf("not supported\n"); 247 } 248 249 error(cmd) 250 char *cmd; 251 { 252 extern int errno; 253 254 if (errno == ESRCH) 255 fprintf(stderr, "not in table\n"); 256 else if (errno == EBUSY) 257 fprintf(stderr, "entry in use\n"); 258 else if (errno == ENOBUFS) 259 fprintf(stderr, "routing table overflow\n"); 260 else 261 perror(cmd); 262 } 263 264 /* 265 * Interpret an argument as a network address of some kind, 266 * returning 1 if a host address, 0 if a network address. 267 */ 268 getaddr(s, sin) 269 char *s; 270 struct sockaddr_in *sin; 271 { 272 struct hostent *hp; 273 struct netent *np; 274 u_long val; 275 276 if (strcmp(s, "default") == 0) { 277 sin->sin_family = AF_INET; 278 sin->sin_addr = inet_makeaddr(0, INADDR_ANY); 279 return(0); 280 } 281 np = getnetbyname(s); 282 if (np) { 283 sin->sin_family = np->n_addrtype; 284 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 285 return(0); 286 } 287 hp = gethostbyname(s); 288 if (hp) { 289 sin->sin_family = hp->h_addrtype; 290 bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); 291 return(1); 292 } 293 sin->sin_family = AF_INET; 294 val = inet_addr(s); 295 if (val != -1) { 296 sin->sin_addr.s_addr = val; 297 return(inet_lnaof(sin->sin_addr) != INADDR_ANY); 298 } 299 val = inet_network(s); 300 if (val != -1) { 301 sin->sin_addr = inet_makeaddr(val, INADDR_ANY); 302 return(0); 303 } 304 fprintf(stderr, "%s: bad value\n", s); 305 exit(1); 306 } 307