Example #1
0
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;
}
Example #2
0
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++;
    }
}