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