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