Skip to content

Commit 26dc527

Browse files
committed
network: add support for configuring extra peers via a separate json file
Peers added to this file are only used locally and not advertised on the network. Peers should use IP addresses that are part of locally announced or otherwise configured subnets Signed-off-by: Felix Fietkau <[email protected]>
1 parent 8ad1197 commit 26dc527

File tree

7 files changed

+157
-53
lines changed

7 files changed

+157
-53
lines changed

examples/net0.peers

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"test": {
3+
"key": "uEXsoKYc31VH/kzv55eHVmKlzvmoGOPwA7xeTjGgLXc=",
4+
"endpoint": "192.168.1.4:51830",
5+
"ipaddr": [ "192.168.99.1" ]
6+
}
7+
}
8+

examples/test-net0.sh

+1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ ip link add dev $ifname type wireguard > /dev/null 2>&1
1515
"tunnels": {
1616
"vx0": "l2-tunnel"
1717
},
18+
"peer_data": [ "'"$PWD/net0.peers"'" ],
1819
"update-cmd": "'"$PWD/../scripts/update-cmd.pl"'"
1920
}'

host.c

+129-50
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
* Copyright (C) 2022 Felix Fietkau <[email protected]>
44
*/
55
#include <libubox/avl-cmp.h>
6+
#include <libubox/blobmsg_json.h>
67
#include "unetd.h"
78

89
static LIST_HEAD(old_hosts);
10+
static struct blob_buf b;
911

1012
static int avl_key_cmp(const void *k1, const void *k2, void *ptr)
1113
{
@@ -83,41 +85,43 @@ network_host_add_group(struct network *net, struct network_host *host,
8385
group->members[group->n_members - 1] = host;
8486
}
8587

88+
enum {
89+
NETWORK_HOST_KEY,
90+
NETWORK_HOST_GROUPS,
91+
NETWORK_HOST_IPADDR,
92+
NETWORK_HOST_SUBNET,
93+
NETWORK_HOST_PORT,
94+
NETWORK_HOST_PEX_PORT,
95+
NETWORK_HOST_ENDPOINT,
96+
NETWORK_HOST_GATEWAY,
97+
__NETWORK_HOST_MAX
98+
};
99+
100+
static const struct blobmsg_policy host_policy[__NETWORK_HOST_MAX] = {
101+
[NETWORK_HOST_KEY] = { "key", BLOBMSG_TYPE_STRING },
102+
[NETWORK_HOST_GROUPS] = { "groups", BLOBMSG_TYPE_ARRAY },
103+
[NETWORK_HOST_IPADDR] = { "ipaddr", BLOBMSG_TYPE_ARRAY },
104+
[NETWORK_HOST_SUBNET] = { "subnet", BLOBMSG_TYPE_ARRAY },
105+
[NETWORK_HOST_PORT] = { "port", BLOBMSG_TYPE_INT32 },
106+
[NETWORK_HOST_PEX_PORT] = { "peer-exchange-port", BLOBMSG_TYPE_INT32 },
107+
[NETWORK_HOST_ENDPOINT] = { "endpoint", BLOBMSG_TYPE_STRING },
108+
[NETWORK_HOST_GATEWAY] = { "gateway", BLOBMSG_TYPE_STRING },
109+
};
110+
86111
static void
87-
network_host_create(struct network *net, struct blob_attr *attr)
112+
network_host_create(struct network *net, struct blob_attr *attr, bool dynamic)
88113
{
89-
enum {
90-
NETWORK_HOST_KEY,
91-
NETWORK_HOST_GROUPS,
92-
NETWORK_HOST_IPADDR,
93-
NETWORK_HOST_SUBNET,
94-
NETWORK_HOST_PORT,
95-
NETWORK_HOST_PEX_PORT,
96-
NETWORK_HOST_ENDPOINT,
97-
NETWORK_HOST_GATEWAY,
98-
__NETWORK_HOST_MAX
99-
};
100-
static const struct blobmsg_policy policy[__NETWORK_HOST_MAX] = {
101-
[NETWORK_HOST_KEY] = { "key", BLOBMSG_TYPE_STRING },
102-
[NETWORK_HOST_GROUPS] = { "groups", BLOBMSG_TYPE_ARRAY },
103-
[NETWORK_HOST_IPADDR] = { "ipaddr", BLOBMSG_TYPE_ARRAY },
104-
[NETWORK_HOST_SUBNET] = { "subnet", BLOBMSG_TYPE_ARRAY },
105-
[NETWORK_HOST_PORT] = { "port", BLOBMSG_TYPE_INT32 },
106-
[NETWORK_HOST_PEX_PORT] = { "peer-exchange-port", BLOBMSG_TYPE_INT32 },
107-
[NETWORK_HOST_ENDPOINT] = { "endpoint", BLOBMSG_TYPE_STRING },
108-
[NETWORK_HOST_GATEWAY] = { "gateway", BLOBMSG_TYPE_STRING },
109-
};
110114
struct blob_attr *tb[__NETWORK_HOST_MAX];
111115
struct blob_attr *cur, *ipaddr, *subnet;
112116
uint8_t key[CURVE25519_KEY_SIZE];
113-
struct network_host *host;
117+
struct network_host *host = NULL;
114118
struct network_peer *peer;
115119
int ipaddr_len, subnet_len;
116-
const char *name, *endpoint, *gateway;
117-
char *name_buf, *endpoint_buf, *gateway_buf;
120+
const char *endpoint, *gateway;
121+
char *endpoint_buf, *gateway_buf;
118122
int rem;
119123

120-
blobmsg_parse(policy, __NETWORK_HOST_MAX, tb, blobmsg_data(attr), blobmsg_len(attr));
124+
blobmsg_parse(host_policy, __NETWORK_HOST_MAX, tb, blobmsg_data(attr), blobmsg_len(attr));
121125

122126
if (!tb[NETWORK_HOST_KEY])
123127
return;
@@ -137,7 +141,7 @@ network_host_create(struct network *net, struct blob_attr *attr)
137141
else
138142
endpoint = NULL;
139143

140-
if ((cur = tb[NETWORK_HOST_GATEWAY]) != NULL)
144+
if (!dynamic && (cur = tb[NETWORK_HOST_GATEWAY]) != NULL)
141145
gateway = blobmsg_get_string(cur);
142146
else
143147
gateway = NULL;
@@ -146,18 +150,41 @@ network_host_create(struct network *net, struct blob_attr *attr)
146150
sizeof(key)) != sizeof(key))
147151
return;
148152

