summaryrefslogtreecommitdiff
path: root/src/network/networkd-dhcp-common.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-08-23 01:36:21 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-08-23 20:36:09 +0900
commitc995fa02b1e23ea73cd1b7f62cb4dd23e951def7 (patch)
tree38b94d431ac0165f993bd215371471e2acf30f92 /src/network/networkd-dhcp-common.c
parentf95d1ef5fafd96c65a9da57fa2bcdd503fce694c (diff)
downloadsystemd-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.c90
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);
+ }
+}