]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: also enforce limit on total number of address/routes
authorLennart Poettering <lennart@poettering.net>
Fri, 3 Jun 2016 17:51:48 +0000 (19:51 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 3 Jun 2016 17:53:43 +0000 (19:53 +0200)
This covers the address/routers acquire dynamically.

src/network/networkd-address.c
src/network/networkd-route.c
src/network/networkd-route.h

index 4cdb500bd67a3dd62cd92a466aa685e14c261eac..9275ccf9a953158a9783e1ef2b1e0ddb93b44a98 100644 (file)
@@ -32,6 +32,7 @@
 #include "utf8.h"
 #include "util.h"
 
+#define ADDRESSES_PER_LINK_MAX 2048U
 #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
 
 int address_new(Address **ret) {
@@ -392,31 +393,38 @@ int address_drop(Address *address) {
         return 0;
 }
 
-int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
-        Address address = {}, *existing;
+int address_get(Link *link,
+                int family,
+                const union in_addr_union *in_addr,
+                unsigned char prefixlen,
+                Address **ret) {
+
+        Address address, *existing;
 
         assert(link);
         assert(in_addr);
-        assert(ret);
 
-        address.family = family;
-        address.in_addr = *in_addr;
-        address.prefixlen = prefixlen;
+        address = (Address) {
+                .family = family,
+                .in_addr = *in_addr,
+                .prefixlen = prefixlen,
+        };
 
         existing = set_get(link->addresses, &address);
         if (existing) {
-                *ret = existing;
-
+                if (ret)
+                        *ret = existing;
                 return 1;
-        } else {
-                existing = set_get(link->addresses_foreign, &address);
-                if (!existing)
-                        return -ENOENT;
         }
 
-        *ret = existing;
+        existing = set_get(link->addresses_foreign, &address);
+        if (existing) {
+                if (ret)
+                        *ret = existing;
+                return 0;
+        }
 
-        return 0;
+        return -ENOENT;
 }
 
 int address_remove(
@@ -518,7 +526,12 @@ static int address_acquire(Link *link, Address *original, Address **ret) {
         return 0;
 }
 
-int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update) {
+int address_configure(
+                Address *address,
+                Link *link,
+                sd_netlink_message_handler_t callback,
+                bool update) {
+
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
@@ -529,6 +542,11 @@ int address_configure(Address *address, Link *link, sd_netlink_message_handler_t
         assert(link->manager);
         assert(link->manager->rtnl);
 
+        /* If this is a new address, then refuse adding more than the limit */
+        if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 &&
+            set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
+                return -E2BIG;
+
         r = address_acquire(link, address, &address);
         if (r < 0)
                 return r;
index 1b480385c68a5711cf40a3febb8b9aca0bd6f730..0d2a5bb83d21f37a5bef59830f2a1a21e0265277 100644 (file)
@@ -28,6 +28,7 @@
 #include "string-util.h"
 #include "util.h"
 
+#define ROUTES_PER_LINK_MAX 2048U
 #define STATIC_ROUTES_PER_NETWORK_MAX 1024U
 
 int route_new(Route **ret) {
@@ -187,39 +188,42 @@ static const struct hash_ops route_hash_ops = {
 
 int route_get(Link *link,
               int family,
-              union in_addr_union *dst,
+              const union in_addr_union *dst,
               unsigned char dst_prefixlen,
               unsigned char tos,
               uint32_t priority,
               unsigned char table,
               Route **ret) {
-        Route route = {
+
+        Route route, *existing;
+
+        assert(link);
+        assert(dst);
+
+        route = (Route) {
                 .family = family,
+                .dst = *dst,
                 .dst_prefixlen = dst_prefixlen,
                 .tos = tos,
                 .priority = priority,
                 .table = table,
-        }, *existing;
-
-        assert(link);
-        assert(dst);
-        assert(ret);
-
-        route.dst = *dst;
+        };
 
         existing = set_get(link->routes, &route);
         if (existing) {
-                *ret = existing;
+                if (ret)
+                        *ret = existing;
                 return 1;
-        } else {
-                existing = set_get(link->routes_foreign, &route);
-                if (!existing)
-                        return -ENOENT;
         }
 
-        *ret = existing;
+        existing = set_get(link->routes_foreign, &route);
+        if (existing) {
+                if (ret)
+                        *ret = existing;
+                return 0;
+        }
 
-        return 0;
+        return -ENOENT;
 }
 
 static int route_add_internal(Link *link, Set **routes,
@@ -460,8 +464,11 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
         return 1;
 }
 
-int route_configure(Route *route, Link *link,
-                    sd_netlink_message_handler_t callback) {
+int route_configure(
+                Route *route,
+                Link *link,
+                sd_netlink_message_handler_t callback) {
+
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
         usec_t lifetime;
@@ -473,6 +480,10 @@ int route_configure(Route *route, Link *link,
         assert(link->ifindex > 0);
         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(route->link->routes) >= ROUTES_PER_LINK_MAX)
+                return -E2BIG;
+
         r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
                                       RTM_NEWROUTE, route->family,
                                       route->protocol);
index 39de8363edd32a2f93c89db82a4e88fc77681101..ddc3e1da57d07555fac37e8eb678228f16dd6447 100644 (file)
@@ -57,7 +57,7 @@ void route_free(Route *route);
 int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
 int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback);
 
-int route_get(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
+int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
 int route_add(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
 int route_add_foreign(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
 int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);