149-
name = blobmsg_name(attr);
150-
host = avl_find_element(&net->hosts, name, host, node);
151-
if (host)
152-
return;
153+
if (dynamic) {
154+
struct network_dynamic_peer *dyn_peer;
155+
156+
/* don't override/alter hosts configured via network data */
157+
peer = vlist_find(&net->peers, key, peer, node);
158+
if (peer && !peer->dynamic &&
159+
peer->node.version == net->peers.version)
160+
return;
161+
162+
dyn_peer = calloc_a(sizeof(*dyn_peer),
163+
&ipaddr, ipaddr_len,
164+
&subnet, subnet_len,
165+
&endpoint_buf, endpoint ? strlen(endpoint) + 1 : 0);
166+
list_add_tail(&dyn_peer->list, &net->dynamic_peers);
167+
peer = &dyn_peer->peer;
168+
} else {
169+
const char *name;
170+
char *name_buf;
171+
172+
name = blobmsg_name(attr);
173+
host = avl_find_element(&net->hosts, name, host, node);
174+
if (host)
175+
return;
153176

154-
host = calloc_a(sizeof(*host),
155-
&name_buf, strlen(name) + 1,
156-
&ipaddr, ipaddr_len,
157-
&subnet, subnet_len,
158-
&endpoint_buf, endpoint ? strlen(endpoint) + 1 : 0,
159-
&gateway_buf, gateway ? strlen(endpoint) + 1 : 0);
160-
peer = &host->peer;
177+
host = calloc_a(sizeof(*host),
178+
&name_buf, strlen(name) + 1,
179+
&ipaddr, ipaddr_len,
180+
&subnet, subnet_len,
181+
&endpoint_buf, endpoint ? strlen(endpoint) + 1 : 0,
182+
&gateway_buf, gateway ? strlen(endpoint) + 1 : 0);
183+
host->node.key = strcpy(name_buf, name);
184+
peer = &host->peer;
185+
}
186+
187+
peer->dynamic = dynamic;
161188
if ((cur = tb[NETWORK_HOST_IPADDR]) != NULL && ipaddr_len)
162189
peer->ipaddr = memcpy(ipaddr, cur, ipaddr_len);
163190
if ((cur = tb[NETWORK_HOST_SUBNET]) != NULL && subnet_len)
@@ -172,16 +199,19 @@ network_host_create(struct network *net, struct blob_attr *attr)
172199
peer->pex_port = net->net_config.pex_port;
173200
if (endpoint)
174201
peer->endpoint = strcpy(endpoint_buf, endpoint);
175-
if (gateway)
176-
host->gateway = strcpy(gateway_buf, gateway);
177202
memcpy(peer->key, key, sizeof(key));
178-
host->node.key = strcpy(name_buf, name);
179203

