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