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