Пример #1
0
int
main(int argc, char *argv[])
#endif
{
	int c, all, namesonly, downonly, uponly;
	const struct afswtch *afp = NULL;
	int ifindex;
	struct ifaddrs *ifap, *ifa;
	struct ifreq paifr;
	const struct sockaddr_dl *sdl;
	char options[1024], *cp;
	const char *ifname;
#ifdef __rtems__
	struct ifconfig_option *p;
#else
	struct option *p;
#endif
	size_t iflen;
#ifdef __rtems__
	struct getopt_data getopt_reent;
#define optind getopt_reent.optind
#define optarg getopt_reent.optarg
#define opterr getopt_reent.opterr
#define optopt getopt_reent.optopt
#endif

	all = downonly = uponly = namesonly = noload = verbose = 0;

	/* Parse leading line options */
	strlcpy(options, "adklmnuv", sizeof(options));
	for (p = opts; p != NULL; p = p->next)
		strlcat(options, p->opt, sizeof(options));
#ifdef __rtems__
	memset(&getopt_reent, 0, sizeof(getopt_data));
	while ((c = getopt_r(argc, argv, options, &getopt_reent)) != -1) {
#else
	while ((c = getopt(argc, argv, options)) != -1) {
#endif
		switch (c) {
		case 'a':	/* scan all interfaces */
			all++;
			break;
		case 'd':	/* restrict scan to "down" interfaces */
			downonly++;
			break;
		case 'k':
			printkeys++;
			break;
		case 'l':	/* scan interface names only */
			namesonly++;
			break;
		case 'm':	/* show media choices in status */
			supmedia = 1;
			break;
		case 'n':	/* suppress module loading */
			noload++;
			break;
		case 'u':	/* restrict scan to "up" interfaces */
			uponly++;
			break;
		case 'v':
			verbose++;
			break;
		default:
			for (p = opts; p != NULL; p = p->next)
				if (p->opt[0] == c) {
					p->cb(optarg);
					break;
				}
			if (p == NULL)
				usage();
			break;
		}
	}
	argc -= optind;
	argv += optind;

	/* -l cannot be used with -a or -m */
	if (namesonly && (all || supmedia))
		usage();

	/* nonsense.. */
	if (uponly && downonly)
		usage();

	/* no arguments is equivalent to '-a' */
	if (!namesonly && argc < 1)
		all = 1;

	/* -a and -l allow an address family arg to limit the output */
	if (all || namesonly) {
		if (argc > 1)
			usage();

		ifname = NULL;
		ifindex = 0;
		if (argc == 1) {
			afp = af_getbyname(*argv);
			if (afp == NULL)
				usage();
			if (afp->af_name != NULL)
				argc--, argv++;
			/* leave with afp non-zero */
		}
	} else {
		/* not listing, need an argument */
		if (argc < 1)
			usage();

		ifname = *argv;
		argc--, argv++;

		/* check and maybe load support for this interface */
		ifmaybeload(ifname);

		ifindex = if_nametoindex(ifname);
		if (ifindex == 0) {
			/*
			 * NOTE:  We must special-case the `create' command
			 * right here as we would otherwise fail when trying
			 * to find the interface.
			 */
			if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
			    strcmp(argv[0], "plumb") == 0)) {
				iflen = strlcpy(name, ifname, sizeof(name));
				if (iflen >= sizeof(name))
					errx(1, "%s: cloning name too long",
					    ifname);
				ifconfig(argc, argv, 1, NULL);
				exit(0);
			}
			/*
			 * NOTE:  We have to special-case the `-vnet' command
			 * right here as we would otherwise fail when trying
			 * to find the interface as it lives in another vnet.
			 */
			if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) {
				iflen = strlcpy(name, ifname, sizeof(name));
				if (iflen >= sizeof(name))
					errx(1, "%s: interface name too long",
					    ifname);
				ifconfig(argc, argv, 0, NULL);
				exit(0);
			}
			errx(1, "interface %s does not exist", ifname);
		}
	}

	/* Check for address family */
	if (argc > 0) {
		afp = af_getbyname(*argv);
		if (afp != NULL)
			argc--, argv++;
	}

	if (getifaddrs(&ifap) != 0)
		err(EXIT_FAILURE, "getifaddrs");
	cp = NULL;
	ifindex = 0;
	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
		memset(&paifr, 0, sizeof(paifr));
		strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
		if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
			memcpy(&paifr.ifr_addr, ifa->ifa_addr,
			    ifa->ifa_addr->sa_len);
		}

		if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
			continue;
		if (ifa->ifa_addr->sa_family == AF_LINK)
			sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
		else
			sdl = NULL;
		if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0)
			continue;
		iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
		if (iflen >= sizeof(name)) {
			warnx("%s: interface name too long, skipping",
			    ifa->ifa_name);
			continue;
		}
		cp = ifa->ifa_name;

		if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
			continue;
		if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
			continue;
		ifindex++;
		/*
		 * Are we just listing the interfaces?
		 */
		if (namesonly) {
			if (ifindex > 1)
				printf(" ");
			fputs(name, stdout);
			continue;
		}

		if (argc > 0)
			ifconfig(argc, argv, 0, afp);
		else
			status(afp, sdl, ifa);
	}
	if (namesonly)
		printf("\n");
	freeifaddrs(ifap);

	exit(0);
}

