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 #ifdef INET6 138 char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/ 139 #endif 140 141 void Perror __P((const char *cmd)); 142 void checkatrange __P((struct sockaddr_at *)); 143 int ifconfig __P((int argc, char *const *argv, const struct afswtch *afp)); 144 void notealias __P((const char *, int, int, const struct afswtch *afp)); 145 void printb __P((const char *s, unsigned value, const char *bits)); 146 void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 147 void status __P((const struct afswtch *afp, int addrcount, 148 struct sockaddr_dl *sdl, struct if_msghdr *ifm, 149 struct ifa_msghdr *ifam)); 150 void usage __P((void)); 151 void ifmaybeload __P((char *name)); 152 153 #ifdef INET6 154 int prefix __P((void *, int)); 155 static char *sec2str __P((time_t)); 156 int explicit_prefix = 0; 157 #endif 158 159 typedef void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp)); 160 c_func setatphase, setatrange; 161 c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask; 162 #ifdef INET6 163 c_func setifprefixlen; 164 c_func setip6flags; 165 c_func setip6vltime; 166 c_func setip6pltime; 167 #endif 168 c_func setifipdst; 169 c_func setifflags, setifmetric, setifmtu, setiflladdr; 170 171 172 #define NEXTARG 0xffffff 173 174 const 175 struct cmd { 176 const char *c_name; 177 int c_parameter; /* NEXTARG means next argv */ 178 void (*c_func) __P((const char *, int, int, const struct afswtch *afp)); 179 } cmds[] = { 180 { "up", IFF_UP, setifflags } , 181 { "down", -IFF_UP, setifflags }, 182 { "arp", -IFF_NOARP, setifflags }, 183 { "-arp", IFF_NOARP, setifflags }, 184 { "debug", IFF_DEBUG, setifflags }, 185 { "-debug", -IFF_DEBUG, setifflags }, 186 { "add", IFF_UP, notealias }, 187 { "alias", IFF_UP, notealias }, 188 { "-alias", -IFF_UP, notealias }, 189 { "delete", -IFF_UP, notealias }, 190 { "remove", -IFF_UP, notealias }, 191 #ifdef notdef 192 #define EN_SWABIPS 0x1000 193 { "swabips", EN_SWABIPS, setifflags }, 194 { "-swabips", -EN_SWABIPS, setifflags }, 195 #endif 196 { "netmask", NEXTARG, setifnetmask }, 197 #ifdef INET6 198 { "prefixlen", NEXTARG, setifprefixlen }, 199 { "anycast", IN6_IFF_ANYCAST, setip6flags }, 200 { "tentative", IN6_IFF_TENTATIVE, setip6flags }, 201 { "-tentative", -IN6_IFF_TENTATIVE, setip6flags }, 202 { "vltime", NEXTARG, setip6vltime }, 203 { "pltime", NEXTARG, setip6pltime }, 204 #endif 205 { "range", NEXTARG, setatrange }, 206 { "phase", NEXTARG, setatphase }, 207 { "metric", NEXTARG, setifmetric }, 208 { "broadcast", NEXTARG, setifbroadaddr }, 209 { "ipdst", NEXTARG, setifipdst }, 210 { "link0", IFF_LINK0, setifflags }, 211 { "-link0", -IFF_LINK0, setifflags }, 212 { "link1", IFF_LINK1, setifflags }, 213 { "-link1", -IFF_LINK1, setifflags }, 214 { "link2", IFF_LINK2, setifflags }, 215 { "-link2", -IFF_LINK2, setifflags }, 216 #ifdef USE_IF_MEDIA 217 { "media", NEXTARG, setmedia }, 218 { "mediaopt", NEXTARG, setmediaopt }, 219 { "-mediaopt", NEXTARG, unsetmediaopt }, 220 #endif 221 #ifdef USE_VLANS 222 { "vlan", NEXTARG, setvlantag }, 223 { "vlandev", NEXTARG, setvlandev }, 224 { "-vlandev", NEXTARG, unsetvlandev }, 225 #endif 226 { "normal", -IFF_LINK0, setifflags }, 227 { "compress", IFF_LINK0, setifflags }, 228 { "noicmp", IFF_LINK1, setifflags }, 229 { "mtu", NEXTARG, setifmtu }, 230 { "lladdr", NEXTARG, setiflladdr }, 231 { 0, 0, setifaddr }, 232 { 0, 0, setifdstaddr }, 233 }; 234 235 /* 236 * XNS support liberally adapted from code written at the University of 237 * Maryland principally by James O'Toole and Chris Torek. 238 */ 239 typedef void af_status __P((int, struct rt_addrinfo *)); 240 typedef void af_getaddr __P((const char *, int)); 241 typedef void af_getprefix __P((const char *, int)); 242 243 af_status in_status, ipx_status, at_status, ether_status; 244 af_getaddr in_getaddr, ipx_getaddr, at_getaddr, ether_getaddr; 245 246 #ifdef INET6 247 af_status in6_status; 248 af_getaddr in6_getaddr; 249 af_getprefix in6_getprefix; 250 #endif /*INET6*/ 251 #ifdef NS 252 af_status xns_status; 253 af_getaddr xns_getaddr; 254 #endif 255 256 /* Known address families */ 257 const 258 struct afswtch { 259 const char *af_name; 260 short af_af; 261 af_status *af_status; 262 af_getaddr *af_getaddr; 263 af_getprefix *af_getprefix; 264 u_long af_difaddr; 265 u_long af_aifaddr; 266 caddr_t af_ridreq; 267 caddr_t af_addreq; 268 } afs[] = { 269 #define C(x) ((caddr_t) &x) 270 { "inet", AF_INET, in_status, in_getaddr, NULL, 271 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 272 #ifdef INET6 273 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 274 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 275 C(in6_ridreq), C(in6_addreq) }, 276 #endif /*INET6*/ 277 { "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL, 278 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 279 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 280 SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) }, 281 #ifdef NS 282 { "ns", AF_NS, xns_status, xns_getaddr, NULL, 283 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 284 #endif 285 { "ether", AF_LINK, ether_status, ether_getaddr, NULL, 286 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 287 #if 0 /* XXX conflicts with the media command */ 288 #ifdef USE_IF_MEDIA 289 { "media", AF_UNSPEC, media_status, NULL, NULL, }, /* XXX not real!! */ 290 #endif 291 #ifdef USE_VLANS 292 { "vlan", AF_UNSPEC, vlan_status, NULL, NULL, }, /* XXX not real!! */ 293 #endif 294 #endif 295 { 0, 0, 0, 0 } 296 }; 297 298 /* 299 * Expand the compacted form of addresses as returned via the 300 * configuration read via sysctl(). 301 */ 302 303 #define ROUNDUP(a) \ 304 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 305 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 306 307 void 308 rt_xaddrs(cp, cplim, rtinfo) 309 caddr_t cp, cplim; 310 struct rt_addrinfo *rtinfo; 311 { 312 struct sockaddr *sa; 313 int i; 314 315 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 316 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 317 if ((rtinfo->rti_addrs & (1 << i)) == 0) 318 continue; 319 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 320 ADVANCE(cp, sa); 321 } 322 } 323 324 325 void 326 usage() 327 { 328 #ifndef INET6 329 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 330 "usage: ifconfig interface address_family [address [dest_address]]", 331 " [parameters]", 332 " ifconfig -a [-d] [-u] [address_family]", 333 " ifconfig -l [-d] [-u] [address_family]", 334 " ifconfig [-d] [-u]"); 335 #else 336 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 337 "usage: ifconfig [-L] interface address_family [address [dest_address]]", 338 " [parameters]", 339 " ifconfig -a [-L] [-d] [-u] [address_family]", 340 " ifconfig -l [-d] [-u] [address_family]", 341 " ifconfig [-L] [-d] [-u]"); 342 #endif 343 exit(1); 344 } 345 346 int 347 main(argc, argv) 348 int argc; 349 char *const *argv; 350 { 351 int c; 352 int all, namesonly, downonly, uponly; 353 int foundit = 0, need_nl = 0; 354 const struct afswtch *afp = 0; 355 int addrcount; 356 struct if_msghdr *ifm, *nextifm; 357 struct ifa_msghdr *ifam; 358 struct sockaddr_dl *sdl; 359 char *buf, *lim, *next; 360 361 362 size_t needed; 363 int mib[6]; 364 365 /* Parse leading line options */ 366 all = downonly = uponly = namesonly = 0; 367 while ((c = getopt(argc, argv, "adlmu" 368 #ifdef INET6 369 "L" 370 #endif 371 )) != -1) { 372 switch (c) { 373 case 'a': /* scan all interfaces */ 374 all++; 375 break; 376 #ifdef INET6 377 case 'L': 378 ip6lifetime++; /* print IPv6 address lifetime */ 379 break; 380 #endif 381 case 'l': /* scan interface names only */ 382 namesonly++; 383 break; 384 case 'd': /* restrict scan to "down" interfaces */ 385 downonly++; 386 break; 387 case 'u': /* restrict scan to "up" interfaces */ 388 uponly++; 389 break; 390 case 'm': /* show media choices in status */ 391 /* ignored for compatibility */ 392 break; 393 default: 394 usage(); 395 break; 396 } 397 } 398 argc -= optind; 399 argv += optind; 400 401 /* -l cannot be used with -a or -m */ 402 if (namesonly && all) 403 usage(); 404 405 /* nonsense.. */ 406 if (uponly && downonly) 407 usage(); 408 409 /* no arguments is equivalent to '-a' */ 410 if (!namesonly && argc < 1) 411 all = 1; 412 413 /* -a and -l allow an address family arg to limit the output */ 414 if (all || namesonly) { 415 if (argc > 1) 416 usage(); 417 418 if (argc == 1) { 419 for (afp = afs; afp->af_name; afp++) 420 if (strcmp(afp->af_name, *argv) == 0) { 421 argc--, argv++; 422 break; 423 } 424 if (afp->af_name == NULL) 425 usage(); 426 /* leave with afp non-zero */ 427 } 428 } else { 429 /* not listing, need an argument */ 430 if (argc < 1) 431 usage(); 432 433 strncpy(name, *argv, sizeof(name)); 434 argc--, argv++; 435 436 /* check and maybe load support for this interface */ 437 ifmaybeload(name); 438 } 439 440 /* Check for address family */ 441 if (argc > 0) { 442 for (afp = afs; afp->af_name; afp++) 443 if (strcmp(afp->af_name, *argv) == 0) { 444 argc--, argv++; 445 break; 446 } 447 if (afp->af_name == NULL) 448 afp = NULL; /* not a family, NULL */ 449 } 450 451 mib[0] = CTL_NET; 452 mib[1] = PF_ROUTE; 453 mib[2] = 0; 454 mib[3] = 0; /* address family */ 455 mib[4] = NET_RT_IFLIST; 456 mib[5] = 0; 457 458 /* if particular family specified, only ask about it */ 459 if (afp) 460 mib[3] = afp->af_af; 461 462 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 463 errx(1, "iflist-sysctl-estimate"); 464 if ((buf = malloc(needed)) == NULL) 465 errx(1, "malloc"); 466 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 467 errx(1, "actual retrieval of interface table"); 468 lim = buf + needed; 469 470 next = buf; 471 while (next < lim) { 472 473 ifm = (struct if_msghdr *)next; 474 475 if (ifm->ifm_type == RTM_IFINFO) { 476 sdl = (struct sockaddr_dl *)(ifm + 1); 477 flags = ifm->ifm_flags; 478 } else { 479 fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n"); 480 fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, 481 ifm->ifm_type); 482 fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); 483 fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, 484 lim); 485 exit (1); 486 } 487 488 next += ifm->ifm_msglen; 489 ifam = NULL; 490 addrcount = 0; 491 while (next < lim) { 492 493 nextifm = (struct if_msghdr *)next; 494 495 if (nextifm->ifm_type != RTM_NEWADDR) 496 break; 497 498 if (ifam == NULL) 499 ifam = (struct ifa_msghdr *)nextifm; 500 501 addrcount++; 502 next += nextifm->ifm_msglen; 503 } 504 505 if (all || namesonly) { 506 if (uponly) 507 if ((flags & IFF_UP) == 0) 508 continue; /* not up */ 509 if (downonly) 510 if (flags & IFF_UP) 511 continue; /* not down */ 512 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 513 name[sdl->sdl_nlen] = '\0'; 514 if (namesonly) { 515 if (afp == NULL || 516 afp->af_status != ether_status || 517 sdl->sdl_type == IFT_ETHER) { 518 if (need_nl) 519 putchar(' '); 520 fputs(name, stdout); 521 need_nl++; 522 } 523 continue; 524 } 525 } else { 526 if (strlen(name) != sdl->sdl_nlen) 527 continue; /* not same len */ 528 if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) 529 continue; /* not same name */ 530 } 531 532 if (argc > 0) 533 ifconfig(argc, argv, afp); 534 else 535 status(afp, addrcount, sdl, ifm, ifam); 536 537 if (all == 0 && namesonly == 0) { 538 foundit++; /* flag it as 'done' */ 539 break; 540 } 541 } 542 free(buf); 543 544 if (namesonly && need_nl > 0) 545 putchar('\n'); 546 547 if (all == 0 && namesonly == 0 && foundit == 0) 548 errx(1, "interface %s does not exist", name); 549 550 551 exit (0); 552 } 553 554 555 int 556 ifconfig(argc, argv, afp) 557 int argc; 558 char *const *argv; 559 const struct afswtch *afp; 560 { 561 int s; 562 563 if (afp == NULL) 564 afp = &afs[0]; 565 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 566 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 567 568 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 569 err(1, "socket"); 570 571 while (argc > 0) { 572 register const struct cmd *p; 573 574 for (p = cmds; p->c_name; p++) 575 if (strcmp(*argv, p->c_name) == 0) 576 break; 577 if (p->c_name == 0 && setaddr) 578 p++; /* got src, do dst */ 579 if (p->c_func) { 580 if (p->c_parameter == NEXTARG) { 581 if (argv[1] == NULL) 582 errx(1, "'%s' requires argument", 583 p->c_name); 584 (*p->c_func)(argv[1], 0, s, afp); 585 argc--, argv++; 586 } else 587 (*p->c_func)(*argv, p->c_parameter, s, afp); 588 } 589 argc--, argv++; 590 } 591 #ifdef INET6 592 if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) { 593 /* Aggregatable address architecture defines all prefixes 594 are 64. So, it is convenient to set prefixlen to 64 if 595 it is not specified. */ 596 setifprefixlen("64", 0, s, afp); 597 /* in6_getprefix("64", MASK) if MASK is available here... */ 598 } 599 #endif 600 if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) { 601 struct ipxip_req rq; 602 int size = sizeof(rq); 603 604 rq.rq_ipx = addreq.ifra_addr; 605 rq.rq_ip = addreq.ifra_dstaddr; 606 607 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 608 Perror("Encapsulation Routing"); 609 } 610 if (ifr.ifr_addr.sa_family == AF_APPLETALK) 611 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 612 #ifdef NS 613 if (setipdst && ifr.ifr_addr.sa_family == AF_NS) { 614 struct nsip_req rq; 615 int size = sizeof(rq); 616 617 rq.rq_ns = addreq.ifra_addr; 618 rq.rq_ip = addreq.ifra_dstaddr; 619 620 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 621 Perror("Encapsulation Routing"); 622 } 623 #endif 624 if (clearaddr) { 625 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 626 warnx("interface %s cannot change %s addresses!", 627 name, afp->af_name); 628 clearaddr = NULL; 629 } 630 } 631 if (clearaddr) { 632 int ret; 633 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 634 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { 635 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 636 /* means no previous address for interface */ 637 } else 638 Perror("ioctl (SIOCDIFADDR)"); 639 } 640 } 641 if (newaddr) { 642 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 643 warnx("interface %s cannot change %s addresses!", 644 name, afp->af_name); 645 newaddr = 0; 646 } 647 } 648 if (newaddr) { 649 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 650 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 651 Perror("ioctl (SIOCAIFADDR)"); 652 } 653 close(s); 654 return(0); 655 } 656 #define RIDADDR 0 657 #define ADDR 1 658 #define MASK 2 659 #define DSTADDR 3 660 661 /*ARGSUSED*/ 662 void 663 setifaddr(addr, param, s, afp) 664 const char *addr; 665 int param; 666 int s; 667 const struct afswtch *afp; 668 { 669 if (*afp->af_getaddr == NULL) 670 return; 671 /* 672 * Delay the ioctl to set the interface addr until flags are all set. 673 * The address interpretation may depend on the flags, 674 * and the flags may change when the address is set. 675 */ 676 setaddr++; 677 if (doalias == 0 && afp->af_af != AF_LINK) 678 clearaddr = 1; 679 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 680 } 681 682 void 683 setifnetmask(addr, dummy, s, afp) 684 const char *addr; 685 int dummy __unused; 686 int s; 687 const struct afswtch *afp; 688 { 689 if (*afp->af_getaddr == NULL) 690 return; 691 (*afp->af_getaddr)(addr, MASK); 692 } 693 694 #ifdef INET6 695 void 696 setifprefixlen(addr, dummy, s, afp) 697 const char *addr; 698 int dummy __unused; 699 int s; 700 const struct afswtch *afp; 701 { 702 if (*afp->af_getprefix) 703 (*afp->af_getprefix)(addr, MASK); 704 explicit_prefix = 1; 705 } 706 707 void 708 setip6flags(dummyaddr, flag, dummysoc, afp) 709 const char *dummyaddr __unused; 710 int flag; 711 int dummysoc __unused; 712 const struct afswtch *afp; 713 { 714 if (afp->af_af != AF_INET6) 715 err(1, "address flags can be set only for inet6 addresses"); 716 717 if (flag < 0) 718 in6_addreq.ifra_flags &= ~(-flag); 719 else 720 in6_addreq.ifra_flags |= flag; 721 } 722 723 void 724 setip6vltime(seconds, dummy, s, afp) 725 const char *seconds; 726 int dummy __unused; 727 int s; 728 const struct afswtch *afp; 729 { 730 in6_addreq.ifra_lifetime.ia6t_vltime = atoi(seconds); 731 } 732 733 void 734 setip6pltime(seconds, dummy, s, afp) 735 const char *seconds; 736 int dummy __unused; 737 int s; 738 const struct afswtch *afp; 739 { 740 in6_addreq.ifra_lifetime.ia6t_pltime = atoi(seconds); 741 } 742 #endif 743 744 void 745 setifbroadaddr(addr, dummy, s, afp) 746 const char *addr; 747 int dummy __unused; 748 int s; 749 const struct afswtch *afp; 750 { 751 if (*afp->af_getaddr == NULL) 752 return; 753 (*afp->af_getaddr)(addr, DSTADDR); 754 } 755 756 void 757 setifipdst(addr, dummy, s, afp) 758 const char *addr; 759 int dummy __unused; 760 int s; 761 const struct afswtch *afp; 762 { 763 in_getaddr(addr, DSTADDR); 764 setipdst++; 765 clearaddr = 0; 766 newaddr = 0; 767 } 768 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 769 770 void 771 notealias(addr, param, s, afp) 772 const char *addr; 773 int param; 774 int s; 775 const struct afswtch *afp; 776 { 777 if (setaddr && doalias == 0 && param < 0) 778 bcopy((caddr_t)rqtosa(af_addreq), 779 (caddr_t)rqtosa(af_ridreq), 780 rqtosa(af_addreq)->sa_len); 781 doalias = param; 782 if (param < 0) { 783 clearaddr = 1; 784 newaddr = 0; 785 } else 786 clearaddr = 0; 787 } 788 789 /*ARGSUSED*/ 790 void 791 setifdstaddr(addr, param, s, afp) 792 const char *addr; 793 int param __unused; 794 int s; 795 const struct afswtch *afp; 796 { 797 if (*afp->af_getaddr == NULL) 798 return; 799 (*afp->af_getaddr)(addr, DSTADDR); 800 } 801 802 /* 803 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 804 * of the ifreq structure, which may confuse other parts of ifconfig. 805 * Make a private copy so we can avoid that. 806 */ 807 void 808 setifflags(vname, value, s, afp) 809 const char *vname; 810 int value; 811 int s; 812 const struct afswtch *afp; 813 { 814 struct ifreq my_ifr; 815 816 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 817 818 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 819 Perror("ioctl (SIOCGIFFLAGS)"); 820 exit(1); 821 } 822 strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name)); 823 flags = my_ifr.ifr_flags; 824 825 if (value < 0) { 826 value = -value; 827 flags &= ~value; 828 } else 829 flags |= value; 830 my_ifr.ifr_flags = flags; 831 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 832 Perror(vname); 833 } 834 835 void 836 setifmetric(val, dummy, s, afp) 837 const char *val; 838 int dummy __unused; 839 int s; 840 const struct afswtch *afp; 841 { 842 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 843 ifr.ifr_metric = atoi(val); 844 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 845 warn("ioctl (set metric)"); 846 } 847 848 void 849 setifmtu(val, dummy, s, afp) 850 const char *val; 851 int dummy __unused; 852 int s; 853 const struct afswtch *afp; 854 { 855 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 856 ifr.ifr_mtu = atoi(val); 857 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 858 warn("ioctl (set mtu)"); 859 } 860 861 void 862 setiflladdr(val, dummy, s, afp) 863 const char *val; 864 int dummy __unused; 865 int s; 866 const struct afswtch *afp; 867 { 868 struct ether_addr *ea; 869 870 ea = ether_aton(val); 871 if (ea == NULL) { 872 warn("malformed link-level address"); 873 return; 874 } 875 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 876 ifr.ifr_addr.sa_len = ETHER_ADDR_LEN; 877 ifr.ifr_addr.sa_family = AF_LINK; 878 bcopy(ea, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN); 879 if (ioctl(s, SIOCSIFLLADDR, (caddr_t)&ifr) < 0) 880 warn("ioctl (set lladdr)"); 881 882 return; 883 } 884 885 #define IFFBITS \ 886 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 887 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 888 "\20MULTICAST" 889 890 /* 891 * Print the status of the interface. If an address family was 892 * specified, show it and it only; otherwise, show them all. 893 */ 894 void 895 status(afp, addrcount, sdl, ifm, ifam) 896 const struct afswtch *afp; 897 int addrcount; 898 struct sockaddr_dl *sdl; 899 struct if_msghdr *ifm; 900 struct ifa_msghdr *ifam; 901 { 902 const struct afswtch *p = NULL; 903 struct rt_addrinfo info; 904 int allfamilies, s; 905 struct ifstat ifs; 906 907 if (afp == NULL) { 908 allfamilies = 1; 909 afp = &afs[0]; 910 } else 911 allfamilies = 0; 912 913 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 914 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 915 916 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 917 err(1, "socket"); 918 919 /* 920 * XXX is it we are doing a SIOCGIFMETRIC etc for one family. 921 * is it possible that the metric and mtu can be different for 922 * each family? If so, we have a format problem, because the 923 * metric and mtu is printed on the global the flags line. 924 */ 925 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 926 warn("ioctl (SIOCGIFMETRIC)"); 927 else 928 metric = ifr.ifr_metric; 929 930 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) 931 warn("ioctl (SIOCGIFMTU)"); 932 else 933 mtu = ifr.ifr_mtu; 934 935 printf("%s: ", name); 936 printb("flags", flags, IFFBITS); 937 if (metric) 938 printf(" metric %d", metric); 939 if (mtu) 940 printf(" mtu %d", mtu); 941 putchar('\n'); 942 943 while (addrcount > 0) { 944 945 info.rti_addrs = ifam->ifam_addrs; 946 947 /* Expand the compacted addresses */ 948 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 949 &info); 950 951 if (!allfamilies) { 952 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family) { 953 p = afp; 954 (*p->af_status)(s, &info); 955 } 956 } else for (p = afs; p->af_name; p++) { 957 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family) 958 (*p->af_status)(s, &info); 959 } 960 addrcount--; 961 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); 962 } 963 if (allfamilies || afp->af_status == ether_status) 964 ether_status(s, (struct rt_addrinfo *)sdl); 965 #ifdef USE_IF_MEDIA 966 if (allfamilies || afp->af_status == media_status) 967 media_status(s, NULL); 968 #endif 969 #ifdef USE_VLANS 970 if (allfamilies || afp->af_status == vlan_status) 971 vlan_status(s, NULL); 972 #endif 973 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 974 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 975 printf("%s", ifs.ascii); 976 977 if (!allfamilies && !p && afp->af_status != media_status && 978 afp->af_status != ether_status && afp->af_status != vlan_status) 979 warnx("%s has no %s interface address!", name, afp->af_name); 980 981 close(s); 982 return; 983 } 984 985 void 986 in_status(s, info) 987 int s __unused; 988 struct rt_addrinfo * info; 989 { 990 struct sockaddr_in *sin, null_sin; 991 992 memset(&null_sin, 0, sizeof(null_sin)); 993 994 sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; 995 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 996 997 if (flags & IFF_POINTOPOINT) { 998 /* note RTAX_BRD overlap with IFF_BROADCAST */ 999 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1000 if (!sin) 1001 sin = &null_sin; 1002 printf("--> %s ", inet_ntoa(sin->sin_addr)); 1003 } 1004 1005 sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; 1006 if (!sin) 1007 sin = &null_sin; 1008 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 1009 1010 if (flags & IFF_BROADCAST) { 1011 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1012 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1013 if (sin && sin->sin_addr.s_addr != 0) 1014 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 1015 } 1016 putchar('\n'); 1017 } 1018 1019 #ifdef INET6 1020 void 1021 in6_status(s, info) 1022 int s __unused; 1023 struct rt_addrinfo * info; 1024 { 1025 struct sockaddr_in6 *sin, null_sin; 1026 struct in6_ifreq ifr6; 1027 int s6; 1028 u_int32_t flags6; 1029 struct in6_addrlifetime lifetime; 1030 time_t t = time(NULL); 1031 int error; 1032 u_int32_t scopeid; 1033 1034 memset(&null_sin, 0, sizeof(null_sin)); 1035 1036 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA]; 1037 strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); 1038 if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1039 perror("ifconfig: socket"); 1040 return; 1041 } 1042 ifr6.ifr_addr = *sin; 1043 if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 1044 perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)"); 1045 close(s6); 1046 return; 1047 } 1048 flags6 = ifr6.ifr_ifru.ifru_flags6; 1049 memset(&lifetime, 0, sizeof(lifetime)); 1050 ifr6.ifr_addr = *sin; 1051 if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) { 1052 perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)"); 1053 close(s6); 1054 return; 1055 } 1056 lifetime = ifr6.ifr_ifru.ifru_lifetime; 1057 close(s6); 1058 1059 /* XXX: embedded link local addr check */ 1060 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1061 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1062 u_short index; 1063 1064 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1065 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1066 if (sin->sin6_scope_id == 0) 1067 sin->sin6_scope_id = ntohs(index); 1068 } 1069 scopeid = sin->sin6_scope_id; 1070 1071 error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, 1072 sizeof(addr_buf), NULL, 0, 1073 NI_NUMERICHOST|NI_WITHSCOPEID); 1074 if (error != 0) 1075 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1076 sizeof(addr_buf)); 1077 printf("\tinet6 %s ", addr_buf); 1078 1079 if (flags & IFF_POINTOPOINT) { 1080 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1081 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD]; 1082 /* 1083 * some of the interfaces do not have valid destination 1084 * address. 1085 */ 1086 if (sin && sin->sin6_family == AF_INET6) { 1087 int error; 1088 1089 /* XXX: embedded link local addr check */ 1090 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1091 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1092 u_short index; 1093 1094 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1095 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1096 if (sin->sin6_scope_id == 0) 1097 sin->sin6_scope_id = ntohs(index); 1098 } 1099 1100 error = getnameinfo((struct sockaddr *)sin, 1101 sin->sin6_len, addr_buf, 1102 sizeof(addr_buf), NULL, 0, 1103 NI_NUMERICHOST|NI_WITHSCOPEID); 1104 if (error != 0) 1105 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1106 sizeof(addr_buf)); 1107 printf("--> %s ", addr_buf); 1108 } 1109 } 1110 1111 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; 1112 if (!sin) 1113 sin = &null_sin; 1114 printf("prefixlen %d ", prefix(&sin->sin6_addr, 1115 sizeof(struct in6_addr))); 1116 1117 if (flags6 & IN6_IFF_ANYCAST) 1118 printf("anycast "); 1119 if (flags6 & IN6_IFF_TENTATIVE) 1120 printf("tentative "); 1121 if (flags6 & IN6_IFF_DUPLICATED) 1122 printf("duplicated "); 1123 if (flags6 & IN6_IFF_DETACHED) 1124 printf("detached "); 1125 if (flags6 & IN6_IFF_DEPRECATED) 1126 printf("deprecated "); 1127 1128 if (scopeid) 1129 printf("scopeid 0x%x ", scopeid); 1130 1131 if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { 1132 printf("pltime "); 1133 if (lifetime.ia6t_preferred) { 1134 printf("%s ", lifetime.ia6t_preferred < t 1135 ? "0" : sec2str(lifetime.ia6t_preferred - t)); 1136 } else 1137 printf("infty "); 1138 1139 printf("vltime "); 1140 if (lifetime.ia6t_expire) { 1141 printf("%s ", lifetime.ia6t_expire < t 1142 ? "0" : sec2str(lifetime.ia6t_expire - t)); 1143 } else 1144 printf("infty "); 1145 } 1146 1147 putchar('\n'); 1148 } 1149 #endif /*INET6*/ 1150 1151 void 1152 ipx_status(s, info) 1153 int s __unused; 1154 struct rt_addrinfo * info; 1155 { 1156 struct sockaddr_ipx *sipx, null_sipx; 1157 1158 memset(&null_sipx, 0, sizeof(null_sipx)); 1159 1160 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA]; 1161 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 1162 1163 if (flags & IFF_POINTOPOINT) { 1164 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD]; 1165 if (!sipx) 1166 sipx = &null_sipx; 1167 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 1168 } 1169 putchar('\n'); 1170 } 1171 1172 void 1173 at_status(s, info) 1174 int s __unused; 1175 struct rt_addrinfo * info; 1176 { 1177 struct sockaddr_at *sat, null_sat; 1178 struct netrange *nr; 1179 1180 memset(&null_sat, 0, sizeof(null_sat)); 1181 1182 sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA]; 1183 nr = &sat->sat_range.r_netrange; 1184 printf("\tatalk %d.%d range %d-%d phase %d", 1185 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1186 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 1187 if (flags & IFF_POINTOPOINT) { 1188 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1189 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1190 if (!sat) 1191 sat = &null_sat; 1192 printf("--> %d.%d", 1193 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 1194 } 1195 if (flags & IFF_BROADCAST) { 1196 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1197 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1198 if (sat) 1199 printf(" broadcast %d.%d", 1200 ntohs(sat->sat_addr.s_net), 1201 sat->sat_addr.s_node); 1202 } 1203 1204 putchar('\n'); 1205 } 1206 1207 #ifdef NS 1208 void 1209 xns_status(s, info) 1210 int s __unused; 1211 struct rt_addrinfo * info; 1212 { 1213 struct sockaddr_ns *sns, null_sns; 1214 1215 memset(&null_sns, 0, sizeof(null_sns)); 1216 1217 sns = (struct sockaddr_ns *)info->rti_info[RTAX_IFA]; 1218 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1219 1220 if (flags & IFF_POINTOPOINT) { 1221 sns = (struct sockaddr_ns *)info->rti_info[RTAX_BRD]; 1222 if (!sns) 1223 sns = &null_sns; 1224 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1225 } 1226 1227 putchar('\n'); 1228 close(s); 1229 } 1230 #endif 1231 1232 1233 void 1234 ether_status(s, info) 1235 int s __unused; 1236 struct rt_addrinfo *info; 1237 { 1238 char *cp; 1239 int n; 1240 struct sockaddr_dl *sdl = (struct sockaddr_dl *)info; 1241 1242 cp = (char *)LLADDR(sdl); 1243 if ((n = sdl->sdl_alen) > 0) { 1244 if (sdl->sdl_type == IFT_ETHER) 1245 printf ("\tether "); 1246 else 1247 printf ("\tlladdr "); 1248 while (--n >= 0) 1249 printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' '); 1250 putchar('\n'); 1251 } 1252 } 1253 1254 void 1255 Perror(cmd) 1256 const char *cmd; 1257 { 1258 switch (errno) { 1259 1260 case ENXIO: 1261 errx(1, "%s: no such interface", cmd); 1262 break; 1263 1264 case EPERM: 1265 errx(1, "%s: permission denied", cmd); 1266 break; 1267 1268 default: 1269 err(1, "%s", cmd); 1270 } 1271 } 1272 1273 #define SIN(x) ((struct sockaddr_in *) &(x)) 1274 struct sockaddr_in *sintab[] = { 1275 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1276 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1277 1278 void 1279 in_getaddr(s, which) 1280 const char *s; 1281 int which; 1282 { 1283 register struct sockaddr_in *sin = sintab[which]; 1284 struct hostent *hp; 1285 struct netent *np; 1286 1287 sin->sin_len = sizeof(*sin); 1288 if (which != MASK) 1289 sin->sin_family = AF_INET; 1290 1291 if (inet_aton(s, &sin->sin_addr)) 1292 return; 1293 if ((hp = gethostbyname(s)) != 0) 1294 bcopy(hp->h_addr, (char *)&sin->sin_addr, 1295 MIN(hp->h_length, sizeof(sin->sin_addr))); 1296 else if ((np = getnetbyname(s)) != 0) 1297 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1298 else 1299 errx(1, "%s: bad value", s); 1300 } 1301 1302 #ifdef INET6 1303 #define SIN6(x) ((struct sockaddr_in6 *) &(x)) 1304 struct sockaddr_in6 *sin6tab[] = { 1305 SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 1306 SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 1307 1308 void 1309 in6_getaddr(s, which) 1310 const char *s; 1311 int which; 1312 { 1313 register struct sockaddr_in6 *sin = sin6tab[which]; 1314 struct addrinfo hints, *res; 1315 int error = -1; 1316 1317 newaddr &= 1; 1318 1319 sin->sin6_len = sizeof(*sin); 1320 if (which != MASK) 1321 sin->sin6_family = AF_INET6; 1322 1323 if (sin->sin6_family == AF_INET6) { 1324 bzero(&hints, sizeof(struct addrinfo)); 1325 hints.ai_family = AF_INET6; 1326 error = getaddrinfo(s, NULL, &hints, &res); 1327 } 1328 if (error != 0) { 1329 if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) 1330 errx(1, "%s: bad value", s); 1331 } else 1332 bcopy(res->ai_addr, sin, res->ai_addrlen); 1333 } 1334 1335 void 1336 in6_getprefix(plen, which) 1337 const char *plen; 1338 int which; 1339 { 1340 register struct sockaddr_in6 *sin = sin6tab[which]; 1341 register u_char *cp; 1342 int len = atoi(plen); 1343 1344 if ((len < 0) || (len > 128)) 1345 errx(1, "%s: bad value", plen); 1346 sin->sin6_len = sizeof(*sin); 1347 if (which != MASK) 1348 sin->sin6_family = AF_INET6; 1349 if ((len == 0) || (len == 128)) { 1350 memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); 1351 return; 1352 } 1353 memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); 1354 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 1355 *cp++ = 0xff; 1356 *cp = 0xff << (8 - len); 1357 } 1358 #endif 1359 1360 /* 1361 * Print a value a la the %b format of the kernel's printf 1362 */ 1363 void 1364 printb(s, v, bits) 1365 const char *s; 1366 register unsigned v; 1367 register const char *bits; 1368 { 1369 register int i, any = 0; 1370 register char c; 1371 1372 if (bits && *bits == 8) 1373 printf("%s=%o", s, v); 1374 else 1375 printf("%s=%x", s, v); 1376 bits++; 1377 if (bits) { 1378 putchar('<'); 1379 while ((i = *bits++) != '\0') { 1380 if (v & (1 << (i-1))) { 1381 if (any) 1382 putchar(','); 1383 any = 1; 1384 for (; (c = *bits) > 32; bits++) 1385 putchar(c); 1386 } else 1387 for (; *bits > 32; bits++) 1388 ; 1389 } 1390 putchar('>'); 1391 } 1392 } 1393 1394 #define SIPX(x) ((struct sockaddr_ipx *) &(x)) 1395 struct sockaddr_ipx *sipxtab[] = { 1396 SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 1397 SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 1398 1399 void 1400 ipx_getaddr(addr, which) 1401 const char *addr; 1402 int which; 1403 { 1404 struct sockaddr_ipx *sipx = sipxtab[which]; 1405 1406 sipx->sipx_family = AF_IPX; 1407 sipx->sipx_len = sizeof(*sipx); 1408 sipx->sipx_addr = ipx_addr(addr); 1409 if (which == MASK) 1410 printf("Attempt to set IPX netmask will be ineffectual\n"); 1411 } 1412 1413 void 1414 at_getaddr(addr, which) 1415 const char *addr; 1416 int which; 1417 { 1418 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 1419 u_int net, node; 1420 1421 sat->sat_family = AF_APPLETALK; 1422 sat->sat_len = sizeof(*sat); 1423 if (which == MASK) 1424 errx(1, "AppleTalk does not use netmasks"); 1425 if (sscanf(addr, "%u.%u", &net, &node) != 2 1426 || net > 0xffff || node > 0xfe) 1427 errx(1, "%s: illegal address", addr); 1428 sat->sat_addr.s_net = htons(net); 1429 sat->sat_addr.s_node = node; 1430 } 1431 1432 void 1433 ether_getaddr(addr, which) 1434 const char *addr; 1435 int which; 1436 { 1437 struct ether_addr *ea; 1438 struct sockaddr *sea = &ridreq.ifr_addr; 1439 1440 ea = ether_aton(addr); 1441 if (ea == NULL) 1442 errx(1, "malformed ether address"); 1443 if (which == MASK) 1444 errx(1, "Ethernet does not use netmasks"); 1445 sea->sa_family = AF_LINK; 1446 sea->sa_len = ETHER_ADDR_LEN; 1447 bcopy(ea, sea->sa_data, ETHER_ADDR_LEN); 1448 } 1449 1450 /* XXX FIXME -- should use strtoul for better parsing. */ 1451 void 1452 setatrange(range, dummy, s, afp) 1453 const char *range; 1454 int dummy __unused; 1455 int s; 1456 const struct afswtch *afp; 1457 { 1458 u_short first = 123, last = 123; 1459 1460 if (sscanf(range, "%hu-%hu", &first, &last) != 2 1461 || first == 0 || first > 0xffff 1462 || last == 0 || last > 0xffff || first > last) 1463 errx(1, "%s: illegal net range: %u-%u", range, first, last); 1464 at_nr.nr_firstnet = htons(first); 1465 at_nr.nr_lastnet = htons(last); 1466 } 1467 1468 void 1469 setatphase(phase, dummy, s, afp) 1470 const char *phase; 1471 int dummy __unused; 1472 int s; 1473 const struct afswtch *afp; 1474 { 1475 if (!strcmp(phase, "1")) 1476 at_nr.nr_phase = 1; 1477 else if (!strcmp(phase, "2")) 1478 at_nr.nr_phase = 2; 1479 else 1480 errx(1, "%s: illegal phase", phase); 1481 } 1482 1483 void 1484 checkatrange(struct sockaddr_at *sat) 1485 { 1486 if (at_nr.nr_phase == 0) 1487 at_nr.nr_phase = 2; /* Default phase 2 */ 1488 if (at_nr.nr_firstnet == 0) 1489 at_nr.nr_firstnet = /* Default range of one */ 1490 at_nr.nr_lastnet = sat->sat_addr.s_net; 1491 printf("\tatalk %d.%d range %d-%d phase %d\n", 1492 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1493 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 1494 if ((u_short) ntohs(at_nr.nr_firstnet) > 1495 (u_short) ntohs(sat->sat_addr.s_net) 1496 || (u_short) ntohs(at_nr.nr_lastnet) < 1497 (u_short) ntohs(sat->sat_addr.s_net)) 1498 errx(1, "AppleTalk address is not in range"); 1499 sat->sat_range.r_netrange = at_nr; 1500 } 1501 1502 #ifdef NS 1503 #define SNS(x) ((struct sockaddr_ns *) &(x)) 1504 struct sockaddr_ns *snstab[] = { 1505 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 1506 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 1507 1508 void 1509 xns_getaddr(addr, which) 1510 const char *addr; 1511 int which; 1512 { 1513 struct sockaddr_ns *sns = snstab[which]; 1514 1515 sns->sns_family = AF_NS; 1516 sns->sns_len = sizeof(*sns); 1517 sns->sns_addr = ns_addr(addr); 1518 if (which == MASK) 1519 printf("Attempt to set XNS netmask will be ineffectual\n"); 1520 } 1521 #endif 1522 1523 #ifdef INET6 1524 int 1525 prefix(val, size) 1526 void *val; 1527 int size; 1528 { 1529 register u_char *name = (u_char *)val; 1530 register int byte, bit, plen = 0; 1531 1532 for (byte = 0; byte < size; byte++, plen += 8) 1533 if (name[byte] != 0xff) 1534 break; 1535 if (byte == size) 1536 return (plen); 1537 for (bit = 7; bit != 0; bit--, plen++) 1538 if (!(name[byte] & (1 << bit))) 1539 break; 1540 for (; bit != 0; bit--) 1541 if (name[byte] & (1 << bit)) 1542 return(0); 1543 byte++; 1544 for (; byte < size; byte++) 1545 if (name[byte]) 1546 return(0); 1547 return (plen); 1548 } 1549 1550 static char * 1551 sec2str(total) 1552 time_t total; 1553 { 1554 static char result[256]; 1555 int days, hours, mins, secs; 1556 int first = 1; 1557 char *p = result; 1558 1559 if (0) { 1560 days = total / 3600 / 24; 1561 hours = (total / 3600) % 24; 1562 mins = (total / 60) % 60; 1563 secs = total % 60; 1564 1565 if (days) { 1566 first = 0; 1567 p += sprintf(p, "%dd", days); 1568 } 1569 if (!first || hours) { 1570 first = 0; 1571 p += sprintf(p, "%dh", hours); 1572 } 1573 if (!first || mins) { 1574 first = 0; 1575 p += sprintf(p, "%dm", mins); 1576 } 1577 sprintf(p, "%ds", secs); 1578 } else 1579 sprintf(result, "%lu", (unsigned long)total); 1580 1581 return(result); 1582 } 1583 #endif /*INET6*/ 1584 1585 void 1586 ifmaybeload(name) 1587 char *name; 1588 { 1589 struct module_stat mstat; 1590 int fileid, modid; 1591 char ifkind[35], *cp, *dp; 1592 1593 1594 /* turn interface and unit into module name */ 1595 strcpy(ifkind, "if_"); 1596 for (cp = name, dp = ifkind + 3; (*cp != 0) && !isdigit(*cp); cp++, dp++) 1597 *dp = *cp; 1598 *dp = 0; 1599 1600 /* scan files in kernel */ 1601 mstat.version = sizeof(struct module_stat); 1602 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1603 /* scan modules in file */ 1604 for (modid = kldfirstmod(fileid); modid > 0; 1605 modid = modfnext(modid)) { 1606 if (modstat(modid, &mstat) < 0) 1607 continue; 1608 /* strip bus name if present */ 1609 if ((cp = strchr(mstat.name, '/')) != NULL) { 1610 cp++; 1611 } else { 1612 cp = mstat.name; 1613 } 1614 /* already loaded? */ 1615 if (!strcmp(ifkind, cp)) 1616 return; 1617 } 1618 } 1619 1620 /* not present, we should try to load it */ 1621 kldload(ifkind); 1622 } 1623