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