180204
memcpy(&peer->local_addr.network_id,
181205
&net->net_config.addr.network_id,
182206
sizeof(peer->local_addr.network_id));
183207
network_fill_host_addr(&peer->local_addr, peer->key);
184208

209+
if (!host)
210+
return;
211+
212+
if (gateway)
213+
host->gateway = strcpy(gateway_buf, gateway);
214+
185215
blobmsg_for_each_attr(cur, tb[NETWORK_HOST_GROUPS], rem) {
186216
if (!blobmsg_check_attr(cur, false) ||
187217
blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
@@ -200,6 +230,36 @@ network_host_create(struct network *net, struct blob_attr *attr)
200230
}
201231
}
202232

233+
static void
234+
network_hosts_load_dynamic_file(struct network *net, const char *file)
235+
{
236+
struct blob_attr *cur;
237+
int rem;
238+
239+
blob_buf_init(&b, 0);
240+
241+
if (!blobmsg_add_json_from_file(&b, file))
242+
return;
243+
244+
blob_for_each_attr(cur, b.head, rem)
245+
network_host_create(net, cur, true);
246+
}
247+
248+
static void
249+
network_hosts_load_dynamic(struct network *net)
250+
{
251+
struct blob_attr *cur;
252+
int rem;
253+
254+
if (!net->config.peer_data)
255+
return;
256+
257+
blobmsg_for_each_attr(cur, net->config.peer_data, rem)
258+
network_hosts_load_dynamic_file(net, blobmsg_get_string(cur));
259+
260+
blob_buf_free(&b);
261+
}
262+
203263
void network_hosts_update_start(struct network *net)
204264
{
205265
struct network_host *host, *htmp;
@@ -216,11 +276,18 @@ void network_hosts_update_start(struct network *net)
216276
vlist_update(&net->peers);
217277
}
218278

219-
void network_hosts_update_done(struct network *net)
279+
static void
280+
__network_hosts_update_done(struct network *net, bool free_net)
220281
{
221282
struct network_host *local, *host, *tmp;
283+
struct network_dynamic_peer *dyn, *dyn_tmp;
284+
LIST_HEAD(old_dynamic);
222285
const char *local_name;
223286

287+
list_splice_init(&net->dynamic_peers, &old_dynamic);
288+
if (free_net)
289+
goto out;
290+
224291
local = net->net_config.local_host;
225292
if (!local)
226293
goto out;
@@ -240,20 +307,36 @@ void network_hosts_update_done(struct network *net)
240307
vlist_add(&net->peers, &host->peer.node, host->peer.key);
241308
}
242309

310+
network_hosts_load_dynamic(net);
311+
312+
list_for_each_entry(dyn, &net->dynamic_peers, list)
313+
vlist_add(&net->peers, &dyn->peer.node, &dyn->peer.key);
314+
243315
out:
244316
vlist_flush(&net->peers);
245317

318+
list_for_each_entry_safe(dyn, dyn_tmp, &old_dynamic, list) {
319+
list_del(&dyn->list);
320+
free(dyn);
321+
}
322+
246323
list_for_each_entry_safe(host, tmp, &old_hosts, node.list) {
247324
list_del(&host->node.list);
248325
free(host);
249326
}
250327
}
251328

