Beispiel #1
0
static void tcp_received(struct net_context *context,
			 struct net_pkt *pkt,
			 int status,
			 void *user_data)
{
	static char dbg[MAX_DBG_PRINT + 1];
	sa_family_t family = net_pkt_family(pkt);
	struct net_pkt *reply_pkt;
	int ret;

	snprintf(dbg, MAX_DBG_PRINT, "TCP IPv%c",
		 family == AF_INET6 ? '6' : '4');

	reply_pkt = build_reply_pkt(dbg, context, pkt);

	net_pkt_unref(pkt);

	ret = net_context_send(reply_pkt, pkt_sent, K_NO_WAIT,
			       UINT_TO_POINTER(net_pkt_get_len(reply_pkt)),
			       NULL);
	if (ret < 0) {
		printk("Cannot send data to peer (%d)", ret);
		net_pkt_unref(reply_pkt);

		quit();
	}
}
Beispiel #2
0
static void send_tcp_data(struct net_app_ctx *ctx,
			  struct data *data)
{
	struct net_pkt *pkt;
	size_t len;
	int ret;

	do {
		data->expecting_tcp = sys_rand32_get() % ipsum_len;
	} while (data->expecting_tcp == 0);

	data->received_tcp = 0;

	pkt = prepare_send_pkt(ctx, data->proto, data->expecting_tcp);
	if (!pkt) {
		return;
	}

	len = net_pkt_get_len(pkt);

	NET_ASSERT_INFO(data->expecting_tcp == len,
			"%s data to send %d bytes, real len %zu",
			data->proto, data->expecting_tcp, len);

	ret = net_app_send_pkt(ctx, pkt, NULL, 0, K_FOREVER,
			       UINT_TO_POINTER(len));
	if (ret < 0) {
		NET_ERR("Cannot send %s data to peer (%d)", data->proto, ret);
		net_pkt_unref(pkt);
	}
}
Beispiel #3
0
static void udp_received(struct net_context *context,
			 struct net_pkt *pkt,
			 int status,
			 void *user_data)
{
	struct net_pkt *reply_pkt;
	struct sockaddr dst_addr;
	sa_family_t family = net_pkt_family(pkt);
	static char dbg[MAX_DBG_PRINT + 1];
	int ret;

	snprintf(dbg, MAX_DBG_PRINT, "UDP IPv%c",
		 family == AF_INET6 ? '6' : '4');

	set_dst_addr(family, pkt, &dst_addr);

	reply_pkt = build_reply_pkt(dbg, context, pkt);

	net_pkt_unref(pkt);

	ret = net_context_sendto(reply_pkt, &dst_addr,
				 family == AF_INET6 ?
				 sizeof(struct sockaddr_in6) :
				 sizeof(struct sockaddr_in),
				 pkt_sent, 0,
				 UINT_TO_POINTER(net_pkt_get_len(reply_pkt)),
				 user_data);
	if (ret < 0) {
		printk("Cannot send data to peer (%d)", ret);
		net_pkt_unref(reply_pkt);
	}
}
Beispiel #4
0
int net_ipv4_finalize_raw(struct net_pkt *pkt, u8_t next_header)
{
	/* Set the length of the IPv4 header */
	size_t total_len;

	net_pkt_compact(pkt);

	total_len = net_pkt_get_len(pkt);

	NET_IPV4_HDR(pkt)->len[0] = total_len / 256;
	NET_IPV4_HDR(pkt)->len[1] = total_len - NET_IPV4_HDR(pkt)->len[0] * 256;

	NET_IPV4_HDR(pkt)->chksum = 0;
	NET_IPV4_HDR(pkt)->chksum = ~net_calc_chksum_ipv4(pkt);

#if defined(CONFIG_NET_UDP)
	if (next_header == IPPROTO_UDP) {
		NET_UDP_HDR(pkt)->chksum = 0;
		NET_UDP_HDR(pkt)->chksum = ~net_calc_chksum_udp(pkt);
	}
#endif
#if defined(CONFIG_NET_TCP)
	if (next_header == IPPROTO_TCP) {
		NET_TCP_HDR(pkt)->chksum = 0;
		NET_TCP_HDR(pkt)->chksum = ~net_calc_chksum_tcp(pkt);
	}
#endif

	return 0;
}
Beispiel #5
0
int udp_tx(void *context, const unsigned char *buf, size_t size)
{
	struct udp_context *ctx = context;
	struct net_context *net_ctx;
	struct net_pkt *send_pkt;

	int rc, len;

	net_ctx = ctx->net_ctx;

	send_pkt = net_pkt_get_tx(net_ctx, K_FOREVER);
	if (!send_pkt) {
		printk("cannot create pkt\n");
		return -EIO;
	}

	rc = net_pkt_append_all(send_pkt, size, (u8_t *) buf, K_FOREVER);
	if (!rc) {
		printk("cannot write buf\n");
		return -EIO;
	}

	len = net_pkt_get_len(send_pkt);

	rc = net_context_sendto(send_pkt, &net_ctx->remote,
				addrlen, NULL, K_FOREVER, NULL, NULL);

	if (rc < 0) {
		printk("Cannot send data to peer (%d)\n", rc);
		net_pkt_unref(send_pkt);
		return -EIO;
	} else {
		return len;
	}
}
Beispiel #6
0
int net_recv_data(struct net_if *iface, struct net_pkt *pkt)
{
	SYS_LOG_DBG("Got data, pkt %p, frags->len %d",
		    pkt, net_pkt_get_len(pkt));

	k_fifo_put(&tx_queue, pkt);

	return 0;
}
Beispiel #7
0
static enum net_verdict net_bt_recv(struct net_if *iface, struct net_pkt *pkt)
{
	NET_DBG("iface %p pkt %p len %zu", iface, pkt, net_pkt_get_len(pkt));

