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