mirror of
https://github.com/systemd/systemd
synced 2026-04-21 22:44:51 +02:00
Compare commits
8 Commits
82a03e8a85
...
fb70f1de69
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb70f1de69 | ||
|
|
745f0620ed | ||
|
|
2971e2adf1 | ||
|
|
e1e4cd1eed | ||
|
|
8bed7c55bf | ||
|
|
d3aff22f19 | ||
|
|
a79a8d16d5 | ||
|
|
cae162a79c |
@ -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) {
|
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;
|
int r;
|
||||||
|
|
||||||
assert(label);
|
assert(label);
|
||||||
@ -106,29 +106,48 @@ static int address_label_configure(AddressLabel *label, Link *link, link_netlink
|
|||||||
assert(link->manager->rtnl);
|
assert(link->manager->rtnl);
|
||||||
assert(callback);
|
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);
|
link->ifindex, AF_INET6);
|
||||||
if (r < 0)
|
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)
|
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)
|
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)
|
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);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -160,18 +179,6 @@ int link_request_static_address_labels(Link *link) {
|
|||||||
return 0;
|
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) {
|
static int address_label_section_verify(AddressLabel *label) {
|
||||||
assert(label);
|
assert(label);
|
||||||
assert(label->section);
|
assert(label->section);
|
||||||
|
|||||||
@ -656,36 +656,36 @@ static void log_address_debug(const Address *address, const char *str, const Lin
|
|||||||
strna(flags_str), strna(scope_str));
|
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;
|
uint32_t flags;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(address);
|
assert(address);
|
||||||
assert(req);
|
assert(m);
|
||||||
assert(link);
|
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)
|
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
|
/* 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
|
* 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
|
* addresses generated by kernel will not be removed automatically when the main address is
|
||||||
* removed. */
|
* removed. */
|
||||||
flags = address->flags & ~IFA_F_TENTATIVE;
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not set flags: %m");
|
return r;
|
||||||
|
|
||||||
if ((flags & ~0xff) != 0) {
|
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)
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
|
return r;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -707,7 +707,7 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
|
|||||||
}
|
}
|
||||||
|
|
||||||
int address_remove(Address *address) {
|
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;
|
Link *link;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -722,20 +722,20 @@ int address_remove(Address *address) {
|
|||||||
|
|
||||||
log_address_debug(address, "Removing", link);
|
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);
|
link->ifindex, address->family);
|
||||||
if (r < 0)
|
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)
|
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,
|
address_remove_handler,
|
||||||
link_netlink_destroy_callback, link);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
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);
|
link_ref(link);
|
||||||
|
|
||||||
@ -1025,7 +1025,7 @@ static int address_configure(
|
|||||||
Link *link,
|
Link *link,
|
||||||
link_netlink_message_handler_t callback) {
|
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;
|
int r;
|
||||||
|
|
||||||
assert(address);
|
assert(address);
|
||||||
@ -1038,89 +1038,87 @@ static int address_configure(
|
|||||||
|
|
||||||
log_address_debug(address, "Configuring", link);
|
log_address_debug(address, "Configuring", link);
|
||||||
|
|
||||||
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
|
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &m, link->ifindex, address->family);
|
||||||
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);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_rtnl_message_addr_set_scope(req, address->scope);
|
r = address_set_netlink_message(address, m, link);
|
||||||
if (r < 0)
|
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)) {
|
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)
|
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)) {
|
} 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)
|
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) {
|
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)
|
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) {}));
|
address_set_cinfo(address, &(struct ifa_cacheinfo) {}));
|
||||||
if (r < 0)
|
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)
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
link_ref(link);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void address_cancel_request(Address *address) {
|
static bool address_is_ready_to_configure(Link *link, const Address *address) {
|
||||||
Request req;
|
assert(link);
|
||||||
|
|
||||||
assert(address);
|
assert(address);
|
||||||
assert(address->link);
|
|
||||||
|
|
||||||
if (!address_is_requesting(address))
|
if (!link_is_ready_to_configure(link, false))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
req = (Request) {
|
if (FLAGS_SET(address->state, NETWORK_CONFIG_STATE_PROBING))
|
||||||
.link = address->link,
|
return false;
|
||||||
.type = REQUEST_TYPE_ADDRESS,
|
|
||||||
.address = address,
|
|
||||||
};
|
|
||||||
|
|
||||||
request_drop(ordered_set_get(address->link->manager->request_queue, &req));
|
/* Refuse adding more than the limit */
|
||||||
address_cancel_requesting(address);
|
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;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(req);
|
||||||
assert(link->static_address_messages > 0);
|
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 (!address_is_ready_to_configure(link, address))
|
||||||
if (r <= 0)
|
return 0;
|
||||||
return r;
|
|
||||||
|
|
||||||
if (link->static_address_messages == 0) {
|
r = address_configure(address, link, req->netlink_handler);
|
||||||
log_link_debug(link, "Addresses set");
|
if (r < 0)
|
||||||
link->static_addresses_configured = true;
|
return log_link_warning_errno(link, r, "Failed to configure address: %m");
|
||||||
link_check_ready(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
address_enter_configuring(address);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,6 +1208,27 @@ int link_request_address(
|
|||||||
return 1;
|
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) {
|
int link_request_static_address(Link *link, Address *address, bool consume) {
|
||||||
assert(link);
|
assert(link);
|
||||||
assert(address);
|
assert(address);
|
||||||
@ -1253,49 +1272,23 @@ int link_request_static_addresses(Link *link) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool address_is_ready_to_configure(Link *link, const Address *address) {
|
void address_cancel_request(Address *address) {
|
||||||
assert(link);
|
Request req;
|
||||||
|
|
||||||
assert(address);
|
assert(address);
|
||||||
|
assert(address->link);
|
||||||
|
|
||||||
if (!link_is_ready_to_configure(link, false))
|
if (!address_is_requesting(address))
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (FLAGS_SET(address->state, NETWORK_CONFIG_STATE_PROBING))
|
req = (Request) {
|
||||||
return false;
|
.link = address->link,
|
||||||
|
.type = REQUEST_TYPE_ADDRESS,
|
||||||
|
.address = address,
|
||||||
|
};
|
||||||
|
|
||||||
/* Refuse adding more than the limit */
|
request_drop(ordered_set_get(address->link->manager->request_queue, &req));
|
||||||
if (set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
|
address_cancel_requesting(address);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
|
|||||||
@ -168,30 +168,29 @@ static int bridge_fdb_configure_message(const BridgeFDB *fdb, Link *link, sd_net
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int link_request_static_bridge_fdb(Link *link) {
|
static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message_handler_t callback) {
|
||||||
BridgeFDB *fdb;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(fdb);
|
||||||
assert(link);
|
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 = bridge_fdb_configure_message(fdb, link, m);
|
||||||
r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false,
|
if (r < 0)
|
||||||
&link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL);
|
return r;
|
||||||
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) {
|
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||||
link->static_bridge_fdb_configured = true;
|
link_netlink_destroy_callback, link);
|
||||||
link_check_ready(link);
|
if (r < 0)
|
||||||
} else {
|
return r;
|
||||||
log_link_debug(link, "Setting bridge FDB entries");
|
|
||||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
link_ref(link);
|
||||||
return 0;
|
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) {
|
int request_process_bridge_fdb(Request *req) {
|
||||||
|
BridgeFDB *fdb;
|
||||||
Link *link;
|
Link *link;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(req);
|
assert(req);
|
||||||
assert(req->fdb);
|
|
||||||
assert(req->type == REQUEST_TYPE_BRIDGE_FDB);
|
assert(req->type == REQUEST_TYPE_BRIDGE_FDB);
|
||||||
assert_se(link = req->link);
|
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;
|
return 0;
|
||||||
|
|
||||||
/* create new RTM message */
|
r = bridge_fdb_configure(fdb, link, req->netlink_handler);
|
||||||
_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);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not allocate netlink message: %m");
|
return log_link_warning_errno(link, r, "Failed to configure bridge FDB: %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 1;
|
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) {
|
void network_drop_invalid_bridge_fdb_entries(Network *network) {
|
||||||
BridgeFDB *fdb;
|
BridgeFDB *fdb;
|
||||||
|
|
||||||
|
|||||||
@ -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 */
|
/* 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) {
|
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;
|
struct br_mdb_entry entry;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -156,22 +156,71 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message
|
|||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create new RTM message */
|
r = sd_rtnl_message_new_mdb(link->manager->rtnl, &m, RTM_NEWMDB,
|
||||||
r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB,
|
|
||||||
link->master_ifindex > 0 ? link->master_ifindex : link->ifindex);
|
link->master_ifindex > 0 ? link->master_ifindex : link->ifindex);
|
||||||
if (r < 0)
|
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)
|
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);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -210,48 +259,6 @@ finish:
|
|||||||
return 0;
|
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) {
|
static int bridge_mdb_verify(BridgeMDB *mdb) {
|
||||||
if (section_is_invalid(mdb->section))
|
if (section_is_invalid(mdb->section))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@ -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");
|
return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m");
|
||||||
|
|
||||||
log_link_debug(link, "Offering DHCPv4 leases");
|
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) {
|
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) {
|
int request_process_dhcp_server(Request *req) {
|
||||||
assert(req);
|
Link *link;
|
||||||
assert(req->link);
|
int r;
|
||||||
assert(req->type == REQUEST_TYPE_DHCP_SERVER);
|
|
||||||
|
|
||||||
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 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(
|
int config_parse_dhcp_server_relay_agent_suboption(
|
||||||
|
|||||||
@ -53,7 +53,7 @@ static int ipv6_proxy_ndp_address_configure(
|
|||||||
Link *link,
|
Link *link,
|
||||||
link_netlink_message_handler_t callback) {
|
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;
|
int r;
|
||||||
|
|
||||||
assert(address);
|
assert(address);
|
||||||
@ -63,24 +63,42 @@ static int ipv6_proxy_ndp_address_configure(
|
|||||||
assert(callback);
|
assert(callback);
|
||||||
|
|
||||||
/* create new netlink message */
|
/* 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)
|
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)
|
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)
|
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);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -113,18 +131,6 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) {
|
|||||||
return 0;
|
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(
|
int config_parse_ipv6_proxy_ndp_address(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
|||||||
@ -198,7 +198,7 @@ static int neighbor_configure(
|
|||||||
Link *link,
|
Link *link,
|
||||||
link_netlink_message_handler_t callback) {
|
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;
|
int r;
|
||||||
|
|
||||||
assert(neighbor);
|
assert(neighbor);
|
||||||
@ -210,24 +210,45 @@ static int neighbor_configure(
|
|||||||
|
|
||||||
log_neighbor_debug(neighbor, "Configuring", link);
|
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);
|
link->ifindex, neighbor->family);
|
||||||
if (r < 0)
|
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)
|
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);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send netlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
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);
|
neighbor_enter_configuring(neighbor);
|
||||||
return r;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
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;
|
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) {
|
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
_cleanup_(neighbor_freep) Neighbor *tmp = NULL;
|
_cleanup_(neighbor_freep) Neighbor *tmp = NULL;
|
||||||
Neighbor *neighbor = NULL;
|
Neighbor *neighbor = NULL;
|
||||||
|
|||||||
@ -430,7 +430,7 @@ static int nexthop_configure(
|
|||||||
Link *link,
|
Link *link,
|
||||||
link_netlink_message_handler_t callback) {
|
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;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
@ -442,16 +442,14 @@ static int nexthop_configure(
|
|||||||
|
|
||||||
log_nexthop_debug(nexthop, "Configuring", link);
|
log_nexthop_debug(nexthop, "Configuring", link);
|
||||||
|
|
||||||
r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req,
|
r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &m, RTM_NEWNEXTHOP, nexthop->family, nexthop->protocol);
|
||||||
RTM_NEWNEXTHOP, nexthop->family,
|
|
||||||
nexthop->protocol);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not create RTM_NEWNEXTHOP message: %m");
|
return r;
|
||||||
|
|
||||||
if (nexthop->id > 0) {
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append NHA_ID attribute: %m");
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hashmap_isempty(nexthop->group)) {
|
if (!hashmap_isempty(nexthop->group)) {
|
||||||
@ -466,38 +464,36 @@ static int nexthop_configure(
|
|||||||
HASHMAP_FOREACH(nhg, nexthop->group)
|
HASHMAP_FOREACH(nhg, nexthop->group)
|
||||||
*p++ = *nhg;
|
*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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append NHA_GROUP attribute: %m");
|
return r;
|
||||||
|
|
||||||
} else if (nexthop->blackhole) {
|
} 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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append NHA_BLACKHOLE attribute: %m");
|
return r;
|
||||||
} else {
|
} 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)
|
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)) {
|
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)
|
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)
|
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);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
link_ref(link);
|
||||||
|
|
||||||
nexthop_enter_configuring(nexthop);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,6 +524,72 @@ static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
|
|||||||
return 1;
|
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(
|
static int link_request_nexthop(
|
||||||
Link *link,
|
Link *link,
|
||||||
NextHop *nexthop,
|
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) {
|
int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
_cleanup_(nexthop_freep) NextHop *tmp = NULL;
|
_cleanup_(nexthop_freep) NextHop *tmp = NULL;
|
||||||
_cleanup_free_ void *raw_group = NULL;
|
_cleanup_free_ void *raw_group = NULL;
|
||||||
|
|||||||
@ -1166,7 +1166,7 @@ static int route_configure(
|
|||||||
Link *link,
|
Link *link,
|
||||||
link_netlink_message_handler_t callback) {
|
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;
|
int r;
|
||||||
|
|
||||||
assert(route);
|
assert(route);
|
||||||
@ -1179,279 +1179,93 @@ static int route_configure(
|
|||||||
|
|
||||||
log_route_debug(route, "Configuring", link, link->manager);
|
log_route_debug(route, "Configuring", link, link->manager);
|
||||||
|
|
||||||
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
|
r = sd_rtnl_message_new_route(link->manager->rtnl, &m, RTM_NEWROUTE, route->family, route->protocol);
|
||||||
RTM_NEWROUTE, route->family,
|
|
||||||
route->protocol);
|
|
||||||
if (r < 0)
|
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)
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Could not fill netlink message: %m");
|
return r;
|
||||||
|
|
||||||
if (route->lifetime_usec != USEC_INFINITY) {
|
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));
|
MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now(clock_boottime_or_monotonic())), USEC_PER_SEC), UINT32_MAX));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m");
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route->ttl_propagate >= 0) {
|
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)
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
|
return r;
|
||||||
|
|
||||||
if (route->mtu > 0) {
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m");
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route->initcwnd > 0) {
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m");
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route->initrwnd > 0) {
|
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)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route->quickack >= 0) {
|
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)
|
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) {
|
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)
|
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) {
|
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)
|
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)
|
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)) {
|
if (!ordered_set_isempty(route->multipath_routes)) {
|
||||||
assert(route->nexthop_id == 0);
|
assert(route->nexthop_id == 0);
|
||||||
assert(!in_addr_is_set(route->gw_family, &route->gw));
|
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)
|
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);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
link_ref(link);
|
||||||
return 0;
|
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) {
|
static int route_is_ready_to_configure(const Route *route, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1583,6 +1397,190 @@ int request_process_route(Request *req) {
|
|||||||
return 1;
|
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(
|
static int process_route_one(
|
||||||
Manager *manager,
|
Manager *manager,
|
||||||
Link *link,
|
Link *link,
|
||||||
|
|||||||
@ -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);
|
r = sd_rtnl_message_new_routing_policy_rule(rule->manager->rtnl, &m, RTM_DELRULE, rule->family);
|
||||||
if (r < 0)
|
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);
|
r = routing_policy_rule_set_netlink_message(rule, m, NULL);
|
||||||
if (r < 0)
|
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,
|
r = netlink_call_async(rule->manager->rtnl, NULL, m,
|
||||||
routing_policy_rule_remove_handler,
|
routing_policy_rule_remove_handler,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (r < 0)
|
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);
|
routing_policy_rule_enter_removing(rule);
|
||||||
return 0;
|
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);
|
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family);
|
||||||
if (r < 0)
|
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);
|
r = routing_policy_rule_set_netlink_message(rule, m, link);
|
||||||
if (r < 0)
|
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,
|
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||||
link_netlink_destroy_callback, link);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send netlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
link_ref(link);
|
||||||
|
return 0;
|
||||||
routing_policy_rule_enter_configuring(rule);
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) {
|
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) {
|
static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -858,24 +878,6 @@ int link_request_static_routing_policy_rules(Link *link) {
|
|||||||
return 0;
|
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[] = {
|
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 = 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, },
|
{ .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, },
|
||||||
|
|||||||
@ -546,7 +546,7 @@ static bool link_is_ready_to_call_set_link(Request *req) {
|
|||||||
* is outdated, and checking the counter causes a deadlock. */
|
* is outdated, and checking the counter causes a deadlock. */
|
||||||
if (FLAGS_SET(link->flags, IFF_UP)) {
|
if (FLAGS_SET(link->flags, IFF_UP)) {
|
||||||
/* The CAN interface must be down to configure bitrate, etc... */
|
/* The CAN interface must be down to configure bitrate, etc... */
|
||||||
r = link_down(link);
|
r = link_down_now(link);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
link_enter_failed(link);
|
link_enter_failed(link);
|
||||||
return false;
|
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
|
/* This is the second attempt to set hardware address. On the first attempt
|
||||||
* req->netlink_handler points to link_set_mac_allow_retry_handler().
|
* req->netlink_handler points to link_set_mac_allow_retry_handler().
|
||||||
* The first attempt failed as the interface was up. */
|
* The first attempt failed as the interface was up. */
|
||||||
r = link_down(link);
|
r = link_down_now(link);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
link_enter_failed(link);
|
link_enter_failed(link);
|
||||||
return false;
|
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. */
|
* is outdated, and checking the counter causes a deadlock. */
|
||||||
if (FLAGS_SET(link->flags, IFF_UP)) {
|
if (FLAGS_SET(link->flags, IFF_UP)) {
|
||||||
/* link must be down when joining to bond master. */
|
/* link must be down when joining to bond master. */
|
||||||
r = link_down(link);
|
r = link_down_now(link);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
link_enter_failed(link);
|
link_enter_failed(link);
|
||||||
return false;
|
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);
|
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||||
if (r < 0)
|
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);
|
r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
|
||||||
if (r < 0)
|
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,
|
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
|
||||||
link_netlink_destroy_callback, link);
|
link_netlink_destroy_callback, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m");
|
return r;
|
||||||
|
|
||||||
link_ref(link);
|
link_ref(link);
|
||||||
|
|
||||||
return 0;
|
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) {
|
static bool link_is_ready_to_activate(Link *link) {
|
||||||
assert(link);
|
assert(link);
|
||||||
|
|
||||||
@ -1127,7 +1114,7 @@ int request_process_activation(Request *req) {
|
|||||||
|
|
||||||
r = link_up_or_down(link, up, req->netlink_handler);
|
r = link_up_or_down(link, up, req->netlink_handler);
|
||||||
if (r < 0)
|
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;
|
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);
|
r = link_up_or_down(link, up, req->netlink_handler);
|
||||||
if (r < 0)
|
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;
|
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,
|
r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages,
|
||||||
up ? link_up_handler : link_down_handler, &req);
|
up ? link_up_handler : link_down_handler, &req);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Failed to request to bring %s link: %m",
|
return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m",
|
||||||
up_or_down(up));
|
up_or_down(up));
|
||||||
|
|
||||||
req->userdata = INT_TO_PTR(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;
|
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) {
|
static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
|||||||
@ -42,12 +42,11 @@ int link_configure_mtu(Link *link);
|
|||||||
|
|
||||||
int request_process_set_link(Request *req);
|
int request_process_set_link(Request *req);
|
||||||
|
|
||||||
int link_down(Link *link);
|
|
||||||
|
|
||||||
int request_process_activation(Request *req);
|
int request_process_activation(Request *req);
|
||||||
int link_request_to_activate(Link *link);
|
int link_request_to_activate(Link *link);
|
||||||
|
|
||||||
int request_process_link_up_or_down(Request *req);
|
int request_process_link_up_or_down(Request *req);
|
||||||
int link_request_to_bring_up_or_down(Link *link, bool up);
|
int link_request_to_bring_up_or_down(Link *link, bool up);
|
||||||
|
|
||||||
|
int link_down_now(Link *link);
|
||||||
int link_remove(Link *link);
|
int link_remove(Link *link);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user