summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/ifaddrs.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
committerUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
commita334319f6530564d22e775935d9c91663623a1b4 (patch)
treeb5877475619e4c938e98757d518bb1e9cbead751 /sysdeps/unix/sysv/linux/ifaddrs.c
parent0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (diff)
downloadglibc-a334319f6530564d22e775935d9c91663623a1b4.tar.gz
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
Diffstat (limited to 'sysdeps/unix/sysv/linux/ifaddrs.c')
-rw-r--r--sysdeps/unix/sysv/linux/ifaddrs.c138
1 files changed, 51 insertions, 87 deletions
diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c
index 02e6935538..8a052e212d 100644
--- a/sysdeps/unix/sysv/linux/ifaddrs.c
+++ b/sysdeps/unix/sysv/linux/ifaddrs.c
@@ -1,5 +1,5 @@
/* getifaddrs -- get names and addresses of all network interfaces
- Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,7 +17,6 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#include <alloca.h>
#include <assert.h>
#include <errno.h>
#include <ifaddrs.h>
@@ -25,7 +24,6 @@
#include <netinet/in.h>
#include <netpacket/packet.h>
#include <stdbool.h>
-#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
@@ -86,14 +84,13 @@ __netlink_free_handle (struct netlink_handle *h)
}
-static int
+int
__netlink_sendreq (struct netlink_handle *h, int type)
{
- struct req
+ struct
{
struct nlmsghdr nlh;
struct rtgenmsg g;
- char pad[0];
} req;
struct sockaddr_nl nladdr;
@@ -106,8 +103,6 @@ __netlink_sendreq (struct netlink_handle *h, int type)
req.nlh.nlmsg_pid = 0;
req.nlh.nlmsg_seq = h->seq;
req.g.rtgen_family = AF_UNSPEC;
- if (sizeof (req) != offsetof (struct req, pad))
- memset (req.pad, '\0', sizeof (req) - offsetof (struct req, pad));
memset (&nladdr, '\0', sizeof (nladdr));
nladdr.nl_family = AF_NETLINK;
@@ -119,40 +114,16 @@ __netlink_sendreq (struct netlink_handle *h, int type)
int
-__netlink_request (struct netlink_handle *h, int type)
+__netlink_receive (struct netlink_handle *h)
{
struct netlink_res *nlm_next;
+ char buf[4096];
+ struct iovec iov = { buf, sizeof (buf) };
struct sockaddr_nl nladdr;
struct nlmsghdr *nlmh;
- ssize_t read_len;
+ int read_len;
bool done = false;
-#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;
-#else
- const size_t buf_size = __getpagesize ();
-#endif
- bool use_malloc = false;
- char *buf;
-
- if (__libc_use_alloca (buf_size))
- buf = alloca (buf_size);
- else
- {
- buf = malloc (buf_size);
- if (buf != NULL)
- use_malloc = true;
- else
- goto out_fail;
- }
-
- struct iovec iov = { buf, buf_size };
-
- if (__netlink_sendreq (h, type) < 0)
- goto out_fail;
-
while (! done)
{
struct msghdr msg =
@@ -165,25 +136,33 @@ __netlink_request (struct netlink_handle *h, int type)
read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0));
if (read_len < 0)
- goto out_fail;
+ return -1;
- if (nladdr.nl_pid != 0)
- continue;
+ if (msg.msg_flags & MSG_TRUNC)
+ return -1;
- if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0))
- goto out_fail;
+ nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res)
+ + read_len);
+ if (nlm_next == NULL)
+ return -1;
+ nlm_next->next = NULL;
+ nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len);
+ nlm_next->size = read_len;
+ nlm_next->seq = h->seq;
+ if (h->nlm_list == NULL)
+ h->nlm_list = nlm_next;
+ else
+ h->end_ptr->next = nlm_next;
+ h->end_ptr = nlm_next;
- size_t count = 0;
- size_t remaining_len = read_len;
for (nlmh = (struct nlmsghdr *) buf;
- NLMSG_OK (nlmh, remaining_len);
- nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len))
+ NLMSG_OK (nlmh, (size_t) read_len);
+ nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len))
{
- if ((pid_t) nlmh->nlmsg_pid != h->pid
+ if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != h->pid
|| nlmh->nlmsg_seq != h->seq)
continue;
- ++count;
if (nlmh->nlmsg_type == NLMSG_DONE)
{
/* We found the end, leave the loop. */
@@ -197,38 +176,11 @@ __netlink_request (struct netlink_handle *h, int type)
errno = EIO;
else
errno = -nlerr->error;
- goto out_fail;
+ return -1;
}
}
-
- /* If there was nothing with the expected nlmsg_pid and nlmsg_seq,
- there is no point to record it. */
- if (count == 0)
- continue;
-
- nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res)
- + read_len);
- if (nlm_next == NULL)
- goto out_fail;
- nlm_next->next = NULL;
- nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len);
- nlm_next->size = read_len;
- nlm_next->seq = h->seq;
- if (h->nlm_list == NULL)
- h->nlm_list = nlm_next;
- else
- h->end_ptr->next = nlm_next;
- h->end_ptr = nlm_next;
}
-
- if (use_malloc)
- free (buf);
return 0;
-
-out_fail:
- if (use_malloc)
- free (buf);
- return -1;
}
@@ -316,11 +268,12 @@ getifaddrs (struct ifaddrs **ifap)
unsigned int i, newlink, newaddr, newaddr_idx;
int *map_newlink_data;
size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */
- char *ifa_data_ptr; /* Pointer to the unused part of memory for
+ char *ifa_data_ptr; /* Pointer to the unused part of memory for
ifa_data. */
int result = 0;
- *ifap = NULL;
+ if (ifap)
+ *ifap = NULL;
if (! __no_netlink_support && __netlink_open (&nh) < 0)
{
@@ -335,20 +288,28 @@ getifaddrs (struct ifaddrs **ifap)
#endif
/* Tell the kernel that we wish to get a list of all
- active interfaces, collect all data for every interface. */
- if (__netlink_request (&nh, RTM_GETLINK) < 0)
+ active interfaces. */
+ if (__netlink_sendreq (&nh, RTM_GETLINK) < 0)
+ {
+ result = -1;
+ goto exit_close;
+ }
+ /* Collect all data for every interface. */
+ if (__netlink_receive (&nh) < 0)
{
result = -1;
goto exit_free;
}
+
/* Now ask the kernel for all addresses which are assigned
- to an interface and collect all data for every interface.
- Since we store the addresses after the interfaces in the
- list, we will later always find the interface before the
- corresponding addresses. */
+ to an interface. Since we store the addresses after the
+ interfaces in the list, we will later always find the
+ interface before the corresponding addresses. */
++nh.seq;
- if (__netlink_request (&nh, RTM_GETADDR) < 0)
+ if (__netlink_sendreq (&nh, RTM_GETADDR) < 0
+ /* Collect all data for every interface. */
+ || __netlink_receive (&nh) < 0)
{
result = -1;
goto exit_free;
@@ -366,7 +327,7 @@ getifaddrs (struct ifaddrs **ifap)
continue;
/* Walk through all entries we got from the kernel and look, which
- message type they contain. */
+ message type they contain. */
for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
{
/* Check if the message is what we want. */
@@ -462,7 +423,7 @@ getifaddrs (struct ifaddrs **ifap)
/* Interfaces are stored in the first "newlink" entries
of our list, starting in the order as we got from the
kernel. */
- ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
+ ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
map_newlink_data, newlink);
ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags;
@@ -801,10 +762,13 @@ getifaddrs (struct ifaddrs **ifap)
memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
}
- *ifap = &ifas[0].ifa;
+ if (ifap != NULL)
+ *ifap = &ifas[0].ifa;
exit_free:
__netlink_free_handle (&nh);
+
+ exit_close:
__netlink_close (&nh);
return result;