aboutsummaryrefslogtreecommitdiff
path: root/sbin/ifconfig/ifconfig.c
diff options
context:
space:
mode:
authorSam Leffler <sam@FreeBSD.org>2007-02-24 23:55:46 +0000
committerSam Leffler <sam@FreeBSD.org>2007-02-24 23:55:46 +0000
commitcb8c905ae9cee73c8fb9e836f01ef946de1dd1f2 (patch)
treec3dc617e94bd4dffc5a8ead0c6679f2de41ca65d /sbin/ifconfig/ifconfig.c
parent16d84e0140e32270cf24302479a59052404b54fa (diff)
downloadsrc-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.c222
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;