diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 550e5c7f5a..5192bbcc00 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1091,10 +1091,6 @@ static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link log_link_debug(link, "Addresses set"); link->static_addresses_configured = true; link_check_ready(link); - - r = dhcp4_server_configure(link); - if (r < 0) - link_enter_failed(link); } return 1; diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 045c40e9c5..8d88464271 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -15,6 +15,7 @@ #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-network.h" +#include "networkd-queue.h" #include "parse-util.h" #include "socket-netlink.h" #include "string-table.h" @@ -289,7 +290,7 @@ static int dhcp4_server_set_dns_from_resolve_conf(Link *link) { return sd_dhcp_server_set_dns(link->dhcp_server, addresses, n_addresses); } -int dhcp4_server_configure(Link *link) { +static int dhcp4_server_configure(Link *link) { bool acquired_uplink = false; sd_dhcp_option *p; DHCPStaticLease *static_lease; @@ -300,21 +301,18 @@ int dhcp4_server_configure(Link *link) { assert(link); - if (!link_dhcp4_server_enabled(link)) - return 0; + log_link_debug(link, "Configuring DHCP Server."); - if (!(link->flags & IFF_UP)) - return 0; + if (link->dhcp_server) + return -EBUSY; - if (!link->dhcp_server) { - r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex); - if (r < 0) - return r; + r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex); + if (r < 0) + return r; - r = sd_dhcp_server_attach_event(link->dhcp_server, link->manager->event, 0); - if (r < 0) - return r; - } + r = sd_dhcp_server_attach_event(link->dhcp_server, link->manager->event, 0); + if (r < 0) + return r; r = sd_dhcp_server_set_callback(link->dhcp_server, dhcp_server_callback, link); if (r < 0) @@ -455,7 +453,60 @@ int dhcp4_server_configure(Link *link) { log_link_debug(link, "Offering DHCPv4 leases"); } - return 0; + return 1; +} + +int link_request_dhcp_server(Link *link) { + assert(link); + + if (!link_dhcp4_server_enabled(link)) + return 0; + + if (link->dhcp_server) + return 0; + + log_link_debug(link, "Requesting DHCP server."); + return link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, NULL, false, NULL, NULL, NULL); +} + +static bool dhcp_server_is_ready_to_configure(Link *link) { + Address *a; + + assert(link); + + if (!link->network) + return false; + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return false; + + if (!link_has_carrier(link)) + return false; + + if (link->address_remove_messages > 0) + return false; + + if (!link->static_addresses_configured) + return false; + + if (link_find_dhcp_server_address(link, &a) < 0) + return false; + + if (!address_is_ready(a)) + return false; + + return true; +} + +int request_process_dhcp_server(Request *req) { + assert(req); + assert(req->link); + assert(req->type == REQUEST_TYPE_DHCP_SERVER); + + if (!dhcp_server_is_ready_to_configure(req->link)) + return 0; + + return dhcp4_server_configure(req->link); } int config_parse_dhcp_server_relay_agent_suboption( diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h index d58978cc05..a02cd995ec 100644 --- a/src/network/networkd-dhcp-server.h +++ b/src/network/networkd-dhcp-server.h @@ -5,10 +5,12 @@ typedef struct Link Link; typedef struct Network Network; +typedef struct Request Request; void network_adjust_dhcp_server(Network *network); -int dhcp4_server_configure(Link *link); +int link_request_dhcp_server(Link *link); +int request_process_dhcp_server(Request *req); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 97529f6be0..9aa69bdc73 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2122,6 +2122,10 @@ static int link_configure(Link *link) { if (r < 0) return r; + r = link_request_dhcp_server(link); + if (r < 0) + return r; + r = radv_configure(link); if (r < 0) return r; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index cb782c72bc..ca472a6174 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -16,7 +16,6 @@ #include "networkd-dhcp-common.h" #include "networkd-dhcp4.h" #include "networkd-dhcp6.h" -#include "networkd-dhcp-server.h" #include "networkd-lldp-rx.h" #include "networkd-lldp-tx.h" #include "networkd-ndisc.h" diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 8f4fda5da9..758cd4de2a 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -2,6 +2,7 @@ #include "networkd-address.h" #include "networkd-bridge-fdb.h" +#include "networkd-dhcp-server.h" #include "networkd-manager.h" #include "networkd-neighbor.h" #include "networkd-nexthop.h" @@ -17,6 +18,8 @@ static void request_free_object(RequestType type, void *object) { case REQUEST_TYPE_BRIDGE_FDB: bridge_fdb_free(object); break; + case REQUEST_TYPE_DHCP_SERVER: + break; case REQUEST_TYPE_NEIGHBOR: neighbor_free(object); break; @@ -73,8 +76,10 @@ int link_queue_request( assert(link); assert(link->manager); assert(type >= 0 && type < _REQUEST_TYPE_MAX); - assert(object); - assert(netlink_handler); + if (type != REQUEST_TYPE_DHCP_SERVER) { + assert(object); + assert(netlink_handler); + } req = new(Request, 1); if (!req) { @@ -126,6 +131,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) { case REQUEST_TYPE_BRIDGE_FDB: r = request_process_bridge_fdb(req); break; + case REQUEST_TYPE_DHCP_SERVER: + r = request_process_dhcp_server(req); + break; case REQUEST_TYPE_NEIGHBOR: r = request_process_neighbor(req); break; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 343fe067ae..9eab751da4 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -20,6 +20,7 @@ typedef void (*request_on_free_handler_t)(Request*); typedef enum RequestType { REQUEST_TYPE_ADDRESS, REQUEST_TYPE_BRIDGE_FDB, + REQUEST_TYPE_DHCP_SERVER, REQUEST_TYPE_NEIGHBOR, REQUEST_TYPE_NEXTHOP, REQUEST_TYPE_ROUTE,