summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-08-21 09:06:28 -0400
committerLennart Poettering <lennart@poettering.net>2016-08-21 15:06:28 +0200
commit47d2d30d83eb7494593181915967be38451d72f1 (patch)
treebd052c93846cb3ebf1342854c2de8c2be80b4d91
parente3fc2b025e6277c913e34bbee7c60d2561adcc48 (diff)
networkd: limit the number of routes to the kernel limit (#4007)
Fixes #3922.
-rw-r--r--src/network/networkd-route.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index b197a5da6b..6f60ee5e31 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -26,10 +26,37 @@
#include "parse-util.h"
#include "set.h"
#include "string-util.h"
+#include "sysctl-util.h"
#include "util.h"
-#define ROUTES_PER_LINK_MAX 2048U
-#define STATIC_ROUTES_PER_NETWORK_MAX 1024U
+#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
+
+static unsigned routes_max(void) {
+ static thread_local unsigned cached = 0;
+
+ _cleanup_free_ char *s4 = NULL, *s6 = NULL;
+ unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY;
+
+ if (cached > 0)
+ return cached;
+
+ if (sysctl_read("net/ipv4/route/max_size", &s4) >= 0) {
+ truncate_nl(s4);
+ if (safe_atou(s4, &val4) >= 0 &&
+ val4 == 2147483647U)
+ /* This is the default "no limit" value in the kernel */
+ val4 = ROUTES_DEFAULT_MAX_PER_FAMILY;
+ }
+
+ if (sysctl_read("net/ipv6/route/max_size", &s6) >= 0) {
+ truncate_nl(s6);
+ (void) safe_atou(s6, &val6);
+ }
+
+ cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) +
+ MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6);
+ return cached;
+}
int route_new(Route **ret) {
_cleanup_route_free_ Route *route = NULL;
@@ -67,7 +94,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
}
}
- if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX)
+ if (network->n_static_routes >= routes_max())
return -E2BIG;
r = route_new(&route);
@@ -484,7 +511,7 @@ int route_configure(
assert(route->family == AF_INET || route->family == AF_INET6);
if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 &&
- set_size(link->routes) >= ROUTES_PER_LINK_MAX)
+ set_size(link->routes) >= routes_max())
return -E2BIG;
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,