Esempio n. 1
0
File: slip.c Progetto: agatti/zephyr
static void process_msg(struct slip_context *slip)
{
	u16_t vlan_tag = NET_VLAN_TAG_UNSPEC;
	struct net_pkt *pkt;

	pkt = slip_poll_handler(slip);
	if (!pkt || !pkt->frags) {
		return;
	}

#if defined(CONFIG_NET_VLAN)
	{
		struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);

		if (ntohs(hdr->type) == NET_ETH_PTYPE_VLAN) {
			struct net_eth_vlan_hdr *hdr_vlan =
				(struct net_eth_vlan_hdr *)NET_ETH_HDR(pkt);

			net_pkt_set_vlan_tci(pkt, ntohs(hdr_vlan->vlan.tci));
			vlan_tag = net_pkt_vlan_tag(pkt);
		}
	}
#endif

	if (net_recv_data(get_iface(slip, vlan_tag), pkt) < 0) {
		net_pkt_unref(pkt);
	}

	slip->rx = NULL;
	slip->last = NULL;
}
Esempio n. 2
0
static inline struct net_pkt *prepare_arp_request(struct net_if *iface,
						  struct net_pkt *req,
						  struct net_eth_addr *addr)
{
	struct net_pkt *pkt;
	struct net_buf *frag;
	struct net_arp_hdr *hdr, *req_hdr;
	struct net_eth_hdr *eth, *eth_req;

	pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr),
				      K_FOREVER);
	if (!pkt) {
		goto fail;
	}

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

	net_pkt_frag_add(pkt, frag);
	net_pkt_set_iface(pkt, iface);

	hdr = NET_ARP_HDR(pkt);
	eth = NET_ETH_HDR(pkt);
	req_hdr = NET_ARP_HDR(req);
	eth_req = NET_ETH_HDR(req);

	eth->type = htons(NET_ETH_PTYPE_ARP);

	memset(&eth->dst.addr, 0xff, sizeof(struct net_eth_addr));
	memcpy(&eth->src.addr, addr, sizeof(struct net_eth_addr));

	hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
	hdr->protocol = htons(NET_ETH_PTYPE_IP);
	hdr->hwlen = sizeof(struct net_eth_addr);
	hdr->protolen = sizeof(struct in_addr);
	hdr->opcode = htons(NET_ARP_REQUEST);

	memset(&hdr->dst_hwaddr.addr, 0x00, sizeof(struct net_eth_addr));
	memcpy(&hdr->src_hwaddr.addr, addr, sizeof(struct net_eth_addr));

	net_ipaddr_copy(&hdr->src_ipaddr, &req_hdr->src_ipaddr);
	net_ipaddr_copy(&hdr->dst_ipaddr, &req_hdr->dst_ipaddr);

	net_buf_add(frag, sizeof(struct net_arp_hdr));

	return pkt;