	if (!net_6lo_uncompress(pkt)) {
		NET_DBG("Packet decompression failed");
		return NET_DROP;
	}

	return NET_CONTINUE;
}
Beispiel #8
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;
}
Beispiel #9
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);
}
Beispiel #10
0
static void net_rx_thread(void)
{
	struct net_pkt *pkt;

	NET_DBG("Starting RX thread (stack %zu bytes)", sizeof(rx_stack));

	/* Starting TX side. The ordering is important here and the TX
	 * can only be started when RX side is ready to receive packets.
	 * We synchronize the startup of the device so that both RX and TX
	 * are only started fully when both are ready to receive or send
	 * data.
	 */
	net_if_init(&startup_sync);

	k_sem_take(&startup_sync, K_FOREVER);

	/* This will take the interface up and start everything. */
	net_if_post_init();

	while (1) {
#if defined(CONFIG_NET_STATISTICS) || defined(CONFIG_NET_DEBUG_CORE)
		size_t pkt_len;
#endif

		pkt = k_fifo_get(&rx_queue, K_FOREVER);

		net_analyze_stack("RX thread", rx_stack, sizeof(rx_stack));

#if defined(CONFIG_NET_STATISTICS) || defined(CONFIG_NET_DEBUG_CORE)
		pkt_len = net_pkt_get_len(pkt);
#endif
		NET_DBG("Received pkt %p len %zu", pkt, pkt_len);

		net_stats_update_bytes_recv(pkt_len);

		processing_data(pkt, false);

		net_print_statistics();
		net_pkt_print();

		k_yield();
	}
}
Beispiel #11
0
bool ieee802154_decipher_data_frame(struct net_if *iface, struct net_pkt *pkt,
				    struct ieee802154_mpdu *mpdu)
{
	struct ieee802154_context *ctx = net_if_l2_data(iface);
	u8_t level;

	if (!mpdu->mhr.fs->fc.security_enabled) {
		return true;
	}

	/* Section 7.2.3 (i) talks about "security level policy" conformance
	 * but such policy does not seem to be detailed. So let's assume both
	 * ends should have same security level.
	 */
	if (mpdu->mhr.aux_sec->control.security_level != ctx->sec_ctx.level) {
		return false;
	}

	/* ToDo: handle src short address
	 * This will require to look up in nbr cache with short addr
	 * in order to get the extended address related to it
	 */
	if (!ieee802154_decrypt_auth(&ctx->sec_ctx, net_pkt_ll(pkt),
				     net_pkt_ll_reserve(pkt),
				     net_pkt_get_len(pkt),
				     net_pkt_ll_src(pkt)->addr,
				     sys_le32_to_cpu(
					mpdu->mhr.aux_sec->frame_counter))) {
		NET_ERR("Could not decipher the frame");
		return false;
	}

	level = ctx->sec_ctx.level;
	if (level >= IEEE802154_SECURITY_LEVEL_ENC) {
		level -= 4;
	}

	/* We remove tag size from frag's length, it is now useless */
	pkt->frags->len -= level_2_tag_size[level];

	return true;
}
Beispiel #12
0
static enum net_verdict net_bt_send(struct net_if *iface, struct net_pkt *pkt)
{
	struct bt_context *ctxt = net_if_get_device(iface)->driver_data;

	NET_DBG("iface %p pkt %p len %zu", iface, pkt, net_pkt_get_len(pkt));

	/* Only accept IPv6 packets */
	if (net_pkt_family(pkt) != AF_INET6) {
		return NET_DROP;
	}

	if (!net_6lo_compress(pkt, true, NULL)) {
		NET_DBG("Packet compression failed");
		return NET_DROP;
	}

	net_if_queue_tx(ctxt->iface, pkt);

	return NET_OK;
}
Beispiel #13
0
static int bt_iface_send(struct net_if *iface, struct net_pkt *pkt)
{
	struct bt_context *ctxt = net_if_get_device(iface)->driver_data;
	struct net_buf *frags;
	int ret;

	NET_DBG("iface %p pkt %p len %zu", iface, pkt, net_pkt_get_len(pkt));

	/* Dettach data fragments for packet */
	frags = pkt->frags;
	pkt->frags = NULL;

	net_pkt_unref(pkt);

	ret = bt_l2cap_chan_send(&ctxt->ipsp_chan.chan, frags);
	if (ret < 0) {
		return ret;
	}

	return ret;
}
Beispiel #14
0
/**
 * TX - transmit to SLIP interface
 */
