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\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU" 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 && 1163 #ifdef USE_IF_MEDIA 1164 afp->af_status != media_status && 1165 #endif 1166 afp->af_status != link_status 1167 #ifdef USE_VLANS 1168 && afp->af_status != vlan_status 1169 #endif 1170 ) 1171 warnx("%s has no %s interface address!", name, afp->af_name); 1172 1173 close(s); 1174 return; 1175 } 1176 1177 void 1178 tunnel_status(int s) 1179 { 1180 char psrcaddr[NI_MAXHOST]; 1181 char pdstaddr[NI_MAXHOST]; 1182 u_long srccmd, dstcmd; 1183 struct ifreq *ifrp; 1184 const char *ver = ""; 1185 #ifdef NI_WITHSCOPEID 1186 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 1187 #else 1188 const int niflag = NI_NUMERICHOST; 1189 #endif 1190 #ifdef INET6 1191 struct in6_ifreq in6_ifr; 1192 int s6; 1193 #endif /* INET6 */ 1194 1195 psrcaddr[0] = pdstaddr[0] = '\0'; 1196 1197 #ifdef INET6 1198 memset(&in6_ifr, 0, sizeof(in6_ifr)); 1199 strncpy(in6_ifr.ifr_name, name, IFNAMSIZ); 1200 s6 = socket(AF_INET6, SOCK_DGRAM, 0); 1201 if (s6 < 0) { 1202 srccmd = SIOCGIFPSRCADDR; 1203 dstcmd = SIOCGIFPDSTADDR; 1204 ifrp = 𝔦 1205 } else { 1206 close(s6); 1207 srccmd = SIOCGIFPSRCADDR_IN6; 1208 dstcmd = SIOCGIFPDSTADDR_IN6; 1209 ifrp = (struct ifreq *)&in6_ifr; 1210 } 1211 #else /* INET6 */ 1212 srccmd = SIOCGIFPSRCADDR; 1213 dstcmd = SIOCGIFPDSTADDR; 1214 ifrp = 𝔦 1215 #endif /* INET6 */ 1216 1217 if (ioctl(s, srccmd, (caddr_t)ifrp) < 0) 1218 return; 1219 #ifdef INET6 1220 if (ifrp->ifr_addr.sa_family == AF_INET6) 1221 in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr); 1222 #endif 1223 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 1224 psrcaddr, sizeof(psrcaddr), 0, 0, niflag); 1225 #ifdef INET6 1226 if (ifrp->ifr_addr.sa_family == AF_INET6) 1227 ver = "6"; 1228 #endif 1229 1230 if (ioctl(s, dstcmd, (caddr_t)ifrp) < 0) 1231 return; 1232 #ifdef INET6 1233 if (ifrp->ifr_addr.sa_family == AF_INET6) 1234 in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr); 1235 #endif 1236 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 1237 pdstaddr, sizeof(pdstaddr), 0, 0, niflag); 1238 1239 printf("\ttunnel inet%s %s --> %s\n", ver, 1240 psrcaddr, pdstaddr); 1241 } 1242 1243 void 1244 in_status(int s __unused, struct rt_addrinfo * info) 1245 { 1246 struct sockaddr_in *sin, null_sin; 1247 1248 memset(&null_sin, 0, sizeof(null_sin)); 1249 1250 sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; 1251 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 1252 1253 if (flags & IFF_POINTOPOINT) { 1254 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1255 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1256 if (!sin) 1257 sin = &null_sin; 1258 printf("--> %s ", inet_ntoa(sin->sin_addr)); 1259 } 1260 1261 sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; 1262 if (!sin) 1263 sin = &null_sin; 1264 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 1265 1266 if (flags & IFF_BROADCAST) { 1267 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1268 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1269 if (sin && sin->sin_addr.s_addr != 0) 1270 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 1271 } 1272 putchar('\n'); 1273 } 1274 1275 #ifdef INET6 1276 void 1277 in6_fillscopeid(struct sockaddr_in6 *sin6) 1278 { 1279 #if defined(__KAME__) && defined(KAME_SCOPEID) 1280 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1281 sin6->sin6_scope_id = 1282 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 1283 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 1284 } 1285 #endif 1286 } 1287 1288 void 1289 in6_status(int s __unused, struct rt_addrinfo * info) 1290 { 1291 struct sockaddr_in6 *sin, null_sin; 1292 struct in6_ifreq ifr6; 1293 int s6; 1294 u_int32_t flags6; 1295 struct in6_addrlifetime lifetime; 1296 time_t t = time(NULL); 1297 int error; 1298 u_int32_t scopeid; 1299 1300 memset(&null_sin, 0, sizeof(null_sin)); 1301 1302 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA]; 1303 strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); 1304 if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1305 perror("ifconfig: socket"); 1306 return; 1307 } 1308 ifr6.ifr_addr = *sin; 1309 if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 1310 perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)"); 1311 close(s6); 1312 return; 1313 } 1314 flags6 = ifr6.ifr_ifru.ifru_flags6; 1315 memset(&lifetime, 0, sizeof(lifetime)); 1316 ifr6.ifr_addr = *sin; 1317 if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) { 1318 perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)"); 1319 close(s6); 1320 return; 1321 } 1322 lifetime = ifr6.ifr_ifru.ifru_lifetime; 1323 close(s6); 1324 1325 /* XXX: embedded link local addr check */ 1326 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1327 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1328 u_short index; 1329 1330 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1331 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1332 if (sin->sin6_scope_id == 0) 1333 sin->sin6_scope_id = ntohs(index); 1334 } 1335 scopeid = sin->sin6_scope_id; 1336 1337 error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, 1338 sizeof(addr_buf), NULL, 0, 1339 NI_NUMERICHOST|NI_WITHSCOPEID); 1340 if (error != 0) 1341 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1342 sizeof(addr_buf)); 1343 printf("\tinet6 %s ", addr_buf); 1344 1345 if (flags & IFF_POINTOPOINT) { 1346 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1347 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD]; 1348 /* 1349 * some of the interfaces do not have valid destination 1350 * address. 1351 */ 1352 if (sin && sin->sin6_family == AF_INET6) { 1353 int error; 1354 1355 /* XXX: embedded link local addr check */ 1356 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1357 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1358 u_short index; 1359 1360 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1361 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1362 if (sin->sin6_scope_id == 0) 1363 sin->sin6_scope_id = ntohs(index); 1364 } 1365 1366 error = getnameinfo((struct sockaddr *)sin, 1367 sin->sin6_len, addr_buf, 1368 sizeof(addr_buf), NULL, 0, 1369 NI_NUMERICHOST|NI_WITHSCOPEID); 1370 if (error != 0) 1371 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1372 sizeof(addr_buf)); 1373 printf("--> %s ", addr_buf); 1374 } 1375 } 1376 1377 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; 1378 if (!sin) 1379 sin = &null_sin; 1380 printf("prefixlen %d ", prefix(&sin->sin6_addr, 1381 sizeof(struct in6_addr))); 1382 1383 if ((flags6 & IN6_IFF_ANYCAST) != 0) 1384 printf("anycast "); 1385 if ((flags6 & IN6_IFF_TENTATIVE) != 0) 1386 printf("tentative "); 1387 if ((flags6 & IN6_IFF_DUPLICATED) != 0) 1388 printf("duplicated "); 1389 if ((flags6 & IN6_IFF_DETACHED) != 0) 1390 printf("detached "); 1391 if ((flags6 & IN6_IFF_DEPRECATED) != 0) 1392 printf("deprecated "); 1393 if ((flags6 & IN6_IFF_AUTOCONF) != 0) 1394 printf("autoconf "); 1395 if ((flags6 & IN6_IFF_TEMPORARY) != 0) 1396 printf("temporary "); 1397 1398 if (scopeid) 1399 printf("scopeid 0x%x ", scopeid); 1400 1401 if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { 1402 printf("pltime "); 1403 if (lifetime.ia6t_preferred) { 1404 printf("%s ", lifetime.ia6t_preferred < t 1405 ? "0" : sec2str(lifetime.ia6t_preferred - t)); 1406 } else 1407 printf("infty "); 1408 1409 printf("vltime "); 1410 if (lifetime.ia6t_expire) { 1411 printf("%s ", lifetime.ia6t_expire < t 1412 ? "0" : sec2str(lifetime.ia6t_expire - t)); 1413 } else 1414 printf("infty "); 1415 } 1416 1417 putchar('\n'); 1418 } 1419 #endif /*INET6*/ 1420 1421 #ifndef NO_IPX 1422 void 1423 ipx_status(int s __unused, struct rt_addrinfo * info) 1424 { 1425 struct sockaddr_ipx *sipx, null_sipx; 1426 1427 memset(&null_sipx, 0, sizeof(null_sipx)); 1428 1429 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA]; 1430 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 1431 1432 if (flags & IFF_POINTOPOINT) { 1433 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD]; 1434 if (!sipx) 1435 sipx = &null_sipx; 1436 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 1437 } 1438 putchar('\n'); 1439 } 1440 #endif 1441 1442 void 1443 at_status(int s __unused, struct rt_addrinfo * info) 1444 { 1445 struct sockaddr_at *sat, null_sat; 1446 struct netrange *nr; 1447 1448 memset(&null_sat, 0, sizeof(null_sat)); 1449 1450 sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA]; 1451 nr = &sat->sat_range.r_netrange; 1452 printf("\tatalk %d.%d range %d-%d phase %d", 1453 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1454 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 1455 if (flags & IFF_POINTOPOINT) { 1456 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1457 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1458 if (!sat) 1459 sat = &null_sat; 1460 printf("--> %d.%d", 1461 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 1462 } 1463 if (flags & IFF_BROADCAST) { 1464 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1465 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1466 if (sat) 1467 printf(" broadcast %d.%d", 1468 ntohs(sat->sat_addr.s_net), 1469 sat->sat_addr.s_node); 1470 } 1471 1472 putchar('\n'); 1473 } 1474 1475 #ifdef NS 1476 void 1477 xns_status(int s __unused, struct rt_addrinfo * info) 1478 { 1479 struct sockaddr_ns *sns, null_sns; 1480 1481 memset(&null_sns, 0, sizeof(null_sns)); 1482 1483 sns = (struct sockaddr_ns *)info->rti_info[RTAX_IFA]; 1484 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1485 1486 if (flags & IFF_POINTOPOINT) { 1487 sns = (struct sockaddr_ns *)info->rti_info[RTAX_BRD]; 1488 if (!sns) 1489 sns = &null_sns; 1490 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1491 } 1492 1493 putchar('\n'); 1494 close(s); 1495 } 1496 #endif 1497 1498 1499 void 1500 link_status(int s __unused, struct rt_addrinfo *info) 1501 { 1502 struct sockaddr_dl *sdl = (struct sockaddr_dl *)info; 1503 1504 if (sdl->sdl_alen > 0) { 1505 if (sdl->sdl_type == IFT_ETHER && 1506 sdl->sdl_alen == ETHER_ADDR_LEN) 1507 printf("\tether %s\n", 1508 ether_ntoa((struct ether_addr *)LLADDR(sdl))); 1509 else { 1510 int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0; 1511 1512 printf("\tlladdr %s\n", link_ntoa(sdl) + n); 1513 } 1514 } 1515 } 1516 1517 void 1518 Perror(const char *cmd) 1519 { 1520 switch (errno) { 1521 1522 case ENXIO: 1523 errx(1, "%s: no such interface", cmd); 1524 break; 1525 1526 case EPERM: 1527 errx(1, "%s: permission denied", cmd); 1528 break; 1529 1530 default: 1531 err(1, "%s", cmd); 1532 } 1533 } 1534 1535 #define SIN(x) ((struct sockaddr_in *) &(x)) 1536 struct sockaddr_in *sintab[] = { 1537 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1538 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1539 1540 void 1541 in_getaddr(const char *s, int which) 1542 { 1543 struct sockaddr_in *sin = sintab[which]; 1544 struct hostent *hp; 1545 struct netent *np; 1546 1547 sin->sin_len = sizeof(*sin); 1548 if (which != MASK) 1549 sin->sin_family = AF_INET; 1550 1551 if (which == ADDR) { 1552 char *p = NULL; 1553 1554 if((p = strrchr(s, '/')) != NULL) { 1555 /* address is `name/masklen' */ 1556 int masklen; 1557 int ret; 1558 struct sockaddr_in *min = sintab[MASK]; 1559 *p = '\0'; 1560 ret = sscanf(p+1, "%u", &masklen); 1561 if(ret != 1 || (masklen < 0 || masklen > 32)) { 1562 *p = '/'; 1563 errx(1, "%s: bad value", s); 1564 } 1565 min->sin_len = sizeof(*min); 1566 min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) & 1567 0xffffffff); 1568 } 1569 } 1570 1571 if (inet_aton(s, &sin->sin_addr)) 1572 return; 1573 if ((hp = gethostbyname(s)) != 0) 1574 bcopy(hp->h_addr, (char *)&sin->sin_addr, 1575 MIN(hp->h_length, sizeof(sin->sin_addr))); 1576 else if ((np = getnetbyname(s)) != 0) 1577 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1578 else 1579 errx(1, "%s: bad value", s); 1580 } 1581 1582 #ifdef INET6 1583 #define SIN6(x) ((struct sockaddr_in6 *) &(x)) 1584 struct sockaddr_in6 *sin6tab[] = { 1585 SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 1586 SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 1587 1588 void 1589 in6_getaddr(const char *s, int which) 1590 { 1591 struct sockaddr_in6 *sin = sin6tab[which]; 1592 struct addrinfo hints, *res; 1593 int error = -1; 1594 1595 newaddr &= 1; 1596 1597 sin->sin6_len = sizeof(*sin); 1598 if (which != MASK) 1599 sin->sin6_family = AF_INET6; 1600 1601 if (which == ADDR) { 1602 char *p = NULL; 1603 if((p = strrchr(s, '/')) != NULL) { 1604 *p = '\0'; 1605 in6_getprefix(p + 1, MASK); 1606 explicit_prefix = 1; 1607 } 1608 } 1609 1610 if (sin->sin6_family == AF_INET6) { 1611 bzero(&hints, sizeof(struct addrinfo)); 1612 hints.ai_family = AF_INET6; 1613 error = getaddrinfo(s, NULL, &hints, &res); 1614 } 1615 if (error != 0) { 1616 if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) 1617 errx(1, "%s: bad value", s); 1618 } else 1619 bcopy(res->ai_addr, sin, res->ai_addrlen); 1620 } 1621 1622 void 1623 in6_getprefix(const char *plen, int which) 1624 { 1625 struct sockaddr_in6 *sin = sin6tab[which]; 1626 u_char *cp; 1627 int len = atoi(plen); 1628 1629 if ((len < 0) || (len > 128)) 1630 errx(1, "%s: bad value", plen); 1631 sin->sin6_len = sizeof(*sin); 1632 if (which != MASK) 1633 sin->sin6_family = AF_INET6; 1634 if ((len == 0) || (len == 128)) { 1635 memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); 1636 return; 1637 } 1638 memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); 1639 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 1640 *cp++ = 0xff; 1641 *cp = 0xff << (8 - len); 1642 } 1643 #endif 1644 1645 /* 1646 * Print a value a la the %b format of the kernel's printf 1647 */ 1648 void 1649 printb(const char *s, unsigned v, const char *bits) 1650 { 1651 int i, any = 0; 1652 char c; 1653 1654 if (bits && *bits == 8) 1655 printf("%s=%o", s, v); 1656 else 1657 printf("%s=%x", s, v); 1658 bits++; 1659 if (bits) { 1660 putchar('<'); 1661 while ((i = *bits++) != '\0') { 1662 if (v & (1 << (i-1))) { 1663 if (any) 1664 putchar(','); 1665 any = 1; 1666 for (; (c = *bits) > 32; bits++) 1667 putchar(c); 1668 } else 1669 for (; *bits > 32; bits++) 1670 ; 1671 } 1672 putchar('>'); 1673 } 1674 } 1675 1676 #ifndef NO_IPX 1677 #define SIPX(x) ((struct sockaddr_ipx *) &(x)) 1678 struct sockaddr_ipx *sipxtab[] = { 1679 SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 1680 SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 1681 1682 void 1683 ipx_getaddr(const char *addr, int which) 1684 { 1685 struct sockaddr_ipx *sipx = sipxtab[which]; 1686 1687 sipx->sipx_family = AF_IPX; 1688 sipx->sipx_len = sizeof(*sipx); 1689 sipx->sipx_addr = ipx_addr(addr); 1690 if (which == MASK) 1691 printf("Attempt to set IPX netmask will be ineffectual\n"); 1692 } 1693 #endif 1694 1695 void 1696 at_getaddr(const char *addr, int which) 1697 { 1698 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 1699 u_int net, node; 1700 1701 sat->sat_family = AF_APPLETALK; 1702 sat->sat_len = sizeof(*sat); 1703 if (which == MASK) 1704 errx(1, "AppleTalk does not use netmasks"); 1705 if (sscanf(addr, "%u.%u", &net, &node) != 2 1706 || net > 0xffff || node > 0xfe) 1707 errx(1, "%s: illegal address", addr); 1708 sat->sat_addr.s_net = htons(net); 1709 sat->sat_addr.s_node = node; 1710 } 1711 1712 void 1713 link_getaddr(const char *addr, int which) 1714 { 1715 char *temp; 1716 struct sockaddr_dl sdl; 1717 struct sockaddr *sa = &ridreq.ifr_addr; 1718 1719 if (which != ADDR) 1720 errx(1, "can't set link-level netmask or broadcast"); 1721 if ((temp = malloc(strlen(addr) + 1)) == NULL) 1722 errx(1, "malloc failed"); 1723 temp[0] = ':'; 1724 strcpy(temp + 1, addr); 1725 sdl.sdl_len = sizeof(sdl); 1726 link_addr(temp, &sdl); 1727 free(temp); 1728 if (sdl.sdl_alen > sizeof(sa->sa_data)) 1729 errx(1, "malformed link-level address"); 1730 sa->sa_family = AF_LINK; 1731 sa->sa_len = sdl.sdl_alen; 1732 bcopy(LLADDR(&sdl), sa->sa_data, sdl.sdl_alen); 1733 } 1734 1735 /* XXX FIXME -- should use strtoul for better parsing. */ 1736 void 1737 setatrange(const char *range, int dummy __unused, int s, 1738 const struct afswtch *afp) 1739 { 1740 u_short first = 123, last = 123; 1741 1742 if (sscanf(range, "%hu-%hu", &first, &last) != 2 1743 || first == 0 || first > 0xffff 1744 || last == 0 || last > 0xffff || first > last) 1745 errx(1, "%s: illegal net range: %u-%u", range, first, last); 1746 at_nr.nr_firstnet = htons(first); 1747 at_nr.nr_lastnet = htons(last); 1748 } 1749 1750 void 1751 setatphase(const char *phase, int dummy __unused, int s, 1752 const struct afswtch *afp) 1753 { 1754 if (!strcmp(phase, "1")) 1755 at_nr.nr_phase = 1; 1756 else if (!strcmp(phase, "2")) 1757 at_nr.nr_phase = 2; 1758 else 1759 errx(1, "%s: illegal phase", phase); 1760 } 1761 1762 void 1763 checkatrange(struct sockaddr_at *sat) 1764 { 1765 if (at_nr.nr_phase == 0) 1766 at_nr.nr_phase = 2; /* Default phase 2 */ 1767 if (at_nr.nr_firstnet == 0) 1768 at_nr.nr_firstnet = /* Default range of one */ 1769 at_nr.nr_lastnet = sat->sat_addr.s_net; 1770 printf("\tatalk %d.%d range %d-%d phase %d\n", 1771 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1772 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 1773 if ((u_short) ntohs(at_nr.nr_firstnet) > 1774 (u_short) ntohs(sat->sat_addr.s_net) 1775 || (u_short) ntohs(at_nr.nr_lastnet) < 1776 (u_short) ntohs(sat->sat_addr.s_net)) 1777 errx(1, "AppleTalk address is not in range"); 1778 sat->sat_range.r_netrange = at_nr; 1779 } 1780 1781 #ifdef NS 1782 #define SNS(x) ((struct sockaddr_ns *) &(x)) 1783 struct sockaddr_ns *snstab[] = { 1784 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 1785 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 1786 1787 void 1788 xns_getaddr(const char *addr, int which) 1789 { 1790 struct sockaddr_ns *sns = snstab[which]; 1791 1792 sns->sns_family = AF_NS; 1793 sns->sns_len = sizeof(*sns); 1794 sns->sns_addr = ns_addr(addr); 1795 if (which == MASK) 1796 printf("Attempt to set XNS netmask will be ineffectual\n"); 1797 } 1798 #endif 1799 1800 #ifdef INET6 1801 int 1802 prefix(void *val, int size) 1803 { 1804 u_char *name = (u_char *)val; 1805 int byte, bit, plen = 0; 1806 1807 for (byte = 0; byte < size; byte++, plen += 8) 1808 if (name[byte] != 0xff) 1809 break; 1810 if (byte == size) 1811 return (plen); 1812 for (bit = 7; bit != 0; bit--, plen++) 1813 if (!(name[byte] & (1 << bit))) 1814 break; 1815 for (; bit != 0; bit--) 1816 if (name[byte] & (1 << bit)) 1817 return(0); 1818 byte++; 1819 for (; byte < size; byte++) 1820 if (name[byte]) 1821 return(0); 1822 return (plen); 1823 } 1824 1825 static char * 1826 sec2str(time_t total) 1827 { 1828 static char result[256]; 1829 int days, hours, mins, secs; 1830 int first = 1; 1831 char *p = result; 1832 1833 if (0) { 1834 days = total / 3600 / 24; 1835 hours = (total / 3600) % 24; 1836 mins = (total / 60) % 60; 1837 secs = total % 60; 1838 1839 if (days) { 1840 first = 0; 1841 p += sprintf(p, "%dd", days); 1842 } 1843 if (!first || hours) { 1844 first = 0; 1845 p += sprintf(p, "%dh", hours); 1846 } 1847 if (!first || mins) { 1848 first = 0; 1849 p += sprintf(p, "%dm", mins); 1850 } 1851 sprintf(p, "%ds", secs); 1852 } else 1853 sprintf(result, "%lu", (unsigned long)total); 1854 1855 return(result); 1856 } 1857 #endif /*INET6*/ 1858 1859 void 1860 ifmaybeload(char *name) 1861 { 1862 struct module_stat mstat; 1863 int fileid, modid; 1864 char ifkind[35], *cp, *dp; 1865 1866 /* turn interface and unit into module name */ 1867 strcpy(ifkind, "if_"); 1868 for (cp = name, dp = ifkind + 3; 1869 (*cp != 0) && !isdigit(*cp); cp++, dp++) 1870 *dp = *cp; 1871 *dp = 0; 1872 1873 /* scan files in kernel */ 1874 mstat.version = sizeof(struct module_stat); 1875 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1876 /* scan modules in file */ 1877 for (modid = kldfirstmod(fileid); modid > 0; 1878 modid = modfnext(modid)) { 1879 if (modstat(modid, &mstat) < 0) 1880 continue; 1881 /* strip bus name if present */ 1882 if ((cp = strchr(mstat.name, '/')) != NULL) { 1883 cp++; 1884 } else { 1885 cp = mstat.name; 1886 } 1887 /* already loaded? */ 1888 if (!strcmp(ifkind, cp)) 1889 return; 1890 } 1891 } 1892 1893 /* not present, we should try to load it */ 1894 kldload(ifkind); 1895 } 1896 1897 void 1898 list_cloners(void) 1899 { 1900 struct if_clonereq ifcr; 1901 char *cp, *buf; 1902 int idx; 1903 int s; 1904 1905 s = socket(AF_INET, SOCK_DGRAM, 0); 1906 if (s == -1) 1907 err(1, "socket"); 1908 1909 memset(&ifcr, 0, sizeof(ifcr)); 1910 1911 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 1912 err(1, "SIOCIFGCLONERS for count"); 1913 1914 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 1915 if (buf == NULL) 1916 err(1, "unable to allocate cloner name buffer"); 1917 1918 ifcr.ifcr_count = ifcr.ifcr_total; 1919 ifcr.ifcr_buffer = buf; 1920 1921 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 1922 err(1, "SIOCIFGCLONERS for names"); 1923 1924 /* 1925 * In case some disappeared in the mean time, clamp it down. 1926 */ 1927 if (ifcr.ifcr_count > ifcr.ifcr_total) 1928 ifcr.ifcr_count = ifcr.ifcr_total; 1929 1930 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 1931 if (idx > 0) 1932 putchar(' '); 1933 printf("%s", cp); 1934 } 1935 1936 putchar('\n'); 1937 free(buf); 1938 } 1939 1940 void 1941 clone_create(void) 1942 { 1943 int s; 1944 1945 s = socket(AF_INET, SOCK_DGRAM, 0); 1946 if (s == -1) 1947 err(1, "socket"); 1948 1949 memset(&ifr, 0, sizeof(ifr)); 1950 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1951 if (ioctl(s, SIOCIFCREATE, &ifr) < 0) 1952 err(1, "SIOCIFCREATE"); 1953 1954 if (strcmp(name, ifr.ifr_name) != 0) { 1955 printf("%s\n", ifr.ifr_name); 1956 strlcpy(name, ifr.ifr_name, sizeof(name)); 1957 } 1958 1959 close(s); 1960 } 1961 1962 void 1963 clone_destroy(const char *val, int d, int s, const struct afswtch *rafp) 1964 { 1965 1966 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1967 if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) 1968 err(1, "SIOCIFDESTROY"); 1969 } 1970