fail:
	net_pkt_unref(pkt);
	return NULL;
}
Esempio n. 3
0
static bool run_tests(void)
{
	struct net_pkt *pkt, *pkt2;
	struct net_buf *frag;
	struct net_if *iface;
	struct net_if_addr *ifaddr;
	struct net_arp_hdr *arp_hdr;
	struct net_ipv4_hdr *ipv4;
	struct net_eth_hdr *eth_hdr;
	int len;

	struct in_addr dst = { { { 192, 168, 0, 2 } } };
	struct in_addr dst_far = { { { 10, 11, 12, 13 } } };
	struct in_addr dst_far2 = { { { 172, 16, 14, 186 } } };
	struct in_addr src = { { { 192, 168, 0, 1 } } };
	struct in_addr netmask = { { { 255, 255, 255, 0 } } };
	struct in_addr gw = { { { 192, 168, 0, 42 } } };

	net_arp_init();

	iface = net_if_get_default();

	net_if_ipv4_set_gw(iface, &gw);
	net_if_ipv4_set_netmask(iface, &netmask);

	/* Unicast test */
	ifaddr = net_if_ipv4_addr_add(iface,
				      &src,
				      NET_ADDR_MANUAL,
				      0);
	ifaddr->addr_state = NET_ADDR_PREFERRED;

	/* Application data for testing */
	pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr), K_FOREVER);
	if (!pkt) {
		printk("Out of mem TX\n");
		return false;
	}

	frag = net_pkt_get_frag(pkt, K_FOREVER);
	if (!frag) {
		printk("Out of mem DATA\n");
		return false;
	}

	net_pkt_frag_add(pkt, frag);

	net_pkt_set_iface(pkt, iface);

	setup_eth_header(iface, pkt, &hwaddr, NET_ETH_PTYPE_IP);

	len = strlen(app_data);

	if (net_pkt_ll_reserve(pkt) != sizeof(struct net_eth_hdr)) {
		printk("LL reserve invalid, should be %zd was %d\n",
		       sizeof(struct net_eth_hdr),
		       net_pkt_ll_reserve(pkt));
		return false;
	}

	ipv4 = (struct net_ipv4_hdr *)net_buf_add(frag,
						  sizeof(struct net_ipv4_hdr));
	net_ipaddr_copy(&ipv4->src, &src);
	net_ipaddr_copy(&ipv4->dst, &dst);

	memcpy(net_buf_add(frag, len), app_data, len);

	pkt2 = net_arp_prepare(pkt);

	/* pkt2 is the ARP packet and pkt is the IPv4 packet and it was
	 * stored in ARP table.
	 */
	if (pkt2 == pkt) {
		/* The packets cannot be the same as the ARP cache has
		 * still room for the pkt.
		 */
		printk("ARP cache should still have free space\n");
		return false;
	}

	if (!pkt2) {
		printk("ARP pkt is empty\n");
		return false;
	}

	/* The ARP cache should now have a link to pending net_pkt
	 * that is to be sent after we have got an ARP reply.
	 */
	if (!pkt->frags) {
		printk("Pending pkt fragment is NULL\n");
		return false;
	}
	pending_pkt = pkt;

	/* pkt2 should contain the arp header, verify it */
	if (memcmp(net_pkt_ll(pkt2), net_eth_broadcast_addr(),
		   sizeof(struct net_eth_addr))) {
		printk("ARP ETH dest address invalid\n");
		net_hexdump("ETH dest wrong  ", net_pkt_ll(pkt2),
			    sizeof(struct net_eth_addr));
		net_hexdump("ETH dest correct",
			    (u8_t *)net_eth_broadcast_addr(),
			    sizeof(struct net_eth_addr));
		return false;
	}

	if (memcmp(net_pkt_ll(pkt2) + sizeof(struct net_eth_addr),
		   iface->link_addr.addr,
		   sizeof(struct net_eth_addr))) {
		printk("ARP ETH source address invalid\n");
		net_hexdump("ETH src correct",
			    iface->link_addr.addr,
			    sizeof(struct net_eth_addr));
		net_hexdump("ETH src wrong  ",
			    net_pkt_ll(pkt2) +	sizeof(struct net_eth_addr),
			    sizeof(struct net_eth_addr));
		return false;
	}

	arp_hdr = NET_ARP_HDR(pkt2);
	eth_hdr = NET_ETH_HDR(pkt2);

	if (eth_hdr->type != htons(NET_ETH_PTYPE_ARP)) {
		printk("ETH type 0x%x, should be 0x%x\n",
		       eth_hdr->type, htons(NET_ETH_PTYPE_ARP));
		return false;
	}

	if (arp_hdr->hwtype != htons(NET_ARP_HTYPE_ETH)) {
		printk("ARP hwtype 0x%x, should be 0x%x\n",
		       arp_hdr->hwtype, htons(NET_ARP_HTYPE_ETH));
		return false;
	}

	if (arp_hdr->protocol != htons(NET_ETH_PTYPE_IP)) {
		printk("ARP protocol 0x%x, should be 0x%x\n",
		       arp_hdr->protocol, htons(NET_ETH_PTYPE_IP));
		return false;
	}

	if (arp_hdr->hwlen != sizeof(struct net_eth_addr)) {
		printk("ARP hwlen 0x%x, should be 0x%zx\n",
		       arp_hdr->hwlen, sizeof(struct net_eth_addr));
		return false;
	}

	if (arp_hdr->protolen != sizeof(struct in_addr)) {
		printk("ARP IP addr len 0x%x, should be 0x%zx\n",
		       arp_hdr->protolen, sizeof(struct in_addr));
		return false;
	}

	if (arp_hdr->opcode != htons(NET_ARP_REQUEST)) {
		printk("ARP opcode 0x%x, should be 0x%x\n",
		       arp_hdr->opcode, htons(NET_ARP_REQUEST));
		return false;
	}

	if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr,
			       &NET_IPV4_HDR(pkt)->dst)) {
		char out[sizeof("xxx.xxx.xxx.xxx")];
		snprintk(out, sizeof(out), "%s",
			 net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr));
		printk("ARP IP dest invalid %s, should be %s", out,
		       net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->dst));
		return false;
	}

	if (!net_ipv4_addr_cmp(&arp_hdr->src_ipaddr,
			       &NET_IPV4_HDR(pkt)->src)) {
		char out[sizeof("xxx.xxx.xxx.xxx")];
		snprintk(out, sizeof(out), "%s",
			 net_sprint_ipv4_addr(&arp_hdr->src_ipaddr));
		printk("ARP IP src invalid %s, should be %s", out,
		       net_sprint_ipv4_addr(&NET_IPV4_HDR(pkt)->src));
		return false;
	}

	/* We could have send the new ARP request but for this test we
	 * just free it.
	 */
	net_pkt_unref(pkt2);

	if (pkt->ref != 2) {
		printk("ARP cache should own the original packet\n");
		return false;
	}

	/* Then a case where target is not in the same subnet */
	net_ipaddr_copy(&ipv4->dst, &dst_far);

	pkt2 = net_arp_prepare(pkt);

	if (pkt2 == pkt) {
		printk("ARP cache should not find anything\n");
		return false;
	}

	if (!pkt2) {
		printk("ARP pkt2 is empty\n");
		return false;
	}

	arp_hdr = NET_ARP_HDR(pkt2);

	if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr, &iface->ipv4.gw)) {
		char out[sizeof("xxx.xxx.xxx.xxx")];
		snprintk(out, sizeof(out), "%s",
			 net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr));
		printk("ARP IP dst invalid %s, should be %s\n", out,
			 net_sprint_ipv4_addr(&iface->ipv4.gw));
		return false;
	}

	net_pkt_unref(pkt2);

	/* Try to find the same destination again, this should fail as there
	 * is a pending request in ARP cache.
	 */
	net_ipaddr_copy(&ipv4->dst, &dst_far);

	/* Make sure prepare will not free the pkt because it will be
	 * needed in the later test case.
	 */
	net_pkt_ref(pkt);

	pkt2 = net_arp_prepare(pkt);
	if (!pkt2) {
		printk("ARP cache is not sending the request again\n");
		return false;
	}

	net_pkt_unref(pkt2);

	/* Try to find the different destination, this should fail too
	 * as the cache table should be full.
	 */
	net_ipaddr_copy(&ipv4->dst, &dst_far2);

	/* Make sure prepare will not free the pkt because it will be
	 * needed in the next test case.
	 */
	net_pkt_ref(pkt);

	pkt2 = net_arp_prepare(pkt);
	if (!pkt2) {
		printk("ARP cache did not send a req\n");
		return false;
	}

	/* Restore the original address so that following test case can
	 * work properly.
	 */
	net_ipaddr_copy(&ipv4->dst, &dst);

	/* The arp request packet is now verified, create an arp reply.
	 * The previous value of pkt is stored in arp table and is not lost.
	 */
	pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER);
	if (!pkt) {
		printk("Out of mem RX reply\n");
		return false;
	}
	printk("%d pkt %p\n", __LINE__, pkt);

	frag = net_pkt_get_frag(pkt, K_FOREVER);
	if (!frag) {
		printk("Out of mem DATA reply\n");
		return false;
	}
	printk("%d frag %p\n", __LINE__, frag);

	net_pkt_frag_add(pkt, frag);

	net_pkt_set_iface(pkt, iface);

	arp_hdr = NET_ARP_HDR(pkt);
	net_buf_add(frag, sizeof(struct net_arp_hdr));

	net_ipaddr_copy(&arp_hdr->dst_ipaddr, &dst);
	net_ipaddr_copy(&arp_hdr->src_ipaddr, &src);

	pkt2 = prepare_arp_reply(iface, pkt, &hwaddr);
	if (!pkt2) {
		printk("ARP reply generation failed.");
		return false;
	}

	/* The pending packet should now be sent */
	switch (net_arp_input(pkt2)) {
	case NET_OK:
	case NET_CONTINUE:
		break;
	case NET_DROP:
		break;
	}

	/* Yielding so that network interface TX thread can proceed. */
	k_yield();

	if (send_status < 0) {
		printk("ARP reply was not sent\n");
		return false;
	}

	if (pkt->ref != 1) {
		printk("ARP cache should no longer own the original packet\n");
		return false;
	}

	net_pkt_unref(pkt);

	/* Then feed in ARP request */
	pkt = net_pkt_get_reserve_rx(sizeof(struct net_eth_hdr), K_FOREVER);
	if (!pkt) {
		printk("Out of mem RX request\n");
		return false;
	}

	frag = net_pkt_get_frag(pkt, K_FOREVER);
	if (!frag) {
		printk("Out of mem DATA request\n");
		return false;
	}

	net_pkt_frag_add(pkt, frag);

	net_pkt_set_iface(pkt, iface);
	send_status = -EINVAL;

	arp_hdr = NET_ARP_HDR(pkt);
	net_buf_add(frag, sizeof(struct net_arp_hdr));

	net_ipaddr_copy(&arp_hdr->dst_ipaddr, &src);
	net_ipaddr_copy(&arp_hdr->src_ipaddr, &dst);
	setup_eth_header(iface, pkt, &hwaddr, NET_ETH_PTYPE_ARP);

	pkt2 = prepare_arp_request(iface, pkt, &hwaddr);
	if (!pkt2) {
		printk("ARP request generation failed.");
		return false;
	}

	req_test = true;

	switch (net_arp_input(pkt2)) {
	case NET_OK:
	case NET_CONTINUE:
		break;
	case NET_DROP:
		break;
	}

	/* Yielding so that network interface TX thread can proceed. */
	k_yield();

	if (send_status < 0) {
		printk("ARP req was not sent\n");
		return false;
	}

	net_pkt_unref(pkt);

	printk("Network ARP checks passed\n");

	return true;
}