ifconfig.c revision 1.167
1/* $NetBSD: ifconfig.c,v 1.167 2005/03/20 02:51:47 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40/* 41 * Copyright (c) 1983, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. Neither the name of the University nor the names of its contributors 53 * may be used to endorse or promote products derived from this software 54 * without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 */ 68 69#include <sys/cdefs.h> 70#ifndef lint 71__COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\ 72 The Regents of the University of California. All rights reserved.\n"); 73#endif /* not lint */ 74 75#ifndef lint 76#if 0 77static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 78#else 79__RCSID("$NetBSD: ifconfig.c,v 1.167 2005/03/20 02:51:47 thorpej Exp $"); 80#endif 81#endif /* not lint */ 82 83#include <sys/param.h> 84#include <sys/socket.h> 85#include <sys/ioctl.h> 86 87#include <net/if.h> 88#include <net/if_dl.h> 89#include <net/if_media.h> 90#include <net/if_ether.h> 91#include <netinet/in.h> /* XXX */ 92#include <netinet/in_var.h> /* XXX */ 93 94#include <netdb.h> 95 96#include <sys/protosw.h> 97 98#include <ctype.h> 99#include <err.h> 100#include <errno.h> 101#include <stddef.h> 102#include <stdio.h> 103#include <stdlib.h> 104#include <string.h> 105#include <unistd.h> 106#include <ifaddrs.h> 107#include <util.h> 108 109#include "extern.h" 110 111#ifndef INET_ONLY 112#include "af_atalk.h" 113#include "af_iso.h" 114#include "af_ns.h" 115#endif /* ! INET_ONLY */ 116#include "af_inet.h" 117#ifdef INET6 118#include "af_inet6.h" 119#endif /* INET6 */ 120 121#include "agr.h" 122#include "ieee80211.h" 123#include "tunnel.h" 124#include "vlan.h" 125 126struct ifreq ifr, ridreq; 127struct ifaliasreq addreq __attribute__((aligned(4))); 128 129char name[30]; 130u_short flags; 131int setaddr, doalias; 132u_long metric, mtu; 133int clearaddr, s; 134int newaddr = -1; 135int conflicting = 0; 136int af; 137int aflag, bflag, Cflag, dflag, lflag, mflag, sflag, uflag, vflag, zflag; 138#ifdef INET6 139int Lflag; 140#endif 141int explicit_prefix = 0; 142 143struct ifcapreq g_ifcr; 144int g_ifcr_updated; 145 146void notealias(const char *, int); 147void notrailers(const char *, int); 148void setifaddr(const char *, int); 149void setifdstaddr(const char *, int); 150void setifflags(const char *, int); 151void setifcaps(const char *, int); 152void setifbroadaddr(const char *, int); 153void setifipdst(const char *, int); 154void setifmetric(const char *, int); 155void setifmtu(const char *, int); 156void setifnetmask(const char *, int); 157void setifprefixlen(const char *, int); 158void setmedia(const char *, int); 159void setmediamode(const char *, int); 160void setmediaopt(const char *, int); 161void unsetmediaopt(const char *, int); 162void setmediainst(const char *, int); 163void clone_create(const char *, int); 164void clone_destroy(const char *, int); 165int main(int, char *[]); 166 167/* 168 * Media stuff. Whenever a media command is first performed, the 169 * currently select media is grabbed for this interface. If `media' 170 * is given, the current media word is modifed. `mediaopt' commands 171 * only modify the set and clear words. They then operate on the 172 * current media word later. 173 */ 174int media_current; 175int mediaopt_set; 176int mediaopt_clear; 177 178int actions; /* Actions performed */ 179 180#define A_MEDIA 0x0001 /* media command */ 181#define A_MEDIAOPTSET 0x0002 /* mediaopt command */ 182#define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */ 183#define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR) 184#define A_MEDIAINST 0x0008 /* instance or inst command */ 185#define A_MEDIAMODE 0x0010 /* mode command */ 186 187#define NEXTARG 0xffffff 188#define NEXTARG2 0xfffffe 189 190const struct cmd { 191 const char *c_name; 192 int c_parameter; /* NEXTARG means next argv */ 193 int c_action; /* defered action */ 194 void (*c_func)(const char *, int); 195 void (*c_func2)(const char *, const char *); 196} cmds[] = { 197 { "up", IFF_UP, 0, setifflags } , 198 { "down", -IFF_UP, 0, setifflags }, 199 { "trailers", -1, 0, notrailers }, 200 { "-trailers", 1, 0, notrailers }, 201 { "arp", -IFF_NOARP, 0, setifflags }, 202 { "-arp", IFF_NOARP, 0, setifflags }, 203 { "debug", IFF_DEBUG, 0, setifflags }, 204 { "-debug", -IFF_DEBUG, 0, setifflags }, 205 { "alias", IFF_UP, 0, notealias }, 206 { "-alias", -IFF_UP, 0, notealias }, 207 { "delete", -IFF_UP, 0, notealias }, 208#ifdef notdef 209#define EN_SWABIPS 0x1000 210 { "swabips", EN_SWABIPS, 0, setifflags }, 211 { "-swabips", -EN_SWABIPS, 0, setifflags }, 212#endif 213 { "netmask", NEXTARG, 0, setifnetmask }, 214 { "metric", NEXTARG, 0, setifmetric }, 215 { "mtu", NEXTARG, 0, setifmtu }, 216 { "bssid", NEXTARG, 0, setifbssid }, 217 { "-bssid", -1, 0, setifbssid }, 218 { "chan", NEXTARG, 0, setifchan }, 219 { "-chan", -1, 0, setifchan }, 220 { "ssid", NEXTARG, 0, setifnwid }, 221 { "nwid", NEXTARG, 0, setifnwid }, 222 { "nwkey", NEXTARG, 0, setifnwkey }, 223 { "-nwkey", -1, 0, setifnwkey }, 224 { "powersave", 1, 0, setifpowersave }, 225 { "-powersave", 0, 0, setifpowersave }, 226 { "powersavesleep", NEXTARG, 0, setifpowersavesleep }, 227 { "broadcast", NEXTARG, 0, setifbroadaddr }, 228 { "ipdst", NEXTARG, 0, setifipdst }, 229 { "prefixlen", NEXTARG, 0, setifprefixlen}, 230#ifdef INET6 231 { "anycast", IN6_IFF_ANYCAST, 0, setia6flags }, 232 { "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags }, 233 { "tentative", IN6_IFF_TENTATIVE, 0, setia6flags }, 234 { "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags }, 235 { "deprecated", IN6_IFF_DEPRECATED, 0, setia6flags }, 236 { "-deprecated", -IN6_IFF_DEPRECATED, 0, setia6flags }, 237 { "pltime", NEXTARG, 0, setia6pltime }, 238 { "vltime", NEXTARG, 0, setia6vltime }, 239 { "eui64", 0, 0, setia6eui64 }, 240#endif /*INET6*/ 241#ifndef INET_ONLY 242 { "range", NEXTARG, 0, setatrange }, 243 { "phase", NEXTARG, 0, setatphase }, 244 { "snpaoffset", NEXTARG, 0, setsnpaoffset }, 245 { "nsellength", NEXTARG, 0, setnsellength }, 246#endif /* INET_ONLY */ 247 { "tunnel", NEXTARG2, 0, NULL, 248 settunnel } , 249 { "deletetunnel", 0, 0, deletetunnel }, 250 { "vlan", NEXTARG, 0, setvlan } , 251 { "vlanif", NEXTARG, 0, setvlanif } , 252 { "-vlanif", 0, 0, unsetvlanif } , 253#if 0 254 /* XXX `create' special-cased below */ 255 { "create", 0, 0, clone_create } , 256#endif 257 { "destroy", 0, 0, clone_destroy } , 258 { "link0", IFF_LINK0, 0, setifflags } , 259 { "-link0", -IFF_LINK0, 0, setifflags } , 260 { "link1", IFF_LINK1, 0, setifflags } , 261 { "-link1", -IFF_LINK1, 0, setifflags } , 262 { "link2", IFF_LINK2, 0, setifflags } , 263 { "-link2", -IFF_LINK2, 0, setifflags } , 264 { "media", NEXTARG, A_MEDIA, setmedia }, 265 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt }, 266 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt }, 267 { "mode", NEXTARG, A_MEDIAMODE, setmediamode }, 268 { "instance", NEXTARG, A_MEDIAINST, setmediainst }, 269 { "inst", NEXTARG, A_MEDIAINST, setmediainst }, 270 { "ip4csum", IFCAP_CSUM_IPv4,0, setifcaps }, 271 { "-ip4csum", -IFCAP_CSUM_IPv4,0, setifcaps }, 272 { "tcp4csum", IFCAP_CSUM_TCPv4,0, setifcaps }, 273 { "-tcp4csum", -IFCAP_CSUM_TCPv4,0, setifcaps }, 274 { "udp4csum", IFCAP_CSUM_UDPv4,0, setifcaps }, 275 { "-udp4csum", -IFCAP_CSUM_UDPv4,0, setifcaps }, 276 { "tcp6csum", IFCAP_CSUM_TCPv6,0, setifcaps }, 277 { "-tcp6csum", -IFCAP_CSUM_TCPv6,0, setifcaps }, 278 { "udp6csum", IFCAP_CSUM_UDPv6,0, setifcaps }, 279 { "-udp6csum", -IFCAP_CSUM_UDPv6,0, setifcaps }, 280 { "tcp4csum-rx",IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 281 { "-tcp4csum-rx",-IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 282 { "udp4csum-rx",IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 283 { "-udp4csum-rx",-IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 284 { "tso4", IFCAP_TSOv4, 0, setifcaps }, 285 { "-tso4", -IFCAP_TSOv4, 0, setifcaps }, 286 { "agrport", NEXTARG, 0, agraddport } , 287 { "-agrport", NEXTARG, 0, agrremport } , 288 { 0, 0, 0, setifaddr }, 289 { 0, 0, 0, setifdstaddr }, 290}; 291 292int getinfo(struct ifreq *); 293int carrier(void); 294void printall(const char *); 295void list_cloners(void); 296void status(const struct sockaddr_dl *); 297void usage(void); 298 299void print_media_word(int, const char *); 300void process_media_commands(void); 301void init_current_media(void); 302 303/* Known address families */ 304const struct afswtch afs[] = { 305 { "inet", AF_INET, in_status, in_getaddr, in_getprefix, 306 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &ridreq, &in_addreq }, 307#ifdef INET6 308 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 309 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 310 /* 311 * Deleting the first address before setting new one is 312 * not prefered way in this protocol. 313 */ 314 0, 315 &in6_ridreq, &in6_addreq }, 316#endif 317#ifndef INET_ONLY /* small version, for boot media */ 318 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 319 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &addreq, &addreq }, 320 { "ns", AF_NS, xns_status, xns_getaddr, NULL, 321 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &ridreq, &addreq }, 322 { "iso", AF_ISO, iso_status, iso_getaddr, NULL, 323 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, SIOCGIFADDR_ISO, 324 &iso_ridreq, &iso_addreq }, 325#endif /* INET_ONLY */ 326 { 0, 0, 0, 0 } 327}; 328 329const struct afswtch *afp; /*the address family being set or asked about*/ 330 331int 332main(int argc, char *argv[]) 333{ 334 int ch; 335 336 /* Parse command-line options */ 337 aflag = mflag = vflag = zflag = 0; 338 while ((ch = getopt(argc, argv, "AabCdlmsuvz" 339#ifdef INET6 340 "L" 341#endif 342 )) != -1) { 343 switch (ch) { 344 case 'A': 345 warnx("-A is deprecated"); 346 break; 347 348 case 'a': 349 aflag = 1; 350 break; 351 352 case 'b': 353 bflag = 1; 354 break; 355 356 case 'C': 357 Cflag = 1; 358 break; 359 360 case 'd': 361 dflag = 1; 362 break; 363 364#ifdef INET6 365 case 'L': 366 Lflag = 1; 367 break; 368#endif 369 370 case 'l': 371 lflag = 1; 372 break; 373 374 case 'm': 375 mflag = 1; 376 break; 377 378 case 's': 379 sflag = 1; 380 break; 381 382 case 'u': 383 uflag = 1; 384 break; 385 386 case 'v': 387 vflag = 1; 388 break; 389 390 case 'z': 391 zflag = 1; 392 break; 393 394 395 default: 396 usage(); 397 /* NOTREACHED */ 398 } 399 } 400 argc -= optind; 401 argv += optind; 402 403 /* 404 * -l means "list all interfaces", and is mutally exclusive with 405 * all other flags/commands. 406 * 407 * -C means "list all names of cloners", and it mutually exclusive 408 * with all other flags/commands. 409 * 410 * -a means "print status of all interfaces". 411 */ 412 if ((lflag || Cflag) && (aflag || mflag || vflag || argc || zflag)) 413 usage(); 414#ifdef INET6 415 if ((lflag || Cflag) && Lflag) 416 usage(); 417#endif 418 if (lflag && Cflag) 419 usage(); 420 if (Cflag) { 421 if (argc) 422 usage(); 423 list_cloners(); 424 exit(0); 425 } 426 if (aflag || lflag) { 427 if (argc > 1) 428 usage(); 429 else if (argc == 1) { 430 afp = lookup_af_byname(argv[0]); 431 if (afp == NULL) 432 usage(); 433 } 434 if (afp) 435 af = ifr.ifr_addr.sa_family = afp->af_af; 436 else 437 af = ifr.ifr_addr.sa_family = afs[0].af_af; 438 printall(NULL); 439 exit(0); 440 } 441 442 /* Make sure there's an interface name. */ 443 if (argc < 1) 444 usage(); 445 if (strlcpy(name, argv[0], sizeof(name)) >= sizeof(name)) 446 errx(1, "interface name '%s' too long", argv[0]); 447 argc--; argv++; 448 449 /* 450 * NOTE: We must special-case the `create' command right 451 * here as we would otherwise fail in getinfo(). 452 */ 453 if (argc > 0 && strcmp(argv[0], "create") == 0) { 454 clone_create(argv[0], 0); 455 argc--, argv++; 456 if (argc == 0) 457 exit(0); 458 } 459 460 /* Check for address family. */ 461 afp = NULL; 462 if (argc > 0) { 463 afp = lookup_af_byname(argv[0]); 464 if (afp != NULL) { 465 argv++; 466 argc--; 467 } 468 } 469 470 /* Initialize af, just for use in getinfo(). */ 471 if (afp == NULL) 472 af = afs->af_af; 473 else 474 af = afp->af_af; 475 476 /* Get information about the interface. */ 477 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 478 if (getinfo(&ifr) < 0) 479 exit(1); 480 481 if (sflag) { 482 if (argc != 0) 483 usage(); 484 else 485 exit(carrier()); 486 } 487 488 /* No more arguments means interface status. */ 489 if (argc == 0) { 490 printall(name); 491 exit(0); 492 } 493 494 /* The following operations assume inet family as the default. */ 495 if (afp == NULL) 496 afp = afs; 497 af = ifr.ifr_addr.sa_family = afp->af_af; 498 499#ifdef INET6 500 in6_init(); 501#endif 502 503 /* Process commands. */ 504 while (argc > 0) { 505 const struct cmd *p; 506 507 for (p = cmds; p->c_name; p++) 508 if (strcmp(argv[0], p->c_name) == 0) 509 break; 510 if (p->c_name == 0 && setaddr) { 511 if ((flags & IFF_POINTOPOINT) == 0) { 512 errx(EXIT_FAILURE, 513 "can't set destination address %s", 514 "on non-point-to-point link"); 515 } 516 p++; /* got src, do dst */ 517 } 518 if (p->c_func != NULL || p->c_func2 != NULL) { 519 if (p->c_parameter == NEXTARG) { 520 if (argc < 2) 521 errx(EXIT_FAILURE, 522 "'%s' requires argument", 523 p->c_name); 524 (*p->c_func)(argv[1], 0); 525 argc--, argv++; 526 } else if (p->c_parameter == NEXTARG2) { 527 if (argc < 3) 528 errx(EXIT_FAILURE, 529 "'%s' requires 2 arguments", 530 p->c_name); 531 (*p->c_func2)(argv[1], argv[2]); 532 argc -= 2, argv += 2; 533 } else 534 (*p->c_func)(argv[0], p->c_parameter); 535 actions |= p->c_action; 536 } 537 argc--, argv++; 538 } 539 540 /* 541 * See if multiple alias, -alias, or delete commands were 542 * specified. More than one constitutes an invalid command line 543 */ 544 545 if (conflicting > 1) 546 errx(EXIT_FAILURE, 547 "Only one use of alias, -alias or delete is valid."); 548 549 /* Process any media commands that may have been issued. */ 550 process_media_commands(); 551 552 if (af == AF_INET6 && explicit_prefix == 0) { 553 /* 554 * Aggregatable address architecture defines all prefixes 555 * are 64. So, it is convenient to set prefixlen to 64 if 556 * it is not specified. 557 */ 558 setifprefixlen("64", 0); 559 /* in6_getprefix("64", MASK) if MASK is available here... */ 560 } 561 562#ifndef INET_ONLY 563 if (af == AF_ISO) 564 adjust_nsellength(); 565 566 if (af == AF_APPLETALK) 567 checkatrange(&addreq.ifra_addr); 568 569 if (setipdst && af == AF_NS) 570 xns_set_nsip_route(&addreq.ifra_addr, &addreq.ifra_dstaddr); 571#endif /* INET_ONLY */ 572 573 if (clearaddr) { 574 (void) strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 575 if (ioctl(s, afp->af_difaddr, afp->af_ridreq) == -1) 576 err(EXIT_FAILURE, "SIOCDIFADDR"); 577 } 578 if (newaddr > 0) { 579 (void) strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 580 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) == -1) 581 warn("SIOCAIFADDR"); 582 } 583 584 if (g_ifcr_updated) { 585 (void) strncpy(g_ifcr.ifcr_name, name, 586 sizeof(g_ifcr.ifcr_name)); 587 if (ioctl(s, SIOCSIFCAP, &g_ifcr) == -1) 588 err(EXIT_FAILURE, "SIOCSIFCAP"); 589 } 590 591 exit(0); 592} 593 594const struct afswtch * 595lookup_af_byname(const char *cp) 596{ 597 const struct afswtch *a; 598 599 for (a = afs; a->af_name != NULL; a++) 600 if (strcmp(a->af_name, cp) == 0) 601 return (a); 602 return (NULL); 603} 604 605const struct afswtch * 606lookup_af_bynum(int afnum) 607{ 608 const struct afswtch *a; 609 610 for (a = afs; a->af_name != NULL; a++) 611 if (a->af_af == afnum) 612 return (a); 613 return (NULL); 614} 615 616void 617getsock(int naf) 618{ 619 static int oaf = -1; 620 621 if (oaf == naf) 622 return; 623 if (oaf != -1) 624 close(s); 625 s = socket(naf, SOCK_DGRAM, 0); 626 if (s < 0) 627 oaf = -1; 628 else 629 oaf = naf; 630} 631 632int 633getinfo(struct ifreq *giifr) 634{ 635 636 getsock(af); 637 if (s < 0) 638 err(EXIT_FAILURE, "socket"); 639 if (ioctl(s, SIOCGIFFLAGS, giifr) == -1) { 640 warn("SIOCGIFFLAGS %s", giifr->ifr_name); 641 return (-1); 642 } 643 flags = giifr->ifr_flags; 644 if (ioctl(s, SIOCGIFMETRIC, giifr) == -1) { 645 warn("SIOCGIFMETRIC %s", giifr->ifr_name); 646 metric = 0; 647 } else 648 metric = giifr->ifr_metric; 649 if (ioctl(s, SIOCGIFMTU, giifr) == -1) 650 mtu = 0; 651 else 652 mtu = giifr->ifr_mtu; 653 654 memset(&g_ifcr, 0, sizeof(g_ifcr)); 655 strcpy(g_ifcr.ifcr_name, giifr->ifr_name); 656 (void) ioctl(s, SIOCGIFCAP, &g_ifcr); 657 658 return (0); 659} 660 661void 662printall(const char *ifname) 663{ 664 struct ifaddrs *ifap, *ifa; 665 struct ifreq paifr; 666 const struct sockaddr_dl *sdl = NULL; 667 int idx; 668 char *p; 669 670 if (getifaddrs(&ifap) != 0) 671 err(EXIT_FAILURE, "getifaddrs"); 672 p = NULL; 673 idx = 0; 674 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 675 memset(&paifr, 0, sizeof(paifr)); 676 strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 677 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 678 memcpy(&paifr.ifr_addr, ifa->ifa_addr, 679 ifa->ifa_addr->sa_len); 680 } 681 682 if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 683 continue; 684 if (ifa->ifa_addr->sa_family == AF_LINK) 685 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 686 if (p && strcmp(p, ifa->ifa_name) == 0) 687 continue; 688 if (strlcpy(name, ifa->ifa_name, sizeof(name)) >= sizeof(name)) 689 continue; 690 p = ifa->ifa_name; 691 692 if (getinfo(&paifr) < 0) 693 continue; 694 if (bflag && (ifa->ifa_flags & IFF_BROADCAST) == 0) 695 continue; 696 if (dflag && (ifa->ifa_flags & IFF_UP) != 0) 697 continue; 698 if (uflag && (ifa->ifa_flags & IFF_UP) == 0) 699 continue; 700 701 if (sflag && carrier()) 702 continue; 703 idx++; 704 /* 705 * Are we just listing the interfaces? 706 */ 707 if (lflag) { 708 if (idx > 1) 709 printf(" "); 710 fputs(name, stdout); 711 continue; 712 } 713 714 status(sdl); 715 sdl = NULL; 716 } 717 if (lflag) 718 printf("\n"); 719 freeifaddrs(ifap); 720} 721 722void 723list_cloners(void) 724{ 725 struct if_clonereq ifcr; 726 char *cp, *buf; 727 int idx; 728 729 memset(&ifcr, 0, sizeof(ifcr)); 730 731 getsock(AF_INET); 732 733 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 734 err(EXIT_FAILURE, "SIOCIFGCLONERS for count"); 735 736 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 737 if (buf == NULL) 738 err(EXIT_FAILURE, "unable to allocate cloner name buffer"); 739 740 ifcr.ifcr_count = ifcr.ifcr_total; 741 ifcr.ifcr_buffer = buf; 742 743 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 744 err(EXIT_FAILURE, "SIOCIFGCLONERS for names"); 745 746 /* 747 * In case some disappeared in the mean time, clamp it down. 748 */ 749 if (ifcr.ifcr_count > ifcr.ifcr_total) 750 ifcr.ifcr_count = ifcr.ifcr_total; 751 752 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 753 if (idx > 0) 754 printf(" "); 755 printf("%s", cp); 756 } 757 758 printf("\n"); 759 free(buf); 760 return; 761} 762 763/*ARGSUSED*/ 764void 765clone_create(const char *addr, int param) 766{ 767 768 /* We're called early... */ 769 getsock(AF_INET); 770 771 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 772 if (ioctl(s, SIOCIFCREATE, &ifr) == -1) 773 err(EXIT_FAILURE, "SIOCIFCREATE"); 774} 775 776/*ARGSUSED*/ 777void 778clone_destroy(const char *addr, int param) 779{ 780 781 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 782 if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) 783 err(EXIT_FAILURE, "SIOCIFDESTROY"); 784} 785 786/*ARGSUSED*/ 787void 788setifaddr(const char *addr, int param) 789{ 790 struct ifreq *siifr; /* XXX */ 791 792 /* 793 * Delay the ioctl to set the interface addr until flags are all set. 794 * The address interpretation may depend on the flags, 795 * and the flags may change when the address is set. 796 */ 797 setaddr++; 798 if (newaddr == -1) 799 newaddr = 1; 800 if (doalias == 0 && afp->af_gifaddr != 0) { 801 siifr = (struct ifreq *)afp->af_ridreq; 802 (void) strncpy(siifr->ifr_name, name, sizeof(siifr->ifr_name)); 803 siifr->ifr_addr.sa_family = afp->af_af; 804 if (ioctl(s, afp->af_gifaddr, afp->af_ridreq) == 0) 805 clearaddr = 1; 806 else if (errno == EADDRNOTAVAIL) 807 /* No address was assigned yet. */ 808 ; 809 else 810 err(EXIT_FAILURE, "SIOCGIFADDR"); 811 } 812 813 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 814} 815 816void 817setifnetmask(const char *addr, int d) 818{ 819 (*afp->af_getaddr)(addr, MASK); 820} 821 822void 823setifbroadaddr(const char *addr, int d) 824{ 825 (*afp->af_getaddr)(addr, DSTADDR); 826} 827 828#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 829/*ARGSUSED*/ 830void 831notealias(const char *addr, int param) 832{ 833 if (setaddr && doalias == 0 && param < 0) 834 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), 835 rqtosa(af_addreq)->sa_len); 836 doalias = param; 837 if (param < 0) { 838 clearaddr = 1; 839 newaddr = 0; 840 conflicting++; 841 } else { 842 clearaddr = 0; 843 conflicting++; 844 } 845} 846 847/*ARGSUSED*/ 848void 849notrailers(const char *vname, int value) 850{ 851 puts("Note: trailers are no longer sent, but always received"); 852} 853 854/*ARGSUSED*/ 855void 856setifdstaddr(const char *addr, int param) 857{ 858 (*afp->af_getaddr)(addr, DSTADDR); 859} 860 861void 862setifflags(const char *vname, int value) 863{ 864 struct ifreq ifreq; 865 866 (void) strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); 867 if (ioctl(s, SIOCGIFFLAGS, &ifreq) == -1) 868 err(EXIT_FAILURE, "SIOCGIFFLAGS"); 869 flags = ifreq.ifr_flags; 870 871 if (value < 0) { 872 value = -value; 873 flags &= ~value; 874 } else 875 flags |= value; 876 ifreq.ifr_flags = flags; 877 if (ioctl(s, SIOCSIFFLAGS, &ifreq) == -1) 878 err(EXIT_FAILURE, "SIOCSIFFLAGS"); 879} 880 881void 882setifcaps(const char *vname, int value) 883{ 884 885 if (value < 0) { 886 value = -value; 887 g_ifcr.ifcr_capenable &= ~value; 888 } else 889 g_ifcr.ifcr_capenable |= value; 890 891 g_ifcr_updated = 1; 892} 893 894void 895setifmetric(const char *val, int d) 896{ 897 char *ep = NULL; 898 899 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 900 ifr.ifr_metric = strtoul(val, &ep, 10); 901 if (!ep || *ep) 902 errx(EXIT_FAILURE, "%s: invalid metric", val); 903 if (ioctl(s, SIOCSIFMETRIC, &ifr) == -1) 904 warn("SIOCSIFMETRIC"); 905} 906 907void 908setifmtu(const char *val, int d) 909{ 910 char *ep = NULL; 911 912 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 913 ifr.ifr_mtu = strtoul(val, &ep, 10); 914 if (!ep || *ep) 915 errx(EXIT_FAILURE, "%s: invalid mtu", val); 916 if (ioctl(s, SIOCSIFMTU, &ifr) == -1) 917 warn("SIOCSIFMTU"); 918} 919 920const char * 921get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) 922{ 923 int len; 924 int hexstr; 925 u_int8_t *p; 926 927 len = *lenp; 928 p = buf; 929 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); 930 if (hexstr) 931 val += 2; 932 for (;;) { 933 if (*val == '\0') 934 break; 935 if (sep != NULL && strchr(sep, *val) != NULL) { 936 val++; 937 break; 938 } 939 if (hexstr) { 940 if (!isxdigit((u_char)val[0]) || 941 !isxdigit((u_char)val[1])) { 942 warnx("bad hexadecimal digits"); 943 return NULL; 944 } 945 } 946 if (p > buf + len) { 947 if (hexstr) 948 warnx("hexadecimal digits too long"); 949 else 950 warnx("strings too long"); 951 return NULL; 952 } 953 if (hexstr) { 954#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) 955 *p++ = (tohex((u_char)val[0]) << 4) | 956 tohex((u_char)val[1]); 957#undef tohex 958 val += 2; 959 } else 960 *p++ = *val++; 961 } 962 len = p - buf; 963 if (len < *lenp) 964 memset(p, 0, *lenp - len); 965 *lenp = len; 966 return val; 967} 968 969void 970print_string(const u_int8_t *buf, int len) 971{ 972 int i; 973 int hasspc; 974 975 i = 0; 976 hasspc = 0; 977 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { 978 for (; i < len; i++) { 979 if (!isprint(buf[i])) 980 break; 981 if (isspace(buf[i])) 982 hasspc++; 983 } 984 } 985 if (i == len) { 986 if (hasspc || len == 0) 987 printf("\"%.*s\"", len, buf); 988 else 989 printf("%.*s", len, buf); 990 } else { 991 printf("0x"); 992 for (i = 0; i < len; i++) 993 printf("%02x", buf[i]); 994 } 995} 996 997static void 998media_error(int type, const char *val, const char *opt) 999{ 1000 errx(EXIT_FAILURE, "unknown %s media %s: %s", 1001 get_media_type_string(type), opt, val); 1002} 1003 1004void 1005init_current_media(void) 1006{ 1007 struct ifmediareq ifmr; 1008 1009 /* 1010 * If we have not yet done so, grab the currently-selected 1011 * media. 1012 */ 1013 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { 1014 (void) memset(&ifmr, 0, sizeof(ifmr)); 1015 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1016 1017 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) { 1018 /* 1019 * If we get E2BIG, the kernel is telling us 1020 * that there are more, so we can ignore it. 1021 */ 1022 if (errno != E2BIG) 1023 err(EXIT_FAILURE, "SGIOCGIFMEDIA"); 1024 } 1025 1026 media_current = ifmr.ifm_current; 1027 } 1028 1029 /* Sanity. */ 1030 if (IFM_TYPE(media_current) == 0) 1031 errx(EXIT_FAILURE, "%s: no link type?", name); 1032} 1033 1034void 1035process_media_commands(void) 1036{ 1037 1038 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { 1039 /* Nothing to do. */ 1040 return; 1041 } 1042 1043 /* 1044 * Media already set up, and commands sanity-checked. Set/clear 1045 * any options, and we're ready to go. 1046 */ 1047 media_current |= mediaopt_set; 1048 media_current &= ~mediaopt_clear; 1049 1050 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1051 ifr.ifr_media = media_current; 1052 1053 if (ioctl(s, SIOCSIFMEDIA, &ifr) == -1) 1054 err(EXIT_FAILURE, "SIOCSIFMEDIA"); 1055} 1056 1057void 1058setmedia(const char *val, int d) 1059{ 1060 int type, subtype, inst; 1061 1062 init_current_media(); 1063 1064 /* Only one media command may be given. */ 1065 if (actions & A_MEDIA) 1066 errx(EXIT_FAILURE, "only one `media' command may be issued"); 1067 1068 /* Must not come after mode commands */ 1069 if (actions & A_MEDIAMODE) 1070 errx(EXIT_FAILURE, 1071 "may not issue `media' after `mode' commands"); 1072 1073 /* Must not come after mediaopt commands */ 1074 if (actions & A_MEDIAOPT) 1075 errx(EXIT_FAILURE, 1076 "may not issue `media' after `mediaopt' commands"); 1077 1078 /* 1079 * No need to check if `instance' has been issued; setmediainst() 1080 * craps out if `media' has not been specified. 1081 */ 1082 1083 type = IFM_TYPE(media_current); 1084 inst = IFM_INST(media_current); 1085 1086 /* Look up the subtype. */ 1087 subtype = get_media_subtype(type, val); 1088 if (subtype == -1) 1089 media_error(type, val, "subtype"); 1090 1091 /* Build the new current media word. */ 1092 media_current = IFM_MAKEWORD(type, subtype, 0, inst); 1093 1094 /* Media will be set after other processing is complete. */ 1095} 1096 1097void 1098setmediaopt(const char *val, int d) 1099{ 1100 char *invalid; 1101 1102 init_current_media(); 1103 1104 /* Can only issue `mediaopt' once. */ 1105 if (actions & A_MEDIAOPTSET) 1106 errx(EXIT_FAILURE, "only one `mediaopt' command may be issued"); 1107 1108 /* Can't issue `mediaopt' if `instance' has already been issued. */ 1109 if (actions & A_MEDIAINST) 1110 errx(EXIT_FAILURE, "may not issue `mediaopt' after `instance'"); 1111 1112 mediaopt_set = get_media_options(media_current, val, &invalid); 1113 if (mediaopt_set == -1) 1114 media_error(media_current, invalid, "option"); 1115 1116 /* Media will be set after other processing is complete. */ 1117} 1118 1119void 1120unsetmediaopt(const char *val, int d) 1121{ 1122 char *invalid; 1123 1124 init_current_media(); 1125 1126 /* Can only issue `-mediaopt' once. */ 1127 if (actions & A_MEDIAOPTCLR) 1128 errx(EXIT_FAILURE, 1129 "only one `-mediaopt' command may be issued"); 1130 1131 /* May not issue `media' and `-mediaopt'. */ 1132 if (actions & A_MEDIA) 1133 errx(EXIT_FAILURE, 1134 "may not issue both `media' and `-mediaopt'"); 1135 1136 /* 1137 * No need to check for A_MEDIAINST, since the test for A_MEDIA 1138 * implicitly checks for A_MEDIAINST. 1139 */ 1140 1141 mediaopt_clear = get_media_options(media_current, val, &invalid); 1142 if (mediaopt_clear == -1) 1143 media_error(media_current, invalid, "option"); 1144 1145 /* Media will be set after other processing is complete. */ 1146} 1147 1148void 1149setmediainst(const char *val, int d) 1150{ 1151 int type, subtype, options, inst; 1152 1153 init_current_media(); 1154 1155 /* Can only issue `instance' once. */ 1156 if (actions & A_MEDIAINST) 1157 errx(EXIT_FAILURE, "only one `instance' command may be issued"); 1158 1159 /* Must have already specified `media' */ 1160 if ((actions & A_MEDIA) == 0) 1161 errx(EXIT_FAILURE, "must specify `media' before `instance'"); 1162 1163 type = IFM_TYPE(media_current); 1164 subtype = IFM_SUBTYPE(media_current); 1165 options = IFM_OPTIONS(media_current); 1166 1167 inst = atoi(val); 1168 if (inst < 0 || inst > IFM_INST_MAX) 1169 errx(EXIT_FAILURE, "invalid media instance: %s", val); 1170 1171 media_current = IFM_MAKEWORD(type, subtype, options, inst); 1172 1173 /* Media will be set after other processing is complete. */ 1174} 1175 1176void 1177setmediamode(const char *val, int d) 1178{ 1179 int type, subtype, options, inst, mode; 1180 1181 init_current_media(); 1182 1183 /* Can only issue `mode' once. */ 1184 if (actions & A_MEDIAMODE) 1185 errx(EXIT_FAILURE, "only one `mode' command may be issued"); 1186 1187 type = IFM_TYPE(media_current); 1188 subtype = IFM_SUBTYPE(media_current); 1189 options = IFM_OPTIONS(media_current); 1190 inst = IFM_INST(media_current); 1191 1192 mode = get_media_mode(type, val); 1193 if (mode == -1) 1194 media_error(type, val, "mode"); 1195 1196 media_current = IFM_MAKEWORD(type, subtype, options, inst) | mode; 1197 1198 /* Media will be set after other processing is complete. */ 1199} 1200 1201void 1202print_media_word(int ifmw, const char *opt_sep) 1203{ 1204 const char *str; 1205 1206 printf("%s", get_media_subtype_string(ifmw)); 1207 1208 /* Find mode. */ 1209 if (IFM_MODE(ifmw) != 0) { 1210 str = get_media_mode_string(ifmw); 1211 if (str != NULL) 1212 printf(" mode %s", str); 1213 } 1214 1215 /* Find options. */ 1216 for (; (str = get_media_option_string(&ifmw)) != NULL; opt_sep = ",") 1217 printf("%s%s", opt_sep, str); 1218 1219 if (IFM_INST(ifmw) != 0) 1220 printf(" instance %d", IFM_INST(ifmw)); 1221} 1222 1223int 1224carrier(void) 1225{ 1226 struct ifmediareq ifmr; 1227 1228 (void) memset(&ifmr, 0, sizeof(ifmr)); 1229 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1230 1231 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) { 1232 /* 1233 * Interface doesn't support SIOC{G,S}IFMEDIA; 1234 * assume ok. 1235 */ 1236 return 0; 1237 } 1238 if ((ifmr.ifm_status & IFM_AVALID) == 0) { 1239 /* 1240 * Interface doesn't report media-valid status. 1241 * assume ok. 1242 */ 1243 return 0; 1244 } 1245 /* otherwise, return ok for active, not-ok if not active. */ 1246 return !(ifmr.ifm_status & IFM_ACTIVE); 1247} 1248 1249 1250const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 1251 1252const struct ifmedia_status_description ifm_status_descriptions[] = 1253 IFM_STATUS_DESCRIPTIONS; 1254 1255/* 1256 * Print the status of the interface. If an address family was 1257 * specified, show it and it only; otherwise, show them all. 1258 */ 1259void 1260status(const struct sockaddr_dl *sdl) 1261{ 1262 const struct afswtch *p = afp; 1263 struct ifmediareq ifmr; 1264 struct ifdatareq ifdr; 1265 int *media_list, i; 1266 char hbuf[NI_MAXHOST]; 1267 char fbuf[BUFSIZ]; 1268 1269 (void)snprintb(fbuf, sizeof(fbuf), IFFBITS, flags); 1270 printf("%s: flags=%s", name, &fbuf[2]); 1271 if (metric) 1272 printf(" metric %lu", metric); 1273 if (mtu) 1274 printf(" mtu %lu", mtu); 1275 printf("\n"); 1276 1277 if (g_ifcr.ifcr_capabilities) { 1278 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS, 1279 g_ifcr.ifcr_capabilities); 1280 printf("\tcapabilities=%s\n", &fbuf[2]); 1281 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS, 1282 g_ifcr.ifcr_capenable); 1283 printf("\tenabled=%s\n", &fbuf[2]); 1284 } 1285 1286 ieee80211_status(); 1287 vlan_status(); 1288 tunnel_status(); 1289 agr_status(); 1290 1291 if (sdl != NULL && 1292 getnameinfo((const struct sockaddr *)sdl, sdl->sdl_len, 1293 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0 && 1294 hbuf[0] != '\0') 1295 printf("\taddress: %s\n", hbuf); 1296 1297 (void) memset(&ifmr, 0, sizeof(ifmr)); 1298 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1299 1300 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) { 1301 /* 1302 * Interface doesn't support SIOC{G,S}IFMEDIA. 1303 */ 1304 goto iface_stats; 1305 } 1306 1307 if (ifmr.ifm_count == 0) { 1308 warnx("%s: no media types?", name); 1309 goto iface_stats; 1310 } 1311 1312 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 1313 if (media_list == NULL) 1314 err(EXIT_FAILURE, "malloc"); 1315 ifmr.ifm_ulist = media_list; 1316 1317 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) 1318 err(EXIT_FAILURE, "SIOCGIFMEDIA"); 1319 1320 printf("\tmedia: %s ", get_media_type_string(ifmr.ifm_current)); 1321 print_media_word(ifmr.ifm_current, " "); 1322 if (ifmr.ifm_active != ifmr.ifm_current) { 1323 printf(" ("); 1324 print_media_word(ifmr.ifm_active, " "); 1325 printf(")"); 1326 } 1327 printf("\n"); 1328 1329 if (ifmr.ifm_status & IFM_STATUS_VALID) { 1330 const struct ifmedia_status_description *ifms; 1331 int bitno, found = 0; 1332 1333 printf("\tstatus: "); 1334 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { 1335 for (ifms = ifm_status_descriptions; 1336 ifms->ifms_valid != 0; ifms++) { 1337 if (ifms->ifms_type != 1338 IFM_TYPE(ifmr.ifm_current) || 1339 ifms->ifms_valid != 1340 ifm_status_valid_list[bitno]) 1341 continue; 1342 printf("%s%s", found ? ", " : "", 1343 IFM_STATUS_DESC(ifms, ifmr.ifm_status)); 1344 found = 1; 1345 1346 /* 1347 * For each valid indicator bit, there's 1348 * only one entry for each media type, so 1349 * terminate the inner loop now. 1350 */ 1351 break; 1352 } 1353 } 1354 1355 if (found == 0) 1356 printf("unknown"); 1357 printf("\n"); 1358 } 1359 1360 if (mflag) { 1361 int type, printed_type; 1362 1363 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) { 1364 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { 1365 if (IFM_TYPE(media_list[i]) != type) 1366 continue; 1367 if (printed_type == 0) { 1368 printf("\tsupported %s media:\n", 1369 get_media_type_string(type)); 1370 printed_type = 1; 1371 } 1372 printf("\t\tmedia "); 1373 print_media_word(media_list[i], " mediaopt "); 1374 printf("\n"); 1375 } 1376 } 1377 } 1378 1379 free(media_list); 1380 1381 iface_stats: 1382 if (!vflag && !zflag) 1383 goto proto_status; 1384 1385 (void) strncpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name)); 1386 1387 if (ioctl(s, zflag ? SIOCZIFDATA:SIOCGIFDATA, &ifdr) == -1) { 1388 err(EXIT_FAILURE, zflag ? "SIOCZIFDATA" : "SIOCGIFDATA"); 1389 } else { 1390 struct if_data * const ifi = &ifdr.ifdr_data; 1391#define PLURAL(n) ((n) == 1 ? "" : "s") 1392 printf("\tinput: %llu packet%s, %llu byte%s", 1393 (unsigned long long) ifi->ifi_ipackets, 1394 PLURAL(ifi->ifi_ipackets), 1395 (unsigned long long) ifi->ifi_ibytes, 1396 PLURAL(ifi->ifi_ibytes)); 1397 if (ifi->ifi_imcasts) 1398 printf(", %llu multicast%s", 1399 (unsigned long long) ifi->ifi_imcasts, 1400 PLURAL(ifi->ifi_imcasts)); 1401 if (ifi->ifi_ierrors) 1402 printf(", %llu error%s", 1403 (unsigned long long) ifi->ifi_ierrors, 1404 PLURAL(ifi->ifi_ierrors)); 1405 if (ifi->ifi_iqdrops) 1406 printf(", %llu queue drop%s", 1407 (unsigned long long) ifi->ifi_iqdrops, 1408 PLURAL(ifi->ifi_iqdrops)); 1409 if (ifi->ifi_noproto) 1410 printf(", %llu unknown protocol", 1411 (unsigned long long) ifi->ifi_noproto); 1412 printf("\n\toutput: %llu packet%s, %llu byte%s", 1413 (unsigned long long) ifi->ifi_opackets, 1414 PLURAL(ifi->ifi_opackets), 1415 (unsigned long long) ifi->ifi_obytes, 1416 PLURAL(ifi->ifi_obytes)); 1417 if (ifi->ifi_omcasts) 1418 printf(", %llu multicast%s", 1419 (unsigned long long) ifi->ifi_omcasts, 1420 PLURAL(ifi->ifi_omcasts)); 1421 if (ifi->ifi_oerrors) 1422 printf(", %llu error%s", 1423 (unsigned long long) ifi->ifi_oerrors, 1424 PLURAL(ifi->ifi_oerrors)); 1425 if (ifi->ifi_collisions) 1426 printf(", %llu collision%s", 1427 (unsigned long long) ifi->ifi_collisions, 1428 PLURAL(ifi->ifi_collisions)); 1429 printf("\n"); 1430#undef PLURAL 1431 } 1432 1433 ieee80211_statistics(); 1434 1435 proto_status: 1436 if ((p = afp) != NULL) { 1437 (*p->af_status)(1); 1438 } else for (p = afs; p->af_name; p++) { 1439 ifr.ifr_addr.sa_family = p->af_af; 1440 (*p->af_status)(0); 1441 } 1442} 1443 1444void 1445setifprefixlen(const char *addr, int d) 1446{ 1447 if (*afp->af_getprefix) 1448 (*afp->af_getprefix)(addr, MASK); 1449 explicit_prefix = 1; 1450} 1451 1452void 1453usage(void) 1454{ 1455 const char *progname = getprogname(); 1456 1457 fprintf(stderr, 1458 "usage: %s [-m] [-v] [-z] " 1459#ifdef INET6 1460 "[-L] " 1461#endif 1462 "interface\n" 1463 "\t[ af [ address [ dest_addr ] ] [ netmask mask ] [ prefixlen n ]\n" 1464 "\t\t[ alias | -alias ] ]\n" 1465 "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n" 1466 "\t[ nwid network_id ] [ nwkey network_key | -nwkey ]\n" 1467 "\t[ powersave | -powersave ] [ powersavesleep duration ]\n" 1468 "\t[ [ af ] tunnel src_addr dest_addr ] [ deletetunnel ]\n" 1469 "\t[ arp | -arp ]\n" 1470 "\t[ media type ] [ mediaopt opts ] [ -mediaopt opts ] " 1471 "[ instance minst ]\n" 1472 "\t[ vlan n vlanif i ]\n" 1473 "\t[ agrport i ] [ -agrport i ]\n" 1474 "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n" 1475 "\t[ tentative | -tentative ] [ pltime n ] [ vltime n ] [ eui64 ]\n" 1476 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n" 1477 " %s -a [-b] [-m] [-d] [-u] [-v] [-z] [ af ]\n" 1478 " %s -l [-b] [-d] [-u] [-s]\n" 1479 " %s -C\n" 1480 " %s interface create\n" 1481 " %s interface destroy\n", 1482 progname, progname, progname, progname, progname, progname); 1483 exit(1); 1484} 1485