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

5-freebsd-12
Last change on this file since 338f300 was 338f300, checked in by Christian Mauderer <christian.mauderer@…>, on Apr 25, 2018 at 2:28:00 PM

buildset: Add minimal and everything config.

This adds two new buildset configurations: One that leaves out as much
features as possible and one that enables all features. For the default
configuration WiFi? support is now disabled.

To disable IPv6 for the minimal configuration, all -DINET6 are
eliminated in libbsd.py. They are now replaced by a #ifdef that checks
for RTEMS_BSD_MODULE_NETINET6 instead.

Close #3351.

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