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