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