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