static int pico_icmp4_process_in(struct pico_protocol *self, struct pico_frame *f) { struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr; IGNORE_PARAMETER(self); if (hdr->type == PICO_ICMP_ECHO) { hdr->type = PICO_ICMP_ECHOREPLY; /* outgoing frames require a f->len without the ethernet header len */ if (f->dev->eth) f->len -= PICO_SIZE_ETHHDR; pico_icmp4_checksum(f); pico_ipv4_rebound(f); } else if (hdr->type == PICO_ICMP_UNREACH) { f->net_hdr = f->transport_hdr + PICO_ICMPHDR_UN_SIZE; pico_ipv4_unreachable(f, hdr->code); } else if (hdr->type == PICO_ICMP_ECHOREPLY) { #ifdef PICO_SUPPORT_PING ping_recv_reply(f); #endif pico_frame_discard(f); } else { pico_frame_discard(f); } return 0; }
END_TEST START_TEST(tc_pico_frame_copy) { struct pico_frame *f = pico_frame_alloc(FRAME_SIZE); struct pico_frame *c1, *c2, *c3; (void)c3; fail_if(!f); fail_if(!f->buffer); fail_if(*f->usage_count != 1); /* First copy */ c1 = pico_frame_copy(f); fail_if(!c1); fail_if(!c1->buffer); fail_if(!c1->usage_count); fail_if (c1->buffer != f->buffer); fail_if(c1->usage_count != f->usage_count); fail_if(*c1->usage_count != 2); fail_if(*f->usage_count != 2); fail_if(c1->start != c1->buffer); fail_if(c1->len != c1->buffer_len); fail_if(c1->len != FRAME_SIZE); /* Second copy */ c2 = pico_frame_copy(f); fail_if (c2->buffer != f->buffer); fail_if(c2->usage_count != f->usage_count); fail_if(*c2->usage_count != 3); fail_if(*f->usage_count != 3); fail_if(c2->start != c2->buffer); fail_if(c2->len != c2->buffer_len); fail_if(c2->len != FRAME_SIZE); #ifdef PICO_FAULTY printf("Testing with faulty memory in frame_copy (1)\n"); pico_set_mm_failure(1); c3 = pico_frame_copy(f); fail_if(c3); fail_if(!f); #endif /* Discard 1 */ pico_frame_discard(c1); fail_if(*f->usage_count != 2); /* Discard 2 */ pico_frame_discard(c2); fail_if(*f->usage_count != 1); pico_frame_discard(f); }
END_TEST START_TEST(tc_pico_frame_grow) { struct pico_frame *f = pico_frame_alloc(3); fail_if(f->buffer_len != 3); /* Ensure that the usage_count starts at byte 4, for good alignment */ fail_if(((void*)f->usage_count - (void *)f->buffer) != 4); ((uint8_t *)f->buffer)[0] = 'a'; ((uint8_t *)f->buffer)[1] = 'b'; ((uint8_t *)f->buffer)[2] = 'c'; *f->usage_count = 12; /* First, the failing cases. */ fail_if(pico_frame_grow(NULL, 30) == 0); fail_if(pico_frame_grow(f, 2) == 0); f->flags = 0; pico_set_mm_failure(1); fail_if(pico_frame_grow(f, 21) == 0); /* Now, the good one. */ fail_if(pico_frame_grow(f, 21) != 0); fail_if(f->buffer_len != 21); fail_if(((void *)f->usage_count - (void *)f->buffer) != 24); fail_if(((uint8_t *)f->buffer)[0] != 'a'); fail_if(((uint8_t *)f->buffer)[1] != 'b'); fail_if(((uint8_t *)f->buffer)[2] != 'c'); fail_if(*f->usage_count != 12); *f->usage_count = 1; pico_frame_discard(f); f = pico_frame_alloc_skeleton(10, 1); fail_if(!f); fail_if(f->buffer); fail_if(!f->flags); f->buffer = PICO_ZALLOC(10); fail_if(pico_frame_grow(f, 22) != 0); fail_if (f->flags); pico_frame_discard(f); }
static int fp_drop(struct filter_node *filter, struct pico_frame *f) { IGNORE_PARAMETER(filter); ipf_dbg("ipfilter> drop\n"); pico_frame_discard(f); return 1; }
/* 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; }
/* This is called by dev loop in order to ensure correct ethernet addressing. * Returns 0 if the destination is unknown, and -1 if the packet is not deliverable * due to ethernet addressing (i.e., no arp association was possible. * * Only IP packets must pass by this. ARP will always use direct dev->send() function, so * we assume IP is used. */ int32_t pico_ethernet_send(struct pico_frame *f) { const struct pico_eth *dstmac = NULL; int32_t ret = -1; if (IS_IPV6(f)) { /*TODO: Neighbor solicitation */ dstmac = NULL; } else if (IS_IPV4(f)) { if (IS_BCAST(f) || destination_is_bcast(f)) { dstmac = (const struct pico_eth *const) PICO_ETHADDR_ALL; } #ifdef PICO_SUPPORT_MCAST else if (destination_is_mcast(f)) { uint8_t pico_mcast_mac[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 }; dstmac = pico_ethernet_mcast_translate(f, pico_mcast_mac); } #endif else { dstmac = pico_arp_get(f); if (!dstmac) return 0; } /* This sets destination and source address, then pushes the packet to the device. */ if (dstmac && (f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR)) { struct pico_eth_hdr *hdr; f->start -= PICO_SIZE_ETHHDR; f->len += PICO_SIZE_ETHHDR; f->datalink_hdr = f->start; hdr = (struct pico_eth_hdr *) f->datalink_hdr; memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH); memcpy(hdr->daddr, dstmac, PICO_SIZE_ETH); hdr->proto = PICO_IDETH_IPV4; if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)) { dbg("sending out packet destined for our own mac\n"); return pico_ethernet_receive(f); } else if(IS_LIMITED_BCAST(f)) { ret = pico_device_broadcast(f); } else { ret = (int32_t)f->dev->send(f->dev, f->start, (int) f->len); /* Frame is discarded after this return by the caller */ } if(!ret) pico_frame_discard(f); return ret; } else { return -1; } } /* End IPV4 ethernet addressing */ return -1; }
/* Network layer: interface towards socket for frame sending */ int pico_network_send(struct pico_frame *f) { if (!f || !f->sock || !f->sock->net) { pico_frame_discard(f); return -1; } return f->sock->net->push(f->sock->net, f); }
int pico_transport_send(struct pico_frame *f) { if (!f || !f->sock || !f->sock->proto) { pico_frame_discard(f); return -1; } return f->sock->proto->push(f->sock->net, f); }
static int fp_reject(struct filter_node *filter, struct pico_frame *f) { /* TODO check first if sender is pico itself or not */ IGNORE_PARAMETER(filter); ipf_dbg("ipfilter> reject\n"); (void)pico_icmp4_packet_filtered(f); pico_frame_discard(f); return 1; }
static int32_t pico_ipv4_ethernet_receive(struct pico_frame *f) { if (IS_IPV4(f)) { pico_enqueue(pico_proto_ipv4.q_in, f); } else { (void)pico_icmp4_param_problem(f, 0); pico_frame_discard(f); return -1; } return (int32_t)f->buffer_len; }
static int32_t pico_ipv6_ethernet_receive(struct pico_frame *f) { if (IS_IPV6(f)) { pico_enqueue(pico_proto_ipv6.q_in, f); } else { /* Wrong version for link layer type */ pico_frame_discard(f); return -1; } return (int32_t)f->buffer_len; }
static inline int pico_ipv4_crc_check(struct pico_frame *f) { uint16_t checksum_invalid = 1; struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; checksum_invalid = short_be(pico_checksum(hdr, f->net_len)); if (checksum_invalid) { dbg("IP: checksum failed!\n"); pico_frame_discard(f); return 0; } return 1; }
int32_t pico_ethernet_receive(struct pico_frame *f) { struct pico_eth_hdr *hdr; if (!f || !f->dev || !f->datalink_hdr) { pico_frame_discard(f); return -1; } hdr = (struct pico_eth_hdr *) f->datalink_hdr; if ((memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) && (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) && #ifdef PICO_SUPPORT_IPV6 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST6, PICO_SIZE_MCAST6) != 0) && #endif (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0)) { pico_frame_discard(f); return -1; } pico_ll_check_bcast(f); return pico_ll_receive(f); }
static void pico_fragments_empty_tree(struct pico_tree *tree) { struct pico_tree_node *index, *tmp; if (!tree) { return; } pico_tree_foreach_safe(index, tree, tmp) { struct pico_frame * old = index->keyValue; pico_tree_delete(tree, old); pico_frame_discard(old); } }
/* Transport layer */ MOCKABLE int32_t pico_transport_receive(struct pico_frame *f, uint8_t proto) { int32_t ret = -1; switch (proto) { #ifdef PICO_SUPPORT_ICMP4 case PICO_PROTO_ICMP4: ret = pico_enqueue(pico_proto_icmp4.q_in, f); break; #endif #ifdef PICO_SUPPORT_ICMP6 case PICO_PROTO_ICMP6: ret = pico_enqueue(pico_proto_icmp6.q_in, f); break; #endif #if defined(PICO_SUPPORT_IGMP) && defined(PICO_SUPPORT_MCAST) case PICO_PROTO_IGMP: ret = pico_enqueue(pico_proto_igmp.q_in, f); break; #endif #ifdef PICO_SUPPORT_UDP case PICO_PROTO_UDP: ret = pico_enqueue(pico_proto_udp.q_in, f); break; #endif #ifdef PICO_SUPPORT_TCP case PICO_PROTO_TCP: ret = pico_enqueue(pico_proto_tcp.q_in, f); break; #endif default: /* Protocol not available */ dbg("pkt: no such protocol (%d)\n", proto); pico_notify_proto_unreachable(f); pico_frame_discard(f); ret = -1; } return ret; }
int pico_network_receive(struct pico_frame *f) { if (0) {} #ifdef PICO_SUPPORT_IPV4 else if (IS_IPV4(f)) { pico_enqueue(pico_proto_ipv4.q_in, f); } #endif #ifdef PICO_SUPPORT_IPV6 else if (IS_IPV6(f)) { pico_enqueue(pico_proto_ipv6.q_in, f); } #endif else { dbg("Network not found.\n"); pico_frame_discard(f); return -1; } return f->buffer_len; }
static int pico_ipv4_process_mcast_in(struct pico_frame *f) { struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; if (pico_ipv4_is_multicast(hdr->dst.addr)) { #ifdef PICO_SUPPORT_MCAST /* Receiving UDP multicast datagram TODO set f->flags? */ if (hdr->proto == PICO_PROTO_IGMP) { ip_mcast_dbg("MCAST: received IGMP message\n"); pico_transport_receive(f, PICO_PROTO_IGMP); return 1; } else if ((pico_ipv4_mcast_filter(f) == 0) && (hdr->proto == PICO_PROTO_UDP)) { pico_enqueue(pico_proto_udp.q_in, f); return 1; } #endif pico_frame_discard(f); return 1; } return 0; }
END_TEST START_TEST(tc_pico_eth_receive) { struct pico_frame *f = NULL; struct pico_eth_hdr *eth = NULL; int ret = 0, count = 0; STARTING(); f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr) + sizeof(struct pico_eth_hdr)); f->datalink_hdr = f->buffer; f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr); eth = (struct pico_eth_hdr *)f->datalink_hdr; ((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */ /* ETHERNET PROTOCOL : IPV6 */ eth->proto = PICO_IDETH_IPV6; TRYING("With wrong network type\n"); ret = pico_eth_receive(f); CHECKING(count); fail_unless(ret == -1, "Wrong type should've returned an error\n"); SUCCESS(); f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr) + sizeof(struct pico_eth_hdr)); f->datalink_hdr = f->buffer; f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr); eth = (struct pico_eth_hdr *)f->datalink_hdr; ((uint8_t *)(f->net_hdr))[0] = 0x60; /* Ipv6 */ /* ETHERNET PROTOCOL : IPV6 */ eth->proto = PICO_IDETH_IPV6; TRYING("With correct network type\n"); ret = pico_eth_receive(f); CHECKING(count); fail_unless(ret == (int32_t)f->buffer_len, "Was correct frame, should've returned success\n"); SUCCESS(); CHECKING(count); fail_unless(pico_proto_ipv6.q_in->size == f->buffer_len, "Frame not enqueued\n"); SUCCESS(); pico_frame_discard(f); f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr) + sizeof(struct pico_eth_hdr)); f->datalink_hdr = f->buffer; f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr); eth = (struct pico_eth_hdr *)f->datalink_hdr; ((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */ TRYING("With wrong frame type\n"); ret = pico_eth_receive(f); CHECKING(count); fail_unless(ret == -1, "should've returned -1 wrong ethernet protocol\n"); SUCCESS(); f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr) + sizeof(struct pico_eth_hdr)); f->datalink_hdr = f->buffer; f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr); eth = (struct pico_eth_hdr *)f->datalink_hdr; ((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */ eth->proto = PICO_IDETH_IPV4; TRYING("With IPv4 frame\n"); ret = pico_eth_receive(f); CHECKING(count); fail_unless(ret > 0, "Was correct frame should've returned size of frame\n"); SUCCESS(); CHECKING(count); fail_unless(pico_proto_ipv4.q_in->size == f->buffer_len, "Frame not enqueued\n"); SUCCESS(); ENDING(count); }
END_TEST START_TEST(tc_802154_to_ietf) { int test = 1; struct pico_802154 a = { .addr.data = { 1,2,3,4,5,6,7,8 }, .mode = AM_6LOWPAN_EXT }; uint8_t buf[] = {8,7,6,5,4,3,2,1}; STARTING(); // TEST 1 TRYING("Extended address mode\n"); addr_802154_to_ietf(&a); dbg_addr_ext("After", a.addr.data); CHECKING(test); FAIL_UNLESS(0 == memcmp(a.addr.data, buf, SIZE_6LOWPAN_EXT), "Failed converting to IETF endianness\n"); // TEST 2 TRYING("Short address mode\n"); a.mode = AM_6LOWPAN_SHORT; addr_802154_to_ietf(&a); dbg_addr_ext("After", a.addr.data); CHECKING(test); FAIL_UNLESS(a.addr._short.addr == short_be(0x0708), "Failed converting short to IETF endianness\n"); // TEST 3 TRYING("Wrong address mode\n"); a.mode = AM_6LOWPAN_NONE; addr_802154_to_ietf(&a); dbg_addr_ext("After", a.addr.data); buf[0] = 7; buf[1] = 8; CHECKING(test); FAIL_UNLESS(0 == memcmp(a.addr.data, buf, SIZE_6LOWPAN_EXT), "Should've done nothing\n"); ENDING(test); } END_TEST START_TEST(tc_802154_ll_src) { int test = 1; struct pico_ip6 ip = { .addr = {0,0,0,0,0,0,0,0, 3,2,3,4,5,6,7,8} }; struct pico_ip6 ip2 = { .addr = {0,0,0,0,0,0,0,0, 0,0,0,0xff,0xfe,0,0x12,0x34} }; struct pico_6lowpan_info info = { .addr_short.addr = short_be(0x1234), .addr_ext.addr = {3,2,3,4,5,6,7,8} }; struct pico_device dev; struct pico_802154 addr; struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr)); struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->buffer; STARTING(); dev.eth = (struct pico_ethdev *)&info; f->net_hdr = f->buffer; f->dev = &dev; dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN; // TEST 3 TRYING("With an IPv6 address that is derived from MAC short address\n"); info.addr_short.addr = short_be(0x1234); hdr->src = ip2; addr = addr_802154_ll_src(f); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode, "Should've returned device's short address \n"); CHECKING(test); FAIL_UNLESS(short_be(0x1234) == addr.addr._short.addr, "Should've copied the short address from the device\n"); // TEST 4 TRYING("With an IPv6 address that is derived from MAC extended address\n"); ip.addr[8] = 1; hdr->src = ip; addr = addr_802154_ll_src(f); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode, "Should've returned device's extended address\n"); CHECKING(test); FAIL_UNLESS(0 == memcmp(info.addr_ext.addr, addr.addr._ext.addr, SIZE_6LOWPAN_EXT), "Should've copied device's extended address\n"); ENDING(test); } END_TEST START_TEST(tc_802154_ll_dst) { int test = 1; struct pico_ip6 ip; struct pico_ip6 local; struct pico_ip6 local2; struct pico_802154 addr; struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr)); struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->buffer; struct pico_device dev; uint8_t buf[] = {3,2,3,4,5,6,7,8}; pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", ip.addr); pico_string_to_ipv6("fe80:0:0:0:0102:0304:0506:0708", local.addr); pico_string_to_ipv6("fe80:0:0:0:0:0ff:fe00:1234", local2.addr); STARTING(); f->net_hdr = f->buffer; f->dev = &dev; dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN; // TEST 1 TRYING("With a MCAST IPv6 address, should return 0xFFFF\n"); hdr->dst = ip; addr = addr_802154_ll_dst(f); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode, "Should've set address mode to SHORT\n"); CHECKING(test); FAIL_UNLESS(short_be(ADDR_802154_BCAST) == addr.addr._short.addr, "Should've set address to BCAST\n"); // TEST 2 TRYING("With a link local IPv6 address derived from an extended L2 address\n"); hdr->dst = local; addr = addr_802154_ll_dst(f); dbg_addr_ext("After:", addr.addr._ext.addr); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode, "Should've set address mode to EXTENDED\n"); CHECKING(test); FAIL_UNLESS(0 == memcmp(buf, addr.addr._ext.addr, SIZE_6LOWPAN_EXT), "Should've copied the extended address from the IP address\n"); // TEST 3 TRYING("With a link local IPv6 address derived from a short L2 address\n"); hdr->dst = local2; addr = addr_802154_ll_dst(f); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode, "Should've set address mode to SHORT\n"); CHECKING(test); FAIL_UNLESS(short_be(0x1234) == addr.addr._short.addr, "Should've copied the short address from the IP address\n"); /* TODO: Test getting address from neighbour table */ ENDING(test); } END_TEST /******************************************************************************* * FRAME ******************************************************************************/ /* Frame (123 bytes) */ static uint8_t pkt[] = { 0x41, 0xcc, 0xa6, 0xff, 0xff, 0x8a, /* A..... */ 0x18, 0x00, 0xff, 0xff, 0xda, 0x1c, 0x00, 0x88, /* ........ */ 0x18, 0x00, 0xff, 0xff, 0xda, 0x1c, 0x00, 0xc1, /* ........ */ 0x09, 0x00, 0x02, 0x42, 0xfa, 0x40, 0x04, 0x01, /* ...B.@.. */ 0xf0, 0xb1, 0x01, 0x06, 0x6f, 0xaf, 0x48, 0x65, /* ....o.He */ 0x6c, 0x6c, 0x6f, 0x20, 0x30, 0x30, 0x36, 0x20, /* llo 006 */ 0x30, 0x78, 0x46, 0x46, 0x33, 0x43, 0x0a, 0x00, /* 0xFF3C.. */ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, /* ........ */ 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, /* ...... ! */ 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* "#$%&'() */ 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, /* *+,-./01 */ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 23456789 */ 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, /* :;<=>?@A */ 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, /* BCDEFGHI */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, /* JKLMNOPQ */ 0x52, 0x53, 0x54, 0x68, 0x79 /* RSThy */ }; START_TEST(tc_dst_am) { int test = 1; int ret = 0; STARTING(); // TEST 1 TRYING("Trying to determine AM of destination addr from buffer \n"); ret = dst_am((struct pico_802154_hdr *)pkt); DBG("ret = %d\n", ret); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_EXT == ret, "Should've returned the AM of an extended address\n"); ENDING(test); } END_TEST START_TEST(tc_src_am) { int test = 1; int ret = 0; STARTING(); // TEST 1 TRYING("Trying to determine AM of source addr from buffer \n"); ret = src_am((struct pico_802154_hdr *)pkt); DBG("ret = %d\n", ret); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_EXT == ret, "Should've returned the AM of an extended address\n"); ENDING(test); } END_TEST START_TEST(tc_802154_hdr_len) { int test = 1; int ret = 0; STARTING(); // TEST 1 TRYING("Trying to determine length of the header from buffer\n"); ret = frame_802154_hdr_len((struct pico_802154_hdr *)pkt); DBG("ret = %d\n", ret); CHECKING(test); FAIL_UNLESS(21 == ret, "Should've returned the correct length of the header\n"); ENDING(test); } END_TEST START_TEST(tc_802154_src) { int test = 1; struct pico_802154_hdr *hdr; struct pico_802154 addr; uint8_t src[] = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x88}; STARTING(); hdr = (struct pico_802154_hdr *)pkt; // TEST 1 TRYING("To receive the source address from a mapped buffer\n"); addr = frame_802154_src(hdr); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode, "Should've returned an extended address\n"); CHECKING(test); FAIL_UNLESS(0 == memcmp(src, addr.addr._ext.addr, SIZE_6LOWPAN_EXT), "Should've copied the extended source address\n"); ENDING(test); } END_TEST START_TEST(tc_802154_dst) { int test = 1; struct pico_802154_hdr *hdr; struct pico_802154 addr; uint8_t dst[] = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a}; STARTING(); hdr = (struct pico_802154_hdr *)pkt; // TEST 1 TRYING("To receive the source address from a mapped buffer\n"); addr = frame_802154_dst(hdr); CHECKING(test); FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode, "Should've returned an extended address\n"); CHECKING(test); FAIL_UNLESS(0 == memcmp(dst, addr.addr._ext.addr, SIZE_6LOWPAN_EXT), "Should've copied the extended source address\n"); ENDING(test); } END_TEST START_TEST(tc_802154_format) { int test = 1; struct pico_802154 src = { .addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x88}, .mode = AM_6LOWPAN_EXT }; struct pico_802154 dst = { .addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a}, .mode = AM_6LOWPAN_EXT }; struct pico_6lowpan_short pan = { .addr = short_be(0xffff) }; uint8_t buf[127] = {0}; int i = 0; STARTING(); // TEST 1 TRYING("To format a frame like sample capture\n"); frame_802154_format(buf, 166, FCF_INTRA_PAN, FCF_NO_ACK_REQ, FCF_NO_SEC, pan, src, dst); printf("Buffer:"); for (i = 0; i < 21; i++) { if (i % 8 != 0) printf("%02x ", buf[i]); else { printf("\n%02x ", buf[i]); } } printf("\n"); CHECKING(test); FAIL_UNLESS(21 == frame_802154_hdr_len((struct pico_802154_hdr *)buf), "Failed to correctly set the frame header, the length isn't right\n"); CHECKING(test); FAIL_UNLESS(0 == memcmp(pkt, buf, 21), "Failed to correctly format IEEE802.15.4 frame\n"); ENDING(test); } END_TEST START_TEST(tc_802154_process_out) { int i = 0; int ret = 0; int test = 1; struct pico_802154 src = { .addr.data = {3,2,3,4,5,6,7,8}, .mode = AM_6LOWPAN_EXT }; struct pico_802154 dst = { .addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a}, .mode = AM_6LOWPAN_EXT }; struct pico_frame *f = pico_frame_alloc(0); struct pico_6lowpan_info info = { .addr_short.addr = short_be(0x1234), .addr_ext.addr = {3,2,3,4,5,6,7,8}, .pan_id.addr = short_be(0x1234) }; struct pico_device dev; uint8_t buf[] = {0x41,0xcc,0x00,0x34,0x12,0x8a,0x18,0x00, 0xff,0xff,0xda,0x1c,0x00,0x08,0x07,0x06, 0x05,0x04,0x03,0x02,0x03}; dev.eth = (struct pico_ethdev *)&info; dev.q_out = PICO_ZALLOC(sizeof(struct pico_queue)); f->dev = &dev; dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN; STARTING(); pico_stack_init(); // TEST 1 TRYING("Trying with bare frame\n"); f->src.pan = src; f->dst.pan = dst; ret = pico_802154_process_out(f); printf("Buffer:"); for (i = 0; i < 21; i++) { if (i % 8 != 0) printf("%02x ", f->datalink_hdr[i]); else { printf("\n%02x ", f->datalink_hdr[i]); } } printf("\n"); CHECKING(test); FAIL_UNLESS(0 < ret, "Shouldn't have returned an error\n"); CHECKING(test); FAIL_UNLESS(0 == memcmp(buf, f->datalink_hdr, 21), "Frame isn't correctly formatted\n"); pico_frame_discard(f); ENDING(test); } END_TEST START_TEST(tc_802154_process_in) { int ret = 0; int test = 1; struct pico_802154 src = { .addr.data = {3,2,3,4,5,6,7,8}, .mode = AM_6LOWPAN_EXT }; struct pico_802154 dst = { .addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a}, .mode = AM_6LOWPAN_EXT }; struct pico_frame *f = pico_frame_alloc(22); uint8_t buf[] = {0x41,0xcc,0x00,0x34,0x12,0x8a,0x18,0x00, 0xff,0xff,0xda,0x1c,0x00,0x08,0x07,0x06, 0x05,0x04,0x03,0x02,0x03,0x60}; memcpy(f->buffer, buf, 22); f->src.pan = src; f->dst.pan = dst; STARTING(); pico_stack_init(); TRYING("Apply processing function on predefined buffer\n"); ret = pico_802154_process_in(f); CHECKING(test); FAIL_UNLESS(0 < ret, "Should not return failure\n"); } END_TEST static Suite *pico_suite(void) { Suite *s = suite_create("PicoTCP"); TCase *TCase_swap = tcase_create("Unit test for pico_swap"); TCase *TCase_802154_to_ietf = tcase_create("Unit test for 802154_to_ietf"); TCase *TCase_802154_ll_src = tcase_create("Unit test for 802154_ll_src"); TCase *TCase_802154_ll_dst = tcase_create("Unit test for 802154_ll_dst"); TCase *TCase_802154_hdr_len = tcase_create("Unit test for 802154_hdr_len"); TCase *TCase_src_am = tcase_create("Unit test for src_am"); TCase *TCase_dst_am = tcase_create("Unit test for dst_am"); TCase *TCase_802154_src = tcase_create("Unit test for 802154_src"); TCase *TCase_802154_dst = tcase_create("Unit test for 802154_dst"); TCase *TCase_802154_format = tcase_create("Unit test for 802154_format"); TCase *TCase_802154_process_out = tcase_create("Unit test for 802154_process_out"); TCase *TCase_802154_process_in = tcase_create("Unit test for 802154_process_in"); /******************************************************************************* * ADDRESSES ******************************************************************************/ tcase_add_test(TCase_swap, tc_swap); suite_add_tcase(s, TCase_swap); tcase_add_test(TCase_802154_to_ietf, tc_802154_to_ietf); suite_add_tcase(s, TCase_802154_to_ietf); tcase_add_test(TCase_802154_ll_src, tc_802154_ll_src); suite_add_tcase(s, TCase_802154_ll_src); tcase_add_test(TCase_802154_ll_dst, tc_802154_ll_dst); suite_add_tcase(s, TCase_802154_ll_dst); /******************************************************************************* * FRAME ******************************************************************************/ tcase_add_test(TCase_802154_hdr_len, tc_802154_hdr_len); suite_add_tcase(s, TCase_802154_hdr_len); tcase_add_test(TCase_src_am, tc_src_am); suite_add_tcase(s, TCase_src_am); tcase_add_test(TCase_dst_am, tc_dst_am); suite_add_tcase(s, TCase_dst_am); tcase_add_test(TCase_802154_src, tc_802154_src); suite_add_tcase(s, TCase_802154_src); tcase_add_test(TCase_802154_dst, tc_802154_dst); suite_add_tcase(s, TCase_802154_dst); tcase_add_test(TCase_802154_format, tc_802154_format); suite_add_tcase(s, TCase_802154_format); tcase_add_test(TCase_802154_process_out, tc_802154_process_out); suite_add_tcase(s, TCase_802154_process_out); tcase_add_test(TCase_802154_process_in, tc_802154_process_in); suite_add_tcase(s, TCase_802154_process_in); return s; } int main(void) { int fails; Suite *s = pico_suite(); SRunner *sr = srunner_create(s); srunner_run_all(sr, CK_NORMAL); fails = srunner_ntests_failed(sr); srunner_free(sr); return fails; }
END_TEST START_TEST(tc_destination_is_mcast) { struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }}; struct pico_ip6 mcast = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }}; struct pico_ip4 addr4 = {0}; struct pico_ip4 mcast4 = {0}; struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr)); struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *)f->buffer; struct pico_ipv4_hdr *h4 = (struct pico_ipv4_hdr *)f->buffer; /* Test parameters */ int ret = 0, count = 0; f->net_hdr = (uint8_t*) h; f->buffer[0] = 0x60; /* Ipv6 */ STARTING(); pico_string_to_ipv4("232.1.1.0", &(mcast4.addr)); /* 0 */ pico_string_to_ipv4("10.20.0.1", &(addr4.addr)); pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", (mcast.addr)); /* 0 */ pico_string_to_ipv6("fe80:0:0:0:0:0:a28:100", (addr.addr)); /* 0 */ TRYING("With IPv6 unicast addr\n"); memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6); ret = destination_is_mcast(f); CHECKING(count); fail_unless(0 == ret, "Should've returned 0 since not an IPv6 multicast\n"); SUCCESS(); TRYING("With IPv6 multicast addr\n"); memcpy(h->dst.addr, mcast.addr, PICO_SIZE_IP6); ret = destination_is_mcast(f); CHECKING(count); fail_unless(1 == ret, "Should've returned 1 since an IPv6 multicast\n"); SUCCESS(); pico_frame_discard(f); f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr)); h4 = (struct pico_ipv4_hdr *)f->buffer; f->net_hdr = (uint8_t *)h4; f->buffer[0] = 0x40; /* IPv4 */ TRYING("With IPv4 unicast addr\n"); h4->dst = addr4; ret = destination_is_bcast(f); CHECKING(count); fail_unless(0 == ret, "Should've returned 0 since not an IPv4 mcast address\n"); SUCCESS(); TRYING("With IPv4 multicast addr\n"); h4->dst = mcast4; ret = destination_is_mcast(f); CHECKING(count); fail_unless(1 == ret, "Should've returned 1 since an IPv4 multicast\n"); SUCCESS(); BREAKING(); ret = destination_is_bcast(NULL); CHECKING(count); fail_unless(0 == ret, "Should've returned 0 since NULL-pointer\n"); SUCCESS(); ENDING(count); }