diff options
Diffstat (limited to '')
-rw-r--r-- | src/network/networkd-util.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c new file mode 100644 index 0000000..8ddcbb2 --- /dev/null +++ b/src/network/networkd-util.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "condition.h" +#include "conf-parser.h" +#include "networkd-util.h" +#include "parse-util.h" +#include "string-table.h" +#include "string-util.h" +#include "util.h" + +static const char* const address_family_table[_ADDRESS_FAMILY_MAX] = { + [ADDRESS_FAMILY_NO] = "no", + [ADDRESS_FAMILY_YES] = "yes", + [ADDRESS_FAMILY_IPV4] = "ipv4", + [ADDRESS_FAMILY_IPV6] = "ipv6", +}; + +static const char* const link_local_address_family_table[_ADDRESS_FAMILY_MAX] = { + [ADDRESS_FAMILY_NO] = "no", + [ADDRESS_FAMILY_YES] = "yes", + [ADDRESS_FAMILY_IPV4] = "ipv4", + [ADDRESS_FAMILY_IPV6] = "ipv6", + [ADDRESS_FAMILY_FALLBACK] = "fallback", + [ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback", +}; + +static const char* const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = { + [ADDRESS_FAMILY_YES] = "both", + [ADDRESS_FAMILY_IPV4] = "ipv4", + [ADDRESS_FAMILY_IPV6] = "ipv6", +}; + +static const char* const duplicate_address_detection_address_family_table[_ADDRESS_FAMILY_MAX] = { + [ADDRESS_FAMILY_NO] = "none", + [ADDRESS_FAMILY_YES] = "both", + [ADDRESS_FAMILY_IPV4] = "ipv4", + [ADDRESS_FAMILY_IPV6] = "ipv6", +}; + +static const char* const dhcp_lease_server_type_table[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = { + [SD_DHCP_LEASE_DNS] = "DNS servers", + [SD_DHCP_LEASE_NTP] = "NTP servers", + [SD_DHCP_LEASE_SIP] = "SIP servers", + [SD_DHCP_LEASE_POP3] = "POP3 servers", + [SD_DHCP_LEASE_SMTP] = "SMTP servers", + [SD_DHCP_LEASE_LPR] = "LPR servers", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES); +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family, AddressFamily, ADDRESS_FAMILY_YES); +DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily); +DEFINE_STRING_TABLE_LOOKUP(duplicate_address_detection_address_family, AddressFamily); +DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family, + AddressFamily, "Failed to parse option"); +DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type); + +int config_parse_address_family_with_kernel( + 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) { + + AddressFamily *fwd = data, s; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* This function is mostly obsolete now. It simply redirects + * "kernel" to "no". In older networkd versions we used to + * distinguish IPForward=off from IPForward=kernel, where the + * former would explicitly turn off forwarding while the + * latter would simply not touch the setting. But that logic + * is gone, hence silently accept the old setting, but turn it + * to "no". */ + + s = address_family_from_string(rvalue); + if (s < 0) { + if (streq(rvalue, "kernel")) + s = ADDRESS_FAMILY_NO; + else { + log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue); + return 0; + } + } + + *fwd = s; + + return 0; +} + +/* Router lifetime can be set with netlink interface since kernel >= 4.5 + * so for the supported kernel we don't need to expire routes in userspace */ +int kernel_route_expiration_supported(void) { + static int cached = -1; + int r; + + if (cached < 0) { + Condition c = { + .type = CONDITION_KERNEL_VERSION, + .parameter = (char *) ">= 4.5" + }; + r = condition_test(&c, NULL); + if (r < 0) + return r; + + cached = r; + } + return cached; +} + +static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) { + siphash24_compress_string(c->filename, state); + siphash24_compress(&c->line, sizeof(c->line), state); +} + +static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) { + int r; + + r = strcmp(x->filename, y->filename); + if (r != 0) + return r; + + return CMP(x->line, y->line); +} + +DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func); + +int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) { + NetworkConfigSection *cs; + + cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1); + if (!cs) + return -ENOMEM; + + strcpy(cs->filename, filename); + cs->line = line; + + *s = TAKE_PTR(cs); + + return 0; +} + +void network_config_section_free(NetworkConfigSection *cs) { + free(cs); +} + +unsigned hashmap_find_free_section_line(Hashmap *hashmap) { + NetworkConfigSection *cs; + unsigned n = 0; + void *entry; + + HASHMAP_FOREACH_KEY(entry, cs, hashmap) + if (n < cs->line) + n = cs->line; + + return n + 1; +} |