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