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