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