static bool ad_parse(struct net_buf_simple *ad, bool (*func)(u8_t type, const u8_t *data, u8_t data_len, void *user_data), void *user_data) { while (ad->len > 1) { u8_t len = net_buf_simple_pull_u8(ad); u8_t type; /* Check for early termination */ if (len == 0) { return false; } if (len > ad->len || ad->len < 1) { NET_ERR("AD malformed\n"); return false; } type = net_buf_simple_pull_u8(ad); if (func(type, ad->data, len - 1, user_data)) { return true; } net_buf_simple_pull(ad, len - 1); } return false; }
static void secure_beacon_recv(struct net_buf_simple *buf) { u8_t *data, *net_id, *auth; struct bt_mesh_subnet *sub; u32_t iv_index; bool new_key, kr_change, iv_change; u8_t flags; if (buf->len < 21) { BT_ERR("Too short secure beacon (len %u)", buf->len); return; } sub = cache_check(buf->data); if (sub) { /* We've seen this beacon before - just update the stats */ goto update_stats; } /* So we can add to the cache if auth matches */ data = buf->data; flags = net_buf_simple_pull_u8(buf); net_id = buf->data; net_buf_simple_pull(buf, 8); iv_index = net_buf_simple_pull_be32(buf); auth = buf->data; BT_DBG("flags 0x%02x id %s iv_index 0x%08x", flags, bt_hex(net_id, 8), iv_index); sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key); if (!sub) { BT_DBG("No subnet that matched beacon"); return; } if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) { BT_WARN("Ignoring Phase 2 KR Update secured using old key"); return; } cache_add(data, sub); /* If we have NetKey0 accept initiation only from it */ if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) && sub->net_idx != BT_MESH_KEY_PRIMARY) { BT_WARN("Ignoring secure beacon on non-primary subnet"); goto update_stats; } BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x", sub->net_idx, iv_index, bt_mesh.iv_index); if (bt_mesh.ivu_initiator && bt_mesh.iv_update == BT_MESH_IV_UPDATE(flags)) { bt_mesh_beacon_ivu_initiator(false); } iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags)); kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key); if (kr_change) { bt_mesh_net_beacon_update(sub); } if (iv_change) { /* Update all subnets */ bt_mesh_net_sec_update(NULL); } else if (kr_change) { /* Key Refresh without IV Update only impacts one subnet */ bt_mesh_net_sec_update(sub); } update_stats: if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED && sub->beacons_cur < 0xff) { sub->beacons_cur++; } }