From 84ebe6f01381c21b88e37e856956c9c9ee6781d6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 10 Sep 2021 13:58:28 +0900 Subject: [PATCH] core: replace IPAddressAccessItem with struct in_addr_prefix Previously, if a unit file which contains n IPAddressAllow/Deny= lines, then the computational order of parsing the file was O(n^3), as ip_address_access_reduce(), whose order is O(n^2), is called for each line. By replacing in_addr_prefix related functions, now the computational order is O(n log n). Fixes #20680. --- src/analyze/analyze-security.c | 8 +- src/core/bpf-firewall.c | 34 +++-- src/core/cgroup.c | 27 ++-- src/core/cgroup.h | 9 +- src/core/dbus-cgroup.c | 70 +++++---- src/core/ip-address-access.c | 208 -------------------------- src/core/ip-address-access.h | 25 ---- src/core/load-fragment-gperf.gperf.in | 5 +- src/core/manager.h | 1 - src/core/meson.build | 2 - src/core/unit.h | 1 + src/test/test-bpf-firewall.c | 45 ++++-- 12 files changed, 123 insertions(+), 312 deletions(-) delete mode 100644 src/core/ip-address-access.c delete mode 100644 src/core/ip-address-access.h diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c index c674961001..400eebbda8 100644 --- a/src/analyze/analyze-security.c +++ b/src/analyze/analyze-security.c @@ -11,7 +11,7 @@ #include "bus-util.h" #include "env-util.h" #include "format-table.h" -#include "in-addr-util.h" +#include "in-addr-prefix-util.h" #include "locale-util.h" #include "macro.h" #include "manager.h" @@ -2582,10 +2582,10 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security return log_oom(); } - IPAddressAccessItem *i; + struct in_addr_prefix *i; bool deny_ipv4 = false, deny_ipv6 = false; - LIST_FOREACH(items, i, g->ip_address_deny) { + SET_FOREACH(i, g->ip_address_deny) { if (i->family == AF_INET && i->prefixlen == 0) deny_ipv4 = true; else if (i->family == AF_INET6 && i->prefixlen == 0) @@ -2594,7 +2594,7 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security info->ip_address_deny_all = deny_ipv4 && deny_ipv6; info->ip_address_allow_localhost = info->ip_address_allow_other = false; - LIST_FOREACH(items, i, g->ip_address_allow) { + SET_FOREACH(i, g->ip_address_allow) { if (in_addr_is_localhost(i->family, &i->address)) info->ip_address_allow_localhost = true; else diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index 9317edeb4c..d23b43bcb2 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -18,7 +18,7 @@ #include "bpf-firewall.h" #include "bpf-program.h" #include "fd-util.h" -#include "ip-address-access.h" +#include "in-addr-prefix-util.h" #include "memory-util.h" #include "missing_syscall.h" #include "unit.h" @@ -335,13 +335,13 @@ static int bpf_firewall_compile_bpf( return 0; } -static int bpf_firewall_count_access_items(IPAddressAccessItem *list, size_t *n_ipv4, size_t *n_ipv6) { - IPAddressAccessItem *a; +static int bpf_firewall_count_access_items(Set *prefixes, size_t *n_ipv4, size_t *n_ipv6) { + struct in_addr_prefix *a; assert(n_ipv4); assert(n_ipv6); - LIST_FOREACH(items, a, list) { + SET_FOREACH(a, prefixes) switch (a->family) { case AF_INET: @@ -355,26 +355,25 @@ static int bpf_firewall_count_access_items(IPAddressAccessItem *list, size_t *n_ default: return -EAFNOSUPPORT; } - } return 0; } static int bpf_firewall_add_access_items( - IPAddressAccessItem *list, + Set *prefixes, int ipv4_map_fd, int ipv6_map_fd, int verdict) { struct bpf_lpm_trie_key *key_ipv4, *key_ipv6; + struct in_addr_prefix *a; uint64_t value = verdict; - IPAddressAccessItem *a; int r; key_ipv4 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t)); key_ipv6 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t) * 4); - LIST_FOREACH(items, a, list) { + SET_FOREACH(a, prefixes) switch (a->family) { case AF_INET: @@ -400,7 +399,6 @@ static int bpf_firewall_add_access_items( default: return -EAFNOSUPPORT; } - } return 0; } @@ -414,7 +412,6 @@ static int bpf_firewall_prepare_access_maps( _cleanup_close_ int ipv4_map_fd = -1, ipv6_map_fd = -1; size_t n_ipv4 = 0, n_ipv6 = 0; - IPAddressAccessItem *list; Unit *p; int r; @@ -424,18 +421,29 @@ static int bpf_firewall_prepare_access_maps( for (p = u; p; p = UNIT_GET_SLICE(p)) { CGroupContext *cc; + Set *prefixes; + bool *reduced; cc = unit_get_cgroup_context(p); if (!cc) continue; - list = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny; + prefixes = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny; + reduced = verdict == ACCESS_ALLOWED ? &cc->ip_address_allow_reduced : &cc->ip_address_deny_reduced; - bpf_firewall_count_access_items(list, &n_ipv4, &n_ipv6); + if (!*reduced) { + r = in_addr_prefixes_reduce(prefixes); + if (r < 0) + return r; + + *reduced = true; + } + + bpf_firewall_count_access_items(prefixes, &n_ipv4, &n_ipv6); /* Skip making the LPM trie map in cases where we are using "any" in order to hack around * needing CAP_SYS_ADMIN for allocating LPM trie map. */ - if (ip_address_access_item_is_any(list)) { + if (in_addr_prefixes_is_any(prefixes)) { *ret_has_any = true; return 0; } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 52bdf54b5f..2d136793f9 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -19,6 +19,7 @@ #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "in-addr-prefix-util.h" #include "io-util.h" #include "ip-protocol-list.h" #include "limits-util.h" @@ -238,8 +239,8 @@ void cgroup_context_done(CGroupContext *c) { cgroup_context_remove_socket_bind(&c->socket_bind_allow); cgroup_context_remove_socket_bind(&c->socket_bind_deny); - c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow); - c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny); + c->ip_address_allow = set_free(c->ip_address_allow); + c->ip_address_deny = set_free(c->ip_address_deny); c->ip_filters_ingress = strv_free(c->ip_filters_ingress); c->ip_filters_egress = strv_free(c->ip_filters_egress); @@ -395,7 +396,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { CGroupDeviceAllow *a; CGroupContext *c; CGroupSocketBindItem *bi; - IPAddressAccessItem *iaai; + struct in_addr_prefix *iaai; char **path; char cda[FORMAT_CGROUP_DIFF_MAX]; @@ -549,18 +550,18 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { FORMAT_BYTES(b->wbps)); } - LIST_FOREACH(items, iaai, c->ip_address_allow) { + SET_FOREACH(iaai, c->ip_address_allow) { _cleanup_free_ char *k = NULL; - (void) in_addr_to_string(iaai->family, &iaai->address, &k); - fprintf(f, "%sIPAddressAllow: %s/%u\n", prefix, strnull(k), iaai->prefixlen); + (void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k); + fprintf(f, "%sIPAddressAllow: %s\n", prefix, strnull(k)); } - LIST_FOREACH(items, iaai, c->ip_address_deny) { + SET_FOREACH(iaai, c->ip_address_deny) { _cleanup_free_ char *k = NULL; - (void) in_addr_to_string(iaai->family, &iaai->address, &k); - fprintf(f, "%sIPAddressDeny: %s/%u\n", prefix, strnull(k), iaai->prefixlen); + (void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k); + fprintf(f, "%sIPAddressDeny: %s\n", prefix, strnull(k)); } STRV_FOREACH(path, c->ip_filters_ingress) @@ -1555,8 +1556,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) { return false; if (c->ip_accounting || - c->ip_address_allow || - c->ip_address_deny || + !set_isempty(c->ip_address_allow) || + !set_isempty(c->ip_address_deny) || c->ip_filters_ingress || c->ip_filters_egress) return true; @@ -1567,8 +1568,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) { if (!c) return false; - if (c->ip_address_allow || - c->ip_address_deny) + if (!set_isempty(c->ip_address_allow) || + !set_isempty(c->ip_address_deny)) return true; } diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 5b55dd7121..9bb968b6c1 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -5,7 +5,6 @@ #include "cgroup-util.h" #include "cpu-set-util.h" -#include "ip-address-access.h" #include "list.h" #include "time-util.h" @@ -153,8 +152,12 @@ struct CGroupContext { bool memory_min_set:1; bool memory_low_set:1; - LIST_HEAD(IPAddressAccessItem, ip_address_allow); - LIST_HEAD(IPAddressAccessItem, ip_address_deny); + Set *ip_address_allow; + Set *ip_address_deny; + /* These two flags indicate that redundant entries have been removed from + * ip_address_allow/ip_address_deny, i.e. in_addr_prefixes_reduce() has already been called. */ + bool ip_address_allow_reduced; + bool ip_address_deny_reduced; char **ip_filters_ingress; char **ip_filters_egress; diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 75efa9fe1f..ef7d529de9 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -15,6 +15,7 @@ #include "errno-util.h" #include "fd-util.h" #include "fileio.h" +#include "in-addr-prefix-util.h" #include "ip-protocol-list.h" #include "limits-util.h" #include "parse-util.h" @@ -318,14 +319,17 @@ static int property_get_ip_address_access( void *userdata, sd_bus_error *error) { - IPAddressAccessItem** items = userdata, *i; + Set **prefixes = userdata; + struct in_addr_prefix *i; int r; + assert(prefixes); + r = sd_bus_message_open_container(reply, 'a', "(iayu)"); if (r < 0) return r; - LIST_FOREACH(items, i, *items) { + SET_FOREACH(i, *prefixes) { r = sd_bus_message_open_container(reply, 'r', "iayu"); if (r < 0) @@ -1745,11 +1749,9 @@ int bus_cgroup_set_property( return 1; } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) { - IPAddressAccessItem **list; + _cleanup_set_free_ Set *new_prefixes = NULL; size_t n = 0; - list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny; - r = sd_bus_message_enter_container(message, 'a', "(iayu)"); if (r < 0) return r; @@ -1789,17 +1791,16 @@ int bus_cgroup_set_property( return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family)); if (!UNIT_WRITE_FLAGS_NOOP(flags)) { - IPAddressAccessItem *item; + struct in_addr_prefix prefix = { + .family = family, + .prefixlen = prefixlen, + }; - item = new0(IPAddressAccessItem, 1); - if (!item) - return -ENOMEM; + memcpy(&prefix.address, ap, an); - item->family = family; - item->prefixlen = prefixlen; - memcpy(&item->address, ap, an); - - LIST_PREPEND(items, *list, item); + r = in_addr_prefix_add(&new_prefixes, &prefix); + if (r < 0) + return r; } r = sd_bus_message_exit_container(message); @@ -1813,33 +1814,46 @@ int bus_cgroup_set_property( if (r < 0) return r; - *list = ip_address_access_reduce(*list); - if (!UNIT_WRITE_FLAGS_NOOP(flags)) { _cleanup_free_ char *buf = NULL; _cleanup_fclose_ FILE *f = NULL; - IPAddressAccessItem *item; size_t size = 0; - - if (n == 0) - *list = ip_address_access_free_all(*list); + Set **prefixes; + bool *reduced; unit_invalidate_cgroup_bpf(u); f = open_memstream_unlocked(&buf, &size); if (!f) return -ENOMEM; - fputs(name, f); - fputs("=\n", f); + prefixes = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny; + reduced = streq(name, "IPAddressAllow") ? &c->ip_address_allow_reduced : &c->ip_address_deny_reduced; - LIST_FOREACH(items, item, *list) { - char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; + if (n == 0) { + *reduced = true; + *prefixes = set_free(*prefixes); + fputs(name, f); + fputs("=\n", f); + } else { + struct in_addr_prefix *p; - errno = 0; - if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer))) - return errno_or_else(EINVAL); + *reduced = false; - fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen); + r = in_addr_prefixes_merge(prefixes, new_prefixes); + if (r < 0) + return r; + + SET_FOREACH(p, new_prefixes) { + _cleanup_free_ char *buffer = NULL; + + r = in_addr_prefix_to_string(p->family, &p->address, p->prefixlen, &buffer); + if (r == -ENOMEM) + return r; + if (r < 0) + continue; + + fprintf(f, "%s=%s\n", name, buffer); + } } r = fflush_and_check(f); diff --git a/src/core/ip-address-access.c b/src/core/ip-address-access.c deleted file mode 100644 index a11251e94e..0000000000 --- a/src/core/ip-address-access.c +++ /dev/null @@ -1,208 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include -#include - -#include "alloc-util.h" -#include "bpf-firewall.h" -#include "extract-word.h" -#include "hostname-util.h" -#include "ip-address-access.h" -#include "parse-util.h" -#include "string-util.h" - -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 **list = data; - const char *p; - int r; - - assert(list); - - if (isempty(rvalue)) { - *list = ip_address_access_free_all(*list); - return 0; - } - - p = rvalue; - - for (;;) { - _cleanup_free_ IPAddressAccessItem *a = NULL; - _cleanup_free_ char *word = NULL; - - r = extract_first_word(&p, &word, NULL, 0); - if (r == 0) - break; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); - break; - } - - a = new0(IPAddressAccessItem, 1); - if (!a) - return log_oom(); - - if (streq(word, "any")) { - /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */ - - a->family = AF_INET; - LIST_APPEND(items, *list, a); - - a = new0(IPAddressAccessItem, 1); - if (!a) - return log_oom(); - - a->family = AF_INET6; - - } else if (is_localhost(word)) { - /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */ - - a->family = AF_INET; - a->address.in.s_addr = htobe32(0x7f000000); - a->prefixlen = 8; - LIST_APPEND(items, *list, a); - - a = new0(IPAddressAccessItem, 1); - if (!a) - return log_oom(); - - a->family = AF_INET6; - a->address.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT; - a->prefixlen = 128; - - } else if (streq(word, "link-local")) { - - /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */ - - a->family = AF_INET; - a->address.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16)); - a->prefixlen = 16; - LIST_APPEND(items, *list, a); - - a = new0(IPAddressAccessItem, 1); - if (!a) - return log_oom(); - - a->family = AF_INET6; - a->address.in6 = (struct in6_addr) { - .s6_addr32[0] = htobe32(0xfe800000) - }; - a->prefixlen = 64; - - } else if (streq(word, "multicast")) { - - /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */ - - a->family = AF_INET; - a->address.in.s_addr = htobe32((UINT32_C(224) << 24)); - a->prefixlen = 4; - LIST_APPEND(items, *list, a); - - a = new0(IPAddressAccessItem, 1); - if (!a) - return log_oom(); - - a->family = AF_INET6; - a->address.in6 = (struct in6_addr) { - .s6_addr32[0] = htobe32(0xff000000) - }; - a->prefixlen = 8; - - } else { - r = in_addr_prefix_from_string_auto(word, &a->family, &a->address, &a->prefixlen); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Address prefix is invalid, ignoring assignment: %s", word); - return 0; - } - } - - LIST_APPEND(items, *list, a); - a = NULL; - } - - *list = ip_address_access_reduce(*list); - - return 0; -} - -IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) { - IPAddressAccessItem *next, *p = first; - - while (p) { - next = p->items_next; - free(p); - - p = next; - } - - 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) { - /* b covers a fully, then let's drop a */ - LIST_REMOVE(items, first, a); - free(a); - break; - } - } - } - - return first; -} - -bool ip_address_access_item_is_any(IPAddressAccessItem *first) { - /* Check for exactly two entries */ - if (!first || !first->items_next || first->items_next->items_next) - return false; - - /* Check both entries cover the full range */ - if (first->prefixlen != 0 || first->items_next->prefixlen != 0) - return false; - - /* Check that one of them is the IPv4 and the other IPv6 */ - if (!((first->family == AF_INET && first->items_next->family == AF_INET6) || - (first->family == AF_INET6 && first->items_next->family == AF_INET))) - return false; - - /* No need to check the actual addresses, they don't matter if the prefix is zero */ - return true; -} diff --git a/src/core/ip-address-access.h b/src/core/ip-address-access.h deleted file mode 100644 index 71b5459e2a..0000000000 --- a/src/core/ip-address-access.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "conf-parser.h" -#include "in-addr-util.h" -#include "list.h" - -typedef struct IPAddressAccessItem IPAddressAccessItem; - -struct IPAddressAccessItem { - int family; - unsigned char prefixlen; - union in_addr_union address; - LIST_FIELDS(IPAddressAccessItem, items); -}; - -CONFIG_PARSER_PROTOTYPE(config_parse_ip_address_access); - -IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first); - -IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first); - -/* Returns true if a list consists of only the two items necessary for "any" - * (0.0.0.0/0 and ::/0). */ -bool ip_address_access_item_is_any(IPAddressAccessItem *first); diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index 489841af7a..b3dc3bc0fc 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -221,8 +221,8 @@ {{type}}.Delegate, config_parse_delegate, 0, offsetof({{type}}, cgroup_context) {{type}}.DisableControllers, config_parse_disable_controllers, 0, offsetof({{type}}, cgroup_context) {{type}}.IPAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.ip_accounting) -{{type}}.IPAddressAllow, config_parse_ip_address_access, 0, offsetof({{type}}, cgroup_context.ip_address_allow) -{{type}}.IPAddressDeny, config_parse_ip_address_access, 0, offsetof({{type}}, cgroup_context.ip_address_deny) +{{type}}.IPAddressAllow, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_allow) +{{type}}.IPAddressDeny, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_deny) {{type}}.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_ingress) {{type}}.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_egress) {{type}}.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof({{type}}, cgroup_context.moom_swap) @@ -243,6 +243,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include #include "all-units.h" #include "conf-parser.h" +#include "in-addr-prefix-util.h" #include "load-fragment.h" %} struct ConfigPerfItem; diff --git a/src/core/manager.h b/src/core/manager.h index 1220c9fb16..4234e187fd 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -12,7 +12,6 @@ #include "cgroup.h" #include "fdset.h" #include "hashmap.h" -#include "ip-address-access.h" #include "list.h" #include "prioq.h" #include "ratelimit.h" diff --git a/src/core/meson.build b/src/core/meson.build index 87a15ec71a..d36be869ce 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -71,8 +71,6 @@ libcore_sources = ''' generator-setup.h ima-setup.c ima-setup.h - ip-address-access.c - ip-address-access.h job.c job.h kill.c diff --git a/src/core/unit.h b/src/core/unit.h index 80d56aefc1..c8e99acf70 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "sd-id128.h" diff --git a/src/test/test-bpf-firewall.c b/src/test/test-bpf-firewall.c index 8b7d46bee3..1e0ad177b9 100644 --- a/src/test/test-bpf-firewall.c +++ b/src/test/test-bpf-firewall.c @@ -6,6 +6,7 @@ #include "bpf-firewall.h" #include "bpf-program.h" +#include "in-addr-prefix-util.h" #include "load-fragment.h" #include "manager.h" #include "memory-util.h" @@ -106,21 +107,39 @@ int main(int argc, char *argv[]) { cc->ip_accounting = true; - assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "10.0.1.0/24", &cc->ip_address_allow, NULL) == 0); - assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "127.0.0.2", &cc->ip_address_allow, NULL) == 0); - assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.3", &cc->ip_address_deny, NULL) == 0); - assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "10.0.3.2/24", &cc->ip_address_deny, NULL) == 0); - assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.1/25", &cc->ip_address_deny, NULL) == 0); - assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.4", &cc->ip_address_deny, NULL) == 0); + assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "10.0.1.0/24", &cc->ip_address_allow, NULL) == 0); + assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "127.0.0.2", &cc->ip_address_allow, NULL) == 0); + assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.3", &cc->ip_address_deny, NULL) == 0); + assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "10.0.3.2/24", &cc->ip_address_deny, NULL) == 0); + assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.1/25", &cc->ip_address_deny, NULL) == 0); + assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.4", &cc->ip_address_deny, NULL) == 0); - assert(cc->ip_address_allow); - assert(cc->ip_address_allow->items_next); - assert(!cc->ip_address_allow->items_next->items_next); + assert_se(set_size(cc->ip_address_allow) == 2); + assert_se(set_size(cc->ip_address_deny) == 4); - /* The deny list is defined redundantly, let's ensure it got properly reduced */ - assert(cc->ip_address_deny); - assert(cc->ip_address_deny->items_next); - assert(!cc->ip_address_deny->items_next->items_next); + /* The deny list is defined redundantly, let's ensure it will be properly reduced */ + assert_se(in_addr_prefixes_reduce(cc->ip_address_allow) >= 0); + assert_se(in_addr_prefixes_reduce(cc->ip_address_deny) >= 0); + + assert_se(set_size(cc->ip_address_allow) == 2); + assert_se(set_size(cc->ip_address_deny) == 2); + + assert_se(set_contains(cc->ip_address_allow, &(struct in_addr_prefix) { + .family = AF_INET, + .address.in.s_addr = htobe32((UINT32_C(10) << 24) | (UINT32_C(1) << 8)), + .prefixlen = 24 })); + assert_se(set_contains(cc->ip_address_allow, &(struct in_addr_prefix) { + .family = AF_INET, + .address.in.s_addr = htobe32(0x7f000002), + .prefixlen = 32 })); + assert_se(set_contains(cc->ip_address_deny, &(struct in_addr_prefix) { + .family = AF_INET, + .address.in.s_addr = htobe32(0x7f000000), + .prefixlen = 25 })); + assert_se(set_contains(cc->ip_address_deny, &(struct in_addr_prefix) { + .family = AF_INET, + .address.in.s_addr = htobe32((UINT32_C(10) << 24) | (UINT32_C(3) << 8)), + .prefixlen = 24 })); assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.2 -W 5", SERVICE(u)->exec_command, u) == 0); assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.3 -W 5", SERVICE(u)->exec_command, u) == 0);