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