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