2
0

network.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
  4. */
  5. #define _GNU_SOURCE
  6. #include <arpa/inet.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <sys/wait.h>
  10. #include <net/if.h>
  11. #include <libubox/avl-cmp.h>
  12. #include <libubox/utils.h>
  13. #include <libubox/blobmsg_json.h>
  14. #include "unetd.h"
  15. enum {
  16. NETDATA_ATTR_CONFIG,
  17. NETDATA_ATTR_HOSTS,
  18. NETDATA_ATTR_GROUPS,
  19. NETDATA_ATTR_SERVICES,
  20. __NETDATA_ATTR_MAX,
  21. };
  22. static const struct blobmsg_policy netdata_policy[__NETDATA_ATTR_MAX] = {
  23. [NETDATA_ATTR_CONFIG] = { "config", BLOBMSG_TYPE_TABLE },
  24. [NETDATA_ATTR_HOSTS] = { "hosts", BLOBMSG_TYPE_TABLE },
  25. [NETDATA_ATTR_SERVICES] = { "services", BLOBMSG_TYPE_TABLE },
  26. };
  27. enum {
  28. NETCONF_ATTR_ID,
  29. NETCONF_ATTR_PORT,
  30. NETCONF_ATTR_PEX_PORT,
  31. NETCONF_ATTR_KEEPALIVE,
  32. NETCONF_ATTR_STUN_SERVERS,
  33. __NETCONF_ATTR_MAX
  34. };
  35. static const struct blobmsg_policy netconf_policy[__NETCONF_ATTR_MAX] = {
  36. [NETCONF_ATTR_ID] = { "id", BLOBMSG_TYPE_STRING },
  37. [NETCONF_ATTR_PORT] = { "port", BLOBMSG_TYPE_INT32 },
  38. [NETCONF_ATTR_PEX_PORT] = { "peer-exchange-port", BLOBMSG_TYPE_INT32 },
  39. [NETCONF_ATTR_KEEPALIVE] = { "keepalive", BLOBMSG_TYPE_INT32 },
  40. [NETCONF_ATTR_STUN_SERVERS] = { "stun-servers", BLOBMSG_TYPE_ARRAY },
  41. };
  42. const struct blobmsg_policy network_policy[__NETWORK_ATTR_MAX] = {
  43. [NETWORK_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
  44. [NETWORK_ATTR_TYPE] = { "type", BLOBMSG_TYPE_STRING },
  45. [NETWORK_ATTR_AUTH_KEY] = { "auth_key", BLOBMSG_TYPE_STRING },
  46. [NETWORK_ATTR_KEY] = { "key", BLOBMSG_TYPE_STRING },
  47. [NETWORK_ATTR_FILE] = { "file", BLOBMSG_TYPE_STRING },
  48. [NETWORK_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE },
  49. [NETWORK_ATTR_INTERFACE] = { "interface", BLOBMSG_TYPE_STRING },
  50. [NETWORK_ATTR_KEEPALIVE] = { "keepalive", BLOBMSG_TYPE_INT32 },
  51. [NETWORK_ATTR_DOMAIN] = { "domain", BLOBMSG_TYPE_STRING },
  52. [NETWORK_ATTR_UPDATE_CMD] = { "update-cmd", BLOBMSG_TYPE_STRING },
  53. [NETWORK_ATTR_TUNNELS] = { "tunnels", BLOBMSG_TYPE_TABLE },
  54. [NETWORK_ATTR_AUTH_CONNECT] = { "auth_connect", BLOBMSG_TYPE_ARRAY },
  55. [NETWORK_ATTR_PEER_DATA] = { "peer_data", BLOBMSG_TYPE_ARRAY },
  56. };
  57. AVL_TREE(networks, avl_strcmp, false, NULL);
  58. static struct blob_buf b;
  59. static void network_load_stun_servers(struct network *net, struct blob_attr *data)
  60. {
  61. struct blob_attr *cur;
  62. int rem;
  63. blobmsg_for_each_attr(cur, data, rem)
  64. network_stun_server_add(net, blobmsg_get_string(cur));
  65. }
  66. static void network_load_config_data(struct network *net, struct blob_attr *data)
  67. {
  68. struct blob_attr *tb[__NETCONF_ATTR_MAX];
  69. struct blob_attr *cur;
  70. siphash_key_t key = {};
  71. blobmsg_parse(netconf_policy, __NETCONF_ATTR_MAX, tb,
  72. blobmsg_data(data), blobmsg_len(data));
  73. if ((cur = tb[NETCONF_ATTR_PORT]) != NULL)
  74. net->net_config.port = blobmsg_get_u32(cur);
  75. else
  76. net->net_config.port = 51820;
  77. if ((cur = tb[NETCONF_ATTR_PEX_PORT]) != NULL)
  78. net->net_config.pex_port = blobmsg_get_u32(cur);
  79. if ((cur = tb[NETCONF_ATTR_ID]) != NULL) {
  80. const char *id = blobmsg_get_string(cur);
  81. siphash_to_le64(&net->net_config.addr.network_id, id, strlen(id), &key);
  82. } else {
  83. uint32_t port = cpu_to_le32(net->net_config.port);
  84. siphash_to_le64(&net->net_config.addr.network_id, &port, sizeof(port), &key);
  85. }
  86. net->net_config.addr.network_id[0] = 0xfd;
  87. network_fill_host_addr(&net->net_config.addr, net->config.pubkey);
  88. if (net->config.keepalive >= 0)
  89. net->net_config.keepalive = net->config.keepalive;
  90. else if ((cur = tb[NETCONF_ATTR_KEEPALIVE]) != NULL)
  91. net->net_config.keepalive = blobmsg_get_u32(cur);
  92. else
  93. net->net_config.keepalive = 0;
  94. if ((cur = tb[NETCONF_ATTR_STUN_SERVERS]) != NULL &&
  95. blobmsg_check_array(cur, BLOBMSG_TYPE_STRING) > 0)
  96. network_load_stun_servers(net, cur);
  97. }
  98. static int network_load_data(struct network *net, struct blob_attr *data)
  99. {
  100. struct blob_attr *tb[__NETDATA_ATTR_MAX];
  101. siphash_key_t key = {};
  102. net->net_config.hash = siphash(data, blob_raw_len(data), &key);
  103. blobmsg_parse(netdata_policy, __NETDATA_ATTR_MAX, tb,
  104. blobmsg_data(data), blobmsg_len(data));
  105. network_load_config_data(net, tb[NETDATA_ATTR_CONFIG]);
  106. network_hosts_add(net, tb[NETDATA_ATTR_HOSTS]);
  107. network_services_add(net, tb[NETDATA_ATTR_SERVICES]);
  108. return 0;
  109. }
  110. static int network_load_file(struct network *net)
  111. {
  112. blob_buf_init(&b, 0);
  113. if (!blobmsg_add_json_from_file(&b, net->config.file))
  114. return -1;
  115. return network_load_data(net, b.head);
  116. }
  117. static int network_load_dynamic(struct network *net)
  118. {
  119. const char *json = NULL;
  120. char *fname = NULL;
  121. struct stat st;
  122. FILE *f = NULL;
  123. int ret = -1;
  124. if (asprintf(&fname, "%s/%s.bin", data_dir, network_name(net)) < 0)
  125. return -1;
  126. f = fopen(fname, "r");
  127. free(fname);
  128. if (!f) {
  129. D_NET(net, "failed to open %s/%s.bin\n", data_dir, network_name(net));
  130. return -1;
  131. }
  132. if (fstat(fileno(f), &st) < 0)
  133. goto out;
  134. net->net_data_len = st.st_size;
  135. net->net_data = realloc(net->net_data, net->net_data_len + 1);
  136. memset(net->net_data + net->net_data_len, 0, 1);
  137. if (fread(net->net_data, 1, net->net_data_len, f) != net->net_data_len ||
  138. unet_auth_data_validate(net->config.auth_key, net->net_data,
  139. net->net_data_len, &net->net_data_version, &json)) {
  140. net->net_data_len = 0;
  141. goto out;
  142. }
  143. fclose(f);
  144. blob_buf_init(&b, 0);
  145. if (!blobmsg_add_json_from_string(&b, json)) {
  146. net->net_data_len = 0;
  147. return -1;
  148. }
  149. return network_load_data(net, b.head);
  150. out:
  151. fclose(f);
  152. return ret;
  153. }
  154. int network_save_dynamic(struct network *net)
  155. {
  156. char *fname = NULL, *fname2;
  157. size_t len;
  158. FILE *f;
  159. int fd, ret;
  160. if (net->config.type != NETWORK_TYPE_DYNAMIC ||
  161. !net->net_data_len)
  162. return -1;
  163. if (asprintf(&fname, "%s/%s.bin.XXXXXXXX", data_dir, network_name(net)) < 0)
  164. return -1;
  165. fd = mkstemp(fname);
  166. if (fd < 0)
  167. goto error;
  168. f = fdopen(fd, "w");
  169. if (!f) {
  170. close(fd);
  171. goto error;
  172. }
  173. len = fwrite(net->net_data, 1, net->net_data_len, f);
  174. fflush(f);
  175. fdatasync(fd);
  176. fclose(f);
  177. if (len != net->net_data_len)
  178. goto error;
  179. fname2 = strdup(fname);
  180. *strrchr(fname2, '.') = 0;
  181. ret = rename(fname, fname2);
  182. free(fname2);
  183. if (ret)
  184. unlink(fname);
  185. free(fname);
  186. return ret;
  187. error:
  188. free(fname);
  189. return -1;
  190. }
  191. static void
  192. network_fill_ip(struct blob_buf *buf, int af, union network_addr *addr, int mask)
  193. {
  194. char *str;
  195. void *c;
  196. c = blobmsg_open_table(buf, NULL);
  197. blobmsg_printf(buf, "mask", "%d", mask);
  198. str = blobmsg_alloc_string_buffer(buf, "ipaddr", INET6_ADDRSTRLEN);
  199. inet_ntop(af, addr, str, INET6_ADDRSTRLEN);
  200. blobmsg_add_string_buffer(buf);
  201. blobmsg_close_table(buf, c);
  202. }
  203. static void
  204. network_fill_ipaddr_list(struct network_host *host, struct blob_buf *b, bool ipv6)
  205. {
  206. union network_addr addr = {};
  207. struct blob_attr *cur;
  208. void *c;
  209. int rem;
  210. int af;
  211. af = ipv6 ? AF_INET6 : AF_INET;
  212. blobmsg_for_each_attr(cur, host->peer.ipaddr, rem) {
  213. const char *str = blobmsg_get_string(cur);
  214. if (!!strchr(str, ':') != ipv6)
  215. continue;
  216. if (inet_pton(af, str, &addr) != 1)
  217. continue;
  218. c = blobmsg_open_table(b, NULL);
  219. blobmsg_add_string(b, "ipaddr", str);
  220. blobmsg_add_string(b, "mask", ipv6 ? "128" : "32");
  221. blobmsg_close_table(b, c);
  222. }
  223. }
  224. static void
  225. network_fill_ip_settings(struct network *net, struct blob_buf *buf)
  226. {
  227. struct network_host *host = net->net_config.local_host;
  228. void *c;
  229. c = blobmsg_open_array(buf, "ipaddr");
  230. network_fill_ipaddr_list(host, buf, false);
  231. blobmsg_close_array(buf, c);
  232. c = blobmsg_open_array(buf, "ip6addr");
  233. network_fill_ip(buf, AF_INET6, &host->peer.local_addr, 64);
  234. network_fill_ipaddr_list(host, buf, true);
  235. blobmsg_close_array(buf, c);
  236. }
  237. static void
  238. __network_fill_host_subnets(struct network_host *host, struct blob_buf *b, bool ipv6)
  239. {
  240. union network_addr addr = {};
  241. struct blob_attr *cur;
  242. void *c;
  243. int af;
  244. int mask;
  245. int rem;
  246. af = ipv6 ? AF_INET6 : AF_INET;
  247. blobmsg_for_each_attr(cur, host->peer.subnet, rem) {
  248. const char *str = blobmsg_get_string(cur);
  249. char *buf;
  250. if (!!strchr(str, ':') != ipv6)
  251. continue;
  252. if (network_get_subnet(af, &addr, &mask, str))
  253. continue;
  254. c = blobmsg_open_table(b, NULL);
  255. buf = blobmsg_alloc_string_buffer(b, "target", INET6_ADDRSTRLEN);
  256. inet_ntop(af, &addr, buf, INET6_ADDRSTRLEN);
  257. blobmsg_add_string_buffer(b);
  258. blobmsg_printf(b, "netmask", "%d", mask);
  259. blobmsg_close_table(b, c);
  260. }
  261. blobmsg_for_each_attr(cur, host->peer.ipaddr, rem) {
  262. const char *str = blobmsg_get_string(cur);
  263. if (!!strchr(str, ':') != ipv6)
  264. continue;
  265. if (inet_pton(af, str, &addr) != 1)
  266. continue;
  267. c = blobmsg_open_table(b, NULL);
  268. blobmsg_add_string(b, "target", str);
  269. blobmsg_add_string(b, "netmask", ipv6 ? "128" : "32");
  270. blobmsg_close_table(b, c);
  271. }
  272. }
  273. static void
  274. __network_fill_subnets(struct network *net, struct blob_buf *buf, bool ipv6)
  275. {
  276. struct network_host *host;
  277. void *c;
  278. c = blobmsg_open_array(buf, ipv6 ? "routes6": "routes");
  279. avl_for_each_element(&net->hosts, host, node) {
  280. if (host == net->net_config.local_host)
  281. continue;
  282. __network_fill_host_subnets(host, buf, ipv6);
  283. }
  284. blobmsg_close_array(buf, c);
  285. }
  286. static void
  287. network_fill_subnets(struct network *net, struct blob_buf *buf)
  288. {
  289. __network_fill_subnets(net, buf, false);
  290. __network_fill_subnets(net, buf, true);
  291. }
  292. static bool
  293. __network_skip_endpoint_route(struct network *net, struct network_host *host,
  294. union network_endpoint *ep)
  295. {
  296. bool ipv6 = ep->sa.sa_family == AF_INET6;
  297. uint32_t *subnet32, *addr32, mask32;
  298. union network_addr addr = {};
  299. struct blob_attr *cur;
  300. int mask, rem;
  301. blobmsg_for_each_attr(cur, host->peer.ipaddr, rem) {
  302. const char *str = blobmsg_get_string(cur);
  303. if (!!strchr(str, ':') != ipv6)
  304. continue;
  305. if (inet_pton(ep->sa.sa_family, str, &addr) != 1)
  306. continue;
  307. if (ipv6) {
  308. if (!memcmp(&addr.in6, &ep->in6.sin6_addr, sizeof(addr.in6)))
  309. return true;
  310. } else {
  311. if (!memcmp(&addr.in, &ep->in.sin_addr, sizeof(addr.in)))
  312. return true;
  313. }
  314. }
  315. if (ipv6)
  316. addr32 = (uint32_t *)&ep->in6.sin6_addr;
  317. else
  318. addr32 = (uint32_t *)&ep->in.sin_addr;
  319. subnet32 = (uint32_t *)&addr;
  320. blobmsg_for_each_attr(cur, host->peer.subnet, rem) {
  321. const char *str = blobmsg_get_string(cur);
  322. int i;
  323. if (!!strchr(str, ':') != ipv6)
  324. continue;
  325. if (network_get_subnet(ep->sa.sa_family, &addr, &mask, str))
  326. continue;
  327. if (mask <= 1)
  328. continue;
  329. for (i = 0; i < (ipv6 ? 4 : 1); i++) {
  330. int cur_mask = mask > 32 ? 32 : mask;
  331. if (mask > 32)
  332. mask -= 32;
  333. else
  334. mask = 0;
  335. mask32 = ~0ULL << (32 - cur_mask);
  336. if (ntohl(subnet32[i] ^ addr32[i]) & mask32)
  337. continue;
  338. }
  339. return true;
  340. }
  341. return false;
  342. }
  343. bool network_skip_endpoint_route(struct network *net, union network_endpoint *ep)
  344. {
  345. struct network_host *host;
  346. avl_for_each_element(&net->hosts, host, node)
  347. if (__network_skip_endpoint_route(net, host, ep))
  348. return true;
  349. return false;
  350. }
  351. static void
  352. network_do_update(struct network *net, bool up)
  353. {
  354. if (!net->net_config.local_host)
  355. up = false;
  356. blob_buf_init(&b, 0);
  357. blobmsg_add_u32(&b, "action", 0);
  358. blobmsg_add_string(&b, "ifname", network_name(net));
  359. blobmsg_add_u8(&b, "link-up", up);
  360. if (up) {
  361. network_fill_ip_settings(net, &b);
  362. network_fill_subnets(net, &b);
  363. }
  364. if (debug) {
  365. char *s = blobmsg_format_json(b.head, true);
  366. D_NET(net, "update: %s", s);
  367. free(s);
  368. }
  369. if (net->config.update_cmd) {
  370. const char *argv[] = { net->config.update_cmd, NULL, NULL };
  371. int pid, stat;
  372. pid = fork();
  373. if (pid == 0) {
  374. argv[1] = blobmsg_format_json(b.head, true);
  375. execvp(argv[0], (char **)argv);
  376. exit(1);
  377. }
  378. waitpid(pid, &stat, 0);
  379. }
  380. if (!net->config.interface)
  381. return;
  382. blobmsg_add_string(&b, "interface", net->config.interface);
  383. unetd_ubus_netifd_update(b.head);
  384. }
  385. static void network_reload(struct uloop_timeout *t)
  386. {
  387. struct network *net = container_of(t, struct network, reload_timer);
  388. net->prev_local_host = net->net_config.local_host;
  389. memset(&net->net_config, 0, sizeof(net->net_config));
  390. network_stun_free(net);
  391. network_pex_close(net);
  392. network_services_free(net);
  393. network_hosts_update_start(net);
  394. network_services_update_start(net);
  395. switch (net->config.type) {
  396. case NETWORK_TYPE_FILE:
  397. network_load_file(net);
  398. break;
  399. case NETWORK_TYPE_INLINE:
  400. network_load_data(net, net->config.net_data);
  401. break;
  402. case NETWORK_TYPE_DYNAMIC:
  403. network_load_dynamic(net);
  404. break;
  405. }
  406. network_services_update_done(net);
  407. network_hosts_update_done(net);
  408. uloop_timeout_set(&net->connect_timer, 10);
  409. net->prev_local_host = NULL;
  410. unetd_write_hosts();
  411. network_do_update(net, true);
  412. network_pex_open(net);
  413. network_stun_start(net);
  414. unetd_ubus_notify(net);
  415. }
  416. void network_soft_reload(struct network *net)
  417. {
  418. siphash_key_t key = {};
  419. uint64_t hash;
  420. if (net->config.type == NETWORK_TYPE_FILE) {
  421. blob_buf_init(&b, 0);
  422. if (!blobmsg_add_json_from_file(&b, net->config.file))
  423. return;
  424. hash = siphash(b.head, blob_raw_len(b.head), &key);
  425. if (hash != net->net_config.hash) {
  426. uloop_timeout_set(&net->reload_timer, 1);
  427. return;
  428. }
  429. }
  430. network_hosts_reload_dynamic_peers(net);
  431. }
  432. static int network_setup(struct network *net)
  433. {
  434. if (wg_init_network(net)) {
  435. fprintf(stderr, "Setup failed for network %s\n", network_name(net));
  436. return -1;
  437. }
  438. net->ifindex = if_nametoindex(network_name(net));
  439. if (!net->ifindex) {
  440. fprintf(stderr, "Could not get ifindex for network %s\n", network_name(net));
  441. return -1;
  442. }
  443. return 0;
  444. }
  445. static void network_teardown(struct network *net)
  446. {
  447. uloop_timeout_cancel(&net->connect_timer);
  448. uloop_timeout_cancel(&net->reload_timer);
  449. network_do_update(net, false);
  450. network_stun_free(net);
  451. network_pex_close(net);
  452. network_pex_free(net);
  453. network_hosts_free(net);
  454. network_services_free(net);
  455. wg_cleanup_network(net);
  456. }
  457. static void
  458. network_destroy(struct network *net)
  459. {
  460. network_teardown(net);
  461. avl_delete(&networks, &net->node);
  462. free(net->net_data);
  463. free(net->config.data);
  464. free(net);
  465. }
  466. static int
  467. network_set_config(struct network *net, struct blob_attr *config)
  468. {
  469. struct blob_attr *tb[__NETWORK_ATTR_MAX];
  470. struct blob_attr *cur;
  471. if (net->config.data && blob_attr_equal(net->config.data, config))
  472. goto reload;
  473. network_teardown(net);
  474. free(net->config.data);
  475. memset(&net->config, 0, sizeof(net->config));
  476. net->config.data = blob_memdup(config);
  477. blobmsg_parse(network_policy, __NETWORK_ATTR_MAX, tb,
  478. blobmsg_data(net->config.data),
  479. blobmsg_len(net->config.data));
  480. if ((cur = tb[NETWORK_ATTR_TYPE]) == NULL ||
  481. !strlen(blobmsg_get_string(cur)) ||
  482. !strcmp(blobmsg_get_string(cur), "dynamic"))
  483. net->config.type = NETWORK_TYPE_DYNAMIC;
  484. else if (!strcmp(blobmsg_get_string(cur), "file"))
  485. net->config.type = NETWORK_TYPE_FILE;
  486. else if (!strcmp(blobmsg_get_string(cur), "inline"))
  487. net->config.type = NETWORK_TYPE_INLINE;
  488. else
  489. goto invalid;
  490. if ((cur = tb[NETWORK_ATTR_KEEPALIVE]) != NULL)
  491. net->config.keepalive = blobmsg_get_u32(cur);
  492. else
  493. net->config.keepalive = -1;
  494. switch (net->config.type) {
  495. case NETWORK_TYPE_FILE:
  496. if ((cur = tb[NETWORK_ATTR_FILE]) != NULL)
  497. net->config.file = blobmsg_get_string(cur);
  498. else
  499. goto invalid;
  500. break;
  501. case NETWORK_TYPE_INLINE:
  502. net->config.net_data = tb[NETWORK_ATTR_DATA];
  503. if (!net->config.net_data)
  504. goto invalid;
  505. break;
  506. case NETWORK_TYPE_DYNAMIC:
  507. if ((cur = tb[NETWORK_ATTR_AUTH_KEY]) == NULL)
  508. goto invalid;
  509. if (b64_decode(blobmsg_get_string(cur), net->config.auth_key,
  510. sizeof(net->config.auth_key)) != sizeof(net->config.auth_key))
  511. goto invalid;
  512. break;
  513. }
  514. if ((cur = tb[NETWORK_ATTR_INTERFACE]) != NULL &&
  515. strlen(blobmsg_get_string(cur)) > 0)
  516. net->config.interface = blobmsg_get_string(cur);
  517. if ((cur = tb[NETWORK_ATTR_UPDATE_CMD]) != NULL &&
  518. strlen(blobmsg_get_string(cur)) > 0)
  519. net->config.update_cmd = blobmsg_get_string(cur);
  520. if ((cur = tb[NETWORK_ATTR_DOMAIN]) != NULL &&
  521. strlen(blobmsg_get_string(cur)) > 0)
  522. net->config.domain = blobmsg_get_string(cur);
  523. if ((cur = tb[NETWORK_ATTR_TUNNELS]) != NULL)
  524. net->config.tunnels = cur;
  525. if ((cur = tb[NETWORK_ATTR_AUTH_CONNECT]) != NULL &&
  526. blobmsg_check_array(cur, BLOBMSG_TYPE_STRING) > 0)
  527. net->config.auth_connect = cur;
  528. if ((cur = tb[NETWORK_ATTR_PEER_DATA]) != NULL &&
  529. blobmsg_check_array(cur, BLOBMSG_TYPE_STRING) > 0)
  530. net->config.peer_data = cur;
  531. if ((cur = tb[NETWORK_ATTR_KEY]) == NULL)
  532. goto invalid;
  533. if (b64_decode(blobmsg_get_string(cur), net->config.key, sizeof(net->config.key)) !=
  534. sizeof(net->config.key))
  535. goto invalid;
  536. curve25519_generate_public(net->config.pubkey, net->config.key);
  537. if (network_setup(net))
  538. goto invalid;
  539. reload:
  540. network_reload(&net->reload_timer);
  541. return 0;
  542. invalid:
  543. network_destroy(net);
  544. return -1;
  545. }
  546. static struct network *
  547. network_alloc(const char *name)
  548. {
  549. struct network *net;
  550. char *name_buf;
  551. net = calloc_a(sizeof(*net), &name_buf, strlen(name) + 1);
  552. net->node.key = strcpy(name_buf, name);
  553. net->reload_timer.cb = network_reload;
  554. avl_insert(&networks, &net->node);
  555. network_pex_init(net);
  556. network_stun_init(net);
  557. network_hosts_init(net);
  558. network_services_init(net);
  559. return net;
  560. }
  561. void network_fill_host_addr(union network_addr *addr, uint8_t *pubkey)
  562. {
  563. siphash_key_t key = {
  564. .key = {
  565. get_unaligned_le64(addr->network_id),
  566. get_unaligned_le64(addr->network_id)
  567. }
  568. };
  569. siphash_to_le64(&addr->host_addr, pubkey, CURVE25519_KEY_SIZE, &key);
  570. }
  571. int unetd_network_add(const char *name, struct blob_attr *config)
  572. {
  573. struct network *net;
  574. if (strchr(name, '/'))
  575. return -1;
  576. net = avl_find_element(&networks, name, net, node);
  577. if (!net)
  578. net = network_alloc(name);
  579. return network_set_config(net, config);
  580. }
  581. int unetd_network_remove(const char *name)
  582. {
  583. struct network *net;
  584. net = avl_find_element(&networks, name, net, node);
  585. if (!net)
  586. return -1;
  587. network_destroy(net);
  588. return 0;
  589. }
  590. void network_free_all(void)
  591. {
  592. struct network *net, *tmp;
  593. avl_for_each_element_safe(&networks, net, node, tmp)
  594. network_destroy(net);
  595. }