summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai-Heng Feng <kai.heng.feng@canonical.com>2016-12-07 18:15:13 +0800
committerThomas Haller <thaller@redhat.com>2016-12-13 11:26:58 +0100
commit713c74f6e4a88f874cf3e9908b3fb153f2ea5b83 (patch)
treef42c545ed1a07f666bf0c533193d2a2c57f74fa4
parent99e1e4d6a19f8fc183ceaea39830c60cdeb1e778 (diff)
downloadNetworkManager-713c74f6e4a88f874cf3e9908b3fb153f2ea5b83.tar.gz
platform: add a new function nmp_utils_open_sysctl()
A race condition may happen when NetworkManager opens sysfs and udev renames interface name at the same time. Thomas Haller provides a new function [1] which can avoid the race condition when opening sysfs. This patch is a direct copy from [1]. [1] https://mail.gnome.org/archives/networkmanager-list/2016-December/msg00004.html Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
-rw-r--r--src/platform/nm-platform-utils.c50
-rw-r--r--src/platform/nm-platform-utils.h2
2 files changed, 52 insertions, 0 deletions
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index 9ef0707d58..6c585c21fa 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -31,6 +31,7 @@
#include <linux/mii.h>
#include <linux/version.h>
#include <linux/rtnetlink.h>
+#include <fcntl.h>
#include "nm-utils.h"
#include "nm-setting-wired.h"
@@ -47,6 +48,7 @@
G_STMT_START { (pedata)->speed = (guint16) (speed); } G_STMT_END
#endif
+extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
static gboolean
ethtool_get (const char *name, gpointer edata)
@@ -623,3 +625,51 @@ nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize
return buf;
}
+int
+nmp_utils_open_sysctl(int ifindex, const char *ifname)
+{
+ #define SYS_CLASS_NET "/sys/class/net/"
+ char ifname_buf[IFNAMSIZ];
+ guint try_count = 0;
+ char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ + 1] = SYS_CLASS_NET;
+ char fd_buf[256];
+ int fd;
+ int fd_ifindex;
+ ssize_t nn;
+
+ while (++try_count < 4) {
+ if (!ifname) {
+ ifname = if_indextoname (ifindex, ifname_buf);
+ if (!ifname)
+ return -1;
+ }
+
+ nm_utils_ifname_cpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], ifname);
+ fd = open (sysdir, O_DIRECTORY);
+ if (fd < 0)
+ goto next;
+ fd_ifindex = openat (fd, "ifindex", 0);
+ if (fd_ifindex < 0) {
+ close (fd);
+ goto next;
+ }
+ /* read ifindex file, and compare it to @ifindex. If match, return fd. */
+ nn = nm_utils_fd_read_loop (fd_ifindex, fd_buf, sizeof (fd_buf) - 1, FALSE);
+ if (nn < 0) {
+ close (fd);
+ close (fd_ifindex);
+ goto next;
+ }
+ fd_buf[sizeof (fd_buf) - 1] = '\0';
+
+ if (ifindex != _nm_utils_ascii_str_to_int64 (fd_buf, 10, 1, G_MAXINT, -1)) {
+ close (fd);
+ close (fd_ifindex);
+ goto next;
+ }
+ return fd;
+next:
+ ifname = NULL;
+ }
+ return -1;
+}
diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h
index 4b4868c1e8..72a06a8a92 100644
--- a/src/platform/nm-platform-utils.h
+++ b/src/platform/nm-platform-utils.h
@@ -61,4 +61,6 @@ NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource
NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source) _nm_const;
const char * nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len);
+int nmp_utils_open_sysctl(int ifindex, const char *ifname);
+
#endif /* __NM_PLATFORM_UTILS_H__ */