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