START_TEST (test_ipv4) { #define IP_TST_SIZ 256 int i; struct pico_device *dev[IP_TST_SIZ]; char devname[8]; struct pico_ip4 a[IP_TST_SIZ], d[IP_TST_SIZ], *source[IP_TST_SIZ], nm16, nm32, gw[IP_TST_SIZ], r[IP_TST_SIZ], ret; struct pico_ipv4_link *l[IP_TST_SIZ]; char ipstr[] = "192.168.1.1"; struct pico_ip4 ipaddr; struct pico_frame *f_NULL = NULL; struct pico_ip4 *dst_NULL = NULL; pico_stack_init(); nm16.addr = long_be(0xFFFF0000); nm32.addr = long_be(0xFFFFFFFF); /*link_add*/ for (i = 0; i < IP_TST_SIZ; i++) { snprintf(devname, 8, "nul%d", i); dev[i] = pico_null_create(devname); a[i].addr = long_be(0x0a000001 + (i << 16)); d[i].addr = long_be(0x0a000002 + (i << 16)); fail_if(pico_ipv4_link_add(dev[i], a[i], nm16) != 0, "Error adding link"); } /*link_find + link_get + route_add*/ for (i = 0; i < IP_TST_SIZ; i++) { gw[i].addr = long_be(0x0a0000f0 + (i << 16)); r[i].addr = long_be(0x0c00001 + (i << 16)); fail_unless(pico_ipv4_link_find(&a[i]) == dev[i], "Error finding link"); l[i] = pico_ipv4_link_get(&a[i]); fail_if(l[i] == NULL, "Error getting link"); fail_if(pico_ipv4_route_add(r[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route"); fail_if(pico_ipv4_route_add(d[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route"); } /*get_gateway + source_find*/ for (i = 0; i < IP_TST_SIZ; i++) { ret = pico_ipv4_route_get_gateway(&r[i]); fail_if(ret.addr != gw[i].addr, "Error get gateway: returned wrong route"); source[i] = pico_ipv4_source_find(&d[i]); fail_if(source[i]->addr != a[i].addr, "Error find source: returned wrong route"); } /*route_del + link_del*/ for (i = 0; i < IP_TST_SIZ; i++) { fail_if(pico_ipv4_route_del(r[i], nm32, 1) != 0, "Error deleting route"); fail_if(pico_ipv4_link_del(dev[i], a[i]) != 0, "Error deleting link"); } /*string_to_ipv4 + ipv4_to_string*/ pico_string_to_ipv4(ipstr, &(ipaddr.addr)); fail_if(ipaddr.addr != long_be(0xc0a80101), "Error string to ipv4"); memset(ipstr, 0, 12); pico_ipv4_to_string(ipstr, ipaddr.addr); fail_if(strncmp(ipstr, "192.168.1.1", 11) != 0, "Error ipv4 to string"); /*valid_netmask*/ fail_if(pico_ipv4_valid_netmask(long_be(nm32.addr)) != 32, "Error checking netmask"); /*is_unicast*/ fail_if((pico_ipv4_is_unicast(long_be(0xc0a80101))) != 1, "Error checking unicast"); fail_if((pico_ipv4_is_unicast(long_be(0xe0000001))) != 0, "Error checking unicast"); /*rebound*/ fail_if(pico_ipv4_rebound(f_NULL) != -1, "Error rebound frame"); /*frame_push*/ fail_if(pico_ipv4_frame_push(f_NULL, dst_NULL, PICO_PROTO_TCP) != -1, "Error push frame"); } END_TEST START_TEST (test_nat_enable_disable) { struct pico_ipv4_link link = { .address = {.addr = long_be(0x0a320001)} }; /* 10.50.0.1 */ struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, PICO_UDPHDR_SIZE); struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr; struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr; char *raw_data = "ello"; net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */ net->tos = 0; net->len = short_be(32); /* hdr + data (bytes) */ net->id = short_be(0x91c0); net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */ net->ttl = 64; net->proto = 17; /* UDP */ net->crc = 0; net->crc = pico_ipv4_checksum(f); net->src.addr = long_be(0x0a280008); /* 10.40.0.8 */ net->dst.addr = long_be(0x0a320001); /* 10.50.0.1 */ udp->trans.sport = short_be(5555); udp->trans.dport = short_be(6667); udp->len = 12; udp->crc = 0; f->payload = f->transport_hdr + PICO_UDPHDR_SIZE; memcpy(f->payload, raw_data, 4); printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT ENABLE/DISABLE TEST\n"); pico_stack_init(); fail_if(pico_ipv4_nat_enable(&link)); fail_unless(nat_link->address.addr == link.address.addr); fail_unless(pico_ipv4_nat_is_enabled(&link.address)); fail_if(pico_ipv4_nat_outbound(f, &net->dst)); pico_ipv4_nat_table_cleanup(pico_tick, NULL); fail_if(pico_ipv4_nat_disable()); fail_if(pico_ipv4_nat_is_enabled(&link.address)); } END_TEST START_TEST (test_nat_translation) { struct pico_ipv4_link link = { .address = {.addr = long_be(0x0a320001)} }; /* 10.50.0.1 */ struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, PICO_UDPHDR_SIZE); struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr; struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr; struct pico_ip4 src_ori = { .addr = long_be(0x0a280008) }; /* 10.40.0.8 */ struct pico_ip4 dst_ori = { .addr = long_be(0x0a320009) }; /* 10.50.0.9 */ struct pico_ip4 nat = { .addr = long_be(0x0a320001) }; /* 10.50.0.9 */ char *raw_data = "ello"; uint16_t sport_ori = short_be(5555); uint16_t dport_ori = short_be(6667); uint16_t nat_port = 0; net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */ net->tos = 0; net->len = short_be(32); /* hdr + data (bytes) */ net->id = short_be(0x91c0); net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */ net->ttl = 64; net->proto = 17; /* UDP */ net->crc = 0; net->crc = pico_ipv4_checksum(f); net->src = src_ori; net->dst = dst_ori; udp->trans.sport = sport_ori; udp->trans.dport = dport_ori; udp->len = 12; udp->crc = 0; f->payload = f->transport_hdr + PICO_UDPHDR_SIZE; memcpy(f->payload, raw_data, 4); printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT TRANSLATION TEST\n"); pico_stack_init(); fail_if(pico_ipv4_nat_enable(&link)); /* perform outbound translation, check if source IP got translated */ fail_if(pico_ipv4_nat_outbound(f, &nat_link->address)); fail_if(net->src.addr != link.address.addr, "source address not translated"); /* perform outbound translation of same packet, check if source IP and PORT got translated the same as previous packet */ nat_port = udp->trans.sport; net->src = src_ori; /* restore original src */ udp->trans.sport = sport_ori; /* restore original sport */ fail_if(pico_ipv4_nat_outbound(f, &nat_link->address)); fail_if(net->src.addr != link.address.addr, "source address not translated"); fail_if(udp->trans.sport != nat_port, "frames with the same source IP, source PORT and PROTO did not get translated the same"); /* perform outbound translation of packet with changed source PORT, check if source PORT got translated differently as previous packet */ nat_port = udp->trans.sport; net->src = src_ori; /* restore original src */ udp->trans.sport = short_be(5556); /* change sport */ fail_if(pico_ipv4_nat_outbound(f, &nat_link->address)); fail_if(net->src.addr != link.address.addr, "source address not translated"); fail_if(udp->trans.sport == short_be(sport_ori), "two frames with different sport get translated the same"); /* perform inbound translation of previous packet, check if destination IP and PORT got translated to the original source IP and PORT */ nat_port = udp->trans.sport; net->src = dst_ori; net->dst = nat; udp->trans.sport = sport_ori; udp->trans.dport = nat_port; fail_if(pico_ipv4_nat_inbound(f, &nat_link->address)); fail_if(net->dst.addr != src_ori.addr, "destination address not translated correctly"); fail_if(udp->trans.dport != short_be(5556), "ports not translated correctly"); pico_ipv4_nat_table_cleanup(pico_tick, NULL); fail_if(pico_ipv4_nat_disable()); } END_TEST START_TEST (test_nat_port_forwarding) { struct pico_ipv4_link link = { .address = {.addr = long_be(0x0a320001)} }; /* 10.50.0.1 */ struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, PICO_UDPHDR_SIZE); struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr; struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr; struct pico_ip4 src_addr = { .addr = long_be(0x0a280008) }; /* 10.40.0.8 */ struct pico_ip4 dst_addr = { .addr = long_be(0x0a320009) }; /* 10.50.0.9 */ struct pico_ip4 nat_addr = { .addr = long_be(0x0a320001) }; /* 10.50.0.9 */ char *raw_data = "ello"; uint16_t sport_ori = short_be(5555); uint16_t fport_pub = short_be(80); uint16_t fport_priv = short_be(8080); net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */ net->tos = 0; net->len = short_be(32); /* hdr + data (bytes) */ net->id = short_be(0x91c0); net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */ net->ttl = 64; net->proto = 17; /* UDP */ net->crc = 0; net->crc = pico_ipv4_checksum(f); net->src = dst_addr; net->dst = nat_addr; udp->trans.sport = sport_ori; udp->trans.dport = fport_pub; udp->len = 12; udp->crc = 0; f->payload = f->transport_hdr + PICO_UDPHDR_SIZE; memcpy(f->payload, raw_data, 4); printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT PORT FORWARD TEST\n"); pico_stack_init(); fail_if(pico_ipv4_nat_enable(&link)); fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_ADD)); fail_if(pico_ipv4_nat_inbound(f, &nat_link->address)); fail_if(net->dst.addr != src_addr.addr, "destination address not translated correctly"); fail_if(udp->trans.dport != fport_priv, "destination port not translated correctly"); fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_DEL)); pico_ipv4_nat_table_cleanup(pico_tick, NULL); } END_TEST START_TEST (test_ipfilter) { struct pico_device *dev = NULL; uint8_t proto = 0, tos = 0; uint16_t sport = 0, dport = 0; int8_t priority = 0; int ret = 0; struct pico_ip4 src_addr = { 0 }; struct pico_ip4 saddr_netmask = { 0 }; struct pico_ip4 dst_addr = { 0 }; struct pico_ip4 daddr_netmask = { 0 }; enum filter_action action = 1; int filter_id1; /* 192.168.1.2:16415 -> 192.168.1.109:1222 [sending a TCP syn] */ uint8_t ipv4_buf[] = { 0x00, 0x02, 0xf7, 0xf1, 0x79, 0x33, 0xe0, 0xdb, 0x55, 0xd4, 0xb6, 0x27, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf7, 0x0f, 0xc0, 0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x6d, 0x40, 0x1f, 0x04, 0xc6, 0x00, 0xb1, 0x56, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x70, 0x32, 0x00, 0x00 }; struct pico_frame *f; printf("IP Filter> Adding a new filter...\n"); filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action); fail_if(filter_id1 <= 0, "Error adding filter\n"); printf("filter_id1 = %d\n", filter_id1); printf("IP Filter> Trying to add the same filter...\n"); ret = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action); fail_if(ret > 0, "Error adding filter\n"); printf("IP Filter> Deleting added filter...\n"); ret = pico_ipv4_filter_del(filter_id1); fail_if(ret != 0, "Error deleting the filter\n"); printf("IP Filter> Trying to delete the same filter\n"); ret = pico_ipv4_filter_del(filter_id1); fail_if(ret != -1, "Deleting non existing filter failed\n"); f = (struct pico_frame *)PICO_ZALLOC(200); f->buffer = PICO_ZALLOC(20); f->usage_count = PICO_ZALLOC(sizeof(uint32_t)); f->buffer = ipv4_buf; f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */ f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */ /* adding exact filter */ pico_string_to_ipv4("192.168.1.109", &src_addr.addr); pico_string_to_ipv4("255.255.255.255", &saddr_netmask.addr); sport = 1222u; filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_REJECT); fail_if(filter_id1 <= 0, "Error adding exact filter\n"); printf("Filter is added\n"); sync(); sleep(1); ret = ipfilter(f); fail_if(ret != 1, "Frame wasn't filtered\n"); printf("IP Filter> Deleting added filter...\n"); ret = pico_ipv4_filter_del(filter_id1); fail_if(ret != 0, "Error deleting the filter\n"); printf("IP Filter> Adding masked filter...\n"); pico_string_to_ipv4("192.168.1.7", &src_addr.addr); pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr); sport = 1222u; filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP); fail_if(filter_id1 <= 0, "Error adding masked filter\n"); f = (struct pico_frame *)PICO_ZALLOC(200); f->buffer = PICO_ZALLOC(20); f->usage_count = PICO_ZALLOC(sizeof(uint32_t)); f->buffer = ipv4_buf; f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */ f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */ ret = ipfilter(f); fail_if(ret != 1, "Mask filter failed to filter\n"); printf("IP Filter> Deleting added filter...\n"); ret = pico_ipv4_filter_del(filter_id1); fail_if(ret != 0, "Error deleting the filter\n"); printf("IP Filter> Adding bad filter..\n"); pico_string_to_ipv4("191.1.1.7", &src_addr.addr); pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr); sport = 1991u; filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP); fail_if(filter_id1 <= 0, "Error adding bad filter\n"); f = (struct pico_frame *)PICO_ZALLOC(200); f->buffer = PICO_ZALLOC(20); f->usage_count = PICO_ZALLOC(sizeof(uint32_t)); f->buffer = ipv4_buf; f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */ f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */ ret = ipfilter(f); fail_if(ret != 0, "Filter shouldn't have filtered this frame\n"); printf("IP Filter> Deleting added filter...\n"); ret = pico_ipv4_filter_del(filter_id1); fail_if(ret != 0, "Error deleting the filter\n"); } END_TEST #ifdef PICO_SUPPORT_MCAST START_TEST (test_igmp_sockopts) { int i = 0, j = 0, k = 0, ret = 0; struct pico_socket *s, *s1 = NULL; struct pico_device *dev = NULL; union pico_address *source = NULL; union pico_address inaddr_dst = { 0 }, inaddr_incorrect = { 0 }, inaddr_uni = { 0 }, inaddr_null = { 0 }, netmask = { 0 }; union pico_address inaddr_link[2] = {{0}}; union pico_address inaddr_mcast[8] = {{0}}; union pico_address inaddr_source[8] = {{0}}; struct pico_ip_mreq _mreq = {{0}}, mreq[16] = {{{0}}}; struct pico_ip_mreq_source mreq_source[128] = {{{0}}}; struct pico_tree_node *index = NULL; int ttl = 64; int getttl = 0; int loop = 9; int getloop = 0; union pico_address mcast_default_link = { 0 }; pico_stack_init(); printf("START IGMP SOCKOPTS TEST\n"); pico_string_to_ipv4("224.7.7.7", &inaddr_dst.ip4.addr); pico_string_to_ipv4("10.40.0.2", &inaddr_uni.ip4.addr); pico_string_to_ipv4("224.8.8.8", &inaddr_incorrect.ip4.addr); pico_string_to_ipv4("0.0.0.0", &inaddr_null.ip4.addr); pico_string_to_ipv4("10.40.0.1", &inaddr_link[0].ip4.addr); /* 0 */ pico_string_to_ipv4("10.50.0.1", &inaddr_link[1].ip4.addr); /* 1 */ pico_string_to_ipv4("232.1.1.0", &inaddr_mcast[0].ip4.addr); /* 0 */ pico_string_to_ipv4("232.2.2.1", &inaddr_mcast[1].ip4.addr); /* 1 */ pico_string_to_ipv4("232.3.3.2", &inaddr_mcast[2].ip4.addr); /* 2 */ pico_string_to_ipv4("232.4.4.3", &inaddr_mcast[3].ip4.addr); /* 3 */ pico_string_to_ipv4("232.5.5.4", &inaddr_mcast[4].ip4.addr); /* 4 */ pico_string_to_ipv4("232.6.6.5", &inaddr_mcast[5].ip4.addr); /* 5 */ pico_string_to_ipv4("232.7.7.6", &inaddr_mcast[6].ip4.addr); /* 6 */ pico_string_to_ipv4("232.8.8.7", &inaddr_mcast[7].ip4.addr); /* 7 */ pico_string_to_ipv4("10.40.1.0", &inaddr_source[0].ip4.addr); /* 0 */ pico_string_to_ipv4("10.40.1.1", &inaddr_source[1].ip4.addr); /* 1 */ pico_string_to_ipv4("10.40.1.2", &inaddr_source[2].ip4.addr); /* 2 */ pico_string_to_ipv4("10.40.1.3", &inaddr_source[3].ip4.addr); /* 3 */ pico_string_to_ipv4("10.40.1.4", &inaddr_source[4].ip4.addr); /* 4 */ pico_string_to_ipv4("10.40.1.5", &inaddr_source[5].ip4.addr); /* 5 */ pico_string_to_ipv4("10.40.1.6", &inaddr_source[6].ip4.addr); /* 6 */ pico_string_to_ipv4("10.40.1.7", &inaddr_source[7].ip4.addr); /* 7 */ /* 00 01 02 03 04 05 06 07 | 10 11 12 13 14 15 16 17 */ for (i = 0; i < 16; i++) { mreq[i].mcast_link_addr = inaddr_link[i / 8]; mreq[i].mcast_group_addr = inaddr_mcast[i % 8]; } /* 000 001 002 003 004 005 006 007 | 010 011 012 013 014 015 016 017 */ for (i = 0; i < 16; i++) { for (j = 0; j < 8; j++) { /* printf(">>>>> mreq_source[%d]: link[%d] mcast[%d] source[%d]\n", (i*8)+j, i/8, i%8, j); */ mreq_source[(i * 8) + j].mcast_link_addr = inaddr_link[i / 8]; mreq_source[(i * 8) + j].mcast_group_addr = inaddr_mcast[i % 8]; mreq_source[(i * 8) + j].mcast_source_addr = inaddr_source[j]; } } dev = pico_null_create("dummy0"); netmask.ip4.addr = long_be(0xFFFF0000); ret = pico_ipv4_link_add(dev, inaddr_link[0].ip4, netmask.ip4); fail_if(ret < 0, "link add failed"); dev = pico_null_create("dummy1"); netmask.ip4.addr = long_be(0xFFFF0000); ret = pico_ipv4_link_add(dev, inaddr_link[1].ip4, netmask.ip4); fail_if(ret < 0, "link add failed"); s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL); fail_if(s == NULL, "UDP socket open failed"); s1 = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL); fail_if(s1 == NULL, "UDP socket open failed"); /* argument validation tests */ printf("IGMP SETOPTION ARGUMENT VALIDATION TEST\n"); ret = pico_socket_setoption(s, PICO_IP_MULTICAST_IF, &mcast_default_link); fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n"); ret = pico_socket_getoption(s, PICO_IP_MULTICAST_IF, &mcast_default_link); fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_MULTICAST_TTL, &ttl); fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n"); ret = pico_socket_getoption(s, PICO_IP_MULTICAST_TTL, &getttl); fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n"); fail_if(getttl != ttl, "setoption ttl != getoption ttl\n"); ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop); fail_if(ret == 0, "PICO_IP_MULTICAST_LOOP succeeded with invalid (not 0 or 1) loop value\n"); loop = 0; ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop); fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed disabling\n"); ret = pico_socket_getoption(s, PICO_IP_MULTICAST_LOOP, &getloop); fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed getting value\n"); fail_if(getloop != loop, "setoption loop != getoption loop\n"); _mreq.mcast_group_addr = inaddr_dst; _mreq.mcast_link_addr = inaddr_link[0]; ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq); fail_if(ret < 0, "supported PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq); fail_if(ret < 0, "supported PICO_IP_DROP_MEMBERSHIP failed\n"); _mreq.mcast_group_addr = inaddr_dst; _mreq.mcast_link_addr = inaddr_null; ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed with valid NULL (use default) link address\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed with valid NULL (use default) link address\n"); _mreq.mcast_group_addr = inaddr_uni; _mreq.mcast_link_addr = inaddr_link[0]; ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq); fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (unicast) group address\n"); _mreq.mcast_group_addr = inaddr_null; _mreq.mcast_link_addr = inaddr_link[0]; ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq); fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (NULL) group address\n"); _mreq.mcast_group_addr = inaddr_dst; _mreq.mcast_link_addr = inaddr_uni; ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq); fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid link address\n"); _mreq.mcast_group_addr = inaddr_incorrect; _mreq.mcast_link_addr = inaddr_link[0]; ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq); fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (not added) group address\n"); _mreq.mcast_group_addr = inaddr_uni; _mreq.mcast_link_addr = inaddr_link[0]; ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq); fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) group address\n"); _mreq.mcast_group_addr = inaddr_null; _mreq.mcast_link_addr = inaddr_link[0]; ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq); fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (NULL) group address\n"); _mreq.mcast_group_addr = inaddr_dst; _mreq.mcast_link_addr = inaddr_uni; ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq); fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) link address\n"); /* flow validation tests */ printf("IGMP SETOPTION FLOW VALIDATION TEST\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed with err %s\n", strerror(pico_err)); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_UNBLOCK_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_BLOCK_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n"); ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); /* stress tests */ printf("IGMP SETOPTION STRESS TEST\n"); for (k = 0; k < 2; k++) { /* ADD for even combinations of group and link, ADD_SOURCE for uneven */ for (i = 0; i < 16; i++) { if (i % 2) { ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[i]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); for (j = 0; j < 8; j++) { ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[(i * 8) + j]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); } } else { for (j = 0; j < 8; j++) { ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); } } } /* UNBLOCK and DROP for even combinations, DROP_SOURCE for uneven */ for (i = 0; i < 16; i++) { if (i % 2) { for (j = 0; j < 8; j++) { ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[(i * 8) + j]); fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n"); } ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[i]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); } else { for (j = 0; j < 8; j++) { ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]); fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n"); } } } /* everything should be cleanup up, next iteration will fail if not */ } /* filter validation tests */ printf("IGMP SETOPTION FILTER VALIDATION TEST\n"); /* INCLUDE + INCLUDE expected filter: source of 0 and 1*/ ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); i = 0; pico_tree_foreach(index, &MCASTFilter) { if (++i > 2) fail("MCASTFilter (INCLUDE + INCLUDE) too many elements\n"); source = index->keyValue; if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */ } else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */ } else { fail("MCASTFilter (INCLUDE + INCLUDE) incorrect\n"); } } ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); /* INCLUDE + EXCLUDE expected filter: source of 2 */ ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[1]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[2]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); i = 0; pico_tree_foreach(index, &MCASTFilter) { if (++i > 1) fail("MCASTFilter (INCLUDE + EXCLUDE) too many elements\n"); source = index->keyValue; if (source->ip4.addr == mreq_source[2].mcast_source_addr.ip4.addr) { /* OK */ } else { fail("MCASTFilter (INCLUDE + EXCLUDE) incorrect\n"); } } ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); /* EXCLUDE + INCLUDE expected filter: source of 0 and 1 */ ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[3]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[4]); fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n"); i = 0; pico_tree_foreach(index, &MCASTFilter) { if (++i > 2) fail("MCASTFilter (EXCLUDE + INCLUDE) too many elements\n"); source = index->keyValue; if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */ } else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */ } else { fail("MCASTFilter (EXCLUDE + INCLUDE) incorrect\n"); } } ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); /* EXCLUDE + EXCLUDE expected filter: source of 3 and 4 */ ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[3]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[4]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[5]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[6]); fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n"); i = 0; pico_tree_foreach(index, &MCASTFilter) { if (++i > 2) fail("MCASTFilter (EXCLUDE + EXCLUDE) too many elements\n"); source = index->keyValue; if (source->ip4.addr == mreq_source[3].mcast_source_addr.ip4.addr) { /* OK */ } else if (source->ip4.addr == mreq_source[4].mcast_source_addr.ip4.addr) { /* OK */ } else { fail("MCASTFilter (EXCLUDE + EXCLUDE) incorrect\n"); } } ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]); fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n"); ret = pico_socket_close(s); fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err)); ret = pico_socket_close(s1); fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err)); } END_TEST #endif START_TEST (test_slaacv4) { uint32_t tmp; struct pico_device *dev; struct mock_device *mock; char ip_addr[20]; uint8_t macaddr1[6] = { 0xc1, 0, 0, 0xa, 0xb, 0xf }; /* verify min boundary*/ tmp = SLAACV4_CREATE_IPV4(0); pico_ipv4_to_string(ip_addr, tmp); printf("IP address generated by slaac: %s\n", ip_addr); fail_if(long_be(tmp) < (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE)); /* verify max boundary*/ tmp = SLAACV4_CREATE_IPV4(0x00FD); fail_if(long_be(tmp) > (long_be(SLAACV4_NETWORK) | 0x0000FEFF)); /* verify case where dev->eth is NULL */ dev = pico_null_create("dummy"); tmp = pico_slaacv4_getip(dev, 0); fail_if(long_be(tmp) != (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE)); /* verify nominal case; two runs of slaacv4_get_ip need to return same value */ mock = pico_mock_create(macaddr1); tmp = pico_slaacv4_getip(mock->dev, 0); fail_if(tmp != pico_slaacv4_getip(mock->dev, 0)); } END_TEST