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