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