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