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