diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/networkd-lldp-tx.c | 30 | ||||
-rw-r--r-- | src/network/networkd-lldp-tx.h | 1 | ||||
-rw-r--r-- | src/network/networkd-sysctl.c | 63 |
3 files changed, 93 insertions, 1 deletions
diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c index f48781e..cc22fbf 100644 --- a/src/network/networkd-lldp-tx.c +++ b/src/network/networkd-lldp-tx.c @@ -86,6 +86,36 @@ int link_lldp_tx_configure(Link *link) { return 0; } +int link_lldp_tx_update_capabilities(Link *link) { + int r; + + assert(link); + + if (!link->lldp_tx) + return 0; /* disabled, or not configured yet. */ + + r = sd_lldp_tx_set_capabilities(link->lldp_tx, + SD_LLDP_SYSTEM_CAPABILITIES_STATION | + SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE | + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER, + (link_get_ip_forwarding(link, AF_INET) > 0 || link_get_ip_forwarding(link, AF_INET6) > 0) ? + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : SD_LLDP_SYSTEM_CAPABILITIES_STATION); + if (r < 0) + return r; + + if (sd_lldp_tx_is_running(link->lldp_tx)) { + r = sd_lldp_tx_stop(link->lldp_tx); + if (r < 0) + return r; + + r = sd_lldp_tx_start(link->lldp_tx); + if (r < 0) + return r; + } + + return 0; +} + static const char * const lldp_multicast_mode_table[_SD_LLDP_MULTICAST_MODE_MAX] = { [SD_LLDP_MULTICAST_MODE_NEAREST_BRIDGE] = "nearest-bridge", [SD_LLDP_MULTICAST_MODE_NON_TPMR_BRIDGE] = "non-tpmr-bridge", diff --git a/src/network/networkd-lldp-tx.h b/src/network/networkd-lldp-tx.h index 73757f1..346eb5c 100644 --- a/src/network/networkd-lldp-tx.h +++ b/src/network/networkd-lldp-tx.h @@ -6,5 +6,6 @@ typedef struct Link Link; int link_lldp_tx_configure(Link *link); +int link_lldp_tx_update_capabilities(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_lldp_multicast_mode); diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index 68c23e0..a454322 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -7,7 +7,9 @@ #include "af-list.h" #include "missing_network.h" #include "networkd-link.h" +#include "networkd-lldp-tx.h" #include "networkd-manager.h" +#include "networkd-ndisc.h" #include "networkd-network.h" #include "networkd-sysctl.h" #include "socket-util.h" @@ -130,7 +132,7 @@ int link_get_ip_forwarding(Link *link, int family) { return link->manager->ip_forwarding[family == AF_INET6]; } -static int link_set_ip_forwarding(Link *link, int family) { +static int link_set_ip_forwarding_impl(Link *link, int family) { int r, t; assert(link); @@ -151,6 +153,65 @@ static int link_set_ip_forwarding(Link *link, int family) { return 0; } +static int link_reapply_ip_forwarding(Link *link, int family) { + int r, ret = 0; + + assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + return 0; + + (void) link_set_ip_forwarding_impl(link, family); + + r = link_lldp_tx_update_capabilities(link); + if (r < 0) + RET_GATHER(ret, log_link_warning_errno(link, r, "Could not update LLDP capabilities, ignoring: %m")); + + if (family == AF_INET6 && !link_ndisc_enabled(link)) { + r = ndisc_stop(link); + if (r < 0) + RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery, ignoring: %m")); + + ndisc_flush(link); + } + + return ret; +} + +static int link_set_ip_forwarding(Link *link, int family) { + int r; + + assert(link); + assert(link->manager); + assert(link->network); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (!link_is_configured_for_family(link, family)) + return 0; + + /* When IPMasquerade= is enabled and the global setting is unset, enable _global_ IP forwarding, and + * re-apply per-link setting for all links. */ + if (FLAGS_SET(link->network->ip_masquerade, family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6) && + link->manager->ip_forwarding[family == AF_INET6] < 0) { + + link->manager->ip_forwarding[family == AF_INET6] = true; + manager_set_ip_forwarding(link->manager, family); + + Link *other; + HASHMAP_FOREACH(other, link->manager->links_by_index) { + r = link_reapply_ip_forwarding(other, family); + if (r < 0) + link_enter_failed(other); + } + + return 0; + } + + /* Otherwise, apply per-link setting for _this_ link. */ + return link_set_ip_forwarding_impl(link, family); +} + static int link_set_ipv4_rp_filter(Link *link) { assert(link); |