about summary refs log tree commit diff
path: root/src/platform/nm-platform-utils.c
diff options
context:
space:
mode:
authorAron Xu <aron@debian.org>2016-12-20 20:06:37 +0800
committerAron Xu <aron@debian.org>2016-12-20 20:06:37 +0800
commit45cb5bb3c0e6edb887cf69b417fcaf7053814a9b (patch)
tree795f8d6a3aa1145e4ba8fa1564f39425ea0c6ed9 /src/platform/nm-platform-utils.c
parent270c4830551c9810ad4e83f9a1db2b1cb946208c (diff)
Imported Upstream version 1.4.4 upstream/1.4.4
Diffstat (limited to 'src/platform/nm-platform-utils.c')
-rw-r--r--src/platform/nm-platform-utils.c87
1 files changed, 85 insertions, 2 deletions
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index 068801ee..b939e783 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -31,12 +31,15 @@
 #include <linux/mii.h>
 #include <linux/version.h>
 #include <linux/rtnetlink.h>
+#include <fcntl.h>
 
 #include "nm-utils.h"
 #include "nm-setting-wired.h"
 
 #include "nm-core-utils.h"
 
+extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
+
 /******************************************************************
  * ethtool
  ******************************************************************/
@@ -60,7 +63,7 @@ ethtool_get (const char *name, gpointer edata)
 	nm_utils_ifname_cpy (ifr.ifr_name, name);
 	ifr.ifr_data = edata;
 
-	fd = socket (PF_INET, SOCK_DGRAM, 0);
+	fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
 	if (fd < 0) {
 		nm_log_err (LOGD_PLATFORM, "ethtool: Could not open socket.");
 		return FALSE;
@@ -342,7 +345,7 @@ nmp_utils_mii_supports_carrier_detect (const char *ifname)
 	if (!nmp_utils_device_exists (ifname))
 		return FALSE;
 
-	fd = socket (PF_INET, SOCK_DGRAM, 0);
+	fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
 	if (fd < 0) {
 		nm_log_err (LOGD_PLATFORM, "mii: couldn't open control socket (%s)", ifname);
 		return FALSE;
@@ -558,3 +561,83 @@ nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize
 	return buf;
 }
 
+/**
+ * nmp_utils_sysctl_open_netdir:
+ * @ifindex: the ifindex for which to open "/sys/class/net/%s"
+ * @ifname_guess: (allow-none): optional argument, if present used as initial
+ *   guess as the current name for @ifindex. If guessed right,
+ *   it saves an addtional if_indextoname() call.
+ * @out_ifname: (allow-none): if present, must be at least IFNAMSIZ
+ *   characters. On success, this will contain the actual ifname
+ *   found while opening the directory.
+ *
+ * Returns: a negative value on failure, on success returns the open fd
+ *   to the "/sys/class/net/%s" directory for @ifindex.
+ */
+int
+nmp_utils_sysctl_open_netdir (int ifindex,
+                              const char *ifname_guess,
+                              char *out_ifname)
+{
+	#define SYS_CLASS_NET "/sys/class/net/"
+	const char *ifname = ifname_guess;
+	char ifname_buf_last_try[IFNAMSIZ];
+	char ifname_buf[IFNAMSIZ];
+	guint try_count = 0;
+	char sysdir[NM_STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET;
+	char fd_buf[256];
+	ssize_t nn;
+
+	g_return_val_if_fail (ifindex >= 0, -1);
+
+	ifname_buf_last_try[0] = '\0';
+
+	for (try_count = 0; try_count < 10; try_count++, ifname = NULL) {
+		nm_auto_close int fd_dir = -1;
+		nm_auto_close int fd_ifindex = -1;
+		int fd;
+
+		if (!ifname) {
+			ifname = if_indextoname (ifindex, ifname_buf);
+			if (!ifname)
+				return -1;
+		}
+
+		nm_assert (nm_utils_iface_valid_name (ifname));
+
+		if (g_strlcpy (&sysdir[NM_STRLEN (SYS_CLASS_NET)], ifname, IFNAMSIZ) >= IFNAMSIZ)
+			g_return_val_if_reached (-1);
+
+		/* we only retry, if the name changed since previous attempt.
+		 * Hence, it is extremely unlikely that this loop runes until the
+		 * end of the @try_count. */
+		if (nm_streq (ifname, ifname_buf_last_try))
+			return -1;
+		strcpy (ifname_buf_last_try, ifname);
+
+		fd_dir = open (sysdir, O_DIRECTORY | O_CLOEXEC);
+		if (fd_dir < 0)
+			continue;
+
+		fd_ifindex = openat (fd_dir, "ifindex", O_CLOEXEC);
+		if (fd_ifindex < 0)
+			continue;
+
+		nn = nm_utils_fd_read_loop (fd_ifindex, fd_buf, sizeof (fd_buf) - 2, FALSE);
+		if (nn <= 0)
+			continue;
+		fd_buf[nn] = '\0';
+
+		if (ifindex != _nm_utils_ascii_str_to_int64 (fd_buf, 10, 1, G_MAXINT, -1))
+			continue;
+
+		if (out_ifname)
+			strcpy (out_ifname, ifname);
+
+		fd = fd_dir;
+		fd_dir = -1;
+		return fd;
+	}
+
+	return -1;
+}