File: | build-scan/../src/network/netdev/wireguard.c |
Warning: | line 598, column 25 Potential leak of memory pointed to by 'endpoint' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
22 | static void resolve_endpoints(NetDev *netdev); | |||
23 | ||||
24 | static 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 | ||||
43 | static 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 | ||||
196 | static 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 | ||||
205 | DEFINE_TRIVIAL_CLEANUP_FUNC(WireguardEndpoint*, wireguard_endpoint_free)static inline void wireguard_endpoint_freep(WireguardEndpoint * *p) { if (*p) wireguard_endpoint_free(*p); }; | |||
206 | ||||
207 | static 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 | */ | |||
228 | static int exponential_backoff_milliseconds(unsigned n_retries) { | |||
229 | return (2 << MAX(n_retries, 7U)__extension__ ({ const typeof((n_retries)) __unique_prefix_A10 = ((n_retries)); const typeof((7U)) __unique_prefix_B11 = (( 7U)); __unique_prefix_A10 > __unique_prefix_B11 ? __unique_prefix_A10 : __unique_prefix_B11; })) * 100 * USEC_PER_MSEC((usec_t) 1000ULL); | |||
230 | } | |||
231 | ||||
232 | static 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 | ||||
283 | static 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 | ||||
316 | static 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 | ||||
328 | int 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 | ||||
356 | static 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 | ||||
389 | int 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 | ||||
420 | int 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 | ||||
455 | int 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 | ||||
490 | int 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 | ||||
548 | int 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 | ||||
623 | int 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 | ||||
661 | static 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 | ||||
673 | static 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); | |||
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); | |||
681 | w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source); | |||
682 | ||||
683 | while ((peer = w->peers)) { | |||
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); | |||
685 | while ((mask = peer->ipmasks)) { | |||
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); | |||
690 | } | |||
691 | } | |||
692 | ||||
693 | const 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 | }; |