Esempio n. 1
0
static uint8_t att_signed_write_cmd(struct bt_att *att, struct net_buf *buf)
{
	struct bt_conn *conn = att->chan.conn;
	struct bt_att_signed_write_cmd *req;
	uint16_t handle;
	int err;

	req = (void *)buf->data;

	handle = sys_le16_to_cpu(req->handle);

	BT_DBG("handle 0x%04x", handle);

	/* Verifying data requires full buffer including attribute header */
	net_buf_push(buf, sizeof(struct bt_att_hdr));
	err = bt_smp_sign_verify(conn, buf);
	if (err) {
		BT_ERR("Error verifying data");
		/* No response for this command */
		return 0;
	}

	net_buf_pull(buf, sizeof(struct bt_att_hdr));
	net_buf_pull(buf, sizeof(*req));

	return att_write_rsp(conn, 0, 0, handle, 0, buf->data,
			     buf->len - sizeof(struct bt_att_signature));
}
Esempio n. 2
0
static void deserialize_struct(struct net_buf *buf, const uint8_t **struct_ptr,
			       uint8_t *struct_length)
{
	*struct_length = net_buf_pull_u8(buf);
	*struct_ptr = buf->data;
	net_buf_pull(buf, *struct_length);
}
Esempio n. 3
0
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf)
{
	struct bt_l2cap_hdr *hdr = (void *)buf->data;
	struct bt_l2cap_chan *chan;
	uint16_t cid;

	if (IS_ENABLED(CONFIG_BLUETOOTH_BREDR) &&
	    conn->type == BT_CONN_TYPE_BR) {
		bt_l2cap_br_recv(conn, buf);
		return;
	}

	if (buf->len < sizeof(*hdr)) {
		BT_ERR("Too small L2CAP PDU received");
		net_buf_unref(buf);
		return;
	}

	cid = sys_le16_to_cpu(hdr->cid);
	net_buf_pull(buf, sizeof(*hdr));

	BT_DBG("Packet for CID %u len %u", cid, buf->len);

	chan = bt_l2cap_le_lookup_rx_cid(conn, cid);
	if (!chan) {
		BT_WARN("Ignoring data for unknown CID 0x%04x", cid);
		net_buf_unref(buf);
		return;
	}

	l2cap_chan_recv(chan, buf);
	net_buf_unref(buf);
}
Esempio n. 4
0
struct net_buf *
ieee802154_create_mac_cmd_frame(struct net_if *iface,
				enum ieee802154_cfi type,
				struct ieee802154_frame_params *params)
{
	struct ieee802154_context *ctx = net_if_l2_data(iface);
	struct ieee802154_fcf_seq *fs;
	struct net_buf *buf, *frag;
	uint8_t *p_buf;

	buf = net_nbuf_get_reserve_tx(0);
	if (!buf) {
		return NULL;
	}

	frag = net_nbuf_get_reserve_data(0);
	if (!frag) {
		goto error;
	}

	net_buf_frag_add(buf, frag);
	p_buf = net_nbuf_ll(buf);

	fs = generate_fcf_grounds(&p_buf, false);

	fs->fc.frame_type = IEEE802154_FRAME_TYPE_MAC_COMMAND;
	fs->sequence = ctx->sequence;

	if (!cfi_to_fs_settings(type, fs, params)) {
		goto error;
	}

	p_buf = generate_addressing_fields(iface, fs, params, p_buf);

	/* Let's insert the cfi */
	((struct ieee802154_command *)p_buf)->cfi = type;

	/* In MAC command, we consider ll header being the mhr.
	 * Rest will be the MAC command itself. This will proove
	 * to be easy to handle afterwards to point directly to MAC
	 * command space, in order to fill-in its content.
	 */
	net_nbuf_set_ll_reserve(buf, p_buf - net_nbuf_ll(buf));
	net_buf_pull(frag, net_nbuf_ll_reserve(buf));

	/* Thus setting the right MAC command length
	 * Now up to the caller to fill-in this space relevantly.
	 * See ieee802154_mac_command() helper.
	 */
	net_nbuf_set_len(frag, mac_command_length(type));

	dbg_print_fs(fs);

	return buf;
error:
	net_nbuf_unref(buf);

