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