1 /* $NetBSD: ifconfig.c,v 1.133 2002/09/30 05:38:13 onoe 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. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by the University of 55 * California, Berkeley and its contributors. 56 * 4. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 */ 72 73 #include <sys/cdefs.h> 74 #ifndef lint 75 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\ 76 The Regents of the University of California. All rights reserved.\n"); 77 #endif /* not lint */ 78 79 #ifndef lint 80 #if 0 81 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 82 #else 83 __RCSID("$NetBSD: ifconfig.c,v 1.133 2002/09/30 05:38:13 onoe Exp $"); 84 #endif 85 #endif /* not lint */ 86 87 #include <sys/param.h> 88 #include <sys/socket.h> 89 #include <sys/ioctl.h> 90 91 #include <net/if.h> 92 #include <net/if_dl.h> 93 #include <net/if_media.h> 94 #include <net/if_ether.h> 95 #include <net/if_ieee80211.h> 96 #include <net/if_vlanvar.h> 97 #include <netinet/in.h> 98 #include <netinet/in_var.h> 99 #ifdef INET6 100 #include <netinet6/nd6.h> 101 #endif 102 #include <arpa/inet.h> 103 104 #include <netatalk/at.h> 105 106 #define NSIP 107 #include <netns/ns.h> 108 #include <netns/ns_if.h> 109 #include <netdb.h> 110 111 #define EON 112 #include <netiso/iso.h> 113 #include <netiso/iso_var.h> 114 #include <sys/protosw.h> 115 116 #include <ctype.h> 117 #include <err.h> 118 #include <errno.h> 119 #include <stddef.h> 120 #include <stdio.h> 121 #include <stdlib.h> 122 #include <string.h> 123 #include <unistd.h> 124 #include <ifaddrs.h> 125 #include <util.h> 126 127 struct ifreq ifr, ridreq; 128 struct ifaliasreq addreq __attribute__((aligned(4))); 129 struct in_aliasreq in_addreq; 130 #ifdef INET6 131 struct in6_ifreq ifr6; 132 struct in6_ifreq in6_ridreq; 133 struct in6_aliasreq in6_addreq; 134 #endif 135 struct iso_ifreq iso_ridreq; 136 struct iso_aliasreq iso_addreq; 137 struct sockaddr_in netmask; 138 struct netrange at_nr; /* AppleTalk net range */ 139 140 char name[30]; 141 u_short flags; 142 int setaddr, setipdst, doalias; 143 u_long metric, mtu; 144 int clearaddr, s; 145 int newaddr = -1; 146 int conflicting = 0; 147 int nsellength = 1; 148 int af; 149 int aflag, bflag, Cflag, dflag, lflag, mflag, sflag, uflag, vflag; 150 #ifdef INET6 151 int Lflag; 152 #endif 153 int reset_if_flags; 154 int explicit_prefix = 0; 155 u_int vlan_tag = (u_int)-1; 156 157 struct ifcapreq g_ifcr; 158 int g_ifcr_updated; 159 160 void notealias __P((const char *, int)); 161 void notrailers __P((const char *, int)); 162 void setifaddr __P((const char *, int)); 163 void setifdstaddr __P((const char *, int)); 164 void setifflags __P((const char *, int)); 165 void setifcaps __P((const char *, int)); 166 void setifbroadaddr __P((const char *, int)); 167 void setifipdst __P((const char *, int)); 168 void setifmetric __P((const char *, int)); 169 void setifmtu __P((const char *, int)); 170 void setifnwid __P((const char *, int)); 171 void setifnwkey __P((const char *, int)); 172 void setifbssid __P((const char *, int)); 173 void setifchan __P((const char *, int)); 174 void setifpowersave __P((const char *, int)); 175 void setifpowersavesleep __P((const char *, int)); 176 void setifnetmask __P((const char *, int)); 177 void setifprefixlen __P((const char *, int)); 178 void setnsellength __P((const char *, int)); 179 void setsnpaoffset __P((const char *, int)); 180 void setatrange __P((const char *, int)); 181 void setatphase __P((const char *, int)); 182 void settunnel __P((const char *, const char *)); 183 void deletetunnel __P((const char *, int)); 184 #ifdef INET6 185 void setia6flags __P((const char *, int)); 186 void setia6pltime __P((const char *, int)); 187 void setia6vltime __P((const char *, int)); 188 void setia6lifetime __P((const char *, const char *)); 189 void setia6eui64 __P((const char *, int)); 190 #endif 191 void checkatrange __P ((struct sockaddr_at *)); 192 void setmedia __P((const char *, int)); 193 void setmediaopt __P((const char *, int)); 194 void unsetmediaopt __P((const char *, int)); 195 void setmediainst __P((const char *, int)); 196 void clone_create __P((const char *, int)); 197 void clone_destroy __P((const char *, int)); 198 void fixnsel __P((struct sockaddr_iso *)); 199 void setvlan __P((const char *, int)); 200 void setvlanif __P((const char *, int)); 201 void unsetvlanif __P((const char *, int)); 202 int main __P((int, char *[])); 203 204 /* 205 * Media stuff. Whenever a media command is first performed, the 206 * currently select media is grabbed for this interface. If `media' 207 * is given, the current media word is modifed. `mediaopt' commands 208 * only modify the set and clear words. They then operate on the 209 * current media word later. 210 */ 211 int media_current; 212 int mediaopt_set; 213 int mediaopt_clear; 214 215 int actions; /* Actions performed */ 216 217 #define A_MEDIA 0x0001 /* media command */ 218 #define A_MEDIAOPTSET 0x0002 /* mediaopt command */ 219 #define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */ 220 #define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR) 221 #define A_MEDIAINST 0x0008 /* instance or inst command */ 222 223 #define NEXTARG 0xffffff 224 #define NEXTARG2 0xfffffe 225 226 const struct cmd { 227 const char *c_name; 228 int c_parameter; /* NEXTARG means next argv */ 229 int c_action; /* defered action */ 230 void (*c_func) __P((const char *, int)); 231 void (*c_func2) __P((const char *, const char *)); 232 } cmds[] = { 233 { "up", IFF_UP, 0, setifflags } , 234 { "down", -IFF_UP, 0, setifflags }, 235 { "trailers", -1, 0, notrailers }, 236 { "-trailers", 1, 0, notrailers }, 237 { "arp", -IFF_NOARP, 0, setifflags }, 238 { "-arp", IFF_NOARP, 0, setifflags }, 239 { "debug", IFF_DEBUG, 0, setifflags }, 240 { "-debug", -IFF_DEBUG, 0, setifflags }, 241 { "alias", IFF_UP, 0, notealias }, 242 { "-alias", -IFF_UP, 0, notealias }, 243 { "delete", -IFF_UP, 0, notealias }, 244 #ifdef notdef 245 #define EN_SWABIPS 0x1000 246 { "swabips", EN_SWABIPS, 0, setifflags }, 247 { "-swabips", -EN_SWABIPS, 0, setifflags }, 248 #endif 249 { "netmask", NEXTARG, 0, setifnetmask }, 250 { "metric", NEXTARG, 0, setifmetric }, 251 { "mtu", NEXTARG, 0, setifmtu }, 252 { "bssid", NEXTARG, 0, setifbssid }, 253 { "-bssid", -1, 0, setifbssid }, 254 { "chan", NEXTARG, 0, setifchan }, 255 { "-chan", -1, 0, setifchan }, 256 { "nwid", NEXTARG, 0, setifnwid }, 257 { "nwkey", NEXTARG, 0, setifnwkey }, 258 { "-nwkey", -1, 0, setifnwkey }, 259 { "powersave", 1, 0, setifpowersave }, 260 { "-powersave", 0, 0, setifpowersave }, 261 { "powersavesleep", NEXTARG, 0, setifpowersavesleep }, 262 { "broadcast", NEXTARG, 0, setifbroadaddr }, 263 { "ipdst", NEXTARG, 0, setifipdst }, 264 { "prefixlen", NEXTARG, 0, setifprefixlen}, 265 #ifdef INET6 266 { "anycast", IN6_IFF_ANYCAST, 0, setia6flags }, 267 { "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags }, 268 { "tentative", IN6_IFF_TENTATIVE, 0, setia6flags }, 269 { "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags }, 270 { "deprecated", IN6_IFF_DEPRECATED, 0, setia6flags }, 271 { "-deprecated", -IN6_IFF_DEPRECATED, 0, setia6flags }, 272 { "pltime", NEXTARG, 0, setia6pltime }, 273 { "vltime", NEXTARG, 0, setia6vltime }, 274 { "eui64", 0, 0, setia6eui64 }, 275 #endif /*INET6*/ 276 #ifndef INET_ONLY 277 { "range", NEXTARG, 0, setatrange }, 278 { "phase", NEXTARG, 0, setatphase }, 279 { "snpaoffset", NEXTARG, 0, setsnpaoffset }, 280 { "nsellength", NEXTARG, 0, setnsellength }, 281 #endif /* INET_ONLY */ 282 { "tunnel", NEXTARG2, 0, NULL, 283 settunnel } , 284 { "deletetunnel", 0, 0, deletetunnel }, 285 { "vlan", NEXTARG, 0, setvlan } , 286 { "vlanif", NEXTARG, 0, setvlanif } , 287 { "-vlanif", 0, 0, unsetvlanif } , 288 #if 0 289 /* XXX `create' special-cased below */ 290 { "create", 0, 0, clone_create } , 291 #endif 292 { "destroy", 0, 0, clone_destroy } , 293 { "link0", IFF_LINK0, 0, setifflags } , 294 { "-link0", -IFF_LINK0, 0, setifflags } , 295 { "link1", IFF_LINK1, 0, setifflags } , 296 { "-link1", -IFF_LINK1, 0, setifflags } , 297 { "link2", IFF_LINK2, 0, setifflags } , 298 { "-link2", -IFF_LINK2, 0, setifflags } , 299 { "media", NEXTARG, A_MEDIA, setmedia }, 300 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt }, 301 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt }, 302 { "instance", NEXTARG, A_MEDIAINST, setmediainst }, 303 { "inst", NEXTARG, A_MEDIAINST, setmediainst }, 304 { "ip4csum", IFCAP_CSUM_IPv4,0, setifcaps }, 305 { "-ip4csum", -IFCAP_CSUM_IPv4,0, setifcaps }, 306 { "tcp4csum", IFCAP_CSUM_TCPv4,0, setifcaps }, 307 { "-tcp4csum", -IFCAP_CSUM_TCPv4,0, setifcaps }, 308 { "udp4csum", IFCAP_CSUM_UDPv4,0, setifcaps }, 309 { "-udp4csum", -IFCAP_CSUM_UDPv4,0, setifcaps }, 310 { "tcp6csum", IFCAP_CSUM_TCPv6,0, setifcaps }, 311 { "-tcp6csum", -IFCAP_CSUM_TCPv6,0, setifcaps }, 312 { "udp6csum", IFCAP_CSUM_UDPv6,0, setifcaps }, 313 { "-udp6csum", -IFCAP_CSUM_UDPv6,0, setifcaps }, 314 { "tcp4csum-rx",IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 315 { "-tcp4csum-rx",-IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 316 { "udp4csum-rx",IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 317 { "-udp4csum-rx",-IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 318 { 0, 0, 0, setifaddr }, 319 { 0, 0, 0, setifdstaddr }, 320 }; 321 322 void adjust_nsellength __P((void)); 323 int getinfo __P((struct ifreq *)); 324 int carrier __P((void)); 325 void getsock __P((int)); 326 void printall __P((const char *)); 327 void list_cloners __P((void)); 328 int prefix __P((void *, int)); 329 void status __P((const struct sockaddr_dl *)); 330 void usage __P((void)); 331 const char *get_string __P((const char *, const char *, u_int8_t *, int *)); 332 void print_string __P((const u_int8_t *, int)); 333 char *sec2str __P((time_t)); 334 335 const char *get_media_type_string __P((int)); 336 const char *get_media_subtype_string __P((int)); 337 int get_media_subtype __P((int, const char *)); 338 int get_media_options __P((int, const char *)); 339 int lookup_media_word __P((struct ifmedia_description *, int, 340 const char *)); 341 void print_media_word __P((int, int, int)); 342 void process_media_commands __P((void)); 343 void init_current_media __P((void)); 344 345 /* 346 * XNS support liberally adapted from code written at the University of 347 * Maryland principally by James O'Toole and Chris Torek. 348 */ 349 void in_alias __P((struct ifreq *)); 350 void in_status __P((int)); 351 void in_getaddr __P((const char *, int)); 352 void in_getprefix __P((const char *, int)); 353 #ifdef INET6 354 void in6_fillscopeid __P((struct sockaddr_in6 *sin6)); 355 void in6_alias __P((struct in6_ifreq *)); 356 void in6_status __P((int)); 357 void in6_getaddr __P((const char *, int)); 358 void in6_getprefix __P((const char *, int)); 359 #endif 360 void at_status __P((int)); 361 void at_getaddr __P((const char *, int)); 362 void xns_status __P((int)); 363 void xns_getaddr __P((const char *, int)); 364 void iso_status __P((int)); 365 void iso_getaddr __P((const char *, int)); 366 367 void ieee80211_status __P((void)); 368 void tunnel_status __P((void)); 369 void vlan_status __P((void)); 370 371 /* Known address families */ 372 struct afswtch { 373 const char *af_name; 374 short af_af; 375 void (*af_status) __P((int)); 376 void (*af_getaddr) __P((const char *, int)); 377 void (*af_getprefix) __P((const char *, int)); 378 u_long af_difaddr; 379 u_long af_aifaddr; 380 u_long af_gifaddr; 381 caddr_t af_ridreq; 382 caddr_t af_addreq; 383 } afs[] = { 384 #define C(x) ((caddr_t) &x) 385 { "inet", AF_INET, in_status, in_getaddr, in_getprefix, 386 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, C(ridreq), C(in_addreq) }, 387 #ifdef INET6 388 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 389 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 390 /* 391 * Deleting the first address before setting new one is 392 * not prefered way in this protocol. 393 */ 394 0, 395 C(in6_ridreq), C(in6_addreq) }, 396 #endif 397 #ifndef INET_ONLY /* small version, for boot media */ 398 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 399 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, C(addreq), C(addreq) }, 400 { "ns", AF_NS, xns_status, xns_getaddr, NULL, 401 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, C(ridreq), C(addreq) }, 402 { "iso", AF_ISO, iso_status, iso_getaddr, NULL, 403 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, SIOCGIFADDR_ISO, 404 C(iso_ridreq), C(iso_addreq) }, 405 #endif /* INET_ONLY */ 406 { 0, 0, 0, 0 } 407 }; 408 409 struct afswtch *afp; /*the address family being set or asked about*/ 410 411 struct afswtch *lookup_af __P((const char *)); 412 413 int 414 main(argc, argv) 415 int argc; 416 char *argv[]; 417 { 418 struct ifreq ifreq; 419 int ch; 420 421 /* Parse command-line options */ 422 aflag = mflag = vflag = 0; 423 while ((ch = getopt(argc, argv, "AabCdlmsuv" 424 #ifdef INET6 425 "L" 426 #endif 427 )) != -1) { 428 switch (ch) { 429 case 'A': 430 warnx("-A is deprecated"); 431 break; 432 433 case 'a': 434 aflag = 1; 435 break; 436 437 case 'b': 438 bflag = 1; 439 break; 440 441 442 case 'C': 443 Cflag = 1; 444 break; 445 446 case 'd': 447 dflag = 1; 448 break; 449 450 #ifdef INET6 451 case 'L': 452 Lflag = 1; 453 break; 454 #endif 455 456 case 'l': 457 lflag = 1; 458 break; 459 460 case 'm': 461 mflag = 1; 462 break; 463 464 case 's': 465 sflag = 1; 466 break; 467 468 case 'u': 469 uflag = 1; 470 break; 471 472 case 'v': 473 vflag = 1; 474 break; 475 476 477 default: 478 usage(); 479 /* NOTREACHED */ 480 } 481 } 482 argc -= optind; 483 argv += optind; 484 485 /* 486 * -l means "list all interfaces", and is mutally exclusive with 487 * all other flags/commands. 488 * 489 * -C means "list all names of cloners", and it mutually exclusive 490 * with all other flags/commands. 491 * 492 * -a means "print status of all interfaces". 493 */ 494 if ((lflag || Cflag) && (aflag || mflag || vflag || argc)) 495 usage(); 496 #ifdef INET6 497 if ((lflag || Cflag) && Lflag) 498 usage(); 499 #endif 500 if (lflag && Cflag) 501 usage(); 502 if (Cflag) { 503 if (argc) 504 usage(); 505 list_cloners(); 506 exit(0); 507 } 508 if (aflag || lflag) { 509 if (argc > 1) 510 usage(); 511 else if (argc == 1) { 512 afp = lookup_af(argv[0]); 513 if (afp == NULL) 514 usage(); 515 } 516 if (afp) 517 af = ifr.ifr_addr.sa_family = afp->af_af; 518 else 519 af = ifr.ifr_addr.sa_family = afs[0].af_af; 520 printall(NULL); 521 exit(0); 522 } 523 524 /* Make sure there's an interface name. */ 525 if (argc < 1) 526 usage(); 527 (void) strncpy(name, argv[0], sizeof(name)); 528 argc--; argv++; 529 530 /* 531 * NOTE: We must special-case the `create' command right 532 * here as we would otherwise fail in getinfo(). 533 */ 534 if (argc > 0 && strcmp(argv[0], "create") == 0) { 535 clone_create(argv[0], 0); 536 argc--, argv++; 537 if (argc == 0) 538 exit(0); 539 } 540 541 /* Check for address family. */ 542 afp = NULL; 543 if (argc > 0) { 544 afp = lookup_af(argv[0]); 545 if (afp != NULL) { 546 argv++; 547 argc--; 548 } 549 } 550 551 /* Initialize af, just for use in getinfo(). */ 552 if (afp == NULL) 553 af = afs->af_af; 554 else 555 af = afp->af_af; 556 557 /* Get information about the interface. */ 558 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 559 if (getinfo(&ifr) < 0) 560 exit(1); 561 562 if (sflag) { 563 if (argc != 0) 564 usage(); 565 else 566 exit(carrier()); 567 } 568 569 /* No more arguments means interface status. */ 570 if (argc == 0) { 571 printall(name); 572 exit(0); 573 } 574 575 /* The following operations assume inet family as the default. */ 576 if (afp == NULL) 577 afp = afs; 578 af = ifr.ifr_addr.sa_family = afp->af_af; 579 580 #ifdef INET6 581 /* initialization */ 582 in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 583 in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 584 #endif 585 586 /* Process commands. */ 587 while (argc > 0) { 588 const struct cmd *p; 589 590 for (p = cmds; p->c_name; p++) 591 if (strcmp(argv[0], p->c_name) == 0) 592 break; 593 if (p->c_name == 0 && setaddr) { 594 if ((flags & IFF_POINTOPOINT) == 0) { 595 errx(EXIT_FAILURE, 596 "can't set destination address %s", 597 "on non-point-to-point link"); 598 } 599 p++; /* got src, do dst */ 600 } 601 if (p->c_func != NULL || p->c_func2 != NULL) { 602 if (p->c_parameter == NEXTARG) { 603 if (argc < 2) 604 errx(EXIT_FAILURE, 605 "'%s' requires argument", 606 p->c_name); 607 (*p->c_func)(argv[1], 0); 608 argc--, argv++; 609 } else if (p->c_parameter == NEXTARG2) { 610 if (argc < 3) 611 errx(EXIT_FAILURE, 612 "'%s' requires 2 arguments", 613 p->c_name); 614 (*p->c_func2)(argv[1], argv[2]); 615 argc -= 2, argv += 2; 616 } else 617 (*p->c_func)(argv[0], p->c_parameter); 618 actions |= p->c_action; 619 } 620 argc--, argv++; 621 } 622 623 /* 624 * See if multiple alias, -alias, or delete commands were 625 * specified. More than one constitutes an invalid command line 626 */ 627 628 if (conflicting > 1) 629 err(EXIT_FAILURE, 630 "Only one use of alias, -alias or delete is valid."); 631 632 /* Process any media commands that may have been issued. */ 633 process_media_commands(); 634 635 if (af == AF_INET6 && explicit_prefix == 0) { 636 /* 637 * Aggregatable address architecture defines all prefixes 638 * are 64. So, it is convenient to set prefixlen to 64 if 639 * it is not specified. 640 */ 641 setifprefixlen("64", 0); 642 /* in6_getprefix("64", MASK) if MASK is available here... */ 643 } 644 645 #ifndef INET_ONLY 646 if (af == AF_ISO) 647 adjust_nsellength(); 648 649 if (af == AF_APPLETALK) 650 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 651 652 if (setipdst && af==AF_NS) { 653 struct nsip_req rq; 654 int size = sizeof(rq); 655 656 rq.rq_ns = addreq.ifra_addr; 657 rq.rq_ip = addreq.ifra_dstaddr; 658 659 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 660 warn("encapsulation routing"); 661 } 662 663 #endif /* INET_ONLY */ 664 665 if (clearaddr) { 666 (void) strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 667 if (ioctl(s, afp->af_difaddr, afp->af_ridreq) == -1) 668 err(EXIT_FAILURE, "SIOCDIFADDR"); 669 } 670 if (newaddr > 0) { 671 (void) strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 672 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) == -1) 673 warn("SIOCAIFADDR"); 674 } 675 676 if (g_ifcr_updated) { 677 (void) strncpy(g_ifcr.ifcr_name, name, 678 sizeof(g_ifcr.ifcr_name)); 679 if (ioctl(s, SIOCSIFCAP, (caddr_t) &g_ifcr) == -1) 680 err(EXIT_FAILURE, "SIOCSIFCAP"); 681 } 682 683 if (reset_if_flags) { 684 (void) strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); 685 ifreq.ifr_flags = flags; 686 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifreq) == -1) 687 err(EXIT_FAILURE, "SIOCSIFFLAGS"); 688 } 689 exit(0); 690 } 691 692 struct afswtch * 693 lookup_af(cp) 694 const char *cp; 695 { 696 struct afswtch *a; 697 698 for (a = afs; a->af_name != NULL; a++) 699 if (strcmp(a->af_name, cp) == 0) 700 return (a); 701 return (NULL); 702 } 703 704 void 705 getsock(naf) 706 int naf; 707 { 708 static int oaf = -1; 709 710 if (oaf == naf) 711 return; 712 if (oaf != -1) 713 close(s); 714 s = socket(naf, SOCK_DGRAM, 0); 715 if (s < 0) 716 oaf = -1; 717 else 718 oaf = naf; 719 } 720 721 int 722 getinfo(giifr) 723 struct ifreq *giifr; 724 { 725 726 getsock(af); 727 if (s < 0) 728 err(EXIT_FAILURE, "socket"); 729 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)giifr) == -1) { 730 warn("SIOCGIFFLAGS %s", giifr->ifr_name); 731 return (-1); 732 } 733 flags = giifr->ifr_flags; 734 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)giifr) == -1) { 735 warn("SIOCGIFMETRIC %s", giifr->ifr_name); 736 metric = 0; 737 } else 738 metric = giifr->ifr_metric; 739 if (ioctl(s, SIOCGIFMTU, (caddr_t)giifr) == -1) 740 mtu = 0; 741 else 742 mtu = giifr->ifr_mtu; 743 744 memset(&g_ifcr, 0, sizeof(g_ifcr)); 745 strcpy(g_ifcr.ifcr_name, giifr->ifr_name); 746 (void) ioctl(s, SIOCGIFCAP, (caddr_t) &g_ifcr); 747 748 return (0); 749 } 750 751 void 752 printall(ifname) 753 const char *ifname; 754 { 755 struct ifaddrs *ifap, *ifa; 756 struct ifreq paifr; 757 const struct sockaddr_dl *sdl = NULL; 758 int idx; 759 char *p; 760 761 if (getifaddrs(&ifap) != 0) 762 err(EXIT_FAILURE, "getifaddrs"); 763 p = NULL; 764 idx = 0; 765 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 766 memset(&paifr, 0, sizeof(paifr)); 767 strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 768 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 769 memcpy(&paifr.ifr_addr, ifa->ifa_addr, 770 ifa->ifa_addr->sa_len); 771 } 772 773 if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 774 continue; 775 if (ifa->ifa_addr->sa_family == AF_LINK) 776 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 777 if (p && strcmp(p, ifa->ifa_name) == 0) 778 continue; 779 (void) strncpy(name, ifa->ifa_name, sizeof(name)); 780 name[sizeof(name) - 1] = '\0'; 781 p = ifa->ifa_name; 782 783 if (getinfo(&paifr) < 0) 784 continue; 785 if (bflag && (ifa->ifa_flags & (IFF_POINTOPOINT|IFF_LOOPBACK))) 786 continue; 787 if (dflag && (ifa->ifa_flags & IFF_UP) != 0) 788 continue; 789 if (uflag && (ifa->ifa_flags & IFF_UP) == 0) 790 continue; 791 792 if (sflag && carrier()) 793 continue; 794 idx++; 795 /* 796 * Are we just listing the interfaces? 797 */ 798 if (lflag) { 799 if (idx > 1) 800 putchar(' '); 801 fputs(name, stdout); 802 continue; 803 } 804 805 status(sdl); 806 sdl = NULL; 807 } 808 if (lflag) 809 putchar('\n'); 810 freeifaddrs(ifap); 811 } 812 813 void 814 list_cloners(void) 815 { 816 struct if_clonereq ifcr; 817 char *cp, *buf; 818 int idx; 819 820 memset(&ifcr, 0, sizeof(ifcr)); 821 822 getsock(AF_INET); 823 824 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 825 err(EXIT_FAILURE, "SIOCIFGCLONERS for count"); 826 827 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 828 if (buf == NULL) 829 err(EXIT_FAILURE, "unable to allocate cloner name buffer"); 830 831 ifcr.ifcr_count = ifcr.ifcr_total; 832 ifcr.ifcr_buffer = buf; 833 834 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 835 err(EXIT_FAILURE, "SIOCIFGCLONERS for names"); 836 837 /* 838 * In case some disappeared in the mean time, clamp it down. 839 */ 840 if (ifcr.ifcr_count > ifcr.ifcr_total) 841 ifcr.ifcr_count = ifcr.ifcr_total; 842 843 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 844 if (idx > 0) 845 putchar(' '); 846 printf("%s", cp); 847 } 848 849 putchar('\n'); 850 free(buf); 851 return; 852 } 853 854 /*ARGSUSED*/ 855 void 856 clone_create(addr, param) 857 const char *addr; 858 int param; 859 { 860 861 /* We're called early... */ 862 getsock(AF_INET); 863 864 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 865 if (ioctl(s, SIOCIFCREATE, &ifr) == -1) 866 err(EXIT_FAILURE, "SIOCIFCREATE"); 867 } 868 869 /*ARGSUSED*/ 870 void 871 clone_destroy(addr, param) 872 const char *addr; 873 int param; 874 { 875 876 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 877 if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) 878 err(EXIT_FAILURE, "SIOCIFDESTROY"); 879 } 880 881 #define RIDADDR 0 882 #define ADDR 1 883 #define MASK 2 884 #define DSTADDR 3 885 886 /*ARGSUSED*/ 887 void 888 setifaddr(addr, param) 889 const char *addr; 890 int param; 891 { 892 struct ifreq *siifr; /* XXX */ 893 894 /* 895 * Delay the ioctl to set the interface addr until flags are all set. 896 * The address interpretation may depend on the flags, 897 * and the flags may change when the address is set. 898 */ 899 setaddr++; 900 if (newaddr == -1) 901 newaddr = 1; 902 if (doalias == 0 && afp->af_gifaddr != 0) { 903 siifr = (struct ifreq *)afp->af_ridreq; 904 (void) strncpy(siifr->ifr_name, name, sizeof(siifr->ifr_name)); 905 siifr->ifr_addr.sa_family = afp->af_af; 906 if (ioctl(s, afp->af_gifaddr, afp->af_ridreq) == 0) 907 clearaddr = 1; 908 else if (errno == EADDRNOTAVAIL) 909 /* No address was assigned yet. */ 910 ; 911 else 912 err(EXIT_FAILURE, "SIOCGIFADDR"); 913 } 914 915 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 916 } 917 918 void 919 settunnel(src, dst) 920 const char *src, *dst; 921 { 922 struct addrinfo hints, *srcres, *dstres; 923 int ecode; 924 struct if_laddrreq req; 925 926 memset(&hints, 0, sizeof(hints)); 927 hints.ai_family = afp->af_af; 928 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 929 930 if ((ecode = getaddrinfo(src, NULL, &hints, &srcres)) != 0) 931 errx(EXIT_FAILURE, "error in parsing address string: %s", 932 gai_strerror(ecode)); 933 934 if ((ecode = getaddrinfo(dst, NULL, &hints, &dstres)) != 0) 935 errx(EXIT_FAILURE, "error in parsing address string: %s", 936 gai_strerror(ecode)); 937 938 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 939 errx(EXIT_FAILURE, 940 "source and destination address families do not match"); 941 942 if (srcres->ai_addrlen > sizeof(req.addr) || 943 dstres->ai_addrlen > sizeof(req.dstaddr)) 944 errx(EXIT_FAILURE, "invalid sockaddr"); 945 946 memset(&req, 0, sizeof(req)); 947 strncpy(req.iflr_name, name, sizeof(req.iflr_name)); 948 memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); 949 memcpy(&req.dstaddr, dstres->ai_addr, dstres->ai_addrlen); 950 951 #ifdef INET6 952 if (req.addr.ss_family == AF_INET6) { 953 struct sockaddr_in6 *s6, *d; 954 955 s6 = (struct sockaddr_in6 *)&req.addr; 956 d = (struct sockaddr_in6 *)&req.dstaddr; 957 if (s6->sin6_scope_id != d->sin6_scope_id) { 958 errx(EXIT_FAILURE, "scope mismatch"); 959 /* NOTREACHED */ 960 } 961 #ifdef __KAME__ 962 /* embed scopeid */ 963 if (s6->sin6_scope_id && 964 (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr) || 965 IN6_IS_ADDR_MC_LINKLOCAL(&s6->sin6_addr))) { 966 *(u_int16_t *)&s6->sin6_addr.s6_addr[2] = 967 htons(s6->sin6_scope_id); 968 } 969 if (d->sin6_scope_id && 970 (IN6_IS_ADDR_LINKLOCAL(&d->sin6_addr) || 971 IN6_IS_ADDR_MC_LINKLOCAL(&d->sin6_addr))) { 972 *(u_int16_t *)&d->sin6_addr.s6_addr[2] = 973 htons(d->sin6_scope_id); 974 } 975 #endif 976 } 977 #endif 978 979 if (ioctl(s, SIOCSLIFPHYADDR, &req) == -1) 980 warn("SIOCSLIFPHYADDR"); 981 982 freeaddrinfo(srcres); 983 freeaddrinfo(dstres); 984 } 985 986 /* ARGSUSED */ 987 void 988 deletetunnel(vname, param) 989 const char *vname; 990 int param; 991 { 992 993 if (ioctl(s, SIOCDIFPHYADDR, &ifr) == -1) 994 err(EXIT_FAILURE, "SIOCDIFPHYADDR"); 995 } 996 997 void setvlan(val, d) 998 const char *val; 999 int d; 1000 { 1001 struct vlanreq vlr; 1002 1003 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 1004 !isdigit(ifr.ifr_name[4])) 1005 errx(EXIT_FAILURE, 1006 "``vlan'' valid only with vlan(4) interfaces"); 1007 1008 vlan_tag = atoi(val); 1009 1010 memset(&vlr, 0, sizeof(vlr)); 1011 ifr.ifr_data = (caddr_t)&vlr; 1012 1013 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 1014 err(EXIT_FAILURE, "SIOCGETVLAN"); 1015 1016 vlr.vlr_tag = vlan_tag; 1017 1018 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 1019 err(EXIT_FAILURE, "SIOCSETVLAN"); 1020 } 1021 1022 void setvlanif(val, d) 1023 const char *val; 1024 int d; 1025 { 1026 struct vlanreq vlr; 1027 1028 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 1029 !isdigit(ifr.ifr_name[4])) 1030 errx(EXIT_FAILURE, 1031 "``vlanif'' valid only with vlan(4) interfaces"); 1032 1033 if (vlan_tag == (u_int)-1) 1034 errx(EXIT_FAILURE, 1035 "must specify both ``vlan'' and ``vlanif''"); 1036 1037 memset(&vlr, 0, sizeof(vlr)); 1038 ifr.ifr_data = (caddr_t)&vlr; 1039 1040 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 1041 err(EXIT_FAILURE, "SIOCGETVLAN"); 1042 1043 strlcpy(vlr.vlr_parent, val, sizeof(vlr.vlr_parent)); 1044 vlr.vlr_tag = vlan_tag; 1045 1046 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 1047 err(EXIT_FAILURE, "SIOCSETVLAN"); 1048 } 1049 1050 void unsetvlanif(val, d) 1051 const char *val; 1052 int d; 1053 { 1054 struct vlanreq vlr; 1055 1056 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 1057 !isdigit(ifr.ifr_name[4])) 1058 errx(EXIT_FAILURE, 1059 "``vlanif'' valid only with vlan(4) interfaces"); 1060 1061 memset(&vlr, 0, sizeof(vlr)); 1062 ifr.ifr_data = (caddr_t)&vlr; 1063 1064 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 1065 err(EXIT_FAILURE, "SIOCGETVLAN"); 1066 1067 vlr.vlr_parent[0] = '\0'; 1068 vlr.vlr_tag = 0; 1069 1070 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 1071 err(EXIT_FAILURE, "SIOCSETVLAN"); 1072 } 1073 1074 void 1075 setifnetmask(addr, d) 1076 const char *addr; 1077 int d; 1078 { 1079 (*afp->af_getaddr)(addr, MASK); 1080 } 1081 1082 void 1083 setifbroadaddr(addr, d) 1084 const char *addr; 1085 int d; 1086 { 1087 (*afp->af_getaddr)(addr, DSTADDR); 1088 } 1089 1090 void 1091 setifipdst(addr, d) 1092 const char *addr; 1093 int d; 1094 { 1095 in_getaddr(addr, DSTADDR); 1096 setipdst++; 1097 clearaddr = 0; 1098 newaddr = 0; 1099 } 1100 1101 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 1102 /*ARGSUSED*/ 1103 void 1104 notealias(addr, param) 1105 const char *addr; 1106 int param; 1107 { 1108 if (setaddr && doalias == 0 && param < 0) 1109 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), 1110 rqtosa(af_addreq)->sa_len); 1111 doalias = param; 1112 if (param < 0) { 1113 clearaddr = 1; 1114 newaddr = 0; 1115 conflicting++; 1116 } else { 1117 clearaddr = 0; 1118 conflicting++; 1119 } 1120 } 1121 1122 /*ARGSUSED*/ 1123 void 1124 notrailers(vname, value) 1125 const char *vname; 1126 int value; 1127 { 1128 puts("Note: trailers are no longer sent, but always received"); 1129 } 1130 1131 /*ARGSUSED*/ 1132 void 1133 setifdstaddr(addr, param) 1134 const char *addr; 1135 int param; 1136 { 1137 (*afp->af_getaddr)(addr, DSTADDR); 1138 } 1139 1140 void 1141 setifflags(vname, value) 1142 const char *vname; 1143 int value; 1144 { 1145 struct ifreq ifreq; 1146 1147 (void) strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); 1148 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifreq) == -1) 1149 err(EXIT_FAILURE, "SIOCGIFFLAGS"); 1150 flags = ifreq.ifr_flags; 1151 1152 if (value < 0) { 1153 value = -value; 1154 flags &= ~value; 1155 } else 1156 flags |= value; 1157 ifreq.ifr_flags = flags; 1158 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifreq) == -1) 1159 err(EXIT_FAILURE, "SIOCSIFFLAGS"); 1160 1161 reset_if_flags = 1; 1162 } 1163 1164 void 1165 setifcaps(vname, value) 1166 const char *vname; 1167 int value; 1168 { 1169 1170 if (value < 0) { 1171 value = -value; 1172 g_ifcr.ifcr_capenable &= ~value; 1173 } else 1174 g_ifcr.ifcr_capenable |= value; 1175 1176 g_ifcr_updated = 1; 1177 } 1178 1179 #ifdef INET6 1180 void 1181 setia6flags(vname, value) 1182 const char *vname; 1183 int value; 1184 { 1185 1186 if (value < 0) { 1187 value = -value; 1188 in6_addreq.ifra_flags &= ~value; 1189 } else 1190 in6_addreq.ifra_flags |= value; 1191 } 1192 1193 void 1194 setia6pltime(val, d) 1195 const char *val; 1196 int d; 1197 { 1198 1199 setia6lifetime("pltime", val); 1200 } 1201 1202 void 1203 setia6vltime(val, d) 1204 const char *val; 1205 int d; 1206 { 1207 1208 setia6lifetime("vltime", val); 1209 } 1210 1211 void 1212 setia6lifetime(cmd, val) 1213 const char *cmd; 1214 const char *val; 1215 { 1216 time_t newval, t; 1217 char *ep; 1218 1219 t = time(NULL); 1220 newval = (time_t)strtoul(val, &ep, 0); 1221 if (val == ep) 1222 errx(EXIT_FAILURE, "invalid %s", cmd); 1223 if (afp->af_af != AF_INET6) 1224 errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); 1225 if (strcmp(cmd, "vltime") == 0) { 1226 in6_addreq.ifra_lifetime.ia6t_expire = t + newval; 1227 in6_addreq.ifra_lifetime.ia6t_vltime = newval; 1228 } else if (strcmp(cmd, "pltime") == 0) { 1229 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; 1230 in6_addreq.ifra_lifetime.ia6t_pltime = newval; 1231 } 1232 } 1233 1234 void 1235 setia6eui64(cmd, val) 1236 const char *cmd; 1237 int val; 1238 { 1239 struct ifaddrs *ifap, *ifa; 1240 const struct sockaddr_in6 *sin6 = NULL; 1241 const struct in6_addr *lladdr = NULL; 1242 struct in6_addr *in6; 1243 1244 if (afp->af_af != AF_INET6) 1245 errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); 1246 in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; 1247 if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) 1248 errx(EXIT_FAILURE, "interface index is already filled"); 1249 if (getifaddrs(&ifap) != 0) 1250 err(EXIT_FAILURE, "getifaddrs"); 1251 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1252 if (ifa->ifa_addr->sa_family == AF_INET6 && 1253 strcmp(ifa->ifa_name, name) == 0) { 1254 sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; 1255 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1256 lladdr = &sin6->sin6_addr; 1257 break; 1258 } 1259 } 1260 } 1261 if (!lladdr) 1262 errx(EXIT_FAILURE, "could not determine link local address"); 1263 1264 memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); 1265 1266 freeifaddrs(ifap); 1267 } 1268 #endif 1269 1270 void 1271 setifmetric(val, d) 1272 const char *val; 1273 int d; 1274 { 1275 char *ep = NULL; 1276 1277 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1278 ifr.ifr_metric = strtoul(val, &ep, 10); 1279 if (!ep || *ep) 1280 errx(EXIT_FAILURE, "%s: invalid metric", val); 1281 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) == -1) 1282 warn("SIOCSIFMETRIC"); 1283 } 1284 1285 void 1286 setifmtu(val, d) 1287 const char *val; 1288 int d; 1289 { 1290 char *ep = NULL; 1291 1292 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1293 ifr.ifr_mtu = strtoul(val, &ep, 10); 1294 if (!ep || *ep) 1295 errx(EXIT_FAILURE, "%s: invalid mtu", val); 1296 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) == -1) 1297 warn("SIOCSIFMTU"); 1298 } 1299 1300 const char * 1301 get_string(val, sep, buf, lenp) 1302 const char *val, *sep; 1303 u_int8_t *buf; 1304 int *lenp; 1305 { 1306 int len; 1307 int hexstr; 1308 u_int8_t *p; 1309 1310 len = *lenp; 1311 p = buf; 1312 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); 1313 if (hexstr) 1314 val += 2; 1315 for (;;) { 1316 if (*val == '\0') 1317 break; 1318 if (sep != NULL && strchr(sep, *val) != NULL) { 1319 val++; 1320 break; 1321 } 1322 if (hexstr) { 1323 if (!isxdigit((u_char)val[0]) || 1324 !isxdigit((u_char)val[1])) { 1325 warnx("bad hexadecimal digits"); 1326 return NULL; 1327 } 1328 } 1329 if (p > buf + len) { 1330 if (hexstr) 1331 warnx("hexadecimal digits too long"); 1332 else 1333 warnx("strings too long"); 1334 return NULL; 1335 } 1336 if (hexstr) { 1337 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) 1338 *p++ = (tohex((u_char)val[0]) << 4) | 1339 tohex((u_char)val[1]); 1340 #undef tohex 1341 val += 2; 1342 } else 1343 *p++ = *val++; 1344 } 1345 len = p - buf; 1346 if (len < *lenp) 1347 memset(p, 0, *lenp - len); 1348 *lenp = len; 1349 return val; 1350 } 1351 1352 void 1353 print_string(buf, len) 1354 const u_int8_t *buf; 1355 int len; 1356 { 1357 int i; 1358 int hasspc; 1359 1360 i = 0; 1361 hasspc = 0; 1362 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { 1363 for (; i < len; i++) { 1364 if (!isprint(buf[i])) 1365 break; 1366 if (isspace(buf[i])) 1367 hasspc++; 1368 } 1369 } 1370 if (i == len) { 1371 if (hasspc || len == 0) 1372 printf("\"%.*s\"", len, buf); 1373 else 1374 printf("%.*s", len, buf); 1375 } else { 1376 printf("0x"); 1377 for (i = 0; i < len; i++) 1378 printf("%02x", buf[i]); 1379 } 1380 } 1381 1382 void 1383 setifnwid(val, d) 1384 const char *val; 1385 int d; 1386 { 1387 struct ieee80211_nwid nwid; 1388 int len; 1389 1390 len = sizeof(nwid.i_nwid); 1391 if (get_string(val, NULL, nwid.i_nwid, &len) == NULL) 1392 return; 1393 nwid.i_len = len; 1394 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1395 ifr.ifr_data = (caddr_t)&nwid; 1396 if (ioctl(s, SIOCS80211NWID, (caddr_t)&ifr) == -1) 1397 warn("SIOCS80211NWID"); 1398 } 1399 1400 void 1401 setifbssid(val, d) 1402 const char *val; 1403 int d; 1404 { 1405 struct ieee80211_bssid bssid; 1406 struct ether_addr *ea; 1407 1408 if (d != 0) { 1409 /* no BSSID is especially desired */ 1410 memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid)); 1411 } else { 1412 ea = ether_aton(val); 1413 if (ea == NULL) { 1414 warnx("malformed BSSID: %s", val); 1415 return; 1416 } 1417 memcpy(&bssid.i_bssid, ea->ether_addr_octet, 1418 sizeof(bssid.i_bssid)); 1419 } 1420 (void)strncpy(bssid.i_name, name, sizeof(bssid.i_name)); 1421 if (ioctl(s, SIOCS80211BSSID, (caddr_t)&bssid) == -1) 1422 warn("SIOCS80211BSSID"); 1423 } 1424 1425 void 1426 setifchan(val, d) 1427 const char *val; 1428 int d; 1429 { 1430 struct ieee80211_channel channel; 1431 int chan; 1432 1433 if (d != 0) 1434 chan = IEEE80211_CHAN_ANY; 1435 else { 1436 chan = atoi(val); 1437 if (chan < 0 || chan > 0xffff) { 1438 warnx("invalid channel: %s", val); 1439 return; 1440 } 1441 } 1442 1443 (void)strncpy(channel.i_name, name, sizeof(channel.i_name)); 1444 channel.i_channel = (u_int16_t) chan; 1445 if (ioctl(s, SIOCS80211CHANNEL, (caddr_t)&channel) == -1) 1446 warn("SIOCS80211CHANNEL"); 1447 } 1448 1449 void 1450 setifnwkey(val, d) 1451 const char *val; 1452 int d; 1453 { 1454 struct ieee80211_nwkey nwkey; 1455 int i; 1456 u_int8_t keybuf[IEEE80211_WEP_NKID][16]; 1457 1458 nwkey.i_wepon = IEEE80211_NWKEY_WEP; 1459 nwkey.i_defkid = 1; 1460 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1461 nwkey.i_key[i].i_keylen = sizeof(keybuf[i]); 1462 nwkey.i_key[i].i_keydat = keybuf[i]; 1463 } 1464 if (d != 0) { 1465 /* disable WEP encryption */ 1466 nwkey.i_wepon = 0; 1467 i = 0; 1468 } else if (strcasecmp("persist", val) == 0) { 1469 /* use all values from persistent memory */ 1470 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; 1471 nwkey.i_defkid = 0; 1472 for (i = 0; i < IEEE80211_WEP_NKID; i++) 1473 nwkey.i_key[i].i_keylen = -1; 1474 } else if (strncasecmp("persist:", val, 8) == 0) { 1475 val += 8; 1476 /* program keys in persistent memory */ 1477 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; 1478 goto set_nwkey; 1479 } else { 1480 set_nwkey: 1481 if (isdigit(val[0]) && val[1] == ':') { 1482 /* specifying a full set of four keys */ 1483 nwkey.i_defkid = val[0] - '0'; 1484 val += 2; 1485 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1486 val = get_string(val, ",", keybuf[i], 1487 &nwkey.i_key[i].i_keylen); 1488 if (val == NULL) 1489 return; 1490 } 1491 if (*val != '\0') { 1492 warnx("SIOCS80211NWKEY: too many keys."); 1493 return; 1494 } 1495 } else { 1496 val = get_string(val, NULL, keybuf[0], 1497 &nwkey.i_key[0].i_keylen); 1498 if (val == NULL) 1499 return; 1500 i = 1; 1501 } 1502 } 1503 for (; i < IEEE80211_WEP_NKID; i++) 1504 nwkey.i_key[i].i_keylen = 0; 1505 (void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name)); 1506 if (ioctl(s, SIOCS80211NWKEY, (caddr_t)&nwkey) == -1) 1507 warn("SIOCS80211NWKEY"); 1508 } 1509 1510 void 1511 setifpowersave(val, d) 1512 const char *val; 1513 int d; 1514 { 1515 struct ieee80211_power power; 1516 1517 (void)strncpy(power.i_name, name, sizeof(power.i_name)); 1518 if (ioctl(s, SIOCG80211POWER, (caddr_t)&power) == -1) { 1519 warn("SIOCG80211POWER"); 1520 return; 1521 } 1522 1523 power.i_enabled = d; 1524 if (ioctl(s, SIOCS80211POWER, (caddr_t)&power) == -1) 1525 warn("SIOCS80211POWER"); 1526 } 1527 1528 void 1529 setifpowersavesleep(val, d) 1530 const char *val; 1531 int d; 1532 { 1533 struct ieee80211_power power; 1534 1535 (void)strncpy(power.i_name, name, sizeof(power.i_name)); 1536 if (ioctl(s, SIOCG80211POWER, (caddr_t)&power) == -1) { 1537 warn("SIOCG80211POWER"); 1538 return; 1539 } 1540 1541 power.i_maxsleep = atoi(val); 1542 if (ioctl(s, SIOCS80211POWER, (caddr_t)&power) == -1) 1543 warn("SIOCS80211POWER"); 1544 } 1545 1546 void 1547 ieee80211_status() 1548 { 1549 int i, nwkey_verbose; 1550 struct ieee80211_nwid nwid; 1551 struct ieee80211_nwkey nwkey; 1552 struct ieee80211_power power; 1553 u_int8_t keybuf[IEEE80211_WEP_NKID][16]; 1554 struct ieee80211_bssid bssid; 1555 struct ieee80211_channel channel; 1556 struct ether_addr ea; 1557 static const u_int8_t zero_macaddr[IEEE80211_ADDR_LEN]; 1558 1559 memset(&ifr, 0, sizeof(ifr)); 1560 ifr.ifr_data = (caddr_t)&nwid; 1561 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1562 if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr) == -1) 1563 return; 1564 if (nwid.i_len > IEEE80211_NWID_LEN) { 1565 warnx("SIOCG80211NWID: wrong length of nwid (%d)", nwid.i_len); 1566 return; 1567 } 1568 printf("\tnwid "); 1569 print_string(nwid.i_nwid, nwid.i_len); 1570 memset(&nwkey, 0, sizeof(nwkey)); 1571 (void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name)); 1572 /* show nwkey only when WEP is enabled */ 1573 if (ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey) == -1 || 1574 nwkey.i_wepon == 0) { 1575 printf("\n"); 1576 goto skip_wep; 1577 } 1578 1579 printf(" nwkey "); 1580 /* try to retrieve WEP keys */ 1581 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1582 nwkey.i_key[i].i_keydat = keybuf[i]; 1583 nwkey.i_key[i].i_keylen = sizeof(keybuf[i]); 1584 } 1585 if (ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey) == -1) { 1586 printf("*****"); 1587 } else { 1588 nwkey_verbose = 0; 1589 /* check to see non default key or multiple keys defined */ 1590 if (nwkey.i_defkid != 1) { 1591 nwkey_verbose = 1; 1592 } else { 1593 for (i = 1; i < IEEE80211_WEP_NKID; i++) { 1594 if (nwkey.i_key[i].i_keylen != 0) { 1595 nwkey_verbose = 1; 1596 break; 1597 } 1598 } 1599 } 1600 /* check extra ambiguity with keywords */ 1601 if (!nwkey_verbose) { 1602 if (nwkey.i_key[0].i_keylen >= 2 && 1603 isdigit(nwkey.i_key[0].i_keydat[0]) && 1604 nwkey.i_key[0].i_keydat[1] == ':') 1605 nwkey_verbose = 1; 1606 else if (nwkey.i_key[0].i_keylen >= 7 && 1607 strncasecmp("persist", nwkey.i_key[0].i_keydat, 7) 1608 == 0) 1609 nwkey_verbose = 1; 1610 } 1611 if (nwkey_verbose) 1612 printf("%d:", nwkey.i_defkid); 1613 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1614 if (i > 0) 1615 printf(","); 1616 if (nwkey.i_key[i].i_keylen < 0) 1617 printf("persist"); 1618 else 1619 print_string(nwkey.i_key[i].i_keydat, 1620 nwkey.i_key[i].i_keylen); 1621 if (!nwkey_verbose) 1622 break; 1623 } 1624 } 1625 printf("\n"); 1626 1627 skip_wep: 1628 (void)strncpy(power.i_name, name, sizeof(power.i_name)); 1629 if (ioctl(s, SIOCG80211POWER, &power) == -1) 1630 goto skip_power; 1631 printf("\tpowersave "); 1632 if (power.i_enabled) 1633 printf("on (%dms sleep)", power.i_maxsleep); 1634 else 1635 printf("off"); 1636 printf("\n"); 1637 1638 skip_power: 1639 (void)strncpy(bssid.i_name, name, sizeof(bssid.i_name)); 1640 if (ioctl(s, SIOCG80211BSSID, &bssid) == -1) 1641 return; 1642 (void)strncpy(channel.i_name, name, sizeof(channel.i_name)); 1643 if (ioctl(s, SIOCG80211CHANNEL, &channel) == -1) 1644 return; 1645 if (memcmp(bssid.i_bssid, zero_macaddr, IEEE80211_ADDR_LEN) == 0) { 1646 if (channel.i_channel != (u_int16_t)-1) 1647 printf("\tchan %d\n", channel.i_channel); 1648 } else { 1649 memcpy(ea.ether_addr_octet, bssid.i_bssid, 1650 sizeof(ea.ether_addr_octet)); 1651 printf("\tbssid %s", ether_ntoa(&ea)); 1652 if (channel.i_channel != IEEE80211_CHAN_ANY) 1653 printf(" chan %d", channel.i_channel); 1654 printf("\n"); 1655 } 1656 } 1657 1658 void 1659 init_current_media() 1660 { 1661 struct ifmediareq ifmr; 1662 1663 /* 1664 * If we have not yet done so, grab the currently-selected 1665 * media. 1666 */ 1667 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) { 1668 (void) memset(&ifmr, 0, sizeof(ifmr)); 1669 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1670 1671 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) { 1672 /* 1673 * If we get E2BIG, the kernel is telling us 1674 * that there are more, so we can ignore it. 1675 */ 1676 if (errno != E2BIG) 1677 err(EXIT_FAILURE, "SGIOCGIFMEDIA"); 1678 } 1679 1680 media_current = ifmr.ifm_current; 1681 } 1682 1683 /* Sanity. */ 1684 if (IFM_TYPE(media_current) == 0) 1685 errx(EXIT_FAILURE, "%s: no link type?", name); 1686 } 1687 1688 void 1689 process_media_commands() 1690 { 1691 1692 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) { 1693 /* Nothing to do. */ 1694 return; 1695 } 1696 1697 /* 1698 * Media already set up, and commands sanity-checked. Set/clear 1699 * any options, and we're ready to go. 1700 */ 1701 media_current |= mediaopt_set; 1702 media_current &= ~mediaopt_clear; 1703 1704 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1705 ifr.ifr_media = media_current; 1706 1707 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) == -1) 1708 err(EXIT_FAILURE, "SIOCSIFMEDIA"); 1709 } 1710 1711 void 1712 setmedia(val, d) 1713 const char *val; 1714 int d; 1715 { 1716 int type, subtype, inst; 1717 1718 init_current_media(); 1719 1720 /* Only one media command may be given. */ 1721 if (actions & A_MEDIA) 1722 errx(EXIT_FAILURE, "only one `media' command may be issued"); 1723 1724 /* Must not come after mediaopt commands */ 1725 if (actions & A_MEDIAOPT) 1726 errx(EXIT_FAILURE, 1727 "may not issue `media' after `mediaopt' commands"); 1728 1729 /* 1730 * No need to check if `instance' has been issued; setmediainst() 1731 * craps out if `media' has not been specified. 1732 */ 1733 1734 type = IFM_TYPE(media_current); 1735 inst = IFM_INST(media_current); 1736 1737 /* Look up the subtype. */ 1738 subtype = get_media_subtype(type, val); 1739 1740 /* Build the new current media word. */ 1741 media_current = IFM_MAKEWORD(type, subtype, 0, inst); 1742 1743 /* Media will be set after other processing is complete. */ 1744 } 1745 1746 void 1747 setmediaopt(val, d) 1748 const char *val; 1749 int d; 1750 { 1751 1752 init_current_media(); 1753 1754 /* Can only issue `mediaopt' once. */ 1755 if (actions & A_MEDIAOPTSET) 1756 errx(EXIT_FAILURE, "only one `mediaopt' command may be issued"); 1757 1758 /* Can't issue `mediaopt' if `instance' has already been issued. */ 1759 if (actions & A_MEDIAINST) 1760 errx(EXIT_FAILURE, "may not issue `mediaopt' after `instance'"); 1761 1762 mediaopt_set = get_media_options(IFM_TYPE(media_current), val); 1763 1764 /* Media will be set after other processing is complete. */ 1765 } 1766 1767 void 1768 unsetmediaopt(val, d) 1769 const char *val; 1770 int d; 1771 { 1772 1773 init_current_media(); 1774 1775 /* Can only issue `-mediaopt' once. */ 1776 if (actions & A_MEDIAOPTCLR) 1777 errx(EXIT_FAILURE, 1778 "only one `-mediaopt' command may be issued"); 1779 1780 /* May not issue `media' and `-mediaopt'. */ 1781 if (actions & A_MEDIA) 1782 errx(EXIT_FAILURE, 1783 "may not issue both `media' and `-mediaopt'"); 1784 1785 /* 1786 * No need to check for A_MEDIAINST, since the test for A_MEDIA 1787 * implicitly checks for A_MEDIAINST. 1788 */ 1789 1790 mediaopt_clear = get_media_options(IFM_TYPE(media_current), val); 1791 1792 /* Media will be set after other processing is complete. */ 1793 } 1794 1795 void 1796 setmediainst(val, d) 1797 const char *val; 1798 int d; 1799 { 1800 int type, subtype, options, inst; 1801 1802 init_current_media(); 1803 1804 /* Can only issue `instance' once. */ 1805 if (actions & A_MEDIAINST) 1806 errx(EXIT_FAILURE, "only one `instance' command may be issued"); 1807 1808 /* Must have already specified `media' */ 1809 if ((actions & A_MEDIA) == 0) 1810 errx(EXIT_FAILURE, "must specify `media' before `instance'"); 1811 1812 type = IFM_TYPE(media_current); 1813 subtype = IFM_SUBTYPE(media_current); 1814 options = IFM_OPTIONS(media_current); 1815 1816 inst = atoi(val); 1817 if (inst < 0 || inst > IFM_INST_MAX) 1818 errx(EXIT_FAILURE, "invalid media instance: %s", val); 1819 1820 media_current = IFM_MAKEWORD(type, subtype, options, inst); 1821 1822 /* Media will be set after other processing is complete. */ 1823 } 1824 1825 struct ifmedia_description ifm_type_descriptions[] = 1826 IFM_TYPE_DESCRIPTIONS; 1827 1828 struct ifmedia_description ifm_subtype_descriptions[] = 1829 IFM_SUBTYPE_DESCRIPTIONS; 1830 1831 struct ifmedia_description ifm_option_descriptions[] = 1832 IFM_OPTION_DESCRIPTIONS; 1833 1834 const char * 1835 get_media_type_string(mword) 1836 int mword; 1837 { 1838 struct ifmedia_description *desc; 1839 1840 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; 1841 desc++) { 1842 if (IFM_TYPE(mword) == desc->ifmt_word) 1843 return (desc->ifmt_string); 1844 } 1845 return ("<unknown type>"); 1846 } 1847 1848 const char * 1849 get_media_subtype_string(mword) 1850 int mword; 1851 { 1852 struct ifmedia_description *desc; 1853 1854 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL; 1855 desc++) { 1856 if (IFM_TYPE_MATCH(desc->ifmt_word, mword) && 1857 IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword)) 1858 return (desc->ifmt_string); 1859 } 1860 return ("<unknown subtype>"); 1861 } 1862 1863 int 1864 get_media_subtype(type, val) 1865 int type; 1866 const char *val; 1867 { 1868 int rval; 1869 1870 rval = lookup_media_word(ifm_subtype_descriptions, type, val); 1871 if (rval == -1) 1872 errx(EXIT_FAILURE, "unknown %s media subtype: %s", 1873 get_media_type_string(type), val); 1874 1875 return (rval); 1876 } 1877 1878 int 1879 get_media_options(type, val) 1880 int type; 1881 const char *val; 1882 { 1883 char *optlist, *str; 1884 int option, rval = 0; 1885 1886 /* We muck with the string, so copy it. */ 1887 optlist = strdup(val); 1888 if (optlist == NULL) 1889 err(EXIT_FAILURE, "strdup"); 1890 str = optlist; 1891 1892 /* 1893 * Look up the options in the user-provided comma-separated list. 1894 */ 1895 for (; (str = strtok(str, ",")) != NULL; str = NULL) { 1896 option = lookup_media_word(ifm_option_descriptions, type, str); 1897 if (option == -1) 1898 errx(EXIT_FAILURE, "unknown %s media option: %s", 1899 get_media_type_string(type), str); 1900 rval |= IFM_OPTIONS(option); 1901 } 1902 1903 free(optlist); 1904 return (rval); 1905 } 1906 1907 int 1908 lookup_media_word(desc, type, val) 1909 struct ifmedia_description *desc; 1910 int type; 1911 const char *val; 1912 { 1913 1914 for (; desc->ifmt_string != NULL; desc++) { 1915 if (IFM_TYPE_MATCH(desc->ifmt_word, type) && 1916 strcasecmp(desc->ifmt_string, val) == 0) 1917 return (desc->ifmt_word); 1918 } 1919 return (-1); 1920 } 1921 1922 void 1923 print_media_word(ifmw, print_type, as_syntax) 1924 int ifmw, print_type, as_syntax; 1925 { 1926 struct ifmedia_description *desc; 1927 int seen_option = 0; 1928 1929 if (print_type) 1930 printf("%s ", get_media_type_string(ifmw)); 1931 printf("%s%s", as_syntax ? "media " : "", 1932 get_media_subtype_string(ifmw)); 1933 1934 /* Find options. */ 1935 for (desc = ifm_option_descriptions; desc->ifmt_string != NULL; 1936 desc++) { 1937 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) && 1938 (ifmw & IFM_OPTIONS(desc->ifmt_word)) != 0 && 1939 (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) { 1940 if (seen_option == 0) 1941 printf(" %s", as_syntax ? "mediaopt " : ""); 1942 printf("%s%s", seen_option ? "," : "", 1943 desc->ifmt_string); 1944 seen_option |= IFM_OPTIONS(desc->ifmt_word); 1945 } 1946 } 1947 if (IFM_INST(ifmw) != 0) 1948 printf(" instance %d", IFM_INST(ifmw)); 1949 } 1950 1951 int carrier() 1952 { 1953 struct ifmediareq ifmr; 1954 1955 (void) memset(&ifmr, 0, sizeof(ifmr)); 1956 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1957 1958 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) { 1959 /* 1960 * Interface doesn't support SIOC{G,S}IFMEDIA; 1961 * assume ok. 1962 */ 1963 return 0; 1964 } 1965 if ((ifmr.ifm_status & IFM_AVALID) == 0) { 1966 /* 1967 * Interface doesn't report media-valid status. 1968 * assume ok. 1969 */ 1970 return 0; 1971 } 1972 /* otherwise, return ok for active, not-ok if not active. */ 1973 return !(ifmr.ifm_status & IFM_ACTIVE); 1974 } 1975 1976 1977 #define IFFBITS \ 1978 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 1979 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 1980 1981 #define IFCAPBITS \ 1982 "\020\1IP4CSUM\2TCP4CSUM\3UDP4CSUM\4TCP6CSUM\5UDP6CSUM\6TCP4CSUM_Rx\7UDP4CSUM_Rx" 1983 1984 const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 1985 1986 const struct ifmedia_status_description ifm_status_descriptions[] = 1987 IFM_STATUS_DESCRIPTIONS; 1988 1989 /* 1990 * Print the status of the interface. If an address family was 1991 * specified, show it and it only; otherwise, show them all. 1992 */ 1993 void 1994 status(sdl) 1995 const struct sockaddr_dl *sdl; 1996 { 1997 struct afswtch *p = afp; 1998 struct ifmediareq ifmr; 1999 struct ifdatareq ifdr; 2000 int *media_list, i; 2001 char hbuf[NI_MAXHOST]; 2002 char fbuf[BUFSIZ]; 2003 2004 (void)snprintb(fbuf, sizeof(fbuf), IFFBITS, flags); 2005 printf("%s: flags=%s", name, &fbuf[2]); 2006 if (metric) 2007 printf(" metric %lu", metric); 2008 if (mtu) 2009 printf(" mtu %lu", mtu); 2010 putchar('\n'); 2011 2012 if (g_ifcr.ifcr_capabilities) { 2013 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS, 2014 g_ifcr.ifcr_capabilities); 2015 printf("\tcapabilities=%s\n", &fbuf[2]); 2016 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS, 2017 g_ifcr.ifcr_capenable); 2018 printf("\tenabled=%s\n", &fbuf[2]); 2019 } 2020 2021 ieee80211_status(); 2022 vlan_status(); 2023 tunnel_status(); 2024 2025 if (sdl != NULL && 2026 getnameinfo((struct sockaddr *)sdl, sdl->sdl_len, 2027 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0 && 2028 hbuf[0] != '\0') 2029 printf("\taddress: %s\n", hbuf); 2030 2031 (void) memset(&ifmr, 0, sizeof(ifmr)); 2032 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 2033 2034 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) { 2035 /* 2036 * Interface doesn't support SIOC{G,S}IFMEDIA. 2037 */ 2038 goto iface_stats; 2039 } 2040 2041 if (ifmr.ifm_count == 0) { 2042 warnx("%s: no media types?", name); 2043 goto iface_stats; 2044 } 2045 2046 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 2047 if (media_list == NULL) 2048 err(EXIT_FAILURE, "malloc"); 2049 ifmr.ifm_ulist = media_list; 2050 2051 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) 2052 err(EXIT_FAILURE, "SIOCGIFMEDIA"); 2053 2054 printf("\tmedia: "); 2055 print_media_word(ifmr.ifm_current, 1, 0); 2056 if (ifmr.ifm_active != ifmr.ifm_current) { 2057 putchar(' '); 2058 putchar('('); 2059 print_media_word(ifmr.ifm_active, 0, 0); 2060 putchar(')'); 2061 } 2062 putchar('\n'); 2063 2064 if (ifmr.ifm_status & IFM_STATUS_VALID) { 2065 const struct ifmedia_status_description *ifms; 2066 int bitno, found = 0; 2067 2068 printf("\tstatus: "); 2069 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { 2070 for (ifms = ifm_status_descriptions; 2071 ifms->ifms_valid != 0; ifms++) { 2072 if (ifms->ifms_type != 2073 IFM_TYPE(ifmr.ifm_current) || 2074 ifms->ifms_valid != 2075 ifm_status_valid_list[bitno]) 2076 continue; 2077 printf("%s%s", found ? ", " : "", 2078 IFM_STATUS_DESC(ifms, ifmr.ifm_status)); 2079 found = 1; 2080 2081 /* 2082 * For each valid indicator bit, there's 2083 * only one entry for each media type, so 2084 * terminate the inner loop now. 2085 */ 2086 break; 2087 } 2088 } 2089 2090 if (found == 0) 2091 printf("unknown"); 2092 putchar('\n'); 2093 } 2094 2095 if (mflag) { 2096 int type, printed_type; 2097 2098 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) { 2099 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { 2100 if (IFM_TYPE(media_list[i]) == type) { 2101 if (printed_type == 0) { 2102 printf("\tsupported %s media:\n", 2103 get_media_type_string(type)); 2104 printed_type = 1; 2105 } 2106 printf("\t\t"); 2107 print_media_word(media_list[i], 0, 1); 2108 printf("\n"); 2109 } 2110 } 2111 } 2112 } 2113 2114 free(media_list); 2115 2116 iface_stats: 2117 if (!vflag) 2118 goto proto_status; 2119 2120 (void) strncpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name)); 2121 2122 if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifdr) != -1) { 2123 struct if_data * const ifi = &ifdr.ifdr_data; 2124 #define PLURAL(n) ((n) == 1 ? "" : "s") 2125 printf("\tinput: %llu packet%s, %llu byte%s", 2126 (unsigned long long) ifi->ifi_ipackets, 2127 PLURAL(ifi->ifi_ipackets), 2128 (unsigned long long) ifi->ifi_ibytes, 2129 PLURAL(ifi->ifi_ibytes)); 2130 if (ifi->ifi_imcasts) 2131 printf(", %llu multicast%s", 2132 (unsigned long long) ifi->ifi_imcasts, 2133 PLURAL(ifi->ifi_imcasts)); 2134 if (ifi->ifi_ierrors) 2135 printf(", %llu error%s", 2136 (unsigned long long) ifi->ifi_ierrors, 2137 PLURAL(ifi->ifi_ierrors)); 2138 if (ifi->ifi_iqdrops) 2139 printf(", %llu queue drop%s", 2140 (unsigned long long) ifi->ifi_iqdrops, 2141 PLURAL(ifi->ifi_iqdrops)); 2142 if (ifi->ifi_noproto) 2143 printf(", %llu unknown protocol", 2144 (unsigned long long) ifi->ifi_noproto); 2145 printf("\n\toutput: %llu packet%s, %llu byte%s", 2146 (unsigned long long) ifi->ifi_opackets, 2147 PLURAL(ifi->ifi_opackets), 2148 (unsigned long long) ifi->ifi_obytes, 2149 PLURAL(ifi->ifi_obytes)); 2150 if (ifi->ifi_omcasts) 2151 printf(", %llu multicast%s", 2152 (unsigned long long) ifi->ifi_omcasts, 2153 PLURAL(ifi->ifi_omcasts)); 2154 if (ifi->ifi_oerrors) 2155 printf(", %llu error%s", 2156 (unsigned long long) ifi->ifi_oerrors, 2157 PLURAL(ifi->ifi_oerrors)); 2158 if (ifi->ifi_collisions) 2159 printf(", %llu collision%s", 2160 (unsigned long long) ifi->ifi_collisions, 2161 PLURAL(ifi->ifi_collisions)); 2162 printf("\n"); 2163 #undef PLURAL 2164 } 2165 2166 proto_status: 2167 if ((p = afp) != NULL) { 2168 (*p->af_status)(1); 2169 } else for (p = afs; p->af_name; p++) { 2170 ifr.ifr_addr.sa_family = p->af_af; 2171 (*p->af_status)(0); 2172 } 2173 } 2174 2175 void 2176 tunnel_status() 2177 { 2178 char psrcaddr[NI_MAXHOST]; 2179 char pdstaddr[NI_MAXHOST]; 2180 const char *ver = ""; 2181 #ifdef NI_WITHSCOPEID 2182 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 2183 #else 2184 const int niflag = NI_NUMERICHOST; 2185 #endif 2186 struct if_laddrreq req; 2187 2188 psrcaddr[0] = pdstaddr[0] = '\0'; 2189 2190 memset(&req, 0, sizeof(req)); 2191 strncpy(req.iflr_name, name, IFNAMSIZ); 2192 if (ioctl(s, SIOCGLIFPHYADDR, (caddr_t)&req) == -1) 2193 return; 2194 #ifdef INET6 2195 if (req.addr.ss_family == AF_INET6) 2196 in6_fillscopeid((struct sockaddr_in6 *)&req.addr); 2197 #endif 2198 getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len, 2199 psrcaddr, sizeof(psrcaddr), 0, 0, niflag); 2200 #ifdef INET6 2201 if (req.addr.ss_family == AF_INET6) 2202 ver = "6"; 2203 #endif 2204 2205 #ifdef INET6 2206 if (req.dstaddr.ss_family == AF_INET6) 2207 in6_fillscopeid((struct sockaddr_in6 *)&req.dstaddr); 2208 #endif 2209 getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len, 2210 pdstaddr, sizeof(pdstaddr), 0, 0, niflag); 2211 2212 printf("\ttunnel inet%s %s --> %s\n", ver, psrcaddr, pdstaddr); 2213 } 2214 2215 void 2216 vlan_status() 2217 { 2218 struct vlanreq vlr; 2219 2220 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 2221 !isdigit(ifr.ifr_name[4])) 2222 return; 2223 2224 memset(&vlr, 0, sizeof(vlr)); 2225 ifr.ifr_data = (caddr_t)&vlr; 2226 2227 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 2228 return; 2229 2230 if (vlr.vlr_tag || vlr.vlr_parent[0] != '\0') 2231 printf("\tvlan: %d parent: %s\n", 2232 vlr.vlr_tag, vlr.vlr_parent[0] == '\0' ? 2233 "<none>" : vlr.vlr_parent); 2234 } 2235 2236 void 2237 in_alias(creq) 2238 struct ifreq *creq; 2239 { 2240 struct sockaddr_in *iasin; 2241 int alias; 2242 2243 if (lflag) 2244 return; 2245 2246 alias = 1; 2247 2248 /* Get the non-alias address for this interface. */ 2249 getsock(AF_INET); 2250 if (s < 0) { 2251 if (errno == EPROTONOSUPPORT) 2252 return; 2253 err(EXIT_FAILURE, "socket"); 2254 } 2255 (void) memset(&ifr, 0, sizeof(ifr)); 2256 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2257 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) == -1) { 2258 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2259 return; 2260 } else 2261 warn("SIOCGIFADDR"); 2262 } 2263 /* If creq and ifr are the same address, this is not an alias. */ 2264 if (memcmp(&ifr.ifr_addr, &creq->ifr_addr, 2265 sizeof(creq->ifr_addr)) == 0) 2266 alias = 0; 2267 (void) memset(&in_addreq, 0, sizeof(in_addreq)); 2268 (void) strncpy(in_addreq.ifra_name, name, sizeof(in_addreq.ifra_name)); 2269 memcpy(&in_addreq.ifra_addr, &creq->ifr_addr, 2270 sizeof(in_addreq.ifra_addr)); 2271 if (ioctl(s, SIOCGIFALIAS, (caddr_t)&in_addreq) == -1) { 2272 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2273 return; 2274 } else 2275 warn("SIOCGIFALIAS"); 2276 } 2277 2278 iasin = &in_addreq.ifra_addr; 2279 printf("\tinet %s%s", alias ? "alias " : "", inet_ntoa(iasin->sin_addr)); 2280 2281 if (flags & IFF_POINTOPOINT) { 2282 iasin = &in_addreq.ifra_dstaddr; 2283 printf(" -> %s", inet_ntoa(iasin->sin_addr)); 2284 } 2285 2286 iasin = &in_addreq.ifra_mask; 2287 printf(" netmask 0x%x", ntohl(iasin->sin_addr.s_addr)); 2288 2289 if (flags & IFF_BROADCAST) { 2290 iasin = &in_addreq.ifra_broadaddr; 2291 printf(" broadcast %s", inet_ntoa(iasin->sin_addr)); 2292 } 2293 printf("\n"); 2294 } 2295 2296 void 2297 in_status(force) 2298 int force; 2299 { 2300 struct ifaddrs *ifap, *ifa; 2301 struct ifreq isifr; 2302 2303 if (getifaddrs(&ifap) != 0) 2304 err(EXIT_FAILURE, "getifaddrs"); 2305 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2306 if (strcmp(name, ifa->ifa_name) != 0) 2307 continue; 2308 if (ifa->ifa_addr->sa_family != AF_INET) 2309 continue; 2310 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len) 2311 continue; 2312 2313 memset(&isifr, 0, sizeof(isifr)); 2314 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name)); 2315 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 2316 in_alias(&isifr); 2317 } 2318 freeifaddrs(ifap); 2319 } 2320 2321 void 2322 setifprefixlen(addr, d) 2323 const char *addr; 2324 int d; 2325 { 2326 if (*afp->af_getprefix) 2327 (*afp->af_getprefix)(addr, MASK); 2328 explicit_prefix = 1; 2329 } 2330 2331 #ifdef INET6 2332 void 2333 in6_fillscopeid(sin6) 2334 struct sockaddr_in6 *sin6; 2335 { 2336 #if defined(__KAME__) && defined(KAME_SCOPEID) 2337 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 2338 sin6->sin6_scope_id = 2339 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 2340 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 2341 } 2342 #endif 2343 } 2344 2345 /* XXX not really an alias */ 2346 void 2347 in6_alias(creq) 2348 struct in6_ifreq *creq; 2349 { 2350 struct sockaddr_in6 *sin6; 2351 char hbuf[NI_MAXHOST]; 2352 u_int32_t scopeid; 2353 #ifdef NI_WITHSCOPEID 2354 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 2355 #else 2356 const int niflag = NI_NUMERICHOST; 2357 #endif 2358 2359 /* Get the non-alias address for this interface. */ 2360 getsock(AF_INET6); 2361 if (s < 0) { 2362 if (errno == EPROTONOSUPPORT) 2363 return; 2364 err(EXIT_FAILURE, "socket"); 2365 } 2366 2367 sin6 = (struct sockaddr_in6 *)&creq->ifr_addr; 2368 2369 in6_fillscopeid(sin6); 2370 scopeid = sin6->sin6_scope_id; 2371 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 2372 hbuf, sizeof(hbuf), NULL, 0, niflag)) 2373 strncpy(hbuf, "", sizeof(hbuf)); /* some message? */ 2374 printf("\tinet6 %s", hbuf); 2375 2376 if (flags & IFF_POINTOPOINT) { 2377 (void) memset(&ifr6, 0, sizeof(ifr6)); 2378 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2379 ifr6.ifr_addr = creq->ifr_addr; 2380 if (ioctl(s, SIOCGIFDSTADDR_IN6, (caddr_t)&ifr6) == -1) { 2381 if (errno != EADDRNOTAVAIL) 2382 warn("SIOCGIFDSTADDR_IN6"); 2383 (void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr)); 2384 ifr6.ifr_addr.sin6_family = AF_INET6; 2385 ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6); 2386 } 2387 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 2388 in6_fillscopeid(sin6); 2389 hbuf[0] = '\0'; 2390 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 2391 hbuf, sizeof(hbuf), NULL, 0, niflag)) 2392 strncpy(hbuf, "", sizeof(hbuf)); /* some message? */ 2393 printf(" -> %s", hbuf); 2394 } 2395 2396 (void) memset(&ifr6, 0, sizeof(ifr6)); 2397 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2398 ifr6.ifr_addr = creq->ifr_addr; 2399 if (ioctl(s, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) == -1) { 2400 if (errno != EADDRNOTAVAIL) 2401 warn("SIOCGIFNETMASK_IN6"); 2402 } else { 2403 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 2404 printf(" prefixlen %d", prefix(&sin6->sin6_addr, 2405 sizeof(struct in6_addr))); 2406 } 2407 2408 (void) memset(&ifr6, 0, sizeof(ifr6)); 2409 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2410 ifr6.ifr_addr = creq->ifr_addr; 2411 if (ioctl(s, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) == -1) { 2412 if (errno != EADDRNOTAVAIL) 2413 warn("SIOCGIFAFLAG_IN6"); 2414 } else { 2415 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST) 2416 printf(" anycast"); 2417 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) 2418 printf(" tentative"); 2419 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) 2420 printf(" duplicated"); 2421 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED) 2422 printf(" detached"); 2423 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) 2424 printf(" deprecated"); 2425 } 2426 2427 if (scopeid) 2428 printf(" scopeid 0x%x", scopeid); 2429 2430 if (Lflag) { 2431 struct in6_addrlifetime *lifetime; 2432 (void) memset(&ifr6, 0, sizeof(ifr6)); 2433 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2434 ifr6.ifr_addr = creq->ifr_addr; 2435 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 2436 if (ioctl(s, SIOCGIFALIFETIME_IN6, (caddr_t)&ifr6) == -1) { 2437 if (errno != EADDRNOTAVAIL) 2438 warn("SIOCGIFALIFETIME_IN6"); 2439 } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { 2440 time_t t = time(NULL); 2441 printf(" pltime "); 2442 if (lifetime->ia6t_preferred) { 2443 printf("%s", lifetime->ia6t_preferred < t 2444 ? "0" 2445 : sec2str(lifetime->ia6t_preferred - t)); 2446 } else 2447 printf("infty"); 2448 2449 printf(" vltime "); 2450 if (lifetime->ia6t_expire) { 2451 printf("%s", lifetime->ia6t_expire < t 2452 ? "0" 2453 : sec2str(lifetime->ia6t_expire - t)); 2454 } else 2455 printf("infty"); 2456 } 2457 } 2458 2459 printf("\n"); 2460 } 2461 2462 void 2463 in6_status(force) 2464 int force; 2465 { 2466 struct ifaddrs *ifap, *ifa; 2467 struct in6_ifreq isifr; 2468 2469 if (getifaddrs(&ifap) != 0) 2470 err(EXIT_FAILURE, "getifaddrs"); 2471 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2472 if (strcmp(name, ifa->ifa_name) != 0) 2473 continue; 2474 if (ifa->ifa_addr->sa_family != AF_INET6) 2475 continue; 2476 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len) 2477 continue; 2478 2479 memset(&isifr, 0, sizeof(isifr)); 2480 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name)); 2481 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 2482 in6_alias(&isifr); 2483 } 2484 freeifaddrs(ifap); 2485 } 2486 #endif /*INET6*/ 2487 2488 #ifndef INET_ONLY 2489 2490 void 2491 at_status(force) 2492 int force; 2493 { 2494 struct sockaddr_at *sat, null_sat; 2495 struct netrange *nr; 2496 2497 getsock(AF_APPLETALK); 2498 if (s < 0) { 2499 if (errno == EPROTONOSUPPORT) 2500 return; 2501 err(EXIT_FAILURE, "socket"); 2502 } 2503 (void) memset(&ifr, 0, sizeof(ifr)); 2504 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2505 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) == -1) { 2506 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2507 if (!force) 2508 return; 2509 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 2510 } else 2511 warn("SIOCGIFADDR"); 2512 } 2513 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 2514 sat = (struct sockaddr_at *)&ifr.ifr_addr; 2515 2516 (void) memset(&null_sat, 0, sizeof(null_sat)); 2517 2518 nr = (struct netrange *) &sat->sat_zero; 2519 printf("\tatalk %d.%d range %d-%d phase %d", 2520 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 2521 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 2522 if (flags & IFF_POINTOPOINT) { 2523 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) == -1) { 2524 if (errno == EADDRNOTAVAIL) 2525 (void) memset(&ifr.ifr_addr, 0, 2526 sizeof(ifr.ifr_addr)); 2527 else 2528 warn("SIOCGIFDSTADDR"); 2529 } 2530 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 2531 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr; 2532 if (!sat) 2533 sat = &null_sat; 2534 printf("--> %d.%d", 2535 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 2536 } 2537 if (flags & IFF_BROADCAST) { 2538 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 2539 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr; 2540 if (sat) 2541 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net), 2542 sat->sat_addr.s_node); 2543 } 2544 putchar('\n'); 2545 } 2546 2547 void 2548 xns_status(force) 2549 int force; 2550 { 2551 struct sockaddr_ns *sns; 2552 2553 getsock(AF_NS); 2554 if (s < 0) { 2555 if (errno == EPROTONOSUPPORT) 2556 return; 2557 err(EXIT_FAILURE, "socket"); 2558 } 2559 (void) memset(&ifr, 0, sizeof(ifr)); 2560 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2561 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) == -1) { 2562 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2563 if (!force) 2564 return; 2565 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 2566 } else 2567 warn("SIOCGIFADDR"); 2568 } 2569 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 2570 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 2571 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 2572 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 2573 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) == -1) { 2574 if (errno == EADDRNOTAVAIL) 2575 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 2576 else 2577 warn("SIOCGIFDSTADDR"); 2578 } 2579 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 2580 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 2581 printf("--> %s ", ns_ntoa(sns->sns_addr)); 2582 } 2583 putchar('\n'); 2584 } 2585 2586 void 2587 iso_status(force) 2588 int force; 2589 { 2590 struct sockaddr_iso *siso; 2591 struct iso_ifreq isoifr; 2592 2593 getsock(AF_ISO); 2594 if (s < 0) { 2595 if (errno == EPROTONOSUPPORT) 2596 return; 2597 err(EXIT_FAILURE, "socket"); 2598 } 2599 (void) memset(&isoifr, 0, sizeof(isoifr)); 2600 (void) strncpy(isoifr.ifr_name, name, sizeof(isoifr.ifr_name)); 2601 if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&isoifr) == -1) { 2602 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2603 if (!force) 2604 return; 2605 (void) memset(&isoifr.ifr_Addr, 0, 2606 sizeof(isoifr.ifr_Addr)); 2607 } else 2608 warn("SIOCGIFADDR_ISO"); 2609 } 2610 (void) strncpy(isoifr.ifr_name, name, sizeof isoifr.ifr_name); 2611 siso = &isoifr.ifr_Addr; 2612 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 2613 if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&isoifr) == -1) { 2614 if (errno == EADDRNOTAVAIL) 2615 memset(&isoifr.ifr_Addr, 0, sizeof(isoifr.ifr_Addr)); 2616 else 2617 warn("SIOCGIFNETMASK_ISO"); 2618 } else { 2619 if (siso->siso_len > offsetof(struct sockaddr_iso, siso_addr)) 2620 siso->siso_addr.isoa_len = siso->siso_len 2621 - offsetof(struct sockaddr_iso, siso_addr); 2622 printf("\n\t\tnetmask %s ", iso_ntoa(&siso->siso_addr)); 2623 } 2624 if (flags & IFF_POINTOPOINT) { 2625 if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&isoifr) == -1) { 2626 if (errno == EADDRNOTAVAIL) 2627 memset(&isoifr.ifr_Addr, 0, 2628 sizeof(isoifr.ifr_Addr)); 2629 else 2630 warn("SIOCGIFDSTADDR_ISO"); 2631 } 2632 (void) strncpy(isoifr.ifr_name, name, sizeof (isoifr.ifr_name)); 2633 siso = &isoifr.ifr_Addr; 2634 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 2635 } 2636 putchar('\n'); 2637 } 2638 2639 #endif /* INET_ONLY */ 2640 2641 #define SIN(x) ((struct sockaddr_in *) &(x)) 2642 struct sockaddr_in *sintab[] = { 2643 SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr), 2644 SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)}; 2645 2646 void 2647 in_getaddr(str, which) 2648 const char *str; 2649 int which; 2650 { 2651 struct sockaddr_in *gasin = sintab[which]; 2652 struct hostent *hp; 2653 struct netent *np; 2654 2655 gasin->sin_len = sizeof(*gasin); 2656 if (which != MASK) 2657 gasin->sin_family = AF_INET; 2658 2659 if (which == ADDR) { 2660 char *p = NULL; 2661 if ((p = strrchr(str, '/')) != NULL) { 2662 *p = '\0'; 2663 in_getprefix(p + 1, MASK); 2664 } 2665 } 2666 2667 if (inet_aton(str, &gasin->sin_addr) == 0) { 2668 if ((hp = gethostbyname(str)) != NULL) 2669 (void) memcpy(&gasin->sin_addr, hp->h_addr, hp->h_length); 2670 else if ((np = getnetbyname(str)) != NULL) 2671 gasin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 2672 else 2673 errx(EXIT_FAILURE, "%s: bad value", str); 2674 } 2675 } 2676 2677 void 2678 in_getprefix(plen, which) 2679 const char *plen; 2680 int which; 2681 { 2682 register struct sockaddr_in *igsin = sintab[which]; 2683 register u_char *cp; 2684 int len = strtol(plen, (char **)NULL, 10); 2685 2686 if ((len < 0) || (len > 32)) 2687 errx(EXIT_FAILURE, "%s: bad value", plen); 2688 igsin->sin_len = sizeof(*igsin); 2689 if (which != MASK) 2690 igsin->sin_family = AF_INET; 2691 if ((len == 0) || (len == 32)) { 2692 memset(&igsin->sin_addr, 0xff, sizeof(struct in_addr)); 2693 return; 2694 } 2695 memset((void *)&igsin->sin_addr, 0x00, sizeof(igsin->sin_addr)); 2696 for (cp = (u_char *)&igsin->sin_addr; len > 7; len -= 8) 2697 *cp++ = 0xff; 2698 if (len) 2699 *cp = 0xff << (8 - len); 2700 } 2701 2702 #ifdef INET6 2703 #define SIN6(x) ((struct sockaddr_in6 *) &(x)) 2704 struct sockaddr_in6 *sin6tab[] = { 2705 SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 2706 SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 2707 2708 void 2709 in6_getaddr(str, which) 2710 const char *str; 2711 int which; 2712 { 2713 #if defined(__KAME__) && defined(KAME_SCOPEID) 2714 struct sockaddr_in6 *sin6 = sin6tab[which]; 2715 struct addrinfo hints, *res; 2716 int error; 2717 2718 memset(&hints, 0, sizeof(hints)); 2719 hints.ai_family = AF_INET6; 2720 hints.ai_socktype = SOCK_DGRAM; 2721 #if 0 /* in_getaddr() allows FQDN */ 2722 hints.ai_flags = AI_NUMERICHOST; 2723 #endif 2724 error = getaddrinfo(str, "0", &hints, &res); 2725 if (error) 2726 errx(EXIT_FAILURE, "%s: %s", str, gai_strerror(error)); 2727 if (res->ai_next) 2728 errx(EXIT_FAILURE, "%s: resolved to multiple hosts", str); 2729 if (res->ai_addrlen != sizeof(struct sockaddr_in6)) 2730 errx(EXIT_FAILURE, "%s: bad value", str); 2731 memcpy(sin6, res->ai_addr, res->ai_addrlen); 2732 freeaddrinfo(res); 2733 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && sin6->sin6_scope_id) { 2734 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] = 2735 htons(sin6->sin6_scope_id); 2736 sin6->sin6_scope_id = 0; 2737 } 2738 #else 2739 struct sockaddr_in6 *gasin = sin6tab[which]; 2740 2741 gasin->sin6_len = sizeof(*gasin); 2742 if (which != MASK) 2743 gasin->sin6_family = AF_INET6; 2744 2745 if (which == ADDR) { 2746 char *p = NULL; 2747 if((p = strrchr(str, '/')) != NULL) { 2748 *p = '\0'; 2749 in6_getprefix(p + 1, MASK); 2750 explicit_prefix = 1; 2751 } 2752 } 2753 2754 if (inet_pton(AF_INET6, str, &gasin->sin6_addr) != 1) 2755 errx(EXIT_FAILURE, "%s: bad value", str); 2756 #endif 2757 } 2758 2759 void 2760 in6_getprefix(plen, which) 2761 const char *plen; 2762 int which; 2763 { 2764 register struct sockaddr_in6 *gpsin = sin6tab[which]; 2765 register u_char *cp; 2766 int len = strtol(plen, (char **)NULL, 10); 2767 2768 if ((len < 0) || (len > 128)) 2769 errx(EXIT_FAILURE, "%s: bad value", plen); 2770 gpsin->sin6_len = sizeof(*gpsin); 2771 if (which != MASK) 2772 gpsin->sin6_family = AF_INET6; 2773 if ((len == 0) || (len == 128)) { 2774 memset(&gpsin->sin6_addr, 0xff, sizeof(struct in6_addr)); 2775 return; 2776 } 2777 memset((void *)&gpsin->sin6_addr, 0x00, sizeof(gpsin->sin6_addr)); 2778 for (cp = (u_char *)&gpsin->sin6_addr; len > 7; len -= 8) 2779 *cp++ = 0xff; 2780 if (len) 2781 *cp = 0xff << (8 - len); 2782 } 2783 2784 int 2785 prefix(val, size) 2786 void *val; 2787 int size; 2788 { 2789 register u_char *pname = (u_char *)val; 2790 register int byte, bit, plen = 0; 2791 2792 for (byte = 0; byte < size; byte++, plen += 8) 2793 if (pname[byte] != 0xff) 2794 break; 2795 if (byte == size) 2796 return (plen); 2797 for (bit = 7; bit != 0; bit--, plen++) 2798 if (!(pname[byte] & (1 << bit))) 2799 break; 2800 for (; bit != 0; bit--) 2801 if (pname[byte] & (1 << bit)) 2802 return(0); 2803 byte++; 2804 for (; byte < size; byte++) 2805 if (pname[byte]) 2806 return(0); 2807 return (plen); 2808 } 2809 #endif /*INET6*/ 2810 2811 #ifndef INET_ONLY 2812 void 2813 at_getaddr(addr, which) 2814 const char *addr; 2815 int which; 2816 { 2817 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 2818 u_int net, node; 2819 2820 sat->sat_family = AF_APPLETALK; 2821 sat->sat_len = sizeof(*sat); 2822 if (which == MASK) 2823 errx(EXIT_FAILURE, "AppleTalk does not use netmasks"); 2824 if (sscanf(addr, "%u.%u", &net, &node) != 2 2825 || net == 0 || net > 0xffff || node == 0 || node > 0xfe) 2826 errx(EXIT_FAILURE, "%s: illegal address", addr); 2827 sat->sat_addr.s_net = htons(net); 2828 sat->sat_addr.s_node = node; 2829 } 2830 2831 void 2832 setatrange(range, d) 2833 const char *range; 2834 int d; 2835 { 2836 u_short first = 123, last = 123; 2837 2838 if (sscanf(range, "%hu-%hu", &first, &last) != 2 2839 || first == 0 /* || first > 0xffff */ 2840 || last == 0 /* || last > 0xffff */ || first > last) 2841 errx(EXIT_FAILURE, "%s: illegal net range: %u-%u", range, 2842 first, last); 2843 at_nr.nr_firstnet = htons(first); 2844 at_nr.nr_lastnet = htons(last); 2845 } 2846 2847 void 2848 setatphase(phase, d) 2849 const char *phase; 2850 int d; 2851 { 2852 if (!strcmp(phase, "1")) 2853 at_nr.nr_phase = 1; 2854 else if (!strcmp(phase, "2")) 2855 at_nr.nr_phase = 2; 2856 else 2857 errx(EXIT_FAILURE, "%s: illegal phase", phase); 2858 } 2859 2860 void 2861 checkatrange(sat) 2862 struct sockaddr_at *sat; 2863 { 2864 if (at_nr.nr_phase == 0) 2865 at_nr.nr_phase = 2; /* Default phase 2 */ 2866 if (at_nr.nr_firstnet == 0) 2867 at_nr.nr_firstnet = /* Default range of one */ 2868 at_nr.nr_lastnet = sat->sat_addr.s_net; 2869 printf("\tatalk %d.%d range %d-%d phase %d\n", 2870 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 2871 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 2872 if ((u_short) ntohs(at_nr.nr_firstnet) > 2873 (u_short) ntohs(sat->sat_addr.s_net) 2874 || (u_short) ntohs(at_nr.nr_lastnet) < 2875 (u_short) ntohs(sat->sat_addr.s_net)) 2876 errx(EXIT_FAILURE, "AppleTalk address is not in range"); 2877 *((struct netrange *) &sat->sat_zero) = at_nr; 2878 } 2879 2880 #define SNS(x) ((struct sockaddr_ns *) &(x)) 2881 struct sockaddr_ns *snstab[] = { 2882 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 2883 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 2884 2885 void 2886 xns_getaddr(addr, which) 2887 const char *addr; 2888 int which; 2889 { 2890 struct sockaddr_ns *sns = snstab[which]; 2891 2892 sns->sns_family = AF_NS; 2893 sns->sns_len = sizeof(*sns); 2894 sns->sns_addr = ns_addr(addr); 2895 if (which == MASK) 2896 puts("Attempt to set XNS netmask will be ineffectual"); 2897 } 2898 2899 #define SISO(x) ((struct sockaddr_iso *) &(x)) 2900 struct sockaddr_iso *sisotab[] = { 2901 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 2902 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 2903 2904 void 2905 iso_getaddr(addr, which) 2906 const char *addr; 2907 int which; 2908 { 2909 struct sockaddr_iso *siso = sisotab[which]; 2910 siso->siso_addr = *iso_addr(addr); 2911 2912 if (which == MASK) { 2913 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 2914 siso->siso_nlen = 0; 2915 } else { 2916 siso->siso_len = sizeof(*siso); 2917 siso->siso_family = AF_ISO; 2918 } 2919 } 2920 2921 void 2922 setsnpaoffset(val, d) 2923 const char *val; 2924 int d; 2925 { 2926 iso_addreq.ifra_snpaoffset = atoi(val); 2927 } 2928 2929 void 2930 setnsellength(val, d) 2931 const char *val; 2932 int d; 2933 { 2934 nsellength = atoi(val); 2935 if (nsellength < 0) 2936 errx(EXIT_FAILURE, "Negative NSEL length is absurd"); 2937 if (afp == 0 || afp->af_af != AF_ISO) 2938 errx(EXIT_FAILURE, "Setting NSEL length valid only for iso"); 2939 } 2940 2941 void 2942 fixnsel(siso) 2943 struct sockaddr_iso *siso; 2944 { 2945 if (siso->siso_family == 0) 2946 return; 2947 siso->siso_tlen = nsellength; 2948 } 2949 2950 void 2951 adjust_nsellength() 2952 { 2953 fixnsel(sisotab[RIDADDR]); 2954 fixnsel(sisotab[ADDR]); 2955 fixnsel(sisotab[DSTADDR]); 2956 } 2957 2958 #endif /* INET_ONLY */ 2959 2960 void 2961 usage() 2962 { 2963 const char *progname = getprogname(); 2964 2965 fprintf(stderr, 2966 "usage: %s [ -m ] [ -v ]" 2967 #ifdef INET6 2968 "[ -L ] " 2969 #endif 2970 "interface\n" 2971 "\t[ af [ address [ dest_addr ] ] [ netmask mask ] [ prefixlen n ]\n" 2972 "\t\t[ alias | -alias ] ]\n" 2973 "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n" 2974 "\t[ nwid network_id ] [ nwkey network_key | -nwkey ]\n" 2975 "\t[ powersave | -powersave ] [ powersavesleep duration ]\n" 2976 "\t[ [ af ] tunnel src_addr dest_addr ] [ deletetunnel ]\n" 2977 "\t[ arp | -arp ]\n" 2978 "\t[ media type ] [ mediaopt opts ] [ -mediaopt opts ] " 2979 "[ instance minst ]\n" 2980 "\t[ vlan n vlanif i ]\n" 2981 "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n" 2982 "\t[ tentative | -tentative ] [ pltime n ] [ vltime n ] [ eui64 ]\n" 2983 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n" 2984 " %s -a [ -m ] [ -d ] [ -u ] [ -v ] [ af ]\n" 2985 " %s -l [ -b ] [ -d ] [ -u ] [ -s ]\n" 2986 " %s -C\n" 2987 " %s interface create\n" 2988 " %s interface destroy\n", 2989 progname, progname, progname, progname, progname, progname); 2990 exit(1); 2991 } 2992 2993 #ifdef INET6 2994 char * 2995 sec2str(total) 2996 time_t total; 2997 { 2998 static char result[256]; 2999 int days, hours, mins, secs; 3000 int first = 1; 3001 char *p = result; 3002 char *end = &result[sizeof(result)]; 3003 int n; 3004 3005 if (0) { /*XXX*/ 3006 days = total / 3600 / 24; 3007 hours = (total / 3600) % 24; 3008 mins = (total / 60) % 60; 3009 secs = total % 60; 3010 3011 if (days) { 3012 first = 0; 3013 n = snprintf(p, end - p, "%dd", days); 3014 if (n < 0 || n >= end - p) 3015 return(result); 3016 p += n; 3017 } 3018 if (!first || hours) { 3019 first = 0; 3020 n = snprintf(p, end - p, "%dh", hours); 3021 if (n < 0 || n >= end - p) 3022 return(result); 3023 p += n; 3024 } 3025 if (!first || mins) { 3026 first = 0; 3027 n = snprintf(p, end - p, "%dm", mins); 3028 if (n < 0 || n >= end - p) 3029 return(result); 3030 p += n; 3031 } 3032 snprintf(p, end - p, "%ds", secs); 3033 } else 3034 snprintf(p, end - p, "%lu", (u_long)total); 3035 3036 return(result); 3037 } 3038 #endif 3039