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, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)route.c 5.20 (Berkeley) 11/29/90"; 36 #endif /* not lint */ 37 38 #include <sys/param.h> 39 #include <sys/socket.h> 40 #include <sys/mbuf.h> 41 42 #include <net/if.h> 43 #define KERNEL 44 #include <net/route.h> 45 #undef KERNEL 46 #include <netinet/in.h> 47 48 #ifdef NS 49 #include <netns/ns.h> 50 #endif 51 52 #ifdef ISO 53 #include <netiso/iso.h> 54 #include <net/if_dl.h> 55 #include <netiso/iso_snpac.h> 56 #endif 57 58 #include <netdb.h> 59 #include <sys/kinfo.h> 60 61 #include <stdio.h> 62 #include <string.h> 63 64 extern int nflag, aflag, Aflag, af; 65 int do_rtent; 66 extern char *routename(), *netname(), *plural(); 67 #ifdef NS 68 extern char *ns_print(); 69 #endif 70 extern char *malloc(); 71 #define kget(p, d) \ 72 (kvm_read((off_t)(p), (char *)&(d), sizeof (d))) 73 74 /* 75 * Definitions for showing gateway flags. 76 */ 77 struct bits { 78 short b_mask; 79 char b_val; 80 } bits[] = { 81 { RTF_UP, 'U' }, 82 { RTF_GATEWAY, 'G' }, 83 { RTF_HOST, 'H' }, 84 { RTF_DYNAMIC, 'D' }, 85 { RTF_MODIFIED, 'M' }, 86 { RTF_CLONING, 'C' }, 87 { RTF_XRESOLVE, 'X' }, 88 { RTF_LLINFO, 'L' }, 89 { RTF_REJECT, 'R' }, 90 { 0 } 91 }; 92 93 #ifdef ISO 94 struct bits2 { 95 short b_mask; 96 char b_val; 97 } bits2[] = { 98 { SNPA_ES, 'E' }, 99 { SNPA_IS, 'I' }, 100 { SNPA_PERM, 'P' }, 101 { 0 } 102 }; 103 #endif 104 105 /* 106 * Print routing tables. 107 */ 108 routepr(hostaddr, netaddr, hashsizeaddr, treeaddr) 109 off_t hostaddr, netaddr, hashsizeaddr, treeaddr; 110 { 111 struct mbuf mb; 112 register struct ortentry *rt; 113 register struct mbuf *m; 114 char name[16], *flags; 115 struct mbuf **routehash; 116 int hashsize; 117 int i, doinghost = 1; 118 119 printf("Routing tables\n"); 120 if (treeaddr) 121 return treestuff(treeaddr); 122 if (hostaddr == 0) { 123 printf("rthost: symbol not in namelist\n"); 124 return; 125 } 126 if (netaddr == 0) { 127 printf("rtnet: symbol not in namelist\n"); 128 return; 129 } 130 if (hashsizeaddr == 0) { 131 printf("rthashsize: symbol not in namelist\n"); 132 return; 133 } 134 kget(hashsizeaddr, hashsize); 135 routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) ); 136 kvm_read(hostaddr, (char *)routehash, hashsize*sizeof (struct mbuf *)); 137 again: 138 for (i = 0; i < hashsize; i++) { 139 if (routehash[i] == 0) 140 continue; 141 m = routehash[i]; 142 while (m) { 143 kget(m, mb); 144 if (Aflag) 145 printf("%8.8x ", m); 146 p_ortentry((struct ortentry *)(mb.m_dat)); 147 m = mb.m_next; 148 } 149 } 150 if (doinghost) { 151 kvm_read(netaddr, (char *)routehash, 152 hashsize*sizeof (struct mbuf *)); 153 doinghost = 0; 154 goto again; 155 } 156 free((char *)routehash); 157 return; 158 } 159 160 161 char * 162 af_name(af) 163 { 164 static char buf[10]; 165 166 switch(af) { 167 case AF_INET: 168 return "inet"; 169 case AF_UNIX: 170 return "unix"; 171 case AF_NS: 172 return "ns"; 173 case AF_ISO: 174 return "iso"; 175 default: 176 sprintf(buf, "%d", af); 177 } 178 return buf; 179 } 180 181 void 182 p_heading(af) 183 { 184 if (Aflag) 185 printf("%-8.8s ","Address"); 186 switch(af) { 187 case AF_INET: 188 printf("%-16.16s %-18.18s %-6.6s %6.6s %8.8s %s\n", 189 "Destination", "Gateway", 190 "Flags", "Refs", "Use", "Interface"); 191 break; 192 case AF_ISO: 193 if (nflag) { 194 printf("%-50.50s %-17.17s %-5.5s %s\n", 195 "Destination", "Media addr", "Flags", "Intf"); 196 } else { 197 printf("%-12.12s %-19.19s %-17.17s %-6.6s %6s %8s %s\n", 198 "NSAP-prefix", "Area/Id", "Media addr", 199 "Flags", "Refs", "Use", "Intf"); 200 } 201 break; 202 default: 203 printf("%-16.16s %-18.18s %-6.6s %6.6s%8.8s %s\n", 204 "Destination", "Gateway", 205 "Flags", "Refs", "Use", "Interface"); 206 } 207 } 208 209 210 static union { 211 struct sockaddr u_sa; 212 u_short u_data[128]; 213 } pt_u; 214 int do_rtent = 0; 215 struct rtentry rtentry; 216 struct radix_node rnode; 217 struct radix_mask rmask; 218 219 int NewTree = 0; 220 treestuff(rtree) 221 off_t rtree; 222 { 223 struct radix_node_head *rnh, head; 224 225 if (Aflag == 0 && NewTree) 226 return(ntreestuff()); 227 for (kget(rtree, rnh); rnh; rnh = head.rnh_next) { 228 kget(rnh, head); 229 if (head.rnh_af == 0) { 230 if (Aflag || af == AF_UNSPEC) { 231 printf("Netmasks:\n"); 232 p_tree(head.rnh_treetop); 233 } 234 } else if (af == AF_UNSPEC || af == head.rnh_af) { 235 printf("\nRoute Tree for Protocol Family %s:\n", 236 af_name(head.rnh_af)); 237 p_heading(head.rnh_af); 238 do_rtent = 1; 239 p_tree(head.rnh_treetop); 240 } 241 } 242 } 243 244 struct sockaddr * 245 kgetsa(dst) 246 register struct sockaddr *dst; 247 { 248 kget(dst, pt_u.u_sa); 249 if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) { 250 kvm_read((off_t)dst, pt_u.u_data, pt_u.u_sa.sa_len); 251 } 252 return (&pt_u.u_sa); 253 } 254 255 p_tree(rn) 256 struct radix_node *rn; 257 { 258 259 again: 260 kget(rn, rnode); 261 if (rnode.rn_b < 0) { 262 if (Aflag) 263 printf("%-8.8x ", rn); 264 if (rnode.rn_flags & RNF_ROOT) 265 printf("(root node)%s", 266 rnode.rn_dupedkey ? " =>\n" : "\n"); 267 else if (do_rtent) { 268 kget(rn, rtentry); 269 p_rtentry(&rtentry); 270 if (Aflag) 271 p_rtnode(); 272 } else { 273 p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key), 274 0, 44); 275 putchar('\n'); 276 } 277 if (rn = rnode.rn_dupedkey) 278 goto again; 279 } else { 280 if (Aflag && do_rtent) { 281 printf("%-8.8x ", rn); 282 p_rtnode(); 283 } 284 rn = rnode.rn_r; 285 p_tree(rnode.rn_l); 286 p_tree(rn); 287 } 288 } 289 char nbuf[20]; 290 291 p_rtnode() 292 { 293 294 struct radix_mask *rm = rnode.rn_mklist; 295 if (rnode.rn_b < 0) { 296 if (rnode.rn_mask) { 297 printf("\t mask "); 298 p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask), 299 0, -1); 300 } else if (rm == 0) 301 return; 302 } else { 303 sprintf(nbuf, "(%d)", rnode.rn_b); 304 printf("%6.6s %8.8x : %8.8x", nbuf, rnode.rn_l, rnode.rn_r); 305 } 306 while (rm) { 307 kget(rm, rmask); 308 sprintf(nbuf, " %d refs, ", rmask.rm_refs); 309 printf(" mk = %8.8x {(%d),%s", 310 rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " "); 311 p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), 0, -1); 312 putchar('}'); 313 if (rm = rmask.rm_mklist) 314 printf(" ->"); 315 } 316 putchar('\n'); 317 } 318 319 ntreestuff() 320 { 321 int needed; 322 char *buf, *next, *lim; 323 register struct rt_msghdr *rtm; 324 325 if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0) 326 { perror("route-getkerninfo-estimate"); exit(1);} 327 if ((buf = malloc(needed)) == 0) 328 { printf("out of space\n"); exit(1);} 329 if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0) 330 { perror("actual retrieval of routing table"); exit(1);} 331 lim = buf + needed; 332 for (next = buf; next < lim; next += rtm->rtm_msglen) { 333 rtm = (struct rt_msghdr *)next; 334 np_rtentry(rtm); 335 } 336 } 337 338 np_rtentry(rtm) 339 register struct rt_msghdr *rtm; 340 { 341 register struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 342 static int masks_done, old_af, banner_printed; 343 int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; 344 345 #ifdef notdef 346 /* for the moment, netmasks are skipped over */ 347 if (!banner_printed) { 348 printf("Netmasks:\n"); 349 banner_printed = 1; 350 } 351 if (masks_done == 0) { 352 if (rtm->rtm_addrs != RTA_DST ) { 353 masks_done = 1; 354 af = sa->sa_family; 355 } 356 } else 357 #endif 358 af = sa->sa_family; 359 if (af != old_af) { 360 printf("\nRoute Tree for Protocol Family %d:\n", af); 361 old_af = af; 362 } 363 if (rtm->rtm_addrs == RTA_DST) 364 p_sockaddr(sa, 0, 36); 365 else { 366 p_sockaddr(sa, rtm->rtm_flags, 16); 367 if (sa->sa_len == 0) 368 sa->sa_len = sizeof(long); 369 sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 370 p_sockaddr(sa, 0, 18); 371 } 372 p_flags(rtm->rtm_flags & interesting, "%-6.6s "); 373 putchar('\n'); 374 } 375 376 #ifdef ISO 377 extern char* dl_print(); 378 #endif 379 380 p_sockaddr(sa, flags, width) 381 struct sockaddr *sa; 382 int flags, width; 383 { 384 char format[20], workbuf[128], *cp, *cplim; 385 register char *cpout; 386 387 switch(sa->sa_family) { 388 case AF_INET: 389 { 390 register struct sockaddr_in *sin = (struct sockaddr_in *)sa; 391 392 cp = (sin->sin_addr.s_addr == 0) ? "default" : 393 ((flags & RTF_HOST) ? 394 routename(sin->sin_addr) : netname(sin->sin_addr, 0L)); 395 } 396 break; 397 398 #ifdef NS 399 case AF_NS: 400 cp = ns_print((struct sockaddr_ns *)sa); 401 break; 402 #endif 403 #ifdef ISO 404 case AF_ISO: 405 cp = iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr); 406 break; 407 408 case AF_LINK: 409 cp = dl_print((struct sockaddr_dl *)sa); 410 break; 411 #endif 412 413 default: 414 { 415 register u_short *s = ((u_short *)sa->sa_data), *slim; 416 417 slim = (u_short *) sa + ((sa->sa_len + sizeof(u_short) - 1) / 418 sizeof(u_short)); 419 cp = workbuf; 420 cplim = cp + sizeof(workbuf) - 6; 421 cp += sprintf(cp, "(%d)", sa->sa_family); 422 while (s < slim && cp < cplim) 423 cp += sprintf(cp, " %x", *s++); 424 cp = workbuf; 425 } 426 } 427 if (width < 0 ) 428 printf("%s ", cp); 429 else { 430 if (nflag) 431 printf("%-*s ", width, cp); 432 else 433 printf("%-*.*s ", width, width, cp); 434 } 435 } 436 437 p_flags(f, format) 438 register int f; 439 char *format; 440 { 441 char name[33], *flags; 442 register struct bits *p = bits; 443 for (flags = name; p->b_mask; p++) 444 if (p->b_mask & f) 445 *flags++ = p->b_val; 446 *flags = '\0'; 447 printf(format, name); 448 } 449 450 451 #ifdef ISO 452 453 p_iso_flags(f, lli, format) 454 register int f; 455 char *format; 456 caddr_t lli; 457 { 458 struct llinfo_llc ls; 459 char name[33], *flags; 460 register struct bits *p = bits; 461 register struct bits2 *p2 = bits2; 462 463 for (flags = name; p->b_mask; p++) 464 if (p->b_mask & f) 465 *flags++ = p->b_val; 466 if (lli) { 467 kget(lli, ls); 468 for (; p2->b_mask; p2++) 469 if (p2->b_mask & ls.lc_flags) 470 *flags++ = p2->b_val; 471 } 472 *flags = '\0'; 473 printf(format, name); 474 } 475 476 static char *hexlist = "0123456789abcdef"; 477 478 char * 479 iso_areatoa(isoa) 480 const struct iso_addr *isoa; 481 { 482 static char obuf[16]; 483 register char *out = obuf; 484 register int i; 485 /* Assumption: ISO address always with 2 byte area, 1 byte NSEL */ 486 /* and 6 bytes ID */ 487 register u_char *in = (u_char*)isoa->isoa_genaddr + isoa->isoa_len - 9; 488 u_char *inlim = in + 2; 489 490 if (isoa->isoa_len < 10) return ""; 491 while (in < inlim) { 492 i = *in++; 493 out[1] = hexlist[i & 0xf]; 494 i >>= 4; 495 out[0] = hexlist[i]; 496 out += 2; 497 } 498 *out = 0; 499 return(obuf); 500 } 501 502 char * 503 iso_idtoa(isoa) 504 const struct iso_addr *isoa; 505 { 506 static char obuf[16]; 507 register char *out = obuf; 508 register int i; 509 /* Assumption: ISO address always with 1 byte NSEL and 6 bytes ID */ 510 register u_char *in = (u_char*)isoa->isoa_genaddr + isoa->isoa_len - 7; 511 u_char *inlim = in + 6; 512 513 if (isoa->isoa_len < 10) return ""; 514 out[1] = 0; 515 while (in < inlim) { 516 i = *in++; 517 if ((inlim - in) % 2 || out == obuf) 518 *out++ = '.'; 519 out[1] = hexlist[i & 0xf]; 520 i >>= 4; 521 out[0] = hexlist[i]; 522 out += 2; 523 } 524 *out = 0; 525 return(obuf + 1); 526 } 527 528 p_iso_route(rt, sa) 529 struct rtentry *rt; 530 struct sockaddr *sa; 531 { 532 struct sockaddr_iso *siso = (struct sockaddr_iso *)sa; 533 534 if (nflag) { 535 p_sockaddr(sa, rt->rt_flags, 50); 536 p_sockaddr(kgetsa(rt->rt_gateway), 0, 17); 537 p_iso_flags(rt->rt_flags, rt->rt_llinfo, "%-6.6s"); 538 p_interface_nl(rt); 539 } else { 540 p_sockaddr(sa, rt->rt_flags, 12); 541 printf("%4.4s/%14.14s ", 542 iso_areatoa(&siso->siso_addr), 543 iso_idtoa(&siso->siso_addr)); 544 p_sockaddr(kgetsa(rt->rt_gateway), 0, 17); 545 p_iso_flags(rt->rt_flags, rt->rt_llinfo, "%-6.6s "); 546 printf("%6d %8d", rt->rt_refcnt, rt->rt_use); 547 p_interface_nl(rt); 548 } 549 } 550 #endif /* ISO */ 551 552 p_interface_nl(rt) 553 struct rtentry *rt; 554 { 555 struct ifnet ifnet; 556 char name[16]; 557 558 if (rt->rt_ifp == 0) { 559 putchar('\n'); 560 return; 561 } 562 kget(rt->rt_ifp, ifnet); 563 kvm_read((off_t)ifnet.if_name, name, 16); 564 printf(" %.15s%d%s", name, ifnet.if_unit, 565 rt->rt_nodes[0].rn_dupedkey ? " =>\n" : "\n"); 566 } 567 568 p_rtentry(rt) 569 register struct rtentry *rt; 570 { 571 struct sockaddr *sa; 572 573 sa = kgetsa(rt_key(rt)); 574 if (sa->sa_family == AF_ISO) { 575 p_iso_route(rt, sa); 576 return; 577 } 578 p_sockaddr(sa, rt->rt_flags, 16); 579 p_sockaddr(kgetsa(rt->rt_gateway), RTF_HOST, 18); 580 p_flags(rt->rt_flags, "%-6.6s "); 581 printf("%6d %8d ", rt->rt_refcnt, rt->rt_use); 582 p_interface_nl(rt); 583 } 584 585 p_ortentry(rt) 586 register struct ortentry *rt; 587 { 588 char name[16], *flags; 589 register struct bits *p; 590 register struct sockaddr_in *sin; 591 struct ifnet ifnet; 592 593 p_sockaddr(&rt->rt_dst, rt->rt_flags, 16); 594 p_sockaddr(&rt->rt_gateway, 0, 18); 595 p_flags(rt->rt_flags, "%-6.6s "); 596 printf("%6d %8d ", rt->rt_refcnt, rt->rt_use); 597 if (rt->rt_ifp == 0) { 598 putchar('\n'); 599 return; 600 } 601 kget(rt->rt_ifp, ifnet); 602 kvm_read((off_t)ifnet.if_name, name, 16); 603 printf(" %.15s%d\n", name, ifnet.if_unit); 604 } 605 606 char * 607 routename(in) 608 struct in_addr in; 609 { 610 register char *cp; 611 static char line[MAXHOSTNAMELEN + 1]; 612 struct hostent *hp; 613 static char domain[MAXHOSTNAMELEN + 1]; 614 static int first = 1; 615 char *index(); 616 617 if (first) { 618 first = 0; 619 if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 620 (cp = index(domain, '.'))) 621 (void) strcpy(domain, cp + 1); 622 else 623 domain[0] = 0; 624 } 625 cp = 0; 626 if (!nflag) { 627 hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), 628 AF_INET); 629 if (hp) { 630 if ((cp = index(hp->h_name, '.')) && 631 !strcmp(cp + 1, domain)) 632 *cp = 0; 633 cp = hp->h_name; 634 } 635 } 636 if (cp) 637 strncpy(line, cp, sizeof(line) - 1); 638 else { 639 #define C(x) ((x) & 0xff) 640 in.s_addr = ntohl(in.s_addr); 641 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 642 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 643 } 644 return (line); 645 } 646 647 /* 648 * Return the name of the network whose address is given. 649 * The address is assumed to be that of a net or subnet, not a host. 650 */ 651 char * 652 netname(in, mask) 653 struct in_addr in; 654 u_long mask; 655 { 656 char *cp = 0; 657 static char line[MAXHOSTNAMELEN + 1]; 658 struct netent *np = 0; 659 u_long net; 660 register i; 661 int subnetshift; 662 663 i = ntohl(in.s_addr); 664 if (!nflag && i) { 665 if (mask == 0) { 666 if (IN_CLASSA(i)) { 667 mask = IN_CLASSA_NET; 668 subnetshift = 8; 669 } else if (IN_CLASSB(i)) { 670 mask = IN_CLASSB_NET; 671 subnetshift = 8; 672 } else { 673 mask = IN_CLASSC_NET; 674 subnetshift = 4; 675 } 676 /* 677 * If there are more bits than the standard mask 678 * would suggest, subnets must be in use. 679 * Guess at the subnet mask, assuming reasonable 680 * width subnet fields. 681 */ 682 while (i &~ mask) 683 mask = (long)mask >> subnetshift; 684 } 685 net = i & mask; 686 while ((mask & 1) == 0) 687 mask >>= 1, net >>= 1; 688 np = getnetbyaddr(net, AF_INET); 689 if (np) 690 cp = np->n_name; 691 } 692 if (cp) 693 strncpy(line, cp, sizeof(line) - 1); 694 else if ((i & 0xffffff) == 0) 695 sprintf(line, "%u", C(i >> 24)); 696 else if ((i & 0xffff) == 0) 697 sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16)); 698 else if ((i & 0xff) == 0) 699 sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8)); 700 else 701 sprintf(line, "%u.%u.%u.%u", C(i >> 24), 702 C(i >> 16), C(i >> 8), C(i)); 703 return (line); 704 } 705 706 /* 707 * Print routing statistics 708 */ 709 rt_stats(off) 710 off_t off; 711 { 712 struct rtstat rtstat; 713 714 if (off == 0) { 715 printf("rtstat: symbol not in namelist\n"); 716 return; 717 } 718 kvm_read(off, (char *)&rtstat, sizeof (rtstat)); 719 printf("routing:\n"); 720 printf("\t%u bad routing redirect%s\n", 721 rtstat.rts_badredirect, plural(rtstat.rts_badredirect)); 722 printf("\t%u dynamically created route%s\n", 723 rtstat.rts_dynamic, plural(rtstat.rts_dynamic)); 724 printf("\t%u new gateway%s due to redirects\n", 725 rtstat.rts_newgateway, plural(rtstat.rts_newgateway)); 726 printf("\t%u destination%s found unreachable\n", 727 rtstat.rts_unreach, plural(rtstat.rts_unreach)); 728 printf("\t%u use%s of a wildcard route\n", 729 rtstat.rts_wildcard, plural(rtstat.rts_wildcard)); 730 } 731 #ifdef NS 732 short ns_nullh[] = {0,0,0}; 733 short ns_bh[] = {-1,-1,-1}; 734 735 char * 736 ns_print(sns) 737 struct sockaddr_ns *sns; 738 { 739 struct ns_addr work; 740 union { union ns_net net_e; u_long long_e; } net; 741 u_short port; 742 static char mybuf[50], cport[10], chost[25]; 743 char *host = ""; 744 register char *p; register u_char *q; 745 746 work = sns->sns_addr; 747 port = ntohs(work.x_port); 748 work.x_port = 0; 749 net.net_e = work.x_net; 750 if (ns_nullhost(work) && net.long_e == 0) { 751 if (port ) { 752 sprintf(mybuf, "*.%xH", port); 753 upHex(mybuf); 754 } else 755 sprintf(mybuf, "*.*"); 756 return (mybuf); 757 } 758 759 if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) { 760 host = "any"; 761 } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) { 762 host = "*"; 763 } else { 764 q = work.x_host.c_host; 765 sprintf(chost, "%02x%02x%02x%02x%02x%02xH", 766 q[0], q[1], q[2], q[3], q[4], q[5]); 767 for (p = chost; *p == '0' && p < chost + 12; p++); 768 host = p; 769 } 770 if (port) 771 sprintf(cport, ".%xH", htons(port)); 772 else 773 *cport = 0; 774 775 sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport); 776 upHex(mybuf); 777 return(mybuf); 778 } 779 780 char * 781 ns_phost(sns) 782 struct sockaddr_ns *sns; 783 { 784 struct sockaddr_ns work; 785 static union ns_net ns_zeronet; 786 char *p; 787 788 work = *sns; 789 work.sns_addr.x_port = 0; 790 work.sns_addr.x_net = ns_zeronet; 791 792 p = ns_print(&work); 793 if (strncmp("0H.", p, 3) == 0) p += 3; 794 return(p); 795 } 796 upHex(p0) 797 char *p0; 798 { 799 register char *p = p0; 800 for (; *p; p++) switch (*p) { 801 802 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 803 *p += ('A' - 'a'); 804 } 805 } 806 #endif /* NS */ 807 #ifdef ISO 808 809 char * 810 dl_print(sdl) 811 struct sockaddr_dl *sdl; 812 { 813 static char buf[20]; 814 char *cp = buf, *dp; 815 int i; 816 817 dp = sdl->sdl_data; 818 for (i = 0; i < sdl->sdl_nlen; i++) 819 *cp++ = *dp++; 820 if (sdl->sdl_nlen != 0 && sdl->sdl_alen != 0) 821 *cp++ = ':'; 822 for (; i < sdl->sdl_nlen + sdl->sdl_alen; i++) 823 cp += sprintf(cp, "%x%c", *dp++ & 0xff, 824 i + 1 == sdl->sdl_nlen + sdl->sdl_alen ? ' ' : '.'); 825 *cp = 0; 826 return buf; 827 } 828 #endif /* ISO */ 829