Bug Summary

File:build-scan/../src/network/netdev/wireguard.c
Warning:line 684, column 17
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name wireguard.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/network/libnetworkd-core.a.p -I src/network -I ../src/network -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/network/netdev/wireguard.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2/***
3 Copyright © 2016-2017 Jörg Thalheim <joerg@thalheim.io>
4 Copyright © 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
5***/
6
7#include <sys/ioctl.h>
8#include <net/if.h>
9
10#include "alloc-util.h"
11#include "parse-util.h"
12#include "fd-util.h"
13#include "strv.h"
14#include "hexdecoct.h"
15#include "string-util.h"
16#include "wireguard.h"
17#include "networkd-link.h"
18#include "networkd-util.h"
19#include "networkd-manager.h"
20#include "wireguard-netlink.h"
21
22static void resolve_endpoints(NetDev *netdev);
23
24static WireguardPeer *wireguard_peer_new(Wireguard *w, unsigned section) {
25 WireguardPeer *peer;
26
27 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 27, __PRETTY_FUNCTION__); } while (0)
;
28
29 if (w->last_peer_section == section && w->peers)
30 return w->peers;
31
32 peer = new0(WireguardPeer, 1)((WireguardPeer*) calloc((1), sizeof(WireguardPeer)));
33 if (!peer)
34 return NULL((void*)0);
35 peer->flags = WGPEER_F_REPLACE_ALLOWEDIPS;
36
37 LIST_PREPEND(peers, w->peers, peer)do { typeof(*(w->peers)) **_head = &(w->peers), *_item
= (peer); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/network/netdev/wireguard.c"
, 37, __PRETTY_FUNCTION__); } while (0); if ((_item->peers_next
= *_head)) _item->peers_next->peers_prev = _item; _item
->peers_prev = ((void*)0); *_head = _item; } while (0)
;
38 w->last_peer_section = section;
39
40 return peer;
41}
42
43static int set_wireguard_interface(NetDev *netdev) {
44 int r;
45 unsigned int i, j;
46 WireguardPeer *peer, *peer_start;
47 WireguardIPmask *mask, *mask_start = NULL((void*)0);
48 _cleanup_(sd_netlink_message_unrefp)__attribute__((cleanup(sd_netlink_message_unrefp))) sd_netlink_message *message = NULL((void*)0);
49 Wireguard *w;
50 uint32_t serial;
51
52 assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/wireguard.c"
, 52, __PRETTY_FUNCTION__); } while (0)
;
53 w = WIREGUARD(netdev);
54 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 54, __PRETTY_FUNCTION__); } while (0)
;
55
56 peer_start = w->peers;
57
58 do {
59 message = sd_netlink_message_unref(message);
60
61 r = sd_genl_message_new(netdev->manager->genl, SD_GENL_WIREGUARD, WG_CMD_SET_DEVICE, &message);
62 if (r < 0)
63 return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 63, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Failed to allocate generic netlink message: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 63, __func__, "Failed to allocate generic netlink message: %m"
); })
;
64
65 r = sd_netlink_message_append_string(message, WGDEVICE_A_IFNAME, netdev->ifname);
66 if (r < 0)
67 return log_netdev_error_errno(netdev, r, "Could not append wireguard interface name: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 67, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not append wireguard interface name: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 67, __func__, "Could not append wireguard interface name: %m"
); })
;
68
69 if (peer_start == w->peers) {
70 r = sd_netlink_message_append_data(message, WGDEVICE_A_PRIVATE_KEY, &w->private_key, WG_KEY_LEN32);
71 if (r < 0)
72 return log_netdev_error_errno(netdev, r, "Could not append wireguard private key: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 72, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not append wireguard private key: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 72, __func__, "Could not append wireguard private key: %m"
); })
;
73
74 r = sd_netlink_message_append_u16(message, WGDEVICE_A_LISTEN_PORT, w->port);
75 if (r < 0)
76 return log_netdev_error_errno(netdev, r, "Could not append wireguard port: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 76, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not append wireguard port: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 76, __func__, "Could not append wireguard port: %m"
); })
;
77
78 r = sd_netlink_message_append_u32(message, WGDEVICE_A_FWMARK, w->fwmark);
79 if (r < 0)
80 return log_netdev_error_errno(netdev, r, "Could not append wireguard fwmark: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 80, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not append wireguard fwmark: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 80, __func__, "Could not append wireguard fwmark: %m"
); })
;
81
82 r = sd_netlink_message_append_u32(message, WGDEVICE_A_FLAGS, w->flags);
83 if (r < 0)
84 return log_netdev_error_errno(netdev, r, "Could not append wireguard flags: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 84, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not append wireguard flags: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 84, __func__, "Could not append wireguard flags: %m"
); })
;
85 }
86
87 r = sd_netlink_message_open_container(message, WGDEVICE_A_PEERS);
88 if (r < 0)
89 return log_netdev_error_errno(netdev, r, "Could not append wireguard peer attributes: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 89, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not append wireguard peer attributes: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 89, __func__, "Could not append wireguard peer attributes: %m"
); })
;
90
91 i = 0;
92
93 LIST_FOREACH(peers, peer, peer_start)for ((peer) = (peer_start); (peer); (peer) = (peer)->peers_next
)
{
94 r = sd_netlink_message_open_array(message, ++i);
95 if (r < 0)
96 break;
97
98 r = sd_netlink_message_append_data(message, WGPEER_A_PUBLIC_KEY, &peer->public_key, sizeof(peer->public_key));
99 if (r < 0)
100 break;
101
102 if (!mask_start) {
103 r = sd_netlink_message_append_data(message, WGPEER_A_PRESHARED_KEY, &peer->preshared_key, WG_KEY_LEN32);
104 if (r < 0)
105 break;
106
107 r = sd_netlink_message_append_u32(message, WGPEER_A_FLAGS, peer->flags);
108 if (r < 0)
109 break;
110
111 r = sd_netlink_message_append_u32(message, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval);
112 if (r < 0)
113 break;
114
115 if (peer->endpoint.sa.sa_family == AF_INET2) {
116 r = sd_netlink_message_append_data(message, WGPEER_A_ENDPOINT, &peer->endpoint.in, sizeof(peer->endpoint.in));
117 if (r < 0)
118 break;
119 } else if (peer->endpoint.sa.sa_family == AF_INET610) {
120 r = sd_netlink_message_append_data(message, WGPEER_A_ENDPOINT, &peer->endpoint.in6, sizeof(peer->endpoint.in6));
121 if (r < 0)
122 break;
123 }
124
125 mask_start = peer->ipmasks;
126 }
127
128 r = sd_netlink_message_open_container(message, WGPEER_A_ALLOWEDIPS);
129 if (r < 0) {
130 mask_start = NULL((void*)0);
131 break;
132 }
133 j = 0;
134 LIST_FOREACH(ipmasks, mask, mask_start)for ((mask) = (mask_start); (mask); (mask) = (mask)->ipmasks_next
)
{
135 r = sd_netlink_message_open_array(message, ++j);
136 if (r < 0)
137 break;
138
139 r = sd_netlink_message_append_u16(message, WGALLOWEDIP_A_FAMILY, mask->family);
140 if (r < 0)
141 break;
142
143 if (mask->family == AF_INET2) {
144 r = sd_netlink_message_append_in_addr(message, WGALLOWEDIP_A_IPADDR, &mask->ip.in);
145 if (r < 0)
146 break;
147 } else if (mask->family == AF_INET610) {
148 r = sd_netlink_message_append_in6_addr(message, WGALLOWEDIP_A_IPADDR, &mask->ip.in6);
149 if (r < 0)
150 break;
151 }
152
153 r = sd_netlink_message_append_u8(message, WGALLOWEDIP_A_CIDR_MASK, mask->cidr);
154 if (r < 0)
155 break;
156
157 r = sd_netlink_message_close_container(message);
158 if (r < 0)
159 return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 159, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not add wireguard allowed ip: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 159, __func__, "Could not add wireguard allowed ip: %m"
); })
;
160 }
161 mask_start = mask;
162 if (mask_start) {
163 r = sd_netlink_message_cancel_array(message);
164 if (r < 0)
165 return log_netdev_error_errno(netdev, r, "Could not cancel wireguard allowed ip message attribute: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 165, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not cancel wireguard allowed ip message attribute: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 165, __func__, "Could not cancel wireguard allowed ip message attribute: %m"
); })
;
166 }
167 r = sd_netlink_message_close_container(message);
168 if (r < 0)
169 return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 169, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not add wireguard allowed ip: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 169, __func__, "Could not add wireguard allowed ip: %m"
); })
;
170
171 r = sd_netlink_message_close_container(message);
172 if (r < 0)
173 return log_netdev_error_errno(netdev, r, "Could not add wireguard peer: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 173, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not add wireguard peer: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 173, __func__, "Could not add wireguard peer: %m"
); })
;
174 }
175
176 peer_start = peer;
177 if (peer_start && !mask_start) {
178 r = sd_netlink_message_cancel_array(message);
179 if (r < 0)
180 return log_netdev_error_errno(netdev, r, "Could not cancel wireguard peers: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 180, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not cancel wireguard peers: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 180, __func__, "Could not cancel wireguard peers: %m"
); })
;
181 }
182
183 r = sd_netlink_message_close_container(message);
184 if (r < 0)
185 return log_netdev_error_errno(netdev, r, "Could not close wireguard container: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 185, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not close wireguard container: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 185, __func__, "Could not close wireguard container: %m"
); })
;
186
187 r = sd_netlink_send(netdev->manager->genl, message, &serial);
188 if (r < 0)
189 return log_netdev_error_errno(netdev, r, "Could not set wireguard device: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 189, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not set wireguard device: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 189, __func__, "Could not set wireguard device: %m"
); })
;
190
191 } while (peer || mask_start);
192
193 return 0;
194}
195
196static WireguardEndpoint* wireguard_endpoint_free(WireguardEndpoint *e) {
197 if (!e)
198 return NULL((void*)0);
199 netdev_unref(e->netdev);
200 e->host = mfree(e->host);
201 e->port = mfree(e->port);
202 return mfree(e);
203}
204
205DEFINE_TRIVIAL_CLEANUP_FUNC(WireguardEndpoint*, wireguard_endpoint_free)static inline void wireguard_endpoint_freep(WireguardEndpoint
* *p) { if (*p) wireguard_endpoint_free(*p); }
;
206
207static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) {
208 NetDev *netdev = userdata;
209 Wireguard *w;
210
211 assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/wireguard.c"
, 211, __PRETTY_FUNCTION__); } while (0)
;
212 w = WIREGUARD(netdev);
213 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 213, __PRETTY_FUNCTION__); } while (0)
;
214
215 w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source);
216
217 w->unresolved_endpoints = TAKE_PTR(w->failed_endpoints)({ typeof(w->failed_endpoints) _ptr_ = (w->failed_endpoints
); (w->failed_endpoints) = ((void*)0); _ptr_; })
;
218
219 resolve_endpoints(netdev);
220
221 return 0;
222}
223
224/*
225 * Given the number of retries this function will return will an exponential
226 * increasing time in milliseconds to wait starting at 200ms and capped at 25 seconds.
227 */
228static int exponential_backoff_milliseconds(unsigned n_retries) {
229 return (2 << MAX(n_retries, 7U)__extension__ ({ const typeof((n_retries)) __unique_prefix_A14
= ((n_retries)); const typeof((7U)) __unique_prefix_B15 = ((
7U)); __unique_prefix_A14 > __unique_prefix_B15 ? __unique_prefix_A14
: __unique_prefix_B15; })
) * 100 * USEC_PER_MSEC((usec_t) 1000ULL);
230}
231
232static int wireguard_resolve_handler(sd_resolve_query *q,
233 int ret,
234 const struct addrinfo *ai,
235 void *userdata) {
236 NetDev *netdev;
237 Wireguard *w;
238 _cleanup_(wireguard_endpoint_freep)__attribute__((cleanup(wireguard_endpoint_freep))) WireguardEndpoint *e;
239 int r;
240
241 assert(userdata)do { if ((__builtin_expect(!!(!(userdata)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("userdata"), "../src/network/netdev/wireguard.c"
, 241, __PRETTY_FUNCTION__); } while (0)
;
242 e = userdata;
243 netdev = e->netdev;
244
245 assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/wireguard.c"
, 245, __PRETTY_FUNCTION__); } while (0)
;
246 w = WIREGUARD(netdev);
247 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 247, __PRETTY_FUNCTION__); } while (0)
;
248
249 w->resolve_query = sd_resolve_query_unref(w->resolve_query);
250
251 if (ret != 0) {
252 log_netdev_error(netdev, "Failed to resolve host '%s:%s': %s", e->host, e->port, gai_strerror(ret))({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0
, "../src/network/netdev/wireguard.c", 252, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Failed to resolve host '%s:%s': %s"
, e->host, e->port, gai_strerror(ret)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/network/netdev/wireguard.c"
, 252, __func__, "Failed to resolve host '%s:%s': %s", e->
host, e->port, gai_strerror(ret)); })
;
253 LIST_PREPEND(endpoints, w->failed_endpoints, e)do { typeof(*(w->failed_endpoints)) **_head = &(w->
failed_endpoints), *_item = (e); do { if ((__builtin_expect(!
!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"_item"), "../src/network/netdev/wireguard.c", 253, __PRETTY_FUNCTION__
); } while (0); if ((_item->endpoints_next = *_head)) _item
->endpoints_next->endpoints_prev = _item; _item->endpoints_prev
= ((void*)0); *_head = _item; } while (0)
;
254 e = NULL((void*)0);
255 } else if ((ai->ai_family == AF_INET2 && ai->ai_addrlen == sizeof(struct sockaddr_in)) ||
256 (ai->ai_family == AF_INET610 && ai->ai_addrlen == sizeof(struct sockaddr_in6)))
257 memcpy(&e->peer->endpoint, ai->ai_addr, ai->ai_addrlen);
258 else
259 log_netdev_error(netdev, "Neither IPv4 nor IPv6 address found for peer endpoint: %s:%s", e->host, e->port)({ const NetDev *_n = (netdev); _n ? log_object_internal(3, 0
, "../src/network/netdev/wireguard.c", 259, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Neither IPv4 nor IPv6 address found for peer endpoint: %s:%s"
, e->host, e->port) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((3))), 0, "../src/network/netdev/wireguard.c"
, 259, __func__, "Neither IPv4 nor IPv6 address found for peer endpoint: %s:%s"
, e->host, e->port); })
;
260
261 if (w->unresolved_endpoints) {
262 resolve_endpoints(netdev);
263 return 0;
264 }
265
266 set_wireguard_interface(netdev);
267 if (w->failed_endpoints) {
268 w->n_retries++;
269 r = sd_event_add_time(netdev->manager->event,
270 &w->resolve_retry_event_source,
271 CLOCK_MONOTONIC1,
272 now(CLOCK_MONOTONIC1) + exponential_backoff_milliseconds(w->n_retries),
273 0,
274 on_resolve_retry,
275 netdev);
276 if (r < 0)
277 log_netdev_warning_errno(netdev, r, "Could not arm resolve retry handler: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(4, r
, "../src/network/netdev/wireguard.c", 277, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Could not arm resolve retry handler: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4
))), r, "../src/network/netdev/wireguard.c", 277, __func__, "Could not arm resolve retry handler: %m"
); })
;
278 }
279
280 return 0;
281}
282
283static void resolve_endpoints(NetDev *netdev) {
284 int r = 0;
285 Wireguard *w;
286 WireguardEndpoint *endpoint;
287 static const struct addrinfo hints = {
288 .ai_family = AF_UNSPEC0,
289 .ai_socktype = SOCK_DGRAMSOCK_DGRAM,
290 .ai_protocol = IPPROTO_UDPIPPROTO_UDP
291 };
292
293 assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/wireguard.c"
, 293, __PRETTY_FUNCTION__); } while (0)
;
294 w = WIREGUARD(netdev);
295 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 295, __PRETTY_FUNCTION__); } while (0)
;
296
297 LIST_FOREACH(endpoints, endpoint, w->unresolved_endpoints)for ((endpoint) = (w->unresolved_endpoints); (endpoint); (
endpoint) = (endpoint)->endpoints_next)
{
298 r = sd_resolve_getaddrinfo(netdev->manager->resolve,
299 &w->resolve_query,
300 endpoint->host,
301 endpoint->port,
302 &hints,
303 wireguard_resolve_handler,
304 endpoint);
305
306 if (r == -ENOBUFS105)
307 break;
308
309 LIST_REMOVE(endpoints, w->unresolved_endpoints, endpoint)do { typeof(*(w->unresolved_endpoints)) **_head = &(w->
unresolved_endpoints), *_item = (endpoint); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/network/netdev/wireguard.c", 309, __PRETTY_FUNCTION__
); } while (0); if (_item->endpoints_next) _item->endpoints_next
->endpoints_prev = _item->endpoints_prev; if (_item->
endpoints_prev) _item->endpoints_prev->endpoints_next =
_item->endpoints_next; else { do { if ((__builtin_expect(
!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/network/netdev/wireguard.c", 309
, __PRETTY_FUNCTION__); } while (0); *_head = _item->endpoints_next
; } _item->endpoints_next = _item->endpoints_prev = ((void
*)0); } while (0)
;
310
311 if (r < 0)
312 log_netdev_error_errno(netdev, r, "Failed create resolver: %m")({ const NetDev *_n = (netdev); _n ? log_object_internal(3, r
, "../src/network/netdev/wireguard.c", 312, __func__, "INTERFACE="
, _n->ifname, ((void*)0), ((void*)0), "Failed create resolver: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/network/netdev/wireguard.c", 312, __func__, "Failed create resolver: %m"
); })
;
313 }
314}
315
316static int netdev_wireguard_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
317 Wireguard *w;
318
319 assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/wireguard.c"
, 319, __PRETTY_FUNCTION__); } while (0)
;
320 w = WIREGUARD(netdev);
321 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 321, __PRETTY_FUNCTION__); } while (0)
;
322
323 set_wireguard_interface(netdev);
324 resolve_endpoints(netdev);
325 return 0;
326}
327
328int config_parse_wireguard_listen_port(const char *unit,
329 const char *filename,
330 unsigned line,
331 const char *section,
332 unsigned section_line,
333 const char *lvalue,
334 int ltype,
335 const char *rvalue,
336 void *data,
337 void *userdata) {
338 uint16_t *s = data;
339 uint16_t port = 0;
340 int r;
341
342 assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rvalue"), "../src/network/netdev/wireguard.c"
, 342, __PRETTY_FUNCTION__); } while (0)
;
343 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/wireguard.c"
, 343, __PRETTY_FUNCTION__); } while (0)
;
344
345 if (!streq(rvalue, "auto")(strcmp((rvalue),("auto")) == 0)) {
346 r = parse_ip_port(rvalue, &port);
347 if (r < 0)
348 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid port specification, ignoring assignment: %s", rvalue)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 348
, __func__, "Invalid port specification, ignoring assignment: %s"
, rvalue) : -abs(_e); })
;
349 }
350
351 *s = port;
352
353 return 0;
354}
355
356static int parse_wireguard_key(const char *unit,
357 const char *filename,
358 unsigned line,
359 const char *section,
360 unsigned section_line,
361 const char *lvalue,
362 int ltype,
363 const char *rvalue,
364 void *data,
365 void *userdata) {
366 _cleanup_free___attribute__((cleanup(freep))) void *key = NULL((void*)0);
367 size_t len;
368 int r;
369
370 assert(filename)do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("filename"), "../src/network/netdev/wireguard.c"
, 370, __PRETTY_FUNCTION__); } while (0)
;
371 assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rvalue"), "../src/network/netdev/wireguard.c"
, 371, __PRETTY_FUNCTION__); } while (0)
;
372 assert(userdata)do { if ((__builtin_expect(!!(!(userdata)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("userdata"), "../src/network/netdev/wireguard.c"
, 372, __PRETTY_FUNCTION__); } while (0)
;
373
374 r = unbase64mem(rvalue, strlen(rvalue), &key, &len);
375 if (r < 0) {
376 log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse wireguard key \"%s\", ignoring assignment: %m", rvalue)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 376
, __func__, "Could not parse wireguard key \"%s\", ignoring assignment: %m"
, rvalue) : -abs(_e); })
;
377 return 0;
378 }
379 if (len != WG_KEY_LEN32) {
380 log_syntax(unit, LOG_ERR, filename, line, EINVAL,({ int _level = (3), _e = (22); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 381
, __func__, "Wireguard key is too short, ignoring assignment: %s"
, rvalue) : -abs(_e); })
381 "Wireguard key is too short, ignoring assignment: %s", rvalue)({ int _level = (3), _e = (22); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 381
, __func__, "Wireguard key is too short, ignoring assignment: %s"
, rvalue) : -abs(_e); })
;
382 return 0;
383 }
384
385 memcpy(userdata, key, WG_KEY_LEN32);
386 return true1;
387}
388
389int config_parse_wireguard_private_key(const char *unit,
390 const char *filename,
391 unsigned line,
392 const char *section,
393 unsigned section_line,
394 const char *lvalue,
395 int ltype,
396 const char *rvalue,
397 void *data,
398 void *userdata) {
399 Wireguard *w;
400
401 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/wireguard.c"
, 401, __PRETTY_FUNCTION__); } while (0)
;
402
403 w = WIREGUARD(data);
404
405 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 405, __PRETTY_FUNCTION__); } while (0)
;
406
407 return parse_wireguard_key(unit,
408 filename,
409 line,
410 section,
411 section_line,
412 lvalue,
413 ltype,
414 rvalue,
415 data,
416 &w->private_key);
417
418}
419
420int config_parse_wireguard_preshared_key(const char *unit,
421 const char *filename,
422 unsigned line,
423 const char *section,
424 unsigned section_line,
425 const char *lvalue,
426 int ltype,
427 const char *rvalue,
428 void *data,
429 void *userdata) {
430 Wireguard *w;
431 WireguardPeer *peer;
432
433 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/wireguard.c"
, 433, __PRETTY_FUNCTION__); } while (0)
;
434
435 w = WIREGUARD(data);
436
437 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 437, __PRETTY_FUNCTION__); } while (0)
;
438
439 peer = wireguard_peer_new(w, section_line);
440 if (!peer)
441 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 441, __func__)
;
442
443 return parse_wireguard_key(unit,
444 filename,
445 line,
446 section,
447 section_line,
448 lvalue,
449 ltype,
450 rvalue,
451 data,
452 peer->preshared_key);
453}
454
455int config_parse_wireguard_public_key(const char *unit,
456 const char *filename,
457 unsigned line,
458 const char *section,
459 unsigned section_line,
460 const char *lvalue,
461 int ltype,
462 const char *rvalue,
463 void *data,
464 void *userdata) {
465 Wireguard *w;
466 WireguardPeer *peer;
467
468 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/wireguard.c"
, 468, __PRETTY_FUNCTION__); } while (0)
;
469
470 w = WIREGUARD(data);
471
472 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 472, __PRETTY_FUNCTION__); } while (0)
;
473
474 peer = wireguard_peer_new(w, section_line);
475 if (!peer)
476 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 476, __func__)
;
477
478 return parse_wireguard_key(unit,
479 filename,
480 line,
481 section,
482 section_line,
483 lvalue,
484 ltype,
485 rvalue,
486 data,
487 peer->public_key);
488}
489
490int config_parse_wireguard_allowed_ips(const char *unit,
491 const char *filename,
492 unsigned line,
493 const char *section,
494 unsigned section_line,
495 const char *lvalue,
496 int ltype,
497 const char *rvalue,
498 void *data,
499 void *userdata) {
500 union in_addr_union addr;
501 unsigned char prefixlen;
502 int r, family;
503 Wireguard *w;
504 WireguardPeer *peer;
505 WireguardIPmask *ipmask;
506
507 assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rvalue"), "../src/network/netdev/wireguard.c"
, 507, __PRETTY_FUNCTION__); } while (0)
;
508 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/wireguard.c"
, 508, __PRETTY_FUNCTION__); } while (0)
;
509
510 w = WIREGUARD(data);
511
512 peer = wireguard_peer_new(w, section_line);
513 if (!peer)
514 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 514, __func__)
;
515
516 for (;;) {
517 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0);
518
519 r = extract_first_word(&rvalue, &word, "," WHITESPACE" \t\n\r", 0);
520 if (r == 0)
521 break;
522 if (r == -ENOMEM12)
523 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 523, __func__)
;
524 if (r < 0) {
525 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split allowed ips \"%s\" option: %m", rvalue)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 525
, __func__, "Failed to split allowed ips \"%s\" option: %m", rvalue
) : -abs(_e); })
;
526 break;
527 }
528
529 r = in_addr_prefix_from_string_auto(word, &family, &addr, &prefixlen);
530 if (r < 0) {
531 log_syntax(unit, LOG_ERR, filename, line, r, "Network address is invalid, ignoring assignment: %s", word)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 531
, __func__, "Network address is invalid, ignoring assignment: %s"
, word) : -abs(_e); })
;
532 return 0;
533 }
534
535 ipmask = new0(WireguardIPmask, 1)((WireguardIPmask*) calloc((1), sizeof(WireguardIPmask)));
536 if (!ipmask)
537 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 537, __func__)
;
538 ipmask->family = family;
539 ipmask->ip.in6 = addr.in6;
540 ipmask->cidr = prefixlen;
541
542 LIST_PREPEND(ipmasks, peer->ipmasks, ipmask)do { typeof(*(peer->ipmasks)) **_head = &(peer->ipmasks
), *_item = (ipmask); do { if ((__builtin_expect(!!(!(_item))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/network/netdev/wireguard.c"
, 542, __PRETTY_FUNCTION__); } while (0); if ((_item->ipmasks_next
= *_head)) _item->ipmasks_next->ipmasks_prev = _item; _item
->ipmasks_prev = ((void*)0); *_head = _item; } while (0)
;
543 }
544
545 return 0;
546}
547
548int config_parse_wireguard_endpoint(const char *unit,
549 const char *filename,
550 unsigned line,
551 const char *section,
552 unsigned section_line,
553 const char *lvalue,
554 int ltype,
555 const char *rvalue,
556 void *data,
557 void *userdata) {
558 Wireguard *w;
559 WireguardPeer *peer;
560 size_t len;
561 const char *begin, *end = NULL((void*)0);
562 _cleanup_free___attribute__((cleanup(freep))) char *host = NULL((void*)0), *port = NULL((void*)0);
563 _cleanup_(wireguard_endpoint_freep)__attribute__((cleanup(wireguard_endpoint_freep))) WireguardEndpoint *endpoint = NULL((void*)0);
564
565 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/wireguard.c"
, 565, __PRETTY_FUNCTION__); } while (0)
;
566 assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rvalue"), "../src/network/netdev/wireguard.c"
, 566, __PRETTY_FUNCTION__); } while (0)
;
567
568 w = WIREGUARD(data);
569
570 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 570, __PRETTY_FUNCTION__); } while (0)
;
571
572 peer = wireguard_peer_new(w, section_line);
573 if (!peer)
574 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 574, __func__)
;
575
576 endpoint = new0(WireguardEndpoint, 1)((WireguardEndpoint*) calloc((1), sizeof(WireguardEndpoint)));
577 if (!endpoint)
578 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 578, __func__)
;
579
580 if (rvalue[0] == '[') {
581 begin = &rvalue[1];
582 end = strchr(rvalue, ']');
583 if (!end) {
584 log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to find matching brace of endpoint, ignoring assignment: %s", rvalue)({ int _level = (3), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 584
, __func__, "Unable to find matching brace of endpoint, ignoring assignment: %s"
, rvalue) : -abs(_e); })
;
585 return 0;
586 }
587 len = end - begin;
588 ++end;
589 if (*end != ':' || !*(end + 1)) {
590 log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to find port of endpoint: %s", rvalue)({ int _level = (3), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 590
, __func__, "Unable to find port of endpoint: %s", rvalue) : -
abs(_e); })
;
591 return 0;
592 }
593 ++end;
594 } else {
595 begin = rvalue;
596 end = strrchr(rvalue, ':');
597 if (!end || !*(end + 1)) {
598 log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to find port of endpoint: %s", rvalue)({ int _level = (3), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 598
, __func__, "Unable to find port of endpoint: %s", rvalue) : -
abs(_e); })
;
599 return 0;
600 }
601 len = end - begin;
602 ++end;
603 }
604
605 host = strndup(begin, len);
606 if (!host)
607 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 607, __func__)
;
608
609 port = strdup(end);
610 if (!port)
611 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 611, __func__)
;
612
613 endpoint->peer = TAKE_PTR(peer)({ typeof(peer) _ptr_ = (peer); (peer) = ((void*)0); _ptr_; }
)
;
614 endpoint->host = TAKE_PTR(host)({ typeof(host) _ptr_ = (host); (host) = ((void*)0); _ptr_; }
)
;
615 endpoint->port = TAKE_PTR(port)({ typeof(port) _ptr_ = (port); (port) = ((void*)0); _ptr_; }
)
;
616 endpoint->netdev = netdev_ref(data);
617 LIST_PREPEND(endpoints, w->unresolved_endpoints, endpoint)do { typeof(*(w->unresolved_endpoints)) **_head = &(w->
unresolved_endpoints), *_item = (endpoint); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/network/netdev/wireguard.c", 617, __PRETTY_FUNCTION__
); } while (0); if ((_item->endpoints_next = *_head)) _item
->endpoints_next->endpoints_prev = _item; _item->endpoints_prev
= ((void*)0); *_head = _item; } while (0)
;
618 endpoint = NULL((void*)0);
619
620 return 0;
621}
622
623int config_parse_wireguard_keepalive(const char *unit,
624 const char *filename,
625 unsigned line,
626 const char *section,
627 unsigned section_line,
628 const char *lvalue,
629 int ltype,
630 const char *rvalue,
631 void *data,
632 void *userdata) {
633 int r;
634 uint16_t keepalive = 0;
635 Wireguard *w;
636 WireguardPeer *peer;
637
638 assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("rvalue"), "../src/network/netdev/wireguard.c"
, 638, __PRETTY_FUNCTION__); } while (0)
;
639 assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("data"), "../src/network/netdev/wireguard.c"
, 639, __PRETTY_FUNCTION__); } while (0)
;
640
641 w = WIREGUARD(data);
642
643 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 643, __PRETTY_FUNCTION__); } while (0)
;
644
645 peer = wireguard_peer_new(w, section_line);
646 if (!peer)
647 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/network/netdev/wireguard.c"
, 647, __func__)
;
648
649 if (streq(rvalue, "off")(strcmp((rvalue),("off")) == 0))
650 keepalive = 0;
651 else {
652 r = safe_atou16(rvalue, &keepalive);
653 if (r < 0)
654 log_syntax(unit, LOG_ERR, filename, line, r, "The persistent keepalive interval must be 0-65535. Ignore assignment: %s", rvalue)({ int _level = (3), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/network/netdev/wireguard.c", 654
, __func__, "The persistent keepalive interval must be 0-65535. Ignore assignment: %s"
, rvalue) : -abs(_e); })
;
655 }
656
657 peer->persistent_keepalive_interval = keepalive;
658 return 0;
659}
660
661static void wireguard_init(NetDev *netdev) {
662 Wireguard *w;
663
664 assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/wireguard.c"
, 664, __PRETTY_FUNCTION__); } while (0)
;
665
666 w = WIREGUARD(netdev);
667
668 assert(w)do { if ((__builtin_expect(!!(!(w)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("w"), "../src/network/netdev/wireguard.c"
, 668, __PRETTY_FUNCTION__); } while (0)
;
669
670 w->flags = WGDEVICE_F_REPLACE_PEERS;
671}
672
673static void wireguard_done(NetDev *netdev) {
674 Wireguard *w;
675 WireguardPeer *peer;
676 WireguardIPmask *mask;
677
678 assert(netdev)do { if ((__builtin_expect(!!(!(netdev)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("netdev"), "../src/network/netdev/wireguard.c"
, 678, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'netdev' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
679 w = WIREGUARD(netdev);
680 assert(!w->unresolved_endpoints)do { if ((__builtin_expect(!!(!(!w->unresolved_endpoints))
,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!w->unresolved_endpoints"
), "../src/network/netdev/wireguard.c", 680, __PRETTY_FUNCTION__
); } while (0)
;
4
Assuming field 'unresolved_endpoints' is null
5
Taking false branch
6
Loop condition is false. Exiting loop
681 w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source);
682
683 while ((peer = w->peers)) {
7
Loop condition is true. Entering loop body
17
Loop condition is true. Entering loop body
684 LIST_REMOVE(peers, w->peers, peer)do { typeof(*(w->peers)) **_head = &(w->peers), *_item
= (peer); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/network/netdev/wireguard.c"
, 684, __PRETTY_FUNCTION__); } while (0); if (_item->peers_next
) _item->peers_next->peers_prev = _item->peers_prev;
if (_item->peers_prev) _item->peers_prev->peers_next
= _item->peers_next; else { do { if ((__builtin_expect(!!
(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/network/netdev/wireguard.c", 684
, __PRETTY_FUNCTION__); } while (0); *_head = _item->peers_next
; } _item->peers_next = _item->peers_prev = ((void*)0);
} while (0)
;
8
Taking false branch
9
Loop condition is false. Exiting loop
10
Assuming field 'peers_next' is null
11
Taking false branch
12
Assuming field 'peers_prev' is non-null
13
Taking true branch
14
Loop condition is false. Exiting loop
18
Taking false branch
19
Loop condition is false. Exiting loop
20
Use of memory after it is freed
685 while ((mask = peer->ipmasks)) {
15
Loop condition is false. Execution continues on line 689
686 LIST_REMOVE(ipmasks, peer->ipmasks, mask)do { typeof(*(peer->ipmasks)) **_head = &(peer->ipmasks
), *_item = (mask); do { if ((__builtin_expect(!!(!(_item)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/network/netdev/wireguard.c"
, 686, __PRETTY_FUNCTION__); } while (0); if (_item->ipmasks_next
) _item->ipmasks_next->ipmasks_prev = _item->ipmasks_prev
; if (_item->ipmasks_prev) _item->ipmasks_prev->ipmasks_next
= _item->ipmasks_next; else { do { if ((__builtin_expect(
!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/network/netdev/wireguard.c", 686
, __PRETTY_FUNCTION__); } while (0); *_head = _item->ipmasks_next
; } _item->ipmasks_next = _item->ipmasks_prev = ((void*
)0); } while (0)
;
687 free(mask);
688 }
689 free(peer);
16
Memory is released
690 }
691}
692
693const NetDevVTable wireguard_vtable = {
694 .object_size = sizeof(Wireguard),
695 .sections = "Match\0NetDev\0WireGuard\0WireGuardPeer\0",
696 .post_create = netdev_wireguard_post_create,
697 .init = wireguard_init,
698 .done = wireguard_done,
699 .create_type = NETDEV_CREATE_INDEPENDENT,
700};