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