<div dir="ltr">Hi,<div><br></div><div>Seems like "git send-mail" decided to send this without an explanation. So here it is;</div><div><br></div><div>While implementing get_ips API for Go bindings I realized that function can receive an interface name as a parameter. There was no way to find the interface names from the container so this patch introduces get_interfaces method to API.</div>

</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Sep 13, 2013 at 6:21 PM, S.Çağlar Onur <span dir="ltr"><<a href="mailto:caglar@10ur.org" target="_blank">caglar@10ur.org</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Signed-off-by: S.Çağlar Onur <<a href="mailto:caglar@10ur.org">caglar@10ur.org</a>><br>
---<br>
 src/lxc/lxccontainer.c | 119 +++++++++++++++++++++++++++++++++++++++----------<br>
 src/lxc/lxccontainer.h |   1 +<br>
 2 files changed, 97 insertions(+), 23 deletions(-)<br>
<br>
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c<br>
index 79237df..14b6942 100644<br>
--- a/src/lxc/lxccontainer.c<br>
+++ b/src/lxc/lxccontainer.c<br>
@@ -1179,23 +1179,26 @@ static bool lxcapi_clear_config_item(struct lxc_container *c, const char *key)<br>
        return ret == 0;<br>
 }<br>
<br>
-char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, int scope)<br>
-{<br>
-       int count = 0;<br>
-       struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;<br>
-       char addressOutputBuffer[INET6_ADDRSTRLEN];<br>
-       void *tempAddrPtr = NULL;<br>
-       char **addresses = NULL, **temp;<br>
-       char *address = NULL;<br>
+static void exit_from_ns(struct lxc_container *c, int *old_netns, int *new_netns) {<br>
+       /* Switch back to original netns */<br>
+       if (*old_netns >= 0 && setns(*old_netns, CLONE_NEWNET))<br>
+               SYSERROR("failed to setns");<br>
+       if (*new_netns >= 0)<br>
+               close(*new_netns);<br>
+       if (*old_netns >= 0)<br>
+               close(*old_netns);<br>
+}<br>
+<br>
+static bool enter_to_ns(struct lxc_container *c, int *old_netns, int *new_netns) {<br>
+       int ret = 0;<br>
        char new_netns_path[MAXPATHLEN];<br>
-       int old_netns = -1, new_netns = -1, ret = 0;<br>
<br>
        if (!c->is_running(c))<br>
                goto out;<br>
<br>
        /* Save reference to old netns */<br>
-       old_netns = open("/proc/self/ns/net", O_RDONLY);<br>
-       if (old_netns < 0) {<br>
+       *old_netns = open("/proc/self/ns/net", O_RDONLY);<br>
+       if (*old_netns < 0) {<br>
                SYSERROR("failed to open /proc/self/ns/net");<br>
                goto out;<br>
        }<br>
@@ -1205,16 +1208,93 @@ char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, in<br>
        if (ret < 0 || ret >= MAXPATHLEN)<br>
                goto out;<br>
<br>
-       new_netns = open(new_netns_path, O_RDONLY);<br>
-       if (new_netns < 0) {<br>
+       *new_netns = open(new_netns_path, O_RDONLY);<br>
+       if (*new_netns < 0) {<br>
                SYSERROR("failed to open %s", new_netns_path);<br>
                goto out;<br>
        }<br>
<br>
-       if (setns(new_netns, CLONE_NEWNET)) {<br>
+       if (setns(*new_netns, CLONE_NEWNET)) {<br>
                SYSERROR("failed to setns");<br>
                goto out;<br>
        }<br>
+       return true;<br>
+out:<br>
+       exit_from_ns(c, old_netns, new_netns);<br>
+       return false;<br>
+}<br>
+<br>
+char** lxcapi_get_interfaces(struct lxc_container *c)<br>
+{<br>
+       int count = 0;<br>
+       struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;<br>
+       char **interfaces = NULL, **temp;<br>
+       int old_netns = -1, new_netns = -1;<br>
+<br>
+       if (!enter_to_ns(c, &old_netns, &new_netns))<br>
+               goto out;<br>
+<br>
+       /* Grab the list of interfaces */<br>
+       if (getifaddrs(&interfaceArray)) {<br>
+               SYSERROR("failed to get interfaces list");<br>
+               goto out;<br>
+       }<br>
+<br>
+       /* Iterate through the interfaces */<br>
+       for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {<br>
+        if (tempIfAddr->ifa_addr == NULL)<br>
+            continue;<br>
+<br>
+               if(tempIfAddr->ifa_addr->sa_family != AF_PACKET) {<br>
+            continue;<br>
+        }<br>
+<br>
+        count += 1;<br>
+        temp = realloc(interfaces, count * sizeof(*interfaces));<br>
+        if (!temp) {<br>
+            count -= 1;<br>
+            goto out;<br>
+        }<br>
+        interfaces = temp;<br>
+        interfaces[count - 1] = strdup(tempIfAddr->ifa_name);<br>
+    }<br>
+<br>
+out:<br>
+       if(interfaceArray)<br>
+               freeifaddrs(interfaceArray);<br>
+<br>
+       exit_from_ns(c, &old_netns, &new_netns);<br>
+<br>
+       /* Append NULL to the array */<br>
+       if (count) {<br>
+               count++;<br>
+               temp = realloc(interfaces, count * sizeof(*interfaces));<br>
+               if (!temp) {<br>
+                       int i;<br>
+                       for (i = 0; i < count-1; i++)<br>
+                               free(interfaces[i]);<br>
+                       free(interfaces);<br>
+                       return NULL;<br>
+               }<br>
+               interfaces = temp;<br>
+               interfaces[count - 1] = NULL;<br>
+       }<br>
+<br>
+       return interfaces;<br>
+}<br>
+<br>
+char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, int scope)<br>
+{<br>
+       int count = 0;<br>
+       struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;<br>
+       char addressOutputBuffer[INET6_ADDRSTRLEN];<br>
+       void *tempAddrPtr = NULL;<br>
+       char **addresses = NULL, **temp;<br>
+       char *address = NULL;<br>
+       int old_netns = -1, new_netns = -1;<br>
+<br>
+       if (!enter_to_ns(c, &old_netns, &new_netns))<br>
+               goto out;<br>
<br>
        /* Grab the list of interfaces */<br>
        if (getifaddrs(&interfaceArray)) {<br>
@@ -1241,8 +1321,6 @@ char** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, in<br>
<br>
                if (interface && strcmp(interface, tempIfAddr->ifa_name))<br>
                        continue;<br>
-               else if (!interface && strcmp("lo", tempIfAddr->ifa_name) == 0)<br>
-                       continue;<br>
<br>
                address = (char *)inet_ntop(tempIfAddr->ifa_addr->sa_family,<br>
                                           tempAddrPtr,<br>
@@ -1265,13 +1343,7 @@ out:<br>
        if(interfaceArray)<br>
                freeifaddrs(interfaceArray);<br>
<br>
-       /* Switch back to original netns */<br>
-       if (old_netns >= 0 && setns(old_netns, CLONE_NEWNET))<br>
-               SYSERROR("failed to setns");<br>
-       if (new_netns >= 0)<br>
-               close(new_netns);<br>
-       if (old_netns >= 0)<br>
-               close(old_netns);<br>
+       exit_from_ns(c, &old_netns, &new_netns);<br>
<br>
        /* Append NULL to the array */<br>
        if (count) {<br>
@@ -2576,6 +2648,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath<br>
        c->get_config_path = lxcapi_get_config_path;<br>
        c->set_config_path = lxcapi_set_config_path;<br>
        c->clone = lxcapi_clone;<br>
+       c->get_interfaces = lxcapi_get_interfaces;<br>
        c->get_ips = lxcapi_get_ips;<br>
        c->attach = lxcapi_attach;<br>
        c->attach_run_wait = lxcapi_attach_run_wait;<br>
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h<br>
index f9ae43b..f17d975 100644<br>
--- a/src/lxc/lxccontainer.h<br>
+++ b/src/lxc/lxccontainer.h<br>
@@ -90,6 +90,7 @@ struct lxc_container {<br>
         * the length which was our would be printed. */<br>
        int (*get_config_item)(struct lxc_container *c, const char *key, char *retv, int inlen);<br>
        int (*get_keys)(struct lxc_container *c, const char *key, char *retv, int inlen);<br>
+       char** (*get_interfaces)(struct lxc_container *c);<br>
        char** (*get_ips)(struct lxc_container *c, char* interface, char* family, int scope);<br>
        /*<br>
         * get_cgroup_item returns the number of bytes read, or an error (<0).<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.1.2<br>
<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br>S.Çağlar Onur <<a href="mailto:caglar@10ur.org">caglar@10ur.org</a>>
</div>