1 /* $NetBSD: route.c,v 1.106 2007/02/18 01:48:37 hubertf Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1989, 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1991, 1993\n\ 35 The Regents of the University of California. All rights reserved.\n"); 36 #endif /* not lint */ 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95"; 41 #else 42 __RCSID("$NetBSD: route.c,v 1.106 2007/02/18 01:48:37 hubertf Exp $"); 43 #endif 44 #endif /* not lint */ 45 46 #include <sys/param.h> 47 #include <sys/file.h> 48 #include <sys/socket.h> 49 #include <sys/ioctl.h> 50 #include <sys/mbuf.h> 51 #include <sys/sysctl.h> 52 53 #include <net/if.h> 54 #include <net/route.h> 55 #include <net/if_dl.h> 56 #include <net80211/ieee80211_netbsd.h> 57 #include <netinet/in.h> 58 #include <netatalk/at.h> 59 #include <netiso/iso.h> 60 #include <arpa/inet.h> 61 #include <netdb.h> 62 63 #include <errno.h> 64 #include <unistd.h> 65 #include <stdio.h> 66 #include <ctype.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include <time.h> 70 #include <paths.h> 71 #include <err.h> 72 73 #include "keywords.h" 74 #include "extern.h" 75 76 typedef union sockunion *sup; 77 78 static char *any_ntoa(const struct sockaddr *); 79 static const char *route_strerror(int); 80 static void set_metric(char *, int); 81 static int newroute(int, char **); 82 static void inet_makenetandmask(u_int32_t, struct sockaddr_in *); 83 #ifdef INET6 84 static int inet6_makenetandmask(struct sockaddr_in6 *); 85 #endif 86 static int getaddr(int, char *, struct hostent **); 87 static int flushroutes(int, char *[], int); 88 static int prefixlen(const char *); 89 #ifndef SMALL 90 static void interfaces(void); 91 static void monitor(void); 92 static int print_getmsg(struct rt_msghdr *, int); 93 static const char *linkstate(struct if_msghdr *); 94 #endif /* SMALL */ 95 static int rtmsg(int, int ); 96 static void mask_addr(void); 97 static void print_rtmsg(struct rt_msghdr *, int); 98 static void pmsg_common(struct rt_msghdr *); 99 static void pmsg_addrs(char *, int); 100 static void bprintf(FILE *, int, const char *); 101 static void sodump(sup, const char *); 102 static void sockaddr(char *, struct sockaddr *); 103 104 union sockunion { 105 struct sockaddr sa; 106 struct sockaddr_in sin; 107 #ifdef INET6 108 struct sockaddr_in6 sin6; 109 #endif 110 struct sockaddr_at sat; 111 struct sockaddr_dl sdl; 112 #ifndef SMALL 113 struct sockaddr_iso siso; 114 #endif /* SMALL */ 115 } so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; 116 117 int pid, rtm_addrs; 118 int sock; 119 int forcehost, forcenet, doflush, nflag, af, qflag, tflag, Sflag; 120 int iflag, verbose, aflen = sizeof(struct sockaddr_in); 121 int locking, lockrest, debugonly, shortoutput; 122 struct rt_metrics rt_metrics; 123 u_int32_t rtm_inits; 124 short ns_nullh[] = {0,0,0}; 125 short ns_bh[] = {-1,-1,-1}; 126 127 128 void 129 usage(const char *cp) 130 { 131 132 if (cp) 133 warnx("botched keyword: %s", cp); 134 (void)fprintf(stderr, 135 "Usage: %s [ -fnqSsv ] cmd [[ -<qualifers> ] args ]\n", 136 getprogname()); 137 exit(1); 138 /* NOTREACHED */ 139 } 140 141 #define PRIETHER "02x:%02x:%02x:%02x:%02x:%02x" 142 #define PRIETHER_ARGS(__enaddr) (__enaddr)[0], (__enaddr)[1], (__enaddr)[2], \ 143 (__enaddr)[3], (__enaddr)[4], (__enaddr)[5] 144 #define ROUNDUP(a) \ 145 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 146 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 147 148 int 149 main(int argc, char **argv) 150 { 151 int ch; 152 153 if (argc < 2) 154 usage(NULL); 155 156 while ((ch = getopt(argc, argv, "dfnqSstv")) != -1) 157 switch (ch) { 158 case 'd': 159 debugonly = 1; 160 break; 161 case 'f': 162 doflush = 1; 163 break; 164 case 'n': 165 nflag = 1; 166 break; 167 case 'q': 168 qflag = 1; 169 break; 170 case 'S': 171 Sflag = 1; 172 break; 173 case 's': 174 shortoutput = 1; 175 break; 176 case 't': 177 tflag = 1; 178 break; 179 case 'v': 180 verbose = 1; 181 break; 182 case '?': 183 default: 184 usage(NULL); 185 /*NOTREACHED*/ 186 } 187 argc -= optind; 188 argv += optind; 189 190 pid = getpid(); 191 if (tflag) 192 sock = open("/dev/null", O_WRONLY, 0); 193 else 194 sock = socket(PF_ROUTE, SOCK_RAW, 0); 195 if (sock < 0) 196 err(EXIT_FAILURE, "socket"); 197 198 if (*argv == NULL) { 199 if (doflush) 200 ch = K_FLUSH; 201 else 202 goto no_cmd; 203 } else 204 ch = keyword(*argv); 205 206 switch (ch) { 207 #ifndef SMALL 208 case K_GET: 209 #endif /* SMALL */ 210 case K_CHANGE: 211 case K_ADD: 212 case K_DELETE: 213 if (doflush) 214 (void)flushroutes(1, argv, 0); 215 return newroute(argc, argv); 216 217 case K_SHOW: 218 show(argc, argv); 219 return 0; 220 221 #ifndef SMALL 222 case K_MONITOR: 223 monitor(); 224 return 0; 225 226 #endif /* SMALL */ 227 case K_FLUSH: 228 return flushroutes(argc, argv, 0); 229 230 case K_FLUSHALL: 231 return flushroutes(argc, argv, 1); 232 no_cmd: 233 default: 234 usage(*argv); 235 /*NOTREACHED*/ 236 } 237 } 238 239 /* 240 * Purge all entries in the routing tables not 241 * associated with network interfaces. 242 */ 243 static int 244 flushroutes(int argc, char *argv[], int doall) 245 { 246 struct sockaddr *sa; 247 size_t needed; 248 int flags, mib[6], rlen, seqno; 249 char *buf, *next, *lim; 250 const char *afname; 251 struct rt_msghdr *rtm; 252 253 flags = 0; 254 af = AF_UNSPEC; 255 shutdown(sock, SHUT_RD); /* Don't want to read back our messages */ 256 parse_show_opts(argc, argv, &af, &flags, &afname, 0); 257 mib[0] = CTL_NET; 258 mib[1] = PF_ROUTE; 259 mib[2] = 0; /* protocol */ 260 mib[3] = 0; /* wildcard address family */ 261 mib[4] = NET_RT_DUMP; 262 mib[5] = 0; /* no flags */ 263 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 264 err(EXIT_FAILURE, "route-sysctl-estimate"); 265 buf = lim = NULL; 266 if (needed) { 267 if ((buf = malloc(needed)) == NULL) 268 err(EXIT_FAILURE, "malloc"); 269 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 270 err(EXIT_FAILURE, "actual retrieval of routing table"); 271 lim = buf + needed; 272 } 273 if (verbose) { 274 (void)printf("Examining routing table from sysctl\n"); 275 if (af != AF_UNSPEC) 276 printf("(address family %s)\n", afname); 277 } 278 if (needed == 0) 279 return 0; 280 seqno = 0; /* ??? */ 281 for (next = buf; next < lim; next += rtm->rtm_msglen) { 282 rtm = (struct rt_msghdr *)next; 283 sa = (struct sockaddr *)(rtm + 1); 284 if (verbose) 285 print_rtmsg(rtm, rtm->rtm_msglen); 286 if ((rtm->rtm_flags & flags) != flags) 287 continue; 288 if (!(rtm->rtm_flags & (RTF_GATEWAY | RTF_STATIC | 289 RTF_LLINFO)) && !doall) 290 continue; 291 if (af != AF_UNSPEC && sa->sa_family != af) 292 continue; 293 if (debugonly) 294 continue; 295 rtm->rtm_type = RTM_DELETE; 296 rtm->rtm_seq = seqno; 297 if ((rlen = write(sock, next, rtm->rtm_msglen)) < 0) { 298 warnx("writing to routing socket: %s", 299 route_strerror(errno)); 300 return 1; 301 } 302 if (rlen < (int)rtm->rtm_msglen) { 303 warnx("write to routing socket, got %d for rlen", rlen); 304 return 1; 305 } 306 seqno++; 307 if (qflag) 308 continue; 309 if (verbose) 310 print_rtmsg(rtm, rlen); 311 else { 312 (void)printf("%-20.20s ", 313 routename(sa, NULL, rtm->rtm_flags)); 314 sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + 315 (char *)sa); 316 (void)printf("%-20.20s ", 317 routename(sa, NULL, RTF_HOST)); 318 (void)printf("done\n"); 319 } 320 } 321 free(buf); 322 return 0; 323 } 324 325 326 static char hexlist[] = "0123456789abcdef"; 327 328 static char * 329 any_ntoa(const struct sockaddr *sa) 330 { 331 static char obuf[3 * 256]; 332 const char *in; 333 char *out; 334 int len; 335 336 #if __GNUC__ > 2 337 len = sa->sa_len - offsetof(struct sockaddr, sa_data); 338 #else 339 len = sa->sa_len - ((struct sockaddr*)&sa->sa_data - sa); 340 #endif 341 in = sa->sa_data; 342 out = obuf; 343 344 do { 345 *out++ = hexlist[(*in >> 4) & 15]; 346 *out++ = hexlist[(*in++) & 15]; 347 *out++ = '.'; 348 } while (--len > 0); 349 out[-1] = '\0'; 350 return obuf; 351 } 352 353 int 354 netmask_length(struct sockaddr *nm, int family) 355 { 356 static int 357 /* number of bits in a nibble */ 358 _t[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }, 359 /* good nibbles are 1111, 1110, 1100, 1000, 0000 */ 360 _g[] = { 1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1 }; 361 int mask, good, zeroes, maskbytes, bit, i; 362 unsigned char *maskdata; 363 364 if (nm == NULL) 365 return 0; 366 367 mask = 0; 368 good = 1; 369 zeroes = 0; 370 371 switch (family) { 372 case AF_INET: { 373 struct sockaddr_in *nsin = (struct sockaddr_in *)nm; 374 maskdata = (unsigned char *)&nsin->sin_addr; 375 maskbytes = nsin->sin_len - 376 ((caddr_t)&nsin->sin_addr - (caddr_t)nsin); 377 break; 378 } 379 case AF_INET6: { 380 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nm; 381 maskdata = (unsigned char *)&sin6->sin6_addr; 382 maskbytes = sin6->sin6_len - 383 ((caddr_t)&sin6->sin6_addr - (caddr_t)sin6); 384 break; 385 } 386 default: 387 return 0; 388 } 389 390 /* 391 * Count the bits in the nibbles of the mask, and marking the 392 * netmask as not good (or at best, non-standard and very 393 * discouraged, in the case of AF_INET) if we find either of 394 * a nibble with non-contiguous bits, or a non-zero nibble 395 * after we've found a zero nibble. 396 */ 397 for (i = 0; i < maskbytes; i++) { 398 /* high nibble */ 399 mask += bit = _t[maskdata[i] >> 4]; 400 good &= _g[maskdata[i] >> 4]; 401 if (zeroes && bit) 402 good = 0; 403 if (bit == 0) 404 zeroes = 1; 405 /* low nibble */ 406 mask += bit = _t[maskdata[i] & 0xf]; 407 good &= _g[maskdata[i] & 0xf]; 408 if (zeroes && bit) 409 good = 0; 410 if (bit == 0) 411 zeroes = 1; 412 } 413 414 /* 415 * Always return the number of bits found, but as a negative 416 * if the mask wasn't one we like. 417 */ 418 return good ? mask : -mask; 419 } 420 421 char * 422 netmask_string(struct sockaddr *mask, int len, int family) 423 { 424 static char smask[INET6_ADDRSTRLEN]; 425 struct sockaddr_in nsin; 426 struct sockaddr_in6 nsin6; 427 428 if (len >= 0) 429 snprintf(smask, sizeof(smask), "%d", len); 430 else { 431 switch (family) { 432 case AF_INET: 433 memset(&nsin, 0, sizeof(nsin)); 434 memcpy(&nsin, mask, mask->sa_len); 435 snprintf(smask, sizeof(smask), "%s", 436 inet_ntoa(nsin.sin_addr)); 437 break; 438 case AF_INET6: 439 memset(&nsin6, 0, sizeof(nsin6)); 440 memcpy(&nsin6, mask, mask->sa_len); 441 inet_ntop(family, &nsin6.sin6_addr, smask, 442 sizeof(smask)); 443 break; 444 default: 445 snprintf(smask, sizeof(smask), "%s", any_ntoa(mask)); 446 } 447 } 448 449 return smask; 450 } 451 452 const char * 453 routename(struct sockaddr *sa, struct sockaddr *nm, int flags) 454 { 455 const char *cp; 456 static char line[50]; 457 struct hostent *hp; 458 static char domain[MAXHOSTNAMELEN + 1]; 459 static int first = 1; 460 struct in_addr in; 461 int nml; 462 463 if ((flags & RTF_HOST) == 0) 464 return netname(sa, nm); 465 466 if (first) { 467 first = 0; 468 if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 469 (cp = strchr(domain, '.'))) 470 (void)strlcpy(domain, cp + 1, sizeof(domain)); 471 else 472 domain[0] = 0; 473 } 474 475 if (sa->sa_len == 0) 476 strlcpy(line, "default", sizeof(line)); 477 else switch (sa->sa_family) { 478 479 case AF_INET: 480 in = ((struct sockaddr_in *)sa)->sin_addr; 481 nml = netmask_length(nm, AF_INET); 482 483 cp = 0; 484 if (in.s_addr == INADDR_ANY || sa->sa_len < 4) { 485 if (nml == 0) 486 cp = "default"; 487 else { 488 static char notdefault[sizeof(NOTDEFSTRING)]; 489 490 snprintf(notdefault, sizeof(notdefault), 491 "0.0.0.0/%s", 492 netmask_string(nm, nml, AF_INET)); 493 cp = notdefault; 494 } 495 } 496 if (cp == 0 && !nflag) { 497 hp = gethostbyaddr((char *)&in, sizeof(struct in_addr), 498 AF_INET); 499 if (hp) { 500 char *ccp; 501 if ((ccp = strchr(hp->h_name, '.')) && 502 !strcmp(ccp + 1, domain)) 503 *ccp = '\0'; 504 cp = hp->h_name; 505 } 506 } 507 if (cp) 508 (void)strlcpy(line, cp, sizeof(line)); 509 else 510 (void)strlcpy(line, inet_ntoa(in), sizeof(line)); 511 break; 512 513 case AF_LINK: 514 return (link_ntoa((struct sockaddr_dl *)sa)); 515 516 #ifdef INET6 517 case AF_INET6: 518 { 519 struct sockaddr_in6 sin6; 520 int niflags; 521 char nihost[NI_MAXHOST]; 522 523 niflags = 0; 524 if (nflag) 525 niflags |= NI_NUMERICHOST; 526 memset(&sin6, 0, sizeof(sin6)); 527 memcpy(&sin6, sa, sa->sa_len); 528 sin6.sin6_len = sizeof(struct sockaddr_in6); 529 sin6.sin6_family = AF_INET6; 530 #ifdef __KAME__ 531 if (sa->sa_len == sizeof(struct sockaddr_in6) && 532 (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || 533 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) && 534 sin6.sin6_scope_id == 0) { 535 sin6.sin6_scope_id = 536 ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); 537 sin6.sin6_addr.s6_addr[2] = 0; 538 sin6.sin6_addr.s6_addr[3] = 0; 539 } 540 #endif 541 nml = netmask_length(nm, AF_INET6); 542 if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)) { 543 if (nml == 0) 544 strlcpy(line, "::", sizeof(line)); 545 else 546 /* noncontiguous never happens in ipv6 */ 547 snprintf(line, sizeof(line), "::/%d", nml); 548 } 549 else if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 550 nihost, sizeof(nihost), NULL, 0, niflags) != 0) 551 strlcpy(line, "invalid", sizeof(line)); 552 else { 553 char *ccp; 554 if (!nflag && (ccp = strchr(nihost, '.')) && 555 strcmp(ccp + 1, domain) == 0) 556 *ccp = '\0'; 557 strlcpy(line, nihost, sizeof(line)); 558 } 559 break; 560 } 561 #endif 562 563 #ifndef SMALL 564 case AF_ISO: 565 (void)snprintf(line, sizeof line, "iso %s", 566 iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); 567 break; 568 569 case AF_APPLETALK: 570 (void)snprintf(line, sizeof(line), "atalk %d.%d", 571 ((struct sockaddr_at *)sa)->sat_addr.s_net, 572 ((struct sockaddr_at *)sa)->sat_addr.s_node); 573 break; 574 #endif /* SMALL */ 575 576 default: 577 (void)snprintf(line, sizeof line, "(%d) %s", 578 sa->sa_family, any_ntoa(sa)); 579 break; 580 581 } 582 return (line); 583 } 584 585 /* 586 * Return the name of the network whose address is given. 587 * The address is assumed to be that of a net or subnet, not a host. 588 */ 589 const char * 590 netname(struct sockaddr *sa, struct sockaddr *nm) 591 { 592 const char *cp = 0; 593 static char line[50]; 594 struct netent *np = 0; 595 u_int32_t net, mask; 596 u_int32_t i; 597 int subnetshift, nml; 598 struct in_addr in; 599 600 switch (sa->sa_family) { 601 602 case AF_INET: 603 in = ((struct sockaddr_in *)sa)->sin_addr; 604 i = ntohl(in.s_addr); 605 nml = netmask_length(nm, AF_INET); 606 if (i == 0) { 607 if (nml == 0) 608 cp = "default"; 609 else { 610 static char notdefault[sizeof(NOTDEFSTRING)]; 611 612 snprintf(notdefault, sizeof(notdefault), 613 "0.0.0.0/%s", 614 netmask_string(nm, nml, AF_INET)); 615 cp = notdefault; 616 } 617 } 618 else if (!nflag) { 619 if (IN_CLASSA(i)) { 620 mask = IN_CLASSA_NET; 621 subnetshift = 8; 622 } else if (IN_CLASSB(i)) { 623 mask = IN_CLASSB_NET; 624 subnetshift = 8; 625 } else { 626 mask = IN_CLASSC_NET; 627 subnetshift = 4; 628 } 629 /* 630 * If there are more bits than the standard mask 631 * would suggest, subnets must be in use. 632 * Guess at the subnet mask, assuming reasonable 633 * width subnet fields. 634 */ 635 while (i &~ mask) 636 mask = (int32_t)mask >> subnetshift; 637 net = i & mask; 638 while ((mask & 1) == 0) 639 mask >>= 1, net >>= 1; 640 np = getnetbyaddr(net, AF_INET); 641 if (np) 642 cp = np->n_name; 643 } 644 if (cp) 645 (void)strlcpy(line, cp, sizeof(line)); 646 else { 647 if (nml == 0) 648 strlcpy(line, inet_ntoa(in), sizeof(line)); 649 else if (nml < 0) { 650 snprintf(line, sizeof(line), "%s&%s", 651 inet_ntoa(in), 652 netmask_string(nm, nml, AF_INET)); 653 } else { 654 snprintf(line, sizeof(line), "%s/%d", 655 inet_ntoa(in), nml); 656 } 657 } 658 break; 659 660 case AF_LINK: 661 return (link_ntoa((struct sockaddr_dl *)sa)); 662 663 #ifdef INET6 664 case AF_INET6: 665 { 666 struct sockaddr_in6 sin6; 667 int niflags; 668 669 niflags = 0; 670 if (nflag) 671 niflags |= NI_NUMERICHOST; 672 memset(&sin6, 0, sizeof(sin6)); 673 memcpy(&sin6, sa, sa->sa_len); 674 sin6.sin6_len = sizeof(struct sockaddr_in6); 675 sin6.sin6_family = AF_INET6; 676 #ifdef __KAME__ 677 if (sa->sa_len == sizeof(struct sockaddr_in6) && 678 (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || 679 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) && 680 sin6.sin6_scope_id == 0) { 681 sin6.sin6_scope_id = 682 ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); 683 sin6.sin6_addr.s6_addr[2] = 0; 684 sin6.sin6_addr.s6_addr[3] = 0; 685 } 686 #endif 687 nml = netmask_length(nm, AF_INET6); 688 if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)) { 689 if (nml == 0) 690 strlcpy(line, "::", sizeof(line)); 691 else 692 /* noncontiguous never happens in ipv6 */ 693 snprintf(line, sizeof(line), "::/%d", nml); 694 } 695 else if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 696 line, sizeof(line), NULL, 0, niflags) != 0) 697 strlcpy(line, "invalid", sizeof(line)); 698 break; 699 } 700 #endif 701 702 #ifndef SMALL 703 case AF_ISO: 704 (void)snprintf(line, sizeof line, "iso %s", 705 iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); 706 break; 707 708 case AF_APPLETALK: 709 (void)snprintf(line, sizeof(line), "atalk %d.%d", 710 ((struct sockaddr_at *)sa)->sat_addr.s_net, 711 ((struct sockaddr_at *)sa)->sat_addr.s_node); 712 break; 713 #endif /* SMALL */ 714 715 default: 716 (void)snprintf(line, sizeof line, "af %d: %s", 717 sa->sa_family, any_ntoa(sa)); 718 break; 719 } 720 return (line); 721 } 722 723 static const char * 724 route_strerror(int error) 725 { 726 727 switch (error) { 728 case ESRCH: 729 return "not in table"; 730 case EBUSY: 731 return "entry in use"; 732 case ENOBUFS: 733 return "routing table overflow"; 734 default: 735 return strerror(error); 736 } 737 } 738 739 static void 740 set_metric(char *value, int key) 741 { 742 int flag = 0; 743 u_long noval, *valp = &noval; 744 745 switch (key) { 746 #define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break 747 caseof(K_MTU, RTV_MTU, rmx_mtu); 748 caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); 749 caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); 750 caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); 751 caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); 752 caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); 753 caseof(K_RTT, RTV_RTT, rmx_rtt); 754 caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); 755 } 756 rtm_inits |= flag; 757 if (lockrest || locking) 758 rt_metrics.rmx_locks |= flag; 759 if (locking) 760 locking = 0; 761 *valp = atoi(value); 762 } 763 764 static int 765 newroute(int argc, char **argv) 766 { 767 const char *cmd, *dest = "", *gateway = ""; 768 int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC; 769 int key; 770 struct hostent *hp = 0; 771 772 cmd = argv[0]; 773 af = AF_UNSPEC; 774 if (*cmd != 'g') 775 shutdown(sock, SHUT_RD); /* Don't want to read back our messages */ 776 while (--argc > 0) { 777 if (**(++argv)== '-') { 778 switch (key = keyword(1 + *argv)) { 779 780 case K_SA: 781 af = PF_ROUTE; 782 aflen = sizeof(union sockunion); 783 break; 784 785 #ifndef SMALL 786 case K_ATALK: 787 af = AF_APPLETALK; 788 aflen = sizeof(struct sockaddr_at); 789 break; 790 #endif 791 792 case K_INET: 793 af = AF_INET; 794 aflen = sizeof(struct sockaddr_in); 795 break; 796 797 #ifdef INET6 798 case K_INET6: 799 af = AF_INET6; 800 aflen = sizeof(struct sockaddr_in6); 801 break; 802 #endif 803 804 case K_LINK: 805 af = AF_LINK; 806 aflen = sizeof(struct sockaddr_dl); 807 break; 808 809 #ifndef SMALL 810 case K_OSI: 811 case K_ISO: 812 af = AF_ISO; 813 aflen = sizeof(struct sockaddr_iso); 814 break; 815 #endif /* SMALL */ 816 817 case K_IFACE: 818 case K_INTERFACE: 819 iflag++; 820 break; 821 case K_NOSTATIC: 822 flags &= ~RTF_STATIC; 823 break; 824 case K_LLINFO: 825 flags |= RTF_LLINFO; 826 break; 827 case K_LOCK: 828 locking = 1; 829 break; 830 case K_LOCKREST: 831 lockrest = 1; 832 break; 833 case K_HOST: 834 forcehost++; 835 break; 836 case K_REJECT: 837 flags |= RTF_REJECT; 838 break; 839 case K_BLACKHOLE: 840 flags |= RTF_BLACKHOLE; 841 break; 842 case K_CLONED: 843 flags |= RTF_CLONED; 844 break; 845 case K_NOCLONED: 846 flags &= ~RTF_CLONED; 847 break; 848 case K_PROTO1: 849 flags |= RTF_PROTO1; 850 break; 851 case K_PROTO2: 852 flags |= RTF_PROTO2; 853 break; 854 case K_CLONING: 855 flags |= RTF_CLONING; 856 break; 857 case K_NOCLONING: 858 flags &= ~RTF_CLONING; 859 break; 860 case K_XRESOLVE: 861 flags |= RTF_XRESOLVE; 862 break; 863 case K_STATIC: 864 flags |= RTF_STATIC; 865 break; 866 case K_IFA: 867 if (!--argc) 868 usage(1+*argv); 869 (void)getaddr(RTA_IFA, *++argv, 0); 870 break; 871 case K_IFP: 872 if (!--argc) 873 usage(1+*argv); 874 (void)getaddr(RTA_IFP, *++argv, 0); 875 break; 876 case K_GENMASK: 877 if (!--argc) 878 usage(1+*argv); 879 (void)getaddr(RTA_GENMASK, *++argv, 0); 880 break; 881 case K_GATEWAY: 882 if (!--argc) 883 usage(1+*argv); 884 (void)getaddr(RTA_GATEWAY, *++argv, 0); 885 break; 886 case K_DST: 887 if (!--argc) 888 usage(1+*argv); 889 ishost = getaddr(RTA_DST, *++argv, &hp); 890 dest = *argv; 891 break; 892 case K_NETMASK: 893 if (!--argc) 894 usage(1+*argv); 895 (void)getaddr(RTA_NETMASK, *++argv, 0); 896 /* FALLTHROUGH */ 897 case K_NET: 898 forcenet++; 899 break; 900 case K_PREFIXLEN: 901 if (!--argc) 902 usage(1+*argv); 903 ishost = prefixlen(*++argv); 904 break; 905 case K_MTU: 906 case K_HOPCOUNT: 907 case K_EXPIRE: 908 case K_RECVPIPE: 909 case K_SENDPIPE: 910 case K_SSTHRESH: 911 case K_RTT: 912 case K_RTTVAR: 913 if (!--argc) 914 usage(1+*argv); 915 set_metric(*++argv, key); 916 break; 917 default: 918 usage(1+*argv); 919 } 920 } else { 921 if ((rtm_addrs & RTA_DST) == 0) { 922 dest = *argv; 923 ishost = getaddr(RTA_DST, *argv, &hp); 924 } else if ((rtm_addrs & RTA_GATEWAY) == 0) { 925 gateway = *argv; 926 (void)getaddr(RTA_GATEWAY, *argv, &hp); 927 } else { 928 ret = atoi(*argv); 929 930 if (ret == 0) { 931 if (strcmp(*argv, "0") == 0) { 932 if (!qflag) { 933 warnx("%s, %s", 934 "old usage of trailing 0", 935 "assuming route to if"); 936 } 937 } else 938 usage(NULL); 939 iflag = 1; 940 continue; 941 } else if (ret > 0 && ret < 10) { 942 if (!qflag) { 943 warnx("%s, %s", 944 "old usage of trailing digit", 945 "assuming route via gateway"); 946 } 947 iflag = 0; 948 continue; 949 } 950 (void)getaddr(RTA_NETMASK, *argv, 0); 951 } 952 } 953 } 954 if (forcehost && forcenet) 955 errx(EXIT_FAILURE, "-host and -net conflict"); 956 else if (forcehost) 957 ishost = 1; 958 else if (forcenet) 959 ishost = 0; 960 flags |= RTF_UP; 961 if (ishost) 962 flags |= RTF_HOST; 963 if (iflag == 0) 964 flags |= RTF_GATEWAY; 965 for (attempts = 1; ; attempts++) { 966 errno = 0; 967 if ((ret = rtmsg(*cmd, flags)) == 0) 968 break; 969 if (errno != ENETUNREACH && errno != ESRCH) 970 break; 971 if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) { 972 hp->h_addr_list++; 973 memmove(&so_gate.sin.sin_addr, hp->h_addr_list[0], 974 hp->h_length); 975 } else 976 break; 977 } 978 if (*cmd == 'g') 979 return (ret != 0); 980 if (!qflag) { 981 oerrno = errno; 982 (void)printf("%s %s %s", cmd, ishost? "host" : "net", dest); 983 if (*gateway) { 984 (void)printf(": gateway %s", gateway); 985 if (attempts > 1 && ret == 0 && af == AF_INET) 986 (void)printf(" (%s)", 987 inet_ntoa(so_gate.sin.sin_addr)); 988 } 989 if (ret == 0) 990 (void)printf("\n"); 991 else 992 (void)printf(": %s\n", route_strerror(oerrno)); 993 } 994 return (ret != 0); 995 } 996 997 static void 998 inet_makenetandmask(u_int32_t net, struct sockaddr_in *isin) 999 { 1000 u_int32_t addr, mask = 0; 1001 char *cp; 1002 1003 rtm_addrs |= RTA_NETMASK; 1004 if (net == 0) 1005 mask = addr = 0; 1006 else if (net < 128) { 1007 addr = net << IN_CLASSA_NSHIFT; 1008 mask = IN_CLASSA_NET; 1009 } else if (net < 192) { 1010 addr = net << IN_CLASSA_NSHIFT; 1011 mask = IN_CLASSB_NET; 1012 } else if (net < 224) { 1013 addr = net << IN_CLASSA_NSHIFT; 1014 mask = IN_CLASSC_NET; 1015 } else if (net < 256) { 1016 addr = net << IN_CLASSA_NSHIFT; 1017 mask = IN_CLASSD_NET; 1018 } else if (net < 49152) { /* 192 * 256 */ 1019 addr = net << IN_CLASSB_NSHIFT; 1020 mask = IN_CLASSB_NET; 1021 } else if (net < 57344) { /* 224 * 256 */ 1022 addr = net << IN_CLASSB_NSHIFT; 1023 mask = IN_CLASSC_NET; 1024 } else if (net < 65536) { 1025 addr = net << IN_CLASSB_NSHIFT; 1026 mask = IN_CLASSB_NET; 1027 } else if (net < 14680064L) { /* 224 * 65536 */ 1028 addr = net << IN_CLASSC_NSHIFT; 1029 mask = IN_CLASSC_NET; 1030 } else if (net < 16777216L) { 1031 addr = net << IN_CLASSC_NSHIFT; 1032 mask = IN_CLASSD_NET; 1033 } else { 1034 addr = net; 1035 if ((addr & IN_CLASSA_HOST) == 0) 1036 mask = IN_CLASSA_NET; 1037 else if ((addr & IN_CLASSB_HOST) == 0) 1038 mask = IN_CLASSB_NET; 1039 else if ((addr & IN_CLASSC_HOST) == 0) 1040 mask = IN_CLASSC_NET; 1041 else 1042 mask = -1; 1043 } 1044 isin->sin_addr.s_addr = htonl(addr); 1045 isin = &so_mask.sin; 1046 isin->sin_addr.s_addr = htonl(mask); 1047 isin->sin_len = 0; 1048 isin->sin_family = 0; 1049 cp = (char *)(&isin->sin_addr + 1); 1050 while (*--cp == 0 && cp > (char *)isin) 1051 ; 1052 isin->sin_len = 1 + cp - (char *)isin; 1053 isin->sin_family = AF_INET; 1054 } 1055 1056 #ifdef INET6 1057 /* 1058 * XXX the function may need more improvement... 1059 */ 1060 static int 1061 inet6_makenetandmask(struct sockaddr_in6 *sin6) 1062 { 1063 const char *plen; 1064 struct in6_addr in6; 1065 1066 plen = NULL; 1067 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && 1068 sin6->sin6_scope_id == 0) { 1069 plen = "0"; 1070 } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) { 1071 /* aggregatable global unicast - RFC2374 */ 1072 memset(&in6, 0, sizeof(in6)); 1073 if (!memcmp(&sin6->sin6_addr.s6_addr[8], &in6.s6_addr[8], 8)) 1074 plen = "64"; 1075 } 1076 1077 if (!plen || strcmp(plen, "128") == 0) 1078 return 1; 1079 else { 1080 rtm_addrs |= RTA_NETMASK; 1081 (void)prefixlen(plen); 1082 return 0; 1083 } 1084 } 1085 #endif 1086 1087 /* 1088 * Interpret an argument as a network address of some kind, 1089 * returning 1 if a host address, 0 if a network address. 1090 */ 1091 static int 1092 getaddr(int which, char *s, struct hostent **hpp) 1093 { 1094 sup su; 1095 struct hostent *hp; 1096 struct netent *np; 1097 u_int32_t val; 1098 char *t; 1099 int afamily; /* local copy of af so we can change it */ 1100 1101 if (af == AF_UNSPEC) { 1102 af = AF_INET; 1103 aflen = sizeof(struct sockaddr_in); 1104 } 1105 afamily = af; 1106 rtm_addrs |= which; 1107 switch (which) { 1108 case RTA_DST: 1109 su = &so_dst; 1110 break; 1111 case RTA_GATEWAY: 1112 su = &so_gate; 1113 break; 1114 case RTA_NETMASK: 1115 su = &so_mask; 1116 break; 1117 case RTA_GENMASK: 1118 su = &so_genmask; 1119 break; 1120 case RTA_IFP: 1121 su = &so_ifp; 1122 afamily = AF_LINK; 1123 break; 1124 case RTA_IFA: 1125 su = &so_ifa; 1126 su->sa.sa_family = af; 1127 break; 1128 default: 1129 su = NULL; 1130 usage("Internal Error"); 1131 /*NOTREACHED*/ 1132 } 1133 su->sa.sa_len = aflen; 1134 su->sa.sa_family = afamily; /* cases that don't want it have left already */ 1135 if (strcmp(s, "default") == 0) { 1136 switch (which) { 1137 case RTA_DST: 1138 forcenet++; 1139 (void)getaddr(RTA_NETMASK, s, 0); 1140 break; 1141 case RTA_NETMASK: 1142 case RTA_GENMASK: 1143 su->sa.sa_len = 0; 1144 } 1145 return (0); 1146 } 1147 switch (afamily) { 1148 #ifdef INET6 1149 case AF_INET6: 1150 { 1151 struct addrinfo hints, *res; 1152 char *slash = 0; 1153 1154 if (which == RTA_DST && (slash = (strrchr(s, '/'))) != 0) 1155 *slash = '\0'; 1156 memset(&hints, 0, sizeof(hints)); 1157 hints.ai_family = afamily; /*AF_INET6*/ 1158 hints.ai_flags = AI_NUMERICHOST; 1159 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 1160 if (getaddrinfo(s, "0", &hints, &res) != 0) { 1161 hints.ai_flags = 0; 1162 if (slash) { 1163 *slash = '/'; 1164 slash = 0; 1165 } 1166 if (getaddrinfo(s, "0", &hints, &res) != 0) 1167 errx(EXIT_FAILURE, "%s: bad value", s); 1168 } 1169 if (slash) 1170 *slash = '/'; 1171 if (sizeof(su->sin6) != res->ai_addrlen) 1172 errx(EXIT_FAILURE, "%s: bad value", s); 1173 if (res->ai_next) { 1174 errx(EXIT_FAILURE, 1175 "%s: address resolved to multiple values", s); 1176 } 1177 memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6)); 1178 freeaddrinfo(res); 1179 #ifdef __KAME__ 1180 if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) || 1181 IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr)) && 1182 su->sin6.sin6_scope_id) { 1183 *(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] = 1184 htons(su->sin6.sin6_scope_id); 1185 su->sin6.sin6_scope_id = 0; 1186 } 1187 #endif 1188 if (hints.ai_flags == AI_NUMERICHOST) { 1189 if (slash) 1190 return (prefixlen(slash + 1)); 1191 if (which == RTA_DST) 1192 return (inet6_makenetandmask(&su->sin6)); 1193 return (0); 1194 } else 1195 return (1); 1196 } 1197 #endif 1198 1199 #ifndef SMALL 1200 case AF_OSI: 1201 su->siso.siso_addr = *iso_addr(s); 1202 if (which == RTA_NETMASK || which == RTA_GENMASK) { 1203 const char *cp = TSEL(&su->siso); 1204 su->siso.siso_nlen = 0; 1205 do {--cp ;} while ((cp > (char *)su) && (*cp == 0)); 1206 su->siso.siso_len = 1 + cp - (char *)su; 1207 } 1208 return (1); 1209 #endif /* SMALL */ 1210 1211 case PF_ROUTE: 1212 su->sa.sa_len = sizeof(*su); 1213 sockaddr(s, &su->sa); 1214 return (1); 1215 1216 #ifndef SMALL 1217 case AF_APPLETALK: 1218 t = strchr (s, '.'); 1219 if (!t) { 1220 badataddr: 1221 errx(EXIT_FAILURE, "bad address: %s", s); 1222 } 1223 val = atoi (s); 1224 if (val > 65535) 1225 goto badataddr; 1226 su->sat.sat_addr.s_net = val; 1227 val = atoi (t); 1228 if (val > 256) 1229 goto badataddr; 1230 su->sat.sat_addr.s_node = val; 1231 rtm_addrs |= RTA_NETMASK; 1232 return(forcehost || su->sat.sat_addr.s_node != 0); 1233 #endif 1234 1235 case AF_LINK: 1236 link_addr(s, &su->sdl); 1237 return (1); 1238 1239 case AF_INET: 1240 default: 1241 break; 1242 } 1243 1244 if (hpp == NULL) 1245 hpp = &hp; 1246 *hpp = NULL; 1247 1248 if ((t = strchr(s, '/')) != NULL && which == RTA_DST) { 1249 *t = '\0'; 1250 if (forcenet == 0) { 1251 if ((val = inet_addr(s)) != INADDR_NONE) { 1252 inet_makenetandmask(htonl(val), &su->sin); 1253 return prefixlen(&t[1]); 1254 } 1255 } else { 1256 if ((val = inet_network(s)) != INADDR_NONE) { 1257 inet_makenetandmask(val, &su->sin); 1258 return prefixlen(&t[1]); 1259 } 1260 } 1261 *t = '/'; 1262 } 1263 if (inet_aton(s, &su->sin.sin_addr) && 1264 (which != RTA_DST || forcenet == 0)) { 1265 val = su->sin.sin_addr.s_addr; 1266 if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) 1267 return (1); 1268 else { 1269 val = ntohl(val); 1270 goto netdone; 1271 } 1272 } 1273 if ((val = inet_network(s)) != INADDR_NONE || 1274 ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0)) { 1275 netdone: 1276 if (which == RTA_DST) 1277 inet_makenetandmask(val, &su->sin); 1278 return (0); 1279 } 1280 hp = gethostbyname(s); 1281 if (hp) { 1282 *hpp = hp; 1283 su->sin.sin_family = hp->h_addrtype; 1284 memmove(&su->sin.sin_addr, hp->h_addr, hp->h_length); 1285 return (1); 1286 } 1287 errx(EXIT_FAILURE, "%s: bad value", s); 1288 /*NOTREACHED*/ 1289 } 1290 1291 int 1292 prefixlen(const char *s) 1293 { 1294 int len = atoi(s), q, r; 1295 int max; 1296 1297 switch (af) { 1298 case AF_INET: 1299 max = sizeof(struct in_addr) * 8; 1300 break; 1301 #ifdef INET6 1302 case AF_INET6: 1303 max = sizeof(struct in6_addr) * 8; 1304 break; 1305 #endif 1306 default: 1307 errx(EXIT_FAILURE, "prefixlen is not supported with af %d", af); 1308 /*NOTREACHED*/ 1309 } 1310 1311 rtm_addrs |= RTA_NETMASK; 1312 if (len < -1 || len > max) 1313 errx(EXIT_FAILURE, "%s: bad value", s); 1314 1315 q = len >> 3; 1316 r = len & 7; 1317 switch (af) { 1318 case AF_INET: 1319 memset(&so_mask, 0, sizeof(so_mask)); 1320 so_mask.sin.sin_family = AF_INET; 1321 so_mask.sin.sin_len = sizeof(struct sockaddr_in); 1322 so_mask.sin.sin_addr.s_addr = (len == 0 ? 0 1323 : htonl(0xffffffff << (32 - len))); 1324 break; 1325 #ifdef INET6 1326 case AF_INET6: 1327 so_mask.sin6.sin6_family = AF_INET6; 1328 so_mask.sin6.sin6_len = sizeof(struct sockaddr_in6); 1329 memset((void *)&so_mask.sin6.sin6_addr, 0, 1330 sizeof(so_mask.sin6.sin6_addr)); 1331 if (q > 0) 1332 memset((void *)&so_mask.sin6.sin6_addr, 0xff, q); 1333 if (r > 0) 1334 *((u_char *)&so_mask.sin6.sin6_addr + q) = 1335 (0xff00 >> r) & 0xff; 1336 break; 1337 #endif 1338 } 1339 return (len == max); 1340 } 1341 1342 #ifndef SMALL 1343 static void 1344 interfaces(void) 1345 { 1346 size_t needed; 1347 int mib[6]; 1348 char *buf, *lim, *next; 1349 struct rt_msghdr *rtm; 1350 1351 mib[0] = CTL_NET; 1352 mib[1] = PF_ROUTE; 1353 mib[2] = 0; /* protocol */ 1354 mib[3] = 0; /* wildcard address family */ 1355 mib[4] = NET_RT_IFLIST; 1356 mib[5] = 0; /* no flags */ 1357 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 1358 err(EXIT_FAILURE, "route-sysctl-estimate"); 1359 if (needed) { 1360 if ((buf = malloc(needed)) == NULL) 1361 err(EXIT_FAILURE, "malloc"); 1362 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 1363 err(EXIT_FAILURE, 1364 "actual retrieval of interface table"); 1365 } 1366 lim = buf + needed; 1367 for (next = buf; next < lim; next += rtm->rtm_msglen) { 1368 rtm = (struct rt_msghdr *)next; 1369 print_rtmsg(rtm, rtm->rtm_msglen); 1370 } 1371 free(buf); 1372 } 1373 } 1374 1375 static void 1376 monitor(void) 1377 { 1378 int n; 1379 char msg[2048]; 1380 1381 verbose = 1; 1382 if (debugonly) { 1383 interfaces(); 1384 exit(0); 1385 } 1386 for(;;) { 1387 time_t now; 1388 n = read(sock, msg, 2048); 1389 now = time(NULL); 1390 (void)printf("got message of size %d on %s", n, ctime(&now)); 1391 print_rtmsg((struct rt_msghdr *)msg, n); 1392 } 1393 } 1394 1395 #endif /* SMALL */ 1396 1397 1398 struct { 1399 struct rt_msghdr m_rtm; 1400 char m_space[512]; 1401 } m_rtmsg; 1402 1403 static int 1404 rtmsg(int cmd, int flags) 1405 { 1406 static int seq; 1407 int rlen; 1408 char *cp = m_rtmsg.m_space; 1409 int l; 1410 1411 #define NEXTADDR(w, u) \ 1412 if (rtm_addrs & (w)) {\ 1413 l = ROUNDUP(u.sa.sa_len); memmove(cp, &(u), l); cp += l;\ 1414 if (verbose && ! shortoutput) sodump(&(u),#u);\ 1415 } 1416 1417 errno = 0; 1418 memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 1419 if (cmd == 'a') 1420 cmd = RTM_ADD; 1421 else if (cmd == 'c') 1422 cmd = RTM_CHANGE; 1423 else if (cmd == 'g') { 1424 #ifdef SMALL 1425 return (-1); 1426 #else /* SMALL */ 1427 cmd = RTM_GET; 1428 if (so_ifp.sa.sa_family == 0) { 1429 so_ifp.sa.sa_family = AF_LINK; 1430 so_ifp.sa.sa_len = sizeof(struct sockaddr_dl); 1431 rtm_addrs |= RTA_IFP; 1432 } 1433 #endif /* SMALL */ 1434 } else 1435 cmd = RTM_DELETE; 1436 #define rtm m_rtmsg.m_rtm 1437 rtm.rtm_type = cmd; 1438 rtm.rtm_flags = flags; 1439 rtm.rtm_version = RTM_VERSION; 1440 rtm.rtm_seq = ++seq; 1441 rtm.rtm_addrs = rtm_addrs; 1442 rtm.rtm_rmx = rt_metrics; 1443 rtm.rtm_inits = rtm_inits; 1444 1445 if (rtm_addrs & RTA_NETMASK) 1446 mask_addr(); 1447 NEXTADDR(RTA_DST, so_dst); 1448 NEXTADDR(RTA_GATEWAY, so_gate); 1449 NEXTADDR(RTA_NETMASK, so_mask); 1450 NEXTADDR(RTA_GENMASK, so_genmask); 1451 NEXTADDR(RTA_IFP, so_ifp); 1452 NEXTADDR(RTA_IFA, so_ifa); 1453 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; 1454 if (verbose && ! shortoutput) { 1455 if (rtm_addrs) 1456 putchar('\n'); 1457 print_rtmsg(&rtm, l); 1458 } 1459 if (debugonly) 1460 return (0); 1461 if ((rlen = write(sock, (char *)&m_rtmsg, l)) < 0) { 1462 warnx("writing to routing socket: %s", route_strerror(errno)); 1463 return (-1); 1464 } 1465 if (rlen < l) { 1466 warnx("write to routing socket, got %d for rlen", rlen); 1467 return 1; 1468 } 1469 #ifndef SMALL 1470 if (cmd == RTM_GET) { 1471 do { 1472 l = read(sock, (char *)&m_rtmsg, sizeof(m_rtmsg)); 1473 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); 1474 if (l < 0) 1475 err(EXIT_FAILURE, "read from routing socket"); 1476 else 1477 return print_getmsg(&rtm, l); 1478 } 1479 #endif /* SMALL */ 1480 #undef rtm 1481 return (0); 1482 } 1483 1484 static void 1485 mask_addr(void) 1486 { 1487 int olen = so_mask.sa.sa_len; 1488 char *cp1 = olen + (char *)&so_mask, *cp2; 1489 1490 for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; ) 1491 if (*--cp1 != 0) { 1492 so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask; 1493 break; 1494 } 1495 if ((rtm_addrs & RTA_DST) == 0) 1496 return; 1497 switch (so_dst.sa.sa_family) { 1498 case AF_INET: 1499 #ifdef INET6 1500 case AF_INET6: 1501 #endif 1502 #ifndef SMALL 1503 case AF_APPLETALK: 1504 #endif /* SMALL */ 1505 case 0: 1506 return; 1507 #ifndef SMALL 1508 case AF_ISO: 1509 olen = MIN(so_dst.siso.siso_nlen, 1510 MAX(so_mask.sa.sa_len - 6, 0)); 1511 break; 1512 #endif /* SMALL */ 1513 } 1514 cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst; 1515 cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst; 1516 while (cp2 > cp1) 1517 *--cp2 = 0; 1518 cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask; 1519 while (cp1 > so_dst.sa.sa_data) 1520 *--cp1 &= *--cp2; 1521 #ifndef SMALL 1522 switch (so_dst.sa.sa_family) { 1523 case AF_ISO: 1524 so_dst.siso.siso_nlen = olen; 1525 break; 1526 } 1527 #endif /* SMALL */ 1528 } 1529 1530 const char *msgtypes[] = { 1531 "", 1532 "RTM_ADD: Add Route", 1533 "RTM_DELETE: Delete Route", 1534 "RTM_CHANGE: Change Metrics or flags", 1535 "RTM_GET: Report Metrics", 1536 "RTM_LOSING: Kernel Suspects Partitioning", 1537 "RTM_REDIRECT: Told to use different route", 1538 "RTM_MISS: Lookup failed on this address", 1539 "RTM_LOCK: fix specified metrics", 1540 "RTM_OLDADD: caused by SIOCADDRT", 1541 "RTM_OLDDEL: caused by SIOCDELRT", 1542 "RTM_RESOLVE: Route created by cloning", 1543 "RTM_NEWADDR: address being added to iface", 1544 "RTM_DELADDR: address being removed from iface", 1545 "RTM_OIFINFO: iface status change (pre-1.5)", 1546 "RTM_IFINFO: iface status change", 1547 "RTM_IFANNOUNCE: iface arrival/departure", 1548 "RTM_IEEE80211: IEEE80211 wireless event", 1549 0, 1550 }; 1551 1552 const char metricnames[] = 1553 "\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu"; 1554 const char routeflags[] = 1555 "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016CLONED\017PROTO2\020PROTO1"; 1556 const char ifnetflags[] = 1557 "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST"; 1558 const char addrnames[] = 1559 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; 1560 1561 1562 #ifndef SMALL 1563 static const char * 1564 linkstate(struct if_msghdr *ifm) 1565 { 1566 static char buf[64]; 1567 1568 switch (ifm->ifm_data.ifi_link_state) { 1569 case LINK_STATE_UNKNOWN: 1570 return "carrier: unknown"; 1571 case LINK_STATE_DOWN: 1572 return "carrier: no carrier"; 1573 case LINK_STATE_UP: 1574 return "carrier: active"; 1575 default: 1576 (void)snprintf(buf, sizeof(buf), "carrier: 0x%x", 1577 ifm->ifm_data.ifi_link_state); 1578 return buf; 1579 } 1580 } 1581 #endif /* SMALL */ 1582 1583 static void 1584 print_rtmsg(struct rt_msghdr *rtm, int msglen) 1585 { 1586 struct if_msghdr *ifm; 1587 struct ifa_msghdr *ifam; 1588 struct if_announcemsghdr *ifan; 1589 union { 1590 struct ieee80211_join_event join; 1591 struct ieee80211_leave_event leave; 1592 struct ieee80211_replay_event replay; 1593 struct ieee80211_michael_event michael; 1594 } ev; 1595 size_t evlen = 0; 1596 1597 if (verbose == 0) 1598 return; 1599 if (rtm->rtm_version != RTM_VERSION) { 1600 (void)printf("routing message version %d not understood\n", 1601 rtm->rtm_version); 1602 return; 1603 } 1604 if (msgtypes[rtm->rtm_type]) 1605 (void)printf("%s: ", msgtypes[rtm->rtm_type]); 1606 else 1607 (void)printf("#%d: ", rtm->rtm_type); 1608 (void)printf("len %d, ", rtm->rtm_msglen); 1609 switch (rtm->rtm_type) { 1610 case RTM_IFINFO: 1611 ifm = (struct if_msghdr *)rtm; 1612 (void)printf("if# %d, %s, flags: ", ifm->ifm_index, 1613 #ifdef SMALL 1614 "" 1615 #else 1616 linkstate(ifm) 1617 #endif /* SMALL */ 1618 ); 1619 bprintf(stdout, ifm->ifm_flags, ifnetflags); 1620 pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs); 1621 break; 1622 case RTM_NEWADDR: 1623 case RTM_DELADDR: 1624 ifam = (struct ifa_msghdr *)rtm; 1625 (void)printf("metric %d, flags: ", ifam->ifam_metric); 1626 bprintf(stdout, ifam->ifam_flags, routeflags); 1627 pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs); 1628 break; 1629 case RTM_IEEE80211: 1630 ifan = (struct if_announcemsghdr *)rtm; 1631 (void)printf("if# %d, what: ", ifan->ifan_index); 1632 switch (ifan->ifan_what) { 1633 case RTM_IEEE80211_ASSOC: 1634 printf("associate"); 1635 break; 1636 case RTM_IEEE80211_REASSOC: 1637 printf("re-associate"); 1638 break; 1639 case RTM_IEEE80211_DISASSOC: 1640 printf("disassociate"); 1641 break; 1642 case RTM_IEEE80211_SCAN: 1643 printf("scan complete"); 1644 break; 1645 case RTM_IEEE80211_JOIN: 1646 evlen = sizeof(ev.join); 1647 printf("join"); 1648 break; 1649 case RTM_IEEE80211_LEAVE: 1650 evlen = sizeof(ev.leave); 1651 printf("leave"); 1652 break; 1653 case RTM_IEEE80211_MICHAEL: 1654 evlen = sizeof(ev.michael); 1655 printf("michael"); 1656 break; 1657 case RTM_IEEE80211_REPLAY: 1658 evlen = sizeof(ev.replay); 1659 printf("replay"); 1660 break; 1661 default: 1662 evlen = 0; 1663 printf("#%d", ifan->ifan_what); 1664 break; 1665 } 1666 if (sizeof(*ifan) + evlen > ifan->ifan_msglen) { 1667 printf(" (truncated)\n"); 1668 break; 1669 } 1670 (void)memcpy(&ev, (ifan + 1), evlen); 1671 switch (ifan->ifan_what) { 1672 case RTM_IEEE80211_JOIN: 1673 case RTM_IEEE80211_LEAVE: 1674 printf(" mac %" PRIETHER, 1675 PRIETHER_ARGS(ev.join.iev_addr)); 1676 break; 1677 case RTM_IEEE80211_REPLAY: 1678 case RTM_IEEE80211_MICHAEL: 1679 printf(" src %" PRIETHER " dst %" PRIETHER 1680 " cipher %" PRIu8 " keyix %" PRIu8, 1681 PRIETHER_ARGS(ev.replay.iev_src), 1682 PRIETHER_ARGS(ev.replay.iev_dst), 1683 ev.replay.iev_cipher, 1684 ev.replay.iev_keyix); 1685 if (ifan->ifan_what == RTM_IEEE80211_REPLAY) { 1686 printf(" key rsc %#" PRIx64 1687 " frame rsc %#" PRIx64, 1688 ev.replay.iev_keyrsc, ev.replay.iev_rsc); 1689 } 1690 break; 1691 default: 1692 break; 1693 } 1694 printf("\n"); 1695 break; 1696 case RTM_IFANNOUNCE: 1697 ifan = (struct if_announcemsghdr *)rtm; 1698 (void)printf("if# %d, what: ", ifan->ifan_index); 1699 switch (ifan->ifan_what) { 1700 case IFAN_ARRIVAL: 1701 printf("arrival"); 1702 break; 1703 case IFAN_DEPARTURE: 1704 printf("departure"); 1705 break; 1706 default: 1707 printf("#%d", ifan->ifan_what); 1708 break; 1709 } 1710 printf("\n"); 1711 break; 1712 default: 1713 (void)printf("pid %d, seq %d, errno %d, flags: ", 1714 rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); 1715 bprintf(stdout, rtm->rtm_flags, routeflags); 1716 pmsg_common(rtm); 1717 } 1718 } 1719 1720 #ifndef SMALL 1721 static int 1722 print_getmsg(struct rt_msghdr *rtm, int msglen) 1723 { 1724 struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL; 1725 struct sockaddr_dl *ifp = NULL; 1726 struct sockaddr *sa; 1727 char *cp; 1728 int i; 1729 1730 if (! shortoutput) 1731 (void)printf(" route to: %s\n", 1732 routename((struct sockaddr *) &so_dst, NULL, RTF_HOST)); 1733 if (rtm->rtm_version != RTM_VERSION) { 1734 warnx("routing message version %d not understood", 1735 rtm->rtm_version); 1736 return 1; 1737 } 1738 if (rtm->rtm_msglen > msglen) { 1739 warnx("message length mismatch, in packet %d, returned %d", 1740 rtm->rtm_msglen, msglen); 1741 } 1742 if (rtm->rtm_errno) { 1743 warnx("RTM_GET: %s (errno %d)", 1744 strerror(rtm->rtm_errno), rtm->rtm_errno); 1745 return 1; 1746 } 1747 cp = ((char *)(rtm + 1)); 1748 if (rtm->rtm_addrs) 1749 for (i = 1; i; i <<= 1) 1750 if (i & rtm->rtm_addrs) { 1751 sa = (struct sockaddr *)cp; 1752 switch (i) { 1753 case RTA_DST: 1754 dst = sa; 1755 break; 1756 case RTA_GATEWAY: 1757 gate = sa; 1758 break; 1759 case RTA_NETMASK: 1760 mask = sa; 1761 break; 1762 case RTA_IFP: 1763 if (sa->sa_family == AF_LINK && 1764 ((struct sockaddr_dl *)sa)->sdl_nlen) 1765 ifp = (struct sockaddr_dl *)sa; 1766 break; 1767 case RTA_IFA: 1768 ifa = sa; 1769 break; 1770 } 1771 ADVANCE(cp, sa); 1772 } 1773 if (dst && mask) 1774 mask->sa_family = dst->sa_family; /* XXX */ 1775 if (dst && ! shortoutput) 1776 (void)printf("destination: %s\n", 1777 routename(dst, mask, RTF_HOST)); 1778 if (mask && ! shortoutput) { 1779 int savenflag = nflag; 1780 1781 nflag = 1; 1782 (void)printf(" mask: %s\n", 1783 routename(mask, NULL, RTF_HOST)); 1784 nflag = savenflag; 1785 } 1786 if (gate && rtm->rtm_flags & RTF_GATEWAY) { 1787 const char *name; 1788 1789 name = routename(gate, NULL, RTF_HOST); 1790 if (shortoutput) { 1791 if (*name == '\0') 1792 return (1); 1793 (void)printf("%s\n", name); 1794 } else 1795 (void)printf(" gateway: %s\n", name); 1796 } 1797 if (ifa && ! shortoutput) 1798 (void)printf(" local addr: %s\n", 1799 routename(ifa, NULL, RTF_HOST)); 1800 if (ifp && ! shortoutput) 1801 (void)printf(" interface: %.*s\n", 1802 ifp->sdl_nlen, ifp->sdl_data); 1803 if (! shortoutput) { 1804 (void)printf(" flags: "); 1805 bprintf(stdout, rtm->rtm_flags, routeflags); 1806 } 1807 1808 #define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') 1809 #define msec(u) (((u) + 500) / 1000) /* usec to msec */ 1810 1811 if (! shortoutput) { 1812 (void)printf("\n%s\n", "\ 1813 recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire"); 1814 printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE)); 1815 printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE)); 1816 printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH)); 1817 printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT)); 1818 printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR)); 1819 printf("%8ld%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT)); 1820 printf("%8ld%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU)); 1821 if (rtm->rtm_rmx.rmx_expire) 1822 rtm->rtm_rmx.rmx_expire -= time(0); 1823 printf("%8ld%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE)); 1824 } 1825 #undef lock 1826 #undef msec 1827 #define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) 1828 1829 if (shortoutput) 1830 return ((rtm->rtm_addrs & RTF_GATEWAY) == 0); 1831 else if (verbose) 1832 pmsg_common(rtm); 1833 else if (rtm->rtm_addrs &~ RTA_IGN) { 1834 (void)printf("sockaddrs: "); 1835 bprintf(stdout, rtm->rtm_addrs, addrnames); 1836 putchar('\n'); 1837 } 1838 return 0; 1839 #undef RTA_IGN 1840 } 1841 #endif /* SMALL */ 1842 1843 void 1844 pmsg_common(struct rt_msghdr *rtm) 1845 { 1846 (void)printf("\nlocks: "); 1847 bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); 1848 (void)printf(" inits: "); 1849 bprintf(stdout, rtm->rtm_inits, metricnames); 1850 pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs); 1851 } 1852 1853 static void 1854 pmsg_addrs(char *cp, int addrs) 1855 { 1856 struct sockaddr *sa[RTAX_MAX]; 1857 int i, nmf; 1858 1859 if (addrs != 0) { 1860 (void)printf("\nsockaddrs: "); 1861 bprintf(stdout, addrs, addrnames); 1862 (void)putchar('\n'); 1863 nmf = -1; 1864 for (i = 0; i < RTAX_MAX; i++) { 1865 if ((1 << i) & addrs) { 1866 sa[i] = (struct sockaddr *)cp; 1867 if ((i == RTAX_DST || i == RTAX_IFA) && 1868 nmf == -1) 1869 nmf = sa[i]->sa_family; 1870 ADVANCE(cp, sa[i]); 1871 } else 1872 sa[i] = NULL; 1873 } 1874 for (i = 0; i < RTAX_MAX; i++) { 1875 if (sa[i] != NULL) { 1876 if (i == RTAX_NETMASK && sa[i]->sa_len) 1877 (void)printf(" %s", 1878 netmask_string(sa[i], -1, nmf)); 1879 else 1880 (void)printf(" %s", 1881 routename(sa[i], NULL, RTF_HOST)); 1882 } 1883 } 1884 } 1885 (void)putchar('\n'); 1886 (void)fflush(stdout); 1887 } 1888 1889 static void 1890 bprintf(FILE *fp, int b, const char *f) 1891 { 1892 int i; 1893 int gotsome = 0; 1894 const uint8_t *s = (const uint8_t *)f; 1895 1896 if (b == 0) 1897 return; 1898 while ((i = *s++) != 0) { 1899 if (b & (1 << (i-1))) { 1900 if (gotsome == 0) 1901 i = '<'; 1902 else 1903 i = ','; 1904 (void)putc(i, fp); 1905 gotsome = 1; 1906 for (; (i = *s) > 32; s++) 1907 (void)putc(i, fp); 1908 } else 1909 while (*s > 32) 1910 s++; 1911 } 1912 if (gotsome) 1913 (void)putc('>', fp); 1914 } 1915 1916 int 1917 keyword(char *cp) 1918 { 1919 struct keytab *kt = keywords; 1920 1921 while (kt->kt_cp && strcmp(kt->kt_cp, cp)) 1922 kt++; 1923 return kt->kt_i; 1924 } 1925 1926 static void 1927 sodump(sup su, const char *which) 1928 { 1929 #ifdef INET6 1930 char ntop_buf[NI_MAXHOST]; 1931 #endif 1932 1933 switch (su->sa.sa_family) { 1934 case AF_INET: 1935 (void)printf("%s: inet %s; ", 1936 which, inet_ntoa(su->sin.sin_addr)); 1937 break; 1938 #ifndef SMALL 1939 case AF_APPLETALK: 1940 (void)printf("%s: atalk %d.%d; ", 1941 which, su->sat.sat_addr.s_net, su->sat.sat_addr.s_node); 1942 break; 1943 #endif 1944 case AF_LINK: 1945 (void)printf("%s: link %s; ", 1946 which, link_ntoa(&su->sdl)); 1947 break; 1948 #ifdef INET6 1949 case AF_INET6: 1950 (void)printf("%s: inet6 %s; ", 1951 which, inet_ntop(AF_INET6, &su->sin6.sin6_addr, 1952 ntop_buf, sizeof(ntop_buf))); 1953 break; 1954 #endif 1955 #ifndef SMALL 1956 case AF_ISO: 1957 (void)printf("%s: iso %s; ", 1958 which, iso_ntoa(&su->siso.siso_addr)); 1959 break; 1960 #endif /* SMALL */ 1961 default: 1962 (void)printf("%s: (%d) %s; ", 1963 which, su->sa.sa_family, any_ntoa(&su->sa)); 1964 } 1965 (void)fflush(stdout); 1966 } 1967 1968 /* States*/ 1969 #define VIRGIN 0 1970 #define GOTONE 1 1971 #define GOTTWO 2 1972 /* Inputs */ 1973 #define DIGIT (4*0) 1974 #define END (4*1) 1975 #define DELIM (4*2) 1976 1977 static void 1978 sockaddr(char *addr, struct sockaddr *sa) 1979 { 1980 char *cp = (char *)sa; 1981 int size = sa->sa_len; 1982 char *cplim = cp + size; 1983 int byte = 0, state = VIRGIN, new = 0; 1984 1985 (void)memset(cp, 0, size); 1986 cp++; 1987 do { 1988 if ((*addr >= '0') && (*addr <= '9')) { 1989 new = *addr - '0'; 1990 } else if ((*addr >= 'a') && (*addr <= 'f')) { 1991 new = *addr - 'a' + 10; 1992 } else if ((*addr >= 'A') && (*addr <= 'F')) { 1993 new = *addr - 'A' + 10; 1994 } else if (*addr == 0) 1995 state |= END; 1996 else 1997 state |= DELIM; 1998 addr++; 1999 switch (state /* | INPUT */) { 2000 case GOTTWO | DIGIT: 2001 *cp++ = byte; /*FALLTHROUGH*/ 2002 case VIRGIN | DIGIT: 2003 state = GOTONE; byte = new; continue; 2004 case GOTONE | DIGIT: 2005 state = GOTTWO; byte = new + (byte << 4); continue; 2006 default: /* | DELIM */ 2007 state = VIRGIN; *cp++ = byte; byte = 0; continue; 2008 case GOTONE | END: 2009 case GOTTWO | END: 2010 *cp++ = byte; /* FALLTHROUGH */ 2011 case VIRGIN | END: 2012 break; 2013 } 2014 break; 2015 } while (cp < cplim); 2016 sa->sa_len = cp - (char *)sa; 2017 } 2018