/* The pico_ethernet_receive() function is used by * those devices supporting ETH in order to push packets up * into the stack. */ int32_t pico_ethernet_receive(struct pico_frame *f) { struct pico_eth_hdr *hdr; if (!f || !f->dev || !f->datalink_hdr) goto discard; hdr = (struct pico_eth_hdr *) f->datalink_hdr; if ((memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) && #ifdef PICO_SUPPORT_MCAST (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) && #endif (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0)) goto discard; f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr); if (hdr->proto == PICO_IDETH_ARP) return pico_arp_receive(f); if ((hdr->proto == PICO_IDETH_IPV4) || (hdr->proto == PICO_IDETH_IPV6)) return pico_network_receive(f); discard: pico_frame_discard(f); return -1; }
static int32_t pico_ll_receive(struct pico_frame *f) { struct pico_eth_hdr *hdr = (struct pico_eth_hdr *) f->datalink_hdr; f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr); #if (defined PICO_SUPPORT_IPV4) && (defined PICO_SUPPORT_ETH) if (hdr->proto == PICO_IDETH_ARP) return pico_arp_receive(f); #endif #if defined (PICO_SUPPORT_IPV4) if (hdr->proto == PICO_IDETH_IPV4) return pico_ipv4_ethernet_receive(f); #endif #if defined (PICO_SUPPORT_IPV6) if (hdr->proto == PICO_IDETH_IPV6) return pico_ipv6_ethernet_receive(f); #endif pico_frame_discard(f); return -1; }
END_TEST START_TEST(tc_pico_arp_queue) { struct pico_ip4 addr = { .addr = 0xaabbccdd }; int i; struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr)); struct pico_ipv4_hdr *h = (struct pico_ipv4_hdr *) f->buffer; fail_if(!f); f->net_hdr = h; h->dst.addr = addr.addr; for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) { fail_if(frames_queued[i] != NULL); } pico_arp_unreachable(&addr); for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) { fail_if(frames_queued[i] != NULL); } pico_arp_postpone(f); fail_if(frames_queued[0]->buffer != f->buffer); pico_arp_unreachable(&addr); for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) { fail_if(frames_queued[i] != NULL); } PICO_FREE(f); } END_TEST START_TEST (arp_receive_test) { struct mock_device *mock; struct pico_frame *f = NULL; struct pico_arp_hdr *ah = NULL; struct pico_eth_hdr *eh = NULL; uint8_t macaddr1[6] = { 0, 0, 0, 0xa, 0xb, 0xf }; uint8_t macaddr2[6] = { 0, 0, 0, 0xc, 0xd, 0xf }; struct pico_ip4 netmask = { .addr = long_be(0xffffff00) }; struct pico_ip4 ip1 = { .addr = long_be(0x0A28000A) }; struct pico_ip4 ip2 = { .addr = long_be(0x0A28000B) }; pico_stack_init(); /* Create mock device */ mock = pico_mock_create(macaddr1); fail_if(!mock, "MOCK DEVICE creation failed"); fail_if(pico_ipv4_link_add(mock->dev, ip1, netmask), "add link to mock device failed"); /* Normal ARP request */ f = init_frame(mock->dev); fail_if(!f, "FRAME INIT failed"); eh = (struct pico_eth_hdr *) f->datalink_hdr; ah = (struct pico_arp_hdr *) f->net_hdr; memcpy(eh->saddr, macaddr2, PICO_SIZE_ETH); memcpy(eh->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH); eh->proto = PICO_IDETH_ARP; ah->htype = PICO_ARP_HTYPE_ETH; ah->ptype = PICO_IDETH_IPV4; ah->hsize = PICO_SIZE_ETH; ah->psize = PICO_SIZE_IP4; ah->opcode = PICO_ARP_REQUEST; memcpy(ah->s_mac, macaddr2, PICO_SIZE_ETH); ah->src.addr = ip2.addr; ah->dst.addr = ip1.addr; fail_unless(pico_arp_receive(f) == 0); /* net_hdr is a nullpointer */ f = init_frame(mock->dev); fail_if(!f, "FRAME INIT failed"); f->net_hdr = NULL; fail_unless(pico_arp_receive(f) == -1); /* wrong hardware type */ f = init_frame(mock->dev); fail_if(!f, "FRAME INIT failed"); ah = (struct pico_arp_hdr *) f->net_hdr; ah->htype = 0; fail_unless(pico_arp_receive(f) == -1); /* wrong protocol type */ f = init_frame(mock->dev); fail_if(!f, "FRAME INIT failed"); ah = (struct pico_arp_hdr *) f->net_hdr; ah->ptype = 0; fail_unless(pico_arp_receive(f) == -1); /* source mac address is multicast */ f = init_frame(mock->dev); fail_if(!f, "FRAME INIT failed"); ah = (struct pico_arp_hdr *) f->net_hdr; ah->s_mac[0] = 0x01; fail_unless(pico_arp_receive(f) == -1); } END_TEST START_TEST (arp_get_test) { struct pico_frame *f = NULL; struct mock_device *mock; struct pico_ipv4_hdr *hdr = NULL; struct pico_eth *eth = NULL; uint8_t macaddr[6] = { 0, 0, 0, 0xa, 0xb, 0xf }; struct pico_ip4 netmask = { .addr = long_be(0xffffff00) }; struct pico_ip4 ip = { .addr = long_be(0x0A28000A) }; mock = pico_mock_create(macaddr); fail_if(!mock, "MOCK DEVICE creation failed"); fail_if(pico_ipv4_link_add(mock->dev, ip, netmask), "add link to mock device failed"); f = pico_frame_alloc(PICO_SIZE_ETHHDR + sizeof(struct pico_ipv4_hdr)); f->net_hdr = f->start + PICO_SIZE_ETHHDR; f->datalink_hdr = f->start; f->dev = mock->dev; hdr = (struct pico_ipv4_hdr *) f->net_hdr; hdr->dst.addr = ip.addr; eth = pico_arp_get(f); fail_unless(eth == &mock->dev->eth->mac); } END_TEST