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