summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2013-07-30 05:34:15 -0300
committerAlexandre Oliva <aoliva@redhat.com>2013-09-17 17:13:03 -0300
commite07ac713b388f6ea44a0891241ae7c67959bc3c8 (patch)
tree56cba74c2d6eafdab95375ee8adb64e435b11a2c
parent7fc88e8889a72d69a74835cf4141aa911db82280 (diff)
downloadglibc-lxoliva/assorted.tar.gz
Grow the netlink buffer and retry instead of failing getifaddrslxoliva/assorted
for ChangeLog * sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_request): Grow buffer and retry when message is fragmented.
-rw-r--r--sysdeps/unix/sysv/linux/ifaddrs.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c
index 89fda156a2..c9decc30e4 100644
--- a/sysdeps/unix/sysv/linux/ifaddrs.c
+++ b/sysdeps/unix/sysv/linux/ifaddrs.c
@@ -135,13 +135,14 @@ __netlink_request (struct netlink_handle *h, int type)
#ifdef PAGE_SIZE
/* Help the compiler optimize out the malloc call if PAGE_SIZE
is constant and smaller or equal to PTHREAD_STACK_MIN/4. */
- const size_t buf_size = PAGE_SIZE;
+ size_t buf_size = PAGE_SIZE;
#else
- const size_t buf_size = __getpagesize ();
+ size_t buf_size = __getpagesize ();
#endif
bool use_malloc = false;
char *buf;
+ retry:
if (__libc_use_alloca (buf_size))
buf = alloca (buf_size);
else
@@ -176,7 +177,23 @@ __netlink_request (struct netlink_handle *h, int type)
continue;
if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0))
- goto out_fail;
+ {
+ /* Consume the rest of the truncated response, then retry
+ with a larger buffer. */
+ do
+ {
+ read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0));
+ if (read_len < 0)
+ break;
+ buf_size += read_len;
+ }
+ while ((msg.msg_flags & MSG_TRUNC) != 0);
+
+ if (use_malloc)
+ free (buf);
+ goto retry;
+ }
+
size_t count = 0;
size_t remaining_len = read_len;