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 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 #3
0
u16_t net_calc_chksum(struct net_pkt *pkt, u8_t proto)
{
	u16_t upper_layer_len;
	u16_t sum;

	switch (net_pkt_family(pkt)) {
#if defined(CONFIG_NET_IPV4)
	case AF_INET:
		upper_layer_len = (NET_IPV4_HDR(pkt)->len[0] << 8) +
			NET_IPV4_HDR(pkt)->len[1] -
			net_pkt_ipv6_ext_len(pkt) -
			net_pkt_ip_hdr_len(pkt);

		if (proto == IPPROTO_ICMP) {
			return htons(calc_chksum(0, net_pkt_ip_data(pkt) +
						 net_pkt_ip_hdr_len(pkt),
						 upper_layer_len));
		} else {
			sum = calc_chksum(upper_layer_len + proto,
					  (u8_t *)&NET_IPV4_HDR(pkt)->src,
					  2 * sizeof(struct in_addr));
		}
		break;
#endif
#if defined(CONFIG_NET_IPV6)
	case AF_INET6:
		upper_layer_len = (NET_IPV6_HDR(pkt)->len[0] << 8) +
			NET_IPV6_HDR(pkt)->len[1] - net_pkt_ipv6_ext_len(pkt);
		sum = calc_chksum(upper_layer_len + proto,
				  (u8_t *)&NET_IPV6_HDR(pkt)->src,
				  2 * sizeof(struct in6_addr));
		break;
#endif
	default:
		NET_DBG("Unknown protocol family %d", net_pkt_family(pkt));
		return 0;
	}

	sum = calc_chksum_pkt(sum, pkt, upper_layer_len);

	sum = (sum == 0) ? 0xffff : htons(sum);

	return sum;
}
Beispiel #4
0
static int loopback_send(struct net_if *iface, struct net_pkt *pkt)
{
	struct net_pkt *cloned;
	int res;

	if (!pkt->frags) {
		SYS_LOG_ERR("No data to send");
		return -ENODATA;
	}

	/* We need to swap the IP addresses because otherwise
	 * the packet will be dropped.
	 */

	if (net_pkt_family(pkt) == AF_INET6) {
		struct in6_addr addr;

		net_ipaddr_copy(&addr, &NET_IPV6_HDR(pkt)->src);
		net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src,
				&NET_IPV6_HDR(pkt)->dst);
		net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, &addr);
	} else {
		struct in_addr addr;

		net_ipaddr_copy(&addr, &NET_IPV4_HDR(pkt)->src);
		net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src,
				&NET_IPV4_HDR(pkt)->dst);
		net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr);
	}

	/* We should simulate normal driver meaning that if the packet is
	 * properly sent (which is always in this driver), then the packet
	 * must be dropped. This is very much needed for TCP packets where
	 * the packet is reference counted in various stages of sending.
	 */
	cloned = net_pkt_clone(pkt, K_MSEC(100));
	if (!cloned) {
		res = -ENOMEM;
		goto out;
	}

	res = net_recv_data(iface, cloned);
	if (res < 0) {
		SYS_LOG_ERR("Data receive failed.");
		goto out;
	}

	net_pkt_unref(pkt);

out:
	/* Let the receiving thread run now */
	k_yield();

	return res;
}
Beispiel #5
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 #6
0
/* Called when data needs to be sent to network */
int net_send_data(struct net_pkt *pkt)
{
	int status;

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

	if (!net_pkt_iface(pkt)) {
		return -EINVAL;
	}

#if defined(CONFIG_NET_STATISTICS)
	switch (net_pkt_family(pkt)) {
	case AF_INET:
		net_stats_update_ipv4_sent();
		break;
	case AF_INET6:
		net_stats_update_ipv6_sent();
		break;
	}
#endif

	status = check_ip_addr(pkt);
	if (status < 0) {
		return status;
	} else if (status > 0) {
		/* Packet is destined back to us so send it directly
		 * to RX processing.
		 */
		NET_DBG("Loopback pkt %p back to us", pkt);
		processing_data(pkt, true);
		return 0;
	}

	if (net_if_send_data(net_pkt_iface(pkt), pkt) == NET_DROP) {
		return -EIO;
	}

	return 0;
}
Beispiel #7
0
static enum net_verdict ieee802154_send(struct net_if *iface,
					struct net_pkt *pkt)
{
	struct ieee802154_context *ctx = net_if_l2_data(iface);
	u8_t reserved_space = net_pkt_ll_reserve(pkt);
	struct net_buf *frag;

