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