1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
8 #include <netinet/in.h>
9 #include <linux/if_arp.h>
10 #include <linux/ipv6_route.h>
12 #include "sd-resolve.h"
14 #include "alloc-util.h"
15 #include "dns-domain.h"
16 #include "event-util.h"
19 #include "hexdecoct.h"
20 #include "memory-util.h"
21 #include "netlink-util.h"
22 #include "networkd-manager.h"
23 #include "networkd-route-util.h"
24 #include "networkd-route.h"
25 #include "networkd-util.h"
26 #include "parse-util.h"
27 #include "path-util.h"
28 #include "random-util.h"
29 #include "resolve-private.h"
30 #include "string-util.h"
32 #include "wireguard.h"
34 static void wireguard_resolve_endpoints(NetDev
*netdev
);
35 static int peer_resolve_endpoint(WireguardPeer
*peer
);
37 static WireguardPeer
* wireguard_peer_free(WireguardPeer
*peer
) {
38 WireguardIPmask
*mask
;
43 if (peer
->wireguard
) {
44 LIST_REMOVE(peers
, peer
->wireguard
->peers
, peer
);
47 hashmap_remove(peer
->wireguard
->peers_by_section
, peer
->section
);
50 config_section_free(peer
->section
);
52 while ((mask
= peer
->ipmasks
)) {
53 LIST_REMOVE(ipmasks
, peer
->ipmasks
, mask
);
57 free(peer
->endpoint_host
);
58 free(peer
->endpoint_port
);
59 free(peer
->preshared_key_file
);
60 explicit_bzero_safe(peer
->preshared_key
, WG_KEY_LEN
);
62 sd_event_source_disable_unref(peer
->resolve_retry_event_source
);
63 sd_resolve_query_unref(peer
->resolve_query
);
68 DEFINE_SECTION_CLEANUP_FUNCTIONS(WireguardPeer
, wireguard_peer_free
);
70 static int wireguard_peer_new_static(Wireguard
*w
, const char *filename
, unsigned section_line
, WireguardPeer
**ret
) {
71 _cleanup_(config_section_freep
) ConfigSection
*n
= NULL
;
72 _cleanup_(wireguard_peer_freep
) WireguardPeer
*peer
= NULL
;
78 assert(section_line
> 0);
80 r
= config_section_new(filename
, section_line
, &n
);
84 peer
= hashmap_get(w
->peers_by_section
, n
);
86 *ret
= TAKE_PTR(peer
);
90 peer
= new(WireguardPeer
, 1);
94 *peer
= (WireguardPeer
) {
95 .flags
= WGPEER_F_REPLACE_ALLOWEDIPS
,
97 .section
= TAKE_PTR(n
),
100 LIST_PREPEND(peers
, w
->peers
, peer
);
102 r
= hashmap_ensure_put(&w
->peers_by_section
, &config_section_hash_ops
, peer
->section
, peer
);
106 *ret
= TAKE_PTR(peer
);
110 static int wireguard_set_ipmask_one(NetDev
*netdev
, sd_netlink_message
*message
, const WireguardIPmask
*mask
, uint16_t index
) {
117 /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */
119 r
= sd_netlink_message_open_array(message
, index
);
123 r
= sd_netlink_message_append_u16(message
, WGALLOWEDIP_A_FAMILY
, mask
->family
);
127 r
= netlink_message_append_in_addr_union(message
, WGALLOWEDIP_A_IPADDR
, mask
->family
, &mask
->ip
);
131 r
= sd_netlink_message_append_u8(message
, WGALLOWEDIP_A_CIDR_MASK
, mask
->cidr
);
135 r
= sd_netlink_message_close_container(message
);
137 return log_netdev_error_errno(netdev
, r
, "Could not add wireguard allowed ip: %m");
142 r
= sd_netlink_message_cancel_array(message
);
144 return log_netdev_error_errno(netdev
, r
, "Could not cancel wireguard allowed ip message attribute: %m");
149 static int wireguard_set_peer_one(NetDev
*netdev
, sd_netlink_message
*message
, const WireguardPeer
*peer
, uint16_t index
, WireguardIPmask
**mask_start
) {
150 WireguardIPmask
*mask
, *start
;
159 /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */
161 start
= *mask_start
?: peer
->ipmasks
;
163 r
= sd_netlink_message_open_array(message
, index
);
167 r
= sd_netlink_message_append_data(message
, WGPEER_A_PUBLIC_KEY
, &peer
->public_key
, sizeof(peer
->public_key
));
172 r
= sd_netlink_message_append_data(message
, WGPEER_A_PRESHARED_KEY
, &peer
->preshared_key
, WG_KEY_LEN
);
176 r
= sd_netlink_message_append_u32(message
, WGPEER_A_FLAGS
, peer
->flags
);
180 r
= sd_netlink_message_append_u16(message
, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL
, peer
->persistent_keepalive_interval
);
184 if (IN_SET(peer
->endpoint
.sa
.sa_family
, AF_INET
, AF_INET6
)) {
185 r
= netlink_message_append_sockaddr_union(message
, WGPEER_A_ENDPOINT
, &peer
->endpoint
);
191 r
= sd_netlink_message_open_container(message
, WGPEER_A_ALLOWEDIPS
);
195 LIST_FOREACH(ipmasks
, mask
, start
) {
196 r
= wireguard_set_ipmask_one(netdev
, message
, mask
, ++j
);
203 r
= sd_netlink_message_close_container(message
);
205 return log_netdev_error_errno(netdev
, r
, "Could not add wireguard allowed ip: %m");
207 r
= sd_netlink_message_close_container(message
);
209 return log_netdev_error_errno(netdev
, r
, "Could not add wireguard peer: %m");
211 *mask_start
= mask
; /* Start next cycle from this mask. */
215 r
= sd_netlink_message_cancel_array(message
);
217 return log_netdev_error_errno(netdev
, r
, "Could not cancel wireguard peers: %m");
222 static int wireguard_set_interface(NetDev
*netdev
) {
223 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
;
224 WireguardIPmask
*mask_start
= NULL
;
225 WireguardPeer
*peer
, *peer_start
;
226 bool sent_once
= false;
232 w
= WIREGUARD(netdev
);
235 for (peer_start
= w
->peers
; peer_start
|| !sent_once
; ) {
238 message
= sd_netlink_message_unref(message
);
240 r
= sd_genl_message_new(netdev
->manager
->genl
, WG_GENL_NAME
, WG_CMD_SET_DEVICE
, &message
);
242 return log_netdev_error_errno(netdev
, r
, "Failed to allocate generic netlink message: %m");
244 r
= sd_netlink_message_append_string(message
, WGDEVICE_A_IFNAME
, netdev
->ifname
);
246 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard interface name: %m");
248 if (peer_start
== w
->peers
) {
249 r
= sd_netlink_message_append_data(message
, WGDEVICE_A_PRIVATE_KEY
, &w
->private_key
, WG_KEY_LEN
);
251 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard private key: %m");
253 r
= sd_netlink_message_append_u16(message
, WGDEVICE_A_LISTEN_PORT
, w
->port
);
255 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard port: %m");
257 r
= sd_netlink_message_append_u32(message
, WGDEVICE_A_FWMARK
, w
->fwmark
);
259 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard fwmark: %m");
261 r
= sd_netlink_message_append_u32(message
, WGDEVICE_A_FLAGS
, w
->flags
);
263 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard flags: %m");
266 r
= sd_netlink_message_open_container(message
, WGDEVICE_A_PEERS
);
268 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard peer attributes: %m");
270 LIST_FOREACH(peers
, peer
, peer_start
) {
271 r
= wireguard_set_peer_one(netdev
, message
, peer
, ++i
, &mask_start
);
277 peer_start
= peer
; /* Start next cycle from this peer. */
279 r
= sd_netlink_message_close_container(message
);
281 return log_netdev_error_errno(netdev
, r
, "Could not close wireguard container: %m");
283 r
= sd_netlink_send(netdev
->manager
->genl
, message
, &serial
);
285 return log_netdev_error_errno(netdev
, r
, "Could not set wireguard device: %m");
293 static int on_resolve_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
294 WireguardPeer
*peer
= userdata
;
298 assert(peer
->wireguard
);
300 netdev
= NETDEV(peer
->wireguard
);
302 if (!netdev_is_managed(netdev
))
305 peer
->resolve_query
= sd_resolve_query_unref(peer
->resolve_query
);
307 (void) peer_resolve_endpoint(peer
);
311 static usec_t
peer_next_resolve_usec(WireguardPeer
*peer
) {
314 /* Given the number of retries this function will return an exponential increasing amount of
315 * milliseconds to wait starting at 200ms and capped at 25 seconds. */
319 usec
= (2 << MIN(peer
->n_retries
, 7U)) * 100 * USEC_PER_MSEC
;
321 return random_u64_range(usec
/ 10) + usec
* 9 / 10;
324 static int wireguard_peer_resolve_handler(
327 const struct addrinfo
*ai
,
330 WireguardPeer
*peer
= userdata
;
335 assert(peer
->wireguard
);
337 netdev
= NETDEV(peer
->wireguard
);
339 if (!netdev_is_managed(netdev
))
343 log_netdev_warning(netdev
, "Failed to resolve host '%s:%s', ignoring: %s",
344 peer
->endpoint_host
, peer
->endpoint_port
, gai_strerror(ret
));
349 for (; ai
; ai
= ai
->ai_next
) {
350 if (!IN_SET(ai
->ai_family
, AF_INET
, AF_INET6
))
353 if (ai
->ai_addrlen
!= (ai
->ai_family
== AF_INET
? sizeof(struct sockaddr_in
) : sizeof(struct sockaddr_in6
)))
356 memcpy(&peer
->endpoint
, ai
->ai_addr
, ai
->ai_addrlen
);
357 (void) wireguard_set_interface(netdev
);
364 log_netdev_warning(netdev
, "Neither IPv4 nor IPv6 address found for peer endpoint %s:%s, ignoring the endpoint.",
365 peer
->endpoint_host
, peer
->endpoint_port
);
370 if (peer
->n_retries
> 0) {
371 r
= event_reset_time_relative(netdev
->manager
->event
,
372 &peer
->resolve_retry_event_source
,
373 clock_boottime_or_monotonic(),
374 peer_next_resolve_usec(peer
), 0,
375 on_resolve_retry
, peer
, 0, "wireguard-resolve-retry", true);
377 log_netdev_warning_errno(netdev
, r
, "Could not arm resolve retry handler for endpoint %s:%s, ignoring: %m",
378 peer
->endpoint_host
, peer
->endpoint_port
);
381 wireguard_resolve_endpoints(netdev
);
385 static int peer_resolve_endpoint(WireguardPeer
*peer
) {
386 static const struct addrinfo hints
= {
387 .ai_family
= AF_UNSPEC
,
388 .ai_socktype
= SOCK_DGRAM
,
389 .ai_protocol
= IPPROTO_UDP
395 assert(peer
->wireguard
);
397 netdev
= NETDEV(peer
->wireguard
);
399 if (!peer
->endpoint_host
|| !peer
->endpoint_port
)
400 /* Not necessary to resolve the endpoint. */
403 if (event_source_is_enabled(peer
->resolve_retry_event_source
) > 0)
404 /* Timer event source is enabled. The endpoint will be resolved later. */
407 if (peer
->resolve_query
)
408 /* Being resolved, or already resolved. */
411 r
= sd_resolve_getaddrinfo(netdev
->manager
->resolve
,
412 &peer
->resolve_query
,
416 wireguard_peer_resolve_handler
,
419 return log_netdev_full_errno(netdev
, r
== -ENOBUFS
? LOG_DEBUG
: LOG_WARNING
, r
,
420 "Failed to create endpoint resolver for %s:%s, ignoring: %m",
421 peer
->endpoint_host
, peer
->endpoint_port
);
426 static void wireguard_resolve_endpoints(NetDev
*netdev
) {
431 w
= WIREGUARD(netdev
);
434 LIST_FOREACH(peers
, peer
, w
->peers
)
435 if (peer_resolve_endpoint(peer
) == -ENOBUFS
)
436 /* Too many requests. Let's resolve remaining endpoints later. */
440 static int netdev_wireguard_post_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
442 assert(WIREGUARD(netdev
));
444 (void) wireguard_set_interface(netdev
);
445 wireguard_resolve_endpoints(netdev
);
449 int config_parse_wireguard_listen_port(
451 const char *filename
,
454 unsigned section_line
,
467 if (isempty(rvalue
) || streq(rvalue
, "auto")) {
472 r
= parse_ip_port(rvalue
, s
);
474 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
475 "Invalid port specification, ignoring assignment: %s", rvalue
);
482 static int wireguard_decode_key_and_warn(
484 uint8_t ret
[static WG_KEY_LEN
],
486 const char *filename
,
488 const char *lvalue
) {
490 _cleanup_(erase_and_freep
) void *key
= NULL
;
499 if (isempty(rvalue
)) {
500 memzero(ret
, WG_KEY_LEN
);
504 if (!streq(lvalue
, "PublicKey"))
505 (void) warn_file_is_world_accessible(filename
, NULL
, unit
, line
);
507 r
= unbase64mem_full(rvalue
, strlen(rvalue
), true, &key
, &len
);
511 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
512 "Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue
);
515 if (len
!= WG_KEY_LEN
) {
516 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
517 "Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.",
522 memcpy(ret
, key
, WG_KEY_LEN
);
526 int config_parse_wireguard_private_key(
528 const char *filename
,
531 unsigned section_line
,
544 return wireguard_decode_key_and_warn(rvalue
, w
->private_key
, unit
, filename
, line
, lvalue
);
547 int config_parse_wireguard_private_key_file(
549 const char *filename
,
552 unsigned section_line
,
559 _cleanup_free_
char *path
= NULL
;
566 if (isempty(rvalue
)) {
567 w
->private_key_file
= mfree(w
->private_key_file
);
571 path
= strdup(rvalue
);
575 if (path_simplify_and_warn(path
, PATH_CHECK_ABSOLUTE
, unit
, filename
, line
, lvalue
) < 0)
578 return free_and_replace(w
->private_key_file
, path
);
581 int config_parse_wireguard_peer_key(
583 const char *filename
,
586 unsigned section_line
,
593 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
601 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
605 r
= wireguard_decode_key_and_warn(rvalue
,
606 streq(lvalue
, "PublicKey") ? peer
->public_key
: peer
->preshared_key
,
607 unit
, filename
, line
, lvalue
);
615 int config_parse_wireguard_preshared_key_file(
617 const char *filename
,
620 unsigned section_line
,
627 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
628 _cleanup_free_
char *path
= NULL
;
636 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
640 if (isempty(rvalue
)) {
641 peer
->preshared_key_file
= mfree(peer
->preshared_key_file
);
646 path
= strdup(rvalue
);
650 if (path_simplify_and_warn(path
, PATH_CHECK_ABSOLUTE
, unit
, filename
, line
, lvalue
) < 0)
653 free_and_replace(peer
->preshared_key_file
, path
);
658 int config_parse_wireguard_allowed_ips(
660 const char *filename
,
663 unsigned section_line
,
670 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
671 union in_addr_union addr
;
672 unsigned char prefixlen
;
675 WireguardIPmask
*ipmask
;
683 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
687 for (const char *p
= rvalue
;;) {
688 _cleanup_free_
char *word
= NULL
;
689 union in_addr_union masked
;
691 r
= extract_first_word(&p
, &word
, "," WHITESPACE
, 0);
697 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
698 "Failed to split allowed ips \"%s\" option: %m", rvalue
);
702 r
= in_addr_prefix_from_string_auto(word
, &family
, &addr
, &prefixlen
);
704 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
705 "Network address is invalid, ignoring assignment: %s", word
);
710 assert_se(in_addr_mask(family
, &masked
, prefixlen
) >= 0);
711 if (!in_addr_equal(family
, &masked
, &addr
)) {
712 _cleanup_free_
char *buf
= NULL
;
714 (void) in_addr_prefix_to_string(family
, &masked
, prefixlen
, &buf
);
715 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
716 "Specified address '%s' is not properly masked, assuming '%s'.", word
, strna(buf
));
719 ipmask
= new(WireguardIPmask
, 1);
723 *ipmask
= (WireguardIPmask
) {
729 LIST_PREPEND(ipmasks
, peer
->ipmasks
, ipmask
);
736 int config_parse_wireguard_endpoint(
738 const char *filename
,
741 unsigned section_line
,
748 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
749 _cleanup_free_
char *host
= NULL
;
750 union in_addr_union addr
;
760 w
= WIREGUARD(userdata
);
763 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
767 r
= in_addr_port_ifindex_name_from_string_auto(rvalue
, &family
, &addr
, &port
, NULL
, NULL
);
769 if (family
== AF_INET
)
770 peer
->endpoint
.in
= (struct sockaddr_in
) {
771 .sin_family
= AF_INET
,
773 .sin_port
= htobe16(port
),
775 else if (family
== AF_INET6
)
776 peer
->endpoint
.in6
= (struct sockaddr_in6
) {
777 .sin6_family
= AF_INET6
,
778 .sin6_addr
= addr
.in6
,
779 .sin6_port
= htobe16(port
),
782 assert_not_reached();
784 peer
->endpoint_host
= mfree(peer
->endpoint_host
);
785 peer
->endpoint_port
= mfree(peer
->endpoint_port
);
791 p
= strrchr(rvalue
, ':');
793 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
794 "Unable to find port of endpoint, ignoring assignment: %s",
799 host
= strndup(rvalue
, p
- rvalue
);
803 if (!dns_name_is_valid(host
)) {
804 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
805 "Invalid domain name of endpoint, ignoring assignment: %s",
811 r
= parse_ip_port(p
, &port
);
813 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
814 "Invalid port of endpoint, ignoring assignment: %s",
819 peer
->endpoint
= (union sockaddr_union
) {};
821 free_and_replace(peer
->endpoint_host
, host
);
823 r
= free_and_strdup(&peer
->endpoint_port
, p
);
827 TAKE_PTR(peer
); /* The peer may already have been in the hash map, that is fine too. */
831 int config_parse_wireguard_keepalive(
833 const char *filename
,
836 unsigned section_line
,
843 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
844 uint16_t keepalive
= 0;
854 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
858 if (streq(rvalue
, "off"))
861 r
= safe_atou16(rvalue
, &keepalive
);
863 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
864 "Failed to parse \"%s\" as keepalive interval (range 0–65535), ignoring assignment: %m",
870 peer
->persistent_keepalive_interval
= keepalive
;
876 int config_parse_wireguard_route_table(
878 const char *filename
,
881 unsigned section_line
,
888 NetDev
*netdev
= userdata
;
889 uint32_t *table
= data
;
898 if (isempty(rvalue
) || parse_boolean(rvalue
) == 0) {
899 *table
= 0; /* Disabled. */
903 r
= manager_get_route_table_from_string(netdev
->manager
, rvalue
, table
);
905 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
906 "Failed to parse %s=, ignoring assignment: %s",
914 int config_parse_wireguard_peer_route_table(
916 const char *filename
,
919 unsigned section_line
,
926 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
927 NetDev
*netdev
= userdata
;
935 assert(netdev
->manager
);
937 w
= WIREGUARD(netdev
);
940 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
944 if (isempty(rvalue
)) {
945 peer
->route_table_set
= false; /* Use the table specified in [WireGuard] section. */
950 if (parse_boolean(rvalue
) == 0) {
951 peer
->route_table
= 0; /* Disabled. */
952 peer
->route_table_set
= true;
957 r
= manager_get_route_table_from_string(netdev
->manager
, rvalue
, &peer
->route_table
);
959 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
960 "Failed to parse %s=, ignoring assignment: %s",
965 peer
->route_table_set
= true;
970 int config_parse_wireguard_route_priority(
972 const char *filename
,
975 unsigned section_line
,
982 uint32_t *priority
= data
;
990 if (isempty(rvalue
)) {
995 r
= safe_atou32(rvalue
, priority
);
997 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
998 "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue
);
1005 int config_parse_wireguard_peer_route_priority(
1007 const char *filename
,
1009 const char *section
,
1010 unsigned section_line
,
1017 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
1026 w
= WIREGUARD(userdata
);
1029 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
1033 if (isempty(rvalue
)) {
1034 peer
->route_priority_set
= false; /* Use the priority specified in [WireGuard] section. */
1039 r
= safe_atou32(rvalue
, &peer
->route_priority
);
1041 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
1042 "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue
);
1046 peer
->route_priority_set
= true;
1051 static void wireguard_init(NetDev
*netdev
) {
1055 w
= WIREGUARD(netdev
);
1058 w
->flags
= WGDEVICE_F_REPLACE_PEERS
;
1061 static void wireguard_done(NetDev
*netdev
) {
1065 w
= WIREGUARD(netdev
);
1068 explicit_bzero_safe(w
->private_key
, WG_KEY_LEN
);
1069 free(w
->private_key_file
);
1071 hashmap_free_with_destructor(w
->peers_by_section
, wireguard_peer_free
);
1073 set_free(w
->routes
);
1076 static int wireguard_read_key_file(const char *filename
, uint8_t dest
[static WG_KEY_LEN
]) {
1077 _cleanup_(erase_and_freep
) char *key
= NULL
;
1086 (void) warn_file_is_world_accessible(filename
, NULL
, NULL
, 0);
1088 r
= read_full_file_full(
1089 AT_FDCWD
, filename
, UINT64_MAX
, SIZE_MAX
,
1090 READ_FULL_FILE_SECURE
| READ_FULL_FILE_UNBASE64
| READ_FULL_FILE_WARN_WORLD_READABLE
| READ_FULL_FILE_CONNECT_SOCKET
,
1091 NULL
, &key
, &key_len
);
1095 if (key_len
!= WG_KEY_LEN
)
1098 memcpy(dest
, key
, WG_KEY_LEN
);
1102 static int wireguard_peer_verify(WireguardPeer
*peer
) {
1103 NetDev
*netdev
= NETDEV(peer
->wireguard
);
1106 if (section_is_invalid(peer
->section
))
1109 if (eqzero(peer
->public_key
))
1110 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
1111 "%s: WireGuardPeer section without PublicKey= configured. "
1112 "Ignoring [WireGuardPeer] section from line %u.",
1113 peer
->section
->filename
, peer
->section
->line
);
1115 r
= wireguard_read_key_file(peer
->preshared_key_file
, peer
->preshared_key
);
1117 return log_netdev_error_errno(netdev
, r
,
1118 "%s: Failed to read preshared key from '%s'. "
1119 "Ignoring [WireGuardPeer] section from line %u.",
1120 peer
->section
->filename
, peer
->preshared_key_file
,
1121 peer
->section
->line
);
1126 static int wireguard_verify(NetDev
*netdev
, const char *filename
) {
1127 WireguardPeer
*peer
, *peer_next
;
1132 w
= WIREGUARD(netdev
);
1135 r
= wireguard_read_key_file(w
->private_key_file
, w
->private_key
);
1137 return log_netdev_error_errno(netdev
, r
,
1138 "Failed to read private key from %s. Ignoring network device.",
1139 w
->private_key_file
);
1141 if (eqzero(w
->private_key
))
1142 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
1143 "%s: Missing PrivateKey= or PrivateKeyFile=, "
1144 "Ignoring network device.", filename
);
1146 LIST_FOREACH_SAFE(peers
, peer
, peer_next
, w
->peers
) {
1147 WireguardIPmask
*ipmask
;
1149 if (wireguard_peer_verify(peer
) < 0) {
1150 wireguard_peer_free(peer
);
1154 if ((peer
->route_table_set
? peer
->route_table
: w
->route_table
) == 0)
1157 LIST_FOREACH(ipmasks
, ipmask
, peer
->ipmasks
) {
1158 _cleanup_(route_freep
) Route
*route
= NULL
;
1160 r
= route_new(&route
);
1164 route
->family
= ipmask
->family
;
1165 route
->dst
= ipmask
->ip
;
1166 route
->dst_prefixlen
= ipmask
->cidr
;
1167 route
->scope
= RT_SCOPE_UNIVERSE
;
1168 route
->protocol
= RTPROT_STATIC
;
1169 route
->table
= peer
->route_table_set
? peer
->route_table
: w
->route_table
;
1170 route
->priority
= peer
->route_priority_set
? peer
->route_priority
: w
->route_priority
;
1171 if (route
->priority
== 0 && route
->family
== AF_INET6
)
1172 route
->priority
= IP6_RT_PRIO_USER
;
1173 route
->source
= NETWORK_CONFIG_SOURCE_STATIC
;
1175 r
= set_ensure_consume(&w
->routes
, &route_hash_ops
, TAKE_PTR(route
));
1184 const NetDevVTable wireguard_vtable
= {
1185 .object_size
= sizeof(Wireguard
),
1186 .sections
= NETDEV_COMMON_SECTIONS
"WireGuard\0WireGuardPeer\0",
1187 .post_create
= netdev_wireguard_post_create
,
1188 .init
= wireguard_init
,
1189 .done
= wireguard_done
,
1190 .create_type
= NETDEV_CREATE_INDEPENDENT
,
1191 .config_verify
= wireguard_verify
,
1192 .iftype
= ARPHRD_NONE
,