pex: after receiving data update req, notify peer of local address/port
[project/unetd.git] / host.c
diff --git a/host.c b/host.c
index 71fc8408ef3cfaa1a2064190f4e4e253fd390a52..e4e38d33079978b6f4f5c402c601aa1e1d9c15eb 100644 (file)
--- a/host.c
+++ b/host.c
@@ -179,7 +179,7 @@ network_host_create(struct network *net, struct blob_attr *attr, bool dynamic)
                                &ipaddr, ipaddr_len,
                                &subnet, subnet_len,
                                &endpoint_buf, endpoint ? strlen(endpoint) + 1 : 0,
-                               &gateway_buf, gateway ? strlen(endpoint) + 1 : 0);
+                               &gateway_buf, gateway ? strlen(gateway) + 1 : 0);
                host->node.key = strcpy(name_buf, name);
                peer = &host->peer;
        }
@@ -246,8 +246,9 @@ network_hosts_load_dynamic_file(struct network *net, const char *file)
 }
 
 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;
 
@@ -258,6 +259,41 @@ network_hosts_load_dynamic(struct network *net)
                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)
@@ -280,7 +316,6 @@ static void
 __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;
 
@@ -307,18 +342,12 @@ __network_hosts_update_done(struct network *net, bool free_net)
                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);
@@ -331,6 +360,35 @@ void network_hosts_update_done(struct network *net)
        return __network_hosts_update_done(net, false);
 }
 
+static union network_endpoint *
+network_peer_next_endpoint(struct network_peer *peer)
+{
+       union network_endpoint *ep;
+       int i;
+
+       for (i = 0; i < __ENDPOINT_TYPE_MAX; i++) {
+               int cur = peer->state.next_endpoint_idx;
+
+               if (++peer->state.next_endpoint_idx == __ENDPOINT_TYPE_MAX)
+                       peer->state.next_endpoint_idx = 0;
+
+               ep = &peer->state.next_endpoint[cur];
+               if (cur == ENDPOINT_TYPE_STATIC &&
+                       (!peer->endpoint ||
+                    network_get_endpoint(ep, AF_UNSPEC, peer->endpoint, peer->port,
+                                         peer->state.connect_attempt++)))
+                       continue;
+
+               if (!ep->sa.sa_family)
+                       continue;
+
+               return ep;
+       }
+
+       return NULL;
+}
+
+
 static void
 network_hosts_connect_cb(struct uloop_timeout *t)
 {
@@ -352,16 +410,12 @@ network_hosts_connect_cb(struct uloop_timeout *t)
                if (peer->state.connected)
                        continue;
 
-               ep = &peer->state.next_endpoint;
-               if (peer->endpoint &&
-                   network_get_endpoint(ep, peer->endpoint, peer->port,
-                                        peer->state.connect_attempt++))
-                       continue;
-
-               if (!ep->sa.sa_family)
+               ep = network_peer_next_endpoint(peer);
+               if (!ep)
                        continue;
 
-               if (memcmp(ep, &peer->state.endpoint, sizeof(*ep)) != 0)
+               if (memcmp(ep, &peer->state.endpoint, sizeof(*ep)) != 0 &&
+                   !network_skip_endpoint_route(net, ep))
                        unetd_ubus_netifd_add_route(net, ep);
 
                wg_peer_connect(net, peer, ep);