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

Reply via email to