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