|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983, 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: char copyright[] = ! 22: "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ ! 23: All rights reserved.\n"; ! 24: #endif /* not lint */ ! 25: ! 26: #ifndef lint ! 27: static char sccsid[] = "@(#)route.c 5.27 (Berkeley) 6/22/90"; ! 28: #endif /* not lint */ ! 29: ! 30: #include <sys/param.h> ! 31: #include <sys/socket.h> ! 32: #include <sys/ioctl.h> ! 33: #include <sys/file.h> ! 34: #include <sys/mbuf.h> ! 35: #include <sys/kinfo.h> ! 36: ! 37: #include <net/route.h> ! 38: #include <net/if_dl.h> ! 39: #include <netinet/in.h> ! 40: #include <netns/ns.h> ! 41: #include <netiso/iso.h> ! 42: ! 43: #include <netdb.h> ! 44: #include <stdio.h> ! 45: #include <errno.h> ! 46: #include <ctype.h> ! 47: #include <paths.h> ! 48: ! 49: struct keytab { ! 50: char *kt_cp; ! 51: int kt_i; ! 52: } keywords[] = { ! 53: #include "keywords.h" ! 54: {0, 0} ! 55: }; ! 56: ! 57: struct ortentry route; ! 58: union sockunion { ! 59: struct sockaddr sa; ! 60: struct sockaddr_in sin; ! 61: struct sockaddr_ns sns; ! 62: struct sockaddr_iso siso; ! 63: struct sockaddr_dl sdl; ! 64: } so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, *so_addrs[] = ! 65: { &so_dst, &so_gate, &so_mask, &so_genmask, &so_ifa, &so_ifp, 0}; ! 66: typedef union sockunion *sup; ! 67: int pid, rtm_addrs; ! 68: int s; ! 69: int forcehost, forcenet, doflush, nflag, af, qflag, Cflag, keyword(); ! 70: int iflag, verbose, aflen = sizeof (struct sockaddr_in); ! 71: int locking, lockrest, debugonly; ! 72: struct sockaddr_in sin = { sizeof(sin), AF_INET }; ! 73: struct rt_metrics rt_metrics; ! 74: u_long rtm_inits; ! 75: struct in_addr inet_makeaddr(); ! 76: char *malloc(), *routename(), *netname(); ! 77: extern char *iso_ntoa(), *link_ntoa(); ! 78: #define kget(p, d) \ ! 79: (lseek(kmem, (off_t)(p), 0), read(kmem, (char *)&(d), sizeof (d))) ! 80: ! 81: usage(cp) ! 82: char *cp; ! 83: { ! 84: fprintf(stderr, ! 85: "usage: route [ -nqCv ] cmd [[ -<qualifers> ] args ]\n"); ! 86: if (cp) fprintf(stderr, "(botched keyword: %s)\n", cp); ! 87: ! 88: exit(1); ! 89: } ! 90: ! 91: main(argc, argv) ! 92: int argc; ! 93: char *argv[]; ! 94: { ! 95: ! 96: char *argvp; ! 97: if (argc < 2) ! 98: usage((char *)0); ! 99: argc--, argv++; ! 100: for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) { ! 101: for (argvp = argv[0]++; *argvp; argvp++) ! 102: switch (*argv[0]) { ! 103: case 'n': ! 104: nflag++; ! 105: break; ! 106: case 'q': ! 107: qflag++; ! 108: break; ! 109: case 'C': ! 110: Cflag++; /* Use old ioctls */ ! 111: break; ! 112: case 'v': ! 113: verbose++; ! 114: } ! 115: } ! 116: pid = getpid(); ! 117: if (Cflag) ! 118: s = socket(AF_INET, SOCK_RAW, 0); ! 119: else ! 120: s = socket(PF_ROUTE, SOCK_RAW, 0); ! 121: if (s < 0) { ! 122: perror("route: socket"); ! 123: exit(1); ! 124: } ! 125: if (argc > 0) switch (keyword(*argv)) { ! 126: case K_ADD: ! 127: case K_CHANGE: ! 128: case K_DELETE: ! 129: newroute(argc, argv); ! 130: case K_MONITOR: ! 131: monitor(); ! 132: case K_FLUSH: ! 133: flushroutes(argc, argv); ! 134: } ! 135: usage(*argv); ! 136: } ! 137: ! 138: /* ! 139: * Purge all entries in the routing tables not ! 140: * associated with network interfaces. ! 141: */ ! 142: flushroutes(argc, argv) ! 143: char *argv[]; ! 144: { ! 145: int bufsize, needed, seqno, rlen; ! 146: char *buf, *next, *lim; ! 147: register struct rt_msghdr *rtm; ! 148: struct { ! 149: struct rt_msghdr m_rtm; ! 150: union { ! 151: char u_saddrs[200]; ! 152: struct sockaddr u_sa; ! 153: } m_u; ! 154: } m; ! 155: ! 156: shutdown(s, 0); /* Don't want to read back our messages */ ! 157: if (argc > 1) { ! 158: argv++; ! 159: if (argc == 2 && **argv == '-') switch (keyword(1 + *argv)) { ! 160: case K_INET: af = AF_INET; break; ! 161: case K_XNS: af = AF_NS; break; ! 162: case K_LINK: af = AF_LINK; break; ! 163: case K_ISO: case K_OSI: af = AF_ISO; break; ! 164: default: goto bad; ! 165: } else ! 166: bad: usage(*argv); ! 167: } ! 168: if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0) ! 169: { perror("route-getkerninfo-estimate"); exit(1);} ! 170: if ((buf = malloc(needed)) == 0) ! 171: { printf("out of space\n");; exit(1);} ! 172: if ((rlen = getkerninfo(KINFO_RT_DUMP, buf, &needed, 0)) < 0) ! 173: { perror("actual retrieval of routing table"); exit(1);} ! 174: lim = buf + rlen; ! 175: for (next = buf; next < lim; next += rtm->rtm_msglen) { ! 176: rtm = (struct rt_msghdr *)next; ! 177: if ((rtm->rtm_flags & RTF_GATEWAY) == 0) ! 178: continue; ! 179: if (af) { ! 180: struct sockaddr *sa = (struct sockaddr *)(rtm + 1); ! 181: if (sa->sa_family != af) ! 182: continue; ! 183: } ! 184: rtm->rtm_type = RTM_DELETE; ! 185: rtm->rtm_seq = seqno; ! 186: if ((rlen = write(s, next, rtm->rtm_msglen)) < 0) { ! 187: perror("writing to routing socket"); ! 188: printf("got only %d for rlen\n", rlen); ! 189: break; ! 190: } ! 191: seqno++; ! 192: if (qflag) ! 193: continue; ! 194: if (verbose) { ! 195: print_rtmsg(rtm, rlen); ! 196: } else { ! 197: struct sockaddr *sa = &m.m_u.u_sa; ! 198: printf("%-20.20s ", (rtm->rtm_flags & RTF_HOST) ? ! 199: routename(sa) : netname(sa)); ! 200: sa = (struct sockaddr *)(sa->sa_len + (char *)sa); ! 201: printf("%-20.20s ", routename(sa)); ! 202: printf("done\n"); ! 203: } ! 204: } ! 205: exit(0); ! 206: } ! 207: ! 208: char * ! 209: routename(sa) ! 210: struct sockaddr *sa; ! 211: { ! 212: register char *cp; ! 213: static char line[50]; ! 214: struct hostent *hp; ! 215: static char domain[MAXHOSTNAMELEN + 1]; ! 216: static int first = 1; ! 217: char *index(); ! 218: char *ns_print(); ! 219: ! 220: if (first) { ! 221: first = 0; ! 222: if (gethostname(domain, MAXHOSTNAMELEN) == 0 && ! 223: (cp = index(domain, '.'))) ! 224: (void) strcpy(domain, cp + 1); ! 225: else ! 226: domain[0] = 0; ! 227: } ! 228: switch (sa->sa_family) { ! 229: ! 230: case AF_INET: ! 231: { struct in_addr in; ! 232: in = ((struct sockaddr_in *)sa)->sin_addr; ! 233: ! 234: cp = 0; ! 235: if (in.s_addr == INADDR_ANY) ! 236: cp = "default"; ! 237: if (cp == 0 && !nflag) { ! 238: hp = gethostbyaddr(&in, sizeof (struct in_addr), ! 239: AF_INET); ! 240: if (hp) { ! 241: if ((cp = index(hp->h_name, '.')) && ! 242: !strcmp(cp + 1, domain)) ! 243: *cp = 0; ! 244: cp = hp->h_name; ! 245: } ! 246: } ! 247: if (cp) ! 248: strcpy(line, cp); ! 249: else { ! 250: #define C(x) ((x) & 0xff) ! 251: in.s_addr = ntohl(in.s_addr); ! 252: (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), ! 253: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); ! 254: } ! 255: break; ! 256: } ! 257: ! 258: case AF_NS: ! 259: return (ns_print((struct sockaddr_ns *)sa)); ! 260: ! 261: case AF_LINK: ! 262: return (link_ntoa((struct sockaddr_dl *)sa)); ! 263: ! 264: case AF_ISO: ! 265: (void) sprintf(line, "iso %s", ! 266: iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); ! 267: break; ! 268: ! 269: default: ! 270: { u_short *s = (u_short *)sa->sa_data; ! 271: u_short *slim = s + ((sa->sa_len + 1)>>1); ! 272: char *cp = line + sprintf(line, "(%d)", sa->sa_family); ! 273: int n; ! 274: ! 275: while (s < slim) { ! 276: n = sprintf(cp, " %x", *s); ! 277: s++; cp += n; ! 278: } ! 279: break; ! 280: } ! 281: } ! 282: return (line); ! 283: } ! 284: ! 285: /* ! 286: * Return the name of the network whose address is given. ! 287: * The address is assumed to be that of a net or subnet, not a host. ! 288: */ ! 289: char * ! 290: netname(sa) ! 291: struct sockaddr *sa; ! 292: { ! 293: char *cp = 0; ! 294: static char line[50]; ! 295: struct netent *np = 0; ! 296: u_long net, mask; ! 297: register u_long i; ! 298: int subnetshift; ! 299: char *ns_print(); ! 300: ! 301: switch (sa->sa_family) { ! 302: ! 303: case AF_INET: ! 304: { struct in_addr in; ! 305: in = ((struct sockaddr_in *)sa)->sin_addr; ! 306: ! 307: i = in.s_addr = ntohl(in.s_addr); ! 308: if (in.s_addr == 0) ! 309: cp = "default"; ! 310: else if (!nflag) { ! 311: if (IN_CLASSA(i)) { ! 312: mask = IN_CLASSA_NET; ! 313: subnetshift = 8; ! 314: } else if (IN_CLASSB(i)) { ! 315: mask = IN_CLASSB_NET; ! 316: subnetshift = 8; ! 317: } else { ! 318: mask = IN_CLASSC_NET; ! 319: subnetshift = 4; ! 320: } ! 321: /* ! 322: * If there are more bits than the standard mask ! 323: * would suggest, subnets must be in use. ! 324: * Guess at the subnet mask, assuming reasonable ! 325: * width subnet fields. ! 326: */ ! 327: while (in.s_addr &~ mask) ! 328: mask = (long)mask >> subnetshift; ! 329: net = in.s_addr & mask; ! 330: while ((mask & 1) == 0) ! 331: mask >>= 1, net >>= 1; ! 332: np = getnetbyaddr(net, AF_INET); ! 333: if (np) ! 334: cp = np->n_name; ! 335: } ! 336: if (cp) ! 337: strcpy(line, cp); ! 338: else if ((in.s_addr & 0xffffff) == 0) ! 339: (void)sprintf(line, "%u", C(in.s_addr >> 24)); ! 340: else if ((in.s_addr & 0xffff) == 0) ! 341: (void)sprintf(line, "%u.%u", C(in.s_addr >> 24), ! 342: C(in.s_addr >> 16)); ! 343: else if ((in.s_addr & 0xff) == 0) ! 344: (void)sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), ! 345: C(in.s_addr >> 16), C(in.s_addr >> 8)); ! 346: else ! 347: (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), ! 348: C(in.s_addr >> 16), C(in.s_addr >> 8), ! 349: C(in.s_addr)); ! 350: break; ! 351: } ! 352: ! 353: case AF_NS: ! 354: return (ns_print((struct sockaddr_ns *)sa)); ! 355: break; ! 356: ! 357: case AF_LINK: ! 358: return (link_ntoa((struct sockaddr_dl *)sa)); ! 359: ! 360: case AF_ISO: ! 361: (void) sprintf(line, "iso %s", ! 362: iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); ! 363: break; ! 364: ! 365: default: ! 366: { u_short *s = (u_short *)sa->sa_data; ! 367: u_short *slim = s + ((sa->sa_len + 1)>>1); ! 368: char *cp = line + sprintf(line, "af %d:", sa->sa_family); ! 369: int n; ! 370: ! 371: while (s < slim) { ! 372: n = sprintf(cp, " %x", *s); ! 373: s++; cp += n; ! 374: } ! 375: break; ! 376: } ! 377: } ! 378: return (line); ! 379: } ! 380: ! 381: set_metric(value, key) ! 382: char *value; ! 383: { ! 384: int flag = 0; ! 385: u_long noval, *valp = &noval; ! 386: ! 387: switch (key) { ! 388: #define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break ! 389: caseof(K_MTU, RTV_MTU, rmx_mtu); ! 390: caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); ! 391: caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); ! 392: caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); ! 393: caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); ! 394: caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); ! 395: caseof(K_RTT, RTV_RTT, rmx_rtt); ! 396: caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); ! 397: } ! 398: rtm_inits |= flag; ! 399: if (lockrest || locking) ! 400: rt_metrics.rmx_locks |= flag; ! 401: if (locking) ! 402: locking = 0; ! 403: *valp = atoi(value); ! 404: } ! 405: ! 406: newroute(argc, argv) ! 407: int argc; ! 408: register char **argv; ! 409: { ! 410: struct sockaddr_in *sin; ! 411: char *cmd, *dest, *gateway, *mask; ! 412: int ishost, metric = 0, ret, attempts, oerrno, flags = 0, next; ! 413: int key; ! 414: struct hostent *hp = 0; ! 415: extern int errno; ! 416: ! 417: shutdown(s, 0); /* Don't want to read back our messages */ ! 418: cmd = argv[0]; ! 419: while (--argc > 0) { ! 420: if (**(++argv)== '-') { ! 421: switch(key = keyword(1 + *argv)) { ! 422: case K_LINK: ! 423: af = AF_LINK; ! 424: aflen = sizeof(struct sockaddr_dl); ! 425: break; ! 426: case K_OSI: ! 427: case K_ISO: ! 428: af = AF_ISO; ! 429: aflen = sizeof(struct sockaddr_iso); ! 430: break; ! 431: case K_INET: ! 432: af = AF_INET; ! 433: aflen = sizeof(struct sockaddr_in); ! 434: break; ! 435: case K_XNS: ! 436: af = AF_NS; ! 437: aflen = sizeof(struct sockaddr_ns); ! 438: break; ! 439: case K_IFACE: ! 440: case K_INTERFACE: ! 441: iflag++; ! 442: break; ! 443: case K_LOCK: ! 444: locking = 1; ! 445: break; ! 446: case K_LOCKREST: ! 447: lockrest = 1; ! 448: break; ! 449: case K_HOST: ! 450: forcehost++; ! 451: break; ! 452: case K_NETMASK: ! 453: argc--; ! 454: (void) getaddr(RTA_NETMASK, *++argv, 0); ! 455: /* FALLTHROUGH */ ! 456: case K_NET: ! 457: forcenet++; ! 458: break; ! 459: case K_CLONING: ! 460: flags |= RTF_CLONING; ! 461: break; ! 462: case K_XRESOLVE: ! 463: flags |= RTF_XRESOLVE; ! 464: break; ! 465: case K_GENMASK: ! 466: argc--; ! 467: (void) getaddr(RTA_GENMASK, *++argv, 0); ! 468: break; ! 469: case K_MTU: ! 470: case K_HOPCOUNT: ! 471: case K_EXPIRE: ! 472: case K_RECVPIPE: ! 473: case K_SENDPIPE: ! 474: case K_SSTHRESH: ! 475: case K_RTT: ! 476: case K_RTTVAR: ! 477: argc--; ! 478: set_metric(*++argv, key); ! 479: break; ! 480: default: ! 481: usage(1+*argv); ! 482: } ! 483: } else { ! 484: if ((rtm_addrs & RTA_DST) == 0) { ! 485: dest = *argv; ! 486: ishost = getaddr(RTA_DST, *argv, &hp); ! 487: } else if ((rtm_addrs & RTA_GATEWAY) == 0) { ! 488: gateway = *argv; ! 489: (void) getaddr(RTA_GATEWAY, *argv, &hp); ! 490: } else { ! 491: int ret = atoi(*argv); ! 492: if (ret == 0) { ! 493: printf("%s,%s", "old usage of trailing 0", ! 494: "assuming route to if\n"); ! 495: iflag = 1; ! 496: continue; ! 497: } else if (ret > 0 && ret < 10) { ! 498: printf("old usage of trailing digit, "); ! 499: printf("assuming route via gateway\n"); ! 500: iflag = 0; ! 501: continue; ! 502: } ! 503: (void) getaddr(RTA_NETMASK, *argv, 0); ! 504: } ! 505: } ! 506: } ! 507: if (forcehost) ! 508: ishost = 1; ! 509: if (forcenet) ! 510: ishost = 0; ! 511: flags |= RTF_UP; ! 512: if (ishost) ! 513: flags |= RTF_HOST; ! 514: if (iflag == 0) ! 515: flags |= RTF_GATEWAY; ! 516: for (attempts = 1; ; attempts++) { ! 517: errno = 0; ! 518: if (Cflag && (af == AF_INET || af == AF_NS)) { ! 519: route.rt_flags = flags; ! 520: route.rt_dst = so_dst.sa; ! 521: route.rt_gateway = so_gate.sa; ! 522: if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT, ! 523: (caddr_t)&route)) == 0) ! 524: break; ! 525: } else { ! 526: if ((ret = rtmsg(*cmd, flags)) == 0); ! 527: break; ! 528: } ! 529: if (errno != ENETUNREACH && errno != ESRCH) ! 530: break; ! 531: if (hp && hp->h_addr_list[1]) { ! 532: hp->h_addr_list++; ! 533: bcopy(hp->h_addr_list[0], (caddr_t)&so_dst.sin.sin_addr, ! 534: hp->h_length); ! 535: } else ! 536: break; ! 537: } ! 538: oerrno = errno; ! 539: printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net", ! 540: dest, gateway); ! 541: if (attempts > 1 && ret == 0) ! 542: printf(" (%s)", ! 543: inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); ! 544: if (ret == 0) ! 545: printf("\n"); ! 546: else { ! 547: printf(": "); ! 548: fflush(stdout); ! 549: errno = oerrno; ! 550: error(""); ! 551: } ! 552: exit(0); ! 553: } ! 554: ! 555: error(cmd) ! 556: char *cmd; ! 557: { ! 558: extern int errno; ! 559: ! 560: switch(errno) { ! 561: case ESRCH: ! 562: printf("not in table\n"); ! 563: break; ! 564: case EBUSY: ! 565: printf("entry in use\n"); ! 566: break; ! 567: case ENOBUFS: ! 568: printf("routing table overflow\n"); ! 569: break; ! 570: default: ! 571: printf("ioctl returns %d\n", errno); ! 572: perror(cmd); ! 573: } ! 574: fflush(stdout); ! 575: errno = 0; ! 576: } ! 577: ! 578: char * ! 579: savestr(s) ! 580: char *s; ! 581: { ! 582: char *sav; ! 583: ! 584: sav = malloc(strlen(s) + 1); ! 585: if (sav == NULL) { ! 586: fprintf("route: out of memory\n"); ! 587: exit(1); ! 588: } ! 589: strcpy(sav, s); ! 590: return (sav); ! 591: } ! 592: ! 593: inet_makenetandmask(net, sin) ! 594: u_long net; ! 595: register struct sockaddr_in *sin; ! 596: { ! 597: u_long addr; ! 598: u_long mask = 0; ! 599: register char *cp; ! 600: ! 601: rtm_addrs |= RTA_NETMASK; ! 602: if (net == 0) ! 603: mask = addr = 0; ! 604: else if (net < 128) { ! 605: addr = net << IN_CLASSA_NSHIFT; ! 606: mask = IN_CLASSA_NET; ! 607: } else if (net < 65536) { ! 608: addr = net << IN_CLASSB_NSHIFT; ! 609: mask = IN_CLASSB_NET; ! 610: } else if (net < 16777216L) { ! 611: addr = net << IN_CLASSC_NSHIFT; ! 612: mask = IN_CLASSC_NET; ! 613: } else { ! 614: addr = net; ! 615: if ((addr & IN_CLASSA_HOST) == 0) ! 616: mask = IN_CLASSA_NET; ! 617: else if ((addr & IN_CLASSB_HOST) == 0) ! 618: mask = IN_CLASSB_NET; ! 619: else if ((addr & IN_CLASSC_HOST) == 0) ! 620: mask = IN_CLASSC_NET; ! 621: else ! 622: mask = -1; ! 623: } ! 624: sin->sin_addr.s_addr = htonl(addr); ! 625: sin = &so_mask.sin; ! 626: sin->sin_addr.s_addr = htonl(mask); ! 627: sin->sin_len = 0; ! 628: sin->sin_family = 0; ! 629: cp = (char *)(1 + &(sin->sin_addr)); ! 630: while (*--cp == 0 && cp > (char *)sin) ! 631: ; ! 632: sin->sin_len = 1 + cp - (char *)sin; ! 633: } ! 634: ! 635: /* ! 636: * Interpret an argument as a network address of some kind, ! 637: * returning 1 if a host address, 0 if a network address. ! 638: */ ! 639: getaddr(which, s, hpp) ! 640: char *s; ! 641: struct hostent **hpp; ! 642: { ! 643: register union sockunion *su; ! 644: struct ns_addr ns_addr(); ! 645: struct iso_addr *iso_addr(); ! 646: struct hostent *hp; ! 647: struct netent *np; ! 648: u_long val; ! 649: ! 650: if (af == 0) { ! 651: af = AF_INET; ! 652: aflen = sizeof(struct sockaddr_in); ! 653: } ! 654: rtm_addrs |= which; ! 655: switch (which) { ! 656: case RTA_DST: su = so_addrs[0]; su->sa.sa_family = af; break; ! 657: case RTA_GATEWAY: su = so_addrs[1]; su->sa.sa_family = af; break; ! 658: case RTA_NETMASK: su = so_addrs[2]; break; ! 659: case RTA_GENMASK: su = so_addrs[3]; break; ! 660: default: usage("Internal Error"); /*NOTREACHED*/ ! 661: } ! 662: su->sa.sa_len = aflen; ! 663: if (strcmp(s, "default") == 0) { ! 664: switch (which) { ! 665: case RTA_DST: ! 666: forcenet++; ! 667: getaddr(RTA_NETMASK, s, 0); ! 668: break; ! 669: case RTA_NETMASK: ! 670: case RTA_GENMASK: ! 671: su->sa.sa_len = 0; ! 672: } ! 673: return 0; ! 674: } ! 675: if (af == AF_NS) ! 676: goto do_xns; ! 677: if (af == AF_OSI) ! 678: goto do_osi; ! 679: if (af == AF_LINK) ! 680: goto do_link; ! 681: if (hpp == 0) hpp = &hp; ! 682: *hpp = 0; ! 683: if (((val = inet_addr(s)) != -1) && ! 684: (which != RTA_DST || forcenet == 0)) { ! 685: su->sin.sin_addr.s_addr = val; ! 686: if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) ! 687: return (1); ! 688: else { ! 689: val = ntohl(val); ! 690: out: if (which == RTA_DST) ! 691: inet_makenetandmask(val, &su->sin); ! 692: return (0); ! 693: } ! 694: } ! 695: val = inet_network(s); ! 696: if (val != -1) { ! 697: goto out; ! 698: } ! 699: np = getnetbyname(s); ! 700: if (np) { ! 701: val = np->n_net; ! 702: goto out; ! 703: } ! 704: hp = gethostbyname(s); ! 705: if (hp) { ! 706: *hpp = hp; ! 707: su->sin.sin_family = hp->h_addrtype; ! 708: bcopy(hp->h_addr, &su->sin.sin_addr, hp->h_length); ! 709: return (1); ! 710: } ! 711: fprintf(stderr, "%s: bad value\n", s); ! 712: exit(1); ! 713: do_xns: ! 714: if (val == 0) ! 715: return(0); ! 716: if (which == RTA_DST) { ! 717: extern short ns_bh[3]; ! 718: struct sockaddr_ns *sms = &(so_mask.sns); ! 719: bzero((char *)sms, sizeof(*sms)); ! 720: sms->sns_family = 0; ! 721: sms->sns_len = 6; ! 722: sms->sns_addr.x_net = *(union ns_net *)ns_bh; ! 723: rtm_addrs |= RTA_NETMASK; ! 724: } ! 725: su->sns.sns_addr = ns_addr(s); ! 726: return (!ns_nullhost(su->sns.sns_addr)); ! 727: do_osi: ! 728: su->siso.siso_addr = *iso_addr(s); ! 729: if (which == RTA_NETMASK || which == RTA_GENMASK) { ! 730: register char *cp = (char *)TSEL(&su->siso); ! 731: su->siso.siso_nlen = 0; ! 732: do {--cp ;} while ((cp > (char *)su) && (*cp == 0)); ! 733: su->siso.siso_len = 1 + cp - (char *)su; ! 734: } ! 735: return (1); ! 736: do_link: ! 737: link_addr(s, &su->sdl); ! 738: return (1); ! 739: } ! 740: ! 741: short ns_nullh[] = {0,0,0}; ! 742: short ns_bh[] = {-1,-1,-1}; ! 743: ! 744: char * ! 745: ns_print(sns) ! 746: struct sockaddr_ns *sns; ! 747: { ! 748: struct ns_addr work; ! 749: union { union ns_net net_e; u_long long_e; } net; ! 750: u_short port; ! 751: static char mybuf[50], cport[10], chost[25]; ! 752: char *host = ""; ! 753: register char *p; register u_char *q; u_char *q_lim; ! 754: ! 755: work = sns->sns_addr; ! 756: port = ntohs(work.x_port); ! 757: work.x_port = 0; ! 758: net.net_e = work.x_net; ! 759: if (ns_nullhost(work) && net.long_e == 0) { ! 760: if (port ) { ! 761: (void)sprintf(mybuf, "*.%xH", port); ! 762: upHex(mybuf); ! 763: } else ! 764: (void)sprintf(mybuf, "*.*"); ! 765: return (mybuf); ! 766: } ! 767: ! 768: if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) { ! 769: host = "any"; ! 770: } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) { ! 771: host = "*"; ! 772: } else { ! 773: q = work.x_host.c_host; ! 774: (void)sprintf(chost, "%02x%02x%02x%02x%02x%02xH", ! 775: q[0], q[1], q[2], q[3], q[4], q[5]); ! 776: for (p = chost; *p == '0' && p < chost + 12; p++); ! 777: host = p; ! 778: } ! 779: if (port) ! 780: (void)sprintf(cport, ".%xH", htons(port)); ! 781: else ! 782: *cport = 0; ! 783: ! 784: (void)sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport); ! 785: upHex(mybuf); ! 786: return(mybuf); ! 787: } ! 788: ! 789: upHex(p0) ! 790: char *p0; ! 791: { ! 792: register char *p = p0; ! 793: for (; *p; p++) switch (*p) { ! 794: ! 795: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ! 796: *p += ('A' - 'a'); ! 797: } ! 798: } ! 799: ! 800: monitor() ! 801: { ! 802: int n; ! 803: char msg[2048]; ! 804: verbose = 1; ! 805: for(;;) { ! 806: n = read(s, msg, 2048); ! 807: printf("got message of size %d\n", n); ! 808: print_rtmsg((struct rt_msghdr *)msg); ! 809: } ! 810: } ! 811: ! 812: struct { ! 813: struct rt_msghdr m_rtm; ! 814: char m_space[512]; ! 815: } m_rtmsg; ! 816: ! 817: rtmsg(cmd, flags) ! 818: { ! 819: static int seq; ! 820: int rlen; ! 821: extern int errno; ! 822: register char *cp = m_rtmsg.m_space; ! 823: register int l; ! 824: ! 825: errno = 0; ! 826: bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); ! 827: if (cmd == 'a') ! 828: cmd = RTM_ADD; ! 829: else if (cmd == 'c') ! 830: cmd = RTM_CHANGE; ! 831: else ! 832: cmd = RTM_DELETE; ! 833: m_rtmsg.m_rtm.rtm_flags = flags; ! 834: m_rtmsg.m_rtm.rtm_version = RTM_VERSION; ! 835: m_rtmsg.m_rtm.rtm_seq = ++seq; ! 836: m_rtmsg.m_rtm.rtm_addrs = rtm_addrs; ! 837: m_rtmsg.m_rtm.rtm_rmx = rt_metrics; ! 838: m_rtmsg.m_rtm.rtm_inits = rtm_inits; ! 839: ! 840: #define ROUND(a) (1 + (((a) - 1) | (sizeof(long) - 1))) ! 841: #define NEXTADDR(w, u) { if (rtm_addrs & (w)) {l = (u).sa.sa_len;\ ! 842: if(verbose)sodump(&(u),"u");if(l == 0) l = sizeof(int); l = ROUND(l);\ ! 843: bcopy((char *)&(u), cp, l); cp += l;}} ! 844: ! 845: NEXTADDR(RTA_DST, so_dst); ! 846: NEXTADDR(RTA_GATEWAY, so_gate); ! 847: NEXTADDR(RTA_NETMASK, so_mask); ! 848: NEXTADDR(RTA_GENMASK, so_genmask); ! 849: m_rtmsg.m_rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; ! 850: m_rtmsg.m_rtm.rtm_type = cmd; ! 851: if (verbose) ! 852: print_rtmsg(&m_rtmsg.m_rtm, l); ! 853: if (debugonly) ! 854: return 0; ! 855: if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { ! 856: perror("writing to routing socket"); ! 857: printf("got only %d for rlen\n", rlen); ! 858: return (-1); ! 859: } ! 860: return (0); ! 861: } ! 862: ! 863: char *msgtypes[] = { ! 864: "", ! 865: "RTM_ADD: Add Route", ! 866: "RTM_DELETE: Delete Route", ! 867: "RTM_CHANGE: Change Metrics or flags", ! 868: "RTM_GET: Report Metrics", ! 869: "RTM_LOSING: Kernel Suspects Partitioning", ! 870: "RTM_REDIRECT: Told to use different route", ! 871: "RTM_MISS: Lookup failed on this address", ! 872: "RTM_LOCK: fix specified metrics", ! 873: "RTM_OLDADD: caused by SIOCADDRT", ! 874: "RTM_OLDDEL: caused by SIOCDELRT", ! 875: 0, }; ! 876: ! 877: char metricnames[] = ! 878: "\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu"; ! 879: char routeflags[] = ! 880: "\1UP\2GATEWAY\3HOST\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE"; ! 881: ! 882: #define ROUNDUP(a) ((char *)(1 + (((((int)a)) - 1) | (sizeof(long) - 1)))) ! 883: ! 884: print_rtmsg(rtm, n) ! 885: register struct rt_msghdr *rtm; ! 886: { ! 887: char *cp; ! 888: register struct sockaddr *sa; ! 889: int i; ! 890: ! 891: if (verbose == 0) ! 892: return; ! 893: if (rtm->rtm_version != RTM_VERSION) { ! 894: printf("routing message version %d not understood\n", ! 895: rtm->rtm_version); ! 896: } else { ! 897: printf("%s\npid: %d, len %d, seq %d, errno %d, flags:", ! 898: msgtypes[rtm->rtm_type], rtm->rtm_pid, rtm->rtm_msglen, ! 899: rtm->rtm_seq, rtm->rtm_errno); ! 900: bprintf(stdout, rtm->rtm_flags, routeflags); ! 901: printf("\nlocks: "); bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); ! 902: printf(" inits: "); bprintf(stdout, rtm->rtm_inits, metricnames); ! 903: printf("\nsockaddrs: "); ! 904: bprintf(stdout, rtm->rtm_addrs, ! 905: "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR"); ! 906: putchar('\n'); ! 907: cp = ((char *)(rtm + 1)); ! 908: if (rtm->rtm_addrs) ! 909: for (i = 1; i; i <<= 1) ! 910: if (i & rtm->rtm_addrs) { ! 911: sa = (struct sockaddr *)cp; ! 912: printf(" %s", routename(sa)); ! 913: cp = ROUNDUP(cp + sa->sa_len); ! 914: } ! 915: putchar('\n'); ! 916: } ! 917: fflush(stdout); ! 918: } ! 919: ! 920: bprintf(fp, b, s) ! 921: register FILE *fp; ! 922: register int b; ! 923: register u_char *s; ! 924: { ! 925: register int i; ! 926: int gotsome = 0; ! 927: ! 928: if (b == 0) ! 929: return; ! 930: while (i = *s++) { ! 931: if (b & (1 << (i-1))) { ! 932: if (gotsome == 0) i = '<'; else i = ','; ! 933: putc(i, fp); ! 934: gotsome = 1; ! 935: for (; (i = *s) > 32; s++) ! 936: putc(i, fp); ! 937: } else ! 938: while (*s > 32) ! 939: s++; ! 940: } ! 941: if (gotsome) ! 942: putc('>', fp); ! 943: } ! 944: int ! 945: keyword(cp) ! 946: char *cp; ! 947: { ! 948: register struct keytab *kt = keywords; ! 949: while (kt->kt_cp && strcmp(kt->kt_cp, cp)) ! 950: kt++; ! 951: return kt->kt_i; ! 952: } ! 953: ! 954: sodump(su, which) ! 955: register union sockunion *su; ! 956: char *which; ! 957: { ! 958: switch (su->sa.sa_family) { ! 959: case AF_LINK: ! 960: printf("%s: link %s; ", which, link_ntoa(&su->sdl)); ! 961: break; ! 962: case AF_ISO: ! 963: printf("%s: iso %s; ", which, iso_ntoa(&su->siso.siso_addr)); ! 964: break; ! 965: case AF_INET: ! 966: printf("%s: inet %s; ", which, inet_ntoa(su->sin.sin_addr)); ! 967: break; ! 968: case AF_NS: ! 969: printf("%s: xns %s; ", which, ns_ntoa(&su->sns.sns_addr)); ! 970: break; ! 971: } ! 972: fflush(stdout); ! 973: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.