	return NULL;
}
Esempio n. 5
0
void on_nble_gap_adv_report_evt(const struct nble_gap_adv_report_evt *evt,
				const uint8_t *buf, uint8_t len)
{
#if TODO_IMPLEMENT_CONNECTION
	uint8_t num_reports = buf->data[0];
	struct bt_hci_ev_le_advertising_info *info;

	BT_DBG("Adv number of reports %u",  num_reports);

	info = net_buf_pull(buf, sizeof(num_reports));

	while (num_reports--) {
		int8_t rssi = info->data[info->length];
		const bt_addr_le_t *addr;

		BT_DBG("%s event %u, len %u, rssi %d dBm",
		       bt_addr_le_str(&info->addr),
		       info->evt_type, info->length, rssi);

		addr = find_id_addr(&info->addr);
#endif

		BT_DBG("nble gap: event:%u, len %u", evt->adv_type, len);

		if (scan_dev_found_cb) {
			scan_dev_found_cb(&evt->addr, evt->rssi, evt->adv_type,
					  buf, len);
		}
#if TODO_IMPLEMENT_CONNECTION
#if defined(CONFIG_BLUETOOTH_CONN)
		check_pending_conn(addr, &info->addr, info->evt_type);
#endif /* CONFIG_BLUETOOTH_CONN */
		/* Get next report iteration by moving pointer to right offset
		 * in buf according to spec 4.2, Vol 2, Part E, 7.7.65.2.
		 */
		info = net_buf_pull(buf, sizeof(*info) + info->length +
				    sizeof(rssi));
	}
#endif
}
Esempio n. 6
0
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,
					     struct net_buf *buf,
					     size_t sdu_hdr_len)
{
	struct net_buf *seg;
	uint16_t headroom;
	uint16_t len;

	/* Segment if data (+ data headroom) is bigger than MPS */
	if (buf->len + sdu_hdr_len > ch->tx.mps) {
		goto segment;
	}

	/* Segment if there is no space in the user_data */
	if (buf->pool->user_data_size < BT_BUF_USER_DATA_MIN) {
		BT_WARN("Too small buffer user_data_size %u",
			buf->pool->user_data_size);
		goto segment;
	}

	headroom = sizeof(struct bt_hci_acl_hdr) +
		   sizeof(struct bt_l2cap_hdr) + sdu_hdr_len;

	/* Check if original buffer has enough headroom and don't have any
	 * fragments.
	 */
	if (net_buf_headroom(buf) >= headroom && !buf->frags) {
		if (sdu_hdr_len) {
			/* Push SDU length if set */
			net_buf_push_le16(buf, net_buf_frags_len(buf));
		}
		return net_buf_ref(buf);
	}

segment:
	seg = bt_l2cap_create_pdu(&le_data_pool, 0);

	if (sdu_hdr_len) {
		net_buf_add_le16(seg, net_buf_frags_len(buf));
	}

	/* Don't send more that TX MPS including SDU length */
	len = min(net_buf_tailroom(seg), ch->tx.mps - sdu_hdr_len);
	/* Limit if original buffer is smaller than the segment */
	len = min(buf->len, len);
	net_buf_add_mem(seg, buf->data, len);
	net_buf_pull(buf, len);

	BT_DBG("ch %p seg %p len %u", ch, seg, seg->len);

	return seg;
}
Esempio n. 7
0
static uint8_t att_read_group_req(struct bt_att *att, struct net_buf *buf)
{
	struct bt_conn *conn = att->chan.conn;
	struct bt_att_read_group_req *req;
	uint16_t start_handle, end_handle, err_handle;
	union {
		struct bt_uuid uuid;
		struct bt_uuid_16 u16;
		struct bt_uuid_128 u128;
	} u;

	/* Type can only be UUID16 or UUID128 */
	if (buf->len != sizeof(*req) + 2 && buf->len != sizeof(*req) + 16) {
		return BT_ATT_ERR_INVALID_PDU;
	}

	req = (void *)buf->data;

	start_handle = sys_le16_to_cpu(req->start_handle);
	end_handle = sys_le16_to_cpu(req->end_handle);
	net_buf_pull(buf, sizeof(*req));

	if (!uuid_create(&u.uuid, buf)) {
		return BT_ATT_ERR_UNLIKELY;
	}

	BT_DBG("start_handle 0x%04x end_handle 0x%04x type %s",
	       start_handle, end_handle, bt_uuid_str(&u.uuid));

	if (!range_is_valid(start_handle, end_handle, &err_handle)) {
		send_err_rsp(conn, BT_ATT_OP_READ_GROUP_REQ, err_handle,
			     BT_ATT_ERR_INVALID_HANDLE);
		return 0;
	}

	/* Core v4.2, Vol 3, sec 2.5.3 Attribute Grouping:
	 * Not all of the grouping attributes can be used in the ATT
	 * Read By Group Type Request. The «Primary Service» and «Secondary
	 * Service» grouping types may be used in the Read By Group Type
	 * Request. The «Characteristic» grouping type shall not be used in
	 * the ATT Read By Group Type Request.
	 */
	if (bt_uuid_cmp(&u.uuid, BT_UUID_GATT_PRIMARY) &&
	    bt_uuid_cmp(&u.uuid, BT_UUID_GATT_SECONDARY)) {
		send_err_rsp(conn, BT_ATT_OP_READ_GROUP_REQ, start_handle,
				     BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE);
		return 0;
	}

	return att_read_group_rsp(att, &u.uuid, start_handle, end_handle);
}
Esempio n. 8
0
File: h4.c Progetto: 01org/zephyr
static inline void process_tx(void)
{
	int bytes;

	if (!tx.buf) {
		tx.buf = net_buf_get(&tx.fifo, K_NO_WAIT);
		if (!tx.buf) {
			BT_ERR("TX interrupt but no pending buffer!");
			uart_irq_tx_disable(h4_dev);
			return;
		}
	}

	if (!tx.type) {
		switch (bt_buf_get_type(tx.buf)) {
		case BT_BUF_ACL_OUT:
			tx.type = H4_ACL;
			break;
		case BT_BUF_CMD:
			tx.type = H4_CMD;
			break;
		default:
			BT_ERR("Unknown buffer type");
			goto done;
		}

		bytes = uart_fifo_fill(h4_dev, &tx.type, 1);
		if (bytes != 1) {
			BT_WARN("Unable to send H:4 type");
			tx.type = H4_NONE;
			return;
		}
	}

	bytes = uart_fifo_fill(h4_dev, tx.buf->data, tx.buf->len);
	net_buf_pull(tx.buf, bytes);

	if (tx.buf->len) {
		return;
	}

done:
	tx.type = H4_NONE;
	net_buf_unref(tx.buf);
	tx.buf = net_buf_get(&tx.fifo, K_NO_WAIT);
	if (!tx.buf) {
		uart_irq_tx_disable(h4_dev);
	}
}
Esempio n. 9
0
static uint8_t att_write_req(struct bt_att *att, struct net_buf *buf)
{
	struct bt_conn *conn = att->chan.conn;
	struct bt_att_write_req *req;
	uint16_t handle;

	req = (void *)buf->data;

	handle = sys_le16_to_cpu(req->handle);
	net_buf_pull(buf, sizeof(*req));

	BT_DBG("handle 0x%04x", handle);

	return att_write_rsp(conn, BT_ATT_OP_WRITE_REQ, BT_ATT_OP_WRITE_RSP,
			     handle, 0, buf->data, buf->len);
}
Esempio n. 10
0
static void l2cap_chan_le_recv_sdu(struct bt_l2cap_le_chan *chan,
				   struct net_buf *buf)
{
	struct net_buf *frag;
	uint16_t len;

