| File: | build-scan/../src/network/netdev/wireguard.c |
| Warning: | line 611, column 24 Potential leak of memory pointed to by 'host' |
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_A12 = ((n_retries)); const typeof((7U)) __unique_prefix_B13 = (( 7U)); __unique_prefix_A12 > __unique_prefix_B13 ? __unique_prefix_A12 : __unique_prefix_B13; })) * 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 | }; |