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