]> git.saurik.com Git - apple/network_cmds.git/blob - ifconfig.tproj/ifconfig.c
network_cmds-543.50.4.tar.gz
[apple/network_cmds.git] / ifconfig.tproj / ifconfig.c
1 /*
2 * Copyright (c) 2009-2018 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 <stdio.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include <unistd.h>
101 #include <sysexits.h>
102
103 #include "ifconfig.h"
104
105 /*
106 * Since "struct ifreq" is composed of various union members, callers
107 * should pay special attention to interprete the value.
108 * (.e.g. little/big endian difference in the structure.)
109 */
110 struct ifreq ifr;
111
112 char name[IFNAMSIZ];
113 int setaddr;
114 int setmask;
115 int doalias;
116 int clearaddr;
117 int newaddr = 1;
118 int noload;
119 int all;
120
121 int bond_details = 0;
122 int supmedia = 0;
123 #if TARGET_OS_EMBEDDED
124 int verbose = 1;
125 int showrtref = 1;
126 #else /* !TARGET_OS_EMBEDDED */
127 int verbose = 0;
128 int showrtref = 0;
129 #endif /* !TARGET_OS_EMBEDDED */
130 int printkeys = 0; /* Print keying material for interfaces. */
131
132 static int ifconfig(int argc, char *const *argv, int iscreate,
133 const struct afswtch *afp);
134 static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
135 struct ifaddrs *ifa);
136 static char *bytes_to_str(unsigned long long bytes);
137 static char *bps_to_str(unsigned long long rate);
138 static char *ns_to_str(unsigned long long nsec);
139 static void tunnel_status(int s);
140 static void usage(void);
141 static char *sched2str(unsigned int s);
142 static char *tl2str(unsigned int s);
143 static char *ift2str(unsigned int t, unsigned int f, unsigned int sf);
144
145 static struct afswtch *af_getbyname(const char *name);
146 static struct afswtch *af_getbyfamily(int af);
147 static void af_other_status(int);
148
149 static struct option *opts = NULL;
150
151 void
152 opt_register(struct option *p)
153 {
154 p->next = opts;
155 opts = p;
156 }
157
158 static void
159 usage(void)
160 {
161 char options[1024];
162 struct option *p;
163
164 /* XXX not right but close enough for now */
165 options[0] = '\0';
166 for (p = opts; p != NULL; p = p->next) {
167 strlcat(options, p->opt_usage, sizeof(options));
168 strlcat(options, " ", sizeof(options));
169 }
170
171 fprintf(stderr,
172 "usage: ifconfig %sinterface address_family [address [dest_address]]\n"
173 " [parameters]\n"
174 " ifconfig interface create\n"
175 " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
176 " ifconfig -l [-d] [-u] [address_family]\n"
177 " ifconfig %s[-d] [-m] [-u] [-v]\n",
178 options, options, options);
179 exit(1);
180 }
181
182 int
183 main(int argc, char *argv[])
184 {
185 int c, namesonly, downonly, uponly;
186 const struct afswtch *afp = NULL;
187 int ifindex;
188 struct ifaddrs *ifap, *ifa;
189 struct ifreq paifr;
190 const struct sockaddr_dl *sdl;
191 char options[1024], *cp;
192 const char *ifname;
193 struct option *p;
194 size_t iflen;
195
196 all = downonly = uponly = namesonly = noload = 0;
197
198 /* Parse leading line options */
199 #ifndef __APPLE__
200 strlcpy(options, "adklmnuv", sizeof(options));
201 #else
202 strlcpy(options, "abdlmruv", sizeof(options));
203 #endif
204 for (p = opts; p != NULL; p = p->next)
205 strlcat(options, p->opt, sizeof(options));
206 while ((c = getopt(argc, argv, options)) != -1) {
207 switch (c) {
208 case 'a': /* scan all interfaces */
209 all++;
210 break;
211 case 'b': /* bond detailed output */
212 bond_details++;
213 break;
214 case 'd': /* restrict scan to "down" interfaces */
215 downonly++;
216 break;
217 #ifndef __APPLE__
218 case 'k':
219 printkeys++;
220 break;
221 #endif
222 case 'l': /* scan interface names only */
223 namesonly++;
224 break;
225 case 'm': /* show media choices in status */
226 supmedia = 1;
227 break;
228 #ifndef __APPLE__
229 case 'n': /* suppress module loading */
230 noload++;
231 break;
232 #endif
233 case 'r':
234 showrtref++;
235 break;
236 case 'u': /* restrict scan to "up" interfaces */
237 uponly++;
238 break;
239 case 'v':
240 verbose++;
241 break;
242 default:
243 for (p = opts; p != NULL; p = p->next)
244 if (p->opt[0] == c) {
245 p->cb(optarg);
246 break;
247 }
248 if (p == NULL)
249 usage();
250 break;
251 }
252 }
253 argc -= optind;
254 argv += optind;
255
256 /* -l cannot be used with -a or -q or -m or -b */
257 if (namesonly &&
258 (all || supmedia || bond_details))
259 usage();
260
261 /* nonsense.. */
262 if (uponly && downonly)
263 usage();
264
265 /* no arguments is equivalent to '-a' */
266 if (!namesonly && argc < 1)
267 all = 1;
268
269 /* -a and -l allow an address family arg to limit the output */
270 if (all || namesonly) {
271 if (argc > 1)
272 usage();
273
274 ifname = NULL;
275 if (argc == 1) {
276 afp = af_getbyname(*argv);
277 if (afp == NULL)
278 usage();
279 if (afp->af_name != NULL)
280 argc--, argv++;
281 /* leave with afp non-zero */
282 }
283 } else {
284 /* not listing, need an argument */
285 if (argc < 1)
286 usage();
287
288 ifname = *argv;
289 argc--, argv++;
290
291 #ifdef notdef
292 /* check and maybe load support for this interface */
293 ifmaybeload(ifname);
294 #endif
295 ifindex = if_nametoindex(ifname);
296 if (ifindex == 0) {
297 /*
298 * NOTE: We must special-case the `create' command
299 * right here as we would otherwise fail when trying
300 * to find the interface.
301 */
302 if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
303 strcmp(argv[0], "plumb") == 0)) {
304 iflen = strlcpy(name, ifname, sizeof(name));
305 if (iflen >= sizeof(name))
306 errx(1, "%s: cloning name too long",
307 ifname);
308 ifconfig(argc, argv, 1, NULL);
309 exit(0);
310 }
311 errx(1, "interface %s does not exist", ifname);
312 }
313 }
314
315 /* Check for address family */
316 if (argc > 0) {
317 afp = af_getbyname(*argv);
318 if (afp != NULL)
319 argc--, argv++;
320 }
321
322 if (getifaddrs(&ifap) != 0)
323 err(EXIT_FAILURE, "getifaddrs");
324 cp = NULL;
325 ifindex = 0;
326 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
327 memset(&paifr, 0, sizeof(paifr));
328 strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
329 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
330 memcpy(&paifr.ifr_addr, ifa->ifa_addr,
331 ifa->ifa_addr->sa_len);
332 }
333
334 if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
335 continue;
336 if (ifa->ifa_addr->sa_family == AF_LINK)
337 sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
338 else
339 sdl = NULL;
340 if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0)
341 continue;
342 iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
343 if (iflen >= sizeof(name)) {
344 warnx("%s: interface name too long, skipping",
345 ifa->ifa_name);
346 continue;
347 }
348 cp = ifa->ifa_name;
349
350 if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
351 continue;
352 if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
353 continue;
354 ifindex++;
355 /*
356 * Are we just listing the interfaces?
357 */
358 if (namesonly) {
359 if (ifindex > 1)
360 printf(" ");
361 fputs(name, stdout);
362 continue;
363 }
364
365 if (argc > 0)
366 ifconfig(argc, argv, 0, afp);
367 else
368 status(afp, sdl, ifa);
369 }
370 if (namesonly)
371 printf("\n");
372 freeifaddrs(ifap);
373
374 exit(0);
375 }
376
377 static struct afswtch *afs = NULL;
378
379 void
380 af_register(struct afswtch *p)
381 {
382 p->af_next = afs;
383 afs = p;
384 }
385
386 static struct afswtch *
387 af_getbyname(const char *name)
388 {
389 struct afswtch *afp;
390
391 for (afp = afs; afp != NULL; afp = afp->af_next)
392 if (strcmp(afp->af_name, name) == 0)
393 return afp;
394 return NULL;
395 }
396
397 static struct afswtch *
398 af_getbyfamily(int af)
399 {
400 struct afswtch *afp;
401
402 for (afp = afs; afp != NULL; afp = afp->af_next)
403 if (afp->af_af == af)
404 return afp;
405 return NULL;
406 }
407
408 static void
409 af_other_status(int s)
410 {
411 struct afswtch *afp;
412 uint8_t afmask[howmany(AF_MAX, NBBY)];
413
414 memset(afmask, 0, sizeof(afmask));
415 for (afp = afs; afp != NULL; afp = afp->af_next) {
416 if (afp->af_other_status == NULL)
417 continue;
418 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
419 continue;
420 afp->af_other_status(s);
421 setbit(afmask, afp->af_af);
422 }
423 }
424
425 static void
426 af_all_tunnel_status(int s)
427 {
428 struct afswtch *afp;
429 uint8_t afmask[howmany(AF_MAX, NBBY)];
430
431 memset(afmask, 0, sizeof(afmask));
432 for (afp = afs; afp != NULL; afp = afp->af_next) {
433 if (afp->af_status_tunnel == NULL)
434 continue;
435 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
436 continue;
437 afp->af_status_tunnel(s);
438 setbit(afmask, afp->af_af);
439 }
440 }
441
442 static struct cmd *cmds = NULL;
443
444 void
445 cmd_register(struct cmd *p)
446 {
447 p->c_next = cmds;
448 cmds = p;
449 }
450
451 static const struct cmd *
452 cmd_lookup(const char *name)
453 {
454 #define N(a) (sizeof(a)/sizeof(a[0]))
455 const struct cmd *p;
456
457 for (p = cmds; p != NULL; p = p->c_next)
458 if (strcmp(name, p->c_name) == 0)
459 return p;
460 return NULL;
461 #undef N
462 }
463
464 struct callback {
465 callback_func *cb_func;
466 void *cb_arg;
467 struct callback *cb_next;
468 };
469 static struct callback *callbacks = NULL;
470
471 void
472 callback_register(callback_func *func, void *arg)
473 {
474 struct callback *cb;
475
476 cb = malloc(sizeof(struct callback));
477 if (cb == NULL)
478 errx(1, "unable to allocate memory for callback");
479 cb->cb_func = func;
480 cb->cb_arg = arg;
481 cb->cb_next = callbacks;
482 callbacks = cb;
483 }
484
485 /* specially-handled commands */
486 static void setifaddr(const char *, int, int, const struct afswtch *);
487 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr);
488
489 static void setifdstaddr(const char *, int, int, const struct afswtch *);
490 static const struct cmd setifdstaddr_cmd =
491 DEF_CMD("ifdstaddr", 0, setifdstaddr);
492
493 static int
494 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp)
495 {
496 const struct afswtch *nafp;
497 struct callback *cb;
498 int s;
499
500 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
501 top:
502 if (afp == NULL)
503 afp = af_getbyname("inet");
504 ifr.ifr_addr.sa_family =
505 afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
506 AF_INET : afp->af_af;
507
508 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
509 err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family);
510
511 while (argc > 0) {
512 const struct cmd *p;
513
514 p = cmd_lookup(*argv);
515 if (p == NULL) {
516 /*
517 * Not a recognized command, choose between setting
518 * the interface address and the dst address.
519 */
520 p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
521 }
522 if (p->c_u.c_func || p->c_u.c_func2) {
523 if (iscreate && !p->c_iscloneop) {
524 /*
525 * Push the clone create callback so the new
526 * device is created and can be used for any
527 * remaining arguments.
528 */
529 cb = callbacks;
530 if (cb == NULL)
531 errx(1, "internal error, no callback");
532 callbacks = cb->cb_next;
533 cb->cb_func(s, cb->cb_arg);
534 iscreate = 0;
535 /*
536 * Handle any address family spec that
537 * immediately follows and potentially
538 * recreate the socket.
539 */
540 nafp = af_getbyname(*argv);
541 if (nafp != NULL) {
542 argc--, argv++;
543 if (nafp != afp) {
544 close(s);
545 afp = nafp;
546 goto top;
547 }
548 }
549 }
550 if (p->c_parameter == NEXTARG) {
551 if (argv[1] == NULL)
552 errx(1, "'%s' requires argument",
553 p->c_name);
554 p->c_u.c_func(argv[1], 0, s, afp);
555 argc--, argv++;
556 } else if (p->c_parameter == OPTARG) {
557 p->c_u.c_func(argv[1], 0, s, afp);
558 if (argv[1] != NULL)
559 argc--, argv++;
560 } else if (p->c_parameter == NEXTARG2) {
561 if (argc < 3)
562 errx(1, "'%s' requires 2 arguments",
563 p->c_name);
564 p->c_u.c_func2(argv[1], argv[2], s, afp);
565 argc -= 2, argv += 2;
566 } else
567 p->c_u.c_func(*argv, p->c_parameter, s, afp);
568 }
569 argc--, argv++;
570 }
571
572 /*
573 * Do any post argument processing required by the address family.
574 */
575 if (afp->af_postproc != NULL)
576 afp->af_postproc(s, afp);
577 /*
578 * Do deferred callbacks registered while processing
579 * command-line arguments.
580 */
581 for (cb = callbacks; cb != NULL; cb = cb->cb_next)
582 cb->cb_func(s, cb->cb_arg);
583 /*
584 * Do deferred operations.
585 */
586 if (clearaddr) {
587 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
588 warnx("interface %s cannot change %s addresses!",
589 name, afp->af_name);
590 clearaddr = 0;
591 }
592 }
593 if (clearaddr) {
594 int ret;
595 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
596 ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
597 if (ret < 0) {
598 if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
599 /* means no previous address for interface */
600 } else
601 Perror("ioctl (SIOCDIFADDR)");
602 }
603 }
604 if (newaddr) {
605 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
606 warnx("interface %s cannot change %s addresses!",
607 name, afp->af_name);
608 newaddr = 0;
609 }
610 }
611 if (newaddr && (setaddr || setmask)) {
612 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
613 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
614 Perror("ioctl (SIOCAIFADDR)");
615 }
616
617 close(s);
618 return(0);
619 }
620
621 /*ARGSUSED*/
622 static void
623 setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
624 {
625 if (afp->af_getaddr == NULL)
626 return;
627 /*
628 * Delay the ioctl to set the interface addr until flags are all set.
629 * The address interpretation may depend on the flags,
630 * and the flags may change when the address is set.
631 */
632 setaddr++;
633 if (doalias == 0 && afp->af_af != AF_LINK)
634 clearaddr = 1;
635 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR));
636 }
637
638 static void
639 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
640 {
641 struct addrinfo *srcres, *dstres;
642 int ecode;
643
644 if (afp->af_settunnel == NULL) {
645 warn("address family %s does not support tunnel setup",
646 afp->af_name);
647 return;
648 }
649
650 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
651 errx(1, "error in parsing address string: %s",
652 gai_strerror(ecode));
653
654 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
655 errx(1, "error in parsing address string: %s",
656 gai_strerror(ecode));
657
658 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
659 errx(1,
660 "source and destination address families do not match");
661
662 afp->af_settunnel(s, srcres, dstres);
663
664 freeaddrinfo(srcres);
665 freeaddrinfo(dstres);
666 }
667
668 /* ARGSUSED */
669 static void
670 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp)
671 {
672
673 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
674 err(1, "SIOCDIFPHYADDR");
675 }
676
677 static void
678 setifnetmask(const char *addr, int dummy __unused, int s,
679 const struct afswtch *afp)
680 {
681 if (afp->af_getaddr != NULL) {
682 setmask++;
683 afp->af_getaddr(addr, MASK);
684 }
685 }
686
687 static void
688 setifbroadaddr(const char *addr, int dummy __unused, int s,
689 const struct afswtch *afp)
690 {
691 if (afp->af_getaddr != NULL)
692 afp->af_getaddr(addr, DSTADDR);
693 }
694
695 static void
696 setifipdst(const char *addr, int dummy __unused, int s,
697 const struct afswtch *afp)
698 {
699 const struct afswtch *inet;
700
701 inet = af_getbyname("inet");
702 if (inet == NULL)
703 return;
704 inet->af_getaddr(addr, DSTADDR);
705 clearaddr = 0;
706 newaddr = 0;
707 }
708
709 static void
710 notealias(const char *addr, int param, int s, const struct afswtch *afp)
711 {
712 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
713 if (setaddr && doalias == 0 && param < 0)
714 if (afp->af_addreq != NULL && afp->af_ridreq != NULL)
715 bcopy((caddr_t)rqtosa(af_addreq),
716 (caddr_t)rqtosa(af_ridreq),
717 rqtosa(af_addreq)->sa_len);
718 doalias = param;
719 if (param < 0) {
720 clearaddr = 1;
721 newaddr = 0;
722 } else
723 clearaddr = 0;
724 #undef rqtosa
725 }
726
727 /*ARGSUSED*/
728 static void
729 setifdstaddr(const char *addr, int param __unused, int s,
730 const struct afswtch *afp)
731 {
732 if (afp->af_getaddr != NULL)
733 afp->af_getaddr(addr, DSTADDR);
734 }
735
736 /*
737 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
738 * of the ifreq structure, which may confuse other parts of ifconfig.
739 * Make a private copy so we can avoid that.
740 */
741 static void
742 setifflags(const char *vname, int value, int s, const struct afswtch *afp)
743 {
744 struct ifreq my_ifr;
745 int flags;
746
747 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq));
748
749 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
750 Perror("ioctl (SIOCGIFFLAGS)");
751 exit(1);
752 }
753 strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name));
754 flags = my_ifr.ifr_flags;
755
756 if (value < 0) {
757 value = -value;
758 flags &= ~value;
759 } else
760 flags |= value;
761 my_ifr.ifr_flags = flags & 0xffff;
762 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
763 Perror(vname);
764 }
765
766 void
767 setifcap(const char *vname, int value, int s, const struct afswtch *afp)
768 {
769 int flags;
770
771 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
772 Perror("ioctl (SIOCGIFCAP)");
773 exit(1);
774 }
775 flags = ifr.ifr_curcap;
776 if (value < 0) {
777 value = -value;
778 flags &= ~value;
779 } else
780 flags |= value;
781 flags &= ifr.ifr_reqcap;
782 ifr.ifr_reqcap = flags;
783 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
784 Perror(vname);
785 }
786
787 static void
788 setifmetric(const char *val, int dummy __unused, int s,
789 const struct afswtch *afp)
790 {
791 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
792 ifr.ifr_metric = atoi(val);
793 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
794 warn("ioctl (set metric)");
795 }
796
797 static void
798 setifmtu(const char *val, int dummy __unused, int s,
799 const struct afswtch *afp)
800 {
801 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
802 ifr.ifr_mtu = atoi(val);
803 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
804 warn("ioctl (set mtu)");
805 }
806
807 #ifndef __APPLE__
808 static void
809 setifname(const char *val, int dummy __unused, int s,
810 const struct afswtch *afp)
811 {
812 char *newname;
813
814 newname = strdup(val);
815 if (newname == NULL) {
816 warn("no memory to set ifname");
817 return;
818 }
819 ifr.ifr_data = newname;
820 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
821 warn("ioctl (set name)");
822 free(newname);
823 return;
824 }
825 strlcpy(name, newname, sizeof(name));
826 free(newname);
827 }
828 #endif
829
830 static void
831 setrouter(const char *vname, int value, int s, const struct afswtch *afp)
832 {
833 if (afp->af_setrouter == NULL) {
834 warn("address family %s does not support router mode",
835 afp->af_name);
836 return;
837 }
838
839 afp->af_setrouter(s, value);
840 }
841
842 static void
843 setifdesc(const char *val, int dummy __unused, int s, const struct afswtch *afp)
844 {
845 struct if_descreq ifdr;
846
847 bzero(&ifdr, sizeof (ifdr));
848 strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name));
849 ifdr.ifdr_len = strlen(val);
850 strncpy((char *)ifdr.ifdr_desc, val, sizeof (ifdr.ifdr_desc));
851
852 if (ioctl(s, SIOCSIFDESC, (caddr_t)&ifdr) < 0) {
853 warn("ioctl (set desc)");
854 }
855 }
856
857 static void
858 settbr(const char *val, int dummy __unused, int s, const struct afswtch *afp)
859 {
860 struct if_linkparamsreq iflpr;
861 long double bps;
862 u_int64_t rate;
863 u_int32_t percent = 0;
864 char *cp;
865
866 errno = 0;
867 bzero(&iflpr, sizeof (iflpr));
868 strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name));
869
870 bps = strtold(val, &cp);
871 if (val == cp || errno != 0) {
872 warn("Invalid value '%s'", val);
873 return;
874 }
875 rate = (u_int64_t)bps;
876 if (cp != NULL) {
877 if (!strcmp(cp, "b") || !strcmp(cp, "bps")) {
878 ; /* nothing */
879 } else if (!strcmp(cp, "Kb") || !strcmp(cp, "Kbps")) {
880 rate *= 1000;
881 } else if (!strcmp(cp, "Mb") || !strcmp(cp, "Mbps")) {
882 rate *= 1000 * 1000;
883 } else if (!strcmp(cp, "Gb") || !strcmp(cp, "Gbps")) {
884 rate *= 1000 * 1000 * 1000;
885 } else if (!strcmp(cp, "%")) {
886 percent = rate;
887 if (percent == 0 || percent > 100) {
888 printf("Value out of range '%s'", val);
889 return;
890 }
891 } else if (*cp != '\0') {
892 printf("Unknown unit '%s'", cp);
893 return;
894 }
895 }
896 iflpr.iflpr_output_tbr_rate = rate;
897 iflpr.iflpr_output_tbr_percent = percent;
898 if (ioctl(s, SIOCSIFLINKPARAMS, &iflpr) < 0 &&
899 errno != ENOENT && errno != ENXIO && errno != ENODEV) {
900 warn("ioctl (set link params)");
901 } else if (errno == ENXIO) {
902 printf("TBR cannot be set on %s\n", name);
903 } else if (errno == ENOENT || rate == 0) {
904 printf("%s: TBR is now disabled\n", name);
905 } else if (errno == ENODEV) {
906 printf("%s: requires absolute TBR rate\n", name);
907 } else if (percent != 0) {
908 printf("%s: TBR rate set to %u%% of effective link rate\n",
909 name, percent);
910 } else {
911 printf("%s: TBR rate set to %s\n", name, bps_to_str(rate));
912 }
913 }
914
915 static void
916 setthrottle(const char *val, int dummy __unused, int s,
917 const struct afswtch *afp)
918 {
919 struct if_throttlereq iftr;
920 char *cp;
921
922 errno = 0;
923 bzero(&iftr, sizeof (iftr));
924 strncpy(iftr.ifthr_name, name, sizeof (iftr.ifthr_name));
925
926 iftr.ifthr_level = strtold(val, &cp);
927 if (val == cp || errno != 0) {
928 warn("Invalid value '%s'", val);
929 return;
930 }
931
932 if (ioctl(s, SIOCSIFTHROTTLE, &iftr) < 0 && errno != ENXIO) {
933 warn("ioctl (set throttling level)");
934 } else if (errno == ENXIO) {
935 printf("throttling level cannot be set on %s\n", name);
936 } else {
937 printf("%s: throttling level set to %d\n", name,
938 iftr.ifthr_level);
939 }
940 }
941
942 static void
943 setdisableoutput(const char *val, int dummy __unused, int s,
944 const struct afswtch *afp)
945 {
946 struct ifreq ifr;
947 char *cp;
948 errno = 0;
949 bzero(&ifr, sizeof (ifr));
950 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
951
952 ifr.ifr_ifru.ifru_disable_output = strtold(val, &cp);
953 if (val == cp || errno != 0) {
954 warn("Invalid value '%s'", val);
955 return;
956 }
957
958 if (ioctl(s, SIOCSIFDISABLEOUTPUT, &ifr) < 0 && errno != ENXIO) {
959 warn("ioctl set disable output");
960 } else if (errno == ENXIO) {
961 printf("output thread can not be disabled on %s\n", name);
962 } else {
963 printf("output %s on %s\n",
964 ((ifr.ifr_ifru.ifru_disable_output == 0) ? "enabled" : "disabled"),
965 name);
966 }
967 }
968
969 static void
970 setlog(const char *val, int dummy __unused, int s,
971 const struct afswtch *afp)
972 {
973 char *cp;
974
975 errno = 0;
976 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
977
978 ifr.ifr_log.ifl_level = strtold(val, &cp);
979 if (val == cp || errno != 0) {
980 warn("Invalid value '%s'", val);
981 return;
982 }
983 ifr.ifr_log.ifl_flags = (IFRLOGF_DLIL|IFRLOGF_FAMILY|IFRLOGF_DRIVER|
984 IFRLOGF_FIRMWARE);
985
986 if (ioctl(s, SIOCSIFLOG, &ifr) < 0)
987 warn("ioctl (set logging parameters)");
988 }
989
990 void
991 setcl2k(const char *vname, int value, int s, const struct afswtch *afp)
992 {
993 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
994 ifr.ifr_ifru.ifru_2kcl = value;
995
996 if (ioctl(s, SIOCSIF2KCL, (caddr_t)&ifr) < 0)
997 Perror(vname);
998 }
999
1000 void
1001 setexpensive(const char *vname, int value, int s, const struct afswtch *afp)
1002 {
1003 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1004 ifr.ifr_ifru.ifru_expensive = value;
1005
1006 if (ioctl(s, SIOCSIFEXPENSIVE, (caddr_t)&ifr) < 0)
1007 Perror(vname);
1008 }
1009
1010 void
1011 settimestamp(const char *vname, int value, int s, const struct afswtch *afp)
1012 {
1013 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1014
1015 if (value == 0) {
1016 if (ioctl(s, SIOCSIFTIMESTAMPDISABLE, (caddr_t)&ifr) < 0)
1017 Perror(vname);
1018 } else {
1019 if (ioctl(s, SIOCSIFTIMESTAMPENABLE, (caddr_t)&ifr) < 0)
1020 Perror(vname);
1021 }
1022 }
1023
1024 void
1025 setecnmode(const char *val, int dummy __unused, int s,
1026 const struct afswtch *afp)
1027 {
1028 char *cp;
1029
1030 if (strcmp(val, "default") == 0)
1031 ifr.ifr_ifru.ifru_ecn_mode = IFRTYPE_ECN_DEFAULT;
1032 else if (strcmp(val, "enable") == 0)
1033 ifr.ifr_ifru.ifru_ecn_mode = IFRTYPE_ECN_ENABLE;
1034 else if (strcmp(val, "disable") == 0)
1035 ifr.ifr_ifru.ifru_ecn_mode = IFRTYPE_ECN_DISABLE;
1036 else {
1037 ifr.ifr_ifru.ifru_ecn_mode = strtold(val, &cp);
1038 if (val == cp || errno != 0) {
1039 warn("Invalid ECN mode value '%s'", val);
1040 return;
1041 }
1042 }
1043
1044 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1045
1046 if (ioctl(s, SIOCSECNMODE, (caddr_t)&ifr) < 0)
1047 Perror("ioctl(SIOCSECNMODE)");
1048 }
1049
1050 void
1051 setprobeconnectivity(const char *vname, int value, int s, const struct afswtch *afp)
1052 {
1053 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1054 ifr.ifr_ifru.ifru_probe_connectivity = value;
1055
1056 if (ioctl(s, SIOCSIFPROBECONNECTIVITY, (caddr_t)&ifr) < 0)
1057 Perror(vname);
1058 }
1059
1060 #if defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED)
1061
1062 void
1063 setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1064 {
1065 u_long ioc;
1066
1067 #if (DEBUG | DEVELOPMENT)
1068 printf("%s(%s, %s)\n", __func__, cmd, arg);
1069 #endif /* (DEBUG | DEVELOPMENT) */
1070
1071 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1072
1073 if (strcmp(cmd, "mode") == 0) {
1074 ioc = SIOCSQOSMARKINGMODE;
1075
1076 if (strcmp(arg, "fastlane") == 0)
1077 ifr.ifr_qosmarking_mode = IFRTYPE_QOSMARKING_FASTLANE;
1078 else if (strcasecmp(arg, "none") == 0 || strcasecmp(arg, "off") == 0)
1079 ifr.ifr_qosmarking_mode = IFRTYPE_QOSMARKING_MODE_NONE;
1080 else
1081 err(EX_USAGE, "bad value for qosmarking mode: %s", arg);
1082 } else if (strcmp(cmd, "enabled") == 0) {
1083 ioc = SIOCSQOSMARKINGENABLED;
1084 if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
1085 strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
1086 ifr.ifr_qosmarking_enabled = 1;
1087 else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
1088 strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
1089 ifr.ifr_qosmarking_enabled = 0;
1090 else
1091 err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
1092 } else {
1093 err(EX_USAGE, "qosmarking takes mode or enabled");
1094 }
1095
1096 if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
1097 err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
1098 }
1099
1100 void
1101 setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1102 {
1103 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1104
1105 warnx("### fastlane is obsolete, use qosmarking ###");
1106
1107 if (strcmp(cmd, "capable") == 0) {
1108 if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
1109 strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
1110 setqosmarking("mode", "fastlane", s, afp);
1111 else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
1112 strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
1113 setqosmarking("mode", "off", s, afp);
1114 else
1115 err(EX_USAGE, "bad value for fastlane %s", cmd);
1116 } else if (strcmp(cmd, "enable") == 0) {
1117 if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
1118 strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
1119 setqosmarking("enabled", "1", s, afp);
1120 else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
1121 strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
1122 setqosmarking("enabled", "0", s, afp);
1123 else
1124 err(EX_USAGE, "bad value for fastlane %s", cmd);
1125 } else {
1126 err(EX_USAGE, "fastlane takes capable or enable");
1127 }
1128 }
1129
1130 #else /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
1131
1132 void
1133 setfastlane(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1134 {
1135 int value;
1136 u_long ioc;
1137
1138 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1139
1140 if (strcmp(cmd, "capable") == 0)
1141 ioc = SIOCSFASTLANECAPABLE;
1142 else if (strcmp(cmd, "enable") == 0)
1143 ioc = SIOCSFASTLEENABLED;
1144 else
1145 err(EX_USAGE, "fastlane takes capable or enabled");
1146
1147 if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
1148 strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
1149 value = 1;
1150 else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
1151 strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
1152 value = 0;
1153 else
1154 err(EX_USAGE, "bad value for fastlane %s", cmd);
1155
1156 if (ioc == SIOCSFASTLANECAPABLE)
1157 ifr.ifr_fastlane_capable = value;
1158 else
1159 ifr.ifr_fastlane_enabled = value;
1160
1161 if (ioctl(s, ioc, (caddr_t)&ifr) < 0)
1162 err(EX_OSERR, "ioctl(%s, %s)", cmd, arg);
1163 }
1164
1165
1166 void
1167 setqosmarking(const char *cmd, const char *arg, int s, const struct afswtch *afp)
1168 {
1169 if (strcmp(cmd, "mode") == 0) {
1170 if (strcmp(arg, "fastlane") == 0)
1171 setfastlane("capable", "on", s, afp);
1172 else if (strcmp(arg, "none") == 0)
1173 setfastlane("capable", "off", s, afp);
1174 else
1175 err(EX_USAGE, "bad value for qosmarking mode: %s", arg);
1176 } else if (strcmp(cmd, "enabled") == 0) {
1177 if (strcmp(arg, "1") == 0 || strcasecmp(arg, "on") == 0||
1178 strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0)
1179 setfastlane("enable", "on", s, afp);
1180 else if (strcmp(arg, "0") == 0 || strcasecmp(arg, "off") == 0||
1181 strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0)
1182 setfastlane("enable", "off", s, afp);
1183 else
1184 err(EX_USAGE, "bad value for qosmarking enabled: %s", arg);
1185 } else {
1186 err(EX_USAGE, "qosmarking takes mode or enabled");
1187 }
1188 }
1189
1190 #endif /* defined(SIOCSQOSMARKINGMODE) && defined(SIOCSQOSMARKINGENABLED) */
1191
1192 #define IFFBITS \
1193 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
1194 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
1195 "\20MULTICAST"
1196
1197 #define IFEFBITS \
1198 "\020\1AUTOCONFIGURING\4PROBE_CONNECTIVITY\5FASTLN_CAP\6IPV6_DISABLED\7ACCEPT_RTADV\10TXSTART\11RXPOLL" \
1199 "\12VLAN\13BOND\14ARPLL\15NOWINDOWSCALE\16NOAUTOIPV6LL\17EXPENSIVE\20ROUTER4" \
1200 "\21ROUTER6\22LOCALNET_PRIVATE\23ND6ALT\24RESTRICTED_RECV\25AWDL\26NOACKPRI" \
1201 "\27AWDL_RESTRICTED\30CL2K\31ECN_ENABLE\32ECN_DISABLE\33CHANNEL_DRV\34CA" \
1202 "\35SENDLIST\36DIRECTLINK\37FASTLN_ON\40UPDOWNCHANGE"
1203
1204 #define IFCAPBITS \
1205 "\020\1RXCSUM\2TXCSUM\3VLAN_MTU\4VLAN_HWTAGGING\5JUMBO_MTU" \
1206 "\6TSO4\7TSO6\10LRO\11AV\12TXSTATUS\13CHANNEL_IO\14HW_TIMESTAMP\15SW_TIMESTAMP" \
1207 "\16PARTIAL_CSUM\17ZEROINVERT_CSUM"
1208
1209 #define IFRLOGF_BITS \
1210 "\020\1DLIL\21FAMILY\31DRIVER\35FIRMWARE"
1211
1212 /*
1213 * Print the status of the interface. If an address family was
1214 * specified, show only it; otherwise, show them all.
1215 */
1216 static void
1217 status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
1218 struct ifaddrs *ifa)
1219 {
1220 struct ifaddrs *ift;
1221 int allfamilies, s;
1222 struct ifstat ifs;
1223 struct if_descreq ifdr;
1224 struct if_linkparamsreq iflpr;
1225 int mib[6];
1226 struct ifmibdata_supplemental ifmsupp;
1227 size_t miblen = sizeof(struct ifmibdata_supplemental);
1228 u_int64_t eflags = 0;
1229 int curcap = 0;
1230
1231 if (afp == NULL) {
1232 allfamilies = 1;
1233 afp = af_getbyname("inet");
1234 } else
1235 allfamilies = 0;
1236
1237 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af;
1238 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1239
1240 s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
1241 if (s < 0)
1242 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
1243
1244 printf("%s: ", name);
1245 printb("flags", ifa->ifa_flags, IFFBITS);
1246 if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
1247 if (ifr.ifr_metric)
1248 printf(" metric %d", ifr.ifr_metric);
1249 if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
1250 printf(" mtu %d", ifr.ifr_mtu);
1251 if (showrtref && ioctl(s, SIOCGIFGETRTREFCNT, &ifr) != -1)
1252 printf(" rtref %d", ifr.ifr_route_refcnt);
1253 if (verbose) {
1254 unsigned int ifindex = if_nametoindex(ifa->ifa_name);
1255 if (ifindex != 0)
1256 printf(" index %u", ifindex);
1257 }
1258 putchar('\n');
1259
1260 if (verbose && ioctl(s, SIOCGIFEFLAGS, (caddr_t)&ifr) != -1 &&
1261 (eflags = ifr.ifr_eflags) != 0) {
1262 printb("\teflags", eflags, IFEFBITS);
1263 putchar('\n');
1264 }
1265
1266 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
1267 if (ifr.ifr_curcap != 0) {
1268 curcap = ifr.ifr_curcap;
1269 printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
1270 putchar('\n');
1271 }
1272 if (supmedia && ifr.ifr_reqcap != 0) {
1273 printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS);
1274 putchar('\n');
1275 }
1276 }
1277
1278 tunnel_status(s);
1279
1280 for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
1281 if (ift->ifa_addr == NULL)
1282 continue;
1283 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0)
1284 continue;
1285 if (allfamilies) {
1286 const struct afswtch *p;
1287 p = af_getbyfamily(ift->ifa_addr->sa_family);
1288 if (p != NULL && p->af_status != NULL)
1289 p->af_status(s, ift);
1290 } else if (afp->af_af == ift->ifa_addr->sa_family)
1291 afp->af_status(s, ift);
1292 }
1293 #if 0
1294 if (allfamilies || afp->af_af == AF_LINK) {
1295 const struct afswtch *lafp;
1296
1297 /*
1298 * Hack; the link level address is received separately
1299 * from the routing information so any address is not
1300 * handled above. Cobble together an entry and invoke
1301 * the status method specially.
1302 */
1303 lafp = af_getbyname("lladdr");
1304 if (lafp != NULL) {
1305 info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl;
1306 lafp->af_status(s, &info);
1307 }
1308 }
1309 #endif
1310 if (allfamilies)
1311 af_other_status(s);
1312 else if (afp->af_other_status != NULL)
1313 afp->af_other_status(s);
1314
1315 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
1316 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
1317 printf("%s", ifs.ascii);
1318
1319 /* The rest is for when verbose is set; if not set, we're done */
1320 if (!verbose)
1321 goto done;
1322
1323 if (ioctl(s, SIOCGIFTYPE, &ifr) != -1) {
1324 char *c = ift2str(ifr.ifr_type.ift_type,
1325 ifr.ifr_type.ift_family, ifr.ifr_type.ift_subfamily);
1326 if (c != NULL)
1327 printf("\ttype: %s\n", c);
1328 }
1329
1330 if (verbose > 0) {
1331 struct if_agentidsreq ifar;
1332 memset(&ifar, 0, sizeof(ifar));
1333
1334 strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name));
1335
1336 if (ioctl(s, SIOCGIFAGENTIDS, &ifar) != -1) {
1337 if (ifar.ifar_count != 0) {
1338 ifar.ifar_uuids = calloc(ifar.ifar_count, sizeof(uuid_t));
1339 if (ifar.ifar_uuids != NULL) {
1340 if (ioctl(s, SIOCGIFAGENTIDS, &ifar) != 1) {
1341 for (int agent_i = 0; agent_i < ifar.ifar_count; agent_i++) {
1342 struct netagent_req nar;
1343 memset(&nar, 0, sizeof(nar));
1344
1345 uuid_copy(nar.netagent_uuid, ifar.ifar_uuids[agent_i]);
1346
1347 if (ioctl(s, SIOCGIFAGENTDATA, &nar) != 1) {
1348 printf("\tagent domain:%s type:%s flags:0x%x desc:\"%s\"\n",
1349 nar.netagent_domain, nar.netagent_type,
1350 nar.netagent_flags, nar.netagent_desc);
1351 }
1352 }
1353 }
1354 free(ifar.ifar_uuids);
1355 }
1356 }
1357 }
1358 }
1359
1360 if (ioctl(s, SIOCGIFLINKQUALITYMETRIC, &ifr) != -1) {
1361 int lqm = ifr.ifr_link_quality_metric;
1362 if (verbose > 1) {
1363 printf("\tlink quality: %d ", lqm);
1364 if (lqm == IFNET_LQM_THRESH_OFF)
1365 printf("(off)");
1366 else if (lqm == IFNET_LQM_THRESH_UNKNOWN)
1367 printf("(unknown)");
1368 else if (lqm > IFNET_LQM_THRESH_UNKNOWN &&
1369 lqm <= IFNET_LQM_THRESH_BAD)
1370 printf("(bad)");
1371 else if (lqm > IFNET_LQM_THRESH_UNKNOWN &&
1372 lqm <= IFNET_LQM_THRESH_POOR)
1373 printf("(poor)");
1374 else if (lqm > IFNET_LQM_THRESH_POOR &&
1375 lqm <= IFNET_LQM_THRESH_GOOD)
1376 printf("(good)");
1377 else
1378 printf("(?)");
1379 printf("\n");
1380 } else if (lqm > IFNET_LQM_THRESH_UNKNOWN) {
1381 printf("\tlink quality: %d ", lqm);
1382 if (lqm <= IFNET_LQM_THRESH_BAD)
1383 printf("(bad)");
1384 else if (lqm <= IFNET_LQM_THRESH_POOR)
1385 printf("(poor)");
1386 else if (lqm <= IFNET_LQM_THRESH_GOOD)
1387 printf("(good)");
1388 else
1389 printf("(?)");
1390 printf("\n");
1391 }
1392 }
1393
1394 if (verbose > 0) {
1395 if (ioctl(s, SIOCGIFINTERFACESTATE, &ifr) != -1) {
1396 printf("\tstate");
1397 if (ifr.ifr_interface_state.valid_bitmask &
1398 IF_INTERFACE_STATE_RRC_STATE_VALID) {
1399 uint8_t rrc_state = ifr.ifr_interface_state.rrc_state;
1400
1401 printf(" rrc: %u ", rrc_state);
1402 if (rrc_state == IF_INTERFACE_STATE_RRC_STATE_CONNECTED)
1403 printf("(connected)");
1404 else if (rrc_state == IF_INTERFACE_STATE_RRC_STATE_IDLE)
1405 printf("(idle)");
1406 else
1407 printf("(?)");
1408 }
1409 if (ifr.ifr_interface_state.valid_bitmask &
1410 IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID) {
1411 uint8_t ifavail = ifr.ifr_interface_state.interface_availability;
1412
1413 printf(" availability: %u ", ifavail);
1414 if (ifavail == IF_INTERFACE_STATE_INTERFACE_AVAILABLE)
1415 printf("(true)");
1416 else if (ifavail == IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE)
1417 printf("(false)");
1418 else
1419 printf("(?)");
1420 } else {
1421 printf(" availability: (not valid)");
1422 }
1423 if (verbose > 1 &&
1424 ifr.ifr_interface_state.valid_bitmask &
1425 IF_INTERFACE_STATE_LQM_STATE_VALID) {
1426 int8_t lqm = ifr.ifr_interface_state.lqm_state;
1427
1428 printf(" lqm: %d", lqm);
1429
1430 if (lqm == IFNET_LQM_THRESH_OFF)
1431 printf("(off)");
1432 else if (lqm == IFNET_LQM_THRESH_UNKNOWN)
1433 printf("(unknown)");
1434 else if (lqm == IFNET_LQM_THRESH_BAD)
1435 printf("(bad)");
1436 else if (lqm == IFNET_LQM_THRESH_POOR)
1437 printf("(poor)");
1438 else if (lqm == IFNET_LQM_THRESH_GOOD)
1439 printf("(good)");
1440 else
1441 printf("(?)");
1442 }
1443 }
1444 printf("\n");
1445 }
1446
1447 bzero(&iflpr, sizeof (iflpr));
1448 strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name));
1449 if (ioctl(s, SIOCGIFLINKPARAMS, &iflpr) != -1) {
1450 u_int64_t ibw_max = iflpr.iflpr_input_bw.max_bw;
1451 u_int64_t ibw_eff = iflpr.iflpr_input_bw.eff_bw;
1452 u_int64_t obw_max = iflpr.iflpr_output_bw.max_bw;
1453 u_int64_t obw_eff = iflpr.iflpr_output_bw.eff_bw;
1454 u_int64_t obw_tbr = iflpr.iflpr_output_tbr_rate;
1455 u_int32_t obw_pct = iflpr.iflpr_output_tbr_percent;
1456 u_int64_t ilt_max = iflpr.iflpr_input_lt.max_lt;
1457 u_int64_t ilt_eff = iflpr.iflpr_input_lt.eff_lt;
1458 u_int64_t olt_max = iflpr.iflpr_output_lt.max_lt;
1459 u_int64_t olt_eff = iflpr.iflpr_output_lt.eff_lt;
1460
1461
1462 if (eflags & IFEF_TXSTART) {
1463 u_int32_t flags = iflpr.iflpr_flags;
1464 u_int32_t sched = iflpr.iflpr_output_sched;
1465 struct if_throttlereq iftr;
1466
1467 printf("\tscheduler: %s%s ",
1468 (flags & IFLPRF_ALTQ) ? "ALTQ_" : "",
1469 sched2str(sched));
1470 if (flags & IFLPRF_DRVMANAGED)
1471 printf("(driver managed)");
1472 printf("\n");
1473
1474 bzero(&iftr, sizeof (iftr));
1475 strncpy(iftr.ifthr_name, name,
1476 sizeof (iftr.ifthr_name));
1477 if (ioctl(s, SIOCGIFTHROTTLE, &iftr) != -1 &&
1478 iftr.ifthr_level != IFNET_THROTTLE_OFF)
1479 printf("\tthrottling: level %d (%s)\n",
1480 iftr.ifthr_level, tl2str(iftr.ifthr_level));
1481 }
1482
1483 if (obw_tbr != 0 && obw_eff > obw_tbr)
1484 obw_eff = obw_tbr;
1485
1486 if (ibw_max != 0 || obw_max != 0) {
1487 if (ibw_max == obw_max && ibw_eff == obw_eff &&
1488 ibw_max == ibw_eff && obw_tbr == 0) {
1489 printf("\tlink rate: %s\n",
1490 bps_to_str(ibw_max));
1491 } else {
1492 printf("\tuplink rate: %s [eff] / ",
1493 bps_to_str(obw_eff));
1494 if (obw_tbr != 0) {
1495 if (obw_pct == 0)
1496 printf("%s [tbr] / ",
1497 bps_to_str(obw_tbr));
1498 else
1499 printf("%s [tbr %u%%] / ",
1500 bps_to_str(obw_tbr),
1501 obw_pct);
1502 }
1503 printf("%s", bps_to_str(obw_max));
1504 if (obw_tbr != 0)
1505 printf(" [max]");
1506 printf("\n");
1507 if (ibw_eff == ibw_max) {
1508 printf("\tdownlink rate: %s\n",
1509 bps_to_str(ibw_max));
1510 } else {
1511 printf("\tdownlink rate: "
1512 "%s [eff] / ", bps_to_str(ibw_eff));
1513 printf("%s [max]\n",
1514 bps_to_str(ibw_max));
1515 }
1516 }
1517 } else if (obw_tbr != 0) {
1518 printf("\tuplink rate: %s [tbr]\n",
1519 bps_to_str(obw_tbr));
1520 }
1521
1522 if (ilt_max != 0 || olt_max != 0) {
1523 if (ilt_max == olt_max && ilt_eff == olt_eff &&
1524 ilt_max == ilt_eff) {
1525 printf("\tlink latency: %s\n",
1526 ns_to_str(ilt_max));
1527 } else {
1528 if (olt_max != 0 && olt_eff == olt_max) {
1529 printf("\tuplink latency: %s\n",
1530 ns_to_str(olt_max));
1531 } else if (olt_max != 0) {
1532 printf("\tuplink latency: "
1533 "%s [eff] / ", ns_to_str(olt_eff));
1534 printf("%s [max]\n",
1535 ns_to_str(olt_max));
1536 }
1537 if (ilt_max != 0 && ilt_eff == ilt_max) {
1538 printf("\tdownlink latency: %s\n",
1539 ns_to_str(ilt_max));
1540 } else if (ilt_max != 0) {
1541 printf("\tdownlink latency: "
1542 "%s [eff] / ", ns_to_str(ilt_eff));
1543 printf("%s [max]\n",
1544 ns_to_str(ilt_max));
1545 }
1546 }
1547 }
1548 }
1549
1550 /* Common OID prefix */
1551 mib[0] = CTL_NET;
1552 mib[1] = PF_LINK;
1553 mib[2] = NETLINK_GENERIC;
1554 mib[3] = IFMIB_IFDATA;
1555 mib[4] = if_nametoindex(name);
1556 mib[5] = IFDATA_SUPPLEMENTAL;
1557 if (sysctl(mib, 6, &ifmsupp, &miblen, (void *)0, 0) == -1)
1558 err(1, "sysctl IFDATA_SUPPLEMENTAL");
1559
1560 if (ifmsupp.ifmd_data_extended.ifi_alignerrs != 0) {
1561 printf("\tunaligned pkts: %llu\n",
1562 ifmsupp.ifmd_data_extended.ifi_alignerrs);
1563 }
1564 if (ifmsupp.ifmd_data_extended.ifi_dt_bytes != 0) {
1565 printf("\tdata milestone interval: %s\n",
1566 bytes_to_str(ifmsupp.ifmd_data_extended.ifi_dt_bytes));
1567 }
1568
1569 bzero(&ifdr, sizeof (ifdr));
1570 strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name));
1571 if (ioctl(s, SIOCGIFDESC, &ifdr) != -1 && ifdr.ifdr_len) {
1572 printf("\tdesc: %s\n", ifdr.ifdr_desc);
1573 }
1574
1575 if (ioctl(s, SIOCGIFLOG, &ifr) != -1 && ifr.ifr_log.ifl_level) {
1576 printf("\tlogging: level %d ", ifr.ifr_log.ifl_level);
1577 printb("facilities", ifr.ifr_log.ifl_flags, IFRLOGF_BITS);
1578 putchar('\n');
1579 }
1580
1581 if (ioctl(s, SIOCGIFDELEGATE, &ifr) != -1 && ifr.ifr_delegated) {
1582 char delegatedif[IFNAMSIZ+1];
1583 if (if_indextoname(ifr.ifr_delegated, delegatedif) != NULL)
1584 printf("\teffective interface: %s\n", delegatedif);
1585 }
1586
1587 if (ioctl(s, SIOCGSTARTDELAY, &ifr) != -1) {
1588 if (ifr.ifr_start_delay_qlen > 0 &&
1589 ifr.ifr_start_delay_timeout > 0) {
1590 printf("\ttxstart qlen: %u packets "
1591 "timeout: %u microseconds\n",
1592 ifr.ifr_start_delay_qlen,
1593 ifr.ifr_start_delay_timeout/1000);
1594 }
1595 }
1596 #if defined(IFCAP_HW_TIMESTAMP) && defined(IFCAP_SW_TIMESTAMP)
1597 if ((curcap & (IFCAP_HW_TIMESTAMP | IFCAP_SW_TIMESTAMP)) &&
1598 ioctl(s, SIOCGIFTIMESTAMPENABLED, &ifr) != -1) {
1599 printf("\ttimestamp: %s\n",
1600 (ifr.ifr_intval != 0) ? "enabled" : "disabled");
1601 }
1602 #endif
1603 #if defined(SIOCGQOSMARKINGENABLED) && defined(SIOCGQOSMARKINGMODE)
1604 if (ioctl(s, SIOCGQOSMARKINGENABLED, &ifr) != -1) {
1605 printf("\tqosmarking enabled: %s mode: ",
1606 ifr.ifr_qosmarking_enabled ? "yes" : "no");
1607 if (ioctl(s, SIOCGQOSMARKINGMODE, &ifr) != -1) {
1608 switch (ifr.ifr_qosmarking_mode) {
1609 case IFRTYPE_QOSMARKING_FASTLANE:
1610 printf("fastlane\n");
1611 break;
1612 case IFRTYPE_QOSMARKING_MODE_NONE:
1613 printf("none\n");
1614 break;
1615 default:
1616 printf("unknown (%u)\n", ifr.ifr_qosmarking_mode);
1617 break;
1618 }
1619 }
1620 }
1621 #endif /* defined(SIOCGQOSMARKINGENABLED) && defined(SIOCGQOSMARKINGMODE) */
1622 done:
1623 close(s);
1624 return;
1625 }
1626
1627 #define KILOBYTES 1024
1628 #define MEGABYTES (KILOBYTES * KILOBYTES)
1629 #define GIGABYTES (KILOBYTES * KILOBYTES * KILOBYTES)
1630
1631 static char *
1632 bytes_to_str(unsigned long long bytes)
1633 {
1634 static char buf[32];
1635 const char *u;
1636 long double n = bytes, t;
1637
1638 if (bytes >= GIGABYTES) {
1639 t = n / GIGABYTES;
1640 u = "GB";
1641 } else if (n >= MEGABYTES) {
1642 t = n / MEGABYTES;
1643 u = "MB";
1644 } else if (n >= KILOBYTES) {
1645 t = n / KILOBYTES;
1646 u = "KB";
1647 } else {
1648 t = n;
1649 u = "bytes";
1650 }
1651
1652 snprintf(buf, sizeof (buf), "%-4.2Lf %s", t, u);
1653 return (buf);
1654 }
1655
1656 #define GIGABIT_PER_SEC 1000000000 /* gigabit per second */
1657 #define MEGABIT_PER_SEC 1000000 /* megabit per second */
1658 #define KILOBIT_PER_SEC 1000 /* kilobit per second */
1659
1660 static char *
1661 bps_to_str(unsigned long long rate)
1662 {
1663 static char buf[32];
1664 const char *u;
1665 long double n = rate, t;
1666
1667 if (rate >= GIGABIT_PER_SEC) {
1668 t = n / GIGABIT_PER_SEC;
1669 u = "Gbps";
1670 } else if (n >= MEGABIT_PER_SEC) {
1671 t = n / MEGABIT_PER_SEC;
1672 u = "Mbps";
1673 } else if (n >= KILOBIT_PER_SEC) {
1674 t = n / KILOBIT_PER_SEC;
1675 u = "Kbps";
1676 } else {
1677 t = n;
1678 u = "bps ";
1679 }
1680
1681 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
1682 return (buf);
1683 }
1684
1685 #define NSEC_PER_SEC 1000000000 /* nanosecond per second */
1686 #define USEC_PER_SEC 1000000 /* microsecond per second */
1687 #define MSEC_PER_SEC 1000 /* millisecond per second */
1688
1689 static char *
1690 ns_to_str(unsigned long long nsec)
1691 {
1692 static char buf[32];
1693 const char *u;
1694 long double n = nsec, t;
1695
1696 if (nsec >= NSEC_PER_SEC) {
1697 t = n / NSEC_PER_SEC;
1698 u = "sec ";
1699 } else if (n >= USEC_PER_SEC) {
1700 t = n / USEC_PER_SEC;
1701 u = "msec";
1702 } else if (n >= MSEC_PER_SEC) {
1703 t = n / MSEC_PER_SEC;
1704 u = "usec";
1705 } else {
1706 t = n;
1707 u = "nsec";
1708 }
1709
1710 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
1711 return (buf);
1712 }
1713
1714 static void
1715 tunnel_status(int s)
1716 {
1717 af_all_tunnel_status(s);
1718 }
1719
1720 void
1721 Perror(const char *cmd)
1722 {
1723 switch (errno) {
1724
1725 case ENXIO:
1726 errx(1, "%s: no such interface", cmd);
1727 break;
1728
1729 case EPERM:
1730 errx(1, "%s: permission denied", cmd);
1731 break;
1732
1733 default:
1734 err(1, "%s", cmd);
1735 }
1736 }
1737
1738 /*
1739 * Print a value a la the %b format of the kernel's printf
1740 */
1741 void
1742 printb(const char *s, unsigned v, const char *bits)
1743 {
1744 int i, any = 0;
1745 char c;
1746
1747 if (bits && *bits == 8)
1748 printf("%s=%o", s, v);
1749 else
1750 printf("%s=%x", s, v);
1751 bits++;
1752 if (bits) {
1753 putchar('<');
1754 while ((i = *bits++) != '\0') {
1755 if (v & (1 << (i-1))) {
1756 if (any)
1757 putchar(',');
1758 any = 1;
1759 for (; (c = *bits) > 32; bits++)
1760 putchar(c);
1761 } else
1762 for (; *bits > 32; bits++)
1763 ;
1764 }
1765 putchar('>');
1766 }
1767 }
1768
1769 #ifndef __APPLE__
1770 void
1771 ifmaybeload(const char *name)
1772 {
1773 #define MOD_PREFIX_LEN 3 /* "if_" */
1774 struct module_stat mstat;
1775 int fileid, modid;
1776 char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
1777 const char *cp;
1778
1779 /* loading suppressed by the user */
1780 if (noload)
1781 return;
1782
1783 /* trim the interface number off the end */
1784 strlcpy(ifname, name, sizeof(ifname));
1785 for (dp = ifname; *dp != 0; dp++)
1786 if (isdigit(*dp)) {
1787 *dp = 0;
1788 break;
1789 }
1790
1791 /* turn interface and unit into module name */
1792 strlcpy(ifkind, "if_", sizeof(ifkind));
1793 strlcpy(ifkind + MOD_PREFIX_LEN, ifname,
1794 sizeof(ifkind) - MOD_PREFIX_LEN);
1795
1796 /* scan files in kernel */
1797 mstat.version = sizeof(struct module_stat);
1798 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
1799 /* scan modules in file */
1800 for (modid = kldfirstmod(fileid); modid > 0;
1801 modid = modfnext(modid)) {
1802 if (modstat(modid, &mstat) < 0)
1803 continue;
1804 /* strip bus name if present */
1805 if ((cp = strchr(mstat.name, '/')) != NULL) {
1806 cp++;
1807 } else {
1808 cp = mstat.name;
1809 }
1810 /* already loaded? */
1811 if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 ||
1812 strncmp(ifkind, cp, strlen(ifkind) + 1) == 0)
1813 return;
1814 }
1815 }
1816
1817 /* not present, we should try to load it */
1818 kldload(ifkind);
1819 }
1820 #endif
1821
1822 static struct cmd basic_cmds[] = {
1823 DEF_CMD("up", IFF_UP, setifflags),
1824 DEF_CMD("down", -IFF_UP, setifflags),
1825 DEF_CMD("arp", -IFF_NOARP, setifflags),
1826 DEF_CMD("-arp", IFF_NOARP, setifflags),
1827 DEF_CMD("debug", IFF_DEBUG, setifflags),
1828 DEF_CMD("-debug", -IFF_DEBUG, setifflags),
1829 #ifdef IFF_PPROMISC
1830 DEF_CMD("promisc", IFF_PPROMISC, setifflags),
1831 DEF_CMD("-promisc", -IFF_PPROMISC, setifflags),
1832 #endif /* IFF_PPROMISC */
1833 DEF_CMD("add", IFF_UP, notealias),
1834 DEF_CMD("alias", IFF_UP, notealias),
1835 DEF_CMD("-alias", -IFF_UP, notealias),
1836 DEF_CMD("delete", -IFF_UP, notealias),
1837 DEF_CMD("remove", -IFF_UP, notealias),
1838 #ifdef notdef
1839 #define EN_SWABIPS 0x1000
1840 DEF_CMD("swabips", EN_SWABIPS, setifflags),
1841 DEF_CMD("-swabips", -EN_SWABIPS, setifflags),
1842 #endif
1843 DEF_CMD_ARG("netmask", setifnetmask),
1844 DEF_CMD_ARG("metric", setifmetric),
1845 DEF_CMD_ARG("broadcast", setifbroadaddr),
1846 DEF_CMD_ARG("ipdst", setifipdst),
1847 DEF_CMD_ARG2("tunnel", settunnel),
1848 DEF_CMD("-tunnel", 0, deletetunnel),
1849 DEF_CMD("deletetunnel", 0, deletetunnel),
1850 DEF_CMD("link0", IFF_LINK0, setifflags),
1851 DEF_CMD("-link0", -IFF_LINK0, setifflags),
1852 DEF_CMD("link1", IFF_LINK1, setifflags),
1853 DEF_CMD("-link1", -IFF_LINK1, setifflags),
1854 DEF_CMD("link2", IFF_LINK2, setifflags),
1855 DEF_CMD("-link2", -IFF_LINK2, setifflags),
1856 #ifdef IFF_MONITOR
1857 DEF_CMD("monitor", IFF_MONITOR:, setifflags),
1858 DEF_CMD("-monitor", -IFF_MONITOR, setifflags),
1859 #endif /* IFF_MONITOR */
1860 #ifdef IFF_STATICARP
1861 DEF_CMD("staticarp", IFF_STATICARP, setifflags),
1862 DEF_CMD("-staticarp", -IFF_STATICARP, setifflags),
1863 #endif /* IFF_STATICARP */
1864 #ifdef IFCAP_RXCSUM
1865 DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap),
1866 DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap),
1867 #endif /* IFCAP_RXCSUM */
1868 #ifdef IFCAP_TXCSUM
1869 DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap),
1870 DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap),
1871 #endif /* IFCAP_TXCSUM */
1872 #ifdef IFCAP_NETCONS
1873 DEF_CMD("netcons", IFCAP_NETCONS, setifcap),
1874 DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap),
1875 #endif /* IFCAP_NETCONS */
1876 #ifdef IFCAP_POLLING
1877 DEF_CMD("polling", IFCAP_POLLING, setifcap),
1878 DEF_CMD("-polling", -IFCAP_POLLING, setifcap),
1879 #endif /* IFCAP_POLLING */
1880 #ifdef IFCAP_TSO
1881 DEF_CMD("tso", IFCAP_TSO, setifcap),
1882 DEF_CMD("-tso", -IFCAP_TSO, setifcap),
1883 #endif /* IFCAP_TSO */
1884 #ifdef IFCAP_LRO
1885 DEF_CMD("lro", IFCAP_LRO, setifcap),
1886 DEF_CMD("-lro", -IFCAP_LRO, setifcap),
1887 #endif /* IFCAP_LRO */
1888 #ifdef IFCAP_WOL
1889 DEF_CMD("wol", IFCAP_WOL, setifcap),
1890 DEF_CMD("-wol", -IFCAP_WOL, setifcap),
1891 #endif /* IFCAP_WOL */
1892 #ifdef IFCAP_WOL_UCAST
1893 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap),
1894 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap),
1895 #endif /* IFCAP_WOL_UCAST */
1896 #ifdef IFCAP_WOL_MCAST
1897 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap),
1898 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap),
1899 #endif /* IFCAP_WOL_MCAST */
1900 #ifdef IFCAP_WOL_MAGIC
1901 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap),
1902 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap),
1903 #endif /* IFCAP_WOL_MAGIC */
1904 DEF_CMD("normal", -IFF_LINK0, setifflags),
1905 DEF_CMD("compress", IFF_LINK0, setifflags),
1906 DEF_CMD("noicmp", IFF_LINK1, setifflags),
1907 DEF_CMD_ARG("mtu", setifmtu),
1908 #ifdef notdef
1909 DEF_CMD_ARG("name", setifname),
1910 #endif /* notdef */
1911 #ifdef IFCAP_AV
1912 DEF_CMD("av", IFCAP_AV, setifcap),
1913 DEF_CMD("-av", -IFCAP_AV, setifcap),
1914 #endif /* IFCAP_AV */
1915 DEF_CMD("router", 1, setrouter),
1916 DEF_CMD("-router", 0, setrouter),
1917 DEF_CMD_ARG("desc", setifdesc),
1918 DEF_CMD_ARG("tbr", settbr),
1919 DEF_CMD_ARG("throttle", setthrottle),
1920 DEF_CMD_ARG("log", setlog),
1921 DEF_CMD("cl2k", 1, setcl2k),
1922 DEF_CMD("-cl2k", 0, setcl2k),
1923 DEF_CMD("expensive", 1, setexpensive),
1924 DEF_CMD("-expensive", 0, setexpensive),
1925 DEF_CMD("timestamp", 1, settimestamp),
1926 DEF_CMD("-timestamp", 0, settimestamp),
1927 DEF_CMD_ARG("ecn", setecnmode),
1928 DEF_CMD_ARG2("fastlane", setfastlane),
1929 DEF_CMD_ARG2("qosmarking", setqosmarking),
1930 DEF_CMD_ARG("disable_output", setdisableoutput),
1931 DEF_CMD("probe_connectivity", 1, setprobeconnectivity),
1932 DEF_CMD("-probe_connectivity", 0, setprobeconnectivity),
1933 };
1934
1935 static __constructor void
1936 ifconfig_ctor(void)
1937 {
1938 #define N(a) (sizeof(a) / sizeof(a[0]))
1939 int i;
1940
1941 for (i = 0; i < N(basic_cmds); i++)
1942 cmd_register(&basic_cmds[i]);
1943 #undef N
1944 }
1945
1946 static char *
1947 sched2str(unsigned int s)
1948 {
1949 char *c;
1950
1951 switch (s) {
1952 case PKTSCHEDT_NONE:
1953 c = "NONE";
1954 break;
1955 case PKTSCHEDT_TCQ:
1956 c = "TCQ";
1957 break;
1958 case PKTSCHEDT_QFQ:
1959 c = "QFQ";
1960 break;
1961 case PKTSCHEDT_FQ_CODEL:
1962 c = "FQ_CODEL";
1963 break;
1964 default:
1965 c = "UNKNOWN";
1966 break;
1967 }
1968
1969 return (c);
1970 }
1971
1972 static char *
1973 tl2str(unsigned int s)
1974 {
1975 char *c;
1976
1977 switch (s) {
1978 case IFNET_THROTTLE_OFF:
1979 c = "off";
1980 break;
1981 case IFNET_THROTTLE_OPPORTUNISTIC:
1982 c = "opportunistic";
1983 break;
1984 default:
1985 c = "unknown";
1986 break;
1987 }
1988
1989 return (c);
1990 }
1991
1992 static char *
1993 ift2str(unsigned int t, unsigned int f, unsigned int sf)
1994 {
1995 static char buf[256];
1996 char *c = NULL;
1997
1998 switch (t) {
1999 case IFT_ETHER:
2000 switch (sf) {
2001 case IFRTYPE_SUBFAMILY_USB:
2002 c = "USB Ethernet";
2003 break;
2004 case IFRTYPE_SUBFAMILY_BLUETOOTH:
2005 c = "Bluetooth PAN";
2006 break;
2007 case IFRTYPE_SUBFAMILY_WIFI:
2008 c = "Wi-Fi";
2009 break;
2010 case IFRTYPE_SUBFAMILY_THUNDERBOLT:
2011 c = "IP over Thunderbolt";
2012 break;
2013 case IFRTYPE_SUBFAMILY_ANY:
2014 default:
2015 c = "Ethernet";
2016 break;
2017 }
2018 break;
2019
2020 case IFT_IEEE1394:
2021 c = "IP over FireWire";
2022 break;
2023
2024 case IFT_PKTAP:
2025 c = "Packet capture";
2026 break;
2027
2028 case IFT_CELLULAR:
2029 c = "Cellular";
2030 break;
2031
2032 case IFT_BRIDGE:
2033 case IFT_PFLOG:
2034 case IFT_PFSYNC:
2035 case IFT_OTHER:
2036 case IFT_PPP:
2037 case IFT_LOOP:
2038 case IFT_GIF:
2039 case IFT_STF:
2040 case IFT_L2VLAN:
2041 case IFT_IEEE8023ADLAG:
2042 default:
2043 break;
2044 }
2045
2046 if (verbose > 1) {
2047 if (c == NULL) {
2048 (void) snprintf(buf, sizeof (buf),
2049 "0x%x family: %u subfamily: %u",
2050 ifr.ifr_type.ift_type, ifr.ifr_type.ift_family,
2051 ifr.ifr_type.ift_subfamily);
2052 } else {
2053 (void) snprintf(buf, sizeof (buf),
2054 "%s (0x%x) family: %u subfamily: %u", c,
2055 ifr.ifr_type.ift_type, ifr.ifr_type.ift_family,
2056 ifr.ifr_type.ift_subfamily);
2057 }
2058 c = buf;
2059 }
2060
2061 return (c);
2062 }