static void tx_thread(void)
{
	SYS_LOG_DBG("TX thread started");

	/* Allow to send one TX */
	k_sem_give(&tx_sem);

	while (1) {
		struct net_pkt *pkt;
		struct net_buf *buf;
		size_t len;

		k_sem_take(&tx_sem, K_FOREVER);

		pkt = k_fifo_get(&tx_queue, K_FOREVER);
		buf = net_buf_frag_last(pkt->frags);
		len = net_pkt_get_len(pkt);

		SYS_LOG_DBG("Send pkt %p buf %p len %d", pkt, buf, len);

		hexdump("SLIP <", buf->data, buf->len);

		/* Remove LQI */
		/* TODO: Reuse get_lqi() */
		buf->len -= 1;

		/* remove FCS 2 bytes */
		buf->len -= 2;

		/* SLIP encode and send */
		len = slip_buffer(slip_buf, buf);
		uart_fifo_fill(uart_dev, slip_buf, len);

		net_pkt_unref(pkt);

#if 0
		k_yield();
#endif
	}
}
Beispiel #15
0
/* Called by driver when an IP packet has been received */
int net_recv_data(struct net_if *iface, struct net_pkt *pkt)
{
	NET_ASSERT(pkt && pkt->frags);
	NET_ASSERT(iface);

	if (!pkt->frags) {
		return -ENODATA;
	}

	if (!atomic_test_bit(iface->flags, NET_IF_UP)) {
		return -ENETDOWN;
	}

	NET_DBG("fifo %p iface %p pkt %p len %zu", &rx_queue, iface, pkt,
		net_pkt_get_len(pkt));

	net_pkt_set_iface(pkt, iface);

	k_fifo_put(&rx_queue, pkt);

	return 0;
}
Beispiel #16
0
static inline void telnet_handle_input(struct net_pkt *pkt)
{
	struct console_input *input;
	u16_t len, offset, pos;

	len = net_pkt_appdatalen(pkt);
	if (len > CONSOLE_MAX_LINE_LEN || len < TELNET_MIN_MSG) {
		return;
	}

	if (telnet_handle_command(pkt)) {
		return;
	}

	if (!avail_queue || !input_queue) {
		return;
	}

	input = k_fifo_get(avail_queue, K_NO_WAIT);
	if (!input) {
		return;
	}

	offset = net_pkt_get_len(pkt) - len;
	net_frag_read(pkt->frags, offset, &pos, len, input->line);

	/* LF/CR will be removed if only the line is not NUL terminated */
	if (input->line[len-1] != NVT_NUL) {
		if (input->line[len-1] == NVT_LF) {
			input->line[len-1] = NVT_NUL;
		}

		if (input->line[len-2] == NVT_CR) {
			input->line[len-2] = NVT_NUL;
		}
	}

	k_fifo_put(input_queue, input);
}
Beispiel #17
0
static int eth_send(struct device *dev, struct net_pkt *pkt)
{
	struct eth_context *ctx = dev->driver_data;
	int count = net_pkt_get_len(pkt);
	int ret;

	ret = net_pkt_read(pkt, ctx->send, count);
	if (ret) {
		return ret;
	}

	update_gptp(net_pkt_iface(pkt), pkt, true);

	LOG_DBG("Send pkt %p len %d", pkt, count);

	ret = eth_write_data(ctx->dev_fd, ctx->send, count);
	if (ret < 0) {
		LOG_DBG("Cannot send pkt %p (%d)", pkt, ret);
	}

	return ret < 0 ? ret : 0;
}
Beispiel #18
0
static void test_fragment_compact(void)
{
	struct net_pkt *pkt;
	struct net_buf *frags[FRAG_COUNT], *frag;
	int i, bytes, total, count;

	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	frag = NULL;

	for (i = 0, total = 0; i < FRAG_COUNT; i++) {
		frags[i] = net_pkt_get_reserve_rx_data(12, K_FOREVER);

		if (frag) {
			net_buf_frag_add(frag, frags[i]);
		}

		frag = frags[i];

		/* Copy character test data in front of the fragment */
		memcpy(net_buf_add(frags[i], sizeof(test_data)),
		       test_data, sizeof(test_data));

		/* Followed by bytes of zeroes */
		memset(net_buf_add(frags[i], sizeof(test_data)), 0,
		       sizeof(test_data));

		total++;
	}

	if (total != FRAG_COUNT) {
		printk("There should be %d fragments but was %d\n",
		       FRAG_COUNT, total);
		zassert_true(false, "Invalid fragment count");
	}

	DBG("step 1\n");

	pkt->frags = net_buf_frag_add(pkt->frags, frags[0]);

	bytes = net_pkt_get_len(pkt);
	if (bytes != FRAG_COUNT * sizeof(test_data) * 2) {
		printk("Compact test failed, fragments had %d bytes but "
		       "should have had %zd\n", bytes,
		       FRAG_COUNT * sizeof(test_data) * 2);
		zassert_true(false, "Invalid fragment bytes");
	}

	zassert_false(net_pkt_is_compact(pkt),
		      "The pkt is definitely not compact");

	DBG("step 2\n");

	net_pkt_compact(pkt);

	zassert_true(net_pkt_is_compact(pkt),
		     "The pkt should be in compact form");

	DBG("step 3\n");

	/* Try compacting again, nothing should happen */
	net_pkt_compact(pkt);

	zassert_true(net_pkt_is_compact(pkt),
		     "The pkt should be compacted now");

	total = calc_fragments(pkt);

	/* Add empty fragment at the end and compact, the last fragment
	 * should be removed.
	 */
	frag = net_pkt_get_reserve_rx_data(0, K_FOREVER);

	net_pkt_frag_add(pkt, frag);

	count = calc_fragments(pkt);

	DBG("step 4\n");

	net_pkt_compact(pkt);

	i = calc_fragments(pkt);

	if (count != (i + 1)) {
		printk("Last fragment removal failed, chain should have %d "
		       "fragments but had %d\n", i-1, i);
		zassert_true(false, "Last frag rm fails");
	}

	if (i != total) {
		printk("Fragments missing, expecting %d but got %d\n",
		       total, i);
		zassert_true(false, "Frags missing");
	}

	/* Add two empty fragments at the end and compact, the last two
	 * fragment should be removed.
	 */
	frag = net_pkt_get_reserve_rx_data(0, K_FOREVER);

	net_pkt_frag_add(pkt, frag);

	frag = net_pkt_get_reserve_rx_data(0, K_FOREVER);

	net_pkt_frag_add(pkt, frag);

	count = calc_fragments(pkt);

	DBG("step 5\n");

	net_pkt_compact(pkt);

	i = calc_fragments(pkt);

	if (count != (i + 2)) {
		printk("Last two fragment removal failed, chain should have "
		       "%d fragments but had %d\n", i-2, i);
		zassert_true(false, "Last two frag rm fails");
	}

	if (i != total) {
		printk("Fragments missing, expecting %d but got %d\n",
		       total, i);
		zassert_true(false, "Frags missing");
	}

	/* Add empty fragment at the beginning and at the end, and then
	 * compact, the two fragment should be removed.
	 */
	frag = net_pkt_get_reserve_rx_data(0, K_FOREVER);

	net_pkt_frag_insert(pkt, frag);

	frag = net_pkt_get_reserve_rx_data(0, K_FOREVER);

	net_pkt_frag_add(pkt, frag);

	count = calc_fragments(pkt);

	DBG("step 6\n");

	net_pkt_compact(pkt);

	i = calc_fragments(pkt);

	if (count != (i + 2)) {
		printk("Two fragment removal failed, chain should have "
		       "%d fragments but had %d\n", i-2, i);
		zassert_true(false, "Two frag rm fails");
	}

	if (i != total) {
		printk("Fragments missing, expecting %d but got %d\n",
		       total, i);
		zassert_true(false, "Frags missing");
	}

	DBG("test_fragment_compact passed\n");
}
Beispiel #19
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;
}
Beispiel #20
0
static void test_pkt_read_append(void)
{
	int remaining = strlen(sample_data);
	u8_t verify_rw_short[sizeof(test_rw_short)];
	u8_t verify_rw_long[sizeof(test_rw_long)];
	struct net_pkt *pkt;
	struct net_buf *frag;
	struct net_buf *tfrag;
	struct ipv6_hdr *ipv6;
	struct udp_hdr *udp;
	u8_t data[10];
	int pos = 0;
	int bytes;
	u16_t off;
	u16_t tpos;
	u16_t fail_pos;

	/* Example of multi fragment read, append and skip APS's */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER);

	/* Place the IP + UDP header in the first fragment */
	if (!net_buf_tailroom(frag)) {
		ipv6 = (struct ipv6_hdr *)(frag->data);
		udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6));
		if (net_buf_tailroom(frag) < sizeof(ipv6)) {
			printk("Not enough space for IPv6 header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(ipv6), net_buf_tailroom(frag));
			zassert_true(false, "No space for IPv6 header");
		}
		net_buf_add(frag, sizeof(ipv6));

		if (net_buf_tailroom(frag) < sizeof(udp)) {
			printk("Not enough space for UDP header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(udp), net_buf_tailroom(frag));
			zassert_true(false, "No space for UDP header");
		}

		net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp));
		net_pkt_set_appdatalen(pkt, 0);
	}

	net_pkt_frag_add(pkt, frag);

	/* Put some data to rest of the fragments */
	frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER);
	if (net_buf_tailroom(frag) -
	      (CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE)) {
		printk("Invalid number of bytes available in the buf, "
		       "should be 0 but was %zd - %d\n",
		       net_buf_tailroom(frag),
		       CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE);
		zassert_true(false, "Invalid number of bytes avail");
	}

	if (((int)net_buf_tailroom(frag) - remaining) > 0) {
		printk("We should have been out of space now, "
		       "tailroom %zd user data len %zd\n",
		       net_buf_tailroom(frag),
		       strlen(sample_data));
		zassert_true(false, "Not out of space");
	}

	while (remaining > 0) {
		int copy;

		bytes = net_buf_tailroom(frag);
		copy = remaining > bytes ? bytes : remaining;
		memcpy(net_buf_add(frag, copy), &sample_data[pos], copy);

		DBG("Remaining %d left %d copy %d\n", remaining, bytes, copy);

		pos += bytes;
		remaining -= bytes;
		if (net_buf_tailroom(frag) - (bytes - copy)) {
			printk("There should have not been any tailroom left, "
			       "tailroom %zd\n",
			       net_buf_tailroom(frag) - (bytes - copy));
			zassert_true(false, "Still tailroom left");
		}

		net_pkt_frag_add(pkt, frag);
		if (remaining > 0) {
			frag = net_pkt_get_reserve_rx_data(LL_RESERVE,
							   K_FOREVER);
		}
	}

	bytes = net_pkt_get_len(pkt);
	if (bytes != strlen(sample_data)) {
		printk("Invalid number of bytes in message, %zd vs %d\n",
		       strlen(sample_data), bytes);
		zassert_true(false, "Message size wrong");
	}

	/* Failure cases */
	/* Invalid buffer */
	tfrag = net_frag_skip(NULL, 10, &fail_pos, 10);
	zassert_true(!tfrag && fail_pos == 0xffff, "Invalid case NULL buffer");

	/* Invalid: Skip more than a buffer length.*/
	tfrag = net_buf_frag_last(pkt->frags);
	tfrag = net_frag_skip(tfrag, tfrag->len - 1, &fail_pos, tfrag->len + 2);
	if (!(!tfrag && fail_pos == 0xffff)) {
		printk("Invalid case offset %d length to skip %d,"
		       "frag length %d\n",
		       tfrag->len - 1, tfrag->len + 2, tfrag->len);
		zassert_true(false, "Invalid offset");
	}

	/* Invalid offset */
	tfrag = net_buf_frag_last(pkt->frags);
	tfrag = net_frag_skip(tfrag, tfrag->len + 10, &fail_pos, 10);
	if (!(!tfrag && fail_pos == 0xffff)) {
		printk("Invalid case offset %d length to skip %d,"
		       "frag length %d\n",
		       tfrag->len + 10, 10, tfrag->len);
		zassert_true(false, "Invalid offset");
	}

	/* Valid cases */

	/* Offset is more than single fragment length */
	/* Get the first data fragment */
	tfrag = pkt->frags;
	tfrag = tfrag->frags;
	off = tfrag->len;
	tfrag = net_frag_read(tfrag, off + 10, &tpos, 10, data);
	if (!tfrag ||
	    memcmp(sample_data + off + 10, data, 10)) {
		printk("Failed to read from offset %d, frag length %d "
		       "read length %d\n",
		       tfrag->len + 10, tfrag->len, 10);
		zassert_true(false, "Fail offset read");
	}

	/* Skip till end of all fragments */
	/* Get the first data fragment */
	tfrag = pkt->frags;
	tfrag = tfrag->frags;
	tfrag = net_frag_skip(tfrag, 0, &tpos, strlen(sample_data));
	zassert_true(!tfrag && tpos == 0,
		     "Invalid skip till end of all fragments");

	/* Short data test case */
	/* Test case scenario:
	 * 1) Cache the current fragment and offset
	 * 2) Append short data
	 * 3) Append short data again
	 * 4) Skip first short data from cached frag or offset
	 * 5) Read short data and compare
	 */
	tfrag = net_buf_frag_last(pkt->frags);
	off = tfrag->len;

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short),
					test_rw_short, K_FOREVER),
		     "net_pkt_append failed");

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short),
					test_rw_short, K_FOREVER),
		     "net_pkt_append failed");

	tfrag = net_frag_skip(tfrag, off, &tpos,
			     (u16_t)sizeof(test_rw_short));
	zassert_not_null(tfrag, "net_frag_skip failed");

	tfrag = net_frag_read(tfrag, tpos, &tpos,
			     (u16_t)sizeof(test_rw_short),
			     verify_rw_short);
	zassert_true(!tfrag && tpos == 0, "net_frag_read failed");
	zassert_false(memcmp(test_rw_short, verify_rw_short,
			     sizeof(test_rw_short)),
		      "net_frag_read failed with mismatch data");

	/* Long data test case */
	/* Test case scenario:
	 * 1) Cache the current fragment and offset
	 * 2) Append long data
	 * 3) Append long data again
	 * 4) Skip first long data from cached frag or offset
	 * 5) Read long data and compare
	 */
	tfrag = net_buf_frag_last(pkt->frags);
	off = tfrag->len;

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long),
					test_rw_long, K_FOREVER),
		     "net_pkt_append failed");

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long),
					test_rw_long, K_FOREVER),
		     "net_pkt_append failed");

	tfrag = net_frag_skip(tfrag, off, &tpos,
			      (u16_t)sizeof(test_rw_long));
	zassert_not_null(tfrag, "net_frag_skip failed");

	tfrag = net_frag_read(tfrag, tpos, &tpos,
			     (u16_t)sizeof(test_rw_long),
			     verify_rw_long);
	zassert_true(!tfrag && tpos == 0, "net_frag_read failed");
	zassert_false(memcmp(test_rw_long, verify_rw_long,
			     sizeof(test_rw_long)),
		      "net_frag_read failed with mismatch data");

	net_pkt_unref(pkt);

	DBG("test_pkt_read_append passed\n");
}
Beispiel #21
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);
}
Beispiel #22
0
void http_rx_tx(struct net_context *net_ctx, struct net_pkt *rx, int status,
		void *user_data)
{
	struct http_server_ctx *http_ctx = NULL;
	struct net_buf *data = NULL;
	u16_t rcv_len;
	u16_t offset;
	int parsed_len;
	int rc;

	if (status) {
		printf("[%s:%d] Status code: %d, <%s>\n",
			__func__, __LINE__, status, RC_STR(status));
		goto lb_exit;
	}

	if (!user_data) {
		printf("[%s:%d] User data is null\n", __func__, __LINE__);
		goto lb_exit;
	}

	http_ctx = (struct http_server_ctx *)user_data;
	if (http_ctx->net_ctx != net_ctx) {
		printf("[%s:%d] Wrong network context received\n",
		       __func__, __LINE__);
		goto lb_exit;
	}

	if (!rx) {
		printf("[%s:%d] Connection closed by peer\n",
		       __func__, __LINE__);
		goto lb_exit;
	}

	rcv_len = net_pkt_appdatalen(rx);
	if (rcv_len == 0) {
		/* don't print info about zero-length app data buffers */
		goto lb_exit;
	}

	data = net_buf_alloc(&http_msg_pool, APP_SLEEP_MSECS);
	if (data == NULL) {
		printf("[%s:%d] Data buffer alloc error\n", __func__, __LINE__);
		goto lb_exit;
	}

	offset = net_pkt_get_len(rx) - rcv_len;
	rc = net_frag_linear_copy(data, rx->frags, offset, rcv_len);
	if (rc != 0) {
		printf("[%s:%d] Linear copy error\n", __func__, __LINE__);
		goto lb_exit;
	}

	data->data[min(data->size - 1, rcv_len)] = 0;

	parser_init(http_ctx);
	parsed_len = parser_parse_request(http_ctx, data);
	if (parsed_len <= 0) {
		printf("[%s:%d] Received: %u bytes, only parsed: %d bytes\n",
		       __func__, __LINE__, rcv_len, parsed_len);
	}

	if (http_ctx->parser.http_errno != HPE_OK) {
		http_response_400(http_ctx, NULL);
	} else {
		http_tx(http_ctx);
	}

lb_exit:
	net_pkt_frag_unref(data);
	net_pkt_unref(rx);

	http_ctx_release(http_ctx);
}
Beispiel #23
0
static void test_fragment_copy(void)
{
	struct net_pkt *pkt, *new_pkt;
	struct net_buf *frag, *new_frag;
	struct ipv6_hdr *ipv6;
	struct udp_hdr *udp;
	size_t orig_len, reserve;
	int pos;

	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER);

	/* Place the IP + UDP header in the first fragment */
	if (net_buf_tailroom(frag)) {
		ipv6 = (struct ipv6_hdr *)(frag->data);
		udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6));
		if (net_buf_tailroom(frag) < sizeof(*ipv6)) {
			printk("Not enough space for IPv6 header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(ipv6), net_buf_tailroom(frag));
			zassert_true(false, "No space for IPv6 header");
		}
		net_buf_add(frag, sizeof(*ipv6));

		if (net_buf_tailroom(frag) < sizeof(*udp)) {
			printk("Not enough space for UDP header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(udp), net_buf_tailroom(frag));
			zassert_true(false, "No space for UDP header");
		}

		net_buf_add(frag, sizeof(*udp));

		memcpy(net_buf_add(frag, 15), example_data, 15);

		net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp) + 15);
		net_pkt_set_appdatalen(pkt, 0);
	}

	net_pkt_frag_add(pkt, frag);

	orig_len = net_pkt_get_len(pkt);

	DBG("Total copy data len %zd\n", orig_len);

	linearize(pkt, buf_orig, orig_len);

	/* Then copy a fragment list to a new fragment list.
	 * Reserve some space in front of the buffers.
	 */
	reserve = sizeof(struct ipv6_hdr) + sizeof(struct icmp_hdr);
	new_frag = net_pkt_copy_all(pkt, reserve, K_FOREVER);
	zassert_not_null(new_frag, "Cannot copy fragment list");

	new_pkt = net_pkt_get_reserve_tx(0, K_FOREVER);
	new_pkt->frags = net_buf_frag_add(new_pkt->frags, new_frag);

	DBG("Total new data len %zd\n", net_pkt_get_len(new_pkt));

	if ((net_pkt_get_len(pkt) + reserve) != net_pkt_get_len(new_pkt)) {
		int diff;

		diff = net_pkt_get_len(new_pkt) - reserve -
			net_pkt_get_len(pkt);

		printk("Fragment list missing data, %d bytes not copied "
		       "(%zd vs %zd)\n", diff,
		       net_pkt_get_len(pkt) + reserve,
		       net_pkt_get_len(new_pkt));
		zassert_true(false, "Frag list missing");
	}

	if (net_pkt_get_len(new_pkt) != (orig_len + sizeof(struct ipv6_hdr) +
					   sizeof(struct icmp_hdr))) {
		printk("Fragment list missing data, new pkt len %zd "
		       "should be %zd\n", net_pkt_get_len(new_pkt),
		       orig_len + sizeof(struct ipv6_hdr) +
		       sizeof(struct icmp_hdr));
		zassert_true(false, "Frag list missing data");
	}

	linearize(new_pkt, buf_copy, sizeof(buf_copy));

	zassert_true(memcmp(buf_orig, buf_copy, sizeof(buf_orig)),
		     "Buffer copy failed, buffers are same");

	pos = memcmp(buf_orig, buf_copy + sizeof(struct ipv6_hdr) +
		     sizeof(struct icmp_hdr), orig_len);
	if (pos) {
		printk("Buffer copy failed at pos %d\n", pos);
		zassert_true(false, "Buf copy failed");
	}
}
Beispiel #24
0
static void test_ipv6_multi_frags(void)
{
	struct net_pkt *pkt;
	struct net_buf *frag;
	struct ipv6_hdr *ipv6;
	struct udp_hdr *udp;
	int bytes, remaining = strlen(example_data), pos = 0;

	/* Example of multi fragment scenario with IPv6 */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER);

	/* Place the IP + UDP header in the first fragment */
	if (!net_buf_tailroom(frag)) {
		ipv6 = (struct ipv6_hdr *)(frag->data);
		udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6));
		if (net_buf_tailroom(frag) < sizeof(ipv6)) {
			printk("Not enough space for IPv6 header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(ipv6), net_buf_tailroom(frag));
			zassert_true(false, "No space for IPv6 header");
		}
		net_buf_add(frag, sizeof(ipv6));

		if (net_buf_tailroom(frag) < sizeof(udp)) {
			printk("Not enough space for UDP header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(udp), net_buf_tailroom(frag));
			zassert_true(false, "No space for UDP header");
		}

		net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp));
		net_pkt_set_appdatalen(pkt, 0);
	}

	net_pkt_frag_add(pkt, frag);

	/* Put some data to rest of the fragments */
	frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER);
	if (net_buf_tailroom(frag) -
	      (CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE)) {
		printk("Invalid number of bytes available in the buf, "
		       "should be 0 but was %zd - %d\n",
		       net_buf_tailroom(frag),
		       CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE);
		zassert_true(false, "Invalid byte count");
	}

	if (((int)net_buf_tailroom(frag) - remaining) > 0) {
		printk("We should have been out of space now, "
		       "tailroom %zd user data len %zd\n",
		       net_buf_tailroom(frag),
		       strlen(example_data));
		zassert_true(false, "Still space");
	}

	while (remaining > 0) {
		int copy;

		bytes = net_buf_tailroom(frag);
		copy = remaining > bytes ? bytes : remaining;
		memcpy(net_buf_add(frag, copy), &example_data[pos], copy);

		DBG("Remaining %d left %d copy %d\n", remaining, bytes, copy);

		pos += bytes;
		remaining -= bytes;
		if (net_buf_tailroom(frag) - (bytes - copy)) {
			printk("There should have not been any tailroom left, "
			       "tailroom %zd\n",
			       net_buf_tailroom(frag) - (bytes - copy));
			zassert_true(false, "There is still tailroom left");
		}

		net_pkt_frag_add(pkt, frag);
		if (remaining > 0) {
			frag = net_pkt_get_reserve_rx_data(LL_RESERVE,
							   K_FOREVER);
		}
	}

	bytes = net_pkt_get_len(pkt);
	if (bytes != strlen(example_data)) {
		printk("Invalid number of bytes in message, %zd vs %d\n",
		       strlen(example_data), bytes);
		zassert_true(false, "Invalid number of bytes");
	}

	/* Normally one should not unref the fragment list like this
	 * because it will leave the pkt->frags pointing to already
	 * freed fragment.
	 */
	net_pkt_frag_unref(pkt->frags);

	zassert_not_null(pkt->frags, "Frag list empty");

	pkt->frags = NULL; /* to prevent double free */

	net_pkt_unref(pkt);
}
Beispiel #25
0
int http_request(struct http_client_ctx *ctx,
		 struct http_client_request *req,
		 s32_t timeout)
{
	const char *method = http_method_str(req->method);
	struct net_pkt *pkt;
	int ret = -ENOMEM;

	pkt = net_pkt_get_tx(ctx->tcp.ctx, timeout);
	if (!pkt) {
		return -ENOMEM;
	}

	if (!net_pkt_append_all(pkt, strlen(method), (u8_t *)method,
				timeout)) {
		goto out;
	}

	/* Space after method string. */
	if (!net_pkt_append_all(pkt, 1, (u8_t *)" ", timeout)) {
		goto out;
	}

	if (!net_pkt_append_all(pkt, strlen(req->url), (u8_t *)req->url,
				timeout)) {
		goto out;
	}

	if (!net_pkt_append_all(pkt, strlen(req->protocol),
				(u8_t *)req->protocol, timeout)) {
		goto out;
	}

	if (req->host) {
		if (!net_pkt_append_all(pkt, strlen(HTTP_HOST),
					(u8_t *)HTTP_HOST, timeout)) {
			goto out;
		}

		if (!net_pkt_append_all(pkt, strlen(req->host),
					(u8_t *)req->host, timeout)) {
			goto out;
		}

		if (!net_pkt_append_all(pkt, strlen(HTTP_CRLF),
					(u8_t *)HTTP_CRLF, timeout)) {
			goto out;
		}
	}

	if (req->header_fields) {
		if (!net_pkt_append_all(pkt, strlen(req->header_fields),
					(u8_t *)req->header_fields,
					timeout)) {
			goto out;
		}
	}

	if (req->content_type_value) {
		if (!net_pkt_append_all(pkt, strlen(HTTP_CONTENT_TYPE),
					(u8_t *)HTTP_CONTENT_TYPE,
					timeout)) {
			goto out;
		}

		if (!net_pkt_append_all(pkt, strlen(req->content_type_value),
					(u8_t *)req->content_type_value,
					timeout)) {
			goto out;
		}
	}

	if (req->payload && req->payload_size) {
		char content_len_str[HTTP_CONT_LEN_SIZE];

		ret = snprintk(content_len_str, HTTP_CONT_LEN_SIZE,
			       HTTP_CRLF "Content-Length: %u"
			       HTTP_CRLF HTTP_CRLF,
			       req->payload_size);
		if (ret <= 0 || ret >= HTTP_CONT_LEN_SIZE) {
			ret = -ENOMEM;
			goto out;
		}

		if (!net_pkt_append_all(pkt, ret, (u8_t *)content_len_str,
					timeout)) {
			ret = -ENOMEM;
			goto out;
		}

		if (!net_pkt_append_all(pkt, req->payload_size,
					(u8_t *)req->payload,
					timeout)) {
			ret = -ENOMEM;
			goto out;
		}
	} else {
		if (!net_pkt_append_all(pkt, strlen(HTTP_EOF),
					(u8_t *)HTTP_EOF,
					timeout)) {
			goto out;
		}
	}

#if defined(CONFIG_NET_IPV6)
	if (net_pkt_family(pkt) == AF_INET6) {
		net_pkt_set_appdatalen(pkt, net_pkt_get_len(pkt) -
				       net_pkt_ip_hdr_len(pkt) -
				       net_pkt_ipv6_ext_opt_len(pkt));
	} else
#endif
	{
		net_pkt_set_appdatalen(pkt, net_pkt_get_len(pkt) -
				       net_pkt_ip_hdr_len(pkt));
	}

	ret = ctx->tcp.send_data(pkt, NULL, timeout, NULL, ctx);
	if (ret == 0) {
		return 0;
	}

out:
	net_pkt_unref(pkt);

	return ret;
}
Beispiel #26
0
enum net_verdict net_ipv4_process_pkt(struct net_pkt *pkt)
{
	struct net_ipv4_hdr *hdr = NET_IPV4_HDR(pkt);
	int real_len = net_pkt_get_len(pkt);
	int pkt_len = (hdr->len[0] << 8) + hdr->len[1];
	enum net_verdict verdict = NET_DROP;

