]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/ifconfig/ifconfig.c
ifconfig: remove global 'printifname' variable.
[FreeBSD/FreeBSD.git] / sbin / ifconfig / ifconfig.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1983, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #ifndef lint
33 static const char copyright[] =
34 "@(#) Copyright (c) 1983, 1993\n\
35         The Regents of the University of California.  All rights reserved.\n";
36 #if 0
37 static char sccsid[] = "@(#)ifconfig.c  8.2 (Berkeley) 2/16/94";
38 #endif
39 static const char rcsid[] =
40   "$FreeBSD$";
41 #endif /* not lint */
42
43 #include <sys/param.h>
44 #include <sys/ioctl.h>
45 #ifdef JAIL
46 #include <sys/jail.h>
47 #endif
48 #include <sys/module.h>
49 #include <sys/linker.h>
50 #include <sys/nv.h>
51 #include <sys/queue.h>
52 #include <sys/socket.h>
53 #include <sys/time.h>
54
55 #include <net/ethernet.h>
56 #include <net/if.h>
57 #include <net/if_dl.h>
58 #include <net/if_types.h>
59 #include <net/route.h>
60
61 /* IP */
62 #include <netinet/in.h>
63 #include <netinet/in_var.h>
64 #include <arpa/inet.h>
65 #include <netdb.h>
66
67 #include <fnmatch.h>
68 #include <ifaddrs.h>
69 #include <ctype.h>
70 #include <err.h>
71 #include <errno.h>
72 #include <fcntl.h>
73 #ifdef JAIL
74 #include <jail.h>
75 #endif
76 #include <stdbool.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <unistd.h>
81
82 #include <libifconfig.h>
83
84 #include "ifconfig.h"
85
86 ifconfig_handle_t *lifh;
87
88 /*
89  * Since "struct ifreq" is composed of various union members, callers
90  * should pay special attention to interpret the value.
91  * (.e.g. little/big endian difference in the structure.)
92  */
93 struct  ifreq ifr;
94
95 char    name[IFNAMSIZ];
96 #ifdef WITHOUT_NETLINK
97 static char     *descr = NULL;
98 static size_t   descrlen = 64;
99 #endif
100 static int      setaddr;
101 static int      setmask;
102 static int      doalias;
103 static int      clearaddr;
104 int     newaddr = 1;
105
106 struct ifconfig_args global_args;
107
108 int     exit_code = 0;
109
110 static char ifname_to_print[IFNAMSIZ]; /* Helper for printifnamemaybe() */
111
112 /* Formatter Strings */
113 char    *f_inet, *f_inet6, *f_ether, *f_addr;
114
115 #ifdef WITHOUT_NETLINK
116 static void list_interfaces_ioctl(struct ifconfig_args *args);
117 static  void status(struct ifconfig_args *args, const struct sockaddr_dl *sdl,
118                 struct ifaddrs *ifa);
119 #endif
120 static _Noreturn void usage(void);
121 static void Perrorc(const char *cmd, int error);
122
123 static int getifflags(const char *ifname, int us, bool err_ok);
124
125 static struct afswtch *af_getbyname(const char *name);
126
127 static struct option *opts = NULL;
128
129 struct ifa_order_elt {
130         int if_order;
131         int af_orders[255];
132         struct ifaddrs *ifa;
133         TAILQ_ENTRY(ifa_order_elt) link;
134 };
135
136 TAILQ_HEAD(ifa_queue, ifa_order_elt);
137
138 static struct module_map_entry {
139         const char *ifname;
140         const char *kldname;
141 } module_map[] = {
142         {
143                 .ifname = "tun",
144                 .kldname = "if_tuntap",
145         },
146         {
147                 .ifname = "tap",
148                 .kldname = "if_tuntap",
149         },
150         {
151                 .ifname = "vmnet",
152                 .kldname = "if_tuntap",
153         },
154         {
155                 .ifname = "ipsec",
156                 .kldname = "ipsec",
157         },
158         {
159                 /*
160                  * This mapping exists because there is a conflicting enc module
161                  * in CAM.  ifconfig's guessing behavior will attempt to match
162                  * the ifname to a module as well as if_${ifname} and clash with
163                  * CAM enc.  This is an assertion of the correct module to load.
164                  */
165                 .ifname = "enc",
166                 .kldname = "if_enc",
167         },
168 };
169
170
171 void
172 opt_register(struct option *p)
173 {
174         p->next = opts;
175         opts = p;
176 }
177
178 static void
179 usage(void)
180 {
181         char options[1024];
182         struct option *p;
183
184         /* XXX not right but close enough for now */
185         options[0] = '\0';
186         for (p = opts; p != NULL; p = p->next) {
187                 strlcat(options, p->opt_usage, sizeof(options));
188                 strlcat(options, " ", sizeof(options));
189         }
190
191         fprintf(stderr,
192         "usage: ifconfig [-j jail] [-f type:format] %sinterface address_family\n"
193         "                [address [dest_address]] [parameters]\n"
194         "       ifconfig [-j jail] interface create\n"
195         "       ifconfig [-j jail] -a %s[-d] [-m] [-u] [-v] [address_family]\n"
196         "       ifconfig [-j jail] -l [-d] [-u] [address_family]\n"
197         "       ifconfig [-j jail] %s[-d] [-m] [-u] [-v]\n",
198                 options, options, options);
199         exit(1);
200 }
201
202 static void
203 ifname_update(if_ctx *ctx, const char *name)
204 {
205         strlcpy(ctx->_ifname_storage_ioctl, name, sizeof(ctx->_ifname_storage_ioctl));
206         ctx->ifname = ctx->_ifname_storage_ioctl;
207
208         strlcpy(ifname_to_print, name, sizeof(ifname_to_print));
209 }
210
211 void
212 ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr)
213 {
214         char ifname_orig[IFNAMSIZ];
215
216         strlcpy(ifname_orig, ifr->ifr_name, sizeof(ifname_orig));
217
218         if (ioctl(ctx->io_s, SIOCIFCREATE2, ifr) < 0) {
219                 switch (errno) {
220                 case EEXIST:
221                         errx(1, "interface %s already exists", ifr->ifr_name);
222                 default:
223                         err(1, "SIOCIFCREATE2 (%s)", ifr->ifr_name);
224                 }
225         }
226
227         if (strncmp(ifname_orig, ifr->ifr_name, sizeof(ifname_orig)) != 0)
228                 ifname_update(ctx, ifr->ifr_name);
229 }
230
231 #ifdef WITHOUT_NETLINK
232 static int
233 calcorders(struct ifaddrs *ifa, struct ifa_queue *q)
234 {
235         struct ifaddrs *prev;
236         struct ifa_order_elt *cur;
237         unsigned int ord, af, ifa_ord;
238
239         prev = NULL;
240         cur = NULL;
241         ord = 0;
242         ifa_ord = 0;
243
244         while (ifa != NULL) {
245                 if (prev == NULL ||
246                     strcmp(ifa->ifa_name, prev->ifa_name) != 0) {
247                         cur = calloc(1, sizeof(*cur));
248
249                         if (cur == NULL)
250                                 return (-1);
251
252                         TAILQ_INSERT_TAIL(q, cur, link);
253                         cur->if_order = ifa_ord ++;
254                         cur->ifa = ifa;
255                         ord = 0;
256                 }
257
258                 if (ifa->ifa_addr) {
259                         af = ifa->ifa_addr->sa_family;
260
261                         if (af < nitems(cur->af_orders) &&
262                             cur->af_orders[af] == 0)
263                                 cur->af_orders[af] = ++ord;
264                 }
265                 prev = ifa;
266                 ifa = ifa->ifa_next;
267         }
268
269         return (0);
270 }
271
272 static int
273 cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q)
274 {
275         struct ifa_order_elt *cur, *e1, *e2;
276         unsigned int af1, af2;
277         int ret;
278
279         e1 = e2 = NULL;
280
281         ret = strcmp(a->ifa_name, b->ifa_name);
282         if (ret != 0) {
283                 TAILQ_FOREACH(cur, q, link) {
284                         if (e1 && e2)
285                                 break;
286
287                         if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0)
288                                 e1 = cur;
289                         else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0)
290                                 e2 = cur;
291                 }
292
293                 if (!e1 || !e2)
294                         return (0);
295                 else
296                         return (e1->if_order - e2->if_order);
297
298         } else if (a->ifa_addr != NULL && b->ifa_addr != NULL) {
299                 TAILQ_FOREACH(cur, q, link) {
300                         if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) {
301                                 e1 = cur;
302                                 break;
303                         }
304                 }
305
306                 if (!e1)
307                         return (0);
308
309                 af1 = a->ifa_addr->sa_family;
310                 af2 = b->ifa_addr->sa_family;
311
312                 if (af1 < nitems(e1->af_orders) && af2 < nitems(e1->af_orders))
313                         return (e1->af_orders[af1] - e1->af_orders[af2]);
314         }
315
316         return (0);
317 }
318 #endif
319
320 static void freeformat(void)
321 {
322
323         if (f_inet != NULL)
324                 free(f_inet);
325         if (f_inet6 != NULL)
326                 free(f_inet6);
327         if (f_ether != NULL)
328                 free(f_ether);
329         if (f_addr != NULL)
330                 free(f_addr);
331 }
332
333 static void setformat(char *input)
334 {
335         char    *formatstr, *category, *modifier; 
336
337         formatstr = strdup(input);
338         while ((category = strsep(&formatstr, ",")) != NULL) {
339                 modifier = strchr(category, ':');
340                 if (modifier == NULL || modifier[1] == '\0') {
341                         warnx("Skipping invalid format specification: %s\n",
342                             category);
343                         continue;
344                 }
345
346                 /* Split the string on the separator, then seek past it */
347                 modifier[0] = '\0';
348                 modifier++;
349
350                 if (strcmp(category, "addr") == 0)
351                         f_addr = strdup(modifier);
352                 else if (strcmp(category, "ether") == 0)
353                         f_ether = strdup(modifier);
354                 else if (strcmp(category, "inet") == 0)
355                         f_inet = strdup(modifier);
356                 else if (strcmp(category, "inet6") == 0)
357                         f_inet6 = strdup(modifier);
358         }
359         free(formatstr);
360 }
361
362 #ifdef WITHOUT_NETLINK
363 static struct ifaddrs *
364 sortifaddrs(struct ifaddrs *list,
365     int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *),
366     struct ifa_queue *q)
367 {
368         struct ifaddrs *right, *temp, *last, *result, *next, *tail;
369         
370         right = list;
371         temp = list;
372         last = list;
373         result = NULL;
374         next = NULL;
375         tail = NULL;
376
377         if (!list || !list->ifa_next)
378                 return (list);
379
380         while (temp && temp->ifa_next) {
381                 last = right;
382                 right = right->ifa_next;
383                 temp = temp->ifa_next->ifa_next;
384         }
385
386         last->ifa_next = NULL;
387
388         list = sortifaddrs(list, compare, q);
389         right = sortifaddrs(right, compare, q);
390
391         while (list || right) {
392
393                 if (!right) {
394                         next = list;
395                         list = list->ifa_next;
396                 } else if (!list) {
397                         next = right;
398                         right = right->ifa_next;
399                 } else if (compare(list, right, q) <= 0) {
400                         next = list;
401                         list = list->ifa_next;
402                 } else {
403                         next = right;
404                         right = right->ifa_next;
405                 }
406
407                 if (!result)
408                         result = next;
409                 else
410                         tail->ifa_next = next;
411
412                 tail = next;
413         }
414
415         return (result);
416 }
417 #endif
418
419 static void
420 printifnamemaybe(void)
421 {
422         if (ifname_to_print[0] != '\0')
423                 printf("%s\n", ifname_to_print);
424 }
425
426 static void
427 list_interfaces(struct ifconfig_args *args)
428 {
429 #ifdef WITHOUT_NETLINK
430         list_interfaces_ioctl(args);
431 #else
432         list_interfaces_nl(args);
433 #endif
434 }
435
436 static char *
437 args_peek(struct ifconfig_args *args)
438 {
439         if (args->argc > 0)
440                 return (args->argv[0]);
441         return (NULL);
442 }
443
444 static char *
445 args_pop(struct ifconfig_args *args)
446 {
447         if (args->argc == 0)
448                 return (NULL);
449
450         char *arg = args->argv[0];
451
452         args->argc--;
453         args->argv++;
454
455         return (arg);
456 }
457
458 static void
459 args_parse(struct ifconfig_args *args, int argc, char *argv[])
460 {
461         char options[1024];
462         struct option *p;
463         int c;
464
465         /* Parse leading line options */
466         strlcpy(options, "G:adf:j:klmnuv", sizeof(options));
467         for (p = opts; p != NULL; p = p->next)
468                 strlcat(options, p->opt, sizeof(options));
469         while ((c = getopt(argc, argv, options)) != -1) {
470                 switch (c) {
471                 case 'a':       /* scan all interfaces */
472                         args->all = true;
473                         break;
474                 case 'd':       /* restrict scan to "down" interfaces */
475                         args->downonly = true;
476                         break;
477                 case 'f':
478                         if (optarg == NULL)
479                                 usage();
480                         setformat(optarg);
481                         break;
482                 case 'G':
483                         if (optarg == NULL || args->all == 0)
484                                 usage();
485                         args->nogroup = optarg;
486                         break;
487                 case 'j':
488 #ifdef JAIL
489                         if (optarg == NULL)
490                                 usage();
491                         args->jail_name = optarg;
492 #else
493                         Perror("not built with jail support");
494 #endif
495                         break;
496                 case 'k':
497                         args->printkeys = true;
498                         break;
499                 case 'l':       /* scan interface names only */
500                         args->namesonly++;
501                         break;
502                 case 'm':       /* show media choices in status */
503                         args->supmedia = true;
504                         break;
505                 case 'n':       /* suppress module loading */
506                         args->noload = true;
507                         break;
508                 case 'u':       /* restrict scan to "up" interfaces */
509                         args->uponly = true;
510                         break;
511                 case 'v':
512                         args->verbose++;
513                         break;
514                 case 'g':
515                         if (args->all) {
516                                 if (optarg == NULL)
517                                         usage();
518                                 args->matchgroup = optarg;
519                                 break;
520                         }
521                         /* FALLTHROUGH */
522                 default:
523                         for (p = opts; p != NULL; p = p->next)
524                                 if (p->opt[0] == c) {
525                                         p->cb(optarg);
526                                         break;
527                                 }
528                         if (p == NULL)
529                                 usage();
530                         break;
531                 }
532         }
533         argc -= optind;
534         argv += optind;
535
536         /* -l cannot be used with -a or -m */
537         if (args->namesonly && (args->all || args->supmedia))
538                 usage();
539
540         /* nonsense.. */
541         if (args->uponly && args->downonly)
542                 usage();
543
544         /* no arguments is equivalent to '-a' */
545         if (!args->namesonly && argc < 1)
546                 args->all = 1;
547
548         /* -a and -l allow an address family arg to limit the output */
549         if (args->all || args->namesonly) {
550                 if (argc > 1)
551                         usage();
552
553                 if (argc == 1) {
554                         const struct afswtch *afp = af_getbyname(*argv);
555
556                         if (afp == NULL) {
557                                 warnx("Address family '%s' unknown.", *argv);
558                                 usage();
559                         }
560                         if (afp->af_name != NULL)
561                                 argc--, argv++;
562                         /* leave with afp non-zero */
563                         args->afp = afp;
564                 }
565         } else {
566                 /* not listing, need an argument */
567                 if (argc < 1)
568                         usage();
569         }
570
571         args->argc = argc;
572         args->argv = argv;
573 }
574
575 static int
576 ifconfig_wrapper(struct ifconfig_args *args, int iscreate,
577     const struct afswtch *uafp)
578 {
579 #ifdef WITHOUT_NETLINK
580         struct ifconfig_context ctx = {
581                 .args = args,
582                 .io_s = -1,
583         };
584
585         return (ifconfig(&ctx, iscreate, uafp));
586 #else
587         return (ifconfig_wrapper_nl(args, iscreate, uafp));
588 #endif
589 }
590
591 static bool
592 isargcreate(const char *arg)
593 {
594         if (arg == NULL)
595                 return (false);
596
597         if (strcmp(arg, "create") == 0 || strcmp(arg, "plumb") == 0)
598                 return (true);
599
600         return (false);
601 }
602
603 int
604 main(int ac, char *av[])
605 {
606         char *envformat;
607         size_t iflen;
608         int flags;
609 #ifdef JAIL
610         int jid;
611 #endif
612         struct ifconfig_args *args = &global_args;
613
614         f_inet = f_inet6 = f_ether = f_addr = NULL;
615
616         lifh = ifconfig_open();
617         if (lifh == NULL)
618                 err(EXIT_FAILURE, "ifconfig_open");
619
620         envformat = getenv("IFCONFIG_FORMAT");
621         if (envformat != NULL)
622                 setformat(envformat);
623
624         /*
625          * Ensure we print interface name when expected to,
626          * even if we terminate early due to error.
627          */
628         atexit(printifnamemaybe);
629
630         args_parse(args, ac, av);
631
632 #ifdef JAIL
633         if (args->jail_name) {
634                 jid = jail_getid(args->jail_name);
635                 if (jid == -1)
636                         Perror("jail not found");
637                 if (jail_attach(jid) != 0)
638                         Perror("cannot attach to jail");
639         }
640 #endif
641
642         if (!args->all && !args->namesonly) {
643                 /* not listing, need an argument */
644                 args->ifname = args_pop(args);
645
646                 /* check and maybe load support for this interface */
647                 ifmaybeload(args, args->ifname);
648
649                 char *arg = args_peek(args);
650                 if (if_nametoindex(args->ifname) == 0) {
651                         /*
652                          * NOTE:  We must special-case the `create' command
653                          * right here as we would otherwise fail when trying
654                          * to find the interface.
655                          */
656                         if (isargcreate(arg)) {
657                                 iflen = strlcpy(name, args->ifname, sizeof(name));
658                                 if (iflen >= sizeof(name))
659                                         errx(1, "%s: cloning name too long",
660                                             args->ifname);
661                                 ifconfig_wrapper(args, 1, NULL);
662                                 exit(exit_code);
663                         }
664 #ifdef JAIL
665                         /*
666                          * NOTE:  We have to special-case the `-vnet' command
667                          * right here as we would otherwise fail when trying
668                          * to find the interface as it lives in another vnet.
669                          */
670                         if (arg != NULL && (strcmp(arg, "-vnet") == 0)) {
671                                 iflen = strlcpy(name, args->ifname, sizeof(name));
672                                 if (iflen >= sizeof(name))
673                                         errx(1, "%s: interface name too long",
674                                             args->ifname);
675                                 ifconfig_wrapper(args, 0, NULL);
676                                 exit(exit_code);
677                         }
678 #endif
679                         errx(1, "interface %s does not exist", args->ifname);
680                 } else {
681                         /*
682                          * Do not allow use `create` command as hostname if
683                          * address family is not specified.
684                          */
685                         if (isargcreate(arg)) {
686                                 if (args->argc == 1)
687                                         errx(1, "interface %s already exists",
688                                             args->ifname);
689                                 args_pop(args);
690                         }
691                 }
692         }
693
694         /* Check for address family */
695         if (args->argc > 0) {
696                 args->afp = af_getbyname(args_peek(args));
697                 if (args->afp != NULL)
698                         args_pop(args);
699         }
700
701         /*
702          * Check for a requested configuration action on a single interface,
703          * which doesn't require building, sorting, and searching the entire
704          * system address list
705          */
706         if ((args->argc > 0) && (args->ifname != NULL)) {
707                 iflen = strlcpy(name, args->ifname, sizeof(name));
708                 if (iflen >= sizeof(name)) {
709                         warnx("%s: interface name too long, skipping", args->ifname);
710                 } else {
711                         flags = getifflags(name, -1, false);
712                         if (!(((flags & IFF_CANTCONFIG) != 0) ||
713                                 (args->downonly && (flags & IFF_UP) != 0) ||
714                                 (args->uponly && (flags & IFF_UP) == 0)))
715                                 ifconfig_wrapper(args, 0, args->afp);
716                 }
717                 goto done;
718         }
719
720         args->allfamilies = args->afp == NULL;
721
722         list_interfaces(args);
723
724 done:
725         freeformat();
726         ifconfig_close(lifh);
727         exit(exit_code);
728 }
729
730 bool
731 match_ether(const struct sockaddr_dl *sdl)
732 {
733         switch (sdl->sdl_type) {
734                 case IFT_ETHER:
735                 case IFT_L2VLAN:
736                 case IFT_BRIDGE:
737                         if (sdl->sdl_alen == ETHER_ADDR_LEN)
738                                 return (true);
739                 default:
740                         return (false);
741         }
742 }
743
744 bool
745 match_if_flags(struct ifconfig_args *args, int if_flags)
746 {
747         if ((if_flags & IFF_CANTCONFIG) != 0)
748                 return (false);
749         if (args->downonly && (if_flags & IFF_UP) != 0)
750                 return (false);
751         if (args->uponly && (if_flags & IFF_UP) == 0)
752                 return (false);
753         return (true);
754 }
755
756 #ifdef WITHOUT_NETLINK
757 static bool
758 match_afp(const struct afswtch *afp, int sa_family, const struct sockaddr_dl *sdl)
759 {
760         if (afp == NULL)
761                 return (true);
762         /* special case for "ether" address family */
763         if (!strcmp(afp->af_name, "ether")) {
764                 if (sdl == NULL && !match_ether(sdl))
765                         return (false);
766                 return (true);
767         }
768         return (afp->af_af == sa_family);
769 }
770
771 static void
772 list_interfaces_ioctl(struct ifconfig_args *args)
773 {
774         struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
775         struct ifaddrs *ifap, *sifap, *ifa;
776         struct ifa_order_elt *cur, *tmp;
777         char *namecp = NULL;
778         int ifindex;
779         size_t iflen;
780
781         if (getifaddrs(&ifap) != 0)
782                 err(EXIT_FAILURE, "getifaddrs");
783
784         char *cp = NULL;
785         
786         if (calcorders(ifap, &q) != 0)
787                 err(EXIT_FAILURE, "calcorders");
788                 
789         sifap = sortifaddrs(ifap, cmpifaddrs, &q);
790
791         TAILQ_FOREACH_SAFE(cur, &q, link, tmp)
792                 free(cur);
793
794         ifindex = 0;
795         for (ifa = sifap; ifa; ifa = ifa->ifa_next) {
796                 struct ifreq paifr = {};
797                 const struct sockaddr_dl *sdl;
798
799                 strlcpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
800                 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
801                         memcpy(&paifr.ifr_addr, ifa->ifa_addr,
802                             ifa->ifa_addr->sa_len);
803                 }
804
805                 if (args->ifname != NULL && strcmp(args->ifname, ifa->ifa_name) != 0)
806                         continue;
807                 if (ifa->ifa_addr->sa_family == AF_LINK)
808                         sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
809                 else
810                         sdl = NULL;
811                 if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !args->namesonly)
812                         continue;
813                 iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
814                 if (iflen >= sizeof(name)) {
815                         warnx("%s: interface name too long, skipping",
816                             ifa->ifa_name);
817                         continue;
818                 }
819                 cp = ifa->ifa_name;
820
821                 if (!match_if_flags(args, ifa->ifa_flags))
822                         continue;
823                 if (!group_member(ifa->ifa_name, args->matchgroup, args->nogroup))
824                         continue;
825                 /*
826                  * Are we just listing the interfaces?
827                  */
828                 if (args->namesonly) {
829                         if (namecp == cp)
830                                 continue;
831                         if (!match_afp(args->afp, ifa->ifa_addr->sa_family, sdl))
832                                 continue;
833                         namecp = cp;
834                         ifindex++;
835                         if (ifindex > 1)
836                                 printf(" ");
837                         fputs(name, stdout);
838                         continue;
839                 }
840                 ifindex++;
841
842                 if (args->argc > 0)
843                         ifconfig_wrapper(args, 0, args->afp);
844                 else
845                         status(args, sdl, ifa);
846         }
847         if (args->namesonly)
848                 printf("\n");
849         freeifaddrs(ifap);
850 }
851 #endif
852
853 /*
854  * Returns true if an interface should be listed because any its groups
855  * matches shell pattern "match" and none of groups matches pattern "nomatch".
856  * If any pattern is NULL, corresponding condition is skipped.
857  */
858 bool
859 group_member(const char *ifname, const char *match, const char *nomatch)
860 {
861         static int               sock = -1;
862
863         struct ifgroupreq        ifgr;
864         struct ifg_req          *ifg;
865         unsigned int             len;
866         bool                     matched, nomatched;
867
868         /* Sanity checks. */
869         if (match == NULL && nomatch == NULL)
870                 return (true);
871         if (ifname == NULL)
872                 return (false);
873
874         memset(&ifgr, 0, sizeof(ifgr));
875         strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ);
876
877         /* The socket is opened once. Let _exit() close it. */
878         if (sock == -1) {
879                 sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
880                 if (sock == -1)
881                     errx(1, "%s: socket(AF_LOCAL,SOCK_DGRAM)", __func__);
882         }
883
884         /* Determine amount of memory for the list of groups. */
885         if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
886                 if (errno == EINVAL || errno == ENOTTY)
887                         return (false);
888                 else
889                         errx(1, "%s: SIOCGIFGROUP", __func__);
890         }
891
892         /* Obtain the list of groups. */
893         len = ifgr.ifgr_len;
894         ifgr.ifgr_groups =
895             (struct ifg_req *)calloc(len / sizeof(*ifg), sizeof(*ifg));
896
897         if (ifgr.ifgr_groups == NULL)
898                 errx(1, "%s: no memory", __func__);
899         if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
900                 errx(1, "%s: SIOCGIFGROUP", __func__);
901
902         /* Perform matching. */
903         matched = false;
904         nomatched = true;
905         for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) {
906                 len -= sizeof(struct ifg_req);
907                 if (match)
908                         matched |= !fnmatch(match, ifg->ifgrq_group, 0);
909                 if (nomatch)
910                         nomatched &= fnmatch(nomatch, ifg->ifgrq_group, 0);
911         }
912         free(ifgr.ifgr_groups);
913
914         if (match && !nomatch)
915                 return (matched);
916         if (!match && nomatch)
917                 return (nomatched);
918         return (matched && nomatched);
919 }
920
921 static struct afswtch *afs = NULL;
922
923 void
924 af_register(struct afswtch *p)
925 {
926         p->af_next = afs;
927         afs = p;
928 }
929
930 static struct afswtch *
931 af_getbyname(const char *name)
932 {
933         struct afswtch *afp;
934
935         for (afp = afs; afp !=  NULL; afp = afp->af_next)
936                 if (strcmp(afp->af_name, name) == 0)
937                         return afp;
938         return NULL;
939 }
940
941 struct afswtch *
942 af_getbyfamily(int af)
943 {
944         struct afswtch *afp;
945
946         for (afp = afs; afp != NULL; afp = afp->af_next)
947                 if (afp->af_af == af)
948                         return afp;
949         return NULL;
950 }
951
952 void
953 af_other_status(if_ctx *ctx)
954 {
955         struct afswtch *afp;
956         uint8_t afmask[howmany(AF_MAX, NBBY)];
957
958         memset(afmask, 0, sizeof(afmask));
959         for (afp = afs; afp != NULL; afp = afp->af_next) {
960                 if (afp->af_other_status == NULL)
961                         continue;
962                 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
963                         continue;
964                 afp->af_other_status(ctx);
965                 setbit(afmask, afp->af_af);
966         }
967 }
968
969 static void
970 af_all_tunnel_status(int s)
971 {
972         struct afswtch *afp;
973         uint8_t afmask[howmany(AF_MAX, NBBY)];
974
975         memset(afmask, 0, sizeof(afmask));
976         for (afp = afs; afp != NULL; afp = afp->af_next) {
977                 if (afp->af_status_tunnel == NULL)
978                         continue;
979                 if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
980                         continue;
981                 afp->af_status_tunnel(s);
982                 setbit(afmask, afp->af_af);
983         }
984 }
985
986 static struct cmd *cmds = NULL;
987
988 void
989 cmd_register(struct cmd *p)
990 {
991         p->c_next = cmds;
992         cmds = p;
993 }
994
995 static const struct cmd *
996 cmd_lookup(const char *name, int iscreate)
997 {
998         const struct cmd *p;
999
1000         for (p = cmds; p != NULL; p = p->c_next)
1001                 if (strcmp(name, p->c_name) == 0) {
1002                         if (iscreate) {
1003                                 if (p->c_iscloneop)
1004                                         return p;
1005                         } else {
1006                                 if (!p->c_iscloneop)
1007                                         return p;
1008                         }
1009                 }
1010         return NULL;
1011 }
1012
1013 struct callback {
1014         callback_func *cb_func;
1015         void    *cb_arg;
1016         struct callback *cb_next;
1017 };
1018 static struct callback *callbacks = NULL;
1019
1020 void
1021 callback_register(callback_func *func, void *arg)
1022 {
1023         struct callback *cb;
1024
1025         cb = malloc(sizeof(struct callback));
1026         if (cb == NULL)
1027                 errx(1, "unable to allocate memory for callback");
1028         cb->cb_func = func;
1029         cb->cb_arg = arg;
1030         cb->cb_next = callbacks;
1031         callbacks = cb;
1032 }
1033
1034 /* specially-handled commands */
1035 static void setifaddr(if_ctx *ctx, const char *addr, int param);
1036 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr);
1037
1038 static void setifdstaddr(if_ctx *ctx, const char *addr, int param __unused);
1039 static const struct cmd setifdstaddr_cmd =
1040         DEF_CMD("ifdstaddr", 0, setifdstaddr);
1041
1042 int
1043 af_exec_ioctl(if_ctx *ctx, unsigned long action, void *data)
1044 {
1045         struct ifreq *req = (struct ifreq *)data;
1046
1047         strlcpy(req->ifr_name, name, sizeof(req->ifr_name));
1048         if (ioctl_ctx(ctx, action, req) == 0)
1049                 return (0);
1050         return (errno);
1051 }
1052
1053 static void
1054 delifaddr(if_ctx *ctx, const struct afswtch *afp)
1055 {
1056         int error;
1057
1058         if (afp->af_exec == NULL) {
1059                 warnx("interface %s cannot change %s addresses!",
1060                     name, afp->af_name);
1061                 clearaddr = 0;
1062                 return;
1063         }
1064
1065         error = afp->af_exec(ctx, afp->af_difaddr, afp->af_ridreq);
1066         if (error != 0) {
1067                 if (error == EADDRNOTAVAIL && (doalias >= 0)) {
1068                         /* means no previous address for interface */
1069                 } else
1070                         Perrorc("ioctl (SIOCDIFADDR)", error);
1071         }
1072 }
1073
1074 static void
1075 addifaddr(if_ctx *ctx, const struct afswtch *afp)
1076 {
1077         if (afp->af_exec == NULL) {
1078                 warnx("interface %s cannot change %s addresses!",
1079                       name, afp->af_name);
1080                 newaddr = 0;
1081                 return;
1082         }
1083
1084         if (setaddr || setmask) {
1085                 int error = afp->af_exec(ctx, afp->af_aifaddr, afp->af_addreq);
1086                 if (error != 0)
1087                         Perrorc("ioctl (SIOCAIFADDR)", error);
1088         }
1089 }
1090
1091 int
1092 ifconfig(if_ctx *orig_ctx, int iscreate, const struct afswtch *uafp)
1093 {
1094         const struct afswtch *afp, *nafp;
1095         const struct cmd *p;
1096         struct callback *cb;
1097         int s;
1098         int argc = orig_ctx->args->argc;
1099         char *const *argv = orig_ctx->args->argv;
1100         struct ifconfig_context _ctx = {
1101                 .args = orig_ctx->args,
1102                 .io_ss = orig_ctx->io_ss,
1103         };
1104         struct ifconfig_context *ctx = &_ctx;
1105
1106         strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1107         afp = NULL;
1108         if (uafp != NULL)
1109                 afp = uafp;
1110         /*
1111          * This is the historical "accident" allowing users to configure IPv4
1112          * addresses without the "inet" keyword which while a nice feature has
1113          * proven to complicate other things.  We cannot remove this but only
1114          * make sure we will never have a similar implicit default for IPv6 or
1115          * any other address familiy.  We need a fallback though for
1116          * ifconfig IF up/down etc. to work without INET support as people
1117          * never used ifconfig IF link up/down, etc. either.
1118          */
1119 #ifndef RESCUE
1120 #ifdef INET
1121         if (afp == NULL && feature_present("inet"))
1122                 afp = af_getbyname("inet");
1123 #endif
1124 #endif
1125         if (afp == NULL)
1126                 afp = af_getbyname("link");
1127         if (afp == NULL) {
1128                 warnx("Please specify an address_family.");
1129                 usage();
1130         }
1131
1132 top:
1133         ifr.ifr_addr.sa_family =
1134                 afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
1135                 AF_LOCAL : afp->af_af;
1136
1137         if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 &&
1138             (uafp != NULL || errno != EAFNOSUPPORT ||
1139              (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0))
1140                 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
1141
1142         ctx->io_s = s;
1143         ctx->afp = afp;
1144
1145         while (argc > 0) {
1146                 p = cmd_lookup(*argv, iscreate);
1147                 if (iscreate && p == NULL) {
1148                         /*
1149                          * Push the clone create callback so the new
1150                          * device is created and can be used for any
1151                          * remaining arguments.
1152                          */
1153                         cb = callbacks;
1154                         if (cb == NULL)
1155                                 errx(1, "internal error, no callback");
1156                         callbacks = cb->cb_next;
1157                         cb->cb_func(ctx, cb->cb_arg);
1158                         iscreate = 0;
1159                         /*
1160                          * Handle any address family spec that
1161                          * immediately follows and potentially
1162                          * recreate the socket.
1163                          */
1164                         nafp = af_getbyname(*argv);
1165                         if (nafp != NULL) {
1166                                 argc--, argv++;
1167                                 if (nafp != afp) {
1168                                         close(s);
1169                                         afp = nafp;
1170                                         goto top;
1171                                 }
1172                         }
1173                         /*
1174                          * Look for a normal parameter.
1175                          */
1176                         continue;
1177                 }
1178                 if (p == NULL) {
1179                         /*
1180                          * Not a recognized command, choose between setting
1181                          * the interface address and the dst address.
1182                          */
1183                         p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
1184                 }
1185                 if (p->c_parameter == NEXTARG && p->c_u.c_func) {
1186                         if (argv[1] == NULL)
1187                                 errx(1, "'%s' requires argument",
1188                                     p->c_name);
1189                         p->c_u.c_func(ctx, argv[1], 0);
1190                         argc--, argv++;
1191                 } else if (p->c_parameter == OPTARG && p->c_u.c_func) {
1192                         p->c_u.c_func(ctx, argv[1], 0);
1193                         if (argv[1] != NULL)
1194                                 argc--, argv++;
1195                 } else if (p->c_parameter == NEXTARG2 && p->c_u.c_func2) {
1196                         if (argc < 3)
1197                                 errx(1, "'%s' requires 2 arguments",
1198                                     p->c_name);
1199                         p->c_u.c_func2(ctx, argv[1], argv[2]);
1200                         argc -= 2, argv += 2;
1201                 } else if (p->c_parameter == SPARAM && p->c_u.c_func3) {
1202                         p->c_u.c_func3(ctx, *argv, p->c_sparameter);
1203                 } else if (p->c_u.c_func)
1204                         p->c_u.c_func(ctx, *argv, p->c_parameter);
1205                 argc--, argv++;
1206         }
1207
1208         /*
1209          * Do any post argument processing required by the address family.
1210          */
1211         if (afp->af_postproc != NULL)
1212                 afp->af_postproc(ctx, newaddr, getifflags(name, s, true));
1213         /*
1214          * Do deferred callbacks registered while processing
1215          * command-line arguments.
1216          */
1217         for (cb = callbacks; cb != NULL; cb = cb->cb_next)
1218                 cb->cb_func(ctx, cb->cb_arg);
1219         /*
1220          * Do deferred operations.
1221          */
1222         if (clearaddr)
1223                 delifaddr(ctx, afp);
1224         if (newaddr)
1225                 addifaddr(ctx, afp);
1226
1227         close(s);
1228         return(0);
1229 }
1230
1231 static void
1232 setifaddr(if_ctx *ctx, const char *addr, int param)
1233 {
1234         const struct afswtch *afp = ctx->afp;
1235
1236         if (afp->af_getaddr == NULL)
1237                 return;
1238         /*
1239          * Delay the ioctl to set the interface addr until flags are all set.
1240          * The address interpretation may depend on the flags,
1241          * and the flags may change when the address is set.
1242          */
1243         setaddr++;
1244         if (doalias == 0 && afp->af_af != AF_LINK)
1245                 clearaddr = 1;
1246         afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR));
1247 }
1248
1249 static void
1250 settunnel(if_ctx *ctx, const char *src, const char *dst)
1251 {
1252         const struct afswtch *afp = ctx->afp;
1253         struct addrinfo *srcres, *dstres;
1254         int ecode;
1255
1256         if (afp->af_settunnel == NULL) {
1257                 warn("address family %s does not support tunnel setup",
1258                         afp->af_name);
1259                 return;
1260         }
1261
1262         if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
1263                 errx(1, "error in parsing address string: %s",
1264                     gai_strerror(ecode));
1265
1266         if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
1267                 errx(1, "error in parsing address string: %s",
1268                     gai_strerror(ecode));
1269
1270         if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
1271                 errx(1,
1272                     "source and destination address families do not match");
1273
1274         afp->af_settunnel(ctx->io_s, srcres, dstres);
1275
1276         freeaddrinfo(srcres);
1277         freeaddrinfo(dstres);
1278 }
1279
1280 static void
1281 deletetunnel(if_ctx *ctx, const char *vname, int param)
1282 {
1283
1284         if (ioctl(ctx->io_s, SIOCDIFPHYADDR, &ifr) < 0)
1285                 err(1, "SIOCDIFPHYADDR");
1286 }
1287
1288 #ifdef JAIL
1289 static void
1290 setifvnet(if_ctx *ctx, const char *jname, int dummy __unused)
1291 {
1292         struct ifreq my_ifr;
1293
1294         memcpy(&my_ifr, &ifr, sizeof(my_ifr));
1295         my_ifr.ifr_jid = jail_getid(jname);
1296         if (my_ifr.ifr_jid < 0)
1297                 errx(1, "%s", jail_errmsg);
1298         if (ioctl(ctx->io_s, SIOCSIFVNET, &my_ifr) < 0)
1299                 err(1, "SIOCSIFVNET");
1300 }
1301
1302 static void
1303 setifrvnet(if_ctx *ctx, const char *jname, int dummy __unused)
1304 {
1305         struct ifreq my_ifr;
1306
1307         memcpy(&my_ifr, &ifr, sizeof(my_ifr));
1308         my_ifr.ifr_jid = jail_getid(jname);
1309         if (my_ifr.ifr_jid < 0)
1310                 errx(1, "%s", jail_errmsg);
1311         if (ioctl(ctx->io_s, SIOCSIFRVNET, &my_ifr) < 0)
1312                 err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name);
1313 }
1314 #endif
1315
1316 static void
1317 setifnetmask(if_ctx *ctx, const char *addr, int dummy __unused)
1318 {
1319         const struct afswtch *afp = ctx->afp;
1320
1321         if (afp->af_getaddr != NULL) {
1322                 setmask++;
1323                 afp->af_getaddr(addr, MASK);
1324         }
1325 }
1326
1327 static void
1328 setifbroadaddr(if_ctx *ctx, const char *addr, int dummy __unused)
1329 {
1330         const struct afswtch *afp = ctx->afp;
1331
1332         if (afp->af_getaddr != NULL)
1333                 afp->af_getaddr(addr, BRDADDR);
1334 }
1335
1336 static void
1337 notealias(if_ctx *ctx, const char *addr, int param)
1338 {
1339         const struct afswtch *afp = ctx->afp;
1340
1341         if (setaddr && doalias == 0 && param < 0) {
1342                 if (afp->af_copyaddr != NULL)
1343                         afp->af_copyaddr(ctx, RIDADDR, ADDR);
1344         }
1345         doalias = param;
1346         if (param < 0) {
1347                 clearaddr = 1;
1348                 newaddr = 0;
1349         } else
1350                 clearaddr = 0;
1351 }
1352
1353 static void
1354 setifdstaddr(if_ctx *ctx, const char *addr, int param __unused)
1355 {
1356         const struct afswtch *afp = ctx->afp;
1357
1358         if (afp->af_getaddr != NULL)
1359                 afp->af_getaddr(addr, DSTADDR);
1360 }
1361
1362 static int
1363 getifflags(const char *ifname, int us, bool err_ok)
1364 {
1365         struct ifreq my_ifr;
1366         int s;
1367         
1368         memset(&my_ifr, 0, sizeof(my_ifr));
1369         (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name));
1370         if (us < 0) {
1371                 if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)
1372                         err(1, "socket(family AF_LOCAL,SOCK_DGRAM");
1373         } else
1374                 s = us;
1375         if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
1376                 if (!err_ok) {
1377                         Perror("ioctl (SIOCGIFFLAGS)");
1378                         exit(1);
1379                 }
1380         }
1381         if (us < 0)
1382                 close(s);
1383         return ((my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16));
1384 }
1385
1386 /*
1387  * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
1388  * of the ifreq structure, which may confuse other parts of ifconfig.
1389  * Make a private copy so we can avoid that.
1390  */
1391 static void
1392 setifflags(if_ctx *ctx, const char *vname, int value)
1393 {
1394         struct ifreq            my_ifr;
1395         int flags;
1396
1397         flags = getifflags(name, ctx->io_s, false);
1398         if (value < 0) {
1399                 value = -value;
1400                 flags &= ~value;
1401         } else
1402                 flags |= value;
1403         memset(&my_ifr, 0, sizeof(my_ifr));
1404         (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name));
1405         my_ifr.ifr_flags = flags & 0xffff;
1406         my_ifr.ifr_flagshigh = flags >> 16;
1407         if (ioctl(ctx->io_s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
1408                 Perror(vname);
1409 }
1410
1411 void
1412 setifcap(if_ctx *ctx, const char *vname, int value)
1413 {
1414         int flags;
1415
1416         if (ioctl(ctx->io_s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
1417                 Perror("ioctl (SIOCGIFCAP)");
1418                 exit(1);
1419         }
1420         flags = ifr.ifr_curcap;
1421         if (value < 0) {
1422                 value = -value;
1423                 flags &= ~value;
1424         } else
1425                 flags |= value;
1426         flags &= ifr.ifr_reqcap;
1427         /* Check for no change in capabilities. */
1428         if (ifr.ifr_curcap == flags)
1429                 return;
1430         ifr.ifr_reqcap = flags;
1431         if (ioctl(ctx->io_s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
1432                 Perror(vname);
1433 }
1434
1435 void
1436 setifcapnv(if_ctx *ctx, const char *vname, const char *arg)
1437 {
1438         nvlist_t *nvcap;
1439         void *buf;
1440         char *marg, *mopt;
1441         size_t nvbuflen;
1442         bool neg;
1443
1444         if (ioctl(ctx->io_s, SIOCGIFCAP, (caddr_t)&ifr) < 0)
1445                 Perror("ioctl (SIOCGIFCAP)");
1446         if ((ifr.ifr_curcap & IFCAP_NV) == 0) {
1447                 warnx("IFCAP_NV not supported");
1448                 return; /* Not exit() */
1449         }
1450
1451         marg = strdup(arg);
1452         if (marg == NULL)
1453                 Perror("strdup");
1454         nvcap = nvlist_create(0);
1455         if (nvcap == NULL)
1456                 Perror("nvlist_create");
1457         while ((mopt = strsep(&marg, ",")) != NULL) {
1458                 neg = *mopt == '-';
1459                 if (neg)
1460                         mopt++;
1461                 if (strcmp(mopt, "rxtls") == 0) {
1462                         nvlist_add_bool(nvcap, "rxtls4", !neg);
1463                         nvlist_add_bool(nvcap, "rxtls6", !neg);
1464                 } else {
1465                         nvlist_add_bool(nvcap, mopt, !neg);
1466                 }
1467         }
1468         buf = nvlist_pack(nvcap, &nvbuflen);
1469         if (buf == NULL) {
1470                 errx(1, "nvlist_pack error");
1471                 exit(1);
1472         }
1473         ifr.ifr_cap_nv.buf_length = ifr.ifr_cap_nv.length = nvbuflen;
1474         ifr.ifr_cap_nv.buffer = buf;
1475         if (ioctl(ctx->io_s, SIOCSIFCAPNV, (caddr_t)&ifr) < 0)
1476                 Perror(vname);
1477         free(buf);
1478         nvlist_destroy(nvcap);
1479         free(marg);
1480 }
1481
1482 static void
1483 setifmetric(if_ctx *ctx, const char *val, int dummy __unused)
1484 {
1485         strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1486         ifr.ifr_metric = atoi(val);
1487         if (ioctl(ctx->io_s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
1488                 err(1, "ioctl SIOCSIFMETRIC (set metric)");
1489 }
1490
1491 static void
1492 setifmtu(if_ctx *ctx, const char *val, int dummy __unused)
1493 {
1494         strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1495         ifr.ifr_mtu = atoi(val);
1496         if (ioctl(ctx->io_s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
1497                 err(1, "ioctl SIOCSIFMTU (set mtu)");
1498 }
1499
1500 static void
1501 setifpcp(if_ctx *ctx, const char *val, int arg __unused)
1502 {
1503         u_long ul;
1504         char *endp;
1505
1506         ul = strtoul(val, &endp, 0);
1507         if (*endp != '\0')
1508                 errx(1, "invalid value for pcp");
1509         if (ul > 7)
1510                 errx(1, "value for pcp out of range");
1511         ifr.ifr_lan_pcp = ul;
1512         if (ioctl(ctx->io_s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
1513                 err(1, "SIOCSLANPCP");
1514 }
1515
1516 static void
1517 disableifpcp(if_ctx *ctx, const char *val, int arg __unused)
1518 {
1519
1520         ifr.ifr_lan_pcp = IFNET_PCP_NONE;
1521         if (ioctl(ctx->io_s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
1522                 err(1, "SIOCSLANPCP");
1523 }
1524
1525 static void
1526 setifname(if_ctx *ctx, const char *val, int dummy __unused)
1527 {
1528         char *newname;
1529         
1530         strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1531
1532         newname = strdup(val);
1533         if (newname == NULL)
1534                 err(1, "no memory to set ifname");
1535         ifr.ifr_data = newname;
1536         if (ioctl(ctx->io_s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
1537                 free(newname);
1538                 err(1, "ioctl SIOCSIFNAME (set name)");
1539         }
1540         ifname_update(ctx, newname);
1541         free(newname);
1542 }
1543
1544 static void
1545 setifdescr(if_ctx *ctx, const char *val, int dummy __unused)
1546 {
1547         char *newdescr;
1548
1549         strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1550         
1551         ifr.ifr_buffer.length = strlen(val) + 1;
1552         if (ifr.ifr_buffer.length == 1) {
1553                 ifr.ifr_buffer.buffer = newdescr = NULL;
1554                 ifr.ifr_buffer.length = 0;
1555         } else {
1556                 newdescr = strdup(val);
1557                 ifr.ifr_buffer.buffer = newdescr;
1558                 if (newdescr == NULL) {
1559                         warn("no memory to set ifdescr");
1560                         return;
1561                 }
1562         }
1563
1564         if (ioctl(ctx->io_s, SIOCSIFDESCR, (caddr_t)&ifr) < 0)
1565                 err(1, "ioctl SIOCSIFDESCR (set descr)");
1566
1567         free(newdescr);
1568 }
1569
1570 static void
1571 unsetifdescr(if_ctx *ctx, const char *val, int value)
1572 {
1573         setifdescr(ctx, "", 0);
1574 }
1575
1576 #define IFFBITS \
1577 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \
1578 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
1579 "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25STICKYARP"
1580
1581 #define IFCAPBITS \
1582 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
1583 "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \
1584 "\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \
1585 "\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6" \
1586 "\36VXLAN_HWCSUM\37VXLAN_HWTSO\40TXTLS_RTLMT"
1587
1588 static void
1589 print_ifcap_nv(struct ifconfig_args *args, int s)
1590 {
1591         nvlist_t *nvcap;
1592         const char *nvname;
1593         void *buf, *cookie;
1594         bool first, val;
1595         int type;
1596
1597         buf = malloc(IFR_CAP_NV_MAXBUFSIZE);
1598         if (buf == NULL)
1599                 Perror("malloc");
1600         ifr.ifr_cap_nv.buffer = buf;
1601         ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
1602         if (ioctl(s, SIOCGIFCAPNV, (caddr_t)&ifr) != 0)
1603                 Perror("ioctl (SIOCGIFCAPNV)");
1604         nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer,
1605             ifr.ifr_cap_nv.length, 0);
1606         if (nvcap == NULL)
1607                 Perror("nvlist_unpack");
1608         printf("\toptions");
1609         cookie = NULL;
1610         for (first = true;; first = false) {
1611                 nvname = nvlist_next(nvcap, &type, &cookie);
1612                 if (nvname == NULL) {
1613                         printf("\n");
1614                         break;
1615                 }
1616                 if (type == NV_TYPE_BOOL) {
1617                         val = nvlist_get_bool(nvcap, nvname);
1618                         if (val) {
1619                                 printf("%c%s",
1620                                     first ? ' ' : ',', nvname);
1621                         }
1622                 }
1623         }
1624         if (args->supmedia) {
1625                 printf("\tcapabilities");
1626                 cookie = NULL;
1627                 for (first = true;; first = false) {
1628                         nvname = nvlist_next(nvcap, &type,
1629                             &cookie);
1630                         if (nvname == NULL) {
1631                                 printf("\n");
1632                                 break;
1633                         }
1634                         if (type == NV_TYPE_BOOL)
1635                                 printf("%c%s", first ? ' ' :
1636                                     ',', nvname);
1637                 }
1638         }
1639         nvlist_destroy(nvcap);
1640         free(buf);
1641
1642         if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
1643                 Perror("ioctl (SIOCGIFCAP)");
1644 }
1645
1646 void
1647 print_ifcap(struct ifconfig_args *args, int s)
1648 {
1649         if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
1650                 return;
1651
1652         if ((ifr.ifr_curcap & IFCAP_NV) != 0)
1653                 print_ifcap_nv(args, s);
1654         else {
1655                 printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
1656                 putchar('\n');
1657                 if (args->supmedia && ifr.ifr_reqcap != 0) {
1658                         printb("\tcapabilities", ifr.ifr_reqcap,
1659                             IFCAPBITS);
1660                         putchar('\n');
1661                 }
1662         }
1663 }
1664
1665 void
1666 print_ifstatus(int s)
1667 {
1668         struct ifstat ifs;
1669
1670         strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
1671         if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
1672                 printf("%s", ifs.ascii);
1673 }
1674
1675 void
1676 print_metric(int s)
1677 {
1678         if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
1679                 printf(" metric %d", ifr.ifr_metric);
1680 }
1681
1682 #ifdef WITHOUT_NETLINK
1683 static void
1684 print_mtu(int s)
1685 {
1686         if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
1687                 printf(" mtu %d", ifr.ifr_mtu);
1688 }
1689
1690 static void
1691 print_description(int s)
1692 {
1693         for (;;) {
1694                 if ((descr = reallocf(descr, descrlen)) != NULL) {
1695                         ifr.ifr_buffer.buffer = descr;
1696                         ifr.ifr_buffer.length = descrlen;
1697                         if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
1698                                 if (ifr.ifr_buffer.buffer == descr) {
1699                                         if (strlen(descr) > 0)
1700                                                 printf("\tdescription: %s\n",
1701                                                     descr);
1702                                 } else if (ifr.ifr_buffer.length > descrlen) {
1703                                         descrlen = ifr.ifr_buffer.length;
1704                                         continue;
1705                                 }
1706                         }
1707                 } else
1708                         warn("unable to allocate memory for interface"
1709                             "description");
1710                 break;
1711         }
1712 }
1713
1714 /*
1715  * Print the status of the interface.  If an address family was
1716  * specified, show only it; otherwise, show them all.
1717  */
1718 static void
1719 status(struct ifconfig_args *args, const struct sockaddr_dl *sdl,
1720         struct ifaddrs *ifa)
1721 {
1722         struct ifaddrs *ift;
1723         int s;
1724         bool allfamilies = args->afp == NULL;
1725
1726         if (args->afp == NULL)
1727                 ifr.ifr_addr.sa_family = AF_LOCAL;
1728         else
1729                 ifr.ifr_addr.sa_family =
1730                    args->afp->af_af == AF_LINK ? AF_LOCAL : args->afp->af_af;
1731         strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1732
1733         s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
1734         if (s < 0)
1735                 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
1736
1737         struct ifconfig_context _ctx = { .io_s = s }, *ctx;
1738         ctx = &_ctx;
1739
1740         printf("%s: ", name);
1741         printb("flags", ifa->ifa_flags, IFFBITS);
1742         print_metric(s);
1743         print_mtu(s);
1744         putchar('\n');
1745
1746         print_description(s);
1747
1748         print_ifcap(args, s);
1749
1750         tunnel_status(s);
1751
1752         for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
1753                 if (ift->ifa_addr == NULL)
1754                         continue;
1755                 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0)
1756                         continue;
1757                 if (allfamilies) {
1758                         const struct afswtch *p;
1759                         p = af_getbyfamily(ift->ifa_addr->sa_family);
1760                         if (p != NULL && p->af_status != NULL)
1761                                 p->af_status(ctx, ift);
1762                 } else if (args->afp->af_af == ift->ifa_addr->sa_family)
1763                         args->afp->af_status(ctx, ift);
1764         }
1765 #if 0
1766         if (allfamilies || afp->af_af == AF_LINK) {
1767                 const struct afswtch *lafp;
1768
1769                 /*
1770                  * Hack; the link level address is received separately
1771                  * from the routing information so any address is not
1772                  * handled above.  Cobble together an entry and invoke
1773                  * the status method specially.
1774                  */
1775                 lafp = af_getbyname("lladdr");
1776                 if (lafp != NULL) {
1777                         info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl;
1778                         lafp->af_status(s, &info);
1779                 }
1780         }
1781 #endif
1782         if (allfamilies)
1783                 af_other_status(ctx);
1784         else if (args->afp->af_other_status != NULL)
1785                 args->afp->af_other_status(ctx);
1786
1787         print_ifstatus(s);
1788         if (args->verbose > 0)
1789                 sfp_status(ctx);
1790
1791         close(s);
1792         return;
1793 }
1794 #endif
1795
1796 void
1797 tunnel_status(int s)
1798 {
1799         af_all_tunnel_status(s);
1800 }
1801
1802 static void
1803 Perrorc(const char *cmd, int error)
1804 {
1805         switch (errno) {
1806
1807         case ENXIO:
1808                 errx(1, "%s: no such interface", cmd);
1809                 break;
1810
1811         case EPERM:
1812                 errx(1, "%s: permission denied", cmd);
1813                 break;
1814
1815         default:
1816                 errc(1, error, "%s", cmd);
1817         }
1818 }
1819
1820 void
1821 Perror(const char *cmd)
1822 {
1823         Perrorc(cmd, errno);
1824 }
1825
1826 /*
1827  * Print a value a la the %b format of the kernel's printf
1828  */
1829 void
1830 printb(const char *s, unsigned v, const char *bits)
1831 {
1832         int i, any = 0;
1833         char c;
1834
1835         if (bits && *bits == 8)
1836                 printf("%s=%o", s, v);
1837         else
1838                 printf("%s=%x", s, v);
1839         if (bits) {
1840                 bits++;
1841                 putchar('<');
1842                 while ((i = *bits++) != '\0') {
1843                         if (v & (1u << (i-1))) {
1844                                 if (any)
1845                                         putchar(',');
1846                                 any = 1;
1847                                 for (; (c = *bits) > 32; bits++)
1848                                         putchar(c);
1849                         } else
1850                                 for (; *bits > 32; bits++)
1851                                         ;
1852                 }
1853                 putchar('>');
1854         }
1855 }
1856
1857 void
1858 print_vhid(const struct ifaddrs *ifa, const char *s)
1859 {
1860         struct if_data *ifd;
1861
1862         if (ifa->ifa_data == NULL)
1863                 return;
1864
1865         ifd = ifa->ifa_data;
1866         if (ifd->ifi_vhid == 0)
1867                 return;
1868         
1869         printf(" vhid %d", ifd->ifi_vhid);
1870 }
1871
1872 void
1873 ifmaybeload(struct ifconfig_args *args, const char *name)
1874 {
1875 #define MOD_PREFIX_LEN          3       /* "if_" */
1876         struct module_stat mstat;
1877         int fileid, modid;
1878         char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
1879         const char *cp;
1880         struct module_map_entry *mme;
1881         bool found;
1882
1883         /* loading suppressed by the user */
1884         if (args->noload)
1885                 return;
1886
1887         /* trim the interface number off the end */
1888         strlcpy(ifname, name, sizeof(ifname));
1889         dp = ifname + strlen(ifname) - 1;
1890         for (; dp > ifname; dp--) {
1891                 if (isdigit(*dp))
1892                         *dp = '\0';
1893                 else
1894                         break;
1895         }
1896
1897         /* Either derive it from the map or guess otherwise */
1898         *ifkind = '\0';
1899         found = false;
1900         for (unsigned i = 0; i < nitems(module_map); ++i) {
1901                 mme = &module_map[i];
1902                 if (strcmp(mme->ifname, ifname) == 0) {
1903                         strlcpy(ifkind, mme->kldname, sizeof(ifkind));
1904                         found = true;
1905                         break;
1906                 }
1907         }
1908
1909         /* We didn't have an alias for it... we'll guess. */
1910         if (!found) {
1911             /* turn interface and unit into module name */
1912             strlcpy(ifkind, "if_", sizeof(ifkind));
1913             strlcat(ifkind, ifname, sizeof(ifkind));
1914         }
1915
1916         /* scan files in kernel */
1917         mstat.version = sizeof(struct module_stat);
1918         for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
1919                 /* scan modules in file */
1920                 for (modid = kldfirstmod(fileid); modid > 0;
1921                      modid = modfnext(modid)) {
1922                         if (modstat(modid, &mstat) < 0)
1923                                 continue;
1924                         /* strip bus name if present */
1925                         if ((cp = strchr(mstat.name, '/')) != NULL) {
1926                                 cp++;
1927                         } else {
1928                                 cp = mstat.name;
1929                         }
1930                         /*
1931                          * Is it already loaded?  Don't compare with ifname if
1932                          * we were specifically told which kld to use.  Doing
1933                          * so could lead to conflicts not trivially solved.
1934                          */
1935                         if ((!found && strcmp(ifname, cp) == 0) ||
1936                             strcmp(ifkind, cp) == 0)
1937                                 return;
1938                 }
1939         }
1940
1941         /*
1942          * Try to load the module.  But ignore failures, because ifconfig can't
1943          * infer the names of all drivers (eg mlx4en(4)).
1944          */
1945         (void) kldload(ifkind);
1946 }
1947
1948 static struct cmd basic_cmds[] = {
1949         DEF_CMD("up",           IFF_UP,         setifflags),
1950         DEF_CMD("down",         -IFF_UP,        setifflags),
1951         DEF_CMD("arp",          -IFF_NOARP,     setifflags),
1952         DEF_CMD("-arp",         IFF_NOARP,      setifflags),
1953         DEF_CMD("debug",        IFF_DEBUG,      setifflags),
1954         DEF_CMD("-debug",       -IFF_DEBUG,     setifflags),
1955         DEF_CMD_ARG("description",              setifdescr),
1956         DEF_CMD_ARG("descr",                    setifdescr),
1957         DEF_CMD("-description", 0,              unsetifdescr),
1958         DEF_CMD("-descr",       0,              unsetifdescr),
1959         DEF_CMD("promisc",      IFF_PPROMISC,   setifflags),
1960         DEF_CMD("-promisc",     -IFF_PPROMISC,  setifflags),
1961         DEF_CMD("add",          IFF_UP,         notealias),
1962         DEF_CMD("alias",        IFF_UP,         notealias),
1963         DEF_CMD("-alias",       -IFF_UP,        notealias),
1964         DEF_CMD("delete",       -IFF_UP,        notealias),
1965         DEF_CMD("remove",       -IFF_UP,        notealias),
1966 #ifdef notdef
1967 #define EN_SWABIPS      0x1000
1968         DEF_CMD("swabips",      EN_SWABIPS,     setifflags),
1969         DEF_CMD("-swabips",     -EN_SWABIPS,    setifflags),
1970 #endif
1971         DEF_CMD_ARG("netmask",                  setifnetmask),
1972         DEF_CMD_ARG("metric",                   setifmetric),
1973         DEF_CMD_ARG("broadcast",                setifbroadaddr),
1974         DEF_CMD_ARG2("tunnel",                  settunnel),
1975         DEF_CMD("-tunnel", 0,                   deletetunnel),
1976         DEF_CMD("deletetunnel", 0,              deletetunnel),
1977 #ifdef JAIL
1978         DEF_CMD_ARG("vnet",                     setifvnet),
1979         DEF_CMD_ARG("-vnet",                    setifrvnet),
1980 #endif
1981         DEF_CMD("link0",        IFF_LINK0,      setifflags),
1982         DEF_CMD("-link0",       -IFF_LINK0,     setifflags),
1983         DEF_CMD("link1",        IFF_LINK1,      setifflags),
1984         DEF_CMD("-link1",       -IFF_LINK1,     setifflags),
1985         DEF_CMD("link2",        IFF_LINK2,      setifflags),
1986         DEF_CMD("-link2",       -IFF_LINK2,     setifflags),
1987         DEF_CMD("monitor",      IFF_MONITOR,    setifflags),
1988         DEF_CMD("-monitor",     -IFF_MONITOR,   setifflags),
1989         DEF_CMD("mextpg",       IFCAP_MEXTPG,   setifcap),
1990         DEF_CMD("-mextpg",      -IFCAP_MEXTPG,  setifcap),
1991         DEF_CMD("staticarp",    IFF_STATICARP,  setifflags),
1992         DEF_CMD("-staticarp",   -IFF_STATICARP, setifflags),
1993         DEF_CMD("stickyarp",    IFF_STICKYARP,  setifflags),
1994         DEF_CMD("-stickyarp",   -IFF_STICKYARP, setifflags),
1995         DEF_CMD("rxcsum6",      IFCAP_RXCSUM_IPV6,      setifcap),
1996         DEF_CMD("-rxcsum6",     -IFCAP_RXCSUM_IPV6,     setifcap),
1997         DEF_CMD("txcsum6",      IFCAP_TXCSUM_IPV6,      setifcap),
1998         DEF_CMD("-txcsum6",     -IFCAP_TXCSUM_IPV6,     setifcap),
1999         DEF_CMD("rxcsum",       IFCAP_RXCSUM,   setifcap),
2000         DEF_CMD("-rxcsum",      -IFCAP_RXCSUM,  setifcap),
2001         DEF_CMD("txcsum",       IFCAP_TXCSUM,   setifcap),
2002         DEF_CMD("-txcsum",      -IFCAP_TXCSUM,  setifcap),
2003         DEF_CMD("netcons",      IFCAP_NETCONS,  setifcap),
2004         DEF_CMD("-netcons",     -IFCAP_NETCONS, setifcap),
2005         DEF_CMD_ARG("pcp",                      setifpcp),
2006         DEF_CMD("-pcp", 0,                      disableifpcp),
2007         DEF_CMD("polling",      IFCAP_POLLING,  setifcap),
2008         DEF_CMD("-polling",     -IFCAP_POLLING, setifcap),
2009         DEF_CMD("tso6",         IFCAP_TSO6,     setifcap),
2010         DEF_CMD("-tso6",        -IFCAP_TSO6,    setifcap),
2011         DEF_CMD("tso4",         IFCAP_TSO4,     setifcap),
2012         DEF_CMD("-tso4",        -IFCAP_TSO4,    setifcap),
2013         DEF_CMD("tso",          IFCAP_TSO,      setifcap),
2014         DEF_CMD("-tso",         -IFCAP_TSO,     setifcap),
2015         DEF_CMD("toe",          IFCAP_TOE,      setifcap),
2016         DEF_CMD("-toe",         -IFCAP_TOE,     setifcap),
2017         DEF_CMD("lro",          IFCAP_LRO,      setifcap),
2018         DEF_CMD("-lro",         -IFCAP_LRO,     setifcap),
2019         DEF_CMD("txtls",        IFCAP_TXTLS,    setifcap),
2020         DEF_CMD("-txtls",       -IFCAP_TXTLS,   setifcap),
2021         DEF_CMD_SARG("rxtls",   IFCAP2_RXTLS4_NAME "," IFCAP2_RXTLS6_NAME,
2022             setifcapnv),
2023         DEF_CMD_SARG("-rxtls",  "-"IFCAP2_RXTLS4_NAME ",-" IFCAP2_RXTLS6_NAME,
2024             setifcapnv),
2025         DEF_CMD("wol",          IFCAP_WOL,      setifcap),
2026         DEF_CMD("-wol",         -IFCAP_WOL,     setifcap),
2027         DEF_CMD("wol_ucast",    IFCAP_WOL_UCAST,        setifcap),
2028         DEF_CMD("-wol_ucast",   -IFCAP_WOL_UCAST,       setifcap),
2029         DEF_CMD("wol_mcast",    IFCAP_WOL_MCAST,        setifcap),
2030         DEF_CMD("-wol_mcast",   -IFCAP_WOL_MCAST,       setifcap),
2031         DEF_CMD("wol_magic",    IFCAP_WOL_MAGIC,        setifcap),
2032         DEF_CMD("-wol_magic",   -IFCAP_WOL_MAGIC,       setifcap),
2033         DEF_CMD("txrtlmt",      IFCAP_TXRTLMT,  setifcap),
2034         DEF_CMD("-txrtlmt",     -IFCAP_TXRTLMT, setifcap),
2035         DEF_CMD("txtlsrtlmt",   IFCAP_TXTLS_RTLMT,      setifcap),
2036         DEF_CMD("-txtlsrtlmt",  -IFCAP_TXTLS_RTLMT,     setifcap),
2037         DEF_CMD("hwrxtstmp",    IFCAP_HWRXTSTMP,        setifcap),
2038         DEF_CMD("-hwrxtstmp",   -IFCAP_HWRXTSTMP,       setifcap),
2039         DEF_CMD("normal",       -IFF_LINK0,     setifflags),
2040         DEF_CMD("compress",     IFF_LINK0,      setifflags),
2041         DEF_CMD("noicmp",       IFF_LINK1,      setifflags),
2042         DEF_CMD_ARG("mtu",                      setifmtu),
2043         DEF_CMD_ARG("name",                     setifname),
2044 };
2045
2046 static __constructor void
2047 ifconfig_ctor(void)
2048 {
2049         size_t i;
2050
2051         for (i = 0; i < nitems(basic_cmds);  i++)
2052                 cmd_register(&basic_cmds[i]);
2053 }