remote: close file on usteer_init_local_id fread fail
[project/usteer.git] / remote.c
index 8e6e37eedd5572911de2032dfca1ce960a529952..bf58ea3c9564226068b41c39d24dacb7a3282243 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -17,6 +17,8 @@
  *   Copyright (C) 2020 John Crispin <john@phrozen.org> 
  */
 
+#define _GNU_SOURCE
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -153,9 +155,11 @@ static void
 interface_add_station(struct usteer_remote_node *node, struct blob_attr *data)
 {
        struct sta *sta;
-       struct sta_info *si;
+       struct sta_info *si, *local_si;
        struct apmsg_sta msg;
+       struct usteer_node *local_node;
        bool create;
+       bool connect_change;
 
        if (!parse_apmsg_sta(&msg, data)) {
                MSG(DEBUG, "Cannot parse station in message\n");
@@ -175,9 +179,26 @@ interface_add_station(struct usteer_remote_node *node, struct blob_attr *data)
        if (!si)
                return;
 
+       connect_change = si->connected != msg.connected;
        si->connected = msg.connected;
        si->signal = msg.signal;
        si->seen = current_time - msg.seen;
+       si->last_connected = current_time - msg.last_connected;
+
+       /* Check if client roamed to this foreign node */
+       if ((connect_change || create) && si->connected == STA_CONNECTED) {
+               for_each_local_node(local_node) {
+                       local_si = usteer_sta_info_get(sta, local_node, NULL);
+                       if (!local_si)
+                               continue;
+
+                       if (current_time - local_si->last_connected < config.roam_process_timeout) {
+                               node->node.roam_events.target++;
+                               break;
+                       }
+               }
+       }
+
        usteer_sta_info_update_timeout(si, msg.timeout);
 }
 
@@ -189,12 +210,14 @@ remote_node_free(struct usteer_remote_node *node)
        list_del(&node->list);
        list_del(&node->host_list);
        usteer_sta_node_cleanup(&node->node);
+       usteer_measurement_report_node_cleanup(&node->node);
        free(node);
 
        if (!list_empty(&host->nodes))
                return;
 
        avl_delete(&remote_hosts, &host->avl);
+       free(host->addr);
        free(host);
 }
 
@@ -235,12 +258,14 @@ interface_get_node(struct usteer_remote_host *host, const char *name)
 
        node = calloc_a(sizeof(*node), &buf, addr_len + 1 + strlen(name) + 1);
        node->node.type = NODE_TYPE_REMOTE;
+       node->node.created = current_time;
 
        sprintf(buf, "%s#%s", host->addr, name);
        node->node.avl.key = buf;
        node->name = buf + addr_len + 1;
        node->host = host;
        INIT_LIST_HEAD(&node->node.sta_info);
+       INIT_LIST_HEAD(&node->node.measurements);
 
        list_add_tail(&node->list, &remote_nodes);
        list_add_tail(&node->host_list, &host->nodes);
@@ -264,10 +289,15 @@ interface_add_node(struct usteer_remote_host *host, struct blob_attr *data)
        node = interface_get_node(host, msg.name);
        node->check = 0;
        node->node.freq = msg.freq;
+       node->node.channel = msg.channel;
+       node->node.op_class = msg.op_class;
        node->node.n_assoc = msg.n_assoc;
        node->node.max_assoc = msg.max_assoc;
        node->node.noise = msg.noise;
        node->node.load = msg.load;
+
+       memcpy(node->node.bssid, msg.bssid, sizeof(node->node.bssid));
+
        snprintf(node->node.ssid, sizeof(node->node.ssid), "%s", msg.ssid);
        usteer_node_set_blob(&node->node.rrm_nr, msg.rrm_nr);
        usteer_node_set_blob(&node->node.node_info, msg.node_info);
@@ -285,6 +315,9 @@ interface_recv_msg(struct interface *iface, char *addr_str, void *buf, int len)
        struct blob_attr *cur;
        int rem;
 
+       if (config.local_mode)
+               return;
+
        if (blob_pad_len(data) != len) {
                MSG(DEBUG, "Invalid message length (header: %d, real: %d)\n", blob_pad_len(data), len);
                return;
@@ -513,6 +546,7 @@ static void interface_send_msg(struct interface *iface, struct blob_attr *data){
 static void usteer_send_sta_info(struct sta_info *sta)
 {
        int seen = current_time - sta->seen;
+       int last_connected = !!sta->connected ? 0 : current_time - sta->last_connected;
        void *c;
 
        c = blob_nest_start(&buf, 0);
@@ -520,6 +554,7 @@ static void usteer_send_sta_info(struct sta_info *sta)
        blob_put_int8(&buf, APMSG_STA_CONNECTED, !!sta->connected);
        blob_put_int32(&buf, APMSG_STA_SIGNAL, sta->signal);
        blob_put_int32(&buf, APMSG_STA_SEEN, seen);
+       blob_put_int32(&buf, APMSG_STA_LAST_CONNECTED, last_connected);
        blob_put_int32(&buf, APMSG_STA_TIMEOUT, config.local_sta_timeout - seen);
        blob_nest_end(&buf, c);
 }
@@ -537,6 +572,9 @@ static void usteer_send_node(struct usteer_node *node, struct sta_info *sta)
        blob_put_int32(&buf, APMSG_NODE_LOAD, node->load);
        blob_put_int32(&buf, APMSG_NODE_N_ASSOC, node->n_assoc);
        blob_put_int32(&buf, APMSG_NODE_MAX_ASSOC, node->max_assoc);
+       blob_put_int32(&buf, APMSG_NODE_OP_CLASS, node->op_class);
+       blob_put_int32(&buf, APMSG_NODE_CHANNEL, node->channel);
+       blob_put(&buf, APMSG_NODE_BSSID, node->bssid, sizeof(node->bssid));
        if (node->rrm_nr) {
                r = blob_nest_start(&buf, APMSG_NODE_RRM_NR);
                blobmsg_add_field(&buf, BLOBMSG_TYPE_ARRAY, "",
@@ -571,7 +609,7 @@ usteer_check_timeout(void)
        int timeout = config.remote_node_timeout;
 
        list_for_each_entry_safe(node, tmp, &remote_nodes, list) {
-               if (node->check++ > timeout)
+               if (config.local_mode || node->check++ > timeout)
                        remote_node_free(node);
        }
 }
@@ -615,17 +653,17 @@ usteer_send_update_timer(struct uloop_timeout *t)
        struct usteer_node *node;
        void *c;
 
-       if (avl_is_empty(&local_nodes) && !host_info_blob)
-               return;
-
        usteer_update_time();
        uloop_timeout_set(t, config.remote_update_interval);
 
-       c = usteer_update_init();
-       for_each_local_node(node)
-               usteer_send_node(node, NULL);
+       if (!config.local_mode &&
+           (!avl_is_empty(&local_nodes) || host_info_blob)) {
+               c = usteer_update_init();
+               for_each_local_node(node)
+                       usteer_send_node(node, NULL);
 
-       usteer_update_send(c);
+               usteer_update_send(c);
+       }
        usteer_check_timeout();
 }
 
@@ -640,8 +678,10 @@ usteer_init_local_id(void)
                return -1;
        }
 
-       if (fread(&local_id, sizeof(local_id), 1, f) < 1)
+       if (fread(&local_id, sizeof(local_id), 1, f) < 1) {
+               fclose(f);
                return -1;
+       }
 
        fclose(f);
        return 0;