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