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