3
3
* Copyright (C) 2022 Felix Fietkau <[email protected] >
4
4
*/
5
5
#include <libubox/avl-cmp.h>
6
+ #include <libubox/blobmsg_json.h>
6
7
#include "unetd.h"
7
8
8
9
static LIST_HEAD (old_hosts );
10
+ static struct blob_buf b ;
9
11
10
12
static int avl_key_cmp (const void * k1 , const void * k2 , void * ptr )
11
13
{
@@ -83,41 +85,43 @@ network_host_add_group(struct network *net, struct network_host *host,
83
85
group -> members [group -> n_members - 1 ] = host ;
84
86
}
85
87
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
+
86
111
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 )
88
113
{
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
- };
110
114
struct blob_attr * tb [__NETWORK_HOST_MAX ];
111
115
struct blob_attr * cur , * ipaddr , * subnet ;
112
116
uint8_t key [CURVE25519_KEY_SIZE ];
113
- struct network_host * host ;
117
+ struct network_host * host = NULL ;
114
118
struct network_peer * peer ;
115
119
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 ;
118
122
int rem ;
119
123
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 ));
121
125
122
126
if (!tb [NETWORK_HOST_KEY ])
123
127
return ;
@@ -137,7 +141,7 @@ network_host_create(struct network *net, struct blob_attr *attr)
137
141
else
138
142
endpoint = NULL ;
139
143
140
- if ((cur = tb [NETWORK_HOST_GATEWAY ]) != NULL )
144
+ if (! dynamic && (cur = tb [NETWORK_HOST_GATEWAY ]) != NULL )
141
145
gateway = blobmsg_get_string (cur );
142
146
else
143
147
gateway = NULL ;
@@ -146,18 +150,41 @@ network_host_create(struct network *net, struct blob_attr *attr)
146
150
sizeof (key )) != sizeof (key ))
147
151
return ;
148
152
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 ;
153
176
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 ;
161
188
if ((cur = tb [NETWORK_HOST_IPADDR ]) != NULL && ipaddr_len )
162
189
peer -> ipaddr = memcpy (ipaddr , cur , ipaddr_len );
163
190
if ((cur = tb [NETWORK_HOST_SUBNET ]) != NULL && subnet_len )
@@ -172,16 +199,19 @@ network_host_create(struct network *net, struct blob_attr *attr)
172
199
peer -> pex_port = net -> net_config .pex_port ;
173
200
if (endpoint )
174
201
peer -> endpoint = strcpy (endpoint_buf , endpoint );
175
- if (gateway )
176
- host -> gateway = strcpy (gateway_buf , gateway );
177
202
memcpy (peer -> key , key , sizeof (key ));
178
- host -> node .key = strcpy (name_buf , name );
179
203
180
204
memcpy (& peer -> local_addr .network_id ,
181
205
& net -> net_config .addr .network_id ,
182
206
sizeof (peer -> local_addr .network_id ));
183
207
network_fill_host_addr (& peer -> local_addr , peer -> key );
184
208
209
+ if (!host )
210
+ return ;
211
+
212
+ if (gateway )
213
+ host -> gateway = strcpy (gateway_buf , gateway );
214
+
185
215
blobmsg_for_each_attr (cur , tb [NETWORK_HOST_GROUPS ], rem ) {
186
216
if (!blobmsg_check_attr (cur , false) ||
187
217
blobmsg_type (cur ) != BLOBMSG_TYPE_STRING )
@@ -200,6 +230,36 @@ network_host_create(struct network *net, struct blob_attr *attr)
200
230
}
201
231
}
202
232
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
+
203
263
void network_hosts_update_start (struct network * net )
204
264
{
205
265
struct network_host * host , * htmp ;
@@ -216,11 +276,18 @@ void network_hosts_update_start(struct network *net)
216
276
vlist_update (& net -> peers );
217
277
}
218
278
219
- void network_hosts_update_done (struct network * net )
279
+ static void
280
+ __network_hosts_update_done (struct network * net , bool free_net )
220
281
{
221
282
struct network_host * local , * host , * tmp ;
283
+ struct network_dynamic_peer * dyn , * dyn_tmp ;
284
+ LIST_HEAD (old_dynamic );
222
285
const char * local_name ;
223
286
287
+ list_splice_init (& net -> dynamic_peers , & old_dynamic );
288
+ if (free_net )
289
+ goto out ;
290
+
224
291
local = net -> net_config .local_host ;
225
292
if (!local )
226
293
goto out ;
@@ -240,20 +307,36 @@ void network_hosts_update_done(struct network *net)
240
307
vlist_add (& net -> peers , & host -> peer .node , host -> peer .key );
241
308
}
242
309
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
+
243
315
out :
244
316
vlist_flush (& net -> peers );
245
317
318
+ list_for_each_entry_safe (dyn , dyn_tmp , & old_dynamic , list ) {
319
+ list_del (& dyn -> list );
320
+ free (dyn );
321
+ }
322
+
246
323
list_for_each_entry_safe (host , tmp , & old_hosts , node .list ) {
247
324
list_del (& host -> node .list );
248
325
free (host );
249
326
}
250
327
}
251
328
329
+ void network_hosts_update_done (struct network * net )
330
+ {
331
+ return __network_hosts_update_done (net , false);
332
+ }
333
+
252
334
static void
253
335
network_hosts_connect_cb (struct uloop_timeout * t )
254
336
{
255
337
struct network * net = container_of (t , struct network , connect_timer );
256
338
struct network_host * host ;
339
+ struct network_peer * peer ;
257
340
union network_endpoint * ep ;
258
341
259
342
avl_for_each_element (& net -> hosts , host , node )
@@ -265,12 +348,7 @@ network_hosts_connect_cb(struct uloop_timeout *t)
265
348
266
349
wg_peer_refresh (net );
267
350
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 ) {
274
352
if (peer -> state .connected )
275
353
continue ;
276
354
@@ -300,11 +378,12 @@ void network_hosts_add(struct network *net, struct blob_attr *hosts)
300
378
int rem ;
301
379
302
380
blobmsg_for_each_attr (cur , hosts , rem )
303
- network_host_create (net , cur );
381
+ network_host_create (net , cur , false );
304
382
}
305
383
306
384
void network_hosts_init (struct network * net )
307
385
{
386
+ INIT_LIST_HEAD (& net -> dynamic_peers );
308
387
avl_init (& net -> hosts , avl_strcmp , false, NULL );
309
388
vlist_init (& net -> peers , avl_key_cmp , network_peer_update );
310
389
avl_init (& net -> groups , avl_strcmp , false, NULL );
@@ -315,5 +394,5 @@ void network_hosts_free(struct network *net)
315
394
{
316
395
uloop_timeout_cancel (& net -> connect_timer );
317
396
network_hosts_update_start (net );
318
- network_hosts_update_done (net );
397
+ __network_hosts_update_done (net , true );
319
398
}
0 commit comments