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

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since a9be4b0 was a9be4b0, checked in by Sebastian Huber <sebastian.huber@…>, on 10/17/13 at 13:30:31

Move shell items to separate file

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