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