1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #ifndef lint 33 static const char copyright[] = 34 "@(#) Copyright (c) 1983, 1993\n\ 35 The Regents of the University of California. All rights reserved.\n"; 36 #if 0 37 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 38 #endif 39 static const char rcsid[] = 40 "$FreeBSD$"; 41 #endif /* not lint */ 42 43 #include <sys/param.h> 44 #include <sys/ioctl.h> 45 #include <sys/module.h> 46 #include <sys/linker.h> 47 #include <sys/nv.h> 48 #include <sys/queue.h> 49 #include <sys/socket.h> 50 #include <sys/time.h> 51 52 #include <net/ethernet.h> 53 #include <net/if.h> 54 #include <net/if_dl.h> 55 #include <net/if_types.h> 56 #include <net/route.h> 57 58 /* IP */ 59 #include <netinet/in.h> 60 #include <netinet/in_var.h> 61 #include <arpa/inet.h> 62 #include <netdb.h> 63 64 #include <fnmatch.h> 65 #include <ifaddrs.h> 66 #include <ctype.h> 67 #include <err.h> 68 #include <errno.h> 69 #include <fcntl.h> 70 #ifdef JAIL 71 #include <jail.h> 72 #endif 73 #include <stdbool.h> 74 #include <stdio.h> 75 #include <stdlib.h> 76 #include <string.h> 77 #include <unistd.h> 78 79 #include <libifconfig.h> 80 81 #include "ifconfig.h" 82 83 ifconfig_handle_t *lifh; 84 85 /* 86 * Since "struct ifreq" is composed of various union members, callers 87 * should pay special attention to interpret the value. 88 * (.e.g. little/big endian difference in the structure.) 89 */ 90 struct ifreq ifr; 91 92 char name[IFNAMSIZ]; 93 char *descr = NULL; 94 size_t descrlen = 64; 95 int setaddr; 96 int setmask; 97 int doalias; 98 int clearaddr; 99 int newaddr = 1; 100 int verbose; 101 int printifname = 0; 102 103 struct ifconfig_args args; 104 105 int printkeys = 0; /* Print keying material for interfaces. */ 106 int exit_code = 0; 107 108 /* Formatter Strings */ 109 char *f_inet, *f_inet6, *f_ether, *f_addr; 110 111 static bool group_member(const char *ifname, const char *match, 112 const char *nomatch); 113 static int ifconfig(int argc, char *const *argv, int iscreate, 114 const struct afswtch *afp); 115 static void status(struct ifconfig_args *args, const struct sockaddr_dl *sdl, 116 struct ifaddrs *ifa); 117 static void tunnel_status(int s); 118 static _Noreturn void usage(void); 119 120 static int getifflags(const char *ifname, int us, bool err_ok); 121 122 static struct afswtch *af_getbyname(const char *name); 123 static struct afswtch *af_getbyfamily(int af); 124 static void af_other_status(int); 125 126 void printifnamemaybe(void); 127 128 static struct option *opts = NULL; 129 130 struct ifa_order_elt { 131 int if_order; 132 int af_orders[255]; 133 struct ifaddrs *ifa; 134 TAILQ_ENTRY(ifa_order_elt) link; 135 }; 136 137 TAILQ_HEAD(ifa_queue, ifa_order_elt); 138 139 static struct module_map_entry { 140 const char *ifname; 141 const char *kldname; 142 } module_map[] = { 143 { 144 .ifname = "tun", 145 .kldname = "if_tuntap", 146 }, 147 { 148 .ifname = "tap", 149 .kldname = "if_tuntap", 150 }, 151 { 152 .ifname = "vmnet", 153 .kldname = "if_tuntap", 154 }, 155 { 156 .ifname = "ipsec", 157 .kldname = "ipsec", 158 }, 159 { 160 /* 161 * This mapping exists because there is a conflicting enc module 162 * in CAM. ifconfig's guessing behavior will attempt to match 163 * the ifname to a module as well as if_${ifname} and clash with 164 * CAM enc. This is an assertion of the correct module to load. 165 */ 166 .ifname = "enc", 167 .kldname = "if_enc", 168 }, 169 }; 170 171 172 void 173 opt_register(struct option *p) 174 { 175 p->next = opts; 176 opts = p; 177 } 178 179 static void 180 usage(void) 181 { 182 char options[1024]; 183 struct option *p; 184 185 /* XXX not right but close enough for now */ 186 options[0] = '\0'; 187 for (p = opts; p != NULL; p = p->next) { 188 strlcat(options, p->opt_usage, sizeof(options)); 189 strlcat(options, " ", sizeof(options)); 190 } 191 192 fprintf(stderr, 193 "usage: ifconfig [-f type:format] %sinterface address_family\n" 194 " [address [dest_address]] [parameters]\n" 195 " ifconfig interface create\n" 196 " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n" 197 " ifconfig -l [-d] [-u] [address_family]\n" 198 " ifconfig %s[-d] [-m] [-u] [-v]\n", 199 options, options, options); 200 exit(1); 201 } 202 203 void 204 ioctl_ifcreate(int s, struct ifreq *ifr) 205 { 206 if (ioctl(s, SIOCIFCREATE2, ifr) < 0) { 207 switch (errno) { 208 case EEXIST: 209 errx(1, "interface %s already exists", ifr->ifr_name); 210 default: 211 err(1, "SIOCIFCREATE2 (%s)", ifr->ifr_name); 212 } 213 } 214 } 215 216 static int 217 calcorders(struct ifaddrs *ifa, struct ifa_queue *q) 218 { 219 struct ifaddrs *prev; 220 struct ifa_order_elt *cur; 221 unsigned int ord, af, ifa_ord; 222 223 prev = NULL; 224 cur = NULL; 225 ord = 0; 226 ifa_ord = 0; 227 228 while (ifa != NULL) { 229 if (prev == NULL || 230 strcmp(ifa->ifa_name, prev->ifa_name) != 0) { 231 cur = calloc(1, sizeof(*cur)); 232 233 if (cur == NULL) 234 return (-1); 235 236 TAILQ_INSERT_TAIL(q, cur, link); 237 cur->if_order = ifa_ord ++; 238 cur->ifa = ifa; 239 ord = 0; 240 } 241 242 if (ifa->ifa_addr) { 243 af = ifa->ifa_addr->sa_family; 244 245 if (af < nitems(cur->af_orders) && 246 cur->af_orders[af] == 0) 247 cur->af_orders[af] = ++ord; 248 } 249 prev = ifa; 250 ifa = ifa->ifa_next; 251 } 252 253 return (0); 254 } 255 256 static int 257 cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q) 258 { 259 struct ifa_order_elt *cur, *e1, *e2; 260 unsigned int af1, af2; 261 int ret; 262 263 e1 = e2 = NULL; 264 265 ret = strcmp(a->ifa_name, b->ifa_name); 266 if (ret != 0) { 267 TAILQ_FOREACH(cur, q, link) { 268 if (e1 && e2) 269 break; 270 271 if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) 272 e1 = cur; 273 else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0) 274 e2 = cur; 275 } 276 277 if (!e1 || !e2) 278 return (0); 279 else 280 return (e1->if_order - e2->if_order); 281 282 } else if (a->ifa_addr != NULL && b->ifa_addr != NULL) { 283 TAILQ_FOREACH(cur, q, link) { 284 if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) { 285 e1 = cur; 286 break; 287 } 288 } 289 290 if (!e1) 291 return (0); 292 293 af1 = a->ifa_addr->sa_family; 294 af2 = b->ifa_addr->sa_family; 295 296 if (af1 < nitems(e1->af_orders) && af2 < nitems(e1->af_orders)) 297 return (e1->af_orders[af1] - e1->af_orders[af2]); 298 } 299 300 return (0); 301 } 302 303 static void freeformat(void) 304 { 305 306 if (f_inet != NULL) 307 free(f_inet); 308 if (f_inet6 != NULL) 309 free(f_inet6); 310 if (f_ether != NULL) 311 free(f_ether); 312 if (f_addr != NULL) 313 free(f_addr); 314 } 315 316 static void setformat(char *input) 317 { 318 char *formatstr, *category, *modifier; 319 320 formatstr = strdup(input); 321 while ((category = strsep(&formatstr, ",")) != NULL) { 322 modifier = strchr(category, ':'); 323 if (modifier == NULL || modifier[1] == '\0') { 324 warnx("Skipping invalid format specification: %s\n", 325 category); 326 continue; 327 } 328 329 /* Split the string on the separator, then seek past it */ 330 modifier[0] = '\0'; 331 modifier++; 332 333 if (strcmp(category, "addr") == 0) 334 f_addr = strdup(modifier); 335 else if (strcmp(category, "ether") == 0) 336 f_ether = strdup(modifier); 337 else if (strcmp(category, "inet") == 0) 338 f_inet = strdup(modifier); 339 else if (strcmp(category, "inet6") == 0) 340 f_inet6 = strdup(modifier); 341 } 342 free(formatstr); 343 } 344 345 static struct ifaddrs * 346 sortifaddrs(struct ifaddrs *list, 347 int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *), 348 struct ifa_queue *q) 349 { 350 struct ifaddrs *right, *temp, *last, *result, *next, *tail; 351 352 right = list; 353 temp = list; 354 last = list; 355 result = NULL; 356 next = NULL; 357 tail = NULL; 358 359 if (!list || !list->ifa_next) 360 return (list); 361 362 while (temp && temp->ifa_next) { 363 last = right; 364 right = right->ifa_next; 365 temp = temp->ifa_next->ifa_next; 366 } 367 368 last->ifa_next = NULL; 369 370 list = sortifaddrs(list, compare, q); 371 right = sortifaddrs(right, compare, q); 372 373 while (list || right) { 374 375 if (!right) { 376 next = list; 377 list = list->ifa_next; 378 } else if (!list) { 379 next = right; 380 right = right->ifa_next; 381 } else if (compare(list, right, q) <= 0) { 382 next = list; 383 list = list->ifa_next; 384 } else { 385 next = right; 386 right = right->ifa_next; 387 } 388 389 if (!result) 390 result = next; 391 else 392 tail->ifa_next = next; 393 394 tail = next; 395 } 396 397 return (result); 398 } 399 400 void printifnamemaybe() 401 { 402 if (printifname) 403 printf("%s\n", name); 404 } 405 406 static void list_interfaces(struct ifconfig_args *args); 407 408 int 409 main(int argc, char *argv[]) 410 { 411 int c; 412 const struct afswtch *afp = NULL; 413 int ifindex; 414 char options[1024], *envformat; 415 struct option *p; 416 size_t iflen; 417 int flags; 418 419 f_inet = f_inet6 = f_ether = f_addr = NULL; 420 421 lifh = ifconfig_open(); 422 if (lifh == NULL) 423 err(EXIT_FAILURE, "ifconfig_open"); 424 425 envformat = getenv("IFCONFIG_FORMAT"); 426 if (envformat != NULL) 427 setformat(envformat); 428 429 /* 430 * Ensure we print interface name when expected to, 431 * even if we terminate early due to error. 432 */ 433 atexit(printifnamemaybe); 434 435 /* Parse leading line options */ 436 strlcpy(options, "G:adf:klmnuv", sizeof(options)); 437 for (p = opts; p != NULL; p = p->next) 438 strlcat(options, p->opt, sizeof(options)); 439 while ((c = getopt(argc, argv, options)) != -1) { 440 switch (c) { 441 case 'a': /* scan all interfaces */ 442 args.all = true; 443 break; 444 case 'd': /* restrict scan to "down" interfaces */ 445 args.downonly = true; 446 break; 447 case 'f': 448 if (optarg == NULL) 449 usage(); 450 setformat(optarg); 451 break; 452 case 'G': 453 if (optarg == NULL || args.all == 0) 454 usage(); 455 args.nogroup = optarg; 456 break; 457 case 'k': 458 args.printkeys = true; 459 break; 460 case 'l': /* scan interface names only */ 461 args.namesonly++; 462 break; 463 case 'm': /* show media choices in status */ 464 args.supmedia = true; 465 break; 466 case 'n': /* suppress module loading */ 467 args.noload = true; 468 break; 469 case 'u': /* restrict scan to "up" interfaces */ 470 args.uponly = true; 471 break; 472 case 'v': 473 args.verbose++; 474 break; 475 case 'g': 476 if (args.all) { 477 if (optarg == NULL) 478 usage(); 479 args.matchgroup = optarg; 480 break; 481 } 482 /* FALLTHROUGH */ 483 default: 484 for (p = opts; p != NULL; p = p->next) 485 if (p->opt[0] == c) { 486 p->cb(optarg); 487 break; 488 } 489 if (p == NULL) 490 usage(); 491 break; 492 } 493 } 494 argc -= optind; 495 argv += optind; 496 497 /* Sync global variables */ 498 printkeys = args.printkeys; 499 verbose = args.verbose; 500 501 /* -l cannot be used with -a or -m */ 502 if (args.namesonly && (args.all || args.supmedia)) 503 usage(); 504 505 /* nonsense.. */ 506 if (args.uponly && args.downonly) 507 usage(); 508 509 /* no arguments is equivalent to '-a' */ 510 if (!args.namesonly && argc < 1) 511 args.all = 1; 512 513 /* -a and -l allow an address family arg to limit the output */ 514 if (args.all || args.namesonly) { 515 if (argc > 1) 516 usage(); 517 518 ifindex = 0; 519 if (argc == 1) { 520 afp = af_getbyname(*argv); 521 if (afp == NULL) { 522 warnx("Address family '%s' unknown.", *argv); 523 usage(); 524 } 525 if (afp->af_name != NULL) 526 argc--, argv++; 527 /* leave with afp non-zero */ 528 } 529 } else { 530 /* not listing, need an argument */ 531 if (argc < 1) 532 usage(); 533 534 args.ifname = *argv; 535 argc--, argv++; 536 537 /* check and maybe load support for this interface */ 538 ifmaybeload(&args, args.ifname); 539 540 ifindex = if_nametoindex(args.ifname); 541 if (ifindex == 0) { 542 /* 543 * NOTE: We must special-case the `create' command 544 * right here as we would otherwise fail when trying 545 * to find the interface. 546 */ 547 if (argc > 0 && (strcmp(argv[0], "create") == 0 || 548 strcmp(argv[0], "plumb") == 0)) { 549 iflen = strlcpy(name, args.ifname, sizeof(name)); 550 if (iflen >= sizeof(name)) 551 errx(1, "%s: cloning name too long", 552 args.ifname); 553 ifconfig(argc, argv, 1, NULL); 554 exit(exit_code); 555 } 556 #ifdef JAIL 557 /* 558 * NOTE: We have to special-case the `-vnet' command 559 * right here as we would otherwise fail when trying 560 * to find the interface as it lives in another vnet. 561 */ 562 if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) { 563 iflen = strlcpy(name, args.ifname, sizeof(name)); 564 if (iflen >= sizeof(name)) 565 errx(1, "%s: interface name too long", 566 args.ifname); 567 ifconfig(argc, argv, 0, NULL); 568 exit(exit_code); 569 } 570 #endif 571 errx(1, "interface %s does not exist", args.ifname); 572 } else { 573 /* 574 * Do not allow use `create` command as hostname if 575 * address family is not specified. 576 */ 577 if (argc > 0 && (strcmp(argv[0], "create") == 0 || 578 strcmp(argv[0], "plumb") == 0)) { 579 if (argc == 1) 580 errx(1, "interface %s already exists", 581 args.ifname); 582 argc--, argv++; 583 } 584 } 585 } 586 587 /* Check for address family */ 588 if (argc > 0) { 589 afp = af_getbyname(*argv); 590 if (afp != NULL) 591 argc--, argv++; 592 } 593 594 /* 595 * Check for a requested configuration action on a single interface, 596 * which doesn't require building, sorting, and searching the entire 597 * system address list 598 */ 599 if ((argc > 0) && (args.ifname != NULL)) { 600 iflen = strlcpy(name, args.ifname, sizeof(name)); 601 if (iflen >= sizeof(name)) { 602 warnx("%s: interface name too long, skipping", args.ifname); 603 } else { 604 flags = getifflags(name, -1, false); 605 if (!(((flags & IFF_CANTCONFIG) != 0) || 606 (args.downonly && (flags & IFF_UP) != 0) || 607 (args.uponly && (flags & IFF_UP) == 0))) 608 ifconfig(argc, argv, 0, afp); 609 } 610 goto done; 611 } 612 613 args.afp = afp; 614 args.allfamilies = afp == NULL; 615 args.argc = argc; 616 args.argv = argv; 617 618 list_interfaces(&args); 619 620 done: 621 freeformat(); 622 ifconfig_close(lifh); 623 exit(exit_code); 624 } 625 626 bool 627 match_ether(const struct sockaddr_dl *sdl) 628 { 629 switch (sdl->sdl_type) { 630 case IFT_ETHER: 631 case IFT_L2VLAN: 632 case IFT_BRIDGE: 633 if (sdl->sdl_alen == ETHER_ADDR_LEN) 634 return (true); 635 default: 636 return (false); 637 } 638 } 639 640 static bool 641 match_afp(const struct afswtch *afp, int sa_family, const struct sockaddr_dl *sdl) 642 { 643 if (afp == NULL) 644 return (true); 645 /* special case for "ether" address family */ 646 if (!strcmp(afp->af_name, "ether")) { 647 if (sdl == NULL && !match_ether(sdl)) 648 return (false); 649 return (true); 650 } 651 return (afp->af_af == sa_family); 652 } 653 654 static bool 655 match_if_flags(struct ifconfig_args *args, int if_flags) 656 { 657 if ((if_flags & IFF_CANTCONFIG) != 0) 658 return (false); 659 if (args->downonly && (if_flags & IFF_UP) != 0) 660 return (false); 661 if (args->uponly && (if_flags & IFF_UP) == 0) 662 return (false); 663 return (true); 664 } 665 666 static void 667 list_interfaces(struct ifconfig_args *args) 668 { 669 struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); 670 struct ifaddrs *ifap, *sifap, *ifa; 671 struct ifa_order_elt *cur, *tmp; 672 char *namecp = NULL; 673 int ifindex; 674 size_t iflen; 675 676 if (getifaddrs(&ifap) != 0) 677 err(EXIT_FAILURE, "getifaddrs"); 678 679 char *cp = NULL; 680 681 if (calcorders(ifap, &q) != 0) 682 err(EXIT_FAILURE, "calcorders"); 683 684 sifap = sortifaddrs(ifap, cmpifaddrs, &q); 685 686 TAILQ_FOREACH_SAFE(cur, &q, link, tmp) 687 free(cur); 688 689 ifindex = 0; 690 for (ifa = sifap; ifa; ifa = ifa->ifa_next) { 691 struct ifreq paifr = {}; 692 const struct sockaddr_dl *sdl; 693 694 strlcpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 695 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 696 memcpy(&paifr.ifr_addr, ifa->ifa_addr, 697 ifa->ifa_addr->sa_len); 698 } 699 700 if (args->ifname != NULL && strcmp(args->ifname, ifa->ifa_name) != 0) 701 continue; 702 if (ifa->ifa_addr->sa_family == AF_LINK) 703 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 704 else 705 sdl = NULL; 706 if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !args->namesonly) 707 continue; 708 iflen = strlcpy(name, ifa->ifa_name, sizeof(name)); 709 if (iflen >= sizeof(name)) { 710 warnx("%s: interface name too long, skipping", 711 ifa->ifa_name); 712 continue; 713 } 714 cp = ifa->ifa_name; 715 716 if (!match_if_flags(args, ifa->ifa_flags)) 717 continue; 718 if (!group_member(ifa->ifa_name, args->matchgroup, args->nogroup)) 719 continue; 720 /* 721 * Are we just listing the interfaces? 722 */ 723 if (args->namesonly) { 724 if (namecp == cp) 725 continue; 726 if (!match_afp(args->afp, ifa->ifa_addr->sa_family, sdl)) 727 continue; 728 namecp = cp; 729 ifindex++; 730 if (ifindex > 1) 731 printf(" "); 732 fputs(name, stdout); 733 continue; 734 } 735 ifindex++; 736 737 if (args->argc > 0) 738 ifconfig(args->argc, args->argv, 0, args->afp); 739 else 740 status(args, sdl, ifa); 741 } 742 if (args->namesonly) 743 printf("\n"); 744 freeifaddrs(ifap); 745 } 746 747 /* 748 * Returns true if an interface should be listed because any its groups 749 * matches shell pattern "match" and none of groups matches pattern "nomatch". 750 * If any pattern is NULL, corresponding condition is skipped. 751 */ 752 static bool 753 group_member(const char *ifname, const char *match, const char *nomatch) 754 { 755 static int sock = -1; 756 757 struct ifgroupreq ifgr; 758 struct ifg_req *ifg; 759 int len; 760 bool matched, nomatched; 761 762 /* Sanity checks. */ 763 if (match == NULL && nomatch == NULL) 764 return (true); 765 if (ifname == NULL) 766 return (false); 767 768 memset(&ifgr, 0, sizeof(ifgr)); 769 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); 770 771 /* The socket is opened once. Let _exit() close it. */ 772 if (sock == -1) { 773 sock = socket(AF_LOCAL, SOCK_DGRAM, 0); 774 if (sock == -1) 775 errx(1, "%s: socket(AF_LOCAL,SOCK_DGRAM)", __func__); 776 } 777 778 /* Determine amount of memory for the list of groups. */ 779 if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 780 if (errno == EINVAL || errno == ENOTTY) 781 return (false); 782 else 783 errx(1, "%s: SIOCGIFGROUP", __func__); 784 } 785 786 /* Obtain the list of groups. */ 787 len = ifgr.ifgr_len; 788 ifgr.ifgr_groups = 789 (struct ifg_req *)calloc(len / sizeof(*ifg), sizeof(*ifg)); 790 791 if (ifgr.ifgr_groups == NULL) 792 errx(1, "%s: no memory", __func__); 793 if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 794 errx(1, "%s: SIOCGIFGROUP", __func__); 795 796 /* Perform matching. */ 797 matched = false; 798 nomatched = true; 799 for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) { 800 len -= sizeof(struct ifg_req); 801 if (match) 802 matched |= !fnmatch(match, ifg->ifgrq_group, 0); 803 if (nomatch) 804 nomatched &= fnmatch(nomatch, ifg->ifgrq_group, 0); 805 } 806 free(ifgr.ifgr_groups); 807 808 if (match && !nomatch) 809 return (matched); 810 if (!match && nomatch) 811 return (nomatched); 812 return (matched && nomatched); 813 } 814 815 static struct afswtch *afs = NULL; 816 817 void 818 af_register(struct afswtch *p) 819 { 820 p->af_next = afs; 821 afs = p; 822 } 823 824 static struct afswtch * 825 af_getbyname(const char *name) 826 { 827 struct afswtch *afp; 828 829 for (afp = afs; afp != NULL; afp = afp->af_next) 830 if (strcmp(afp->af_name, name) == 0) 831 return afp; 832 return NULL; 833 } 834 835 static struct afswtch * 836 af_getbyfamily(int af) 837 { 838 struct afswtch *afp; 839 840 for (afp = afs; afp != NULL; afp = afp->af_next) 841 if (afp->af_af == af) 842 return afp; 843 return NULL; 844 } 845 846 static void 847 af_other_status(int s) 848 { 849 struct afswtch *afp; 850 uint8_t afmask[howmany(AF_MAX, NBBY)]; 851 852 memset(afmask, 0, sizeof(afmask)); 853 for (afp = afs; afp != NULL; afp = afp->af_next) { 854 if (afp->af_other_status == NULL) 855 continue; 856 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 857 continue; 858 afp->af_other_status(s); 859 setbit(afmask, afp->af_af); 860 } 861 } 862 863 static void 864 af_all_tunnel_status(int s) 865 { 866 struct afswtch *afp; 867 uint8_t afmask[howmany(AF_MAX, NBBY)]; 868 869 memset(afmask, 0, sizeof(afmask)); 870 for (afp = afs; afp != NULL; afp = afp->af_next) { 871 if (afp->af_status_tunnel == NULL) 872 continue; 873 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 874 continue; 875 afp->af_status_tunnel(s); 876 setbit(afmask, afp->af_af); 877 } 878 } 879 880 static struct cmd *cmds = NULL; 881 882 void 883 cmd_register(struct cmd *p) 884 { 885 p->c_next = cmds; 886 cmds = p; 887 } 888 889 static const struct cmd * 890 cmd_lookup(const char *name, int iscreate) 891 { 892 const struct cmd *p; 893 894 for (p = cmds; p != NULL; p = p->c_next) 895 if (strcmp(name, p->c_name) == 0) { 896 if (iscreate) { 897 if (p->c_iscloneop) 898 return p; 899 } else { 900 if (!p->c_iscloneop) 901 return p; 902 } 903 } 904 return NULL; 905 } 906 907 struct callback { 908 callback_func *cb_func; 909 void *cb_arg; 910 struct callback *cb_next; 911 }; 912 static struct callback *callbacks = NULL; 913 914 void 915 callback_register(callback_func *func, void *arg) 916 { 917 struct callback *cb; 918 919 cb = malloc(sizeof(struct callback)); 920 if (cb == NULL) 921 errx(1, "unable to allocate memory for callback"); 922 cb->cb_func = func; 923 cb->cb_arg = arg; 924 cb->cb_next = callbacks; 925 callbacks = cb; 926 } 927 928 /* specially-handled commands */ 929 static void setifaddr(const char *, int, int, const struct afswtch *); 930 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); 931 932 static void setifdstaddr(const char *, int, int, const struct afswtch *); 933 static const struct cmd setifdstaddr_cmd = 934 DEF_CMD("ifdstaddr", 0, setifdstaddr); 935 936 static int 937 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp) 938 { 939 const struct afswtch *afp, *nafp; 940 const struct cmd *p; 941 struct callback *cb; 942 int s; 943 944 strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 945 afp = NULL; 946 if (uafp != NULL) 947 afp = uafp; 948 /* 949 * This is the historical "accident" allowing users to configure IPv4 950 * addresses without the "inet" keyword which while a nice feature has 951 * proven to complicate other things. We cannot remove this but only 952 * make sure we will never have a similar implicit default for IPv6 or 953 * any other address familiy. We need a fallback though for 954 * ifconfig IF up/down etc. to work without INET support as people 955 * never used ifconfig IF link up/down, etc. either. 956 */ 957 #ifndef RESCUE 958 #ifdef INET 959 if (afp == NULL && feature_present("inet")) 960 afp = af_getbyname("inet"); 961 #endif 962 #endif 963 if (afp == NULL) 964 afp = af_getbyname("link"); 965 if (afp == NULL) { 966 warnx("Please specify an address_family."); 967 usage(); 968 } 969 top: 970 ifr.ifr_addr.sa_family = 971 afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? 972 AF_LOCAL : afp->af_af; 973 974 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 && 975 (uafp != NULL || errno != EAFNOSUPPORT || 976 (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) 977 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); 978 979 while (argc > 0) { 980 p = cmd_lookup(*argv, iscreate); 981 if (iscreate && p == NULL) { 982 /* 983 * Push the clone create callback so the new 984 * device is created and can be used for any 985 * remaining arguments. 986 */ 987 cb = callbacks; 988 if (cb == NULL) 989 errx(1, "internal error, no callback"); 990 callbacks = cb->cb_next; 991 cb->cb_func(s, cb->cb_arg); 992 iscreate = 0; 993 /* 994 * Handle any address family spec that 995 * immediately follows and potentially 996 * recreate the socket. 997 */ 998 nafp = af_getbyname(*argv); 999 if (nafp != NULL) { 1000 argc--, argv++; 1001 if (nafp != afp) { 1002 close(s); 1003 afp = nafp; 1004 goto top; 1005 } 1006 } 1007 /* 1008 * Look for a normal parameter. 1009 */ 1010 continue; 1011 } 1012 if (p == NULL) { 1013 /* 1014 * Not a recognized command, choose between setting 1015 * the interface address and the dst address. 1016 */ 1017 p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); 1018 } 1019 if (p->c_parameter == NEXTARG && p->c_u.c_func) { 1020 if (argv[1] == NULL) 1021 errx(1, "'%s' requires argument", 1022 p->c_name); 1023 p->c_u.c_func(argv[1], 0, s, afp); 1024 argc--, argv++; 1025 } else if (p->c_parameter == OPTARG && p->c_u.c_func) { 1026 p->c_u.c_func(argv[1], 0, s, afp); 1027 if (argv[1] != NULL) 1028 argc--, argv++; 1029 } else if (p->c_parameter == NEXTARG2 && p->c_u.c_func2) { 1030 if (argc < 3) 1031 errx(1, "'%s' requires 2 arguments", 1032 p->c_name); 1033 p->c_u.c_func2(argv[1], argv[2], s, afp); 1034 argc -= 2, argv += 2; 1035 } else if (p->c_parameter == SPARAM && p->c_u.c_func3) { 1036 p->c_u.c_func3(*argv, p->c_sparameter, s, afp); 1037 } else if (p->c_u.c_func) 1038 p->c_u.c_func(*argv, p->c_parameter, s, afp); 1039 argc--, argv++; 1040 } 1041 1042 /* 1043 * Do any post argument processing required by the address family. 1044 */ 1045 if (afp->af_postproc != NULL) 1046 afp->af_postproc(s, afp, newaddr, getifflags(name, s, true)); 1047 /* 1048 * Do deferred callbacks registered while processing 1049 * command-line arguments. 1050 */ 1051 for (cb = callbacks; cb != NULL; cb = cb->cb_next) 1052 cb->cb_func(s, cb->cb_arg); 1053 /* 1054 * Do deferred operations. 1055 */ 1056 if (clearaddr) { 1057 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 1058 warnx("interface %s cannot change %s addresses!", 1059 name, afp->af_name); 1060 clearaddr = 0; 1061 } 1062 } 1063 if (clearaddr) { 1064 int ret; 1065 strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, name, 1066 sizeof ifr.ifr_name); 1067 ret = ioctl(s, afp->af_difaddr, afp->af_ridreq); 1068 if (ret < 0) { 1069 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 1070 /* means no previous address for interface */ 1071 } else 1072 Perror("ioctl (SIOCDIFADDR)"); 1073 } 1074 } 1075 if (newaddr) { 1076 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 1077 warnx("interface %s cannot change %s addresses!", 1078 name, afp->af_name); 1079 newaddr = 0; 1080 } 1081 } 1082 if (newaddr && (setaddr || setmask)) { 1083 strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name, 1084 sizeof ifr.ifr_name); 1085 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 1086 Perror("ioctl (SIOCAIFADDR)"); 1087 } 1088 1089 close(s); 1090 return(0); 1091 } 1092 1093 /*ARGSUSED*/ 1094 static void 1095 setifaddr(const char *addr, int param, int s, const struct afswtch *afp) 1096 { 1097 if (afp->af_getaddr == NULL) 1098 return; 1099 /* 1100 * Delay the ioctl to set the interface addr until flags are all set. 1101 * The address interpretation may depend on the flags, 1102 * and the flags may change when the address is set. 1103 */ 1104 setaddr++; 1105 if (doalias == 0 && afp->af_af != AF_LINK) 1106 clearaddr = 1; 1107 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); 1108 } 1109 1110 static void 1111 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) 1112 { 1113 struct addrinfo *srcres, *dstres; 1114 int ecode; 1115 1116 if (afp->af_settunnel == NULL) { 1117 warn("address family %s does not support tunnel setup", 1118 afp->af_name); 1119 return; 1120 } 1121 1122 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 1123 errx(1, "error in parsing address string: %s", 1124 gai_strerror(ecode)); 1125 1126 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 1127 errx(1, "error in parsing address string: %s", 1128 gai_strerror(ecode)); 1129 1130 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 1131 errx(1, 1132 "source and destination address families do not match"); 1133 1134 afp->af_settunnel(s, srcres, dstres); 1135 1136 freeaddrinfo(srcres); 1137 freeaddrinfo(dstres); 1138 } 1139 1140 /* ARGSUSED */ 1141 static void 1142 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) 1143 { 1144 1145 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 1146 err(1, "SIOCDIFPHYADDR"); 1147 } 1148 1149 #ifdef JAIL 1150 static void 1151 setifvnet(const char *jname, int dummy __unused, int s, 1152 const struct afswtch *afp) 1153 { 1154 struct ifreq my_ifr; 1155 1156 memcpy(&my_ifr, &ifr, sizeof(my_ifr)); 1157 my_ifr.ifr_jid = jail_getid(jname); 1158 if (my_ifr.ifr_jid < 0) 1159 errx(1, "%s", jail_errmsg); 1160 if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0) 1161 err(1, "SIOCSIFVNET"); 1162 } 1163 1164 static void 1165 setifrvnet(const char *jname, int dummy __unused, int s, 1166 const struct afswtch *afp) 1167 { 1168 struct ifreq my_ifr; 1169 1170 memcpy(&my_ifr, &ifr, sizeof(my_ifr)); 1171 my_ifr.ifr_jid = jail_getid(jname); 1172 if (my_ifr.ifr_jid < 0) 1173 errx(1, "%s", jail_errmsg); 1174 if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0) 1175 err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name); 1176 } 1177 #endif 1178 1179 static void 1180 setifnetmask(const char *addr, int dummy __unused, int s, 1181 const struct afswtch *afp) 1182 { 1183 if (afp->af_getaddr != NULL) { 1184 setmask++; 1185 afp->af_getaddr(addr, MASK); 1186 } 1187 } 1188 1189 static void 1190 setifbroadaddr(const char *addr, int dummy __unused, int s, 1191 const struct afswtch *afp) 1192 { 1193 if (afp->af_getaddr != NULL) 1194 afp->af_getaddr(addr, DSTADDR); 1195 } 1196 1197 static void 1198 notealias(const char *addr, int param, int s, const struct afswtch *afp) 1199 { 1200 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 1201 if (setaddr && doalias == 0 && param < 0) 1202 if (afp->af_addreq != NULL && afp->af_ridreq != NULL) 1203 bcopy((caddr_t)rqtosa(af_addreq), 1204 (caddr_t)rqtosa(af_ridreq), 1205 rqtosa(af_addreq)->sa_len); 1206 doalias = param; 1207 if (param < 0) { 1208 clearaddr = 1; 1209 newaddr = 0; 1210 } else 1211 clearaddr = 0; 1212 #undef rqtosa 1213 } 1214 1215 /*ARGSUSED*/ 1216 static void 1217 setifdstaddr(const char *addr, int param __unused, int s, 1218 const struct afswtch *afp) 1219 { 1220 if (afp->af_getaddr != NULL) 1221 afp->af_getaddr(addr, DSTADDR); 1222 } 1223 1224 static int 1225 getifflags(const char *ifname, int us, bool err_ok) 1226 { 1227 struct ifreq my_ifr; 1228 int s; 1229 1230 memset(&my_ifr, 0, sizeof(my_ifr)); 1231 (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name)); 1232 if (us < 0) { 1233 if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) 1234 err(1, "socket(family AF_LOCAL,SOCK_DGRAM"); 1235 } else 1236 s = us; 1237 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 1238 if (!err_ok) { 1239 Perror("ioctl (SIOCGIFFLAGS)"); 1240 exit(1); 1241 } 1242 } 1243 if (us < 0) 1244 close(s); 1245 return ((my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16)); 1246 } 1247 1248 /* 1249 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 1250 * of the ifreq structure, which may confuse other parts of ifconfig. 1251 * Make a private copy so we can avoid that. 1252 */ 1253 static void 1254 setifflags(const char *vname, int value, int s, const struct afswtch *afp) 1255 { 1256 struct ifreq my_ifr; 1257 int flags; 1258 1259 flags = getifflags(name, s, false); 1260 if (value < 0) { 1261 value = -value; 1262 flags &= ~value; 1263 } else 1264 flags |= value; 1265 memset(&my_ifr, 0, sizeof(my_ifr)); 1266 (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); 1267 my_ifr.ifr_flags = flags & 0xffff; 1268 my_ifr.ifr_flagshigh = flags >> 16; 1269 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 1270 Perror(vname); 1271 } 1272 1273 void 1274 setifcap(const char *vname, int value, int s, const struct afswtch *afp) 1275 { 1276 int flags; 1277 1278 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 1279 Perror("ioctl (SIOCGIFCAP)"); 1280 exit(1); 1281 } 1282 flags = ifr.ifr_curcap; 1283 if (value < 0) { 1284 value = -value; 1285 flags &= ~value; 1286 } else 1287 flags |= value; 1288 flags &= ifr.ifr_reqcap; 1289 /* Check for no change in capabilities. */ 1290 if (ifr.ifr_curcap == flags) 1291 return; 1292 ifr.ifr_reqcap = flags; 1293 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 1294 Perror(vname); 1295 } 1296 1297 void 1298 setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp) 1299 { 1300 nvlist_t *nvcap; 1301 void *buf; 1302 char *marg, *mopt; 1303 size_t nvbuflen; 1304 bool neg; 1305 1306 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) 1307 Perror("ioctl (SIOCGIFCAP)"); 1308 if ((ifr.ifr_curcap & IFCAP_NV) == 0) { 1309 warnx("IFCAP_NV not supported"); 1310 return; /* Not exit() */ 1311 } 1312 1313 marg = strdup(arg); 1314 if (marg == NULL) 1315 Perror("strdup"); 1316 nvcap = nvlist_create(0); 1317 if (nvcap == NULL) 1318 Perror("nvlist_create"); 1319 while ((mopt = strsep(&marg, ",")) != NULL) { 1320 neg = *mopt == '-'; 1321 if (neg) 1322 mopt++; 1323 if (strcmp(mopt, "rxtls") == 0) { 1324 nvlist_add_bool(nvcap, "rxtls4", !neg); 1325 nvlist_add_bool(nvcap, "rxtls6", !neg); 1326 } else { 1327 nvlist_add_bool(nvcap, mopt, !neg); 1328 } 1329 } 1330 buf = nvlist_pack(nvcap, &nvbuflen); 1331 if (buf == NULL) { 1332 errx(1, "nvlist_pack error"); 1333 exit(1); 1334 } 1335 ifr.ifr_cap_nv.buf_length = ifr.ifr_cap_nv.length = nvbuflen; 1336 ifr.ifr_cap_nv.buffer = buf; 1337 if (ioctl(s, SIOCSIFCAPNV, (caddr_t)&ifr) < 0) 1338 Perror(vname); 1339 free(buf); 1340 nvlist_destroy(nvcap); 1341 free(marg); 1342 } 1343 1344 static void 1345 setifmetric(const char *val, int dummy __unused, int s, 1346 const struct afswtch *afp) 1347 { 1348 strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1349 ifr.ifr_metric = atoi(val); 1350 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 1351 err(1, "ioctl SIOCSIFMETRIC (set metric)"); 1352 } 1353 1354 static void 1355 setifmtu(const char *val, int dummy __unused, int s, 1356 const struct afswtch *afp) 1357 { 1358 strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1359 ifr.ifr_mtu = atoi(val); 1360 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 1361 err(1, "ioctl SIOCSIFMTU (set mtu)"); 1362 } 1363 1364 static void 1365 setifpcp(const char *val, int arg __unused, int s, const struct afswtch *afp) 1366 { 1367 u_long ul; 1368 char *endp; 1369 1370 ul = strtoul(val, &endp, 0); 1371 if (*endp != '\0') 1372 errx(1, "invalid value for pcp"); 1373 if (ul > 7) 1374 errx(1, "value for pcp out of range"); 1375 ifr.ifr_lan_pcp = ul; 1376 if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1) 1377 err(1, "SIOCSLANPCP"); 1378 } 1379 1380 static void 1381 disableifpcp(const char *val, int arg __unused, int s, 1382 const struct afswtch *afp) 1383 { 1384 1385 ifr.ifr_lan_pcp = IFNET_PCP_NONE; 1386 if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1) 1387 err(1, "SIOCSLANPCP"); 1388 } 1389 1390 static void 1391 setifname(const char *val, int dummy __unused, int s, 1392 const struct afswtch *afp) 1393 { 1394 char *newname; 1395 1396 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1397 1398 newname = strdup(val); 1399 if (newname == NULL) 1400 err(1, "no memory to set ifname"); 1401 ifr.ifr_data = newname; 1402 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { 1403 free(newname); 1404 err(1, "ioctl SIOCSIFNAME (set name)"); 1405 } 1406 printifname = 1; 1407 strlcpy(name, newname, sizeof(name)); 1408 free(newname); 1409 } 1410 1411 /* ARGSUSED */ 1412 static void 1413 setifdescr(const char *val, int dummy __unused, int s, 1414 const struct afswtch *afp) 1415 { 1416 char *newdescr; 1417 1418 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1419 1420 ifr.ifr_buffer.length = strlen(val) + 1; 1421 if (ifr.ifr_buffer.length == 1) { 1422 ifr.ifr_buffer.buffer = newdescr = NULL; 1423 ifr.ifr_buffer.length = 0; 1424 } else { 1425 newdescr = strdup(val); 1426 ifr.ifr_buffer.buffer = newdescr; 1427 if (newdescr == NULL) { 1428 warn("no memory to set ifdescr"); 1429 return; 1430 } 1431 } 1432 1433 if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) 1434 err(1, "ioctl SIOCSIFDESCR (set descr)"); 1435 1436 free(newdescr); 1437 } 1438 1439 /* ARGSUSED */ 1440 static void 1441 unsetifdescr(const char *val, int value, int s, const struct afswtch *afp) 1442 { 1443 1444 setifdescr("", 0, s, 0); 1445 } 1446 1447 #define IFFBITS \ 1448 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \ 1449 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 1450 "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25STICKYARP" 1451 1452 #define IFCAPBITS \ 1453 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ 1454 "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \ 1455 "\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \ 1456 "\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6" \ 1457 "\36VXLAN_HWCSUM\37VXLAN_HWTSO\40TXTLS_RTLMT" 1458 1459 static void 1460 print_ifcap_nv(struct ifconfig_args *args, int s) 1461 { 1462 nvlist_t *nvcap; 1463 const char *nvname; 1464 void *buf, *cookie; 1465 bool first, val; 1466 int type; 1467 1468 buf = malloc(IFR_CAP_NV_MAXBUFSIZE); 1469 if (buf == NULL) 1470 Perror("malloc"); 1471 ifr.ifr_cap_nv.buffer = buf; 1472 ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE; 1473 if (ioctl(s, SIOCGIFCAPNV, (caddr_t)&ifr) != 0) 1474 Perror("ioctl (SIOCGIFCAPNV)"); 1475 nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer, 1476 ifr.ifr_cap_nv.length, 0); 1477 if (nvcap == NULL) 1478 Perror("nvlist_unpack"); 1479 printf("\toptions"); 1480 cookie = NULL; 1481 for (first = true;; first = false) { 1482 nvname = nvlist_next(nvcap, &type, &cookie); 1483 if (nvname == NULL) { 1484 printf("\n"); 1485 break; 1486 } 1487 if (type == NV_TYPE_BOOL) { 1488 val = nvlist_get_bool(nvcap, nvname); 1489 if (val) { 1490 printf("%c%s", 1491 first ? ' ' : ',', nvname); 1492 } 1493 } 1494 } 1495 if (args->supmedia) { 1496 printf("\tcapabilities"); 1497 cookie = NULL; 1498 for (first = true;; first = false) { 1499 nvname = nvlist_next(nvcap, &type, 1500 &cookie); 1501 if (nvname == NULL) { 1502 printf("\n"); 1503 break; 1504 } 1505 if (type == NV_TYPE_BOOL) 1506 printf("%c%s", first ? ' ' : 1507 ',', nvname); 1508 } 1509 } 1510 nvlist_destroy(nvcap); 1511 free(buf); 1512 1513 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0) 1514 Perror("ioctl (SIOCGIFCAP)"); 1515 } 1516 1517 static void 1518 print_ifcap(struct ifconfig_args *args, int s) 1519 { 1520 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0) 1521 return; 1522 1523 if ((ifr.ifr_curcap & IFCAP_NV) != 0) 1524 print_ifcap_nv(args, s); 1525 else { 1526 printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 1527 putchar('\n'); 1528 if (args->supmedia && ifr.ifr_reqcap != 0) { 1529 printb("\tcapabilities", ifr.ifr_reqcap, 1530 IFCAPBITS); 1531 putchar('\n'); 1532 } 1533 } 1534 } 1535 1536 static void 1537 print_ifstatus(int s) 1538 { 1539 struct ifstat ifs; 1540 1541 strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 1542 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 1543 printf("%s", ifs.ascii); 1544 } 1545 1546 static void 1547 print_metric(int s) 1548 { 1549 if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) 1550 printf(" metric %d", ifr.ifr_metric); 1551 } 1552 1553 static void 1554 print_mtu(int s) 1555 { 1556 if (ioctl(s, SIOCGIFMTU, &ifr) != -1) 1557 printf(" mtu %d", ifr.ifr_mtu); 1558 } 1559 1560 static void 1561 print_description(int s) 1562 { 1563 for (;;) { 1564 if ((descr = reallocf(descr, descrlen)) != NULL) { 1565 ifr.ifr_buffer.buffer = descr; 1566 ifr.ifr_buffer.length = descrlen; 1567 if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) { 1568 if (ifr.ifr_buffer.buffer == descr) { 1569 if (strlen(descr) > 0) 1570 printf("\tdescription: %s\n", 1571 descr); 1572 } else if (ifr.ifr_buffer.length > descrlen) { 1573 descrlen = ifr.ifr_buffer.length; 1574 continue; 1575 } 1576 } 1577 } else 1578 warn("unable to allocate memory for interface" 1579 "description"); 1580 break; 1581 } 1582 } 1583 1584 /* 1585 * Print the status of the interface. If an address family was 1586 * specified, show only it; otherwise, show them all. 1587 */ 1588 static void 1589 status(struct ifconfig_args *args, const struct sockaddr_dl *sdl, 1590 struct ifaddrs *ifa) 1591 { 1592 struct ifaddrs *ift; 1593 int s; 1594 bool allfamilies = args->afp == NULL; 1595 1596 if (args->afp == NULL) 1597 ifr.ifr_addr.sa_family = AF_LOCAL; 1598 else 1599 ifr.ifr_addr.sa_family = 1600 args->afp->af_af == AF_LINK ? AF_LOCAL : args->afp->af_af; 1601 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1602 1603 s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); 1604 if (s < 0) 1605 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); 1606 1607 printf("%s: ", name); 1608 printb("flags", ifa->ifa_flags, IFFBITS); 1609 print_metric(s); 1610 print_mtu(s); 1611 putchar('\n'); 1612 1613 print_description(s); 1614 1615 print_ifcap(args, s); 1616 1617 tunnel_status(s); 1618 1619 for (ift = ifa; ift != NULL; ift = ift->ifa_next) { 1620 if (ift->ifa_addr == NULL) 1621 continue; 1622 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) 1623 continue; 1624 if (allfamilies) { 1625 const struct afswtch *p; 1626 p = af_getbyfamily(ift->ifa_addr->sa_family); 1627 if (p != NULL && p->af_status != NULL) 1628 p->af_status(s, ift); 1629 } else if (args->afp->af_af == ift->ifa_addr->sa_family) 1630 args->afp->af_status(s, ift); 1631 } 1632 #if 0 1633 if (allfamilies || afp->af_af == AF_LINK) { 1634 const struct afswtch *lafp; 1635 1636 /* 1637 * Hack; the link level address is received separately 1638 * from the routing information so any address is not 1639 * handled above. Cobble together an entry and invoke 1640 * the status method specially. 1641 */ 1642 lafp = af_getbyname("lladdr"); 1643 if (lafp != NULL) { 1644 info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl; 1645 lafp->af_status(s, &info); 1646 } 1647 } 1648 #endif 1649 if (allfamilies) 1650 af_other_status(s); 1651 else if (args->afp->af_other_status != NULL) 1652 args->afp->af_other_status(s); 1653 1654 print_ifstatus(s); 1655 if (args->verbose > 0) 1656 sfp_status(s, &ifr, args->verbose); 1657 1658 close(s); 1659 return; 1660 } 1661 1662 static void 1663 tunnel_status(int s) 1664 { 1665 af_all_tunnel_status(s); 1666 } 1667 1668 void 1669 Perror(const char *cmd) 1670 { 1671 switch (errno) { 1672 1673 case ENXIO: 1674 errx(1, "%s: no such interface", cmd); 1675 break; 1676 1677 case EPERM: 1678 errx(1, "%s: permission denied", cmd); 1679 break; 1680 1681 default: 1682 err(1, "%s", cmd); 1683 } 1684 } 1685 1686 /* 1687 * Print a value a la the %b format of the kernel's printf 1688 */ 1689 void 1690 printb(const char *s, unsigned v, const char *bits) 1691 { 1692 int i, any = 0; 1693 char c; 1694 1695 if (bits && *bits == 8) 1696 printf("%s=%o", s, v); 1697 else 1698 printf("%s=%x", s, v); 1699 if (bits) { 1700 bits++; 1701 putchar('<'); 1702 while ((i = *bits++) != '\0') { 1703 if (v & (1u << (i-1))) { 1704 if (any) 1705 putchar(','); 1706 any = 1; 1707 for (; (c = *bits) > 32; bits++) 1708 putchar(c); 1709 } else 1710 for (; *bits > 32; bits++) 1711 ; 1712 } 1713 putchar('>'); 1714 } 1715 } 1716 1717 void 1718 print_vhid(const struct ifaddrs *ifa, const char *s) 1719 { 1720 struct if_data *ifd; 1721 1722 if (ifa->ifa_data == NULL) 1723 return; 1724 1725 ifd = ifa->ifa_data; 1726 if (ifd->ifi_vhid == 0) 1727 return; 1728 1729 printf(" vhid %d", ifd->ifi_vhid); 1730 } 1731 1732 void 1733 ifmaybeload(struct ifconfig_args *args, const char *name) 1734 { 1735 #define MOD_PREFIX_LEN 3 /* "if_" */ 1736 struct module_stat mstat; 1737 int i, fileid, modid; 1738 char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; 1739 const char *cp; 1740 struct module_map_entry *mme; 1741 bool found; 1742 1743 /* loading suppressed by the user */ 1744 if (args->noload) 1745 return; 1746 1747 /* trim the interface number off the end */ 1748 strlcpy(ifname, name, sizeof(ifname)); 1749 for (dp = ifname; *dp != 0; dp++) 1750 if (isdigit(*dp)) { 1751 *dp = 0; 1752 break; 1753 } 1754 1755 /* Either derive it from the map or guess otherwise */ 1756 *ifkind = '\0'; 1757 found = false; 1758 for (i = 0; i < nitems(module_map); ++i) { 1759 mme = &module_map[i]; 1760 if (strcmp(mme->ifname, ifname) == 0) { 1761 strlcpy(ifkind, mme->kldname, sizeof(ifkind)); 1762 found = true; 1763 break; 1764 } 1765 } 1766 1767 /* We didn't have an alias for it... we'll guess. */ 1768 if (!found) { 1769 /* turn interface and unit into module name */ 1770 strlcpy(ifkind, "if_", sizeof(ifkind)); 1771 strlcat(ifkind, ifname, sizeof(ifkind)); 1772 } 1773 1774 /* scan files in kernel */ 1775 mstat.version = sizeof(struct module_stat); 1776 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1777 /* scan modules in file */ 1778 for (modid = kldfirstmod(fileid); modid > 0; 1779 modid = modfnext(modid)) { 1780 if (modstat(modid, &mstat) < 0) 1781 continue; 1782 /* strip bus name if present */ 1783 if ((cp = strchr(mstat.name, '/')) != NULL) { 1784 cp++; 1785 } else { 1786 cp = mstat.name; 1787 } 1788 /* 1789 * Is it already loaded? Don't compare with ifname if 1790 * we were specifically told which kld to use. Doing 1791 * so could lead to conflicts not trivially solved. 1792 */ 1793 if ((!found && strcmp(ifname, cp) == 0) || 1794 strcmp(ifkind, cp) == 0) 1795 return; 1796 } 1797 } 1798 1799 /* 1800 * Try to load the module. But ignore failures, because ifconfig can't 1801 * infer the names of all drivers (eg mlx4en(4)). 1802 */ 1803 (void) kldload(ifkind); 1804 } 1805 1806 static struct cmd basic_cmds[] = { 1807 DEF_CMD("up", IFF_UP, setifflags), 1808 DEF_CMD("down", -IFF_UP, setifflags), 1809 DEF_CMD("arp", -IFF_NOARP, setifflags), 1810 DEF_CMD("-arp", IFF_NOARP, setifflags), 1811 DEF_CMD("debug", IFF_DEBUG, setifflags), 1812 DEF_CMD("-debug", -IFF_DEBUG, setifflags), 1813 DEF_CMD_ARG("description", setifdescr), 1814 DEF_CMD_ARG("descr", setifdescr), 1815 DEF_CMD("-description", 0, unsetifdescr), 1816 DEF_CMD("-descr", 0, unsetifdescr), 1817 DEF_CMD("promisc", IFF_PPROMISC, setifflags), 1818 DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), 1819 DEF_CMD("add", IFF_UP, notealias), 1820 DEF_CMD("alias", IFF_UP, notealias), 1821 DEF_CMD("-alias", -IFF_UP, notealias), 1822 DEF_CMD("delete", -IFF_UP, notealias), 1823 DEF_CMD("remove", -IFF_UP, notealias), 1824 #ifdef notdef 1825 #define EN_SWABIPS 0x1000 1826 DEF_CMD("swabips", EN_SWABIPS, setifflags), 1827 DEF_CMD("-swabips", -EN_SWABIPS, setifflags), 1828 #endif 1829 DEF_CMD_ARG("netmask", setifnetmask), 1830 DEF_CMD_ARG("metric", setifmetric), 1831 DEF_CMD_ARG("broadcast", setifbroadaddr), 1832 DEF_CMD_ARG2("tunnel", settunnel), 1833 DEF_CMD("-tunnel", 0, deletetunnel), 1834 DEF_CMD("deletetunnel", 0, deletetunnel), 1835 #ifdef JAIL 1836 DEF_CMD_ARG("vnet", setifvnet), 1837 DEF_CMD_ARG("-vnet", setifrvnet), 1838 #endif 1839 DEF_CMD("link0", IFF_LINK0, setifflags), 1840 DEF_CMD("-link0", -IFF_LINK0, setifflags), 1841 DEF_CMD("link1", IFF_LINK1, setifflags), 1842 DEF_CMD("-link1", -IFF_LINK1, setifflags), 1843 DEF_CMD("link2", IFF_LINK2, setifflags), 1844 DEF_CMD("-link2", -IFF_LINK2, setifflags), 1845 DEF_CMD("monitor", IFF_MONITOR, setifflags), 1846 DEF_CMD("-monitor", -IFF_MONITOR, setifflags), 1847 DEF_CMD("mextpg", IFCAP_MEXTPG, setifcap), 1848 DEF_CMD("-mextpg", -IFCAP_MEXTPG, setifcap), 1849 DEF_CMD("staticarp", IFF_STATICARP, setifflags), 1850 DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), 1851 DEF_CMD("stickyarp", IFF_STICKYARP, setifflags), 1852 DEF_CMD("-stickyarp", -IFF_STICKYARP, setifflags), 1853 DEF_CMD("rxcsum6", IFCAP_RXCSUM_IPV6, setifcap), 1854 DEF_CMD("-rxcsum6", -IFCAP_RXCSUM_IPV6, setifcap), 1855 DEF_CMD("txcsum6", IFCAP_TXCSUM_IPV6, setifcap), 1856 DEF_CMD("-txcsum6", -IFCAP_TXCSUM_IPV6, setifcap), 1857 DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), 1858 DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), 1859 DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), 1860 DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), 1861 DEF_CMD("netcons", IFCAP_NETCONS, setifcap), 1862 DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), 1863 DEF_CMD_ARG("pcp", setifpcp), 1864 DEF_CMD("-pcp", 0, disableifpcp), 1865 DEF_CMD("polling", IFCAP_POLLING, setifcap), 1866 DEF_CMD("-polling", -IFCAP_POLLING, setifcap), 1867 DEF_CMD("tso6", IFCAP_TSO6, setifcap), 1868 DEF_CMD("-tso6", -IFCAP_TSO6, setifcap), 1869 DEF_CMD("tso4", IFCAP_TSO4, setifcap), 1870 DEF_CMD("-tso4", -IFCAP_TSO4, setifcap), 1871 DEF_CMD("tso", IFCAP_TSO, setifcap), 1872 DEF_CMD("-tso", -IFCAP_TSO, setifcap), 1873 DEF_CMD("toe", IFCAP_TOE, setifcap), 1874 DEF_CMD("-toe", -IFCAP_TOE, setifcap), 1875 DEF_CMD("lro", IFCAP_LRO, setifcap), 1876 DEF_CMD("-lro", -IFCAP_LRO, setifcap), 1877 DEF_CMD("txtls", IFCAP_TXTLS, setifcap), 1878 DEF_CMD("-txtls", -IFCAP_TXTLS, setifcap), 1879 DEF_CMD_SARG("rxtls", IFCAP2_RXTLS4_NAME "," IFCAP2_RXTLS6_NAME, 1880 setifcapnv), 1881 DEF_CMD_SARG("-rxtls", "-"IFCAP2_RXTLS4_NAME ",-" IFCAP2_RXTLS6_NAME, 1882 setifcapnv), 1883 DEF_CMD("wol", IFCAP_WOL, setifcap), 1884 DEF_CMD("-wol", -IFCAP_WOL, setifcap), 1885 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), 1886 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), 1887 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), 1888 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), 1889 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), 1890 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), 1891 DEF_CMD("txrtlmt", IFCAP_TXRTLMT, setifcap), 1892 DEF_CMD("-txrtlmt", -IFCAP_TXRTLMT, setifcap), 1893 DEF_CMD("txtlsrtlmt", IFCAP_TXTLS_RTLMT, setifcap), 1894 DEF_CMD("-txtlsrtlmt", -IFCAP_TXTLS_RTLMT, setifcap), 1895 DEF_CMD("hwrxtstmp", IFCAP_HWRXTSTMP, setifcap), 1896 DEF_CMD("-hwrxtstmp", -IFCAP_HWRXTSTMP, setifcap), 1897 DEF_CMD("normal", -IFF_LINK0, setifflags), 1898 DEF_CMD("compress", IFF_LINK0, setifflags), 1899 DEF_CMD("noicmp", IFF_LINK1, setifflags), 1900 DEF_CMD_ARG("mtu", setifmtu), 1901 DEF_CMD_ARG("name", setifname), 1902 }; 1903 1904 static __constructor void 1905 ifconfig_ctor(void) 1906 { 1907 size_t i; 1908 1909 for (i = 0; i < nitems(basic_cmds); i++) 1910 cmd_register(&basic_cmds[i]); 1911 } 1912