1 /* $FreeBSD: src/usr.sbin/gifconfig/gifconfig.c,v 1.2.2.4 2002/08/30 14:23:39 sobomax Exp $ */ 2 /* $KAME: gifconfig.c,v 1.14 2001/01/01 04:04:56 jinmei Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 /* 38 * gifconfig, derived from ifconfig 39 * 40 * @(#) Copyright (c) 1983, 1993\n\ 41 * The Regents of the University of California. All rights reserved.\n 42 * 43 * @(#)ifconfig.c 8.2 (Berkeley) 2/16/94 44 */ 45 46 /* 47 * 951109 - Andrew@pubnix.net - Changed to iterative buffer growing mechanism 48 * for ifconfig -a so all interfaces are queried. 49 * 50 * 960101 - peter@freebsd.org - Blow away the SIOCGIFCONF code and use 51 * sysctl() to get the structured interface conf 52 * and parse the messages in there. REALLY UGLY! 53 */ 54 55 #include <sys/param.h> 56 #include <sys/socket.h> 57 #include <sys/ioctl.h> 58 #include <sys/sysctl.h> 59 60 #include <net/if.h> 61 #if defined(__DragonFly__) 62 #include <net/if_var.h> 63 #endif /* __DragonFly__ */ 64 #include <net/if_dl.h> 65 #include <net/if_types.h> 66 #include <net/route.h> 67 #include <netinet/in.h> 68 #include <netinet/in_var.h> 69 #include <arpa/inet.h> 70 #include <netdb.h> 71 72 #include <sys/protosw.h> 73 74 #include <ctype.h> 75 #include <err.h> 76 #include <errno.h> 77 #include <stdio.h> 78 #include <stdlib.h> 79 #include <string.h> 80 #include <unistd.h> 81 #include <nlist.h> 82 #include <kvm.h> 83 #include <fcntl.h> 84 85 struct ifreq ifr; 86 struct ifaliasreq addreq; 87 #ifdef INET6 88 struct in6_ifreq in6_ifr; 89 struct in6_aliasreq in6_addreq; 90 #endif 91 92 char name[32]; 93 int flags; 94 int metric; 95 int mtu; 96 int setpsrc = 0; 97 int newaddr = 0; 98 int s; 99 kvm_t *kvmd; 100 101 #ifdef INET6 102 char ntop_buf[INET6_ADDRSTRLEN]; /*inet_ntop()*/ 103 #endif 104 105 void setifpsrc(char *, int); 106 void setifpdst(char *, int); 107 void setifflags(char *, int); 108 #ifdef SIOCDIFPHYADDR 109 void delifaddrs(char *, int); 110 #endif 111 112 #define NEXTARG 0xffffff 113 114 static struct cmd { 115 char *c_name; 116 int c_parameter; /* NEXTARG means next argv */ 117 void (*c_func)(char *, int); 118 } cmds[] = { 119 { "up", IFF_UP, setifflags } , 120 { "down", -IFF_UP, setifflags }, 121 #ifdef SIOCDIFPHYADDR 122 { "delete", 0, delifaddrs }, 123 #endif 124 { 0, 0, setifpsrc }, 125 { 0, 0, setifpdst }, 126 }; 127 128 /* 129 * XNS support liberally adapted from code written at the University of 130 * Maryland principally by James O'Toole and Chris Torek. 131 */ 132 int main(int, char *[]); 133 void status(void); 134 void phys_status(int); 135 void in_status(int); 136 #ifdef INET6 137 void in6_status(int); 138 #endif 139 void ether_status(int); 140 void Perror(char *); 141 void in_getaddr(char *, int); 142 #ifdef INET6 143 void in6_getaddr(char *, int); 144 void in6_getprefix(char *, int); 145 #endif 146 void printb(char *, unsigned int, char *); 147 int prefix(void *, int); 148 149 char ntop_buf[INET6_ADDRSTRLEN]; 150 151 /* Known address families */ 152 struct afswtch { 153 char *af_name; 154 short af_af; 155 void (*af_status)(int); 156 void (*af_getaddr)(char *, int); 157 void (*af_getprefix)(char *, int); 158 u_long af_pifaddr; 159 caddr_t af_addreq; 160 caddr_t af_req; 161 } afs[] = { 162 #define C(x) ((caddr_t) &x) 163 { "inet", AF_INET, in_status, in_getaddr, 0, 164 SIOCSIFPHYADDR, C(addreq), C(ifr) }, 165 #ifdef INET6 166 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 167 SIOCSIFPHYADDR_IN6, C(in6_addreq), C(in6_ifr) }, 168 #endif 169 { "ether", AF_INET, ether_status, NULL, NULL }, /* XXX not real!! */ 170 { 0, 0, 0, 0, 0 } 171 }; 172 173 struct afswtch *afp = NULL; /*the address family being set or asked about*/ 174 175 void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); 176 int ifconfig(int argc, char *argv[], int af, struct afswtch *rafp); 177 178 179 180 /* 181 * Expand the compacted form of addresses as returned via the 182 * configuration read via sysctl(). 183 */ 184 185 #define ROUNDUP(a) \ 186 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 187 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 188 189 void 190 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) 191 { 192 struct sockaddr *sa; 193 int i; 194 195 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 196 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 197 if ((rtinfo->rti_addrs & (1 << i)) == 0) 198 continue; 199 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 200 ADVANCE(cp, sa); 201 } 202 } 203 204 205 /* 206 * Grunge for new-style sysctl() decoding.. :-( 207 * Apologies to the world for committing gross things like this in 1996.. 208 */ 209 struct if_msghdr *ifm; 210 struct ifa_msghdr *ifam; 211 struct sockaddr_dl *sdl; 212 struct rt_addrinfo info; 213 char *buf, *lim, *next; 214 215 216 int 217 main(int argc, char **argv) 218 { 219 int af = AF_INET; 220 struct afswtch *rafp = NULL; 221 size_t needed; 222 int mib[6]; 223 int all; 224 225 if (argc < 2) { 226 fprintf(stderr, 227 "usage: gifconfig interface [af] [physsrc physdst]\n"); 228 #ifdef SIOCDIFPHYADDR 229 fprintf(stderr, 230 " gifconfig interface delete\n"); 231 #endif 232 fprintf(stderr, 233 " gifconfig -a\n"); 234 exit(1); 235 } 236 argc--, argv++; 237 strncpy(name, *argv, sizeof(name)); 238 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 239 argc--, argv++; 240 if (argc > 0) { 241 for (afp = rafp = afs; rafp->af_name; rafp++) 242 if (strcmp(rafp->af_name, *argv) == 0) { 243 afp = rafp; argc--; argv++; 244 break; 245 } 246 rafp = afp; 247 af = ifr.ifr_addr.sa_family = rafp->af_af; 248 } 249 250 mib[0] = CTL_NET; 251 mib[1] = PF_ROUTE; 252 mib[2] = 0; 253 mib[3] = 0; /* address family */ 254 mib[4] = NET_RT_IFLIST; 255 mib[5] = 0; 256 257 /* if particular family specified, only ask about it */ 258 if (afp) { 259 mib[3] = afp->af_af; 260 } 261 262 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 263 errx(1, "iflist-sysctl-estimate"); 264 if ((buf = malloc(needed)) == NULL) 265 errx(1, "malloc"); 266 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 267 errx(1, "actual retrieval of interface table"); 268 lim = buf + needed; 269 270 all = 0; 271 if (strcmp(name, "-a") == 0) 272 all = 1; /* All interfaces */ 273 else if (strcmp(name, "-au") == 0) 274 all = 2; /* All IFF_UPinterfaces */ 275 else if (strcmp(name, "-ad") == 0) 276 all = 3; /* All !IFF_UP interfaces */ 277 278 for (next = buf; next < lim; next += ifm->ifm_msglen) { 279 280 ifm = (struct if_msghdr *)next; 281 282 /* XXX: Swallow up leftover NEWADDR messages */ 283 if (ifm->ifm_type == RTM_NEWADDR) 284 continue; 285 286 if (ifm->ifm_type == RTM_IFINFO) { 287 sdl = (struct sockaddr_dl *)(ifm + 1); 288 flags = ifm->ifm_flags; 289 } else { 290 errx(1, "out of sync parsing NET_RT_IFLIST"); 291 } 292 293 switch(all) { 294 case -1: 295 case 0: 296 if (strlen(name) != sdl->sdl_nlen) 297 continue; /* not same len */ 298 if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) 299 continue; /* not same name */ 300 break; 301 case 1: 302 break; /* always do it */ 303 case 2: 304 if ((flags & IFF_UP) == 0) 305 continue; /* not up */ 306 break; 307 case 3: 308 if (flags & IFF_UP) 309 continue; /* not down */ 310 break; 311 } 312 313 /* 314 * Let's just do it for gif only 315 */ 316 if (sdl->sdl_type != IFT_GIF) { 317 if (all != 0) 318 continue; 319 320 fprintf(stderr, "gifconfig: %s is not gif.\n", 321 ifr.ifr_name); 322 exit(1); 323 } 324 325 if (all > 0) { 326 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 327 name[sdl->sdl_nlen] = '\0'; 328 } 329 330 if ((s = socket(af, SOCK_DGRAM, 0)) < 0) { 331 perror("gifconfig: socket"); 332 exit(1); 333 } 334 335 ifconfig(argc,argv,af,rafp); 336 337 close(s); 338 339 if (all == 0) { 340 all = -1; /* flag it as 'done' */ 341 break; 342 } 343 } 344 free(buf); 345 346 if (all == 0) 347 errx(1, "interface %s does not exist", name); 348 349 350 exit (0); 351 } 352 353 354 int 355 ifconfig(int argc, char **argv, int af, struct afswtch *rafp) 356 { 357 358 af = 0; /*fool gcc*/ 359 360 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 361 #ifdef INET6 362 strncpy(in6_ifr.ifr_name, name, sizeof in6_ifr.ifr_name); 363 #endif /* INET6 */ 364 365 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 366 perror("ioctl (SIOCGIFMETRIC)"); 367 else 368 metric = ifr.ifr_metric; 369 370 #if defined(SIOCGIFMTU) && !defined(__OpenBSD__) 371 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) 372 perror("ioctl (SIOCGIFMTU)"); 373 else 374 mtu = ifr.ifr_mtu; 375 #else 376 mtu = 0; 377 #endif 378 379 if (argc == 0) { 380 status(); 381 return(0); 382 } 383 384 while (argc > 0) { 385 struct cmd *p; 386 387 for (p = cmds; p->c_name; p++) 388 if (strcmp(*argv, p->c_name) == 0) 389 break; 390 if (p->c_name == NULL && setpsrc) 391 p++; /* got src, do dst */ 392 if (p->c_func) { 393 if (p->c_parameter == NEXTARG) { 394 if (argv[1] == NULL) 395 errx(1, "'%s' requires argument", 396 p->c_name); 397 (*p->c_func)(argv[1], 0); 398 argc--, argv++; 399 } else 400 (*p->c_func)(*argv, p->c_parameter); 401 } 402 argc--, argv++; 403 } 404 if (newaddr) { 405 strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name); 406 if (ioctl(s, rafp->af_pifaddr, rafp->af_addreq) < 0) 407 Perror("ioctl (SIOCSIFPHYADDR)"); 408 } 409 else if (setpsrc) { 410 errx(1, "destination is not specified"); 411 } 412 return(0); 413 } 414 #define PSRC 0 415 #define PDST 1 416 417 /*ARGSUSED*/ 418 void 419 setifpsrc(char *addr, int param) 420 { 421 param = 0; /*fool gcc*/ 422 (*afp->af_getaddr)(addr, PSRC); 423 setpsrc = 1; 424 } 425 426 /*ARGSUSED*/ 427 void 428 setifpdst(char *addr, int param) 429 { 430 param = 0; /*fool gcc*/ 431 (*afp->af_getaddr)(addr, PDST); 432 newaddr = 1; 433 } 434 435 void 436 setifflags(char *vname, int value) 437 { 438 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 439 Perror("ioctl (SIOCGIFFLAGS)"); 440 exit(1); 441 } 442 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 443 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); 444 445 if (value < 0) { 446 value = -value; 447 flags &= ~value; 448 } else 449 flags |= value; 450 ifr.ifr_flags = flags & 0xffff; 451 ifr.ifr_flagshigh = flags >> 16; 452 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 453 Perror(vname); 454 } 455 456 #ifdef SIOCDIFPHYADDR 457 /* ARGSUSED */ 458 void 459 delifaddrs(char *vname, int param) 460 { 461 param = 0; /* fool gcc */ 462 vname = NULL; /* ditto */ 463 464 if (ioctl(s, SIOCDIFPHYADDR, (caddr_t)&ifr) < 0) 465 err(1, "ioctl(SIOCDIFPHYADDR)"); 466 } 467 #endif 468 469 #define IFFBITS \ 470 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 471 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 472 473 /* 474 * Print the status of the interface. If an address family was 475 * specified, show it and it only; otherwise, show them all. 476 */ 477 void 478 status(void) 479 { 480 struct afswtch *p = NULL; 481 char *mynext; 482 struct if_msghdr *myifm; 483 484 printf("%s: ", name); 485 printb("flags", flags, IFFBITS); 486 if (metric) 487 printf(" metric %d", metric); 488 if (mtu) 489 printf(" mtu %d", mtu); 490 putchar('\n'); 491 492 /* 493 * XXX: Sigh. This is bad, I know. At this point, we may have 494 * *zero* RTM_NEWADDR's, so we have to "feel the water" before 495 * incrementing the loop. One day, I might feel inspired enough 496 * to get the top level loop to pass a count down here so we 497 * dont have to mess with this. -Peter 498 */ 499 myifm = ifm; 500 501 while (1) { 502 503 mynext = next + ifm->ifm_msglen; 504 505 if (mynext >= lim) 506 break; 507 508 myifm = (struct if_msghdr *)mynext; 509 510 if (myifm->ifm_type != RTM_NEWADDR) 511 break; 512 513 next = mynext; 514 515 ifm = (struct if_msghdr *)next; 516 517 ifam = (struct ifa_msghdr *)myifm; 518 info.rti_addrs = ifam->ifam_addrs; 519 520 /* Expand the compacted addresses */ 521 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 522 &info); 523 524 if (afp) { 525 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family && 526 afp->af_status != ether_status) { 527 p = afp; 528 if (p->af_status != ether_status) 529 (*p->af_status)(1); 530 } 531 } else for (p = afs; p->af_name; p++) { 532 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family && 533 p->af_status != ether_status) 534 (*p->af_status)(0); 535 } 536 } 537 if (afp == NULL || afp->af_status == ether_status) 538 ether_status(0); 539 else if (afp && !p) { 540 warnx("%s has no %s IFA address!", name, afp->af_name); 541 } 542 543 phys_status(0); 544 } 545 546 void 547 phys_status(int force) 548 { 549 char psrcaddr[256]; 550 char pdstaddr[256]; 551 int flags = NI_NUMERICHOST; 552 char *af; 553 #ifndef SIOCGLIFPHYADDR 554 u_long srccmd, dstcmd; 555 struct ifreq *ifrp; 556 #ifdef INET6 557 int s6; 558 #endif 559 560 force = 0; /*fool gcc*/ 561 562 psrcaddr[0] = pdstaddr[0] = '\0'; 563 564 #ifdef INET6 565 s6 = socket(AF_INET6, SOCK_DGRAM, 0); 566 if (s6 < 0) { 567 ifrp = 𝔦 568 srccmd = SIOCGIFPSRCADDR; 569 dstcmd = SIOCGIFPDSTADDR; 570 } else { 571 close(s6); 572 srccmd = SIOCGIFPSRCADDR_IN6; 573 dstcmd = SIOCGIFPDSTADDR_IN6; 574 ifrp = (struct ifreq *)&in6_ifr; 575 } 576 #else /* INET6 */ 577 ifrp = 𝔦 578 srccmd = SIOCGIFPSRCADDR; 579 dstcmd = SIOCGIFPDSTADDR; 580 #endif /* INET6 */ 581 582 if (0 <= ioctl(s, srccmd, (caddr_t)ifrp)) { 583 #ifdef INET6 584 if (ifrp->ifr_addr.sa_family == AF_INET6) 585 af = "inet6"; 586 else 587 af = "inet"; 588 #else 589 af = "inet"; 590 #endif /* INET6 */ 591 if (getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 592 psrcaddr, sizeof(psrcaddr), 0, 0, flags) != 0) 593 psrcaddr[0] = '\0'; 594 } 595 if (0 <= ioctl(s, dstcmd, (caddr_t)ifrp)) { 596 if (getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 597 pdstaddr, sizeof(pdstaddr), 0, 0, flags) != 0) 598 pdstaddr[0] = '\0'; 599 } 600 printf("\tphysical address %s %s --> %s\n", af, psrcaddr, pdstaddr); 601 #else 602 struct if_laddrreq iflr; 603 604 force = 0; /*fool gcc*/ 605 606 psrcaddr[0] = pdstaddr[0] = '\0'; 607 608 memset(&iflr, 0, sizeof(iflr)); 609 memcpy(iflr.iflr_name, ifr.ifr_name, sizeof(iflr.iflr_name)); 610 611 if (0 <= ioctl(s, SIOCGLIFPHYADDR, (caddr_t)&iflr)) { 612 switch (iflr.addr.ss_family) { 613 case AF_INET: 614 af = "inet"; 615 break; 616 #ifdef INET6 617 case AF_INET6: 618 af = "inet6"; 619 break; 620 #endif /* INET6 */ 621 } 622 if (getnameinfo((struct sockaddr *)&iflr.addr, iflr.addr.ss_len, 623 psrcaddr, sizeof(psrcaddr), 0, 0, flags) != 0) 624 psrcaddr[0] = '\0'; 625 if (getnameinfo((struct sockaddr *)&iflr.dstaddr, 626 iflr.dstaddr.ss_len, pdstaddr, sizeof(pdstaddr), 0, 0, 627 flags) != 0) 628 pdstaddr[0] = '\0'; 629 } 630 printf("\tphysical address %s %s --> %s\n", af, psrcaddr, pdstaddr); 631 #endif 632 } 633 634 void 635 in_status(int force) 636 { 637 struct sockaddr_in *sin, null_sin; 638 #if 0 639 char *inet_ntoa(); 640 #endif 641 642 memset(&null_sin, 0, sizeof(null_sin)); 643 644 sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA]; 645 if (!sin || sin->sin_family != AF_INET) { 646 if (!force) 647 return; 648 /* warnx("%s has no AF_INET IFA address!", name); */ 649 sin = &null_sin; 650 } 651 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 652 653 if (flags & IFF_POINTOPOINT) { 654 /* note RTAX_BRD overlap with IFF_BROADCAST */ 655 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD]; 656 if (!sin) 657 sin = &null_sin; 658 printf("--> %s ", inet_ntoa(sin->sin_addr)); 659 } 660 661 sin = (struct sockaddr_in *)info.rti_info[RTAX_NETMASK]; 662 if (!sin) 663 sin = &null_sin; 664 printf("netmask 0x%x ", (u_int32_t)ntohl(sin->sin_addr.s_addr)); 665 666 if (flags & IFF_BROADCAST) { 667 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 668 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD]; 669 if (sin && sin->sin_addr.s_addr != 0) 670 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 671 } 672 putchar('\n'); 673 } 674 675 #ifdef INET6 676 void 677 in6_status(int force) 678 { 679 struct sockaddr_in6 *sin, null_sin; 680 char hostname[NI_MAXHOST]; 681 int niflags = NI_NUMERICHOST; 682 683 memset(&null_sin, 0, sizeof(null_sin)); 684 #ifdef NI_WITHSCOPEID 685 niflags |= NI_WITHSCOPEID; 686 #endif 687 688 sin = (struct sockaddr_in6 *)info.rti_info[RTAX_IFA]; 689 if (!sin || sin->sin6_family != AF_INET6) { 690 if (!force) 691 return; 692 /* warnx("%s has no AF_INET6 IFA address!", name); */ 693 sin = &null_sin; 694 } 695 #ifdef __KAME__ 696 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) { 697 sin->sin6_scope_id = 698 ntohs(*(u_int16_t *)&sin->sin6_addr.s6_addr[2]); 699 sin->sin6_addr.s6_addr[2] = 0; 700 sin->sin6_addr.s6_addr[3] = 0; 701 } 702 #endif 703 getnameinfo((struct sockaddr *)sin, sin->sin6_len, 704 hostname, sizeof(hostname), 0, 0, niflags); 705 printf("\tinet6 %s ", hostname); 706 707 if (flags & IFF_POINTOPOINT) { 708 /* note RTAX_BRD overlap with IFF_BROADCAST */ 709 sin = (struct sockaddr_in6 *)info.rti_info[RTAX_BRD]; 710 /* 711 * some of ther interfaces do not have valid destination 712 * address. 713 */ 714 if (sin->sin6_family == AF_INET6) { 715 #ifdef __KAME__ 716 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) { 717 sin->sin6_scope_id = 718 ntohs(*(u_int16_t *)&sin->sin6_addr.s6_addr[2]); 719 sin->sin6_addr.s6_addr[2] = 0; 720 sin->sin6_addr.s6_addr[3] = 0; 721 } 722 #endif 723 getnameinfo((struct sockaddr *)sin, sin->sin6_len, 724 hostname, sizeof(hostname), 0, 0, niflags); 725 printf("--> %s ", hostname); 726 } 727 } 728 729 sin = (struct sockaddr_in6 *)info.rti_info[RTAX_NETMASK]; 730 if (!sin) 731 sin = &null_sin; 732 printf(" prefixlen %d ", prefix(&sin->sin6_addr, 733 sizeof(struct in6_addr))); 734 735 putchar('\n'); 736 } 737 #endif /*INET6*/ 738 739 /*ARGSUSED*/ 740 void 741 ether_status(int dummy) 742 { 743 char *cp; 744 int n; 745 746 dummy = 0; /*fool gcc*/ 747 748 cp = (char *)LLADDR(sdl); 749 if ((n = sdl->sdl_alen) > 0) { 750 if (sdl->sdl_type == IFT_ETHER) 751 printf ("\tether "); 752 else 753 printf ("\tlladdr "); 754 while (--n >= 0) 755 printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' '); 756 putchar('\n'); 757 } 758 } 759 760 void 761 Perror(char *cmd) 762 { 763 switch (errno) { 764 765 case ENXIO: 766 errx(1, "%s: no such interface", cmd); 767 break; 768 769 case EPERM: 770 errx(1, "%s: permission denied", cmd); 771 break; 772 773 default: 774 err(1, "%s", cmd); 775 } 776 } 777 778 #define SIN(x) ((struct sockaddr_in *) &(x)) 779 struct sockaddr_in *sintab[] = { 780 SIN(addreq.ifra_addr), SIN(addreq.ifra_dstaddr)}; 781 782 void 783 in_getaddr(char *s, int which) 784 { 785 struct sockaddr_in *sin = sintab[which]; 786 struct hostent *hp; 787 struct netent *np; 788 789 sin->sin_len = sizeof(*sin); 790 sin->sin_family = AF_INET; 791 792 if (inet_aton(s, &sin->sin_addr)) 793 ; 794 else if ((hp = gethostbyname(s)) != NULL) 795 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 796 else if ((np = getnetbyname(s)) != NULL) 797 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 798 else 799 errx(1, "%s: bad value", s); 800 } 801 802 #ifdef INET6 803 #define SIN6(x) ((struct sockaddr_in6 *) &(x)) 804 struct sockaddr_in6 *sin6tab[] = { 805 SIN6(in6_addreq.ifra_addr), SIN6(in6_addreq.ifra_dstaddr)}; 806 807 void 808 in6_getaddr(char *s, int which) 809 { 810 struct sockaddr_in6 *sin = sin6tab[which]; 811 812 sin->sin6_len = sizeof(*sin); 813 sin->sin6_family = AF_INET6; 814 815 if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) 816 errx(1, "%s: bad value", s); 817 } 818 819 void 820 in6_getprefix(char *plen, int which) 821 { 822 struct sockaddr_in6 *sin = sin6tab[which]; 823 u_char *cp; 824 int len = atoi(plen); 825 826 if ((len < 0) || (len > 128)) 827 errx(1, "%s: bad value", plen); 828 sin->sin6_len = sizeof(*sin); 829 sin->sin6_family = AF_INET6; 830 if ((len == 0) || (len == 128)) { 831 memset(&sin->sin6_addr, -1, sizeof(struct in6_addr)); 832 return; 833 } 834 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 835 *cp++ = -1; 836 *cp = (-1) << (8 - len); 837 } 838 #endif 839 840 /* 841 * Print a value a la the %b format of the kernel's printf 842 */ 843 void 844 printb(char *s, unsigned int v, char *bits) 845 { 846 int i, any = 0; 847 char c; 848 849 if (bits && *bits == 8) 850 printf("%s=%o", s, v & 0xffff); 851 else 852 printf("%s=%x", s, v & 0xffff); 853 bits++; 854 if (bits) { 855 putchar('<'); 856 while ((i = *bits++) != 0) { 857 if ((v & (1 << (i-1))) != 0) { 858 if (any) 859 putchar(','); 860 any = 1; 861 for (; (c = *bits) > 32; bits++) 862 putchar(c); 863 } else 864 for (; *bits > 32; bits++) 865 ; 866 } 867 putchar('>'); 868 } 869 } 870 871 #ifdef INET6 872 int 873 prefix(void *val, int size) 874 { 875 u_char *name = (u_char *)val; 876 int byte, bit, plen = 0; 877 878 for (byte = 0; byte < size; byte++, plen += 8) 879 if (name[byte] != 0xff) 880 break; 881 if (byte == size) 882 return (plen); 883 for (bit = 7; bit != 0; bit--, plen++) 884 if (!(name[byte] & (1 << bit))) 885 break; 886 for (; bit != 0; bit--) 887 if (name[byte] & (1 << bit)) 888 return(0); 889 byte++; 890 for (; byte < size; byte++) 891 if (name[byte]) 892 return(0); 893 return (plen); 894 } 895 #endif /*INET6*/ 896