	if (real_len != pkt_len) {
		NET_DBG("IPv4 packet size %d pkt len %d", pkt_len, real_len);
		goto drop;
	}

#if defined(CONFIG_NET_DEBUG_IPV4)
	do {
		char out[sizeof("xxx.xxx.xxx.xxx")];

		snprintk(out, sizeof(out), "%s",
			 net_sprint_ipv4_addr(&hdr->dst));
		NET_DBG("IPv4 packet received from %s to %s",
			net_sprint_ipv4_addr(&hdr->src), out);
	} while (0);
#endif /* CONFIG_NET_DEBUG_IPV4 */

	net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));

	if (!net_is_my_ipv4_addr(&hdr->dst)) {
#if defined(CONFIG_NET_DHCPV4)
		if (hdr->proto == IPPROTO_UDP &&
		    net_ipv4_addr_cmp(&hdr->dst,
				      net_ipv4_broadcast_address())) {

			verdict = net_conn_input(IPPROTO_UDP, pkt);
			if (verdict != NET_DROP) {
				return verdict;
			}
		}
#endif
		NET_DBG("IPv4 packet in pkt %p not for me", pkt);
		goto drop;
	}

	switch (hdr->proto) {
	case IPPROTO_ICMP:
		verdict = process_icmpv4_pkt(pkt, hdr);
		break;
	case IPPROTO_UDP:
		verdict = net_conn_input(IPPROTO_UDP, pkt);
		break;
	case IPPROTO_TCP:
		verdict = net_conn_input(IPPROTO_TCP, pkt);
		break;
	}

	if (verdict != NET_DROP) {
		return verdict;
	}

drop:
	net_stats_update_ipv4_drop();
	return NET_DROP;
}