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