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

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 21abaef was 21abaef, checked in by Christian Mauderer <Christian.Mauderer@…>, on Jul 15, 2016 at 5:32:56 AM

freebsd: Don't use new wrappers for old ports.

Some of the commands have been adapted manually. So the wrapper
currently don't necessarily work as expected. For example ifconfig calls
malloc outside of the program call.

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