diff --git a/mesh/crypto.c b/mesh/crypto.c
index 15ee673..8ea906a 100644
--- a/mesh/crypto.c
+++ b/mesh/crypto.c
uint16_t this_dst;
bool is_segmented;
- if (packet_len < 14)
+ if (packet_len < 10)
return false;
this_dst = l_get_be16(packet + 7);
uint8_t this_opcode = packet[9] & OPCODE_MASK;
if (cookie)
- *cookie = l_get_be32(packet + 9);
+ *cookie = l_get_be32(packet + 2) ^ packet[6];
if (opcode)
*opcode = this_opcode;
diff --git a/mesh/friend.c b/mesh/friend.c
index da27728..5f5f6f8 100644
--- a/mesh/friend.c
+++ b/mesh/friend.c
/* Absolute maximum time to wait for LPN to choose us. */
#define RESPONSE_POLL_DELAY 1300 /* 1.300 s */
-
static uint8_t frnd_relay_window = FRND_RELAY_WINDOW;
static uint8_t frnd_cache_size = FRND_CACHE_SIZE;
static uint8_t frnd_sublist_size = FRND_SUB_LIST_SIZE;
-
-struct frnd_negotiation {
- struct l_timeout *timeout;
- struct mesh_net *net;
- uint32_t key_id;
- uint32_t poll_timeout;
- uint16_t low_power_node;
- uint16_t old_relay;
- uint8_t num_ele;
- uint8_t lp_cnt;
- uint8_t fn_cnt;
- uint8_t wrfrw;
- uint8_t receive_delay;
- int8_t rssi;
- bool clearing;
-};
-
-static struct l_queue *frnd_negotiations;
static uint16_t counter;
+static struct l_queue *retired_lpns;
static void response_timeout(struct l_timeout *timeout, void *user_data)
{
- struct frnd_negotiation *neg = user_data;
+ struct mesh_friend *neg = user_data;
+ struct l_queue *negotiations = mesh_net_get_negotiations(neg->net);
/* LPN did not choose us */
- l_debug("Did not win negotiation for %4.4x", neg->low_power_node);
+ l_debug("Did not win negotiation for %4.4x", neg->lp_addr);
- net_key_unref(neg->key_id);
- l_queue_remove(frnd_negotiations, neg);
+ net_key_unref(neg->net_key_cur);
+ net_key_unref(neg->net_key_upd);
+ l_queue_remove(negotiations, neg);
l_timeout_remove(timeout);
l_free(neg);
}
static void response_delay(struct l_timeout *timeout, void *user_data)
{
- struct frnd_negotiation *neg = user_data;
- uint16_t net_idx = mesh_net_get_primary_idx(neg->net);
- uint32_t key_id;
+ struct mesh_friend *neg = user_data;
+ uint16_t net_idx = neg->net_idx;
+ uint32_t key_id, seq;
uint8_t msg[8];
uint16_t n = 0;
bool res;
if (!res)
goto cleanup;
- neg->key_id = net_key_frnd_add(key_id, neg->low_power_node,
+ neg->net_key_cur = net_key_frnd_add(key_id, neg->lp_addr,
mesh_net_get_address(neg->net),
neg->lp_cnt, counter);
- if (!neg->key_id)
+ if (!neg->net_key_cur)
goto cleanup;
neg->fn_cnt = counter++;
msg[n++] = frnd_relay_window;
msg[n++] = frnd_cache_size;
msg[n++] = frnd_sublist_size;
- msg[n++] = neg->rssi;
+ msg[n++] = neg->u.negotiate.rssi;
l_put_be16(neg->fn_cnt, msg + n);
n += 2;
+ seq = mesh_net_next_seq_num(neg->net);
print_packet("Tx-NET_OP_FRND_OFFER", msg, n);
- mesh_net_transport_send(neg->net, 0, true,
+ mesh_net_transport_send(neg->net, key_id, true,
mesh_net_get_iv_index(neg->net), 0,
- 0, 0, neg->low_power_node,
+ seq, 0, neg->lp_addr,
msg, n);
/* Offer expires in 1.3 seconds, which is the max time for LPN to
return;
cleanup:
- net_key_unref(neg->key_id);
- l_queue_remove(frnd_negotiations, neg);
+ net_key_unref(neg->net_key_cur);
+ net_key_unref(neg->net_key_upd);
+ l_queue_remove(mesh_net_get_negotiations(neg->net), neg);
l_free(neg);
}
static bool match_by_lpn(const void *a, const void *b)
{
- const struct frnd_negotiation *neg = a;
+ const struct mesh_friend *neg = a;
uint16_t lpn = L_PTR_TO_UINT(b);
- return neg->low_power_node == lpn;
-}
-
-static bool match_by_dst(const void *a, const void *b)
-{
- const struct mesh_friend *frnd = a;
- uint16_t dst = L_PTR_TO_UINT(b);
-
- return frnd->dst == dst;
+ return neg->lp_addr == lpn;
}
/* Scaling factors in 1/10 ms */
15,
};
-void friend_request(struct mesh_net *net, uint16_t src,
+void friend_request(struct mesh_net *net, uint16_t net_idx, uint16_t src,
uint8_t minReq, uint8_t delay, uint32_t timeout,
uint16_t prev, uint8_t num_ele, uint16_t cntr,
int8_t rssi)
{
- struct frnd_negotiation *neg;
+ struct l_queue *negotiations = mesh_net_get_negotiations(net);
+ struct mesh_friend *neg;
uint8_t rssiScale = (minReq >> 5) & 3;
uint8_t winScale = (minReq >> 3) & 3;
uint8_t minCache = (minReq >> 0) & 7;
if (cache_size(minCache) > frnd_cache_size)
return;
- if (frnd_negotiations == NULL)
- frnd_negotiations = l_queue_new();
-
/* TODO: Check RSSI, and then start Negotiation if appropriate */
/* We are participating in this Negotiation */
- neg = l_new(struct frnd_negotiation, 1);
- l_queue_push_head(frnd_negotiations, neg);
+ neg = l_new(struct mesh_friend, 1);
+ l_queue_push_head(negotiations, neg);
neg->net = net;
- neg->low_power_node = src;
+ neg->lp_addr = src;
neg->lp_cnt = cntr;
- neg->rssi = rssi;
+ neg->u.negotiate.rssi = rssi;
neg->receive_delay = delay;
neg->poll_timeout = timeout;
- neg->old_relay = prev;
- neg->num_ele = num_ele;
+ neg->old_friend = prev;
+ neg->ele_cnt = num_ele;
+ neg->net_idx = net_idx;
/* RSSI (Negative Factor, larger values == less time)
* Scaling factor 0-3 == multiplier of 1.0 - 2.5
response_delay, neg, NULL);
}
-static struct l_queue *retired_lpns;
-
void friend_clear_confirm(struct mesh_net *net, uint16_t src,
uint16_t lpn, uint16_t lpnCounter)
{
- struct frnd_negotiation *neg = l_queue_remove_if(frnd_negotiations,
+ struct l_queue *negotiations = mesh_net_get_negotiations(net);
+ struct mesh_friend *neg = l_queue_remove_if(negotiations,
match_by_lpn, L_UINT_TO_PTR(lpn));
l_debug("Friend Clear confirmed %4.4x (cnt %4.4x)", lpn, lpnCounter);
return;
l_timeout_remove(neg->timeout);
- l_queue_remove(frnd_negotiations, neg);
+ l_queue_remove(negotiations, neg);
l_free(neg);
}
struct mesh_friend *frnd = user_data;
if (mesh_friend_clear(frnd->net, frnd))
- l_debug("Friend Poll Timeout %4.4x", frnd->dst);
+ l_debug("Friend Poll Timeout %4.4x", frnd->lp_addr);
l_timeout_remove(frnd->timeout);
frnd->timeout = NULL;
void friend_clear(struct mesh_net *net, uint16_t src, uint16_t lpn,
uint16_t lpnCounter, struct mesh_friend *frnd)
{
+ struct l_queue *negotiations = mesh_net_get_negotiations(net);
uint8_t msg[5] = { NET_OP_FRND_CLEAR_CONFIRM };
bool removed = false;
uint16_t lpnDelta;
/* Move friend from Network list to Retired list */
removed = mesh_friend_clear(net, frnd);
if (removed) {
- struct mesh_friend *old;
- struct frnd_negotiation *neg = l_queue_remove_if(
- frnd_negotiations,
- match_by_lpn,
- L_UINT_TO_PTR(frnd->dst));
+ struct mesh_friend *neg, *old;
+
+ neg = l_queue_remove_if(negotiations, match_by_lpn,
+ L_UINT_TO_PTR(lpn));
/* Cancel any negotiations or clears */
if (neg) {
l_free(neg);
}
- /* Create Retired LPN list if needed */
- if (retired_lpns == NULL)
- retired_lpns = l_queue_new();
-
/* Find any duplicates */
- old = l_queue_find(retired_lpns, match_by_dst,
- L_UINT_TO_PTR(lpn));
+ old = l_queue_find(retired_lpns, match_by_lpn,
+ L_UINT_TO_PTR(lpn));
/* Force time-out of old friendship */
if (old)
friend_poll_timeout(old->timeout, old);
+ if (!retired_lpns)
+ retired_lpns = l_queue_new();
+
/* Retire this LPN (keeps timeout running) */
l_queue_push_tail(retired_lpns, frnd);
}
} else {
- frnd = l_queue_find(retired_lpns, match_by_dst,
- L_UINT_TO_PTR(lpn));
+ frnd = l_queue_find(retired_lpns, match_by_lpn,
+ L_UINT_TO_PTR(lpn));
if (!frnd)
return;
static void clear_retry(struct l_timeout *timeout, void *user_data)
{
- struct frnd_negotiation *neg = user_data;
+ struct mesh_friend *neg = user_data;
+ struct l_queue *negotiations = mesh_net_get_negotiations(neg->net);
uint8_t msg[5] = { NET_OP_FRND_CLEAR };
uint32_t secs = 1 << neg->receive_delay;
- l_put_be16(neg->low_power_node, msg + 1);
+ l_put_be16(neg->lp_addr, msg + 1);
l_put_be16(neg->lp_cnt, msg + 3);
mesh_net_transport_send(neg->net, 0, false,
mesh_net_get_iv_index(neg->net), DEFAULT_TTL,
- 0, 0, neg->old_relay,
+ 0, 0, neg->old_friend,
msg, sizeof(msg));
if (secs && ((secs << 1) < neg->poll_timeout/10)) {
} else {
l_debug("FRND_CLR timed out %d", secs);
l_timeout_remove(timeout);
- l_queue_remove(frnd_negotiations, neg);
+ l_queue_remove(negotiations, neg);
l_free(neg);
}
}
net_seq = mesh_net_get_seq_num(net);
l_debug("Fwd FRND UPDATE %6.6x with MD == 0", net_seq);
- frnd->last = frnd->seq;
+ frnd->u.active.last = frnd->u.active.seq;
mesh_net_get_snb_state(net, upd + 1, &iv_index);
l_put_be32(iv_index, upd + 2);
upd[6] = false; /* Queue is Empty */
print_packet("Update", upd, sizeof(upd));
mesh_net_transport_send(net, frnd->net_key_cur, false,
mesh_net_get_iv_index(net), 0,
- net_seq, 0, frnd->dst,
+ net_seq, 0, frnd->lp_addr,
upd, sizeof(upd));
mesh_net_next_seq_num(net);
}
void friend_poll(struct mesh_net *net, uint16_t src, bool seq,
struct mesh_friend *frnd)
{
- struct frnd_negotiation *neg;
+ struct l_queue *negotiations = mesh_net_get_negotiations(net);
+ struct mesh_friend *neg;
struct mesh_friend_msg *pkt;
bool md;
- neg = l_queue_find(frnd_negotiations, match_by_lpn, L_UINT_TO_PTR(src));
- if (neg && !neg->clearing) {
+ l_debug("POLL-RXED");
+ neg = l_queue_find(negotiations, match_by_lpn, L_UINT_TO_PTR(src));
+
+ if (neg && !neg->u.negotiate.clearing) {
uint8_t msg[5] = { NET_OP_FRND_CLEAR };
- l_debug("Won negotiation for %4.4x", neg->low_power_node);
+ l_debug("Won negotiation for %4.4x", neg->lp_addr);
/* This call will clean-up and replace if already friends */
- frnd = mesh_friend_new(net, src, neg->num_ele,
+ frnd = mesh_friend_new(net, src, neg->ele_cnt,
neg->receive_delay,
- neg->wrfrw,
+ neg->frw,
neg->poll_timeout,
neg->fn_cnt, neg->lp_cnt);
friend_poll_timeout, frnd, NULL);
l_timeout_remove(neg->timeout);
- net_key_unref(neg->key_id);
- neg->key_id = 0;
+ net_key_unref(neg->net_key_cur);
+ net_key_unref(neg->net_key_upd);
+ neg->net_key_upd = neg->net_key_cur = 0;
- if (neg->old_relay == 0 ||
- neg->old_relay == mesh_net_get_address(net)) {
- l_queue_remove(frnd_negotiations, neg);
+ if (neg->old_friend == 0 ||
+ neg->old_friend == mesh_net_get_address(net)) {
+ l_queue_remove(negotiations, neg);
l_free(neg);
} else {
- neg->clearing = true;
- l_put_be16(neg->low_power_node, msg + 1);
+ neg->u.negotiate.clearing = true;
+ l_put_be16(neg->lp_addr, msg + 1);
l_put_be16(neg->lp_cnt, msg + 3);
mesh_net_transport_send(net, 0, false,
mesh_net_get_iv_index(net), DEFAULT_TTL,
- 0, 0, neg->old_relay,
+ 0, 0, neg->old_friend,
msg, sizeof(msg));
/* Reuse receive_delay as a shift counter to
if (!l_queue_length(frnd->pkt_cache))
goto update;
- if (frnd->seq != frnd->last && frnd->seq != seq) {
+ if (frnd->u.active.seq != frnd->u.active.last &&
+ frnd->u.active.seq != seq) {
pkt = l_queue_peek_head(frnd->pkt_cache);
if (pkt->cnt_out < pkt->cnt_in) {
pkt->cnt_out++;
if (!pkt)
goto update;
- frnd->seq = seq;
- frnd->last = !seq;
+ frnd->u.active.seq = seq;
+ frnd->u.active.last = !seq;
md = !!(l_queue_length(frnd->pkt_cache) > 1);
if (pkt->ctl) {
uint8_t plen = len;
uint8_t msg[] = { NET_OP_PROXY_SUB_CONFIRM, 0 };
- if (!frnd || MAX_FRND_GROUPS < frnd->grp_cnt + (len/2))
+ if (!frnd || MAX_FRND_GROUPS < frnd->u.active.grp_cnt + (len/2))
return;
msg[1] = *pkt++;
return;
}
- new_list = l_malloc(frnd->grp_cnt * sizeof(uint16_t) + len);
- if (frnd->grp_list)
- memcpy(new_list, frnd->grp_list,
- frnd->grp_cnt * sizeof(uint16_t));
+ new_list = l_malloc(frnd->u.active.grp_cnt * sizeof(uint16_t) + len);
+ if (frnd->u.active.grp_list)
+ memcpy(new_list, frnd->u.active.grp_list,
+ frnd->u.active.grp_cnt * sizeof(uint16_t));
while (len >= 2) {
- new_list[frnd->grp_cnt++] = l_get_be16(pkt);
+ new_list[frnd->u.active.grp_cnt++] = l_get_be16(pkt);
pkt += 2;
len -= 2;
}
- l_free(frnd->grp_list);
- frnd->grp_list = new_list;
+ l_free(frnd->u.active.grp_list);
+ frnd->u.active.grp_list = new_list;
print_packet("Tx-NET_OP_PROXY_SUB_CONFIRM", msg, sizeof(msg));
net_seq = mesh_net_get_seq_num(net);
mesh_net_transport_send(net, frnd->net_key_cur, false,
mesh_net_get_iv_index(net), 0,
- net_seq, 0, frnd->dst,
+ net_seq, 0, frnd->lp_addr,
msg, sizeof(msg));
mesh_net_next_seq_num(net);
}
while (len >= 2) {
uint16_t grp = l_get_be16(pkt);
- for (i = frnd->grp_cnt - 1; i >= 0; i--) {
- if (frnd->grp_list[i] == grp) {
- frnd->grp_cnt--;
- memcpy(&frnd->grp_list[i],
- &frnd->grp_list[i + 1],
- (frnd->grp_cnt - i) * 2);
+ for (i = frnd->u.active.grp_cnt - 1; i >= 0; i--) {
+ if (frnd->u.active.grp_list[i] == grp) {
+ frnd->u.active.grp_cnt--;
+ memcpy(&frnd->u.active.grp_list[i],
+ &frnd->u.active.grp_list[i + 1],
+ (frnd->u.active.grp_cnt - i) * 2);
break;
}
}
net_seq = mesh_net_get_seq_num(net);
mesh_net_transport_send(net, frnd->net_key_cur, false,
mesh_net_get_iv_index(net), 0,
- net_seq, 0, frnd->dst,
+ net_seq, 0, frnd->lp_addr,
msg, sizeof(msg));
mesh_net_next_seq_num(net);
}
-
-/* Low-Power-Node role */
-struct frnd_offers {
- uint16_t fn_cnt;
- uint16_t src;
- uint8_t window;
- uint8_t cache;
- uint8_t sub_list_size;
- int8_t local_rssi;
- int8_t remote_rssi;
-};
-
-#define MAX_POLL_RETRIES 5
-static bool quick_pick;
-static uint8_t poll_cnt;
-static struct l_queue *offers;
-static uint16_t old_friend;
-static uint16_t fn_cnt, cnt = 0xffff;
-static uint32_t poll_period_ms;
-static struct l_timeout *poll_retry_to;
-static struct l_timeout *poll_period_to;
-static uint32_t lpn_key_id;
-static uint32_t new_lpn_id;
-
-void frnd_offer(struct mesh_net *net, uint16_t src, uint8_t window,
- uint8_t cache, uint8_t sub_list_size,
- int8_t r_rssi, int8_t l_rssi, uint16_t fn_cnt)
-{
- struct frnd_offers *offer;
-
- l_debug("RSSI of Offer: %d dbm", l_rssi);
-
- /* Ignore RFU window value 0 */
- if (window == 0)
- return;
-
- if (mesh_net_get_friend(net))
- return;
-
- if (quick_pick) {
- if (mesh_net_set_friend(net, src)) {
- old_friend = src;
- frnd_poll(net, false);
- }
- return;
- }
-
- offer = l_new(struct frnd_offers, 1);
- offer->src = src;
- offer->window = window;
- offer->cache = cache;
- offer->sub_list_size = sub_list_size;
- offer->local_rssi = l_rssi;
- offer->remote_rssi = r_rssi;
- offer->fn_cnt = fn_cnt;
-
- l_queue_push_tail(offers, offer);
-}
-
-static void frnd_poll_timeout(struct l_timeout *timeout, void *user_data)
-{
- struct mesh_net *net = user_data;
-
- frnd_poll(net, true);
-}
-
-static void frnd_negotiated_to(struct l_timeout *timeout, void *user_data)
-{
- struct mesh_net *net = user_data;
-
- l_debug("frnd_negotiated_to");
- if (!mesh_net_get_friend(net)) {
- l_timeout_remove(poll_period_to);
- poll_period_to = NULL;
- return;
- }
-
- if (!poll_retry_to)
- frnd_poll(net, false);
-}
-
-void frnd_poll_cancel(struct mesh_net *net)
-{
- l_timeout_remove(poll_retry_to);
- poll_retry_to = NULL;
-}
-
-void frnd_poll(struct mesh_net *net, bool retry)
-{
- uint32_t key_id = lpn_key_id;
- uint32_t net_seq;
- uint8_t msg[2] = { NET_OP_FRND_POLL };
- bool seq = mesh_net_get_frnd_seq(net);
-
- /* Check if we are in Phase 2 of Key Refresh */
- if (new_lpn_id) {
- uint8_t phase;
- uint16_t net_idx = mesh_net_get_primary_idx(net);
- uint8_t status =
- mesh_net_key_refresh_phase_get(net, net_idx, &phase);
-
- if (status == MESH_STATUS_SUCCESS &&
- phase == KEY_REFRESH_PHASE_TWO)
- key_id = new_lpn_id;
- }
-
- if (!retry) {
- poll_cnt = MAX_POLL_RETRIES;
- seq = !seq;
- mesh_net_set_frnd_seq(net, seq);
- } else if (!(poll_cnt--)) {
- l_debug("Lost Friendship with %4.4x", old_friend);
- l_timeout_remove(poll_period_to);
- poll_period_to = NULL;
- frnd_poll_cancel(net);
- net_key_unref(lpn_key_id);
- net_key_unref(new_lpn_id);
- new_lpn_id = lpn_key_id = 0;
- mesh_net_set_friend(net, 0);
- return;
- }
-
- if (poll_retry_to)
- l_timeout_remove(poll_retry_to);
-
- l_debug("TX-FRIEND POLL %d", seq);
- msg[1] = seq;
- net_seq = mesh_net_get_seq_num(net);
- mesh_net_transport_send(net, key_id, true,
- mesh_net_get_iv_index(net), 0,
- net_seq, 0, mesh_net_get_friend(net),
- msg, sizeof(msg));
- mesh_net_next_seq_num(net);
- poll_retry_to = l_timeout_create_ms(1000, frnd_poll_timeout, net, NULL);
-
- /* Reset Poll Period for next "Wake Up" */
- if (poll_period_to)
- l_timeout_modify_ms(poll_period_to, poll_period_ms);
- else
- poll_period_to = l_timeout_create_ms(poll_period_ms,
- frnd_negotiated_to, net, NULL);
-}
-
-void frnd_ack_poll(struct mesh_net *net)
-{
- /* Start new POLL, but only if not already Polling */
- if (poll_retry_to == NULL)
- frnd_poll(net, false);
-}
-
-static void req_timeout(struct l_timeout *timeout, void *user_data)
-{
- struct mesh_net *net = user_data;
- struct frnd_offers *best;
- struct frnd_offers *offer = l_queue_pop_head(offers);
- uint32_t key_id = 0;
- bool res;
-
- l_timeout_remove(timeout);
-
- best = offer;
- while (offer) {
- /* Screen out clearly inferior RSSI friends first */
- if (offer->local_rssi < -40 && offer->remote_rssi < -40) {
- if (best->local_rssi + 20 < offer->local_rssi ||
- best->remote_rssi + 20 < offer->remote_rssi) {
-
- l_free(best);
- best = offer;
- offer = l_queue_pop_head(offers);
- continue;
- }
- }
-
- /* Otherwise use best Windows, with Cache size as tie breaker */
- if (best->window > offer->window ||
- (best->window == offer->window &&
- best->cache < offer->cache)) {
- l_free(best);
- best = offer;
- } else if (best != offer)
- l_free(offer);
-
- offer = l_queue_pop_head(offers);
- }
-
- net_key_unref(lpn_key_id);
- net_key_unref(new_lpn_id);
- new_lpn_id = lpn_key_id = 0;
- if (mesh_net_get_friend(net)) {
- l_free(best);
- return;
- } else if (!best) {
- l_debug("No Offers Received");
- return;
- }
-
- fn_cnt = best->fn_cnt;
- res = mesh_net_get_key(net, false, mesh_net_get_primary_idx(net),
- &key_id);
- if (!res)
- return;
-
- lpn_key_id = net_key_frnd_add(key_id, mesh_net_get_address(net),
- best->src, cnt, best->fn_cnt);
- if (!lpn_key_id)
- return;
-
- res = mesh_net_get_key(net, true, mesh_net_get_primary_idx(net),
- &key_id);
-
- if (!res)
- goto old_keys_only;
-
- new_lpn_id = net_key_frnd_add(key_id, mesh_net_get_address(net),
- best->src, cnt, best->fn_cnt);
-
-old_keys_only:
-
- l_debug("Winning offer %4.4x RSSI: %ddb Window: %dms Cache sz: %d",
- best->src, best->local_rssi,
- best->window, best->cache);
-
- if (mesh_net_set_friend(net, best->src)) {
- old_friend = best->src;
- mesh_net_set_frnd_seq(net, true);
- frnd_poll(net, false);
- }
-
- l_free(best);
-}
-
-void frnd_clear(struct mesh_net *net)
-{
- uint8_t msg[12];
- uint8_t n = 0;
- uint16_t frnd_addr = mesh_net_get_friend(net);
- uint16_t my_addr = mesh_net_get_address(net);
-
- msg[n++] = NET_OP_FRND_CLEAR;
- l_put_be16(my_addr, msg + n);
- n += 2;
- l_put_be16(cnt, msg + n);
- n += 2;
-
- net_key_unref(lpn_key_id);
- net_key_unref(new_lpn_id);
- mesh_net_set_friend(net, 0);
-
- mesh_net_transport_send(net, 0, false,
- mesh_net_get_iv_index(net), 0,
- 0, 0, frnd_addr,
- msg, n);
-}
-
-void frnd_request_friend(struct mesh_net *net, uint8_t cache,
- uint8_t offer_delay, uint8_t delay, uint32_t timeout)
-{
- uint8_t msg[12];
- uint8_t n = 0;
-
- if (offers == NULL)
- offers = l_queue_new();
-
- msg[n++] = NET_OP_FRND_REQUEST;
- msg[n] = cache & 0x07; /* MinRequirements - Cache */
- msg[n++] |= (offer_delay & 0x0f) << 3; /* Offer Delay */
- poll_period_ms = (timeout * 300) / 4; /* 3/4 of the time in ms */
- l_put_be32(timeout, msg + n); /* PollTimeout */
- msg[n++] = delay; /* ReceiveDelay */
- n += 3;
- l_put_be16(old_friend, msg + n); /* PreviousAddress */
- n += 2;
- msg[n++] = mesh_net_get_num_ele(net); /* NumElements */
- l_put_be16(cnt + 1, msg + n); /* Next counter */
- n += 2;
- print_packet("Tx-NET_OP_FRND_REQUEST", msg, n);
- mesh_net_transport_send(net, 0, false,
- mesh_net_get_iv_index(net), 0,
- 0, 0, FRIENDS_ADDRESS,
- msg, n);
- l_timeout_create_ms(1000, req_timeout, net, NULL); /* 1000 ms */
- mesh_net_set_friend(net, 0);
- cnt++;
-}
-
-static uint8_t trans_id;
-void frnd_sub_add(struct mesh_net *net, uint32_t parms[7])
-{
- uint32_t key_id = lpn_key_id;
- uint32_t net_seq;
- uint8_t msg[15] = { NET_OP_PROXY_SUB_ADD };
- uint8_t i, n = 1;
-
- /* Check if we are in Phase 2 of Key Refresh */
- if (new_lpn_id) {
- uint8_t phase;
- uint16_t net_idx = mesh_net_get_primary_idx(net);
- uint8_t status = mesh_net_key_refresh_phase_get(net,
- net_idx, &phase);
-
- if (status == MESH_STATUS_SUCCESS &&
- phase == KEY_REFRESH_PHASE_TWO)
- key_id = new_lpn_id;
- }
-
- msg[n++] = ++trans_id;
- for (i = 0; i < 7; i++) {
- if (parms[i] < 0x8000 || parms[i] > 0xffff)
- break;
-
- l_put_be16(parms[i], msg + n);
- n += 2;
- }
-
- net_seq = mesh_net_get_seq_num(net);
- print_packet("Friend Sub Add", msg, n);
- mesh_net_transport_send(net, key_id, false,
- mesh_net_get_iv_index(net), 0,
- net_seq, 0, mesh_net_get_friend(net),
- msg, n);
- mesh_net_next_seq_num(net);
-}
-
-void frnd_sub_del(struct mesh_net *net, uint32_t parms[7])
-{
- uint32_t key_id = lpn_key_id;
- uint32_t net_seq;
- uint8_t msg[15] = { NET_OP_PROXY_SUB_REMOVE };
- uint8_t i, n = 1;
-
- /* Check if we are in Phase 2 of Key Refresh */
- if (new_lpn_id) {
- uint8_t phase;
- uint16_t net_idx = mesh_net_get_primary_idx(net);
- uint8_t status = mesh_net_key_refresh_phase_get(net,
- net_idx, &phase);
-
- if (status == MESH_STATUS_SUCCESS &&
- phase == KEY_REFRESH_PHASE_TWO)
- key_id = new_lpn_id;
- }
-
- msg[n++] = ++trans_id;
- for (i = 0; i < 7; i++) {
- if (parms[i] < 0x8000 || parms[i] > 0xffff)
- break;
-
- l_put_be16(parms[i], msg + n);
- n += 2;
- }
-
- net_seq = mesh_net_get_seq_num(net);
- print_packet("Friend Sub Del", msg, n);
- mesh_net_transport_send(net, key_id, false,
- mesh_net_get_iv_index(net), 0,
- net_seq, 0, mesh_net_get_friend(net),
- msg, n);
- mesh_net_next_seq_num(net);
-}
-
-void frnd_key_refresh(struct mesh_net *net, uint8_t phase)
-{
- uint16_t net_idx = mesh_net_get_primary_idx(net);
- uint32_t key_id;
-
- switch (phase) {
- default:
- case 0:
- case 3:
- if (new_lpn_id) {
- l_debug("LPN Retiring KeySet %d", lpn_key_id);
- net_key_unref(lpn_key_id);
- lpn_key_id = new_lpn_id;
- }
- return;
-
- case 1:
- net_key_unref(new_lpn_id);
- if (!mesh_net_get_key(net, true, net_idx, &key_id)) {
- new_lpn_id = 0;
- return;
- }
-
- new_lpn_id = net_key_frnd_add(key_id, mesh_net_get_address(net),
- mesh_net_get_friend(net),
- cnt, fn_cnt);
- return;
-
- case 2:
- /* Should we do anything here? Maybe not */
- return;
- }
-}
-
-uint32_t frnd_get_key(struct mesh_net *net)
-{
- uint8_t idx = mesh_net_get_primary_idx(net);
- uint8_t phase = 0;
-
- mesh_net_key_refresh_phase_get(net, idx, &phase);
-
- if (phase == 2)
- return new_lpn_id;
- else
- return lpn_key_id;
-}
diff --git a/mesh/friend.h b/mesh/friend.h
index 7ab5dea..2351dee 100644
--- a/mesh/friend.h
+++ b/mesh/friend.h
void friend_poll(struct mesh_net *net, uint16_t src, bool seq,
struct mesh_friend *frnd);
-void friend_request(struct mesh_net *net, uint16_t src, uint8_t minReq,
- uint8_t delay, uint32_t timeout, uint16_t prev,
- uint8_t num_elements, uint16_t cntr, int8_t rssi);
+void friend_request(struct mesh_net *net, uint16_t net_idx, uint16_t src,
+ uint8_t minReq, uint8_t delay, uint32_t timeout,
+ uint16_t prev, uint8_t num_elements, uint16_t cntr,
+ int8_t rssi);
void friend_clear_confirm(struct mesh_net *net, uint16_t src, uint16_t lpn,
uint16_t lpnCounter);
void friend_clear(struct mesh_net *net, uint16_t src, uint16_t lpn,
diff --git a/mesh/net.c b/mesh/net.c
index 0283a78..439316e 100644
--- a/mesh/net.c
+++ b/mesh/net.c
struct l_queue *sar_out;
struct l_queue *frnd_msgs;
struct l_queue *friends;
+ struct l_queue *negotiations;
struct l_queue *destinations;
uint8_t prov_priv_key[32];
(key_id == subnet->net_key_upd);
}
+static bool match_friend_key_id(const void *a, const void *b)
+{
+ const struct mesh_friend *friend = a;
+ uint32_t key_id = L_PTR_TO_UINT(b);
+
+ return (key_id == friend->net_key_cur) ||
+ (key_id == friend->net_key_upd);
+}
+
static void idle_mesh_heartbeat_send(void *net)
{
mesh_net_heartbeat_send(net);
const struct mesh_friend *frnd = a;
uint16_t dst = L_PTR_TO_UINT(b);
- return frnd->dst == dst;
+ return frnd->lp_addr == dst;
}
static void free_friend_internals(struct mesh_friend *frnd)
if (frnd->pkt_cache)
l_queue_destroy(frnd->pkt_cache, l_free);
- if (frnd->grp_list)
- l_free(frnd->grp_list);
-
+ l_free(frnd->u.active.grp_list);
+ frnd->u.active.grp_list = NULL;
frnd->pkt_cache = NULL;
- frnd->grp_list = NULL;
+
net_key_unref(frnd->net_key_cur);
net_key_unref(frnd->net_key_upd);
+ frnd->net_key_cur = 0;
+ frnd->net_key_upd = 0;
+
}
static void frnd_kr_phase1(void *a, void *b)
struct mesh_friend *frnd = a;
uint32_t key_id = L_PTR_TO_UINT(b);
- frnd->net_key_upd = net_key_frnd_add(key_id, frnd->dst,
+ frnd->net_key_upd = net_key_frnd_add(key_id, frnd->lp_addr,
frnd->net->src_addr, frnd->lp_cnt, frnd->fn_cnt);
}
*/
l_info("Use Both KeySet %d && %d for %4.4x",
- frnd->net_key_cur, frnd->net_key_upd, frnd->dst);
+ frnd->net_key_cur, frnd->net_key_upd, frnd->lp_addr);
}
static void frnd_kr_phase3(void *a, void *b)
struct mesh_friend *frnd = a;
l_info("Replace KeySet %d with %d for %4.4x",
- frnd->net_key_cur, frnd->net_key_upd, frnd->dst);
+ frnd->net_key_cur, frnd->net_key_upd, frnd->lp_addr);
net_key_unref(frnd->net_key_cur);
frnd->net_key_cur = frnd->net_key_upd;
frnd->net_key_upd = 0;
/* add _k2 */
frnd->net = net;
- frnd->dst = dst;
+ frnd->lp_addr = dst;
frnd->frd = frd;
frnd->frw = frw;
frnd->fn_cnt = fn_cnt;
if (!subnet->net_key_upd)
return frnd;
+ frnd->net_idx = subnet->idx;
frnd->net_key_upd = net_key_frnd_add(subnet->net_key_upd,
dst, net->src_addr,
lp_cnt, fn_cnt);
if (!frnd)
return;
- new_list = l_malloc((grp_cnt + frnd->grp_cnt) * sizeof(uint16_t));
- grp_list = frnd->grp_list;
+ new_list = l_malloc((grp_cnt +
+ frnd->u.active.grp_cnt) * sizeof(uint16_t));
+ grp_list = frnd->u.active.grp_list;
- if (grp_list && frnd->grp_cnt)
- memcpy(new_list, grp_list, frnd->grp_cnt * sizeof(uint16_t));
+ if (grp_list && frnd->u.active.grp_cnt)
+ memcpy(new_list, grp_list,
+ frnd->u.active.grp_cnt * sizeof(uint16_t));
- memcpy(&new_list[frnd->grp_cnt], list, grp_cnt * sizeof(uint16_t));
+ memcpy(&new_list[frnd->u.active.grp_cnt], list,
+ grp_cnt * sizeof(uint16_t));
l_free(grp_list);
frnd->ele_cnt = ele_cnt;
- frnd->grp_list = new_list;
- frnd->grp_cnt += grp_cnt;
+ frnd->u.active.grp_list = new_list;
+ frnd->u.active.grp_cnt += grp_cnt;
}
void mesh_friend_sub_del(struct mesh_net *net, uint16_t lpn,
if (!frnd)
return;
- grp_cnt = frnd->grp_cnt;
- grp_list = frnd->grp_list;
+ grp_cnt = frnd->u.active.grp_cnt;
+ grp_list = frnd->u.active.grp_list;
while (cnt-- && grp_cnt) {
cnt16 -= sizeof(uint16_t);
}
}
- frnd->grp_cnt = grp_cnt;
+ frnd->u.active.grp_cnt = grp_cnt;
if (!grp_cnt) {
- l_free(frnd->grp_list);
- frnd->grp_list = NULL;
+ l_free(frnd->u.active.grp_list);
+ frnd->u.active.grp_list = NULL;
}
}
net->sar_in = l_queue_new();
net->sar_out = l_queue_new();
net->frnd_msgs = l_queue_new();
- net->friends = l_queue_new();
net->destinations = l_queue_new();
net->app_keys = l_queue_new();
l_queue_destroy(net->sar_out, mesh_sar_free);
l_queue_destroy(net->frnd_msgs, l_free);
l_queue_destroy(net->friends, mesh_friend_free);
+ l_queue_destroy(net->negotiations, mesh_friend_free);
l_queue_destroy(net->destinations, l_free);
l_queue_destroy(net->app_keys, appkey_key_free);
bool mesh_net_set_friend_mode(struct mesh_net *net, bool enable)
{
+ l_debug("mesh_net_set_friend_mode - %d", enable);
+
if (!net)
return false;
- if (net->friend_enable && !enable)
- l_queue_clear(net->friends, mesh_friend_free);
+ if (net->friend_enable == enable)
+ return true;
+
+ if (enable) {
+ net->friends = l_queue_new();
+ net->negotiations = l_queue_new();
+ } else {
+ l_queue_destroy(net->friends, mesh_friend_free);
+ l_queue_destroy(net->negotiations, mesh_friend_free);
+ net->friends = net->negotiations = NULL;
+ }
net->friend_enable = enable;
trigger_heartbeat(net, FEATURE_FRIEND, enable);
{
const struct mesh_friend *frnd = a;
uint16_t dst = L_PTR_TO_UINT(b);
- int16_t i, grp_cnt = frnd->grp_cnt;
- uint16_t *grp_list = frnd->grp_list;
+ int16_t i, grp_cnt = frnd->u.active.grp_cnt;
+ uint16_t *grp_list = frnd->u.active.grp_list;
/*
* Determine if this message is for this friends unicast
* address, and/or one of it's group/virtual addresses
*/
- if (dst >= frnd->dst && dst < (frnd->dst + frnd->ele_cnt))
+ if (dst >= frnd->lp_addr && dst < (frnd->lp_addr + frnd->ele_cnt))
return true;
if (!(dst & 0x8000))
return false;
}
-static bool is_lpn_friend(struct mesh_net *net, uint16_t addr, bool frnd)
+static bool is_lpn_friend(struct mesh_net *net, uint16_t addr)
{
void *tst;
- if (!frnd)
- return false;
-
tst = l_queue_find(net->friends, match_frnd_dst, L_UINT_TO_PTR(addr));
return tst != NULL;
* Determine if this message is for this friends unicast
* address, and/or one of it's group/virtual addresses
*/
- if (rx->dst >= frnd->dst && (rx->dst - frnd->dst) < frnd->ele_cnt) {
+ if (rx->dst >= frnd->lp_addr && (rx->dst - frnd->lp_addr) <
+ frnd->ele_cnt) {
rx->done = true;
goto enqueue;
}
return;
if (!IS_ALL_NODES(rx->dst)) {
- for (i = 0; i < frnd->grp_cnt; i++) {
- if (rx->dst == frnd->grp_list[i])
+ for (i = 0; i < frnd->u.active.grp_cnt; i++) {
+ if (rx->dst == frnd->u.active.grp_list[i])
goto enqueue;
}
return;
* If we are discarding head for any
* reason, reset FRND SEQ
*/
- frnd->last = frnd->seq;
+ frnd->u.active.last =
+ frnd->u.active.seq;
}
l_free(old);
}
l_debug("%s for %4.4x from %4.4x ttl: %2.2x (seq: %6.6x) (ctl: %d)",
- __func__, frnd->dst, rx->src, rx->ttl,
+ __func__, frnd->lp_addr, rx->src, rx->ttl,
rx->u.one[0].seq, rx->ctl);
if (rx->cnt_in) {
*/
pkt = l_queue_pop_head(frnd->pkt_cache);
l_free(pkt);
- frnd->last = frnd->seq;
+ frnd->u.active.last = frnd->u.active.seq;
}
}
struct mesh_friend *frnd = a;
struct mesh_friend_msg *pkt = b;
- pkt->dst = frnd->dst;
+ pkt->dst = frnd->lp_addr;
pkt->done = false;
enqueue_friend_pkt(frnd, pkt);
}
l_info("Send Friend ACK to Segs: %8.8x", flags);
- if (is_lpn_friend(net, dst, true)) {
+ if (is_lpn_friend(net, dst)) {
/* If we are acking our LPN Friend, queue, don't send */
friend_ack_rxed(net, mesh_net_get_iv_index(net),
mesh_net_next_seq_num(net), 0, dst, msg);
hdr = NET_OP_SEG_ACKNOWLEDGE << OPCODE_HDR_SHIFT;
hdr |= sar->seqZero << SEQ_ZERO_HDR_SHIFT;
- if (is_lpn_friend(net, src, true))
+ if (is_lpn_friend(net, src))
hdr |= true << RELAY_HDR_SHIFT;
l_put_be32(hdr, msg);
l_put_be32(flags, msg + 3);
l_info("Send%s ACK to Segs: %8.8x", sar->frnd ? " Friend" : "", flags);
- if (is_lpn_friend(net, dst, true)) {
+ if (is_lpn_friend(net, dst)) {
/* If we are acking our LPN Friend, queue, don't send */
friend_ack_rxed(net, mesh_net_get_iv_index(net),
mesh_net_next_seq_num(net), src, dst, msg);
outgoing->seg_timeout = l_timeout_create(SEG_TO, outseg_to, net, NULL);
}
-static void outack_to(struct l_timeout *seg_timeout, void *user_data)
-{
- struct mesh_net *net = user_data;
- struct mesh_sar *sar = l_queue_find(net->sar_out,
- match_seg_timeout, seg_timeout);
-
- l_timeout_remove(seg_timeout);
- if (!sar)
- return;
-
- sar->seg_timeout = NULL;
-
- /* Re-Send missing segments by faking NAK */
- ack_received(net, true, sar->remote, sar->src,
- sar->seqZero, sar->last_nak);
-}
-
static void outseg_to(struct l_timeout *seg_timeout, void *user_data)
{
struct mesh_net *net = user_data;
sar->seg_timeout = NULL;
- if (net->friend_addr) {
- /* We are LPN -- Poll for ACK */
- frnd_ack_poll(net);
- sar->seg_timeout = l_timeout_create(SEG_TO,
- outack_to, net, NULL);
- } else {
- /* Re-Send missing segments by faking NACK */
- ack_received(net, true, sar->remote, sar->src,
+ /* Re-Send missing segments by faking NACK */
+ ack_received(net, true, sar->remote, sar->src,
sar->seqZero, sar->last_nak);
- }
}
static bool msg_rxed(struct mesh_net *net, bool frnd, uint32_t iv_index,
net_idx, src, dst, key_aid, data, size);
}
+static uint16_t key_id_to_net_idx(struct mesh_net *net, uint32_t key_id)
+{
+ struct mesh_subnet *subnet;
+ struct mesh_friend *friend;
+
+ if (!net)
+ return NET_IDX_INVALID;
+
+ subnet = l_queue_find(net->subnets, match_key_id,
+ L_UINT_TO_PTR(key_id));
+
+ if (subnet)
+ return subnet->idx;
+
+ friend = l_queue_find(net->friends, match_friend_key_id,
+ L_UINT_TO_PTR(key_id));
+
+ if (friend)
+ return friend->net_idx;
+
+ friend = l_queue_find(net->negotiations, match_friend_key_id,
+ L_UINT_TO_PTR(key_id));
+
+ if (friend)
+ return friend->net_idx;
+ else
+ return NET_IDX_INVALID;
+}
+
static bool match_frnd_sar_dst(const void *a, const void *b)
{
const struct mesh_friend_msg *frnd_msg = a;
if (!frnd)
return;
- if (frnd->last_hdr == hdr_key) {
+ if (frnd->u.active.last_hdr == hdr_key) {
/* We are no longer receiving this msg. Resend final ACK */
- send_frnd_ack(net, dst, src, frnd->last_hdr, 0xffffffff);
+ send_frnd_ack(net, dst, src, frnd->u.active.last_hdr,
+ 0xffffffff);
return;
}
return false;
}
-static bool ctl_received(struct mesh_net *net, bool frnd, uint32_t iv_index,
- uint8_t ttl,
+static bool ctl_received(struct mesh_net *net, uint16_t key_id,
+ uint32_t iv_index, uint8_t ttl,
uint32_t seq,
uint16_t src, uint16_t dst,
uint8_t opcode, int8_t rssi,
uint8_t msg[12];
uint8_t rsp_ttl = DEFAULT_TTL;
uint8_t n = 0;
+ uint16_t net_idx;
- if (!frnd && ttl > 1) {
+ if (ttl > 1) {
uint32_t hdr = opcode << OPCODE_HDR_SHIFT;
uint8_t frnd_ttl = ttl - 1;
return false;
print_packet("Rx-NET_OP_FRND_REQUEST", pkt, len);
- friend_request(net, src, pkt[0], pkt[1],
+ net_idx = key_id_to_net_idx(net, key_id);
+ friend_request(net, net_idx, src, pkt[0], pkt[1],
l_get_be32(pkt + 1) & 0xffffff,
l_get_be16(pkt + 5), pkt[7],
l_get_be16(pkt + 8), rssi);
break;
- case NET_OP_FRND_OFFER:
- if (len != 6 || ttl)
- return false;
-
- print_packet("Rx-NET_OP_FRND_OFFER", pkt, len);
- frnd_offer(net, src, pkt[0], pkt[1], pkt[2],
- (int8_t) pkt[3], rssi, l_get_be16(pkt + 4));
- break;
-
case NET_OP_FRND_CLEAR_CONFIRM:
if (len != 4)
return false;
mesh_io_send(io, &info, packet, size);
}
-static uint16_t key_id_to_net_idx(struct mesh_net *net, uint32_t key_id)
-{
- struct mesh_subnet *subnet;
-
- if (!net)
- return NET_IDX_INVALID;
-
- subnet = l_queue_find(net->subnets, match_key_id,
- L_UINT_TO_PTR(key_id));
-
- if (subnet)
- return subnet->idx;
- else
- return NET_IDX_INVALID;
-}
-
static enum _relay_advice packet_received(void *user_data,
uint32_t key_id, uint32_t iv_index,
const void *data, uint8_t size, int8_t rssi)
uint16_t net_idx;
uint8_t packet[31];
bool net_ctl, net_segmented, net_szmic, net_relay;
- struct mesh_friend *net_frnd = NULL;
memcpy(packet + 2, data, size);
return RELAY_NONE;
}
- /* Ignore incoming packets if we are LPN and frnd bit not set */
- if (net->friend_addr) {
- struct mesh_subnet *subnet;
-
- subnet = l_queue_find(net->subnets, match_key_id,
- L_UINT_TO_PTR(key_id));
- if (subnet)
- return RELAY_NONE;
-
- /* If the queue is empty, stop polling */
- if (net_ctl && net_opcode == NET_OP_FRND_UPDATE && !msg[5])
- frnd_poll_cancel(net);
- else
- frnd_poll(net, false);
-
- } else if (net_dst == 0) {
+ if (net_dst == 0) {
l_error("illegal parms: DST: %4.4x Ctl: %d TTL: %2.2x",
net_dst, net_ctl, net_ttl);
return RELAY_NONE;
net_src, net_dst, net_ttl, iv_index, net_seq);
if (is_us(net, net_dst, false) ||
- is_lpn_friend(net, net_src, !!(net_frnd)) ||
(net_ctl && net_opcode == NET_OP_HEARTBEAT)) {
l_info("RX: App 0x%04x -> 0x%04x : TTL 0x%02x : SEQ 0x%06x",
return RELAY_NONE;
/* If this is an ACK to our friend queue-only */
- if (is_lpn_friend(net, net_dst, true))
+ if (is_lpn_friend(net, net_dst))
friend_ack_rxed(net, iv_index, net_seq,
net_src, net_dst,
msg);
net_seqZero,
l_get_be32(msg + 3));
} else {
- ctl_received(net, !!(net_frnd), iv_index,
+ ctl_received(net, key_id,
+ iv_index,
net_ttl, net_seq, net_src,
net_dst, net_opcode, rssi,
msg, app_msg_len);
/* If we accept SAR packets to non-Unicast, then
* Friend Sar at least needs to be Unicast Only
*/
- if (is_lpn_friend(net, net_dst, true) &&
+ if (is_lpn_friend(net, net_dst) &&
!(net_dst & 0x8000)) {
/* Check TTL >= 2 before accepting segments
* for Friends
msg, app_msg_len);
}
} else {
- seg_rxed(net, net_frnd, iv_index, net_ttl,
+ seg_rxed(net, NULL, iv_index, net_ttl,
net_seq, net_idx,
net_src, net_dst,
net_key_id,
}
} else {
- msg_rxed(net, net_frnd,
+ msg_rxed(net, NULL,
iv_index,
net_ttl,
net_seq,
msg, app_msg_len);
}
- if (!!(net_frnd))
- l_info("Ask for more data!");
-
/* If this is one of our Unicast addresses, disallow relay */
if (IS_UNICAST(net_dst))
return RELAY_DISALLOWED;
}
/* If relay not enable, or no more hops allowed */
- if (!net->relay.enable || net_ttl < 0x02 || net_frnd)
+ if (!net->relay.enable || net_ttl < 0x02)
return RELAY_NONE;
/* Group or Virtual destinations should *always* be relayed */
subnet->kr_phase = KEY_REFRESH_PHASE_TWO;
set_network_beacon(subnet, net);
- if (net->friend_addr)
- frnd_key_refresh(net, 2);
- else
- l_queue_foreach(net->friends, frnd_kr_phase2, net);
+ l_queue_foreach(net->friends, frnd_kr_phase2, net);
mesh_config_net_key_set_phase(node_config_get(net->node), idx,
KEY_REFRESH_PHASE_TWO);
subnet->kr_phase = KEY_REFRESH_PHASE_NONE;
set_network_beacon(subnet, net);
- if (net->friend_addr)
- frnd_key_refresh(net, 3);
- else
- l_queue_foreach(net->friends, frnd_kr_phase3, net);
+ l_queue_foreach(net->friends, frnd_kr_phase3, net);
mesh_config_net_key_set_phase(node_config_get(net->node), idx,
KEY_REFRESH_PHASE_NONE);
l_queue_push_head(net->destinations, dest);
else
l_queue_push_tail(net->destinations, dest);
-
- /* If LPN, and Group/Virtual, add to Subscription List */
- if (net->friend_addr) {
- /* TODO: Fix this garbage */
- uint32_t u32_dst[7] = {dst, 0xffffffff};
-
- frnd_sub_add(net, u32_dst);
- }
}
dest->dst = dst;
if (dest->ref_cnt)
return true;
- /* TODO: If LPN, and Group/Virtual, remove from Subscription List */
- if (net->friend_addr) {
- /* TODO: Fix this garbage */
- uint32_t u32_dst[7] = {dst, 0xffffffff};
-
- frnd_sub_del(net, u32_dst);
- }
-
l_queue_remove(net->destinations, dest);
l_free(dest);
/* TODO: add net key index */
static bool send_seg(struct mesh_net *net, struct mesh_sar *msg, uint8_t segO)
{
+ struct mesh_subnet *subnet;
uint8_t seg_len;
uint8_t gatt_data[30];
uint8_t *packet = gatt_data;
}
print_packet("Clr-Net Tx", packet + 1, packet_len);
- if (msg->frnd_cred && net->friend_addr)
- key_id = frnd_get_key(net);
-
- if (!key_id) {
- struct mesh_subnet *subnet = get_primary_subnet(net);
-
- key_id = subnet->net_key_tx;
- }
+ subnet = get_primary_subnet(net);
+ key_id = subnet->net_key_tx;
if (!net_key_encrypt(key_id, msg->iv_index, packet + 1, packet_len)) {
l_error("Failed to encode packet");
/* Deliver to Local entities if applicable */
if (!(dst & 0x8000) && src >= net->src_addr && src <= net->last_addr) {
- result = ctl_received(net, !!(key_id),
+ result = ctl_received(net, key_id,
iv_index, ttl,
mesh_net_next_seq_num(net),
src, dst,
return MESH_STATUS_CANNOT_UPDATE;
}
- /* If we are an LPN, generate our keys here */
- if (net->friend_addr)
- frnd_key_refresh(net, 1);
- else
- /* If we are a Friend-Node, generate all our new keys */
- l_queue_foreach(net->friends, frnd_kr_phase1,
+ /* If we are a Friend-Node, generate all our new keys */
+ l_queue_foreach(net->friends, frnd_kr_phase1,
L_UINT_TO_PTR(subnet->net_key_upd));
l_info("key refresh phase 1: Key ID %d", subnet->net_key_upd);
features |= FEATURE_RELAY;
if (net->proxy_enable)
features |= FEATURE_PROXY;
- if (!l_queue_isempty(net->friends))
+ if (net->friend_enable)
features |= FEATURE_FRIEND;
if (net->friend_addr != UNASSIGNED_ADDRESS)
features |= FEATURE_LPN;
return frnd->poll_timeout;
}
+struct l_queue *mesh_net_get_friends(struct mesh_net *net)
+{
+ if (net)
+ return net->friends;
+
+ return NULL;
+}
+
+struct l_queue *mesh_net_get_negotiations(struct mesh_net *net)
+{
+ if (net)
+ return net->negotiations;
+
+ return NULL;
+}
+
struct mesh_node *mesh_net_node_get(struct mesh_net *net)
{
return net->node;
diff --git a/mesh/net.h b/mesh/net.h
index 150240f..fe4e0b6 100644
--- a/mesh/net.h
+++ b/mesh/net.h
uint8_t privacy_key[16];
};
+struct friend_neg {
+ int8_t rssi;
+ bool clearing;
+};
+
+struct friend_act {
+ uint16_t *grp_list;
+ uint32_t last_hdr;
+ int16_t grp_cnt;
+ bool seq;
+ bool last;
+};
+
struct mesh_friend {
struct mesh_net *net;
- struct l_queue *pkt_cache;
struct l_timeout *timeout;
+ struct l_queue *pkt_cache;
void *pkt;
- uint16_t *grp_list;
uint32_t poll_timeout;
- uint32_t last_hdr;
uint32_t net_key_cur;
uint32_t net_key_upd;
- uint16_t dst; /* Primary Element unicast addr */
+ uint16_t old_friend;
+ uint16_t net_idx;
+ uint16_t lp_addr;/* dst; * Primary Element unicast addr */
uint16_t fn_cnt;
uint16_t lp_cnt;
- int16_t grp_cnt;
+ uint8_t receive_delay;
uint8_t ele_cnt;
uint8_t frd;
uint8_t frw;
- bool seq;
- bool last;
+ union {
+ struct friend_neg negotiate;
+ struct friend_act active;
+ } u;
};
struct mesh_frnd_pkt {
struct mesh_prov *mesh_net_get_prov(struct mesh_net *net);
void mesh_net_set_prov(struct mesh_net *net, struct mesh_prov *prov);
uint32_t mesh_net_get_instant(struct mesh_net *net);
+struct l_queue *mesh_net_get_friends(struct mesh_net *net);
+struct l_queue *mesh_net_get_negotiations(struct mesh_net *net);
diff --git a/mesh/node.c b/mesh/node.c
index b52b9e4..7b4ee05 100644
--- a/mesh/node.c
+++ b/mesh/node.c
if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
mesh_net_set_proxy_mode(node->net, mode == MESH_MODE_ENABLED);
- mode = node->lpn;
+ mode = node->friend;
if (mode == MESH_MODE_ENABLED || mode == MESH_MODE_DISABLED)
mesh_net_set_friend_mode(node->net, mode == MESH_MODE_ENABLED);