Quoting Stéphane Graber (stgra...@ubuntu.com): > This adds a new get_ips call which takes a family (inet, inet6 or NULL), > a network interface (or NULL for all) and a scope (0 for global) and returns > a char** of all the IPs in the container. > > This also adds a matching python3 binding (function result is a tuple) and > deprecates the previous pure-python get_ips() implementation. > > WARNING: The python get_ips() call is quite different from the previous > implementation. The timeout argument has been removed, the family names are > slightly different (inet/inet6 vs ipv4/ipv6) and an extra scope parameter > has been added. > > Signed-off-by: Stéphane Graber <stgra...@ubuntu.com> > --- > src/lxc/lxccontainer.c | 113 > ++++++++++++++++++++++++++++++++++++ > src/lxc/lxccontainer.h | 1 + > src/python-lxc/examples/api_test.py | 9 ++- > src/python-lxc/lxc.c | 61 +++++++++++++++++++ > src/python-lxc/lxc/__init__.py | 61 ------------------- > 5 files changed, 183 insertions(+), 62 deletions(-) > > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c > index 23db6f2..0e0c029 100644 > --- a/src/lxc/lxccontainer.c > +++ b/src/lxc/lxccontainer.c > @@ -37,6 +37,10 @@ > #include "bdev.h" > #include <lxc/utils.h> > #include <lxc/monitor.h> > +#include <sched.h> > +#include <fcntl.h> > +#include <arpa/inet.h> > +#include <ifaddrs.h> > > static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER; > > @@ -768,6 +772,114 @@ 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; > + 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) { > + SYSERROR("failed to open /proc/self/ns/net"); > + goto out; > + } > + > + /* Switch to new netns */ > + ret = snprintf(new_netns_path, MAXPATHLEN, "/proc/%d/ns/net", > c->init_pid(c)); > + if (ret < 0 || ret >= MAXPATHLEN) > + goto out; > + > + 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)) { > + SYSERROR("failed to setns"); > + 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) { > + if(tempIfAddr->ifa_addr->sa_family == AF_INET) { > + if (family && strcmp(family, "inet")) > + continue; > + tempAddrPtr = &((struct sockaddr_in > *)tempIfAddr->ifa_addr)->sin_addr; > + } > + else { > + if (family && strcmp(family, "inet6")) > + continue; > + > + if (((struct sockaddr_in6 > *)tempIfAddr->ifa_addr)->sin6_scope_id != scope) > + continue; > + > + tempAddrPtr = &((struct sockaddr_in6 > *)tempIfAddr->ifa_addr)->sin6_addr; > + } > + > + if (interface && strcmp(interface, tempIfAddr->ifa_name)) > + continue; > + else if (!interface && strcmp("lo", tempIfAddr->ifa_name) == 0) > + continue; > + > + address = (char *)inet_ntop(tempIfAddr->ifa_addr->sa_family, > + tempAddrPtr, > + addressOutputBuffer, > + sizeof(addressOutputBuffer)); > + if (!address) > + continue; > + > + count += 1; > + temp = realloc(addresses, count * sizeof(*addresses)); > + if (!temp) { > + count--; > + goto out; > + } > + addresses = temp; > + addresses[count - 1] = strdup(address); > + } > + > +out: > + if(interfaceArray) > + freeifaddrs(interfaceArray); > + > + /* Append NULL to the array */ > + if (count) { > + count++; > + temp = realloc(addresses, count * sizeof(*addresses)); > + if (!temp) { > + return NULL;
I think you're better off, in this case, doing something like if (!temp) { free(addresses[count-2]); addresses[count-2] = NULL; } else { addresses = temp; addresses[count - 1] = NULL; } That, or free everything. But as it is, you are leaking memory here. Otherwise, looks good - thanks! -serge ------------------------------------------------------------------------------ Try New Relic Now & We'll Send You this Cool Shirt New Relic is the only SaaS-based application performance monitoring service that delivers powerful full stack analytics. Optimize and monitor your browser, app, & servers with just a few lines of code. Try New Relic and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel