From d4a7da4632329d06d7b25d36133d4b6fa8f42b7a Mon Sep 17 00:00:00 2001 From: tomponline Date: Thu, 25 Apr 2019 12:47:17 +0100 Subject: [PATCH] network: Adds support host side veth device static routes Adds the following new config keys: lxc.net.[i].veth.ipv4.route lxc.net.[i].veth.ipv6.route E.g. lxc.net.0.veth.ipv4.route = 192.0.2.1/32 lxc.net.0.veth.ipv4.route = 192.0.3.0/24 lxc.net.0.veth.ipv6.route = 2001:db8::1/128 lxc.net.0.veth.ipv6.route = 2001:db8:2::/64 Signed-off-by: tomponline --- doc/api-extensions.md | 6 + doc/lxc.container.conf.sgml.in | 16 ++- src/lxc/api_extensions.h | 1 + src/lxc/confile.c | 236 +++++++++++++++++++++++++++++++++ src/lxc/confile_utils.c | 38 +++++- src/lxc/network.c | 70 ++++++++-- src/lxc/network.h | 6 +- src/tests/parse_config_file.c | 20 +++ 8 files changed, 375 insertions(+), 18 deletions(-) diff --git a/doc/api-extensions.md b/doc/api-extensions.md index ae9cced1c..14a572352 100644 --- a/doc/api-extensions.md +++ b/doc/api-extensions.md @@ -32,3 +32,9 @@ until a reboot succeeded. It takes a timeout argument. When set to `> 0` This adds support for injecting and removing mounts into/from a running containers. Two new API functions `mount()` and `umount()` are added. They mirror the current mount and umount API of the kernel. + +## network\_veth\_routes + +This introduces the `lxc.net.[i].veth.ipv4.route` and `lxc.net.[i].veth.ipv6.route` properties +on `veth` type network interfaces. This allows adding static routes on host to the container's +network interface. diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in index 4ed65f63a..3b3dd6dde 100644 --- a/doc/lxc.container.conf.sgml.in +++ b/doc/lxc.container.conf.sgml.in @@ -375,7 +375,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA The only allowed values are 0 and 1. Set this to 1 to destroy a - container on shutdown. + container on shutdown. @@ -459,6 +459,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA the option (except for unprivileged containers where this option is ignored for security reasons). + + Static routes can be added on the host pointing to the container using the + and + options. + Several lines specify several routes. + The route is in format x.y.z.t/m, eg. 192.168.1.0/24. @@ -855,7 +861,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA When manually specifying a size for the log file the value should be a power of 2 when converted to bytes. Valid size prefixes are 'KB', 'MB', 'GB'. (Note that all conversions are based on multiples - of 1024. That means 'KB' == 'KiB', 'MB' == 'MiB', 'GB' == 'GiB'. + of 1024. That means 'KB' == 'KiB', 'MB' == 'MiB', 'GB' == 'GiB'. Additionally, the case of the suffix is ignored, i.e. 'kB', 'KB' and 'Kb' are treated equally.) @@ -1629,7 +1635,7 @@ dev/null proc/kcore none bind,relative 0 0 - To inherit the namespace from another container set the + To inherit the namespace from another container set the to the name of the container, e.g. . @@ -1708,7 +1714,7 @@ dev/null proc/kcore none bind,relative 0 0 - Specify the kernel parameters to be set. The parameters available + Specify the kernel parameters to be set. The parameters available are those listed under /proc/sys/. Note that not all sysctls are namespaced. Changing Non-namespaced sysctls will cause the system-wide setting to be modified. @@ -1716,7 +1722,7 @@ dev/null proc/kcore none bind,relative 0 0 sysctl 8 . - If used with no value, lxc will clear the parameters specified up + If used with no value, lxc will clear the parameters specified up to this point. diff --git a/src/lxc/api_extensions.h b/src/lxc/api_extensions.h index e87c8e924..529f19863 100644 --- a/src/lxc/api_extensions.h +++ b/src/lxc/api_extensions.h @@ -44,6 +44,7 @@ static char *api_extensions[] = { "mount_injection_file", "seccomp_allow_nesting", "seccomp_notify", + "network_veth_routes", }; static size_t nr_api_extensions = sizeof(api_extensions) / sizeof(*api_extensions); diff --git a/src/lxc/confile.c b/src/lxc/confile.c index da5e45ce3..efcb705aa 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -137,6 +137,8 @@ lxc_config_define(net_script_down); lxc_config_define(net_script_up); lxc_config_define(net_type); lxc_config_define(net_veth_pair); +lxc_config_define(net_veth_ipv4_route); +lxc_config_define(net_veth_ipv6_route); lxc_config_define(net_vlan_id); lxc_config_define(no_new_privs); lxc_config_define(personality); @@ -226,6 +228,8 @@ static struct lxc_config_t config_jump_table[] = { { "lxc.net.type", set_config_net_type, get_config_net_type, clr_config_net_type, }, { "lxc.net.vlan.id", set_config_net_vlan_id, get_config_net_vlan_id, clr_config_net_vlan_id, }, { "lxc.net.veth.pair", set_config_net_veth_pair, get_config_net_veth_pair, clr_config_net_veth_pair, }, + { "lxc.net.veth.ipv4.route", set_config_net_veth_ipv4_route, get_config_net_veth_ipv4_route, clr_config_net_veth_ipv4_route, }, + { "lxc.net.veth.ipv6.route", set_config_net_veth_ipv6_route, get_config_net_veth_ipv6_route, clr_config_net_veth_ipv6_route, }, { "lxc.net.", set_config_net_nic, get_config_net_nic, clr_config_net_nic, }, { "lxc.net", set_config_net, get_config_net, clr_config_net, }, { "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, }, @@ -289,6 +293,8 @@ static int set_config_net_type(const char *key, const char *value, if (!strcmp(value, "veth")) { netdev->type = LXC_NET_VETH; + lxc_list_init(&netdev->priv.veth_attr.ipv4_routes); + lxc_list_init(&netdev->priv.veth_attr.ipv6_routes); } else if (!strcmp(value, "macvlan")) { netdev->type = LXC_NET_MACVLAN; lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode, @@ -629,6 +635,69 @@ static int set_config_net_ipv4_gateway(const char *key, const char *value, return 0; } +static int set_config_net_veth_ipv4_route(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) +{ + __do_free char *valdup = NULL; + __do_free struct lxc_inetdev *inetdev = NULL; + __do_free struct lxc_list *list = NULL; + int ret; + char *netmask, *slash; + struct lxc_netdev *netdev = data; + + if (lxc_config_value_empty(value)) + return clr_config_net_veth_ipv4_route(key, lxc_conf, data); + + if (!netdev) + return minus_one_set_errno(EINVAL); + + if (netdev->type != LXC_NET_VETH) { + SYSERROR("Invalid ipv4 route \"%s\", can only be used with veth network", value); + return minus_one_set_errno(EINVAL); + } + + inetdev = malloc(sizeof(*inetdev)); + if (!inetdev) + return -1; + memset(inetdev, 0, sizeof(*inetdev)); + + list = malloc(sizeof(*list)); + if (!list) + return -1; + + lxc_list_init(list); + list->elem = inetdev; + + valdup = strdup(value); + if (!valdup) + return -1; + + slash = strchr(valdup, '/'); + if (!slash) + return minus_one_set_errno(EINVAL); + + *slash = '\0'; + slash++; + if (*slash == '\0') + return minus_one_set_errno(EINVAL); + + netmask = slash; + + ret = lxc_safe_uint(netmask, &inetdev->prefix); + if (ret < 0 || inetdev->prefix > 32) + return minus_one_set_errno(EINVAL); + + ret = inet_pton(AF_INET, valdup, &inetdev->addr); + if (!ret || ret < 0) + return minus_one_set_errno(EINVAL); + + lxc_list_add_tail(&netdev->priv.veth_attr.ipv4_routes, list); + move_ptr(inetdev); + move_ptr(list); + + return 0; +} + static int set_config_net_ipv6_address(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { @@ -733,6 +802,69 @@ static int set_config_net_ipv6_gateway(const char *key, const char *value, return 0; } +static int set_config_net_veth_ipv6_route(const char *key, const char *value, + struct lxc_conf *lxc_conf, void *data) +{ + __do_free char *valdup; + __do_free struct lxc_inet6dev *inet6dev; + __do_free struct lxc_list *list; + int ret; + char *netmask, *slash; + struct lxc_netdev *netdev = data; + + if (lxc_config_value_empty(value)) + return clr_config_net_veth_ipv6_route(key, lxc_conf, data); + + if (!netdev) + return minus_one_set_errno(EINVAL); + + if (netdev->type != LXC_NET_VETH) { + SYSERROR("Invalid ipv6 route \"%s\", can only be used with veth network", value); + return minus_one_set_errno(EINVAL); + } + + inet6dev = malloc(sizeof(*inet6dev)); + if (!inet6dev) + return -1; + memset(inet6dev, 0, sizeof(*inet6dev)); + + list = malloc(sizeof(*list)); + if (!list) + return -1; + + lxc_list_init(list); + list->elem = inet6dev; + + valdup = strdup(value); + if (!valdup) + return -1; + + slash = strchr(valdup, '/'); + if (!slash) + return minus_one_set_errno(EINVAL); + + *slash = '\0'; + slash++; + if (*slash == '\0') + return minus_one_set_errno(EINVAL); + + netmask = slash; + + ret = lxc_safe_uint(netmask, &inet6dev->prefix); + if (ret < 0 || inet6dev->prefix > 128) + return minus_one_set_errno(EINVAL); + + ret = inet_pton(AF_INET6, valdup, &inet6dev->addr); + if (!ret || ret < 0) + return minus_one_set_errno(EINVAL); + + lxc_list_add_tail(&netdev->priv.veth_attr.ipv6_routes, list); + move_ptr(inet6dev); + move_ptr(list); + + return 0; +} + static int set_config_net_script_up(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { @@ -4898,6 +5030,24 @@ static int clr_config_net_ipv4_address(const char *key, return 0; } +static int clr_config_net_veth_ipv4_route(const char *key, + struct lxc_conf *lxc_conf, void *data) +{ + struct lxc_netdev *netdev = data; + struct lxc_list *cur, *next; + + if (!netdev) + return -1; + + lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv4_routes, next) { + lxc_list_del(cur); + free(cur->elem); + free(cur); + } + + return 0; +} + static int clr_config_net_ipv6_gateway(const char *key, struct lxc_conf *lxc_conf, void *data) { @@ -4930,6 +5080,24 @@ static int clr_config_net_ipv6_address(const char *key, return 0; } +static int clr_config_net_veth_ipv6_route(const char *key, + struct lxc_conf *lxc_conf, void *data) +{ + struct lxc_netdev *netdev = data; + struct lxc_list *cur, *next; + + if (!netdev) + return -1; + + lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv6_routes, next) { + lxc_list_del(cur); + free(cur->elem); + free(cur); + } + + return 0; +} + static int get_config_net_nic(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { @@ -5274,6 +5442,39 @@ static int get_config_net_ipv4_address(const char *key, char *retv, int inlen, return fulllen; } +static int get_config_net_veth_ipv4_route(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) +{ + int len; + size_t listlen; + char buf[INET_ADDRSTRLEN]; + struct lxc_list *it; + int fulllen = 0; + struct lxc_netdev *netdev = data; + + if (!retv) + inlen = 0; + else + memset(retv, 0, inlen); + + if (!netdev) + return minus_one_set_errno(EINVAL); + + if (netdev->type != LXC_NET_VETH) + return 0; + + listlen = lxc_list_len(&netdev->priv.veth_attr.ipv4_routes); + + lxc_list_for_each(it, &netdev->priv.veth_attr.ipv4_routes) { + struct lxc_inetdev *i = it->elem; + inet_ntop(AF_INET, &i->addr, buf, sizeof(buf)); + strprint(retv, inlen, "%s/%u%s", buf, i->prefix, + (listlen-- > 1) ? "\n" : ""); + } + + return fulllen; +} + static int get_config_net_ipv6_gateway(const char *key, char *retv, int inlen, struct lxc_conf *c, void *data) { @@ -5330,6 +5531,39 @@ static int get_config_net_ipv6_address(const char *key, char *retv, int inlen, return fulllen; } +static int get_config_net_veth_ipv6_route(const char *key, char *retv, int inlen, + struct lxc_conf *c, void *data) +{ + int len; + size_t listlen; + char buf[INET6_ADDRSTRLEN]; + struct lxc_list *it; + int fulllen = 0; + struct lxc_netdev *netdev = data; + + if (!retv) + inlen = 0; + else + memset(retv, 0, inlen); + + if (!netdev) + return minus_one_set_errno(EINVAL); + + if (netdev->type != LXC_NET_VETH) + return 0; + + listlen = lxc_list_len(&netdev->priv.veth_attr.ipv6_routes); + + lxc_list_for_each(it, &netdev->priv.veth_attr.ipv6_routes) { + struct lxc_inet6dev *i = it->elem; + inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf)); + strprint(retv, inlen, "%s/%u%s", buf, i->prefix, + (listlen-- > 1) ? "\n" : ""); + } + + return fulllen; +} + int lxc_list_config_items(char *retv, int inlen) { size_t i; @@ -5463,6 +5697,8 @@ int lxc_list_net(struct lxc_conf *c, const char *key, char *retv, int inlen) switch (netdev->type) { case LXC_NET_VETH: strprint(retv, inlen, "veth.pair\n"); + strprint(retv, inlen, "veth.ipv4.route\n"); + strprint(retv, inlen, "veth.ipv6.route\n"); break; case LXC_NET_MACVLAN: strprint(retv, inlen, "macvlan.mode\n"); diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c index 50777c448..cfc23f312 100644 --- a/src/lxc/confile_utils.c +++ b/src/lxc/confile_utils.c @@ -317,7 +317,7 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) TRACE("type: none"); break; default: - ERROR("invalid network type %d", netdev->type); + ERROR("Invalid network type %d", netdev->type); return; } @@ -374,6 +374,28 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) sizeof(bufinet6)); TRACE("ipv6 addr: %s", bufinet6); } + + if (netdev->type == LXC_NET_VETH) { + lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv4_routes, next) { + inet4dev = cur->elem; + if (!inet_ntop(AF_INET, &inet4dev->addr, bufinet4, sizeof(bufinet4))) { + ERROR("Invalid ipv4 veth route"); + return; + } + + TRACE("ipv4 veth route: %s/%u", bufinet4, inet4dev->prefix); + } + + lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv6_routes, next) { + inet6dev = cur->elem; + if (!inet_ntop(AF_INET6, &inet6dev->addr, bufinet6, sizeof(bufinet6))) { + ERROR("Invalid ipv6 veth route"); + return; + } + + TRACE("ipv6 veth route: %s/%u", bufinet6, inet6dev->prefix); + } + } } } } @@ -401,6 +423,20 @@ static void lxc_free_netdev(struct lxc_netdev *netdev) free(cur); } + if (netdev->type == LXC_NET_VETH) { + lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv4_routes, next) { + lxc_list_del(cur); + free(cur->elem); + free(cur); + } + + lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv6_routes, next) { + lxc_list_del(cur); + free(cur->elem); + free(cur); + } + } + free(netdev); } diff --git a/src/lxc/network.c b/src/lxc/network.c index b49aae68c..a31544083 100644 --- a/src/lxc/network.c +++ b/src/lxc/network.c @@ -69,6 +69,44 @@ lxc_log_define(network, lxc); typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *); +static int lxc_setup_ipv4_routes(struct lxc_list *ip, int ifindex) +{ + struct lxc_list *iterator; + int err; + + lxc_list_for_each(iterator, ip) { + struct lxc_inetdev *inetdev = iterator->elem; + + err = lxc_ipv4_dest_add(ifindex, &inetdev->addr, inetdev->prefix); + if (err) { + SYSERROR("Failed to setup ipv4 route for network device " + "with ifindex %d", ifindex); + return minus_one_set_errno(-err); + } + } + + return 0; +} + +static int lxc_setup_ipv6_routes(struct lxc_list *ip, int ifindex) +{ + struct lxc_list *iterator; + int err; + + lxc_list_for_each(iterator, ip) { + struct lxc_inet6dev *inet6dev = iterator->elem; + + err = lxc_ipv6_dest_add(ifindex, &inet6dev->addr, inet6dev->prefix); + if (err) { + SYSERROR("Failed to setup ipv6 route for network device " + "with ifindex %d", ifindex); + return minus_one_set_errno(-err); + } + } + + return 0; +} + static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev) { int bridge_index, err; @@ -183,6 +221,18 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd goto out_delete; } + /* setup ipv4 routes on the host interface */ + if (lxc_setup_ipv4_routes(&netdev->priv.veth_attr.ipv4_routes, netdev->priv.veth_attr.ifindex)) { + ERROR("Failed to setup ipv4 routes for network device \"%s\"", veth1); + goto out_delete; + } + + /* setup ipv6 routes on the host interface */ + if (lxc_setup_ipv6_routes(&netdev->priv.veth_attr.ipv6_routes, netdev->priv.veth_attr.ifindex)) { + ERROR("Failed to setup ipv6 routes for network device \"%s\"", veth1); + goto out_delete; + } + if (netdev->upscript) { char *argv[] = { "veth", @@ -1780,7 +1830,7 @@ int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw) return ip_gateway_add(AF_INET6, ifindex, gw); } -static int ip_route_dest_add(int family, int ifindex, void *dest) +static int ip_route_dest_add(int family, int ifindex, void *dest, unsigned int netmask) { int addrlen, err; struct nl_handler nlh; @@ -1815,7 +1865,7 @@ static int ip_route_dest_add(int family, int ifindex, void *dest) rt->rtm_scope = RT_SCOPE_LINK; rt->rtm_protocol = RTPROT_BOOT; rt->rtm_type = RTN_UNICAST; - rt->rtm_dst_len = addrlen * 8; + rt->rtm_dst_len = netmask; err = -EINVAL; if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen)) @@ -1830,14 +1880,14 @@ out: return err; } -int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest) +int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest, unsigned int netmask) { - return ip_route_dest_add(AF_INET, ifindex, dest); + return ip_route_dest_add(AF_INET, ifindex, dest, netmask); } -int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest) +int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest, unsigned int netmask) { - return ip_route_dest_add(AF_INET6, ifindex, dest); + return ip_route_dest_add(AF_INET6, ifindex, dest, netmask); } bool is_ovs_bridge(const char *bridge) @@ -2807,7 +2857,7 @@ static int setup_ipv4_addr(struct lxc_list *ip, int ifindex) if (err) { errno = -err; SYSERROR("Failed to setup ipv4 address for network device " - "with eifindex %d", ifindex); + "with ifindex %d", ifindex); return -1; } } @@ -2829,7 +2879,7 @@ static int setup_ipv6_addr(struct lxc_list *ip, int ifindex) if (err) { errno = -err; SYSERROR("Failed to setup ipv6 address for network device " - "with eifindex %d", ifindex); + "with ifindex %d", ifindex); return -1; } } @@ -2988,7 +3038,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway); if (err) { - err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway); + err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway, 32); if (err) { errno = -err; SYSERROR("Failed to add ipv4 dest for network device \"%s\"", @@ -3027,7 +3077,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway); if (err) { - err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway); + err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway, 128); if (err) { errno = -err; SYSERROR("Failed to add ipv6 dest for network device \"%s\"", diff --git a/src/lxc/network.h b/src/lxc/network.h index ef1b41b89..1084cae2d 100644 --- a/src/lxc/network.h +++ b/src/lxc/network.h @@ -95,6 +95,8 @@ struct ifla_veth { char pair[IFNAMSIZ]; char veth1[IFNAMSIZ]; int ifindex; + struct lxc_list ipv4_routes; + struct lxc_list ipv6_routes; }; struct ifla_vlan { @@ -221,8 +223,8 @@ extern int lxc_ipv4_addr_get(int ifindex, struct in_addr **res); extern int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res); /* Set a destination route to an interface. */ -extern int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest); -extern int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest); +extern int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest, unsigned int netmask); +extern int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest, unsigned int netmask); /* Set default route. */ extern int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw); diff --git a/src/tests/parse_config_file.c b/src/tests/parse_config_file.c index b8b71c8e1..63692264d 100644 --- a/src/tests/parse_config_file.c +++ b/src/tests/parse_config_file.c @@ -134,6 +134,16 @@ static int set_and_clear_complete_netdev(struct lxc_container *c) return -1; } + if (!c->set_config_item(c, "lxc.net.1.veth.ipv4.route", "192.0.2.1/32")) { + lxc_error("%s\n", "lxc.net.1.veth.ipv4.route"); + return -1; + } + + if (!c->set_config_item(c, "lxc.net.1.veth.ipv6.route", "2001:db8::1/128")) { + lxc_error("%s\n", "lxc.net.1.veth.ipv6.route"); + return -1; + } + if (!c->set_config_item(c, "lxc.net.1.hwaddr", "52:54:00:80:7a:5d")) { lxc_error("%s\n", "lxc.net.1.hwaddr"); @@ -695,6 +705,16 @@ int main(int argc, char *argv[]) goto non_test_error; } + if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.ipv4.route", "192.0.2.1/32", tmpf, true, "veth")) { + lxc_error("%s\n", "lxc.net.0.veth.ipv4.route"); + return -1; + } + + if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.ipv6.route", "2001:db8::1/128", tmpf, true, "veth")) { + lxc_error("%s\n", "lxc.net.0.veth.ipv6.route"); + return -1; + } + if (set_get_compare_clear_save_load(c, "lxc.net.0.script.up", "/some/up/path", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.script.up"); goto non_test_error; -- 2.39.2