From 1274b6c68759be1b06140d13e5ec3a0ce3967e94 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 5 Sep 2017 17:41:34 +0200 Subject: [PATCH] ip-address-access: minimize IP address lists Let's drop redundant items from the IP address list after parsing. Let's also mask out redundant bits hidden by the prefixlength. --- src/basic/in-addr-util.c | 24 ++++++++++++++++++++++++ src/basic/in-addr-util.h | 1 + src/core/dbus-cgroup.c | 2 ++ src/core/ip-address-access.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/core/ip-address-access.h | 2 ++ 5 files changed, 71 insertions(+) diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index 94f0625..e27faba 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -465,6 +465,30 @@ int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen) return -EAFNOSUPPORT; } +int in_addr_prefix_covers(int family, + const union in_addr_union *prefix, + unsigned char prefixlen, + const union in_addr_union *address) { + + union in_addr_union masked_prefix, masked_address; + int r; + + assert(prefix); + assert(address); + + masked_prefix = *prefix; + r = in_addr_mask(family, &masked_prefix, prefixlen); + if (r < 0) + return r; + + masked_address = *address; + r = in_addr_mask(family, &masked_address, prefixlen); + if (r < 0) + return r; + + return in_addr_equal(family, &masked_prefix, &masked_address); +} + int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) { uint8_t u; int r; diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index bb57c08..d129bf5 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -60,6 +60,7 @@ struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned cha int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen); int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask); int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen); +int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address); int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret); int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 3bb4108..42381ec 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -1288,6 +1288,8 @@ int bus_cgroup_set_property( if (r < 0) return r; + *list = ip_address_access_reduce(*list); + if (mode != UNIT_CHECK) { _cleanup_free_ char *buf = NULL; _cleanup_fclose_ FILE *f = NULL; diff --git a/src/core/ip-address-access.c b/src/core/ip-address-access.c index 6a89bb2..18d2870 100644 --- a/src/core/ip-address-access.c +++ b/src/core/ip-address-access.c @@ -148,6 +148,8 @@ int config_parse_ip_address_access( a = NULL; } + *list = ip_address_access_reduce(*list); + return 0; } @@ -163,3 +165,43 @@ IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) { return NULL; } + +IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first) { + IPAddressAccessItem *a, *b, *tmp; + int r; + + /* Drops all entries from the list that are covered by another entry in full, thus removing all redundant + * entries. */ + + LIST_FOREACH_SAFE(items, a, tmp, first) { + + /* Drop irrelevant bits */ + (void) in_addr_mask(a->family, &a->address, a->prefixlen); + + LIST_FOREACH(items, b, first) { + + if (a == b) + continue; + + if (a->family != b->family) + continue; + + if (b->prefixlen > a->prefixlen) + continue; + + r = in_addr_prefix_covers(b->family, + &b->address, + b->prefixlen, + &a->address); + if (r <= 0) + continue; + + /* b covers a fully, then let's drop a */ + + LIST_REMOVE(items, first, a); + free(a); + } + } + + return first; +} diff --git a/src/core/ip-address-access.h b/src/core/ip-address-access.h index eea20b4..9aeab1f 100644 --- a/src/core/ip-address-access.h +++ b/src/core/ip-address-access.h @@ -34,3 +34,5 @@ struct IPAddressAccessItem { int config_parse_ip_address_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first); + +IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first); -- 2.7.4