ifconfig.c revision 93281
1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1983, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 43#endif 44static const char rcsid[] = 45 "$FreeBSD: head/sbin/ifconfig/ifconfig.c 93281 2002-03-27 14:29:23Z ru $"; 46#endif /* not lint */ 47 48#include <sys/param.h> 49#include <sys/ioctl.h> 50#include <sys/socket.h> 51#include <sys/sysctl.h> 52#include <sys/time.h> 53#include <sys/module.h> 54#include <sys/linker.h> 55 56#include <net/ethernet.h> 57#include <net/if.h> 58#include <net/if_var.h> 59#include <net/if_dl.h> 60#include <net/if_types.h> 61#include <net/route.h> 62 63/* IP */ 64#include <netinet/in.h> 65#include <netinet/in_var.h> 66#include <arpa/inet.h> 67#include <netdb.h> 68 69#ifdef INET6 70#include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */ 71#endif 72 73#ifndef NO_IPX 74/* IPX */ 75#define IPXIP 76#define IPTUNNEL 77#include <netipx/ipx.h> 78#include <netipx/ipx_if.h> 79#endif 80 81/* Appletalk */ 82#include <netatalk/at.h> 83 84/* XNS */ 85#ifdef NS 86#define NSIP 87#include <netns/ns.h> 88#include <netns/ns_if.h> 89#endif 90 91/* OSI */ 92 93#include <ctype.h> 94#include <err.h> 95#include <errno.h> 96#include <fcntl.h> 97#include <stdio.h> 98#include <stdlib.h> 99#include <string.h> 100#include <unistd.h> 101 102#include "ifconfig.h" 103 104/* wrapper for KAME-special getnameinfo() */ 105#ifndef NI_WITHSCOPEID 106#define NI_WITHSCOPEID 0 107#endif 108 109struct ifreq ifr, ridreq; 110struct ifaliasreq addreq; 111#ifdef INET6 112struct in6_ifreq in6_ridreq; 113struct in6_aliasreq in6_addreq = 114 { { 0 }, 115 { 0 }, 116 { 0 }, 117 { 0 }, 118 0, 119 { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; 120#endif 121struct sockaddr_in netmask; 122struct netrange at_nr; /* AppleTalk net range */ 123 124char name[32]; 125int flags; 126int setaddr; 127int setipdst; 128int setmask; 129int doalias; 130int clearaddr; 131int newaddr = 1; 132#ifdef INET6 133static int ip6lifetime; 134#endif 135 136struct afswtch; 137 138int supmedia = 0; 139int listcloners = 0; 140 141#ifdef INET6 142char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/ 143#endif 144 145void Perror __P((const char *cmd)); 146void checkatrange __P((struct sockaddr_at *)); 147int ifconfig __P((int argc, char *const *argv, const struct afswtch *afp)); 148void notealias __P((const char *, int, int, const struct afswtch *afp)); 149void list_cloners __P((void)); 150void printb __P((const char *s, unsigned value, const char *bits)); 151void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 152void status __P((const struct afswtch *afp, int addrcount, 153 struct sockaddr_dl *sdl, struct if_msghdr *ifm, 154 struct ifa_msghdr *ifam)); 155void tunnel_status __P((int s)); 156void usage __P((void)); 157void ifmaybeload __P((char *name)); 158 159#ifdef INET6 160void in6_fillscopeid __P((struct sockaddr_in6 *sin6)); 161int prefix __P((void *, int)); 162static char *sec2str __P((time_t)); 163int explicit_prefix = 0; 164#endif 165 166typedef void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp)); 167typedef void c_func2 __P((const char *arg, const char *arg2, int s, const struct afswtch *afp)); 168c_func setatphase, setatrange; 169c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask; 170c_func2 settunnel; 171c_func deletetunnel; 172#ifdef INET6 173c_func setifprefixlen; 174c_func setip6flags; 175c_func setip6pltime; 176c_func setip6vltime; 177c_func2 setip6lifetime; 178#endif 179c_func setifipdst; 180c_func setifflags, setifmetric, setifmtu, setifcap; 181c_func clone_destroy; 182 183 184void clone_create __P((void)); 185 186 187#define NEXTARG 0xffffff 188#define NEXTARG2 0xfffffe 189 190const 191struct cmd { 192 const char *c_name; 193 int c_parameter; /* NEXTARG means next argv */ 194 void (*c_func) __P((const char *, int, int, const struct afswtch *afp)); 195 void (*c_func2) __P((const char *, const char *, int, const struct afswtch *afp)); 196} cmds[] = { 197 { "up", IFF_UP, setifflags } , 198 { "down", -IFF_UP, setifflags }, 199 { "arp", -IFF_NOARP, setifflags }, 200 { "-arp", IFF_NOARP, setifflags }, 201 { "debug", IFF_DEBUG, setifflags }, 202 { "-debug", -IFF_DEBUG, setifflags }, 203 { "add", IFF_UP, notealias }, 204 { "alias", IFF_UP, notealias }, 205 { "-alias", -IFF_UP, notealias }, 206 { "delete", -IFF_UP, notealias }, 207 { "remove", -IFF_UP, notealias }, 208#ifdef notdef 209#define EN_SWABIPS 0x1000 210 { "swabips", EN_SWABIPS, setifflags }, 211 { "-swabips", -EN_SWABIPS, setifflags }, 212#endif 213 { "netmask", NEXTARG, setifnetmask }, 214#ifdef INET6 215 { "prefixlen", NEXTARG, setifprefixlen }, 216 { "anycast", IN6_IFF_ANYCAST, setip6flags }, 217 { "tentative", IN6_IFF_TENTATIVE, setip6flags }, 218 { "-tentative", -IN6_IFF_TENTATIVE, setip6flags }, 219 { "deprecated", IN6_IFF_DEPRECATED, setip6flags }, 220 { "-deprecated", -IN6_IFF_DEPRECATED, setip6flags }, 221 { "autoconf", IN6_IFF_AUTOCONF, setip6flags }, 222 { "-autoconf", -IN6_IFF_AUTOCONF, setip6flags }, 223 { "pltime", NEXTARG, setip6pltime }, 224 { "vltime", NEXTARG, setip6vltime }, 225#endif 226 { "range", NEXTARG, setatrange }, 227 { "phase", NEXTARG, setatphase }, 228 { "metric", NEXTARG, setifmetric }, 229 { "broadcast", NEXTARG, setifbroadaddr }, 230 { "ipdst", NEXTARG, setifipdst }, 231 { "tunnel", NEXTARG2, NULL, settunnel }, 232 { "deletetunnel", 0, deletetunnel }, 233 { "link0", IFF_LINK0, setifflags }, 234 { "-link0", -IFF_LINK0, setifflags }, 235 { "link1", IFF_LINK1, setifflags }, 236 { "-link1", -IFF_LINK1, setifflags }, 237 { "link2", IFF_LINK2, setifflags }, 238 { "-link2", -IFF_LINK2, setifflags }, 239#ifdef USE_IF_MEDIA 240 { "media", NEXTARG, setmedia }, 241 { "mediaopt", NEXTARG, setmediaopt }, 242 { "-mediaopt", NEXTARG, unsetmediaopt }, 243#endif 244#ifdef USE_VLANS 245 { "vlan", NEXTARG, setvlantag }, 246 { "vlandev", NEXTARG, setvlandev }, 247 { "-vlandev", NEXTARG, unsetvlandev }, 248#endif 249#if 0 250 /* XXX `create' special-cased below */ 251 {"create", 0, clone_create }, 252 {"plumb", 0, clone_create }, 253#endif 254 {"destroy", 0, clone_destroy }, 255 {"unplumb", 0, clone_destroy }, 256#ifdef USE_IEEE80211 257 { "ssid", NEXTARG, set80211ssid }, 258 { "nwid", NEXTARG, set80211ssid }, 259 { "stationname", NEXTARG, set80211stationname }, 260 { "station", NEXTARG, set80211stationname }, /* BSD/OS */ 261 { "channel", NEXTARG, set80211channel }, 262 { "authmode", NEXTARG, set80211authmode }, 263 { "powersavemode", NEXTARG, set80211powersavemode }, 264 { "powersave", 1, set80211powersave }, 265 { "-powersave", 0, set80211powersave }, 266 { "powersavesleep", NEXTARG, set80211powersavesleep }, 267 { "wepmode", NEXTARG, set80211wepmode }, 268 { "wep", 1, set80211wep }, 269 { "-wep", 0, set80211wep }, 270 { "weptxkey", NEXTARG, set80211weptxkey }, 271 { "wepkey", NEXTARG, set80211wepkey }, 272 { "nwkey", NEXTARG, set80211nwkey }, /* NetBSD */ 273 { "-nwkey", 0, set80211wep }, /* NetBSD */ 274#endif 275 { "rxcsum", IFCAP_RXCSUM, setifcap }, 276 { "-rxcsum", -IFCAP_RXCSUM, setifcap }, 277 { "txcsum", IFCAP_TXCSUM, setifcap }, 278 { "-txcsum", -IFCAP_TXCSUM, setifcap }, 279 { "netcons", IFCAP_NETCONS, setifcap }, 280 { "-netcons", -IFCAP_NETCONS, setifcap }, 281 { "normal", -IFF_LINK0, setifflags }, 282 { "compress", IFF_LINK0, setifflags }, 283 { "noicmp", IFF_LINK1, setifflags }, 284 { "mtu", NEXTARG, setifmtu }, 285 { 0, 0, setifaddr }, 286 { 0, 0, setifdstaddr }, 287}; 288 289/* 290 * XNS support liberally adapted from code written at the University of 291 * Maryland principally by James O'Toole and Chris Torek. 292 */ 293typedef void af_status __P((int, struct rt_addrinfo *)); 294typedef void af_getaddr __P((const char *, int)); 295typedef void af_getprefix __P((const char *, int)); 296 297af_status in_status, at_status, link_status; 298af_getaddr in_getaddr, at_getaddr, link_getaddr; 299 300#ifndef NO_IPX 301af_status ipx_status; 302af_getaddr ipx_getaddr; 303#endif 304 305#ifdef INET6 306af_status in6_status; 307af_getaddr in6_getaddr; 308af_getprefix in6_getprefix; 309#endif /*INET6*/ 310#ifdef NS 311af_status xns_status; 312af_getaddr xns_getaddr; 313#endif 314 315/* Known address families */ 316const 317struct afswtch { 318 const char *af_name; 319 short af_af; 320 af_status *af_status; 321 af_getaddr *af_getaddr; 322 af_getprefix *af_getprefix; 323 u_long af_difaddr; 324 u_long af_aifaddr; 325 caddr_t af_ridreq; 326 caddr_t af_addreq; 327} afs[] = { 328#define C(x) ((caddr_t) &x) 329 { "inet", AF_INET, in_status, in_getaddr, NULL, 330 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 331#ifdef INET6 332 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 333 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 334 C(in6_ridreq), C(in6_addreq) }, 335#endif /*INET6*/ 336#ifndef NO_IPX 337 { "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL, 338 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 339#endif 340 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 341 SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) }, 342#ifdef NS 343 { "ns", AF_NS, xns_status, xns_getaddr, NULL, 344 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 345#endif 346 { "link", AF_LINK, link_status, link_getaddr, NULL, 347 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 348 { "ether", AF_LINK, link_status, link_getaddr, NULL, 349 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 350 { "lladdr", AF_LINK, link_status, link_getaddr, NULL, 351 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 352#if 0 /* XXX conflicts with the media command */ 353#ifdef USE_IF_MEDIA 354 { "media", AF_UNSPEC, media_status, NULL, NULL, }, /* XXX not real!! */ 355#endif 356#ifdef USE_VLANS 357 { "vlan", AF_UNSPEC, vlan_status, NULL, NULL, }, /* XXX not real!! */ 358#endif 359#ifdef USE_IEEE80211 360 { "ieee80211", AF_UNSPEC, ieee80211_status, NULL, NULL, }, /* XXX not real!! */ 361#endif 362#endif 363 { 0, 0, 0, 0 } 364}; 365 366/* 367 * Expand the compacted form of addresses as returned via the 368 * configuration read via sysctl(). 369 */ 370 371#define ROUNDUP(a) \ 372 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 373#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 374 375void 376rt_xaddrs(cp, cplim, rtinfo) 377 caddr_t cp, cplim; 378 struct rt_addrinfo *rtinfo; 379{ 380 struct sockaddr *sa; 381 int i; 382 383 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 384 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 385 if ((rtinfo->rti_addrs & (1 << i)) == 0) 386 continue; 387 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 388 ADVANCE(cp, sa); 389 } 390} 391 392 393void 394usage() 395{ 396#ifndef INET6 397 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 398 "usage: ifconfig interface address_family [address [dest_address]]", 399 " [parameters]", 400 " ifconfig -C", 401 " ifconfig interface create", 402 " ifconfig -a [-d] [-m] [-u] [address_family]", 403 " ifconfig -l [-d] [-u] [address_family]", 404 " ifconfig [-d] [-m] [-u]"); 405#else 406 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 407 "usage: ifconfig [-L] interface address_family [address [dest_address]]", 408 " [parameters]", 409 " ifconfig -C", 410 " ifconfig interface create", 411 " ifconfig -a [-L] [-d] [-m] [-u] [address_family]", 412 " ifconfig -l [-d] [-u] [address_family]", 413 " ifconfig [-L] [-d] [-m] [-u]"); 414#endif 415 exit(1); 416} 417 418int 419main(argc, argv) 420 int argc; 421 char *const *argv; 422{ 423 int c; 424 int all, namesonly, downonly, uponly; 425 int need_nl = 0; 426 const struct afswtch *afp = 0; 427 int addrcount, ifindex; 428 struct if_msghdr *ifm, *nextifm; 429 struct ifa_msghdr *ifam; 430 struct sockaddr_dl *sdl; 431 char *buf, *lim, *next; 432 size_t needed; 433 int mib[6]; 434 435 /* Parse leading line options */ 436 all = downonly = uponly = namesonly = 0; 437 while ((c = getopt(argc, argv, "adlmuC" 438#ifdef INET6 439 "L" 440#endif 441 )) != -1) { 442 switch (c) { 443 case 'a': /* scan all interfaces */ 444 all++; 445 break; 446 case 'd': /* restrict scan to "down" interfaces */ 447 downonly++; 448 break; 449 case 'l': /* scan interface names only */ 450 namesonly++; 451 break; 452 case 'm': /* show media choices in status */ 453 supmedia = 1; 454 break; 455 case 'u': /* restrict scan to "up" interfaces */ 456 uponly++; 457 break; 458 case 'C': 459 listcloners = 1; 460 break; 461#ifdef INET6 462 case 'L': 463 ip6lifetime++; /* print IPv6 address lifetime */ 464 break; 465#endif 466 default: 467 usage(); 468 break; 469 } 470 } 471 argc -= optind; 472 argv += optind; 473 474 if (listcloners) { 475 /* -C must be solitary */ 476 if (all || supmedia || uponly || downonly || namesonly || 477 argc > 0) 478 usage(); 479 480 list_cloners(); 481 exit(0); 482 } 483 484 /* -l cannot be used with -a or -m */ 485 if (namesonly && (all || supmedia)) 486 usage(); 487 488 /* nonsense.. */ 489 if (uponly && downonly) 490 usage(); 491 492 /* no arguments is equivalent to '-a' */ 493 if (!namesonly && argc < 1) 494 all = 1; 495 496 /* -a and -l allow an address family arg to limit the output */ 497 if (all || namesonly) { 498 if (argc > 1) 499 usage(); 500 501 ifindex = 0; 502 if (argc == 1) { 503 for (afp = afs; afp->af_name; afp++) 504 if (strcmp(afp->af_name, *argv) == 0) { 505 argc--, argv++; 506 break; 507 } 508 if (afp->af_name == NULL) 509 usage(); 510 /* leave with afp non-zero */ 511 } 512 } else { 513 /* not listing, need an argument */ 514 if (argc < 1) 515 usage(); 516 517 strncpy(name, *argv, sizeof(name)); 518 argc--, argv++; 519 520 /* check and maybe load support for this interface */ 521 ifmaybeload(name); 522 523 /* 524 * NOTE: We must special-case the `create' command right 525 * here as we would otherwise fail when trying to find 526 * the interface. 527 */ 528 if (argc > 0 && (strcmp(argv[0], "create") == 0 || 529 strcmp(argv[0], "plumb") == 0)) { 530 clone_create(); 531 argc--, argv++; 532 if (argc == 0) 533 exit(0); 534 } 535 ifindex = if_nametoindex(name); 536 if (ifindex == 0) 537 errx(1, "interface %s does not exist", name); 538 } 539 540 /* Check for address family */ 541 if (argc > 0) { 542 for (afp = afs; afp->af_name; afp++) 543 if (strcmp(afp->af_name, *argv) == 0) { 544 argc--, argv++; 545 break; 546 } 547 if (afp->af_name == NULL) 548 afp = NULL; /* not a family, NULL */ 549 } 550 551 mib[0] = CTL_NET; 552 mib[1] = PF_ROUTE; 553 mib[2] = 0; 554 mib[3] = 0; /* address family */ 555 mib[4] = NET_RT_IFLIST; 556 mib[5] = ifindex; /* interface index */ 557 558 /* if particular family specified, only ask about it */ 559 if (afp) 560 mib[3] = afp->af_af; 561 562 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 563 errx(1, "iflist-sysctl-estimate"); 564 if ((buf = malloc(needed)) == NULL) 565 errx(1, "malloc"); 566 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 567 errx(1, "actual retrieval of interface table"); 568 lim = buf + needed; 569 570 next = buf; 571 while (next < lim) { 572 573 ifm = (struct if_msghdr *)next; 574 575 if (ifm->ifm_type == RTM_IFINFO) { 576 sdl = (struct sockaddr_dl *)(ifm + 1); 577 flags = ifm->ifm_flags; 578 } else { 579 fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n"); 580 fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, 581 ifm->ifm_type); 582 fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); 583 fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, 584 lim); 585 exit (1); 586 } 587 588 next += ifm->ifm_msglen; 589 ifam = NULL; 590 addrcount = 0; 591 while (next < lim) { 592 593 nextifm = (struct if_msghdr *)next; 594 595 if (nextifm->ifm_type != RTM_NEWADDR) 596 break; 597 598 if (ifam == NULL) 599 ifam = (struct ifa_msghdr *)nextifm; 600 601 addrcount++; 602 next += nextifm->ifm_msglen; 603 } 604 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 605 name[sdl->sdl_nlen] = '\0'; 606 607 if (all || namesonly) { 608 if (uponly) 609 if ((flags & IFF_UP) == 0) 610 continue; /* not up */ 611 if (downonly) 612 if (flags & IFF_UP) 613 continue; /* not down */ 614 if (namesonly) { 615 if (afp == NULL || 616 afp->af_status != link_status || 617 sdl->sdl_type == IFT_ETHER) { 618 if (need_nl) 619 putchar(' '); 620 fputs(name, stdout); 621 need_nl++; 622 } 623 continue; 624 } 625 } 626 627 if (argc > 0) 628 ifconfig(argc, argv, afp); 629 else 630 status(afp, addrcount, sdl, ifm, ifam); 631 } 632 free(buf); 633 634 if (namesonly && need_nl > 0) 635 putchar('\n'); 636 637 exit (0); 638} 639 640int 641ifconfig(argc, argv, afp) 642 int argc; 643 char *const *argv; 644 const struct afswtch *afp; 645{ 646 int s; 647 648 if (afp == NULL) 649 afp = &afs[0]; 650 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 651 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 652 653 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 654 err(1, "socket"); 655 656 while (argc > 0) { 657 const struct cmd *p; 658 659 for (p = cmds; p->c_name; p++) 660 if (strcmp(*argv, p->c_name) == 0) 661 break; 662 if (p->c_name == 0 && setaddr) 663 p++; /* got src, do dst */ 664 if (p->c_func || p->c_func2) { 665 if (p->c_parameter == NEXTARG) { 666 if (argv[1] == NULL) 667 errx(1, "'%s' requires argument", 668 p->c_name); 669 (*p->c_func)(argv[1], 0, s, afp); 670 argc--, argv++; 671 } else if (p->c_parameter == NEXTARG2) { 672 if (argc < 3) 673 errx(1, "'%s' requires 2 arguments", 674 p->c_name); 675 (*p->c_func2)(argv[1], argv[2], s, afp); 676 argc -= 2, argv += 2; 677 } else 678 (*p->c_func)(*argv, p->c_parameter, s, afp); 679 } 680 argc--, argv++; 681 } 682#ifdef INET6 683 if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) { 684 /* Aggregatable address architecture defines all prefixes 685 are 64. So, it is convenient to set prefixlen to 64 if 686 it is not specified. */ 687 setifprefixlen("64", 0, s, afp); 688 /* in6_getprefix("64", MASK) if MASK is available here... */ 689 } 690#endif 691#ifndef NO_IPX 692 if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) { 693 struct ipxip_req rq; 694 int size = sizeof(rq); 695 696 rq.rq_ipx = addreq.ifra_addr; 697 rq.rq_ip = addreq.ifra_dstaddr; 698 699 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 700 Perror("Encapsulation Routing"); 701 } 702#endif 703 if (ifr.ifr_addr.sa_family == AF_APPLETALK) 704 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 705#ifdef NS 706 if (setipdst && ifr.ifr_addr.sa_family == AF_NS) { 707 struct nsip_req rq; 708 int size = sizeof(rq); 709 710 rq.rq_ns = addreq.ifra_addr; 711 rq.rq_ip = addreq.ifra_dstaddr; 712 713 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 714 Perror("Encapsulation Routing"); 715 } 716#endif 717 if (clearaddr) { 718 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 719 warnx("interface %s cannot change %s addresses!", 720 name, afp->af_name); 721 clearaddr = NULL; 722 } 723 } 724 if (clearaddr) { 725 int ret; 726 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 727 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { 728 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 729 /* means no previous address for interface */ 730 } else 731 Perror("ioctl (SIOCDIFADDR)"); 732 } 733 } 734 if (newaddr) { 735 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 736 warnx("interface %s cannot change %s addresses!", 737 name, afp->af_name); 738 newaddr = 0; 739 } 740 } 741 if (newaddr && (setaddr || setmask)) { 742 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 743 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 744 Perror("ioctl (SIOCAIFADDR)"); 745 } 746 close(s); 747 return(0); 748} 749#define RIDADDR 0 750#define ADDR 1 751#define MASK 2 752#define DSTADDR 3 753 754/*ARGSUSED*/ 755void 756setifaddr(addr, param, s, afp) 757 const char *addr; 758 int param; 759 int s; 760 const struct afswtch *afp; 761{ 762 if (*afp->af_getaddr == NULL) 763 return; 764 /* 765 * Delay the ioctl to set the interface addr until flags are all set. 766 * The address interpretation may depend on the flags, 767 * and the flags may change when the address is set. 768 */ 769 setaddr++; 770 if (doalias == 0 && afp->af_af != AF_LINK) 771 clearaddr = 1; 772 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 773} 774 775void 776settunnel(src, dst, s, afp) 777 const char *src, *dst; 778 int s; 779 const struct afswtch *afp; 780{ 781 struct addrinfo hints, *srcres, *dstres; 782 struct ifaliasreq addreq; 783 int ecode; 784#ifdef INET6 785 struct in6_aliasreq in6_addreq; 786#endif 787 788 memset(&hints, 0, sizeof(hints)); 789 hints.ai_family = afp->af_af; 790 791 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 792 errx(1, "error in parsing address string: %s", 793 gai_strerror(ecode)); 794 795 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 796 errx(1, "error in parsing address string: %s", 797 gai_strerror(ecode)); 798 799 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 800 errx(1, 801 "source and destination address families do not match"); 802 803 switch (srcres->ai_addr->sa_family) { 804 case AF_INET: 805 memset(&addreq, 0, sizeof(addreq)); 806 strncpy(addreq.ifra_name, name, IFNAMSIZ); 807 memcpy(&addreq.ifra_addr, srcres->ai_addr, 808 srcres->ai_addr->sa_len); 809 memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, 810 dstres->ai_addr->sa_len); 811 812 if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0) 813 warn("SIOCSIFPHYADDR"); 814 break; 815 816#ifdef INET6 817 case AF_INET6: 818 memset(&in6_addreq, 0, sizeof(in6_addreq)); 819 strncpy(in6_addreq.ifra_name, name, IFNAMSIZ); 820 memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, 821 srcres->ai_addr->sa_len); 822 memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr, 823 dstres->ai_addr->sa_len); 824 825 if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0) 826 warn("SIOCSIFPHYADDR_IN6"); 827 break; 828#endif /* INET6 */ 829 830 default: 831 warn("address family not supported"); 832 } 833 834 freeaddrinfo(srcres); 835 freeaddrinfo(dstres); 836} 837 838/* ARGSUSED */ 839void 840deletetunnel(vname, param, s, afp) 841 const char *vname; 842 int param; 843 int s; 844 const struct afswtch *afp; 845{ 846 847 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 848 err(1, "SIOCDIFPHYADDR"); 849} 850 851void 852setifnetmask(addr, dummy, s, afp) 853 const char *addr; 854 int dummy __unused; 855 int s; 856 const struct afswtch *afp; 857{ 858 if (*afp->af_getaddr == NULL) 859 return; 860 setmask++; 861 (*afp->af_getaddr)(addr, MASK); 862} 863 864#ifdef INET6 865void 866setifprefixlen(addr, dummy, s, afp) 867 const char *addr; 868 int dummy __unused; 869 int s; 870 const struct afswtch *afp; 871{ 872 if (*afp->af_getprefix) 873 (*afp->af_getprefix)(addr, MASK); 874 explicit_prefix = 1; 875} 876 877void 878setip6flags(dummyaddr, flag, dummysoc, afp) 879 const char *dummyaddr __unused; 880 int flag; 881 int dummysoc __unused; 882 const struct afswtch *afp; 883{ 884 if (afp->af_af != AF_INET6) 885 err(1, "address flags can be set only for inet6 addresses"); 886 887 if (flag < 0) 888 in6_addreq.ifra_flags &= ~(-flag); 889 else 890 in6_addreq.ifra_flags |= flag; 891} 892 893void 894setip6pltime(seconds, dummy, s, afp) 895 const char *seconds; 896 int dummy __unused; 897 int s; 898 const struct afswtch *afp; 899{ 900 setip6lifetime("pltime", seconds, s, afp); 901} 902 903void 904setip6vltime(seconds, dummy, s, afp) 905 const char *seconds; 906 int dummy __unused; 907 int s; 908 const struct afswtch *afp; 909{ 910 setip6lifetime("vltime", seconds, s, afp); 911} 912 913void 914setip6lifetime(cmd, val, s, afp) 915 const char *cmd; 916 const char *val; 917 int s; 918 const struct afswtch *afp; 919{ 920 time_t newval, t; 921 char *ep; 922 923 t = time(NULL); 924 newval = (time_t)strtoul(val, &ep, 0); 925 if (val == ep) 926 errx(1, "invalid %s", cmd); 927 if (afp->af_af != AF_INET6) 928 errx(1, "%s not allowed for the AF", cmd); 929 if (strcmp(cmd, "vltime") == 0) { 930 in6_addreq.ifra_lifetime.ia6t_expire = t + newval; 931 in6_addreq.ifra_lifetime.ia6t_vltime = newval; 932 } else if (strcmp(cmd, "pltime") == 0) { 933 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; 934 in6_addreq.ifra_lifetime.ia6t_pltime = newval; 935 } 936} 937#endif 938 939void 940setifbroadaddr(addr, dummy, s, afp) 941 const char *addr; 942 int dummy __unused; 943 int s; 944 const struct afswtch *afp; 945{ 946 if (*afp->af_getaddr == NULL) 947 return; 948 (*afp->af_getaddr)(addr, DSTADDR); 949} 950 951void 952setifipdst(addr, dummy, s, afp) 953 const char *addr; 954 int dummy __unused; 955 int s; 956 const struct afswtch *afp; 957{ 958 in_getaddr(addr, DSTADDR); 959 setipdst++; 960 clearaddr = 0; 961 newaddr = 0; 962} 963#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 964 965void 966notealias(addr, param, s, afp) 967 const char *addr; 968 int param; 969 int s; 970 const struct afswtch *afp; 971{ 972 if (setaddr && doalias == 0 && param < 0) 973 bcopy((caddr_t)rqtosa(af_addreq), 974 (caddr_t)rqtosa(af_ridreq), 975 rqtosa(af_addreq)->sa_len); 976 doalias = param; 977 if (param < 0) { 978 clearaddr = 1; 979 newaddr = 0; 980 } else 981 clearaddr = 0; 982} 983 984/*ARGSUSED*/ 985void 986setifdstaddr(addr, param, s, afp) 987 const char *addr; 988 int param __unused; 989 int s; 990 const struct afswtch *afp; 991{ 992 if (*afp->af_getaddr == NULL) 993 return; 994 (*afp->af_getaddr)(addr, DSTADDR); 995} 996 997/* 998 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 999 * of the ifreq structure, which may confuse other parts of ifconfig. 1000 * Make a private copy so we can avoid that. 1001 */ 1002void 1003setifflags(vname, value, s, afp) 1004 const char *vname; 1005 int value; 1006 int s; 1007 const struct afswtch *afp; 1008{ 1009 struct ifreq my_ifr; 1010 1011 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 1012 1013 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 1014 Perror("ioctl (SIOCGIFFLAGS)"); 1015 exit(1); 1016 } 1017 strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name)); 1018 flags = my_ifr.ifr_flags; 1019 1020 if (value < 0) { 1021 value = -value; 1022 flags &= ~value; 1023 } else 1024 flags |= value; 1025 my_ifr.ifr_flags = flags; 1026 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 1027 Perror(vname); 1028} 1029 1030void 1031setifcap(vname, value, s, afp) 1032 const char *vname; 1033 int value; 1034 int s; 1035 const struct afswtch *afp; 1036{ 1037 1038 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 1039 Perror("ioctl (SIOCGIFCAP)"); 1040 exit(1); 1041 } 1042 flags = ifr.ifr_curcap; 1043 if (value < 0) { 1044 value = -value; 1045 flags &= ~value; 1046 } else 1047 flags |= value; 1048 ifr.ifr_reqcap = flags; 1049 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 1050 Perror(vname); 1051} 1052 1053void 1054setifmetric(val, dummy, s, afp) 1055 const char *val; 1056 int dummy __unused; 1057 int s; 1058 const struct afswtch *afp; 1059{ 1060 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1061 ifr.ifr_metric = atoi(val); 1062 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 1063 warn("ioctl (set metric)"); 1064} 1065 1066void 1067setifmtu(val, dummy, s, afp) 1068 const char *val; 1069 int dummy __unused; 1070 int s; 1071 const struct afswtch *afp; 1072{ 1073 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1074 ifr.ifr_mtu = atoi(val); 1075 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 1076 warn("ioctl (set mtu)"); 1077} 1078 1079#define IFFBITS \ 1080"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 1081"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 1082"\20MULTICAST" 1083 1084#define IFCAPBITS \ 1085"\003\1rxcsum\2txcsum\3netcons" 1086 1087/* 1088 * Print the status of the interface. If an address family was 1089 * specified, show it and it only; otherwise, show them all. 1090 */ 1091void 1092status(afp, addrcount, sdl, ifm, ifam) 1093 const struct afswtch *afp; 1094 int addrcount; 1095 struct sockaddr_dl *sdl; 1096 struct if_msghdr *ifm; 1097 struct ifa_msghdr *ifam; 1098{ 1099 const struct afswtch *p = NULL; 1100 struct rt_addrinfo info; 1101 int allfamilies, s; 1102 struct ifstat ifs; 1103 1104 if (afp == NULL) { 1105 allfamilies = 1; 1106 afp = &afs[0]; 1107 } else 1108 allfamilies = 0; 1109 1110 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 1111 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1112 1113 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 1114 err(1, "socket"); 1115 1116 printf("%s: ", name); 1117 printb("flags", flags, IFFBITS); 1118 if (ifm->ifm_data.ifi_metric) 1119 printf(" metric %ld", ifm->ifm_data.ifi_metric); 1120 if (ifm->ifm_data.ifi_mtu) 1121 printf(" mtu %ld", ifm->ifm_data.ifi_mtu); 1122 putchar('\n'); 1123 1124 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { 1125 if (ifr.ifr_curcap != 0) { 1126 printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 1127 putchar('\n'); 1128 } 1129 if (supmedia && ifr.ifr_reqcap != 0) { 1130 printf("\tcapability list:\n"); 1131 printb("\t\t", ifr.ifr_reqcap, IFCAPBITS); 1132 putchar('\n'); 1133 } 1134 } 1135 1136 tunnel_status(s); 1137 1138 while (addrcount > 0) { 1139 1140 info.rti_addrs = ifam->ifam_addrs; 1141 1142 /* Expand the compacted addresses */ 1143 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 1144 &info); 1145 1146 if (!allfamilies) { 1147 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family) { 1148 p = afp; 1149 (*p->af_status)(s, &info); 1150 } 1151 } else for (p = afs; p->af_name; p++) { 1152 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family) 1153 (*p->af_status)(s, &info); 1154 } 1155 addrcount--; 1156 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); 1157 } 1158 if (allfamilies || afp->af_status == link_status) 1159 link_status(s, (struct rt_addrinfo *)sdl); 1160#ifdef USE_IF_MEDIA 1161 if (allfamilies || afp->af_status == media_status) 1162 media_status(s, NULL); 1163#endif 1164#ifdef USE_VLANS 1165 if (allfamilies || afp->af_status == vlan_status) 1166 vlan_status(s, NULL); 1167#endif 1168#ifdef USE_IEEE80211 1169 if (allfamilies || afp->af_status == ieee80211_status) 1170 ieee80211_status(s, NULL); 1171#endif 1172 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 1173 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 1174 printf("%s", ifs.ascii); 1175 1176 if (!allfamilies && !p && afp->af_status != media_status && 1177 afp->af_status != link_status 1178#ifdef USE_VLANS 1179 && afp->af_status != vlan_status 1180#endif 1181 ) 1182 warnx("%s has no %s interface address!", name, afp->af_name); 1183 1184 close(s); 1185 return; 1186} 1187 1188void 1189tunnel_status(s) 1190 int s; 1191{ 1192 char psrcaddr[NI_MAXHOST]; 1193 char pdstaddr[NI_MAXHOST]; 1194 u_long srccmd, dstcmd; 1195 struct ifreq *ifrp; 1196 const char *ver = ""; 1197#ifdef NI_WITHSCOPEID 1198 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 1199#else 1200 const int niflag = NI_NUMERICHOST; 1201#endif 1202#ifdef INET6 1203 struct in6_ifreq in6_ifr; 1204 int s6; 1205#endif /* INET6 */ 1206 1207 psrcaddr[0] = pdstaddr[0] = '\0'; 1208 1209#ifdef INET6 1210 memset(&in6_ifr, 0, sizeof(in6_ifr)); 1211 strncpy(in6_ifr.ifr_name, name, IFNAMSIZ); 1212 s6 = socket(AF_INET6, SOCK_DGRAM, 0); 1213 if (s6 < 0) { 1214 srccmd = SIOCGIFPSRCADDR; 1215 dstcmd = SIOCGIFPDSTADDR; 1216 ifrp = 𝔦 1217 } else { 1218 close(s6); 1219 srccmd = SIOCGIFPSRCADDR_IN6; 1220 dstcmd = SIOCGIFPDSTADDR_IN6; 1221 ifrp = (struct ifreq *)&in6_ifr; 1222 } 1223#else /* INET6 */ 1224 srccmd = SIOCGIFPSRCADDR; 1225 dstcmd = SIOCGIFPDSTADDR; 1226 ifrp = 𝔦 1227#endif /* INET6 */ 1228 1229 if (ioctl(s, srccmd, (caddr_t)ifrp) < 0) 1230 return; 1231#ifdef INET6 1232 if (ifrp->ifr_addr.sa_family == AF_INET6) 1233 in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr); 1234#endif 1235 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 1236 psrcaddr, sizeof(psrcaddr), 0, 0, niflag); 1237#ifdef INET6 1238 if (ifrp->ifr_addr.sa_family == AF_INET6) 1239 ver = "6"; 1240#endif 1241 1242 if (ioctl(s, dstcmd, (caddr_t)ifrp) < 0) 1243 return; 1244#ifdef INET6 1245 if (ifrp->ifr_addr.sa_family == AF_INET6) 1246 in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr); 1247#endif 1248 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 1249 pdstaddr, sizeof(pdstaddr), 0, 0, niflag); 1250 1251 printf("\ttunnel inet%s %s --> %s\n", ver, 1252 psrcaddr, pdstaddr); 1253} 1254 1255void 1256in_status(s, info) 1257 int s __unused; 1258 struct rt_addrinfo * info; 1259{ 1260 struct sockaddr_in *sin, null_sin; 1261 1262 memset(&null_sin, 0, sizeof(null_sin)); 1263 1264 sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; 1265 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 1266 1267 if (flags & IFF_POINTOPOINT) { 1268 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1269 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1270 if (!sin) 1271 sin = &null_sin; 1272 printf("--> %s ", inet_ntoa(sin->sin_addr)); 1273 } 1274 1275 sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; 1276 if (!sin) 1277 sin = &null_sin; 1278 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 1279 1280 if (flags & IFF_BROADCAST) { 1281 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1282 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1283 if (sin && sin->sin_addr.s_addr != 0) 1284 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 1285 } 1286 putchar('\n'); 1287} 1288 1289#ifdef INET6 1290void 1291in6_fillscopeid(sin6) 1292 struct sockaddr_in6 *sin6; 1293{ 1294#if defined(__KAME__) && defined(KAME_SCOPEID) 1295 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1296 sin6->sin6_scope_id = 1297 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 1298 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 1299 } 1300#endif 1301} 1302 1303void 1304in6_status(s, info) 1305 int s __unused; 1306 struct rt_addrinfo * info; 1307{ 1308 struct sockaddr_in6 *sin, null_sin; 1309 struct in6_ifreq ifr6; 1310 int s6; 1311 u_int32_t flags6; 1312 struct in6_addrlifetime lifetime; 1313 time_t t = time(NULL); 1314 int error; 1315 u_int32_t scopeid; 1316 1317 memset(&null_sin, 0, sizeof(null_sin)); 1318 1319 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA]; 1320 strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); 1321 if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1322 perror("ifconfig: socket"); 1323 return; 1324 } 1325 ifr6.ifr_addr = *sin; 1326 if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 1327 perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)"); 1328 close(s6); 1329 return; 1330 } 1331 flags6 = ifr6.ifr_ifru.ifru_flags6; 1332 memset(&lifetime, 0, sizeof(lifetime)); 1333 ifr6.ifr_addr = *sin; 1334 if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) { 1335 perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)"); 1336 close(s6); 1337 return; 1338 } 1339 lifetime = ifr6.ifr_ifru.ifru_lifetime; 1340 close(s6); 1341 1342 /* XXX: embedded link local addr check */ 1343 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1344 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1345 u_short index; 1346 1347 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1348 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1349 if (sin->sin6_scope_id == 0) 1350 sin->sin6_scope_id = ntohs(index); 1351 } 1352 scopeid = sin->sin6_scope_id; 1353 1354 error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, 1355 sizeof(addr_buf), NULL, 0, 1356 NI_NUMERICHOST|NI_WITHSCOPEID); 1357 if (error != 0) 1358 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1359 sizeof(addr_buf)); 1360 printf("\tinet6 %s ", addr_buf); 1361 1362 if (flags & IFF_POINTOPOINT) { 1363 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1364 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD]; 1365 /* 1366 * some of the interfaces do not have valid destination 1367 * address. 1368 */ 1369 if (sin && sin->sin6_family == AF_INET6) { 1370 int error; 1371 1372 /* XXX: embedded link local addr check */ 1373 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1374 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1375 u_short index; 1376 1377 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1378 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1379 if (sin->sin6_scope_id == 0) 1380 sin->sin6_scope_id = ntohs(index); 1381 } 1382 1383 error = getnameinfo((struct sockaddr *)sin, 1384 sin->sin6_len, addr_buf, 1385 sizeof(addr_buf), NULL, 0, 1386 NI_NUMERICHOST|NI_WITHSCOPEID); 1387 if (error != 0) 1388 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1389 sizeof(addr_buf)); 1390 printf("--> %s ", addr_buf); 1391 } 1392 } 1393 1394 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; 1395 if (!sin) 1396 sin = &null_sin; 1397 printf("prefixlen %d ", prefix(&sin->sin6_addr, 1398 sizeof(struct in6_addr))); 1399 1400 if ((flags6 & IN6_IFF_ANYCAST) != 0) 1401 printf("anycast "); 1402 if ((flags6 & IN6_IFF_TENTATIVE) != 0) 1403 printf("tentative "); 1404 if ((flags6 & IN6_IFF_DUPLICATED) != 0) 1405 printf("duplicated "); 1406 if ((flags6 & IN6_IFF_DETACHED) != 0) 1407 printf("detached "); 1408 if ((flags6 & IN6_IFF_DEPRECATED) != 0) 1409 printf("deprecated "); 1410 if ((flags6 & IN6_IFF_AUTOCONF) != 0) 1411 printf("autoconf "); 1412 if ((flags6 & IN6_IFF_TEMPORARY) != 0) 1413 printf("temporary "); 1414 1415 if (scopeid) 1416 printf("scopeid 0x%x ", scopeid); 1417 1418 if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { 1419 printf("pltime "); 1420 if (lifetime.ia6t_preferred) { 1421 printf("%s ", lifetime.ia6t_preferred < t 1422 ? "0" : sec2str(lifetime.ia6t_preferred - t)); 1423 } else 1424 printf("infty "); 1425 1426 printf("vltime "); 1427 if (lifetime.ia6t_expire) { 1428 printf("%s ", lifetime.ia6t_expire < t 1429 ? "0" : sec2str(lifetime.ia6t_expire - t)); 1430 } else 1431 printf("infty "); 1432 } 1433 1434 putchar('\n'); 1435} 1436#endif /*INET6*/ 1437 1438#ifndef NO_IPX 1439void 1440ipx_status(s, info) 1441 int s __unused; 1442 struct rt_addrinfo * info; 1443{ 1444 struct sockaddr_ipx *sipx, null_sipx; 1445 1446 memset(&null_sipx, 0, sizeof(null_sipx)); 1447 1448 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA]; 1449 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 1450 1451 if (flags & IFF_POINTOPOINT) { 1452 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD]; 1453 if (!sipx) 1454 sipx = &null_sipx; 1455 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 1456 } 1457 putchar('\n'); 1458} 1459#endif 1460 1461void 1462at_status(s, info) 1463 int s __unused; 1464 struct rt_addrinfo * info; 1465{ 1466 struct sockaddr_at *sat, null_sat; 1467 struct netrange *nr; 1468 1469 memset(&null_sat, 0, sizeof(null_sat)); 1470 1471 sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA]; 1472 nr = &sat->sat_range.r_netrange; 1473 printf("\tatalk %d.%d range %d-%d phase %d", 1474 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1475 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 1476 if (flags & IFF_POINTOPOINT) { 1477 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1478 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1479 if (!sat) 1480 sat = &null_sat; 1481 printf("--> %d.%d", 1482 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 1483 } 1484 if (flags & IFF_BROADCAST) { 1485 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1486 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1487 if (sat) 1488 printf(" broadcast %d.%d", 1489 ntohs(sat->sat_addr.s_net), 1490 sat->sat_addr.s_node); 1491 } 1492 1493 putchar('\n'); 1494} 1495 1496#ifdef NS 1497void 1498xns_status(s, info) 1499 int s __unused; 1500 struct rt_addrinfo * info; 1501{ 1502 struct sockaddr_ns *sns, null_sns; 1503 1504 memset(&null_sns, 0, sizeof(null_sns)); 1505 1506 sns = (struct sockaddr_ns *)info->rti_info[RTAX_IFA]; 1507 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1508 1509 if (flags & IFF_POINTOPOINT) { 1510 sns = (struct sockaddr_ns *)info->rti_info[RTAX_BRD]; 1511 if (!sns) 1512 sns = &null_sns; 1513 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1514 } 1515 1516 putchar('\n'); 1517 close(s); 1518} 1519#endif 1520 1521 1522void 1523link_status(s, info) 1524 int s __unused; 1525 struct rt_addrinfo *info; 1526{ 1527 int n; 1528 struct sockaddr_dl *sdl = (struct sockaddr_dl *)info; 1529 1530 if ((n = sdl->sdl_alen) > 0) { 1531 if (sdl->sdl_type == IFT_ETHER && 1532 sdl->sdl_alen == ETHER_ADDR_LEN) 1533 printf("\tether %s\n", 1534 ether_ntoa((struct ether_addr *)LLADDR(sdl))); 1535 else 1536 printf("\tlladdr %s\n", link_ntoa(sdl) + n + 1); 1537 } 1538} 1539 1540void 1541Perror(cmd) 1542 const char *cmd; 1543{ 1544 switch (errno) { 1545 1546 case ENXIO: 1547 errx(1, "%s: no such interface", cmd); 1548 break; 1549 1550 case EPERM: 1551 errx(1, "%s: permission denied", cmd); 1552 break; 1553 1554 default: 1555 err(1, "%s", cmd); 1556 } 1557} 1558 1559#define SIN(x) ((struct sockaddr_in *) &(x)) 1560struct sockaddr_in *sintab[] = { 1561SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1562SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1563 1564void 1565in_getaddr(s, which) 1566 const char *s; 1567 int which; 1568{ 1569 struct sockaddr_in *sin = sintab[which]; 1570 struct hostent *hp; 1571 struct netent *np; 1572 1573 sin->sin_len = sizeof(*sin); 1574 if (which != MASK) 1575 sin->sin_family = AF_INET; 1576 1577 if (which == ADDR) { 1578 char *p = NULL; 1579 1580 if((p = strrchr(s, '/')) != NULL) { 1581 /* address is `name/masklen' */ 1582 int masklen; 1583 int ret; 1584 struct sockaddr_in *min = sintab[MASK]; 1585 *p = '\0'; 1586 ret = sscanf(p+1, "%u", &masklen); 1587 if(ret != 1 || (masklen < 0 || masklen > 32)) { 1588 *p = '/'; 1589 errx(1, "%s: bad value", s); 1590 } 1591 min->sin_len = sizeof(*min); 1592 min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) & 1593 0xffffffff); 1594 } 1595 } 1596 1597 if (inet_aton(s, &sin->sin_addr)) 1598 return; 1599 if ((hp = gethostbyname(s)) != 0) 1600 bcopy(hp->h_addr, (char *)&sin->sin_addr, 1601 MIN(hp->h_length, sizeof(sin->sin_addr))); 1602 else if ((np = getnetbyname(s)) != 0) 1603 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1604 else 1605 errx(1, "%s: bad value", s); 1606} 1607 1608#ifdef INET6 1609#define SIN6(x) ((struct sockaddr_in6 *) &(x)) 1610struct sockaddr_in6 *sin6tab[] = { 1611SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 1612SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 1613 1614void 1615in6_getaddr(s, which) 1616 const char *s; 1617 int which; 1618{ 1619 struct sockaddr_in6 *sin = sin6tab[which]; 1620 struct addrinfo hints, *res; 1621 int error = -1; 1622 1623 newaddr &= 1; 1624 1625 sin->sin6_len = sizeof(*sin); 1626 if (which != MASK) 1627 sin->sin6_family = AF_INET6; 1628 1629 if (which == ADDR) { 1630 char *p = NULL; 1631 if((p = strrchr(s, '/')) != NULL) { 1632 *p = '\0'; 1633 in6_getprefix(p + 1, MASK); 1634 explicit_prefix = 1; 1635 } 1636 } 1637 1638 if (sin->sin6_family == AF_INET6) { 1639 bzero(&hints, sizeof(struct addrinfo)); 1640 hints.ai_family = AF_INET6; 1641 error = getaddrinfo(s, NULL, &hints, &res); 1642 } 1643 if (error != 0) { 1644 if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) 1645 errx(1, "%s: bad value", s); 1646 } else 1647 bcopy(res->ai_addr, sin, res->ai_addrlen); 1648} 1649 1650void 1651in6_getprefix(plen, which) 1652 const char *plen; 1653 int which; 1654{ 1655 struct sockaddr_in6 *sin = sin6tab[which]; 1656 u_char *cp; 1657 int len = atoi(plen); 1658 1659 if ((len < 0) || (len > 128)) 1660 errx(1, "%s: bad value", plen); 1661 sin->sin6_len = sizeof(*sin); 1662 if (which != MASK) 1663 sin->sin6_family = AF_INET6; 1664 if ((len == 0) || (len == 128)) { 1665 memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); 1666 return; 1667 } 1668 memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); 1669 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 1670 *cp++ = 0xff; 1671 *cp = 0xff << (8 - len); 1672} 1673#endif 1674 1675/* 1676 * Print a value a la the %b format of the kernel's printf 1677 */ 1678void 1679printb(s, v, bits) 1680 const char *s; 1681 unsigned v; 1682 const char *bits; 1683{ 1684 int i, any = 0; 1685 char c; 1686 1687 if (bits && *bits == 8) 1688 printf("%s=%o", s, v); 1689 else 1690 printf("%s=%x", s, v); 1691 bits++; 1692 if (bits) { 1693 putchar('<'); 1694 while ((i = *bits++) != '\0') { 1695 if (v & (1 << (i-1))) { 1696 if (any) 1697 putchar(','); 1698 any = 1; 1699 for (; (c = *bits) > 32; bits++) 1700 putchar(c); 1701 } else 1702 for (; *bits > 32; bits++) 1703 ; 1704 } 1705 putchar('>'); 1706 } 1707} 1708 1709#ifndef NO_IPX 1710#define SIPX(x) ((struct sockaddr_ipx *) &(x)) 1711struct sockaddr_ipx *sipxtab[] = { 1712SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 1713SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 1714 1715void 1716ipx_getaddr(addr, which) 1717 const char *addr; 1718 int which; 1719{ 1720 struct sockaddr_ipx *sipx = sipxtab[which]; 1721 1722 sipx->sipx_family = AF_IPX; 1723 sipx->sipx_len = sizeof(*sipx); 1724 sipx->sipx_addr = ipx_addr(addr); 1725 if (which == MASK) 1726 printf("Attempt to set IPX netmask will be ineffectual\n"); 1727} 1728#endif 1729 1730void 1731at_getaddr(addr, which) 1732 const char *addr; 1733 int which; 1734{ 1735 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 1736 u_int net, node; 1737 1738 sat->sat_family = AF_APPLETALK; 1739 sat->sat_len = sizeof(*sat); 1740 if (which == MASK) 1741 errx(1, "AppleTalk does not use netmasks"); 1742 if (sscanf(addr, "%u.%u", &net, &node) != 2 1743 || net > 0xffff || node > 0xfe) 1744 errx(1, "%s: illegal address", addr); 1745 sat->sat_addr.s_net = htons(net); 1746 sat->sat_addr.s_node = node; 1747} 1748 1749void 1750link_getaddr(addr, which) 1751 const char *addr; 1752 int which; 1753{ 1754 char *temp; 1755 struct sockaddr_dl sdl; 1756 struct sockaddr *sa = &ridreq.ifr_addr; 1757 1758 if (which != ADDR) 1759 errx(1, "can't set link-level netmask or broadcast"); 1760 if ((temp = malloc(strlen(addr) + 1)) == NULL) 1761 errx(1, "malloc failed"); 1762 temp[0] = ':'; 1763 strcpy(temp + 1, addr); 1764 sdl.sdl_len = sizeof(sdl); 1765 link_addr(temp, &sdl); 1766 free(temp); 1767 if (sdl.sdl_alen > sizeof(sa->sa_data)) 1768 errx(1, "malformed link-level address"); 1769 sa->sa_family = AF_LINK; 1770 sa->sa_len = sdl.sdl_alen; 1771 bcopy(LLADDR(&sdl), sa->sa_data, sdl.sdl_alen); 1772} 1773 1774/* XXX FIXME -- should use strtoul for better parsing. */ 1775void 1776setatrange(range, dummy, s, afp) 1777 const char *range; 1778 int dummy __unused; 1779 int s; 1780 const struct afswtch *afp; 1781{ 1782 u_short first = 123, last = 123; 1783 1784 if (sscanf(range, "%hu-%hu", &first, &last) != 2 1785 || first == 0 || first > 0xffff 1786 || last == 0 || last > 0xffff || first > last) 1787 errx(1, "%s: illegal net range: %u-%u", range, first, last); 1788 at_nr.nr_firstnet = htons(first); 1789 at_nr.nr_lastnet = htons(last); 1790} 1791 1792void 1793setatphase(phase, dummy, s, afp) 1794 const char *phase; 1795 int dummy __unused; 1796 int s; 1797 const struct afswtch *afp; 1798{ 1799 if (!strcmp(phase, "1")) 1800 at_nr.nr_phase = 1; 1801 else if (!strcmp(phase, "2")) 1802 at_nr.nr_phase = 2; 1803 else 1804 errx(1, "%s: illegal phase", phase); 1805} 1806 1807void 1808checkatrange(struct sockaddr_at *sat) 1809{ 1810 if (at_nr.nr_phase == 0) 1811 at_nr.nr_phase = 2; /* Default phase 2 */ 1812 if (at_nr.nr_firstnet == 0) 1813 at_nr.nr_firstnet = /* Default range of one */ 1814 at_nr.nr_lastnet = sat->sat_addr.s_net; 1815printf("\tatalk %d.%d range %d-%d phase %d\n", 1816 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1817 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 1818 if ((u_short) ntohs(at_nr.nr_firstnet) > 1819 (u_short) ntohs(sat->sat_addr.s_net) 1820 || (u_short) ntohs(at_nr.nr_lastnet) < 1821 (u_short) ntohs(sat->sat_addr.s_net)) 1822 errx(1, "AppleTalk address is not in range"); 1823 sat->sat_range.r_netrange = at_nr; 1824} 1825 1826#ifdef NS 1827#define SNS(x) ((struct sockaddr_ns *) &(x)) 1828struct sockaddr_ns *snstab[] = { 1829SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 1830SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 1831 1832void 1833xns_getaddr(addr, which) 1834 const char *addr; 1835 int which; 1836{ 1837 struct sockaddr_ns *sns = snstab[which]; 1838 1839 sns->sns_family = AF_NS; 1840 sns->sns_len = sizeof(*sns); 1841 sns->sns_addr = ns_addr(addr); 1842 if (which == MASK) 1843 printf("Attempt to set XNS netmask will be ineffectual\n"); 1844} 1845#endif 1846 1847#ifdef INET6 1848int 1849prefix(val, size) 1850 void *val; 1851 int size; 1852{ 1853 u_char *name = (u_char *)val; 1854 int byte, bit, plen = 0; 1855 1856 for (byte = 0; byte < size; byte++, plen += 8) 1857 if (name[byte] != 0xff) 1858 break; 1859 if (byte == size) 1860 return (plen); 1861 for (bit = 7; bit != 0; bit--, plen++) 1862 if (!(name[byte] & (1 << bit))) 1863 break; 1864 for (; bit != 0; bit--) 1865 if (name[byte] & (1 << bit)) 1866 return(0); 1867 byte++; 1868 for (; byte < size; byte++) 1869 if (name[byte]) 1870 return(0); 1871 return (plen); 1872} 1873 1874static char * 1875sec2str(total) 1876 time_t total; 1877{ 1878 static char result[256]; 1879 int days, hours, mins, secs; 1880 int first = 1; 1881 char *p = result; 1882 1883 if (0) { 1884 days = total / 3600 / 24; 1885 hours = (total / 3600) % 24; 1886 mins = (total / 60) % 60; 1887 secs = total % 60; 1888 1889 if (days) { 1890 first = 0; 1891 p += sprintf(p, "%dd", days); 1892 } 1893 if (!first || hours) { 1894 first = 0; 1895 p += sprintf(p, "%dh", hours); 1896 } 1897 if (!first || mins) { 1898 first = 0; 1899 p += sprintf(p, "%dm", mins); 1900 } 1901 sprintf(p, "%ds", secs); 1902 } else 1903 sprintf(result, "%lu", (unsigned long)total); 1904 1905 return(result); 1906} 1907#endif /*INET6*/ 1908 1909void 1910ifmaybeload(name) 1911 char *name; 1912{ 1913 struct module_stat mstat; 1914 int fileid, modid; 1915 char ifkind[35], *cp, *dp; 1916 1917 /* turn interface and unit into module name */ 1918 strcpy(ifkind, "if_"); 1919 for (cp = name, dp = ifkind + 3; 1920 (*cp != 0) && !isdigit(*cp); cp++, dp++) 1921 *dp = *cp; 1922 *dp = 0; 1923 1924 /* scan files in kernel */ 1925 mstat.version = sizeof(struct module_stat); 1926 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1927 /* scan modules in file */ 1928 for (modid = kldfirstmod(fileid); modid > 0; 1929 modid = modfnext(modid)) { 1930 if (modstat(modid, &mstat) < 0) 1931 continue; 1932 /* strip bus name if present */ 1933 if ((cp = strchr(mstat.name, '/')) != NULL) { 1934 cp++; 1935 } else { 1936 cp = mstat.name; 1937 } 1938 /* already loaded? */ 1939 if (!strcmp(ifkind, cp)) 1940 return; 1941 } 1942 } 1943 1944 /* not present, we should try to load it */ 1945 kldload(ifkind); 1946} 1947 1948void 1949list_cloners(void) 1950{ 1951 struct if_clonereq ifcr; 1952 char *cp, *buf; 1953 int idx; 1954 int s; 1955 1956 s = socket(AF_INET, SOCK_DGRAM, 0); 1957 if (s == -1) 1958 err(1, "socket"); 1959 1960 memset(&ifcr, 0, sizeof(ifcr)); 1961 1962 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 1963 err(1, "SIOCIFGCLONERS for count"); 1964 1965 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 1966 if (buf == NULL) 1967 err(1, "unable to allocate cloner name buffer"); 1968 1969 ifcr.ifcr_count = ifcr.ifcr_total; 1970 ifcr.ifcr_buffer = buf; 1971 1972 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 1973 err(1, "SIOCIFGCLONERS for names"); 1974 1975 /* 1976 * In case some disappeared in the mean time, clamp it down. 1977 */ 1978 if (ifcr.ifcr_count > ifcr.ifcr_total) 1979 ifcr.ifcr_count = ifcr.ifcr_total; 1980 1981 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 1982 if (idx > 0) 1983 putchar(' '); 1984 printf("%s", cp); 1985 } 1986 1987 putchar('\n'); 1988 free(buf); 1989} 1990 1991void 1992clone_create() 1993{ 1994 int s; 1995 1996 s = socket(AF_INET, SOCK_DGRAM, 0); 1997 if (s == -1) 1998 err(1, "socket"); 1999 2000 memset(&ifr, 0, sizeof(ifr)); 2001 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2002 if (ioctl(s, SIOCIFCREATE, &ifr) < 0) 2003 err(1, "SIOCIFCREATE"); 2004 2005 if (strcmp(name, ifr.ifr_name) != 0) { 2006 printf("%s\n", ifr.ifr_name); 2007 strlcpy(name, ifr.ifr_name, sizeof(name)); 2008 } 2009 2010 close(s); 2011} 2012 2013void 2014clone_destroy(val, d, s, rafp) 2015 const char *val; 2016 int d; 2017 int s; 2018 const struct afswtch *rafp; 2019{ 2020 2021 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2022 if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) 2023 err(1, "SIOCIFDESTROY"); 2024} 2025