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