	BT_DBG("chan %p len %u sdu %zu", chan, buf->len,
	       net_buf_frags_len(chan->_sdu));

	if (net_buf_frags_len(chan->_sdu) + buf->len > chan->_sdu_len) {
		BT_ERR("SDU length mismatch");
		bt_l2cap_chan_disconnect(&chan->chan);
		return;
	}

	/* Jump to last fragment */
	frag = net_buf_frag_last(chan->_sdu);

	while (buf->len) {
		/* Check if there is any space left in the current fragment */
		if (!net_buf_tailroom(frag)) {
			frag = l2cap_alloc_frag(chan);
			if (!frag) {
				BT_ERR("Unable to store SDU");
				bt_l2cap_chan_disconnect(&chan->chan);
				return;
			}
		}

		len = min(net_buf_tailroom(frag), buf->len);
		net_buf_add_mem(frag, buf->data, len);
		net_buf_pull(buf, len);

		BT_DBG("frag %p len %u", frag, frag->len);
	}

	if (net_buf_frags_len(chan->_sdu) == chan->_sdu_len) {
		/* Receiving complete SDU, notify channel and reset SDU buf */
		chan->chan.ops->recv(&chan->chan, chan->_sdu);
		net_buf_unref(chan->_sdu);
		chan->_sdu = NULL;
		chan->_sdu_len = 0;
	}

	l2cap_chan_update_credits(chan);
}
Esempio n. 11
0
static void bt_att_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
	struct bt_att *att = CONTAINER_OF(chan, struct bt_att, chan);
	struct bt_att_hdr *hdr = (void *)buf->data;
	uint8_t err = BT_ATT_ERR_NOT_SUPPORTED;
	size_t i;

	BT_ASSERT(att);

	if (buf->len < sizeof(*hdr)) {
		BT_ERR("Too small ATT PDU received");
		return;
	}

	BT_DBG("Received ATT code 0x%02x len %u", hdr->code, buf->len);

	net_buf_pull(buf, sizeof(*hdr));

	for (i = 0; i < ARRAY_SIZE(handlers); i++) {
		if (hdr->code != handlers[i].op) {
			continue;
		}

		if (buf->len < handlers[i].expect_len) {
			BT_ERR("Invalid len %u for code 0x%02x", buf->len,
			       hdr->code);
			err = BT_ATT_ERR_INVALID_PDU;
			break;
		}

		err = handlers[i].func(att, buf);
		break;
	}

	/* Commands don't have response */
	if ((hdr->code & BT_ATT_OP_CMD_FLAG)) {
		return;
	}

	if (err) {
		BT_DBG("ATT error 0x%02x", err);
		send_err_rsp(chan->conn, hdr->code, 0, err);
	}
}
Esempio n. 12
0
static void deserialize_buf(struct net_buf *buf, const uint8_t **buf_ptr,
			    uint16_t *buf_len)
{
	uint8_t b;

	/* Get the current byte */
	b = net_buf_pull_u8(buf);
	*buf_len = b & 0x7F;
	if (b & 0x80) {
		/* Get the current byte */
		b = net_buf_pull_u8(buf);
		*buf_len += (uint16_t)b << 7;
	}

	/* Return the values */
	*buf_ptr = buf->data;

	net_buf_pull(buf, *buf_len);
}
Esempio n. 13
0
static struct net_buf *create_frag(struct bt_conn *conn, struct net_buf *buf)
{
	struct net_buf *frag;
	uint16_t frag_len;

