[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