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