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

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2017a6d was 2017a6d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/16 at 07:48:12

Directly use <sys/time.h> provided by Newlib

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