1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (C) 2017 THL A29 Limited, a Tencent company. 6 * 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 * 4. 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 * Derived from FreeBSD's usr/sbin/ifconfig/ifconfig.c. 33 */ 34 35 #ifndef lint 36 static const char copyright[] = 37 "@(#) Copyright (c) 1983, 1993\n\ 38 The Regents of the University of California. All rights reserved.\n"; 39 #endif /* not lint */ 40 41 #ifndef lint 42 #if 0 43 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 44 #endif 45 static const char rcsid[] = 46 "$FreeBSD$"; 47 #endif /* not lint */ 48 49 #ifndef FSTACK 50 #include <sys/param.h> 51 #include <sys/ioctl.h> 52 #include <sys/module.h> 53 #include <sys/linker.h> 54 #include <sys/queue.h> 55 #include <sys/socket.h> 56 #include <sys/time.h> 57 58 #include <net/ethernet.h> 59 #include <net/if.h> 60 #include <net/if_dl.h> 61 #include <net/if_types.h> 62 #include <net/route.h> 63 64 /* IP */ 65 #include <netinet/in.h> 66 #include <netinet/in_var.h> 67 #include <arpa/inet.h> 68 #include <netdb.h> 69 70 #include <ifaddrs.h> 71 #include <ctype.h> 72 #include <err.h> 73 #include <errno.h> 74 #include <fcntl.h> 75 #ifdef JAIL 76 #include <jail.h> 77 #endif 78 #include <stdio.h> 79 #include <stdlib.h> 80 #include <string.h> 81 #include <unistd.h> 82 83 #else 84 #include <ctype.h> 85 #include <err.h> 86 #include <errno.h> 87 #include <fcntl.h> 88 #include <stdint.h> 89 #include <stdio.h> 90 #include <stdlib.h> 91 #include <string.h> 92 #include <unistd.h> 93 #include <sys/param.h> 94 95 #include "net/ethernet.h" 96 #include "net/if.h" 97 #include "net/if_dl.h" 98 #include "net/if_types.h" 99 #include "net/route.h" 100 101 #include "sys/queue.h" 102 #include "sys/ioctl.h" 103 #include "sys/socket.h" 104 #include "sys/sysctl.h" 105 106 #include "ifaddrs.h" 107 #include "netdb.h" 108 109 #include "ff_ipc.h" 110 111 #endif 112 113 #include "ifconfig.h" 114 115 /* 116 * Since "struct ifreq" is composed of various union members, callers 117 * should pay special attention to interpret the value. 118 * (.e.g. little/big endian difference in the structure.) 119 */ 120 struct ifreq ifr; 121 122 char name[IFNAMSIZ]; 123 char *descr = NULL; 124 size_t descrlen = 64; 125 int setaddr; 126 int setmask; 127 int doalias; 128 int clearaddr; 129 int newaddr = 1; 130 int verbose; 131 int noload; 132 int printifname = 0; 133 134 int supmedia = 0; 135 int printkeys = 0; /* Print keying material for interfaces. */ 136 137 /* Formatter Strings */ 138 char *f_inet, *f_inet6, *f_ether, *f_addr; 139 140 static int ifconfig(int argc, char *const *argv, int iscreate, 141 const struct afswtch *afp); 142 static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 143 struct ifaddrs *ifa); 144 static void tunnel_status(int s); 145 static void usage(void); 146 147 static struct afswtch *af_getbyname(const char *name); 148 static struct afswtch *af_getbyfamily(int af); 149 static void af_other_status(int); 150 151 void printifnamemaybe(void); 152 153 static struct option *opts = NULL; 154 155 struct ifa_order_elt { 156 int if_order; 157 int af_orders[255]; 158 struct ifaddrs *ifa; 159 TAILQ_ENTRY(ifa_order_elt) link; 160 }; 161 162 TAILQ_HEAD(ifa_queue, ifa_order_elt); 163 164 #ifdef FSTACK 165 int 166 fake_socket(int domain, int type, int protocol) 167 { 168 return 0; 169 } 170 171 int 172 fake_close(int fd) 173 { 174 return 0; 175 } 176 #endif 177 178 void 179 opt_register(struct option *p) 180 { 181 p->next = opts; 182 opts = p; 183 } 184 185 static void 186 usage(void) 187 { 188 char options[1024]; 189 struct option *p; 190 191 /* XXX not right but close enough for now */ 192 options[0] = '\0'; 193 for (p = opts; p != NULL; p = p->next) { 194 strlcat(options, p->opt_usage, sizeof(options)); 195 strlcat(options, " ", sizeof(options)); 196 } 197 198 fprintf(stderr, 199 #ifndef FSTACK 200 "usage: ifconfig [-f type:format] %sinterface address_family\n" 201 " [address [dest_address]] [parameters]\n" 202 " ifconfig interface create\n" 203 " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n" 204 " ifconfig -l [-d] [-u] [address_family]\n" 205 " ifconfig %s[-d] [-m] [-u] [-v]\n", 206 #else 207 "usage: ifconfig -p <f-stack proc_id> [-f type:format] %sinterface address_family\n" 208 " [address [dest_address]] [parameters]\n" 209 " ifconfig -p <f-stack proc_id> interface create\n" 210 " ifconfig -p <f-stack proc_id> -a %s[-d] [-m] [-u] [-v] [address_family]\n" 211 " ifconfig -p <f-stack proc_id> -l [-d] [-u] [address_family]\n" 212 " ifconfig -p <f-stack proc_id> %s[-d] [-m] [-u] [-v]\n", 213 #endif 214 options, options, options); 215 216 #ifdef FSTACK 217 ff_ipc_exit(); 218 #endif 219 exit(1); 220 } 221 222 #define ORDERS_SIZE(x) sizeof(x) / sizeof(x[0]) 223 224 static int 225 calcorders(struct ifaddrs *ifa, struct ifa_queue *q) 226 { 227 struct ifaddrs *prev; 228 struct ifa_order_elt *cur; 229 unsigned int ord, af, ifa_ord; 230 231 prev = NULL; 232 cur = NULL; 233 ord = 0; 234 ifa_ord = 0; 235 236 while (ifa != NULL) { 237 if (prev == NULL || 238 strcmp(ifa->ifa_name, prev->ifa_name) != 0) { 239 cur = calloc(1, sizeof(*cur)); 240 241 if (cur == NULL) 242 return (-1); 243 244 TAILQ_INSERT_TAIL(q, cur, link); 245 cur->if_order = ifa_ord ++; 246 cur->ifa = ifa; 247 ord = 0; 248 } 249 250 if (ifa->ifa_addr) { 251 af = ifa->ifa_addr->sa_family; 252 253 if (af < ORDERS_SIZE(cur->af_orders) && 254 cur->af_orders[af] == 0) 255 cur->af_orders[af] = ++ord; 256 } 257 prev = ifa; 258 ifa = ifa->ifa_next; 259 } 260 261 return (0); 262 } 263 264 static int 265 cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q) 266 { 267 struct ifa_order_elt *cur, *e1, *e2; 268 unsigned int af1, af2; 269 int ret; 270 271 e1 = e2 = NULL; 272 273 ret = strcmp(a->ifa_name, b->ifa_name); 274 if (ret != 0) { 275 TAILQ_FOREACH(cur, q, link) { 276 if (e1 && e2) 277 break; 278 279 if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) 280 e1 = cur; 281 else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0) 282 e2 = cur; 283 } 284 285 if (!e1 || !e2) 286 return (0); 287 else 288 return (e1->if_order - e2->if_order); 289 290 } else if (a->ifa_addr != NULL && b->ifa_addr != NULL) { 291 TAILQ_FOREACH(cur, q, link) { 292 if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) { 293 e1 = cur; 294 break; 295 } 296 } 297 298 if (!e1) 299 return (0); 300 301 af1 = a->ifa_addr->sa_family; 302 af2 = b->ifa_addr->sa_family; 303 304 if (af1 < ORDERS_SIZE(e1->af_orders) && 305 af2 < ORDERS_SIZE(e1->af_orders)) 306 return (e1->af_orders[af1] - e1->af_orders[af2]); 307 } 308 309 return (0); 310 } 311 312 static void freeformat(void) 313 { 314 315 if (f_inet != NULL) 316 free(f_inet); 317 if (f_inet6 != NULL) 318 free(f_inet6); 319 if (f_ether != NULL) 320 free(f_ether); 321 if (f_addr != NULL) 322 free(f_addr); 323 } 324 325 static void setformat(char *input) 326 { 327 char *formatstr, *category, *modifier; 328 329 formatstr = strdup(input); 330 while ((category = strsep(&formatstr, ",")) != NULL) { 331 modifier = strchr(category, ':'); 332 if (modifier == NULL || modifier[1] == '\0') { 333 warnx("Skipping invalid format specification: %s\n", 334 category); 335 continue; 336 } 337 338 /* Split the string on the separator, then seek past it */ 339 modifier[0] = '\0'; 340 modifier++; 341 342 if (strcmp(category, "addr") == 0) 343 f_addr = strdup(modifier); 344 else if (strcmp(category, "ether") == 0) 345 f_ether = strdup(modifier); 346 else if (strcmp(category, "inet") == 0) 347 f_inet = strdup(modifier); 348 else if (strcmp(category, "inet6") == 0) 349 f_inet6 = strdup(modifier); 350 } 351 free(formatstr); 352 } 353 354 #undef ORDERS_SIZE 355 356 static struct ifaddrs * 357 sortifaddrs(struct ifaddrs *list, 358 int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *), 359 struct ifa_queue *q) 360 { 361 struct ifaddrs *right, *temp, *last, *result, *next, *tail; 362 363 right = list; 364 temp = list; 365 last = list; 366 result = NULL; 367 next = NULL; 368 tail = NULL; 369 370 if (!list || !list->ifa_next) 371 return (list); 372 373 while (temp && temp->ifa_next) { 374 last = right; 375 right = right->ifa_next; 376 temp = temp->ifa_next->ifa_next; 377 } 378 379 last->ifa_next = NULL; 380 381 list = sortifaddrs(list, compare, q); 382 right = sortifaddrs(right, compare, q); 383 384 while (list || right) { 385 386 if (!right) { 387 next = list; 388 list = list->ifa_next; 389 } else if (!list) { 390 next = right; 391 right = right->ifa_next; 392 } else if (compare(list, right, q) <= 0) { 393 next = list; 394 list = list->ifa_next; 395 } else { 396 next = right; 397 right = right->ifa_next; 398 } 399 400 if (!result) 401 result = next; 402 else 403 tail->ifa_next = next; 404 405 tail = next; 406 } 407 408 return (result); 409 } 410 411 void printifnamemaybe() 412 { 413 if (printifname) 414 printf("%s\n", name); 415 } 416 417 int 418 main(int argc, char *argv[]) 419 { 420 int c, all, namesonly, downonly, uponly; 421 const struct afswtch *afp = NULL; 422 int ifindex; 423 struct ifaddrs *ifap, *sifap, *ifa; 424 struct ifreq paifr; 425 const struct sockaddr_dl *sdl; 426 char options[1024], *cp, *envformat, *namecp = NULL; 427 struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); 428 struct ifa_order_elt *cur, *tmp; 429 const char *ifname; 430 struct option *p; 431 size_t iflen; 432 433 #ifdef FSTACK 434 ff_ipc_init(); 435 #endif 436 437 all = downonly = uponly = namesonly = noload = verbose = 0; 438 f_inet = f_inet6 = f_ether = f_addr = NULL; 439 440 envformat = getenv("IFCONFIG_FORMAT"); 441 if (envformat != NULL) 442 setformat(envformat); 443 444 /* 445 * Ensure we print interface name when expected to, 446 * even if we terminate early due to error. 447 */ 448 atexit(printifnamemaybe); 449 450 /* Parse leading line options */ 451 #ifndef FSTACK 452 strlcpy(options, "f:adklmnuv", sizeof(options)); 453 #else 454 strlcpy(options, "p:f:adklmnuv", sizeof(options)); 455 #endif 456 for (p = opts; p != NULL; p = p->next) 457 strlcat(options, p->opt, sizeof(options)); 458 while ((c = getopt(argc, argv, options)) != -1) { 459 switch (c) { 460 #ifdef FSTACK 461 case 'p': 462 ff_set_proc_id(atoi(optarg)); 463 break; 464 #endif 465 case 'a': /* scan all interfaces */ 466 all++; 467 break; 468 case 'd': /* restrict scan to "down" interfaces */ 469 downonly++; 470 break; 471 case 'f': 472 if (optarg == NULL) 473 usage(); 474 setformat(optarg); 475 break; 476 case 'k': 477 printkeys++; 478 break; 479 case 'l': /* scan interface names only */ 480 namesonly++; 481 break; 482 case 'm': /* show media choices in status */ 483 supmedia = 1; 484 break; 485 case 'n': /* suppress module loading */ 486 noload++; 487 break; 488 case 'u': /* restrict scan to "up" interfaces */ 489 uponly++; 490 break; 491 case 'v': 492 verbose++; 493 break; 494 default: 495 for (p = opts; p != NULL; p = p->next) 496 if (p->opt[0] == c) { 497 p->cb(optarg); 498 break; 499 } 500 if (p == NULL) 501 usage(); 502 break; 503 } 504 } 505 argc -= optind; 506 argv += optind; 507 508 /* -l cannot be used with -a or -m */ 509 if (namesonly && (all || supmedia)) 510 usage(); 511 512 /* nonsense.. */ 513 if (uponly && downonly) 514 usage(); 515 516 /* no arguments is equivalent to '-a' */ 517 if (!namesonly && argc < 1) 518 all = 1; 519 520 /* -a and -l allow an address family arg to limit the output */ 521 if (all || namesonly) { 522 if (argc > 1) 523 usage(); 524 525 ifname = NULL; 526 ifindex = 0; 527 if (argc == 1) { 528 afp = af_getbyname(*argv); 529 if (afp == NULL) { 530 warnx("Address family '%s' unknown.", *argv); 531 usage(); 532 } 533 if (afp->af_name != NULL) 534 argc--, argv++; 535 /* leave with afp non-zero */ 536 } 537 } else { 538 /* not listing, need an argument */ 539 if (argc < 1) 540 usage(); 541 542 ifname = *argv; 543 argc--, argv++; 544 545 /* check and maybe load support for this interface */ 546 ifmaybeload(ifname); 547 548 ifindex = if_nametoindex(ifname); 549 if (ifindex == 0) { 550 /* 551 * NOTE: We must special-case the `create' command 552 * right here as we would otherwise fail when trying 553 * to find the interface. 554 */ 555 if (argc > 0 && (strcmp(argv[0], "create") == 0 || 556 strcmp(argv[0], "plumb") == 0)) { 557 iflen = strlcpy(name, ifname, sizeof(name)); 558 if (iflen >= sizeof(name)) 559 errx(1, "%s: cloning name too long", 560 ifname); 561 ifconfig(argc, argv, 1, NULL); 562 #ifdef FSTACK 563 ff_ipc_exit(); 564 #endif 565 exit(0); 566 } 567 #ifdef JAIL 568 /* 569 * NOTE: We have to special-case the `-vnet' command 570 * right here as we would otherwise fail when trying 571 * to find the interface as it lives in another vnet. 572 */ 573 if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) { 574 iflen = strlcpy(name, ifname, sizeof(name)); 575 if (iflen >= sizeof(name)) 576 errx(1, "%s: interface name too long", 577 ifname); 578 ifconfig(argc, argv, 0, NULL); 579 #ifdef FSTACK 580 ff_ipc_exit(); 581 #endif 582 exit(0); 583 } 584 #endif 585 errx(1, "interface %s does not exist", ifname); 586 } 587 } 588 589 /* Check for address family */ 590 if (argc > 0) { 591 afp = af_getbyname(*argv); 592 if (afp != NULL) 593 argc--, argv++; 594 } 595 596 if (getifaddrs(&ifap) != 0) 597 err(EXIT_FAILURE, "getifaddrs"); 598 599 cp = NULL; 600 601 if (calcorders(ifap, &q) != 0) 602 err(EXIT_FAILURE, "calcorders"); 603 604 sifap = sortifaddrs(ifap, cmpifaddrs, &q); 605 606 TAILQ_FOREACH_SAFE(cur, &q, link, tmp) 607 free(cur); 608 609 ifindex = 0; 610 for (ifa = sifap; ifa; ifa = ifa->ifa_next) { 611 memset(&paifr, 0, sizeof(paifr)); 612 strlcpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 613 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 614 memcpy(&paifr.ifr_addr, ifa->ifa_addr, 615 ifa->ifa_addr->sa_len); 616 } 617 618 if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) 619 continue; 620 if (ifa->ifa_addr->sa_family == AF_LINK) 621 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 622 else 623 sdl = NULL; 624 if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !namesonly) 625 continue; 626 iflen = strlcpy(name, ifa->ifa_name, sizeof(name)); 627 if (iflen >= sizeof(name)) { 628 warnx("%s: interface name too long, skipping", 629 ifa->ifa_name); 630 continue; 631 } 632 cp = ifa->ifa_name; 633 634 if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0) 635 continue; 636 if (downonly && (ifa->ifa_flags & IFF_UP) != 0) 637 continue; 638 if (uponly && (ifa->ifa_flags & IFF_UP) == 0) 639 continue; 640 /* 641 * Are we just listing the interfaces? 642 */ 643 if (namesonly) { 644 if (namecp == cp) 645 continue; 646 if (afp != NULL) { 647 /* special case for "ether" address family */ 648 if (!strcmp(afp->af_name, "ether")) { 649 if (sdl == NULL || 650 (sdl->sdl_type != IFT_ETHER && 651 sdl->sdl_type != IFT_L2VLAN && 652 sdl->sdl_type != IFT_BRIDGE) || 653 sdl->sdl_alen != ETHER_ADDR_LEN) 654 continue; 655 } else { 656 if (ifa->ifa_addr->sa_family 657 != afp->af_af) 658 continue; 659 } 660 } 661 namecp = cp; 662 ifindex++; 663 if (ifindex > 1) 664 printf(" "); 665 fputs(name, stdout); 666 continue; 667 } 668 ifindex++; 669 670 if (argc > 0) 671 ifconfig(argc, argv, 0, afp); 672 else 673 status(afp, sdl, ifa); 674 } 675 if (namesonly) 676 printf("\n"); 677 freeifaddrs(ifap); 678 679 freeformat(); 680 681 #ifdef FSTACK 682 ff_ipc_exit(); 683 #endif 684 exit(0); 685 } 686 687 static struct afswtch *afs = NULL; 688 689 void 690 af_register(struct afswtch *p) 691 { 692 p->af_next = afs; 693 afs = p; 694 } 695 696 static struct afswtch * 697 af_getbyname(const char *name) 698 { 699 struct afswtch *afp; 700 701 for (afp = afs; afp != NULL; afp = afp->af_next) 702 if (strcmp(afp->af_name, name) == 0) 703 return afp; 704 return NULL; 705 } 706 707 static struct afswtch * 708 af_getbyfamily(int af) 709 { 710 struct afswtch *afp; 711 712 for (afp = afs; afp != NULL; afp = afp->af_next) 713 if (afp->af_af == af) 714 return afp; 715 return NULL; 716 } 717 718 static void 719 af_other_status(int s) 720 { 721 struct afswtch *afp; 722 uint8_t afmask[howmany(AF_MAX, NBBY)]; 723 724 memset(afmask, 0, sizeof(afmask)); 725 for (afp = afs; afp != NULL; afp = afp->af_next) { 726 if (afp->af_other_status == NULL) 727 continue; 728 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 729 continue; 730 afp->af_other_status(s); 731 setbit(afmask, afp->af_af); 732 } 733 } 734 735 static void 736 af_all_tunnel_status(int s) 737 { 738 struct afswtch *afp; 739 uint8_t afmask[howmany(AF_MAX, NBBY)]; 740 741 memset(afmask, 0, sizeof(afmask)); 742 for (afp = afs; afp != NULL; afp = afp->af_next) { 743 if (afp->af_status_tunnel == NULL) 744 continue; 745 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 746 continue; 747 afp->af_status_tunnel(s); 748 setbit(afmask, afp->af_af); 749 } 750 } 751 752 static struct cmd *cmds = NULL; 753 754 void 755 cmd_register(struct cmd *p) 756 { 757 p->c_next = cmds; 758 cmds = p; 759 } 760 761 static const struct cmd * 762 cmd_lookup(const char *name, int iscreate) 763 { 764 const struct cmd *p; 765 766 for (p = cmds; p != NULL; p = p->c_next) 767 if (strcmp(name, p->c_name) == 0) { 768 if (iscreate) { 769 if (p->c_iscloneop) 770 return p; 771 } else { 772 if (!p->c_iscloneop) 773 return p; 774 } 775 } 776 return NULL; 777 } 778 779 struct callback { 780 callback_func *cb_func; 781 void *cb_arg; 782 struct callback *cb_next; 783 }; 784 static struct callback *callbacks = NULL; 785 786 void 787 callback_register(callback_func *func, void *arg) 788 { 789 struct callback *cb; 790 791 cb = malloc(sizeof(struct callback)); 792 if (cb == NULL) 793 errx(1, "unable to allocate memory for callback"); 794 cb->cb_func = func; 795 cb->cb_arg = arg; 796 cb->cb_next = callbacks; 797 callbacks = cb; 798 } 799 800 /* specially-handled commands */ 801 static void setifaddr(const char *, int, int, const struct afswtch *); 802 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); 803 804 static void setifdstaddr(const char *, int, int, const struct afswtch *); 805 static const struct cmd setifdstaddr_cmd = 806 DEF_CMD("ifdstaddr", 0, setifdstaddr); 807 808 static int 809 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp) 810 { 811 const struct afswtch *afp, *nafp; 812 const struct cmd *p; 813 struct callback *cb; 814 int s; 815 816 strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 817 afp = NULL; 818 if (uafp != NULL) 819 afp = uafp; 820 /* 821 * This is the historical "accident" allowing users to configure IPv4 822 * addresses without the "inet" keyword which while a nice feature has 823 * proven to complicate other things. We cannot remove this but only 824 * make sure we will never have a similar implicit default for IPv6 or 825 * any other address familiy. We need a fallback though for 826 * ifconfig IF up/down etc. to work without INET support as people 827 * never used ifconfig IF link up/down, etc. either. 828 */ 829 #ifndef RESCUE 830 #ifdef INET 831 if (afp == NULL && feature_present("inet")) 832 afp = af_getbyname("inet"); 833 #endif 834 #endif 835 if (afp == NULL) 836 afp = af_getbyname("link"); 837 if (afp == NULL) { 838 warnx("Please specify an address_family."); 839 usage(); 840 } 841 top: 842 ifr.ifr_addr.sa_family = 843 afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? 844 AF_LOCAL : afp->af_af; 845 846 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 && 847 (uafp != NULL || errno != EAFNOSUPPORT || 848 (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) 849 err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); 850 851 while (argc > 0) { 852 p = cmd_lookup(*argv, iscreate); 853 if (iscreate && p == NULL) { 854 /* 855 * Push the clone create callback so the new 856 * device is created and can be used for any 857 * remaining arguments. 858 */ 859 cb = callbacks; 860 if (cb == NULL) 861 errx(1, "internal error, no callback"); 862 callbacks = cb->cb_next; 863 cb->cb_func(s, cb->cb_arg); 864 iscreate = 0; 865 /* 866 * Handle any address family spec that 867 * immediately follows and potentially 868 * recreate the socket. 869 */ 870 nafp = af_getbyname(*argv); 871 if (nafp != NULL) { 872 argc--, argv++; 873 if (nafp != afp) { 874 close(s); 875 afp = nafp; 876 goto top; 877 } 878 } 879 /* 880 * Look for a normal parameter. 881 */ 882 continue; 883 } 884 if (p == NULL) { 885 /* 886 * Not a recognized command, choose between setting 887 * the interface address and the dst address. 888 */ 889 p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); 890 } 891 if (p->c_u.c_func || p->c_u.c_func2) { 892 if (p->c_parameter == NEXTARG) { 893 if (argv[1] == NULL) 894 errx(1, "'%s' requires argument", 895 p->c_name); 896 p->c_u.c_func(argv[1], 0, s, afp); 897 argc--, argv++; 898 } else if (p->c_parameter == OPTARG) { 899 p->c_u.c_func(argv[1], 0, s, afp); 900 if (argv[1] != NULL) 901 argc--, argv++; 902 } else if (p->c_parameter == NEXTARG2) { 903 if (argc < 3) 904 errx(1, "'%s' requires 2 arguments", 905 p->c_name); 906 p->c_u.c_func2(argv[1], argv[2], s, afp); 907 argc -= 2, argv += 2; 908 } else 909 p->c_u.c_func(*argv, p->c_parameter, s, afp); 910 } 911 argc--, argv++; 912 } 913 914 /* 915 * Do any post argument processing required by the address family. 916 */ 917 if (afp->af_postproc != NULL) 918 afp->af_postproc(s, afp); 919 /* 920 * Do deferred callbacks registered while processing 921 * command-line arguments. 922 */ 923 for (cb = callbacks; cb != NULL; cb = cb->cb_next) 924 cb->cb_func(s, cb->cb_arg); 925 /* 926 * Do deferred operations. 927 */ 928 if (clearaddr) { 929 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 930 warnx("interface %s cannot change %s addresses!", 931 name, afp->af_name); 932 clearaddr = 0; 933 } 934 } 935 if (clearaddr) { 936 int ret; 937 strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, name, 938 sizeof ifr.ifr_name); 939 #ifndef FSTACK 940 ret = ioctl(s, afp->af_difaddr, afp->af_ridreq); 941 #else 942 ret = ioctl_va(s, afp->af_difaddr, afp->af_ridreq, 1, afp->af_af); 943 #endif 944 if (ret < 0) { 945 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 946 /* means no previous address for interface */ 947 } else 948 Perror("ioctl (SIOCDIFADDR)"); 949 } 950 } 951 if (newaddr) { 952 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 953 warnx("interface %s cannot change %s addresses!", 954 name, afp->af_name); 955 newaddr = 0; 956 } 957 } 958 if (newaddr && (setaddr || setmask)) { 959 strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name, 960 sizeof ifr.ifr_name); 961 #ifndef FSTACK 962 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 963 #else 964 if (ioctl_va(s, afp->af_aifaddr, afp->af_addreq, 1, afp->af_af) < 0) 965 #endif 966 Perror("ioctl (SIOCAIFADDR)"); 967 } 968 969 close(s); 970 return(0); 971 } 972 973 /*ARGSUSED*/ 974 static void 975 setifaddr(const char *addr, int param, int s, const struct afswtch *afp) 976 { 977 if (afp->af_getaddr == NULL) 978 return; 979 /* 980 * Delay the ioctl to set the interface addr until flags are all set. 981 * The address interpretation may depend on the flags, 982 * and the flags may change when the address is set. 983 */ 984 setaddr++; 985 if (doalias == 0 && afp->af_af != AF_LINK) 986 clearaddr = 1; 987 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); 988 } 989 990 static void 991 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) 992 { 993 struct addrinfo *srcres, *dstres; 994 int ecode; 995 996 if (afp->af_settunnel == NULL) { 997 warn("address family %s does not support tunnel setup", 998 afp->af_name); 999 return; 1000 } 1001 1002 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 1003 errx(1, "error in parsing address string: %s", 1004 gai_strerror(ecode)); 1005 1006 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 1007 errx(1, "error in parsing address string: %s", 1008 gai_strerror(ecode)); 1009 1010 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 1011 errx(1, 1012 "source and destination address families do not match"); 1013 1014 afp->af_settunnel(s, srcres, dstres); 1015 1016 freeaddrinfo(srcres); 1017 freeaddrinfo(dstres); 1018 } 1019 1020 /* ARGSUSED */ 1021 static void 1022 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) 1023 { 1024 1025 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 1026 err(1, "SIOCDIFPHYADDR"); 1027 } 1028 1029 #ifdef JAIL 1030 static void 1031 setifvnet(const char *jname, int dummy __unused, int s, 1032 const struct afswtch *afp) 1033 { 1034 struct ifreq my_ifr; 1035 1036 memcpy(&my_ifr, &ifr, sizeof(my_ifr)); 1037 my_ifr.ifr_jid = jail_getid(jname); 1038 if (my_ifr.ifr_jid < 0) 1039 errx(1, "%s", jail_errmsg); 1040 if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0) 1041 err(1, "SIOCSIFVNET"); 1042 } 1043 1044 static void 1045 setifrvnet(const char *jname, int dummy __unused, int s, 1046 const struct afswtch *afp) 1047 { 1048 struct ifreq my_ifr; 1049 1050 memcpy(&my_ifr, &ifr, sizeof(my_ifr)); 1051 my_ifr.ifr_jid = jail_getid(jname); 1052 if (my_ifr.ifr_jid < 0) 1053 errx(1, "%s", jail_errmsg); 1054 if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0) 1055 err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name); 1056 } 1057 #endif 1058 1059 static void 1060 setifnetmask(const char *addr, int dummy __unused, int s, 1061 const struct afswtch *afp) 1062 { 1063 if (afp->af_getaddr != NULL) { 1064 setmask++; 1065 afp->af_getaddr(addr, MASK); 1066 } 1067 } 1068 1069 static void 1070 setifbroadaddr(const char *addr, int dummy __unused, int s, 1071 const struct afswtch *afp) 1072 { 1073 if (afp->af_getaddr != NULL) 1074 afp->af_getaddr(addr, DSTADDR); 1075 } 1076 1077 static void 1078 notealias(const char *addr, int param, int s, const struct afswtch *afp) 1079 { 1080 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 1081 if (setaddr && doalias == 0 && param < 0) 1082 if (afp->af_addreq != NULL && afp->af_ridreq != NULL) 1083 bcopy((caddr_t)rqtosa(af_addreq), 1084 (caddr_t)rqtosa(af_ridreq), 1085 rqtosa(af_addreq)->sa_len); 1086 doalias = param; 1087 if (param < 0) { 1088 clearaddr = 1; 1089 newaddr = 0; 1090 } else 1091 clearaddr = 0; 1092 #undef rqtosa 1093 } 1094 1095 /*ARGSUSED*/ 1096 static void 1097 setifdstaddr(const char *addr, int param __unused, int s, 1098 const struct afswtch *afp) 1099 { 1100 if (afp->af_getaddr != NULL) 1101 afp->af_getaddr(addr, DSTADDR); 1102 } 1103 1104 /* 1105 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 1106 * of the ifreq structure, which may confuse other parts of ifconfig. 1107 * Make a private copy so we can avoid that. 1108 */ 1109 static void 1110 setifflags(const char *vname, int value, int s, const struct afswtch *afp) 1111 { 1112 struct ifreq my_ifr; 1113 int flags; 1114 1115 memset(&my_ifr, 0, sizeof(my_ifr)); 1116 (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); 1117 1118 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 1119 Perror("ioctl (SIOCGIFFLAGS)"); 1120 #ifdef FSTACK 1121 ff_ipc_exit(); 1122 #endif 1123 exit(1); 1124 } 1125 flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16); 1126 1127 if (value < 0) { 1128 value = -value; 1129 flags &= ~value; 1130 } else 1131 flags |= value; 1132 my_ifr.ifr_flags = flags & 0xffff; 1133 my_ifr.ifr_flagshigh = flags >> 16; 1134 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 1135 Perror(vname); 1136 } 1137 1138 void 1139 setifcap(const char *vname, int value, int s, const struct afswtch *afp) 1140 { 1141 int flags; 1142 1143 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 1144 Perror("ioctl (SIOCGIFCAP)"); 1145 #ifdef FSTACK 1146 ff_ipc_exit(); 1147 #endif 1148 exit(1); 1149 } 1150 flags = ifr.ifr_curcap; 1151 if (value < 0) { 1152 value = -value; 1153 flags &= ~value; 1154 } else 1155 flags |= value; 1156 flags &= ifr.ifr_reqcap; 1157 ifr.ifr_reqcap = flags; 1158 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 1159 Perror(vname); 1160 } 1161 1162 static void 1163 setifmetric(const char *val, int dummy __unused, int s, 1164 const struct afswtch *afp) 1165 { 1166 strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1167 ifr.ifr_metric = atoi(val); 1168 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 1169 err(1, "ioctl SIOCSIFMETRIC (set metric)"); 1170 } 1171 1172 static void 1173 setifmtu(const char *val, int dummy __unused, int s, 1174 const struct afswtch *afp) 1175 { 1176 strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1177 ifr.ifr_mtu = atoi(val); 1178 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 1179 err(1, "ioctl SIOCSIFMTU (set mtu)"); 1180 } 1181 1182 static void 1183 setifname(const char *val, int dummy __unused, int s, 1184 const struct afswtch *afp) 1185 { 1186 char *newname; 1187 1188 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1189 1190 newname = strdup(val); 1191 if (newname == NULL) 1192 err(1, "no memory to set ifname"); 1193 ifr.ifr_data = newname; 1194 #ifndef FSTACK 1195 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { 1196 #else 1197 size_t offset = (char *)&(ifr.ifr_data) - (char *)&(ifr); 1198 size_t clen = strlen(newname); 1199 if (ioctl_va(s, SIOCSIFNAME, (caddr_t)&ifr, 3, offset, newname, clen) < 0) { 1200 #endif 1201 free(newname); 1202 err(1, "ioctl SIOCSIFNAME (set name)"); 1203 } 1204 printifname = 1; 1205 strlcpy(name, newname, sizeof(name)); 1206 free(newname); 1207 } 1208 1209 /* ARGSUSED */ 1210 static void 1211 setifdescr(const char *val, int dummy __unused, int s, 1212 const struct afswtch *afp) 1213 { 1214 char *newdescr; 1215 1216 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1217 1218 ifr.ifr_buffer.length = strlen(val) + 1; 1219 if (ifr.ifr_buffer.length == 1) { 1220 ifr.ifr_buffer.buffer = newdescr = NULL; 1221 ifr.ifr_buffer.length = 0; 1222 } else { 1223 newdescr = strdup(val); 1224 ifr.ifr_buffer.buffer = newdescr; 1225 if (newdescr == NULL) { 1226 warn("no memory to set ifdescr"); 1227 return; 1228 } 1229 } 1230 1231 #ifdef FSTACK 1232 if (ifr.ifr_buffer.buffer != NULL) { 1233 size_t offset = (char *)&(ifr.ifr_buffer.buffer) - (char *)&(ifr); 1234 if (ioctl_va(s, SIOCSIFDESCR, (caddr_t)&ifr, 3, offset, 1235 ifr.ifr_buffer.buffer, ifr.ifr_buffer.length) < 0) 1236 err(1, "ioctl SIOCSIFDESCR (set descr)"); 1237 } else 1238 #endif 1239 if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) 1240 err(1, "ioctl SIOCSIFDESCR (set descr)"); 1241 1242 free(newdescr); 1243 } 1244 1245 /* ARGSUSED */ 1246 static void 1247 unsetifdescr(const char *val, int value, int s, const struct afswtch *afp) 1248 { 1249 1250 setifdescr("", 0, s, 0); 1251 } 1252 1253 #define IFFBITS \ 1254 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \ 1255 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 1256 "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP" 1257 1258 #define IFCAPBITS \ 1259 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ 1260 "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \ 1261 "\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \ 1262 "\26RXCSUM_IPV6\27TXCSUM_IPV6" 1263 1264 /* 1265 * Print the status of the interface. If an address family was 1266 * specified, show only it; otherwise, show them all. 1267 */ 1268 static void 1269 status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 1270 struct ifaddrs *ifa) 1271 { 1272 struct ifaddrs *ift; 1273 int allfamilies, s; 1274 struct ifstat ifs; 1275 1276 if (afp == NULL) { 1277 allfamilies = 1; 1278 ifr.ifr_addr.sa_family = AF_LOCAL; 1279 } else { 1280 allfamilies = 0; 1281 ifr.ifr_addr.sa_family = 1282 afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af; 1283 } 1284 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1285 1286 s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); 1287 if (s < 0) 1288 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); 1289 1290 printf("%s: ", name); 1291 printb("flags", ifa->ifa_flags, IFFBITS); 1292 if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) 1293 printf(" metric %d", ifr.ifr_metric); 1294 if (ioctl(s, SIOCGIFMTU, &ifr) != -1) 1295 printf(" mtu %d", ifr.ifr_mtu); 1296 putchar('\n'); 1297 1298 for (;;) { 1299 if ((descr = reallocf(descr, descrlen)) != NULL) { 1300 ifr.ifr_buffer.buffer = descr; 1301 ifr.ifr_buffer.length = descrlen; 1302 #ifndef FSTACK 1303 if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) { 1304 #else 1305 size_t offset = (char *)&(ifr.ifr_buffer.buffer) - (char *)&(ifr); 1306 if (ioctl_va(s, SIOCGIFDESCR, &ifr, 3, offset, descr, descrlen) == 0) { 1307 #endif 1308 if (ifr.ifr_buffer.buffer == descr) { 1309 if (strlen(descr) > 0) 1310 printf("\tdescription: %s\n", 1311 descr); 1312 } else if (ifr.ifr_buffer.length > descrlen) { 1313 descrlen = ifr.ifr_buffer.length; 1314 continue; 1315 } 1316 } 1317 } else 1318 warn("unable to allocate memory for interface" 1319 "description"); 1320 break; 1321 } 1322 1323 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { 1324 if (ifr.ifr_curcap != 0) { 1325 printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 1326 putchar('\n'); 1327 } 1328 if (supmedia && ifr.ifr_reqcap != 0) { 1329 printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS); 1330 putchar('\n'); 1331 } 1332 } 1333 1334 tunnel_status(s); 1335 1336 for (ift = ifa; ift != NULL; ift = ift->ifa_next) { 1337 if (ift->ifa_addr == NULL) 1338 continue; 1339 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) 1340 continue; 1341 if (allfamilies) { 1342 const struct afswtch *p; 1343 p = af_getbyfamily(ift->ifa_addr->sa_family); 1344 if (p != NULL && p->af_status != NULL) 1345 p->af_status(s, ift); 1346 } else if (afp->af_af == ift->ifa_addr->sa_family) 1347 afp->af_status(s, ift); 1348 } 1349 #if 0 1350 if (allfamilies || afp->af_af == AF_LINK) { 1351 const struct afswtch *lafp; 1352 1353 /* 1354 * Hack; the link level address is received separately 1355 * from the routing information so any address is not 1356 * handled above. Cobble together an entry and invoke 1357 * the status method specially. 1358 */ 1359 lafp = af_getbyname("lladdr"); 1360 if (lafp != NULL) { 1361 info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl; 1362 lafp->af_status(s, &info); 1363 } 1364 } 1365 #endif 1366 if (allfamilies) 1367 af_other_status(s); 1368 else if (afp->af_other_status != NULL) 1369 afp->af_other_status(s); 1370 1371 strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 1372 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 1373 printf("%s", ifs.ascii); 1374 1375 #ifndef FSTACK 1376 if (verbose > 0) 1377 sfp_status(s, &ifr, verbose); 1378 #endif 1379 1380 close(s); 1381 return; 1382 } 1383 1384 static void 1385 tunnel_status(int s) 1386 { 1387 af_all_tunnel_status(s); 1388 } 1389 1390 void 1391 Perror(const char *cmd) 1392 { 1393 switch (errno) { 1394 1395 case ENXIO: 1396 errx(1, "%s: no such interface", cmd); 1397 break; 1398 1399 case EPERM: 1400 errx(1, "%s: permission denied", cmd); 1401 break; 1402 1403 default: 1404 err(1, "%s", cmd); 1405 } 1406 } 1407 1408 /* 1409 * Print a value a la the %b format of the kernel's printf 1410 */ 1411 void 1412 printb(const char *s, unsigned v, const char *bits) 1413 { 1414 int i, any = 0; 1415 char c; 1416 1417 if (bits && *bits == 8) 1418 printf("%s=%o", s, v); 1419 else 1420 printf("%s=%x", s, v); 1421 bits++; 1422 if (bits) { 1423 putchar('<'); 1424 while ((i = *bits++) != '\0') { 1425 if (v & (1 << (i-1))) { 1426 if (any) 1427 putchar(','); 1428 any = 1; 1429 for (; (c = *bits) > 32; bits++) 1430 putchar(c); 1431 } else 1432 for (; *bits > 32; bits++) 1433 ; 1434 } 1435 putchar('>'); 1436 } 1437 } 1438 1439 void 1440 print_vhid(const struct ifaddrs *ifa, const char *s) 1441 { 1442 struct if_data *ifd; 1443 1444 if (ifa->ifa_data == NULL) 1445 return; 1446 1447 ifd = ifa->ifa_data; 1448 if (ifd->ifi_vhid == 0) 1449 return; 1450 1451 printf("vhid %d ", ifd->ifi_vhid); 1452 } 1453 1454 void 1455 ifmaybeload(const char *name) 1456 { 1457 #ifndef FSTACK 1458 #define MOD_PREFIX_LEN 3 /* "if_" */ 1459 struct module_stat mstat; 1460 int fileid, modid; 1461 char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; 1462 const char *cp; 1463 1464 /* loading suppressed by the user */ 1465 if (noload) 1466 return; 1467 1468 /* trim the interface number off the end */ 1469 strlcpy(ifname, name, sizeof(ifname)); 1470 for (dp = ifname; *dp != 0; dp++) 1471 if (isdigit(*dp)) { 1472 *dp = 0; 1473 break; 1474 } 1475 1476 /* turn interface and unit into module name */ 1477 strlcpy(ifkind, "if_", sizeof(ifkind)); 1478 strlcat(ifkind, ifname, sizeof(ifkind)); 1479 1480 /* scan files in kernel */ 1481 mstat.version = sizeof(struct module_stat); 1482 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1483 /* scan modules in file */ 1484 for (modid = kldfirstmod(fileid); modid > 0; 1485 modid = modfnext(modid)) { 1486 if (modstat(modid, &mstat) < 0) 1487 continue; 1488 /* strip bus name if present */ 1489 if ((cp = strchr(mstat.name, '/')) != NULL) { 1490 cp++; 1491 } else { 1492 cp = mstat.name; 1493 } 1494 /* already loaded? */ 1495 if (strcmp(ifname, cp) == 0 || 1496 strcmp(ifkind, cp) == 0) 1497 return; 1498 } 1499 } 1500 1501 /* not present, we should try to load it */ 1502 kldload(ifkind); 1503 #endif 1504 } 1505 1506 static struct cmd basic_cmds[] = { 1507 DEF_CMD("up", IFF_UP, setifflags), 1508 DEF_CMD("down", -IFF_UP, setifflags), 1509 DEF_CMD("arp", -IFF_NOARP, setifflags), 1510 DEF_CMD("-arp", IFF_NOARP, setifflags), 1511 DEF_CMD("debug", IFF_DEBUG, setifflags), 1512 DEF_CMD("-debug", -IFF_DEBUG, setifflags), 1513 DEF_CMD_ARG("description", setifdescr), 1514 DEF_CMD_ARG("descr", setifdescr), 1515 DEF_CMD("-description", 0, unsetifdescr), 1516 DEF_CMD("-descr", 0, unsetifdescr), 1517 DEF_CMD("promisc", IFF_PPROMISC, setifflags), 1518 DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), 1519 DEF_CMD("add", IFF_UP, notealias), 1520 DEF_CMD("alias", IFF_UP, notealias), 1521 DEF_CMD("-alias", -IFF_UP, notealias), 1522 DEF_CMD("delete", -IFF_UP, notealias), 1523 DEF_CMD("remove", -IFF_UP, notealias), 1524 #ifdef notdef 1525 #define EN_SWABIPS 0x1000 1526 DEF_CMD("swabips", EN_SWABIPS, setifflags), 1527 DEF_CMD("-swabips", -EN_SWABIPS, setifflags), 1528 #endif 1529 DEF_CMD_ARG("netmask", setifnetmask), 1530 DEF_CMD_ARG("metric", setifmetric), 1531 DEF_CMD_ARG("broadcast", setifbroadaddr), 1532 DEF_CMD_ARG2("tunnel", settunnel), 1533 DEF_CMD("-tunnel", 0, deletetunnel), 1534 DEF_CMD("deletetunnel", 0, deletetunnel), 1535 #ifdef JAIL 1536 DEF_CMD_ARG("vnet", setifvnet), 1537 DEF_CMD_ARG("-vnet", setifrvnet), 1538 #endif 1539 DEF_CMD("link0", IFF_LINK0, setifflags), 1540 DEF_CMD("-link0", -IFF_LINK0, setifflags), 1541 DEF_CMD("link1", IFF_LINK1, setifflags), 1542 DEF_CMD("-link1", -IFF_LINK1, setifflags), 1543 DEF_CMD("link2", IFF_LINK2, setifflags), 1544 DEF_CMD("-link2", -IFF_LINK2, setifflags), 1545 DEF_CMD("monitor", IFF_MONITOR, setifflags), 1546 DEF_CMD("-monitor", -IFF_MONITOR, setifflags), 1547 DEF_CMD("staticarp", IFF_STATICARP, setifflags), 1548 DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), 1549 DEF_CMD("rxcsum6", IFCAP_RXCSUM_IPV6, setifcap), 1550 DEF_CMD("-rxcsum6", -IFCAP_RXCSUM_IPV6, setifcap), 1551 DEF_CMD("txcsum6", IFCAP_TXCSUM_IPV6, setifcap), 1552 DEF_CMD("-txcsum6", -IFCAP_TXCSUM_IPV6, setifcap), 1553 DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), 1554 DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), 1555 DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), 1556 DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), 1557 DEF_CMD("netcons", IFCAP_NETCONS, setifcap), 1558 DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), 1559 DEF_CMD("polling", IFCAP_POLLING, setifcap), 1560 DEF_CMD("-polling", -IFCAP_POLLING, setifcap), 1561 DEF_CMD("tso6", IFCAP_TSO6, setifcap), 1562 DEF_CMD("-tso6", -IFCAP_TSO6, setifcap), 1563 DEF_CMD("tso4", IFCAP_TSO4, setifcap), 1564 DEF_CMD("-tso4", -IFCAP_TSO4, setifcap), 1565 DEF_CMD("tso", IFCAP_TSO, setifcap), 1566 DEF_CMD("-tso", -IFCAP_TSO, setifcap), 1567 DEF_CMD("toe", IFCAP_TOE, setifcap), 1568 DEF_CMD("-toe", -IFCAP_TOE, setifcap), 1569 DEF_CMD("lro", IFCAP_LRO, setifcap), 1570 DEF_CMD("-lro", -IFCAP_LRO, setifcap), 1571 DEF_CMD("wol", IFCAP_WOL, setifcap), 1572 DEF_CMD("-wol", -IFCAP_WOL, setifcap), 1573 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), 1574 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), 1575 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), 1576 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), 1577 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), 1578 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), 1579 DEF_CMD("normal", -IFF_LINK0, setifflags), 1580 DEF_CMD("compress", IFF_LINK0, setifflags), 1581 DEF_CMD("noicmp", IFF_LINK1, setifflags), 1582 DEF_CMD_ARG("mtu", setifmtu), 1583 DEF_CMD_ARG("name", setifname), 1584 }; 1585 1586 static __constructor void 1587 ifconfig_ctor(void) 1588 { 1589 size_t i; 1590 1591 for (i = 0; i < nitems(basic_cmds); i++) 1592 cmd_register(&basic_cmds[i]); 1593 } 1594