diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
index 95a99b6..1ab173d 100644
--- a/mesh/mesh-io.c
+++ b/mesh/mesh-io.c
{
io = l_queue_find(io_list, match_by_io, io);
+ if (!io)
+ io = l_queue_peek_head(io_list);
+
if (io && io->api && io->api->send)
return io->api->send(io, info, data, len);
diff --git a/mesh/net-keys.c b/mesh/net-keys.c
index 5be7e0b..65f0808 100644
--- a/mesh/net-keys.c
+++ b/mesh/net-keys.c
#include <ell/ell.h>
+#include "mesh/mesh-defs.h"
+#include "mesh/util.h"
#include "mesh/crypto.h"
+#include "mesh/mesh-io.h"
+#include "mesh/net.h"
#include "mesh/net-keys.h"
#define BEACON_TYPE_SNB 0x01
#define KEY_REFRESH 0x01
#define IV_INDEX_UPDATE 0x02
+#define BEACON_INTERVAL_MIN 10
+#define BEACON_INTERVAL_MAX 600
+
+struct net_beacon {
+ struct l_timeout *timeout;
+ uint32_t ts;
+ uint16_t observe_period;
+ uint16_t observed;
+ uint16_t expected;
+ bool half_period;
+ uint8_t beacon[23];
+};
+
struct net_key {
uint32_t id;
+ struct net_beacon snb;
uint16_t ref_cnt;
+ uint16_t beacon_enables;
uint8_t friend_key;
uint8_t nid;
uint8_t master[16];
if (key && key->ref_cnt) {
if (--key->ref_cnt == 0) {
+ l_timeout_remove(key->snb.timeout);
l_queue_remove(keys, key);
l_free(key);
}
return false;
}
- snb[0] = BEACON_TYPE_SNB;
- snb[1] = 0;
+ snb[0] = MESH_AD_TYPE_BEACON;
+ snb[1] = BEACON_TYPE_SNB;
+ snb[2] = 0;
if (kr)
- snb[1] |= KEY_REFRESH;
+ snb[2] |= KEY_REFRESH;
if (ivu)
- snb[1] |= IV_INDEX_UPDATE;
+ snb[2] |= IV_INDEX_UPDATE;
- memcpy(snb + 2, key->network, 8);
- l_put_be32(iv_index, snb + 10);
- l_put_be64(cmac, snb + 14);
+ memcpy(snb + 3, key->network, 8);
+ l_put_be32(iv_index, snb + 11);
+ l_put_be64(cmac, snb + 15);
return true;
}
+
+static void send_network_beacon(struct net_key *key)
+{
+ struct mesh_io_send_info info = {
+ .type = MESH_IO_TIMING_TYPE_GENERAL,
+ .u.gen.interval = 100,
+ .u.gen.cnt = 1,
+ .u.gen.min_delay = DEFAULT_MIN_DELAY,
+ .u.gen.max_delay = DEFAULT_MAX_DELAY
+ };
+
+ mesh_io_send(NULL, &info, key->snb.beacon, sizeof(key->snb.beacon));
+}
+
+static void snb_timeout(struct l_timeout *timeout, void *user_data)
+{
+ struct net_key *key = user_data;
+ uint32_t interval, scale_factor;
+
+ /* Always send at least one beacon */
+ send_network_beacon(key);
+
+ /* Count our own beacons towards the vicinity total */
+ key->snb.observed++;
+
+ if (!key->snb.half_period) {
+
+ l_debug("beacon %d for %d nodes, period %d, obs %d, exp %d",
+ key->id,
+ key->beacon_enables,
+ key->snb.observe_period,
+ key->snb.observed,
+ key->snb.expected);
+
+
+ interval = (key->snb.observe_period * key->snb.observed)
+ / key->snb.expected;
+
+ /* Limit Increases and Decreases by 10 seconds Up and
+ * 20 seconds down each step, to avoid going nearly silent
+ * in highly populated environments.
+ */
+ if (interval - 10 > key->snb.observe_period)
+ interval = key->snb.observe_period + 10;
+ else if (interval + 20 < key->snb.observe_period)
+ interval = key->snb.observe_period - 20;
+
+ /* Beaconing must be no *slower* than once every 10 minutes,
+ * and no *faster* than once every 10 seconds, per spec.
+ * Observation period is twice beaconing period.
+ */
+ if (interval < BEACON_INTERVAL_MIN * 2)
+ interval = BEACON_INTERVAL_MIN * 2;
+ else if (interval > BEACON_INTERVAL_MAX * 2)
+ interval = BEACON_INTERVAL_MAX * 2;
+
+ key->snb.observe_period = interval;
+ key->snb.observed = 0;
+
+ /* To prevent "over slowing" of the beaconing frequency,
+ * require more significant "over observing" the slower
+ * our own beaconing frequency.
+ */
+ key->snb.expected = interval / 10;
+ scale_factor = interval / 60;
+ key->snb.expected += scale_factor * 3;
+ }
+
+ interval = key->snb.observe_period / 2;
+ key->snb.ts = get_timestamp_secs();
+ key->snb.half_period = !key->snb.half_period;
+
+ if (key->beacon_enables)
+ l_timeout_modify(timeout, interval);
+ else {
+ l_timeout_remove(timeout);
+ key->snb.timeout = NULL;
+ }
+}
+
+void net_key_beacon_seen(uint32_t id)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+
+ if (key)
+ key->snb.observed++;
+}
+
+void net_key_beacon_enable(uint32_t id)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+ bool enabled;
+ uint32_t rand_ms;
+
+ if (!key)
+ return;
+
+ enabled = !!key->beacon_enables;
+ key->beacon_enables++;
+
+ /* If already Enabled, do nothing */
+ if (enabled)
+ return;
+
+ /* Randomize first timeout to avoid bursts of beacons */
+ l_getrandom(&rand_ms, sizeof(rand_ms));
+ rand_ms %= (BEACON_INTERVAL_MIN * 1000);
+ rand_ms++;
+
+ /* Enable Periodic Beaconing on this key */
+ key->snb.ts = get_timestamp_secs();
+ key->snb.observe_period = BEACON_INTERVAL_MIN * 2;
+ key->snb.expected = 2;
+ key->snb.observed = 0;
+ key->snb.half_period = true;
+ l_timeout_remove(key->snb.timeout);
+ key->snb.timeout = l_timeout_create_ms(rand_ms, snb_timeout, key, NULL);
+}
+
+bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+ uint8_t beacon[23];
+ uint32_t rand_ms;
+
+ if (!key)
+ return false;
+
+ if (!net_key_snb_compose(id, iv_index, kr, ivu, beacon))
+ return false;
+
+ if (memcmp(key->snb.beacon, beacon, sizeof(beacon)))
+ memcpy(key->snb.beacon, beacon, sizeof(beacon));
+ else
+ return false;
+
+ l_debug("Setting SNB: IVI: %8.8x, IVU: %d, KR: %d", iv_index, ivu, kr);
+ print_packet("Set SNB Beacon to", beacon, sizeof(beacon));
+
+ /* Send one new SNB soon, after all nodes have seen it */
+ l_getrandom(&rand_ms, sizeof(rand_ms));
+ rand_ms %= 1000;
+ key->snb.expected++;
+
+ if (key->snb.timeout)
+ l_timeout_modify_ms(key->snb.timeout, 500 + rand_ms);
+ else
+ key->snb.timeout = l_timeout_create_ms(500 + rand_ms,
+ snb_timeout, key, NULL);
+
+ return true;
+}
+
+void net_key_beacon_disable(uint32_t id)
+{
+ struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id));
+
+ if (!key || !key->beacon_enables)
+ return;
+
+ key->beacon_enables--;
+
+ if (key->beacon_enables)
+ return;
+
+ /* Disable periodic Beaconing on this key */
+ l_timeout_remove(key->snb.timeout);
+ key->snb.timeout = NULL;
+}
diff --git a/mesh/net-keys.h b/mesh/net-keys.h
index d54c521..3c2c4d0 100644
--- a/mesh/net-keys.h
+++ b/mesh/net-keys.h
*
*/
+#define BEACON_TYPE_SNB 0x01
+#define KEY_REFRESH 0x01
+#define IV_INDEX_UPDATE 0x02
+
bool net_key_confirm(uint32_t id, const uint8_t master[16]);
bool net_key_retrieve(uint32_t id, uint8_t *master);
uint32_t net_key_add(const uint8_t master[16]);
uint64_t cmac);
bool net_key_snb_compose(uint32_t id, uint32_t iv_index, bool kr, bool ivu,
uint8_t *snb);
+void net_key_beacon_seen(uint32_t id);
+void net_key_beacon_enable(uint32_t id);
+bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu);
+void net_key_beacon_disable(uint32_t id);
diff --git a/mesh/net.c b/mesh/net.c
index f662d8a..e708b2a 100644
--- a/mesh/net.c
+++ b/mesh/net.c
#define SEG_TO 2
#define MSG_TO 60
-#define DEFAULT_MIN_DELAY 0
-#define DEFAULT_MAX_DELAY 25
-
#define DEFAULT_TRANSMIT_COUNT 1
#define DEFAULT_TRANSMIT_INTERVAL 100
-#define BEACON_INTERVAL_MIN 10
-#define BEACON_INTERVAL_MAX 600
-
#define SAR_KEY(src, seq0) ((((uint32_t)(seq0)) << 16) | (src))
enum _relay_advice {
uint8_t network_id[8];
};
-struct mesh_beacon {
- struct l_timeout *timeout;
- uint32_t ts;
- uint16_t observe_period;
- uint16_t observed;
- uint16_t expected;
- uint8_t half_period;
- uint8_t beacon[23];
-};
-
struct mesh_subnet {
struct mesh_net *net;
uint16_t idx;
uint32_t net_key_tx;
uint32_t net_key_cur;
uint32_t net_key_upd;
- struct mesh_beacon snb;
uint8_t key_refresh;
uint8_t kr_phase;
};
};
struct net_beacon_data {
- const uint8_t *data;
- uint16_t len;
+ uint32_t key_id;
+ uint32_t ivi;
+ bool ivu;
+ bool kr;
+ bool processed;
};
#define FAST_CACHE_SIZE 8
l_free(subnet);
}
-static void lpn_process_beacon(void *user_data, const void *data, uint8_t size,
- int8_t rssi);
-
static struct mesh_subnet *subnet_new(struct mesh_net *net, uint16_t idx)
{
struct mesh_subnet *subnet;
subnet->net = net;
subnet->idx = idx;
- subnet->snb.beacon[0] = MESH_AD_TYPE_BEACON;
return subnet;
}
-static bool create_secure_beacon(struct mesh_net *net,
- struct mesh_subnet *subnet,
- uint8_t *beacon_data)
+static void enable_beacon(void *a, void *b)
{
- bool kr = (subnet->kr_phase == KEY_REFRESH_PHASE_TWO);
+ struct mesh_subnet *subnet = a;
+ struct mesh_net *net = b;
- return net_key_snb_compose(subnet->net_key_tx, net->iv_index,
- kr, net->iv_update, beacon_data);
+ if (net->beacon_enable)
+ net_key_beacon_enable(subnet->net_key_tx);
+ else
+ net_key_beacon_disable(subnet->net_key_tx);
}
-static void send_network_beacon(struct mesh_subnet *subnet,
- struct mesh_net *net)
+static void enqueue_update(void *a, void *b);
+
+static void queue_friend_update(struct mesh_net *net)
{
- struct mesh_io_send_info info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.interval = net->tx_interval,
- .u.gen.cnt = 1,
- .u.gen.min_delay = DEFAULT_MIN_DELAY,
- .u.gen.max_delay = DEFAULT_MAX_DELAY
- };
+ struct mesh_subnet *subnet;
+ struct mesh_friend *frnd;
+ uint8_t flags = 0;
- l_info("Send SNB on network %3.3x", subnet->idx);
- mesh_io_send(net->io, &info, subnet->snb.beacon,
- sizeof(subnet->snb.beacon));
-}
+ if (l_queue_length(net->friends)) {
+ struct mesh_friend_msg update = {
+ .src = net->src_addr,
+ .iv_index = mesh_net_get_iv_index(net),
+ .last_len = 7,
+ .ctl = true,
+ };
-static void network_beacon_timeout(struct l_timeout *timeout, void *user_data)
-{
- struct mesh_subnet *subnet = user_data;
- uint32_t interval;
+ frnd = l_queue_peek_head(net->friends);
+ subnet = l_queue_find(net->subnets, match_key_index,
+ L_UINT_TO_PTR(frnd->net_idx));
- send_network_beacon(subnet, subnet->net);
+ if (!subnet)
+ return;
- if (!subnet->snb.half_period) {
- l_debug("beacon TO period %d, observed %d, expected %d",
- subnet->snb.observe_period,
- subnet->snb.observed,
- subnet->snb.expected);
- interval = subnet->snb.observe_period *
- (subnet->snb.observed + 1) / subnet->snb.expected;
- subnet->snb.observe_period = interval * 2;
- subnet->snb.expected = subnet->snb.observe_period / 10;
- subnet->snb.observed = 0;
- } else
- interval = subnet->snb.observe_period / 2;
+ if (subnet->kr_phase == KEY_REFRESH_PHASE_TWO)
+ flags |= KEY_REFRESH;
- if (interval < BEACON_INTERVAL_MIN)
- interval = BEACON_INTERVAL_MIN;
+ if (net->iv_update)
+ flags |= IV_INDEX_UPDATE;
- if (interval > BEACON_INTERVAL_MAX)
- interval = BEACON_INTERVAL_MAX;
+ update.u.one[0].hdr = NET_OP_FRND_UPDATE << OPCODE_HDR_SHIFT;
+ update.u.one[0].seq = mesh_net_next_seq_num(net);
+ update.u.one[0].data[0] = NET_OP_FRND_UPDATE;
+ update.u.one[0].data[1] = flags;
+ l_put_be32(net->iv_index, update.u.one[0].data + 2);
+ update.u.one[0].data[6] = 0x01; /* More Data */
+ /* print_packet("Frnd-Beacon-SRC",
+ * beacon_data, sizeof(beacon_data));
+ */
+ /* print_packet("Frnd-Update", update.u.one[0].data, 6); */
- subnet->snb.ts = get_timestamp_secs();
- subnet->snb.half_period ^= 1;
- l_timeout_modify(timeout, interval);
+ l_queue_foreach(net->friends, enqueue_update, &update);
+ }
}
-static void start_network_beacon(void *a, void *b)
+static void refresh_beacon(void *a, void *b)
{
struct mesh_subnet *subnet = a;
struct mesh_net *net = b;
- if (!net->beacon_enable) {
- if (subnet->snb.timeout)
- l_timeout_remove(subnet->snb.timeout);
- subnet->snb.timeout = NULL;
- return;
- }
-
- /* If timeout is active, let it run it's course */
- if (subnet->snb.timeout)
- return;
-
- send_network_beacon(subnet, subnet->net);
-
- subnet->snb.ts = get_timestamp_secs();
- subnet->snb.expected = 2;
- subnet->snb.observed = 0;
- subnet->snb.half_period = 1;
- subnet->snb.observe_period = BEACON_INTERVAL_MIN * 2;
-
- subnet->snb.timeout = l_timeout_create(BEACON_INTERVAL_MIN,
- network_beacon_timeout, subnet, NULL);
+ net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
+ !!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
}
struct mesh_net *mesh_net_new(struct mesh_node *node)
return NULL;
}
- if (!create_secure_beacon(net, subnet, subnet->snb.beacon + 1)) {
- subnet_free(subnet);
- return NULL;
- }
+ net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
+ false, net->iv_update);
+
+ if (net->beacon_enable)
+ net_key_beacon_enable(subnet->net_key_tx);
l_queue_push_tail(net->subnets, subnet);
return MESH_STATUS_STORAGE_FAIL;
}
- if (net->io)
- start_network_beacon(subnet, net);
-
return MESH_STATUS_SUCCESS;
}
return;
*iv_index = net->iv_index;
- *flags = (net->iv_upd_state == IV_UPD_UPDATING) ? 0x02 : 0x00;
+ *flags = net->iv_update ? IV_INDEX_UPDATE : 0x00;
subnet = get_primary_subnet(net);
if (subnet)
- *flags |= subnet->key_refresh ? 0x01 : 0x00;
+ *flags |= subnet->key_refresh ? KEY_REFRESH : 0x00;
}
bool mesh_net_get_key(struct mesh_net *net, bool new_key, uint16_t idx,
L_UINT_TO_PTR(src)));
break;
- case NET_OP_FRND_UPDATE:
- if (ttl)
- return false;
-
- print_packet("Rx-NET_OP_FRND_UPDATE", pkt, len);
- lpn_process_beacon(net, pkt, len, 0);
- break;
-
case NET_OP_FRND_REQUEST:
if (!net->friend_enable)
return false;
}
}
-static void set_network_beacon(void *a, void *b)
-{
- struct mesh_subnet *subnet = a;
- struct mesh_net *net = b;
- uint8_t beacon_data[22];
-
- if (!create_secure_beacon(net, subnet, beacon_data))
- return;
-
- if (memcmp(&subnet->snb.beacon[1], beacon_data,
- sizeof(beacon_data)) == 0)
- return;
-
- memcpy(&subnet->snb.beacon[1], beacon_data, sizeof(beacon_data));
-
- if (net->beacon_enable && !net->friend_addr) {
- print_packet("Set My Beacon to",
- beacon_data, sizeof(beacon_data));
- start_network_beacon(subnet, net);
- }
-
- if (l_queue_length(net->friends)) {
- struct mesh_friend_msg update = {
- .src = net->src_addr,
- .iv_index = mesh_net_get_iv_index(net),
- .last_len = 7,
- .ctl = true,
- };
-
- update.u.one[0].hdr = NET_OP_FRND_UPDATE << OPCODE_HDR_SHIFT;
- update.u.one[0].seq = mesh_net_next_seq_num(net);
- update.u.one[0].data[0] = NET_OP_FRND_UPDATE;
- update.u.one[0].data[1] = beacon_data[3];
- l_put_be32(net->iv_index, update.u.one[0].data + 2);
- update.u.one[0].data[6] = 0x01; /* More Data */
- /* print_packet("Frnd-Beacon-SRC",
- * beacon_data, sizeof(beacon_data));
- */
- /* print_packet("Frnd-Update", update.u.one[0].data, 6); */
-
- l_queue_foreach(net->friends, enqueue_update, &update);
- }
-}
-
static void iv_upd_to(struct l_timeout *upd_timeout, void *user_data)
{
struct mesh_net *net = user_data;
net->iv_update = false;
mesh_config_write_iv_index(node_config_get(net->node),
net->iv_index, false);
- l_queue_foreach(net->subnets, set_network_beacon, net);
+ l_queue_foreach(net->subnets, refresh_beacon, net);
+ queue_friend_update(net);
mesh_net_flush_msg_queues(net);
break;
* it hears beacons from all the nodes
*/
subnet->kr_phase = KEY_REFRESH_PHASE_TWO;
- set_network_beacon(subnet, net);
+ refresh_beacon(subnet, net);
+ queue_friend_update(net);
l_queue_foreach(net->friends, frnd_kr_phase2, net);
subnet->net_key_upd = 0;
subnet->key_refresh = 0;
subnet->kr_phase = KEY_REFRESH_PHASE_NONE;
- set_network_beacon(subnet, net);
+ refresh_beacon(subnet, net);
+ queue_friend_update(net);
l_queue_foreach(net->friends, frnd_kr_phase3, net);
static void process_beacon(void *net_ptr, void *user_data)
{
struct mesh_net *net = net_ptr;
- const uint8_t *buf = *(uint8_t **)user_data;
+ struct net_beacon_data *beacon_data = user_data;
uint32_t ivi;
bool ivu, kr, local_kr;
struct mesh_subnet *subnet;
- uint32_t key_id;
- ivi = l_get_be32(buf + 10);
+ ivi = beacon_data->ivi;
/* Ignore out-of-range IV_Index for this network */
if ((net->iv_index + IV_IDX_DIFF_RANGE < ivi) || (ivi < net->iv_index))
return;
- /* Ignore Network IDs unknown to this mesh universe */
- key_id = net_key_network_id(buf + 2);
- if (!key_id)
- return;
-
+ /* Ignore beacons not in this universe */
subnet = l_queue_find(net->subnets, match_key_id,
- L_UINT_TO_PTR(key_id));
+ L_UINT_TO_PTR(beacon_data->key_id));
+
if (!subnet)
return;
/* Get IVU and KR boolean bits from beacon */
- ivu = !!(buf[1] & 0x02);
- kr = !!(buf[1] & 0x01);
- local_kr = !!(subnet->kr_phase != KEY_REFRESH_PHASE_TWO);
-
- if (net->iv_upd_state != IV_UPD_INIT) {
- /* Ignore beacons that indicate *no change* */
- if (!memcmp(&subnet->snb.beacon[1], buf, 22)) {
- subnet->snb.observed++;
- return;
- }
- }
-
- /* Validate beacon before accepting */
- if (!net_key_snb_check(key_id, ivi, kr, ivu, l_get_be64(buf + 14))) {
- l_error("mesh_crypto_beacon verify failed");
- return;
- }
+ ivu = beacon_data->ivu;
+ kr = beacon_data->kr;
+ local_kr = !!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO);
/* We have officially *seen* this beacon now */
- subnet->snb.observed++;
-
- update_iv_ivu_state(net, ivi, ivu);
- update_kr_state(subnet, kr, key_id);
-
- if (ivi != net->iv_index || ivu != net->iv_update || kr != local_kr)
- set_network_beacon(subnet, net);
-}
-
-static void lpn_process_beacon(void *user_data, const void *data,
- uint8_t size, int8_t rssi)
-{
- struct mesh_net *net = user_data;
- const uint8_t *buf = data;
- uint32_t ivi;
- bool ivu, kr, local_kr;
- struct mesh_subnet *subnet;
- bool kr_transition = false;
-
- /* print_packet("lpn: Secure Net Beacon RXed", data, size); */
- kr = !!(buf[0] & 0x01);
- ivu = !!(buf[0] & 0x02);
- ivi = l_get_be32(buf + 1);
-
- l_debug("KR: %d -- IVU: %d -- IVI: %8.8x", kr, ivu, ivi);
-
- /* TODO: figure out actual network index (i.e., friendship subnet) */
- subnet = get_primary_subnet(net);
- if (!subnet)
- return;
-
- local_kr = (subnet->kr_phase == KEY_REFRESH_PHASE_TWO);
+ beacon_data->processed = true;
- /* Don't bother going further if nothing has changed */
- if (local_kr == kr && ivi == net->iv_index && ivu == net->iv_update &&
- net->iv_upd_state != IV_UPD_INIT)
+ if (ivi == net->iv_index && ivu == net->iv_update && kr == local_kr)
return;
update_iv_ivu_state(net, ivi, ivu);
-
- if (kr)
- update_kr_state(subnet, kr_transition, subnet->net_key_upd);
- else
- update_kr_state(subnet, kr_transition, subnet->net_key_cur);
+ update_kr_state(subnet, kr, beacon_data->key_id);
+ net_key_beacon_refresh(beacon_data->key_id, net->iv_index,
+ !!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
}
static void beacon_recv(void *user_data, struct mesh_io_recv_info *info,
const uint8_t *data, uint16_t len)
{
- const uint8_t *ptr = data + 1;
+ struct net_beacon_data beacon_data = {
+ .processed = false,
+ };
if (len != 23 || data[1] != 0x01)
return;
- l_debug("KR: %d -- IVU: %d -- IV: %8.8x",
- data[2] & 1, !!(data[2] & 2), l_get_be32(data + 11));
+ /* Ignore Network IDs unknown to this daemon */
+ beacon_data.key_id = net_key_network_id(data + 3);
+ if (!beacon_data.key_id)
+ return;
+
+ /* Get data bits from beacon */
+ beacon_data.ivu = !!(data[2] & 0x02);
+ beacon_data.kr = !!(data[2] & 0x01);
+ beacon_data.ivi = l_get_be32(data + 11);
- l_queue_foreach(nets, process_beacon, &ptr);
+ /* Validate beacon before accepting */
+ if (!net_key_snb_check(beacon_data.key_id, beacon_data.ivi,
+ beacon_data.kr, beacon_data.ivu,
+ l_get_be64(data + 15))) {
+ l_error("mesh_crypto_beacon verify failed");
+ return;
+ }
+
+ l_queue_foreach(nets, process_beacon, &beacon_data);
+
+ if (beacon_data.processed)
+ net_key_beacon_seen(beacon_data.key_id);
}
bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable)
if (!net || !IS_UNASSIGNED(net->friend_addr))
return false;
- if (net->beacon_enable != enable) {
- uint8_t type = MESH_AD_TYPE_BEACON;
+ if (net->beacon_enable == enable)
+ return true;
- net->beacon_enable = enable;
+ net->beacon_enable = enable;
- if (!enable)
- mesh_io_send_cancel(net->io, &type, 1);
+ if (enable)
+ l_queue_foreach(net->subnets, refresh_beacon, net);
- l_queue_foreach(net->subnets, start_network_beacon, net);
- }
+ l_queue_foreach(net->subnets, enable_beacon, net);
+ queue_friend_update(net);
return true;
}
if (phase == KEY_REFRESH_PHASE_TWO) {
subnet->key_refresh = 1;
subnet->net_key_tx = subnet->net_key_upd;
+ if (net->beacon_enable) {
+ /* Switch beaconing key */
+ net_key_beacon_disable(subnet->net_key_cur);
+ net_key_beacon_enable(subnet->net_key_upd);
+ }
}
subnet->kr_phase = phase;
- set_network_beacon(subnet, net);
+ net_key_beacon_refresh(subnet->net_key_tx, net->iv_index,
+ !!(subnet->kr_phase == KEY_REFRESH_PHASE_TWO), net->iv_update);
- if (net->io)
- start_network_beacon(subnet, net);
return true;
}
beacon_recv, NULL);
mesh_io_register_recv_cb(io, MESH_IO_FILTER_NET,
net_msg_recv, NULL);
- l_queue_foreach(net->subnets, start_network_beacon, net);
}
if (l_queue_find(nets, is_this_net, net))
net->iv_upd_state = IV_UPD_UPDATING;
net->iv_index++;
net->iv_update = true;
- l_queue_foreach(net->subnets, set_network_beacon, net);
+ l_queue_foreach(net->subnets, refresh_beacon, net);
+ queue_friend_update(net);
net->iv_update_timeout = l_timeout_create(
IV_IDX_UPD_MIN,
iv_upd_to, net, NULL);
net->friend_addr = friend_addr;
- set_network_beacon(get_primary_subnet(net), net);
return true;
}
diff --git a/mesh/net.h b/mesh/net.h
index fe4e0b6..90ca832 100644
--- a/mesh/net.h
+++ b/mesh/net.h
#define FRND_OPCODE(x) \
((x) >= NET_OP_FRND_POLL && (x) <= NET_OP_FRND_CLEAR_CONFIRM)
+#define DEFAULT_MIN_DELAY 0
+#define DEFAULT_MAX_DELAY 25
+
struct mesh_net_addr_range {
uint16_t low;
uint16_t high;