diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-08-23 01:36:21 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-08-23 20:36:09 +0900 |
commit | c995fa02b1e23ea73cd1b7f62cb4dd23e951def7 (patch) | |
tree | 38b94d431ac0165f993bd215371471e2acf30f92 /src/network/networkd-dhcp-common.c | |
parent | f95d1ef5fafd96c65a9da57fa2bcdd503fce694c (diff) | |
download | systemd-c995fa02b1e23ea73cd1b7f62cb4dd23e951def7.tar.gz |
network: dhcp4,ndisc: make addresses in Allow/DenyList= optionally take prefix length
Closes #20505.
Diffstat (limited to 'src/network/networkd-dhcp-common.c')
-rw-r--r-- | src/network/networkd-dhcp-common.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 19c888287c..25725f4f28 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -203,6 +203,30 @@ int dhcp_configure_duid(Link *link, const DUID *duid) { return 0; } +bool address_is_filtered(int family, const union in_addr_union *address, uint8_t prefixlen, Set *allow_list, Set *deny_list) { + struct in_addr_prefix *p; + + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(address); + + if (allow_list) { + SET_FOREACH(p, allow_list) + if (p->family == family && + p->prefixlen <= prefixlen && + in_addr_prefix_covers(family, &p->address, p->prefixlen, address) > 0) + return false; + + return true; + } + + SET_FOREACH(p, deny_list) + if (p->family == family && + in_addr_prefix_intersect(family, &p->address, p->prefixlen, address, prefixlen) > 0) + return true; + + return false; +} + int config_parse_dhcp( const char* unit, const char *filename, @@ -1144,3 +1168,69 @@ int config_parse_network_duid_rawdata( /* For backward compatibility, also set DHCPv6 DUID if not specified explicitly. */ return config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, false, rvalue, &network->dhcp6_duid, network); } + +int config_parse_address_filter( + 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) { + + Set **list = data; + int r; + + assert(filename); + assert(lvalue); + assert(IN_SET(ltype, AF_INET, AF_INET6)); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *list = set_free(*list); + return 0; + } + + for (const char *p = rvalue;;) { + _cleanup_free_ char *n = NULL; + _cleanup_free_ struct in_addr_prefix *a = NULL; + struct in_addr_prefix prefix; + + r = extract_first_word(&p, &n, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse NDisc %s=, ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_prefix_from_string(n, ltype, &prefix.address, &prefix.prefixlen); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "NDisc %s= entry is invalid, ignoring assignment: %s", + lvalue, n); + continue; + } + + prefix.family = ltype; + a = newdup(struct in_addr_prefix, &prefix, 1); + if (!a) + return log_oom(); + + r = set_ensure_consume(list, &in_addr_prefix_hash_ops_free, TAKE_PTR(a)); + if (r < 0) + return log_oom(); + if (r == 0) + log_syntax(unit, LOG_WARNING, filename, line, 0, + "%s %s= entry is duplicated, ignoring assignment: %s", + section, lvalue, n); + } +} |