	frag = bt_conn_create_pdu(&frag_buf, 0);

	if (conn->state != BT_CONN_CONNECTED) {
		net_buf_unref(frag);
		return NULL;
	}

	frag_len = min(conn_mtu(conn), net_buf_tailroom(frag));

	memcpy(net_buf_add(frag, frag_len), buf->data, frag_len);
	net_buf_pull(buf, frag_len);

	return frag;
}
Esempio n. 14
0
static enum net_verdict ieee802154_recv(struct net_if *iface,
					struct net_pkt *pkt)
{
	struct ieee802154_mpdu mpdu;

	if (!ieee802154_validate_frame(net_pkt_ll(pkt),
				       net_pkt_get_len(pkt), &mpdu)) {
		return NET_DROP;
	}

	if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) {
		return ieee802154_handle_beacon(iface, &mpdu);
	}

	if (ieee802154_is_scanning(iface)) {
		return NET_DROP;
	}

	if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_MAC_COMMAND) {
		return ieee802154_handle_mac_command(iface, &mpdu);
	}

	/* At this point the frame has to be a DATA one */

	ieee802154_acknowledge(iface, &mpdu);

	net_pkt_set_ll_reserve(pkt, mpdu.payload - (void *)net_pkt_ll(pkt));
	net_buf_pull(pkt->frags, net_pkt_ll_reserve(pkt));

	set_pkt_ll_addr(net_pkt_ll_src(pkt), mpdu.mhr.fs->fc.pan_id_comp,
			mpdu.mhr.fs->fc.src_addr_mode, mpdu.mhr.src_addr);

	set_pkt_ll_addr(net_pkt_ll_dst(pkt), false,
			mpdu.mhr.fs->fc.dst_addr_mode, mpdu.mhr.dst_addr);

	if (!ieee802154_decipher_data_frame(iface, pkt, &mpdu)) {
		return NET_DROP;
	}

	pkt_hexdump(pkt, true);

	return ieee802154_manage_recv_packet(iface, pkt);
}
Esempio n. 15
0
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,
					     struct net_buf *buf,
					     size_t sdu_hdr_len)
{
	struct net_buf *seg;
	uint16_t headroom;
	uint16_t len;

	/* Segment if data (+ data headroom) is bigger than MPS */
	if (buf->len + sdu_hdr_len > ch->tx.mps) {
		goto segment;
	}

	headroom = sizeof(struct bt_hci_acl_hdr) +
		   sizeof(struct bt_l2cap_hdr) + sdu_hdr_len;

	/* Check if original buffer has enough headroom */
	if (net_buf_headroom(buf) >= headroom) {
		if (sdu_hdr_len) {
			/* Push SDU length if set */
			net_buf_push_le16(buf, buf->len);
		}
		return net_buf_ref(buf);
	}

segment:
	seg = bt_l2cap_create_pdu(&le_data);
	if (!seg) {
		return NULL;
	}

	if (sdu_hdr_len) {
		net_buf_add_le16(seg, buf->len);
	}

	len = min(min(buf->len, L2CAP_LE_MIN_MTU - sdu_hdr_len), ch->tx.mps);
	memcpy(net_buf_add(seg, len), buf->data, len);
	net_buf_pull(buf, len);

	BT_DBG("ch %p seg %p len %u", ch, seg, seg->len);

	return seg;
}
Esempio n. 16
0
void bt_l2cap_recv(struct bt_conn *conn, struct net_buf *buf)
{
	struct bt_l2cap_hdr *hdr = (void *)buf->data;
	struct bt_l2cap_chan *chan;
	uint16_t cid;

	if (buf->len < sizeof(*hdr)) {
		BT_ERR("Too small L2CAP PDU received");
		net_buf_unref(buf);
		return;
	}

	cid = sys_le16_to_cpu(hdr->cid);
	net_buf_pull(buf, sizeof(*hdr));

	BT_DBG("Packet for CID %u len %u", cid, buf->len);

	switch (conn->type) {
	case BT_CONN_TYPE_LE:
		chan = bt_l2cap_le_lookup_rx_cid(conn, cid);
		break;
#if defined(CONFIG_BLUETOOTH_BREDR)
	case BT_CONN_TYPE_BR:
		chan = bt_l2cap_br_lookup_rx_cid(conn, cid);
		break;
#endif /* CONFIG_BLUETOOTH_BREDR */
	default:
		chan = NULL;
		break;
	}

	if (!chan) {
		BT_WARN("Ignoring data for unknown CID 0x%04x", cid);
		net_buf_unref(buf);
		return;
	}

	l2cap_chan_recv(chan, buf);
	net_buf_unref(buf);
}
Esempio n. 17
0
static struct net_pkt *build_reply_pkt(const char *name,
				       struct net_context *context,
				       struct net_pkt *pkt)
{
	struct net_pkt *reply_pkt;
	struct net_buf *tmp;
	int header_len, recv_len, reply_len;

