diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 506238f391..da9a1794b7 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -96,7 +96,7 @@ static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message } static int address_label_configure(AddressLabel *label, Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(label); @@ -106,29 +106,48 @@ static int address_label_configure(AddressLabel *label, Link *link, link_netlink assert(link->manager->rtnl); assert(callback); - r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL, + r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &m, RTM_NEWADDRLABEL, link->ifindex, AF_INET6); if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m"); + return r; - r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen); + r = sd_rtnl_message_addrlabel_set_prefixlen(m, label->prefixlen); if (r < 0) - return log_link_error_errno(link, r, "Could not set prefixlen: %m"); + return r; - r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label); + r = sd_netlink_message_append_u32(m, IFAL_LABEL, label->label); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFAL_LABEL attribute: %m"); + return r; - r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->prefix); + r = sd_netlink_message_append_in6_addr(m, IFA_ADDRESS, &label->prefix); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); + return r; - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + return r; link_ref(link); + return 0; +} + +int request_process_address_label(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->label); + assert(req->type == REQUEST_TYPE_ADDRESS_LABEL); + + link = ASSERT_PTR(req->link); + + if (!link_is_ready_to_configure(link, false)) + return 0; + + r = address_label_configure(req->label, link, req->netlink_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure address label: %m"); return 1; } @@ -160,18 +179,6 @@ int link_request_static_address_labels(Link *link) { return 0; } -int request_process_address_label(Request *req) { - assert(req); - assert(req->link); - assert(req->label); - assert(req->type == REQUEST_TYPE_ADDRESS_LABEL); - - if (!link_is_ready_to_configure(req->link, false)) - return 0; - - return address_label_configure(req->label, req->link, req->netlink_handler); -} - static int address_label_section_verify(AddressLabel *label) { assert(label); assert(label->section); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index d577926a7c..f9d8e9bb6c 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -656,36 +656,36 @@ static void log_address_debug(const Address *address, const char *str, const Lin strna(flags_str), strna(scope_str)); } -static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) { +static int address_set_netlink_message(const Address *address, sd_netlink_message *m, Link *link) { uint32_t flags; int r; assert(address); - assert(req); + assert(m); assert(link); - r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); + r = sd_rtnl_message_addr_set_prefixlen(m, address->prefixlen); if (r < 0) - return log_link_error_errno(link, r, "Could not set prefixlen: %m"); + return r; /* On remove, only IFA_F_MANAGETEMPADDR flag for IPv6 addresses are used. But anyway, set all * flags except tentative flag here unconditionally. Without setting the flag, the template * addresses generated by kernel will not be removed automatically when the main address is * removed. */ flags = address->flags & ~IFA_F_TENTATIVE; - r = sd_rtnl_message_addr_set_flags(req, flags & 0xff); + r = sd_rtnl_message_addr_set_flags(m, flags & 0xff); if (r < 0) - return log_link_error_errno(link, r, "Could not set flags: %m"); + return r; if ((flags & ~0xff) != 0) { - r = sd_netlink_message_append_u32(req, IFA_FLAGS, flags); + r = sd_netlink_message_append_u32(m, IFA_FLAGS, flags); if (r < 0) - return log_link_error_errno(link, r, "Could not set extended flags: %m"); + return r; } - r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr); + r = netlink_message_append_in_addr_union(m, IFA_LOCAL, address->family, &address->in_addr); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m"); + return r; return 0; } @@ -707,7 +707,7 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link } int address_remove(Address *address) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; Link *link; int r; @@ -722,20 +722,20 @@ int address_remove(Address *address) { log_address_debug(address, "Removing", link); - r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR, + r = sd_rtnl_message_new_addr(link->manager->rtnl, &m, RTM_DELADDR, link->ifindex, address->family); if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m"); + return log_link_warning_errno(link, r, "Could not allocate RTM_DELADDR message: %m"); - r = address_set_netlink_message(address, req, link); + r = address_set_netlink_message(address, m, link); if (r < 0) - return r; + return log_link_warning_errno(link, r, "Could not set netlink attributes: %m"); - r = netlink_call_async(link->manager->rtnl, NULL, req, + r = netlink_call_async(link->manager->rtnl, NULL, m, address_remove_handler, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); @@ -1025,7 +1025,7 @@ static int address_configure( Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(address); @@ -1038,89 +1038,87 @@ static int address_configure( log_address_debug(address, "Configuring", link); - r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req, - link->ifindex, address->family); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m"); - - r = address_set_netlink_message(address, req, link); + r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &m, link->ifindex, address->family); if (r < 0) return r; - r = sd_rtnl_message_addr_set_scope(req, address->scope); + r = address_set_netlink_message(address, m, link); if (r < 0) - return log_link_error_errno(link, r, "Could not set scope: %m"); + return r; + + r = sd_rtnl_message_addr_set_scope(m, address->scope); + if (r < 0) + return r; if (in_addr_is_set(address->family, &address->in_addr_peer)) { - r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer); + r = netlink_message_append_in_addr_union(m, IFA_ADDRESS, address->family, &address->in_addr_peer); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); + return r; } else if (in4_addr_is_set(&address->broadcast)) { - r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); + r = sd_netlink_message_append_in_addr(m, IFA_BROADCAST, &address->broadcast); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m"); + return r; } if (address->family == AF_INET && address->label) { - r = sd_netlink_message_append_string(req, IFA_LABEL, address->label); + r = sd_netlink_message_append_string(m, IFA_LABEL, address->label); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m"); + return r; } - r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, + r = sd_netlink_message_append_cache_info(m, IFA_CACHEINFO, address_set_cinfo(address, &(struct ifa_cacheinfo) {})); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m"); + return r; - r = sd_netlink_message_append_u32(req, IFA_RT_PRIORITY, address->route_metric); + r = sd_netlink_message_append_u32(m, IFA_RT_PRIORITY, address->route_metric); if (r < 0) - return log_link_error_errno(link, r, "Could not append IFA_RT_PRIORITY attribute: %m"); + return r; - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link); + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + return r; link_ref(link); return 0; } -void address_cancel_request(Address *address) { - Request req; - +static bool address_is_ready_to_configure(Link *link, const Address *address) { + assert(link); assert(address); - assert(address->link); - if (!address_is_requesting(address)) - return; + if (!link_is_ready_to_configure(link, false)) + return false; - req = (Request) { - .link = address->link, - .type = REQUEST_TYPE_ADDRESS, - .address = address, - }; + if (FLAGS_SET(address->state, NETWORK_CONFIG_STATE_PROBING)) + return false; - request_drop(ordered_set_get(address->link->manager->request_queue, &req)); - address_cancel_requesting(address); + /* Refuse adding more than the limit */ + if (set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX) + return false; + + return true; } -static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { +int request_process_address(Request *req) { + Address *address; + Link *link; int r; - assert(link); - assert(link->static_address_messages > 0); + assert(req); + assert(req->type == REQUEST_TYPE_ADDRESS); - link->static_address_messages--; + address = ASSERT_PTR(req->address); + link = ASSERT_PTR(req->link); - r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address"); - if (r <= 0) - return r; + if (!address_is_ready_to_configure(link, address)) + return 0; - if (link->static_address_messages == 0) { - log_link_debug(link, "Addresses set"); - link->static_addresses_configured = true; - link_check_ready(link); - } + r = address_configure(address, link, req->netlink_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure address: %m"); + address_enter_configuring(address); return 1; } @@ -1210,6 +1208,27 @@ int link_request_address( return 1; } +static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->static_address_messages > 0); + + link->static_address_messages--; + + r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address"); + if (r <= 0) + return r; + + if (link->static_address_messages == 0) { + log_link_debug(link, "Addresses set"); + link->static_addresses_configured = true; + link_check_ready(link); + } + + return 1; +} + int link_request_static_address(Link *link, Address *address, bool consume) { assert(link); assert(address); @@ -1253,49 +1272,23 @@ int link_request_static_addresses(Link *link) { return 0; } -static bool address_is_ready_to_configure(Link *link, const Address *address) { - assert(link); +void address_cancel_request(Address *address) { + Request req; + assert(address); + assert(address->link); - if (!link_is_ready_to_configure(link, false)) - return false; + if (!address_is_requesting(address)) + return; - if (FLAGS_SET(address->state, NETWORK_CONFIG_STATE_PROBING)) - return false; + req = (Request) { + .link = address->link, + .type = REQUEST_TYPE_ADDRESS, + .address = address, + }; - /* Refuse adding more than the limit */ - if (set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX) - return false; - - return true; -} - -int request_process_address(Request *req) { - Address *existing; - Link *link; - int r; - - assert(req); - assert(req->link); - assert(req->address); - assert(req->type == REQUEST_TYPE_ADDRESS); - - link = req->link; - - r = address_get(link, req->address, &existing); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to get address: %m"); - - if (!address_is_ready_to_configure(link, existing)) - return 0; - - r = address_configure(req->address, link, req->netlink_handler); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to configure address: %m"); - - address_enter_configuring(existing); - - return 1; + request_drop(ordered_set_get(address->link->manager->request_queue, &req)); + address_cancel_requesting(address); } int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { diff --git a/src/network/networkd-bridge-fdb.c b/src/network/networkd-bridge-fdb.c index c1e2977d4d..b09b2ad735 100644 --- a/src/network/networkd-bridge-fdb.c +++ b/src/network/networkd-bridge-fdb.c @@ -168,30 +168,29 @@ static int bridge_fdb_configure_message(const BridgeFDB *fdb, Link *link, sd_net return 0; } -int link_request_static_bridge_fdb(Link *link) { - BridgeFDB *fdb; +static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; + assert(fdb); assert(link); - assert(link->network); + assert(link->manager); + assert(callback); - link->static_bridge_fdb_configured = false; + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE); + if (r < 0) + return r; - HASHMAP_FOREACH(fdb, link->network->bridge_fdb_entries_by_section) { - r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false, - &link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Failed to request static bridge FDB entry: %m"); - } + r = bridge_fdb_configure_message(fdb, link, m); + if (r < 0) + return r; - if (link->static_bridge_fdb_messages == 0) { - link->static_bridge_fdb_configured = true; - link_check_ready(link); - } else { - log_link_debug(link, "Setting bridge FDB entries"); - link_set_state(link, LINK_STATE_CONFIGURING); - } + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, + link_netlink_destroy_callback, link); + if (r < 0) + return r; + link_ref(link); return 0; } @@ -221,38 +220,52 @@ static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) { } int request_process_bridge_fdb(Request *req) { + BridgeFDB *fdb; Link *link; int r; assert(req); - assert(req->fdb); assert(req->type == REQUEST_TYPE_BRIDGE_FDB); assert_se(link = req->link); + assert_se(fdb = req->fdb); - if (!bridge_fdb_is_ready_to_configure(req->fdb, link)) + if (!bridge_fdb_is_ready_to_configure(fdb, link)) return 0; - /* create new RTM message */ - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE); + r = bridge_fdb_configure(fdb, link, req->netlink_handler); if (r < 0) - return log_link_error_errno(link, r, "Could not allocate netlink message: %m"); - - r = bridge_fdb_configure_message(req->fdb, link, m); - if (r < 0) - return log_link_error_errno(link, r, "Could not create netlink message: %m"); - - /* send message to the kernel to update its internal static MAC table. */ - r = netlink_call_async(link->manager->rtnl, NULL, m, req->netlink_handler, - link_netlink_destroy_callback, link); - if (r < 0) - return log_link_error_errno(link, r, "Could not send netlink message: %m"); - - link_ref(link); + return log_link_warning_errno(link, r, "Failed to configure bridge FDB: %m"); return 1; } +int link_request_static_bridge_fdb(Link *link) { + BridgeFDB *fdb; + int r; + + assert(link); + assert(link->network); + + link->static_bridge_fdb_configured = false; + + HASHMAP_FOREACH(fdb, link->network->bridge_fdb_entries_by_section) { + r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false, + &link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Failed to request static bridge FDB entry: %m"); + } + + if (link->static_bridge_fdb_messages == 0) { + link->static_bridge_fdb_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting bridge FDB entries"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + void network_drop_invalid_bridge_fdb_entries(Network *network) { BridgeFDB *fdb; diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index d155090ad1..bf9e49ae39 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -115,7 +115,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, /* send a request to the kernel to add an MDB entry */ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; struct br_mdb_entry entry; int r; @@ -156,22 +156,71 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message assert_not_reached(); } - /* create new RTM message */ - r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB, + r = sd_rtnl_message_new_mdb(link->manager->rtnl, &m, RTM_NEWMDB, link->master_ifindex > 0 ? link->master_ifindex : link->ifindex); if (r < 0) - return log_link_error_errno(link, r, "Could not create RTM_NEWMDB message: %m"); + return r; - r = sd_netlink_message_append_data(req, MDBA_SET_ENTRY, &entry, sizeof(entry)); + r = sd_netlink_message_append_data(m, MDBA_SET_ENTRY, &entry, sizeof(entry)); if (r < 0) - return log_link_error_errno(link, r, "Could not append MDBA_SET_ENTRY attribute: %m"); + return r; - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + return r; link_ref(link); + return 0; +} + +static bool bridge_mdb_is_ready_to_configure(Link *link) { + Link *master; + + assert(link); + + if (!link_is_ready_to_configure(link, false)) + return false; + + if (!link->master_set) + return false; + + if (link->master_ifindex <= 0 && streq_ptr(link->kind, "bridge")) + return true; /* The interface is bridge master. */ + + if (link_get_master(link, &master) < 0) + return false; + + if (!streq_ptr(master->kind, "bridge")) + return false; + + if (!IN_SET(master->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return false; + + if (master->set_flags_messages > 0) + return false; + + if (!link_has_carrier(master)) + return false; + + return true; +} + +int request_process_bridge_mdb(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->mdb); + assert(req->type == REQUEST_TYPE_BRIDGE_MDB); + assert_se(link = req->link); + + if (!bridge_mdb_is_ready_to_configure(link)) + return 0; + + r = bridge_mdb_configure(req->mdb, link, req->netlink_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure bridge MDB: %m"); return 1; } @@ -210,48 +259,6 @@ finish: return 0; } -static bool bridge_mdb_is_ready_to_configure(Link *link) { - Link *master; - - if (!link_is_ready_to_configure(link, false)) - return false; - - if (!link->master_set) - return false; - - if (link->master_ifindex <= 0 && streq_ptr(link->kind, "bridge")) - return true; /* The interface is bridge master. */ - - if (link_get_master(link, &master) < 0) - return false; - - if (!streq_ptr(master->kind, "bridge")) - return false; - - if (!IN_SET(master->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) - return false; - - if (master->set_flags_messages > 0) - return false; - - if (!link_has_carrier(master)) - return false; - - return true; -} - -int request_process_bridge_mdb(Request *req) { - assert(req); - assert(req->link); - assert(req->mdb); - assert(req->type == REQUEST_TYPE_BRIDGE_MDB); - - if (!bridge_mdb_is_ready_to_configure(req->link)) - return 0; - - return bridge_mdb_configure(req->mdb, req->link, req->netlink_handler); -} - static int bridge_mdb_verify(BridgeMDB *mdb) { if (section_is_invalid(mdb->section)) return -EINVAL; diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index c4eaac3dee..795ad686af 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -528,21 +528,7 @@ static int dhcp4_server_configure(Link *link) { return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m"); log_link_debug(link, "Offering DHCPv4 leases"); - - 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); + return 0; } static bool dhcp_server_is_ready_to_configure(Link *link) { @@ -582,14 +568,40 @@ static bool dhcp_server_is_ready_to_configure(Link *link) { } int request_process_dhcp_server(Request *req) { - assert(req); - assert(req->link); - assert(req->type == REQUEST_TYPE_DHCP_SERVER); + Link *link; + int r; - if (!dhcp_server_is_ready_to_configure(req->link)) + assert(req); + assert(req->type == REQUEST_TYPE_DHCP_SERVER); + assert_se(link = req->link); + + if (!dhcp_server_is_ready_to_configure(link)) return 0; - return dhcp4_server_configure(req->link); + r = dhcp4_server_configure(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure DHCP server: %m"); + + return 1; +} + +int link_request_dhcp_server(Link *link) { + int r; + + assert(link); + + if (!link_dhcp4_server_enabled(link)) + return 0; + + if (link->dhcp_server) + return 0; + + log_link_debug(link, "Requesting DHCP server."); + r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, NULL, false, NULL, NULL, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to request configuration of DHCP server: %m"); + + return 0; } int config_parse_dhcp_server_relay_agent_suboption( diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c index a332eaefac..22a75bf56b 100644 --- a/src/network/networkd-ipv6-proxy-ndp.c +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -53,7 +53,7 @@ static int ipv6_proxy_ndp_address_configure( Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(address); @@ -63,24 +63,42 @@ static int ipv6_proxy_ndp_address_configure( assert(callback); /* create new netlink message */ - r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6); + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_INET6); if (r < 0) - return log_link_error_errno(link, r, "Could not create RTM_NEWNEIGH message: %m"); + return r; - r = sd_rtnl_message_neigh_set_flags(req, NTF_PROXY); + r = sd_rtnl_message_neigh_set_flags(m, NTF_PROXY); if (r < 0) - return log_link_error_errno(link, r, "Could not set neighbor flags: %m"); + return r; - r = sd_netlink_message_append_in6_addr(req, NDA_DST, address); + r = sd_netlink_message_append_in6_addr(m, NDA_DST, address); if (r < 0) - return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); + return r; - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + return r; link_ref(link); + return 0; +} + +int request_process_ipv6_proxy_ndp_address(Request *req) { + Link *link; + int r; + + assert(req); + assert(req->ipv6_proxy_ndp); + assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP); + assert_se(link = req->link); + + if (!link_is_ready_to_configure(link, false)) + return 0; + + r = ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, link, req->netlink_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure IPv6 proxy NDP address: %m"); return 1; } @@ -113,18 +131,6 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) { return 0; } -int request_process_ipv6_proxy_ndp_address(Request *req) { - assert(req); - assert(req->link); - assert(req->ipv6_proxy_ndp); - assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP); - - if (!link_is_ready_to_configure(req->link, false)) - return 0; - - return ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, req->link, req->netlink_handler); -} - int config_parse_ipv6_proxy_ndp_address( const char *unit, const char *filename, diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c index 4f13053082..8887389807 100644 --- a/src/network/networkd-neighbor.c +++ b/src/network/networkd-neighbor.c @@ -198,7 +198,7 @@ static int neighbor_configure( Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(neighbor); @@ -210,24 +210,45 @@ static int neighbor_configure( log_neighbor_debug(neighbor, "Configuring", link); - r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, neighbor->family); if (r < 0) - return log_link_error_errno(link, r, "Could not allocate netlink message: %m"); + return r; - r = neighbor_configure_message(neighbor, link, req); + r = neighbor_configure_message(neighbor, link, m); if (r < 0) - return log_link_error_errno(link, r, "Could not create netlink message: %m"); + return r; - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send netlink message: %m"); + return r; link_ref(link); + return 0; +} + +int request_process_neighbor(Request *req) { + Neighbor *neighbor; + Link *link; + int r; + + assert(req); + assert(req->type == REQUEST_TYPE_NEIGHBOR); + + neighbor = ASSERT_PTR(req->neighbor); + link = ASSERT_PTR(req->link); + + if (!link_is_ready_to_configure(link, false)) + return 0; + + r = neighbor_configure(neighbor, link, req->netlink_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure neighbor: %m"); + neighbor_enter_configuring(neighbor); - return r; + return 1; } static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -448,24 +469,6 @@ void link_foreignize_neighbors(Link *link) { neighbor->source = NETWORK_CONFIG_SOURCE_FOREIGN; } -int request_process_neighbor(Request *req) { - int r; - - assert(req); - assert(req->link); - assert(req->neighbor); - assert(req->type == REQUEST_TYPE_NEIGHBOR); - - if (!link_is_ready_to_configure(req->link, false)) - return 0; - - r = neighbor_configure(req->neighbor, req->link, req->netlink_handler); - if (r < 0) - return r; - - return 1; -} - int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(neighbor_freep) Neighbor *tmp = NULL; Neighbor *neighbor = NULL; diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c index f2049fa50a..07596821d0 100644 --- a/src/network/networkd-nexthop.c +++ b/src/network/networkd-nexthop.c @@ -430,7 +430,7 @@ static int nexthop_configure( Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(link); @@ -442,16 +442,14 @@ static int nexthop_configure( log_nexthop_debug(nexthop, "Configuring", link); - r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req, - RTM_NEWNEXTHOP, nexthop->family, - nexthop->protocol); + r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &m, RTM_NEWNEXTHOP, nexthop->family, nexthop->protocol); if (r < 0) - return log_link_error_errno(link, r, "Could not create RTM_NEWNEXTHOP message: %m"); + return r; if (nexthop->id > 0) { - r = sd_netlink_message_append_u32(req, NHA_ID, nexthop->id); + r = sd_netlink_message_append_u32(m, NHA_ID, nexthop->id); if (r < 0) - return log_link_error_errno(link, r, "Could not append NHA_ID attribute: %m"); + return r; } if (!hashmap_isempty(nexthop->group)) { @@ -466,38 +464,36 @@ static int nexthop_configure( HASHMAP_FOREACH(nhg, nexthop->group) *p++ = *nhg; - r = sd_netlink_message_append_data(req, NHA_GROUP, group, sizeof(struct nexthop_grp) * hashmap_size(nexthop->group)); + r = sd_netlink_message_append_data(m, NHA_GROUP, group, sizeof(struct nexthop_grp) * hashmap_size(nexthop->group)); if (r < 0) - return log_link_error_errno(link, r, "Could not append NHA_GROUP attribute: %m"); + return r; } else if (nexthop->blackhole) { - r = sd_netlink_message_append_flag(req, NHA_BLACKHOLE); + r = sd_netlink_message_append_flag(m, NHA_BLACKHOLE); if (r < 0) - return log_link_error_errno(link, r, "Could not append NHA_BLACKHOLE attribute: %m"); + return r; } else { - r = sd_netlink_message_append_u32(req, NHA_OIF, link->ifindex); + r = sd_netlink_message_append_u32(m, NHA_OIF, link->ifindex); if (r < 0) - return log_link_error_errno(link, r, "Could not append NHA_OIF attribute: %m"); + return r; if (in_addr_is_set(nexthop->family, &nexthop->gw)) { - r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw); + r = netlink_message_append_in_addr_union(m, NHA_GATEWAY, nexthop->family, &nexthop->gw); if (r < 0) - return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m"); + return r; - r = sd_rtnl_message_nexthop_set_flags(req, nexthop->flags & RTNH_F_ONLINK); + r = sd_rtnl_message_nexthop_set_flags(m, nexthop->flags & RTNH_F_ONLINK); if (r < 0) - return log_link_error_errno(link, r, "Failed to set nexthop flags: %m"); + return r; } } - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + return r; link_ref(link); - - nexthop_enter_configuring(nexthop); return 0; } @@ -528,6 +524,72 @@ static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link return 1; } +static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) { + struct nexthop_grp *nhg; + + assert(link); + assert(nexthop); + + if (!link_is_ready_to_configure(link, false)) + return false; + + if (nexthop_owned_by_link(nexthop)) { + /* TODO: fdb nexthop does not require IFF_UP. The conditions below needs to be updated + * when fdb nexthop support is added. See rtm_to_nh_config() in net/ipv4/nexthop.c of + * kernel. */ + if (link->set_flags_messages > 0) + return false; + if (!FLAGS_SET(link->flags, IFF_UP)) + return false; + } + + /* All group members must be configured first. */ + HASHMAP_FOREACH(nhg, nexthop->group) { + NextHop *g; + + if (manager_get_nexthop_by_id(link->manager, nhg->id, &g) < 0) + return false; + + if (!nexthop_exists(g)) + return false; + } + + if (nexthop->id == 0) { + Request *req; + + ORDERED_SET_FOREACH(req, link->manager->request_queue) { + if (req->type != REQUEST_TYPE_NEXTHOP) + continue; + if (req->nexthop->id != 0) + return false; /* first configure nexthop with id. */ + } + } + + return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw); +} + +int request_process_nexthop(Request *req) { + NextHop *nexthop; + Link *link; + int r; + + assert(req); + assert(req->type == REQUEST_TYPE_NEXTHOP); + + nexthop = ASSERT_PTR(req->nexthop); + link = ASSERT_PTR(req->link); + + if (!nexthop_is_ready_to_configure(link, nexthop)) + return 0; + + r = nexthop_configure(nexthop, link, req->netlink_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure nexthop"); + + nexthop_enter_configuring(nexthop); + return 1; +} + static int link_request_nexthop( Link *link, NextHop *nexthop, @@ -763,68 +825,6 @@ void link_foreignize_nexthops(Link *link) { } } -static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) { - struct nexthop_grp *nhg; - - assert(link); - assert(nexthop); - - if (!link_is_ready_to_configure(link, false)) - return false; - - if (nexthop_owned_by_link(nexthop)) { - /* TODO: fdb nexthop does not require IFF_UP. The conditions below needs to be updated - * when fdb nexthop support is added. See rtm_to_nh_config() in net/ipv4/nexthop.c of - * kernel. */ - if (link->set_flags_messages > 0) - return false; - if (!FLAGS_SET(link->flags, IFF_UP)) - return false; - } - - /* All group members must be configured first. */ - HASHMAP_FOREACH(nhg, nexthop->group) { - NextHop *g; - - if (manager_get_nexthop_by_id(link->manager, nhg->id, &g) < 0) - return false; - - if (!nexthop_exists(g)) - return false; - } - - if (nexthop->id == 0) { - Request *req; - - ORDERED_SET_FOREACH(req, link->manager->request_queue) { - if (req->type != REQUEST_TYPE_NEXTHOP) - continue; - if (req->nexthop->id != 0) - return false; /* first configure nexthop with id. */ - } - } - - return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw); -} - -int request_process_nexthop(Request *req) { - int r; - - assert(req); - assert(req->link); - assert(req->nexthop); - assert(req->type == REQUEST_TYPE_NEXTHOP); - - if (!nexthop_is_ready_to_configure(req->link, req->nexthop)) - return 0; - - r = nexthop_configure(req->nexthop, req->link, req->netlink_handler); - if (r < 0) - return r; - - return 1; -} - int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { _cleanup_(nexthop_freep) NextHop *tmp = NULL; _cleanup_free_ void *raw_group = NULL; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 3a2e4490c1..cb40e3f1ae 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1166,7 +1166,7 @@ static int route_configure( Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; int r; assert(route); @@ -1179,279 +1179,93 @@ static int route_configure( log_route_debug(route, "Configuring", link, link->manager); - r = sd_rtnl_message_new_route(link->manager->rtnl, &req, - RTM_NEWROUTE, route->family, - route->protocol); + r = sd_rtnl_message_new_route(link->manager->rtnl, &m, RTM_NEWROUTE, route->family, route->protocol); if (r < 0) - return log_link_error_errno(link, r, "Could not create netlink message: %m"); + return r; - r = sd_rtnl_message_route_set_type(req, route->type); + r = sd_rtnl_message_route_set_type(m, route->type); if (r < 0) - return log_link_error_errno(link, r, "Could not set route type: %m"); + return r; - r = route_set_netlink_message(route, req, link); + r = route_set_netlink_message(route, m, link); if (r < 0) - return log_error_errno(r, "Could not fill netlink message: %m"); + return r; if (route->lifetime_usec != USEC_INFINITY) { - r = sd_netlink_message_append_u32(req, RTA_EXPIRES, + r = sd_netlink_message_append_u32(m, RTA_EXPIRES, MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX)); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m"); + return r; } if (route->ttl_propagate >= 0) { - r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate); + r = sd_netlink_message_append_u8(m, RTA_TTL_PROPAGATE, route->ttl_propagate); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m"); + return r; } - r = sd_netlink_message_open_container(req, RTA_METRICS); + r = sd_netlink_message_open_container(m, RTA_METRICS); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m"); + return r; if (route->mtu > 0) { - r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu); + r = sd_netlink_message_append_u32(m, RTAX_MTU, route->mtu); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m"); + return r; } if (route->initcwnd > 0) { - r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd); + r = sd_netlink_message_append_u32(m, RTAX_INITCWND, route->initcwnd); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m"); + return r; } if (route->initrwnd > 0) { - r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd); + r = sd_netlink_message_append_u32(m, RTAX_INITRWND, route->initrwnd); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m"); + return r; } if (route->quickack >= 0) { - r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack); + r = sd_netlink_message_append_u32(m, RTAX_QUICKACK, route->quickack); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m"); + return r; } if (route->fast_open_no_cookie >= 0) { - r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie); + r = sd_netlink_message_append_u32(m, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m"); + return r; } if (route->advmss > 0) { - r = sd_netlink_message_append_u32(req, RTAX_ADVMSS, route->advmss); + r = sd_netlink_message_append_u32(m, RTAX_ADVMSS, route->advmss); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTAX_ADVMSS attribute: %m"); + return r; } - r = sd_netlink_message_close_container(req); + r = sd_netlink_message_close_container(m); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m"); + return r; if (!ordered_set_isempty(route->multipath_routes)) { assert(route->nexthop_id == 0); assert(!in_addr_is_set(route->gw_family, &route->gw)); - r = append_nexthops(link, route, req); + r = append_nexthops(link, route, m); if (r < 0) - return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m"); + return r; } - r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + return r; link_ref(link); return 0; } -void route_cancel_request(Route *route, Link *link) { - Request req; - - assert(route); - - link = route->link ?: link; - - assert(link); - - if (!route_is_requesting(route)) - return; - - req = (Request) { - .link = link, - .type = REQUEST_TYPE_ROUTE, - .route = route, - }; - - request_drop(ordered_set_get(link->manager->request_queue, &req)); - route_cancel_requesting(route); -} - -static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - - assert(link); - assert(link->static_route_messages > 0); - - link->static_route_messages--; - - r = route_configure_handler_internal(rtnl, m, link, "Could not set route"); - if (r <= 0) - return r; - - if (link->static_route_messages == 0) { - log_link_debug(link, "Routes set"); - link->static_routes_configured = true; - link_check_ready(link); - } - - return 1; -} - -int link_request_route( - Link *link, - Route *route, - bool consume_object, - unsigned *message_counter, - link_netlink_message_handler_t netlink_handler, - Request **ret) { - - Route *existing; - int r; - - assert(link); - assert(link->manager); - assert(route); - assert(route->source != NETWORK_CONFIG_SOURCE_FOREIGN); - assert(!route_needs_convert(route)); - - if (route_get(link->manager, link, route, &existing) < 0) { - _cleanup_(route_freep) Route *tmp = NULL; - - if (consume_object) - tmp = route; - else { - r = route_dup(route, &tmp); - if (r < 0) - return r; - } - - r = route_add(link->manager, link, tmp); - if (r < 0) - return r; - - existing = TAKE_PTR(tmp); - } else { - existing->source = route->source; - existing->provider = route->provider; - existing->lifetime_usec = route->lifetime_usec; - if (consume_object) - route_free(route); - - if (existing->expire) { - /* When re-configuring an existing route, kernel does not send RTM_NEWROUTE - * message, so we need to update the timer here. */ - r = route_setup_timer(existing, NULL); - if (r < 0) - log_link_warning_errno(link, r, "Failed to update expiration timer for route, ignoring: %m"); - if (r > 0) - log_route_debug(existing, "Updated expiration timer for", link, link->manager); - } - } - - log_route_debug(existing, "Requesting", link, link->manager); - r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false, - message_counter, netlink_handler, ret); - if (r <= 0) - return r; - - route_enter_requesting(existing); - return 1; -} - -static int link_request_static_route(Link *link, Route *route) { - assert(link); - assert(link->manager); - assert(route); - - if (!route_needs_convert(route)) - return link_request_route(link, route, false, &link->static_route_messages, - static_route_handler, NULL); - - log_route_debug(route, "Requesting", link, link->manager); - return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false, - &link->static_route_messages, static_route_handler, NULL); -} - -static int link_request_wireguard_routes(Link *link, bool only_ipv4) { - NetDev *netdev; - Wireguard *w; - Route *route; - int r; - - assert(link); - - if (!streq_ptr(link->kind, "wireguard")) - return 0; - - if (netdev_get(link->manager, link->ifname, &netdev) < 0) - return 0; - - w = WIREGUARD(netdev); - if (!w) - return 0; - - SET_FOREACH(route, w->routes) { - if (only_ipv4 && route->family != AF_INET) - continue; - - r = link_request_static_route(link, route); - if (r < 0) - return r; - } - - return 0; -} - -int link_request_static_routes(Link *link, bool only_ipv4) { - Route *route; - int r; - - assert(link); - assert(link->network); - - link->static_routes_configured = false; - - HASHMAP_FOREACH(route, link->network->routes_by_section) { - if (route->gateway_from_dhcp_or_ra) - continue; - - if (only_ipv4 && route->family != AF_INET) - continue; - - r = link_request_static_route(link, route); - if (r < 0) - return r; - } - - r = link_request_wireguard_routes(link, only_ipv4); - if (r < 0) - return r; - - if (link->static_route_messages == 0) { - link->static_routes_configured = true; - link_check_ready(link); - } else { - log_link_debug(link, "Requesting routes"); - link_set_state(link, LINK_STATE_CONFIGURING); - } - - return 0; -} - static int route_is_ready_to_configure(const Route *route, Link *link) { int r; @@ -1583,6 +1397,190 @@ int request_process_route(Request *req) { return 1; } +int link_request_route( + Link *link, + Route *route, + bool consume_object, + unsigned *message_counter, + link_netlink_message_handler_t netlink_handler, + Request **ret) { + + Route *existing; + int r; + + assert(link); + assert(link->manager); + assert(route); + assert(route->source != NETWORK_CONFIG_SOURCE_FOREIGN); + assert(!route_needs_convert(route)); + + if (route_get(link->manager, link, route, &existing) < 0) { + _cleanup_(route_freep) Route *tmp = NULL; + + if (consume_object) + tmp = route; + else { + r = route_dup(route, &tmp); + if (r < 0) + return r; + } + + r = route_add(link->manager, link, tmp); + if (r < 0) + return r; + + existing = TAKE_PTR(tmp); + } else { + existing->source = route->source; + existing->provider = route->provider; + existing->lifetime_usec = route->lifetime_usec; + if (consume_object) + route_free(route); + + if (existing->expire) { + /* When re-configuring an existing route, kernel does not send RTM_NEWROUTE + * message, so we need to update the timer here. */ + r = route_setup_timer(existing, NULL); + if (r < 0) + log_link_warning_errno(link, r, "Failed to update expiration timer for route, ignoring: %m"); + if (r > 0) + log_route_debug(existing, "Updated expiration timer for", link, link->manager); + } + } + + log_route_debug(existing, "Requesting", link, link->manager); + r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false, + message_counter, netlink_handler, ret); + if (r <= 0) + return r; + + route_enter_requesting(existing); + return 1; +} + +static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->static_route_messages > 0); + + link->static_route_messages--; + + r = route_configure_handler_internal(rtnl, m, link, "Could not set route"); + if (r <= 0) + return r; + + if (link->static_route_messages == 0) { + log_link_debug(link, "Routes set"); + link->static_routes_configured = true; + link_check_ready(link); + } + + return 1; +} + +static int link_request_static_route(Link *link, Route *route) { + assert(link); + assert(link->manager); + assert(route); + + if (!route_needs_convert(route)) + return link_request_route(link, route, false, &link->static_route_messages, + static_route_handler, NULL); + + log_route_debug(route, "Requesting", link, link->manager); + return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false, + &link->static_route_messages, static_route_handler, NULL); +} + +static int link_request_wireguard_routes(Link *link, bool only_ipv4) { + NetDev *netdev; + Wireguard *w; + Route *route; + int r; + + assert(link); + + if (!streq_ptr(link->kind, "wireguard")) + return 0; + + if (netdev_get(link->manager, link->ifname, &netdev) < 0) + return 0; + + w = WIREGUARD(netdev); + if (!w) + return 0; + + SET_FOREACH(route, w->routes) { + if (only_ipv4 && route->family != AF_INET) + continue; + + r = link_request_static_route(link, route); + if (r < 0) + return r; + } + + return 0; +} + +int link_request_static_routes(Link *link, bool only_ipv4) { + Route *route; + int r; + + assert(link); + assert(link->network); + + link->static_routes_configured = false; + + HASHMAP_FOREACH(route, link->network->routes_by_section) { + if (route->gateway_from_dhcp_or_ra) + continue; + + if (only_ipv4 && route->family != AF_INET) + continue; + + r = link_request_static_route(link, route); + if (r < 0) + return r; + } + + r = link_request_wireguard_routes(link, only_ipv4); + if (r < 0) + return r; + + if (link->static_route_messages == 0) { + link->static_routes_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Requesting routes"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + +void route_cancel_request(Route *route, Link *link) { + Request req; + + assert(route); + + link = route->link ?: link; + + assert(link); + + if (!route_is_requesting(route)) + return; + + req = (Request) { + .link = link, + .type = REQUEST_TYPE_ROUTE, + .route = route, + }; + + request_drop(ordered_set_get(link->manager->request_queue, &req)); + route_cancel_requesting(route); +} + static int process_route_one( Manager *manager, Link *link, diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index a17d74e316..5812aee03b 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -588,17 +588,17 @@ static int routing_policy_rule_remove(RoutingPolicyRule *rule) { r = sd_rtnl_message_new_routing_policy_rule(rule->manager->rtnl, &m, RTM_DELRULE, rule->family); if (r < 0) - return log_error_errno(r, "Could not allocate netlink message: %m"); + return log_warning_errno(r, "Could not allocate netlink message: %m"); r = routing_policy_rule_set_netlink_message(rule, m, NULL); if (r < 0) - return log_error_errno(r, "Could not create netlink message: %m"); + return log_warning_errno(r, "Could not create netlink message: %m"); r = netlink_call_async(rule->manager->rtnl, NULL, m, routing_policy_rule_remove_handler, NULL, NULL); if (r < 0) - return log_error_errno(r, "Could not send netlink message: %m"); + return log_warning_errno(r, "Could not send netlink message: %m"); routing_policy_rule_enter_removing(rule); return 0; @@ -624,21 +624,19 @@ static int routing_policy_rule_configure( r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family); if (r < 0) - return log_link_error_errno(link, r, "Could not allocate netlink message: %m"); + return r; r = routing_policy_rule_set_netlink_message(rule, m, link); if (r < 0) - return log_error_errno(r, "Could not create netlink message: %m"); + return r; r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_error_errno(link, r, "Could not send netlink message: %m"); + return r; link_ref(link); - - routing_policy_rule_enter_configuring(rule); - return r; + return 0; } static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) { @@ -730,6 +728,28 @@ void link_foreignize_routing_policy_rules(Link *link) { } } +int request_process_routing_policy_rule(Request *req) { + RoutingPolicyRule *rule; + Link *link; + int r; + + assert(req); + assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE); + + link = ASSERT_PTR(req->link); + rule = ASSERT_PTR(req->rule); + + if (!link_is_ready_to_configure(link, false)) + return 0; + + r = routing_policy_rule_configure(rule, link, req->netlink_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure routing policy rule: %m"); + + routing_policy_rule_enter_configuring(rule); + return 1; +} + static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -858,24 +878,6 @@ int link_request_static_routing_policy_rules(Link *link) { return 0; } -int request_process_routing_policy_rule(Request *req) { - int r; - - assert(req); - assert(req->link); - assert(req->rule); - assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE); - - if (!link_is_ready_to_configure(req->link, false)) - return 0; - - r = routing_policy_rule_configure(req->rule, req->link, req->netlink_handler); - if (r < 0) - return r; - - return 1; -} - static const RoutingPolicyRule kernel_rules[] = { { .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, { .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 542f20c54d..8878de3a2c 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -546,7 +546,7 @@ static bool link_is_ready_to_call_set_link(Request *req) { * is outdated, and checking the counter causes a deadlock. */ if (FLAGS_SET(link->flags, IFF_UP)) { /* The CAN interface must be down to configure bitrate, etc... */ - r = link_down(link); + r = link_down_now(link); if (r < 0) { link_enter_failed(link); return false; @@ -558,7 +558,7 @@ static bool link_is_ready_to_call_set_link(Request *req) { /* This is the second attempt to set hardware address. On the first attempt * req->netlink_handler points to link_set_mac_allow_retry_handler(). * The first attempt failed as the interface was up. */ - r = link_down(link); + r = link_down_now(link); if (r < 0) { link_enter_failed(link); return false; @@ -588,7 +588,7 @@ static bool link_is_ready_to_call_set_link(Request *req) { * is outdated, and checking the counter causes a deadlock. */ if (FLAGS_SET(link->flags, IFF_UP)) { /* link must be down when joining to bond master. */ - r = link_down(link); + r = link_down_now(link); if (r < 0) { link_enter_failed(link); return false; @@ -1068,35 +1068,22 @@ static int link_up_or_down(Link *link, bool up, link_netlink_message_handler_t c r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) - return log_link_debug_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + return r; r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP); if (r < 0) - return log_link_debug_errno(link, r, "Could not set link flags: %m"); + return r; r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link); if (r < 0) - return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m"); + return r; link_ref(link); return 0; } -int link_down(Link *link) { - int r; - - assert(link); - - r = link_up_or_down(link, false, link_down_handler); - if (r < 0) - return log_link_error_errno(link, r, "Failed to bring down interface: %m"); - - link->set_flags_messages++; - return 0; -} - static bool link_is_ready_to_activate(Link *link) { assert(link); @@ -1127,7 +1114,7 @@ int request_process_activation(Request *req) { r = link_up_or_down(link, up, req->netlink_handler); if (r < 0) - return log_link_error_errno(link, r, "Failed to bring %s: %m", up_or_down(up)); + return log_link_warning_errno(link, r, "Failed to activate link: %m"); return 1; } @@ -1222,7 +1209,7 @@ int request_process_link_up_or_down(Request *req) { r = link_up_or_down(link, up, req->netlink_handler); if (r < 0) - return log_link_error_errno(link, r, "Failed to bring %s: %m", up_or_down(up)); + return log_link_warning_errno(link, r, "Failed to bring link %s: %m", up_or_down(up)); return 1; } @@ -1236,8 +1223,8 @@ int link_request_to_bring_up_or_down(Link *link, bool up) { r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages, up ? link_up_handler : link_down_handler, &req); if (r < 0) - return log_link_error_errno(link, r, "Failed to request to bring %s link: %m", - up_or_down(up)); + return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m", + up_or_down(up)); req->userdata = INT_TO_PTR(up); @@ -1245,6 +1232,60 @@ int link_request_to_bring_up_or_down(Link *link, bool up) { return 0; } +static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->set_flags_messages > 0); + + link->set_flags_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 0; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_message_warning_errno(link, m, r, "Could not bring down interface, ignoring"); + + r = link_call_getlink(link, get_link_update_flag_handler); + if (r < 0) { + link_enter_failed(link); + return 0; + } + + link->set_flags_messages++; + return 0; +} + +int link_down_now(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + + log_link_debug(link, "Bringing link down"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set link flags: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, link_down_now_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m"); + + link->set_flags_messages++; + link_ref(link); + return 0; +} + static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index 47d87837e4..e943f2012a 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -42,12 +42,11 @@ int link_configure_mtu(Link *link); int request_process_set_link(Request *req); -int link_down(Link *link); - int request_process_activation(Request *req); int link_request_to_activate(Link *link); int request_process_link_up_or_down(Request *req); int link_request_to_bring_up_or_down(Link *link, bool up); +int link_down_now(Link *link); int link_remove(Link *link);