2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
35 static const char copyright
[] =
36 "@(#) Copyright (c) 1983, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
42 static char sccsid
[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
44 static const char rcsid
[] =
45 "$Id: ifconfig.c,v 1.4 2002/03/05 20:35:12 lindak Exp $";
48 #include <sys/param.h>
49 #include <sys/ioctl.h>
50 #include <sys/socket.h>
51 #include <sys/sysctl.h>
54 #include <net/ethernet.h>
56 #include <net/if_var.h>
57 #include <net/if_dl.h>
58 #include <net/if_types.h>
59 #include <net/route.h>
62 #include <netinet/in.h>
63 #include <netinet/in_var.h>
64 #include <arpa/inet.h>
68 #include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */
76 #include <netns/ns_if.h>
91 /* wrapper for KAME-special getnameinfo() */
92 #ifndef NI_WITHSCOPEID
93 #define NI_WITHSCOPEID 0
96 struct ifreq ifr
, ridreq
;
97 struct ifaliasreq addreq
;
99 struct in6_ifreq in6_ridreq
;
100 struct in6_aliasreq in6_addreq
=
106 { 0, 0, ND6_INFINITE_LIFETIME
, ND6_INFINITE_LIFETIME
} };
108 struct sockaddr_in netmask
;
122 static int ip6lifetime
;
131 char addr_buf
[MAXHOSTNAMELEN
*2 + 1]; /*for getnameinfo()*/
134 void Perror
__P((const char *cmd
));
136 int ifconfig
__P((int argc
, char *const *argv
, const struct afswtch
*afp
));
137 void notealias
__P((const char *, int, int, const struct afswtch
*afp
));
138 void printb
__P((const char *s
, unsigned value
, const char *bits
));
139 void rt_xaddrs
__P((caddr_t
, caddr_t
, struct rt_addrinfo
*));
140 void status
__P((const struct afswtch
*afp
, int addrcount
,
141 struct sockaddr_dl
*sdl
, struct if_msghdr
*ifm
,
142 struct ifa_msghdr
*ifam
));
143 void tunnel_status
__P((int s
));
144 void usage
__P((void));
147 void in6_fillscopeid
__P((struct sockaddr_in6
*sin6
));
148 int prefix
__P((void *, int));
149 static char *sec2str
__P((time_t));
150 int explicit_prefix
= 0;
153 typedef void c_func
__P((const char *cmd
, int arg
, int s
, const struct afswtch
*afp
));
154 typedef void c_func2
__P((const char *arg
, const char *arg2
, int s
, const struct afswtch
*afp
));
155 c_func setifaddr
, setifbroadaddr
, setifdstaddr
, setifnetmask
;
159 c_func setifprefixlen
;
163 c_func2 setip6lifetime
;
166 c_func setifflags
, setifmetric
, setifmtu
, setiflladdr
;
169 #define NEXTARG 0xffffff
170 #define NEXTARG2 0xfffffe
175 int c_parameter
; /* NEXTARG means next argv */
176 void (*c_func
) __P((const char *, int, int, const struct afswtch
*afp
));
177 void (*c_func2
) __P((const char *, const char *, int, const struct afswtch
*afp
));
179 { "up", IFF_UP
, setifflags
} ,
180 { "down", -IFF_UP
, setifflags
},
181 { "arp", -IFF_NOARP
, setifflags
},
182 { "-arp", IFF_NOARP
, setifflags
},
183 { "debug", IFF_DEBUG
, setifflags
},
184 { "-debug", -IFF_DEBUG
, setifflags
},
185 { "add", IFF_UP
, notealias
},
186 { "alias", IFF_UP
, notealias
},
187 { "-alias", -IFF_UP
, notealias
},
188 { "delete", -IFF_UP
, notealias
},
189 { "remove", -IFF_UP
, notealias
},
191 #define EN_SWABIPS 0x1000
192 { "swabips", EN_SWABIPS
, setifflags
},
193 { "-swabips", -EN_SWABIPS
, setifflags
},
195 { "netmask", NEXTARG
, setifnetmask
},
197 { "prefixlen", NEXTARG
, setifprefixlen
},
198 { "anycast", IN6_IFF_ANYCAST
, setip6flags
},
199 { "tentative", IN6_IFF_TENTATIVE
, setip6flags
},
200 { "-tentative", -IN6_IFF_TENTATIVE
, setip6flags
},
201 { "deprecated", IN6_IFF_DEPRECATED
, setip6flags
},
202 { "-deprecated", -IN6_IFF_DEPRECATED
, setip6flags
},
203 { "autoconf", IN6_IFF_AUTOCONF
, setip6flags
},
204 { "-autoconf", -IN6_IFF_AUTOCONF
, setip6flags
},
205 { "pltime", NEXTARG
, setip6pltime
},
206 { "vltime", NEXTARG
, setip6vltime
},
208 { "metric", NEXTARG
, setifmetric
},
209 { "broadcast", NEXTARG
, setifbroadaddr
},
210 { "ipdst", NEXTARG
, setifipdst
},
211 { "tunnel", NEXTARG2
, NULL
, settunnel
},
212 { "deletetunnel", 0, deletetunnel
},
213 { "link0", IFF_LINK0
, setifflags
},
214 { "-link0", -IFF_LINK0
, setifflags
},
215 { "link1", IFF_LINK1
, setifflags
},
216 { "-link1", -IFF_LINK1
, setifflags
},
217 { "link2", IFF_LINK2
, setifflags
},
218 { "-link2", -IFF_LINK2
, setifflags
},
220 { "media", NEXTARG
, setmedia
},
221 { "mediaopt", NEXTARG
, setmediaopt
},
222 { "-mediaopt", NEXTARG
, unsetmediaopt
},
225 { "vlan", NEXTARG
, setvlantag
},
226 { "vlandev", NEXTARG
, setvlandev
},
227 { "-vlandev", NEXTARG
, unsetvlandev
},
230 /* XXX `create' special-cased below */
231 {"create", 0, clone_create
},
232 {"plumb", 0, clone_create
},
235 {"destroy", 0, clone_destroy
},
236 {"unplumb", 0, clone_destroy
},
239 { "ssid", NEXTARG
, set80211ssid
},
240 { "nwid", NEXTARG
, set80211ssid
},
241 { "stationname", NEXTARG
, set80211stationname
},
242 { "station", NEXTARG
, set80211stationname
}, /* BSD/OS */
243 { "channel", NEXTARG
, set80211channel
},
244 { "authmode", NEXTARG
, set80211authmode
},
245 { "powersavemode", NEXTARG
, set80211powersavemode
},
246 { "powersave", 1, set80211powersave
},
247 { "-powersave", 0, set80211powersave
},
248 { "powersavesleep", NEXTARG
, set80211powersavesleep
},
249 { "wepmode", NEXTARG
, set80211wepmode
},
250 { "wep", 1, set80211wep
},
251 { "-wep", 0, set80211wep
},
252 { "weptxkey", NEXTARG
, set80211weptxkey
},
253 { "wepkey", NEXTARG
, set80211wepkey
},
254 { "nwkey", NEXTARG
, set80211nwkey
}, /* NetBSD */
255 { "-nwkey", 0, set80211wep
}, /* NetBSD */
257 { "normal", -IFF_LINK0
, setifflags
},
258 { "compress", IFF_LINK0
, setifflags
},
259 { "noicmp", IFF_LINK1
, setifflags
},
260 { "mtu", NEXTARG
, setifmtu
},
261 { "lladdr", NEXTARG
, setiflladdr
},
263 { 0, 0, setifdstaddr
},
267 * XNS support liberally adapted from code written at the University of
268 * Maryland principally by James O'Toole and Chris Torek.
270 typedef void af_status
__P((int, struct rt_addrinfo
*));
271 typedef void af_getaddr
__P((const char *, int));
272 typedef void af_getprefix
__P((const char *, int));
274 af_status in_status
, at_status
, ether_status
;
275 af_getaddr in_getaddr
, at_getaddr
, ether_getaddr
;
279 af_status in6_status
;
280 af_getaddr in6_getaddr
;
281 af_getprefix in6_getprefix
;
284 af_status xns_status
;
285 af_getaddr xns_getaddr
;
288 /* Known address families */
293 af_status
*af_status
;
294 af_getaddr
*af_getaddr
;
295 af_getprefix
*af_getprefix
;
301 #define C(x) ((caddr_t) &x)
302 { "inet", AF_INET
, in_status
, in_getaddr
, NULL
,
303 SIOCDIFADDR
, SIOCAIFADDR
, C(ridreq
), C(addreq
) },
305 { "inet6", AF_INET6
, in6_status
, in6_getaddr
, in6_getprefix
,
306 SIOCDIFADDR_IN6
, SIOCAIFADDR_IN6
,
307 C(in6_ridreq
), C(in6_addreq
) },
310 { "ns", AF_NS
, xns_status
, xns_getaddr
, NULL
,
311 SIOCDIFADDR
, SIOCAIFADDR
, C(ridreq
), C(addreq
) },
313 { "ether", AF_LINK
, ether_status
, ether_getaddr
, NULL
,
314 0, SIOCSIFLLADDR
, NULL
, C(ridreq
) },
315 #if 0 /* XXX conflicts with the media command */
317 { "media", AF_UNSPEC
, media_status
, NULL
, NULL
, }, /* XXX not real!! */
320 { "vlan", AF_UNSPEC
, vlan_status
, NULL
, NULL
, }, /* XXX not real!! */
323 { "ieee80211", AF_UNSPEC
, ieee80211_status
, NULL
, NULL
, }, /* XXX not real!! */
330 * Expand the compacted form of addresses as returned via the
331 * configuration read via sysctl().
335 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
336 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
339 rt_xaddrs(cp
, cplim
, rtinfo
)
341 struct rt_addrinfo
*rtinfo
;
346 memset(rtinfo
->rti_info
, 0, sizeof(rtinfo
->rti_info
));
347 for (i
= 0; (i
< RTAX_MAX
) && (cp
< cplim
); i
++) {
348 if ((rtinfo
->rti_addrs
& (1 << i
)) == 0)
350 rtinfo
->rti_info
[i
] = sa
= (struct sockaddr
*)cp
;
360 fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
361 "usage: ifconfig interface address_family [address [dest_address]]",
364 " ifconfig interface create",
365 " ifconfig -a [-d] [-m] [-u] [address_family]",
366 " ifconfig -l [-d] [-u] [address_family]",
367 " ifconfig [-d] [-m] [-u]");
369 fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
370 "usage: ifconfig [-L] interface address_family [address [dest_address]]",
373 " ifconfig interface create",
374 " ifconfig -a [-L] [-d] [-m] [-u] [address_family]",
375 " ifconfig -l [-d] [-u] [address_family]",
376 " ifconfig [-L] [-d] [-m] [-u]");
387 int all
, namesonly
, downonly
, uponly
;
388 int foundit
= 0, need_nl
= 0;
389 const struct afswtch
*afp
= 0;
391 struct if_msghdr
*ifm
, *nextifm
;
392 struct ifa_msghdr
*ifam
;
393 struct sockaddr_dl
*sdl
;
394 char *buf
, *lim
, *next
;
400 /* Parse leading line options */
401 all
= downonly
= uponly
= namesonly
= 0;
402 while ((c
= getopt(argc
, argv
, "adlmu"
408 case 'a': /* scan all interfaces */
411 case 'd': /* restrict scan to "down" interfaces */
414 case 'l': /* scan interface names only */
417 case 'm': /* show media choices in status */
420 case 'u': /* restrict scan to "up" interfaces */
425 ip6lifetime
++; /* print IPv6 address lifetime */
436 /* -l cannot be used with -a or -m */
437 if (namesonly
&& (all
|| supmedia
))
441 if (uponly
&& downonly
)
444 /* no arguments is equivalent to '-a' */
445 if (!namesonly
&& argc
< 1)
448 /* -a and -l allow an address family arg to limit the output */
449 if (all
|| namesonly
) {
454 for (afp
= afs
; afp
->af_name
; afp
++)
455 if (strcmp(afp
->af_name
, *argv
) == 0) {
459 if (afp
->af_name
== NULL
)
461 /* leave with afp non-zero */
464 /* not listing, need an argument */
468 strncpy(name
, *argv
, sizeof(name
));
472 * NOTE: We must special-case the `create' command right
473 * here as we would otherwise fail when trying to find
476 if (argc
> 0 && (strcmp(argv
[0], "create") == 0 ||
477 strcmp(argv
[0], "plumb") == 0)) {
487 /* Check for address family */
489 for (afp
= afs
; afp
->af_name
; afp
++)
490 if (strcmp(afp
->af_name
, *argv
) == 0) {
494 if (afp
->af_name
== NULL
)
495 afp
= NULL
; /* not a family, NULL */
501 mib
[3] = 0; /* address family */
502 mib
[4] = NET_RT_IFLIST
;
505 /* if particular family specified, only ask about it */
509 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
510 errx(1, "iflist-sysctl-estimate");
511 if ((buf
= malloc(needed
)) == NULL
)
513 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
514 errx(1, "actual retrieval of interface table");
520 ifm
= (struct if_msghdr
*)next
;
522 if (ifm
->ifm_type
== RTM_IFINFO
) {
523 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
524 flags
= ifm
->ifm_flags
;
526 fprintf(stderr
, "out of sync parsing NET_RT_IFLIST\n");
527 fprintf(stderr
, "expected %d, got %d\n", RTM_IFINFO
,
529 fprintf(stderr
, "msglen = %d\n", ifm
->ifm_msglen
);
530 fprintf(stderr
, "buf:%p, next:%p, lim:%p\n", buf
, next
,
535 next
+= ifm
->ifm_msglen
;
540 nextifm
= (struct if_msghdr
*)next
;
542 if (nextifm
->ifm_type
!= RTM_NEWADDR
)
546 ifam
= (struct ifa_msghdr
*)nextifm
;
549 next
+= nextifm
->ifm_msglen
;
552 if (all
|| namesonly
) {
554 if ((flags
& IFF_UP
) == 0)
555 continue; /* not up */
558 continue; /* not down */
559 strncpy(name
, sdl
->sdl_data
, sdl
->sdl_nlen
);
560 name
[sdl
->sdl_nlen
] = '\0';
563 afp
->af_status
!= ether_status
||
564 sdl
->sdl_type
== IFT_ETHER
) {
573 if (strlen(name
) != sdl
->sdl_nlen
)
574 continue; /* not same len */
575 if (strncmp(name
, sdl
->sdl_data
, sdl
->sdl_nlen
) != 0)
576 continue; /* not same name */
580 ifconfig(argc
, argv
, afp
);
582 status(afp
, addrcount
, sdl
, ifm
, ifam
);
584 if (all
== 0 && namesonly
== 0) {
585 foundit
++; /* flag it as 'done' */
591 if (namesonly
&& need_nl
> 0)
594 if (all
== 0 && namesonly
== 0 && foundit
== 0)
595 errx(1, "interface %s does not exist", name
);
603 ifconfig(argc
, argv
, afp
)
606 const struct afswtch
*afp
;
612 ifr
.ifr_addr
.sa_family
= afp
->af_af
== AF_LINK
? AF_INET
: afp
->af_af
;
613 strncpy(ifr
.ifr_name
, name
, sizeof ifr
.ifr_name
);
615 if ((s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0)) < 0)
619 register const struct cmd
*p
;
621 for (p
= cmds
; p
->c_name
; p
++)
622 if (strcmp(*argv
, p
->c_name
) == 0)
624 if (p
->c_name
== 0 && setaddr
)
625 p
++; /* got src, do dst */
626 if (p
->c_func
|| p
->c_func2
) {
627 if (p
->c_parameter
== NEXTARG
) {
629 errx(1, "'%s' requires argument",
631 (*p
->c_func
)(argv
[1], 0, s
, afp
);
633 } else if (p
->c_parameter
== NEXTARG2
) {
635 errx(1, "'%s' requires 2 arguments",
637 (*p
->c_func2
)(argv
[1], argv
[2], s
, afp
);
638 argc
-= 2, argv
+= 2;
640 (*p
->c_func
)(*argv
, p
->c_parameter
, s
, afp
);
645 if (ifr
.ifr_addr
.sa_family
== AF_INET6
&& explicit_prefix
== 0) {
646 /* Aggregatable address architecture defines all prefixes
647 are 64. So, it is convenient to set prefixlen to 64 if
648 it is not specified. */
649 setifprefixlen("64", 0, s
, afp
);
650 /* in6_getprefix("64", MASK) if MASK is available here... */
654 if (setipdst
&& ifr
.ifr_addr
.sa_family
== AF_NS
) {
656 int size
= sizeof(rq
);
658 rq
.rq_ns
= addreq
.ifra_addr
;
659 rq
.rq_ip
= addreq
.ifra_dstaddr
;
661 if (setsockopt(s
, 0, SO_NSIP_ROUTE
, &rq
, size
) < 0)
662 Perror("Encapsulation Routing");
666 if (afp
->af_ridreq
== NULL
|| afp
->af_difaddr
== 0) {
667 warnx("interface %s cannot change %s addresses!",
674 strncpy(afp
->af_ridreq
, name
, sizeof ifr
.ifr_name
);
675 if ((ret
= ioctl(s
, afp
->af_difaddr
, afp
->af_ridreq
)) < 0) {
676 if (errno
== EADDRNOTAVAIL
&& (doalias
>= 0)) {
677 /* means no previous address for interface */
679 Perror("ioctl (SIOCDIFADDR)");
683 if (afp
->af_addreq
== NULL
|| afp
->af_aifaddr
== 0) {
684 warnx("interface %s cannot change %s addresses!",
689 if (newaddr
&& (setaddr
|| setmask
)) {
690 strncpy(afp
->af_addreq
, name
, sizeof ifr
.ifr_name
);
691 if (ioctl(s
, afp
->af_aifaddr
, afp
->af_addreq
) < 0)
692 Perror("ioctl (SIOCAIFADDR)");
704 setifaddr(addr
, param
, s
, afp
)
708 const struct afswtch
*afp
;
710 if (*afp
->af_getaddr
== NULL
)
713 * Delay the ioctl to set the interface addr until flags are all set.
714 * The address interpretation may depend on the flags,
715 * and the flags may change when the address is set.
718 if (doalias
== 0 && afp
->af_af
!= AF_LINK
)
720 (*afp
->af_getaddr
)(addr
, (doalias
>= 0 ? ADDR
: RIDADDR
));
724 settunnel(src
, dst
, s
, afp
)
725 const char *src
, *dst
;
727 const struct afswtch
*afp
;
729 struct addrinfo hints
, *srcres
, *dstres
;
730 struct ifaliasreq addreq
;
733 struct in6_aliasreq in6_addreq
;
736 memset(&hints
, 0, sizeof(hints
));
737 hints
.ai_family
= afp
->af_af
;
739 if ((ecode
= getaddrinfo(src
, NULL
, NULL
, &srcres
)) != 0)
740 errx(1, "error in parsing address string: %s",
741 gai_strerror(ecode
));
743 if ((ecode
= getaddrinfo(dst
, NULL
, NULL
, &dstres
)) != 0)
744 errx(1, "error in parsing address string: %s",
745 gai_strerror(ecode
));
747 if (srcres
->ai_addr
->sa_family
!= dstres
->ai_addr
->sa_family
)
749 "source and destination address families do not match");
751 switch (srcres
->ai_addr
->sa_family
) {
753 memset(&addreq
, 0, sizeof(addreq
));
754 strncpy(addreq
.ifra_name
, name
, IFNAMSIZ
);
755 memcpy(&addreq
.ifra_addr
, srcres
->ai_addr
,
756 srcres
->ai_addr
->sa_len
);
757 memcpy(&addreq
.ifra_dstaddr
, dstres
->ai_addr
,
758 dstres
->ai_addr
->sa_len
);
760 if (ioctl(s
, SIOCSIFPHYADDR
, &addreq
) < 0)
761 warn("SIOCSIFPHYADDR");
766 memset(&in6_addreq
, 0, sizeof(in6_addreq
));
767 strncpy(in6_addreq
.ifra_name
, name
, IFNAMSIZ
);
768 memcpy(&in6_addreq
.ifra_addr
, srcres
->ai_addr
,
769 srcres
->ai_addr
->sa_len
);
770 memcpy(&in6_addreq
.ifra_dstaddr
, dstres
->ai_addr
,
771 dstres
->ai_addr
->sa_len
);
773 if (ioctl(s
, SIOCSIFPHYADDR_IN6
, &in6_addreq
) < 0)
774 warn("SIOCSIFPHYADDR_IN6");
779 warn("address family not supported");
782 freeaddrinfo(srcres
);
783 freeaddrinfo(dstres
);
788 deletetunnel(vname
, param
, s
, afp
)
792 const struct afswtch
*afp
;
795 if (ioctl(s
, SIOCDIFPHYADDR
, &ifr
) < 0)
796 err(1, "SIOCDIFPHYADDR");
800 setifnetmask(addr
, dummy
, s
, afp
)
804 const struct afswtch
*afp
;
806 if (*afp
->af_getaddr
== NULL
)
809 (*afp
->af_getaddr
)(addr
, MASK
);
814 setifprefixlen(addr
, dummy
, s
, afp
)
818 const struct afswtch
*afp
;
820 if (*afp
->af_getprefix
)
821 (*afp
->af_getprefix
)(addr
, MASK
);
826 setip6flags(dummyaddr
, flag
, dummysoc
, afp
)
827 const char *dummyaddr
;
830 const struct afswtch
*afp
;
832 if (afp
->af_af
!= AF_INET6
)
833 err(1, "address flags can be set only for inet6 addresses");
836 in6_addreq
.ifra_flags
&= ~(-flag
);
838 in6_addreq
.ifra_flags
|= flag
;
842 setip6pltime(seconds
, dummy
, s
, afp
)
846 const struct afswtch
*afp
;
848 setip6lifetime("pltime", seconds
, s
, afp
);
852 setip6vltime(seconds
, dummy
, s
, afp
)
856 const struct afswtch
*afp
;
858 setip6lifetime("vltime", seconds
, s
, afp
);
862 setip6lifetime(cmd
, val
, s
, afp
)
866 const struct afswtch
*afp
;
872 newval
= (time_t)strtoul(val
, &ep
, 0);
874 errx(1, "invalid %s", cmd
);
875 if (afp
->af_af
!= AF_INET6
)
876 errx(1, "%s not allowed for the AF", cmd
);
877 if (strcmp(cmd
, "vltime") == 0) {
878 in6_addreq
.ifra_lifetime
.ia6t_expire
= t
+ newval
;
879 in6_addreq
.ifra_lifetime
.ia6t_vltime
= newval
;
880 } else if (strcmp(cmd
, "pltime") == 0) {
881 in6_addreq
.ifra_lifetime
.ia6t_preferred
= t
+ newval
;
882 in6_addreq
.ifra_lifetime
.ia6t_pltime
= newval
;
888 setifbroadaddr(addr
, dummy
, s
, afp
)
892 const struct afswtch
*afp
;
895 (*afp
->af_getaddr
)(addr
, DSTADDR
);
899 setifipdst(addr
, dummy
, s
, afp
)
903 const struct afswtch
*afp
;
905 in_getaddr(addr
, DSTADDR
);
910 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
913 notealias(addr
, param
, s
, afp
)
917 const struct afswtch
*afp
;
919 if (setaddr
&& doalias
== 0 && param
< 0)
920 bcopy((caddr_t
)rqtosa(af_addreq
),
921 (caddr_t
)rqtosa(af_ridreq
),
922 rqtosa(af_addreq
)->sa_len
);
933 setifdstaddr(addr
, param
, s
, afp
)
937 const struct afswtch
*afp
;
939 if (*afp
->af_getaddr
== NULL
)
941 (*afp
->af_getaddr
)(addr
, DSTADDR
);
945 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
946 * of the ifreq structure, which may confuse other parts of ifconfig.
947 * Make a private copy so we can avoid that.
950 setifflags(vname
, value
, s
, afp
)
954 const struct afswtch
*afp
;
958 bcopy((char *)&ifr
, (char *)&my_ifr
, sizeof(struct ifreq
));
960 if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
)&my_ifr
) < 0) {
961 Perror("ioctl (SIOCGIFFLAGS)");
964 strncpy(my_ifr
.ifr_name
, name
, sizeof (my_ifr
.ifr_name
));
965 flags
= my_ifr
.ifr_flags
;
972 my_ifr
.ifr_flags
= flags
;
973 if (ioctl(s
, SIOCSIFFLAGS
, (caddr_t
)&my_ifr
) < 0)
978 setifmetric(val
, dummy
, s
, afp
)
982 const struct afswtch
*afp
;
984 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
985 ifr
.ifr_metric
= atoi(val
);
986 if (ioctl(s
, SIOCSIFMETRIC
, (caddr_t
)&ifr
) < 0)
987 warn("ioctl (set metric)");
991 setifmtu(val
, dummy
, s
, afp
)
995 const struct afswtch
*afp
;
997 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
998 ifr
.ifr_mtu
= atoi(val
);
999 if (ioctl(s
, SIOCSIFMTU
, (caddr_t
)&ifr
) < 0)
1000 warn("ioctl (set mtu)");
1004 setiflladdr(val
, dummy
, s
, afp
)
1008 const struct afswtch
*afp
;
1010 struct ether_addr
*ea
;
1012 ea
= ether_aton(val
);
1014 warn("malformed link-level address");
1017 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
1018 ifr
.ifr_addr
.sa_len
= ETHER_ADDR_LEN
;
1019 ifr
.ifr_addr
.sa_family
= AF_LINK
;
1020 bcopy(ea
, ifr
.ifr_addr
.sa_data
, ETHER_ADDR_LEN
);
1021 if (ioctl(s
, SIOCSIFLLADDR
, (caddr_t
)&ifr
) < 0)
1022 warn("ioctl (set lladdr)");
1028 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
1029 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
1033 * Print the status of the interface. If an address family was
1034 * specified, show it and it only; otherwise, show them all.
1037 status(afp
, addrcount
, sdl
, ifm
, ifam
)
1038 const struct afswtch
*afp
;
1040 struct sockaddr_dl
*sdl
;
1041 struct if_msghdr
*ifm
;
1042 struct ifa_msghdr
*ifam
;
1044 const struct afswtch
*p
= NULL
;
1045 struct rt_addrinfo info
;
1055 ifr
.ifr_addr
.sa_family
= afp
->af_af
== AF_LINK
? AF_INET
: afp
->af_af
;
1056 strncpy(ifr
.ifr_name
, name
, sizeof ifr
.ifr_name
);
1058 if ((s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0)) < 0)
1062 * XXX is it we are doing a SIOCGIFMETRIC etc for one family.
1063 * is it possible that the metric and mtu can be different for
1064 * each family? If so, we have a format problem, because the
1065 * metric and mtu is printed on the global the flags line.
1067 if (ioctl(s
, SIOCGIFMETRIC
, (caddr_t
)&ifr
) < 0)
1068 warn("ioctl (SIOCGIFMETRIC)");
1070 metric
= ifr
.ifr_metric
;
1072 if (ioctl(s
, SIOCGIFMTU
, (caddr_t
)&ifr
) < 0)
1073 warn("ioctl (SIOCGIFMTU)");
1077 printf("%s: ", name
);
1078 printb("flags", flags
, IFFBITS
);
1080 printf(" metric %d", metric
);
1082 printf(" mtu %d", mtu
);
1087 while (addrcount
> 0) {
1089 info
.rti_addrs
= ifam
->ifam_addrs
;
1091 /* Expand the compacted addresses */
1092 rt_xaddrs((char *)(ifam
+ 1), ifam
->ifam_msglen
+ (char *)ifam
,
1096 if (afp
->af_af
== info
.rti_info
[RTAX_IFA
]->sa_family
) {
1098 (*p
->af_status
)(s
, &info
);
1100 } else for (p
= afs
; p
->af_name
; p
++) {
1101 if (p
->af_af
== info
.rti_info
[RTAX_IFA
]->sa_family
)
1102 (*p
->af_status
)(s
, &info
);
1105 ifam
= (struct ifa_msghdr
*)((char *)ifam
+ ifam
->ifam_msglen
);
1107 if (allfamilies
|| afp
->af_status
== ether_status
)
1108 ether_status(s
, (struct rt_addrinfo
*)sdl
);
1110 if (allfamilies
|| afp
->af_status
== media_status
)
1111 media_status(s
, NULL
);
1114 if (allfamilies
|| afp
->af_status
== vlan_status
)
1115 vlan_status(s
, NULL
);
1117 #ifdef USE_IEEE80211
1118 if (allfamilies
|| afp
->af_status
== ieee80211_status
)
1119 ieee80211_status(s
, NULL
);
1121 strncpy(ifs
.ifs_name
, name
, sizeof ifs
.ifs_name
);
1122 if (ioctl(s
, SIOCGIFSTATUS
, &ifs
) == 0)
1123 printf("%s", ifs
.ascii
);
1125 if (!allfamilies
&& !p
&& afp
->af_status
!= media_status
&&
1126 afp
->af_status
!= ether_status
1128 && afp
->af_status
!= vlan_status
1131 warnx("%s has no %s interface address!", name
, afp
->af_name
);
1141 char psrcaddr
[NI_MAXHOST
];
1142 char pdstaddr
[NI_MAXHOST
];
1143 u_long srccmd
, dstcmd
;
1145 const char *ver
= "";
1146 #ifdef NI_WITHSCOPEID
1147 const int niflag
= NI_NUMERICHOST
| NI_WITHSCOPEID
;
1149 const int niflag
= NI_NUMERICHOST
;
1152 struct in6_ifreq in6_ifr
;
1156 psrcaddr
[0] = pdstaddr
[0] = '\0';
1159 memset(&in6_ifr
, 0, sizeof(in6_ifr
));
1160 strncpy(in6_ifr
.ifr_name
, name
, IFNAMSIZ
);
1161 s6
= socket(AF_INET6
, SOCK_DGRAM
, 0);
1163 srccmd
= SIOCGIFPSRCADDR
;
1164 dstcmd
= SIOCGIFPDSTADDR
;
1168 srccmd
= SIOCGIFPSRCADDR_IN6
;
1169 dstcmd
= SIOCGIFPDSTADDR_IN6
;
1170 ifrp
= (struct ifreq
*)&in6_ifr
;
1173 srccmd
= SIOCGIFPSRCADDR
;
1174 dstcmd
= SIOCGIFPDSTADDR
;
1178 if (ioctl(s
, srccmd
, (caddr_t
)ifrp
) < 0)
1181 if (ifrp
->ifr_addr
.sa_family
== AF_INET6
)
1182 in6_fillscopeid((struct sockaddr_in6
*)&ifrp
->ifr_addr
);
1184 getnameinfo(&ifrp
->ifr_addr
, ifrp
->ifr_addr
.sa_len
,
1185 psrcaddr
, sizeof(psrcaddr
), 0, 0, niflag
);
1187 if (ifrp
->ifr_addr
.sa_family
== AF_INET6
)
1191 if (ioctl(s
, dstcmd
, (caddr_t
)ifrp
) < 0)
1194 if (ifrp
->ifr_addr
.sa_family
== AF_INET6
)
1195 in6_fillscopeid((struct sockaddr_in6
*)&ifrp
->ifr_addr
);
1197 getnameinfo(&ifrp
->ifr_addr
, ifrp
->ifr_addr
.sa_len
,
1198 pdstaddr
, sizeof(pdstaddr
), 0, 0, niflag
);
1200 printf("\ttunnel inet%s %s --> %s\n", ver
,
1201 psrcaddr
, pdstaddr
);
1207 struct rt_addrinfo
* info
;
1209 struct sockaddr_in
*sin
, null_sin
;
1211 memset(&null_sin
, 0, sizeof(null_sin
));
1213 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_IFA
];
1214 printf("\tinet %s ", inet_ntoa(sin
->sin_addr
));
1216 if (flags
& IFF_POINTOPOINT
) {
1217 /* note RTAX_BRD overlap with IFF_BROADCAST */
1218 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_BRD
];
1221 printf("--> %s ", inet_ntoa(sin
->sin_addr
));
1224 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_NETMASK
];
1227 printf("netmask 0x%lx ", (unsigned long)ntohl(sin
->sin_addr
.s_addr
));
1229 if (flags
& IFF_BROADCAST
) {
1230 /* note RTAX_BRD overlap with IFF_POINTOPOINT */
1231 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_BRD
];
1232 if (sin
&& sin
->sin_addr
.s_addr
!= 0)
1233 printf("broadcast %s", inet_ntoa(sin
->sin_addr
));
1240 in6_fillscopeid(sin6
)
1241 struct sockaddr_in6
*sin6
;
1243 #if defined(__KAME__) && defined(KAME_SCOPEID)
1244 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
)) {
1245 sin6
->sin6_scope_id
=
1246 ntohs(*(u_int16_t
*)&sin6
->sin6_addr
.s6_addr
[2]);
1247 sin6
->sin6_addr
.s6_addr
[2] = sin6
->sin6_addr
.s6_addr
[3] = 0;
1255 struct rt_addrinfo
* info
;
1257 struct sockaddr_in6
*sin
, null_sin
;
1258 struct in6_ifreq ifr6
;
1261 struct in6_addrlifetime lifetime
;
1262 time_t t
= time(NULL
);
1266 memset(&null_sin
, 0, sizeof(null_sin
));
1268 sin
= (struct sockaddr_in6
*)info
->rti_info
[RTAX_IFA
];
1269 strncpy(ifr6
.ifr_name
, ifr
.ifr_name
, sizeof(ifr
.ifr_name
));
1270 if ((s6
= socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0) {
1271 perror("ifconfig: socket");
1274 ifr6
.ifr_addr
= *sin
;
1275 if (ioctl(s6
, SIOCGIFAFLAG_IN6
, &ifr6
) < 0) {
1276 perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)");
1280 flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
1281 memset(&lifetime
, 0, sizeof(lifetime
));
1282 ifr6
.ifr_addr
= *sin
;
1283 if (ioctl(s6
, SIOCGIFALIFETIME_IN6
, &ifr6
) < 0) {
1284 perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)");
1288 lifetime
= ifr6
.ifr_ifru
.ifru_lifetime
;
1291 /* XXX: embedded link local addr check */
1292 if (IN6_IS_ADDR_LINKLOCAL(&sin
->sin6_addr
) &&
1293 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] != 0) {
1296 index
= *(u_short
*)&sin
->sin6_addr
.s6_addr
[2];
1297 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] = 0;
1298 if (sin
->sin6_scope_id
== 0)
1299 sin
->sin6_scope_id
= ntohs(index
);
1301 scopeid
= sin
->sin6_scope_id
;
1303 error
= getnameinfo((struct sockaddr
*)sin
, sin
->sin6_len
, addr_buf
,
1304 sizeof(addr_buf
), NULL
, 0,
1305 NI_NUMERICHOST
|NI_WITHSCOPEID
);
1307 inet_ntop(AF_INET6
, &sin
->sin6_addr
, addr_buf
,
1309 printf("\tinet6 %s ", addr_buf
);
1311 if (flags
& IFF_POINTOPOINT
) {
1312 /* note RTAX_BRD overlap with IFF_BROADCAST */
1313 sin
= (struct sockaddr_in6
*)info
->rti_info
[RTAX_BRD
];
1315 * some of the interfaces do not have valid destination
1318 if (sin
&& sin
->sin6_family
== AF_INET6
) {
1321 /* XXX: embedded link local addr check */
1322 if (IN6_IS_ADDR_LINKLOCAL(&sin
->sin6_addr
) &&
1323 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] != 0) {
1326 index
= *(u_short
*)&sin
->sin6_addr
.s6_addr
[2];
1327 *(u_short
*)&sin
->sin6_addr
.s6_addr
[2] = 0;
1328 if (sin
->sin6_scope_id
== 0)
1329 sin
->sin6_scope_id
= ntohs(index
);
1332 error
= getnameinfo((struct sockaddr
*)sin
,
1333 sin
->sin6_len
, addr_buf
,
1334 sizeof(addr_buf
), NULL
, 0,
1335 NI_NUMERICHOST
|NI_WITHSCOPEID
);
1337 inet_ntop(AF_INET6
, &sin
->sin6_addr
, addr_buf
,
1339 printf("--> %s ", addr_buf
);
1343 sin
= (struct sockaddr_in6
*)info
->rti_info
[RTAX_NETMASK
];
1346 printf("prefixlen %d ", prefix(&sin
->sin6_addr
,
1347 sizeof(struct in6_addr
)));
1349 if ((flags6
& IN6_IFF_ANYCAST
) != 0)
1351 if ((flags6
& IN6_IFF_TENTATIVE
) != 0)
1352 printf("tentative ");
1353 if ((flags6
& IN6_IFF_DUPLICATED
) != 0)
1354 printf("duplicated ");
1355 if ((flags6
& IN6_IFF_DETACHED
) != 0)
1356 printf("detached ");
1357 if ((flags6
& IN6_IFF_DEPRECATED
) != 0)
1358 printf("deprecated ");
1359 if ((flags6
& IN6_IFF_AUTOCONF
) != 0)
1360 printf("autoconf ");
1361 if ((flags6
& IN6_IFF_TEMPORARY
) != 0)
1362 printf("temporary ");
1365 printf("scopeid 0x%x ", scopeid
);
1367 if (ip6lifetime
&& (lifetime
.ia6t_preferred
|| lifetime
.ia6t_expire
)) {
1369 if (lifetime
.ia6t_preferred
) {
1370 printf("%s ", lifetime
.ia6t_preferred
< t
1371 ? "0" : sec2str(lifetime
.ia6t_preferred
- t
));
1376 if (lifetime
.ia6t_expire
) {
1377 printf("%s ", lifetime
.ia6t_expire
< t
1378 ? "0" : sec2str(lifetime
.ia6t_expire
- t
));
1391 struct rt_addrinfo
* info
;
1393 struct sockaddr_ns
*sns
, null_sns
;
1395 memset(&null_sns
, 0, sizeof(null_sns
));
1397 sns
= (struct sockaddr_ns
*)info
->rti_info
[RTAX_IFA
];
1398 printf("\tns %s ", ns_ntoa(sns
->sns_addr
));
1400 if (flags
& IFF_POINTOPOINT
) {
1401 sns
= (struct sockaddr_ns
*)info
->rti_info
[RTAX_BRD
];
1404 printf("--> %s ", ns_ntoa(sns
->sns_addr
));
1414 ether_status(s
, info
)
1416 struct rt_addrinfo
*info
;
1420 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)info
;
1422 cp
= (char *)LLADDR(sdl
);
1423 if ((n
= sdl
->sdl_alen
) > 0) {
1424 if (sdl
->sdl_type
== IFT_ETHER
)
1425 printf ("\tether ");
1427 printf ("\tlladdr ");
1429 printf("%02x%c",*cp
++ & 0xff, n
>0? ':' : ' ');
1441 errx(1, "%s: no such interface", cmd
);
1445 errx(1, "%s: permission denied", cmd
);
1453 #define SIN(x) ((struct sockaddr_in *) &(x))
1454 struct sockaddr_in
*sintab
[] = {
1455 SIN(ridreq
.ifr_addr
), SIN(addreq
.ifra_addr
),
1456 SIN(addreq
.ifra_mask
), SIN(addreq
.ifra_broadaddr
)};
1459 in_getaddr(s
, which
)
1463 register struct sockaddr_in
*sin
= sintab
[which
];
1467 sin
->sin_len
= sizeof(*sin
);
1469 sin
->sin_family
= AF_INET
;
1471 if (which
== ADDR
) {
1474 if((p
= strrchr(s
, '/')) != NULL
) {
1475 /* address is `name/masklen' */
1478 struct sockaddr_in
*min
= sintab
[MASK
];
1480 ret
= sscanf(p
+1, "%u", &masklen
);
1481 if(ret
!= 1 || (masklen
< 0 || masklen
> 32)) {
1483 errx(1, "%s: bad value", s
);
1485 min
->sin_len
= sizeof(*min
);
1486 min
->sin_addr
.s_addr
= htonl(~((1LL << (32 - masklen
)) - 1) &
1491 if (inet_aton(s
, &sin
->sin_addr
))
1493 if ((hp
= gethostbyname(s
)) != 0)
1494 bcopy(hp
->h_addr
, (char *)&sin
->sin_addr
,
1495 MIN(hp
->h_length
, sizeof(sin
->sin_addr
)));
1496 else if ((np
= getnetbyname(s
)) != 0)
1497 sin
->sin_addr
= inet_makeaddr(np
->n_net
, INADDR_ANY
);
1499 errx(1, "%s: bad value", s
);
1503 #define SIN6(x) ((struct sockaddr_in6 *) &(x))
1504 struct sockaddr_in6
*sin6tab
[] = {
1505 SIN6(in6_ridreq
.ifr_addr
), SIN6(in6_addreq
.ifra_addr
),
1506 SIN6(in6_addreq
.ifra_prefixmask
), SIN6(in6_addreq
.ifra_dstaddr
)};
1509 in6_getaddr(s
, which
)
1513 register struct sockaddr_in6
*sin
= sin6tab
[which
];
1514 struct addrinfo hints
, *res
;
1519 sin
->sin6_len
= sizeof(*sin
);
1521 sin
->sin6_family
= AF_INET6
;
1523 if (which
== ADDR
) {
1525 if((p
= strrchr(s
, '/')) != NULL
) {
1527 in6_getprefix(p
+ 1, MASK
);
1528 explicit_prefix
= 1;
1532 if (sin
->sin6_family
== AF_INET6
) {
1533 bzero(&hints
, sizeof(struct addrinfo
));
1534 hints
.ai_family
= AF_INET6
;
1535 error
= getaddrinfo(s
, NULL
, &hints
, &res
);
1538 if (inet_pton(AF_INET6
, s
, &sin
->sin6_addr
) != 1)
1539 errx(1, "%s: bad value", s
);
1541 bcopy(res
->ai_addr
, sin
, res
->ai_addrlen
);
1545 in6_getprefix(plen
, which
)
1549 register struct sockaddr_in6
*sin
= sin6tab
[which
];
1550 register u_char
*cp
;
1551 int len
= atoi(plen
);
1553 if ((len
< 0) || (len
> 128))
1554 errx(1, "%s: bad value", plen
);
1555 sin
->sin6_len
= sizeof(*sin
);
1557 sin
->sin6_family
= AF_INET6
;
1558 if ((len
== 0) || (len
== 128)) {
1559 memset(&sin
->sin6_addr
, 0xff, sizeof(struct in6_addr
));
1562 memset((void *)&sin
->sin6_addr
, 0x00, sizeof(sin
->sin6_addr
));
1563 for (cp
= (u_char
*)&sin
->sin6_addr
; len
> 7; len
-= 8)
1565 *cp
= 0xff << (8 - len
);
1570 * Print a value a la the %b format of the kernel's printf
1575 register unsigned v
;
1576 register const char *bits
;
1578 register int i
, any
= 0;
1581 if (bits
&& *bits
== 8)
1582 printf("%s=%o", s
, v
);
1584 printf("%s=%x", s
, v
);
1588 while ((i
= *bits
++) != '\0') {
1589 if (v
& (1 << (i
-1))) {
1593 for (; (c
= *bits
) > 32; bits
++)
1596 for (; *bits
> 32; bits
++)
1604 ether_getaddr(addr
, which
)
1608 struct ether_addr
*ea
;
1609 struct sockaddr
*sea
= &ridreq
.ifr_addr
;
1611 ea
= ether_aton(addr
);
1613 errx(1, "malformed ether address");
1615 errx(1, "Ethernet does not use netmasks");
1616 sea
->sa_family
= AF_LINK
;
1617 sea
->sa_len
= ETHER_ADDR_LEN
;
1618 bcopy(ea
, sea
->sa_data
, ETHER_ADDR_LEN
);
1627 register u_char
*name
= (u_char
*)val
;
1628 register int byte
, bit
, plen
= 0;
1630 for (byte
= 0; byte
< size
; byte
++, plen
+= 8)
1631 if (name
[byte
] != 0xff)
1635 for (bit
= 7; bit
!= 0; bit
--, plen
++)
1636 if (!(name
[byte
] & (1 << bit
)))
1638 for (; bit
!= 0; bit
--)
1639 if (name
[byte
] & (1 << bit
))
1642 for (; byte
< size
; byte
++)
1652 static char result
[256];
1653 int days
, hours
, mins
, secs
;
1658 days
= total
/ 3600 / 24;
1659 hours
= (total
/ 3600) % 24;
1660 mins
= (total
/ 60) % 60;
1665 p
+= sprintf(p
, "%dd", days
);
1667 if (!first
|| hours
) {
1669 p
+= sprintf(p
, "%dh", hours
);
1671 if (!first
|| mins
) {
1673 p
+= sprintf(p
, "%dm", mins
);
1675 sprintf(p
, "%ds", secs
);
1677 sprintf(result
, "%lu", (unsigned long)total
);