	printk("%s received %d bytes", name,
	      net_pkt_appdatalen(pkt));

	reply_pkt = net_pkt_get_tx(context, K_FOREVER);

	recv_len = net_pkt_get_len(pkt);

	tmp = pkt->frags;
	/* Remove frag link so original pkt can be unrefed */
	pkt->frags = NULL;

	/* First fragment will contain IP header so move the data
	 * down in order to get rid of it.
	 */
	header_len = net_pkt_appdata(pkt) - tmp->data;

	/* After this pull, the tmp->data points directly to application
	 * data.
	 */
	net_buf_pull(tmp, header_len);

	/* Add the entire chain into reply */
	net_pkt_frag_add(reply_pkt, tmp);

	reply_len = net_pkt_get_len(reply_pkt);

	printk("Received %d bytes, sending %d bytes", recv_len - header_len,
	       reply_len);

	return reply_pkt;
}
Esempio n. 18
0
static uint8_t att_read_type_req(struct bt_att *att, struct net_buf *buf)
{
	struct bt_conn *conn = att->chan.conn;
	struct bt_att_read_type_req *req;
	uint16_t start_handle, end_handle, err_handle;
	union {
		struct bt_uuid uuid;
		struct bt_uuid_16 u16;
		struct bt_uuid_128 u128;
	} u;

	/* Type can only be UUID16 or UUID128 */
	if (buf->len != sizeof(*req) + 2 && buf->len != sizeof(*req) + 16) {
		return BT_ATT_ERR_INVALID_PDU;
	}

	req = (void *)buf->data;

	start_handle = sys_le16_to_cpu(req->start_handle);
	end_handle = sys_le16_to_cpu(req->end_handle);
	net_buf_pull(buf, sizeof(*req));

	if (!uuid_create(&u.uuid, buf)) {
		return BT_ATT_ERR_UNLIKELY;
	}

	BT_DBG("start_handle 0x%04x end_handle 0x%04x type %s",
	       start_handle, end_handle, bt_uuid_str(&u.uuid));

	if (!range_is_valid(start_handle, end_handle, &err_handle)) {
		send_err_rsp(conn, BT_ATT_OP_READ_TYPE_REQ, err_handle,
			     BT_ATT_ERR_INVALID_HANDLE);
		return 0;
	}

	return att_read_type_rsp(att, &u.uuid, start_handle, end_handle);
}
Esempio n. 19
0
static uint8_t att_find_type_req(struct bt_att *att, struct net_buf *buf)
{
	struct bt_conn *conn = att->chan.conn;
	struct bt_att_find_type_req *req;
	uint16_t start_handle, end_handle, err_handle, type;
	uint8_t *value;

	req = (void *)buf->data;

	start_handle = sys_le16_to_cpu(req->start_handle);
	end_handle = sys_le16_to_cpu(req->end_handle);
	type = sys_le16_to_cpu(req->type);
	value = net_buf_pull(buf, sizeof(*req));

	BT_DBG("start_handle 0x%04x end_handle 0x%04x type %u", start_handle,
	       end_handle, type);

	if (!range_is_valid(start_handle, end_handle, &err_handle)) {
		send_err_rsp(conn, BT_ATT_OP_FIND_TYPE_REQ, err_handle,
			     BT_ATT_ERR_INVALID_HANDLE);
		return 0;
	}

	/* The Attribute Protocol Find By Type Value Request shall be used with
	 * the Attribute Type parameter set to the UUID for «Primary Service»
	 * and the Attribute Value set to the 16-bit Bluetooth UUID or 128-bit
	 * UUID for the specific primary service.
	 */
	if (type != BT_UUID_GATT_PRIMARY_VAL) {
		send_err_rsp(conn, BT_ATT_OP_FIND_TYPE_REQ, start_handle,
			     BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
		return 0;
	}

	return att_find_type_rsp(att, start_handle, end_handle, value,
				 buf->len);
}
Esempio n. 20
0
static void deserialize_ptr(struct net_buf *buf, uintptr_t *priv)
{
	memcpy(priv, buf->data, sizeof(*priv));
	net_buf_pull(buf, sizeof(*priv));
}
Esempio n. 21
0
struct net_pkt *
ieee802154_create_mac_cmd_frame(struct ieee802154_context *ctx,
				enum ieee802154_cfi type,
				struct ieee802154_frame_params *params)
{
	struct ieee802154_fcf_seq *fs;
	struct net_pkt *pkt;
	struct net_buf *frag;
	u8_t *p_buf;

	pkt = net_pkt_get_reserve_tx(0, K_FOREVER);
	if (!pkt) {
		return NULL;
	}

	frag = net_pkt_get_frag(pkt, K_FOREVER);
	if (!frag) {
		goto error;
	}

	net_pkt_frag_add(pkt, frag);
	p_buf = net_pkt_ll(pkt);

	fs = generate_fcf_grounds(&p_buf,
				  type == IEEE802154_CFI_BEACON_REQUEST ?
				  false : ctx->ack_requested);

	fs->fc.frame_type = IEEE802154_FRAME_TYPE_MAC_COMMAND;
	fs->sequence = ctx->sequence;

	if (!cfi_to_fs_settings(type, fs, params)) {
		goto error;
	}

	p_buf = generate_addressing_fields(ctx, fs, params, p_buf);

	/* Let's insert the cfi */
	((struct ieee802154_command *)p_buf)->cfi = type;

	/* In MAC command, we consider ll header being the mhr.
	 * Rest will be the MAC command itself. This will proove
	 * to be easy to handle afterwards to point directly to MAC
	 * command space, in order to fill-in its content.
	 */
	net_pkt_set_ll_reserve(pkt, p_buf - net_pkt_ll(pkt));
	net_buf_pull(frag, net_pkt_ll_reserve(pkt));

	/* Thus setting the right MAC command length
	 * Now up to the caller to fill-in this space relevantly.
	 * See ieee802154_mac_command() helper.
	 */
	frag->len = mac_command_length(type);

	dbg_print_fs(fs);

	return pkt;
error:
	net_pkt_unref(pkt);

	return NULL;
}
Esempio n. 22
0
void rpc_deserialize(struct net_buf *buf)
{

	uint8_t fn_index;
	uint8_t sig_type;

	sig_type = buf->data[0];
	fn_index = buf->data[1];

	net_buf_pull(buf, 2);

	switch (sig_type) {
	case SIG_TYPE_NONE:
		if (fn_index < ARRAY_SIZE(m_fct_none)) {
			BT_DBG("%s", debug_func_none[fn_index]);
			deserialize_none(fn_index, buf);
		}
		break;
	case SIG_TYPE_S:
		if (fn_index < ARRAY_SIZE(m_fct_s)) {
			BT_DBG("%s", debug_func_s[fn_index]);
			deserialize_s(fn_index, buf);
		}
		break;
	case SIG_TYPE_P:
		if (fn_index < ARRAY_SIZE(m_fct_p)) {
			BT_DBG("%s", debug_func_p[fn_index]);
			deserialize_p(fn_index, buf);
		}
		break;
	case SIG_TYPE_S_B:
		if (fn_index < ARRAY_SIZE(m_fct_s_b)) {
			BT_DBG("%s", debug_func_s_b[fn_index]);
			deserialize_s_b(fn_index, buf);
		}
		break;
	case SIG_TYPE_B_B_P:
		if (fn_index < ARRAY_SIZE(m_fct_b_b_p)) {
			BT_DBG("%s", debug_func_b_b_p[fn_index]);
			deserialize_b_b_p(fn_index, buf);
		}
		break;
	case SIG_TYPE_S_P:
		if (fn_index < ARRAY_SIZE(m_fct_s_p)) {
			BT_DBG("%s", debug_func_s_p[fn_index]);
			deserialize_s_p(fn_index, buf);
		}
		break;
	case SIG_TYPE_S_B_P:
		if (fn_index < ARRAY_SIZE(m_fct_s_b_p)) {
			BT_DBG("%s", debug_func_s_b_p[fn_index]);
			deserialize_s_b_p(fn_index, buf);
		}
		break;
	case SIG_TYPE_S_B_B_P:
		if (fn_index < ARRAY_SIZE(m_fct_s_b_b_p)) {
			BT_DBG("%s", debug_func_s_b_b_p[fn_index]);
			deserialize_s_b_b_p(fn_index, buf);
		}
		break;
	default:
		panic(-1);
		break;
	}
}
Esempio n. 23
0
int ssl_rx(void *context, unsigned char *buf, size_t size)
{
	struct http_client_ctx *ctx = context;
	struct rx_fifo_block *rx_data;
	u16_t read_bytes;
	u8_t *ptr;
	int pos;
	int len;
	int ret = 0;

	if (!ctx->https.mbedtls.ssl_ctx.frag) {
		rx_data = k_fifo_get(&ctx->https.mbedtls.ssl_ctx.rx_fifo,
				     K_FOREVER);
		if (!rx_data || !rx_data->pkt) {
			NET_DBG("Closing %p connection", ctx);

			if (rx_data) {
				k_mem_pool_free(&rx_data->block);
			}

			return MBEDTLS_ERR_SSL_CONN_EOF;
		}

		ctx->https.mbedtls.ssl_ctx.rx_pkt = rx_data->pkt;

		k_mem_pool_free(&rx_data->block);

		read_bytes = net_pkt_appdatalen(
					ctx->https.mbedtls.ssl_ctx.rx_pkt);

		ctx->https.mbedtls.ssl_ctx.remaining = read_bytes;
		ctx->https.mbedtls.ssl_ctx.frag =
			ctx->https.mbedtls.ssl_ctx.rx_pkt->frags;

		ptr = net_pkt_appdata(ctx->https.mbedtls.ssl_ctx.rx_pkt);
		len = ptr - ctx->https.mbedtls.ssl_ctx.frag->data;

		if (len > ctx->https.mbedtls.ssl_ctx.frag->size) {
			NET_ERR("Buf overflow (%d > %u)", len,
				ctx->https.mbedtls.ssl_ctx.frag->size);
			return -EINVAL;
		}

		/* This will get rid of IP header */
		net_buf_pull(ctx->https.mbedtls.ssl_ctx.frag, len);
	} else {
		read_bytes = ctx->https.mbedtls.ssl_ctx.remaining;
		ptr = ctx->https.mbedtls.ssl_ctx.frag->data;
	}

	len = ctx->https.mbedtls.ssl_ctx.frag->len;
	pos = 0;
	if (read_bytes > size) {
		while (ctx->https.mbedtls.ssl_ctx.frag) {
			read_bytes = len < (size - pos) ? len : (size - pos);

#if RX_EXTRA_DEBUG == 1
			NET_DBG("Copying %d bytes", read_bytes);
#endif

			memcpy(buf + pos, ptr, read_bytes);

			pos += read_bytes;
			if (pos < size) {
				ctx->https.mbedtls.ssl_ctx.frag =
					ctx->https.mbedtls.ssl_ctx.frag->frags;
				ptr = ctx->https.mbedtls.ssl_ctx.frag->data;
				len = ctx->https.mbedtls.ssl_ctx.frag->len;
			} else {
				if (read_bytes == len) {
					ctx->https.mbedtls.ssl_ctx.frag =
					ctx->https.mbedtls.ssl_ctx.frag->frags;
				} else {
					net_buf_pull(
					       ctx->https.mbedtls.ssl_ctx.frag,
					       read_bytes);
				}

				ctx->https.mbedtls.ssl_ctx.remaining -= size;
				return size;
			}
		}
	} else {
		while (ctx->https.mbedtls.ssl_ctx.frag) {
#if RX_EXTRA_DEBUG == 1
			NET_DBG("Copying all %d bytes", len);
#endif

			memcpy(buf + pos, ptr, len);

			pos += len;
			ctx->https.mbedtls.ssl_ctx.frag =
				ctx->https.mbedtls.ssl_ctx.frag->frags;
			if (!ctx->https.mbedtls.ssl_ctx.frag) {
				break;
			}

			ptr = ctx->https.mbedtls.ssl_ctx.frag->data;
			len = ctx->https.mbedtls.ssl_ctx.frag->len;
		}

		net_pkt_unref(ctx->https.mbedtls.ssl_ctx.rx_pkt);
		ctx->https.mbedtls.ssl_ctx.rx_pkt = NULL;
		ctx->https.mbedtls.ssl_ctx.frag = NULL;
		ctx->https.mbedtls.ssl_ctx.remaining = 0;

		if (read_bytes != pos) {
			return -EIO;
		}

		ret = read_bytes;
	}

	return ret;
}
Esempio n. 24
0
static void l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
	struct bt_l2cap *l2cap = CONTAINER_OF(chan, struct bt_l2cap, chan);
	struct bt_l2cap_sig_hdr *hdr = (void *)buf->data;
	uint16_t len;

	if (buf->len < sizeof(*hdr)) {
		BT_ERR("Too small L2CAP signaling PDU");
		return;
	}

	len = sys_le16_to_cpu(hdr->len);
	net_buf_pull(buf, sizeof(*hdr));

	BT_DBG("Signaling code 0x%02x ident %u len %u", hdr->code,
	       hdr->ident, len);

	if (buf->len != len) {
		BT_ERR("L2CAP length mismatch (%u != %u)", buf->len, len);
		return;
	}

	if (!hdr->ident) {
		BT_ERR("Invalid ident value in L2CAP PDU");
		return;
	}

	switch (hdr->code) {
	case BT_L2CAP_CONN_PARAM_RSP:
		le_conn_param_rsp(l2cap, buf);
		break;
#if defined(CONFIG_BLUETOOTH_CENTRAL)
	case BT_L2CAP_CONN_PARAM_REQ:
		le_conn_param_update_req(l2cap, hdr->ident, buf);
		break;
#endif /* CONFIG_BLUETOOTH_CENTRAL */
#if defined(CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL)
	case BT_L2CAP_LE_CONN_REQ:
		le_conn_req(l2cap, hdr->ident, buf);
		break;
	case BT_L2CAP_LE_CONN_RSP:
		le_conn_rsp(l2cap, hdr->ident, buf);
		break;
	case BT_L2CAP_DISCONN_REQ:
		le_disconn_req(l2cap, hdr->ident, buf);
		break;
	case BT_L2CAP_DISCONN_RSP:
		le_disconn_rsp(l2cap, hdr->ident, buf);
		break;
	case BT_L2CAP_LE_CREDITS:
		le_credits(l2cap, hdr->ident, buf);
		break;
	case BT_L2CAP_CMD_REJECT:
		reject_cmd(l2cap, hdr->ident, buf);
		break;
#else
	case BT_L2CAP_CMD_REJECT:
		/* Ignored */
		break;
#endif /* CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL */
	default:
		BT_WARN("Unknown L2CAP PDU code 0x%02x", hdr->code);
		l2cap_send_reject(chan->conn, hdr->ident,
				  BT_L2CAP_REJ_NOT_UNDERSTOOD, NULL, 0);
		break;
	}
}
Esempio n. 25
0
static void http_receive_cb(struct http_client_ctx *ctx,
			    struct net_pkt *pkt)
{
	size_t start = ctx->rsp.data_len;
	size_t len = 0;
	struct net_buf *frag;
	int header_len;

