1 /* $OpenBSD: route.c,v 1.254 2021/03/12 19:35:43 florian Exp $ */ 2 /* $NetBSD: route.c,v 1.16 1996/04/15 18:27:05 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1989, 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/socket.h> 34 #include <sys/sysctl.h> 35 36 #include <net/if.h> 37 #include <net/if_dl.h> 38 #include <net/if_media.h> 39 #include <net/if_types.h> 40 #include <net/route.h> 41 #include <netinet/in.h> 42 #include <netmpls/mpls.h> 43 44 #ifdef BFD 45 #include <sys/time.h> 46 #include <net/bfd.h> 47 #endif 48 49 #include <arpa/inet.h> 50 #include <netdb.h> 51 52 #include <ifaddrs.h> 53 #include <errno.h> 54 #include <fcntl.h> 55 #include <unistd.h> 56 #include <limits.h> 57 #include <stdio.h> 58 #include <ctype.h> 59 #include <stddef.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <time.h> 63 #include <paths.h> 64 #include <err.h> 65 66 #include "keywords.h" 67 #include "show.h" 68 69 const struct if_status_description 70 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 71 72 union sockunion so_dst, so_gate, so_mask, so_ifa, so_ifp, so_src, so_label, 73 so_source; 74 75 typedef union sockunion *sup; 76 pid_t pid; 77 int rtm_addrs, s; 78 int forcehost, forcenet, Fflag, nflag, qflag, tflag, Tflag; 79 int iflag, verbose, aflen = sizeof(struct sockaddr_in); 80 int locking, lockrest, debugonly; 81 u_long mpls_flags = MPLS_OP_LOCAL; 82 u_long rtm_inits; 83 uid_t uid; 84 u_int tableid; 85 86 struct rt_metrics rt_metrics; 87 88 int flushroutes(int, char **); 89 int newroute(int, char **); 90 int setsource(int, char **); 91 int pushsrc(int, char *, int); 92 int show(int, char *[]); 93 int keycmp(const void *, const void *); 94 int keyword(char *); 95 void monitor(int, char *[]); 96 int prefixlen(int, char *); 97 void sockaddr(char *, struct sockaddr *); 98 void sodump(sup, char *); 99 char *priorityname(uint8_t); 100 uint8_t getpriority(char *); 101 void print_getmsg(struct rt_msghdr *, int); 102 #ifdef BFD 103 const char *bfd_state(unsigned int); 104 const char *bfd_diag(unsigned int); 105 const char *bfd_calc_uptime(time_t); 106 void print_bfdmsg(struct rt_msghdr *); 107 void print_sabfd(struct sockaddr_bfd *, int); 108 #endif 109 const char *get_linkstate(int, int); 110 void print_rtmsg(struct rt_msghdr *, int); 111 void pmsg_common(struct rt_msghdr *); 112 void pmsg_addrs(char *, int); 113 void bprintf(FILE *, int, char *); 114 int getaddr(int, int, char *, struct hostent **); 115 void getmplslabel(char *, int); 116 int rtmsg(int, int, int, uint8_t); 117 __dead void usage(char *); 118 void set_metric(char *, int); 119 void inet_makenetandmask(u_int32_t, struct sockaddr_in *, int); 120 void getlabel(char *); 121 int gettable(const char *); 122 int rdomain(int, char **); 123 void print_rtdns(struct sockaddr_rtdns *); 124 void print_rtstatic(struct sockaddr_rtstatic *); 125 void print_rtsearch(struct sockaddr_rtsearch *); 126 void print_80211info(struct if_ieee80211_msghdr *); 127 128 __dead void 129 usage(char *cp) 130 { 131 extern char *__progname; 132 133 if (cp) 134 warnx("botched keyword: %s", cp); 135 fprintf(stderr, 136 "usage: %s [-dnqtv] [-T rtable] command [[modifiers] args]\n", 137 __progname); 138 fprintf(stderr, 139 "commands: add, change, delete, exec, flush, get, monitor, show, " 140 "sourceaddr\n"); 141 exit(1); 142 } 143 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 unsigned int filter = 0; 152 int ch; 153 int rval = 0; 154 int kw; 155 int Terr = 0; 156 int af = AF_UNSPEC; 157 u_int rtable_any = RTABLE_ANY; 158 159 if (argc < 2) 160 usage(NULL); 161 162 tableid = getrtable(); 163 while ((ch = getopt(argc, argv, "dnqtT:v")) != -1) 164 switch (ch) { 165 case 'n': 166 nflag = 1; 167 break; 168 case 'q': 169 qflag = 1; 170 break; 171 case 'v': 172 verbose = 1; 173 break; 174 case 't': 175 tflag = 1; 176 break; 177 case 'T': 178 Terr = gettable(optarg); 179 Tflag = 1; 180 break; 181 case 'd': 182 debugonly = 1; 183 break; 184 default: 185 usage(NULL); 186 /* NOTREACHED */ 187 } 188 argc -= optind; 189 argv += optind; 190 191 pid = getpid(); 192 uid = geteuid(); 193 if (*argv == NULL) 194 usage(NULL); 195 196 kw = keyword(*argv); 197 if (Tflag && Terr != 0 && kw != K_ADD) { 198 errno = Terr; 199 err(1, "routing table %u", tableid); 200 } 201 if (kw == K_EXEC) 202 exit(rdomain(argc - 1, argv + 1)); 203 204 if (kw == K_MONITOR) { 205 while (--argc > 0) { 206 if (**(++argv)== '-') 207 switch (keyword(*argv + 1)) { 208 case K_INET: 209 af = AF_INET; 210 break; 211 case K_INET6: 212 af = AF_INET6; 213 break; 214 case K_IFACE: 215 case K_INTERFACE: 216 filter = ROUTE_FILTER(RTM_IFINFO) | 217 ROUTE_FILTER(RTM_IFANNOUNCE) | 218 ROUTE_FILTER(RTM_80211INFO); 219 break; 220 default: 221 usage(*argv); 222 /* NOTREACHED */ 223 } 224 else 225 usage(*argv); 226 } 227 } 228 229 if (tflag) 230 s = open(_PATH_DEVNULL, O_WRONLY); 231 else 232 s = socket(AF_ROUTE, SOCK_RAW, af); 233 if (s == -1) 234 err(1, "socket"); 235 236 if (filter != 0) { 237 if (setsockopt(s, AF_ROUTE, ROUTE_MSGFILTER, &filter, 238 sizeof(filter)) == -1) 239 err(1, "setsockopt(ROUTE_MSGFILTER)"); 240 } 241 242 if (!tflag) { 243 /* force socket onto table user requested */ 244 if (Tflag == 1 && Terr == 0) { 245 if (setsockopt(s, AF_ROUTE, ROUTE_TABLEFILTER, 246 &tableid, sizeof(tableid)) == -1) 247 err(1, "setsockopt(ROUTE_TABLEFILTER)"); 248 } else { 249 if (setsockopt(s, AF_ROUTE, ROUTE_TABLEFILTER, 250 &rtable_any, sizeof(tableid)) == -1) 251 err(1, "setsockopt(ROUTE_TABLEFILTER)"); 252 } 253 } 254 255 if (pledge("stdio dns route", NULL) == -1) 256 err(1, "pledge"); 257 258 switch (kw) { 259 case K_SHOW: 260 uid = 0; 261 exit(show(argc, argv)); 262 break; 263 case K_FLUSH: 264 exit(flushroutes(argc, argv)); 265 break; 266 case K_SOURCEADDR: 267 nflag = 1; 268 exit(setsource(argc, argv)); 269 break; 270 } 271 272 if (pledge("stdio dns", NULL) == -1) 273 err(1, "pledge"); 274 275 switch (kw) { 276 case K_GET: 277 uid = 0; 278 /* FALLTHROUGH */ 279 case K_CHANGE: 280 case K_ADD: 281 case K_DEL: 282 case K_DELETE: 283 rval = newroute(argc, argv); 284 break; 285 case K_MONITOR: 286 monitor(argc, argv); 287 break; 288 default: 289 usage(*argv); 290 /* NOTREACHED */ 291 } 292 exit(rval); 293 } 294 295 /* 296 * Purge all entries in the routing tables not 297 * associated with network interfaces. 298 */ 299 int 300 flushroutes(int argc, char **argv) 301 { 302 size_t needed; 303 int mib[7], mcnt, rlen, seqno, af = AF_UNSPEC; 304 char *buf = NULL, *next, *lim = NULL; 305 struct rt_msghdr *rtm; 306 struct sockaddr *sa; 307 uint8_t prio = 0; 308 unsigned int ifindex = 0; 309 310 if (uid) 311 errx(1, "must be root to alter routing table"); 312 shutdown(s, SHUT_RD); /* Don't want to read back our messages */ 313 while (--argc > 0) { 314 if (**(++argv) == '-') 315 switch (keyword(*argv + 1)) { 316 case K_INET: 317 af = AF_INET; 318 break; 319 case K_INET6: 320 af = AF_INET6; 321 break; 322 case K_LINK: 323 af = AF_LINK; 324 break; 325 case K_MPLS: 326 af = AF_MPLS; 327 break; 328 case K_IFACE: 329 case K_INTERFACE: 330 if (!--argc) 331 usage(1+*argv); 332 ifindex = if_nametoindex(*++argv); 333 if (ifindex == 0) 334 errx(1, "no such interface %s", *argv); 335 break; 336 case K_PRIORITY: 337 if (!--argc) 338 usage(1+*argv); 339 prio = getpriority(*++argv); 340 break; 341 default: 342 usage(*argv); 343 /* NOTREACHED */ 344 } 345 else 346 usage(*argv); 347 } 348 mib[0] = CTL_NET; 349 mib[1] = PF_ROUTE; 350 mib[2] = 0; /* protocol */ 351 mib[3] = af; 352 mib[4] = NET_RT_DUMP; 353 mib[5] = prio; 354 mib[6] = tableid; 355 mcnt = 7; 356 357 needed = get_sysctl(mib, mcnt, &buf); 358 lim = buf + needed; 359 360 if (pledge("stdio dns", NULL) == -1) 361 err(1, "pledge"); 362 363 if (verbose) { 364 printf("Examining routing table from sysctl\n"); 365 if (af) 366 printf("(address family %s)\n", (*argv + 1)); 367 } 368 if (buf == NULL) 369 return (1); 370 371 seqno = 0; 372 for (next = buf; next < lim; next += rtm->rtm_msglen) { 373 rtm = (struct rt_msghdr *)next; 374 if (rtm->rtm_version != RTM_VERSION) 375 continue; 376 if (verbose) 377 print_rtmsg(rtm, rtm->rtm_msglen); 378 if ((rtm->rtm_flags & (RTF_GATEWAY|RTF_STATIC|RTF_LLINFO)) == 0) 379 continue; 380 if ((rtm->rtm_flags & (RTF_LOCAL|RTF_BROADCAST)) != 0) 381 continue; 382 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 383 if (ifindex && rtm->rtm_index != ifindex) 384 continue; 385 if (sa->sa_family == AF_KEY) 386 continue; /* Don't flush SPD */ 387 if (debugonly) 388 continue; 389 rtm->rtm_type = RTM_DELETE; 390 rtm->rtm_seq = seqno; 391 rtm->rtm_tableid = tableid; 392 rlen = write(s, next, rtm->rtm_msglen); 393 if (rlen < (int)rtm->rtm_msglen) { 394 warn("write to routing socket"); 395 printf("got only %d for rlen\n", rlen); 396 break; 397 } 398 seqno++; 399 if (qflag) 400 continue; 401 if (verbose) 402 print_rtmsg(rtm, rlen); 403 else { 404 struct sockaddr *mask, *rti_info[RTAX_MAX]; 405 406 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 407 408 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 409 410 sa = rti_info[RTAX_DST]; 411 mask = rti_info[RTAX_NETMASK]; 412 413 p_sockaddr(sa, mask, rtm->rtm_flags, 20); 414 p_sockaddr(rti_info[RTAX_GATEWAY], NULL, RTF_HOST, 20); 415 printf("done\n"); 416 } 417 } 418 free(buf); 419 return (0); 420 } 421 422 void 423 set_metric(char *value, int key) 424 { 425 long long relative_expire; 426 const char *errstr; 427 int flag = 0; 428 429 switch (key) { 430 case K_MTU: 431 rt_metrics.rmx_mtu = strtonum(value, 0, UINT_MAX, &errstr); 432 if (errstr) 433 errx(1, "set_metric mtu: %s is %s", value, errstr); 434 flag = RTV_MTU; 435 break; 436 case K_EXPIRE: 437 relative_expire = strtonum(value, 0, INT_MAX, &errstr); 438 if (errstr) 439 errx(1, "set_metric expire: %s is %s", value, errstr); 440 rt_metrics.rmx_expire = relative_expire ? 441 relative_expire + time(NULL) : 0; 442 flag = RTV_EXPIRE; 443 break; 444 case K_HOPCOUNT: 445 case K_RECVPIPE: 446 case K_SENDPIPE: 447 case K_SSTHRESH: 448 case K_RTT: 449 case K_RTTVAR: 450 /* no longer used, only for compatibility */ 451 return; 452 default: 453 errx(1, "king bula sez: set_metric with invalid key"); 454 } 455 rtm_inits |= flag; 456 if (lockrest || locking) 457 rt_metrics.rmx_locks |= flag; 458 if (locking) 459 locking = 0; 460 } 461 462 463 int 464 setsource(int argc, char **argv) 465 { 466 struct ifaddrs *ifap, *ifa = NULL; 467 char *cmd; 468 int af = AF_UNSPEC, ret = 0, key; 469 unsigned int ifindex = 0; 470 471 cmd = argv[0]; 472 while (--argc > 0) { 473 if (**(++argv)== '-') { 474 switch (key = keyword(1 + *argv)) { 475 case K_INET: 476 af = AF_INET; 477 aflen = sizeof(struct sockaddr_in); 478 break; 479 case K_INET6: 480 af = AF_INET6; 481 aflen = sizeof(struct sockaddr_in6); 482 break; 483 case K_IFP: 484 if (!--argc) 485 usage(1+*argv); 486 ifindex = if_nametoindex(*++argv); 487 if (ifindex == 0) 488 errx(1, "no such interface %s", *argv); 489 break; 490 } 491 } else 492 break; 493 } 494 495 if (argc <= 0 && ifindex == 0) 496 printsource(af, tableid); 497 if (argc > 1 && ifindex == 0) 498 usage(NULL); 499 500 if (uid) 501 errx(1, "must be root to alter source address"); 502 503 if (ifindex) { 504 if (getifaddrs(&ifap) == -1) 505 err(1, "getifaddrs"); 506 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 507 if (if_nametoindex(ifa->ifa_name) != ifindex) 508 continue; 509 if (ifa->ifa_addr == NULL || 510 !(ifa->ifa_addr->sa_family == AF_INET || 511 ifa->ifa_addr->sa_family == AF_INET6)) 512 continue; 513 if ((af != AF_UNSPEC) && 514 (ifa->ifa_addr->sa_family != af)) 515 continue; 516 if (ifa->ifa_addr->sa_family == AF_INET6) { 517 struct sockaddr_in6 *sin6 = 518 (struct sockaddr_in6 *)ifa->ifa_addr; 519 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 520 IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 521 continue; 522 } 523 if (pushsrc(*cmd, routename(ifa->ifa_addr), 524 ifa->ifa_addr->sa_family)) 525 break; 526 } 527 freeifaddrs(ifap); 528 } else { 529 ret = pushsrc(*cmd, *argv, af); 530 } 531 532 return (ret != 0); 533 } 534 535 int 536 pushsrc(int cmd, char *src, int af) 537 { 538 int ret = 0; 539 540 getaddr(RTA_IFA, af, src, NULL); 541 542 errno = 0; 543 ret = rtmsg(cmd, 0, 0, 0); 544 if (!qflag && ret != 0) 545 printf("sourceaddr %s: %s\n", src, strerror(errno)); 546 547 return (ret); 548 } 549 int 550 newroute(int argc, char **argv) 551 { 552 char *cmd, *dest = "", *gateway = "", *error; 553 int ishost = 0, ret = 0, attempts, oerrno, flags = RTF_STATIC; 554 int fmask = 0, af = AF_UNSPEC; 555 int key; 556 uint8_t prio = 0; 557 struct hostent *hp = NULL; 558 int sawdest = 0; 559 560 if (uid) 561 errx(1, "must be root to alter routing table"); 562 cmd = argv[0]; 563 if (*cmd != 'g') 564 shutdown(s, SHUT_RD); /* Don't want to read back our messages */ 565 while (--argc > 0) { 566 if (**(++argv)== '-') { 567 switch (key = keyword(1 + *argv)) { 568 case K_LINK: 569 af = AF_LINK; 570 aflen = sizeof(struct sockaddr_dl); 571 break; 572 case K_INET: 573 af = AF_INET; 574 aflen = sizeof(struct sockaddr_in); 575 break; 576 case K_INET6: 577 af = AF_INET6; 578 aflen = sizeof(struct sockaddr_in6); 579 break; 580 case K_SA: 581 af = PF_ROUTE; 582 aflen = sizeof(struct sockaddr_storage) - 1; 583 break; 584 case K_MPLS: 585 af = AF_MPLS; 586 aflen = sizeof(struct sockaddr_mpls); 587 fmask |= RTF_MPLS; 588 break; 589 case K_MPLSLABEL: 590 if (!--argc) 591 usage(1+*argv); 592 if (af != AF_INET && af != AF_INET6) 593 errx(1, "-mplslabel requires " 594 "-inet or -inet6"); 595 getmplslabel(*++argv, 0); 596 mpls_flags = MPLS_OP_PUSH; 597 flags |= RTF_MPLS; 598 break; 599 case K_IN: 600 if (!--argc) 601 usage(1+*argv); 602 if (af != AF_MPLS) 603 errx(1, "-in requires -mpls"); 604 getmplslabel(*++argv, 1); 605 break; 606 case K_OUT: 607 if (!--argc) 608 usage(1+*argv); 609 if (af != AF_MPLS) 610 errx(1, "-out requires -mpls"); 611 if (mpls_flags == MPLS_OP_LOCAL) 612 errx(1, "-out requires -push, -pop, " 613 "-swap"); 614 getmplslabel(*++argv, 0); 615 flags |= RTF_MPLS; 616 break; 617 case K_POP: 618 if (af != AF_MPLS) 619 errx(1, "-pop requires -mpls"); 620 mpls_flags = MPLS_OP_POP; 621 break; 622 case K_PUSH: 623 if (af != AF_MPLS) 624 errx(1, "-push requires -mpls"); 625 mpls_flags = MPLS_OP_PUSH; 626 break; 627 case K_SWAP: 628 if (af != AF_MPLS) 629 errx(1, "-swap requires -mpls"); 630 mpls_flags = MPLS_OP_SWAP; 631 break; 632 case K_IFACE: 633 case K_INTERFACE: 634 iflag++; 635 break; 636 case K_NOSTATIC: 637 flags &= ~RTF_STATIC; 638 break; 639 case K_LLINFO: 640 flags |= RTF_LLINFO; 641 break; 642 case K_LOCK: 643 locking = 1; 644 break; 645 case K_LOCKREST: 646 lockrest = 1; 647 break; 648 case K_HOST: 649 forcehost++; 650 break; 651 case K_REJECT: 652 flags |= RTF_REJECT; 653 break; 654 case K_BLACKHOLE: 655 flags |= RTF_BLACKHOLE; 656 break; 657 case K_PROTO1: 658 flags |= RTF_PROTO1; 659 break; 660 case K_PROTO2: 661 flags |= RTF_PROTO2; 662 break; 663 case K_CLONING: 664 flags |= RTF_CLONING; 665 break; 666 case K_STATIC: 667 flags |= RTF_STATIC; 668 break; 669 case K_IFA: 670 if (!--argc) 671 usage(1+*argv); 672 getaddr(RTA_IFA, af, *++argv, NULL); 673 break; 674 case K_IFP: 675 if (!--argc) 676 usage(1+*argv); 677 getaddr(RTA_IFP, AF_LINK, *++argv, NULL); 678 break; 679 case K_GATEWAY: 680 if (!--argc) 681 usage(1+*argv); 682 getaddr(RTA_GATEWAY, af, *++argv, NULL); 683 gateway = *argv; 684 break; 685 case K_DST: 686 if (!--argc) 687 usage(1+*argv); 688 ishost = getaddr(RTA_DST, af, *++argv, &hp); 689 dest = *argv; 690 sawdest = 1; 691 break; 692 case K_LABEL: 693 if (!--argc) 694 usage(1+*argv); 695 getlabel(*++argv); 696 break; 697 case K_NETMASK: 698 if (!sawdest) 699 errx(1, "-netmask must follow " 700 "destination parameter"); 701 if (!--argc) 702 usage(1+*argv); 703 getaddr(RTA_NETMASK, af, *++argv, NULL); 704 /* FALLTHROUGH */ 705 case K_NET: 706 forcenet++; 707 break; 708 case K_PREFIXLEN: 709 if (!sawdest) 710 errx(1, "-prefixlen must follow " 711 "destination parameter"); 712 if (!--argc) 713 usage(1+*argv); 714 ishost = prefixlen(af, *++argv); 715 break; 716 case K_MPATH: 717 flags |= RTF_MPATH; 718 break; 719 case K_MTU: 720 case K_HOPCOUNT: 721 case K_EXPIRE: 722 case K_RECVPIPE: 723 case K_SENDPIPE: 724 case K_SSTHRESH: 725 case K_RTT: 726 case K_RTTVAR: 727 if (!--argc) 728 usage(1+*argv); 729 set_metric(*++argv, key); 730 break; 731 case K_PRIORITY: 732 if (!--argc) 733 usage(1+*argv); 734 prio = getpriority(*++argv); 735 break; 736 case K_BFD: 737 flags |= RTF_BFD; 738 fmask |= RTF_BFD; 739 break; 740 case K_NOBFD: 741 flags &= ~RTF_BFD; 742 fmask |= RTF_BFD; 743 break; 744 default: 745 usage(1+*argv); 746 /* NOTREACHED */ 747 } 748 } else { 749 if ((rtm_addrs & RTA_DST) == 0) { 750 dest = *argv; 751 sawdest = 1; 752 ishost = getaddr(RTA_DST, af, *argv, &hp); 753 } else if ((rtm_addrs & RTA_GATEWAY) == 0) { 754 gateway = *argv; 755 getaddr(RTA_GATEWAY, af, *argv, &hp); 756 } else 757 usage(NULL); 758 } 759 } 760 if (forcehost) 761 ishost = 1; 762 if (forcenet) 763 ishost = 0; 764 if (forcenet && !(rtm_addrs & RTA_NETMASK)) 765 errx(1, "netmask missing"); 766 flags |= RTF_UP; 767 if (ishost) 768 flags |= RTF_HOST; 769 if (iflag == 0) 770 flags |= RTF_GATEWAY; 771 for (attempts = 1; ; attempts++) { 772 errno = 0; 773 if ((ret = rtmsg(*cmd, flags, fmask, prio)) == 0) 774 break; 775 if (errno != ENETUNREACH && errno != ESRCH) 776 break; 777 if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) { 778 hp->h_addr_list++; 779 memcpy(&so_gate.sin.sin_addr, hp->h_addr_list[0], 780 hp->h_length); 781 } else 782 break; 783 } 784 oerrno = errno; 785 if (!qflag && (*cmd != 'g' || ret != 0)) { 786 printf("%s %s %s", cmd, ishost ? "host" : "net", dest); 787 if (*gateway) { 788 printf(": gateway %s", gateway); 789 if (attempts > 1 && ret == 0 && af == AF_INET) 790 printf(" (%s)", inet_ntoa(so_gate.sin.sin_addr)); 791 } 792 if (ret == 0) 793 printf("\n"); 794 if (ret != 0) { 795 switch (oerrno) { 796 case ESRCH: 797 error = "not in table"; 798 break; 799 case EBUSY: 800 error = "entry in use"; 801 break; 802 case ENOBUFS: 803 error = "routing table overflow"; 804 break; 805 default: 806 error = strerror(oerrno); 807 break; 808 } 809 printf(": %s\n", error); 810 } 811 } 812 return (ret != 0); 813 } 814 815 int 816 show(int argc, char *argv[]) 817 { 818 int af = AF_UNSPEC; 819 char prio = 0; 820 821 while (--argc > 0) { 822 if (**(++argv)== '-') 823 switch (keyword(*argv + 1)) { 824 case K_INET: 825 af = AF_INET; 826 break; 827 case K_INET6: 828 af = AF_INET6; 829 break; 830 case K_LINK: 831 af = AF_LINK; 832 break; 833 case K_MPLS: 834 af = AF_MPLS; 835 break; 836 case K_GATEWAY: 837 Fflag = 1; 838 break; 839 case K_LABEL: 840 if (!--argc) 841 usage(1+*argv); 842 getlabel(*++argv); 843 break; 844 case K_PRIORITY: 845 if (!--argc) 846 usage(1+*argv); 847 prio = getpriority(*++argv); 848 break; 849 default: 850 usage(*argv); 851 /* NOTREACHED */ 852 } 853 else 854 usage(*argv); 855 } 856 857 p_rttables(af, tableid, prio); 858 return (0); 859 } 860 861 void 862 inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits) 863 { 864 u_int32_t mask; 865 866 rtm_addrs |= RTA_NETMASK; 867 if (bits == 0 && net == 0) 868 mask = 0; 869 else { 870 if (bits == 0) 871 bits = 32; 872 mask = 0xffffffff << (32 - bits); 873 net &= mask; 874 } 875 sin->sin_addr.s_addr = htonl(net); 876 sin = &so_mask.sin; 877 sin->sin_addr.s_addr = htonl(mask); 878 sin->sin_family = AF_INET; 879 sin->sin_len = sizeof(struct sockaddr_in); 880 } 881 882 /* 883 * Interpret an argument as a network address of some kind, 884 * returning 1 if a host address, 0 if a network address. 885 */ 886 int 887 getaddr(int which, int af, char *s, struct hostent **hpp) 888 { 889 sup su = NULL; 890 struct hostent *hp; 891 int aflength, afamily, bits; 892 893 if (af == AF_UNSPEC) { 894 if (strchr(s, ':') != NULL) { 895 af = AF_INET6; 896 aflen = sizeof(struct sockaddr_in6); 897 } else { 898 af = AF_INET; 899 aflen = sizeof(struct sockaddr_in); 900 } 901 } 902 /* local copy of len and af so we can change it */ 903 aflength = aflen; 904 afamily = af; 905 906 rtm_addrs |= which; 907 switch (which) { 908 case RTA_DST: 909 su = &so_dst; 910 break; 911 case RTA_GATEWAY: 912 su = &so_gate; 913 break; 914 case RTA_NETMASK: 915 su = &so_mask; 916 break; 917 case RTA_IFP: 918 su = &so_ifp; 919 aflength = sizeof(struct sockaddr_dl); 920 afamily = AF_LINK; 921 break; 922 case RTA_IFA: 923 su = &so_ifa; 924 break; 925 default: 926 errx(1, "internal error"); 927 /* NOTREACHED */ 928 } 929 memset(su, 0, sizeof(union sockunion)); 930 su->sa.sa_len = aflength; 931 su->sa.sa_family = afamily; 932 933 if (strcmp(s, "default") == 0) { 934 switch (which) { 935 case RTA_DST: 936 forcenet++; 937 getaddr(RTA_NETMASK, af, s, NULL); 938 break; 939 case RTA_NETMASK: 940 su->sa.sa_len = 0; 941 } 942 return (0); 943 } 944 945 switch (afamily) { 946 case AF_INET6: 947 { 948 struct addrinfo hints, *res; 949 char buf[ 950 sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128") 951 ]; 952 char *sep; 953 int error; 954 955 if (strlcpy(buf, s, sizeof buf) >= sizeof buf) { 956 errx(1, "%s: bad value", s); 957 } 958 959 sep = strchr(buf, '/'); 960 if (sep != NULL) 961 *sep++ = '\0'; 962 memset(&hints, 0, sizeof(hints)); 963 hints.ai_family = afamily; /*AF_INET6*/ 964 hints.ai_flags = AI_NUMERICHOST; 965 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 966 error = getaddrinfo(buf, "0", &hints, &res); 967 if (error) { 968 hints.ai_flags = 0; 969 error = getaddrinfo(buf, "0", &hints, &res); 970 if (error) 971 errx(1, "%s: %s", s, gai_strerror(error)); 972 } 973 if (res->ai_next) 974 errx(1, "%s: resolved to multiple values", s); 975 memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6)); 976 freeaddrinfo(res); 977 #ifdef __KAME__ 978 if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) || 979 IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr) || 980 IN6_IS_ADDR_MC_INTFACELOCAL(&su->sin6.sin6_addr)) && 981 su->sin6.sin6_scope_id) { 982 *(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] = 983 htons(su->sin6.sin6_scope_id); 984 su->sin6.sin6_scope_id = 0; 985 } 986 #endif 987 if (hints.ai_flags == AI_NUMERICHOST) { 988 if (which == RTA_DST) { 989 if (sep == NULL && su->sin6.sin6_scope_id == 0 && 990 IN6_IS_ADDR_UNSPECIFIED(&su->sin6.sin6_addr)) 991 sep = "0"; 992 if (sep == NULL || prefixlen(AF_INET6, sep)) 993 return (1); 994 } 995 return (0); 996 } else 997 return (1); 998 } 999 1000 case AF_LINK: 1001 su->sdl.sdl_index = if_nametoindex(s); 1002 memset(&su->sdl.sdl_data, 0, sizeof(su->sdl.sdl_data)); 1003 return (1); 1004 case AF_MPLS: 1005 errx(1, "mpls labels require -in or -out switch"); 1006 case PF_ROUTE: 1007 su->sa.sa_len = sizeof(struct sockaddr_storage) - 1; 1008 sockaddr(s, &su->sa); 1009 return (1); 1010 1011 case AF_INET: 1012 if (hpp != NULL) 1013 *hpp = NULL; 1014 if (which == RTA_DST && !forcehost) { 1015 bits = inet_net_pton(AF_INET, s, &su->sin.sin_addr, 1016 sizeof(su->sin.sin_addr)); 1017 if (bits == 32) 1018 return (1); 1019 if (bits >= 0) { 1020 inet_makenetandmask(ntohl( 1021 su->sin.sin_addr.s_addr), 1022 &su->sin, bits); 1023 return (0); 1024 } 1025 } else if (which != RTA_DST || !forcenet) 1026 if (inet_pton(AF_INET, s, &su->sin.sin_addr) == 1) 1027 return (1); 1028 hp = gethostbyname(s); 1029 if (hp == NULL) 1030 errx(1, "%s: bad address", s); 1031 if (hpp != NULL) 1032 *hpp = hp; 1033 su->sin.sin_addr = *(struct in_addr *)hp->h_addr; 1034 return (1); 1035 1036 default: 1037 errx(1, "%d: bad address family", afamily); 1038 /* NOTREACHED */ 1039 } 1040 } 1041 1042 void 1043 getmplslabel(char *s, int in) 1044 { 1045 sup su = NULL; 1046 const char *errstr; 1047 u_int32_t label; 1048 1049 label = strtonum(s, 0, MPLS_LABEL_MAX, &errstr); 1050 if (errstr) 1051 errx(1, "bad label: %s is %s", s, errstr); 1052 if (in) { 1053 rtm_addrs |= RTA_DST; 1054 su = &so_dst; 1055 su->smpls.smpls_label = htonl(label << MPLS_LABEL_OFFSET); 1056 } else { 1057 rtm_addrs |= RTA_SRC; 1058 su = &so_src; 1059 su->smpls.smpls_label = htonl(label << MPLS_LABEL_OFFSET); 1060 } 1061 1062 su->sa.sa_len = sizeof(struct sockaddr_mpls); 1063 su->sa.sa_family = AF_MPLS; 1064 } 1065 1066 int 1067 prefixlen(int af, char *s) 1068 { 1069 const char *errstr; 1070 int len, q, r; 1071 int max; 1072 1073 switch (af) { 1074 case AF_INET: 1075 max = sizeof(struct in_addr) * 8; 1076 break; 1077 case AF_INET6: 1078 max = sizeof(struct in6_addr) * 8; 1079 break; 1080 default: 1081 errx(1, "prefixlen is not supported with af %d", af); 1082 /* NOTREACHED */ 1083 } 1084 1085 rtm_addrs |= RTA_NETMASK; 1086 len = strtonum(s, 0, max, &errstr); 1087 if (errstr) 1088 errx(1, "prefixlen %s is %s", s, errstr); 1089 1090 q = len >> 3; 1091 r = len & 7; 1092 switch (af) { 1093 case AF_INET: 1094 memset(&so_mask, 0, sizeof(so_mask)); 1095 so_mask.sin.sin_family = AF_INET; 1096 so_mask.sin.sin_len = sizeof(struct sockaddr_in); 1097 if (len != 0) 1098 so_mask.sin.sin_addr.s_addr = htonl(0xffffffff << (32 - len)); 1099 break; 1100 case AF_INET6: 1101 so_mask.sin6.sin6_family = AF_INET6; 1102 so_mask.sin6.sin6_len = sizeof(struct sockaddr_in6); 1103 memset((void *)&so_mask.sin6.sin6_addr, 0, 1104 sizeof(so_mask.sin6.sin6_addr)); 1105 if (q > 0) 1106 memset((void *)&so_mask.sin6.sin6_addr, 0xff, q); 1107 if (r > 0) 1108 *((u_char *)&so_mask.sin6.sin6_addr + q) = 1109 (0xff00 >> r) & 0xff; 1110 break; 1111 } 1112 return (len == max); 1113 } 1114 1115 void 1116 monitor(int argc, char *argv[]) 1117 { 1118 int n; 1119 char msg[2048]; 1120 time_t now; 1121 1122 verbose = 1; 1123 for (;;) { 1124 if ((n = read(s, msg, sizeof(msg))) == -1) { 1125 if (errno == EINTR) 1126 continue; 1127 err(1, "read"); 1128 } 1129 now = time(NULL); 1130 printf("got message of size %d on %s", n, ctime(&now)); 1131 print_rtmsg((struct rt_msghdr *)msg, n); 1132 } 1133 } 1134 1135 struct { 1136 struct rt_msghdr m_rtm; 1137 char m_space[512]; 1138 } m_rtmsg; 1139 1140 int 1141 rtmsg(int cmd, int flags, int fmask, uint8_t prio) 1142 { 1143 static int seq; 1144 char *cp = m_rtmsg.m_space; 1145 int l; 1146 1147 #define NEXTADDR(w, u) \ 1148 if (rtm_addrs & (w)) { \ 1149 l = ROUNDUP(u.sa.sa_len); \ 1150 memcpy(cp, &(u), l); \ 1151 cp += l; \ 1152 if (verbose) \ 1153 sodump(&(u), #u); \ 1154 } 1155 1156 errno = 0; 1157 memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 1158 if (cmd == 'a') 1159 cmd = RTM_ADD; 1160 else if (cmd == 'c') 1161 cmd = RTM_CHANGE; 1162 else if (cmd == 'g') { 1163 cmd = RTM_GET; 1164 if (so_ifp.sa.sa_family == AF_UNSPEC) { 1165 so_ifp.sa.sa_family = AF_LINK; 1166 so_ifp.sa.sa_len = sizeof(struct sockaddr_dl); 1167 rtm_addrs |= RTA_IFP; 1168 } 1169 } else if (cmd == 's') { 1170 cmd = RTM_SOURCE; 1171 } else 1172 cmd = RTM_DELETE; 1173 #define rtm m_rtmsg.m_rtm 1174 rtm.rtm_type = cmd; 1175 rtm.rtm_flags = flags; 1176 rtm.rtm_fmask = fmask; 1177 rtm.rtm_version = RTM_VERSION; 1178 rtm.rtm_seq = ++seq; 1179 rtm.rtm_addrs = rtm_addrs; 1180 rtm.rtm_rmx = rt_metrics; 1181 rtm.rtm_inits = rtm_inits; 1182 rtm.rtm_tableid = tableid; 1183 rtm.rtm_priority = prio; 1184 rtm.rtm_mpls = mpls_flags; 1185 rtm.rtm_hdrlen = sizeof(rtm); 1186 1187 /* store addresses in ascending order of RTA values */ 1188 NEXTADDR(RTA_DST, so_dst); 1189 NEXTADDR(RTA_GATEWAY, so_gate); 1190 NEXTADDR(RTA_NETMASK, so_mask); 1191 NEXTADDR(RTA_IFP, so_ifp); 1192 NEXTADDR(RTA_IFA, so_ifa); 1193 NEXTADDR(RTA_SRC, so_src); 1194 NEXTADDR(RTA_LABEL, so_label); 1195 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; 1196 if (verbose) 1197 print_rtmsg(&rtm, l); 1198 if (debugonly) 1199 return (0); 1200 if (write(s, &m_rtmsg, l) != l) { 1201 return (-1); 1202 } 1203 if (cmd == RTM_GET) { 1204 do { 1205 l = read(s, &m_rtmsg, sizeof(m_rtmsg)); 1206 } while (l > 0 && (rtm.rtm_version != RTM_VERSION || 1207 rtm.rtm_seq != seq || rtm.rtm_pid != pid)); 1208 if (l == -1) 1209 warn("read from routing socket"); 1210 else 1211 print_getmsg(&rtm, l); 1212 } 1213 #undef rtm 1214 return (0); 1215 } 1216 1217 char *msgtypes[] = { 1218 "", 1219 "RTM_ADD: Add Route", 1220 "RTM_DELETE: Delete Route", 1221 "RTM_CHANGE: Change Metrics or flags", 1222 "RTM_GET: Report Metrics", 1223 "RTM_LOSING: Kernel Suspects Partitioning", 1224 "RTM_REDIRECT: Told to use different route", 1225 "RTM_MISS: Lookup failed on this address", 1226 "", 1227 "", 1228 "", 1229 "RTM_RESOLVE: Route created by cloning", 1230 "RTM_NEWADDR: address being added to iface", 1231 "RTM_DELADDR: address being removed from iface", 1232 "RTM_IFINFO: iface status change", 1233 "RTM_IFANNOUNCE: iface arrival/departure", 1234 "RTM_DESYNC: route socket overflow", 1235 "RTM_INVALIDATE: invalidate cache of L2 route", 1236 "RTM_BFD: bidirectional forwarding detection", 1237 "RTM_PROPOSAL: config proposal", 1238 "RTM_CHGADDRATTR: address attributes being changed", 1239 "RTM_80211INFO: 802.11 iface status change" 1240 }; 1241 1242 char metricnames[] = 1243 "\011priority\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu"; 1244 char routeflags[] = 1245 "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010XMASK_PRESENT" 1246 "\011CLONING\012MULTICAST\013LLINFO\014STATIC\015BLACKHOLE\016PROTO3\017PROTO2" 1247 "\020PROTO1\021CLONED\022CACHED\023MPATH\025MPLS\026LOCAL\027BROADCAST" 1248 "\030CONNECTED\031BFD"; 1249 char ifnetflags[] = 1250 "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6STATICARP\7RUNNING\010NOARP\011PPROMISC" 1251 "\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST" 1252 "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII\30AUTOCONF4"; 1253 char addrnames[] = 1254 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011SRC\012SRCMASK\013LABEL\014BFD\015DNS\016STATIC\017SEARCH"; 1255 char ieee80211flags[] = 1256 "\1ASCAN\2SIBSS\011WEPON\012IBSSON\013PMGTON\014DESBSSID\016ROAMING" 1257 "\020TXPOW_FIXED\021TXPOW_AUTO\022SHSLOT\023SHPREAMBLE\024QOS" 1258 "\025USEPROT\026RSNON\027PSK\030COUNTERM\031MFPR\032HTON\033PBAR" 1259 "\034BGSCAN\035AUTO_JOIN\036VHTON"; 1260 char ieee80211xflags[] = 1261 "\1TX_MGMT_ONLY"; 1262 1263 const char * 1264 get_linkstate(int mt, int link_state) 1265 { 1266 const struct if_status_description *p; 1267 static char buf[8]; 1268 1269 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 1270 if (LINK_STATE_DESC_MATCH(p, mt, link_state)) 1271 return (p->ifs_string); 1272 } 1273 snprintf(buf, sizeof(buf), "[#%d]", link_state); 1274 return buf; 1275 } 1276 1277 void 1278 print_rtmsg(struct rt_msghdr *rtm, int msglen) 1279 { 1280 long long relative_expire; 1281 struct if_msghdr *ifm; 1282 struct ifa_msghdr *ifam; 1283 struct if_announcemsghdr *ifan; 1284 char ifname[IF_NAMESIZE]; 1285 1286 if (verbose == 0) 1287 return; 1288 if (rtm->rtm_version != RTM_VERSION) { 1289 warnx("routing message version %u not understood", 1290 rtm->rtm_version); 1291 return; 1292 } 1293 if (rtm->rtm_type > 0 && 1294 rtm->rtm_type < sizeof(msgtypes)/sizeof(msgtypes[0])) 1295 printf("%s", msgtypes[rtm->rtm_type]); 1296 else 1297 printf("[rtm_type %u out of range]", rtm->rtm_type); 1298 1299 printf(": len %u", rtm->rtm_msglen); 1300 switch (rtm->rtm_type) { 1301 case RTM_DESYNC: 1302 printf("\n"); 1303 break; 1304 case RTM_IFINFO: 1305 ifm = (struct if_msghdr *)rtm; 1306 printf(", if# %u, ", ifm->ifm_index); 1307 if (if_indextoname(ifm->ifm_index, ifname) != NULL) 1308 printf("name %s, ", ifname); 1309 printf("link: %s, mtu: %u, flags:", 1310 get_linkstate(ifm->ifm_data.ifi_type, 1311 ifm->ifm_data.ifi_link_state), 1312 ifm->ifm_data.ifi_mtu); 1313 bprintf(stdout, ifm->ifm_flags | (ifm->ifm_xflags << 16), 1314 ifnetflags); 1315 pmsg_addrs((char *)ifm + ifm->ifm_hdrlen, ifm->ifm_addrs); 1316 break; 1317 case RTM_80211INFO: 1318 printf(", if# %u, ", rtm->rtm_index); 1319 if (if_indextoname(rtm->rtm_index, ifname) != NULL) 1320 printf("name %s, ", ifname); 1321 print_80211info((struct if_ieee80211_msghdr *)rtm); 1322 break; 1323 case RTM_NEWADDR: 1324 case RTM_DELADDR: 1325 case RTM_CHGADDRATTR: 1326 ifam = (struct ifa_msghdr *)rtm; 1327 printf(", if# %u, ", ifam->ifam_index); 1328 if (if_indextoname(ifam->ifam_index, ifname) != NULL) 1329 printf("name %s, ", ifname); 1330 printf("metric %d, flags:", ifam->ifam_metric); 1331 bprintf(stdout, ifam->ifam_flags, routeflags); 1332 pmsg_addrs((char *)ifam + ifam->ifam_hdrlen, ifam->ifam_addrs); 1333 break; 1334 case RTM_IFANNOUNCE: 1335 ifan = (struct if_announcemsghdr *)rtm; 1336 printf(", if# %u, name %s, what: ", 1337 ifan->ifan_index, ifan->ifan_name); 1338 switch (ifan->ifan_what) { 1339 case IFAN_ARRIVAL: 1340 printf("arrival"); 1341 break; 1342 case IFAN_DEPARTURE: 1343 printf("departure"); 1344 break; 1345 default: 1346 printf("#%u", ifan->ifan_what); 1347 break; 1348 } 1349 printf("\n"); 1350 break; 1351 #ifdef BFD 1352 case RTM_BFD: 1353 print_bfdmsg(rtm); 1354 break; 1355 #endif 1356 case RTM_PROPOSAL: 1357 printf(", source "); 1358 switch (rtm->rtm_priority) { 1359 case RTP_PROPOSAL_STATIC: 1360 printf("static"); 1361 break; 1362 case RTP_PROPOSAL_DHCLIENT: 1363 printf("dhcp"); 1364 break; 1365 case RTP_PROPOSAL_SLAAC: 1366 printf("slaac"); 1367 break; 1368 case RTP_PROPOSAL_UMB: 1369 printf("umb"); 1370 break; 1371 case RTP_PROPOSAL_SOLICIT: 1372 printf("solicit"); 1373 break; 1374 default: 1375 printf("unknown"); 1376 break; 1377 } 1378 printf(", table %u, if# %u, ", 1379 rtm->rtm_tableid, rtm->rtm_index); 1380 if (if_indextoname(rtm->rtm_index, ifname) != NULL) 1381 printf("name %s, ", ifname); 1382 printf("pid: %ld, seq %d, errno %d\nflags:", 1383 (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); 1384 bprintf(stdout, rtm->rtm_flags, routeflags); 1385 printf("\nfmask:"); 1386 bprintf(stdout, rtm->rtm_fmask, routeflags); 1387 if (verbose) { 1388 #define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') 1389 relative_expire = rtm->rtm_rmx.rmx_expire ? 1390 rtm->rtm_rmx.rmx_expire - time(NULL) : 0; 1391 printf("\nuse: %8llu mtu: %8u%c expire: %8lld%c", 1392 rtm->rtm_rmx.rmx_pksent, 1393 rtm->rtm_rmx.rmx_mtu, lock(MTU), 1394 relative_expire, lock(EXPIRE)); 1395 #undef lock 1396 } 1397 printf("\nlocks: "); 1398 bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); 1399 printf(" inits: "); 1400 bprintf(stdout, rtm->rtm_inits, metricnames); 1401 pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen), 1402 rtm->rtm_addrs & ~(RTA_STATIC | RTA_SEARCH | RTA_DNS)); 1403 1404 if(!(rtm->rtm_addrs & (RTA_STATIC | RTA_SEARCH | RTA_DNS))) 1405 break; 1406 1407 printf("proposals: "); 1408 bprintf(stdout, rtm->rtm_addrs & (RTA_STATIC | RTA_SEARCH | 1409 RTA_DNS), addrnames); 1410 putchar('\n'); 1411 1412 if (rtm->rtm_addrs & RTA_STATIC) { 1413 char *next = (char *)rtm + rtm->rtm_hdrlen; 1414 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1415 struct sockaddr_rtstatic *rtstatic; 1416 sa = (struct sockaddr *)next; 1417 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 1418 rtstatic = (struct sockaddr_rtstatic *) 1419 rti_info[RTAX_STATIC]; 1420 if (rtstatic != NULL) 1421 print_rtstatic(rtstatic); 1422 } 1423 1424 if (rtm->rtm_addrs & RTA_SEARCH) { 1425 char *next = (char *)rtm + rtm->rtm_hdrlen; 1426 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1427 struct sockaddr_rtsearch *rtsearch; 1428 sa = (struct sockaddr *)next; 1429 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 1430 rtsearch = (struct sockaddr_rtsearch *) 1431 rti_info[RTAX_SEARCH]; 1432 if (rtsearch != NULL) 1433 print_rtsearch(rtsearch); 1434 } 1435 1436 if (rtm->rtm_addrs & RTA_DNS) { 1437 char *next = (char *)rtm + rtm->rtm_hdrlen; 1438 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1439 struct sockaddr_rtdns *rtdns; 1440 sa = (struct sockaddr *)next; 1441 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 1442 rtdns = (struct sockaddr_rtdns *)rti_info[RTAX_DNS]; 1443 if (rtdns != NULL) 1444 print_rtdns(rtdns); 1445 } 1446 putchar('\n'); 1447 break; 1448 default: 1449 printf(", priority %u, table %u, if# %u, ", 1450 rtm->rtm_priority, rtm->rtm_tableid, rtm->rtm_index); 1451 if (if_indextoname(rtm->rtm_index, ifname) != NULL) 1452 printf("name %s, ", ifname); 1453 printf("pid: %ld, seq %d, errno %d\nflags:", 1454 (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); 1455 bprintf(stdout, rtm->rtm_flags, routeflags); 1456 printf("\nfmask:"); 1457 bprintf(stdout, rtm->rtm_fmask, routeflags); 1458 if (verbose) { 1459 #define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') 1460 relative_expire = rtm->rtm_rmx.rmx_expire ? 1461 rtm->rtm_rmx.rmx_expire - time(NULL) : 0; 1462 printf("\nuse: %8llu mtu: %8u%c expire: %8lld%c", 1463 rtm->rtm_rmx.rmx_pksent, 1464 rtm->rtm_rmx.rmx_mtu, lock(MTU), 1465 relative_expire, lock(EXPIRE)); 1466 #undef lock 1467 } 1468 pmsg_common(rtm); 1469 } 1470 } 1471 1472 char * 1473 priorityname(uint8_t prio) 1474 { 1475 switch (prio) { 1476 case RTP_NONE: 1477 return ("none"); 1478 case RTP_LOCAL: 1479 return ("local"); 1480 case RTP_CONNECTED: 1481 return ("connected"); 1482 case RTP_STATIC: 1483 return ("static"); 1484 case RTP_OSPF: 1485 return ("ospf"); 1486 case RTP_ISIS: 1487 return ("is-is"); 1488 case RTP_RIP: 1489 return ("rip"); 1490 case RTP_BGP: 1491 return ("bgp"); 1492 case RTP_DEFAULT: 1493 return ("default"); 1494 default: 1495 return (""); 1496 } 1497 } 1498 1499 uint8_t 1500 getpriority(char *priostr) 1501 { 1502 const char *errstr; 1503 uint8_t prio; 1504 1505 switch (keyword(priostr)) { 1506 case K_LOCAL: 1507 prio = RTP_LOCAL; 1508 break; 1509 case K_CONNECTED: 1510 prio = RTP_CONNECTED; 1511 break; 1512 case K_STATIC: 1513 prio = RTP_STATIC; 1514 break; 1515 case K_OSPF: 1516 prio = RTP_OSPF; 1517 break; 1518 case K_RIP: 1519 prio = RTP_RIP; 1520 break; 1521 case K_BGP: 1522 prio = RTP_BGP; 1523 break; 1524 default: 1525 prio = strtonum(priostr, -RTP_MAX, RTP_MAX, &errstr); 1526 if (errstr) 1527 errx(1, "priority is %s: %s", errstr, priostr); 1528 } 1529 1530 return (prio); 1531 } 1532 1533 void 1534 print_getmsg(struct rt_msghdr *rtm, int msglen) 1535 { 1536 long long relative_expire; 1537 struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL; 1538 struct sockaddr_dl *ifp = NULL; 1539 struct sockaddr_rtlabel *sa_rl = NULL; 1540 #ifdef BFD 1541 struct sockaddr_bfd *sa_bfd = NULL; 1542 #endif 1543 struct sockaddr *mpls = NULL; 1544 struct sockaddr *sa; 1545 char *cp; 1546 int i; 1547 1548 printf(" route to: %s\n", routename(&so_dst.sa)); 1549 if (rtm->rtm_version != RTM_VERSION) { 1550 warnx("routing message version %u not understood", 1551 rtm->rtm_version); 1552 return; 1553 } 1554 if (rtm->rtm_msglen > msglen) 1555 warnx("message length mismatch, in packet %u, returned %d", 1556 rtm->rtm_msglen, msglen); 1557 if (rtm->rtm_errno) { 1558 warnx("RTM_GET: %s (errno %d)", 1559 strerror(rtm->rtm_errno), rtm->rtm_errno); 1560 return; 1561 } 1562 cp = ((char *)rtm + rtm->rtm_hdrlen); 1563 if (rtm->rtm_addrs) 1564 for (i = 1; i; i <<= 1) 1565 if (i & rtm->rtm_addrs) { 1566 sa = (struct sockaddr *)cp; 1567 switch (i) { 1568 case RTA_DST: 1569 dst = sa; 1570 break; 1571 case RTA_GATEWAY: 1572 gate = sa; 1573 break; 1574 case RTA_NETMASK: 1575 mask = sa; 1576 break; 1577 case RTA_IFA: 1578 ifa = sa; 1579 break; 1580 case RTA_IFP: 1581 if (sa->sa_family == AF_LINK && 1582 ((struct sockaddr_dl *)sa)->sdl_nlen) 1583 ifp = (struct sockaddr_dl *)sa; 1584 break; 1585 case RTA_SRC: 1586 mpls = sa; 1587 break; 1588 case RTA_LABEL: 1589 sa_rl = (struct sockaddr_rtlabel *)sa; 1590 break; 1591 #ifdef BFD 1592 case RTA_BFD: 1593 sa_bfd = (struct sockaddr_bfd *)sa; 1594 break; 1595 #endif 1596 } 1597 ADVANCE(cp, sa); 1598 } 1599 if (dst && mask) 1600 mask->sa_family = dst->sa_family; /* XXX */ 1601 if (dst) 1602 printf("destination: %s\n", routename(dst)); 1603 if (mask) { 1604 int savenflag = nflag; 1605 1606 nflag = 1; 1607 printf(" mask: %s\n", routename(mask)); 1608 nflag = savenflag; 1609 } 1610 if (gate && rtm->rtm_flags & RTF_GATEWAY) 1611 printf(" gateway: %s\n", routename(gate)); 1612 if (ifp) 1613 printf(" interface: %.*s\n", 1614 ifp->sdl_nlen, ifp->sdl_data); 1615 if (ifa) 1616 printf(" if address: %s\n", routename(ifa)); 1617 if (mpls) { 1618 printf(" mpls label: %s %s\n", mpls_op(rtm->rtm_mpls), 1619 routename(mpls)); 1620 } 1621 printf(" priority: %u (%s)\n", rtm->rtm_priority, 1622 priorityname(rtm->rtm_priority)); 1623 printf(" flags: "); 1624 bprintf(stdout, rtm->rtm_flags, routeflags); 1625 printf("\n"); 1626 if (sa_rl != NULL) 1627 printf(" label: %s\n", sa_rl->sr_label); 1628 #ifdef BFD 1629 if (sa_bfd) 1630 print_sabfd(sa_bfd, rtm->rtm_fmask); 1631 #endif 1632 1633 #define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') 1634 relative_expire = rtm->rtm_rmx.rmx_expire ? 1635 rtm->rtm_rmx.rmx_expire - time(NULL) : 0; 1636 printf(" use mtu expire\n"); 1637 printf("%8llu %8u%c %8lld%c\n", 1638 rtm->rtm_rmx.rmx_pksent, 1639 rtm->rtm_rmx.rmx_mtu, lock(MTU), 1640 relative_expire, lock(EXPIRE)); 1641 #undef lock 1642 #define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) 1643 if (verbose) 1644 pmsg_common(rtm); 1645 else if (rtm->rtm_addrs &~ RTA_IGN) { 1646 printf("sockaddrs: "); 1647 bprintf(stdout, rtm->rtm_addrs, addrnames); 1648 putchar('\n'); 1649 } 1650 #undef RTA_IGN 1651 } 1652 1653 #ifdef BFD 1654 const char * 1655 bfd_state(unsigned int state) 1656 { 1657 switch (state) { 1658 case BFD_STATE_ADMINDOWN: 1659 return("admindown"); 1660 break; 1661 case BFD_STATE_DOWN: 1662 return("down"); 1663 break; 1664 case BFD_STATE_INIT: 1665 return("init"); 1666 break; 1667 case BFD_STATE_UP: 1668 return("up"); 1669 break; 1670 } 1671 return "invalid"; 1672 } 1673 1674 const char * 1675 bfd_diag(unsigned int diag) 1676 { 1677 switch (diag) { 1678 case BFD_DIAG_NONE: 1679 return("none"); 1680 break; 1681 case BFD_DIAG_EXPIRED: 1682 return("expired"); 1683 break; 1684 case BFD_DIAG_ECHO_FAILED: 1685 return("echo-failed"); 1686 break; 1687 case BFD_DIAG_NEIGHBOR_SIGDOWN: 1688 return("neighbor-down"); 1689 break; 1690 case BFD_DIAG_FIB_RESET: 1691 return("fib-reset"); 1692 break; 1693 case BFD_DIAG_PATH_DOWN: 1694 return("path-down"); 1695 break; 1696 case BFD_DIAG_CONCAT_PATH_DOWN: 1697 return("concat-path-down"); 1698 break; 1699 case BFD_DIAG_ADMIN_DOWN: 1700 return("admindown"); 1701 break; 1702 case BFD_DIAG_CONCAT_REVERSE_DOWN: 1703 return("concat-reverse-down"); 1704 break; 1705 } 1706 return "invalid"; 1707 } 1708 1709 const char * 1710 bfd_calc_uptime(time_t time) 1711 { 1712 static char buf[256]; 1713 struct tm *tp; 1714 const char *fmt; 1715 1716 if (time > 2*86400) 1717 fmt = "%dd%kh%Mm%Ss"; 1718 else if (time > 2*3600) 1719 fmt = "%kh%Mm%Ss"; 1720 else if (time > 2*60) 1721 fmt = "%Mm%Ss"; 1722 else 1723 fmt = "%Ss"; 1724 1725 tp = localtime(&time); 1726 (void)strftime(buf, sizeof(buf), fmt, tp); 1727 return (buf); 1728 } 1729 1730 void 1731 print_bfdmsg(struct rt_msghdr *rtm) 1732 { 1733 struct bfd_msghdr *bfdm = (struct bfd_msghdr *)rtm; 1734 1735 printf("\n"); 1736 print_sabfd(&bfdm->bm_sa, rtm->rtm_fmask); 1737 pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen), rtm->rtm_addrs); 1738 } 1739 1740 void 1741 print_sabfd(struct sockaddr_bfd *sa_bfd, int fmask) 1742 { 1743 struct timeval tv; 1744 1745 gettimeofday(&tv, NULL); 1746 1747 printf(" BFD:"); 1748 1749 /* only show the state, unless verbose or -bfd */ 1750 if (!verbose && ((fmask & RTF_BFD) != RTF_BFD)) { 1751 printf(" %s\n", bfd_state(sa_bfd->bs_state)); 1752 return; 1753 } 1754 1755 switch (sa_bfd->bs_mode) { 1756 case BFD_MODE_ASYNC: 1757 printf(" async"); 1758 break; 1759 case BFD_MODE_DEMAND: 1760 printf(" demand"); 1761 break; 1762 default: 1763 printf(" unknown %u", sa_bfd->bs_mode); 1764 break; 1765 } 1766 1767 printf(" state %s", bfd_state(sa_bfd->bs_state)); 1768 printf(" remote %s", bfd_state(sa_bfd->bs_remotestate)); 1769 printf(" laststate %s", bfd_state(sa_bfd->bs_laststate)); 1770 1771 printf(" error %u", sa_bfd->bs_error); 1772 printf("\n "); 1773 printf(" diag %s", bfd_diag(sa_bfd->bs_localdiag)); 1774 printf(" remote %s", bfd_diag(sa_bfd->bs_remotediag)); 1775 printf("\n "); 1776 printf(" discr %u", sa_bfd->bs_localdiscr); 1777 printf(" remote %u", sa_bfd->bs_remotediscr); 1778 printf("\n "); 1779 printf(" uptime %s", bfd_calc_uptime(tv.tv_sec - sa_bfd->bs_uptime)); 1780 if (sa_bfd->bs_lastuptime) 1781 printf(" last state time %s", 1782 bfd_calc_uptime(sa_bfd->bs_lastuptime)); 1783 printf("\n "); 1784 printf(" mintx %u", sa_bfd->bs_mintx); 1785 printf(" minrx %u", sa_bfd->bs_minrx); 1786 printf(" minecho %u", sa_bfd->bs_minecho); 1787 printf(" multiplier %u", sa_bfd->bs_multiplier); 1788 printf("\n"); 1789 } 1790 #endif /* BFD */ 1791 1792 void 1793 pmsg_common(struct rt_msghdr *rtm) 1794 { 1795 printf("\nlocks: "); 1796 bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); 1797 printf(" inits: "); 1798 bprintf(stdout, rtm->rtm_inits, metricnames); 1799 pmsg_addrs(((char *)rtm + rtm->rtm_hdrlen), rtm->rtm_addrs); 1800 } 1801 1802 void 1803 pmsg_addrs(char *cp, int addrs) 1804 { 1805 struct sockaddr *sa; 1806 int family = AF_UNSPEC; 1807 int i; 1808 char *p; 1809 1810 if (addrs != 0) { 1811 printf("\nsockaddrs: "); 1812 bprintf(stdout, addrs, addrnames); 1813 putchar('\n'); 1814 /* first run, search for address family */ 1815 p = cp; 1816 for (i = 1; i; i <<= 1) 1817 if (i & addrs) { 1818 sa = (struct sockaddr *)p; 1819 if (family == AF_UNSPEC) 1820 switch (i) { 1821 case RTA_DST: 1822 case RTA_IFA: 1823 family = sa->sa_family; 1824 } 1825 ADVANCE(p, sa); 1826 } 1827 /* second run, set address family for mask and print */ 1828 p = cp; 1829 for (i = 1; i; i <<= 1) 1830 if (i & addrs) { 1831 sa = (struct sockaddr *)p; 1832 if (family != AF_UNSPEC) 1833 switch (i) { 1834 case RTA_NETMASK: 1835 sa->sa_family = family; 1836 } 1837 printf(" %s", routename(sa)); 1838 ADVANCE(p, sa); 1839 } 1840 } 1841 putchar('\n'); 1842 fflush(stdout); 1843 } 1844 1845 void 1846 bprintf(FILE *fp, int b, char *s) 1847 { 1848 int i; 1849 int gotsome = 0; 1850 1851 if (b == 0) 1852 return; 1853 while ((i = *s++)) { 1854 if ((b & (1 << (i-1)))) { 1855 if (gotsome == 0) 1856 i = '<'; 1857 else 1858 i = ','; 1859 putc(i, fp); 1860 gotsome = 1; 1861 for (; (i = *s) > 32; s++) 1862 putc(i, fp); 1863 } else 1864 while (*s > 32) 1865 s++; 1866 } 1867 if (gotsome) 1868 putc('>', fp); 1869 } 1870 1871 int 1872 keycmp(const void *key, const void *kt) 1873 { 1874 return (strcmp(key, ((struct keytab *)kt)->kt_cp)); 1875 } 1876 1877 int 1878 keyword(char *cp) 1879 { 1880 struct keytab *kt; 1881 1882 kt = bsearch(cp, keywords, sizeof(keywords)/sizeof(keywords[0]), 1883 sizeof(keywords[0]), keycmp); 1884 if (!kt) 1885 return (0); 1886 1887 return (kt->kt_i); 1888 } 1889 1890 void 1891 sodump(sup su, char *which) 1892 { 1893 switch (su->sa.sa_family) { 1894 case AF_LINK: 1895 printf("%s: link %s; ", which, link_ntoa(&su->sdl)); 1896 break; 1897 case AF_INET: 1898 printf("%s: inet %s; ", which, inet_ntoa(su->sin.sin_addr)); 1899 break; 1900 case AF_INET6: 1901 { 1902 char ntop_buf[NI_MAXHOST]; 1903 1904 printf("%s: inet6 %s; ", 1905 which, inet_ntop(AF_INET6, &su->sin6.sin6_addr, 1906 ntop_buf, sizeof(ntop_buf))); 1907 break; 1908 } 1909 } 1910 fflush(stdout); 1911 } 1912 1913 /* States*/ 1914 #define VIRGIN 0 1915 #define GOTONE 1 1916 #define GOTTWO 2 1917 /* Inputs */ 1918 #define DIGIT (4*0) 1919 #define END (4*1) 1920 #define DELIM (4*2) 1921 1922 void 1923 sockaddr(char *addr, struct sockaddr *sa) 1924 { 1925 char *cp = (char *)sa; 1926 int size = sa->sa_len; 1927 char *cplim = cp + size; 1928 int byte = 0, state = VIRGIN, new = 0; 1929 1930 memset(cp, 0, size); 1931 cp++; 1932 do { 1933 if ((*addr >= '0') && (*addr <= '9')) { 1934 new = *addr - '0'; 1935 } else if ((*addr >= 'a') && (*addr <= 'f')) { 1936 new = *addr - 'a' + 10; 1937 } else if ((*addr >= 'A') && (*addr <= 'F')) { 1938 new = *addr - 'A' + 10; 1939 } else if (*addr == '\0') 1940 state |= END; 1941 else 1942 state |= DELIM; 1943 addr++; 1944 switch (state /* | INPUT */) { 1945 case GOTTWO | DIGIT: 1946 *cp++ = byte; /*FALLTHROUGH*/ 1947 case VIRGIN | DIGIT: 1948 state = GOTONE; byte = new; continue; 1949 case GOTONE | DIGIT: 1950 state = GOTTWO; byte = new + (byte << 4); continue; 1951 default: /* | DELIM */ 1952 state = VIRGIN; *cp++ = byte; byte = 0; continue; 1953 case GOTONE | END: 1954 case GOTTWO | END: 1955 *cp++ = byte; /* FALLTHROUGH */ 1956 case VIRGIN | END: 1957 break; 1958 } 1959 break; 1960 } while (cp < cplim); 1961 sa->sa_len = cp - (char *)sa; 1962 } 1963 1964 void 1965 getlabel(char *name) 1966 { 1967 so_label.rtlabel.sr_len = sizeof(so_label.rtlabel); 1968 so_label.rtlabel.sr_family = AF_UNSPEC; 1969 if (strlcpy(so_label.rtlabel.sr_label, name, 1970 sizeof(so_label.rtlabel.sr_label)) >= 1971 sizeof(so_label.rtlabel.sr_label)) 1972 errx(1, "label too long"); 1973 rtm_addrs |= RTA_LABEL; 1974 } 1975 1976 int 1977 gettable(const char *s) 1978 { 1979 const char *errstr; 1980 struct rt_tableinfo info; 1981 int mib[6]; 1982 size_t len; 1983 1984 tableid = strtonum(s, 0, RT_TABLEID_MAX, &errstr); 1985 if (errstr) 1986 errx(1, "invalid table id: %s", errstr); 1987 1988 mib[0] = CTL_NET; 1989 mib[1] = PF_ROUTE; 1990 mib[2] = 0; 1991 mib[3] = 0; 1992 mib[4] = NET_RT_TABLE; 1993 mib[5] = tableid; 1994 1995 len = sizeof(info); 1996 if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) 1997 return (errno); 1998 else 1999 return (0); 2000 } 2001 2002 int 2003 rdomain(int argc, char **argv) 2004 { 2005 if (!argc) 2006 usage(NULL); 2007 if (setrtable(tableid) == -1) 2008 err(1, "setrtable"); 2009 execvp(*argv, argv); 2010 warn("%s", argv[0]); 2011 return (errno == ENOENT ? 127 : 126); 2012 } 2013 2014 /* 2015 * Print RTM_PROPOSAL DNS server addresses. 2016 */ 2017 void 2018 print_rtdns(struct sockaddr_rtdns *rtdns) 2019 { 2020 struct in_addr server; 2021 struct in6_addr in6; 2022 size_t srclen, offset; 2023 unsigned int servercnt; 2024 int i; 2025 char *src = rtdns->sr_dns; 2026 char ntopbuf[INET6_ADDRSTRLEN]; 2027 2028 offset = offsetof(struct sockaddr_rtdns, sr_dns); 2029 if (rtdns->sr_len < offset) { 2030 printf("<invalid sr_len (%u <= %zu)>\n", rtdns->sr_len, 2031 offset); 2032 return; 2033 } 2034 srclen = rtdns->sr_len - offset; 2035 if (srclen > sizeof(rtdns->sr_dns)) { 2036 printf("<invalid sr_len (%zu > %zu)>\n", srclen, 2037 sizeof(rtdns->sr_dns)); 2038 return; 2039 } 2040 switch (rtdns->sr_family) { 2041 case AF_INET: 2042 printf(" INET ["); 2043 /* An array of IPv4 addresses. */ 2044 servercnt = srclen / sizeof(struct in_addr); 2045 if (servercnt * sizeof(struct in_addr) != srclen) { 2046 printf("<invalid server count>\n"); 2047 return; 2048 } 2049 for (i = 0; i < servercnt; i++) { 2050 memcpy(&server.s_addr, src, sizeof(server.s_addr)); 2051 printf("%s%s", inet_ntoa(server), i == servercnt - 1 ? 2052 "": ", "); 2053 src += sizeof(struct in_addr); 2054 } 2055 break; 2056 case AF_INET6: 2057 printf(" INET6 ["); 2058 servercnt = srclen / sizeof(struct in6_addr); 2059 if (servercnt * sizeof(struct in6_addr) != srclen) { 2060 printf("<invalid server count>\n"); 2061 return; 2062 } 2063 for (i = 0; i < servercnt; i++) { 2064 memcpy(&in6, src, sizeof(in6)); 2065 src += sizeof(in6); 2066 printf("%s%s", inet_ntop(AF_INET6, &in6, ntopbuf, 2067 INET6_ADDRSTRLEN), i == servercnt - 1 ? "": ", "); 2068 } 2069 break; 2070 default: 2071 printf(" UNKNOWN ["); 2072 break; 2073 } 2074 printf("]"); 2075 } 2076 2077 /* 2078 * Print RTM_PROPOSAL static routes. 2079 */ 2080 void 2081 print_rtstatic(struct sockaddr_rtstatic *rtstatic) 2082 { 2083 struct sockaddr_in6 gateway6; 2084 struct in6_addr prefix; 2085 struct in_addr dest, gateway; 2086 size_t srclen, offset; 2087 int bits, bytes, error, first = 1; 2088 uint8_t prefixlen; 2089 unsigned char *src = rtstatic->sr_static; 2090 char ntoabuf[INET_ADDRSTRLEN]; 2091 char hbuf[NI_MAXHOST]; 2092 char ntopbuf[INET6_ADDRSTRLEN]; 2093 2094 offset = offsetof(struct sockaddr_rtstatic, sr_static); 2095 if (rtstatic->sr_len <= offset) { 2096 printf("<invalid sr_len (%u <= %zu)>\n", rtstatic->sr_len, 2097 offset); 2098 return; 2099 } 2100 srclen = rtstatic->sr_len - offset; 2101 if (srclen > sizeof(rtstatic->sr_static)) { 2102 printf("<invalid sr_len (%zu > %zu)>\n", srclen, 2103 sizeof(rtstatic->sr_static)); 2104 return; 2105 } 2106 printf(" ["); 2107 switch (rtstatic->sr_family) { 2108 case AF_INET: 2109 /* AF_INET -> RFC 3442 encoded static routes. */ 2110 while (srclen) { 2111 bits = *src; 2112 src++; 2113 srclen--; 2114 bytes = (bits + 7) / 8; 2115 if (srclen < bytes || bytes > sizeof(dest.s_addr)) 2116 break; 2117 memset(&dest, 0, sizeof(dest)); 2118 memcpy(&dest.s_addr, src, bytes); 2119 src += bytes; 2120 srclen -= bytes; 2121 strlcpy(ntoabuf, inet_ntoa(dest), sizeof(ntoabuf)); 2122 if (srclen < sizeof(gateway.s_addr)) 2123 break; 2124 memcpy(&gateway.s_addr, src, sizeof(gateway.s_addr)); 2125 src += sizeof(gateway.s_addr); 2126 srclen -= sizeof(gateway.s_addr); 2127 printf("%s%s/%u %s ", first ? "" : ", ", ntoabuf, bits, 2128 inet_ntoa(gateway)); 2129 first = 0; 2130 } 2131 break; 2132 case AF_INET6: 2133 while (srclen >= sizeof(prefixlen) + sizeof(prefix) + 2134 sizeof(gateway6)) { 2135 memcpy(&prefixlen, src, sizeof(prefixlen)); 2136 srclen -= sizeof(prefixlen); 2137 src += sizeof(prefixlen); 2138 2139 memcpy(&prefix, src, sizeof(prefix)); 2140 srclen -= sizeof(prefix); 2141 src += sizeof(prefix); 2142 2143 memcpy(&gateway6, src, sizeof(gateway6)); 2144 srclen -= sizeof(gateway6); 2145 src += sizeof(gateway6); 2146 2147 if ((error = getnameinfo((struct sockaddr *)&gateway6, 2148 gateway6.sin6_len, hbuf, sizeof(hbuf), NULL, 0, 2149 NI_NUMERICHOST | NI_NUMERICSERV))) { 2150 warnx("cannot get gateway address: %s", 2151 gai_strerror(error)); 2152 return; 2153 } 2154 printf("%s%s/%u %s ", first ? "" : ", ", 2155 inet_ntop(AF_INET6, &prefix, ntopbuf, 2156 INET6_ADDRSTRLEN), prefixlen, hbuf); 2157 first = 0; 2158 } 2159 break; 2160 default: 2161 printf("<unknown address family %u>", rtstatic->sr_family); 2162 break; 2163 } 2164 printf("]"); 2165 } 2166 2167 /* 2168 * Print RTM_PROPOSAL domain search list. 2169 */ 2170 void 2171 print_rtsearch(struct sockaddr_rtsearch *rtsearch) 2172 { 2173 char *src = rtsearch->sr_search; 2174 size_t srclen, offset; 2175 2176 offset = offsetof(struct sockaddr_rtsearch, sr_search); 2177 if (rtsearch->sr_len <= offset) { 2178 printf("<invalid sr_len (%u <= %zu)>\n", rtsearch->sr_len, 2179 offset); 2180 return; 2181 } 2182 srclen = rtsearch->sr_len - offset; 2183 if (srclen > sizeof(rtsearch->sr_search)) { 2184 printf("<invalid sr_len (%zu > %zu)>\n", srclen, 2185 sizeof(rtsearch->sr_search)); 2186 return; 2187 } 2188 2189 printf(" [%.*s]", (int)srclen, src); 2190 } 2191 2192 /* 2193 * Print RTM_80211INFO info. 2194 */ 2195 void 2196 print_80211info(struct if_ieee80211_msghdr *ifim) 2197 { 2198 unsigned int ascii, nwidlen, i; 2199 u_int8_t *nwid, *bssid; 2200 2201 ascii = 1; 2202 nwid = ifim->ifim_ifie.ifie_nwid; 2203 nwidlen = ifim->ifim_ifie.ifie_nwid_len; 2204 for (i = 0; i < nwidlen; i++) { 2205 if (i == 0) 2206 printf("nwid "); 2207 else 2208 printf(":"); 2209 printf("%02x", nwid[i]); 2210 if (!isprint((unsigned int)nwid[i])) 2211 ascii = 0; 2212 } 2213 if (i > 0) { 2214 if (ascii == 1) 2215 printf(" (%.*s)", nwidlen, nwid); 2216 printf(", "); 2217 } 2218 printf("channel %u, ", ifim->ifim_ifie.ifie_channel); 2219 bssid = ifim->ifim_ifie.ifie_addr; 2220 printf("bssid %02x:%02x:%02x:%02x:%02x:%02x\n", 2221 bssid[0], bssid[1], bssid[2], 2222 bssid[3], bssid[4], bssid[5]); 2223 printf("flags:"); 2224 bprintf(stdout, ifim->ifim_ifie.ifie_flags, ieee80211flags); 2225 printf("\nxflags:"); 2226 bprintf(stdout, ifim->ifim_ifie.ifie_xflags, ieee80211xflags); 2227 printf("\n"); 2228 } 2229