static struct afswtch *afs = NULL;

void
af_register(struct afswtch *p)
{
	p->af_next = afs;
	afs = p;
}
Пример #2
0
int
main(int argc, char *argv[])
{
    int c, all, namesonly, downonly, uponly;
    int need_nl = 0, count = 0;
    const struct afswtch *afp = NULL;
    int addrcount, ifindex;
    struct if_msghdr *ifm, *nextifm;
    struct ifa_msghdr *ifam;
    struct sockaddr_dl *sdl;
    char *buf, *lim, *next;
    size_t needed;
    int mib[6];
    char options[1024];
    const char *ifname;
    struct option *p;
    size_t iflen;

    all = downonly = uponly = namesonly = verbose = 0;

    /* Parse leading line options */
    strlcpy(options, "adklmuv", sizeof(options));
    for (p = opts; p != NULL; p = p->next)
        strlcat(options, p->opt, sizeof(options));
    while ((c = getopt(argc, argv, options)) != -1) {
        switch (c) {
        case 'a':	/* scan all interfaces */
            all++;
            break;
        case 'd':	/* restrict scan to "down" interfaces */
            downonly++;
            break;
        case 'k':
            printkeys++;
            break;
        case 'l':	/* scan interface names only */
            namesonly++;
            break;
        case 'm':	/* show media choices in status */
            supmedia = 1;
            break;
        case 'u':	/* restrict scan to "up" interfaces */
            uponly++;
            break;
        case 'v':
            verbose++;
            break;
        default:
            for (p = opts; p != NULL; p = p->next)
                if (p->opt[0] == c) {
                    p->cb(optarg);
                    break;
                }
            if (p == NULL)
                usage();
            break;
        }
    }
    argc -= optind;
    argv += optind;

    /* -l cannot be used with -a or -m */
    if (namesonly && (all || supmedia))
        usage();

    /* nonsense.. */
    if (uponly && downonly)
        usage();

    /* no arguments is equivalent to '-a' */
    if (!namesonly && argc < 1)
        all = 1;

    /* -a and -l allow an address family arg to limit the output */
    if (all || namesonly) {
        if (argc > 1)
            usage();

        ifname = NULL;
        ifindex = 0;
        if (argc == 1) {
            afp = af_getbyname(*argv);
            if (afp == NULL)
                usage();
            if (afp->af_name != NULL)
                argc--, argv++;
            /* leave with afp non-zero */
        }
    } else {
        /* not listing, need an argument */
        if (argc < 1)
            usage();

        ifname = *argv;
        argc--, argv++;

        /* check and maybe load support for this interface */
        ifmaybeload(ifname);
        ifindex = if_nametoindex(ifname);
        if (ifindex == 0) {
            /*
             * NOTE:  We must special-case the `create' command
             * right here as we would otherwise fail when trying
             * to find the interface.
             */
            if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
                             strcmp(argv[0], "plumb") == 0)) {
                iflen = strlcpy(name, ifname, sizeof(name));
                if (iflen >= sizeof(name))
                    errx(1, "%s: cloning name too long",
                         ifname);
                ifconfig(argc, argv, 1, NULL);
                exit(0);
            }
            errx(1, "interface %s does not exist", ifname);
        }
    }

    /* Check for address family */
    if (argc > 0) {
        afp = af_getbyname(*argv);
        if (afp != NULL)
            argc--, argv++;
    }