329+
void network_hosts_update_done(struct network *net)
330+
{
331+
return __network_hosts_update_done(net, false);
332+
}
333+
252334
static void
253335
network_hosts_connect_cb(struct uloop_timeout *t)
254336
{
255337
struct network *net = container_of(t, struct network, connect_timer);
256338
struct network_host *host;
339+
struct network_peer *peer;
257340
union network_endpoint *ep;
258341

259342
avl_for_each_element(&net->hosts, host, node)
@@ -265,12 +348,7 @@ network_hosts_connect_cb(struct uloop_timeout *t)
265348

266349
wg_peer_refresh(net);
267350

268-
avl_for_each_element(&net->hosts, host, node) {
269-
struct network_peer *peer = &host->peer;
270-
271-
if (!network_host_is_peer(host))
272-
continue;
273-
351+
vlist_for_each_element(&net->peers, peer, node) {
274352
if (peer->state.connected)
275353
continue;
276354

@@ -300,11 +378,12 @@ void network_hosts_add(struct network *net, struct blob_attr *hosts)
300378
int rem;
301379

302380
blobmsg_for_each_attr(cur, hosts, rem)
303-
network_host_create(net, cur);
381+
network_host_create(net, cur, false);
304382
}
305383

306384
void network_hosts_init(struct network *net)
307385
{
386+
INIT_LIST_HEAD(&net->dynamic_peers);
308387
avl_init(&net->hosts, avl_strcmp, false, NULL);
309388
vlist_init(&net->peers, avl_key_cmp, network_peer_update);
310389
avl_init(&net->groups, avl_strcmp, false, NULL);
@@ -315,5 +394,5 @@ void network_hosts_free(struct network *net)
315394
{
316395
uloop_timeout_cancel(&net->connect_timer);
317396
network_hosts_update_start(net);
318-
network_hosts_update_done(net);
397+
__network_hosts_update_done(net, true);
319398
}

host.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct network_peer {
1414
struct blob_attr *subnet;
1515
int port;
1616
int pex_port;
17+
bool dynamic;
1718

1819
struct {
1920
int connect_attempt;
@@ -34,6 +35,12 @@ struct network_peer {
3435
} state;
3536
};
3637

38+
struct network_dynamic_peer {
39+
struct list_head list;
40+
41+
struct network_peer peer;
42+
};
43+
3744
struct network_host {
3845
struct avl_node node;
3946

@@ -66,7 +73,7 @@ static inline const char *network_peer_name(struct network_peer *peer)
6673
{
6774
struct network_host *host;
6875

69-
if (!peer)
76+
if (!peer || peer->dynamic)
7077
return "(none)";
7178

7279
host = container_of(peer, struct network_host, peer);

network.c

+5
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const struct blobmsg_policy network_policy[__NETWORK_ATTR_MAX] = {
5555
[NETWORK_ATTR_UPDATE_CMD] = { "update-cmd", BLOBMSG_TYPE_STRING },
5656
[NETWORK_ATTR_TUNNELS] = { "tunnels", BLOBMSG_TYPE_TABLE },
5757
[NETWORK_ATTR_AUTH_CONNECT] = { "auth_connect", BLOBMSG_TYPE_ARRAY },
58+
[NETWORK_ATTR_PEER_DATA] = { "peer_data", BLOBMSG_TYPE_ARRAY },
5859
};
5960

6061
AVL_TREE(networks, avl_strcmp, false, NULL);
@@ -537,6 +538,10 @@ network_set_config(struct network *net, struct blob_attr *config)
537538
blobmsg_check_array(cur, BLOBMSG_TYPE_STRING) > 0)
538539
net->config.auth_connect = cur;
539540

541+
if ((cur = tb[NETWORK_ATTR_PEER_DATA]) != NULL &&
542+
blobmsg_check_array(cur, BLOBMSG_TYPE_STRING) > 0)
543+
net->config.peer_data = cur;
544+
540545
if ((cur = tb[NETWORK_ATTR_KEY]) == NULL)
541546
goto invalid;
542547

network.h

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct network {
3838
struct blob_attr *tunnels;
3939
struct blob_attr *net_data;
4040
struct blob_attr *auth_connect;
41+
struct blob_attr *peer_data;
4142
} config;
4243

4344
struct {
@@ -58,6 +59,8 @@ struct network {
5859

5960
int ifindex;
6061
struct network_host *prev_local_host;
62+
63+
struct list_head dynamic_peers;
6164
struct avl_tree hosts;
6265
struct vlist_tree peers;
6366

@@ -82,6 +85,7 @@ enum {
8285
NETWORK_ATTR_DOMAIN,
8386
NETWORK_ATTR_TUNNELS,
8487
NETWORK_ATTR_AUTH_CONNECT,
88+
NETWORK_ATTR_PEER_DATA,
8589
__NETWORK_ATTR_MAX,
8690
};
8791

0 commit comments

Comments
 (0)