diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-14 20:27:33 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-05-18 20:20:24 +0900 |
commit | 0017ba3165f69e8afb7f73127281bb9a7e5b5641 (patch) | |
tree | 289177e5396d359a86a84aaca0179fe49bd8e1f0 /src/network/networkd-dhcp-server.c | |
parent | 998545a7d9607b49facd0e9868b893ac24942c51 (diff) | |
download | systemd-0017ba3165f69e8afb7f73127281bb9a7e5b5641.tar.gz |
network: dhcp-server: introduce ServerAddress= setting
This may be useful when the link which DHCP server running on has
multiple static addresses.
Diffstat (limited to 'src/network/networkd-dhcp-server.c')
-rw-r--r-- | src/network/networkd-dhcp-server.c | 118 |
1 files changed, 99 insertions, 19 deletions
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 07d6eb95d1..0a396a957f 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -29,33 +29,70 @@ static bool link_dhcp4_server_enabled(Link *link) { if (!link->network) return false; - if (link->network->bond) - return false; - if (link->iftype == ARPHRD_CAN) return false; return link->network->dhcp_server; } -static Address* link_find_dhcp_server_address(Link *link) { +void network_adjust_dhcp_server(Network *network) { + assert(network); + + if (!network->dhcp_server) + return; + + if (network->bond) { + log_warning("%s: DHCPServer= is enabled for bond slave. Disabling DHCP server.", + network->filename); + network->dhcp_server = false; + return; + } + + if (!in4_addr_is_set(&network->dhcp_server_address)) { + Address *address; + bool have = false; + + ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section) { + if (section_is_invalid(address->section)) + continue; + if (address->family == AF_INET && + !in4_addr_is_localhost(&address->in_addr.in) && + in4_addr_is_null(&address->in_addr_peer.in)) { + have = true; + break; + } + } + if (!have) { + log_warning("%s: DHCPServer= is enabled, but no static address configured. " + "Disabling DHCP server.", + network->filename); + network->dhcp_server = false; + return; + } + } +} + +static int link_find_dhcp_server_address(Link *link, Address **ret) { Address *address; assert(link); assert(link->network); - /* The first statically configured address if there is any */ - ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section) - if (address->family == AF_INET && - in_addr_is_set(address->family, &address->in_addr)) - return address; + /* If ServerAddress= is specified, then use the address. */ + if (in4_addr_is_set(&link->network->dhcp_server_address)) + return link_get_ipv4_address(link, &link->network->dhcp_server_address, + link->network->dhcp_server_address_prefixlen, ret); - /* If that didn't work, find a suitable address we got from the pool */ - SET_FOREACH(address, link->pool_addresses) - if (address->family == AF_INET) - return address; + /* If not, then select one from static addresses. */ + SET_FOREACH(address, link->static_addresses) + if (address->family == AF_INET && + !in4_addr_is_localhost(&address->in_addr.in) && + in4_addr_is_null(&address->in_addr_peer.in)) { + *ret = address; + return 0; + } - return NULL; + return -ENOENT; } static int link_push_uplink_to_dhcp_server( @@ -277,10 +314,9 @@ int dhcp4_server_configure(Link *link) { if (r < 0) return log_link_warning_errno(link, r, "Failed to set callback for DHCPv4 server instance: %m"); - address = link_find_dhcp_server_address(link); - if (!address) - return log_link_error_errno(link, SYNTHETIC_ERRNO(EBUSY), - "Failed to find suitable address for DHCPv4 server instance."); + r = link_find_dhcp_server_address(link, &address); + if (r < 0) + return log_link_error_errno(link, r, "Failed to find suitable address for DHCPv4 server instance: %m"); /* use the server address' subnet as the pool */ r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen, @@ -429,7 +465,6 @@ int config_parse_dhcp_server_relay_agent_suboption( assert(lvalue); assert(rvalue); - if (isempty(rvalue)) { *suboption_value = mfree(*suboption_value); return 0; @@ -492,3 +527,48 @@ int config_parse_dhcp_server_emit( emit->addresses[emit->n_addresses++] = a.in; } } + +int config_parse_dhcp_server_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 = userdata; + union in_addr_union a; + unsigned char prefixlen; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + network->dhcp_server_address = (struct in_addr) {}; + network->dhcp_server_address_prefixlen = 0; + return 0; + } + + r = in_addr_prefix_from_string(rvalue, AF_INET, &a, &prefixlen); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + if (in4_addr_is_null(&a.in) || in4_addr_is_localhost(&a.in)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "DHCP server address cannot be the ANY address or a localhost address, " + "ignoring assignment: %s", rvalue); + return 0; + } + + network->dhcp_server_address = a.in; + network->dhcp_server_address_prefixlen = prefixlen; + return 0; +} |