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; }
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); }