	if (!pkt) {
		return;
	}

	/* Get rid of possible IP headers in the first fragment. */
	frag = pkt->frags;

	header_len = net_pkt_appdata(pkt) - frag->data;

	NET_DBG("Received %d bytes data", net_pkt_appdatalen(pkt));

	/* After this pull, the frag->data points directly to application data.
	 */
	net_buf_pull(frag, header_len);

	while (frag) {
		/* If this fragment cannot be copied to result buf,
		 * then parse what we have which will cause the callback to be
		 * called in function on_body(), and continue copying.
		 */
		if (ctx->rsp.data_len + frag->len > ctx->rsp.response_buf_len) {

			/* If the caller has not supplied a callback, then
			 * we cannot really continue if the response buffer
			 * overflows. Set the data_len to mark how many bytes
			 * should be needed in the response_buf.
			 */
			if (!ctx->rsp.cb) {
				ctx->rsp.data_len = net_pkt_get_len(pkt);
				goto out;
			}

			http_parser_execute(&ctx->parser,
					    &ctx->settings,
					    ctx->rsp.response_buf + start,
					    len);

			ctx->rsp.data_len = 0;
			len = 0;
			start = 0;
		}

		memcpy(ctx->rsp.response_buf + ctx->rsp.data_len,
		       frag->data, frag->len);

		ctx->rsp.data_len += frag->len;
		len += frag->len;
		frag = frag->frags;
	}

out:
	/* The parser's error can be catched outside, reading the
	 * http_errno struct member
	 */
	http_parser_execute(&ctx->parser, &ctx->settings,
			    ctx->rsp.response_buf + start, len);

