summaryrefslogtreecommitdiffstats
path: root/src/network/netdev
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 03:50:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 03:50:42 +0000
commit78e9bb837c258ac0ec7712b3d612cc2f407e731e (patch)
treef515d16b6efd858a9aeb5b0ef5d6f90bf288283d /src/network/netdev
parentAdding debian version 255.5-1. (diff)
downloadsystemd-78e9bb837c258ac0ec7712b3d612cc2f407e731e.tar.xz
systemd-78e9bb837c258ac0ec7712b3d612cc2f407e731e.zip
Merging upstream version 256.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/network/netdev')
-rw-r--r--src/network/netdev/bond.c12
-rw-r--r--src/network/netdev/bond.h3
-rw-r--r--src/network/netdev/bridge.c3
-rw-r--r--src/network/netdev/fou-tunnel.c3
-rw-r--r--src/network/netdev/geneve.c3
-rw-r--r--src/network/netdev/ipvlan.c1
-rw-r--r--src/network/netdev/macsec.c5
-rw-r--r--src/network/netdev/macvlan.c60
-rw-r--r--src/network/netdev/macvlan.h2
-rw-r--r--src/network/netdev/netdev-gperf.gperf3
-rw-r--r--src/network/netdev/netdev.c22
-rw-r--r--src/network/netdev/tuntap.c10
-rw-r--r--src/network/netdev/veth.c5
-rw-r--r--src/network/netdev/vlan.c7
-rw-r--r--src/network/netdev/vrf.c3
-rw-r--r--src/network/netdev/vxlan.c3
-rw-r--r--src/network/netdev/wireguard.c155
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);
}
}