source: rtems-libbsd/freebsd/sbin/ifconfig/ifconfig.c @ 0237319

5-freebsd-12
Last change on this file since 0237319 was 0237319, checked in by Sebastian Huber <sebastian.huber@…>, on May 23, 2017 at 11:18:31 AM

Update due to Newlib 2017-06-07 changes

The following files are now provided by Newlib:

  • arpa/inet.h
  • net/if.h
  • netinet/in.h
  • netinet/tcp.h
  • sys/socket.h
  • sys/uio.h
  • sys/un.h

The <sys/param.h> and <sys/cpuset.h> are now compatible enough to be
used directly.

Update #2833.

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