]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/unix/sysv/linux/ifaddrs.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / ifaddrs.c
index 5c1e380fca30b49ea2677e2046064b9302734442..10a1520802c74ac9a1243db26011653eee7d3f40 100644 (file)
@@ -1,5 +1,5 @@
 /* getifaddrs -- get names and addresses of all network interfaces
-   Copyright (C) 2003-2013 Free Software Foundation, Inc.
+   Copyright (C) 2003-2019 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
@@ -32,7 +32,6 @@
 #include <sysdep.h>
 #include <time.h>
 #include <unistd.h>
-#include <kernel-features.h>
 
 #include "netlinkaccess.h"
 
@@ -162,20 +161,24 @@ __netlink_request (struct netlink_handle *h, int type)
     {
       struct msghdr msg =
        {
-         (void *) &nladdr, sizeof (nladdr),
-         &iov, 1,
-         NULL, 0,
-         0
+         .msg_name = (void *) &nladdr,
+         .msg_namelen =  sizeof (nladdr),
+         .msg_iov = &iov,
+         .msg_iovlen = 1,
+         .msg_control = NULL,
+         .msg_controllen = 0,
+         .msg_flags = 0
        };
 
       read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0));
+      __netlink_assert_response (h->fd, read_len);
       if (read_len < 0)
        goto out_fail;
 
       if (nladdr.nl_pid != 0)
        continue;
 
-      if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0))
+      if (__glibc_unlikely (msg.msg_flags & MSG_TRUNC))
        goto out_fail;
 
       size_t count = 0;
@@ -252,7 +255,7 @@ __netlink_open (struct netlink_handle *h)
 {
   struct sockaddr_nl nladdr;
 
-  h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+  h->fd = __socket (PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
   if (h->fd < 0)
     goto out;
 
@@ -283,7 +286,6 @@ __netlink_open (struct netlink_handle *h)
    Since we get at first all RTM_NEWLINK entries, it can never happen
    that a RTM_NEWADDR index is not known to this map.  */
 static int
-internal_function
 map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max)
 {
   int i;
@@ -301,7 +303,7 @@ map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max)
        return i;
     }
 
-  /* This means interfaces changed inbetween the reading of the
+  /* This means interfaces changed between the reading of the
      RTM_GETLINK and RTM_GETADDR information.  We have to repeat
      everything.  */
   return -1;
@@ -368,6 +370,14 @@ getifaddrs_internal (struct ifaddrs **ifap)
          if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
            continue;
 
+         /* If the dump got interrupted, we can't rely on the results
+            so try again. */
+         if (nlh->nlmsg_flags & NLM_F_DUMP_INTR)
+           {
+             result = -EAGAIN;
+             goto exit_free;
+           }
+
          if (nlh->nlmsg_type == NLMSG_DONE)
            break;              /* ok */
 
@@ -459,7 +469,7 @@ getifaddrs_internal (struct ifaddrs **ifap)
                 kernel.  */
              ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
                                       map_newlink_data, newlink);
-             if (__builtin_expect (ifa_index == -1, 0))
+             if (__glibc_unlikely (ifa_index == -1))
                {
                try_again:
                  result = -EAGAIN;
@@ -552,7 +562,7 @@ getifaddrs_internal (struct ifaddrs **ifap)
              ifa_index = newlink + newaddr_idx;
              int idx = map_newlink (ifam->ifa_index - 1, ifas,
                                     map_newlink_data, newlink);
-             if (__builtin_expect (idx == -1, 0))
+             if (__glibc_unlikely (idx == -1))
                goto try_again;
              ifas[ifa_index].ifa.ifa_flags = ifas[idx].ifa.ifa_flags;
              if (ifa_index > 0)
@@ -737,7 +747,7 @@ getifaddrs_internal (struct ifaddrs **ifap)
                {
                  int idx = map_newlink (ifam->ifa_index - 1, ifas,
                                         map_newlink_data, newlink);
-                 if (__builtin_expect (idx == -1, 0))
+                 if (__glibc_unlikely (idx == -1))
                    goto try_again;
                  ifas[ifa_index].ifa.ifa_name = ifas[idx].ifa.ifa_name;
                }
@@ -771,20 +781,17 @@ getifaddrs_internal (struct ifaddrs **ifap)
 
                  if (cp != NULL)
                    {
-                     char c;
                      unsigned int preflen;
 
-                     if ((max_prefixlen > 0) &&
-                         (ifam->ifa_prefixlen > max_prefixlen))
+                     if (ifam->ifa_prefixlen > max_prefixlen)
                        preflen = max_prefixlen;
                      else
                        preflen = ifam->ifa_prefixlen;
 
-                     for (i = 0; i < (preflen / 8); i++)
+                     for (i = 0; i < preflen / 8; i++)
                        *cp++ = 0xff;
-                     c = 0xff;
-                     c <<= (8 - (preflen % 8));
-                     *cp = c;
+                     if (preflen % 8)
+                       *cp = 0xff << (8 - preflen % 8);
                    }
                }
            }
@@ -823,7 +830,7 @@ getifaddrs_internal (struct ifaddrs **ifap)
    network interface on the host machine.  If successful, store the
    list in *IFAP and return 0.  On errors, return -1 and set `errno'.  */
 int
-getifaddrs (struct ifaddrs **ifap)
+__getifaddrs (struct ifaddrs **ifap)
 {
   int res;
 
@@ -833,12 +840,16 @@ getifaddrs (struct ifaddrs **ifap)
 
   return res;
 }
-libc_hidden_def (getifaddrs)
+weak_alias (__getifaddrs, getifaddrs)
+libc_hidden_def (__getifaddrs)
+libc_hidden_weak (getifaddrs)
 
 
 void
-freeifaddrs (struct ifaddrs *ifa)
+__freeifaddrs (struct ifaddrs *ifa)
 {
   free (ifa);
 }
-libc_hidden_def (freeifaddrs)
+weak_alias (__freeifaddrs, freeifaddrs)
+libc_hidden_def (__freeifaddrs)
+libc_hidden_weak (freeifaddrs)