1
2START_TEST (test_ipv4)
3{
4  #define IP_TST_SIZ 256
5    uint32_t i;
6
7    struct pico_device *dev[IP_TST_SIZ];
8    char devname[8];
9    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;
10    struct pico_ipv4_link *l[IP_TST_SIZ];
11
12    char ipstr[] = "192.168.1.1";
13    struct pico_ip4 ipaddr;
14
15    struct pico_frame *f_NULL = NULL;
16    struct pico_ip4 *dst_NULL = NULL;
17
18    pico_stack_init();
19
20    nm16.addr = long_be(0xFFFF0000);
21    nm32.addr = long_be(0xFFFFFFFF);
22
23    /*link_add*/
24    for (i = 0; i < IP_TST_SIZ; i++) {
25        snprintf(devname, 8, "nul%d", i);
26        dev[i] = pico_null_create(devname);
27        a[i].addr = long_be(0x0a000001u + (i << 16));
28        d[i].addr = long_be(0x0a000002u + (i << 16));
29        fail_if(pico_ipv4_link_add(dev[i], a[i], nm16) != 0, "Error adding link");
30    }
31    /*link_find + link_get + route_add*/
32    for (i = 0; i < IP_TST_SIZ; i++) {
33        gw[i].addr = long_be(0x0a0000f0u + (i << 16));
34        r[i].addr = long_be(0x0c00001u + (i << 16));
35        fail_unless(pico_ipv4_link_find(&a[i]) == dev[i], "Error finding link");
36        l[i] = pico_ipv4_link_get(&a[i]);
37        fail_if(l[i] == NULL, "Error getting link");
38        fail_if(pico_ipv4_route_add(r[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route");
39        fail_if(pico_ipv4_route_add(d[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route");
40    }
41    /*get_gateway + source_find*/
42    for (i = 0; i < IP_TST_SIZ; i++) {
43        ret = pico_ipv4_route_get_gateway(&r[i]);
44        fail_if(ret.addr != gw[i].addr, "Error get gateway: returned wrong route");
45        source[i] = pico_ipv4_source_find(&d[i]);
46        fail_if(source[i]->addr != a[i].addr, "Error find source: returned wrong route");
47    }
48    /*route_del + link_del*/
49    for (i = 0; i < IP_TST_SIZ; i++) {
50        fail_if(pico_ipv4_route_del(r[i], nm32, 1) != 0, "Error deleting route");
51        fail_if(pico_ipv4_link_del(dev[i], a[i]) != 0, "Error deleting link");
52    }
53    /*string_to_ipv4 + ipv4_to_string*/
54    pico_string_to_ipv4(ipstr, &(ipaddr.addr));
55    fail_if(ipaddr.addr != long_be(0xc0a80101), "Error string to ipv4");
56    memset(ipstr, 0, 12);
57    pico_ipv4_to_string(ipstr, ipaddr.addr);
58    fail_if(strncmp(ipstr, "192.168.1.1", 11) != 0, "Error ipv4 to string");
59
60    /*valid_netmask*/
61    fail_if(pico_ipv4_valid_netmask(long_be(nm32.addr)) != 32, "Error checking netmask");
62
63    /*is_unicast*/
64    fail_if((pico_ipv4_is_unicast(long_be(0xc0a80101))) != 1, "Error checking unicast");
65    fail_if((pico_ipv4_is_unicast(long_be(0xe0000001))) != 0, "Error checking unicast");
66
67    /*rebound*/
68    fail_if(pico_ipv4_rebound(f_NULL) != -1, "Error rebound frame");
69
70    /*frame_push*/
71    fail_if(pico_ipv4_frame_push(f_NULL, dst_NULL, PICO_PROTO_TCP) != -1, "Error push frame");
72}
73END_TEST
74
75START_TEST (test_nat_enable_disable)
76{
77    struct pico_ipv4_link link = {
78        .address = {.addr = long_be(0x0a320001)}
79    };                                                                       /* 10.50.0.1 */
80    struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
81    struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
82    struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
83    const char *raw_data = "ello";
84
85    net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
86    net->tos = 0;
87    net->len = short_be(32); /* hdr + data (bytes) */
88    net->id = short_be(0x91c0);
89    net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
90    net->ttl = 64;
91    net->proto = 17; /* UDP */
92    net->crc = 0;
93    net->src.addr = long_be(0x0a280008); /* 10.40.0.8 */
94    net->dst.addr = long_be(0x0a320001); /* 10.50.0.1 */
95
96    udp->trans.sport = short_be(5555);
97    udp->trans.dport = short_be(6667);
98    udp->len = 12;
99    udp->crc = 0;
100
101    f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
102    memcpy(f->payload, raw_data, 4);
103
104    printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT ENABLE/DISABLE TEST\n");
105    pico_stack_init();
106
107    fail_if(pico_ipv4_nat_enable(&link));
108    fail_unless(nat_link->address.addr == link.address.addr);
109    fail_unless(pico_ipv4_nat_is_enabled(&link.address));
110
111    fail_if(pico_ipv4_nat_outbound(f, &net->dst));
112    pico_ipv4_nat_table_cleanup(pico_tick, NULL);
113
114    fail_if(pico_ipv4_nat_disable());
115    fail_if(pico_ipv4_nat_is_enabled(&link.address));
116}
117END_TEST
118
119START_TEST (test_nat_translation)
120{
121    struct pico_ipv4_link link = {
122        .address = {.addr = long_be(0x0a320001)}
123    };                                                                       /* 10.50.0.1 */
124    struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
125    struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
126    struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
127    struct pico_ip4 src_ori = {
128        .addr = long_be(0x0a280008)
129    };                                                      /* 10.40.0.8 */
130    struct pico_ip4 dst_ori = {
131        .addr = long_be(0x0a320009)
132    };                                                      /* 10.50.0.9 */
133    struct pico_ip4 nat = {
134        .addr = long_be(0x0a320001)
135    };                                                  /* 10.50.0.9 */
136    const char *raw_data = "ello";
137    uint16_t sport_ori = short_be(5555);
138    uint16_t dport_ori = short_be(6667);
139    uint16_t nat_port = 0;
140
141    net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
142    net->tos = 0;
143    net->len = short_be(32); /* hdr + data (bytes) */
144    net->id = short_be(0x91c0);
145    net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
146    net->ttl = 64;
147    net->proto = 17; /* UDP */
148    net->crc = 0;
149    net->src = src_ori;
150    net->dst = dst_ori;
151
152    udp->trans.sport = sport_ori;
153    udp->trans.dport = dport_ori;
154    udp->len = 12;
155    udp->crc = 0;
156
157    f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
158    memcpy(f->payload, raw_data, 4);
159
160    printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT TRANSLATION TEST\n");
161    pico_stack_init();
162    fail_if(pico_ipv4_nat_enable(&link));
163
164    /* perform outbound translation, check if source IP got translated */
165    fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
166    fail_if(net->src.addr != link.address.addr, "source address not translated");
167
168    /* perform outbound translation of same packet, check if source IP and PORT got translated the same as previous packet */
169    nat_port = udp->trans.sport;
170    net->src = src_ori; /* restore original src */
171    udp->trans.sport = sport_ori; /* restore original sport */
172    fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
173    fail_if(net->src.addr != link.address.addr, "source address not translated");
174    fail_if(udp->trans.sport != nat_port, "frames with the same source IP, source PORT and PROTO did not get translated the same");
175
176    /* perform outbound translation of packet with changed source PORT, check if source PORT got translated differently as previous packet */
177    nat_port = udp->trans.sport;
178    net->src = src_ori; /* restore original src */
179    udp->trans.sport = short_be(5556); /* change sport */
180    fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
181    fail_if(net->src.addr != link.address.addr, "source address not translated");
182    fail_if(udp->trans.sport == short_be(sport_ori), "two frames with different sport get translated the same");
183
184    /* perform inbound translation of previous packet, check if destination IP and PORT got translated to the original source IP and PORT */
185    nat_port = udp->trans.sport;
186    net->src = dst_ori;
187    net->dst = nat;
188    udp->trans.sport = sport_ori;
189    udp->trans.dport = nat_port;
190    fail_if(pico_ipv4_nat_inbound(f, &nat_link->address));
191    fail_if(net->dst.addr != src_ori.addr, "destination address not translated correctly");
192    fail_if(udp->trans.dport != short_be(5556), "ports not translated correctly");
193    pico_ipv4_nat_table_cleanup(pico_tick, NULL);
194
195    fail_if(pico_ipv4_nat_disable());
196}
197END_TEST
198
199START_TEST (test_nat_port_forwarding)
200{
201    struct pico_ipv4_link link = {
202        .address = {.addr = long_be(0x0a320001)}
203    };                                                                       /* 10.50.0.1 */
204    struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
205    struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
206    struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
207    struct pico_ip4 src_addr = {
208        .addr = long_be(0x0a280008)
209    };                                                       /* 10.40.0.8 */
210    struct pico_ip4 dst_addr = {
211        .addr = long_be(0x0a320009)
212    };                                                       /* 10.50.0.9 */
213    struct pico_ip4 nat_addr = {
214        .addr = long_be(0x0a320001)
215    };                                                       /* 10.50.0.9 */
216    const char *raw_data = "ello";
217    uint16_t sport_ori = short_be(5555);
218    uint16_t fport_pub = short_be(80);
219    uint16_t fport_priv = short_be(8080);
220
221    net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
222    net->tos = 0;
223    net->len = short_be(32); /* hdr + data (bytes) */
224    net->id = short_be(0x91c0);
225    net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
226    net->ttl = 64;
227    net->proto = 17; /* UDP */
228    net->crc = 0;
229    net->src = dst_addr;
230    net->dst = nat_addr;
231
232    udp->trans.sport = sport_ori;
233    udp->trans.dport = fport_pub;
234    udp->len = 12;
235    udp->crc = 0;
236
237    f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
238    memcpy(f->payload, raw_data, 4);
239
240    printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT PORT FORWARD TEST\n");
241    pico_stack_init();
242    fail_if(pico_ipv4_nat_enable(&link));
243
244    fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_ADD));
245
246    fail_if(pico_ipv4_nat_inbound(f, &nat_link->address));
247    fail_if(net->dst.addr != src_addr.addr, "destination address not translated correctly");
248    fail_if(udp->trans.dport != fport_priv, "destination port not translated correctly");
249
250    fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_DEL));
251    pico_ipv4_nat_table_cleanup(pico_tick, NULL);
252}
253END_TEST
254
255START_TEST (test_ipfilter)
256{
257    struct pico_device *dev = NULL;
258    uint8_t proto = 0, tos = 0;
259    uint16_t sport = 0, dport = 0;
260    int8_t priority = 0;
261    int ret = 0;
262
263    struct pico_ip4 src_addr = {
264        0
265    };
266    struct pico_ip4 saddr_netmask = {
267        0
268    };
269    struct pico_ip4 dst_addr = {
270        0
271    };
272    struct pico_ip4 daddr_netmask = {
273        0
274    };
275
276    enum filter_action action = 1;
277
278    uint32_t filter_id1;
279
280    /* 192.168.1.2:16415 -> 192.168.1.109:1222 [sending a TCP syn] */
281    uint8_t ipv4_buf[] = {
282        0x00, 0x02, 0xf7, 0xf1, 0x79, 0x33, 0xe0, 0xdb, 0x55,
283        0xd4, 0xb6, 0x27, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28,
284        0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf7, 0x0f, 0xc0,
285        0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x6d, 0x40, 0x1f,
286        0x04, 0xc6, 0x00, 0xb1, 0x56, 0x5a, 0x00, 0x00, 0x00,
287        0x00, 0x50, 0x02, 0x20, 0x00, 0x70, 0x32, 0x00, 0x00
288    };
289
290    struct pico_frame *f;
291
292    printf("IP Filter> Adding a new filter...\n");
293    filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action);
294    fail_if(filter_id1 <= 0, "Error adding filter\n");
295    printf("filter_id1 = %d\n", filter_id1);
296
297    printf("IP Filter> Trying to add the same filter...\n");
298    filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action);
299    fail_if(ret > 0, "Error adding filter\n");
300
301    printf("IP Filter> Deleting added filter...\n");
302    ret = pico_ipv4_filter_del(filter_id1);
303    fail_if(ret != 0, "Error deleting the filter\n");
304
305    printf("IP Filter> Trying to delete the same filter\n");
306    ret = pico_ipv4_filter_del(filter_id1);
307    fail_if(ret != -1, "Deleting non existing filter failed\n");
308
309    f = (struct pico_frame *)PICO_ZALLOC(200);
310    f->buffer = PICO_ZALLOC(20);
311    f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
312    f->buffer = ipv4_buf;
313    f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
314    f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
315
316    /* adding exact filter */
317    pico_string_to_ipv4("192.168.1.109", &src_addr.addr);
318    pico_string_to_ipv4("255.255.255.255", &saddr_netmask.addr);
319    sport = 1222u;
320    filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_REJECT);
321    fail_if(filter_id1 <= 0, "Error adding exact filter\n");
322    printf("Filter is added\n");
323    sync();
324    sleep(1);
325
326    ret = ipfilter(f);
327    fail_if(ret != 1, "Frame wasn't filtered\n");
328
329    printf("IP Filter> Deleting added filter...\n");
330    ret = pico_ipv4_filter_del(filter_id1);
331    fail_if(ret != 0, "Error deleting the filter\n");
332
333    printf("IP Filter> Adding masked filter...\n");
334    pico_string_to_ipv4("192.168.1.7", &src_addr.addr);
335    pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr);
336    sport = 1222u;
337
338    filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP);
339    fail_if(filter_id1 <= 0, "Error adding masked filter\n");
340
341    f = (struct pico_frame *)PICO_ZALLOC(200);
342    f->buffer = PICO_ZALLOC(20);
343    f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
344    f->buffer = ipv4_buf;
345    f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
346    f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
347    ret = ipfilter(f);
348    fail_if(ret != 1, "Mask filter failed to filter\n");
349
350    printf("IP Filter> Deleting added filter...\n");
351    ret = pico_ipv4_filter_del(filter_id1);
352    fail_if(ret != 0, "Error deleting the filter\n");
353
354    printf("IP Filter> Adding bad filter..\n");
355    pico_string_to_ipv4("191.1.1.7", &src_addr.addr);
356    pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr);
357    sport = 1991u;
358    filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP);
359    fail_if(filter_id1 <= 0, "Error adding bad filter\n");
360
361    f = (struct pico_frame *)PICO_ZALLOC(200);
362    f->buffer = PICO_ZALLOC(20);
363    f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
364    f->buffer = ipv4_buf;
365    f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
366    f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
367    ret = ipfilter(f);
368    fail_if(ret != 0, "Filter shouldn't have filtered this frame\n");
369
370    printf("IP Filter> Deleting added filter...\n");
371    ret = pico_ipv4_filter_del(filter_id1);
372    fail_if(ret != 0, "Error deleting the filter\n");
373
374}
375END_TEST
376
377#ifdef PICO_SUPPORT_MCAST
378START_TEST (test_igmp_sockopts)
379{
380    int i = 0, j = 0, k = 0, ret = 0;
381    struct pico_socket *s, *s1 = NULL;
382    struct pico_device *dev = NULL;
383    union pico_address *source = NULL;
384    union pico_address inaddr_dst = {
385        0
386    }, inaddr_incorrect = {
387        0
388    }, inaddr_uni = {
389        0
390    }, inaddr_null = {
391        0
392    }, netmask = {
393        0
394    };
395    union pico_address inaddr_link[2] = {0};
396    union pico_address inaddr_mcast[8] = {0};
397    union pico_address inaddr_source[8] = {0};
398    struct pico_ip_mreq _mreq = {0}, mreq[16] = {0};
399    struct pico_ip_mreq_source mreq_source[128] = {0};
400    struct pico_tree_node *index = NULL;
401
402    int ttl = 64;
403    int getttl = 0;
404    int loop = 9;
405    int getloop = 0;
406    union pico_address mcast_def_link = {
407        0
408    };
409
410    pico_stack_init();
411
412    printf("START IGMP SOCKOPTS TEST\n");
413
414    pico_string_to_ipv4("224.7.7.7", &inaddr_dst.ip4.addr);
415    pico_string_to_ipv4("10.40.0.2", &inaddr_uni.ip4.addr);
416    pico_string_to_ipv4("224.8.8.8", &inaddr_incorrect.ip4.addr);
417    pico_string_to_ipv4("0.0.0.0", &inaddr_null.ip4.addr);
418
419    pico_string_to_ipv4("10.40.0.1", &inaddr_link[0].ip4.addr); /* 0 */
420    pico_string_to_ipv4("10.50.0.1", &inaddr_link[1].ip4.addr); /* 1 */
421
422    pico_string_to_ipv4("232.1.1.0", &inaddr_mcast[0].ip4.addr); /* 0 */
423    pico_string_to_ipv4("232.2.2.1", &inaddr_mcast[1].ip4.addr); /* 1 */
424    pico_string_to_ipv4("232.3.3.2", &inaddr_mcast[2].ip4.addr); /* 2 */
425    pico_string_to_ipv4("232.4.4.3", &inaddr_mcast[3].ip4.addr); /* 3 */
426    pico_string_to_ipv4("232.5.5.4", &inaddr_mcast[4].ip4.addr); /* 4 */
427    pico_string_to_ipv4("232.6.6.5", &inaddr_mcast[5].ip4.addr); /* 5 */
428    pico_string_to_ipv4("232.7.7.6", &inaddr_mcast[6].ip4.addr); /* 6 */
429    pico_string_to_ipv4("232.8.8.7", &inaddr_mcast[7].ip4.addr); /* 7 */
430
431    pico_string_to_ipv4("10.40.1.0", &inaddr_source[0].ip4.addr); /* 0 */
432    pico_string_to_ipv4("10.40.1.1", &inaddr_source[1].ip4.addr); /* 1 */
433    pico_string_to_ipv4("10.40.1.2", &inaddr_source[2].ip4.addr); /* 2 */
434    pico_string_to_ipv4("10.40.1.3", &inaddr_source[3].ip4.addr); /* 3 */
435    pico_string_to_ipv4("10.40.1.4", &inaddr_source[4].ip4.addr); /* 4 */
436    pico_string_to_ipv4("10.40.1.5", &inaddr_source[5].ip4.addr); /* 5 */
437    pico_string_to_ipv4("10.40.1.6", &inaddr_source[6].ip4.addr); /* 6 */
438    pico_string_to_ipv4("10.40.1.7", &inaddr_source[7].ip4.addr); /* 7 */
439
440    /* 00 01 02 03 04 05 06 07 | 10 11 12 13 14 15 16 17 */
441    for (i = 0; i < 16; i++) {
442        mreq[i].mcast_link_addr = inaddr_link[i / 8];
443        mreq[i].mcast_group_addr = inaddr_mcast[i % 8];
444    }
445    /* 000 001 002 003 004 005 006 007 | 010 011 012 013 014 015 016 017  */
446    for (i = 0; i < 16; i++) {
447        for (j = 0; j < 8; j++) {
448            /* printf(">>>>> mreq_source[%d]: link[%d] mcast[%d] source[%d]\n", (i*8)+j, i/8, i%8, j); */
449            mreq_source[(i * 8) + j].mcast_link_addr = inaddr_link[i / 8];
450            mreq_source[(i * 8) + j].mcast_group_addr = inaddr_mcast[i % 8];
451            mreq_source[(i * 8) + j].mcast_source_addr = inaddr_source[j];
452        }
453    }
454    dev = pico_null_create("dummy0");
455    netmask.ip4.addr = long_be(0xFFFF0000);
456    ret = pico_ipv4_link_add(dev, inaddr_link[0].ip4, netmask.ip4);
457    fail_if(ret < 0, "link add failed");
458
459    dev = pico_null_create("dummy1");
460    netmask.ip4.addr = long_be(0xFFFF0000);
461    ret = pico_ipv4_link_add(dev, inaddr_link[1].ip4, netmask.ip4);
462    fail_if(ret < 0, "link add failed");
463
464    s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
465    fail_if(s == NULL, "UDP socket open failed");
466    s1 = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
467    fail_if(s1 == NULL, "UDP socket open failed");
468
469    /* argument validation tests */
470    printf("IGMP SETOPTION ARGUMENT VALIDATION TEST\n");
471    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
472    fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
473    ret = pico_socket_getoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
474    fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
475    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_TTL, &ttl);
476    fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
477
478    ret = pico_socket_getoption(s, PICO_IP_MULTICAST_TTL, &getttl);
479    fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
480    fail_if(getttl != ttl, "setoption ttl != getoption ttl\n");
481
482    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
483    fail_if(ret == 0, "PICO_IP_MULTICAST_LOOP succeeded with invalid (not 0 or 1) loop value\n");
484    loop = 0;
485    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
486    fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed disabling\n");
487    ret = pico_socket_getoption(s, PICO_IP_MULTICAST_LOOP, &getloop);
488    fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed getting value\n");
489    fail_if(getloop != loop, "setoption loop != getoption loop\n");
490    _mreq.mcast_group_addr = inaddr_dst;
491    _mreq.mcast_link_addr = inaddr_link[0];
492    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
493    fail_if(ret < 0, "supported PICO_IP_ADD_MEMBERSHIP failed\n");
494    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
495    fail_if(ret < 0, "supported PICO_IP_DROP_MEMBERSHIP failed\n");
496    _mreq.mcast_group_addr = inaddr_dst;
497    _mreq.mcast_link_addr = inaddr_null;
498    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
499    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed with valid NULL (use default) link address\n");
500    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
501    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed with valid NULL (use default) link address\n");
502    _mreq.mcast_group_addr = inaddr_uni;
503    _mreq.mcast_link_addr = inaddr_link[0];
504    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
505    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (unicast) group address\n");
506    _mreq.mcast_group_addr = inaddr_null;
507    _mreq.mcast_link_addr = inaddr_link[0];
508    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
509    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (NULL) group address\n");
510    _mreq.mcast_group_addr = inaddr_dst;
511    _mreq.mcast_link_addr = inaddr_uni;
512    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
513    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid link address\n");
514    _mreq.mcast_group_addr = inaddr_incorrect;
515    _mreq.mcast_link_addr = inaddr_link[0];
516    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
517    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (not added) group address\n");
518    _mreq.mcast_group_addr = inaddr_uni;
519    _mreq.mcast_link_addr = inaddr_link[0];
520    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
521    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) group address\n");
522    _mreq.mcast_group_addr = inaddr_null;
523    _mreq.mcast_link_addr = inaddr_link[0];
524    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
525    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (NULL) group address\n");
526    _mreq.mcast_group_addr = inaddr_dst;
527    _mreq.mcast_link_addr = inaddr_uni;
528    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
529    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) link address\n");
530
531    /* flow validation tests */
532    printf("IGMP SETOPTION FLOW VALIDATION TEST\n");
533    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
534    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
535    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
536    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
537    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
538    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
539    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
540    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed with err %s\n", strerror(pico_err));
541    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
542    fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
543    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
544    fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
545    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
546    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
547
548    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
549    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded\n");
550    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
551    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
552    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
553    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
554    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
555    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
556    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
557    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
558
559    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
560    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
561    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
562    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
563    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
564    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
565    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
566    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
567    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
568    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
569    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
570    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
571
572    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
573    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
574    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
575    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
576    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
577    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
578    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
579    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
580    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
581    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
582    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
583    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
584
585    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
586    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
587    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
588    fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
589    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
590    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
591    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
592    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
593    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
594    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
595    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
596    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
597    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
598    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
599
600    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
601    fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
602    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
603    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
604    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
605    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
606    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
607    fail_if(ret == 0, "PICO_IP_UNBLOCK_MEMBERSHIP succeeded\n");
608    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
609    fail_if(ret == 0, "PICO_IP_BLOCK_MEMBERSHIP succeeded\n");
610    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
611    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
612    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
613    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
614
615    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
616    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
617    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
618    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
619    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
620    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
621    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
622    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
623    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
624    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
625
626    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
627    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
628    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
629    fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
630    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
631    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
632    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
633    fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
634    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
635    fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
636    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
637    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
638
639    /* stress tests */
640    printf("IGMP SETOPTION STRESS TEST\n");
641    for (k = 0; k < 2; k++) {
642        /* ADD for even combinations of group and link, ADD_SOURCE for uneven */
643        for (i = 0; i < 16; i++) {
644            if (i % 2) {
645                ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[i]);
646                fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
647                for (j = 0; j < 8; j++) {
648                    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[(i * 8) + j]);
649                    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
650                }
651            } else {
652                for (j = 0; j < 8; j++) {
653                    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
654                    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
655                }
656            }
657        }
658        /* UNBLOCK and DROP for even combinations, DROP_SOURCE for uneven */
659        for (i = 0; i < 16; i++) {
660            if (i % 2) {
661                for (j = 0; j < 8; j++) {
662                    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[(i * 8) + j]);
663                    fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
664                }
665                ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[i]);
666                fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
667            } else {
668                for (j = 0; j < 8; j++) {
669                    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
670                    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
671                }
672            }
673        }
674        /* everything should be cleanup up, next iteration will fail if not */
675    }
676    /* filter validation tests */
677    printf("IGMP SETOPTION FILTER VALIDATION TEST\n");
678    /* INCLUDE + INCLUDE expected filter: source of 0 and 1*/
679    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
680    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
681    ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
682    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
683    ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
684    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
685    i = 0;
686    pico_tree_foreach(index, &MCASTFilter)
687    {
688        if (++i > 2)
689            fail("MCASTFilter (INCLUDE + INCLUDE) too many elements\n");
690
691        source = index->keyValue;
692        if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */
693        }
694        else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */
695        }
696        else {
697            fail("MCASTFilter (INCLUDE + INCLUDE) incorrect\n");
698        }
699    }
700    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
701    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
702    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
703    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
704
705    /* INCLUDE + EXCLUDE expected filter: source of 2 */
706    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
707    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
708    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
709    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
710    ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
711    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
712    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
713    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
714    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[2]);
715    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
716    i = 0;
717    pico_tree_foreach(index, &MCASTFilter)
718    {
719        if (++i > 1)
720            fail("MCASTFilter (INCLUDE + EXCLUDE) too many elements\n");
721
722        source = index->keyValue;
723        if (source->ip4.addr == mreq_source[2].mcast_source_addr.ip4.addr) { /* OK */
724        }
725        else {
726            fail("MCASTFilter (INCLUDE + EXCLUDE) incorrect\n");
727        }
728    }
729    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
730    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
731    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
732    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
733
734    /* EXCLUDE + INCLUDE expected filter: source of 0 and 1 */
735    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
736    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
737    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
738    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
739    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
740    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
741    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
742    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
743    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
744    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
745    ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[3]);
746    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
747    ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[4]);
748    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
749    i = 0;
750    pico_tree_foreach(index, &MCASTFilter)
751    {
752        if (++i > 2)
753            fail("MCASTFilter (EXCLUDE + INCLUDE) too many elements\n");
754
755        source = index->keyValue;
756        if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */
757        }
758        else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */
759        }
760        else {
761            fail("MCASTFilter (EXCLUDE + INCLUDE) incorrect\n");
762        }
763    }
764    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
765    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
766    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
767    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
768
769    /* EXCLUDE + EXCLUDE expected filter: source of 3 and 4 */
770    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
771    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
772    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
773    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
774    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
775    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
776    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
777    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
778    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
779    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
780    ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
781    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
782    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
783    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
784    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
785    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
786    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[5]);
787    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
788    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[6]);
789    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
790    i = 0;
791    pico_tree_foreach(index, &MCASTFilter)
792    {
793        if (++i > 2)
794            fail("MCASTFilter (EXCLUDE + EXCLUDE) too many elements\n");
795
796        source = index->keyValue;
797        if (source->ip4.addr == mreq_source[3].mcast_source_addr.ip4.addr) { /* OK */
798        }
799        else if (source->ip4.addr == mreq_source[4].mcast_source_addr.ip4.addr) { /* OK */
800        }
801        else {
802            fail("MCASTFilter (EXCLUDE + EXCLUDE) incorrect\n");
803        }
804    }
805    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
806    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
807    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
808    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
809
810
811    ret = pico_socket_close(s);
812    fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
813    ret = pico_socket_close(s1);
814    fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
815}
816END_TEST
817#endif
818
819START_TEST (test_slaacv4)
820{
821    uint32_t tmp;
822    struct pico_device *dev;
823    struct mock_device *mock;
824    char ip_addr[20];
825    uint8_t macaddr1[6] = {
826        0xc3, 0, 0, 0xa, 0xc, 0xf
827    };
828
829
830
831    /* verify min boundary*/
832    tmp = SLAACV4_CREATE_IPV4(0);
833    pico_ipv4_to_string(ip_addr, tmp);
834    printf("IP address generated by slaac: %s\n", ip_addr);
835
836    fail_if(long_be(tmp) < (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE));
837
838    /* verify max boundary*/
839    tmp = SLAACV4_CREATE_IPV4(0x00FD);
840    fail_if(long_be(tmp) > (long_be(SLAACV4_NETWORK) | 0x0000FEFF));
841
842    /* verify case where dev->eth is NULL */
843    dev = pico_null_create("dummy");
844    tmp = pico_slaacv4_getip(dev, 0);
845    fail_if(long_be(tmp) != (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE));
846    /* verify nominal case; two runs of slaacv4_get_ip need to return same value */
847    mock = pico_mock_create(macaddr1);
848    tmp = pico_slaacv4_getip(mock->dev, 0);
849    fail_if(tmp != pico_slaacv4_getip(mock->dev, 0));
850
851}
852END_TEST
853