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