|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983, 1988 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: static char sccsid[] = "@(#)route.c 5.19 (Berkeley) 6/18/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #include <sys/param.h> ! 25: #include <sys/socket.h> ! 26: #include <sys/mbuf.h> ! 27: ! 28: #include <net/if.h> ! 29: #define KERNEL ! 30: #include <net/route.h> ! 31: #undef KERNEL ! 32: #include <netinet/in.h> ! 33: ! 34: #include <netns/ns.h> ! 35: ! 36: #include <netdb.h> ! 37: #include <sys/kinfo.h> ! 38: ! 39: #include <stdio.h> ! 40: #include <string.h> ! 41: ! 42: extern int nflag; ! 43: extern char *routename(), *netname(), *ns_print(), *plural(); ! 44: extern char *malloc(); ! 45: #define kget(p, d) \ ! 46: (kvm_read((off_t)(p), (char *)&(d), sizeof (d))) ! 47: ! 48: /* ! 49: * Definitions for showing gateway flags. ! 50: */ ! 51: struct bits { ! 52: short b_mask; ! 53: char b_val; ! 54: } bits[] = { ! 55: { RTF_UP, 'U' }, ! 56: { RTF_GATEWAY, 'G' }, ! 57: { RTF_HOST, 'H' }, ! 58: { RTF_DYNAMIC, 'D' }, ! 59: { RTF_MODIFIED, 'M' }, ! 60: { RTF_CLONING, 'C' }, ! 61: { RTF_XRESOLVE, 'R' }, ! 62: { RTF_LLINFO, 'L' }, ! 63: { 0 } ! 64: }; ! 65: ! 66: /* ! 67: * Print routing tables. ! 68: */ ! 69: routepr(hostaddr, netaddr, hashsizeaddr, treeaddr) ! 70: off_t hostaddr, netaddr, hashsizeaddr, treeaddr; ! 71: { ! 72: struct mbuf mb; ! 73: register struct ortentry *rt; ! 74: register struct mbuf *m; ! 75: char name[16], *flags; ! 76: struct mbuf **routehash; ! 77: int hashsize; ! 78: int i, doinghost = 1; ! 79: ! 80: printf("Routing tables\n"); ! 81: printf("%-16.16s %-18.18s %-6.6s %6.6s%8.8s %s\n", ! 82: "Destination", "Gateway", ! 83: "Flags", "Refs", "Use", "Interface"); ! 84: if (treeaddr) ! 85: return treestuff(treeaddr); ! 86: if (hostaddr == 0) { ! 87: printf("rthost: symbol not in namelist\n"); ! 88: return; ! 89: } ! 90: if (netaddr == 0) { ! 91: printf("rtnet: symbol not in namelist\n"); ! 92: return; ! 93: } ! 94: if (hashsizeaddr == 0) { ! 95: printf("rthashsize: symbol not in namelist\n"); ! 96: return; ! 97: } ! 98: kget(hashsizeaddr, hashsize); ! 99: routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) ); ! 100: kvm_read(hostaddr, (char *)routehash, hashsize*sizeof (struct mbuf *)); ! 101: again: ! 102: for (i = 0; i < hashsize; i++) { ! 103: if (routehash[i] == 0) ! 104: continue; ! 105: m = routehash[i]; ! 106: while (m) { ! 107: kget(m, mb); ! 108: p_rtentry((struct rtentry *)(mb.m_dat)); ! 109: m = mb.m_next; ! 110: } ! 111: } ! 112: if (doinghost) { ! 113: kvm_read(netaddr, (char *)routehash, ! 114: hashsize*sizeof (struct mbuf *)); ! 115: doinghost = 0; ! 116: goto again; ! 117: } ! 118: free((char *)routehash); ! 119: return; ! 120: } ! 121: ! 122: static union { ! 123: struct sockaddr u_sa; ! 124: u_short u_data[128]; ! 125: } pt_u; ! 126: static struct rtentry rtentry; ! 127: ! 128: int NewTree = 0; ! 129: treestuff(rtree) ! 130: off_t rtree; ! 131: { ! 132: struct radix_node_head *rnh, head; ! 133: ! 134: if (NewTree) ! 135: return(ntreestuff()); ! 136: for (kget(rtree, rnh); rnh; rnh = head.rnh_next) { ! 137: kget(rnh, head); ! 138: if (head.rnh_af == 0) { ! 139: printf("Netmasks:\n"); ! 140: p_tree(head.rnh_treetop, 0); ! 141: } else { ! 142: printf("\nRoute Tree for Protocol Family %d:\n", ! 143: head.rnh_af); ! 144: p_tree(head.rnh_treetop, 1); ! 145: } ! 146: } ! 147: } ! 148: ! 149: struct sockaddr * ! 150: kgetsa(dst) ! 151: register struct sockaddr *dst; ! 152: { ! 153: kget(dst, pt_u.u_sa); ! 154: if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) { ! 155: kvm_read((off_t)dst, pt_u.u_data, pt_u.u_sa.sa_len); ! 156: } ! 157: return (&pt_u.u_sa); ! 158: } ! 159: ! 160: p_tree(rn, do_rtent) ! 161: struct radix_node *rn; ! 162: { ! 163: struct radix_node rnode; ! 164: register u_short *s, *slim; ! 165: int len; ! 166: ! 167: again: ! 168: kget(rn, rnode); ! 169: if (rnode.rn_b < 0) { ! 170: if (rnode.rn_flags & RNF_ROOT) ! 171: printf("(root node)\n"); ! 172: else if (do_rtent) { ! 173: kget(rn, rtentry); ! 174: p_rtentry(&rtentry); ! 175: } else { ! 176: p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key), ! 177: 0, 44); ! 178: putchar('\n'); ! 179: } ! 180: if (rn = rnode.rn_dupedkey) ! 181: goto again; ! 182: } else { ! 183: p_tree(rnode.rn_l, do_rtent); ! 184: p_tree(rnode.rn_r, do_rtent); ! 185: } ! 186: } ! 187: ! 188: ntreestuff() ! 189: { ! 190: int needed; ! 191: char *buf, *next, *lim; ! 192: register struct rt_msghdr *rtm; ! 193: ! 194: if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0) ! 195: { perror("route-getkerninfo-estimate"); exit(1);} ! 196: if ((buf = malloc(needed)) == 0) ! 197: { printf("out of space\n"); exit(1);} ! 198: if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0) ! 199: { perror("actual retrieval of routing table"); exit(1);} ! 200: lim = buf + needed; ! 201: for (next = buf; next < lim; next += rtm->rtm_msglen) { ! 202: rtm = (struct rt_msghdr *)next; ! 203: np_rtentry(rtm); ! 204: } ! 205: } ! 206: ! 207: np_rtentry(rtm) ! 208: register struct rt_msghdr *rtm; ! 209: { ! 210: register struct sockaddr *sa = (struct sockaddr *)(rtm + 1); ! 211: static int masks_done, old_af, banner_printed; ! 212: int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; ! 213: ! 214: #ifdef notdef ! 215: /* for the moment, netmasks are skipped over */ ! 216: if (!banner_printed) { ! 217: printf("Netmasks:\n"); ! 218: banner_printed = 1; ! 219: } ! 220: if (masks_done == 0) { ! 221: if (rtm->rtm_addrs != RTA_DST ) { ! 222: masks_done = 1; ! 223: af = sa->sa_family; ! 224: } ! 225: } else ! 226: #endif ! 227: af = sa->sa_family; ! 228: if (af != old_af) { ! 229: printf("\nRoute Tree for Protocol Family %d:\n", af); ! 230: old_af = af; ! 231: } ! 232: if (rtm->rtm_addrs == RTA_DST) ! 233: p_sockaddr(sa, 0, 36); ! 234: else { ! 235: p_sockaddr(sa, rtm->rtm_flags, 16); ! 236: if (sa->sa_len == 0) ! 237: sa->sa_len = sizeof(long); ! 238: sa = (struct sockaddr *)(sa->sa_len + (char *)sa); ! 239: p_sockaddr(sa, 0, 18); ! 240: } ! 241: p_flags(rtm->rtm_flags & interesting, "%-6.6s "); ! 242: putchar('\n'); ! 243: } ! 244: ! 245: p_sockaddr(sa, flags, width) ! 246: struct sockaddr *sa; ! 247: int flags, width; ! 248: { ! 249: char format[20], workbuf[128], *cp, *cplim; ! 250: register char *cpout; ! 251: ! 252: switch(sa->sa_family) { ! 253: case AF_INET: ! 254: { ! 255: register struct sockaddr_in *sin = (struct sockaddr_in *)sa; ! 256: ! 257: cp = (sin->sin_addr.s_addr == 0) ? "default" : ! 258: ((flags & RTF_HOST) ? ! 259: routename(sin->sin_addr) : netname(sin->sin_addr, 0L)); ! 260: } ! 261: break; ! 262: ! 263: case AF_NS: ! 264: cp = ns_print((struct sockaddr_ns *)sa); ! 265: break; ! 266: ! 267: default: ! 268: { ! 269: register u_short *s = ((u_short *)sa->sa_data), ! 270: *slim = ((sa->sa_len + 1)/2) + s; ! 271: ! 272: cp = workbuf; ! 273: cplim = cp + sizeof(workbuf) - 6; ! 274: cp += sprintf(cp, "(%d)", sa->sa_family); ! 275: while (s < slim && cp < cplim) ! 276: cp += sprintf(cp, "%x ", *s++); ! 277: cp = workbuf; ! 278: } ! 279: } ! 280: if (nflag) ! 281: printf("%-*s ", width, cp); ! 282: else ! 283: printf("%-*.*s ", width, width, cp); ! 284: } ! 285: ! 286: p_flags(f, format) ! 287: register int f; ! 288: char *format; ! 289: { ! 290: char name[33], *flags; ! 291: register struct bits *p = bits; ! 292: for (flags = name; p->b_mask; p++) ! 293: if (p->b_mask & f) ! 294: *flags++ = p->b_val; ! 295: *flags = '\0'; ! 296: printf(format, name); ! 297: } ! 298: ! 299: p_rtentry(rt) ! 300: register struct rtentry *rt; ! 301: { ! 302: char name[16]; ! 303: register struct sockaddr *sa; ! 304: struct ifnet ifnet; ! 305: ! 306: p_sockaddr(kgetsa(rt_key(rt)), rt->rt_flags, 16); ! 307: p_sockaddr(kgetsa(rt->rt_gateway), 0, 18); ! 308: p_flags(rt->rt_flags, "%-6.6s "); ! 309: printf("%6d %8d ", rt->rt_refcnt, rt->rt_use); ! 310: if (rt->rt_ifp == 0) { ! 311: putchar('\n'); ! 312: return; ! 313: } ! 314: kget(rt->rt_ifp, ifnet); ! 315: kvm_read((off_t)ifnet.if_name, name, 16); ! 316: printf(" %.15s%d\n", name, ifnet.if_unit); ! 317: } ! 318: ! 319: p_ortentry(rt) ! 320: register struct ortentry *rt; ! 321: { ! 322: char name[16], *flags; ! 323: register struct bits *p; ! 324: register struct sockaddr_in *sin; ! 325: struct ifnet ifnet; ! 326: ! 327: p_sockaddr(&rt->rt_dst, rt->rt_flags, 16); ! 328: p_sockaddr(&rt->rt_gateway, 0, 18); ! 329: p_flags(rt->rt_flags, "%-6.6s "); ! 330: printf("%6d %8d ", rt->rt_refcnt, rt->rt_use); ! 331: if (rt->rt_ifp == 0) { ! 332: putchar('\n'); ! 333: return; ! 334: } ! 335: kget(rt->rt_ifp, ifnet); ! 336: kvm_read((off_t)ifnet.if_name, name, 16); ! 337: printf(" %.15s%d\n", name, ifnet.if_unit); ! 338: } ! 339: ! 340: char * ! 341: routename(in) ! 342: struct in_addr in; ! 343: { ! 344: register char *cp; ! 345: static char line[MAXHOSTNAMELEN + 1]; ! 346: struct hostent *hp; ! 347: static char domain[MAXHOSTNAMELEN + 1]; ! 348: static int first = 1; ! 349: char *index(); ! 350: ! 351: if (first) { ! 352: first = 0; ! 353: if (gethostname(domain, MAXHOSTNAMELEN) == 0 && ! 354: (cp = index(domain, '.'))) ! 355: (void) strcpy(domain, cp + 1); ! 356: else ! 357: domain[0] = 0; ! 358: } ! 359: cp = 0; ! 360: if (!nflag) { ! 361: hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), ! 362: AF_INET); ! 363: if (hp) { ! 364: if ((cp = index(hp->h_name, '.')) && ! 365: !strcmp(cp + 1, domain)) ! 366: *cp = 0; ! 367: cp = hp->h_name; ! 368: } ! 369: } ! 370: if (cp) ! 371: strncpy(line, cp, sizeof(line) - 1); ! 372: else { ! 373: #define C(x) ((x) & 0xff) ! 374: in.s_addr = ntohl(in.s_addr); ! 375: sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), ! 376: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); ! 377: } ! 378: return (line); ! 379: } ! 380: ! 381: /* ! 382: * Return the name of the network whose address is given. ! 383: * The address is assumed to be that of a net or subnet, not a host. ! 384: */ ! 385: char * ! 386: netname(in, mask) ! 387: struct in_addr in; ! 388: u_long mask; ! 389: { ! 390: char *cp = 0; ! 391: static char line[MAXHOSTNAMELEN + 1]; ! 392: struct netent *np = 0; ! 393: u_long net; ! 394: register i; ! 395: int subnetshift; ! 396: ! 397: i = ntohl(in.s_addr); ! 398: if (!nflag && i) { ! 399: if (mask == 0) { ! 400: if (IN_CLASSA(i)) { ! 401: mask = IN_CLASSA_NET; ! 402: subnetshift = 8; ! 403: } else if (IN_CLASSB(i)) { ! 404: mask = IN_CLASSB_NET; ! 405: subnetshift = 8; ! 406: } else { ! 407: mask = IN_CLASSC_NET; ! 408: subnetshift = 4; ! 409: } ! 410: /* ! 411: * If there are more bits than the standard mask ! 412: * would suggest, subnets must be in use. ! 413: * Guess at the subnet mask, assuming reasonable ! 414: * width subnet fields. ! 415: */ ! 416: while (i &~ mask) ! 417: mask = (long)mask >> subnetshift; ! 418: } ! 419: net = i & mask; ! 420: while ((mask & 1) == 0) ! 421: mask >>= 1, net >>= 1; ! 422: np = getnetbyaddr(net, AF_INET); ! 423: if (np) ! 424: cp = np->n_name; ! 425: } ! 426: if (cp) ! 427: strncpy(line, cp, sizeof(line) - 1); ! 428: else if ((i & 0xffffff) == 0) ! 429: sprintf(line, "%u", C(i >> 24)); ! 430: else if ((i & 0xffff) == 0) ! 431: sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16)); ! 432: else if ((i & 0xff) == 0) ! 433: sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8)); ! 434: else ! 435: sprintf(line, "%u.%u.%u.%u", C(i >> 24), ! 436: C(i >> 16), C(i >> 8), C(i)); ! 437: return (line); ! 438: } ! 439: ! 440: /* ! 441: * Print routing statistics ! 442: */ ! 443: rt_stats(off) ! 444: off_t off; ! 445: { ! 446: struct rtstat rtstat; ! 447: ! 448: if (off == 0) { ! 449: printf("rtstat: symbol not in namelist\n"); ! 450: return; ! 451: } ! 452: kvm_read(off, (char *)&rtstat, sizeof (rtstat)); ! 453: printf("routing:\n"); ! 454: printf("\t%u bad routing redirect%s\n", ! 455: rtstat.rts_badredirect, plural(rtstat.rts_badredirect)); ! 456: printf("\t%u dynamically created route%s\n", ! 457: rtstat.rts_dynamic, plural(rtstat.rts_dynamic)); ! 458: printf("\t%u new gateway%s due to redirects\n", ! 459: rtstat.rts_newgateway, plural(rtstat.rts_newgateway)); ! 460: printf("\t%u destination%s found unreachable\n", ! 461: rtstat.rts_unreach, plural(rtstat.rts_unreach)); ! 462: printf("\t%u use%s of a wildcard route\n", ! 463: rtstat.rts_wildcard, plural(rtstat.rts_wildcard)); ! 464: } ! 465: short ns_nullh[] = {0,0,0}; ! 466: short ns_bh[] = {-1,-1,-1}; ! 467: ! 468: char * ! 469: ns_print(sns) ! 470: struct sockaddr_ns *sns; ! 471: { ! 472: struct ns_addr work; ! 473: union { union ns_net net_e; u_long long_e; } net; ! 474: u_short port; ! 475: static char mybuf[50], cport[10], chost[25]; ! 476: char *host = ""; ! 477: register char *p; register u_char *q; ! 478: ! 479: work = sns->sns_addr; ! 480: port = ntohs(work.x_port); ! 481: work.x_port = 0; ! 482: net.net_e = work.x_net; ! 483: if (ns_nullhost(work) && net.long_e == 0) { ! 484: if (port ) { ! 485: sprintf(mybuf, "*.%xH", port); ! 486: upHex(mybuf); ! 487: } else ! 488: sprintf(mybuf, "*.*"); ! 489: return (mybuf); ! 490: } ! 491: ! 492: if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) { ! 493: host = "any"; ! 494: } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) { ! 495: host = "*"; ! 496: } else { ! 497: q = work.x_host.c_host; ! 498: sprintf(chost, "%02x%02x%02x%02x%02x%02xH", ! 499: q[0], q[1], q[2], q[3], q[4], q[5]); ! 500: for (p = chost; *p == '0' && p < chost + 12; p++); ! 501: host = p; ! 502: } ! 503: if (port) ! 504: sprintf(cport, ".%xH", htons(port)); ! 505: else ! 506: *cport = 0; ! 507: ! 508: sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport); ! 509: upHex(mybuf); ! 510: return(mybuf); ! 511: } ! 512: ! 513: char * ! 514: ns_phost(sns) ! 515: struct sockaddr_ns *sns; ! 516: { ! 517: struct sockaddr_ns work; ! 518: static union ns_net ns_zeronet; ! 519: char *p; ! 520: ! 521: work = *sns; ! 522: work.sns_addr.x_port = 0; ! 523: work.sns_addr.x_net = ns_zeronet; ! 524: ! 525: p = ns_print(&work); ! 526: if (strncmp("0H.", p, 3) == 0) p += 3; ! 527: return(p); ! 528: } ! 529: upHex(p0) ! 530: char *p0; ! 531: { ! 532: register char *p = p0; ! 533: for (; *p; p++) switch (*p) { ! 534: ! 535: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ! 536: *p += ('A' - 'a'); ! 537: } ! 538: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.