diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:40 +0000 |
commit | fc53809803cd2bc2434e312b19a18fa36776da12 (patch) | |
tree | b4b43bd6538f51965ce32856e9c053d0f90919c8 /src/network/netdev | |
parent | Adding upstream version 255.5. (diff) | |
download | systemd-fc53809803cd2bc2434e312b19a18fa36776da12.tar.xz systemd-fc53809803cd2bc2434e312b19a18fa36776da12.zip |
Adding upstream version 256.upstream/256
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/network/netdev')
-rw-r--r-- | src/network/netdev/bond.c | 12 | ||||
-rw-r--r-- | src/network/netdev/bond.h | 3 | ||||
-rw-r--r-- | src/network/netdev/bridge.c | 3 | ||||
-rw-r--r-- | src/network/netdev/fou-tunnel.c | 3 | ||||
-rw-r--r-- | src/network/netdev/geneve.c | 3 | ||||
-rw-r--r-- | src/network/netdev/ipvlan.c | 1 | ||||
-rw-r--r-- | src/network/netdev/macsec.c | 5 | ||||
-rw-r--r-- | src/network/netdev/macvlan.c | 60 | ||||
-rw-r--r-- | src/network/netdev/macvlan.h | 2 | ||||
-rw-r--r-- | src/network/netdev/netdev-gperf.gperf | 3 | ||||
-rw-r--r-- | src/network/netdev/netdev.c | 22 | ||||
-rw-r--r-- | src/network/netdev/tuntap.c | 10 | ||||
-rw-r--r-- | src/network/netdev/veth.c | 5 | ||||
-rw-r--r-- | src/network/netdev/vlan.c | 7 | ||||
-rw-r--r-- | src/network/netdev/vrf.c | 3 | ||||
-rw-r--r-- | src/network/netdev/vxlan.c | 3 | ||||
-rw-r--r-- | src/network/netdev/wireguard.c | 155 |
17 files changed, 242 insertions, 58 deletions
diff --git a/src/network/netdev/bond.c b/src/network/netdev/bond.c index 4d75a0d..52a7f12 100644 --- a/src/network/netdev/bond.c +++ b/src/network/netdev/bond.c @@ -88,6 +88,12 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin return r; } + if (b->peer_notify_delay != 0) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_PEER_NOTIF_DELAY, b->peer_notify_delay / USEC_PER_MSEC); + if (r < 0) + return r; + } + if (b->downdelay != 0) { r = sd_netlink_message_append_u32(m, IFLA_BOND_DOWNDELAY, b->downdelay / USEC_PER_MSEC); if (r < 0) @@ -198,6 +204,12 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin return r; } + if (b->arp_missed_max > 0) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_MISSED_MAX, b->arp_missed_max); + if (r < 0) + return r; + } + if (b->arp_interval > 0 && !ordered_set_isempty(b->arp_ip_targets)) { void *val; int n = 0; diff --git a/src/network/netdev/bond.h b/src/network/netdev/bond.h index e4b0a0d..ea94001 100644 --- a/src/network/netdev/bond.h +++ b/src/network/netdev/bond.h @@ -34,11 +34,14 @@ typedef struct Bond { uint16_t ad_user_port_key; struct ether_addr ad_actor_system; + uint8_t arp_missed_max; + usec_t miimon; usec_t updelay; usec_t downdelay; usec_t arp_interval; usec_t lp_interval; + usec_t peer_notify_delay; OrderedSet *arp_ip_targets; } Bond; diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c index 3e394ed..d426c0c 100644 --- a/src/network/netdev/bridge.c +++ b/src/network/netdev/bridge.c @@ -1,9 +1,10 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> -#include <netinet/in.h> #include <linux/if_arp.h> #include <linux/if_bridge.h> +#include <netinet/in.h> #include "bridge.h" #include "netlink-util.h" diff --git a/src/network/netdev/fou-tunnel.c b/src/network/netdev/fou-tunnel.c index 3bf41a8..bddee5e 100644 --- a/src/network/netdev/fou-tunnel.c +++ b/src/network/netdev/fou-tunnel.c @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include <linux/fou.h> +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> +#include <linux/fou.h> #include <netinet/in.h> #include <linux/ip.h> diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c index bc655ec..22c2b00 100644 --- a/src/network/netdev/geneve.c +++ b/src/network/netdev/geneve.c @@ -1,8 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> -#include <netinet/in.h> #include <linux/if_arp.h> +#include <netinet/in.h> #include "alloc-util.h" #include "conf-parser.h" diff --git a/src/network/netdev/ipvlan.c b/src/network/netdev/ipvlan.c index 05d5d01..51ae643 100644 --- a/src/network/netdev/ipvlan.c +++ b/src/network/netdev/ipvlan.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> #include <netinet/in.h> #include <linux/if_arp.h> diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c index 17d6ace..4b9f19c 100644 --- a/src/network/netdev/macsec.c +++ b/src/network/netdev/macsec.c @@ -18,6 +18,7 @@ #include "socket-util.h" #include "string-table.h" #include "string-util.h" +#include "unaligned.h" static void security_association_clear(SecurityAssociation *sa) { if (!sa) @@ -711,7 +712,7 @@ int config_parse_macsec_key( dest = a ? &a->sa : &b->sa; - r = unhexmem_full(rvalue, strlen(rvalue), true, &p, &l); + r = unhexmem_full(rvalue, SIZE_MAX, /* secure = */ true, &p, &l); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse key. Ignoring assignment: %m"); return 0; @@ -819,7 +820,7 @@ int config_parse_macsec_key_id( if (r < 0) return log_oom(); - r = unhexmem(rvalue, strlen(rvalue), &p, &l); + r = unhexmem(rvalue, &p, &l); if (r == -ENOMEM) return log_oom(); if (r < 0) { diff --git a/src/network/netdev/macvlan.c b/src/network/netdev/macvlan.c index 203807e..21933d3 100644 --- a/src/network/netdev/macvlan.c +++ b/src/network/netdev/macvlan.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> #include <netinet/in.h> #include <linux/if_arp.h> @@ -10,6 +11,11 @@ #include "networkd-network.h" #include "parse-util.h" +typedef enum BCQueueThreshold { + BC_QUEUE_THRESHOLD_UNDEF = INT32_MIN, + BC_QUEUE_THRESHOLD_DISABLE = -1, +} BCQueueThreshold; + DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode"); static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { @@ -62,6 +68,12 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net return r; } + if (m->bc_queue_threshold != BC_QUEUE_THRESHOLD_UNDEF) { + r = sd_netlink_message_append_s32(req, IFLA_MACVLAN_BC_CUTOFF, m->bc_queue_threshold); + if (r < 0) + return r; + } + return 0; } @@ -96,6 +108,53 @@ int config_parse_macvlan_broadcast_queue_size( &m->bc_queue_length); } +int config_parse_macvlan_broadcast_queue_threshold( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + int32_t v, *threshold = ASSERT_PTR(data); + int r; + + if (isempty(rvalue)) { + *threshold = BC_QUEUE_THRESHOLD_UNDEF; + return 0; + } + + if (streq(rvalue, "no")) { + *threshold = BC_QUEUE_THRESHOLD_DISABLE; + return 0; + } + + r = safe_atoi32(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse %s=, ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + if (v < 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Invalid %s= value specified, ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + *threshold = v; + return 0; +} + static void macvlan_done(NetDev *netdev) { MacVlan *m = ASSERT_PTR(netdev)->kind == NETDEV_KIND_MACVLAN ? MACVLAN(netdev) : MACVTAP(netdev); @@ -107,6 +166,7 @@ static void macvlan_init(NetDev *netdev) { m->mode = _NETDEV_MACVLAN_MODE_INVALID; m->bc_queue_length = UINT32_MAX; + m->bc_queue_threshold = BC_QUEUE_THRESHOLD_UNDEF; } const NetDevVTable macvtap_vtable = { diff --git a/src/network/netdev/macvlan.h b/src/network/netdev/macvlan.h index c45fc4f..76b53a6 100644 --- a/src/network/netdev/macvlan.h +++ b/src/network/netdev/macvlan.h @@ -14,6 +14,7 @@ struct MacVlan { Set *match_source_mac; uint32_t bc_queue_length; + int32_t bc_queue_threshold; }; DEFINE_NETDEV_CAST(MACVLAN, MacVlan); @@ -23,3 +24,4 @@ extern const NetDevVTable macvtap_vtable; CONFIG_PARSER_PROTOTYPE(config_parse_macvlan_mode); CONFIG_PARSER_PROTOTYPE(config_parse_macvlan_broadcast_queue_size); +CONFIG_PARSER_PROTOTYPE(config_parse_macvlan_broadcast_queue_threshold); diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index d5aa522..4883a26 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -64,6 +64,7 @@ VLAN.IngressQOSMaps, config_parse_vlan_qos_maps, MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) MACVLAN.SourceMACAddress, config_parse_ether_addrs, 0, offsetof(MacVlan, match_source_mac) MACVLAN.BroadcastMulticastQueueLength, config_parse_macvlan_broadcast_queue_size, 0, offsetof(MacVlan, bc_queue_length) +MACVLAN.BroadcastQueueThreshold, config_parse_macvlan_broadcast_queue_threshold, 0, offsetof(MacVlan, bc_queue_threshold) MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) MACVTAP.SourceMACAddress, config_parse_ether_addrs, 0, offsetof(MacVlan, match_source_mac) IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) @@ -215,9 +216,11 @@ Bond.UpDelaySec, config_parse_sec, Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay) Bond.ARPIntervalSec, config_parse_sec, 0, offsetof(Bond, arp_interval) Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval) +Bond.PeerNotifyDelaySec, config_parse_sec, 0, offsetof(Bond, peer_notify_delay) Bond.AdActorSystemPriority, config_parse_ad_actor_sys_prio, 0, offsetof(Bond, ad_actor_sys_prio) Bond.AdUserPortKey, config_parse_ad_user_port_key, 0, offsetof(Bond, ad_user_port_key) Bond.AdActorSystem, config_parse_ad_actor_system, 0, offsetof(Bond, ad_actor_system) +Bond.ARPMissedMax, config_parse_uint8, 0, offsetof(Bond, arp_missed_max) Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time) Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age) Bridge.AgeingTimeSec, config_parse_sec, 0, offsetof(Bridge, ageing_time) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 57127a8..2b41142 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> #include <netinet/in.h> #include <linux/if_arp.h> @@ -198,14 +199,6 @@ static void netdev_detach_from_manager(NetDev *netdev) { static NetDev *netdev_free(NetDev *netdev) { assert(netdev); - netdev_detach_from_manager(netdev); - - free(netdev->filename); - - free(netdev->description); - free(netdev->ifname); - condition_free_list(netdev->conditions); - /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that * because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure * allocation, with no room for per-kind fields), and once to read the kind's properties (with a full, @@ -218,6 +211,13 @@ static NetDev *netdev_free(NetDev *netdev) { NETDEV_VTABLE(netdev)->done) NETDEV_VTABLE(netdev)->done(netdev); + netdev_detach_from_manager(netdev); + + condition_free_list(netdev->conditions); + free(netdev->filename); + free(netdev->description); + free(netdev->ifname); + return mfree(netdev); } @@ -449,8 +449,7 @@ int netdev_generate_hw_addr( memcpy(a.bytes, &result, a.length); if (ether_addr_is_null(&a.ether) || ether_addr_is_broadcast(&a.ether)) { - log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "Failed to generate persistent MAC address, ignoring: %m"); + log_netdev_warning(netdev, "Failed to generate persistent MAC address, ignoring."); a = HW_ADDR_NULL; goto finalize; } @@ -458,8 +457,7 @@ int netdev_generate_hw_addr( break; case ARPHRD_INFINIBAND: if (result == 0) { - log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "Failed to generate persistent MAC address: %m"); + log_netdev_warning(netdev, "Failed to generate persistent MAC address."); goto finalize; } diff --git a/src/network/netdev/tuntap.c b/src/network/netdev/tuntap.c index 9e909d1..f5be31e 100644 --- a/src/network/netdev/tuntap.c +++ b/src/network/netdev/tuntap.c @@ -1,13 +1,14 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ +#include <net/if.h> #include <errno.h> #include <fcntl.h> -#include <net/if.h> +#include <linux/if_tun.h> #include <netinet/if_ether.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> -#include <linux/if_tun.h> #include "alloc-util.h" #include "daemon-util.h" @@ -33,11 +34,6 @@ static TunTap* TUNTAP(NetDev *netdev) { } } -static void *close_fd_ptr(void *p) { - safe_close(PTR_TO_FD(p)); - return NULL; -} - DEFINE_PRIVATE_HASH_OPS_FULL(named_fd_hash_ops, char, string_hash_func, string_compare_func, free, void, close_fd_ptr); int manager_add_tuntap_fd(Manager *m, int fd, const char *name) { diff --git a/src/network/netdev/veth.c b/src/network/netdev/veth.c index e0f5b4e..7855528 100644 --- a/src/network/netdev/veth.c +++ b/src/network/netdev/veth.c @@ -1,10 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include <errno.h> +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> -#include <netinet/in.h> +#include <errno.h> #include <linux/if_arp.h> #include <linux/veth.h> +#include <netinet/in.h> #include "netlink-util.h" #include "veth.h" diff --git a/src/network/netdev/vlan.c b/src/network/netdev/vlan.c index 2390206..60e49a5 100644 --- a/src/network/netdev/vlan.c +++ b/src/network/netdev/vlan.c @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include <errno.h> +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> +#include <errno.h> #include <linux/if_arp.h> #include <linux/if_vlan.h> @@ -91,8 +92,8 @@ static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlin } static void vlan_qos_maps_hash_func(const struct ifla_vlan_qos_mapping *x, struct siphash *state) { - siphash24_compress(&x->from, sizeof(x->from), state); - siphash24_compress(&x->to, sizeof(x->to), state); + siphash24_compress_typesafe(x->from, state); + siphash24_compress_typesafe(x->to, state); } static int vlan_qos_maps_compare_func(const struct ifla_vlan_qos_mapping *a, const struct ifla_vlan_qos_mapping *b) { diff --git a/src/network/netdev/vrf.c b/src/network/netdev/vrf.c index b75ec2b..24079a7 100644 --- a/src/network/netdev/vrf.c +++ b/src/network/netdev/vrf.c @@ -1,8 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> -#include <netinet/in.h> #include <linux/if_arp.h> +#include <netinet/in.h> #include "vrf.h" diff --git a/src/network/netdev/vxlan.c b/src/network/netdev/vxlan.c index b11fdbb..37f6596 100644 --- a/src/network/netdev/vxlan.c +++ b/src/network/netdev/vxlan.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> #include <netinet/in.h> #include <linux/if_arp.h> @@ -289,7 +290,7 @@ int config_parse_port_range( VxLan *v = ASSERT_PTR(userdata); int r; - r = parse_ip_port_range(rvalue, &v->port_range.low, &v->port_range.high); + r = parse_ip_port_range(rvalue, &v->port_range.low, &v->port_range.high, /* allow_zero = */ false); if (r < 0) log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", rvalue); diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c index 4c7d837..fed1be8 100644 --- a/src/network/netdev/wireguard.c +++ b/src/network/netdev/wireguard.c @@ -3,15 +3,17 @@ Copyright © 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. ***/ -#include <sys/ioctl.h> +/* Make sure the net/if.h header is included before any linux/ one */ #include <net/if.h> -#include <netinet/in.h> #include <linux/if_arp.h> #include <linux/ipv6_route.h> +#include <netinet/in.h> +#include <sys/ioctl.h> #include "sd-resolve.h" #include "alloc-util.h" +#include "creds-util.h" #include "dns-domain.h" #include "event-util.h" #include "fd-util.h" @@ -25,6 +27,7 @@ #include "networkd-util.h" #include "parse-helpers.h" #include "parse-util.h" +#include "path-util.h" #include "random-util.h" #include "resolve-private.h" #include "string-util.h" @@ -480,6 +483,8 @@ static int wireguard_decode_key_and_warn( const char *lvalue) { _cleanup_(erase_and_freep) void *key = NULL; + _cleanup_(erase_and_freep) char *cred = NULL; + const char *cred_name; size_t len; int r; @@ -493,10 +498,22 @@ static int wireguard_decode_key_and_warn( return 0; } - if (!streq(lvalue, "PublicKey")) + cred_name = startswith(rvalue, "@"); + if (cred_name) { + r = read_credential(cred_name, (void**) &cred, /* ret_size = */ NULL); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to read credential for wireguard key (%s=), ignoring assignment: %m", + lvalue); + return 0; + } + + } else if (!streq(lvalue, "PublicKey")) (void) warn_file_is_world_accessible(filename, NULL, unit, line); - r = unbase64mem_full(rvalue, strlen(rvalue), true, &key, &len); + r = unbase64mem_full(cred ?: rvalue, SIZE_MAX, /* secure = */ true, &key, &len); if (r == -ENOMEM) return log_oom(); if (r < 0) { @@ -721,23 +738,39 @@ int config_parse_wireguard_endpoint( void *data, void *userdata) { - assert(filename); - assert(rvalue); - assert(userdata); - Wireguard *w = WIREGUARD(userdata); _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; - _cleanup_free_ char *host = NULL; - union in_addr_union addr; - const char *p; + _cleanup_free_ char *cred = NULL; + const char *cred_name, *endpoint; uint16_t port; - int family, r; + int r; + + assert(filename); + assert(rvalue); r = wireguard_peer_new_static(w, filename, section_line, &peer); if (r < 0) return log_oom(); - r = in_addr_port_ifindex_name_from_string_auto(rvalue, &family, &addr, &port, NULL, NULL); + cred_name = startswith(rvalue, "@"); + if (cred_name) { + r = read_credential(cred_name, (void**) &cred, /* ret_size = */ NULL); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to read credential for wireguard endpoint, ignoring assignment: %m"); + return 0; + } + + endpoint = strstrip(cred); + } else + endpoint = rvalue; + + union in_addr_union addr; + int family; + + r = in_addr_port_ifindex_name_from_string_auto(endpoint, &family, &addr, &port, NULL, NULL); if (r >= 0) { if (family == AF_INET) peer->endpoint.in = (struct sockaddr_in) { @@ -761,17 +794,23 @@ int config_parse_wireguard_endpoint( return 0; } - p = strrchr(rvalue, ':'); + _cleanup_free_ char *host = NULL; + const char *p; + + p = strrchr(endpoint, ':'); if (!p) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Unable to find port of endpoint, ignoring assignment: %s", - rvalue); + rvalue); /* We log the original assignment instead of resolved credential here, + as the latter might be previously encrypted and we'd expose them in + unprotected logs otherwise. */ return 0; } - host = strndup(rvalue, p - rvalue); + host = strndup(endpoint, p - endpoint); if (!host) return log_oom(); + p++; if (!dns_name_is_valid(host)) { log_syntax(unit, LOG_WARNING, filename, line, 0, @@ -780,7 +819,6 @@ int config_parse_wireguard_endpoint( return 0; } - p++; r = parse_ip_port(p, &port); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, @@ -1078,6 +1116,55 @@ static int wireguard_peer_verify(WireguardPeer *peer) { return 0; } +static int wireguard_read_default_key_cred(NetDev *netdev, const char *filename) { + Wireguard *w = WIREGUARD(netdev); + _cleanup_free_ char *config_name = NULL; + int r; + + assert(filename); + + r = path_extract_filename(filename, &config_name); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "%s: Failed to extract config name, ignoring network device: %m", + filename); + + char *p = endswith(config_name, ".netdev"); + if (!p) + /* Fuzzer run? Then we just ignore this device. */ + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: Invalid netdev config name, refusing default key lookup.", + filename); + *p = '\0'; + + _cleanup_(erase_and_freep) char *cred = NULL; + + r = read_credential(strjoina("network.wireguard.private.", config_name), (void**) &cred, /* ret_size = */ NULL); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "%s: No private key specified and default key isn't available, " + "ignoring network device: %m", + filename); + + _cleanup_(erase_and_freep) void *key = NULL; + size_t len; + + r = unbase64mem_full(cred, SIZE_MAX, /* secure = */ true, &key, &len); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "%s: No private key specified and default key cannot be parsed, " + "ignoring network device: %m", + filename); + if (len != WG_KEY_LEN) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: No private key specified and default key is invalid. " + "Ignoring network device.", + filename); + + memcpy(w->private_key, key, WG_KEY_LEN); + return 0; +} + static int wireguard_verify(NetDev *netdev, const char *filename) { Wireguard *w = WIREGUARD(netdev); int r; @@ -1088,10 +1175,11 @@ static int wireguard_verify(NetDev *netdev, const char *filename) { "Failed to read private key from %s. Ignoring network device.", w->private_key_file); - if (eqzero(w->private_key)) - return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), - "%s: Missing PrivateKey= or PrivateKeyFile=, " - "Ignoring network device.", filename); + if (eqzero(w->private_key)) { + r = wireguard_read_default_key_cred(netdev, filename); + if (r < 0) + return r; + } LIST_FOREACH(peers, peer, w->peers) { if (wireguard_peer_verify(peer) < 0) { @@ -1103,26 +1191,39 @@ static int wireguard_verify(NetDev *netdev, const char *filename) { continue; LIST_FOREACH(ipmasks, ipmask, peer->ipmasks) { - _cleanup_(route_freep) Route *route = NULL; + _cleanup_(route_unrefp) Route *route = NULL; r = route_new(&route); if (r < 0) return log_oom(); + /* For route_section_verify() below. */ + r = config_section_new(peer->section->filename, peer->section->line, &route->section); + if (r < 0) + return log_oom(); + + route->source = NETWORK_CONFIG_SOURCE_STATIC; route->family = ipmask->family; route->dst = ipmask->ip; route->dst_prefixlen = ipmask->cidr; - route->scope = RT_SCOPE_UNIVERSE; route->protocol = RTPROT_STATIC; + route->protocol_set = true; route->table = peer->route_table_set ? peer->route_table : w->route_table; + route->table_set = true; route->priority = peer->route_priority_set ? peer->route_priority : w->route_priority; - if (route->priority == 0 && route->family == AF_INET6) - route->priority = IP6_RT_PRIO_USER; - route->source = NETWORK_CONFIG_SOURCE_STATIC; + route->priority_set = true; - r = set_ensure_consume(&w->routes, &route_hash_ops, TAKE_PTR(route)); + if (route_section_verify(route) < 0) + continue; + + r = set_ensure_put(&w->routes, &route_hash_ops, route); if (r < 0) return log_oom(); + if (r == 0) + continue; + + route->wireguard = w; + TAKE_PTR(route); } } |