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