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