diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-07-02 09:46:38 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-02 09:46:38 +0200 |
commit | 8fabb625ac505d3a5af4d465822d07cc67ad5e56 (patch) | |
tree | d6e0760e4d6b274a9e4fb04b99f6e6f4a8df8e17 | |
parent | e28fd95ffb2067298c9495353a3673568fe30bfd (diff) | |
parent | ceac2c2b62dc2b5ac67856ab423a47f152d49925 (diff) | |
download | systemd-8fabb625ac505d3a5af4d465822d07cc67ad5e56.tar.gz |
Merge pull request #12912 from yuwata/network-move-functions
network: move functions
25 files changed, 1175 insertions, 1089 deletions
diff --git a/src/network/meson.build b/src/network/meson.build index 5465f9eb64..14951c544c 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -55,11 +55,18 @@ sources = files(''' networkd-can.h networkd-conf.c networkd-conf.h + networkd-dhcp-common.c + networkd-dhcp-common.h + networkd-dhcp-server.c + networkd-dhcp-server.h networkd-dhcp4.c + networkd-dhcp4.h networkd-dhcp6.c + networkd-dhcp6.h networkd-fdb.c networkd-fdb.h networkd-ipv4ll.c + networkd-ipv4ll.h networkd-ipv6-proxy-ndp.c networkd-ipv6-proxy-ndp.h networkd-link-bus.c @@ -80,6 +87,7 @@ sources = files(''' networkd-radv.c networkd-radv.h networkd-network-bus.c + networkd-network-bus.h networkd-network.c networkd-network.h networkd-route.c diff --git a/src/network/networkd-brvlan.h b/src/network/networkd-brvlan.h index f6af140d3e..7533034021 100644 --- a/src/network/networkd-brvlan.h +++ b/src/network/networkd-brvlan.h @@ -9,6 +9,9 @@ #include "conf-parser.h" +#define BRIDGE_VLAN_BITMAP_MAX 4096 +#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32) + typedef struct Link Link; int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap); diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c new file mode 100644 index 0000000000..743f2d8ec2 --- /dev/null +++ b/src/network/networkd-dhcp-common.c @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "networkd-dhcp-common.h" +#include "networkd-network.h" +#include "parse-util.h" +#include "string-table.h" + +int config_parse_dhcp( + 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) { + + AddressFamilyBoolean *dhcp = data, s; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* Note that this is mostly like + * config_parse_address_family_boolean(), except that it + * understands some old names for the enum values */ + + s = address_family_boolean_from_string(rvalue); + if (s < 0) { + + /* Previously, we had a slightly different enum here, + * support its values for compatibility. */ + + if (streq(rvalue, "none")) + s = ADDRESS_FAMILY_NO; + else if (streq(rvalue, "v4")) + s = ADDRESS_FAMILY_IPV4; + else if (streq(rvalue, "v6")) + s = ADDRESS_FAMILY_IPV6; + else if (streq(rvalue, "both")) + s = ADDRESS_FAMILY_YES; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse DHCP option, ignoring: %s", rvalue); + return 0; + } + + log_syntax(unit, LOG_WARNING, filename, line, 0, + "DHCP=%s is deprecated, please use DHCP=%s instead.", + rvalue, address_family_boolean_to_string(s)); + } + + *dhcp = s; + return 0; +} + +int config_parse_section_route_table( + 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) { + + Network *network = data; + uint32_t rt; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &rt); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue); + return 0; + } + + if (streq_ptr(section, "DHCP")) { + network->dhcp_route_table = rt; + network->dhcp_route_table_set = true; + } else { /* section is IPv6AcceptRA */ + network->ipv6_accept_ra_route_table = rt; + network->ipv6_accept_ra_route_table_set = true; + } + + return 0; +} + +int config_parse_iaid(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) { + Network *network = data; + uint32_t iaid; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(network); + + r = safe_atou32(rvalue, &iaid); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Unable to read IAID, ignoring assignment: %s", rvalue); + return 0; + } + + network->iaid = iaid; + network->iaid_set = true; + + return 0; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, + "Failed to parse DHCP use domains setting"); + +static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { + [DHCP_USE_DOMAINS_NO] = "no", + [DHCP_USE_DOMAINS_ROUTE] = "route", + [DHCP_USE_DOMAINS_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h new file mode 100644 index 0000000000..0e6e051599 --- /dev/null +++ b/src/network/networkd-dhcp-common.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "dhcp-identifier.h" +#include "time-util.h" + +#define DHCP_ROUTE_METRIC 1024 + +typedef enum DHCPUseDomains { + DHCP_USE_DOMAINS_NO, + DHCP_USE_DOMAINS_YES, + DHCP_USE_DOMAINS_ROUTE, + _DHCP_USE_DOMAINS_MAX, + _DHCP_USE_DOMAINS_INVALID = -1, +} DHCPUseDomains; + +typedef struct DUID { + /* Value of Type in [DHCP] section */ + DUIDType type; + + uint8_t raw_data_len; + uint8_t raw_data[MAX_DUID_LEN]; + usec_t llt_time; +} DUID; + +const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; +DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains); +CONFIG_PARSER_PROTOTYPE(config_parse_iaid); +CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c new file mode 100644 index 0000000000..f4c2178b7b --- /dev/null +++ b/src/network/networkd-dhcp-server.c @@ -0,0 +1,347 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-dhcp-server.h" + +#include "networkd-dhcp-server.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-network.h" +#include "strv.h" + +static Address* link_find_dhcp_server_address(Link *link) { + Address *address; + + assert(link); + assert(link->network); + + /* The first statically configured address if there is any */ + LIST_FOREACH(addresses, address, link->network->static_addresses) { + + if (address->family != AF_INET) + continue; + + if (in_addr_is_null(address->family, &address->in_addr)) + continue; + + return address; + } + + /* If that didn't work, find a suitable address we got from the pool */ + LIST_FOREACH(addresses, address, link->pool_addresses) { + if (address->family != AF_INET) + continue; + + return address; + } + + return NULL; +} + +static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { + _cleanup_free_ struct in_addr *addresses = NULL; + size_t n_addresses = 0, n_allocated = 0; + unsigned i; + + log_debug("Copying DNS server information from %s", link->ifname); + + if (!link->network) + return 0; + + for (i = 0; i < link->network->n_dns; i++) { + struct in_addr ia; + + /* Only look for IPv4 addresses */ + if (link->network->dns[i].family != AF_INET) + continue; + + ia = link->network->dns[i].address.in; + + /* Never propagate obviously borked data */ + if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia)) + continue; + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) + return log_oom(); + + addresses[n_addresses++] = ia; + } + + if (link->network->dhcp_use_dns && link->dhcp_lease) { + const struct in_addr *da = NULL; + int j, n; + + n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da); + if (n > 0) { + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) + return log_oom(); + + for (j = 0; j < n; j++) + if (in4_addr_is_non_local(&da[j])) + addresses[n_addresses++] = da[j]; + } + } + + if (n_addresses <= 0) + return 0; + + return sd_dhcp_server_set_dns(s, addresses, n_addresses); +} + +static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { + _cleanup_free_ struct in_addr *addresses = NULL; + size_t n_addresses = 0, n_allocated = 0; + char **a; + + if (!link->network) + return 0; + + log_debug("Copying NTP server information from %s", link->ifname); + + STRV_FOREACH(a, link->network->ntp) { + union in_addr_union ia; + + /* Only look for IPv4 addresses */ + if (in_addr_from_string(AF_INET, *a, &ia) <= 0) + continue; + + /* Never propagate obviously borked data */ + if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in)) + continue; + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) + return log_oom(); + + addresses[n_addresses++] = ia.in; + } + + if (link->network->dhcp_use_ntp && link->dhcp_lease) { + const struct in_addr *da = NULL; + int j, n; + + n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da); + if (n > 0) { + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) + return log_oom(); + + for (j = 0; j < n; j++) + if (in4_addr_is_non_local(&da[j])) + addresses[n_addresses++] = da[j]; + } + } + + if (n_addresses <= 0) + return 0; + + return sd_dhcp_server_set_ntp(s, addresses, n_addresses); +} + +int dhcp4_server_configure(Link *link) { + Address *address; + Link *uplink = NULL; + bool acquired_uplink = false; + int r; + + address = link_find_dhcp_server_address(link); + if (!address) + return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBUSY), + "Failed to find suitable address for DHCPv4 server instance."); + + /* use the server address' subnet as the pool */ + r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen, + link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size); + if (r < 0) + return r; + + /* TODO: + r = sd_dhcp_server_set_router(link->dhcp_server, &main_address->in_addr.in); + if (r < 0) + return r; + */ + + if (link->network->dhcp_server_max_lease_time_usec > 0) { + r = sd_dhcp_server_set_max_lease_time(link->dhcp_server, + DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC)); + if (r < 0) + return r; + } + + if (link->network->dhcp_server_default_lease_time_usec > 0) { + r = sd_dhcp_server_set_default_lease_time(link->dhcp_server, + DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC)); + if (r < 0) + return r; + } + + if (link->network->dhcp_server_emit_dns) { + if (link->network->n_dhcp_server_dns > 0) + r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); + else { + uplink = manager_find_uplink(link->manager, link); + acquired_uplink = true; + + if (!uplink) { + log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink."); + r = 0; + } else + r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server); + } + if (r < 0) + log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); + } + + if (link->network->dhcp_server_emit_ntp) { + if (link->network->n_dhcp_server_ntp > 0) + r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); + else { + if (!acquired_uplink) + uplink = manager_find_uplink(link->manager, link); + + if (!uplink) { + log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink."); + r = 0; + } else + r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server); + + } + if (r < 0) + log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); + } + + r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m"); + + if (link->network->dhcp_server_emit_timezone) { + _cleanup_free_ char *buffer = NULL; + const char *tz; + + if (link->network->dhcp_server_timezone) + tz = link->network->dhcp_server_timezone; + else { + r = get_timezone(&buffer); + if (r < 0) + return log_warning_errno(r, "Failed to determine timezone: %m"); + + tz = buffer; + } + + r = sd_dhcp_server_set_timezone(link->dhcp_server, tz); + if (r < 0) + return r; + } + if (!sd_dhcp_server_is_running(link->dhcp_server)) { + r = sd_dhcp_server_start(link->dhcp_server); + if (r < 0) + return log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m"); + } + + return 0; +} + +int config_parse_dhcp_server_dns( + 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) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + struct in_addr *m; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + break; + + r = in_addr_from_string(AF_INET, w, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DNS server address '%s', ignoring assignment: %m", w); + continue; + } + + m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[n->n_dhcp_server_dns++] = a.in; + n->dhcp_server_dns = m; + } + + return 0; +} + +int config_parse_dhcp_server_ntp( + 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) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + struct in_addr *m; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_from_string(AF_INET, w, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse NTP server address '%s', ignoring: %m", w); + continue; + } + + m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[n->n_dhcp_server_ntp++] = a.in; + n->dhcp_server_ntp = m; + } +} diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h new file mode 100644 index 0000000000..e97e56b9f2 --- /dev/null +++ b/src/network/networkd-dhcp-server.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" + +typedef struct Link Link; + +int dhcp4_server_configure(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 978378d7b8..3e384a47c0 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -7,9 +7,11 @@ #include "hostname-util.h" #include "parse-util.h" #include "network-internal.h" +#include "networkd-dhcp4.h" #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "string-table.h" #include "string-util.h" #include "sysctl-util.h" @@ -1078,3 +1080,175 @@ int dhcp4_configure(Link *link) { return dhcp4_set_client_identifier(link); } + +int config_parse_dhcp_max_attempts( + 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) { + + Network *network = data; + uint64_t a; + int r; + + assert(network); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + network->dhcp_max_attempts = 0; + return 0; + } + + if (streq(rvalue, "infinity")) { + network->dhcp_max_attempts = (uint64_t) -1; + return 0; + } + + r = safe_atou64(rvalue, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue); + return 0; + } + + if (a == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue); + return 0; + } + + network->dhcp_max_attempts = a; + + return 0; +} + +int config_parse_dhcp_black_listed_ip_address( + 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) { + + Network *network = data; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip); + return 0; + } + + for (p = rvalue;;) { + _cleanup_free_ char *n = NULL; + union in_addr_union ip; + + r = extract_first_word(&p, &n, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCP black listed ip address, ignoring assignment: %s", + rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_from_string(AF_INET, n, &ip); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "DHCP black listed ip address is invalid, ignoring assignment: %s", n); + continue; + } + + r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL); + if (r < 0) + return log_oom(); + + r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr)); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n); + } + + return 0; +} + +int config_parse_dhcp_user_class( + 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) { + + char ***l = data; + int r; + + assert(l); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *l = strv_free(*l); + return 0; + } + + for (;;) { + _cleanup_free_ char *w = NULL; + + r = extract_first_word(&rvalue, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to split user classes option, ignoring: %s", rvalue); + break; + } + if (r == 0) + break; + + if (strlen(w) > 255) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "%s length is not in the range 1-255, ignoring.", w); + continue; + } + + r = strv_push(l, w); + if (r < 0) + return log_oom(); + + w = NULL; + } + + return 0; +} + +static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = { + [DHCP_CLIENT_ID_MAC] = "mac", + [DHCP_CLIENT_ID_DUID] = "duid", + [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier, + "Failed to parse client identifier type"); diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h new file mode 100644 index 0000000000..117b7110d3 --- /dev/null +++ b/src/network/networkd-dhcp4.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" + +typedef struct Link Link; + +typedef enum DHCPClientIdentifier { + DHCP_CLIENT_ID_MAC, + DHCP_CLIENT_ID_DUID, + /* The following option may not be good for RFC regarding DHCP (3315 and 4361). + * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK + * requires the client id to be set to a custom string, reported at + * https://github.com/systemd/systemd/issues/7828 */ + DHCP_CLIENT_ID_DUID_ONLY, + _DHCP_CLIENT_ID_MAX, + _DHCP_CLIENT_ID_INVALID = -1, +} DHCPClientIdentifier; + +void dhcp4_release_old_lease(Link *link); +int dhcp4_configure(Link *link); +int dhcp4_set_client_identifier(Link *link); +int dhcp4_set_promote_secondaries(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index afa3e2cfd6..286b9071ae 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -13,6 +13,7 @@ #include "hostname-util.h" #include "missing_network.h" #include "network-internal.h" +#include "networkd-dhcp6.h" #include "networkd-link.h" #include "networkd-manager.h" #include "siphash24.h" @@ -20,6 +21,9 @@ #include "radv-internal.h" static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); +static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr); +static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link); +static int dhcp6_prefix_remove_all(Manager *m, Link *link); static bool dhcp6_get_prefix_delegation(Link *link) { if (!link->network) @@ -90,7 +94,7 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix, if (r < 0 && r != -EEXIST) return r; - r = manager_dhcp6_prefix_add(link->manager, prefix, link); + r = dhcp6_prefix_add(link->manager, prefix, link); if (r < 0) return r; @@ -104,7 +108,7 @@ static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Lin r = sd_netlink_message_get_errno(m); if (r < 0) - log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnetl: %m"); + log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnet: %m"); return 1; } @@ -202,7 +206,7 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i, if (!dhcp6_get_prefix_delegation(link)) continue; - assigned_link = manager_dhcp6_prefix_get(manager, &prefix.in6); + assigned_link = dhcp6_prefix_get(manager, &prefix.in6); if (assigned_link && assigned_link != link) continue; @@ -488,7 +492,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { log_link_warning(link, "DHCPv6 lease lost"); (void) dhcp6_lease_pd_prefix_lost(client, link); - (void) manager_dhcp6_prefix_remove_all(link->manager, link); + (void) dhcp6_prefix_remove_all(link->manager, link); link->dhcp6_configured = false; break; @@ -685,3 +689,123 @@ int dhcp6_configure(Link *link) { return 0; } + +static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr) { + assert_return(m, NULL); + assert_return(addr, NULL); + + return hashmap_get(m->dhcp6_prefixes, addr); +} + +static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m"); + + return 0; +} + +static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) { + _cleanup_free_ struct in6_addr *a = NULL; + _cleanup_free_ char *buf = NULL; + Link *assigned_link; + Route *route; + int r; + + assert_return(m, -EINVAL); + assert_return(addr, -EINVAL); + + r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64, + 0, 0, 0, &route); + if (r < 0) + return r; + + r = route_configure(route, link, dhcp6_route_add_handler); + if (r < 0) + return r; + + (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); + log_link_debug(link, "Adding prefix route %s/64", strnull(buf)); + + assigned_link = hashmap_get(m->dhcp6_prefixes, addr); + if (assigned_link) { + assert(assigned_link == link); + return 0; + } + + a = newdup(struct in6_addr, addr, 1); + if (!a) + return -ENOMEM; + + r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(m->dhcp6_prefixes, a, link); + if (r < 0) + return r; + + TAKE_PTR(a); + link_ref(link); + return 0; +} + +static int dhcp6_prefix_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m"); + + return 1; +} + +int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) { + _cleanup_free_ struct in6_addr *a = NULL; + _cleanup_(link_unrefp) Link *l = NULL; + _cleanup_free_ char *buf = NULL; + Route *route; + int r; + + assert_return(m, -EINVAL); + assert_return(addr, -EINVAL); + + l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a); + if (!l) + return -EINVAL; + + (void) sd_radv_remove_prefix(l->radv, addr, 64); + r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route); + if (r < 0) + return r; + + r = route_remove(route, l, dhcp6_prefix_remove_handler); + if (r < 0) + return r; + + (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); + log_link_debug(l, "Removing prefix route %s/64", strnull(buf)); + + return 0; +} + +static int dhcp6_prefix_remove_all(Manager *m, Link *link) { + struct in6_addr *addr; + Iterator i; + Link *l; + + assert_return(m, -EINVAL); + assert_return(link, -EINVAL); + + HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i) + if (l == link) + (void) dhcp6_prefix_remove(m, addr); + + return 0; +} diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h new file mode 100644 index 0000000000..26d810f40c --- /dev/null +++ b/src/network/networkd-dhcp6.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-dhcp6-client.h" + +#include "conf-parser.h" + +typedef struct Link Link; +typedef struct Manager Manager; + +int dhcp6_request_prefix_delegation(Link *link); +int dhcp6_configure(Link *link); +int dhcp6_request_address(Link *link, int ir); +int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link); +int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr); diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 738d22cb5b..d76f02d563 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -5,8 +5,10 @@ #include "network-internal.h" #include "networkd-address.h" -#include "networkd-manager.h" +#include "networkd-ipv4ll.h" #include "networkd-link.h" +#include "networkd-manager.h" +#include "parse-util.h" static int ipv4ll_address_lost(Link *link) { _cleanup_(address_freep) Address *address = NULL; @@ -234,3 +236,45 @@ int ipv4ll_configure(Link *link) { return 0; } + +int config_parse_ipv4ll( + 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) { + + AddressFamilyBoolean *link_local = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* Note that this is mostly like + * config_parse_address_family_boolean(), except that it + * applies only to IPv4 */ + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse %s=%s, ignoring assignment. " + "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.", + lvalue, rvalue, lvalue); + return 0; + } + + SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r); + + log_syntax(unit, LOG_WARNING, filename, line, 0, + "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.", + lvalue, rvalue, address_family_boolean_to_string(*link_local)); + + return 0; +} diff --git a/src/network/networkd-ipv4ll.h b/src/network/networkd-ipv4ll.h new file mode 100644 index 0000000000..49b6fb56ad --- /dev/null +++ b/src/network/networkd-ipv4ll.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" + +#define IPV4LL_ROUTE_METRIC 2048 + +typedef struct Link Link; + +int ipv4ll_configure(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9f228a9d30..78a8e15935 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -19,6 +19,10 @@ #include "netlink-util.h" #include "network-internal.h" #include "networkd-can.h" +#include "networkd-dhcp-server.h" +#include "networkd-dhcp4.h" +#include "networkd-dhcp6.h" +#include "networkd-ipv4ll.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-link-bus.h" #include "networkd-link.h" @@ -797,35 +801,6 @@ void link_enter_failed(Link *link) { link_dirty(link); } -static Address* link_find_dhcp_server_address(Link *link) { - Address *address; - - assert(link); - assert(link->network); - - /* The first statically configured address if there is any */ - LIST_FOREACH(addresses, address, link->network->static_addresses) { - - if (address->family != AF_INET) - continue; - - if (in_addr_is_null(address->family, &address->in_addr)) - continue; - - return address; - } - - /* If that didn't work, find a suitable address we got from the pool */ - LIST_FOREACH(addresses, address, link->pool_addresses) { - if (address->family != AF_INET) - continue; - - return address; - } - - return NULL; -} - static int link_join_netdevs_after_configured(Link *link) { NetDev *netdev; Iterator i; @@ -1104,106 +1079,6 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) return 1; } -static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { - _cleanup_free_ struct in_addr *addresses = NULL; - size_t n_addresses = 0, n_allocated = 0; - unsigned i; - - log_debug("Copying DNS server information from %s", link->ifname); - - if (!link->network) - return 0; - - for (i = 0; i < link->network->n_dns; i++) { - struct in_addr ia; - - /* Only look for IPv4 addresses */ - if (link->network->dns[i].family != AF_INET) - continue; - - ia = link->network->dns[i].address.in; - - /* Never propagate obviously borked data */ - if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia)) - continue; - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) - return log_oom(); - - addresses[n_addresses++] = ia; - } - - if (link->network->dhcp_use_dns && link->dhcp_lease) { - const struct in_addr *da = NULL; - int j, n; - - n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da); - if (n > 0) { - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) - return log_oom(); - - for (j = 0; j < n; j++) - if (in4_addr_is_non_local(&da[j])) - addresses[n_addresses++] = da[j]; - } - } - - if (n_addresses <= 0) - return 0; - - return sd_dhcp_server_set_dns(s, addresses, n_addresses); -} - -static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { - _cleanup_free_ struct in_addr *addresses = NULL; - size_t n_addresses = 0, n_allocated = 0; - char **a; - - if (!link->network) - return 0; - - log_debug("Copying NTP server information from %s", link->ifname); - - STRV_FOREACH(a, link->network->ntp) { - union in_addr_union ia; - - /* Only look for IPv4 addresses */ - if (in_addr_from_string(AF_INET, *a, &ia) <= 0) - continue; - - /* Never propagate obviously borked data */ - if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in)) - continue; - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) - return log_oom(); - - addresses[n_addresses++] = ia.in; - } - - if (link->network->dhcp_use_ntp && link->dhcp_lease) { - const struct in_addr *da = NULL; - int j, n; - - n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da); - if (n > 0) { - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) - return log_oom(); - - for (j = 0; j < n; j++) - if (in4_addr_is_non_local(&da[j])) - addresses[n_addresses++] = da[j]; - } - } - - if (n_addresses <= 0) - return 0; - - return sd_dhcp_server_set_ntp(s, addresses, n_addresses); -} - static int link_set_bridge_fdb(Link *link) { FdbEntry *fdb_entry; int r; @@ -1272,118 +1147,11 @@ static int link_request_set_addresses(Link *link) { /* now that we can figure out a default address for the dhcp server, start it */ if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) { - Address *address; - Link *uplink = NULL; - bool acquired_uplink = false; - - address = link_find_dhcp_server_address(link); - if (!address) { - log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance."); + r = dhcp4_server_configure(link); + if (r < 0) { link_enter_failed(link); - return 0; - } - - /* use the server address' subnet as the pool */ - r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen, - link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size); - if (r < 0) - return r; - - /* TODO: - r = sd_dhcp_server_set_router(link->dhcp_server, - &main_address->in_addr.in); - if (r < 0) return r; - */ - - if (link->network->dhcp_server_max_lease_time_usec > 0) { - r = sd_dhcp_server_set_max_lease_time( - link->dhcp_server, - DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC)); - if (r < 0) - return r; } - - if (link->network->dhcp_server_default_lease_time_usec > 0) { - r = sd_dhcp_server_set_default_lease_time( - link->dhcp_server, - DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC)); - if (r < 0) - return r; - } - - if (link->network->dhcp_server_emit_dns) { - - if (link->network->n_dhcp_server_dns > 0) - r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); - else { - uplink = manager_find_uplink(link->manager, link); - acquired_uplink = true; - - if (!uplink) { - log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server); - } - if (r < 0) - log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); - } - - if (link->network->dhcp_server_emit_ntp) { - - if (link->network->n_dhcp_server_ntp > 0) - r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); - else { - if (!acquired_uplink) - uplink = manager_find_uplink(link->manager, link); - - if (!uplink) { - log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server); - - } - if (r < 0) - log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); - } - - r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m"); - - if (link->network->dhcp_server_emit_timezone) { - _cleanup_free_ char *buffer = NULL; - const char *tz = NULL; - - if (link->network->dhcp_server_timezone) - tz = link->network->dhcp_server_timezone; - else { - r = get_timezone(&buffer); - if (r < 0) - log_warning_errno(r, "Failed to determine timezone: %m"); - else - tz = buffer; - } - - if (tz) { - r = sd_dhcp_server_set_timezone(link->dhcp_server, tz); - if (r < 0) - return r; - } - } - if (!sd_dhcp_server_is_running(link->dhcp_server)) { - r = sd_dhcp_server_start(link->dhcp_server); - if (r < 0) { - log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m"); - - link_enter_failed(link); - - return 0; - } - } - log_link_debug(link, "Offering DHCPv4 leases"); } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index ac1532c066..43efa42312 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -168,18 +168,8 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address); int link_set_mtu(Link *link, uint32_t mtu); -int ipv4ll_configure(Link *link); bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask); -void dhcp4_release_old_lease(Link *link); -int dhcp4_configure(Link *link); -int dhcp4_set_client_identifier(Link *link); -int dhcp4_set_promote_secondaries(Link *link); -int dhcp6_request_prefix_delegation(Link *link); -int dhcp6_configure(Link *link); -int dhcp6_request_address(Link *link, int ir); -int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link); - int link_stop_clients(Link *link, bool may_keep_dhcp); const char* link_state_to_string(LinkState s) _const_; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index ea82268cd5..33b7ec1d6c 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -21,8 +21,10 @@ #include "local-addresses.h" #include "netlink-util.h" #include "network-internal.h" +#include "networkd-dhcp6.h" #include "networkd-link-bus.h" #include "networkd-manager.h" +#include "networkd-network-bus.h" #include "networkd-speed-meter.h" #include "ordered-set.h" #include "path-util.h" @@ -1313,126 +1315,6 @@ static int manager_dirty_handler(sd_event_source *s, void *userdata) { return 1; } -Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr) { - assert_return(m, NULL); - assert_return(addr, NULL); - - return hashmap_get(m->dhcp6_prefixes, addr); -} - -static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { - int r; - - assert(link); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m"); - - return 0; -} - -int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) { - _cleanup_free_ struct in6_addr *a = NULL; - _cleanup_free_ char *buf = NULL; - Link *assigned_link; - Route *route; - int r; - - assert_return(m, -EINVAL); - assert_return(addr, -EINVAL); - - r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64, - 0, 0, 0, &route); - if (r < 0) - return r; - - r = route_configure(route, link, dhcp6_route_add_handler); - if (r < 0) - return r; - - (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); - log_link_debug(link, "Adding prefix route %s/64", strnull(buf)); - - assigned_link = hashmap_get(m->dhcp6_prefixes, addr); - if (assigned_link) { - assert(assigned_link == link); - return 0; - } - - a = newdup(struct in6_addr, addr, 1); - if (!a) - return -ENOMEM; - - r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(m->dhcp6_prefixes, a, link); - if (r < 0) - return r; - - TAKE_PTR(a); - link_ref(link); - return 0; -} - -static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { - int r; - - assert(link); - - r = sd_netlink_message_get_errno(m); - if (r < 0) - log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m"); - - return 1; -} - -static int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) { - _cleanup_free_ struct in6_addr *a = NULL; - _cleanup_(link_unrefp) Link *l = NULL; - _cleanup_free_ char *buf = NULL; - Route *route; - int r; - - assert_return(m, -EINVAL); - assert_return(addr, -EINVAL); - - l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a); - if (!l) - return -EINVAL; - - (void) sd_radv_remove_prefix(l->radv, addr, 64); - r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route); - if (r < 0) - return r; - - r = route_remove(route, l, dhcp6_route_remove_handler); - if (r < 0) - return r; - - (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); - log_link_debug(l, "Removing prefix route %s/64", strnull(buf)); - - return 0; -} - -int manager_dhcp6_prefix_remove_all(Manager *m, Link *link) { - struct in6_addr *addr; - Iterator i; - Link *l; - - assert_return(m, -EINVAL); - assert_return(link, -EINVAL); - - HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i) - if (l == link) - (void) manager_dhcp6_prefix_remove(m, addr); - - return 0; -} - int manager_new(Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -1505,7 +1387,7 @@ void manager_free(Manager *m) { free(m->state_file); while ((a = hashmap_first_key(m->dhcp6_prefixes))) - (void) manager_dhcp6_prefix_remove(m, a); + (void) dhcp6_prefix_remove(m, a); hashmap_free(m->dhcp6_prefixes); while ((link = hashmap_steal_first(m->links))) { diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index e0ec45aa2f..9b3b05bccc 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -96,8 +96,4 @@ int manager_set_hostname(Manager *m, const char *hostname); int manager_set_timezone(Manager *m, const char *timezone); int manager_request_product_uuid(Manager *m, Link *link); -Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr); -int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link); -int manager_dhcp6_prefix_remove_all(Manager *m, Link *link); - DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 0d2fde2f74..851223a860 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -9,6 +9,7 @@ #include "sd-ndisc.h" #include "missing_network.h" +#include "networkd-dhcp6.h" #include "networkd-ndisc.h" #include "networkd-route.h" #include "strv.h" diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c index e3ba148ce1..a895f72688 100644 --- a/src/network/networkd-network-bus.c +++ b/src/network/networkd-network-bus.c @@ -3,6 +3,7 @@ #include "alloc-util.h" #include "ether-addr-util.h" #include "networkd-manager.h" +#include "networkd-network-bus.h" #include "string-util.h" #include "strv.h" diff --git a/src/network/networkd-network-bus.h b/src/network/networkd-network-bus.h new file mode 100644 index 0000000000..650e145d42 --- /dev/null +++ b/src/network/networkd-network-bus.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +typedef struct Link Link; + +extern const sd_bus_vtable network_vtable[]; + +int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 8d0a596c87..e6723f2e90 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -6,6 +6,10 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "conf-parser.h" #include "network-internal.h" #include "networkd-conf.h" +#include "networkd-dhcp-common.h" +#include "networkd-dhcp-server.h" +#include "networkd-dhcp4.h" +#include "networkd-ipv4ll.h" #include "networkd-ndisc.h" #include "networkd-network.h" #include "vlan-util.h" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 8b8311058c..0b5205e8e2 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -803,110 +803,6 @@ int config_parse_domains( return 0; } -int config_parse_ipv4ll( - 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) { - - AddressFamilyBoolean *link_local = data; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - /* Note that this is mostly like - * config_parse_address_family_boolean(), except that it - * applies only to IPv4 */ - - r = parse_boolean(rvalue); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse %s=%s, ignoring assignment. " - "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.", - lvalue, rvalue, lvalue); - return 0; - } - - SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r); - - log_syntax(unit, LOG_WARNING, filename, line, 0, - "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.", - lvalue, rvalue, address_family_boolean_to_string(*link_local)); - - return 0; -} - -int config_parse_dhcp( - 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) { - - AddressFamilyBoolean *dhcp = data, s; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - /* Note that this is mostly like - * config_parse_address_family_boolean(), except that it - * understands some old names for the enum values */ - - s = address_family_boolean_from_string(rvalue); - if (s < 0) { - - /* Previously, we had a slightly different enum here, - * support its values for compatibility. */ - - if (streq(rvalue, "none")) - s = ADDRESS_FAMILY_NO; - else if (streq(rvalue, "v4")) - s = ADDRESS_FAMILY_IPV4; - else if (streq(rvalue, "v6")) - s = ADDRESS_FAMILY_IPV6; - else if (streq(rvalue, "both")) - s = ADDRESS_FAMILY_YES; - else { - log_syntax(unit, LOG_ERR, filename, line, 0, - "Failed to parse DHCP option, ignoring: %s", rvalue); - return 0; - } - - log_syntax(unit, LOG_WARNING, filename, line, 0, - "DHCP=%s is deprecated, please use DHCP=%s instead.", - rvalue, address_family_boolean_to_string(s)); - } - - *dhcp = s; - return 0; -} - -static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = { - [DHCP_CLIENT_ID_MAC] = "mac", - [DHCP_CLIENT_ID_DUID] = "duid", - [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier); -DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier, - "Failed to parse client identifier type"); - int config_parse_ipv6token( const char* unit, const char *filename, @@ -1087,220 +983,6 @@ int config_parse_timezone( return free_and_replace(*datap, tz); } -int config_parse_dhcp_server_dns( - 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) { - - Network *n = data; - const char *p = rvalue; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - for (;;) { - _cleanup_free_ char *w = NULL; - union in_addr_union a; - struct in_addr *m; - - r = extract_first_word(&p, &w, NULL, 0); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to extract word, ignoring: %s", rvalue); - return 0; - } - if (r == 0) - break; - - r = in_addr_from_string(AF_INET, w, &a); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse DNS server address '%s', ignoring assignment: %m", w); - continue; - } - - m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_dns++] = a.in; - n->dhcp_server_dns = m; - } - - return 0; -} - -int config_parse_radv_dns( - 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) { - - Network *n = data; - const char *p = rvalue; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - for (;;) { - _cleanup_free_ char *w = NULL; - union in_addr_union a; - - r = extract_first_word(&p, &w, NULL, 0); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to extract word, ignoring: %s", rvalue); - return 0; - } - if (r == 0) - break; - - if (in_addr_from_string(AF_INET6, w, &a) >= 0) { - struct in6_addr *m; - - m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr)); - if (!m) - return log_oom(); - - m[n->n_router_dns++] = a.in6; - n->router_dns = m; - - } else - log_syntax(unit, LOG_ERR, filename, line, 0, - "Failed to parse DNS server address, ignoring: %s", w); - } - - return 0; -} - -int config_parse_radv_search_domains( - 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) { - - Network *n = data; - const char *p = rvalue; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - for (;;) { - _cleanup_free_ char *w = NULL, *idna = NULL; - - r = extract_first_word(&p, &w, NULL, 0); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to extract word, ignoring: %s", rvalue); - return 0; - } - if (r == 0) - break; - - r = dns_name_apply_idna(w, &idna); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to apply IDNA to domain name '%s', ignoring: %m", w); - continue; - } else if (r == 0) - /* transfer ownership to simplify subsequent operations */ - idna = TAKE_PTR(w); - - r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops); - if (r < 0) - return r; - - r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna)); - if (r < 0) - return r; - } - - return 0; -} - -int config_parse_dhcp_server_ntp( - 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) { - - Network *n = data; - const char *p = rvalue; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - for (;;) { - _cleanup_free_ char *w = NULL; - union in_addr_union a; - struct in_addr *m; - - r = extract_first_word(&p, &w, NULL, 0); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to extract word, ignoring: %s", rvalue); - return 0; - } - if (r == 0) - return 0; - - r = in_addr_from_string(AF_INET, w, &a); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse NTP server address '%s', ignoring: %m", w); - continue; - } - - m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_ntp++] = a.in; - n->dhcp_server_ntp = m; - } -} - int config_parse_dns( const char *unit, const char *filename, @@ -1477,250 +1159,6 @@ int config_parse_ntp( return 0; } -int config_parse_dhcp_user_class( - 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) { - - char ***l = data; - int r; - - assert(l); - assert(lvalue); - assert(rvalue); - - if (isempty(rvalue)) { - *l = strv_free(*l); - return 0; - } - - for (;;) { - _cleanup_free_ char *w = NULL; - - r = extract_first_word(&rvalue, &w, NULL, 0); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to split user classes option, ignoring: %s", rvalue); - break; - } - if (r == 0) - break; - - if (strlen(w) > 255) { - log_syntax(unit, LOG_ERR, filename, line, 0, - "%s length is not in the range 1-255, ignoring.", w); - continue; - } - - r = strv_push(l, w); - if (r < 0) - return log_oom(); - - w = NULL; - } - - return 0; -} - -int config_parse_section_route_table( - 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) { - - Network *network = data; - uint32_t rt; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = safe_atou32(rvalue, &rt); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue); - return 0; - } - - if (streq_ptr(section, "DHCP")) { - network->dhcp_route_table = rt; - network->dhcp_route_table_set = true; - } else { /* section is IPv6AcceptRA */ - network->ipv6_accept_ra_route_table = rt; - network->ipv6_accept_ra_route_table_set = true; - } - - return 0; -} - -int config_parse_dhcp_max_attempts( - 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) { - - Network *network = data; - uint64_t a; - int r; - - assert(network); - assert(lvalue); - assert(rvalue); - - if (isempty(rvalue)) { - network->dhcp_max_attempts = 0; - return 0; - } - - if (streq(rvalue, "infinity")) { - network->dhcp_max_attempts = (uint64_t) -1; - return 0; - } - - r = safe_atou64(rvalue, &a); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue); - return 0; - } - - if (a == 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, - "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue); - return 0; - } - - network->dhcp_max_attempts = a; - - return 0; -} - -int config_parse_dhcp_black_listed_ip_address( - 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) { - - Network *network = data; - const char *p; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip); - return 0; - } - - for (p = rvalue;;) { - _cleanup_free_ char *n = NULL; - union in_addr_union ip; - - r = extract_first_word(&p, &n, NULL, 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse DHCP black listed ip address, ignoring assignment: %s", - rvalue); - return 0; - } - if (r == 0) - return 0; - - r = in_addr_from_string(AF_INET, n, &ip); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "DHCP black listed ip address is invalid, ignoring assignment: %s", n); - continue; - } - - r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL); - if (r < 0) - return log_oom(); - - r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr)); - if (r < 0) - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n); - } - - return 0; -} - -DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, - "Failed to parse DHCP use domains setting"); - -static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { - [DHCP_USE_DOMAINS_NO] = "no", - [DHCP_USE_DOMAINS_ROUTE] = "route", - [DHCP_USE_DOMAINS_YES] = "yes", -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); - -int config_parse_iaid(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) { - Network *network = data; - uint32_t iaid; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(network); - - r = safe_atou32(rvalue, &iaid); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Unable to read IAID, ignoring assignment: %s", rvalue); - return 0; - } - - network->iaid = iaid; - network->iaid_set = true; - - return 0; -} - int config_parse_required_for_online( const char *unit, const char *filename, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 2b7cca8bae..72f1b94666 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -6,13 +6,14 @@ #include "condition.h" #include "conf-parser.h" -#include "dhcp-identifier.h" #include "hashmap.h" #include "netdev/bridge.h" #include "netdev/netdev.h" #include "networkd-address-label.h" #include "networkd-address.h" #include "networkd-brvlan.h" +#include "networkd-dhcp-common.h" +#include "networkd-dhcp4.h" #include "networkd-fdb.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-lldp-rx.h" @@ -25,24 +26,6 @@ #include "ordered-set.h" #include "resolve-util.h" -#define DHCP_ROUTE_METRIC 1024 -#define IPV4LL_ROUTE_METRIC 2048 - -#define BRIDGE_VLAN_BITMAP_MAX 4096 -#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32) - -typedef enum DHCPClientIdentifier { - DHCP_CLIENT_ID_MAC, - DHCP_CLIENT_ID_DUID, - /* The following option may not be good for RFC regarding DHCP (3315 and 4361). - * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK - * requires the client id to be set to a custom string, reported at - * https://github.com/systemd/systemd/issues/7828 */ - DHCP_CLIENT_ID_DUID_ONLY, - _DHCP_CLIENT_ID_MAX, - _DHCP_CLIENT_ID_INVALID = -1, -} DHCPClientIdentifier; - typedef enum IPv6PrivacyExtensions { /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ IPV6_PRIVACY_EXTENSIONS_NO, @@ -52,32 +35,6 @@ typedef enum IPv6PrivacyExtensions { _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, } IPv6PrivacyExtensions; -typedef enum DHCPUseDomains { - DHCP_USE_DOMAINS_NO, - DHCP_USE_DOMAINS_YES, - DHCP_USE_DOMAINS_ROUTE, - _DHCP_USE_DOMAINS_MAX, - _DHCP_USE_DOMAINS_INVALID = -1, -} DHCPUseDomains; - -typedef struct DUID { - /* Value of Type in [DHCP] section */ - DUIDType type; - - uint8_t raw_data_len; - uint8_t raw_data[MAX_DUID_LEN]; - usec_t llt_time; -} DUID; - -typedef enum RADVPrefixDelegation { - RADV_PREFIX_DELEGATION_NONE, - RADV_PREFIX_DELEGATION_STATIC, - RADV_PREFIX_DELEGATION_DHCP6, - RADV_PREFIX_DELEGATION_BOTH, - _RADV_PREFIX_DELEGATION_MAX, - _RADV_PREFIX_DELEGATION_INVALID = -1, -} RADVPrefixDelegation; - typedef enum KeepConfiguration { KEEP_CONFIGURATION_NO = 0, KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0, @@ -309,47 +266,22 @@ void network_apply_anonymize_if_set(Network *network); bool network_has_static_ipv6_addresses(Network *network); CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev); -CONFIG_PARSER_PROTOTYPE(config_parse_domains); CONFIG_PARSER_PROTOTYPE(config_parse_tunnel); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp); -CONFIG_PARSER_PROTOTYPE(config_parse_dns); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions); +CONFIG_PARSER_PROTOTYPE(config_parse_domains); +CONFIG_PARSER_PROTOTYPE(config_parse_dns); CONFIG_PARSER_PROTOTYPE(config_parse_hostname); CONFIG_PARSER_PROTOTYPE(config_parse_timezone); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address); -CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); -CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp); CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains); -CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class); CONFIG_PARSER_PROTOTYPE(config_parse_ntp); -CONFIG_PARSER_PROTOTYPE(config_parse_iaid); CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration); -/* Legacy IPv4LL support */ -CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll); const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); -extern const sd_bus_vtable network_vtable[]; - -int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); -int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); - const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; -const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; -DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; - -const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; -RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_; - const char* keep_configuration_to_string(KeepConfiguration i) _const_; KeepConfiguration keep_configuration_from_string(const char *s) _pure_; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index fdbf7cac62..25321aefed 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -6,6 +6,7 @@ #include <netinet/icmp6.h> #include <arpa/inet.h> +#include "dns-domain.h" #include "networkd-address.h" #include "networkd-manager.h" #include "networkd-radv.h" @@ -15,80 +16,6 @@ #include "string-table.h" #include "strv.h" -static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = { - [RADV_PREFIX_DELEGATION_NONE] = "no", - [RADV_PREFIX_DELEGATION_STATIC] = "static", - [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6", - [RADV_PREFIX_DELEGATION_BOTH] = "yes", -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN( - radv_prefix_delegation, - RADVPrefixDelegation, - RADV_PREFIX_DELEGATION_BOTH); - -int config_parse_router_prefix_delegation( - 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) { - - Network *network = userdata; - RADVPrefixDelegation d; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - d = radv_prefix_delegation_from_string(rvalue); - if (d < 0) { - log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue); - return 0; - } - - network->router_prefix_delegation = d; - - return 0; -} - -int config_parse_router_preference(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) { - Network *network = userdata; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - if (streq(rvalue, "high")) - network->router_preference = SD_NDISC_PREFERENCE_HIGH; - else if (STR_IN_SET(rvalue, "medium", "normal", "default")) - network->router_preference = SD_NDISC_PREFERENCE_MEDIUM; - else if (streq(rvalue, "low")) - network->router_preference = SD_NDISC_PREFERENCE_LOW; - else - log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue); - - return 0; -} - void prefix_free(Prefix *prefix) { if (!prefix) return; @@ -515,3 +442,185 @@ int radv_configure(Link *link) { return radv_emit_dns(link); } + +int config_parse_radv_dns( + 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) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + break; + + if (in_addr_from_string(AF_INET6, w, &a) >= 0) { + struct in6_addr *m; + + m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr)); + if (!m) + return log_oom(); + + m[n->n_router_dns++] = a.in6; + n->router_dns = m; + + } else + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse DNS server address, ignoring: %s", w); + } + + return 0; +} + +int config_parse_radv_search_domains( + 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) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL, *idna = NULL; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + break; + + r = dns_name_apply_idna(w, &idna); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to apply IDNA to domain name '%s', ignoring: %m", w); + continue; + } else if (r == 0) + /* transfer ownership to simplify subsequent operations */ + idna = TAKE_PTR(w); + + r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna)); + if (r < 0) + return r; + } + + return 0; +} + +static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = { + [RADV_PREFIX_DELEGATION_NONE] = "no", + [RADV_PREFIX_DELEGATION_STATIC] = "static", + [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6", + [RADV_PREFIX_DELEGATION_BOTH] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN( + radv_prefix_delegation, + RADVPrefixDelegation, + RADV_PREFIX_DELEGATION_BOTH); + +int config_parse_router_prefix_delegation( + 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) { + + Network *network = userdata; + RADVPrefixDelegation d; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + d = radv_prefix_delegation_from_string(rvalue); + if (d < 0) { + log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue); + return 0; + } + + network->router_prefix_delegation = d; + + return 0; +} + +int config_parse_router_preference(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) { + Network *network = userdata; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(rvalue, "high")) + network->router_preference = SD_NDISC_PREFERENCE_HIGH; + else if (STR_IN_SET(rvalue, "medium", "normal", "default")) + network->router_preference = SD_NDISC_PREFERENCE_MEDIUM; + else if (streq(rvalue, "low")) + network->router_preference = SD_NDISC_PREFERENCE_LOW; + else + log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue); + + return 0; +} diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h index 3192bb8b6c..45be083bfe 100644 --- a/src/network/networkd-radv.h +++ b/src/network/networkd-radv.h @@ -12,6 +12,15 @@ typedef struct Prefix Prefix; +typedef enum RADVPrefixDelegation { + RADV_PREFIX_DELEGATION_NONE, + RADV_PREFIX_DELEGATION_STATIC, + RADV_PREFIX_DELEGATION_DHCP6, + RADV_PREFIX_DELEGATION_BOTH, + _RADV_PREFIX_DELEGATION_MAX, + _RADV_PREFIX_DELEGATION_INVALID = -1, +} RADVPrefixDelegation; + struct Prefix { Network *network; NetworkConfigSection *section; @@ -26,11 +35,16 @@ void prefix_free(Prefix *prefix); DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); +int radv_emit_dns(Link *link); +int radv_configure(Link *link); + +const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; +RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_; + CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation); CONFIG_PARSER_PROTOTYPE(config_parse_router_preference); CONFIG_PARSER_PROTOTYPE(config_parse_prefix); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); - -int radv_emit_dns(Link *link); -int radv_configure(Link *link); +CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); +CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index cd31548f94..f79d5b2057 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -7,6 +7,7 @@ #include "in-addr-util.h" #include "missing_network.h" #include "netlink-util.h" +#include "networkd-ipv4ll.h" #include "networkd-manager.h" #include "networkd-route.h" #include "parse-util.h" |