	if (net_pkt_family(pkt) != AF_INET6) {
		return NET_DROP;
	}

	if (!ieee802154_manage_send_packet(iface, pkt)) {
		return NET_DROP;
	}

	frag = pkt->frags;
	while (frag) {
		if (frag->len > IEEE802154_MTU) {
			NET_ERR("Frag %p as too big length %u",
				frag, frag->len);
			return NET_DROP;
		}

		if (!ieee802154_create_data_frame(ctx, net_pkt_ll_dst(pkt),
						  frag, reserved_space)) {
			return NET_DROP;
		}

		frag = frag->frags;
	}

	pkt_hexdump(pkt, true);

	net_if_queue_tx(iface, pkt);

	return NET_OK;
}
Beispiel #8
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 #9
0
/* Check if the IPv{4|6} addresses are proper. As this can be expensive,
 * make this optional.
 */
static inline int check_ip_addr(struct net_pkt *pkt)
{
#if defined(CONFIG_NET_IPV6)
	if (net_pkt_family(pkt) == AF_INET6) {
		if (net_ipv6_addr_cmp(&NET_IPV6_HDR(pkt)->dst,
				      net_ipv6_unspecified_address())) {
			NET_DBG("IPv6 dst address missing");
			return -EADDRNOTAVAIL;
		}

		/* If the destination address is our own, then route it
		 * back to us.
		 */
		if (net_is_ipv6_addr_loopback(&NET_IPV6_HDR(pkt)->dst) ||
		    net_is_my_ipv6_addr(&NET_IPV6_HDR(pkt)->dst)) {
			struct in6_addr addr;

			/* Swap the addresses so that in receiving side
			 * the packet is accepted.
			 */
			net_ipaddr_copy(&addr, &NET_IPV6_HDR(pkt)->src);
			net_ipaddr_copy(&NET_IPV6_HDR(pkt)->src,
					&NET_IPV6_HDR(pkt)->dst);
			net_ipaddr_copy(&NET_IPV6_HDR(pkt)->dst, &addr);

			return 1;
		}

		/* The source check must be done after the destination check
		 * as having src ::1 is perfectly ok if dst is ::1 too.
		 */
		if (net_is_ipv6_addr_loopback(&NET_IPV6_HDR(pkt)->src)) {
			NET_DBG("IPv6 loopback src address");
			return -EADDRNOTAVAIL;
		}
	} else
#endif /* CONFIG_NET_IPV6 */

#if defined(CONFIG_NET_IPV4)
	if (net_pkt_family(pkt) == AF_INET) {
		if (net_ipv4_addr_cmp(&NET_IPV4_HDR(pkt)->dst,
				      net_ipv4_unspecified_address())) {
			return -EADDRNOTAVAIL;
		}

		/* If the destination address is our own, then route it
		 * back to us.
		 */
		if (net_is_ipv4_addr_loopback(&NET_IPV4_HDR(pkt)->dst) ||
		    net_is_my_ipv4_addr(&NET_IPV4_HDR(pkt)->dst)) {
			struct in_addr addr;

			/* Swap the addresses so that in receiving side
			 * the packet is accepted.
			 */
			net_ipaddr_copy(&addr, &NET_IPV4_HDR(pkt)->src);
			net_ipaddr_copy(&NET_IPV4_HDR(pkt)->src,
					&NET_IPV4_HDR(pkt)->dst);
			net_ipaddr_copy(&NET_IPV4_HDR(pkt)->dst, &addr);

			return 1;
		}

		/* The source check must be done after the destination check
		 * as having src 127.0.0.0/8 is perfectly ok if dst is in
		 * localhost subnet too.
		 */
		if (net_is_ipv4_addr_loopback(&NET_IPV4_HDR(pkt)->src)) {
			NET_DBG("IPv4 loopback src address");
			return -EADDRNOTAVAIL;
		}
	} else
#endif /* CONFIG_NET_IPV4 */

	{
		;
	}

	return 0;
}