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