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