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