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