retry:
    mib[0] = CTL_NET;
    mib[1] = PF_ROUTE;
    mib[2] = 0;
    mib[3] = 0;			/* address family */
    mib[4] = NET_RT_IFLIST;
    mib[5] = ifindex;		/* interface index */

    /* if particular family specified, only ask about it */
    if (afp != NULL)
        mib[3] = afp->af_af;

    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
        errx(1, "iflist-sysctl-estimate");
    if ((buf = malloc(needed)) == NULL)
        errx(1, "malloc");
    if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
        if (errno == ENOMEM && count++ < 10) {
            warnx("Routing table grew, retrying");
            free(buf);
            sleep(1);
            goto retry;
        }
        errx(1, "actual retrieval of interface table");
    }
    lim = buf + needed;

    next = buf;
    while (next < lim) {
        int name_len;

        ifm = (struct if_msghdr *)next;

        if (ifm->ifm_type == RTM_IFINFO) {
#ifdef notyet
            if (ifm->ifm_data.ifi_datalen == 0)
                ifm->ifm_data.ifi_datalen = sizeof(struct if_data);
            sdl = (struct sockaddr_dl *)((char *)ifm + sizeof(struct if_msghdr) -
                                         sizeof(struct if_data) + ifm->ifm_data.ifi_datalen);
#else
            sdl = (struct sockaddr_dl *)(ifm + 1);
#endif
            flags = ifm->ifm_flags;
        } else {
            fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n");
            fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO,
                    ifm->ifm_type);
            fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
            fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next,
                    lim);
            exit (1);
        }

        next += ifm->ifm_msglen;
        ifam = NULL;
        addrcount = 0;
        while (next < lim) {

            nextifm = (struct if_msghdr *)next;

            if (nextifm->ifm_type != RTM_NEWADDR)
                break;

            if (ifam == NULL)
                ifam = (struct ifa_msghdr *)nextifm;

            addrcount++;
            next += nextifm->ifm_msglen;
        }

        if (sizeof(name) <= sdl->sdl_nlen)
            name_len = sizeof(name) - 1;
        else
            name_len = sdl->sdl_nlen;

        memcpy(name, sdl->sdl_data, name_len);
        name[name_len] = '\0';

        if (all || namesonly) {
            if (uponly)
                if ((flags & IFF_UP) == 0)
                    continue; /* not up */
            if (downonly)
                if (flags & IFF_UP)
                    continue; /* not down */
            if (namesonly) {
                if (afp == NULL || afp->af_af != AF_LINK ||
                        sdl->sdl_type == IFT_ETHER) {
                    if (need_nl)
                        putchar(' ');
                    fputs(name, stdout);
                    need_nl++;
                }
                continue;
            }
        }

        if (argc > 0)
            ifconfig(argc, argv, 0, afp);
        else
            status(afp, addrcount, sdl, ifm, ifam);
    }
    free(buf);

    if (namesonly && need_nl > 0)
        putchar('\n');
    if (printname)
        printf("%s\n", name);

    exit (0);
}