	net_pkt_unref(pkt);
}
Esempio n. 26
0
static struct net_pkt *build_reply_pkt(const char *name,
				       struct net_context *context,
				       struct net_pkt *pkt)
{
	struct net_pkt *reply_pkt;
	struct net_buf *frag, *tmp;
	int header_len, recv_len, reply_len;

	NET_INFO("%s received %d bytes", name,
		 net_pkt_appdatalen(pkt));

	if (net_pkt_appdatalen(pkt) == 0) {
		return NULL;
	}

	reply_pkt = net_pkt_get_tx(context, K_FOREVER);

	NET_ASSERT(reply_pkt);

	recv_len = net_pkt_get_len(pkt);

	tmp = pkt->frags;

	/* First fragment will contain IP header so move the data
	 * down in order to get rid of it.
	 */
	header_len = net_pkt_appdata(pkt) - tmp->data;

	NET_ASSERT(header_len < CONFIG_NET_BUF_DATA_SIZE);

	/* After this pull, the tmp->data points directly to application
	 * data.
	 */
	net_buf_pull(tmp, header_len);

	while (tmp) {
		frag = net_pkt_get_data(context, K_FOREVER);

		if (!net_buf_headroom(tmp)) {
			/* If there is no link layer headers in the
			 * received fragment, then get rid of that also
			 * in the sending fragment. We end up here
			 * if MTU is larger than fragment size, this
			 * is typical for ethernet.
			 */
			net_buf_push(frag, net_buf_headroom(frag));

			frag->len = 0; /* to make fragment empty */

			/* Make sure to set the reserve so that
			 * in sending side we add the link layer
			 * header if needed.
			 */
			net_pkt_set_ll_reserve(reply_pkt, 0);
		}

		NET_ASSERT(net_buf_tailroom(frag) >= tmp->len);

		memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len);

		net_pkt_frag_add(reply_pkt, frag);

		tmp = net_pkt_frag_del(pkt, NULL, tmp);
	}

	reply_len = net_pkt_get_len(reply_pkt);

	NET_ASSERT_INFO((recv_len - header_len) == reply_len,
			"Received %d bytes, sending %d bytes",
			recv_len - header_len, reply_len);

	return reply_pkt;
}