2 * Copyright (c) 2009-2019 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
58 #include <sys/cdefs.h>
61 __unused
static const char copyright
[] =
62 "@(#) Copyright (c) 1983, 1993\n\
63 The Regents of the University of California. All rights reserved.\n";
66 #include <sys/param.h>
67 #include <sys/ioctl.h>
68 #include <sys/socket.h>
69 #include <sys/sysctl.h>
72 #include <sys/module.h>
73 #include <sys/linker.h>
76 #include <net/ethernet.h>
78 #include <net/if_var.h>
79 #include <net/if_dl.h>
80 #include <net/if_types.h>
81 #include <net/if_mib.h>
82 #include <net/route.h>
83 #include <net/pktsched/pktsched.h>
84 #include <net/network_agent.h>
87 #include <netinet/in.h>
88 #include <netinet/in_var.h>
89 #include <arpa/inet.h>
103 #include <sysexits.h>
106 #include "ifconfig.h"
109 #include <TargetConditionals.h>
112 #ifndef IF_NETEM_PARAMS_PSCALE
113 #define IF_NETEM_PARAMS_PSCALE 100000
117 * Since "struct ifreq" is composed of various union members, callers
118 * should pay special attention to interprete the value.
119 * (.e.g. little/big endian difference in the structure.)
132 int bond_details
= 0;
134 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
137 #else /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
140 #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
141 int printkeys
= 0; /* Print keying material for interfaces. */
143 static int ifconfig(int argc
, char *const *argv
, int iscreate
,
144 const struct afswtch
*afp
);
145 static void status(const struct afswtch
*afp
, const struct sockaddr_dl
*sdl
,
146 struct ifaddrs
*ifa
);
147 static char *bytes_to_str(unsigned long long bytes
);
148 static char *bps_to_str(unsigned long long rate
);
149 static char *ns_to_str(unsigned long long nsec
);
150 static void tunnel_status(int s
);
151 static void clat46_addr(int s
, char *name
);
152 static void nat64_status(int s
, char *name
);
153 static void usage(void);
154 static char *sched2str(unsigned int s
);
155 static char *tl2str(unsigned int s
);
156 static char *ift2str(unsigned int t
, unsigned int f
, unsigned int sf
);
157 static char *iffunct2str(u_int32_t functional_type
);
159 static struct afswtch
*af_getbyname(const char *name
);
160 static struct afswtch
*af_getbyfamily(int af
);
161 static void af_other_status(int);
163 static struct option
*opts
= NULL
;
166 opt_register(struct option
*p
)
178 /* XXX not right but close enough for now */
180 for (p
= opts
; p
!= NULL
; p
= p
->next
) {
181 strlcat(options
, p
->opt_usage
, sizeof(options
));
182 strlcat(options
, " ", sizeof(options
));
186 "usage: ifconfig %sinterface address_family [address [dest_address]]\n"
188 " ifconfig interface create\n"
189 " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
190 " ifconfig -l [-d] [-u] [address_family]\n"
191 " ifconfig %s[-d] [-m] [-u] [-v]\n",
192 options
, options
, options
);
197 main(int argc
, char *argv
[])
199 int c
, namesonly
, downonly
, uponly
;
200 const struct afswtch
*afp
= NULL
;
202 struct ifaddrs
*ifap
, *ifa
;
204 const struct sockaddr_dl
*sdl
;
205 char options
[1024], *cp
;
210 all
= downonly
= uponly
= namesonly
= noload
= 0;
212 /* Parse leading line options */
214 strlcpy(options
, "adklmnuv", sizeof(options
));
216 strlcpy(options
, "abdlmruv", sizeof(options
));
218 for (p
= opts
; p
!= NULL
; p
= p
->next
)
219 strlcat(options
, p
->opt
, sizeof(options
));
220 while ((c
= getopt(argc
, argv
, options
)) != -1) {
222 case 'a': /* scan all interfaces */
225 case 'b': /* bond detailed output */
228 case 'd': /* restrict scan to "down" interfaces */
236 case 'l': /* scan interface names only */
239 case 'm': /* show media choices in status */
243 case 'n': /* suppress module loading */
250 case 'u': /* restrict scan to "up" interfaces */
257 for (p
= opts
; p
!= NULL
; p
= p
->next
)
258 if (p
->opt
[0] == c
) {
270 /* -l cannot be used with -a or -q or -m or -b */
272 (all
|| supmedia
|| bond_details
))
276 if (uponly
&& downonly
)
279 /* no arguments is equivalent to '-a' */
280 if (!namesonly
&& argc
< 1)
283 /* -a and -l allow an address family arg to limit the output */
284 if (all
|| namesonly
) {
290 afp
= af_getbyname(*argv
);
293 if (afp
->af_name
!= NULL
)
295 /* leave with afp non-zero */
298 /* not listing, need an argument */
306 /* check and maybe load support for this interface */
309 ifindex
= if_nametoindex(ifname
);
312 * NOTE: We must special-case the `create' command
313 * right here as we would otherwise fail when trying
314 * to find the interface.
316 if (argc
> 0 && (strcmp(argv
[0], "create") == 0 ||
317 strcmp(argv
[0], "plumb") == 0)) {
318 iflen
= strlcpy(name
, ifname
, sizeof(name
));
319 if (iflen
>= sizeof(name
))
320 errx(1, "%s: cloning name too long",
322 ifconfig(argc
, argv
, 1, NULL
);
325 errx(1, "interface %s does not exist", ifname
);
329 /* Check for address family */
331 afp
= af_getbyname(*argv
);
336 if (getifaddrs(&ifap
) != 0)
337 err(EXIT_FAILURE
, "getifaddrs");
340 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
341 memset(&paifr
, 0, sizeof(paifr
));
342 strlcpy(paifr
.ifr_name
, ifa
->ifa_name
, sizeof(paifr
.ifr_name
));
343 if (sizeof(paifr
.ifr_addr
) >= ifa
->ifa_addr
->sa_len
) {
344 memcpy(&paifr
.ifr_addr
, ifa
->ifa_addr
,
345 ifa
->ifa_addr
->sa_len
);
348 if (ifname
!= NULL
&& strcmp(ifname
, ifa
->ifa_name
) != 0)
350 if (ifa
->ifa_addr
->sa_family
== AF_LINK
)
351 sdl
= (const struct sockaddr_dl
*) ifa
->ifa_addr
;
354 if (cp
!= NULL
&& strcmp(cp
, ifa
->ifa_name
) == 0)
356 iflen
= strlcpy(name
, ifa
->ifa_name
, sizeof(name
));
357 if (iflen
>= sizeof(name
)) {
358 warnx("%s: interface name too long, skipping",
364 if (downonly
&& (ifa
->ifa_flags
& IFF_UP
) != 0)
366 if (uponly
&& (ifa
->ifa_flags
& IFF_UP
) == 0)
370 * Are we just listing the interfaces?
380 ifconfig(argc
, argv
, 0, afp
);
382 status(afp
, sdl
, ifa
);
391 static struct afswtch
*afs
= NULL
;
394 af_register(struct afswtch
*p
)
400 static struct afswtch
*
401 af_getbyname(const char *name
)
405 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
)
406 if (strcmp(afp
->af_name
, name
) == 0)
411 static struct afswtch
*
412 af_getbyfamily(int af
)
416 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
)
417 if (afp
->af_af
== af
)
423 af_other_status(int s
)
426 uint8_t afmask
[howmany(AF_MAX
, NBBY
)];
428 memset(afmask
, 0, sizeof(afmask
));
429 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
) {
430 if (afp
->af_other_status
== NULL
)
432 if (afp
->af_af
!= AF_UNSPEC
&& isset(afmask
, afp
->af_af
))
434 afp
->af_other_status(s
);
435 setbit(afmask
, afp
->af_af
);
440 af_all_tunnel_status(int s
)
443 uint8_t afmask
[howmany(AF_MAX
, NBBY
)];
445 memset(afmask
, 0, sizeof(afmask
));
446 for (afp
= afs
; afp
!= NULL
; afp
= afp
->af_next
) {
447 if (afp
->af_status_tunnel
== NULL
)
449 if (afp
->af_af
!= AF_UNSPEC
&& isset(afmask
, afp
->af_af
))
451 afp
->af_status_tunnel(s
);
452 setbit(afmask
, afp
->af_af
);
456 static struct cmd
*cmds
= NULL
;
459 cmd_register(struct cmd
*p
)
465 static const struct cmd
*
466 cmd_lookup(const char *name
)
468 #define N(a) (sizeof(a)/sizeof(a[0]))
471 for (p
= cmds
; p
!= NULL
; p
= p
->c_next
)
472 if (strcmp(name
, p
->c_name
) == 0)
479 callback_func
*cb_func
;
481 struct callback
*cb_next
;
483 static struct callback
*callbacks
= NULL
;
486 callback_register(callback_func
*func
, void *arg
)
490 cb
= malloc(sizeof(struct callback
));
492 errx(1, "unable to allocate memory for callback");
495 cb
->cb_next
= callbacks
;
499 /* specially-handled commands */
500 static void setifaddr(const char *, int, int, const struct afswtch
*);
501 static const struct cmd setifaddr_cmd
= DEF_CMD("ifaddr", 0, setifaddr
);
503 static void setifdstaddr(const char *, int, int, const struct afswtch
*);
504 static const struct cmd setifdstaddr_cmd
=
505 DEF_CMD("ifdstaddr", 0, setifdstaddr
);
508 ifconfig(int argc
, char *const *argv
, int iscreate
, const struct afswtch
*afp
)
510 const struct afswtch
*nafp
;
514 strlcpy(ifr
.ifr_name
, name
, sizeof ifr
.ifr_name
);
517 afp
= af_getbyname("inet");
518 ifr
.ifr_addr
.sa_family
=
519 afp
->af_af
== AF_LINK
|| afp
->af_af
== AF_UNSPEC
?
520 AF_INET
: afp
->af_af
;
522 if ((s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0)) < 0)
523 err(1, "socket(family %u,SOCK_DGRAM", ifr
.ifr_addr
.sa_family
);
528 p
= cmd_lookup(*argv
);
531 * Not a recognized command, choose between setting
532 * the interface address and the dst address.
534 p
= (setaddr
? &setifdstaddr_cmd
: &setifaddr_cmd
);
536 if (p
->c_u
.c_func
|| p
->c_u
.c_func2
) {
537 if (iscreate
&& !p
->c_iscloneop
) {
539 * Push the clone create callback so the new
540 * device is created and can be used for any
541 * remaining arguments.
545 errx(1, "internal error, no callback");
546 callbacks
= cb
->cb_next
;
547 cb
->cb_func(s
, cb
->cb_arg
);
550 * Handle any address family spec that
551 * immediately follows and potentially
552 * recreate the socket.
554 nafp
= af_getbyname(*argv
);
564 if (p
->c_parameter
== NEXTARG
) {
566 errx(1, "'%s' requires argument",
568 p
->c_u
.c_func(argv
[1], 0, s
, afp
);
570 } else if (p
->c_parameter
== OPTARG
) {
571 p
->c_u
.c_func(argv
[1], 0, s
, afp
);
574 } else if (p
->c_parameter
== NEXTARG2
) {
576 errx(1, "'%s' requires 2 arguments",
578 p
->c_u
.c_func2(argv
[1], argv
[2], s
, afp
);
579 argc
-= 2, argv
+= 2;
580 } else if (p
->c_parameter
== VAARGS
) {
581 ret
= p
->c_u
.c_funcv(argc
- 1, argv
+ 1, s
, afp
);
583 errx(1, "'%s' command error",
585 argc
-= ret
, argv
+= ret
;
587 p
->c_u
.c_func(*argv
, p
->c_parameter
, s
, afp
);
594 * Do any post argument processing required by the address family.
596 if (afp
->af_postproc
!= NULL
)
597 afp
->af_postproc(s
, afp
);
599 * Do deferred callbacks registered while processing
600 * command-line arguments.
602 for (cb
= callbacks
; cb
!= NULL
; cb
= cb
->cb_next
)
603 cb
->cb_func(s
, cb
->cb_arg
);
605 * Do deferred operations.
608 if (afp
->af_ridreq
== NULL
|| afp
->af_difaddr
== 0) {
609 warnx("interface %s cannot change %s addresses!",
615 strlcpy(afp
->af_ridreq
, name
, sizeof ifr
.ifr_name
);
616 ret
= ioctl(s
, afp
->af_difaddr
, afp
->af_ridreq
);
618 if (errno
== EADDRNOTAVAIL
&& (doalias
>= 0)) {
619 /* means no previous address for interface */
621 Perror("ioctl (SIOCDIFADDR)");
625 if (afp
->af_addreq
== NULL
|| afp
->af_aifaddr
== 0) {
626 warnx("interface %s cannot change %s addresses!",
631 if (newaddr
&& (setaddr
|| setmask
)) {
632 strlcpy(afp
->af_addreq
, name
, sizeof ifr
.ifr_name
);
633 if (ioctl(s
, afp
->af_aifaddr
, afp
->af_addreq
) < 0)
634 Perror("ioctl (SIOCAIFADDR)");
643 setifaddr(const char *addr
, int param
, int s
, const struct afswtch
*afp
)
645 if (afp
->af_getaddr
== NULL
)
648 * Delay the ioctl to set the interface addr until flags are all set.
649 * The address interpretation may depend on the flags,
650 * and the flags may change when the address is set.
653 if (doalias
== 0 && afp
->af_af
!= AF_LINK
)
655 afp
->af_getaddr(addr
, (doalias
>= 0 ? ADDR
: RIDADDR
));
659 settunnel(const char *src
, const char *dst
, int s
, const struct afswtch
*afp
)
661 struct addrinfo
*srcres
, *dstres
;
664 if (afp
->af_settunnel
== NULL
) {
665 warn("address family %s does not support tunnel setup",
670 if ((ecode
= getaddrinfo(src
, NULL
, NULL
, &srcres
)) != 0)
671 errx(1, "error in parsing address string: %s",
672 gai_strerror(ecode
));
674 if ((ecode
= getaddrinfo(dst
, NULL
, NULL
, &dstres
)) != 0)
675 errx(1, "error in parsing address string: %s",
676 gai_strerror(ecode
));
678 if (srcres
->ai_addr
->sa_family
!= dstres
->ai_addr
->sa_family
)
680 "source and destination address families do not match");
682 afp
->af_settunnel(s
, srcres
, dstres
);
684 freeaddrinfo(srcres
);
685 freeaddrinfo(dstres
);
690 deletetunnel(const char *vname
, int param
, int s
, const struct afswtch
*afp
)
693 if (ioctl(s
, SIOCDIFPHYADDR
, &ifr
) < 0)
694 err(1, "SIOCDIFPHYADDR");
698 setifnetmask(const char *addr
, int dummy __unused
, int s
,
699 const struct afswtch
*afp
)
701 if (afp
->af_getaddr
!= NULL
) {
703 afp
->af_getaddr(addr
, MASK
);
708 setifbroadaddr(const char *addr
, int dummy __unused
, int s
,
709 const struct afswtch
*afp
)
711 if (afp
->af_getaddr
!= NULL
)
712 afp
->af_getaddr(addr
, DSTADDR
);
716 setifipdst(const char *addr
, int dummy __unused
, int s
,
717 const struct afswtch
*afp
)
719 const struct afswtch
*inet
;
721 inet
= af_getbyname("inet");
724 inet
->af_getaddr(addr
, DSTADDR
);
730 notealias(const char *addr
, int param
, int s
, const struct afswtch
*afp
)
732 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
733 if (setaddr
&& doalias
== 0 && param
< 0)
734 if (afp
->af_addreq
!= NULL
&& afp
->af_ridreq
!= NULL
)
735 bcopy((caddr_t
)rqtosa(af_addreq
),
736 (caddr_t
)rqtosa(af_ridreq
),
737 rqtosa(af_addreq
)->sa_len
);
749 setifdstaddr(const char *addr
, int param __unused
, int s
,
750 const struct afswtch
*afp
)
752 if (afp
->af_getaddr
!= NULL
)
753 afp
->af_getaddr(addr
, DSTADDR
);
757 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
758 * of the ifreq structure, which may confuse other parts of ifconfig.
759 * Make a private copy so we can avoid that.
762 setifflags(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
767 bcopy((char *)&ifr
, (char *)&my_ifr
, sizeof(struct ifreq
));
769 if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
)&my_ifr
) < 0) {
770 Perror("ioctl (SIOCGIFFLAGS)");
773 strlcpy(my_ifr
.ifr_name
, name
, sizeof (my_ifr
.ifr_name
));
774 flags
= my_ifr
.ifr_flags
;
781 my_ifr
.ifr_flags
= flags
& 0xffff;
782 if (ioctl(s
, SIOCSIFFLAGS
, (caddr_t
)&my_ifr
) < 0)
787 setifcap(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
791 if (ioctl(s
, SIOCGIFCAP
, (caddr_t
)&ifr
) < 0) {
792 Perror("ioctl (SIOCGIFCAP)");
795 flags
= ifr
.ifr_curcap
;
801 flags
&= ifr
.ifr_reqcap
;
802 ifr
.ifr_reqcap
= flags
;
803 if (ioctl(s
, SIOCSIFCAP
, (caddr_t
)&ifr
) < 0)
808 setifmetric(const char *val
, int dummy __unused
, int s
,
809 const struct afswtch
*afp
)
811 strlcpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
812 ifr
.ifr_metric
= atoi(val
);
813 if (ioctl(s
, SIOCSIFMETRIC
, (caddr_t
)&ifr
) < 0)
814 warn("ioctl (set metric)");
818 setifmtu(const char *val
, int dummy __unused
, int s
,
819 const struct afswtch
*afp
)
821 strlcpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
822 ifr
.ifr_mtu
= atoi(val
);
823 if (ioctl(s
, SIOCSIFMTU
, (caddr_t
)&ifr
) < 0)
824 warn("ioctl (set mtu)");
829 setifname(const char *val
, int dummy __unused
, int s
,
830 const struct afswtch
*afp
)
834 newname
= strdup(val
);
835 if (newname
== NULL
) {
836 warn("no memory to set ifname");
839 ifr
.ifr_data
= newname
;
840 if (ioctl(s
, SIOCSIFNAME
, (caddr_t
)&ifr
) < 0) {
841 warn("ioctl (set name)");
845 strlcpy(name
, newname
, sizeof(name
));
851 setrouter(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
853 if (afp
->af_setrouter
== NULL
) {
854 warn("address family %s does not support router mode",
859 afp
->af_setrouter(s
, value
);
863 routermode(int argc
, char *const *argv
, int s
, const struct afswtch
*afp
)
865 return (*afp
->af_routermode
)(s
, argc
, argv
);
870 setifdesc(const char *val
, int dummy __unused
, int s
, const struct afswtch
*afp
)
872 struct if_descreq ifdr
;
874 bzero(&ifdr
, sizeof (ifdr
));
875 strlcpy(ifdr
.ifdr_name
, name
, sizeof (ifdr
.ifdr_name
));
876 ifdr
.ifdr_len
= strlen(val
);
877 strlcpy((char *)ifdr
.ifdr_desc
, val
, sizeof (ifdr
.ifdr_desc
));
879 if (ioctl(s
, SIOCSIFDESC
, (caddr_t
)&ifdr
) < 0) {
880 warn("ioctl (set desc)");
885 settbr(const char *val
, int dummy __unused
, int s
, const struct afswtch
*afp
)
887 struct if_linkparamsreq iflpr
;
890 u_int32_t percent
= 0;
894 bzero(&iflpr
, sizeof (iflpr
));
895 strlcpy(iflpr
.iflpr_name
, name
, sizeof (iflpr
.iflpr_name
));
897 bps
= strtold(val
, &cp
);
898 if (val
== cp
|| errno
!= 0) {
899 warn("Invalid value '%s'", val
);
902 rate
= (u_int64_t
)bps
;
904 if (!strcmp(cp
, "b") || !strcmp(cp
, "bps")) {
906 } else if (!strcmp(cp
, "Kb") || !strcmp(cp
, "Kbps")) {
908 } else if (!strcmp(cp
, "Mb") || !strcmp(cp
, "Mbps")) {
910 } else if (!strcmp(cp
, "Gb") || !strcmp(cp
, "Gbps")) {
911 rate
*= 1000 * 1000 * 1000;
912 } else if (!strcmp(cp
, "%")) {
914 if (percent
== 0 || percent
> 100) {
915 printf("Value out of range '%s'", val
);
918 } else if (*cp
!= '\0') {
919 printf("Unknown unit '%s'", cp
);
923 iflpr
.iflpr_output_tbr_rate
= rate
;
924 iflpr
.iflpr_output_tbr_percent
= percent
;
925 if (ioctl(s
, SIOCSIFLINKPARAMS
, &iflpr
) < 0 &&
926 errno
!= ENOENT
&& errno
!= ENXIO
&& errno
!= ENODEV
) {
927 warn("ioctl (set link params)");
928 } else if (errno
== ENXIO
) {
929 printf("TBR cannot be set on %s\n", name
);
930 } else if (errno
== 0 && rate
== 0) {
931 printf("%s: TBR is now disabled\n", name
);
932 } else if (errno
== ENODEV
) {
933 printf("%s: requires absolute TBR rate\n", name
);
934 } else if (percent
!= 0) {
935 printf("%s: TBR rate set to %u%% of effective link rate\n",
938 printf("%s: TBR rate set to %s\n", name
, bps_to_str(rate
));
942 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
944 get_int64(uint64_t *i
, char const *s
)
947 *i
= strtol(s
, &cp
, 10);
948 if (cp
== s
|| errno
!= 0) {
955 get_int32(uint32_t *i
, char const *s
)
958 *i
= strtol(s
, &cp
, 10);
959 if (cp
== s
|| errno
!= 0) {
966 get_percent(double *d
, const char *s
)
969 *d
= strtod(s
, &cp
) / (double)100;
970 if (*d
== HUGE_VALF
|| *d
== HUGE_VALL
) {
973 if (*d
== 0.0 || (*cp
!= '\0' && strcmp(cp
, "%") != 0)) {
980 get_percent_fixed_point(uint32_t *i
, const char *s
)
984 if (get_percent(&p
, s
) != 0){
988 *i
= p
* IF_NETEM_PARAMS_PSCALE
;
993 netem_parse_args(struct if_netem_params
*p
, int argc
, char *const *argv
)
995 int argc_saved
= argc
;
996 uint64_t bandwitdh
= 0;
997 uint32_t latency
= 0, jitter
= 0;
998 uint32_t corruption
= 0;
999 uint32_t duplication
= 0;
1000 uint32_t loss_p_gr_gl
= 0, loss_p_gr_bl
= 0, loss_p_bl_br
= 0,
1001 loss_p_bl_gr
= 0, loss_p_br_bl
= 0;
1002 uint32_t reordering
= 0;
1004 bzero(p
, sizeof (*p
));
1006 /* take out "input"/"output" */
1009 for ( ; argc
> 0; ) {
1010 if (strcmp(*argv
, "bandwidth") == 0) {
1012 if (argc
<= 0 || get_int64(&bandwitdh
, *argv
) != 0) {
1013 err(1, "Invalid value '%s'", *argv
);
1016 } else if (strcmp(*argv
, "corruption") == 0) {
1019 get_percent_fixed_point(&corruption
, *argv
) != 0) {
1020 err(1, "Invalid value '%s'", *argv
);
1023 } else if (strcmp(*argv
, "delay") == 0) {
1025 if (argc
<= 0 || get_int32(&latency
, *argv
) != 0) {
1026 err(1, "Invalid value '%s'", *argv
);
1029 if (argc
> 0 && get_int32(&jitter
, *argv
) == 0) {
1032 } else if (strcmp(*argv
, "duplication") == 0) {
1035 get_percent_fixed_point(&duplication
, *argv
) != 0) {
1036 err(1, "Invalid value '%s'", *argv
);
1040 } else if (strcmp(*argv
, "loss") == 0) {
1042 if (argc
<= 0 || get_percent_fixed_point(&loss_p_gr_gl
, *argv
) != 0) {
1043 err(1, "Invalid value '%s'", *argv
);
1045 /* we may have all 5 probs, use naive model if not */
1047 if (argc
<= 0 || get_percent_fixed_point(&loss_p_gr_bl
, *argv
) != 0) {
1050 /* if more than p_gr_gl, then should have all probs */
1052 if (argc
<= 0 || get_percent_fixed_point(&loss_p_bl_br
, *argv
) != 0) {
1053 err(1, "Invalid value '%s' for p_bl_br", *argv
);
1056 if (argc
<= 0 || get_percent_fixed_point(&loss_p_bl_gr
, *argv
) != 0) {
1057 err(1, "Invalid value '%s' for p_bl_gr", *argv
);
1060 if (argc
<= 0 || get_percent_fixed_point(&loss_p_br_bl
, *argv
) != 0) {
1061 err(1, "Invalid value '%s' for p_br_bl", *argv
);
1064 } else if (strcmp(*argv
, "reordering") == 0) {
1066 if (argc
<= 0 || get_percent_fixed_point(&reordering
, *argv
) != 0) {
1067 err(1, "Invalid value '%s'", *argv
);
1075 if (corruption
> IF_NETEM_PARAMS_PSCALE
) {
1076 err(1, "corruption percentage > 100%%");
1079 if (duplication
> IF_NETEM_PARAMS_PSCALE
) {
1080 err(1, "duplication percentage > 100%%");
1083 if (duplication
> 0 && latency
== 0) {
1084 /* we need to insert dup'ed packet with latency */
1085 err(1, "duplication needs latency param");
1088 if (latency
> 1000) {
1089 err(1, "latency %dms too big (> 1 sec)", latency
);
1092 if (jitter
* 3 > latency
) {
1093 err(1, "jitter %dms too big (latency %dms)", jitter
, latency
);
1096 /* if gr_gl == 0 (no loss), other prob should all be zero */
1097 if (loss_p_gr_gl
== 0 &&
1098 (loss_p_gr_bl
!= 0 || loss_p_bl_br
!= 0 || loss_p_bl_gr
!= 0 ||
1099 loss_p_br_bl
!= 0)) {
1100 err(1, "loss params not all zero when gr_gl is zero");
1103 /* check state machine transition prob integrity */
1104 if (loss_p_gr_gl
> IF_NETEM_PARAMS_PSCALE
||
1105 /* gr_gl = IF_NETEM_PARAMS_PSCALE for total loss */
1106 loss_p_gr_bl
> IF_NETEM_PARAMS_PSCALE
||
1107 loss_p_bl_br
> IF_NETEM_PARAMS_PSCALE
||
1108 loss_p_bl_gr
> IF_NETEM_PARAMS_PSCALE
||
1109 loss_p_br_bl
> IF_NETEM_PARAMS_PSCALE
||
1110 loss_p_gr_gl
+ loss_p_gr_bl
> IF_NETEM_PARAMS_PSCALE
||
1111 loss_p_bl_br
+ loss_p_bl_gr
> IF_NETEM_PARAMS_PSCALE
) {
1112 err(1, "loss params too big");
1115 if (reordering
> IF_NETEM_PARAMS_PSCALE
) {
1116 err(1, "reordering percentage > 100%%");
1119 p
->ifnetem_bandwidth_bps
= bandwitdh
;
1120 p
->ifnetem_latency_ms
= latency
;
1121 p
->ifnetem_jitter_ms
= jitter
;
1122 p
->ifnetem_corruption_p
= corruption
;
1123 p
->ifnetem_duplication_p
= duplication
;
1124 p
->ifnetem_loss_p_gr_gl
= loss_p_gr_gl
;
1125 p
->ifnetem_loss_p_gr_bl
= loss_p_gr_bl
;
1126 p
->ifnetem_loss_p_bl_br
= loss_p_bl_br
;
1127 p
->ifnetem_loss_p_bl_gr
= loss_p_bl_gr
;
1128 p
->ifnetem_loss_p_br_bl
= loss_p_br_bl
;
1129 p
->ifnetem_reordering_p
= reordering
;
1131 return (argc_saved
- argc
);
1135 print_netem_params(struct if_netem_params
*p
, const char *desc
)
1137 struct if_netem_params zero_params
;
1138 double pscale
= IF_NETEM_PARAMS_PSCALE
/ 100;
1139 bzero(&zero_params
, sizeof (zero_params
));
1141 if (memcmp(p
, &zero_params
, sizeof (zero_params
)) == 0) {
1142 printf("%s NetEm Disabled\n\n", desc
);
1145 "%s NetEm Parameters\n"
1146 "\tbandwidth rate %llubps\n"
1147 "\tdelay latency %dms\n"
1149 desc
, p
->ifnetem_bandwidth_bps
,
1150 p
->ifnetem_latency_ms
, p
->ifnetem_jitter_ms
);
1151 if (p
->ifnetem_loss_p_gr_bl
== 0 &&
1152 p
->ifnetem_loss_p_bl_br
== 0 &&
1153 p
->ifnetem_loss_p_bl_gr
== 0 &&
1154 p
->ifnetem_loss_p_br_bl
== 0) {
1157 (double) p
->ifnetem_loss_p_gr_gl
/ pscale
);
1160 "\tloss GAP_RECV -> GAP_LOSS %.3f%%\n"
1161 "\t GAP_RECV -> BURST_LOSS %.3f%%\n"
1162 "\t BURST_LOSS -> BURST_RECV %.3f%%\n"
1163 "\t BURST_LOSS -> GAP_RECV %.3f%%\n"
1164 "\t BURST_RECV -> BURST_LOSS %.3f%%\n",
1165 (double) p
->ifnetem_loss_p_gr_gl
/ pscale
,
1166 (double) p
->ifnetem_loss_p_gr_bl
/ pscale
,
1167 (double) p
->ifnetem_loss_p_bl_br
/ pscale
,
1168 (double) p
->ifnetem_loss_p_bl_gr
/ pscale
,
1169 (double) p
->ifnetem_loss_p_br_bl
/ pscale
);
1172 "\tcorruption %.3f%%\n"
1173 "\treordering %.3f%%\n\n",
1174 (double) p
->ifnetem_corruption_p
/ pscale
,
1175 (double) p
->ifnetem_reordering_p
/ pscale
);
1180 setnetem(int argc
, char *const *argv
, int s
, const struct afswtch
*afp
)
1182 struct if_linkparamsreq iflpr
;
1183 struct if_netem_params input_params
, output_params
;
1184 int ret
= 0, error
= 0;
1186 bzero(&iflpr
, sizeof (iflpr
));
1187 bzero(&input_params
, sizeof (input_params
));
1188 bzero(&output_params
, sizeof (output_params
));
1191 if (strcmp(argv
[0], "input") == 0) {
1192 ret
= netem_parse_args(&input_params
, argc
, argv
);
1193 } else if (strcmp(argv
[0], "output") == 0) {
1194 ret
= netem_parse_args(&output_params
, argc
, argv
);
1195 } else if (strcmp(argv
[0], "-h") == 0 || strcmp(argv
[0], "--help") == 0) {
1198 fprintf(stderr
, "uknown option %s\n", argv
[0]);
1207 strlcpy(iflpr
.iflpr_name
, name
, sizeof (iflpr
.iflpr_name
));
1208 error
= ioctl(s
, SIOCGIFLINKPARAMS
, &iflpr
);
1210 warn("ioctl (get link params)");
1214 print_netem_params(&iflpr
.iflpr_input_netem
, "Input");
1215 print_netem_params(&iflpr
.iflpr_output_netem
, "Output");
1217 } else if (argc
== 1) {
1218 if (strcmp(argv
[0], "input") == 0) {
1219 bzero(&iflpr
.iflpr_input_netem
,
1220 sizeof (iflpr
.iflpr_input_netem
));
1221 } else if (strcmp(argv
[0], "output") == 0) {
1222 bzero(&iflpr
.iflpr_output_netem
,
1223 sizeof (iflpr
.iflpr_output_netem
));
1225 fprintf(stderr
, "uknown option %s\n", argv
[0]);
1228 printf("%s: netem is now disabled for %s\n", name
, argv
[0]);
1231 if (strcmp(argv
[0], "input") == 0) {
1232 iflpr
.iflpr_input_netem
= input_params
;
1233 } else if (strcmp(argv
[0], "output") == 0) {
1234 iflpr
.iflpr_output_netem
= output_params
;
1238 error
= ioctl(s
, SIOCSIFLINKPARAMS
, &iflpr
);
1239 if (error
< 0 && errno
!= ENOENT
&& errno
!= ENXIO
&& errno
!= ENODEV
) {
1240 warn("ioctl (set link params)");
1241 } else if (errno
== ENXIO
) {
1242 printf("netem cannot be set on %s\n", name
);
1244 printf("%s: netem configured\n", name
);
1249 fprintf(stderr
, "Usage:\n"
1250 "\tTo enable/set netem params\n"
1251 "\t\tnetem <input|output>\n"
1252 "\t\t [ bandwidth BIT_PER_SEC ]\n"
1253 "\t\t [ delay DELAY_MSEC [ JITTER_MSEC ] ]\n"
1254 "\t\t [ loss PERCENTAGE ]\n"
1255 "\t\t [ duplication PERCENTAGE ]\n"
1256 "\t\t [ reordering PERCENTAGE ]\n\n"
1257 "\tTo disable <input|output> netem\n"
1258 "\t\tnetem <input|output>\n\n"
1259 "\tTo show current settings\n"
1266 setthrottle(const char *val
, int dummy __unused
, int s
,
1267 const struct afswtch
*afp
)
1269 struct if_throttlereq iftr
;
1273 bzero(&iftr
, sizeof (iftr
));
1274 strlcpy(iftr
.ifthr_name
, name
, sizeof (iftr
.ifthr_name
));
1276 iftr
.ifthr_level
= strtold(val
, &cp
);
1277 if (val
== cp
|| errno
!= 0) {
1278 warn("Invalid value '%s'", val
);
1282 if (ioctl(s
, SIOCSIFTHROTTLE
, &iftr
) < 0 && errno
!= ENXIO
) {
1283 warn("ioctl (set throttling level)");
1284 } else if (errno
== ENXIO
) {
1285 printf("throttling level cannot be set on %s\n", name
);
1287 printf("%s: throttling level set to %d\n", name
,
1293 setdisableoutput(const char *val
, int dummy __unused
, int s
,
1294 const struct afswtch
*afp
)
1299 bzero(&ifr
, sizeof (ifr
));
1300 strlcpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
1302 ifr
.ifr_ifru
.ifru_disable_output
= strtold(val
, &cp
);
1303 if (val
== cp
|| errno
!= 0) {
1304 warn("Invalid value '%s'", val
);
1308 if (ioctl(s
, SIOCSIFDISABLEOUTPUT
, &ifr
) < 0 && errno
!= ENXIO
) {
1309 warn("ioctl set disable output");
1310 } else if (errno
== ENXIO
) {
1311 printf("output thread can not be disabled on %s\n", name
);
1313 printf("output %s on %s\n",
1314 ((ifr
.ifr_ifru
.ifru_disable_output
== 0) ? "enabled" : "disabled"),
1320 setlog(const char *val
, int dummy __unused
, int s
,
1321 const struct afswtch
*afp
)
1326 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1328 ifr
.ifr_log
.ifl_level
= strtold(val
, &cp
);
1329 if (val
== cp
|| errno
!= 0) {
1330 warn("Invalid value '%s'", val
);
1333 ifr
.ifr_log
.ifl_flags
= (IFRLOGF_DLIL
|IFRLOGF_FAMILY
|IFRLOGF_DRIVER
|
1336 if (ioctl(s
, SIOCSIFLOG
, &ifr
) < 0)
1337 warn("ioctl (set logging parameters)");
1341 setcl2k(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1343 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1344 ifr
.ifr_ifru
.ifru_2kcl
= value
;
1346 if (ioctl(s
, SIOCSIF2KCL
, (caddr_t
)&ifr
) < 0)
1351 setexpensive(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1353 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1354 ifr
.ifr_ifru
.ifru_expensive
= value
;
1356 if (ioctl(s
, SIOCSIFEXPENSIVE
, (caddr_t
)&ifr
) < 0)
1360 #ifdef SIOCSIFCONSTRAINED
1362 setconstrained(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1364 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1365 ifr
.ifr_ifru
.ifru_constrained
= value
;
1367 if (ioctl(s
, SIOCSIFCONSTRAINED
, (caddr_t
)&ifr
) < 0)
1372 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
1374 setifmpklog(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1376 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1377 ifr
.ifr_ifru
.ifru_mpk_log
= value
;
1379 if (ioctl(s
, SIOCSIFMPKLOG
, (caddr_t
)&ifr
) < 0)
1385 settimestamp(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1387 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1390 if (ioctl(s
, SIOCSIFTIMESTAMPDISABLE
, (caddr_t
)&ifr
) < 0)
1393 if (ioctl(s
, SIOCSIFTIMESTAMPENABLE
, (caddr_t
)&ifr
) < 0)
1399 setecnmode(const char *val
, int dummy __unused
, int s
,
1400 const struct afswtch
*afp
)
1404 if (strcmp(val
, "default") == 0)
1405 ifr
.ifr_ifru
.ifru_ecn_mode
= IFRTYPE_ECN_DEFAULT
;
1406 else if (strcmp(val
, "enable") == 0)
1407 ifr
.ifr_ifru
.ifru_ecn_mode
= IFRTYPE_ECN_ENABLE
;
1408 else if (strcmp(val
, "disable") == 0)
1409 ifr
.ifr_ifru
.ifru_ecn_mode
= IFRTYPE_ECN_DISABLE
;
1411 ifr
.ifr_ifru
.ifru_ecn_mode
= strtold(val
, &cp
);
1412 if (val
== cp
|| errno
!= 0) {
1413 warn("Invalid ECN mode value '%s'", val
);
1418 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1420 if (ioctl(s
, SIOCSECNMODE
, (caddr_t
)&ifr
) < 0)
1421 Perror("ioctl(SIOCSECNMODE)");
1425 setprobeconnectivity(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1427 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1428 ifr
.ifr_ifru
.ifru_probe_connectivity
= value
;
1430 if (ioctl(s
, SIOCSIFPROBECONNECTIVITY
, (caddr_t
)&ifr
) < 0)
1434 #if defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED)
1437 setqosmarking(const char *cmd
, const char *arg
, int s
, const struct afswtch
*afp
)
1441 #if (DEBUG | DEVELOPMENT)
1442 printf("%s(%s, %s)\n", __func__
, cmd
, arg
);
1443 #endif /* (DEBUG | DEVELOPMENT) */
1445 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1447 if (strcmp(cmd
, "mode") == 0) {
1448 ioc
= SIOCSQOSMARKINGMODE
;
1450 if (strcmp(arg
, "fastlane") == 0)
1451 ifr
.ifr_qosmarking_mode
= IFRTYPE_QOSMARKING_FASTLANE
;
1452 #if defined(IFRTYPE_QOSMARKING_RFC4594)
1453 else if (strcmp(arg
, "rfc4594") == 0)
1454 ifr
.ifr_qosmarking_mode
= IFRTYPE_QOSMARKING_RFC4594
;
1456 else if (strcasecmp(arg
, "none") == 0 || strcasecmp(arg
, "off") == 0)
1457 ifr
.ifr_qosmarking_mode
= IFRTYPE_QOSMARKING_MODE_NONE
;
1459 err(EX_USAGE
, "bad value for qosmarking mode: %s", arg
);
1460 } else if (strcmp(cmd
, "enabled") == 0) {
1461 ioc
= SIOCSQOSMARKINGENABLED
;
1462 if (strcmp(arg
, "1") == 0 || strcasecmp(arg
, "on") == 0||
1463 strcasecmp(arg
, "yes") == 0 || strcasecmp(arg
, "true") == 0)
1464 ifr
.ifr_qosmarking_enabled
= 1;
1465 else if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "off") == 0||
1466 strcasecmp(arg
, "no") == 0 || strcasecmp(arg
, "false") == 0)
1467 ifr
.ifr_qosmarking_enabled
= 0;
1469 err(EX_USAGE
, "bad value for qosmarking enabled: %s", arg
);
1471 err(EX_USAGE
, "qosmarking takes mode or enabled");
1474 if (ioctl(s
, ioc
, (caddr_t
)&ifr
) < 0)
1475 err(EX_OSERR
, "ioctl(%s, %s)", cmd
, arg
);
1479 setfastlane(const char *cmd
, const char *arg
, int s
, const struct afswtch
*afp
)
1481 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1483 warnx("### fastlane is obsolete, use qosmarking ###");
1485 if (strcmp(cmd
, "capable") == 0) {
1486 if (strcmp(arg
, "1") == 0 || strcasecmp(arg
, "on") == 0||
1487 strcasecmp(arg
, "yes") == 0 || strcasecmp(arg
, "true") == 0)
1488 setqosmarking("mode", "fastlane", s
, afp
);
1489 else if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "off") == 0||
1490 strcasecmp(arg
, "no") == 0 || strcasecmp(arg
, "false") == 0)
1491 setqosmarking("mode", "off", s
, afp
);
1493 err(EX_USAGE
, "bad value for fastlane %s", cmd
);
1494 } else if (strcmp(cmd
, "enable") == 0) {
1495 if (strcmp(arg
, "1") == 0 || strcasecmp(arg
, "on") == 0||
1496 strcasecmp(arg
, "yes") == 0 || strcasecmp(arg
, "true") == 0)
1497 setqosmarking("enabled", "1", s
, afp
);
1498 else if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "off") == 0||
1499 strcasecmp(arg
, "no") == 0 || strcasecmp(arg
, "false") == 0)
1500 setqosmarking("enabled", "0", s
, afp
);
1502 err(EX_USAGE
, "bad value for fastlane %s", cmd
);
1504 err(EX_USAGE
, "fastlane takes capable or enable");
1508 #else /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
1511 setfastlane(const char *cmd
, const char *arg
, int s
, const struct afswtch
*afp
)
1516 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1518 if (strcmp(cmd
, "capable") == 0)
1519 ioc
= SIOCSFASTLANECAPABLE
;
1520 else if (strcmp(cmd
, "enable") == 0)
1521 ioc
= SIOCSFASTLEENABLED
;
1523 err(EX_USAGE
, "fastlane takes capable or enabled");
1525 if (strcmp(arg
, "1") == 0 || strcasecmp(arg
, "on") == 0||
1526 strcasecmp(arg
, "yes") == 0 || strcasecmp(arg
, "true") == 0)
1528 else if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "off") == 0||
1529 strcasecmp(arg
, "no") == 0 || strcasecmp(arg
, "false") == 0)
1532 err(EX_USAGE
, "bad value for fastlane %s", cmd
);
1534 if (ioc
== SIOCSFASTLANECAPABLE
)
1535 ifr
.ifr_fastlane_capable
= value
;
1537 ifr
.ifr_fastlane_enabled
= value
;
1539 if (ioctl(s
, ioc
, (caddr_t
)&ifr
) < 0)
1540 err(EX_OSERR
, "ioctl(%s, %s)", cmd
, arg
);
1545 setqosmarking(const char *cmd
, const char *arg
, int s
, const struct afswtch
*afp
)
1547 if (strcmp(cmd
, "mode") == 0) {
1548 if (strcmp(arg
, "fastlane") == 0)
1549 setfastlane("capable", "on", s
, afp
);
1550 else if (strcmp(arg
, "none") == 0)
1551 setfastlane("capable", "off", s
, afp
);
1553 err(EX_USAGE
, "bad value for qosmarking mode: %s", arg
);
1554 } else if (strcmp(cmd
, "enabled") == 0) {
1555 if (strcmp(arg
, "1") == 0 || strcasecmp(arg
, "on") == 0||
1556 strcasecmp(arg
, "yes") == 0 || strcasecmp(arg
, "true") == 0)
1557 setfastlane("enable", "on", s
, afp
);
1558 else if (strcmp(arg
, "0") == 0 || strcasecmp(arg
, "off") == 0||
1559 strcasecmp(arg
, "no") == 0 || strcasecmp(arg
, "false") == 0)
1560 setfastlane("enable", "off", s
, afp
);
1562 err(EX_USAGE
, "bad value for qosmarking enabled: %s", arg
);
1564 err(EX_USAGE
, "qosmarking takes mode or enabled");
1568 #endif /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
1571 setlowpowermode(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1573 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1574 ifr
.ifr_low_power_mode
= !!value
;
1576 if (ioctl(s
, SIOCSIFLOWPOWER
, (caddr_t
)&ifr
) < 0)
1580 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
1586 static struct str2num subfamily_str2num
[] = {
1587 { .str
= "any", .num
= IFRTYPE_SUBFAMILY_ANY
},
1588 { .str
= "USB", .num
= IFRTYPE_SUBFAMILY_USB
},
1589 { .str
= "Bluetooth", .num
= IFRTYPE_SUBFAMILY_BLUETOOTH
},
1590 { .str
= "Wi-Fi", .num
= IFRTYPE_SUBFAMILY_WIFI
},
1591 { .str
= "wifi", .num
= IFRTYPE_SUBFAMILY_WIFI
},
1592 { .str
= "Thunderbolt", .num
= IFRTYPE_SUBFAMILY_THUNDERBOLT
},
1593 { .str
= "reserverd", .num
= IFRTYPE_SUBFAMILY_RESERVED
},
1594 { .str
= "intcoproc", .num
= IFRTYPE_SUBFAMILY_INTCOPROC
},
1595 { .str
= "QuickRelay", .num
= IFRTYPE_SUBFAMILY_QUICKRELAY
},
1596 { .str
= "Default", .num
= IFRTYPE_SUBFAMILY_DEFAULT
},
1597 { .str
= NULL
, .num
= 0 },
1601 get_num_from_str(struct str2num
* str2nums
, const char *str
)
1603 struct str2num
*str2num
= str2nums
;
1605 while (str2num
!= NULL
&& str2num
->str
!= NULL
) {
1606 if (strcasecmp(str2num
->str
, str
) == 0) {
1607 return str2num
->num
;
1615 setifsubfamily(const char *val
, int dummy __unused
, int s
,
1616 const struct afswtch
*afp
)
1618 strlcpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
1621 uint32_t subfamily
= strtoul(val
, &endptr
, 0);
1623 subfamily
= get_num_from_str(subfamily_str2num
, val
);
1624 if (subfamily
== 0) {
1629 ifr
.ifr_type
.ift_subfamily
= subfamily
;
1630 if (ioctl(s
, SIOCSIFSUBFAMILY
, (caddr_t
)&ifr
) < 0)
1631 warn("ioctl(SIOCSIFSUBFAMILY)");
1635 setifavailability(const char *vname
, int value
, int s
, const struct afswtch
*afp
)
1637 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1638 ifr
.ifr_interface_state
.valid_bitmask
= IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID
;
1640 ifr
.ifr_interface_state
.interface_availability
= IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE
;
1642 ifr
.ifr_interface_state
.interface_availability
= IF_INTERFACE_STATE_INTERFACE_AVAILABLE
;
1644 if (ioctl(s
, SIOCSIFINTERFACESTATE
, (caddr_t
)&ifr
) < 0)
1645 warn("ioctl(SIOCSIFINTERFACESTATE)");
1650 show_routermode(int s
)
1652 struct afswtch
*afp
;
1654 afp
= af_getbyname("inet");
1656 (*afp
->af_routermode
)(s
, 0, NULL
);
1661 show_routermode6(void)
1663 struct afswtch
*afp
;
1666 afp
= af_getbyname("inet6");
1669 s
= socket(AF_INET6
, SOCK_DGRAM
, 0);
1675 (*afp
->af_routermode
)(s
, 0, NULL
);
1680 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
1681 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
1685 "\020\1AUTOCONFIGURING\4PROBE_CONNECTIVITY\5FASTLN_CAP\6IPV6_DISABLED\7ACCEPT_RTADV\10TXSTART\11RXPOLL" \
1686 "\12VLAN\13BOND\14ARPLL\15CLAT46\16NOAUTOIPV6LL\17EXPENSIVE\20ROUTER4" \
1687 "\22LOCALNET_PRIVATE\23ND6ALT\24RESTRICTED_RECV\25AWDL\26NOACKPRI" \
1688 "\27AWDL_RESTRICTED\30CL2K\31ECN_ENABLE\32ECN_DISABLE\33CHANNEL_DRV\34CA" \
1689 "\35SENDLIST\36DIRECTLINK\37FASTLN_ON\40UPDOWNCHANGE"
1692 "\020\1WOL\2TIMESTAMP\3NOAUTONX\4LEGACY\5TXLOWINET\6RXLOWINET\7ALLOCKPI" \
1693 "\10LOWPOWER\11MPKLOG\12CONSTRAINED"
1696 "\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \
1697 "\6TSO4\7TSO6\10LRO\11AV\12TXSTATUS\13CHANNEL_IO\14HW_TIMESTAMP\15SW_TIMESTAMP" \
1698 "\16PARTIAL_CSUM\17ZEROINVERT_CSUM"
1700 #define IFRLOGF_BITS \
1701 "\020\1DLIL\21FAMILY\31DRIVER\35FIRMWARE"
1704 * Print the status of the interface. If an address family was
1705 * specified, show only it; otherwise, show them all.
1708 status(const struct afswtch
*afp
, const struct sockaddr_dl
*sdl
,
1709 struct ifaddrs
*ifa
)
1711 struct ifaddrs
*ift
;
1714 struct if_descreq ifdr
;
1715 struct if_linkparamsreq iflpr
;
1717 struct ifmibdata_supplemental ifmsupp
;
1718 size_t miblen
= sizeof(struct ifmibdata_supplemental
);
1719 u_int64_t eflags
= 0;
1720 u_int64_t xflags
= 0;
1725 afp
= af_getbyname("inet");
1729 ifr
.ifr_addr
.sa_family
= afp
->af_af
== AF_LINK
? AF_INET
: afp
->af_af
;
1730 strlcpy(ifr
.ifr_name
, name
, sizeof(ifr
.ifr_name
));
1732 s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0);
1734 err(1, "socket(family %u,SOCK_DGRAM)", ifr
.ifr_addr
.sa_family
);
1736 printf("%s: ", name
);
1737 printb("flags", ifa
->ifa_flags
, IFFBITS
);
1738 if (ioctl(s
, SIOCGIFMETRIC
, &ifr
) != -1)
1740 printf(" metric %d", ifr
.ifr_metric
);
1741 if (ioctl(s
, SIOCGIFMTU
, &ifr
) != -1)
1742 printf(" mtu %d", ifr
.ifr_mtu
);
1743 if (showrtref
&& ioctl(s
, SIOCGIFGETRTREFCNT
, &ifr
) != -1)
1744 printf(" rtref %d", ifr
.ifr_route_refcnt
);
1746 unsigned int ifindex
= if_nametoindex(ifa
->ifa_name
);
1748 printf(" index %u", ifindex
);
1750 #ifdef SIOCGIFCONSTRAINED
1751 // Constrained is stored in if_xflags which isn't exposed directly
1752 if (ioctl(s
, SIOCGIFCONSTRAINED
, (caddr_t
)&ifr
) == 0 &&
1753 ifr
.ifr_constrained
!= 0) {
1754 printf(" constrained");
1759 if (verbose
&& ioctl(s
, SIOCGIFEFLAGS
, (caddr_t
)&ifr
) != -1 &&
1760 (eflags
= ifr
.ifr_eflags
) != 0) {
1761 printb("\teflags", eflags
, IFEFBITS
);
1765 #if defined(SIOCGIFXFLAGS)
1766 if (verbose
&& ioctl(s
, SIOCGIFXFLAGS
, (caddr_t
)&ifr
) != -1 &&
1767 (xflags
= ifr
.ifr_xflags
) != 0) {
1768 printb("\txflags", xflags
, IFXFBITS
);
1773 if (ioctl(s
, SIOCGIFCAP
, (caddr_t
)&ifr
) == 0) {
1774 if (ifr
.ifr_curcap
!= 0) {
1775 curcap
= ifr
.ifr_curcap
;
1776 printb("\toptions", ifr
.ifr_curcap
, IFCAPBITS
);
1779 if (supmedia
&& ifr
.ifr_reqcap
!= 0) {
1780 printb("\tcapabilities", ifr
.ifr_reqcap
, IFCAPBITS
);
1787 for (ift
= ifa
; ift
!= NULL
; ift
= ift
->ifa_next
) {
1788 if (ift
->ifa_addr
== NULL
)
1790 if (strcmp(ifa
->ifa_name
, ift
->ifa_name
) != 0)
1793 const struct afswtch
*p
;
1794 p
= af_getbyfamily(ift
->ifa_addr
->sa_family
);
1795 if (p
!= NULL
&& p
->af_status
!= NULL
)
1796 p
->af_status(s
, ift
);
1797 } else if (afp
->af_af
== ift
->ifa_addr
->sa_family
)
1798 afp
->af_status(s
, ift
);
1801 /* Print CLAT46 address */
1802 clat46_addr(s
, name
);
1804 /* Print NAT64 prefix */
1805 nat64_status(s
, name
);
1808 if (allfamilies
|| afp
->af_af
== AF_LINK
) {
1809 const struct afswtch
*lafp
;
1812 * Hack; the link level address is received separately
1813 * from the routing information so any address is not
1814 * handled above. Cobble together an entry and invoke
1815 * the status method specially.
1817 lafp
= af_getbyname("lladdr");
1819 info
.rti_info
[RTAX_IFA
] = (struct sockaddr
*)sdl
;
1820 lafp
->af_status(s
, &info
);
1826 else if (afp
->af_other_status
!= NULL
)
1827 afp
->af_other_status(s
);
1829 strlcpy(ifs
.ifs_name
, name
, sizeof ifs
.ifs_name
);
1830 if (ioctl(s
, SIOCGIFSTATUS
, &ifs
) == 0)
1831 printf("%s", ifs
.ascii
);
1833 /* The rest is for when verbose is set; if not set, we're done */
1837 if (ioctl(s
, SIOCGIFTYPE
, &ifr
) != -1) {
1838 char *c
= ift2str(ifr
.ifr_type
.ift_type
,
1839 ifr
.ifr_type
.ift_family
, ifr
.ifr_type
.ift_subfamily
);
1841 printf("\ttype: %s\n", c
);
1845 if (ioctl(s
, SIOCGIFFUNCTIONALTYPE
, &ifr
) != -1) {
1846 char *c
= iffunct2str(ifr
.ifr_functional_type
);
1848 printf("\tfunctional type: %s\n", c
);
1852 struct if_agentidsreq ifar
;
1853 memset(&ifar
, 0, sizeof(ifar
));
1855 strlcpy(ifar
.ifar_name
, name
, sizeof(ifar
.ifar_name
));
1857 if (ioctl(s
, SIOCGIFAGENTIDS
, &ifar
) != -1) {
1858 if (ifar
.ifar_count
!= 0) {
1859 ifar
.ifar_uuids
= calloc(ifar
.ifar_count
, sizeof(uuid_t
));
1860 if (ifar
.ifar_uuids
!= NULL
) {
1861 if (ioctl(s
, SIOCGIFAGENTIDS
, &ifar
) != 1) {
1862 for (int agent_i
= 0; agent_i
< ifar
.ifar_count
; agent_i
++) {
1863 struct netagent_req nar
;
1864 memset(&nar
, 0, sizeof(nar
));
1866 uuid_copy(nar
.netagent_uuid
, ifar
.ifar_uuids
[agent_i
]);
1868 if (ioctl(s
, SIOCGIFAGENTDATA
, &nar
) != 1) {
1869 printf("\tagent domain:%s type:%s flags:0x%x desc:\"%s\"\n",
1870 nar
.netagent_domain
, nar
.netagent_type
,
1871 nar
.netagent_flags
, nar
.netagent_desc
);
1875 free(ifar
.ifar_uuids
);
1881 if (ioctl(s
, SIOCGIFLINKQUALITYMETRIC
, &ifr
) != -1) {
1882 int lqm
= ifr
.ifr_link_quality_metric
;
1884 printf("\tlink quality: %d ", lqm
);
1885 if (lqm
== IFNET_LQM_THRESH_OFF
)
1887 else if (lqm
== IFNET_LQM_THRESH_UNKNOWN
)
1888 printf("(unknown)");
1889 else if (lqm
> IFNET_LQM_THRESH_UNKNOWN
&&
1890 lqm
<= IFNET_LQM_THRESH_BAD
)
1892 else if (lqm
> IFNET_LQM_THRESH_UNKNOWN
&&
1893 lqm
<= IFNET_LQM_THRESH_POOR
)
1895 else if (lqm
> IFNET_LQM_THRESH_POOR
&&
1896 lqm
<= IFNET_LQM_THRESH_GOOD
)
1901 } else if (lqm
> IFNET_LQM_THRESH_UNKNOWN
) {
1902 printf("\tlink quality: %d ", lqm
);
1903 if (lqm
<= IFNET_LQM_THRESH_BAD
)
1905 else if (lqm
<= IFNET_LQM_THRESH_POOR
)
1907 else if (lqm
<= IFNET_LQM_THRESH_GOOD
)
1916 if (ioctl(s
, SIOCGIFINTERFACESTATE
, &ifr
) != -1) {
1918 if (ifr
.ifr_interface_state
.valid_bitmask
&
1919 IF_INTERFACE_STATE_RRC_STATE_VALID
) {
1920 uint8_t rrc_state
= ifr
.ifr_interface_state
.rrc_state
;
1922 printf(" rrc: %u ", rrc_state
);
1923 if (rrc_state
== IF_INTERFACE_STATE_RRC_STATE_CONNECTED
)
1924 printf("(connected)");
1925 else if (rrc_state
== IF_INTERFACE_STATE_RRC_STATE_IDLE
)
1930 if (ifr
.ifr_interface_state
.valid_bitmask
&
1931 IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID
) {
1932 uint8_t ifavail
= ifr
.ifr_interface_state
.interface_availability
;
1934 printf(" availability: %u ", ifavail
);
1935 if (ifavail
== IF_INTERFACE_STATE_INTERFACE_AVAILABLE
)
1937 else if (ifavail
== IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE
)
1942 printf(" availability: (not valid)");
1945 ifr
.ifr_interface_state
.valid_bitmask
&
1946 IF_INTERFACE_STATE_LQM_STATE_VALID
) {
1947 int8_t lqm
= ifr
.ifr_interface_state
.lqm_state
;
1949 printf(" lqm: %d", lqm
);
1951 if (lqm
== IFNET_LQM_THRESH_OFF
)
1953 else if (lqm
== IFNET_LQM_THRESH_UNKNOWN
)
1954 printf("(unknown)");
1955 else if (lqm
== IFNET_LQM_THRESH_BAD
)
1957 else if (lqm
== IFNET_LQM_THRESH_POOR
)
1959 else if (lqm
== IFNET_LQM_THRESH_GOOD
)
1968 bzero(&iflpr
, sizeof (iflpr
));
1969 strlcpy(iflpr
.iflpr_name
, name
, sizeof (iflpr
.iflpr_name
));
1970 if (ioctl(s
, SIOCGIFLINKPARAMS
, &iflpr
) != -1) {
1971 u_int64_t ibw_max
= iflpr
.iflpr_input_bw
.max_bw
;
1972 u_int64_t ibw_eff
= iflpr
.iflpr_input_bw
.eff_bw
;
1973 u_int64_t obw_max
= iflpr
.iflpr_output_bw
.max_bw
;
1974 u_int64_t obw_eff
= iflpr
.iflpr_output_bw
.eff_bw
;
1975 u_int64_t obw_tbr
= iflpr
.iflpr_output_tbr_rate
;
1976 u_int32_t obw_pct
= iflpr
.iflpr_output_tbr_percent
;
1977 u_int64_t ilt_max
= iflpr
.iflpr_input_lt
.max_lt
;
1978 u_int64_t ilt_eff
= iflpr
.iflpr_input_lt
.eff_lt
;
1979 u_int64_t olt_max
= iflpr
.iflpr_output_lt
.max_lt
;
1980 u_int64_t olt_eff
= iflpr
.iflpr_output_lt
.eff_lt
;
1983 if (eflags
& IFEF_TXSTART
) {
1984 u_int32_t flags
= iflpr
.iflpr_flags
;
1985 u_int32_t sched
= iflpr
.iflpr_output_sched
;
1986 struct if_throttlereq iftr
;
1988 printf("\tscheduler: %s%s ",
1989 (flags
& IFLPRF_ALTQ
) ? "ALTQ_" : "",
1991 if (flags
& IFLPRF_DRVMANAGED
)
1992 printf("(driver managed)");
1995 bzero(&iftr
, sizeof (iftr
));
1996 strlcpy(iftr
.ifthr_name
, name
,
1997 sizeof (iftr
.ifthr_name
));
1998 if (ioctl(s
, SIOCGIFTHROTTLE
, &iftr
) != -1 &&
1999 iftr
.ifthr_level
!= IFNET_THROTTLE_OFF
)
2000 printf("\tthrottling: level %d (%s)\n",
2001 iftr
.ifthr_level
, tl2str(iftr
.ifthr_level
));
2004 if (obw_tbr
!= 0 && obw_eff
> obw_tbr
)
2007 if (ibw_max
!= 0 || obw_max
!= 0) {
2008 if (ibw_max
== obw_max
&& ibw_eff
== obw_eff
&&
2009 ibw_max
== ibw_eff
&& obw_tbr
== 0) {
2010 printf("\tlink rate: %s\n",
2011 bps_to_str(ibw_max
));
2013 printf("\tuplink rate: %s [eff] / ",
2014 bps_to_str(obw_eff
));
2017 printf("%s [tbr] / ",
2018 bps_to_str(obw_tbr
));
2020 printf("%s [tbr %u%%] / ",
2021 bps_to_str(obw_tbr
),
2024 printf("%s", bps_to_str(obw_max
));
2028 if (ibw_eff
== ibw_max
) {
2029 printf("\tdownlink rate: %s\n",
2030 bps_to_str(ibw_max
));
2032 printf("\tdownlink rate: "
2033 "%s [eff] / ", bps_to_str(ibw_eff
));
2034 printf("%s [max]\n",
2035 bps_to_str(ibw_max
));
2038 } else if (obw_tbr
!= 0) {
2039 printf("\tuplink rate: %s [tbr]\n",
2040 bps_to_str(obw_tbr
));
2043 if (ilt_max
!= 0 || olt_max
!= 0) {
2044 if (ilt_max
== olt_max
&& ilt_eff
== olt_eff
&&
2045 ilt_max
== ilt_eff
) {
2046 printf("\tlink latency: %s\n",
2047 ns_to_str(ilt_max
));
2049 if (olt_max
!= 0 && olt_eff
== olt_max
) {
2050 printf("\tuplink latency: %s\n",
2051 ns_to_str(olt_max
));
2052 } else if (olt_max
!= 0) {
2053 printf("\tuplink latency: "
2054 "%s [eff] / ", ns_to_str(olt_eff
));
2055 printf("%s [max]\n",
2056 ns_to_str(olt_max
));
2058 if (ilt_max
!= 0 && ilt_eff
== ilt_max
) {
2059 printf("\tdownlink latency: %s\n",
2060 ns_to_str(ilt_max
));
2061 } else if (ilt_max
!= 0) {
2062 printf("\tdownlink latency: "
2063 "%s [eff] / ", ns_to_str(ilt_eff
));
2064 printf("%s [max]\n",
2065 ns_to_str(ilt_max
));
2071 /* Common OID prefix */
2074 mib
[2] = NETLINK_GENERIC
;
2075 mib
[3] = IFMIB_IFDATA
;
2076 mib
[4] = if_nametoindex(name
);
2077 mib
[5] = IFDATA_SUPPLEMENTAL
;
2078 if (sysctl(mib
, 6, &ifmsupp
, &miblen
, (void *)0, 0) == -1)
2079 err(1, "sysctl IFDATA_SUPPLEMENTAL");
2081 if (ifmsupp
.ifmd_data_extended
.ifi_alignerrs
!= 0) {
2082 printf("\tunaligned pkts: %llu\n",
2083 ifmsupp
.ifmd_data_extended
.ifi_alignerrs
);
2085 if (ifmsupp
.ifmd_data_extended
.ifi_dt_bytes
!= 0) {
2086 printf("\tdata milestone interval: %s\n",
2087 bytes_to_str(ifmsupp
.ifmd_data_extended
.ifi_dt_bytes
));
2090 bzero(&ifdr
, sizeof (ifdr
));
2091 strlcpy(ifdr
.ifdr_name
, name
, sizeof (ifdr
.ifdr_name
));
2092 if (ioctl(s
, SIOCGIFDESC
, &ifdr
) != -1 && ifdr
.ifdr_len
) {
2093 printf("\tdesc: %s\n", ifdr
.ifdr_desc
);
2096 if (ioctl(s
, SIOCGIFLOG
, &ifr
) != -1 && ifr
.ifr_log
.ifl_level
) {
2097 printf("\tlogging: level %d ", ifr
.ifr_log
.ifl_level
);
2098 printb("facilities", ifr
.ifr_log
.ifl_flags
, IFRLOGF_BITS
);
2102 if (ioctl(s
, SIOCGIFDELEGATE
, &ifr
) != -1 && ifr
.ifr_delegated
) {
2103 char delegatedif
[IFNAMSIZ
+1];
2104 if (if_indextoname(ifr
.ifr_delegated
, delegatedif
) != NULL
)
2105 printf("\teffective interface: %s\n", delegatedif
);
2108 if (ioctl(s
, SIOCGSTARTDELAY
, &ifr
) != -1) {
2109 if (ifr
.ifr_start_delay_qlen
> 0 &&
2110 ifr
.ifr_start_delay_timeout
> 0) {
2111 printf("\ttxstart qlen: %u packets "
2112 "timeout: %u microseconds\n",
2113 ifr
.ifr_start_delay_qlen
,
2114 ifr
.ifr_start_delay_timeout
/1000);
2117 #if defined(IFCAP_HW_TIMESTAMP) && defined(IFCAP_SW_TIMESTAMP)
2118 if ((curcap
& (IFCAP_HW_TIMESTAMP
| IFCAP_SW_TIMESTAMP
)) &&
2119 ioctl(s
, SIOCGIFTIMESTAMPENABLED
, &ifr
) != -1) {
2120 printf("\ttimestamp: %s\n",
2121 (ifr
.ifr_intval
!= 0) ? "enabled" : "disabled");
2124 #if defined(SIOCGQOSMARKINGENABLED) && defined(SIOCGQOSMARKINGMODE)
2125 if (ioctl(s
, SIOCGQOSMARKINGENABLED
, &ifr
) != -1) {
2126 printf("\tqosmarking enabled: %s mode: ",
2127 ifr
.ifr_qosmarking_enabled
? "yes" : "no");
2128 if (ioctl(s
, SIOCGQOSMARKINGMODE
, &ifr
) != -1) {
2129 switch (ifr
.ifr_qosmarking_mode
) {
2130 case IFRTYPE_QOSMARKING_FASTLANE
:
2131 printf("fastlane\n");
2133 #if defined(IFRTYPE_QOSMARKING_RFC4594)
2134 case IFRTYPE_QOSMARKING_RFC4594
:
2135 printf("RFC4594\n");
2138 case IFRTYPE_QOSMARKING_MODE_NONE
:
2142 printf("unknown (%u)\n", ifr
.ifr_qosmarking_mode
);
2147 #endif /* defined(SIOCGQOSMARKINGENABLED) && defined(SIOCGQOSMARKINGMODE) */
2149 if (ioctl(s
, SIOCGIFLOWPOWER
, &ifr
) != -1) {
2150 printf("\tlow power mode: %s\n",
2151 (ifr
.ifr_low_power_mode
!= 0) ? "enabled" : "disabled");
2153 #if defined(SIOCGIFMPKLOG)
2154 if (ioctl(s
, SIOCGIFMPKLOG
, &ifr
) != -1) {
2155 printf("\tmulti layer packet logging (mpklog): %s\n",
2156 (ifr
.ifr_mpk_log
!= 0) ? "enabled" : "disabled");
2167 #define KILOBYTES 1024
2168 #define MEGABYTES (KILOBYTES * KILOBYTES)
2169 #define GIGABYTES (KILOBYTES * KILOBYTES * KILOBYTES)
2172 bytes_to_str(unsigned long long bytes
)
2174 static char buf
[32];
2176 long double n
= bytes
, t
;
2178 if (bytes
>= GIGABYTES
) {
2181 } else if (n
>= MEGABYTES
) {
2184 } else if (n
>= KILOBYTES
) {
2192 snprintf(buf
, sizeof (buf
), "%-4.2Lf %s", t
, u
);
2196 #define GIGABIT_PER_SEC 1000000000 /* gigabit per second */
2197 #define MEGABIT_PER_SEC 1000000 /* megabit per second */
2198 #define KILOBIT_PER_SEC 1000 /* kilobit per second */
2201 bps_to_str(unsigned long long rate
)
2203 static char buf
[32];
2205 long double n
= rate
, t
;
2207 if (rate
>= GIGABIT_PER_SEC
) {
2208 t
= n
/ GIGABIT_PER_SEC
;
2210 } else if (n
>= MEGABIT_PER_SEC
) {
2211 t
= n
/ MEGABIT_PER_SEC
;
2213 } else if (n
>= KILOBIT_PER_SEC
) {
2214 t
= n
/ KILOBIT_PER_SEC
;
2221 snprintf(buf
, sizeof (buf
), "%-4.2Lf %4s", t
, u
);
2225 #define NSEC_PER_SEC 1000000000 /* nanosecond per second */
2226 #define USEC_PER_SEC 1000000 /* microsecond per second */
2227 #define MSEC_PER_SEC 1000 /* millisecond per second */
2230 ns_to_str(unsigned long long nsec
)
2232 static char buf
[32];
2234 long double n
= nsec
, t
;
2236 if (nsec
>= NSEC_PER_SEC
) {
2237 t
= n
/ NSEC_PER_SEC
;
2239 } else if (n
>= USEC_PER_SEC
) {
2240 t
= n
/ USEC_PER_SEC
;
2242 } else if (n
>= MSEC_PER_SEC
) {
2243 t
= n
/ MSEC_PER_SEC
;
2250 snprintf(buf
, sizeof (buf
), "%-4.2Lf %4s", t
, u
);
2255 tunnel_status(int s
)
2257 af_all_tunnel_status(s
);
2261 clat46_addr(int s
, char * if_name
)
2263 struct if_clat46req ifr
;
2264 char buf
[MAXHOSTNAMELEN
];
2266 bzero(&ifr
, sizeof (ifr
));
2267 strlcpy(ifr
.ifclat46_name
, if_name
, sizeof(ifr
.ifclat46_name
));
2269 if (ioctl(s
, SIOCGIFCLAT46ADDR
, &ifr
) < 0) {
2270 if (errno
!= ENOENT
)
2271 syslog(LOG_WARNING
, "ioctl (SIOCGIFCLAT46ADDR): %d", errno
);
2275 if (inet_ntop(AF_INET6
, &ifr
.ifclat46_addr
.v6_address
, buf
, sizeof(buf
)) != NULL
)
2276 printf("\tinet6 %s prefixlen %d clat46\n",
2277 buf
, ifr
.ifclat46_addr
.v6_prefixlen
);
2281 nat64_status(int s
, char * if_name
)
2284 struct if_nat64req ifr
;
2285 char buf
[MAXHOSTNAMELEN
];
2287 bzero(&ifr
, sizeof(ifr
));
2288 strlcpy(ifr
.ifnat64_name
, if_name
, sizeof(ifr
.ifnat64_name
));
2290 if (ioctl(s
, SIOCGIFNAT64PREFIX
, &ifr
) < 0) {
2291 if (errno
!= ENOENT
)
2292 syslog(LOG_WARNING
, "ioctl(SIOCGIFNAT64PREFIX): %d", errno
);
2296 for (i
= 0; i
< NAT64_MAX_NUM_PREFIXES
; i
++) {
2297 if (ifr
.ifnat64_prefixes
[i
].prefix_len
> 0) {
2298 inet_ntop(AF_INET6
, &ifr
.ifnat64_prefixes
[i
].ipv6_prefix
, buf
, sizeof(buf
));
2299 printf("\tnat64 prefix %s prefixlen %d\n",
2300 buf
, ifr
.ifnat64_prefixes
[i
].prefix_len
<< 3);
2306 Perror(const char *cmd
)
2311 errx(1, "%s: no such interface", cmd
);
2315 errx(1, "%s: permission denied", cmd
);
2324 * Print a value a la the %b format of the kernel's printf
2327 printb(const char *s
, unsigned v
, const char *bits
)
2332 if (bits
&& *bits
== 8)
2333 printf("%s=%o", s
, v
);
2335 printf("%s=%x", s
, v
);
2339 while ((i
= *bits
++) != '\0') {
2340 if (v
& (1 << (i
-1))) {
2344 for (; (c
= *bits
) > 32; bits
++)
2347 for (; *bits
> 32; bits
++)
2356 ifmaybeload(const char *name
)
2358 #define MOD_PREFIX_LEN 3 /* "if_" */
2359 struct module_stat mstat
;
2361 char ifkind
[IFNAMSIZ
+ MOD_PREFIX_LEN
], ifname
[IFNAMSIZ
], *dp
;
2364 /* loading suppressed by the user */
2368 /* trim the interface number off the end */
2369 strlcpy(ifname
, name
, sizeof(ifname
));
2370 for (dp
= ifname
; *dp
!= 0; dp
++)
2376 /* turn interface and unit into module name */
2377 strlcpy(ifkind
, "if_", sizeof(ifkind
));
2378 strlcpy(ifkind
+ MOD_PREFIX_LEN
, ifname
,
2379 sizeof(ifkind
) - MOD_PREFIX_LEN
);
2381 /* scan files in kernel */
2382 mstat
.version
= sizeof(struct module_stat
);
2383 for (fileid
= kldnext(0); fileid
> 0; fileid
= kldnext(fileid
)) {
2384 /* scan modules in file */
2385 for (modid
= kldfirstmod(fileid
); modid
> 0;
2386 modid
= modfnext(modid
)) {
2387 if (modstat(modid
, &mstat
) < 0)
2389 /* strip bus name if present */
2390 if ((cp
= strchr(mstat
.name
, '/')) != NULL
) {
2395 /* already loaded? */
2396 if (strncmp(ifname
, cp
, strlen(ifname
) + 1) == 0 ||
2397 strncmp(ifkind
, cp
, strlen(ifkind
) + 1) == 0)
2402 /* not present, we should try to load it */
2407 static struct cmd basic_cmds
[] = {
2408 DEF_CMD("up", IFF_UP
, setifflags
),
2409 DEF_CMD("down", -IFF_UP
, setifflags
),
2410 DEF_CMD("arp", -IFF_NOARP
, setifflags
),
2411 DEF_CMD("-arp", IFF_NOARP
, setifflags
),
2412 DEF_CMD("debug", IFF_DEBUG
, setifflags
),
2413 DEF_CMD("-debug", -IFF_DEBUG
, setifflags
),
2415 DEF_CMD("promisc", IFF_PPROMISC
, setifflags
),
2416 DEF_CMD("-promisc", -IFF_PPROMISC
, setifflags
),
2417 #endif /* IFF_PPROMISC */
2418 DEF_CMD("add", IFF_UP
, notealias
),
2419 DEF_CMD("alias", IFF_UP
, notealias
),
2420 DEF_CMD("-alias", -IFF_UP
, notealias
),
2421 DEF_CMD("delete", -IFF_UP
, notealias
),
2422 DEF_CMD("remove", -IFF_UP
, notealias
),
2424 #define EN_SWABIPS 0x1000
2425 DEF_CMD("swabips", EN_SWABIPS
, setifflags
),
2426 DEF_CMD("-swabips", -EN_SWABIPS
, setifflags
),
2428 DEF_CMD_ARG("netmask", setifnetmask
),
2429 DEF_CMD_ARG("metric", setifmetric
),
2430 DEF_CMD_ARG("broadcast", setifbroadaddr
),
2431 DEF_CMD_ARG("ipdst", setifipdst
),
2432 DEF_CMD_ARG2("tunnel", settunnel
),
2433 DEF_CMD("-tunnel", 0, deletetunnel
),
2434 DEF_CMD("deletetunnel", 0, deletetunnel
),
2435 DEF_CMD("link0", IFF_LINK0
, setifflags
),
2436 DEF_CMD("-link0", -IFF_LINK0
, setifflags
),
2437 DEF_CMD("link1", IFF_LINK1
, setifflags
),
2438 DEF_CMD("-link1", -IFF_LINK1
, setifflags
),
2439 DEF_CMD("link2", IFF_LINK2
, setifflags
),
2440 DEF_CMD("-link2", -IFF_LINK2
, setifflags
),
2442 DEF_CMD("monitor", IFF_MONITOR
:, setifflags
),
2443 DEF_CMD("-monitor", -IFF_MONITOR
, setifflags
),
2444 #endif /* IFF_MONITOR */
2445 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
2446 DEF_CMD("mpklog", 1, setifmpklog
),
2447 DEF_CMD("-mpklog", 0, setifmpklog
),
2449 #ifdef IFF_STATICARP
2450 DEF_CMD("staticarp", IFF_STATICARP
, setifflags
),
2451 DEF_CMD("-staticarp", -IFF_STATICARP
, setifflags
),
2452 #endif /* IFF_STATICARP */
2454 DEF_CMD("rxcsum", IFCAP_RXCSUM
, setifcap
),
2455 DEF_CMD("-rxcsum", -IFCAP_RXCSUM
, setifcap
),
2456 #endif /* IFCAP_RXCSUM */
2458 DEF_CMD("txcsum", IFCAP_TXCSUM
, setifcap
),
2459 DEF_CMD("-txcsum", -IFCAP_TXCSUM
, setifcap
),
2460 #endif /* IFCAP_TXCSUM */
2461 #ifdef IFCAP_NETCONS
2462 DEF_CMD("netcons", IFCAP_NETCONS
, setifcap
),
2463 DEF_CMD("-netcons", -IFCAP_NETCONS
, setifcap
),
2464 #endif /* IFCAP_NETCONS */
2465 #ifdef IFCAP_POLLING
2466 DEF_CMD("polling", IFCAP_POLLING
, setifcap
),
2467 DEF_CMD("-polling", -IFCAP_POLLING
, setifcap
),
2468 #endif /* IFCAP_POLLING */
2470 DEF_CMD("tso", IFCAP_TSO
, setifcap
),
2471 DEF_CMD("-tso", -IFCAP_TSO
, setifcap
),
2472 #endif /* IFCAP_TSO */
2474 DEF_CMD("lro", IFCAP_LRO
, setifcap
),
2475 DEF_CMD("-lro", -IFCAP_LRO
, setifcap
),
2476 #endif /* IFCAP_LRO */
2478 DEF_CMD("wol", IFCAP_WOL
, setifcap
),
2479 DEF_CMD("-wol", -IFCAP_WOL
, setifcap
),
2480 #endif /* IFCAP_WOL */
2481 #ifdef IFCAP_WOL_UCAST
2482 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST
, setifcap
),
2483 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST
, setifcap
),
2484 #endif /* IFCAP_WOL_UCAST */
2485 #ifdef IFCAP_WOL_MCAST
2486 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST
, setifcap
),
2487 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST
, setifcap
),
2488 #endif /* IFCAP_WOL_MCAST */
2489 #ifdef IFCAP_WOL_MAGIC
2490 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC
, setifcap
),
2491 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC
, setifcap
),
2492 #endif /* IFCAP_WOL_MAGIC */
2493 DEF_CMD("normal", -IFF_LINK0
, setifflags
),
2494 DEF_CMD("compress", IFF_LINK0
, setifflags
),
2495 DEF_CMD("noicmp", IFF_LINK1
, setifflags
),
2496 DEF_CMD_ARG("mtu", setifmtu
),
2498 DEF_CMD_ARG("name", setifname
),
2501 DEF_CMD("av", IFCAP_AV
, setifcap
),
2502 DEF_CMD("-av", -IFCAP_AV
, setifcap
),
2503 #endif /* IFCAP_AV */
2504 DEF_CMD("router", 1, setrouter
),
2505 DEF_CMD("-router", 0, setrouter
),
2506 DEF_CMD_VA("routermode", routermode
),
2507 DEF_CMD_ARG("desc", setifdesc
),
2508 DEF_CMD_ARG("tbr", settbr
),
2509 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
2510 DEF_CMD_VA("netem", setnetem
),
2512 DEF_CMD_ARG("throttle", setthrottle
),
2513 DEF_CMD_ARG("log", setlog
),
2514 DEF_CMD("cl2k", 1, setcl2k
),
2515 DEF_CMD("-cl2k", 0, setcl2k
),
2516 DEF_CMD("expensive", 1, setexpensive
),
2517 DEF_CMD("-expensive", 0, setexpensive
),
2518 #ifdef SIOCSIFCONSTRAINED
2519 DEF_CMD("constrained", 1, setconstrained
),
2520 DEF_CMD("-constrained", 0, setconstrained
),
2522 DEF_CMD("timestamp", 1, settimestamp
),
2523 DEF_CMD("-timestamp", 0, settimestamp
),
2524 DEF_CMD_ARG("ecn", setecnmode
),
2525 DEF_CMD_ARG2("fastlane", setfastlane
),
2526 DEF_CMD_ARG2("qosmarking", setqosmarking
),
2527 DEF_CMD_ARG("disable_output", setdisableoutput
),
2528 DEF_CMD("probe_connectivity", 1, setprobeconnectivity
),
2529 DEF_CMD("-probe_connectivity", 0, setprobeconnectivity
),
2530 DEF_CMD("lowpowermode", 1, setlowpowermode
),
2531 DEF_CMD("-lowpowermode", 0, setlowpowermode
),
2532 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
2533 DEF_CMD_ARG("subfamily", setifsubfamily
),
2535 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
2536 DEF_CMD("available", 1, setifavailability
),
2537 DEF_CMD("-available", 0, setifavailability
),
2538 DEF_CMD("unavailable", 0, setifavailability
),
2542 static __constructor
void
2545 #define N(a) (sizeof(a) / sizeof(a[0]))
2548 for (i
= 0; i
< N(basic_cmds
); i
++)
2549 cmd_register(&basic_cmds
[i
]);
2554 sched2str(unsigned int s
)
2559 case PKTSCHEDT_NONE
:
2562 case PKTSCHEDT_FQ_CODEL
:
2574 tl2str(unsigned int s
)
2579 case IFNET_THROTTLE_OFF
:
2582 case IFNET_THROTTLE_OPPORTUNISTIC
:
2583 c
= "opportunistic";
2594 ift2str(unsigned int t
, unsigned int f
, unsigned int sf
)
2596 static char buf
[256];
2602 case IFRTYPE_SUBFAMILY_USB
:
2605 case IFRTYPE_SUBFAMILY_BLUETOOTH
:
2606 c
= "Bluetooth PAN";
2608 case IFRTYPE_SUBFAMILY_WIFI
:
2611 case IFRTYPE_SUBFAMILY_THUNDERBOLT
:
2612 c
= "IP over Thunderbolt";
2614 case IFRTYPE_SUBFAMILY_ANY
:
2622 c
= "IP over FireWire";
2626 c
= "Packet capture";
2633 #if defined(APPLE_IF_FAM_IPSEC)
2635 if (ifr
.ifr_type
.ift_family
== APPLE_IF_FAM_IPSEC
) {
2636 if (ifr
.ifr_type
.ift_subfamily
== IFRTYPE_SUBFAMILY_BLUETOOTH
) {
2637 c
= "Companion Link Bluetooth";
2638 } else if (ifr
.ifr_type
.ift_subfamily
== IFRTYPE_SUBFAMILY_QUICKRELAY
) {
2639 c
= "Companion Link QuickRelay";
2640 } else if (ifr
.ifr_type
.ift_subfamily
== IFRTYPE_SUBFAMILY_WIFI
) {
2641 c
= "Companion Link Wi-Fi";
2642 } else if (ifr
.ifr_type
.ift_subfamily
== IFRTYPE_SUBFAMILY_DEFAULT
) {
2643 c
= "Companion Link Default";
2657 case IFT_IEEE8023ADLAG
:
2664 (void) snprintf(buf
, sizeof (buf
),
2665 "0x%x family: %u subfamily: %u",
2666 ifr
.ifr_type
.ift_type
, ifr
.ifr_type
.ift_family
,
2667 ifr
.ifr_type
.ift_subfamily
);
2669 (void) snprintf(buf
, sizeof (buf
),
2670 "%s (0x%x) family: %u subfamily: %u", c
,
2671 ifr
.ifr_type
.ift_type
, ifr
.ifr_type
.ift_family
,
2672 ifr
.ifr_type
.ift_subfamily
);
2681 iffunct2str(u_int32_t functional_type
)
2685 switch (functional_type
) {
2686 case IFRTYPE_FUNCTIONAL_UNKNOWN
:
2689 case IFRTYPE_FUNCTIONAL_LOOPBACK
:
2693 case IFRTYPE_FUNCTIONAL_WIRED
:
2697 case IFRTYPE_FUNCTIONAL_WIFI_INFRA
:
2701 case IFRTYPE_FUNCTIONAL_WIFI_AWDL
:
2705 case IFRTYPE_FUNCTIONAL_CELLULAR
:
2709 case IFRTYPE_FUNCTIONAL_INTCOPROC
:
2712 #if defined(IFRTYPE_FUNCTIONAL_COMPANIONLINK)
2713 case IFRTYPE_FUNCTIONAL_COMPANIONLINK
:
2714 str
= "companionlink";