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