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