diff options
author | Kai-Heng Feng <kai.heng.feng@canonical.com> | 2016-12-07 18:15:13 +0800 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-12-13 11:26:58 +0100 |
commit | 713c74f6e4a88f874cf3e9908b3fb153f2ea5b83 (patch) | |
tree | f42c545ed1a07f666bf0c533193d2a2c57f74fa4 | |
parent | 99e1e4d6a19f8fc183ceaea39830c60cdeb1e778 (diff) | |
download | NetworkManager-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.c | 50 | ||||
-rw-r--r-- | src/platform/nm-platform-utils.h | 2 |
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__ */ |