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