From: Guy Harris Date: Wed, 28 Apr 2010 19:29:19 +0000 (-0700) Subject: Update description fetching code for FreeBSD, fix code for OpenBSD. X-Git-Tag: libpcap-1.2.1~85^2~59 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/c65292b04b98d6a76d58c5a54ca8f81463bf24de Update description fetching code for FreeBSD, fix code for OpenBSD. Update from Jason (Xin) Li to reflect changes to the FreeBSD SIOCGIFDESCR implementation - it now doesn't return an error if the buffer is too short, it sets the buffer pointer to NULL. No FreeBSD release has SIOCGIFDESCR, so this doesn't break on any release. The loop, trying to increase the buffer size until it's big enough, works only on FreeBSD, as that's the only OS where you get told what length to use; OpenBSD clamps the description length at IFDESCRSIZE, so we just use that. --- diff --git a/inet.c b/inet.c index 0b16a659..178eb81f 100644 --- a/inet.c +++ b/inet.c @@ -431,26 +431,54 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name); s = socket(AF_INET, SOCK_DGRAM, 0); if (s >= 0) { +#ifdef __FreeBSD__ + /* + * On FreeBSD, if the buffer isn't big enough for the + * description, the ioctl succeeds, but the description + * isn't copied, ifr_buffer.length is set to the description + * length, and ifr_buffer.buffer is set to NULL. + */ for (;;) { free(description); if ((description = malloc(descrlen)) != NULL) { -#ifdef __FreeBSD__ ifrdesc.ifr_buffer.buffer = description; ifrdesc.ifr_buffer.length = descrlen; -#else /* __FreeBSD__ */ - ifrdesc.ifr_data = (caddr_t)description; -#endif /* __FreeBSD__ */ - if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) - break; -#ifdef __FreeBSD__ - else if (errno == ENAMETOOLONG) - descrlen = ifrdesc.ifr_buffer.length; -#endif /* __FreeBSD__ */ - else + if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) { + if (ifrdesc.ifr_buffer.buffer == + description) + break; + else + descrlen = ifrdesc.ifr_buffer.length; + } else { + /* + * Failed to get interface description. + */ + free(description); + description = NULL; break; + } } else break; } +#else /* __FreeBSD__ */ + /* + * The only other OS that currently supports + * SIOCGIFDESCR is OpenBSD, and it has no way + * to get the description length - it's clamped + * to a maximum of IFDESCRSIZE. + */ + if ((description = malloc(descrlen)) != NULL) { + ifrdesc.ifr_data = (caddr_t)description; + if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) { + /* + * Failed to get interface description. + */ + free(description); + description = NULL; + } + } else + break; +#endif /* __FreeBSD__ */ close(s); if (description != NULL && strlen(description) == 0) { free(description);