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