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