From 576400e5e01b6634bbc8e8fa11beffa71cc4ef45 Mon Sep 17 00:00:00 2001 From: fli Date: Tue, 6 Dec 2016 00:59:52 -0800 Subject: [PATCH] confile: support the network link string pattern matching Enable lxc network config support the following type and link: lxc.network.type = phys lxc.network.link = eth+ Here, the suffix '+' will trigger a string pattern matching and when lxc find any network interfaces name prefixed with "eth" such as "eth0", "eth1", "ethxxxx" and so on, it will try to move them into the container's namespace; If it didn't find any matching, it would do nothing for this configure line. Signed-off-by: fli --- src/lxc/confile.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/src/lxc/confile.c b/src/lxc/confile.c index d7362caed..732b9ddea 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -50,6 +50,12 @@ #include "network.h" #include "lxcseccomp.h" +#if HAVE_IFADDRS_H +#include +#else +#include <../include/ifaddrs.h> +#endif + #if HAVE_SYS_PERSONALITY_H #include #endif @@ -672,16 +678,85 @@ static int config_network_flags(const char *key, const char *value, return 0; } +static int set_network_link(const char *key, const char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_netdev *netdev; + + netdev = network_netdev(key, value, &lxc_conf->network); + if (!netdev) + return -1; + + return network_ifname(&netdev->link, value); +} + +static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf) +{ + struct ifaddrs *ifaddr, *ifa; + const char *type_key = "lxc.network.type"; + const char *link_key = "lxc.network.link"; + const char *tmpvalue = "phys"; + int n, ret = 0; + + if (getifaddrs(&ifaddr) == -1) { + SYSERROR("Get network interfaces failed"); + return -1; + } + + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { + if (!ifa->ifa_addr) + continue; + if (ifa->ifa_addr->sa_family != AF_PACKET) + continue; + + if (!strncmp(value, ifa->ifa_name, strlen(value)-1)) { + ret = config_network_type(type_key, tmpvalue, lxc_conf); + if (!ret) { + ret = set_network_link(link_key, ifa->ifa_name, lxc_conf); + if (ret) { + ERROR("failed to create matched ifnames"); + break; + } + } else { + ERROR("failed to create matched ifnames"); + break; + } + } + } + + freeifaddrs(ifaddr); /* free the dynamic memory */ + ifaddr = NULL; /* prevent use after free */ + + return ret; +} + static int config_network_link(const char *key, const char *value, struct lxc_conf *lxc_conf) { struct lxc_netdev *netdev; + struct lxc_list * it; + int ret = 0; netdev = network_netdev(key, value, &lxc_conf->network); if (!netdev) return -1; - return network_ifname(&netdev->link, value); + if (value[strlen(value) - 1] == '+' && netdev->type == LXC_NET_PHYS) { + //get the last network list and remove it. + it = lxc_conf->network.prev; + if (((struct lxc_netdev *)(it->elem))->type != LXC_NET_PHYS) { + ERROR("lxc config cannot support string pattern matching for this link type"); + return -1; + } + + lxc_list_del(it); + free(it); + ret = create_matched_ifnames(value, lxc_conf); + + } else { + ret = network_ifname(&netdev->link, value); + } + + return ret; } static int config_network_name(const char *key, const char *value,