1/* 2 * Copyright (c) 2009-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * Copyright (c) 1983, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 4. Neither the name of the University nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58#include <sys/cdefs.h> 59 60#ifndef lint 61__unused static const char copyright[] = 62"@(#) Copyright (c) 1983, 1993\n\ 63 The Regents of the University of California. All rights reserved.\n"; 64#endif /* not lint */ 65 66#include <sys/param.h> 67#include <sys/ioctl.h> 68#include <sys/socket.h> 69#include <sys/sysctl.h> 70#include <sys/time.h> 71#ifndef __APPLE__ 72#include <sys/module.h> 73#include <sys/linker.h> 74#endif 75 76#include <net/ethernet.h> 77#include <net/if.h> 78#include <net/if_var.h> 79#include <net/if_dl.h> 80#include <net/if_types.h> 81#include <net/if_mib.h> 82#include <net/route.h> 83#include <net/pktsched/pktsched.h> 84 85/* IP */ 86#include <netinet/in.h> 87#include <netinet/in_var.h> 88#include <arpa/inet.h> 89#include <netdb.h> 90 91#include <ifaddrs.h> 92#include <ctype.h> 93#include <err.h> 94#include <errno.h> 95#include <fcntl.h> 96#include <stdio.h> 97#include <stdlib.h> 98#include <string.h> 99#include <unistd.h> 100 101#include "ifconfig.h" 102 103/* 104 * Since "struct ifreq" is composed of various union members, callers 105 * should pay special attention to interprete the value. 106 * (.e.g. little/big endian difference in the structure.) 107 */ 108struct ifreq ifr; 109 110char name[IFNAMSIZ]; 111int setaddr; 112int setmask; 113int doalias; 114int clearaddr; 115int newaddr = 1; 116int noload; 117int all; 118 119int bond_details = 0; 120int supmedia = 0; 121#if TARGET_OS_EMBEDDED 122int verbose = 1; 123int showrtref = 1; 124#else /* !TARGET_OS_EMBEDDED */ 125int verbose = 0; 126int showrtref = 0; 127#endif /* !TARGET_OS_EMBEDDED */ 128int printkeys = 0; /* Print keying material for interfaces. */ 129 130static int ifconfig(int argc, char *const *argv, int iscreate, 131 const struct afswtch *afp); 132static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 133 struct ifaddrs *ifa); 134static char *bytes_to_str(unsigned long long bytes); 135static char *bps_to_str(unsigned long long rate); 136static char *ns_to_str(unsigned long long nsec); 137static void tunnel_status(int s); 138static void usage(void); 139static char *sched2str(unsigned int s); 140static char *tl2str(unsigned int s); 141static char *ift2str(unsigned int t, unsigned int f, unsigned int sf); 142 143static struct afswtch *af_getbyname(const char *name); 144static struct afswtch *af_getbyfamily(int af); 145static void af_other_status(int); 146 147static struct option *opts = NULL; 148 149void 150opt_register(struct option *p) 151{ 152 p->next = opts; 153 opts = p; 154} 155 156static void 157usage(void) 158{ 159 char options[1024]; 160 struct option *p; 161 162 /* XXX not right but close enough for now */ 163 options[0] = '\0'; 164 for (p = opts; p != NULL; p = p->next) { 165 strlcat(options, p->opt_usage, sizeof(options)); 166 strlcat(options, " ", sizeof(options)); 167 } 168 169 fprintf(stderr, 170 "usage: ifconfig %sinterface address_family [address [dest_address]]\n" 171 " [parameters]\n" 172 " ifconfig interface create\n" 173 " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n" 174 " ifconfig -l [-d] [-u] [address_family]\n" 175 " ifconfig %s[-d] [-m] [-u] [-v]\n", 176 options, options, options); 177 exit(1); 178} 179 180int 181main(int argc, char *argv[]) 182{ 183 int c, namesonly, downonly, uponly; 184 const struct afswtch *afp = NULL; 185 int ifindex; 186 struct ifaddrs *ifap, *ifa; 187 struct ifreq paifr; 188 const struct sockaddr_dl *sdl; 189 char options[1024], *cp; 190 const char *ifname; 191 struct option *p; 192 size_t iflen; 193 194 all = downonly = uponly = namesonly = noload = 0; 195 196 /* Parse leading line options */ 197#ifndef __APPLE__ 198 strlcpy(options, "adklmnuv", sizeof(options)); 199#else 200 strlcpy(options, "abdlmruv", sizeof(options)); 201#endif 202 for (p = opts; p != NULL; p = p->next) 203 strlcat(options, p->opt, sizeof(options)); 204 while ((c = getopt(argc, argv, options)) != -1) { 205 switch (c) { 206 case 'a': /* scan all interfaces */ 207 all++; 208 break; 209 case 'b': /* bond detailed output */ 210 bond_details++; 211 break; 212 case 'd': /* restrict scan to "down" interfaces */ 213 downonly++; 214 break; 215#ifndef __APPLE__ 216 case 'k': 217 printkeys++; 218 break; 219#endif 220 case 'l': /* scan interface names only */ 221 namesonly++; 222 break; 223 case 'm': /* show media choices in status */ 224 supmedia = 1; 225 break; 226#ifndef __APPLE__ 227 case 'n': /* suppress module loading */ 228 noload++; 229 break; 230#endif 231 case 'r': 232 showrtref++; 233 break; 234 case 'u': /* restrict scan to "up" interfaces */ 235 uponly++; 236 break; 237 case 'v': 238 verbose++; 239 break; 240 default: 241 for (p = opts; p != NULL; p = p->next) 242 if (p->opt[0] == c) { 243 p->cb(optarg); 244 break; 245 } 246 if (p == NULL) 247 usage(); 248 break; 249 } 250 } 251 argc -= optind; 252 argv += optind; 253 254 /* -l cannot be used with -a or -q or -m or -b */ 255 if (namesonly && 256 (all || supmedia || bond_details)) 257 usage(); 258 259 /* nonsense.. */ 260 if (uponly && downonly) 261 usage(); 262 263 /* no arguments is equivalent to '-a' */ 264 if (!namesonly && argc < 1) 265 all = 1; 266 267 /* -a and -l allow an address family arg to limit the output */ 268 if (all || namesonly) { 269 if (argc > 1) 270 usage(); 271 272 ifname = NULL; 273 ifindex = 0; 274 if (argc == 1) { 275 afp = af_getbyname(*argv); 276 if (afp == NULL) 277 usage(); 278 if (afp->af_name != NULL) 279 argc--, argv++; 280 /* leave with afp non-zero */ 281 } 282 } else { 283 /* not listing, need an argument */ 284 if (argc < 1) 285 usage(); 286 287 ifname = *argv; 288 argc--, argv++; 289 290#ifdef notdef 291 /* check and maybe load support for this interface */ 292 ifmaybeload(ifname); 293#endif 294 ifindex = if_nametoindex(ifname); 295 if (ifindex == 0) { 296 /* 297 * NOTE: We must special-case the `create' command 298 * right here as we would otherwise fail when trying 299 * to find the interface. 300 */ 301 if (argc > 0 && (strcmp(argv[0], "create") == 0 || 302 strcmp(argv[0], "plumb") == 0)) { 303 iflen = strlcpy(name, ifname, sizeof(name)); 304 if (iflen >= sizeof(name)) 305 errx(1, "%s: cloning name too long", 306 ifname); 307 ifconfig(argc, argv, 1, NULL); 308 exit(0); 309 } 310 errx(1, "interface %s does not exist", ifname); 311 } 312 } 313 314 /* Check for address family */ 315 if (argc > 0) { 316 afp = af_getbyname(*argv); 317 if (afp != NULL) 318 argc--, argv++; 319 } 320 321 if (getifaddrs(&ifap) != 0) 322 err(EXIT_FAILURE, "getifaddrs"); 323 cp = NULL; 324 ifindex = 0; 325 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 326 memset(&paifr, 0, sizeof(paifr)); 327 strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 328 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 329 memcpy(&paifr.ifr_addr, ifa->ifa_addr, 330 ifa->ifa_addr->sa_len); 331 } 332 333 if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) 334 continue; 335 if (ifa->ifa_addr->sa_family == AF_LINK) 336 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 337 else 338 sdl = NULL; 339 if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0) 340 continue; 341 iflen = strlcpy(name, ifa->ifa_name, sizeof(name)); 342 if (iflen >= sizeof(name)) { 343 warnx("%s: interface name too long, skipping", 344 ifa->ifa_name); 345 continue; 346 } 347 cp = ifa->ifa_name; 348 349 if (downonly && (ifa->ifa_flags & IFF_UP) != 0) 350 continue; 351 if (uponly && (ifa->ifa_flags & IFF_UP) == 0) 352 continue; 353 ifindex++; 354 /* 355 * Are we just listing the interfaces? 356 */ 357 if (namesonly) { 358 if (ifindex > 1) 359 printf(" "); 360 fputs(name, stdout); 361 continue; 362 } 363 364 if (argc > 0) 365 ifconfig(argc, argv, 0, afp); 366 else 367 status(afp, sdl, ifa); 368 } 369 if (namesonly) 370 printf("\n"); 371 freeifaddrs(ifap); 372 373 exit(0); 374} 375 376static struct afswtch *afs = NULL; 377 378void 379af_register(struct afswtch *p) 380{ 381 p->af_next = afs; 382 afs = p; 383} 384 385static struct afswtch * 386af_getbyname(const char *name) 387{ 388 struct afswtch *afp; 389 390 for (afp = afs; afp != NULL; afp = afp->af_next) 391 if (strcmp(afp->af_name, name) == 0) 392 return afp; 393 return NULL; 394} 395 396static struct afswtch * 397af_getbyfamily(int af) 398{ 399 struct afswtch *afp; 400 401 for (afp = afs; afp != NULL; afp = afp->af_next) 402 if (afp->af_af == af) 403 return afp; 404 return NULL; 405} 406 407static void 408af_other_status(int s) 409{ 410 struct afswtch *afp; 411 uint8_t afmask[howmany(AF_MAX, NBBY)]; 412 413 memset(afmask, 0, sizeof(afmask)); 414 for (afp = afs; afp != NULL; afp = afp->af_next) { 415 if (afp->af_other_status == NULL) 416 continue; 417 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 418 continue; 419 afp->af_other_status(s); 420 setbit(afmask, afp->af_af); 421 } 422} 423 424static void 425af_all_tunnel_status(int s) 426{ 427 struct afswtch *afp; 428 uint8_t afmask[howmany(AF_MAX, NBBY)]; 429 430 memset(afmask, 0, sizeof(afmask)); 431 for (afp = afs; afp != NULL; afp = afp->af_next) { 432 if (afp->af_status_tunnel == NULL) 433 continue; 434 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 435 continue; 436 afp->af_status_tunnel(s); 437 setbit(afmask, afp->af_af); 438 } 439} 440 441static struct cmd *cmds = NULL; 442 443void 444cmd_register(struct cmd *p) 445{ 446 p->c_next = cmds; 447 cmds = p; 448} 449 450static const struct cmd * 451cmd_lookup(const char *name) 452{ 453#define N(a) (sizeof(a)/sizeof(a[0])) 454 const struct cmd *p; 455 456 for (p = cmds; p != NULL; p = p->c_next) 457 if (strcmp(name, p->c_name) == 0) 458 return p; 459 return NULL; 460#undef N 461} 462 463struct callback { 464 callback_func *cb_func; 465 void *cb_arg; 466 struct callback *cb_next; 467}; 468static struct callback *callbacks = NULL; 469 470void 471callback_register(callback_func *func, void *arg) 472{ 473 struct callback *cb; 474 475 cb = malloc(sizeof(struct callback)); 476 if (cb == NULL) 477 errx(1, "unable to allocate memory for callback"); 478 cb->cb_func = func; 479 cb->cb_arg = arg; 480 cb->cb_next = callbacks; 481 callbacks = cb; 482} 483 484/* specially-handled commands */ 485static void setifaddr(const char *, int, int, const struct afswtch *); 486static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); 487 488static void setifdstaddr(const char *, int, int, const struct afswtch *); 489static const struct cmd setifdstaddr_cmd = 490 DEF_CMD("ifdstaddr", 0, setifdstaddr); 491 492static int 493ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp) 494{ 495 const struct afswtch *nafp; 496 struct callback *cb; 497 int s; 498 499 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 500top: 501 if (afp == NULL) 502 afp = af_getbyname("inet"); 503 ifr.ifr_addr.sa_family = 504 afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? 505 AF_INET : afp->af_af; 506 507 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 508 err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); 509 510 while (argc > 0) { 511 const struct cmd *p; 512 513 p = cmd_lookup(*argv); 514 if (p == NULL) { 515 /* 516 * Not a recognized command, choose between setting 517 * the interface address and the dst address. 518 */ 519 p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); 520 } 521 if (p->c_u.c_func || p->c_u.c_func2) { 522 if (iscreate && !p->c_iscloneop) { 523 /* 524 * Push the clone create callback so the new 525 * device is created and can be used for any 526 * remaining arguments. 527 */ 528 cb = callbacks; 529 if (cb == NULL) 530 errx(1, "internal error, no callback"); 531 callbacks = cb->cb_next; 532 cb->cb_func(s, cb->cb_arg); 533 iscreate = 0; 534 /* 535 * Handle any address family spec that 536 * immediately follows and potentially 537 * recreate the socket. 538 */ 539 nafp = af_getbyname(*argv); 540 if (nafp != NULL) { 541 argc--, argv++; 542 if (nafp != afp) { 543 close(s); 544 afp = nafp; 545 goto top; 546 } 547 } 548 } 549 if (p->c_parameter == NEXTARG) { 550 if (argv[1] == NULL) 551 errx(1, "'%s' requires argument", 552 p->c_name); 553 p->c_u.c_func(argv[1], 0, s, afp); 554 argc--, argv++; 555 } else if (p->c_parameter == OPTARG) { 556 p->c_u.c_func(argv[1], 0, s, afp); 557 if (argv[1] != NULL) 558 argc--, argv++; 559 } else if (p->c_parameter == NEXTARG2) { 560 if (argc < 3) 561 errx(1, "'%s' requires 2 arguments", 562 p->c_name); 563 p->c_u.c_func2(argv[1], argv[2], s, afp); 564 argc -= 2, argv += 2; 565 } else 566 p->c_u.c_func(*argv, p->c_parameter, s, afp); 567 } 568 argc--, argv++; 569 } 570 571 /* 572 * Do any post argument processing required by the address family. 573 */ 574 if (afp->af_postproc != NULL) 575 afp->af_postproc(s, afp); 576 /* 577 * Do deferred callbacks registered while processing 578 * command-line arguments. 579 */ 580 for (cb = callbacks; cb != NULL; cb = cb->cb_next) 581 cb->cb_func(s, cb->cb_arg); 582 /* 583 * Do deferred operations. 584 */ 585 if (clearaddr) { 586 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 587 warnx("interface %s cannot change %s addresses!", 588 name, afp->af_name); 589 clearaddr = 0; 590 } 591 } 592 if (clearaddr) { 593 int ret; 594 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 595 ret = ioctl(s, afp->af_difaddr, afp->af_ridreq); 596 if (ret < 0) { 597 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 598 /* means no previous address for interface */ 599 } else 600 Perror("ioctl (SIOCDIFADDR)"); 601 } 602 } 603 if (newaddr) { 604 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 605 warnx("interface %s cannot change %s addresses!", 606 name, afp->af_name); 607 newaddr = 0; 608 } 609 } 610 if (newaddr && (setaddr || setmask)) { 611 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 612 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 613 Perror("ioctl (SIOCAIFADDR)"); 614 } 615 616 close(s); 617 return(0); 618} 619 620/*ARGSUSED*/ 621static void 622setifaddr(const char *addr, int param, int s, const struct afswtch *afp) 623{ 624 if (afp->af_getaddr == NULL) 625 return; 626 /* 627 * Delay the ioctl to set the interface addr until flags are all set. 628 * The address interpretation may depend on the flags, 629 * and the flags may change when the address is set. 630 */ 631 setaddr++; 632 if (doalias == 0 && afp->af_af != AF_LINK) 633 clearaddr = 1; 634 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); 635} 636 637static void 638settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) 639{ 640 struct addrinfo *srcres, *dstres; 641 int ecode; 642 643 if (afp->af_settunnel == NULL) { 644 warn("address family %s does not support tunnel setup", 645 afp->af_name); 646 return; 647 } 648 649 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 650 errx(1, "error in parsing address string: %s", 651 gai_strerror(ecode)); 652 653 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 654 errx(1, "error in parsing address string: %s", 655 gai_strerror(ecode)); 656 657 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 658 errx(1, 659 "source and destination address families do not match"); 660 661 afp->af_settunnel(s, srcres, dstres); 662 663 freeaddrinfo(srcres); 664 freeaddrinfo(dstres); 665} 666 667/* ARGSUSED */ 668static void 669deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) 670{ 671 672 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 673 err(1, "SIOCDIFPHYADDR"); 674} 675 676static void 677setifnetmask(const char *addr, int dummy __unused, int s, 678 const struct afswtch *afp) 679{ 680 if (afp->af_getaddr != NULL) { 681 setmask++; 682 afp->af_getaddr(addr, MASK); 683 } 684} 685 686static void 687setifbroadaddr(const char *addr, int dummy __unused, int s, 688 const struct afswtch *afp) 689{ 690 if (afp->af_getaddr != NULL) 691 afp->af_getaddr(addr, DSTADDR); 692} 693 694static void 695setifipdst(const char *addr, int dummy __unused, int s, 696 const struct afswtch *afp) 697{ 698 const struct afswtch *inet; 699 700 inet = af_getbyname("inet"); 701 if (inet == NULL) 702 return; 703 inet->af_getaddr(addr, DSTADDR); 704 clearaddr = 0; 705 newaddr = 0; 706} 707 708static void 709notealias(const char *addr, int param, int s, const struct afswtch *afp) 710{ 711#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 712 if (setaddr && doalias == 0 && param < 0) 713 if (afp->af_addreq != NULL && afp->af_ridreq != NULL) 714 bcopy((caddr_t)rqtosa(af_addreq), 715 (caddr_t)rqtosa(af_ridreq), 716 rqtosa(af_addreq)->sa_len); 717 doalias = param; 718 if (param < 0) { 719 clearaddr = 1; 720 newaddr = 0; 721 } else 722 clearaddr = 0; 723#undef rqtosa 724} 725 726/*ARGSUSED*/ 727static void 728setifdstaddr(const char *addr, int param __unused, int s, 729 const struct afswtch *afp) 730{ 731 if (afp->af_getaddr != NULL) 732 afp->af_getaddr(addr, DSTADDR); 733} 734 735/* 736 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 737 * of the ifreq structure, which may confuse other parts of ifconfig. 738 * Make a private copy so we can avoid that. 739 */ 740static void 741setifflags(const char *vname, int value, int s, const struct afswtch *afp) 742{ 743 struct ifreq my_ifr; 744 int flags; 745 746 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 747 748 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 749 Perror("ioctl (SIOCGIFFLAGS)"); 750 exit(1); 751 } 752 strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name)); 753 flags = my_ifr.ifr_flags; 754 755 if (value < 0) { 756 value = -value; 757 flags &= ~value; 758 } else 759 flags |= value; 760 my_ifr.ifr_flags = flags & 0xffff; 761 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 762 Perror(vname); 763} 764 765#ifdef SIOCGIFCAP 766void 767setifcap(const char *vname, int value, int s, const struct afswtch *afp) 768{ 769 int flags; 770 771 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 772 Perror("ioctl (SIOCGIFCAP)"); 773 exit(1); 774 } 775 flags = ifr.ifr_curcap; 776 if (value < 0) { 777 value = -value; 778 flags &= ~value; 779 } else 780 flags |= value; 781 flags &= ifr.ifr_reqcap; 782 ifr.ifr_reqcap = flags; 783 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 784 Perror(vname); 785} 786#endif 787 788static void 789setifmetric(const char *val, int dummy __unused, int s, 790 const struct afswtch *afp) 791{ 792 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 793 ifr.ifr_metric = atoi(val); 794 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 795 warn("ioctl (set metric)"); 796} 797 798static void 799setifmtu(const char *val, int dummy __unused, int s, 800 const struct afswtch *afp) 801{ 802 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 803 ifr.ifr_mtu = atoi(val); 804 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 805 warn("ioctl (set mtu)"); 806} 807 808#ifndef __APPLE__ 809static void 810setifname(const char *val, int dummy __unused, int s, 811 const struct afswtch *afp) 812{ 813 char *newname; 814 815 newname = strdup(val); 816 if (newname == NULL) { 817 warn("no memory to set ifname"); 818 return; 819 } 820 ifr.ifr_data = newname; 821 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { 822 warn("ioctl (set name)"); 823 free(newname); 824 return; 825 } 826 strlcpy(name, newname, sizeof(name)); 827 free(newname); 828} 829#endif 830 831static void 832setrouter(const char *vname, int value, int s, const struct afswtch *afp) 833{ 834 if (afp->af_setrouter == NULL) { 835 warn("address family %s does not support router mode", 836 afp->af_name); 837 return; 838 } 839 840 afp->af_setrouter(s, value); 841} 842 843static void 844setifdesc(const char *val, int dummy __unused, int s, const struct afswtch *afp) 845{ 846 struct if_descreq ifdr; 847 848 bzero(&ifdr, sizeof (ifdr)); 849 strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name)); 850 ifdr.ifdr_len = strlen(val); 851 strncpy((char *)ifdr.ifdr_desc, val, sizeof (ifdr.ifdr_desc)); 852 853 if (ioctl(s, SIOCSIFDESC, (caddr_t)&ifdr) < 0) { 854 warn("ioctl (set desc)"); 855 } 856} 857 858static void 859settbr(const char *val, int dummy __unused, int s, const struct afswtch *afp) 860{ 861 struct if_linkparamsreq iflpr; 862 long double bps; 863 u_int64_t rate; 864 u_int32_t percent = 0; 865 char *cp; 866 867 errno = 0; 868 bzero(&iflpr, sizeof (iflpr)); 869 strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name)); 870 871 bps = strtold(val, &cp); 872 if (val == cp || errno != 0) { 873 warn("Invalid value '%s'", val); 874 return; 875 } 876 rate = (u_int64_t)bps; 877 if (cp != NULL) { 878 if (!strcmp(cp, "b") || !strcmp(cp, "bps")) { 879 ; /* nothing */ 880 } else if (!strcmp(cp, "Kb") || !strcmp(cp, "Kbps")) { 881 rate *= 1000; 882 } else if (!strcmp(cp, "Mb") || !strcmp(cp, "Mbps")) { 883 rate *= 1000 * 1000; 884 } else if (!strcmp(cp, "Gb") || !strcmp(cp, "Gbps")) { 885 rate *= 1000 * 1000 * 1000; 886 } else if (!strcmp(cp, "%")) { 887 percent = rate; 888 if (percent == 0 || percent > 100) { 889 printf("Value out of range '%s'", val); 890 return; 891 } 892 } else if (*cp != '\0') { 893 printf("Unknown unit '%s'", cp); 894 return; 895 } 896 } 897 iflpr.iflpr_output_tbr_rate = rate; 898 iflpr.iflpr_output_tbr_percent = percent; 899 if (ioctl(s, SIOCSIFLINKPARAMS, &iflpr) < 0 && 900 errno != ENOENT && errno != ENXIO && errno != ENODEV) { 901 warn("ioctl (set link params)"); 902 } else if (errno == ENXIO) { 903 printf("TBR cannot be set on %s\n", name); 904 } else if (errno == ENOENT || rate == 0) { 905 printf("%s: TBR is now disabled\n", name); 906 } else if (errno == ENODEV) { 907 printf("%s: requires absolute TBR rate\n", name); 908 } else if (percent != 0) { 909 printf("%s: TBR rate set to %u%% of effective link rate\n", 910 name, percent); 911 } else { 912 printf("%s: TBR rate set to %s\n", name, bps_to_str(rate)); 913 } 914} 915 916static void 917setthrottle(const char *val, int dummy __unused, int s, 918 const struct afswtch *afp) 919{ 920 struct if_throttlereq iftr; 921 char *cp; 922 923 errno = 0; 924 bzero(&iftr, sizeof (iftr)); 925 strncpy(iftr.ifthr_name, name, sizeof (iftr.ifthr_name)); 926 927 iftr.ifthr_level = strtold(val, &cp); 928 if (val == cp || errno != 0) { 929 warn("Invalid value '%s'", val); 930 return; 931 } 932 933 if (ioctl(s, SIOCSIFTHROTTLE, &iftr) < 0 && errno != ENXIO) { 934 warn("ioctl (set throttling level)"); 935 } else if (errno == ENXIO) { 936 printf("throttling level cannot be set on %s\n", name); 937 } else { 938 printf("%s: throttling level set to %d\n", name, 939 iftr.ifthr_level); 940 } 941} 942 943static void 944setlog(const char *val, int dummy __unused, int s, 945 const struct afswtch *afp) 946{ 947 char *cp; 948 949 errno = 0; 950 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 951 952 ifr.ifr_log.ifl_level = strtold(val, &cp); 953 if (val == cp || errno != 0) { 954 warn("Invalid value '%s'", val); 955 return; 956 } 957 ifr.ifr_log.ifl_flags = (IFRLOGF_DLIL|IFRLOGF_FAMILY|IFRLOGF_DRIVER| 958 IFRLOGF_FIRMWARE); 959 960 if (ioctl(s, SIOCSIFLOG, &ifr) < 0) 961 warn("ioctl (set logging parameters)"); 962} 963 964void 965setcl2k(const char *vname, int value, int s, const struct afswtch *afp) 966{ 967 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 968 ifr.ifr_ifru.ifru_2kcl = value; 969 970 if (ioctl(s, SIOCSIF2KCL, (caddr_t)&ifr) < 0) 971 Perror(vname); 972} 973 974#define IFFBITS \ 975"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 976"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 977"\20MULTICAST" 978 979#define IFEFBITS \ 980"\020\1AUTOCONFIGURING\6IPV6_DISABLED\7ACCEPT_RTADV\10TXSTART\11RXPOLL" \ 981"\12VLAN\13BOND\14ARPLL\15NOWINDOWSCALE\16NOAUTOIPV6LL\17EXPENSIVE\20ROUTER4" \ 982"\21ROUTER6\22LOCALNET_PRIVATE\23ND6ALT\24RESTRICTED_RECV\25AWDL\26NOACKPRI" \ 983"\27AWDL_RESTRICTED\30CL2K\35SENDLIST\36DIRECTLINK\40UPDOWNCHANGE" 984 985#define IFCAPBITS \ 986"\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \ 987"\6TSO4\7TSO6\10LRO\11AV\12TXSTATUS" 988 989#define IFRLOGF_BITS \ 990"\020\1DLIL\21FAMILY\31DRIVER\35FIRMWARE" 991 992/* 993 * Print the status of the interface. If an address family was 994 * specified, show only it; otherwise, show them all. 995 */ 996static void 997status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 998 struct ifaddrs *ifa) 999{ 1000 struct ifaddrs *ift; 1001 int allfamilies, s; 1002 struct ifstat ifs; 1003 struct if_descreq ifdr; 1004 struct if_linkparamsreq iflpr; 1005 int mib[6]; 1006 struct ifmibdata_supplemental ifmsupp; 1007 size_t miblen = sizeof(struct ifmibdata_supplemental); 1008 u_int64_t eflags = 0; 1009 1010 if (afp == NULL) { 1011 allfamilies = 1; 1012 afp = af_getbyname("inet"); 1013 } else 1014 allfamilies = 0; 1015 1016 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 1017 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1018 1019 s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); 1020 if (s < 0) 1021 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); 1022 1023 printf("%s: ", name); 1024 printb("flags", ifa->ifa_flags, IFFBITS); 1025 if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) 1026 if (ifr.ifr_metric) 1027 printf(" metric %d", ifr.ifr_metric); 1028 if (ioctl(s, SIOCGIFMTU, &ifr) != -1) 1029 printf(" mtu %d", ifr.ifr_mtu); 1030 if (showrtref && ioctl(s, SIOCGIFGETRTREFCNT, &ifr) != -1) 1031 printf(" rtref %d", ifr.ifr_route_refcnt); 1032 if (verbose) { 1033 unsigned int ifindex = if_nametoindex(ifa->ifa_name); 1034 if (ifindex != 0) 1035 printf(" index %u", ifindex); 1036 } 1037 putchar('\n'); 1038 1039 if (verbose && ioctl(s, SIOCGIFEFLAGS, (caddr_t)&ifr) != -1 && 1040 (eflags = ifr.ifr_eflags) != 0) { 1041 printb("\teflags", eflags, IFEFBITS); 1042 putchar('\n'); 1043 } 1044 1045#ifdef SIOCGIFCAP 1046 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { 1047 if (ifr.ifr_curcap != 0) { 1048 printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 1049 putchar('\n'); 1050 } 1051 if (supmedia && ifr.ifr_reqcap != 0) { 1052 printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS); 1053 putchar('\n'); 1054 } 1055 } 1056#endif 1057 1058 tunnel_status(s); 1059 1060 for (ift = ifa; ift != NULL; ift = ift->ifa_next) { 1061 if (ift->ifa_addr == NULL) 1062 continue; 1063 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) 1064 continue; 1065 if (allfamilies) { 1066 const struct afswtch *p; 1067 p = af_getbyfamily(ift->ifa_addr->sa_family); 1068 if (p != NULL && p->af_status != NULL) 1069 p->af_status(s, ift); 1070 } else if (afp->af_af == ift->ifa_addr->sa_family) 1071 afp->af_status(s, ift); 1072 } 1073#if 0 1074 if (allfamilies || afp->af_af == AF_LINK) { 1075 const struct afswtch *lafp; 1076 1077 /* 1078 * Hack; the link level address is received separately 1079 * from the routing information so any address is not 1080 * handled above. Cobble together an entry and invoke 1081 * the status method specially. 1082 */ 1083 lafp = af_getbyname("lladdr"); 1084 if (lafp != NULL) { 1085 info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl; 1086 lafp->af_status(s, &info); 1087 } 1088 } 1089#endif 1090 if (allfamilies) 1091 af_other_status(s); 1092 else if (afp->af_other_status != NULL) 1093 afp->af_other_status(s); 1094 1095 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 1096 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 1097 printf("%s", ifs.ascii); 1098 1099 /* The rest is for when verbose is set; if not set, we're done */ 1100 if (!verbose) 1101 goto done; 1102 1103 if (ioctl(s, SIOCGIFTYPE, &ifr) != -1) { 1104 char *c = ift2str(ifr.ifr_type.ift_type, 1105 ifr.ifr_type.ift_family, ifr.ifr_type.ift_subfamily); 1106 if (c != NULL) 1107 printf("\ttype: %s\n", c); 1108 } 1109 1110 if (ioctl(s, SIOCGIFLINKQUALITYMETRIC, &ifr) != -1) { 1111 int lqm = ifr.ifr_link_quality_metric; 1112 if (verbose > 1) { 1113 printf("\tlink quality: %d ", lqm); 1114 if (lqm == IFNET_LQM_THRESH_OFF) { 1115 printf("(off)"); 1116 } else if (lqm == IFNET_LQM_THRESH_UNKNOWN) { 1117 printf("(unknown)"); 1118 } else if (lqm > IFNET_LQM_THRESH_UNKNOWN && 1119 lqm <= IFNET_LQM_THRESH_POOR) 1120 printf("(poor)"); 1121 else if (lqm > IFNET_LQM_THRESH_POOR && 1122 lqm <= IFNET_LQM_THRESH_GOOD) 1123 printf("(good)"); 1124 else 1125 printf("(?)"); 1126 printf("\n"); 1127 } else if (lqm > IFNET_LQM_THRESH_UNKNOWN) { 1128 printf("\tlink quality: %d ", lqm); 1129 if (lqm <= IFNET_LQM_THRESH_POOR) 1130 printf("(poor)"); 1131 else if (lqm > IFNET_LQM_THRESH_POOR && 1132 lqm <= IFNET_LQM_THRESH_GOOD) 1133 printf("(good)"); 1134 else 1135 printf("(?)"); 1136 printf("\n"); 1137 } 1138 } 1139 1140 bzero(&iflpr, sizeof (iflpr)); 1141 strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name)); 1142 if (ioctl(s, SIOCGIFLINKPARAMS, &iflpr) != -1) { 1143 u_int64_t ibw_max = iflpr.iflpr_input_bw.max_bw; 1144 u_int64_t ibw_eff = iflpr.iflpr_input_bw.eff_bw; 1145 u_int64_t obw_max = iflpr.iflpr_output_bw.max_bw; 1146 u_int64_t obw_eff = iflpr.iflpr_output_bw.eff_bw; 1147 u_int64_t obw_tbr = iflpr.iflpr_output_tbr_rate; 1148 u_int32_t obw_pct = iflpr.iflpr_output_tbr_percent; 1149 u_int64_t ilt_max = iflpr.iflpr_input_lt.max_lt; 1150 u_int64_t ilt_eff = iflpr.iflpr_input_lt.eff_lt; 1151 u_int64_t olt_max = iflpr.iflpr_output_lt.max_lt; 1152 u_int64_t olt_eff = iflpr.iflpr_output_lt.eff_lt; 1153 1154 1155 if (eflags & IFEF_TXSTART) { 1156 u_int32_t flags = iflpr.iflpr_flags; 1157 u_int32_t sched = iflpr.iflpr_output_sched; 1158 struct if_throttlereq iftr; 1159 1160 printf("\tscheduler: %s%s ", 1161 (flags & IFLPRF_ALTQ) ? "ALTQ_" : "", 1162 sched2str(sched)); 1163 if (flags & IFLPRF_DRVMANAGED) 1164 printf("(driver managed)"); 1165 printf("\n"); 1166 1167 bzero(&iftr, sizeof (iftr)); 1168 strncpy(iftr.ifthr_name, name, 1169 sizeof (iftr.ifthr_name)); 1170 if (ioctl(s, SIOCGIFTHROTTLE, &iftr) != -1 && 1171 iftr.ifthr_level != IFNET_THROTTLE_OFF) 1172 printf("\tthrottling: level %d (%s)\n", 1173 iftr.ifthr_level, tl2str(iftr.ifthr_level)); 1174 } 1175 1176 if (obw_tbr != 0 && obw_eff > obw_tbr) 1177 obw_eff = obw_tbr; 1178 1179 if (ibw_max != 0 || obw_max != 0) { 1180 if (ibw_max == obw_max && ibw_eff == obw_eff && 1181 ibw_max == ibw_eff && obw_tbr == 0) { 1182 printf("\tlink rate: %s\n", 1183 bps_to_str(ibw_max)); 1184 } else { 1185 printf("\tuplink rate: %s [eff] / ", 1186 bps_to_str(obw_eff)); 1187 if (obw_tbr != 0) { 1188 if (obw_pct == 0) 1189 printf("%s [tbr] / ", 1190 bps_to_str(obw_tbr)); 1191 else 1192 printf("%s [tbr %u%%] / ", 1193 bps_to_str(obw_tbr), 1194 obw_pct); 1195 } 1196 printf("%s", bps_to_str(obw_max)); 1197 if (obw_tbr != 0) 1198 printf(" [max]"); 1199 printf("\n"); 1200 if (ibw_eff == ibw_max) { 1201 printf("\tdownlink rate: %s\n", 1202 bps_to_str(ibw_max)); 1203 } else { 1204 printf("\tdownlink rate: " 1205 "%s [eff] / ", bps_to_str(ibw_eff)); 1206 printf("%s [max]\n", 1207 bps_to_str(ibw_max)); 1208 } 1209 } 1210 } else if (obw_tbr != 0) { 1211 printf("\tuplink rate: %s [tbr]\n", 1212 bps_to_str(obw_tbr)); 1213 } 1214 1215 if (ilt_max != 0 || olt_max != 0) { 1216 if (ilt_max == olt_max && ilt_eff == olt_eff && 1217 ilt_max == ilt_eff) { 1218 printf("\tlink latency: %s\n", 1219 ns_to_str(ilt_max)); 1220 } else { 1221 if (olt_max != 0 && olt_eff == olt_max) { 1222 printf("\tuplink latency: %s\n", 1223 ns_to_str(olt_max)); 1224 } else if (olt_max != 0) { 1225 printf("\tuplink latency: " 1226 "%s [eff] / ", ns_to_str(olt_eff)); 1227 printf("%s [max]\n", 1228 ns_to_str(olt_max)); 1229 } 1230 if (ilt_max != 0 && ilt_eff == ilt_max) { 1231 printf("\tdownlink latency: %s\n", 1232 ns_to_str(ilt_max)); 1233 } else if (ilt_max != 0) { 1234 printf("\tdownlink latency: " 1235 "%s [eff] / ", ns_to_str(ilt_eff)); 1236 printf("%s [max]\n", 1237 ns_to_str(ilt_max)); 1238 } 1239 } 1240 } 1241 } 1242 1243 /* Common OID prefix */ 1244 mib[0] = CTL_NET; 1245 mib[1] = PF_LINK; 1246 mib[2] = NETLINK_GENERIC; 1247 mib[3] = IFMIB_IFDATA; 1248 mib[4] = if_nametoindex(name); 1249 mib[5] = IFDATA_SUPPLEMENTAL; 1250 if (sysctl(mib, 6, &ifmsupp, &miblen, (void *)0, 0) == -1) 1251 err(1, "sysctl IFDATA_SUPPLEMENTAL"); 1252 1253 if (ifmsupp.ifmd_data_extended.ifi_alignerrs != 0) { 1254 printf("\tunaligned pkts: %llu\n", 1255 ifmsupp.ifmd_data_extended.ifi_alignerrs); 1256 } 1257 if (ifmsupp.ifmd_data_extended.ifi_dt_bytes != 0) { 1258 printf("\tdata milestone interval: %s\n", 1259 bytes_to_str(ifmsupp.ifmd_data_extended.ifi_dt_bytes)); 1260 } 1261 1262 bzero(&ifdr, sizeof (ifdr)); 1263 strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name)); 1264 if (ioctl(s, SIOCGIFDESC, &ifdr) != -1 && ifdr.ifdr_len) { 1265 printf("\tdesc: %s\n", ifdr.ifdr_desc); 1266 } 1267 1268 if (ioctl(s, SIOCGIFLOG, &ifr) != -1 && ifr.ifr_log.ifl_level) { 1269 printf("\tlogging: level %d ", ifr.ifr_log.ifl_level); 1270 printb("facilities", ifr.ifr_log.ifl_flags, IFRLOGF_BITS); 1271 putchar('\n'); 1272 } 1273 1274 if (ioctl(s, SIOCGIFDELEGATE, &ifr) != -1 && ifr.ifr_delegated) { 1275 char delegatedif[IFNAMSIZ+1]; 1276 if (if_indextoname(ifr.ifr_delegated, delegatedif) != NULL) 1277 printf("\teffective interface: %s\n", delegatedif); 1278 } 1279 1280done: 1281 close(s); 1282 return; 1283} 1284 1285#define KILOBYTES 1024 1286#define MEGABYTES (KILOBYTES * KILOBYTES) 1287#define GIGABYTES (KILOBYTES * KILOBYTES * KILOBYTES) 1288 1289static char * 1290bytes_to_str(unsigned long long bytes) 1291{ 1292 static char buf[32]; 1293 const char *u; 1294 long double n = bytes, t; 1295 1296 if (bytes >= GIGABYTES) { 1297 t = n / GIGABYTES; 1298 u = "GB"; 1299 } else if (n >= MEGABYTES) { 1300 t = n / MEGABYTES; 1301 u = "MB"; 1302 } else if (n >= KILOBYTES) { 1303 t = n / KILOBYTES; 1304 u = "KB"; 1305 } else { 1306 t = n; 1307 u = "bytes"; 1308 } 1309 1310 snprintf(buf, sizeof (buf), "%-4.2Lf %s", t, u); 1311 return (buf); 1312} 1313 1314#define GIGABIT_PER_SEC 1000000000 /* gigabit per second */ 1315#define MEGABIT_PER_SEC 1000000 /* megabit per second */ 1316#define KILOBIT_PER_SEC 1000 /* kilobit per second */ 1317 1318static char * 1319bps_to_str(unsigned long long rate) 1320{ 1321 static char buf[32]; 1322 const char *u; 1323 long double n = rate, t; 1324 1325 if (rate >= GIGABIT_PER_SEC) { 1326 t = n / GIGABIT_PER_SEC; 1327 u = "Gbps"; 1328 } else if (n >= MEGABIT_PER_SEC) { 1329 t = n / MEGABIT_PER_SEC; 1330 u = "Mbps"; 1331 } else if (n >= KILOBIT_PER_SEC) { 1332 t = n / KILOBIT_PER_SEC; 1333 u = "Kbps"; 1334 } else { 1335 t = n; 1336 u = "bps "; 1337 } 1338 1339 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u); 1340 return (buf); 1341} 1342 1343#define NSEC_PER_SEC 1000000000 /* nanosecond per second */ 1344#define USEC_PER_SEC 1000000 /* microsecond per second */ 1345#define MSEC_PER_SEC 1000 /* millisecond per second */ 1346 1347static char * 1348ns_to_str(unsigned long long nsec) 1349{ 1350 static char buf[32]; 1351 const char *u; 1352 long double n = nsec, t; 1353 1354 if (nsec >= NSEC_PER_SEC) { 1355 t = n / NSEC_PER_SEC; 1356 u = "sec "; 1357 } else if (n >= USEC_PER_SEC) { 1358 t = n / USEC_PER_SEC; 1359 u = "msec"; 1360 } else if (n >= MSEC_PER_SEC) { 1361 t = n / MSEC_PER_SEC; 1362 u = "usec"; 1363 } else { 1364 t = n; 1365 u = "nsec"; 1366 } 1367 1368 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u); 1369 return (buf); 1370} 1371 1372static void 1373tunnel_status(int s) 1374{ 1375 af_all_tunnel_status(s); 1376} 1377 1378void 1379Perror(const char *cmd) 1380{ 1381 switch (errno) { 1382 1383 case ENXIO: 1384 errx(1, "%s: no such interface", cmd); 1385 break; 1386 1387 case EPERM: 1388 errx(1, "%s: permission denied", cmd); 1389 break; 1390 1391 default: 1392 err(1, "%s", cmd); 1393 } 1394} 1395 1396/* 1397 * Print a value a la the %b format of the kernel's printf 1398 */ 1399void 1400printb(const char *s, unsigned v, const char *bits) 1401{ 1402 int i, any = 0; 1403 char c; 1404 1405 if (bits && *bits == 8) 1406 printf("%s=%o", s, v); 1407 else 1408 printf("%s=%x", s, v); 1409 bits++; 1410 if (bits) { 1411 putchar('<'); 1412 while ((i = *bits++) != '\0') { 1413 if (v & (1 << (i-1))) { 1414 if (any) 1415 putchar(','); 1416 any = 1; 1417 for (; (c = *bits) > 32; bits++) 1418 putchar(c); 1419 } else 1420 for (; *bits > 32; bits++) 1421 ; 1422 } 1423 putchar('>'); 1424 } 1425} 1426 1427#ifndef __APPLE__ 1428void 1429ifmaybeload(const char *name) 1430{ 1431#define MOD_PREFIX_LEN 3 /* "if_" */ 1432 struct module_stat mstat; 1433 int fileid, modid; 1434 char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; 1435 const char *cp; 1436 1437 /* loading suppressed by the user */ 1438 if (noload) 1439 return; 1440 1441 /* trim the interface number off the end */ 1442 strlcpy(ifname, name, sizeof(ifname)); 1443 for (dp = ifname; *dp != 0; dp++) 1444 if (isdigit(*dp)) { 1445 *dp = 0; 1446 break; 1447 } 1448 1449 /* turn interface and unit into module name */ 1450 strlcpy(ifkind, "if_", sizeof(ifkind)); 1451 strlcpy(ifkind + MOD_PREFIX_LEN, ifname, 1452 sizeof(ifkind) - MOD_PREFIX_LEN); 1453 1454 /* scan files in kernel */ 1455 mstat.version = sizeof(struct module_stat); 1456 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1457 /* scan modules in file */ 1458 for (modid = kldfirstmod(fileid); modid > 0; 1459 modid = modfnext(modid)) { 1460 if (modstat(modid, &mstat) < 0) 1461 continue; 1462 /* strip bus name if present */ 1463 if ((cp = strchr(mstat.name, '/')) != NULL) { 1464 cp++; 1465 } else { 1466 cp = mstat.name; 1467 } 1468 /* already loaded? */ 1469 if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 || 1470 strncmp(ifkind, cp, strlen(ifkind) + 1) == 0) 1471 return; 1472 } 1473 } 1474 1475 /* not present, we should try to load it */ 1476 kldload(ifkind); 1477} 1478#endif 1479 1480static struct cmd basic_cmds[] = { 1481 DEF_CMD("up", IFF_UP, setifflags), 1482 DEF_CMD("down", -IFF_UP, setifflags), 1483 DEF_CMD("arp", -IFF_NOARP, setifflags), 1484 DEF_CMD("-arp", IFF_NOARP, setifflags), 1485 DEF_CMD("debug", IFF_DEBUG, setifflags), 1486 DEF_CMD("-debug", -IFF_DEBUG, setifflags), 1487#ifdef IFF_PPROMISC 1488 DEF_CMD("promisc", IFF_PPROMISC, setifflags), 1489 DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), 1490#endif /* IFF_PPROMISC */ 1491 DEF_CMD("add", IFF_UP, notealias), 1492 DEF_CMD("alias", IFF_UP, notealias), 1493 DEF_CMD("-alias", -IFF_UP, notealias), 1494 DEF_CMD("delete", -IFF_UP, notealias), 1495 DEF_CMD("remove", -IFF_UP, notealias), 1496#ifdef notdef 1497#define EN_SWABIPS 0x1000 1498 DEF_CMD("swabips", EN_SWABIPS, setifflags), 1499 DEF_CMD("-swabips", -EN_SWABIPS, setifflags), 1500#endif 1501 DEF_CMD_ARG("netmask", setifnetmask), 1502 DEF_CMD_ARG("metric", setifmetric), 1503 DEF_CMD_ARG("broadcast", setifbroadaddr), 1504 DEF_CMD_ARG("ipdst", setifipdst), 1505 DEF_CMD_ARG2("tunnel", settunnel), 1506 DEF_CMD("-tunnel", 0, deletetunnel), 1507 DEF_CMD("deletetunnel", 0, deletetunnel), 1508 DEF_CMD("link0", IFF_LINK0, setifflags), 1509 DEF_CMD("-link0", -IFF_LINK0, setifflags), 1510 DEF_CMD("link1", IFF_LINK1, setifflags), 1511 DEF_CMD("-link1", -IFF_LINK1, setifflags), 1512 DEF_CMD("link2", IFF_LINK2, setifflags), 1513 DEF_CMD("-link2", -IFF_LINK2, setifflags), 1514#ifdef IFF_MONITOR 1515 DEF_CMD("monitor", IFF_MONITOR:, setifflags), 1516 DEF_CMD("-monitor", -IFF_MONITOR, setifflags), 1517#endif /* IFF_MONITOR */ 1518#ifdef IFF_STATICARP 1519 DEF_CMD("staticarp", IFF_STATICARP, setifflags), 1520 DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), 1521#endif /* IFF_STATICARP */ 1522#ifdef IFCAP_RXCSUM 1523 DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), 1524 DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), 1525#endif /* IFCAP_RXCSUM */ 1526#ifdef IFCAP_TXCSUM 1527 DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), 1528 DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), 1529#endif /* IFCAP_TXCSUM */ 1530#ifdef IFCAP_NETCONS 1531 DEF_CMD("netcons", IFCAP_NETCONS, setifcap), 1532 DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), 1533#endif /* IFCAP_NETCONS */ 1534#ifdef IFCAP_POLLING 1535 DEF_CMD("polling", IFCAP_POLLING, setifcap), 1536 DEF_CMD("-polling", -IFCAP_POLLING, setifcap), 1537#endif /* IFCAP_POLLING */ 1538#ifdef IFCAP_TSO 1539 DEF_CMD("tso", IFCAP_TSO, setifcap), 1540 DEF_CMD("-tso", -IFCAP_TSO, setifcap), 1541#endif /* IFCAP_TSO */ 1542#ifdef IFCAP_LRO 1543 DEF_CMD("lro", IFCAP_LRO, setifcap), 1544 DEF_CMD("-lro", -IFCAP_LRO, setifcap), 1545#endif /* IFCAP_LRO */ 1546#ifdef IFCAP_WOL 1547 DEF_CMD("wol", IFCAP_WOL, setifcap), 1548 DEF_CMD("-wol", -IFCAP_WOL, setifcap), 1549#endif /* IFCAP_WOL */ 1550#ifdef IFCAP_WOL_UCAST 1551 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), 1552 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), 1553#endif /* IFCAP_WOL_UCAST */ 1554#ifdef IFCAP_WOL_MCAST 1555 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), 1556 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), 1557#endif /* IFCAP_WOL_MCAST */ 1558#ifdef IFCAP_WOL_MAGIC 1559 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), 1560 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), 1561#endif /* IFCAP_WOL_MAGIC */ 1562 DEF_CMD("normal", -IFF_LINK0, setifflags), 1563 DEF_CMD("compress", IFF_LINK0, setifflags), 1564 DEF_CMD("noicmp", IFF_LINK1, setifflags), 1565 DEF_CMD_ARG("mtu", setifmtu), 1566#ifdef notdef 1567 DEF_CMD_ARG("name", setifname), 1568#endif /* notdef */ 1569#ifdef IFCAP_AV 1570 DEF_CMD("av", IFCAP_AV, setifcap), 1571 DEF_CMD("-av", -IFCAP_AV, setifcap), 1572#endif /* IFCAP_AV */ 1573 DEF_CMD("router", 1, setrouter), 1574 DEF_CMD("-router", 0, setrouter), 1575 DEF_CMD_ARG("desc", setifdesc), 1576 DEF_CMD_ARG("tbr", settbr), 1577 DEF_CMD_ARG("throttle", setthrottle), 1578 DEF_CMD_ARG("log", setlog), 1579 DEF_CMD("cl2k", 1, setcl2k), 1580 DEF_CMD("-cl2k", 0, setcl2k), 1581}; 1582 1583static __constructor void 1584ifconfig_ctor(void) 1585{ 1586#define N(a) (sizeof(a) / sizeof(a[0])) 1587 int i; 1588 1589 for (i = 0; i < N(basic_cmds); i++) 1590 cmd_register(&basic_cmds[i]); 1591#undef N 1592} 1593 1594static char * 1595sched2str(unsigned int s) 1596{ 1597 char *c; 1598 1599 switch (s) { 1600 case PKTSCHEDT_NONE: 1601 c = "NONE"; 1602 break; 1603 case PKTSCHEDT_CBQ: 1604 c = "CBQ"; 1605 break; 1606 case PKTSCHEDT_HFSC: 1607 c = "HFSC"; 1608 break; 1609 case PKTSCHEDT_PRIQ: 1610 c = "PRIQ"; 1611 break; 1612 case PKTSCHEDT_FAIRQ: 1613 c = "FAIRQ"; 1614 break; 1615 case PKTSCHEDT_TCQ: 1616 c = "TCQ"; 1617 break; 1618 case PKTSCHEDT_QFQ: 1619 c = "QFQ"; 1620 break; 1621 default: 1622 c = "UNKNOWN"; 1623 break; 1624 } 1625 1626 return (c); 1627} 1628 1629static char * 1630tl2str(unsigned int s) 1631{ 1632 char *c; 1633 1634 switch (s) { 1635 case IFNET_THROTTLE_OFF: 1636 c = "off"; 1637 break; 1638 case IFNET_THROTTLE_OPPORTUNISTIC: 1639 c = "opportunistic"; 1640 break; 1641 default: 1642 c = "unknown"; 1643 break; 1644 } 1645 1646 return (c); 1647} 1648 1649static char * 1650ift2str(unsigned int t, unsigned int f, unsigned int sf) 1651{ 1652 static char buf[256]; 1653 char *c = NULL; 1654 1655 switch (t) { 1656 case IFT_ETHER: 1657 switch (sf) { 1658 case IFRTYPE_SUBFAMILY_USB: 1659 c = "USB Ethernet"; 1660 break; 1661 case IFRTYPE_SUBFAMILY_BLUETOOTH: 1662 c = "Bluetooth PAN"; 1663 break; 1664 case IFRTYPE_SUBFAMILY_WIFI: 1665 c = "Wi-Fi"; 1666 break; 1667 case IFRTYPE_SUBFAMILY_THUNDERBOLT: 1668 c = "IP over Thunderbolt"; 1669 break; 1670 case IFRTYPE_SUBFAMILY_ANY: 1671 default: 1672 c = "Ethernet"; 1673 break; 1674 } 1675 break; 1676 1677 case IFT_IEEE1394: 1678 c = "IP over FireWire"; 1679 break; 1680 1681 case IFT_PKTAP: 1682 c = "Packet capture"; 1683 break; 1684 1685 case IFT_CELLULAR: 1686 c = "Cellular"; 1687 break; 1688 1689 case IFT_BRIDGE: 1690 case IFT_PFLOG: 1691 case IFT_PFSYNC: 1692 case IFT_OTHER: 1693 case IFT_PPP: 1694 case IFT_LOOP: 1695 case IFT_GIF: 1696 case IFT_STF: 1697 case IFT_L2VLAN: 1698 case IFT_IEEE8023ADLAG: 1699 default: 1700 break; 1701 } 1702 1703 if (verbose > 1) { 1704 if (c == NULL) { 1705 (void) snprintf(buf, sizeof (buf), 1706 "0x%x family: %u subfamily: %u", 1707 ifr.ifr_type.ift_type, ifr.ifr_type.ift_family, 1708 ifr.ifr_type.ift_subfamily); 1709 } else { 1710 (void) snprintf(buf, sizeof (buf), 1711 "%s (0x%x) family: %u subfamily: %u", c, 1712 ifr.ifr_type.ift_type, ifr.ifr_type.ift_family, 1713 ifr.ifr_type.ift_subfamily); 1714 } 1715 c = buf; 1716 } 1717 1718 return (c); 1719} 1720