unet-cli: strip initial newline in usage message
[project/unetd.git] / wg.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
4 */
5 #include "unetd.h"
6
7 static const struct wg_ops *wg_get_ops(struct network *net)
8 {
9 if (wg_user_ops.check(net))
10 return &wg_user_ops;
11
12 #ifdef linux
13 return &wg_linux_ops;
14 #else
15 return NULL;
16 #endif
17 }
18
19 int wg_init_network(struct network *net)
20 {
21 net->wg.ops = wg_get_ops(net);
22
23 if (!net->wg.ops)
24 return -1;
25
26 return net->wg.ops->init(net);
27 }
28
29 void wg_cleanup_network(struct network *net)
30 {
31 if (net->wg.ops)
32 net->wg.ops->cleanup(net);
33 }
34
35 static void
36 wg_peer_set_connected(struct network *net, struct network_peer *peer, bool val)
37 {
38 if (peer->state.connected == val)
39 return;
40
41 peer->state.connected = val;
42 network_services_peer_update(net, peer);
43 }
44
45 struct network_peer *wg_peer_update_start(struct network *net, const uint8_t *key)
46 {
47 struct network_peer *peer;
48
49 peer = vlist_find(&net->peers, key, peer, node);
50 if (!peer || peer->indirect)
51 return NULL;
52
53 peer->state.handshake = false;
54 peer->state.idle++;
55 if (peer->state.idle >= 2 * net->net_config.keepalive)
56 wg_peer_set_connected(net, peer, false);
57 if (peer->state.idle > net->net_config.keepalive)
58 network_pex_event(net, peer, PEX_EV_PING);
59
60 return peer;
61 }
62
63 void wg_peer_update_done(struct network *net, struct network_peer *peer)
64 {
65 if (peer->state.handshake)
66 network_pex_event(net, peer, PEX_EV_HANDSHAKE);
67 }
68
69 void wg_peer_set_last_handshake(struct network *net, struct network_peer *peer,
70 uint64_t now, uint64_t sec)
71 {
72 if (sec == peer->state.last_handshake)
73 return;
74
75 peer->state.handshake = true;
76 peer->state.last_handshake = sec;
77 sec = now - sec;
78 if (sec <= net->net_config.keepalive) {
79 if (peer->state.idle > sec)
80 peer->state.idle = sec;
81 wg_peer_set_connected(net, peer, true);
82 peer->state.pinged = false;
83 }
84 }
85
86 void wg_peer_set_rx_bytes(struct network *net, struct network_peer *peer,
87 uint64_t bytes)
88 {
89 int64_t diff = bytes - peer->state.rx_bytes;
90
91 peer->state.rx_bytes = bytes;
92 if (diff > 0) {
93 peer->state.idle = 0;
94 wg_peer_set_connected(net, peer, true);
95 }
96 }
97
98 void wg_peer_set_endpoint(struct network *net, struct network_peer *peer,
99 void *data, size_t len)
100 {
101 if (len > sizeof(peer->state.endpoint))
102 return;
103
104 if (!memcmp(&peer->state.endpoint, data, len))
105 return;
106
107 memset(&peer->state.endpoint, 0, sizeof(peer->state.endpoint));
108 memcpy(&peer->state.endpoint, data, len);
109 network_pex_event(net, peer, PEX_EV_ENDPOINT_CHANGE);
110 }