}
static void
-network_hosts_load_dynamic(struct network *net)
+network_hosts_load_dynamic_peers(struct network *net)
{
+ struct network_dynamic_peer *dyn;
struct blob_attr *cur;
int rem;
network_hosts_load_dynamic_file(net, blobmsg_get_string(cur));
blob_buf_free(&b);
+
+ list_for_each_entry(dyn, &net->dynamic_peers, list)
+ vlist_add(&net->peers, &dyn->peer.node, &dyn->peer.key);
+}
+
+static void
+network_host_free_dynamic_peers(struct list_head *list)
+{
+ struct network_dynamic_peer *dyn, *dyn_tmp;
+
+ list_for_each_entry_safe(dyn, dyn_tmp, list, list) {
+ list_del(&dyn->list);
+ free(dyn);
+ }
+}
+
+void network_hosts_reload_dynamic_peers(struct network *net)
+{
+ struct network_peer *peer;
+ LIST_HEAD(old_entries);
+
+ if (!net->config.peer_data)
+ return;
+
+ list_splice_init(&net->dynamic_peers, &old_entries);
+
+ vlist_for_each_element(&net->peers, peer, node)
+ if (peer->dynamic)
+ peer->node.version = net->peers.version - 1;
+
+ network_hosts_load_dynamic_peers(net);
+
+ vlist_flush(&net->peers);
+
+ network_host_free_dynamic_peers(&old_entries);
}
void network_hosts_update_start(struct network *net)
__network_hosts_update_done(struct network *net, bool free_net)
{
struct network_host *local, *host, *tmp;
- struct network_dynamic_peer *dyn, *dyn_tmp;
LIST_HEAD(old_dynamic);
const char *local_name;
vlist_add(&net->peers, &host->peer.node, host->peer.key);
}
- network_hosts_load_dynamic(net);
-
- list_for_each_entry(dyn, &net->dynamic_peers, list)
- vlist_add(&net->peers, &dyn->peer.node, &dyn->peer.key);
+ network_hosts_load_dynamic_peers(net);
out:
vlist_flush(&net->peers);
- list_for_each_entry_safe(dyn, dyn_tmp, &old_dynamic, list) {
- list_del(&dyn->list);
- free(dyn);
- }
+ network_host_free_dynamic_peers(&old_dynamic);
list_for_each_entry_safe(host, tmp, &old_hosts, node.list) {
list_del(&host->node.list);
void network_hosts_update_start(struct network *net);
void network_hosts_update_done(struct network *net);
void network_hosts_add(struct network *net, struct blob_attr *hosts);
+void network_hosts_reload_dynamic_peers(struct network *net);
void network_hosts_init(struct network *net);
void network_hosts_free(struct network *net);
static int network_load_data(struct network *net, struct blob_attr *data)
{
struct blob_attr *tb[__NETDATA_ATTR_MAX];
+ siphash_key_t key = {};
+ net->net_config.hash = siphash(data, blob_raw_len(data), &key);
blobmsg_parse(netdata_policy, __NETDATA_ATTR_MAX, tb,
blobmsg_data(data), blobmsg_len(data));
network_pex_open(net);
}
+void network_soft_reload(struct network *net)
+{
+ siphash_key_t key = {};
+ uint64_t hash;
+
+ if (net->config.type == NETWORK_TYPE_FILE) {
+ blob_buf_init(&b, 0);
+
+ if (!blobmsg_add_json_from_file(&b, net->config.file))
+ return;
+
+ hash = siphash(b.head, blob_raw_len(b.head), &key);
+ if (hash != net->net_config.hash) {
+ uloop_timeout_set(&net->reload_timer, 1);
+ return;
+ }
+ }
+
+ network_hosts_reload_dynamic_peers(net);
+}
+
static int network_setup(struct network *net)
{
if (wg_init_network(net)) {
} config;
struct {
+ uint64_t hash;
union network_addr addr;
struct network_host *local_host;
unsigned int keepalive;
void network_fill_host_addr(union network_addr *addr, uint8_t *key);
int network_save_dynamic(struct network *net);
+void network_soft_reload(struct network *net);
void network_free_all(void);
int unetd_network_add(const char *name, struct blob_attr *config);
return 0;
}
+static int
+ubus_reload(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct network *net;
+
+ avl_for_each_element(&networks, net, node)
+ network_soft_reload(net);
+
+ return 0;
+}
+
static const struct ubus_method unetd_methods[] = {
UBUS_METHOD("network_add", ubus_network_add, network_policy),
UBUS_METHOD_MASK("network_get", ubus_network_get, network_policy,
(1 << NETWORK_ATTR_NAME)),
UBUS_METHOD("network_connect", ubus_network_connect, connect_policy),
+ UBUS_METHOD_NOARG("reload", ubus_reload),
UBUS_METHOD("service_get", ubus_service_get, service_policy),
};