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