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