netlib_ipv[4|6]adaptor: Add a check to handle the case where the network device configuration changed asynchronously and the second IOCTL returns more data than the allocated buffer.

This commit is contained in:
Gregory Nutt 2017-09-20 06:52:05 -06:00
parent 2cd27e17a1
commit fb804e3498
3 changed files with 38 additions and 8 deletions

View File

@ -160,11 +160,11 @@ int netlib_get_ipv6addr(FAR const char *ifname, FAR struct in6_addr *addr);
int netlib_set_ipv6addr(FAR const char *ifname, FAR const struct in6_addr *addr);
int netlib_set_dripv6addr(FAR const char *ifname, FAR const struct in6_addr *addr);
int netlib_set_ipv6netmask(FAR const char *ifname, FAR const struct in6_addr *addr);
int netlib_ipv6adaptor(FAR const struct in6_addr *destipaddr,
FAR struct in6_addr *srcipaddr);
uint8_t netlib_ipv6netmask2prefix(FAR const uint16_t *mask);
void netlib_prefix2ipv6netmask(uint8_t preflen, FAR struct in6_addr *netmask);
int netlib_ipv6adaptor(FAR const struct in6_addr *destipaddr,
FAR struct in6_addr *srcipaddr);
#endif
#ifdef CONFIG_NETDEV_WIRELESS_IOCTL

View File

@ -91,6 +91,8 @@ int netlib_ipv4adaptor(in_addr_t destipaddr, FAR in_addr_t *srcipaddr)
{
FAR struct ifreq *ifr;
struct ifconf ifc;
size_t allocsize;
size_t buflen;
int nintf;
int ret;
int sd;
@ -123,7 +125,8 @@ int netlib_ipv4adaptor(in_addr_t destipaddr, FAR in_addr_t *srcipaddr)
/* Allocate the buffer to hold the interface descriptions */
ifr = (FAR struct ifreq *)malloc(ifc.ifc_len);
allocsize = ifc.ifc_len;
ifr = (FAR struct ifreq *)malloc(allocsize);
if (ifr == NULL)
{
fprintf(stderr, "ERROR: Failed to allocate IFC buffer\n");
@ -144,10 +147,22 @@ int netlib_ipv4adaptor(in_addr_t destipaddr, FAR in_addr_t *srcipaddr)
}
/* Find an interface that supports the subnet needed by the provided
* IPv4 address.
* IPv4 address. Be careful! The size of the returned buffer could
* be different if the network device configuration changed in between
* the two calls!
*/
nintf = ifc.ifc_len / sizeof(struct ifreq);
buflen = ifc.ifc_len;
if (buflen > allocsize)
{
/* Something has changed. Limit to the original size (OR do the
* allocation and IOCTL again).
*/
buflen = allocsize;
}
nintf = buflen / sizeof(struct ifreq);
ret = -EHOSTUNREACH;
for (i = 0; i < nintf; i++)

View File

@ -92,6 +92,8 @@ int netlib_ipv6adaptor(FAR const struct in6_addr *destipaddr,
{
FAR struct lifreq *lifr;
struct lifconf lifc;
size_t allocsize;
size_t buflen;
int nintf;
int ret;
int sd;
@ -124,7 +126,8 @@ int netlib_ipv6adaptor(FAR const struct in6_addr *destipaddr,
/* Allocate the buffer to hold the interface descriptions */
lifr = (FAR struct lifreq *)malloc(lifc.lifc_len);
allocsize = lifc.lifc_len;
lifr = (FAR struct lifreq *)malloc(allocsize);
if (lifr == NULL)
{
fprintf(stderr, "ERROR: Failed to allocate LIFC buffer\n");
@ -145,10 +148,22 @@ int netlib_ipv6adaptor(FAR const struct in6_addr *destipaddr,
}
/* Find an interface that supports the subnet needed by the provided
* IPv6 address.
* IPv6 address. Be careful! The size of the returned buffer could
* be different if the network device configuration changed in between
* the two calls!
*/
nintf = lifc.lifc_len / sizeof(struct lifreq);
buflen = lifc.lifc_len;
if (buflen > allocsize)
{
/* Something has changed. Limit to the original size (OR do the
* allocation and IOCTL again).
*/
buflen = allocsize;
}
nintf = buflen / sizeof(struct lifreq);
ret = -EHOSTUNREACH;
for (i = 0; i < nintf; i++)