2 * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Copyright (c) 1983, 1993
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 static const char copyright
[] =
60 "@(#) Copyright (c) 1983, 1993\n\
61 The Regents of the University of California. All rights reserved.\n";
66 static char sccsid
[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
68 static const char rcsid
[] =
69 "$FreeBSD: src/sbin/ifconfig/ifconfig.c,v 1.134.2.2.2.1 2008/11/25 02:59:29 kensmith Exp $";
72 #include <sys/param.h>
73 #include <sys/ioctl.h>
74 #include <sys/socket.h>
75 #include <sys/sysctl.h>
78 #include <sys/module.h>
79 #include <sys/linker.h>
82 #include <net/ethernet.h>
84 #include <net/if_var.h>
85 #include <net/if_dl.h>
86 #include <net/if_types.h>
87 #include <net/if_mib.h>
88 #include <net/route.h>
89 #include <net/pktsched/pktsched.h>
92 #include <netinet/in.h>
93 #include <netinet/in_var.h>
94 #include <arpa/inet.h>
107 #include "ifconfig.h"
110 * Since "struct ifreq" is composed of various union members, callers
111 * should pay special attention to interprete the value.
112 * (.e.g. little/big endian difference in the structure.)
125 int bond_details
= 0;
127 #if TARGET_OS_EMBEDDED
130 #else /* !TARGET_OS_EMBEDDED */
133 #endif /* !TARGET_OS_EMBEDDED */
134 int printkeys
= 0; /* Print keying material for interfaces. */
136 static int ifconfig(int argc
, char *const *argv
, int iscreate
,
137 const struct afswtch
*afp
);
138 static void status(const struct afswtch
*afp
, const struct sockaddr_dl
*sdl
,
139 struct ifaddrs
*ifa
);
140 static char *bps_to_str(unsigned long long rate
);
141 static void tunnel_status(int s
);
142 static void usage(void);
143 static char *sched2str(unsigned int s
);
144 static char *tl2str(unsigned int s
);
146 static struct afswtch
*af_getbyname(const char *name
);
147 static struct afswtch
*af_getbyfamily(int af
);
148 static void af_other_status(int);
150 static struct option
*opts
= NULL
;
153 opt_register(struct option
*p
)
165 /* XXX not right but close enough for now */
167 for (p
= opts
; p
!= NULL
; p
= p
->next
) {
168 strlcat(options
, p
->opt_usage
, sizeof(options
));
169 strlcat(options
, " ", sizeof(options
));
173 "usage: ifconfig %sinterface address_family [address [dest_address]]\n"
175 " ifconfig interface create\n"
176 " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
177 " ifconfig -l [-d] [-u] [address_family]\n"
178 " ifconfig %s[-d] [-m] [-u] [-v]\n",
179 options
, options
, options
);
184 main(int argc
, char *argv
[])
186 int c
, namesonly
, downonly
, uponly
;
187 const struct afswtch
*afp
= NULL
;
189 struct ifaddrs
*ifap
, *ifa
;
191 const struct sockaddr_dl
*sdl
;
192 char options
[1024], *cp
;
197 all
= downonly
= uponly
= namesonly
= noload
= 0;
199 /* Parse leading line options */
201 strlcpy(options
, "adklmnuv", sizeof(options
));
203 strlcpy(options
, "abdlmruv", sizeof(options
));
205 for (p
= opts
; p
!= NULL
; p
= p
->next
)
206 strlcat(options
, p
->opt
, sizeof(options
));
207 while ((c
= getopt(argc
, argv
, options
)) != -1) {
209 case 'a': /* scan all interfaces */
212 case 'b': /* bond detailed output */
215 case 'd': /* restrict scan to "down" interfaces */
223 case 'l': /* scan interface names only */
226 case 'm': /* show media choices in status */
230 case 'n': /* suppress module loading */
237 case 'u': /* restrict scan to "up" interfaces */
244 for (p
= opts
; p
!= NULL
; p
= p
->next
)
245 if (p
->opt
[0] == c
) {
257 /* -l cannot be used with -a or -q or -r or -m or -b */
259 #ifdef TARGET_OS_EMBEDDED
260 (all
|| supmedia
|| bond_details
))
261 #else /* TARGET_OS_EMBEDDED */
262 (all
|| supmedia
|| showrtref
|| bond_details
))
263 #endif /* !TARGET_OS_EMBEDDED */
267 if (uponly
&& downonly
)
270 /* no arguments is equivalent to '-a' */
271 if (!namesonly
&& argc
< 1)
274 /* -a and -l allow an address family arg to limit the output */
275 if (all
|| namesonly
) {
282 afp
= af_getbyname(*argv
);
285 if (afp
->af_name
!= NULL
)
287 /* leave with afp non-zero */
290 /* not listing, need an argument */
298 /* check and maybe load support for this interface */
301 ifindex
= if_nametoindex(ifname
);
304 * NOTE: We must special-case the `create' command
305 * right here as we would otherwise fail when trying
306 * to find the interface.
308 if (argc
> 0 && (strcmp(argv
[0], "create") == 0 ||
309 strcmp(argv
[0], "plumb") == 0)) {
310 iflen
= strlcpy(name
, ifname
, sizeof(name
));
311 if (iflen
>= sizeof(name
))
312 errx(1, "%s: cloning name too long",
314 ifconfig(argc
, argv
, 1, NULL
);
317 errx(1, "interface %s does not exist", ifname
);
321 /* Check for address family */
323 afp
= af_getbyname(*argv
);
328 if (getifaddrs(&ifap
) != 0)
329 err(EXIT_FAILURE
, "getifaddrs");
332 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
333 memset(&paifr
, 0, sizeof(paifr
));
334 strncpy(paifr
.ifr_name
, ifa
->ifa_name
, sizeof(paifr
.ifr_name
));
335 if (sizeof(paifr
.ifr_addr
) >= ifa
->ifa_addr
->sa_len
) {
336 memcpy(&paifr
.ifr_addr
, ifa
->ifa_addr
,
337 ifa
->ifa_addr
->sa_len
);
340 if (ifname
!= NULL
&& strcmp(ifname
, ifa
->ifa_name
) != 0)
342 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
343 sdl
= (const struct sockaddr_dl
*) ifa
->ifa_addr
;
346 if (cp
!= NULL
&& strcmp(cp
, ifa
->ifa_name
) == 0)
348 iflen
= strlcpy(name
, ifa
->ifa_name
, sizeof(name
));
349 if (iflen
>= sizeof(name
)) {
350 warnx("%s: interface name too long, skipping",
356 if (downonly
&& (ifa
->ifa_flags
& IFF_UP
) != 0)
358 if (uponly
&& (ifa
->ifa_flags
& IFF_UP
) == 0)
362 * Are we just listing the interfaces?
372 ifconfig(argc
, argv
, 0, afp
);
374 status(afp
, sdl
, ifa
);
383 static struct afswtch
*afs
= NULL
;
386 af_register(struct afswtch
*p
)
392 static struct afswtch
*
393 af_getbyname(const char *name
)
397 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
)
398 if (strcmp(afp
->af_name
, name
) == 0)
403 static struct afswtch
*
404 af_getbyfamily(int af
)
408 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
)
409 if (afp
->af_af
== af
)
415 af_other_status(int s
)
418 uint8_t afmask
[howmany(AF_MAX
, NBBY
)];
420 memset(afmask
, 0, sizeof(afmask
));
421 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
) {
422 if (afp
->af_other_status
== NULL
)
424 if (afp
->af_af
!= AF_UNSPEC
&& isset(afmask
, afp
->af_af
))
426 afp
->af_other_status(s
);
427 setbit(afmask
, afp
->af_af
);
432 af_all_tunnel_status(int s
)
435 uint8_t afmask
[howmany(AF_MAX
, NBBY
)];
437 memset(afmask
, 0, sizeof(afmask
));
438 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
) {
439 if (afp
->af_status_tunnel
== NULL
)
441 if (afp
->af_af
!= AF_UNSPEC
&& isset(afmask
, afp
->af_af
))
443 afp
->af_status_tunnel(s
);
444 setbit(afmask
, afp
->af_af
);
448 static struct cmd
*cmds
= NULL
;
451 cmd_register(struct cmd
*p
)
457 static const struct cmd
*
458 cmd_lookup(const char *name
)
460 #define N(a) (sizeof(a)/sizeof(a[0]))
463 for (p
= cmds
; p
!= NULL
; p
= p
->c_next
)
464 if (strcmp(name
, p
->c_name
) == 0)
471 callback_func
*cb_func
;
473 struct callback
*cb_next
;
475 static struct callback
*callbacks
= NULL
;
478 callback_register(callback_func
*func
, void *arg
)
482 cb
= malloc(sizeof(struct callback
));
484 errx(1, "unable to allocate memory for callback");
487 cb
->cb_next
= callbacks
;
491 /* specially-handled commands */
492 static void setifaddr(const char *, int, int, const struct afswtch
*);
493 static const struct cmd setifaddr_cmd
= DEF_CMD("ifaddr", 0, setifaddr
);
495 static void setifdstaddr(const char *, int, int, const struct afswtch
*);
496 static const struct cmd setifdstaddr_cmd
=
497 DEF_CMD("ifdstaddr", 0, setifdstaddr
);
500 ifconfig(int argc
, char *const *argv
, int iscreate
, const struct afswtch
*afp
)
502 const struct afswtch
*nafp
;
506 strncpy(ifr
.ifr_name
, name
, sizeof ifr
.ifr_name
);
509 afp
= af_getbyname("inet");
510 ifr
.ifr_addr
.sa_family
=
511 afp
->af_af
== AF_LINK
|| afp
->af_af
== AF_UNSPEC
?
512 AF_INET
: afp
->af_af
;
514 if ((s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0)) < 0)
515 err(1, "socket(family %u,SOCK_DGRAM", ifr
.ifr_addr
.sa_family
);
520 p
= cmd_lookup(*argv
);
523 * Not a recognized command, choose between setting
524 * the interface address and the dst address.
526 p
= (setaddr
? &setifdstaddr_cmd
: &setifaddr_cmd
);
528 if (p
->c_u
.c_func
|| p
->c_u
.c_func2
) {
529 if (iscreate
&& !p
->c_iscloneop
) {
531 * Push the clone create callback so the new
532 * device is created and can be used for any
533 * remaining arguments.
537 errx(1, "internal error, no callback");
538 callbacks
= cb
->cb_next
;
539 cb
->cb_func(s
, cb
->cb_arg
);
542 * Handle any address family spec that
543 * immediately follows and potentially
544 * recreate the socket.
546 nafp
= af_getbyname(*argv
);
556 if (p
->c_parameter
== NEXTARG
) {
558 errx(1, "'%s' requires argument",
560 p
->c_u
.c_func(argv
[1], 0, s
, afp
);
562 } else if (p
->c_parameter
== OPTARG
) {
563 p
->c_u
.c_func(argv
[1], 0, s
, afp
);
566 } else if (p
->c_parameter
== NEXTARG2
) {
568 errx(1, "'%s' requires 2 arguments",
570 p
->c_u
.c_func2(argv
[1], argv
[2], s
, afp
);
571 argc
-= 2, argv
+= 2;
573 p
->c_u
.c_func(*argv
, p
->c_parameter
, s
, afp
);
579 * Do any post argument processing required by the address family.
581 if (afp
->af_postproc
!= NULL
)
582 afp
->af_postproc(s
, afp
);
584 * Do deferred callbacks registered while processing
585 * command-line arguments.
587 for (cb
= callbacks
; cb
!= NULL
; cb
= cb
->cb_next
)
588 cb
->cb_func(s
, cb
->cb_arg
);
590 * Do deferred operations.
593 if (afp
->af_ridreq
== NULL
|| afp
->af_difaddr
== 0) {
594 warnx("interface %s cannot change %s addresses!",
601 strncpy(afp
->af_ridreq
, name
, sizeof ifr
.ifr_name
);
602 ret
= ioctl(s
, afp
->af_difaddr
, afp
->af_ridreq
);
604 if (errno
== EADDRNOTAVAIL
&& (doalias
>= 0)) {
605 /* means no previous address for interface */
607 Perror("ioctl (SIOCDIFADDR)");
611 if (afp
->af_addreq
== NULL
|| afp
->af_aifaddr
== 0) {
612 warnx("interface %s cannot change %s addresses!",
617 if (newaddr
&& (setaddr
|| setmask
)) {
618 strncpy(afp
->af_addreq
, name
, sizeof ifr
.ifr_name
);
619 if (ioctl(s
, afp
->af_aifaddr
, afp
->af_addreq
) < 0)
620 Perror("ioctl (SIOCAIFADDR)");
629 setifaddr(const char *addr
, int param
, int s
, const struct afswtch
*afp
)
631 if (afp
->af_getaddr
== NULL
)
634 * Delay the ioctl to set the interface addr until flags are all set.
635 * The address interpretation may depend on the flags,
636 * and the flags may change when the address is set.
639 if (doalias
== 0 && afp
->af_af
!= AF_LINK
)
641 afp
->af_getaddr(addr
, (doalias
>= 0 ? ADDR
: RIDADDR
));
645 settunnel(const char *src
, const char *dst
, int s
, const struct afswtch
*afp
)
647 struct addrinfo
*srcres
, *dstres
;
650 if (afp
->af_settunnel
== NULL
) {
651 warn("address family %s does not support tunnel setup",
656 if ((ecode
= getaddrinfo(src
, NULL
, NULL
, &srcres
)) != 0)
657 errx(1, "error in parsing address string: %s",
658 gai_strerror(ecode
));
660 if ((ecode
= getaddrinfo(dst
, NULL
, NULL
, &dstres
)) != 0)
661 errx(1, "error in parsing address string: %s",
662 gai_strerror(ecode
));
664 if (srcres
->ai_addr
->sa_family
!= dstres
->ai_addr
->sa_family
)
666 "source and destination address families do not match");
668 afp
->af_settunnel(s
, srcres
, dstres
);
670 freeaddrinfo(srcres
);
671 freeaddrinfo(dstres
);
676 deletetunnel(const char *vname
, int param
, int s
, const struct afswtch
*afp
)
679 if (ioctl(s
, SIOCDIFPHYADDR
, &ifr
) < 0)
680 err(1, "SIOCDIFPHYADDR");
684 setifnetmask(const char *addr
, int dummy __unused
, int s
,
685 const struct afswtch
*afp
)
687 if (afp
->af_getaddr
!= NULL
) {
689 afp
->af_getaddr(addr
, MASK
);
694 setifbroadaddr(const char *addr
, int dummy __unused
, int s
,
695 const struct afswtch
*afp
)
697 if (afp
->af_getaddr
!= NULL
)
698 afp
->af_getaddr(addr
, DSTADDR
);
702 setifipdst(const char *addr
, int dummy __unused
, int s
,
703 const struct afswtch
*afp
)
705 const struct afswtch
*inet
;
707 inet
= af_getbyname("inet");
710 inet
->af_getaddr(addr
, DSTADDR
);
716 notealias(const char *addr
, int param
, int s
, const struct afswtch
*afp
)
718 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
719 if (setaddr
&& doalias
== 0 && param
< 0)
720 if (afp
->af_addreq
!= NULL
&& afp
->af_ridreq
!= NULL
)
721 bcopy((caddr_t
)rqtosa(af_addreq
),
722 (caddr_t
)rqtosa(af_ridreq
),
723 rqtosa(af_addreq
)->sa_len
);
735 setifdstaddr(const char *addr
, int param __unused
, int s
,
736 const struct afswtch
*afp
)
738 if (afp
->af_getaddr
!= NULL
)
739 afp
->af_getaddr(addr
, DSTADDR
);
743 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
744 * of the ifreq structure, which may confuse other parts of ifconfig.
745 * Make a private copy so we can avoid that.
748 setifflags(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
753 bcopy((char *)&ifr
, (char *)&my_ifr
, sizeof(struct ifreq
));
755 if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
)&my_ifr
) < 0) {
756 Perror("ioctl (SIOCGIFFLAGS)");
759 strncpy(my_ifr
.ifr_name
, name
, sizeof (my_ifr
.ifr_name
));
760 flags
= my_ifr
.ifr_flags
;
767 my_ifr
.ifr_flags
= flags
& 0xffff;
768 if (ioctl(s
, SIOCSIFFLAGS
, (caddr_t
)&my_ifr
) < 0)
774 setifcap(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
778 if (ioctl(s
, SIOCGIFCAP
, (caddr_t
)&ifr
) < 0) {
779 Perror("ioctl (SIOCGIFCAP)");
782 flags
= ifr
.ifr_curcap
;
788 flags
&= ifr
.ifr_reqcap
;
789 ifr
.ifr_reqcap
= flags
;
790 if (ioctl(s
, SIOCSIFCAP
, (caddr_t
)&ifr
) < 0)
796 setifmetric(const char *val
, int dummy __unused
, int s
,
797 const struct afswtch
*afp
)
799 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
800 ifr
.ifr_metric
= atoi(val
);
801 if (ioctl(s
, SIOCSIFMETRIC
, (caddr_t
)&ifr
) < 0)
802 warn("ioctl (set metric)");
806 setifmtu(const char *val
, int dummy __unused
, int s
,
807 const struct afswtch
*afp
)
809 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
810 ifr
.ifr_mtu
= atoi(val
);
811 if (ioctl(s
, SIOCSIFMTU
, (caddr_t
)&ifr
) < 0)
812 warn("ioctl (set mtu)");
817 setifname(const char *val
, int dummy __unused
, int s
,
818 const struct afswtch
*afp
)
822 newname
= strdup(val
);
823 if (newname
== NULL
) {
824 warn("no memory to set ifname");
827 ifr
.ifr_data
= newname
;
828 if (ioctl(s
, SIOCSIFNAME
, (caddr_t
)&ifr
) < 0) {
829 warn("ioctl (set name)");
833 strlcpy(name
, newname
, sizeof(name
));
839 setrouter(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
841 if (afp
->af_setrouter
== NULL
) {
842 warn("address family %s does not support router mode",
847 afp
->af_setrouter(s
, value
);
851 setifdesc(const char *val
, int dummy __unused
, int s
, const struct afswtch
*afp
)
853 struct if_descreq ifdr
;
855 bzero(&ifdr
, sizeof (ifdr
));
856 strncpy(ifdr
.ifdr_name
, name
, sizeof (ifdr
.ifdr_name
));
857 ifdr
.ifdr_len
= strlen(val
);
858 strncpy((char *)ifdr
.ifdr_desc
, val
, sizeof (ifdr
.ifdr_desc
));
860 if (ioctl(s
, SIOCSIFDESC
, (caddr_t
)&ifdr
) < 0) {
861 warn("ioctl (set desc)");
866 settbr(const char *val
, int dummy __unused
, int s
, const struct afswtch
*afp
)
868 struct if_linkparamsreq iflpr
;
871 u_int32_t percent
= 0;
875 bzero(&iflpr
, sizeof (iflpr
));
876 strncpy(iflpr
.iflpr_name
, name
, sizeof (iflpr
.iflpr_name
));
878 bps
= strtold(val
, &cp
);
879 if (val
== cp
|| errno
!= 0) {
880 warn("Invalid value '%s'", val
);
883 rate
= (u_int64_t
)bps
;
885 if (!strcmp(cp
, "b") || !strcmp(cp
, "bps")) {
887 } else if (!strcmp(cp
, "Kb") || !strcmp(cp
, "Kbps")) {
889 } else if (!strcmp(cp
, "Mb") || !strcmp(cp
, "Mbps")) {
891 } else if (!strcmp(cp
, "Gb") || !strcmp(cp
, "Gbps")) {
892 rate
*= 1000 * 1000 * 1000;
893 } else if (!strcmp(cp
, "%")) {
895 if (percent
== 0 || percent
> 100) {
896 printf("Value out of range '%s'", val
);
899 } else if (*cp
!= '\0') {
900 printf("Unknown unit '%s'", cp
);
904 iflpr
.iflpr_output_tbr_rate
= rate
;
905 iflpr
.iflpr_output_tbr_percent
= percent
;
906 if (ioctl(s
, SIOCSIFLINKPARAMS
, &iflpr
) < 0 &&
907 errno
!= ENOENT
&& errno
!= ENXIO
&& errno
!= ENODEV
) {
908 warn("ioctl (set link params)");
909 } else if (errno
== ENXIO
) {
910 printf("TBR cannot be set on %s\n", name
);
911 } else if (errno
== ENOENT
|| rate
== 0) {
912 printf("%s: TBR is now disabled\n", name
);
913 } else if (errno
== ENODEV
) {
914 printf("%s: requires absolute TBR rate\n", name
);
915 } else if (percent
!= 0) {
916 printf("%s: TBR rate set to %u%% of effective link rate\n",
919 printf("%s: TBR rate set to %s\n", name
, bps_to_str(rate
));
924 setthrottle(const char *val
, int dummy __unused
, int s
,
925 const struct afswtch
*afp
)
927 struct if_throttlereq iftr
;
931 bzero(&iftr
, sizeof (iftr
));
932 strncpy(iftr
.ifthr_name
, name
, sizeof (iftr
.ifthr_name
));
934 iftr
.ifthr_level
= strtold(val
, &cp
);
935 if (val
== cp
|| errno
!= 0) {
936 warn("Invalid value '%s'", val
);
940 if (ioctl(s
, SIOCSIFTHROTTLE
, &iftr
) < 0 && errno
!= ENXIO
) {
941 warn("ioctl (set throttling level)");
942 } else if (errno
== ENXIO
) {
943 printf("throttling level cannot be set on %s\n", name
);
945 printf("%s: throttling level set to %d\n", name
,
951 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
952 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
956 "\020\1AUTOCONFIGURING\7ACCEPT_RTADV\10TXSTART\11RXPOLL\12VLAN\13BOND\14ARPLL" \
957 "\15NOWINDOWSCALE\16NOAUTOIPV6LL\20ROUTER4\21ROUTER6" \
958 "\22LOCALNET_PRIVATE\23ND6ALT\24RESTRICTED_RECV\25AWDL\26NOACKPRI\35SENDLIST"
961 "\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \
962 "\6TSO4\7TSO6\10LRO\11AV"
965 * Print the status of the interface. If an address family was
966 * specified, show only it; otherwise, show them all.
969 status(const struct afswtch
*afp
, const struct sockaddr_dl
*sdl
,
975 struct if_descreq ifdr
;
976 struct if_linkparamsreq iflpr
;
978 struct ifmibdata_supplemental ifmsupp
;
979 size_t miblen
= sizeof(struct ifmibdata_supplemental
);
980 u_int64_t eflags
= 0;
984 afp
= af_getbyname("inet");
988 ifr
.ifr_addr
.sa_family
= afp
->af_af
== AF_LINK
? AF_INET
: afp
->af_af
;
989 strncpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
991 s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0);
993 err(1, "socket(family %u,SOCK_DGRAM)", ifr
.ifr_addr
.sa_family
);
995 printf("%s: ", name
);
996 printb("flags", ifa
->ifa_flags
, IFFBITS
);
997 if (ioctl(s
, SIOCGIFMETRIC
, &ifr
) != -1)
999 printf(" metric %d", ifr
.ifr_metric
);
1000 if (ioctl(s
, SIOCGIFMTU
, &ifr
) != -1)
1001 printf(" mtu %d", ifr
.ifr_mtu
);
1002 if (showrtref
&& ioctl(s
, SIOCGIFGETRTREFCNT
, &ifr
) != -1)
1003 printf(" rtref %d", ifr
.ifr_route_refcnt
);
1005 unsigned int ifindex
= if_nametoindex(ifa
->ifa_name
);
1007 printf(" index %u", ifindex
);
1011 if (verbose
&& ioctl(s
, SIOCGIFEFLAGS
, (caddr_t
)&ifr
) != -1 &&
1012 (eflags
= ifr
.ifr_eflags
) != 0) {
1013 printb("\teflags", eflags
, IFEFBITS
);
1018 if (ioctl(s
, SIOCGIFCAP
, (caddr_t
)&ifr
) == 0) {
1019 if (ifr
.ifr_curcap
!= 0) {
1020 printb("\toptions", ifr
.ifr_curcap
, IFCAPBITS
);
1023 if (supmedia
&& ifr
.ifr_reqcap
!= 0) {
1024 printb("\tcapabilities", ifr
.ifr_reqcap
, IFCAPBITS
);
1032 for (ift
= ifa
; ift
!= NULL
; ift
= ift
->ifa_next
) {
1033 if (ift
->ifa_addr
== NULL
)
1035 if (strcmp(ifa
->ifa_name
, ift
->ifa_name
) != 0)
1038 const struct afswtch
*p
;
1039 p
= af_getbyfamily(ift
->ifa_addr
->sa_family
);
1040 if (p
!= NULL
&& p
->af_status
!= NULL
)
1041 p
->af_status(s
, ift
);
1042 } else if (afp
->af_af
== ift
->ifa_addr
->sa_family
)
1043 afp
->af_status(s
, ift
);
1046 if (allfamilies
|| afp
->af_af
== AF_LINK
) {
1047 const struct afswtch
*lafp
;
1050 * Hack; the link level address is received separately
1051 * from the routing information so any address is not
1052 * handled above. Cobble together an entry and invoke
1053 * the status method specially.
1055 lafp
= af_getbyname("lladdr");
1057 info
.rti_info
[RTAX_IFA
] = (struct sockaddr
*)sdl
;
1058 lafp
->af_status(s
, &info
);
1064 else if (afp
->af_other_status
!= NULL
)
1065 afp
->af_other_status(s
);
1067 strncpy(ifs
.ifs_name
, name
, sizeof ifs
.ifs_name
);
1068 if (ioctl(s
, SIOCGIFSTATUS
, &ifs
) == 0)
1069 printf("%s", ifs
.ascii
);
1071 /* The rest is for when verbose is set; if not set, we're done */
1075 if (ioctl(s
, SIOCGIFLINKQUALITYMETRIC
, &ifr
) != -1) {
1076 int lqm
= ifr
.ifr_link_quality_metric
;
1078 printf("\tlink quality: %d ", lqm
);
1079 if (lqm
== IFNET_LQM_THRESH_OFF
) {
1081 } else if (lqm
== IFNET_LQM_THRESH_UNKNOWN
) {
1082 printf("(unknown)");
1083 } else if (lqm
> IFNET_LQM_THRESH_UNKNOWN
&&
1084 lqm
<= IFNET_LQM_THRESH_POOR
)
1086 else if (lqm
> IFNET_LQM_THRESH_POOR
&&
1087 lqm
<= IFNET_LQM_THRESH_GOOD
)
1092 } else if (lqm
> IFNET_LQM_THRESH_UNKNOWN
) {
1093 printf("\tlink quality: %d ", lqm
);
1094 if (lqm
<= IFNET_LQM_THRESH_POOR
)
1096 else if (lqm
> IFNET_LQM_THRESH_POOR
&&
1097 lqm
<= IFNET_LQM_THRESH_GOOD
)
1105 bzero(&iflpr
, sizeof (iflpr
));
1106 strncpy(iflpr
.iflpr_name
, name
, sizeof (iflpr
.iflpr_name
));
1107 if (ioctl(s
, SIOCGIFLINKPARAMS
, &iflpr
) != -1) {
1108 u_int64_t ibw_max
= iflpr
.iflpr_input_bw
.max_bw
;
1109 u_int64_t ibw_eff
= iflpr
.iflpr_input_bw
.eff_bw
;
1110 u_int64_t obw_max
= iflpr
.iflpr_output_bw
.max_bw
;
1111 u_int64_t obw_eff
= iflpr
.iflpr_output_bw
.eff_bw
;
1112 u_int64_t obw_tbr
= iflpr
.iflpr_output_tbr_rate
;
1113 u_int32_t obw_pct
= iflpr
.iflpr_output_tbr_percent
;
1115 if (eflags
& IFEF_TXSTART
) {
1116 u_int32_t flags
= iflpr
.iflpr_flags
;
1117 u_int32_t sched
= iflpr
.iflpr_output_sched
;
1118 struct if_throttlereq iftr
;
1120 printf("\tscheduler: %s%s ",
1121 (flags
& IFLPRF_ALTQ
) ? "ALTQ_" : "",
1123 if (flags
& IFLPRF_DRVMANAGED
)
1124 printf("(driver managed)");
1127 bzero(&iftr
, sizeof (iftr
));
1128 strncpy(iftr
.ifthr_name
, name
,
1129 sizeof (iftr
.ifthr_name
));
1130 if (ioctl(s
, SIOCGIFTHROTTLE
, &iftr
) != -1 &&
1131 iftr
.ifthr_level
!= IFNET_THROTTLE_OFF
)
1132 printf("\tthrottling: level %d (%s)\n",
1133 iftr
.ifthr_level
, tl2str(iftr
.ifthr_level
));
1136 if (obw_tbr
!= 0 && obw_eff
> obw_tbr
)
1139 if (ibw_max
!= 0 || obw_max
!= 0) {
1140 if (ibw_max
== obw_max
&& ibw_eff
== obw_eff
&&
1141 ibw_max
== ibw_eff
&& obw_tbr
== 0) {
1142 printf("\tlink rate: %s\n",
1143 bps_to_str(ibw_max
));
1145 printf("\tuplink rate: %s [eff] / ",
1146 bps_to_str(obw_eff
));
1149 printf("%s [tbr] / ",
1150 bps_to_str(obw_tbr
));
1152 printf("%s [tbr %u%%] / ",
1153 bps_to_str(obw_tbr
),
1156 printf("%s", bps_to_str(obw_max
));
1160 if (ibw_eff
== ibw_max
) {
1161 printf("\tdownlink rate: %s\n",
1162 bps_to_str(ibw_max
));
1164 printf("\tdownlink rate: "
1165 "%s [eff] / ", bps_to_str(ibw_eff
));
1166 printf("%s [max]\n",
1167 bps_to_str(ibw_max
));
1170 } else if (obw_tbr
!= 0) {
1171 printf("\tuplink rate: %s [tbr]\n",
1172 bps_to_str(obw_tbr
));
1176 /* Common OID prefix */
1179 mib
[2] = NETLINK_GENERIC
;
1180 mib
[3] = IFMIB_IFDATA
;
1181 mib
[4] = if_nametoindex(name
);
1182 mib
[5] = IFDATA_SUPPLEMENTAL
;
1183 if (sysctl(mib
, 6, &ifmsupp
, &miblen
, (void *)0, 0) == -1)
1184 err(1, "sysctl IFDATA_SUPPLEMENTAL");
1186 if (ifmsupp
.ifmd_data_extended
.ifi_alignerrs
!= 0) {
1187 printf("\tunaligned pkts: %lld\n",
1188 ifmsupp
.ifmd_data_extended
.ifi_alignerrs
);
1191 bzero(&ifdr
, sizeof (ifdr
));
1192 strncpy(ifdr
.ifdr_name
, name
, sizeof (ifdr
.ifdr_name
));
1193 if (ioctl(s
, SIOCGIFDESC
, &ifdr
) != -1 && ifdr
.ifdr_len
) {
1194 printf("\tdesc: %s\n", ifdr
.ifdr_desc
);
1202 #define GIGABIT_PER_SEC 1000000000 /* gigabit per second */
1203 #define MEGABIT_PER_SEC 1000000 /* megabit per second */
1204 #define KILOBIT_PER_SEC 1000 /* kilobit per second */
1207 bps_to_str(unsigned long long rate
)
1209 static char buf
[32];
1211 long double n
= rate
, t
;
1213 if (rate
>= GIGABIT_PER_SEC
) {
1214 t
= n
/ GIGABIT_PER_SEC
;
1216 } else if (n
>= MEGABIT_PER_SEC
) {
1217 t
= n
/ MEGABIT_PER_SEC
;
1219 } else if (n
>= KILOBIT_PER_SEC
) {
1220 t
= n
/ KILOBIT_PER_SEC
;
1227 snprintf(buf
, sizeof (buf
), "%-4.2Lf %4s", t
, u
);
1232 tunnel_status(int s
)
1234 af_all_tunnel_status(s
);
1238 Perror(const char *cmd
)
1243 errx(1, "%s: no such interface", cmd
);
1247 errx(1, "%s: permission denied", cmd
);
1256 * Print a value a la the %b format of the kernel's printf
1259 printb(const char *s
, unsigned v
, const char *bits
)
1264 if (bits
&& *bits
== 8)
1265 printf("%s=%o", s
, v
);
1267 printf("%s=%x", s
, v
);
1271 while ((i
= *bits
++) != '\0') {
1272 if (v
& (1 << (i
-1))) {
1276 for (; (c
= *bits
) > 32; bits
++)
1279 for (; *bits
> 32; bits
++)
1288 ifmaybeload(const char *name
)
1290 #define MOD_PREFIX_LEN 3 /* "if_" */
1291 struct module_stat mstat
;
1293 char ifkind
[IFNAMSIZ
+ MOD_PREFIX_LEN
], ifname
[IFNAMSIZ
], *dp
;
1296 /* loading suppressed by the user */
1300 /* trim the interface number off the end */
1301 strlcpy(ifname
, name
, sizeof(ifname
));
1302 for (dp
= ifname
; *dp
!= 0; dp
++)
1308 /* turn interface and unit into module name */
1309 strlcpy(ifkind
, "if_", sizeof(ifkind
));
1310 strlcpy(ifkind
+ MOD_PREFIX_LEN
, ifname
,
1311 sizeof(ifkind
) - MOD_PREFIX_LEN
);
1313 /* scan files in kernel */
1314 mstat
.version
= sizeof(struct module_stat
);
1315 for (fileid
= kldnext(0); fileid
> 0; fileid
= kldnext(fileid
)) {
1316 /* scan modules in file */
1317 for (modid
= kldfirstmod(fileid
); modid
> 0;
1318 modid
= modfnext(modid
)) {
1319 if (modstat(modid
, &mstat
) < 0)
1321 /* strip bus name if present */
1322 if ((cp
= strchr(mstat
.name
, '/')) != NULL
) {
1327 /* already loaded? */
1328 if (strncmp(ifname
, cp
, strlen(ifname
) + 1) == 0 ||
1329 strncmp(ifkind
, cp
, strlen(ifkind
) + 1) == 0)
1334 /* not present, we should try to load it */
1339 static struct cmd basic_cmds
[] = {
1340 DEF_CMD("up", IFF_UP
, setifflags
),
1341 DEF_CMD("down", -IFF_UP
, setifflags
),
1342 DEF_CMD("arp", -IFF_NOARP
, setifflags
),
1343 DEF_CMD("-arp", IFF_NOARP
, setifflags
),
1344 DEF_CMD("debug", IFF_DEBUG
, setifflags
),
1345 DEF_CMD("-debug", -IFF_DEBUG
, setifflags
),
1347 DEF_CMD("promisc", IFF_PPROMISC
, setifflags
),
1348 DEF_CMD("-promisc", -IFF_PPROMISC
, setifflags
),
1349 #endif /* IFF_PPROMISC */
1350 DEF_CMD("add", IFF_UP
, notealias
),
1351 DEF_CMD("alias", IFF_UP
, notealias
),
1352 DEF_CMD("-alias", -IFF_UP
, notealias
),
1353 DEF_CMD("delete", -IFF_UP
, notealias
),
1354 DEF_CMD("remove", -IFF_UP
, notealias
),
1356 #define EN_SWABIPS 0x1000
1357 DEF_CMD("swabips", EN_SWABIPS
, setifflags
),
1358 DEF_CMD("-swabips", -EN_SWABIPS
, setifflags
),
1360 DEF_CMD_ARG("netmask", setifnetmask
),
1361 DEF_CMD_ARG("metric", setifmetric
),
1362 DEF_CMD_ARG("broadcast", setifbroadaddr
),
1363 DEF_CMD_ARG("ipdst", setifipdst
),
1364 DEF_CMD_ARG2("tunnel", settunnel
),
1365 DEF_CMD("-tunnel", 0, deletetunnel
),
1366 DEF_CMD("deletetunnel", 0, deletetunnel
),
1367 DEF_CMD("link0", IFF_LINK0
, setifflags
),
1368 DEF_CMD("-link0", -IFF_LINK0
, setifflags
),
1369 DEF_CMD("link1", IFF_LINK1
, setifflags
),
1370 DEF_CMD("-link1", -IFF_LINK1
, setifflags
),
1371 DEF_CMD("link2", IFF_LINK2
, setifflags
),
1372 DEF_CMD("-link2", -IFF_LINK2
, setifflags
),
1374 DEF_CMD("monitor", IFF_MONITOR
:, setifflags
),
1375 DEF_CMD("-monitor", -IFF_MONITOR
, setifflags
),
1376 #endif /* IFF_MONITOR */
1377 #ifdef IFF_STATICARP
1378 DEF_CMD("staticarp", IFF_STATICARP
, setifflags
),
1379 DEF_CMD("-staticarp", -IFF_STATICARP
, setifflags
),
1380 #endif /* IFF_STATICARP */
1382 DEF_CMD("rxcsum", IFCAP_RXCSUM
, setifcap
),
1383 DEF_CMD("-rxcsum", -IFCAP_RXCSUM
, setifcap
),
1384 #endif /* IFCAP_RXCSUM */
1386 DEF_CMD("txcsum", IFCAP_TXCSUM
, setifcap
),
1387 DEF_CMD("-txcsum", -IFCAP_TXCSUM
, setifcap
),
1388 #endif /* IFCAP_TXCSUM */
1389 #ifdef IFCAP_NETCONS
1390 DEF_CMD("netcons", IFCAP_NETCONS
, setifcap
),
1391 DEF_CMD("-netcons", -IFCAP_NETCONS
, setifcap
),
1392 #endif /* IFCAP_NETCONS */
1393 #ifdef IFCAP_POLLING
1394 DEF_CMD("polling", IFCAP_POLLING
, setifcap
),
1395 DEF_CMD("-polling", -IFCAP_POLLING
, setifcap
),
1396 #endif /* IFCAP_POLLING */
1398 DEF_CMD("tso", IFCAP_TSO
, setifcap
),
1399 DEF_CMD("-tso", -IFCAP_TSO
, setifcap
),
1400 #endif /* IFCAP_TSO */
1402 DEF_CMD("lro", IFCAP_LRO
, setifcap
),
1403 DEF_CMD("-lro", -IFCAP_LRO
, setifcap
),
1404 #endif /* IFCAP_LRO */
1406 DEF_CMD("wol", IFCAP_WOL
, setifcap
),
1407 DEF_CMD("-wol", -IFCAP_WOL
, setifcap
),
1408 #endif /* IFCAP_WOL */
1409 #ifdef IFCAP_WOL_UCAST
1410 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST
, setifcap
),
1411 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST
, setifcap
),
1412 #endif /* IFCAP_WOL_UCAST */
1413 #ifdef IFCAP_WOL_MCAST
1414 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST
, setifcap
),
1415 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST
, setifcap
),
1416 #endif /* IFCAP_WOL_MCAST */
1417 #ifdef IFCAP_WOL_MAGIC
1418 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC
, setifcap
),
1419 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC
, setifcap
),
1420 #endif /* IFCAP_WOL_MAGIC */
1421 DEF_CMD("normal", -IFF_LINK0
, setifflags
),
1422 DEF_CMD("compress", IFF_LINK0
, setifflags
),
1423 DEF_CMD("noicmp", IFF_LINK1
, setifflags
),
1424 DEF_CMD_ARG("mtu", setifmtu
),
1426 DEF_CMD_ARG("name", setifname
),
1429 DEF_CMD("av", IFCAP_AV
, setifcap
),
1430 DEF_CMD("-av", -IFCAP_AV
, setifcap
),
1431 #endif /* IFCAP_AV */
1432 DEF_CMD("router", 1, setrouter
),
1433 DEF_CMD("-router", 0, setrouter
),
1434 DEF_CMD_ARG("desc", setifdesc
),
1435 DEF_CMD_ARG("tbr", settbr
),
1436 DEF_CMD_ARG("throttle", setthrottle
),
1439 static __constructor
void
1442 #define N(a) (sizeof(a) / sizeof(a[0]))
1445 for (i
= 0; i
< N(basic_cmds
); i
++)
1446 cmd_register(&basic_cmds
[i
]);
1451 sched2str(unsigned int s
)
1456 case PKTSCHEDT_NONE
:
1462 case PKTSCHEDT_HFSC
:
1465 case PKTSCHEDT_PRIQ
:
1468 case PKTSCHEDT_FAIRQ
:
1486 tl2str(unsigned int s
)
1491 case IFNET_THROTTLE_OFF
:
1494 case IFNET_THROTTLE_OPPORTUNISTIC
:
1495 c
= "opportunistic";