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