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