]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/gifconfig/gifconfig.c
This commit was generated by cvs2svn to compensate for changes in r74485,
[FreeBSD/FreeBSD.git] / usr.sbin / gifconfig / gifconfig.c
1 /*      $FreeBSD$       */
2 /*      $KAME: gifconfig.c,v 1.12 2000/05/22 05:50:43 itojun 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(__FreeBSD__) && __FreeBSD__ >= 3
62 #include <net/if_var.h>
63 #endif /* __FreeBSD__ >= 3 */
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 __P((char *, int));
106 void setifpdst __P((char *, int));
107 void setifflags __P((char *, int));
108 #ifdef SIOCDIFPHYADDR
109 void delifaddrs __P((char *, int));
110 #endif
111
112 #define NEXTARG         0xffffff
113
114 struct  cmd {
115         char    *c_name;
116         int     c_parameter;            /* NEXTARG means next argv */
117         void    (*c_func) __P((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 __P((int, char *[]));
133 void status __P((void));
134 void phys_status __P((int));
135 void in_status __P((int));
136 #ifdef INET6
137 void in6_status __P((int));
138 #endif
139 void ether_status __P((int));
140 void Perror __P((char *));
141 void in_getaddr __P((char *, int));
142 #ifdef INET6
143 void in6_getaddr __P((char *, int));
144 void in6_getprefix __P((char *, int));
145 #endif
146 void printb __P((char *, unsigned int, char *));
147 int prefix __P((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) __P((int));
156         void (*af_getaddr) __P((char *, int));
157         void (*af_getprefix) __P((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 __P((caddr_t, caddr_t, struct rt_addrinfo *));
176 int     ifconfig __P((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(cp, cplim, rtinfo)
191         caddr_t cp, cplim;
192         struct rt_addrinfo *rtinfo;
193 {
194         struct sockaddr *sa;
195         int i;
196
197         memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
198         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
199                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
200                         continue;
201                 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
202                 ADVANCE(cp, sa);
203         }
204 }
205
206
207 /*
208  * Grunge for new-style sysctl() decoding.. :-(
209  * Apologies to the world for committing gross things like this in 1996..
210  */
211 struct if_msghdr *ifm;
212 struct ifa_msghdr *ifam;
213 struct sockaddr_dl *sdl;
214 struct rt_addrinfo info;
215 char *buf, *lim, *next;
216
217
218 int
219 main(argc, argv)
220         int argc;
221         char *argv[];
222 {
223         int af = AF_INET;
224         struct afswtch *rafp = NULL;
225         size_t needed;
226         int mib[6];
227         int all;
228
229         if (argc < 2) {
230                 fprintf(stderr,
231                     "usage: gifconfig interface [af] [physsrc physdst]\n");
232 #ifdef SIOCDIFPHYADDR
233                 fprintf(stderr,
234                     "       gifconfig interface delete\n");
235 #endif
236                 fprintf(stderr,
237                     "       gifconfig -a\n");
238                 exit(1);
239         }
240         argc--, argv++;
241         strncpy(name, *argv, sizeof(name));
242         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
243         argc--, argv++;
244         if (argc > 0) {
245                 for (afp = rafp = afs; rafp->af_name; rafp++)
246                         if (strcmp(rafp->af_name, *argv) == 0) {
247                                 afp = rafp; argc--; argv++;
248                                 break;
249                         }
250                 rafp = afp;
251                 af = ifr.ifr_addr.sa_family = rafp->af_af;
252         }
253
254         mib[0] = CTL_NET;
255         mib[1] = PF_ROUTE;
256         mib[2] = 0;
257         mib[3] = 0;     /* address family */
258         mib[4] = NET_RT_IFLIST;
259         mib[5] = 0;
260
261         /* if particular family specified, only ask about it */
262         if (afp) {
263                 mib[3] = afp->af_af;
264         }
265
266         if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
267                 errx(1, "iflist-sysctl-estimate");
268         if ((buf = malloc(needed)) == NULL)
269                 errx(1, "malloc");
270         if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
271                 errx(1, "actual retrieval of interface table");
272         lim = buf + needed;
273
274         all = 0;
275         if (strcmp(name, "-a") == 0)
276                 all = 1;        /* All interfaces */
277         else if (strcmp(name, "-au") == 0)
278                 all = 2;        /* All IFF_UPinterfaces */
279         else if (strcmp(name, "-ad") == 0)
280                 all = 3;        /* All !IFF_UP interfaces */
281
282         for (next = buf; next < lim; next += ifm->ifm_msglen) {
283
284                 ifm = (struct if_msghdr *)next;
285
286                 /* XXX: Swallow up leftover NEWADDR messages */
287                 if (ifm->ifm_type == RTM_NEWADDR)
288                         continue;
289
290                 if (ifm->ifm_type == RTM_IFINFO) {
291                         sdl = (struct sockaddr_dl *)(ifm + 1);
292                         flags = ifm->ifm_flags;
293                 } else {
294                         errx(1, "out of sync parsing NET_RT_IFLIST");
295                 }
296
297                 switch(all) {
298                 case -1:
299                 case 0:
300                         if (strlen(name) != sdl->sdl_nlen)
301                                 continue; /* not same len */
302                         if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
303                                 continue; /* not same name */
304                         break;
305                 case 1:
306                         break;  /* always do it */
307                 case 2:
308                         if ((flags & IFF_UP) == 0)
309                                 continue; /* not up */
310                         break;
311                 case 3:
312                         if (flags & IFF_UP)
313                                 continue; /* not down */
314                         break;
315                 }
316
317                 /*
318                  * Let's just do it for gif only
319                  */
320                 if (sdl->sdl_type != IFT_GIF) {
321                         if (all != 0)
322                                 continue;
323
324                         fprintf(stderr, "gifconfig: %s is not gif.\n",
325                                 ifr.ifr_name);
326                         exit(1);
327                 }
328
329                 if (all > 0) {
330                         strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
331                         name[sdl->sdl_nlen] = '\0';
332                 }
333
334                 if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
335                         perror("gifconfig: socket");
336                         exit(1);
337                 }
338
339                 ifconfig(argc,argv,af,rafp);
340
341                 close(s);
342
343                 if (all == 0) {
344                         all = -1; /* flag it as 'done' */
345                         break;
346                 }
347         }
348         free(buf);
349
350         if (all == 0)
351                 errx(1, "interface %s does not exist", name);
352         
353
354         exit (0);
355 }
356
357
358 int
359 ifconfig(argc, argv, af, rafp)
360         int argc;
361         char *argv[];
362         int af;
363         struct afswtch *rafp;
364 {
365
366         af = 0;         /*fool gcc*/
367
368         strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
369 #ifdef INET6
370         strncpy(in6_ifr.ifr_name, name, sizeof in6_ifr.ifr_name);
371 #endif /* INET6 */
372
373         if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
374                 perror("ioctl (SIOCGIFMETRIC)");
375         else
376                 metric = ifr.ifr_metric;
377
378 #if defined(SIOCGIFMTU) && !defined(__OpenBSD__)
379         if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
380                 perror("ioctl (SIOCGIFMTU)");
381         else
382                 mtu = ifr.ifr_mtu;
383 #else
384         mtu = 0;
385 #endif
386
387         if (argc == 0) {
388                 status();
389                 return(0);
390         }
391
392         while (argc > 0) {
393                 register struct cmd *p;
394
395                 for (p = cmds; p->c_name; p++)
396                         if (strcmp(*argv, p->c_name) == 0)
397                                 break;
398                 if (p->c_name == 0 && setpsrc)
399                         p++;    /* got src, do dst */
400                 if (p->c_func) {
401                         if (p->c_parameter == NEXTARG) {
402                                 if (argv[1] == NULL)
403                                         errx(1, "'%s' requires argument",
404                                             p->c_name);
405                                 (*p->c_func)(argv[1], 0);
406                                 argc--, argv++;
407                         } else
408                                 (*p->c_func)(*argv, p->c_parameter);
409                 }
410                 argc--, argv++;
411         }
412         if (newaddr) {
413                 strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name);
414                 if (ioctl(s, rafp->af_pifaddr, rafp->af_addreq) < 0)
415                         Perror("ioctl (SIOCSIFPHYADDR)");
416         }
417         else if (setpsrc) {
418                 errx(1, "destination is not specified");
419         }
420         return(0);
421 }
422 #define PSRC    0
423 #define PDST    1
424
425 /*ARGSUSED*/
426 void
427 setifpsrc(addr, param)
428         char *addr;
429         int param;
430 {
431         param = 0;      /*fool gcc*/
432         (*afp->af_getaddr)(addr, PSRC);
433         setpsrc = 1;
434 }
435
436 /*ARGSUSED*/
437 void
438 setifpdst(addr, param)
439         char *addr;
440         int param;
441 {
442         param = 0;      /*fool gcc*/
443         (*afp->af_getaddr)(addr, PDST);
444         newaddr = 1;
445 }
446
447 void
448 setifflags(vname, value)
449         char *vname;
450         int value;
451 {
452         if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
453                 Perror("ioctl (SIOCGIFFLAGS)");
454                 exit(1);
455         }
456         strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
457         flags = ifr.ifr_flags;
458
459         if (value < 0) {
460                 value = -value;
461                 flags &= ~value;
462         } else
463                 flags |= value;
464         ifr.ifr_flags = flags;
465         if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
466                 Perror(vname);
467 }
468
469 #ifdef SIOCDIFPHYADDR
470 /* ARGSUSED */
471 void
472 delifaddrs(vname, param)
473         char *vname;
474         int param;
475 {
476         param = 0;              /* fool gcc */
477         vname = NULL;           /* ditto */
478
479         if (ioctl(s, SIOCDIFPHYADDR, (caddr_t)&ifr) < 0)
480                 err(1, "ioctl(SIOCDIFPHYADDR)");
481 }
482 #endif
483
484 #define IFFBITS \
485 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
486 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
487
488 /*
489  * Print the status of the interface.  If an address family was
490  * specified, show it and it only; otherwise, show them all.
491  */
492 void
493 status()
494 {
495         struct afswtch *p = NULL;
496         char *mynext;
497         struct if_msghdr *myifm;
498
499         printf("%s: ", name);
500         printb("flags", flags, IFFBITS);
501         if (metric)
502                 printf(" metric %d", metric);
503         if (mtu)
504                 printf(" mtu %d", mtu);
505         putchar('\n');
506
507         /*
508          * XXX: Sigh. This is bad, I know.  At this point, we may have
509          * *zero* RTM_NEWADDR's, so we have to "feel the water" before
510          * incrementing the loop.  One day, I might feel inspired enough
511          * to get the top level loop to pass a count down here so we
512          * dont have to mess with this.  -Peter
513          */
514         myifm = ifm;
515
516         while (1) {
517
518                 mynext = next + ifm->ifm_msglen;
519
520                 if (mynext >= lim)
521                         break;
522
523                 myifm = (struct if_msghdr *)mynext;
524
525                 if (myifm->ifm_type != RTM_NEWADDR)
526                         break;
527
528                 next = mynext;
529
530                 ifm = (struct if_msghdr *)next;
531
532                 ifam = (struct ifa_msghdr *)myifm;
533                 info.rti_addrs = ifam->ifam_addrs;
534
535                 /* Expand the compacted addresses */
536                 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
537                           &info);
538
539                 if (afp) {
540                         if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family &&
541                             afp->af_status != ether_status) {
542                                 p = afp;
543                                 if (p->af_status != ether_status)
544                                         (*p->af_status)(1);
545                         }
546                 } else for (p = afs; p->af_name; p++) {
547                         if (p->af_af == info.rti_info[RTAX_IFA]->sa_family &&
548                             p->af_status != ether_status)
549                                 (*p->af_status)(0);
550                 }
551         }
552         if (afp == NULL || afp->af_status == ether_status)
553                 ether_status(0);
554         else if (afp && !p) {
555                 warnx("%s has no %s IFA address!", name, afp->af_name);
556         }
557
558         phys_status(0);
559 }
560
561 void
562 phys_status(force)
563         int force;
564 {
565         char psrcaddr[256];
566         char pdstaddr[256];
567         char hostname[NI_MAXHOST];
568         u_long srccmd, dstcmd;
569         int flags = NI_NUMERICHOST;
570         struct ifreq *ifrp;
571         char *ver = "";
572 #ifdef INET6
573         int s6;
574 #endif
575
576         force = 0;      /*fool gcc*/
577
578         psrcaddr[0] = pdstaddr[0] = '\0';
579
580 #ifdef INET6
581         s6 = socket(AF_INET6, SOCK_DGRAM, 0);
582         if (s6 < 0) {
583                 ifrp = &ifr;
584                 srccmd = SIOCGIFPSRCADDR;
585                 dstcmd = SIOCGIFPDSTADDR;
586         } else {
587                 close(s6);
588                 srccmd = SIOCGIFPSRCADDR_IN6;
589                 dstcmd = SIOCGIFPDSTADDR_IN6;
590                 ifrp = (struct ifreq *)&in6_ifr;
591         }
592 #else /* INET6 */
593         ifrp = &ifr;
594         srccmd = SIOCGIFPSRCADDR;
595         dstcmd = SIOCGIFPDSTADDR;
596 #endif /* INET6 */
597
598         if (0 <= ioctl(s, srccmd, (caddr_t)ifrp)) {
599                 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
600                             hostname, sizeof(hostname), 0, 0, flags);
601 #ifdef INET6
602                 if (ifrp->ifr_addr.sa_family == AF_INET6)
603                         ver = "6";
604 #endif /* INET6 */
605                 sprintf(psrcaddr, "inet%s %s", ver, hostname);
606         }
607         if (0 <= ioctl(s, dstcmd, (caddr_t)ifrp)) {
608                 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
609                             hostname, sizeof(hostname), 0, 0, flags);
610                 sprintf(pdstaddr, "%s", hostname);
611         }
612         printf("\tphysical address %s --> %s\n", psrcaddr, pdstaddr);
613 }
614
615 void
616 in_status(force)
617         int force;
618 {
619         struct sockaddr_in *sin, null_sin;
620 #if 0
621         char *inet_ntoa();
622 #endif
623         
624         memset(&null_sin, 0, sizeof(null_sin));
625
626         sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
627         if (!sin || sin->sin_family != AF_INET) {
628                 if (!force)
629                         return;
630                 /* warnx("%s has no AF_INET IFA address!", name); */
631                 sin = &null_sin;
632         }
633         printf("\tinet %s ", inet_ntoa(sin->sin_addr));
634
635         if (flags & IFF_POINTOPOINT) {
636                 /* note RTAX_BRD overlap with IFF_BROADCAST */
637                 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
638                 if (!sin)
639                         sin = &null_sin;
640                 printf("--> %s ", inet_ntoa(sin->sin_addr));
641         }
642
643         sin = (struct sockaddr_in *)info.rti_info[RTAX_NETMASK];
644         if (!sin)
645                 sin = &null_sin;
646         printf("netmask 0x%x ", (u_int32_t)ntohl(sin->sin_addr.s_addr));
647
648         if (flags & IFF_BROADCAST) {
649                 /* note RTAX_BRD overlap with IFF_POINTOPOINT */
650                 sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
651                 if (sin && sin->sin_addr.s_addr != 0)
652                         printf("broadcast %s", inet_ntoa(sin->sin_addr));
653         }
654         putchar('\n');
655 }
656
657 #ifdef INET6
658 void
659 in6_status(force)
660         int force;
661 {
662         struct sockaddr_in6 *sin, null_sin;
663         char hostname[NI_MAXHOST];
664         int niflags = NI_NUMERICHOST;
665
666         memset(&null_sin, 0, sizeof(null_sin));
667 #ifdef NI_WITHSCOPEID
668         niflags |= NI_WITHSCOPEID;
669 #endif
670
671         sin = (struct sockaddr_in6 *)info.rti_info[RTAX_IFA];
672         if (!sin || sin->sin6_family != AF_INET6) {
673                 if (!force)
674                         return;
675                 /* warnx("%s has no AF_INET6 IFA address!", name); */
676                 sin = &null_sin;
677         }
678 #ifdef __KAME__
679         if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) {
680                 sin->sin6_scope_id =
681                         ntohs(*(u_int16_t *)&sin->sin6_addr.s6_addr[2]);
682                 sin->sin6_addr.s6_addr[2] = 0;
683                 sin->sin6_addr.s6_addr[3] = 0;
684         }
685 #endif
686         getnameinfo((struct sockaddr *)sin, sin->sin6_len,
687                     hostname, sizeof(hostname), 0, 0, niflags);
688         printf("\tinet6 %s ", hostname);
689
690         if (flags & IFF_POINTOPOINT) {
691                 /* note RTAX_BRD overlap with IFF_BROADCAST */
692                 sin = (struct sockaddr_in6 *)info.rti_info[RTAX_BRD];
693                 /*
694                  * some of ther interfaces do not have valid destination
695                  * address.
696                  */
697                 if (sin->sin6_family == AF_INET6) {
698 #ifdef __KAME__
699                         if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) {
700                                 sin->sin6_scope_id =
701                                         ntohs(*(u_int16_t *)&sin->sin6_addr.s6_addr[2]);
702                                 sin->sin6_addr.s6_addr[2] = 0;
703                                 sin->sin6_addr.s6_addr[3] = 0;
704                         }
705 #endif
706                         getnameinfo((struct sockaddr *)sin, sin->sin6_len,
707                                     hostname, sizeof(hostname), 0, 0, niflags);
708                         printf("--> %s ", hostname);
709                 }
710         }
711
712         sin = (struct sockaddr_in6 *)info.rti_info[RTAX_NETMASK];
713         if (!sin)
714                 sin = &null_sin;
715         printf(" prefixlen %d ", prefix(&sin->sin6_addr,
716                 sizeof(struct in6_addr)));
717
718         putchar('\n');
719 }
720 #endif /*INET6*/
721
722 /*ARGSUSED*/
723 void
724 ether_status(dummy)
725         int dummy;
726 {
727         char *cp;
728         int n;
729
730         dummy = 0;      /*fool gcc*/
731
732         cp = (char *)LLADDR(sdl);
733         if ((n = sdl->sdl_alen) > 0) {
734                 if (sdl->sdl_type == IFT_ETHER)
735                         printf ("\tether ");
736                 else
737                         printf ("\tlladdr ");
738                 while (--n >= 0)
739                         printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' ');
740                 putchar('\n');
741         }
742 }
743
744 void
745 Perror(cmd)
746         char *cmd;
747 {
748         switch (errno) {
749
750         case ENXIO:
751                 errx(1, "%s: no such interface", cmd);
752                 break;
753
754         case EPERM:
755                 errx(1, "%s: permission denied", cmd);
756                 break;
757
758         default:
759                 err(1, "%s", cmd);
760         }
761 }
762
763 #define SIN(x) ((struct sockaddr_in *) &(x))
764 struct sockaddr_in *sintab[] = {
765 SIN(addreq.ifra_addr), SIN(addreq.ifra_dstaddr)};
766
767 void
768 in_getaddr(s, which)
769         char *s;
770         int which;
771 {
772         register struct sockaddr_in *sin = sintab[which];
773         struct hostent *hp;
774         struct netent *np;
775
776         sin->sin_len = sizeof(*sin);
777         sin->sin_family = AF_INET;
778
779         if (inet_aton(s, &sin->sin_addr))
780                 ;
781         else if ((hp = gethostbyname(s)) != NULL)
782                 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
783         else if ((np = getnetbyname(s)) != NULL)
784                 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
785         else
786                 errx(1, "%s: bad value", s);
787 }
788
789 #ifdef INET6
790 #define SIN6(x) ((struct sockaddr_in6 *) &(x))
791 struct sockaddr_in6 *sin6tab[] = {
792 SIN6(in6_addreq.ifra_addr), SIN6(in6_addreq.ifra_dstaddr)};
793
794 void
795 in6_getaddr(s, which)
796         char *s;
797         int which;
798 {
799         register struct sockaddr_in6 *sin = sin6tab[which];
800
801         sin->sin6_len = sizeof(*sin);
802         sin->sin6_family = AF_INET6;
803
804         if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1)
805                 errx(1, "%s: bad value", s);
806 }
807
808 void
809 in6_getprefix(plen, which)
810         char *plen;
811         int which;
812 {
813         register struct sockaddr_in6 *sin = sin6tab[which];
814         register u_char *cp;
815         int len = atoi(plen);
816
817         if ((len < 0) || (len > 128))
818                 errx(1, "%s: bad value", plen);
819         sin->sin6_len = sizeof(*sin);
820         sin->sin6_family = AF_INET6;
821         if ((len == 0) || (len == 128)) {
822                 memset(&sin->sin6_addr, -1, sizeof(struct in6_addr));
823                 return;
824         }
825         for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8)
826                 *cp++ = -1;
827         *cp = (-1) << (8 - len);
828 }
829 #endif
830
831 /*
832  * Print a value a la the %b format of the kernel's printf
833  */
834 void
835 printb(s, v, bits)
836         char *s;
837         register unsigned int v;
838         register char *bits;
839 {
840         register int i, any = 0;
841         register char c;
842
843         if (bits && *bits == 8)
844                 printf("%s=%o", s, v & 0xffff);
845         else
846                 printf("%s=%x", s, v & 0xffff);
847         bits++;
848         if (bits) {
849                 putchar('<');
850                 while ((i = *bits++) != 0) {
851                         if ((v & (1 << (i-1))) != 0) {
852                                 if (any)
853                                         putchar(',');
854                                 any = 1;
855                                 for (; (c = *bits) > 32; bits++)
856                                         putchar(c);
857                         } else
858                                 for (; *bits > 32; bits++)
859                                         ;
860                 }
861                 putchar('>');
862         }
863 }
864
865 #ifdef INET6
866 int
867 prefix(val, size)
868         void *val;
869         int size;
870 {
871         register u_char *name = (u_char *)val;
872         register 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*/