[lxc-devel] [lxc/master] Adds static routes feature
tomponline on Github
lxc-bot at linuxcontainers.org
Thu Apr 25 11:50:05 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 575 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190425/a5307ac3/attachment.bin>
-------------- next part --------------
From 14c538ef3532880ad5396ed8d914940302654246 Mon Sep 17 00:00:00 2001
From: tomponline <tomp at tomp.uk>
Date: Thu, 25 Apr 2019 12:47:17 +0100
Subject: [PATCH] conf: Adds network ipv4.route and ipv6.route config keys
Signed-off-by: tomponline <tomp at tomp.uk>
---
src/lxc/confile.c | 253 ++++++++++++++++++++++++++++++++++++++++
src/lxc/confile_utils.c | 28 +++++
src/lxc/network.h | 2 +
3 files changed, 283 insertions(+)
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 8f94635d1b..15997e1909 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -125,8 +125,10 @@ lxc_config_define(net_flags);
lxc_config_define(net_hwaddr);
lxc_config_define(net_ipv4_address);
lxc_config_define(net_ipv4_gateway);
+lxc_config_define(net_ipv4_route);
lxc_config_define(net_ipv6_address);
lxc_config_define(net_ipv6_gateway);
+lxc_config_define(net_ipv6_route);
lxc_config_define(net_link);
lxc_config_define(net_macvlan_mode);
lxc_config_define(net_mtu);
@@ -213,8 +215,10 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.net.hwaddr", set_config_net_hwaddr, get_config_net_hwaddr, clr_config_net_hwaddr, },
{ "lxc.net.ipv4.address", set_config_net_ipv4_address, get_config_net_ipv4_address, clr_config_net_ipv4_address, },
{ "lxc.net.ipv4.gateway", set_config_net_ipv4_gateway, get_config_net_ipv4_gateway, clr_config_net_ipv4_gateway, },
+ { "lxc.net.ipv4.route", set_config_net_ipv4_route, get_config_net_ipv4_route, clr_config_net_ipv4_route, },
{ "lxc.net.ipv6.address", set_config_net_ipv6_address, get_config_net_ipv6_address, clr_config_net_ipv6_address, },
{ "lxc.net.ipv6.gateway", set_config_net_ipv6_gateway, get_config_net_ipv6_gateway, clr_config_net_ipv6_gateway, },
+ { "lxc.net.ipv6.route", set_config_net_ipv6_route, get_config_net_ipv6_route, clr_config_net_ipv6_route, },
{ "lxc.net.link", set_config_net_link, get_config_net_link, clr_config_net_link, },
{ "lxc.net.macvlan.mode", set_config_net_macvlan_mode, get_config_net_macvlan_mode, clr_config_net_macvlan_mode, },
{ "lxc.net.mtu", set_config_net_mtu, get_config_net_mtu, clr_config_net_mtu, },
@@ -626,6 +630,87 @@ static int set_config_net_ipv4_gateway(const char *key, const char *value,
return 0;
}
+static int set_config_net_ipv4_route(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ struct lxc_netdev *netdev = data;
+ struct lxc_inetdev *inetdev;
+ struct lxc_list *list;
+ char *cursor, *slash;
+ char *addr = NULL, *netmask = NULL;
+
+ if (lxc_config_value_empty(value))
+ return clr_config_net_ipv4_route(key, lxc_conf, data);
+
+ if (!netdev)
+ return -1;
+
+ inetdev = malloc(sizeof(*inetdev));
+ if (!inetdev)
+ return -1;
+ memset(inetdev, 0, sizeof(*inetdev));
+
+ list = malloc(sizeof(*list));
+ if (!list) {
+ free(inetdev);
+ return -1;
+ }
+
+ lxc_list_init(list);
+ list->elem = inetdev;
+
+ addr = strdup(value);
+ if (!addr) {
+ free(inetdev);
+ free(list);
+ return -1;
+ }
+
+ slash = strstr(addr, "/");
+ if (!slash) {
+ SYSERROR("Invalid ipv4 route \"%s\"", value);
+ free(inetdev);
+ free(addr);
+ free(list);
+ return -1;
+ }
+
+ *slash = '\0';
+ netmask = slash + 1;
+
+ if (!netmask) {
+ SYSERROR("Invalid ipv4 route \"%s\"", value);
+ free(inetdev);
+ free(list);
+ free(addr);
+ return -1;
+ }
+
+ ret = lxc_safe_uint(netmask, &inetdev->prefix);
+ if (ret < 0 || (inetdev->prefix < 0 || inetdev->prefix > 32)) {
+ SYSERROR("Invalid ipv4 route \"%s\"", value);
+ free(inetdev);
+ free(addr);
+ free(list);
+ return -1;
+ }
+
+ ret = inet_pton(AF_INET, addr, &inetdev->addr);
+ if (!ret || ret < 0) {
+ SYSERROR("Invalid ipv4 route \"%s\"", value);
+ free(inetdev);
+ free(addr);
+ free(list);
+ return -1;
+ }
+
+ lxc_list_add_tail(&netdev->ipv4_routes, list);
+ free(addr);
+
+ return 0;
+}
+
static int set_config_net_ipv6_address(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@@ -730,6 +815,78 @@ static int set_config_net_ipv6_gateway(const char *key, const char *value,
return 0;
}
+static int set_config_net_ipv6_route(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret;
+ struct lxc_netdev *netdev = data;
+ struct lxc_inet6dev *inet6dev;
+ struct lxc_list *list;
+ char *slash, *valdup, *netmask;
+
+ if (lxc_config_value_empty(value))
+ return clr_config_net_ipv6_route(key, lxc_conf, data);
+
+ if (!netdev)
+ return -1;
+
+ inet6dev = malloc(sizeof(*inet6dev));
+ if (!inet6dev)
+ return -1;
+ memset(inet6dev, 0, sizeof(*inet6dev));
+
+ list = malloc(sizeof(*list));
+ if (!list) {
+ free(inet6dev);
+ return -1;
+ }
+
+ lxc_list_init(list);
+ list->elem = inet6dev;
+
+ valdup = strdup(value);
+ if (!valdup) {
+ free(list);
+ free(inet6dev);
+ return -1;
+ }
+
+ slash = strstr(valdup, "/");
+ if (!slash) {
+ SYSERROR("Invalid ipv6 route \"%s\"", value);
+ free(list);
+ free(inet6dev);
+ free(valdup);
+ return -1;
+ }
+
+ *slash = '\0';
+ netmask = slash + 1;
+
+ ret = lxc_safe_uint(netmask, &inet6dev->prefix);
+ if (ret < 0 || (inet6dev->prefix < 0 || inet6dev->prefix > 128)) {
+ SYSERROR("Invalid ipv6 route \"%s\"", value);
+ free(list);
+ free(inet6dev);
+ free(valdup);
+ return -1;
+ }
+
+ ret = inet_pton(AF_INET6, valdup, &inet6dev->addr);
+ if (!ret || ret < 0) {
+ SYSERROR("Invalid ipv6 route \"%s\"", valdup);
+ free(list);
+ free(inet6dev);
+ free(valdup);
+ return -1;
+ }
+
+ lxc_list_add_tail(&netdev->ipv6_routes, list);
+ free(valdup);
+
+ return 0;
+}
+
static int set_config_net_script_up(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@@ -4848,6 +5005,24 @@ static int clr_config_net_ipv4_address(const char *key,
return 0;
}
+static int clr_config_net_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->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)
{
@@ -4880,6 +5055,24 @@ static int clr_config_net_ipv6_address(const char *key,
return 0;
}
+static int clr_config_net_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->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)
{
@@ -5224,6 +5417,36 @@ static int get_config_net_ipv4_address(const char *key, char *retv, int inlen,
return fulllen;
}
+static int get_config_net_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 -1;
+
+ listlen = lxc_list_len(&netdev->ipv4_routes);
+
+ lxc_list_for_each(it, &netdev->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)
{
@@ -5280,6 +5503,36 @@ static int get_config_net_ipv6_address(const char *key, char *retv, int inlen,
return fulllen;
}
+static int get_config_net_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 -1;
+
+ listlen = lxc_list_len(&netdev->ipv6_routes);
+
+ lxc_list_for_each(it, &netdev->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;
diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c
index 50777c4481..806b9135d7 100644
--- a/src/lxc/confile_utils.c
+++ b/src/lxc/confile_utils.c
@@ -196,7 +196,9 @@ struct lxc_netdev *lxc_network_add(struct lxc_list *networks, int idx, bool tail
memset(netdev, 0, sizeof(*netdev));
lxc_list_init(&netdev->ipv4);
+ lxc_list_init(&netdev->ipv4_routes);
lxc_list_init(&netdev->ipv6);
+ lxc_list_init(&netdev->ipv6_routes);
/* give network a unique index */
netdev->idx = idx;
@@ -359,6 +361,13 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
TRACE("ipv4 addr: %s", bufinet4);
}
+ lxc_list_for_each_safe(cur, &netdev->ipv4_routes, next) {
+ inet4dev = cur->elem;
+ inet_ntop(AF_INET, &inet4dev->addr, bufinet4,
+ sizeof(bufinet4));
+ TRACE("ipv4 route: %s/%u", bufinet4, inet4dev->prefix);
+ }
+
TRACE("ipv6 gateway auto: %s",
netdev->ipv6_gateway_auto ? "true" : "false");
@@ -374,6 +383,13 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
sizeof(bufinet6));
TRACE("ipv6 addr: %s", bufinet6);
}
+
+ lxc_list_for_each_safe(cur, &netdev->ipv6_routes, next) {
+ inet6dev = cur->elem;
+ inet_ntop(AF_INET6, &inet6dev->addr, bufinet6,
+ sizeof(bufinet6));
+ TRACE("ipv6 route: %s/%u", bufinet6, inet6dev->prefix);
+ }
}
}
}
@@ -394,6 +410,12 @@ static void lxc_free_netdev(struct lxc_netdev *netdev)
free(cur);
}
+ lxc_list_for_each_safe(cur, &netdev->ipv4_routes, next) {
+ lxc_list_del(cur);
+ free(cur->elem);
+ free(cur);
+ }
+
free(netdev->ipv6_gateway);
lxc_list_for_each_safe(cur, &netdev->ipv6, next) {
lxc_list_del(cur);
@@ -401,6 +423,12 @@ static void lxc_free_netdev(struct lxc_netdev *netdev)
free(cur);
}
+ lxc_list_for_each_safe(cur, &netdev->ipv6_routes, next) {
+ lxc_list_del(cur);
+ free(cur->elem);
+ free(cur);
+ }
+
free(netdev);
}
diff --git a/src/lxc/network.h b/src/lxc/network.h
index ef1b41b897..43ddf333d5 100644
--- a/src/lxc/network.h
+++ b/src/lxc/network.h
@@ -170,8 +170,10 @@ struct lxc_netdev {
struct lxc_list ipv6;
bool ipv4_gateway_auto;
struct in_addr *ipv4_gateway;
+ struct lxc_list ipv4_routes;
bool ipv6_gateway_auto;
struct in6_addr *ipv6_gateway;
+ struct lxc_list ipv6_routes;
char *upscript;
char *downscript;
};
More information about the lxc-devel
mailing list