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