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