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