services: switch to vlist
[project/unetd.git] / wg.c
1 // SPDX-License-Identifier: GPL-2.0+
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 (dummy_mode)
10 return &wg_dummy_ops;
11
12 if (wg_user_ops.check(net))
13 return &wg_user_ops;
14
15 #ifdef linux
16 return &wg_linux_ops;
17 #else
18 return NULL;
19 #endif
20 }
21
22 int wg_init_network(struct network *net)
23 {
24 net->wg.ops = wg_get_ops(net);
25
26 if (!net->wg.ops)
27 return -1;
28
29 return net->wg.ops->init(net);
30 }
31
32 void wg_cleanup_network(struct network *net)
33 {
34 if (net->wg.ops)
35 net->wg.ops->cleanup(net);
36 }
37
38 struct network_peer *wg_peer_update_start(struct network *net, const uint8_t *key)
39 {
40 struct network_peer *peer;
41
42 peer = vlist_find(&net->peers, key, peer, node);
43 if (!peer)
44 return NULL;
45
46 peer->state.handshake = false;
47 peer->state.idle++;
48 if (peer->state.idle >= 2 * net->net_config.keepalive)
49 peer->state.connected = false;
50 if (peer->state.idle > net->net_config.keepalive)
51 network_pex_event(net, peer, PEX_EV_PING);
52
53 return peer;
54 }
55
56 void wg_peer_update_done(struct network *net, struct network_peer *peer)
57 {
58 if (peer->state.handshake)
59 network_pex_event(net, peer, PEX_EV_HANDSHAKE);
60 }
61
62 void wg_peer_set_last_handshake(struct network *net, struct network_peer *peer,
63 uint64_t now, uint64_t sec)
64 {
65 if (sec == peer->state.last_handshake)
66 return;
67
68 peer->state.handshake = true;
69 peer->state.last_handshake = sec;
70 sec = now - sec;
71 if (sec <= net->net_config.keepalive) {
72 peer->state.connected = true;
73 if (peer->state.idle > sec)
74 peer->state.idle = sec;
75 }
76 }
77
78 void wg_peer_set_rx_bytes(struct network *net, struct network_peer *peer,
79 uint64_t bytes)
80 {
81 int64_t diff = bytes - peer->state.rx_bytes;
82
83 peer->state.rx_bytes = bytes;
84 if (diff > 0) {
85 peer->state.idle = 0;
86 peer->state.connected = true;
87 }
88 }
89
90 void wg_peer_set_endpoint(struct network *net, struct network_peer *peer,
91 void *data, size_t len)
92 {
93 if (len > sizeof(peer->state.endpoint))
94 return;
95
96 if (!memcmp(&peer->state.endpoint, data, len))
97 return;
98
99 memset(&peer->state.endpoint, 0, sizeof(peer->state.endpoint));
100 memcpy(&peer->state.endpoint, data, len);
101 network_pex_event(net, peer, PEX_EV_ENDPOINT_CHANGE);
102 }