]> git.cameronkatri.com Git - apple_cmds.git/blob - network_cmds/ifconfig.tproj/ifconfig.c
network_cmds: Fix compilation for lower targets
[apple_cmds.git] / network_cmds / ifconfig.tproj / ifconfig.c
1 /*
2 * Copyright (c) 2009-2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * Copyright (c) 1983, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
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.
44 *
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
55 * SUCH DAMAGE.
56 */
57
58 #include <sys/cdefs.h>
59
60 #ifndef lint
61 __unused static const char copyright[] =
62 "@(#) Copyright (c) 1983, 1993\n\
63 The Regents of the University of California. All rights reserved.\n";
64 #endif /* not lint */
65
66 #include <sys/param.h>
67 #include <sys/ioctl.h>
68 #include <sys/socket.h>
69 #include <sys/sysctl.h>
70 #include <sys/time.h>
71 #ifndef __APPLE__
72 #include <sys/module.h>
73 #include <sys/linker.h>
74 #endif
75
76 #include <net/ethernet.h>
77 #include <net/if.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>
85
86 /* IP */
87 #include <netinet/in.h>
88 #include <netinet/in_var.h>
89 #include <arpa/inet.h>
90 #include <netdb.h>
91
92 #include <ifaddrs.h>
93 #include <ctype.h>
94 #include <err.h>
95 #include <errno.h>
96 #include <fcntl.h>
97 #include <math.h>
98 #include <stdio.h>
99 #include <stdlib.h>
100 #include <string.h>
101 #include <strings.h>
102 #include <unistd.h>
103 #include <sysexits.h>
104 #include <syslog.h>
105
106 #include "ifconfig.h"
107
108 #ifdef __APPLE__
109 #include <TargetConditionals.h>
110 #endif
111
112 #ifndef IF_NETEM_PARAMS_PSCALE
113 #define IF_NETEM_PARAMS_PSCALE 100000
114 #endif
115
116 /*
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.)
120 */
121 struct ifreq ifr;
122
123 char name[IFNAMSIZ];
124 int setaddr;
125 int setmask;
126 int doalias;
127 int clearaddr;
128 int newaddr = 1;
129 int noload;
130 int all;
131
132 int bond_details = 0;
133 int supmedia = 0;
134 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
135 int verbose = 1;
136 int showrtref = 1;
137 #else /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
138 int verbose = 0;
139 int showrtref = 0;
140 #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
141 int printkeys = 0; /* Print keying material for interfaces. */
142
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);
158
159 static struct afswtch *af_getbyname(const char *name);
160 static struct afswtch *af_getbyfamily(int af);
161 static void af_other_status(int);
162
163 static struct option *opts = NULL;
164
165 void
166 opt_register(struct option *p)
167 {
168 p->next = opts;
169 opts = p;
170 }
171
172 static void
173 usage(void)
174 {
175 char options[1024];
176 struct option *p;
177
178 /* XXX not right but close enough for now */
179 options[0] = '\0';
180 for (p = opts; p != NULL; p = p->next) {
181 strlcat(options, p->opt_usage, sizeof(options));
182 strlcat(options, " ", sizeof(options));
183 }
184
185 fprintf(stderr,
186 "usage: ifconfig %sinterface address_family [address [dest_address]]\n"
187 " [parameters]\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);
193 exit(1);
194 }
195
196 int
197 main(int argc, char *argv[])
198 {
199 int c, namesonly, downonly, uponly;
200 const struct afswtch *afp = NULL;
201 int ifindex;
202 struct ifaddrs *ifap, *ifa;
203 struct ifreq paifr;
204 const struct sockaddr_dl *sdl;
205 char options[1024], *cp;
206 const char *ifname;
207 struct option *p;
208 size_t iflen;
209
210 all = downonly = uponly = namesonly = noload = 0;
211
212 /* Parse leading line options */
213 #ifndef __APPLE__
214 strlcpy(options, "adklmnuv", sizeof(options));
215 #else
216 strlcpy(options, "abdlmruv", sizeof(options));
217 #endif
218 for (p = opts; p != NULL; p = p->next)
219 strlcat(options, p->opt, sizeof(options));
220 while ((c = getopt(argc, argv, options)) != -1) {
221 switch (c) {
222 case 'a': /* scan all interfaces */
223 all++;
224 break;
225 case 'b': /* bond detailed output */
226 bond_details++;
227 break;
228 case 'd': /* restrict scan to "down" interfaces */
229 downonly++;
230 break;
231 #ifndef __APPLE__
232 case 'k':
233 printkeys++;
234 break;
235 #endif
236 case 'l': /* scan interface names only */
237 namesonly++;
238 break;
239 case 'm': /* show media choices in status */
240 supmedia = 1;
241 break;
242 #ifndef __APPLE__
243 case 'n': /* suppress module loading */
244 noload++;
245 break;
246 #endif
247 case 'r':
248 showrtref++;
249 break;
250 case 'u': /* restrict scan to "up" interfaces */
251 uponly++;
252 break;
253 case 'v':
254 verbose++;
255 break;
256 default:
257 for (p = opts; p != NULL; p = p->next)
258 if (p->opt[0] == c) {
259 p->cb(optarg);
260 break;
261 }
262 if (p == NULL)
263 usage();
264 break;
265 }
266 }
267 argc -= optind;
268 argv += optind;
269
270 /* -l cannot be used with -a or -q or -m or -b */
271 if (namesonly &&
272 (all || supmedia || bond_details))
273 usage();
274
275 /* nonsense.. */
276 if (uponly && downonly)
277 usage();
278
279 /* no arguments is equivalent to '-a' */
280 if (!namesonly && argc < 1)
281 all = 1;
282
283 /* -a and -l allow an address family arg to limit the output */
284 if (all || namesonly) {
285 if (argc > 1)
286 usage();
287
288 ifname = NULL;
289 if (argc == 1) {
290 afp = af_getbyname(*argv);
291 if (afp == NULL)
292 usage();
293 if (afp->af_name != NULL)
294 argc--, argv++;
295 /* leave with afp non-zero */
296 }
297 } else {
298 /* not listing, need an argument */
299 if (argc < 1)
300 usage();
301
302 ifname = *argv;
303 argc--, argv++;
304
305 #ifdef notdef
306 /* check and maybe load support for this interface */
307 ifmaybeload(ifname);
308 #endif
309 ifindex = if_nametoindex(ifname);
310 if (ifindex == 0) {
311 /*
312 * NOTE: We must special-case the `create' command
313 * right here as we would otherwise fail when trying
314 * to find the interface.
315 */
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",
321 ifname);
322 ifconfig(argc, argv, 1, NULL);
323 exit(0);
324 }
325 errx(1, "interface %s does not exist", ifname);
326 }
327 }
328
329 /* Check for address family */
330 if (argc > 0) {
331 afp = af_getbyname(*argv);
332 if (afp != NULL)
333 argc--, argv++;
334 }
335
336 if (getifaddrs(&ifap) != 0)
337 err(EXIT_FAILURE, "getifaddrs");
338 cp = NULL;
339 ifindex = 0;
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);
346 }
347
348 if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
349 continue;
350 if (ifa->ifa_addr->sa_family == AF_LINK)
351 sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
352 else
353 sdl = NULL;
354 if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0)
355 continue;
356 iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
357 if (iflen >= sizeof(name)) {
358 warnx("%s: interface name too long, skipping",
359 ifa->ifa_name);
360 continue;
361 }
362 cp = ifa->ifa_name;
363
364 if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
365 continue;
366 if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
367 continue;
368 ifindex++;
369 /*
370 * Are we just listing the interfaces?
371 */
372 if (namesonly) {
373 if (ifindex > 1)
374 printf(" ");
375 fputs(name, stdout);
376 continue;
377 }
378
379 if (argc > 0)
380 ifconfig(argc, argv, 0, afp);
381 else
382 status(afp, sdl, ifa);
383 }
384 if (namesonly)
385 printf("\n");
386 freeifaddrs(ifap);
387
388 exit(0);
389 }
390
391 static struct afswtch *afs = NULL;
392
393 void
394 af_register(struct afswtch *p)
395 {
396 p->af_next = afs;
397 afs = p;
398 }
399
400 static struct afswtch *
401 af_getbyname(const char *name)
402 {
403 struct afswtch *afp;
404
405 for (afp = afs; afp != NULL; afp = afp->af_next)
406 if (strcmp(afp->af_name, name) == 0)
407 return afp;
408 return NULL;
409 }
410
411 static struct afswtch *
412 af_getbyfamily(int af)
413 {
414 struct afswtch *afp;
415
416 for (afp = afs; afp != NULL; afp = afp->af_next)
417 if (afp->af_af == af)
418 return afp;
419 return NULL;
420 }
421
422 static void
423 af_other_status(int s)
424 {
425 struct afswtch *afp;
426 uint8_t afmask[howmany(AF_MAX, NBBY)];
427
428 memset(afmask, 0, sizeof(afmask));
429 for (afp = afs; afp != NULL; afp = afp->af_next) {
430 if (afp->af_other_status == NULL)
431 continue;
432 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
433 continue;
434 afp->af_other_status(s);
435 setbit(afmask, afp->af_af);
436 }
437 }
438
439 static void
440 af_all_tunnel_status(int s)
441 {
442 struct afswtch *afp;
443 uint8_t afmask[howmany(AF_MAX, NBBY)];
444
445 memset(afmask, 0, sizeof(afmask));
446 for (afp = afs; afp != NULL; afp = afp->af_next) {
447 if (afp->af_status_tunnel == NULL)
448 continue;
449 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
450 continue;
451 afp->af_status_tunnel(s);
452 setbit(afmask, afp->af_af);
453 }
454 }
455
456 static struct cmd *cmds = NULL;
457
458 void
459 cmd_register(struct cmd *p)
460 {
461 p->c_next = cmds;
462 cmds = p;
463 }
464
465 static const struct cmd *
466 cmd_lookup(const char *name)
467 {
468 #define N(a) (sizeof(a)/sizeof(a[0]))
469 const struct cmd *p;
470
471 for (p = cmds; p != NULL; p = p->c_next)
472 if (strcmp(name, p->c_name) == 0)
473 return p;
474 return NULL;
475 #undef N
476 }
477
478 struct callback {
479 callback_func *cb_func;
480 void *cb_arg;
481 struct callback *cb_next;
482 };
483 static struct callback *callbacks = NULL;
484
485 void
486 callback_register(callback_func *func, void *arg)
487 {
488 struct callback *cb;
489
490 cb = malloc(sizeof(struct callback));
491 if (cb == NULL)
492 errx(1, "unable to allocate memory for callback");
493 cb->cb_func = func;
494 cb->cb_arg = arg;
495 cb->cb_next = callbacks;
496 callbacks = cb;
497 }
498
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);
502
503 static void setifdstaddr(const char *, int, int, const struct afswtch *);
504 static const struct cmd setifdstaddr_cmd =
505 DEF_CMD("ifdstaddr", 0, setifdstaddr);
506
507 static int
508 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp)
509 {
510 const struct afswtch *nafp;
511 struct callback *cb;
512 int ret, s;
513
514 strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
515 top:
516 if (afp == NULL)
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;
521
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);
524
525 while (argc > 0) {
526 const struct cmd *p;
527
528 p = cmd_lookup(*argv);
529 if (p == NULL) {
530 /*
531 * Not a recognized command, choose between setting
532 * the interface address and the dst address.
533 */
534 p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
535 }
536 if (p->c_u.c_func || p->c_u.c_func2) {
537 if (iscreate && !p->c_iscloneop) {
538 /*
539 * Push the clone create callback so the new
540 * device is created and can be used for any
541 * remaining arguments.
542 */
543 cb = callbacks;
544 if (cb == NULL)
545 errx(1, "internal error, no callback");
546 callbacks = cb->cb_next;
547 cb->cb_func(s, cb->cb_arg);
548 iscreate = 0;
549 /*
550 * Handle any address family spec that
551 * immediately follows and potentially
552 * recreate the socket.
553 */
554 nafp = af_getbyname(*argv);
555 if (nafp != NULL) {
556 argc--, argv++;
557 if (nafp != afp) {
558 close(s);
559 afp = nafp;
560 goto top;
561 }
562 }
563 }
564 if (p->c_parameter == NEXTARG) {
565 if (argv[1] == NULL)
566 errx(1, "'%s' requires argument",
567 p->c_name);
568 p->c_u.c_func(argv[1], 0, s, afp);
569 argc--, argv++;
570 } else if (p->c_parameter == OPTARG) {
571 p->c_u.c_func(argv[1], 0, s, afp);
572 if (argv[1] != NULL)
573 argc--, argv++;
574 } else if (p->c_parameter == NEXTARG2) {
575 if (argc < 3)
576 errx(1, "'%s' requires 2 arguments",
577 p->c_name);
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);
582 if (ret < 0)
583 errx(1, "'%s' command error",
584 p->c_name);
585 argc -= ret, argv += ret;
586 } else {
587 p->c_u.c_func(*argv, p->c_parameter, s, afp);
588 }
589 }
590 argc--, argv++;
591 }
592
593 /*
594 * Do any post argument processing required by the address family.
595 */
596 if (afp->af_postproc != NULL)
597 afp->af_postproc(s, afp);
598 /*
599 * Do deferred callbacks registered while processing
600 * command-line arguments.
601 */
602 for (cb = callbacks; cb != NULL; cb = cb->cb_next)
603 cb->cb_func(s, cb->cb_arg);
604 /*
605 * Do deferred operations.
606 */
607 if (clearaddr) {
608 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
609 warnx("interface %s cannot change %s addresses!",
610 name, afp->af_name);
611 clearaddr = 0;
612 }
613 }
614 if (clearaddr) {
615 strlcpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
616 ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
617 if (ret < 0) {
618 if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
619 /* means no previous address for interface */
620 } else
621 Perror("ioctl (SIOCDIFADDR)");
622 }
623 }
624 if (newaddr) {
625 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
626 warnx("interface %s cannot change %s addresses!",
627 name, afp->af_name);
628 newaddr = 0;
629 }
630 }
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)");
635 }
636
637 close(s);
638 return(0);
639 }
640
641 /*ARGSUSED*/
642 static void
643 setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
644 {
645 if (afp->af_getaddr == NULL)
646 return;
647 /*
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.
651 */
652 setaddr++;
653 if (doalias == 0 && afp->af_af != AF_LINK)
654 clearaddr = 1;
655 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR));
656 }
657
658 static void
659 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
660 {
661 struct addrinfo *srcres, *dstres;
662 int ecode;
663
664 if (afp->af_settunnel == NULL) {
665 warn("address family %s does not support tunnel setup",
666 afp->af_name);
667 return;
668 }
669
670 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
671 errx(1, "error in parsing address string: %s",
672 gai_strerror(ecode));
673
674 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
675 errx(1, "error in parsing address string: %s",
676 gai_strerror(ecode));
677
678 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
679 errx(1,
680 "source and destination address families do not match");
681
682 afp->af_settunnel(s, srcres, dstres);
683
684 freeaddrinfo(srcres);
685 freeaddrinfo(dstres);
686 }
687
688 /* ARGSUSED */
689 static void
690 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp)
691 {
692
693 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
694 err(1, "SIOCDIFPHYADDR");
695 }
696
697 static void
698 setifnetmask(const char *addr, int dummy __unused, int s,
699 const struct afswtch *afp)
700 {
701 if (afp->af_getaddr != NULL) {
702 setmask++;
703 afp->af_getaddr(addr, MASK);
704 }
705 }
706
707 static void
708 setifbroadaddr(const char *addr, int dummy __unused, int s,
709 const struct afswtch *afp)
710 {
711 if (afp->af_getaddr != NULL)
712 afp->af_getaddr(addr, DSTADDR);
713 }
714
715 static void
716 setifipdst(const char *addr, int dummy __unused, int s,
717 const struct afswtch *afp)
718 {
719 const struct afswtch *inet;
720
721 inet = af_getbyname("inet");
722 if (inet == NULL)
723 return;
724 inet->af_getaddr(addr, DSTADDR);
725 clearaddr = 0;
726 newaddr = 0;
727 }
728
729 static void
730 notealias(const char *addr, int param, int s, const struct afswtch *afp)
731 {
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);
738 doalias = param;
739 if (param < 0) {
740 clearaddr = 1;
741 newaddr = 0;
742 } else
743 clearaddr = 0;
744 #undef rqtosa
745 }
746
747 /*ARGSUSED*/
748 static void
749 setifdstaddr(const char *addr, int param __unused, int s,
750 const struct afswtch *afp)
751 {
752 if (afp->af_getaddr != NULL)
753 afp->af_getaddr(addr, DSTADDR);
754 }
755
756 /*
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.
760 */
761 static void
762 setifflags(const char *vname, int value, int s, const struct afswtch *afp)
763 {
764 struct ifreq my_ifr;
765 int flags;
766
767 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
768
769 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
770 Perror("ioctl (SIOCGIFFLAGS)");
771 exit(1);
772 }
773 strlcpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name));
774 flags = my_ifr.ifr_flags;
775
776 if (value < 0) {
777 value = -value;
778 flags &= ~value;
779 } else
780 flags |= value;
781 my_ifr.ifr_flags = flags & 0xffff;
782 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
783 Perror(vname);
784 }
785
786 void
787 setifcap(const char *vname, int value, int s, const struct afswtch *afp)
788 {
789 int flags;
790
791 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
792 Perror("ioctl (SIOCGIFCAP)");
793 exit(1);
794 }
795 flags = ifr.ifr_curcap;
796 if (value < 0) {
797 value = -value;
798 flags &= ~value;
799 } else
800 flags |= value;
801 flags &= ifr.ifr_reqcap;
802 ifr.ifr_reqcap = flags;
803 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
804 Perror(vname);
805 }
806
807 static void
808 setifmetric(const char *val, int dummy __unused, int s,
809 const struct afswtch *afp)
810 {
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)");
815 }
816
817 static void
818 setifmtu(const char *val, int dummy __unused, int s,
819 const struct afswtch *afp)
820 {
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)");
825 }
826
827 #ifndef __APPLE__
828 static void
829 setifname(const char *val, int dummy __unused, int s,
830 const struct afswtch *afp)
831 {
832 char *newname;
833
834 newname = strdup(val);
835 if (newname == NULL) {
836 warn("no memory to set ifname");
837 return;
838 }
839 ifr.ifr_data = newname;
840 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
841 warn("ioctl (set name)");
842 free(newname);
843 return;
844 }
845 strlcpy(name, newname, sizeof(name));
846 free(newname);
847 }
848 #endif
849
850 static void
851 setrouter(const char *vname, int value, int s, const struct afswtch *afp)
852 {
853 if (afp->af_setrouter == NULL) {
854 warn("address family %s does not support router mode",
855 afp->af_name);
856 return;
857 }
858
859 afp->af_setrouter(s, value);
860 }
861
862 static int
863 routermode(int argc, char *const *argv, int s, const struct afswtch *afp)
864 {
865 return (*afp->af_routermode)(s, argc, argv);
866 }
867
868
869 static void
870 setifdesc(const char *val, int dummy __unused, int s, const struct afswtch *afp)
871 {
872 struct if_descreq ifdr;
873
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));
878
879 if (ioctl(s, SIOCSIFDESC, (caddr_t)&ifdr) < 0) {
880 warn("ioctl (set desc)");
881 }
882 }
883
884 static void
885 settbr(const char *val, int dummy __unused, int s, const struct afswtch *afp)
886 {
887 struct if_linkparamsreq iflpr;
888 long double bps;
889 u_int64_t rate;
890 u_int32_t percent = 0;
891 char *cp;
892
893 errno = 0;
894 bzero(&iflpr, sizeof (iflpr));
895 strlcpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name));
896
897 bps = strtold(val, &cp);
898 if (val == cp || errno != 0) {
899 warn("Invalid value '%s'", val);
900 return;
901 }
902 rate = (u_int64_t)bps;
903 if (cp != NULL) {
904 if (!strcmp(cp, "b") || !strcmp(cp, "bps")) {
905 ; /* nothing */
906 } else if (!strcmp(cp, "Kb") || !strcmp(cp, "Kbps")) {
907 rate *= 1000;
908 } else if (!strcmp(cp, "Mb") || !strcmp(cp, "Mbps")) {
909 rate *= 1000 * 1000;
910 } else if (!strcmp(cp, "Gb") || !strcmp(cp, "Gbps")) {
911 rate *= 1000 * 1000 * 1000;
912 } else if (!strcmp(cp, "%")) {
913 percent = rate;
914 if (percent == 0 || percent > 100) {
915 printf("Value out of range '%s'", val);
916 return;
917 }
918 } else if (*cp != '\0') {
919 printf("Unknown unit '%s'", cp);
920 return;
921 }
922 }
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",
936 name, percent);
937 } else {
938 printf("%s: TBR rate set to %s\n", name, bps_to_str(rate));
939 }
940 }
941
942 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
943 static int
944 get_int64(uint64_t *i, char const *s)
945 {
946 char *cp;
947 *i = strtol(s, &cp, 10);
948 if (cp == s || errno != 0) {
949 return (-1);
950 }
951 return (0);
952 }
953
954 static int
955 get_int32(uint32_t *i, char const *s)
956 {
957 char *cp;
958 *i = strtol(s, &cp, 10);
959 if (cp == s || errno != 0) {
960 return (-1);
961 }
962 return (0);
963 }
964
965 static int
966 get_percent(double *d, const char *s)
967 {
968 char *cp;
969 *d = strtod(s, &cp) / (double)100;
970 if (*d == HUGE_VALF || *d == HUGE_VALL) {
971 return (-1);
972 }
973 if (*d == 0.0 || (*cp != '\0' && strcmp(cp, "%") != 0)) {
974 return (-1);
975 }
976 return (0);
977 }
978
979 static int
980 get_percent_fixed_point(uint32_t *i, const char *s)
981 {
982 double p;
983
984 if (get_percent(&p, s) != 0){
985 return (-1);
986 }
987
988 *i = p * IF_NETEM_PARAMS_PSCALE;
989 return (0);
990 }
991
992 static int
993 netem_parse_args(struct if_netem_params *p, int argc, char *const *argv)
994 {
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;
1003
1004 bzero(p, sizeof (*p));
1005
1006 /* take out "input"/"output" */
1007 argc--, argv++;
1008
1009 for ( ; argc > 0; ) {
1010 if (strcmp(*argv, "bandwidth") == 0) {
1011 argc--, argv++;
1012 if (argc <= 0 || get_int64(&bandwitdh, *argv) != 0) {
1013 err(1, "Invalid value '%s'", *argv);
1014 }
1015 argc--, argv++;
1016 } else if (strcmp(*argv, "corruption") == 0) {
1017 argc--, argv++;
1018 if (argc <= 0 ||
1019 get_percent_fixed_point(&corruption, *argv) != 0) {
1020 err(1, "Invalid value '%s'", *argv);
1021 }
1022 argc--, argv++;
1023 } else if (strcmp(*argv, "delay") == 0) {
1024 argc--, argv++;
1025 if (argc <= 0 || get_int32(&latency, *argv) != 0) {
1026 err(1, "Invalid value '%s'", *argv);
1027 }
1028 argc--, argv++;
1029 if (argc > 0 && get_int32(&jitter, *argv) == 0) {
1030 argc--, argv++;
1031 }
1032 } else if (strcmp(*argv, "duplication") == 0) {
1033 argc--, argv++;
1034 if (argc <= 0 ||
1035 get_percent_fixed_point(&duplication, *argv) != 0) {
1036 err(1, "Invalid value '%s'", *argv);
1037 return (-1);
1038 }
1039 argc--, argv++;
1040 } else if (strcmp(*argv, "loss") == 0) {
1041 argc--, argv++;
1042 if (argc <= 0 || get_percent_fixed_point(&loss_p_gr_gl, *argv) != 0) {
1043 err(1, "Invalid value '%s'", *argv);
1044 }
1045 /* we may have all 5 probs, use naive model if not */
1046 argc--, argv++;
1047 if (argc <= 0 || get_percent_fixed_point(&loss_p_gr_bl, *argv) != 0) {
1048 continue;
1049 }
1050 /* if more than p_gr_gl, then should have all probs */
1051 argc--, argv++;
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);
1054 }
1055 argc--, 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);
1058 }
1059 argc--, 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);
1062 }
1063 argc--, argv++;
1064 } else if (strcmp(*argv, "reordering") == 0) {
1065 argc--, argv++;
1066 if (argc <= 0 || get_percent_fixed_point(&reordering, *argv) != 0) {
1067 err(1, "Invalid value '%s'", *argv);
1068 }
1069 argc--, argv++;
1070 } else {
1071 return (-1);
1072 }
1073 }
1074
1075 if (corruption > IF_NETEM_PARAMS_PSCALE) {
1076 err(1, "corruption percentage > 100%%");
1077 }
1078
1079 if (duplication > IF_NETEM_PARAMS_PSCALE) {
1080 err(1, "duplication percentage > 100%%");
1081 }
1082
1083 if (duplication > 0 && latency == 0) {
1084 /* we need to insert dup'ed packet with latency */
1085 err(1, "duplication needs latency param");
1086 }
1087
1088 if (latency > 1000) {
1089 err(1, "latency %dms too big (> 1 sec)", latency);
1090 }
1091
1092 if (jitter * 3 > latency) {
1093 err(1, "jitter %dms too big (latency %dms)", jitter, latency);
1094 }
1095
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");
1101 }
1102
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");
1113 }
1114
1115 if (reordering > IF_NETEM_PARAMS_PSCALE) {
1116 err(1, "reordering percentage > 100%%");
1117 }
1118
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;
1130
1131 return (argc_saved - argc);
1132 }
1133
1134 void
1135 print_netem_params(struct if_netem_params *p, const char *desc)
1136 {
1137 struct if_netem_params zero_params;
1138 double pscale = IF_NETEM_PARAMS_PSCALE / 100;
1139 bzero(&zero_params, sizeof (zero_params));
1140
1141 if (memcmp(p, &zero_params, sizeof (zero_params)) == 0) {
1142 printf("%s NetEm Disabled\n\n", desc);
1143 } else {
1144 printf(
1145 "%s NetEm Parameters\n"
1146 "\tbandwidth rate %llubps\n"
1147 "\tdelay latency %dms\n"
1148 "\t jitter %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) {
1155 printf(
1156 "\tloss %.3f%%\n",
1157 (double) p->ifnetem_loss_p_gr_gl / pscale);
1158 } else {
1159 printf(
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);
1170 }
1171 printf(
1172 "\tcorruption %.3f%%\n"
1173 "\treordering %.3f%%\n\n",
1174 (double) p->ifnetem_corruption_p / pscale,
1175 (double) p->ifnetem_reordering_p / pscale);
1176 }
1177 }
1178
1179 static int
1180 setnetem(int argc, char *const *argv, int s, const struct afswtch *afp)
1181 {
1182 struct if_linkparamsreq iflpr;
1183 struct if_netem_params input_params, output_params;
1184 int ret = 0, error = 0;
1185
1186 bzero(&iflpr, sizeof (iflpr));
1187 bzero(&input_params, sizeof (input_params));
1188 bzero(&output_params, sizeof (output_params));
1189
1190 if (argc > 1) {
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) {
1196 goto bad_args;
1197 } else {
1198 fprintf(stderr, "uknown option %s\n", argv[0]);
1199 goto bad_args;
1200 }
1201 if (ret < 0) {
1202 goto bad_args;
1203 }
1204 }
1205
1206 errno = 0;
1207 strlcpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name));
1208 error = ioctl(s, SIOCGIFLINKPARAMS, &iflpr);
1209 if (error < 0) {
1210 warn("ioctl (get link params)");
1211 }
1212
1213 if (argc == 0) {
1214 print_netem_params(&iflpr.iflpr_input_netem, "Input");
1215 print_netem_params(&iflpr.iflpr_output_netem, "Output");
1216 return (0);
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));
1224 } else {
1225 fprintf(stderr, "uknown option %s\n", argv[0]);
1226 goto bad_args;
1227 }
1228 printf("%s: netem is now disabled for %s\n", name, argv[0]);
1229 ret = 1;
1230 } else {
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;
1235 }
1236 }
1237
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);
1243 } else {
1244 printf("%s: netem configured\n", name);
1245 }
1246
1247 return (ret);
1248 bad_args:
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"
1260 "\t\tnetem\n\n");
1261 return (-1);
1262 }
1263 #endif
1264
1265 static void
1266 setthrottle(const char *val, int dummy __unused, int s,
1267 const struct afswtch *afp)
1268 {
1269 struct if_throttlereq iftr;
1270 char *cp;
1271
1272 errno = 0;
1273 bzero(&iftr, sizeof (iftr));
1274 strlcpy(iftr.ifthr_name, name, sizeof (iftr.ifthr_name));
1275
1276 iftr.ifthr_level = strtold(val, &cp);
1277 if (val == cp || errno != 0) {
1278 warn("Invalid value '%s'", val);
1279 return;
1280 }
1281
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);
1286 } else {
1287 printf("%s: throttling level set to %d\n", name,
1288 iftr.ifthr_level);
1289 }
1290 }
1291
1292 static void
1293 setdisableoutput(const char *val, int dummy __unused, int s,
1294 const struct afswtch *afp)
1295 {
1296 struct ifreq ifr;
1297 char *cp;
1298 errno = 0;
1299 bzero(&ifr, sizeof (ifr));
1300 strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1301
1302 ifr.ifr_ifru.ifru_disable_output = strtold(val, &cp);
1303 if (val == cp || errno != 0) {
1304 warn("Invalid value '%s'", val);
1305 return;
1306 }
1307
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);
1312 } else {
1313 printf("output %s on %s\n",
1314 ((ifr.ifr_ifru.ifru_disable_output == 0) ? "enabled" : "disabled"),
1315 name);
1316 }
1317 }
1318
1319 static void
1320 setlog(const char *val, int dummy __unused, int s,
1321 const struct afswtch *afp)
1322 {
1323 char *cp;
1324
1325 errno = 0;
1326 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1327
1328 ifr.ifr_log.ifl_level = strtold(val, &cp);
1329 if (val == cp || errno != 0) {
1330 warn("Invalid value '%s'", val);
1331 return;
1332 }
1333 ifr.ifr_log.ifl_flags = (IFRLOGF_DLIL|IFRLOGF_FAMILY|IFRLOGF_DRIVER|
1334 IFRLOGF_FIRMWARE);
1335
1336 if (ioctl(s, SIOCSIFLOG, &ifr) < 0)
1337 warn("ioctl (set logging parameters)");
1338 }
1339
1340 void
1341 setcl2k(const char *vname, int value, int s, const struct afswtch *afp)
1342 {
1343 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1344 ifr.ifr_ifru.ifru_2kcl = value;
1345
1346 if (ioctl(s, SIOCSIF2KCL, (caddr_t)&ifr) < 0)
1347 Perror(vname);
1348 }
1349
1350 void
1351 setexpensive(const char *vname, int value, int s, const struct afswtch *afp)
1352 {
1353 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1354 ifr.ifr_ifru.ifru_expensive = value;
1355
1356 if (ioctl(s, SIOCSIFEXPENSIVE, (caddr_t)&ifr) < 0)
1357 Perror(vname);
1358 }
1359
1360 #ifdef SIOCSIFCONSTRAINED
1361 void
1362 setconstrained(const char *vname, int value, int s, const struct afswtch *afp)
1363 {
1364 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1365 ifr.ifr_ifru.ifru_constrained = value;
1366
1367 if (ioctl(s, SIOCSIFCONSTRAINED, (caddr_t)&ifr) < 0)
1368 Perror(vname);
1369 }
1370 #endif
1371
1372 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
1373 static void
1374 setifmpklog(const char *vname, int value, int s, const struct afswtch *afp)
1375 {
1376 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1377 ifr.ifr_ifru.ifru_mpk_log = value;
1378
1379 if (ioctl(s, SIOCSIFMPKLOG, (caddr_t)&ifr) < 0)
1380 Perror(vname);
1381 }
1382 #endif
1383
1384 void
1385 settimestamp(const char *vname, int value, int s, const struct afswtch *afp)
1386 {
1387 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1388
1389 if (value == 0) {
1390 if (ioctl(s, SIOCSIFTIMESTAMPDISABLE, (caddr_t)&ifr) < 0)
1391 Perror(vname);
1392 } else {
1393 if (ioctl(s, SIOCSIFTIMESTAMPENABLE, (caddr_t)&ifr) < 0)
1394 Perror(vname);
1395 }
1396 }
1397
1398 void
1399 setecnmode(const char *val, int dummy __unused, int s,
1400 const struct afswtch *afp)
1401 {
1402 char *cp;
1403
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;
1410 else {
1411 ifr.ifr_ifru.ifru_ecn_mode = strtold(val, &cp);
1412 if (val == cp || errno != 0) {
1413 warn("Invalid ECN mode value '%s'", val);
1414 return;
1415 }
1416 }
1417
1418 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1419
1420 if (ioctl(s, SIOCSECNMODE, (caddr_t)&ifr) < 0)
1421 Perror("ioctl(SIOCSECNMODE)");
1422 }
1423
1424 void
1425 setprobeconnectivity(const char *vname, int value, int s, const struct afswtch *afp)
1426 {
1427 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1428 ifr.ifr_ifru.ifru_probe_connectivity = value;
1429
1430 if (ioctl(s, SIOCSIFPROBECONNECTIVITY, (caddr_t)&ifr) < 0)
1431 Perror(vname);
1432 }
1433
1434 #if defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED)
1435
1436 void
1437 setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1438 {
1439 u_long ioc;
1440
1441 #if (DEBUG | DEVELOPMENT)
1442 printf("%s(%s, %s)\n", __func__, cmd, arg);
1443 #endif /* (DEBUG | DEVELOPMENT) */
1444
1445 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1446
1447 if (strcmp(cmd, "mode") == 0) {
1448 ioc = SIOCSQOSMARKINGMODE;
1449
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;
1455 #endif
1456 else if (strcasecmp(arg, "none") == 0 || strcasecmp(arg, "off") == 0)
1457 ifr.ifr_qosmarking_mode = IFRTYPE_QOSMARKING_MODE_NONE;
1458 else
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;
1468 else
1469 err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
1470 } else {
1471 err(EX_USAGE, "qosmarking takes mode or enabled");
1472 }
1473
1474 if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
1475 err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
1476 }
1477
1478 void
1479 setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1480 {
1481 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1482
1483 warnx("### fastlane is obsolete, use qosmarking ###");
1484
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);
1492 else
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);
1501 else
1502 err(EX_USAGE, "bad value for fastlane %s", cmd);
1503 } else {
1504 err(EX_USAGE, "fastlane takes capable or enable");
1505 }
1506 }
1507
1508 #else /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
1509
1510 void
1511 setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1512 {
1513 int value;
1514 u_long ioc;
1515
1516 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1517
1518 if (strcmp(cmd, "capable") == 0)
1519 ioc = SIOCSFASTLANECAPABLE;
1520 else if (strcmp(cmd, "enable") == 0)
1521 ioc = SIOCSFASTLEENABLED;
1522 else
1523 err(EX_USAGE, "fastlane takes capable or enabled");
1524
1525 if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
1526 strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
1527 value = 1;
1528 else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
1529 strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
1530 value = 0;
1531 else
1532 err(EX_USAGE, "bad value for fastlane %s", cmd);
1533
1534 if (ioc == SIOCSFASTLANECAPABLE)
1535 ifr.ifr_fastlane_capable = value;
1536 else
1537 ifr.ifr_fastlane_enabled = value;
1538
1539 if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
1540 err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
1541 }
1542
1543
1544 void
1545 setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1546 {
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);
1552 else
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);
1561 else
1562 err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
1563 } else {
1564 err(EX_USAGE, "qosmarking takes mode or enabled");
1565 }
1566 }
1567
1568 #endif /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
1569
1570 void
1571 setlowpowermode(const char *vname, int value, int s, const struct afswtch *afp)
1572 {
1573 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1574 ifr.ifr_low_power_mode = !!value;
1575
1576 if (ioctl(s, SIOCSIFLOWPOWER, (caddr_t)&ifr) < 0)
1577 Perror(vname);
1578 }
1579
1580 #if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 135000
1581 struct str2num {
1582 const char *str;
1583 uint32_t num;
1584 };
1585
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 },
1598 };
1599
1600 static uint32_t
1601 get_num_from_str(struct str2num* str2nums, const char *str)
1602 {
1603 struct str2num *str2num = str2nums;
1604
1605 while (str2num != NULL && str2num->str != NULL) {
1606 if (strcasecmp(str2num->str, str) == 0) {
1607 return str2num->num;
1608 }
1609 str2num++;
1610 }
1611 return 0;
1612 }
1613
1614 static void
1615 setifsubfamily(const char *val, int dummy __unused, int s,
1616 const struct afswtch *afp)
1617 {
1618 strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1619
1620 char *endptr;
1621 uint32_t subfamily = strtoul(val, &endptr, 0);
1622 if (*endptr != 0) {
1623 subfamily = get_num_from_str(subfamily_str2num, val);
1624 if (subfamily == 0) {
1625 return;
1626 }
1627 }
1628
1629 ifr.ifr_type.ift_subfamily = subfamily;
1630 if (ioctl(s, SIOCSIFSUBFAMILY, (caddr_t)&ifr) < 0)
1631 warn("ioctl(SIOCSIFSUBFAMILY)");
1632 }
1633
1634 void
1635 setifavailability(const char *vname, int value, int s, const struct afswtch *afp)
1636 {
1637 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1638 ifr.ifr_interface_state.valid_bitmask = IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID;
1639 if (value == 0) {
1640 ifr.ifr_interface_state.interface_availability = IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE;
1641 } else {
1642 ifr.ifr_interface_state.interface_availability = IF_INTERFACE_STATE_INTERFACE_AVAILABLE;
1643 }
1644 if (ioctl(s, SIOCSIFINTERFACESTATE, (caddr_t)&ifr) < 0)
1645 warn("ioctl(SIOCSIFINTERFACESTATE)");
1646 }
1647 #endif
1648
1649 static void
1650 show_routermode(int s)
1651 {
1652 struct afswtch *afp;
1653
1654 afp = af_getbyname("inet");
1655 if (afp != NULL) {
1656 (*afp->af_routermode)(s, 0, NULL);
1657 }
1658 }
1659
1660 static void
1661 show_routermode6(void)
1662 {
1663 struct afswtch *afp;
1664 static int s = -1;
1665
1666 afp = af_getbyname("inet6");
1667 if (afp != NULL) {
1668 if (s < 0) {
1669 s = socket(AF_INET6, SOCK_DGRAM, 0);
1670 if (s < 0) {
1671 perror("socket");
1672 return;
1673 }
1674 }
1675 (*afp->af_routermode)(s, 0, NULL);
1676 }
1677 }
1678
1679 #define IFFBITS \
1680 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
1681 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
1682 "\20MULTICAST"
1683
1684 #define IFEFBITS \
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"
1690
1691 #define IFXFBITS \
1692 "\020\1WOL\2TIMESTAMP\3NOAUTONX\4LEGACY\5TXLOWINET\6RXLOWINET\7ALLOCKPI" \
1693 "\10LOWPOWER\11MPKLOG\12CONSTRAINED"
1694
1695 #define IFCAPBITS \
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"
1699
1700 #define IFRLOGF_BITS \
1701 "\020\1DLIL\21FAMILY\31DRIVER\35FIRMWARE"
1702
1703 /*
1704 * Print the status of the interface. If an address family was
1705 * specified, show only it; otherwise, show them all.
1706 */
1707 static void
1708 status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
1709 struct ifaddrs *ifa)
1710 {
1711 struct ifaddrs *ift;
1712 int allfamilies, s;
1713 struct ifstat ifs;
1714 struct if_descreq ifdr;
1715 struct if_linkparamsreq iflpr;
1716 int mib[6];
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;
1721 int curcap = 0;
1722
1723 if (afp == NULL) {
1724 allfamilies = 1;
1725 afp = af_getbyname("inet");
1726 } else
1727 allfamilies = 0;
1728
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));
1731
1732 s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
1733 if (s < 0)
1734 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
1735
1736 printf("%s: ", name);
1737 printb("flags", ifa->ifa_flags, IFFBITS);
1738 if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
1739 if (ifr.ifr_metric)
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);
1745 if (verbose) {
1746 unsigned int ifindex = if_nametoindex(ifa->ifa_name);
1747 if (ifindex != 0)
1748 printf(" index %u", ifindex);
1749 }
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");
1755 }
1756 #endif
1757 putchar('\n');
1758
1759 if (verbose && ioctl(s, SIOCGIFEFLAGS, (caddr_t)&ifr) != -1 &&
1760 (eflags = ifr.ifr_eflags) != 0) {
1761 printb("\teflags", eflags, IFEFBITS);
1762 putchar('\n');
1763 }
1764
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);
1769 putchar('\n');
1770 }
1771 #endif
1772
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);
1777 putchar('\n');
1778 }
1779 if (supmedia && ifr.ifr_reqcap != 0) {
1780 printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS);
1781 putchar('\n');
1782 }
1783 }
1784
1785 tunnel_status(s);
1786
1787 for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
1788 if (ift->ifa_addr == NULL)
1789 continue;
1790 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0)
1791 continue;
1792 if (allfamilies) {
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);
1799 }
1800
1801 /* Print CLAT46 address */
1802 clat46_addr(s, name);
1803
1804 /* Print NAT64 prefix */
1805 nat64_status(s, name);
1806
1807 #if 0
1808 if (allfamilies || afp->af_af == AF_LINK) {
1809 const struct afswtch *lafp;
1810
1811 /*
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.
1816 */
1817 lafp = af_getbyname("lladdr");
1818 if (lafp != NULL) {
1819 info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl;
1820 lafp->af_status(s, &info);
1821 }
1822 }
1823 #endif
1824 if (allfamilies)
1825 af_other_status(s);
1826 else if (afp->af_other_status != NULL)
1827 afp->af_other_status(s);
1828
1829 strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
1830 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
1831 printf("%s", ifs.ascii);
1832
1833 /* The rest is for when verbose is set; if not set, we're done */
1834 if (!verbose)
1835 goto done;
1836
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);
1840 if (c != NULL)
1841 printf("\ttype: %s\n", c);
1842 }
1843
1844 if (verbose > 1) {
1845 if (ioctl(s, SIOCGIFFUNCTIONALTYPE, &ifr) != -1) {
1846 char *c = iffunct2str(ifr.ifr_functional_type);
1847 if (c != NULL)
1848 printf("\tfunctional type: %s\n", c);
1849 }
1850 }
1851 {
1852 struct if_agentidsreq ifar;
1853 memset(&ifar, 0, sizeof(ifar));
1854
1855 strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name));
1856
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));
1865
1866 uuid_copy(nar.netagent_uuid, ifar.ifar_uuids[agent_i]);
1867
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);
1872 }
1873 }
1874 }
1875 free(ifar.ifar_uuids);
1876 }
1877 }
1878 }
1879 }
1880
1881 if (ioctl(s, SIOCGIFLINKQUALITYMETRIC, &ifr) != -1) {
1882 int lqm = ifr.ifr_link_quality_metric;
1883 if (verbose > 1) {
1884 printf("\tlink quality: %d ", lqm);
1885 if (lqm == IFNET_LQM_THRESH_OFF)
1886 printf("(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)
1891 printf("(bad)");
1892 else if (lqm > IFNET_LQM_THRESH_UNKNOWN &&
1893 lqm <= IFNET_LQM_THRESH_POOR)
1894 printf("(poor)");
1895 else if (lqm > IFNET_LQM_THRESH_POOR &&
1896 lqm <= IFNET_LQM_THRESH_GOOD)
1897 printf("(good)");
1898 else
1899 printf("(?)");
1900 printf("\n");
1901 } else if (lqm > IFNET_LQM_THRESH_UNKNOWN) {
1902 printf("\tlink quality: %d ", lqm);
1903 if (lqm <= IFNET_LQM_THRESH_BAD)
1904 printf("(bad)");
1905 else if (lqm <= IFNET_LQM_THRESH_POOR)
1906 printf("(poor)");
1907 else if (lqm <= IFNET_LQM_THRESH_GOOD)
1908 printf("(good)");
1909 else
1910 printf("(?)");
1911 printf("\n");
1912 }
1913 }
1914
1915 {
1916 if (ioctl(s, SIOCGIFINTERFACESTATE, &ifr) != -1) {
1917 printf("\tstate");
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;
1921
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)
1926 printf("(idle)");
1927 else
1928 printf("(?)");
1929 }
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;
1933
1934 printf(" availability: %u ", ifavail);
1935 if (ifavail == IF_INTERFACE_STATE_INTERFACE_AVAILABLE)
1936 printf("(true)");
1937 else if (ifavail == IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE)
1938 printf("(false)");
1939 else
1940 printf("(?)");
1941 } else {
1942 printf(" availability: (not valid)");
1943 }
1944 if (verbose > 1 &&
1945 ifr.ifr_interface_state.valid_bitmask &
1946 IF_INTERFACE_STATE_LQM_STATE_VALID) {
1947 int8_t lqm = ifr.ifr_interface_state.lqm_state;
1948
1949 printf(" lqm: %d", lqm);
1950
1951 if (lqm == IFNET_LQM_THRESH_OFF)
1952 printf("(off)");
1953 else if (lqm == IFNET_LQM_THRESH_UNKNOWN)
1954 printf("(unknown)");
1955 else if (lqm == IFNET_LQM_THRESH_BAD)
1956 printf("(bad)");
1957 else if (lqm == IFNET_LQM_THRESH_POOR)
1958 printf("(poor)");
1959 else if (lqm == IFNET_LQM_THRESH_GOOD)
1960 printf("(good)");
1961 else
1962 printf("(?)");
1963 }
1964 }
1965 printf("\n");
1966 }
1967
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;
1981
1982
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;
1987
1988 printf("\tscheduler: %s%s ",
1989 (flags & IFLPRF_ALTQ) ? "ALTQ_" : "",
1990 sched2str(sched));
1991 if (flags & IFLPRF_DRVMANAGED)
1992 printf("(driver managed)");
1993 printf("\n");
1994
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));
2002 }
2003
2004 if (obw_tbr != 0 && obw_eff > obw_tbr)
2005 obw_eff = obw_tbr;
2006
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));
2012 } else {
2013 printf("\tuplink rate: %s [eff] / ",
2014 bps_to_str(obw_eff));
2015 if (obw_tbr != 0) {
2016 if (obw_pct == 0)
2017 printf("%s [tbr] / ",
2018 bps_to_str(obw_tbr));
2019 else
2020 printf("%s [tbr %u%%] / ",
2021 bps_to_str(obw_tbr),
2022 obw_pct);
2023 }
2024 printf("%s", bps_to_str(obw_max));
2025 if (obw_tbr != 0)
2026 printf(" [max]");
2027 printf("\n");
2028 if (ibw_eff == ibw_max) {
2029 printf("\tdownlink rate: %s\n",
2030 bps_to_str(ibw_max));
2031 } else {
2032 printf("\tdownlink rate: "
2033 "%s [eff] / ", bps_to_str(ibw_eff));
2034 printf("%s [max]\n",
2035 bps_to_str(ibw_max));
2036 }
2037 }
2038 } else if (obw_tbr != 0) {
2039 printf("\tuplink rate: %s [tbr]\n",
2040 bps_to_str(obw_tbr));
2041 }
2042
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));
2048 } else {
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));
2057 }
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));
2066 }
2067 }
2068 }
2069 }
2070
2071 /* Common OID prefix */
2072 mib[0] = CTL_NET;
2073 mib[1] = PF_LINK;
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");
2080
2081 if (ifmsupp.ifmd_data_extended.ifi_alignerrs != 0) {
2082 printf("\tunaligned pkts: %llu\n",
2083 ifmsupp.ifmd_data_extended.ifi_alignerrs);
2084 }
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));
2088 }
2089
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);
2094 }
2095
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);
2099 putchar('\n');
2100 }
2101
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);
2106 }
2107
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);
2115 }
2116 }
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");
2122 }
2123 #endif
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");
2132 break;
2133 #if defined(IFRTYPE_QOSMARKING_RFC4594)
2134 case IFRTYPE_QOSMARKING_RFC4594:
2135 printf("RFC4594\n");
2136 break;
2137 #endif
2138 case IFRTYPE_QOSMARKING_MODE_NONE:
2139 printf("none\n");
2140 break;
2141 default:
2142 printf("unknown (%u)\n", ifr.ifr_qosmarking_mode);
2143 break;
2144 }
2145 }
2146 }
2147 #endif /* defined(SIOCGQOSMARKINGENABLED) && defined(SIOCGQOSMARKINGMODE) */
2148
2149 if (ioctl(s, SIOCGIFLOWPOWER, &ifr) != -1) {
2150 printf("\tlow power mode: %s\n",
2151 (ifr.ifr_low_power_mode != 0) ? "enabled" : "disabled");
2152 }
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");
2157 }
2158 #endif
2159 show_routermode(s);
2160 show_routermode6();
2161
2162 done:
2163 close(s);
2164 return;
2165 }
2166
2167 #define KILOBYTES 1024
2168 #define MEGABYTES (KILOBYTES * KILOBYTES)
2169 #define GIGABYTES (KILOBYTES * KILOBYTES * KILOBYTES)
2170
2171 static char *
2172 bytes_to_str(unsigned long long bytes)
2173 {
2174 static char buf[32];
2175 const char *u;
2176 long double n = bytes, t;
2177
2178 if (bytes >= GIGABYTES) {
2179 t = n / GIGABYTES;
2180 u = "GB";
2181 } else if (n >= MEGABYTES) {
2182 t = n / MEGABYTES;
2183 u = "MB";
2184 } else if (n >= KILOBYTES) {
2185 t = n / KILOBYTES;
2186 u = "KB";
2187 } else {
2188 t = n;
2189 u = "bytes";
2190 }
2191
2192 snprintf(buf, sizeof (buf), "%-4.2Lf %s", t, u);
2193 return (buf);
2194 }
2195
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 */
2199
2200 static char *
2201 bps_to_str(unsigned long long rate)
2202 {
2203 static char buf[32];
2204 const char *u;
2205 long double n = rate, t;
2206
2207 if (rate >= GIGABIT_PER_SEC) {
2208 t = n / GIGABIT_PER_SEC;
2209 u = "Gbps";
2210 } else if (n >= MEGABIT_PER_SEC) {
2211 t = n / MEGABIT_PER_SEC;
2212 u = "Mbps";
2213 } else if (n >= KILOBIT_PER_SEC) {
2214 t = n / KILOBIT_PER_SEC;
2215 u = "Kbps";
2216 } else {
2217 t = n;
2218 u = "bps ";
2219 }
2220
2221 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
2222 return (buf);
2223 }
2224
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 */
2228
2229 static char *
2230 ns_to_str(unsigned long long nsec)
2231 {
2232 static char buf[32];
2233 const char *u;
2234 long double n = nsec, t;
2235
2236 if (nsec >= NSEC_PER_SEC) {
2237 t = n / NSEC_PER_SEC;
2238 u = "sec ";
2239 } else if (n >= USEC_PER_SEC) {
2240 t = n / USEC_PER_SEC;
2241 u = "msec";
2242 } else if (n >= MSEC_PER_SEC) {
2243 t = n / MSEC_PER_SEC;
2244 u = "usec";
2245 } else {
2246 t = n;
2247 u = "nsec";
2248 }
2249
2250 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
2251 return (buf);
2252 }
2253
2254 static void
2255 tunnel_status(int s)
2256 {
2257 af_all_tunnel_status(s);
2258 }
2259
2260 static void
2261 clat46_addr(int s, char * if_name)
2262 {
2263 struct if_clat46req ifr;
2264 char buf[MAXHOSTNAMELEN];
2265
2266 bzero(&ifr, sizeof (ifr));
2267 strlcpy(ifr.ifclat46_name, if_name, sizeof(ifr.ifclat46_name));
2268
2269 if (ioctl(s, SIOCGIFCLAT46ADDR, &ifr) < 0) {
2270 if (errno != ENOENT)
2271 syslog(LOG_WARNING, "ioctl (SIOCGIFCLAT46ADDR): %d", errno);
2272 return;
2273 }
2274
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);
2278 }
2279
2280 static void
2281 nat64_status(int s, char * if_name)
2282 {
2283 int i;
2284 struct if_nat64req ifr;
2285 char buf[MAXHOSTNAMELEN];
2286
2287 bzero(&ifr, sizeof(ifr));
2288 strlcpy(ifr.ifnat64_name, if_name, sizeof(ifr.ifnat64_name));
2289
2290 if (ioctl(s, SIOCGIFNAT64PREFIX, &ifr) < 0) {
2291 if (errno != ENOENT)
2292 syslog(LOG_WARNING, "ioctl(SIOCGIFNAT64PREFIX): %d", errno);
2293 return;
2294 }
2295
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);
2301 }
2302 }
2303 }
2304
2305 void
2306 Perror(const char *cmd)
2307 {
2308 switch (errno) {
2309
2310 case ENXIO:
2311 errx(1, "%s: no such interface", cmd);
2312 break;
2313
2314 case EPERM:
2315 errx(1, "%s: permission denied", cmd);
2316 break;
2317
2318 default:
2319 err(1, "%s", cmd);
2320 }
2321 }
2322
2323 /*
2324 * Print a value a la the %b format of the kernel's printf
2325 */
2326 void
2327 printb(const char *s, unsigned v, const char *bits)
2328 {
2329 int i, any = 0;
2330 char c;
2331
2332 if (bits && *bits == 8)
2333 printf("%s=%o", s, v);
2334 else
2335 printf("%s=%x", s, v);
2336 bits++;
2337 if (bits) {
2338 putchar('<');
2339 while ((i = *bits++) != '\0') {
2340 if (v & (1 << (i-1))) {
2341 if (any)
2342 putchar(',');
2343 any = 1;
2344 for (; (c = *bits) > 32; bits++)
2345 putchar(c);
2346 } else
2347 for (; *bits > 32; bits++)
2348 ;
2349 }
2350 putchar('>');
2351 }
2352 }
2353
2354 #ifndef __APPLE__
2355 void
2356 ifmaybeload(const char *name)
2357 {
2358 #define MOD_PREFIX_LEN 3 /* "if_" */
2359 struct module_stat mstat;
2360 int fileid, modid;
2361 char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
2362 const char *cp;
2363
2364 /* loading suppressed by the user */
2365 if (noload)
2366 return;
2367
2368 /* trim the interface number off the end */
2369 strlcpy(ifname, name, sizeof(ifname));
2370 for (dp = ifname; *dp != 0; dp++)
2371 if (isdigit(*dp)) {
2372 *dp = 0;
2373 break;
2374 }
2375
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);
2380
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)
2388 continue;
2389 /* strip bus name if present */
2390 if ((cp = strchr(mstat.name, '/')) != NULL) {
2391 cp++;
2392 } else {
2393 cp = mstat.name;
2394 }
2395 /* already loaded? */
2396 if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 ||
2397 strncmp(ifkind, cp, strlen(ifkind) + 1) == 0)
2398 return;
2399 }
2400 }
2401
2402 /* not present, we should try to load it */
2403 kldload(ifkind);
2404 }
2405 #endif
2406
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),
2414 #ifdef IFF_PPROMISC
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),
2423 #ifdef notdef
2424 #define EN_SWABIPS 0x1000
2425 DEF_CMD("swabips", EN_SWABIPS, setifflags),
2426 DEF_CMD("-swabips", -EN_SWABIPS, setifflags),
2427 #endif
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),
2441 #ifdef IFF_MONITOR
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),
2448 #endif
2449 #ifdef IFF_STATICARP
2450 DEF_CMD("staticarp", IFF_STATICARP, setifflags),
2451 DEF_CMD("-staticarp", -IFF_STATICARP, setifflags),
2452 #endif /* IFF_STATICARP */
2453 #ifdef IFCAP_RXCSUM
2454 DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap),
2455 DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap),
2456 #endif /* IFCAP_RXCSUM */
2457 #ifdef IFCAP_TXCSUM
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 */
2469 #ifdef IFCAP_TSO
2470 DEF_CMD("tso", IFCAP_TSO, setifcap),
2471 DEF_CMD("-tso", -IFCAP_TSO, setifcap),
2472 #endif /* IFCAP_TSO */
2473 #ifdef IFCAP_LRO
2474 DEF_CMD("lro", IFCAP_LRO, setifcap),
2475 DEF_CMD("-lro", -IFCAP_LRO, setifcap),
2476 #endif /* IFCAP_LRO */
2477 #ifdef IFCAP_WOL
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),
2497 #ifdef notdef
2498 DEF_CMD_ARG("name", setifname),
2499 #endif /* notdef */
2500 #ifdef IFCAP_AV
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),
2511 #endif
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),
2521 #endif
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),
2534 #endif
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),
2539 #endif
2540 };
2541
2542 static __constructor void
2543 ifconfig_ctor(void)
2544 {
2545 #define N(a) (sizeof(a) / sizeof(a[0]))
2546 int i;
2547
2548 for (i = 0; i < N(basic_cmds); i++)
2549 cmd_register(&basic_cmds[i]);
2550 #undef N
2551 }
2552
2553 static char *
2554 sched2str(unsigned int s)
2555 {
2556 char *c;
2557
2558 switch (s) {
2559 case PKTSCHEDT_NONE:
2560 c = "NONE";
2561 break;
2562 case PKTSCHEDT_FQ_CODEL:
2563 c = "FQ_CODEL";
2564 break;
2565 default:
2566 c = "UNKNOWN";
2567 break;
2568 }
2569
2570 return (c);
2571 }
2572
2573 static char *
2574 tl2str(unsigned int s)
2575 {
2576 char *c;
2577
2578 switch (s) {
2579 case IFNET_THROTTLE_OFF:
2580 c = "off";
2581 break;
2582 case IFNET_THROTTLE_OPPORTUNISTIC:
2583 c = "opportunistic";
2584 break;
2585 default:
2586 c = "unknown";
2587 break;
2588 }
2589
2590 return (c);
2591 }
2592
2593 static char *
2594 ift2str(unsigned int t, unsigned int f, unsigned int sf)
2595 {
2596 static char buf[256];
2597 char *c = NULL;
2598
2599 switch (t) {
2600 case IFT_ETHER:
2601 switch (sf) {
2602 case IFRTYPE_SUBFAMILY_USB:
2603 c = "USB Ethernet";
2604 break;
2605 case IFRTYPE_SUBFAMILY_BLUETOOTH:
2606 c = "Bluetooth PAN";
2607 break;
2608 case IFRTYPE_SUBFAMILY_WIFI:
2609 c = "Wi-Fi";
2610 break;
2611 case IFRTYPE_SUBFAMILY_THUNDERBOLT:
2612 c = "IP over Thunderbolt";
2613 break;
2614 case IFRTYPE_SUBFAMILY_ANY:
2615 default:
2616 c = "Ethernet";
2617 break;
2618 }
2619 break;
2620
2621 case IFT_IEEE1394:
2622 c = "IP over FireWire";
2623 break;
2624
2625 case IFT_PKTAP:
2626 c = "Packet capture";
2627 break;
2628
2629 case IFT_CELLULAR:
2630 c = "Cellular";
2631 break;
2632
2633 #if defined(APPLE_IF_FAM_IPSEC)
2634 case IFT_OTHER:
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";
2644 }
2645 }
2646 break;
2647 #endif
2648
2649 case IFT_BRIDGE:
2650 case IFT_PFLOG:
2651 case IFT_PFSYNC:
2652 case IFT_PPP:
2653 case IFT_LOOP:
2654 case IFT_GIF:
2655 case IFT_STF:
2656 case IFT_L2VLAN:
2657 case IFT_IEEE8023ADLAG:
2658 default:
2659 break;
2660 }
2661
2662 if (verbose > 1) {
2663 if (c == NULL) {
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);
2668 } else {
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);
2673 }
2674 c = buf;
2675 }
2676
2677 return (c);
2678 }
2679
2680 static char *
2681 iffunct2str(u_int32_t functional_type)
2682 {
2683 char *str = NULL;
2684
2685 switch (functional_type) {
2686 case IFRTYPE_FUNCTIONAL_UNKNOWN:
2687 break;
2688
2689 case IFRTYPE_FUNCTIONAL_LOOPBACK:
2690 str = "loopback";
2691 break;
2692
2693 case IFRTYPE_FUNCTIONAL_WIRED:
2694 str = "wired";
2695 break;
2696
2697 case IFRTYPE_FUNCTIONAL_WIFI_INFRA:
2698 str = "wifi";
2699 break;
2700
2701 case IFRTYPE_FUNCTIONAL_WIFI_AWDL:
2702 str = "awdl";
2703 break;
2704
2705 case IFRTYPE_FUNCTIONAL_CELLULAR:
2706 str = "cellular";
2707 break;
2708
2709 case IFRTYPE_FUNCTIONAL_INTCOPROC:
2710 break;
2711
2712 #if defined(IFRTYPE_FUNCTIONAL_COMPANIONLINK)
2713 case IFRTYPE_FUNCTIONAL_COMPANIONLINK:
2714 str = "companionlink";
2715 break;
2716 #endif
2717
2718 default:
2719 break;
2720 }
2721 return str;
2722 }