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/socket.h> 47 #include <sys/sysctl.h> 48 #include <sys/time.h> 49 #include <sys/module.h> 50 #include <sys/linker.h> 51 52 #include <net/ethernet.h> 53 #include <net/if.h> 54 #include <net/if_var.h> 55 #include <net/if_dl.h> 56 #include <net/if_types.h> 57 #include <net/route.h> 58 59 /* IP */ 60 #include <netinet/in.h> 61 #include <netinet/in_var.h> 62 #include <arpa/inet.h> 63 #include <netdb.h> 64 65 #include <ifaddrs.h> 66 #include <ctype.h> 67 #include <err.h> 68 #include <errno.h> 69 #include <fcntl.h> 70 #include <jail.h> 71 #include <stdio.h> 72 #include <stdlib.h> 73 #include <string.h> 74 #include <unistd.h> 75 76 #include "ifconfig.h" 77 78 /* 79 * Since "struct ifreq" is composed of various union members, callers 80 * should pay special attention to interprete the value. 81 * (.e.g. little/big endian difference in the structure.) 82 */ 83 struct ifreq ifr; 84 85 char name[IFNAMSIZ]; 86 int setaddr; 87 int setmask; 88 int doalias; 89 int clearaddr; 90 int newaddr = 1; 91 int verbose; 92 int noload; 93 94 int supmedia = 0; 95 int printkeys = 0; /* Print keying material for interfaces. */ 96 97 static int ifconfig(int argc, char *const *argv, int iscreate, 98 const struct afswtch *afp); 99 static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 100 struct ifaddrs *ifa); 101 static void tunnel_status(int s); 102 static void usage(void); 103 104 static struct afswtch *af_getbyname(const char *name); 105 static struct afswtch *af_getbyfamily(int af); 106 static void af_other_status(int); 107 108 static struct option *opts = NULL; 109 110 void 111 opt_register(struct option *p) 112 { 113 p->next = opts; 114 opts = p; 115 } 116 117 static void 118 usage(void) 119 { 120 char options[1024]; 121 struct option *p; 122 123 /* XXX not right but close enough for now */ 124 options[0] = '\0'; 125 for (p = opts; p != NULL; p = p->next) { 126 strlcat(options, p->opt_usage, sizeof(options)); 127 strlcat(options, " ", sizeof(options)); 128 } 129 130 fprintf(stderr, 131 "usage: ifconfig %sinterface address_family [address [dest_address]]\n" 132 " [parameters]\n" 133 " ifconfig interface create\n" 134 " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n" 135 " ifconfig -l [-d] [-u] [address_family]\n" 136 " ifconfig %s[-d] [-m] [-u] [-v]\n", 137 options, options, options); 138 exit(1); 139 } 140 141 int 142 main(int argc, char *argv[]) 143 { 144 int c, all, namesonly, downonly, uponly; 145 const struct afswtch *afp = NULL; 146 int ifindex; 147 struct ifaddrs *ifap, *ifa; 148 struct ifreq paifr; 149 const struct sockaddr_dl *sdl; 150 char options[1024], *cp, *namecp = NULL; 151 const char *ifname; 152 struct option *p; 153 size_t iflen; 154 155 all = downonly = uponly = namesonly = noload = verbose = 0; 156 157 /* Parse leading line options */ 158 strlcpy(options, "adklmnuv", sizeof(options)); 159 for (p = opts; p != NULL; p = p->next) 160 strlcat(options, p->opt, sizeof(options)); 161 while ((c = getopt(argc, argv, options)) != -1) { 162 switch (c) { 163 case 'a': /* scan all interfaces */ 164 all++; 165 break; 166 case 'd': /* restrict scan to "down" interfaces */ 167 downonly++; 168 break; 169 case 'k': 170 printkeys++; 171 break; 172 case 'l': /* scan interface names only */ 173 namesonly++; 174 break; 175 case 'm': /* show media choices in status */ 176 supmedia = 1; 177 break; 178 case 'n': /* suppress module loading */ 179 noload++; 180 break; 181 case 'u': /* restrict scan to "up" interfaces */ 182 uponly++; 183 break; 184 case 'v': 185 verbose++; 186 break; 187 default: 188 for (p = opts; p != NULL; p = p->next) 189 if (p->opt[0] == c) { 190 p->cb(optarg); 191 break; 192 } 193 if (p == NULL) 194 usage(); 195 break; 196 } 197 } 198 argc -= optind; 199 argv += optind; 200 201 /* -l cannot be used with -a or -m */ 202 if (namesonly && (all || supmedia)) 203 usage(); 204 205 /* nonsense.. */ 206 if (uponly && downonly) 207 usage(); 208 209 /* no arguments is equivalent to '-a' */ 210 if (!namesonly && argc < 1) 211 all = 1; 212 213 /* -a and -l allow an address family arg to limit the output */ 214 if (all || namesonly) { 215 if (argc > 1) 216 usage(); 217 218 ifname = NULL; 219 ifindex = 0; 220 if (argc == 1) { 221 afp = af_getbyname(*argv); 222 if (afp == NULL) 223 usage(); 224 if (afp->af_name != NULL) 225 argc--, argv++; 226 /* leave with afp non-zero */ 227 } 228 } else { 229 /* not listing, need an argument */ 230 if (argc < 1) 231 usage(); 232 233 ifname = *argv; 234 argc--, argv++; 235 236 /* check and maybe load support for this interface */ 237 ifmaybeload(ifname); 238 239 ifindex = if_nametoindex(ifname); 240 if (ifindex == 0) { 241 /* 242 * NOTE: We must special-case the `create' command 243 * right here as we would otherwise fail when trying 244 * to find the interface. 245 */ 246 if (argc > 0 && (strcmp(argv[0], "create") == 0 || 247 strcmp(argv[0], "plumb") == 0)) { 248 iflen = strlcpy(name, ifname, sizeof(name)); 249 if (iflen >= sizeof(name)) 250 errx(1, "%s: cloning name too long", 251 ifname); 252 ifconfig(argc, argv, 1, NULL); 253 exit(0); 254 } 255 /* 256 * NOTE: We have to special-case the `-vnet' command 257 * right here as we would otherwise fail when trying 258 * to find the interface as it lives in another vnet. 259 */ 260 if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) { 261 iflen = strlcpy(name, ifname, sizeof(name)); 262 if (iflen >= sizeof(name)) 263 errx(1, "%s: interface name too long", 264 ifname); 265 ifconfig(argc, argv, 0, NULL); 266 exit(0); 267 } 268 errx(1, "interface %s does not exist", ifname); 269 } 270 } 271 272 /* Check for address family */ 273 if (argc > 0) { 274 afp = af_getbyname(*argv); 275 if (afp != NULL) 276 argc--, argv++; 277 } 278 279 if (getifaddrs(&ifap) != 0) 280 err(EXIT_FAILURE, "getifaddrs"); 281 cp = NULL; 282 ifindex = 0; 283 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 284 memset(&paifr, 0, sizeof(paifr)); 285 strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 286 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 287 memcpy(&paifr.ifr_addr, ifa->ifa_addr, 288 ifa->ifa_addr->sa_len); 289 } 290 291 if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) 292 continue; 293 if (ifa->ifa_addr->sa_family == AF_LINK) 294 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 295 else 296 sdl = NULL; 297 if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !namesonly) 298 continue; 299 iflen = strlcpy(name, ifa->ifa_name, sizeof(name)); 300 if (iflen >= sizeof(name)) { 301 warnx("%s: interface name too long, skipping", 302 ifa->ifa_name); 303 continue; 304 } 305 cp = ifa->ifa_name; 306 307 if (downonly && (ifa->ifa_flags & IFF_UP) != 0) 308 continue; 309 if (uponly && (ifa->ifa_flags & IFF_UP) == 0) 310 continue; 311 /* 312 * Are we just listing the interfaces? 313 */ 314 if (namesonly) { 315 if (namecp == cp) 316 continue; 317 if (afp != NULL) { 318 /* special case for "ether" address family */ 319 if (!strcmp(afp->af_name, "ether")) { 320 if (sdl == NULL || 321 sdl->sdl_type != IFT_ETHER || 322 sdl->sdl_alen != ETHER_ADDR_LEN) 323 continue; 324 } else { 325 if (ifa->ifa_addr->sa_family != afp->af_af) 326 continue; 327 } 328 } 329 namecp = cp; 330 ifindex++; 331 if (ifindex > 1) 332 printf(" "); 333 fputs(name, stdout); 334 continue; 335 } 336 ifindex++; 337 338 if (argc > 0) 339 ifconfig(argc, argv, 0, afp); 340 else 341 status(afp, sdl, ifa); 342 } 343 if (namesonly) 344 printf("\n"); 345 freeifaddrs(ifap); 346 347 exit(0); 348 } 349 350 static struct afswtch *afs = NULL; 351 352 void 353 af_register(struct afswtch *p) 354 { 355 p->af_next = afs; 356 afs = p; 357 } 358 359 static struct afswtch * 360 af_getbyname(const char *name) 361 { 362 struct afswtch *afp; 363 364 for (afp = afs; afp != NULL; afp = afp->af_next) 365 if (strcmp(afp->af_name, name) == 0) 366 return afp; 367 return NULL; 368 } 369 370 static struct afswtch * 371 af_getbyfamily(int af) 372 { 373 struct afswtch *afp; 374 375 for (afp = afs; afp != NULL; afp = afp->af_next) 376 if (afp->af_af == af) 377 return afp; 378 return NULL; 379 } 380 381 static void 382 af_other_status(int s) 383 { 384 struct afswtch *afp; 385 uint8_t afmask[howmany(AF_MAX, NBBY)]; 386 387 memset(afmask, 0, sizeof(afmask)); 388 for (afp = afs; afp != NULL; afp = afp->af_next) { 389 if (afp->af_other_status == NULL) 390 continue; 391 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 392 continue; 393 afp->af_other_status(s); 394 setbit(afmask, afp->af_af); 395 } 396 } 397 398 static void 399 af_all_tunnel_status(int s) 400 { 401 struct afswtch *afp; 402 uint8_t afmask[howmany(AF_MAX, NBBY)]; 403 404 memset(afmask, 0, sizeof(afmask)); 405 for (afp = afs; afp != NULL; afp = afp->af_next) { 406 if (afp->af_status_tunnel == NULL) 407 continue; 408 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 409 continue; 410 afp->af_status_tunnel(s); 411 setbit(afmask, afp->af_af); 412 } 413 } 414 415 static struct cmd *cmds = NULL; 416 417 void 418 cmd_register(struct cmd *p) 419 { 420 p->c_next = cmds; 421 cmds = p; 422 } 423 424 static const struct cmd * 425 cmd_lookup(const char *name, int iscreate) 426 { 427 #define N(a) (sizeof(a)/sizeof(a[0])) 428 const struct cmd *p; 429 430 for (p = cmds; p != NULL; p = p->c_next) 431 if (strcmp(name, p->c_name) == 0) { 432 if (iscreate) { 433 if (p->c_iscloneop) 434 return p; 435 } else { 436 if (!p->c_iscloneop) 437 return p; 438 } 439 } 440 return NULL; 441 #undef N 442 } 443 444 struct callback { 445 callback_func *cb_func; 446 void *cb_arg; 447 struct callback *cb_next; 448 }; 449 static struct callback *callbacks = NULL; 450 451 void 452 callback_register(callback_func *func, void *arg) 453 { 454 struct callback *cb; 455 456 cb = malloc(sizeof(struct callback)); 457 if (cb == NULL) 458 errx(1, "unable to allocate memory for callback"); 459 cb->cb_func = func; 460 cb->cb_arg = arg; 461 cb->cb_next = callbacks; 462 callbacks = cb; 463 } 464 465 /* specially-handled commands */ 466 static void setifaddr(const char *, int, int, const struct afswtch *); 467 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); 468 469 static void setifdstaddr(const char *, int, int, const struct afswtch *); 470 static const struct cmd setifdstaddr_cmd = 471 DEF_CMD("ifdstaddr", 0, setifdstaddr); 472 473 static int 474 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp) 475 { 476 const struct afswtch *afp, *nafp; 477 const struct cmd *p; 478 struct callback *cb; 479 int s; 480 481 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 482 afp = uafp != NULL ? uafp : af_getbyname("inet"); 483 top: 484 ifr.ifr_addr.sa_family = 485 afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? 486 AF_LOCAL : afp->af_af; 487 488 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 && 489 (uafp != NULL || errno != EPROTONOSUPPORT || 490 (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) 491 err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); 492 493 while (argc > 0) { 494 p = cmd_lookup(*argv, iscreate); 495 if (iscreate && p == NULL) { 496 /* 497 * Push the clone create callback so the new 498 * device is created and can be used for any 499 * remaining arguments. 500 */ 501 cb = callbacks; 502 if (cb == NULL) 503 errx(1, "internal error, no callback"); 504 callbacks = cb->cb_next; 505 cb->cb_func(s, cb->cb_arg); 506 iscreate = 0; 507 /* 508 * Handle any address family spec that 509 * immediately follows and potentially 510 * recreate the socket. 511 */ 512 nafp = af_getbyname(*argv); 513 if (nafp != NULL) { 514 argc--, argv++; 515 if (nafp != afp) { 516 close(s); 517 afp = nafp; 518 goto top; 519 } 520 } 521 /* 522 * Look for a normal parameter. 523 */ 524 continue; 525 } 526 if (p == NULL) { 527 /* 528 * Not a recognized command, choose between setting 529 * the interface address and the dst address. 530 */ 531 p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); 532 } 533 if (p->c_u.c_func || p->c_u.c_func2) { 534 if (p->c_parameter == NEXTARG) { 535 if (argv[1] == NULL) 536 errx(1, "'%s' requires argument", 537 p->c_name); 538 p->c_u.c_func(argv[1], 0, s, afp); 539 argc--, argv++; 540 } else if (p->c_parameter == OPTARG) { 541 p->c_u.c_func(argv[1], 0, s, afp); 542 if (argv[1] != NULL) 543 argc--, argv++; 544 } else if (p->c_parameter == NEXTARG2) { 545 if (argc < 3) 546 errx(1, "'%s' requires 2 arguments", 547 p->c_name); 548 p->c_u.c_func2(argv[1], argv[2], s, afp); 549 argc -= 2, argv += 2; 550 } else 551 p->c_u.c_func(*argv, p->c_parameter, s, afp); 552 } 553 argc--, argv++; 554 } 555 556 /* 557 * Do any post argument processing required by the address family. 558 */ 559 if (afp->af_postproc != NULL) 560 afp->af_postproc(s, afp); 561 /* 562 * Do deferred callbacks registered while processing 563 * command-line arguments. 564 */ 565 for (cb = callbacks; cb != NULL; cb = cb->cb_next) 566 cb->cb_func(s, cb->cb_arg); 567 /* 568 * Do deferred operations. 569 */ 570 if (clearaddr) { 571 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 572 warnx("interface %s cannot change %s addresses!", 573 name, afp->af_name); 574 clearaddr = 0; 575 } 576 } 577 if (clearaddr) { 578 int ret; 579 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 580 ret = ioctl(s, afp->af_difaddr, afp->af_ridreq); 581 if (ret < 0) { 582 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 583 /* means no previous address for interface */ 584 } else 585 Perror("ioctl (SIOCDIFADDR)"); 586 } 587 } 588 if (newaddr) { 589 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 590 warnx("interface %s cannot change %s addresses!", 591 name, afp->af_name); 592 newaddr = 0; 593 } 594 } 595 if (newaddr && (setaddr || setmask)) { 596 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 597 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 598 Perror("ioctl (SIOCAIFADDR)"); 599 } 600 601 close(s); 602 return(0); 603 } 604 605 /*ARGSUSED*/ 606 static void 607 setifaddr(const char *addr, int param, int s, const struct afswtch *afp) 608 { 609 if (afp->af_getaddr == NULL) 610 return; 611 /* 612 * Delay the ioctl to set the interface addr until flags are all set. 613 * The address interpretation may depend on the flags, 614 * and the flags may change when the address is set. 615 */ 616 setaddr++; 617 if (doalias == 0 && afp->af_af != AF_LINK) 618 clearaddr = 1; 619 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); 620 } 621 622 static void 623 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) 624 { 625 struct addrinfo *srcres, *dstres; 626 int ecode; 627 628 if (afp->af_settunnel == NULL) { 629 warn("address family %s does not support tunnel setup", 630 afp->af_name); 631 return; 632 } 633 634 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 635 errx(1, "error in parsing address string: %s", 636 gai_strerror(ecode)); 637 638 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 639 errx(1, "error in parsing address string: %s", 640 gai_strerror(ecode)); 641 642 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 643 errx(1, 644 "source and destination address families do not match"); 645 646 afp->af_settunnel(s, srcres, dstres); 647 648 freeaddrinfo(srcres); 649 freeaddrinfo(dstres); 650 } 651 652 /* ARGSUSED */ 653 static void 654 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) 655 { 656 657 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 658 err(1, "SIOCDIFPHYADDR"); 659 } 660 661 static void 662 setifvnet(const char *jname, int dummy __unused, int s, 663 const struct afswtch *afp) 664 { 665 struct ifreq my_ifr; 666 667 memcpy(&my_ifr, &ifr, sizeof(my_ifr)); 668 my_ifr.ifr_jid = jail_getid(jname); 669 if (my_ifr.ifr_jid < 0) 670 errx(1, "%s", jail_errmsg); 671 if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0) 672 err(1, "SIOCSIFVNET"); 673 } 674 675 static void 676 setifrvnet(const char *jname, int dummy __unused, int s, 677 const struct afswtch *afp) 678 { 679 struct ifreq my_ifr; 680 681 memcpy(&my_ifr, &ifr, sizeof(my_ifr)); 682 my_ifr.ifr_jid = jail_getid(jname); 683 if (my_ifr.ifr_jid < 0) 684 errx(1, "%s", jail_errmsg); 685 if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0) 686 err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name); 687 } 688 689 static void 690 setifnetmask(const char *addr, int dummy __unused, int s, 691 const struct afswtch *afp) 692 { 693 if (afp->af_getaddr != NULL) { 694 setmask++; 695 afp->af_getaddr(addr, MASK); 696 } 697 } 698 699 static void 700 setifbroadaddr(const char *addr, int dummy __unused, int s, 701 const struct afswtch *afp) 702 { 703 if (afp->af_getaddr != NULL) 704 afp->af_getaddr(addr, DSTADDR); 705 } 706 707 static void 708 setifipdst(const char *addr, int dummy __unused, int s, 709 const struct afswtch *afp) 710 { 711 const struct afswtch *inet; 712 713 inet = af_getbyname("inet"); 714 if (inet == NULL) 715 return; 716 inet->af_getaddr(addr, DSTADDR); 717 clearaddr = 0; 718 newaddr = 0; 719 } 720 721 static void 722 notealias(const char *addr, int param, int s, const struct afswtch *afp) 723 { 724 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 725 if (setaddr && doalias == 0 && param < 0) 726 if (afp->af_addreq != NULL && afp->af_ridreq != NULL) 727 bcopy((caddr_t)rqtosa(af_addreq), 728 (caddr_t)rqtosa(af_ridreq), 729 rqtosa(af_addreq)->sa_len); 730 doalias = param; 731 if (param < 0) { 732 clearaddr = 1; 733 newaddr = 0; 734 } else 735 clearaddr = 0; 736 #undef rqtosa 737 } 738 739 /*ARGSUSED*/ 740 static void 741 setifdstaddr(const char *addr, int param __unused, int s, 742 const struct afswtch *afp) 743 { 744 if (afp->af_getaddr != NULL) 745 afp->af_getaddr(addr, DSTADDR); 746 } 747 748 /* 749 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 750 * of the ifreq structure, which may confuse other parts of ifconfig. 751 * Make a private copy so we can avoid that. 752 */ 753 static void 754 setifflags(const char *vname, int value, int s, const struct afswtch *afp) 755 { 756 struct ifreq my_ifr; 757 int flags; 758 759 memset(&my_ifr, 0, sizeof(my_ifr)); 760 (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); 761 762 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 763 Perror("ioctl (SIOCGIFFLAGS)"); 764 exit(1); 765 } 766 flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16); 767 768 if (value < 0) { 769 value = -value; 770 flags &= ~value; 771 } else 772 flags |= value; 773 my_ifr.ifr_flags = flags & 0xffff; 774 my_ifr.ifr_flagshigh = flags >> 16; 775 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 776 Perror(vname); 777 } 778 779 void 780 setifcap(const char *vname, int value, int s, const struct afswtch *afp) 781 { 782 int flags; 783 784 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 785 Perror("ioctl (SIOCGIFCAP)"); 786 exit(1); 787 } 788 flags = ifr.ifr_curcap; 789 if (value < 0) { 790 value = -value; 791 flags &= ~value; 792 } else 793 flags |= value; 794 flags &= ifr.ifr_reqcap; 795 ifr.ifr_reqcap = flags; 796 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 797 Perror(vname); 798 } 799 800 static void 801 setifmetric(const char *val, int dummy __unused, int s, 802 const struct afswtch *afp) 803 { 804 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 805 ifr.ifr_metric = atoi(val); 806 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 807 warn("ioctl (set metric)"); 808 } 809 810 static void 811 setifmtu(const char *val, int dummy __unused, int s, 812 const struct afswtch *afp) 813 { 814 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 815 ifr.ifr_mtu = atoi(val); 816 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 817 warn("ioctl (set mtu)"); 818 } 819 820 static void 821 setifname(const char *val, int dummy __unused, int s, 822 const struct afswtch *afp) 823 { 824 char *newname; 825 826 newname = strdup(val); 827 if (newname == NULL) { 828 warn("no memory to set ifname"); 829 return; 830 } 831 ifr.ifr_data = newname; 832 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { 833 warn("ioctl (set name)"); 834 free(newname); 835 return; 836 } 837 strlcpy(name, newname, sizeof(name)); 838 free(newname); 839 } 840 841 #define IFFBITS \ 842 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 843 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 844 "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP" 845 846 #define IFCAPBITS \ 847 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ 848 "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \ 849 "\21VLAN_HWFILTER" 850 851 /* 852 * Print the status of the interface. If an address family was 853 * specified, show only it; otherwise, show them all. 854 */ 855 static void 856 status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 857 struct ifaddrs *ifa) 858 { 859 struct ifaddrs *ift; 860 int allfamilies, s; 861 struct ifstat ifs; 862 863 if (afp == NULL) { 864 allfamilies = 1; 865 ifr.ifr_addr.sa_family = AF_LOCAL; 866 } else { 867 allfamilies = 0; 868 ifr.ifr_addr.sa_family = 869 afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af; 870 } 871 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 872 873 s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); 874 if (s < 0) 875 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); 876 877 printf("%s: ", name); 878 printb("flags", ifa->ifa_flags, IFFBITS); 879 if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) 880 printf(" metric %d", ifr.ifr_metric); 881 if (ioctl(s, SIOCGIFMTU, &ifr) != -1) 882 printf(" mtu %d", ifr.ifr_mtu); 883 putchar('\n'); 884 885 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { 886 if (ifr.ifr_curcap != 0) { 887 printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 888 putchar('\n'); 889 } 890 if (supmedia && ifr.ifr_reqcap != 0) { 891 printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS); 892 putchar('\n'); 893 } 894 } 895 896 tunnel_status(s); 897 898 for (ift = ifa; ift != NULL; ift = ift->ifa_next) { 899 if (ift->ifa_addr == NULL) 900 continue; 901 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) 902 continue; 903 if (allfamilies) { 904 const struct afswtch *p; 905 p = af_getbyfamily(ift->ifa_addr->sa_family); 906 if (p != NULL && p->af_status != NULL) 907 p->af_status(s, ift); 908 } else if (afp->af_af == ift->ifa_addr->sa_family) 909 afp->af_status(s, ift); 910 } 911 #if 0 912 if (allfamilies || afp->af_af == AF_LINK) { 913 const struct afswtch *lafp; 914 915 /* 916 * Hack; the link level address is received separately 917 * from the routing information so any address is not 918 * handled above. Cobble together an entry and invoke 919 * the status method specially. 920 */ 921 lafp = af_getbyname("lladdr"); 922 if (lafp != NULL) { 923 info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl; 924 lafp->af_status(s, &info); 925 } 926 } 927 #endif 928 if (allfamilies) 929 af_other_status(s); 930 else if (afp->af_other_status != NULL) 931 afp->af_other_status(s); 932 933 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 934 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 935 printf("%s", ifs.ascii); 936 937 close(s); 938 return; 939 } 940 941 static void 942 tunnel_status(int s) 943 { 944 af_all_tunnel_status(s); 945 } 946 947 void 948 Perror(const char *cmd) 949 { 950 switch (errno) { 951 952 case ENXIO: 953 errx(1, "%s: no such interface", cmd); 954 break; 955 956 case EPERM: 957 errx(1, "%s: permission denied", cmd); 958 break; 959 960 default: 961 err(1, "%s", cmd); 962 } 963 } 964 965 /* 966 * Print a value a la the %b format of the kernel's printf 967 */ 968 void 969 printb(const char *s, unsigned v, const char *bits) 970 { 971 int i, any = 0; 972 char c; 973 974 if (bits && *bits == 8) 975 printf("%s=%o", s, v); 976 else 977 printf("%s=%x", s, v); 978 bits++; 979 if (bits) { 980 putchar('<'); 981 while ((i = *bits++) != '\0') { 982 if (v & (1 << (i-1))) { 983 if (any) 984 putchar(','); 985 any = 1; 986 for (; (c = *bits) > 32; bits++) 987 putchar(c); 988 } else 989 for (; *bits > 32; bits++) 990 ; 991 } 992 putchar('>'); 993 } 994 } 995 996 void 997 ifmaybeload(const char *name) 998 { 999 #define MOD_PREFIX_LEN 3 /* "if_" */ 1000 struct module_stat mstat; 1001 int fileid, modid; 1002 char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; 1003 const char *cp; 1004 1005 /* loading suppressed by the user */ 1006 if (noload) 1007 return; 1008 1009 /* trim the interface number off the end */ 1010 strlcpy(ifname, name, sizeof(ifname)); 1011 for (dp = ifname; *dp != 0; dp++) 1012 if (isdigit(*dp)) { 1013 *dp = 0; 1014 break; 1015 } 1016 1017 /* turn interface and unit into module name */ 1018 strcpy(ifkind, "if_"); 1019 strlcpy(ifkind + MOD_PREFIX_LEN, ifname, 1020 sizeof(ifkind) - MOD_PREFIX_LEN); 1021 1022 /* scan files in kernel */ 1023 mstat.version = sizeof(struct module_stat); 1024 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1025 /* scan modules in file */ 1026 for (modid = kldfirstmod(fileid); modid > 0; 1027 modid = modfnext(modid)) { 1028 if (modstat(modid, &mstat) < 0) 1029 continue; 1030 /* strip bus name if present */ 1031 if ((cp = strchr(mstat.name, '/')) != NULL) { 1032 cp++; 1033 } else { 1034 cp = mstat.name; 1035 } 1036 /* already loaded? */ 1037 if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 || 1038 strncmp(ifkind, cp, strlen(ifkind) + 1) == 0) 1039 return; 1040 } 1041 } 1042 1043 /* not present, we should try to load it */ 1044 kldload(ifkind); 1045 } 1046 1047 static struct cmd basic_cmds[] = { 1048 DEF_CMD("up", IFF_UP, setifflags), 1049 DEF_CMD("down", -IFF_UP, setifflags), 1050 DEF_CMD("arp", -IFF_NOARP, setifflags), 1051 DEF_CMD("-arp", IFF_NOARP, setifflags), 1052 DEF_CMD("debug", IFF_DEBUG, setifflags), 1053 DEF_CMD("-debug", -IFF_DEBUG, setifflags), 1054 DEF_CMD("promisc", IFF_PPROMISC, setifflags), 1055 DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), 1056 DEF_CMD("add", IFF_UP, notealias), 1057 DEF_CMD("alias", IFF_UP, notealias), 1058 DEF_CMD("-alias", -IFF_UP, notealias), 1059 DEF_CMD("delete", -IFF_UP, notealias), 1060 DEF_CMD("remove", -IFF_UP, notealias), 1061 #ifdef notdef 1062 #define EN_SWABIPS 0x1000 1063 DEF_CMD("swabips", EN_SWABIPS, setifflags), 1064 DEF_CMD("-swabips", -EN_SWABIPS, setifflags), 1065 #endif 1066 DEF_CMD_ARG("netmask", setifnetmask), 1067 DEF_CMD_ARG("metric", setifmetric), 1068 DEF_CMD_ARG("broadcast", setifbroadaddr), 1069 DEF_CMD_ARG("ipdst", setifipdst), 1070 DEF_CMD_ARG2("tunnel", settunnel), 1071 DEF_CMD("-tunnel", 0, deletetunnel), 1072 DEF_CMD("deletetunnel", 0, deletetunnel), 1073 DEF_CMD_ARG("vnet", setifvnet), 1074 DEF_CMD_ARG("-vnet", setifrvnet), 1075 DEF_CMD("link0", IFF_LINK0, setifflags), 1076 DEF_CMD("-link0", -IFF_LINK0, setifflags), 1077 DEF_CMD("link1", IFF_LINK1, setifflags), 1078 DEF_CMD("-link1", -IFF_LINK1, setifflags), 1079 DEF_CMD("link2", IFF_LINK2, setifflags), 1080 DEF_CMD("-link2", -IFF_LINK2, setifflags), 1081 DEF_CMD("monitor", IFF_MONITOR, setifflags), 1082 DEF_CMD("-monitor", -IFF_MONITOR, setifflags), 1083 DEF_CMD("staticarp", IFF_STATICARP, setifflags), 1084 DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), 1085 DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), 1086 DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), 1087 DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), 1088 DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), 1089 DEF_CMD("netcons", IFCAP_NETCONS, setifcap), 1090 DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), 1091 DEF_CMD("polling", IFCAP_POLLING, setifcap), 1092 DEF_CMD("-polling", -IFCAP_POLLING, setifcap), 1093 DEF_CMD("tso", IFCAP_TSO, setifcap), 1094 DEF_CMD("-tso", -IFCAP_TSO, setifcap), 1095 DEF_CMD("lro", IFCAP_LRO, setifcap), 1096 DEF_CMD("-lro", -IFCAP_LRO, setifcap), 1097 DEF_CMD("wol", IFCAP_WOL, setifcap), 1098 DEF_CMD("-wol", -IFCAP_WOL, setifcap), 1099 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), 1100 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), 1101 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), 1102 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), 1103 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), 1104 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), 1105 DEF_CMD("normal", -IFF_LINK0, setifflags), 1106 DEF_CMD("compress", IFF_LINK0, setifflags), 1107 DEF_CMD("noicmp", IFF_LINK1, setifflags), 1108 DEF_CMD_ARG("mtu", setifmtu), 1109 DEF_CMD_ARG("name", setifname), 1110 }; 1111 1112 static __constructor void 1113 ifconfig_ctor(void) 1114 { 1115 #define N(a) (sizeof(a) / sizeof(a[0])) 1116 size_t i; 1117 1118 for (i = 0; i < N(basic_cmds); i++) 1119 cmd_register(&basic_cmds[i]); 1120 #undef N 1121 } 1122