diff options
author | Sam Leffler <sam@FreeBSD.org> | 2007-02-24 23:55:46 +0000 |
---|---|---|
committer | Sam Leffler <sam@FreeBSD.org> | 2007-02-24 23:55:46 +0000 |
commit | cb8c905ae9cee73c8fb9e836f01ef946de1dd1f2 (patch) | |
tree | c3dc617e94bd4dffc5a8ead0c6679f2de41ca65d /sbin/ifconfig/ifconfig.c | |
parent | 16d84e0140e32270cf24302479a59052404b54fa (diff) | |
download | src-cb8c905ae9cee73c8fb9e836f01ef946de1dd1f2.tar.gz src-cb8c905ae9cee73c8fb9e836f01ef946de1dd1f2.zip |
use getifaddrs from libc instead of private code
Reviewed by: bms
MFC after: 1 month
Notes
Notes:
svn path=/head/; revision=166956
Diffstat (limited to 'sbin/ifconfig/ifconfig.c')
-rw-r--r-- | sbin/ifconfig/ifconfig.c | 222 |
1 files changed, 75 insertions, 147 deletions
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 684bf9006828..3860bd5411e9 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -62,6 +62,7 @@ static const char rcsid[] = #include <arpa/inet.h> #include <netdb.h> +#include <ifaddrs.h> #include <ctype.h> #include <err.h> #include <errno.h> @@ -81,7 +82,6 @@ static const char rcsid[] = struct ifreq ifr; char name[IFNAMSIZ]; -int flags; int setaddr; int setipdst; int setmask; @@ -94,9 +94,8 @@ int supmedia = 0; int printkeys = 0; /* Print keying material for interfaces. */ static int ifconfig(int argc, char *const *argv, const struct afswtch *afp); -static void status(const struct afswtch *afp, int addrcount, - struct sockaddr_dl *sdl, struct if_msghdr *ifm, - struct ifa_msghdr *ifam); +static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, + struct ifaddrs *ifa); static void tunnel_status(int s); static void usage(void); @@ -141,16 +140,13 @@ 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]; + int ifindex; + struct ifaddrs *ifap, *ifa; + struct ifreq paifr; + const struct sockaddr_dl *sdl; + char options[1024], *cp; + const char *ifname; struct option *p; all = downonly = uponly = namesonly = verbose = 0; @@ -213,6 +209,7 @@ main(int argc, char *argv[]) if (argc > 1) usage(); + ifname = NULL; ifindex = 0; if (argc == 1) { afp = af_getbyname(*argv); @@ -227,13 +224,13 @@ main(int argc, char *argv[]) if (argc < 1) usage(); - strncpy(name, *argv, sizeof(name)); + ifname = *argv; argc--, argv++; /* check and maybe load support for this interface */ - ifmaybeload(name); + ifmaybeload(ifname); - ifindex = if_nametoindex(name); + ifindex = if_nametoindex(ifname); if (ifindex == 0) { /* * NOTE: We must special-case the `create' command @@ -245,7 +242,7 @@ main(int argc, char *argv[]) ifconfig(argc, argv, NULL); exit(0); } - errx(1, "interface %s does not exist", name); + errx(1, "interface %s does not exist", ifname); } } @@ -256,106 +253,55 @@ main(int argc, char *argv[]) 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) { - - ifm = (struct if_msghdr *)next; - - if (ifm->ifm_type == RTM_IFINFO) { - 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); - 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); + 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); } - 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; + 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; + if (strlcpy(name, ifa->ifa_name, sizeof(name)) >= sizeof(name)) + continue; + cp = ifa->ifa_name; - addrcount++; - next += nextifm->ifm_msglen; - } - memcpy(name, sdl->sdl_data, - sizeof(name) <= sdl->sdl_nlen ? - sizeof(name)-1 : sdl->sdl_nlen); - name[sizeof(name) <= sdl->sdl_nlen ? - sizeof(name)-1 : sdl->sdl_nlen] = '\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 (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, afp); else - status(afp, addrcount, sdl, ifm, ifam); + status(afp, sdl, ifa); } - free(buf); - - if (namesonly && need_nl > 0) - putchar('\n'); + if (namesonly) + printf("\n"); + freeifaddrs(ifap); - exit (0); + exit(0); } static struct afswtch *afs = NULL; @@ -698,6 +644,7 @@ static void setifflags(const char *vname, int value, int s, const struct afswtch *afp) { struct ifreq my_ifr; + int flags; bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); @@ -722,6 +669,7 @@ setifflags(const char *vname, int value, int s, const struct afswtch *afp) void setifcap(const char *vname, int value, int s, const struct afswtch *afp) { + int flags; if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { Perror("ioctl (SIOCGIFCAP)"); @@ -780,25 +728,6 @@ setifname(const char *val, int dummy __unused, int s, free(newname); } -/* - * Expand the compacted form of addresses as returned via the - * configuration read via sysctl(). - */ -static void -rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) -{ - struct sockaddr *sa; - int i; - - memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); - for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { - if ((rtinfo->rti_addrs & (1 << i)) == 0) - continue; - rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; - cp += SA_SIZE(sa); - } -} - #define IFFBITS \ "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ @@ -813,10 +742,10 @@ rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) * specified, show only it; otherwise, show them all. */ static void -status(const struct afswtch *afp, int addrcount, struct sockaddr_dl *sdl, - struct if_msghdr *ifm, struct ifa_msghdr *ifam) +status(const struct afswtch *afp, const struct sockaddr_dl *sdl, + struct ifaddrs *ifa) { - struct rt_addrinfo info; + struct ifaddrs *ift; int allfamilies, s; struct ifstat ifs; @@ -834,11 +763,11 @@ status(const struct afswtch *afp, int addrcount, struct sockaddr_dl *sdl, err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); printf("%s: ", name); - printb("flags", flags, IFFBITS); - if (ifm->ifm_data.ifi_metric) - printf(" metric %ld", ifm->ifm_data.ifi_metric); - if (ifm->ifm_data.ifi_mtu) - printf(" mtu %ld", ifm->ifm_data.ifi_mtu); + printb("flags", ifa->ifa_flags, IFFBITS); + if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) + printf(" metric %d", ifr.ifr_metric); + if (ioctl(s, SIOCGIFMTU, &ifr) != -1) + printf(" mtu %d", ifr.ifr_mtu); putchar('\n'); if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { @@ -854,22 +783,20 @@ status(const struct afswtch *afp, int addrcount, struct sockaddr_dl *sdl, tunnel_status(s); - while (addrcount > 0) { - info.rti_addrs = ifam->ifam_addrs; - /* Expand the compacted addresses */ - rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, - &info); - + for (ift = ifa; ift != NULL; ift = ift->ifa_next) { + if (ift->ifa_addr == NULL) + continue; + if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) + continue; if (allfamilies) { const struct afswtch *p; - p = af_getbyfamily(info.rti_info[RTAX_IFA]->sa_family); + p = af_getbyfamily(ift->ifa_addr->sa_family); if (p != NULL && p->af_status != NULL) - p->af_status(s, &info); - } else if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family) - afp->af_status(s, &info); - addrcount--; - ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); + p->af_status(s, ift); + } else if (afp->af_af == ift->ifa_addr->sa_family) + afp->af_status(s, ift); } +#if 0 if (allfamilies || afp->af_af == AF_LINK) { const struct afswtch *lafp; @@ -885,6 +812,7 @@ status(const struct afswtch *afp, int addrcount, struct sockaddr_dl *sdl, lafp->af_status(s, &info); } } +#endif if (allfamilies) af_other_status(s); else if (afp->af_other_status != NULL) @@ -954,7 +882,7 @@ printb(const char *s, unsigned v, const char *bits) } void -ifmaybeload(char *name) +ifmaybeload(const char *name) { struct module_stat mstat; int fileid, modid; |