[lxc-devel] [PATCH] Add get_interfaces to the API - v2

S.Çağlar Onur caglar at 10ur.org
Mon Sep 16 18:26:47 UTC 2013


get_ips accepts an interface name as a parameter but there was no
way to get the interfaces names from the container. This patch
introduces a new get_interfaces call to the API so that users
can obtain the name of the interfaces.

Signed-off-by: S.Çağlar Onur <caglar at 10ur.org>
---
 src/lxc/lxccontainer.c | 117 ++++++++++++++++++++++++++++++++++---------------
 src/lxc/lxccontainer.h |   1 +
 src/lxc/utils.c        |  22 +++++++++-
 src/lxc/utils.h        |   1 +
 4 files changed, 105 insertions(+), 36 deletions(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 79237df..6aa59fc 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -1179,23 +1179,26 @@ static bool lxcapi_clear_config_item(struct lxc_container *c, const char *key)
 	return ret == 0;
 }
 
-char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, int scope)
-{
-	int count = 0;
-	struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
-	char addressOutputBuffer[INET6_ADDRSTRLEN];
-	void *tempAddrPtr = NULL;
-	char **addresses = NULL, **temp;
-	char *address = NULL;
+static inline void exit_from_ns(struct lxc_container *c, int *old_netns, int *new_netns) {
+	/* Switch back to original netns */
+	if (*old_netns >= 0 && setns(*old_netns, CLONE_NEWNET))
+		SYSERROR("failed to setns");
+	if (*new_netns >= 0)
+		close(*new_netns);
+	if (*old_netns >= 0)
+		close(*old_netns);
+}
+
+static inline bool enter_to_ns(struct lxc_container *c, int *old_netns, int *new_netns) {
+	int ret = 0;
 	char new_netns_path[MAXPATHLEN];
-	int old_netns = -1, new_netns = -1, ret = 0;
 
 	if (!c->is_running(c))
 		goto out;
 
 	/* Save reference to old netns */
-	old_netns = open("/proc/self/ns/net", O_RDONLY);
-	if (old_netns < 0) {
+	*old_netns = open("/proc/self/ns/net", O_RDONLY);
+	if (*old_netns < 0) {
 		SYSERROR("failed to open /proc/self/ns/net");
 		goto out;
 	}
@@ -1205,16 +1208,78 @@ char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, in
 	if (ret < 0 || ret >= MAXPATHLEN)
 		goto out;
 
-	new_netns = open(new_netns_path, O_RDONLY);
-	if (new_netns < 0) {
+	*new_netns = open(new_netns_path, O_RDONLY);
+	if (*new_netns < 0) {
 		SYSERROR("failed to open %s", new_netns_path);
 		goto out;
 	}
 
-	if (setns(new_netns, CLONE_NEWNET)) {
+	if (setns(*new_netns, CLONE_NEWNET)) {
 		SYSERROR("failed to setns");
 		goto out;
 	}
+	return true;
+out:
+	exit_from_ns(c, old_netns, new_netns);
+	return false;
+}
+
+static char** lxcapi_get_interfaces(struct lxc_container *c)
+{
+	int count = 0;
+	struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
+	char **interfaces = NULL, **temp;
+	int old_netns = -1, new_netns = -1;
+
+	if (!enter_to_ns(c, &old_netns, &new_netns))
+		goto out;
+
+	/* Grab the list of interfaces */
+	if (getifaddrs(&interfaceArray)) {
+		SYSERROR("failed to get interfaces list");
+		goto out;
+	}
+
+	/* Iterate through the interfaces */
+	for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {
+		/* filter out loopback interface */
+		if(tempIfAddr->ifa_addr == NULL || tempIfAddr->ifa_addr->sa_family != AF_PACKET || strcmp("lo", tempIfAddr->ifa_name) == 0)
+			continue;
+
+        count += 1;
+        temp = realloc(interfaces, count * sizeof(*interfaces));
+        if (!temp) {
+            count -= 1;
+            goto out;
+        }
+        interfaces = temp;
+        interfaces[count - 1] = strdup(tempIfAddr->ifa_name);
+    }
+
+out:
+	if(interfaceArray)
+		freeifaddrs(interfaceArray);
+
+	exit_from_ns(c, &old_netns, &new_netns);
+
+	/* Append NULL to the array */
+	interfaces = (char **)lxc_append_null_to_array((void **)interfaces, count);
+
+	return interfaces;
+}
+
+static char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, int scope)
+{
+	int count = 0;
+	struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
+	char addressOutputBuffer[INET6_ADDRSTRLEN];
+	void *tempAddrPtr = NULL;
+	char **addresses = NULL, **temp;
+	char *address = NULL;
+	int old_netns = -1, new_netns = -1;
+
+	if (!enter_to_ns(c, &old_netns, &new_netns))
+		goto out;
 
 	/* Grab the list of interfaces */
 	if (getifaddrs(&interfaceArray)) {
@@ -1243,7 +1308,6 @@ char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, in
 			continue;
 		else if (!interface && strcmp("lo", tempIfAddr->ifa_name) == 0)
 			continue;
-
 		address = (char *)inet_ntop(tempIfAddr->ifa_addr->sa_family,
 					   tempAddrPtr,
 					   addressOutputBuffer,
@@ -1265,28 +1329,10 @@ out:
 	if(interfaceArray)
 		freeifaddrs(interfaceArray);
 
-	/* Switch back to original netns */
-	if (old_netns >= 0 && setns(old_netns, CLONE_NEWNET))
-		SYSERROR("failed to setns");
-	if (new_netns >= 0)
-		close(new_netns);
-	if (old_netns >= 0)
-		close(old_netns);
+	exit_from_ns(c, &old_netns, &new_netns);
 
 	/* Append NULL to the array */
-	if (count) {
-		count++;
-		temp = realloc(addresses, count * sizeof(*addresses));
-		if (!temp) {
-			int i;
-			for (i = 0; i < count-1; i++)
-				free(addresses[i]);
-			free(addresses);
-			return NULL;
-		}
-		addresses = temp;
-		addresses[count - 1] = NULL;
-	}
+	addresses = (char **)lxc_append_null_to_array((void **)addresses, count);
 
 	return addresses;
 }
@@ -2576,6 +2622,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
 	c->get_config_path = lxcapi_get_config_path;
 	c->set_config_path = lxcapi_set_config_path;
 	c->clone = lxcapi_clone;
+	c->get_interfaces = lxcapi_get_interfaces;
 	c->get_ips = lxcapi_get_ips;
 	c->attach = lxcapi_attach;
 	c->attach_run_wait = lxcapi_attach_run_wait;
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index f9ae43b..f17d975 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -90,6 +90,7 @@ struct lxc_container {
 	 * the length which was our would be printed. */
 	int (*get_config_item)(struct lxc_container *c, const char *key, char *retv, int inlen);
 	int (*get_keys)(struct lxc_container *c, const char *key, char *retv, int inlen);
+	char** (*get_interfaces)(struct lxc_container *c);
 	char** (*get_ips)(struct lxc_container *c, char* interface, char* family, int scope);
 	/*
 	 * get_cgroup_item returns the number of bytes read, or an error (<0).
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 78b234d..924cc19 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -852,7 +852,7 @@ int lxc_write_to_file(const char *filename, const void* buf, size_t count, bool
 		return -1;
 	ret = lxc_write_nointr(fd, buf, count);
 	if (ret < 0)
-		goto out_error; 
+		goto out_error;
 	if ((size_t)ret != count)
 		goto out_error;
 	if (add_newline) {
@@ -899,3 +899,23 @@ int lxc_read_from_file(const char *filename, void* buf, size_t count)
 	errno = saved_errno;
 	return ret;
 }
+
+void **lxc_append_null_to_array(void **array, size_t count)
+{
+	void **temp;
+
+	/* Append NULL to the array */
+	if (count) {
+		temp = realloc(array, (count + 1) * sizeof(*array));
+		if (!temp) {
+			int i;
+			for (i = 0; i < count; i++)
+				free(array[i]);
+			free(array);
+			return NULL;
+		}
+		array = temp;
+		array[count] = NULL;
+	}
+	return array;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index ba7cfb3..55f98fa 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -236,4 +236,5 @@ extern void lxc_free_array(void **array, lxc_free_fn element_free_fn);
 extern size_t lxc_array_len(void **array);
 extern void **lxc_dup_array(void **array, lxc_dup_fn element_dup_fn, lxc_free_fn element_free_fn);
 
+extern void **lxc_append_null_to_array(void **array, size_t count);
 #endif
-- 
1.8.1.2





More information about the lxc-devel mailing list