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