1
2#ifdef PICO_SUPPORT_IPV6
3START_TEST (test_ipv6)
4{
5    char ipstr[40] = {
6        0
7    };
8    char ipstr0[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
9    char ipstr0_t[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
10    char ipstr1[] = "2001:db8:130f:0000:0000:09c0:876a:130b";
11    char ipstr1_t[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
12    char ipstr2[] = "2001:b8:130f:0000:0000:09c0:876a:130b";
13    char ipstr2_t[] = "2001:00b8:130f:0000:0000:09c0:876a:130b";
14    char ipstr3[] = "2001:8:130f:0000:0000:09c0:876a:130b";
15    char ipstr3_t[] = "2001:0008:130f:0000:0000:09c0:876a:130b";
16    char ipstr4[] = "2001:8:130f:0:0:09c0:876a:130b";
17    char ipstr4_t[] = "2001:0008:130f:0000:0000:09c0:876a:130b";
18    char ipstr5[] = "2001::8:130f:09c0:876a:130b";
19    char ipstr5_t[] = "2001:0000:0000:0008:130f:09c0:876a:130b";
20    char ipstr6[] = "2001::8:09c0:876a:130b";
21    char ipstr6_t[] = "2001:0000:0000:0000:0008:09c0:876a:130b";
22    char ipstr7[] = "2001::8:876a:130b";
23    char ipstr7_t[] = "2001:0000:0000:0000:0000:0008:876a:130b";
24    char ipstr8[] = "2001::876a:130b";
25    char ipstr8_t[] = "2001:0000:0000:0000:0000:0000:876a:130b";
26    char ipstr9[] = "ff01::1";
27    char ipstr9_t[] = "ff01:0000:0000:0000:0000:0000:0000:0001";
28    char ipstr10[] = "::1";
29    char ipstr10_t[] = "0000:0000:0000:0000:0000:0000:0000:0001";
30    char ipstr11[] = "fe80::";
31    char ipstr11_t[] = "fe80:0000:0000:0000:0000:0000:0000:0000";
32    char ipstr12[] = "::";
33    char ipstr12_t[] = "0000:0000:0000:0000:0000:0000:0000:0000";
34    char ipstr13[] = "2001:8:130f::09c0::130b"; /* invalid */
35    char ipstr14[] = "2001:8:xxxx::09c0:130b"; /* invalid */
36    char ipstr15[] = "2001:8:$$$$::09c0:130b"; /* invalid */
37    char ipstr16[] = "2001:8:!@#$::%^&*:()0b"; /* invalid */
38    char ipstr17[] = "2001:1"; /* invalid */
39    char ipstr18[] = "20010db8:130f:0000:0000:09c0:876a:130b"; /* invalid */
40    char ipstr19[] = "20010db8130f0000000009c0876a130b"; /* invalid */
41    char ipstr20[] = "2001;0db8;130f;0000;0000;09c0;876a;130b"; /* invalid */
42    uint8_t iphex0[PICO_SIZE_IP6] = {
43        0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
44    };
45    uint8_t iphex1[PICO_SIZE_IP6] = {
46        0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
47    };
48    uint8_t iphex2[PICO_SIZE_IP6] = {
49        0x20, 0x01, 0x00, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
50    };
51    uint8_t iphex3[PICO_SIZE_IP6] = {
52        0x20, 0x01, 0x00, 0x08, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
53    };
54    uint8_t iphex4[PICO_SIZE_IP6] = {
55        0x20, 0x01, 0x00, 0x08, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
56    };
57    uint8_t iphex5[PICO_SIZE_IP6] = {
58        0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x13, 0x0f, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
59    };
60    uint8_t iphex6[PICO_SIZE_IP6] = {
61        0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
62    };
63    uint8_t iphex7[PICO_SIZE_IP6] = {
64        0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x87, 0x6a, 0x13, 0x0b
65    };
66    uint8_t iphex8[PICO_SIZE_IP6] = {
67        0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x6a, 0x13, 0x0b
68    };
69    uint8_t iphex9[PICO_SIZE_IP6] = {
70        0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
71    };
72    uint8_t iphex10[PICO_SIZE_IP6] = {
73        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
74    };
75    uint8_t iphex11[PICO_SIZE_IP6] = {
76        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
77    };
78    uint8_t iphex12[PICO_SIZE_IP6] = {
79        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
80    };
81    struct pico_ip6 iphex_a = {{ 0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }};
82    struct pico_ip6 iphex_r = {{ 0x40, 0x02, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }};
83    struct pico_ip6 iphex_gw = {{ 0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f }};
84    struct pico_ip6 nm64 = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
85    struct pico_ip6 nm128 = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
86    struct pico_ip6 ipaddr = {{0}};
87
88    struct pico_ip6 _gw, r[IP_TST_SIZ], a[IP_TST_SIZ], gw[IP_TST_SIZ], *source[IP_TST_SIZ];
89    struct pico_device *dev[IP_TST_SIZ];
90    struct pico_ipv6_link *l[IP_TST_SIZ];
91    struct pico_ipv6_link *_link = NULL;
92    struct pico_ipv6_route *_route = NULL;
93    char devname[8];
94    int ret = 0;
95    int i = 0;
96
97    pico_stack_init();
98
99    /* pico_string_to_ipv6 and pico_ipv6_to_string */
100    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr0);
101    pico_string_to_ipv6(ipstr0, ipaddr.addr);
102    fail_if(memcmp(ipaddr.addr, iphex0, PICO_SIZE_IP6), "Error string to ipv6");
103    pico_ipv6_to_string(ipstr, ipaddr.addr);
104    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
105    fail_if(strncmp(ipstr, ipstr0_t, 40) != 0, "Error ipv6 to string");
106
107    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr1);
108    pico_string_to_ipv6(ipstr1, ipaddr.addr);
109    fail_if(memcmp(ipaddr.addr, iphex1, PICO_SIZE_IP6), "Error string to ipv6");
110    pico_ipv6_to_string(ipstr, ipaddr.addr);
111    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
112    fail_if(strncmp(ipstr, ipstr1_t, 40) != 0, "Error ipv6 to string");
113
114    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr2);
115    pico_string_to_ipv6(ipstr2, ipaddr.addr);
116    fail_if(memcmp(ipaddr.addr, iphex2, PICO_SIZE_IP6), "Error string to ipv6");
117    pico_ipv6_to_string(ipstr, ipaddr.addr);
118    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
119    fail_if(strncmp(ipstr, ipstr2_t, 40) != 0, "Error ipv6 to string");
120
121    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr3);
122    pico_string_to_ipv6(ipstr3, ipaddr.addr);
123    fail_if(memcmp(ipaddr.addr, iphex3, PICO_SIZE_IP6), "Error string to ipv6");
124    pico_ipv6_to_string(ipstr, ipaddr.addr);
125    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
126    fail_if(strncmp(ipstr, ipstr3_t, 40) != 0, "Error ipv6 to string");
127
128    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr4);
129    pico_string_to_ipv6(ipstr4, ipaddr.addr);
130    fail_if(memcmp(ipaddr.addr, iphex4, PICO_SIZE_IP6), "Error string to ipv6");
131    pico_ipv6_to_string(ipstr, ipaddr.addr);
132    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
133    fail_if(strncmp(ipstr, ipstr4_t, 40) != 0, "Error ipv6 to string");
134
135    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr5);
136    pico_string_to_ipv6(ipstr5, ipaddr.addr);
137    fail_if(memcmp(ipaddr.addr, iphex5, PICO_SIZE_IP6), "Error string to ipv6");
138    pico_ipv6_to_string(ipstr, ipaddr.addr);
139    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
140    fail_if(strncmp(ipstr, ipstr5_t, 40) != 0, "Error ipv6 to string");
141
142    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr6);
143    pico_string_to_ipv6(ipstr6, ipaddr.addr);
144    fail_if(memcmp(ipaddr.addr, iphex6, PICO_SIZE_IP6), "Error string to ipv6");
145    pico_ipv6_to_string(ipstr, ipaddr.addr);
146    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
147    fail_if(strncmp(ipstr, ipstr6_t, 40) != 0, "Error ipv6 to string");
148
149    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr7);
150    pico_string_to_ipv6(ipstr7, ipaddr.addr);
151    fail_if(memcmp(ipaddr.addr, iphex7, PICO_SIZE_IP6), "Error string to ipv6");
152    pico_ipv6_to_string(ipstr, ipaddr.addr);
153    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
154    fail_if(strncmp(ipstr, ipstr7_t, 40) != 0, "Error ipv6 to string");
155
156    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr8);
157    pico_string_to_ipv6(ipstr8, ipaddr.addr);
158    fail_if(memcmp(ipaddr.addr, iphex8, PICO_SIZE_IP6), "Error string to ipv6");
159    pico_ipv6_to_string(ipstr, ipaddr.addr);
160    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
161    fail_if(strncmp(ipstr, ipstr8_t, 40) != 0, "Error ipv6 to string");
162
163    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr9);
164    pico_string_to_ipv6(ipstr9, ipaddr.addr);
165    fail_if(memcmp(ipaddr.addr, iphex9, PICO_SIZE_IP6), "Error string to ipv6");
166    pico_ipv6_to_string(ipstr, ipaddr.addr);
167    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
168    fail_if(strncmp(ipstr, ipstr9_t, 40) != 0, "Error ipv6 to string");
169
170    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr10);
171    pico_string_to_ipv6(ipstr10, ipaddr.addr);
172    fail_if(memcmp(ipaddr.addr, iphex10, PICO_SIZE_IP6), "Error string to ipv6");
173    pico_ipv6_to_string(ipstr, ipaddr.addr);
174    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
175    fail_if(strncmp(ipstr, ipstr10_t, 40) != 0, "Error ipv6 to string");
176
177    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr11);
178    pico_string_to_ipv6(ipstr11, ipaddr.addr);
179    fail_if(memcmp(ipaddr.addr, iphex11, PICO_SIZE_IP6), "Error string to ipv6");
180    pico_ipv6_to_string(ipstr, ipaddr.addr);
181    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
182    fail_if(strncmp(ipstr, ipstr11_t, 40) != 0, "Error ipv6 to string");
183
184    printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr12);
185    pico_string_to_ipv6(ipstr12, ipaddr.addr);
186    fail_if(memcmp(ipaddr.addr, iphex12, PICO_SIZE_IP6), "Error string to ipv6");
187    pico_ipv6_to_string(ipstr, ipaddr.addr);
188    printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
189    fail_if(strncmp(ipstr, ipstr12_t, 40) != 0, "Error ipv6 to string");
190
191    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr13);
192    ret = pico_string_to_ipv6(ipstr13, ipaddr.addr);
193    fail_if(ret == 0, "Error string to ipv6");
194
195    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr14);
196    ret = pico_string_to_ipv6(ipstr14, ipaddr.addr);
197    fail_if(ret == 0, "Error string to ipv6");
198
199    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr15);
200    ret = pico_string_to_ipv6(ipstr15, ipaddr.addr);
201    fail_if(ret == 0, "Error string to ipv6");
202
203    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr16);
204    ret = pico_string_to_ipv6(ipstr16, ipaddr.addr);
205    fail_if(ret == 0, "Error string to ipv6");
206
207    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr17);
208    ret = pico_string_to_ipv6(ipstr17, ipaddr.addr);
209    fail_if(ret == 0, "Error string to ipv6");
210
211    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr18);
212    ret = pico_string_to_ipv6(ipstr18, ipaddr.addr);
213    fail_if(ret == 0, "Error string to ipv6");
214
215    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr19);
216    ret = pico_string_to_ipv6(ipstr19, ipaddr.addr);
217    fail_if(ret == 0, "Error string to ipv6");
218
219    printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr20);
220    ret = pico_string_to_ipv6(ipstr20, ipaddr.addr);
221    fail_if(ret == 0, "Error string to ipv6");
222
223    /*link_add*/
224    for (i = 0; i < 10; ++i) {
225        snprintf(devname, 8, "nul%d", i);
226        dev[i] = pico_null_create(devname);
227        a[i] = iphex_a;
228        a[i].addr[4] = (uint8_t)(a[i].addr[4] + i);
229        fail_if(pico_ipv6_link_add(dev[i], a[i], nm64) == NULL, "Error adding link");
230    }
231    /*link_find + link_get + route_add*/
232    for (i = 0; i < 10; ++i) {
233        gw[i] = iphex_gw;
234        gw[i].addr[4] = (uint8_t)(gw[i].addr[4] + i);
235        fail_unless(pico_ipv6_link_find(&a[i]) == dev[i], "Error finding link");
236        l[i] = pico_ipv6_link_get(&a[i]);
237        fail_if(l[i] == NULL, "Error getting link");
238        r[i] = iphex_r;
239        r[i].addr[4] = (uint8_t)(r[i].addr[4] + i);
240        fail_if(pico_ipv6_route_add(r[i], nm128, a[i], 1, l[i]) != 0, "Error adding route");
241    }
242    /*get_gateway*/
243    for (i = 0; i < 10; i++) {
244        _gw = pico_ipv6_route_get_gateway(&r[i]);
245        fail_if(memcmp(_gw.addr, a[i].addr, PICO_SIZE_IP6) != 0, "Error get gateway: returned wrong route");
246        source[i] = pico_ipv6_source_find(&r[i]);
247        fail_if(memcmp(source[i]->addr, a[i].addr, PICO_SIZE_IP6) != 0, "Error find source: returned wrong route");
248    }
249    /*route_del + link_del*/
250    for (i = 0; i < 10; i++) {
251        fail_if(pico_ipv6_route_del(r[i], nm128, a[i], 1, l[i]) != 0, "Error deleting route");
252        fail_if(pico_ipv6_link_del(dev[i], a[i]) != 0, "Error deleting link");
253    }
254    /* add 2 links to dev[0] */
255    _link = pico_ipv6_link_add(dev[0], a[0], nm64);
256    fail_if (!_link, "Error adding link");
257    _link = pico_ipv6_link_add(dev[0], a[1], nm64);
258    fail_if (!_link, "Error adding link");
259    /* add 2 routes to each of the links */
260    ret = pico_ipv6_route_add(r[0], nm128, a[0], 1, l[0]);
261    fail_if(ret != 0, "Error adding route");
262    ret = pico_ipv6_route_add(r[1], nm128, a[0], 1, l[0]);
263    fail_if(ret != 0, "Error adding route");
264    ret = pico_ipv6_route_add(r[2], nm128, a[1], 1, l[1]);
265    fail_if(ret != 0, "Error adding route");
266    ret = pico_ipv6_route_add(r[3], nm128, a[1], 1, l[1]);
267    fail_if(ret != 0, "Error adding route");
268
269    /* add 2 links to dev[1] */
270    _link = pico_ipv6_link_add(dev[1], a[8], nm64);
271    fail_if (!_link, "Error adding link");
272    _link = pico_ipv6_link_add(dev[1], a[9], nm64);
273    fail_if (!_link, "Error adding link");
274    /* add 2 routes to each of the links */
275    ret = pico_ipv6_route_add(r[6], nm128, a[8], 1, l[8]);
276    fail_if(ret != 0, "Error adding route");
277    ret = pico_ipv6_route_add(r[7], nm128, a[8], 1, l[8]);
278    fail_if(ret != 0, "Error adding route");
279    ret = pico_ipv6_route_add(r[8], nm128, a[9], 1, l[9]);
280    fail_if(ret != 0, "Error adding route");
281    ret = pico_ipv6_route_add(r[9], nm128, a[9], 1, l[9]);
282    fail_if(ret != 0, "Error adding route");
283
284    /* destroy device, should clean up all links and routes */
285    pico_device_destroy(dev[0]);
286    _link = pico_ipv6_link_get(&a[0]);
287    fail_if(_link != NULL, "Error destroying device");
288    _link = pico_ipv6_link_get(&a[1]);
289    fail_if(_link != NULL, "Error destroying device");
290    _link = pico_ipv6_link_get(&a[8]);
291    fail_if(_link == NULL, "Error destroying device");
292    _link = pico_ipv6_link_get(&a[9]);
293    fail_if(_link == NULL, "Error destroying device");
294
295    _route = pico_ipv6_route_find(&r[0]);
296    fail_if(_route != NULL, "Error destroying device");
297    _route = pico_ipv6_route_find(&r[1]);
298    fail_if(_route != NULL, "Error destroying device");
299    _route = pico_ipv6_route_find(&r[2]);
300    fail_if(_route != NULL, "Error destroying device");
301    _route = pico_ipv6_route_find(&r[3]);
302    fail_if(_route != NULL, "Error destroying device");
303
304    _route = pico_ipv6_route_find(&r[6]);
305    fail_if(_route == NULL, "Error destroying device");
306    _route = pico_ipv6_route_find(&r[7]);
307    fail_if(_route == NULL, "Error destroying device");
308    _route = pico_ipv6_route_find(&r[8]);
309    fail_if(_route == NULL, "Error destroying device");
310    _route = pico_ipv6_route_find(&r[9]);
311    fail_if(_route == NULL, "Error destroying device");
312}
313END_TEST
314
315#ifdef PICO_SUPPORT_MCAST
316START_TEST (test_mld_sockopts)
317{
318    int i = 0, j = 0, k = 0, ret = 0;
319    struct pico_socket *s, *s1 = NULL;
320    struct pico_device *dev = NULL;
321    union pico_address *source = NULL;
322    union pico_address inaddr_dst = {
323        0
324    }, inaddr_incorrect = {
325        0
326    }, inaddr_uni = {
327        0
328    }, inaddr_null = {
329        0
330    };
331    struct pico_ip6 netmask = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
332
333    union pico_address inaddr_link[2] = {0};
334    union pico_address inaddr_mcast[8] = {0};
335    union pico_address inaddr_source[8] = {0};
336    struct pico_ip_mreq _mreq = {0}, mreq[16] = {0};
337    struct pico_ip_mreq_source mreq_source[128] = {0};
338    struct pico_tree_node *index = NULL;
339    struct pico_ipv6_link *ret_link = NULL;
340    int ttl = 64;
341    int getttl = 0;
342    int loop = 9;
343    int getloop = 0;
344    struct pico_ip6 mcast_def_link = {
345        0
346    };
347
348    pico_stack_init();
349
350    printf("START MLD SOCKOPTS TEST\n");
351
352    pico_string_to_ipv6("ff00:0:0:0:0:0:e007:707", inaddr_dst.ip6.addr);
353    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:2", inaddr_uni.ip6.addr);
354    pico_string_to_ipv6("ff00:0:0:0:0:0:e008:808", inaddr_incorrect.ip6.addr);
355    pico_string_to_ipv6("::", inaddr_null.ip6.addr);
356
357    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:0001", inaddr_link[0].ip6.addr); /* 0 */
358    pico_string_to_ipv6("fe80:0:0:0:0:0:a32:0001", inaddr_link[1].ip6.addr); /* 1 */
359
360    pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", inaddr_mcast[0].ip6.addr); /* 0 */
361    pico_string_to_ipv6("ff00:0:0:0:0:0:e802:201", inaddr_mcast[1].ip6.addr); /* 1 */
362    pico_string_to_ipv6("ff00:0:0:0:0:0:e803:302", inaddr_mcast[2].ip6.addr); /* 2 */
363    pico_string_to_ipv6("ff00:0:0:0:0:0:e803:403", inaddr_mcast[3].ip6.addr); /* 3 */
364    pico_string_to_ipv6("ff00:0:0:0:0:0:e803:504", inaddr_mcast[4].ip6.addr); /* 4 */
365    pico_string_to_ipv6("ff00:0:0:0:0:0:e803:605", inaddr_mcast[5].ip6.addr); /* 5 */
366    pico_string_to_ipv6("ff00:0:0:0:0:0:e803:706", inaddr_mcast[6].ip6.addr); /* 6 */
367    pico_string_to_ipv6("ff00:0:0:0:0:0:e803:807", inaddr_mcast[7].ip6.addr); /* 7 */
368
369    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:100", inaddr_source[0].ip6.addr); /* 0 */
370    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:101", inaddr_source[1].ip6.addr); /* 1 */
371    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:102", inaddr_source[2].ip6.addr); /* 2 */
372    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:103", inaddr_source[3].ip6.addr); /* 3 */
373    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:104", inaddr_source[4].ip6.addr); /* 4 */
374    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:105", inaddr_source[5].ip6.addr); /* 5 */
375    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:106", inaddr_source[6].ip6.addr); /* 6 */
376    pico_string_to_ipv6("fe80:0:0:0:0:0:a28:107", inaddr_source[7].ip6.addr); /* 7 */
377
378    /* 00 01 02 03 04 05 06 07 | 10 11 12 13 14 15 16 17 */
379    for (i = 0; i < 16; i++) {
380        mreq[i].mcast_link_addr = inaddr_link[i / 8];
381        mreq[i].mcast_group_addr = inaddr_mcast[i % 8];
382    }
383    /* 000 001 002 003 004 005 006 007 | 010 011 012 013 014 015 016 017  */
384    for (i = 0; i < 16; i++) {
385        for (j = 0; j < 8; j++) {
386            /* printf(">>>>> mreq_source[%d]: link[%d] mcast[%d] source[%d]\n", (i*8)+j, i/8, i%8, j); */
387            mreq_source[(i * 8) + j].mcast_link_addr = inaddr_link[i / 8];
388            mreq_source[(i * 8) + j].mcast_group_addr = inaddr_mcast[i % 8];
389            mreq_source[(i * 8) + j].mcast_source_addr = inaddr_source[j];
390        }
391    }
392    dev = pico_null_create("dummy0");
393    ret_link = pico_ipv6_link_add(dev, inaddr_link[0].ip6, netmask);
394    fail_if(ret_link == NULL, "link add failed");
395    dev = pico_null_create("dummy1");
396    ret_link = pico_ipv6_link_add(dev, inaddr_link[1].ip6, netmask);
397    fail_if(ret_link == NULL, "link add failed");
398
399
400    s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, NULL);
401    fail_if(s == NULL, "UDP socket open failed");
402    s1 = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, NULL);
403    fail_if(s1 == NULL, "UDP socket open failed");
404
405
406    /* argument validation tests */
407    printf("MLD SETOPTION ARGUMENT VALIDATION TEST\n");
408    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
409    fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
410    ret = pico_socket_getoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
411    fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
412    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_TTL, &ttl);
413    fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
414
415    ret = pico_socket_getoption(s, PICO_IP_MULTICAST_TTL, &getttl);
416    fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
417    fail_if(getttl != ttl, "setoption ttl != getoption ttl\n");
418
419    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
420    fail_if(ret == 0, "PICO_IP_MULTICAST_LOOP succeeded with invalid (not 0 or 1) loop value\n");
421    loop = 0;
422    ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
423    fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed disabling\n");
424    ret = pico_socket_getoption(s, PICO_IP_MULTICAST_LOOP, &getloop);
425    fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed getting value\n");
426    fail_if(getloop != loop, "setoption loop != getoption loop\n");
427    memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
428    memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
429    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
430    fail_if(ret < 0, "supported PICO_IP_ADD_MEMBERSHIP failed\n");
431    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
432    fail_if(ret < 0, "supported PICO_IP_DROP_MEMBERSHIP failed\n");
433    memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
434    memcpy(&_mreq.mcast_link_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
435    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
436    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed with valid NULL (use default) link address\n");
437    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
438    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed with valid NULL (use default) link address\n");
439    memcpy(&_mreq.mcast_group_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
440    memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
441    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
442    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (unicast) group address\n");
443    memcpy(&_mreq.mcast_group_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
444    memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
445    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
446    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (NULL) group address\n");
447    memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
448    memcpy(&_mreq.mcast_link_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
449    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
450    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid link address\n");
451    memcpy(&_mreq.mcast_group_addr, &inaddr_incorrect.ip6, sizeof(struct pico_ip6));
452    memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
453    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
454    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (not added) group address\n");
455    memcpy(&_mreq.mcast_group_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
456    memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
457    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
458    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) group address\n");
459    memcpy(&_mreq.mcast_group_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
460    memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
461    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
462    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (NULL) group address\n");
463    memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
464    memcpy(&_mreq.mcast_link_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
465    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
466    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) link address\n");
467    /* flow validation tests */
468    printf("MLD SETOPTION FLOW VALIDATION TEST\n");
469    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
470    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
471    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
472    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
473    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
474    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
475    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
476    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed with err %s\n", strerror(pico_err));
477    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
478    fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
479    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
480    fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
481    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
482    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
483
484    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
485    fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded\n");
486    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
487    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
488    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
489    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
490    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
491    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
492    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
493    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
494
495    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
496    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
497    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
498    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
499    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
500    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
501    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
502    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
503    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
504    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
505    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
506    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
507
508    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
509    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
510    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
511    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
512    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
513    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
514    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
515    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
516    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
517    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
518    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
519    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
520
521    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
522    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
523    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
524    fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
525    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
526    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
527    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
528    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
529    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
530    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
531    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
532    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
533    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
534    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
535
536    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
537    fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
538    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
539    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
540    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
541    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
542    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
543    fail_if(ret == 0, "PICO_IP_UNBLOCK_MEMBERSHIP succeeded\n");
544    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
545    fail_if(ret == 0, "PICO_IP_BLOCK_MEMBERSHIP succeeded\n");
546    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
547    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
548    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
549    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
550
551    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
552    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
553    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
554    fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
555    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
556    fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
557    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
558    fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
559    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
560    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
561
562    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
563    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
564    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
565    fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
566    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
567    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
568    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
569    fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
570    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
571    fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
572    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
573    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
574    /* stress tests */
575
576    printf("MLD SETOPTION STRESS TEST\n");
577    for (k = 0; k < 2; k++) {
578        /* ADD for even combinations of group and link, ADD_SOURCE for uneven */
579        for (i = 0; i < 16; i++) {
580            if (i % 2) {
581                ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[i]);
582                fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
583                for (j = 0; j < 8; j++) {
584                    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[(i * 8) + j]);
585                    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
586                }
587            } else {
588                for (j = 0; j < 8; j++) {
589                    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
590                    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
591                }
592            }
593        }
594        /* UNBLOCK and DROP for even combinations, DROP_SOURCE for uneven */
595        for (i = 0; i < 16; i++) {
596            if (i % 2) {
597                for (j = 0; j < 8; j++) {
598                    ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[(i * 8) + j]);
599                    fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
600                }
601                ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[i]);
602                fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
603            } else {
604                for (j = 0; j < 8; j++) {
605                    ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
606                    fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
607                }
608            }
609        }
610        /* everything should be cleanup up, next iteration will fail if not */
611    }
612    /* filter validation tests */
613    printf("MLD SETOPTION FILTER VALIDATION TEST\n");
614    /* INCLUDE + INCLUDE expected filter: source of 0 and 1*/
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(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
618    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
619    ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
620    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
621    i = 0;
622
623    pico_tree_foreach(index, &MCASTFilter)
624    {
625        if (++i > 2)
626            fail("MCASTFilter (INCLUDE + INCLUDE) too many elements\n");
627
628        source = index->keyValue;
629        if (memcmp(&source->ip6, &mreq_source[0].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
630        }
631        else if (memcmp(&source->ip6, &mreq_source[1].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
632        }
633        else {
634            fail("MCASTFilter (INCLUDE + INCLUDE) incorrect\n");
635        }
636    }
637
638
639    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
640    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
641    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
642    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
643
644    /* INCLUDE + EXCLUDE expected filter: source of 2 */
645    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
646    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
647    ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
648    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
649    ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
650    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
651    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
652    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
653    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[2]);
654    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
655    i = 0;
656    pico_tree_foreach(index, &MCASTFilter)
657    {
658        if (++i > 1)
659            fail("MCASTFilter (INCLUDE + EXCLUDE) too many elements\n");
660
661        source = index->keyValue;
662        if (memcmp(&source->ip6, &mreq_source[2].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
663        }
664        else {
665            fail("MCASTFilter (INCLUDE + EXCLUDE) incorrect\n");
666        }
667    }
668    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
669    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
670    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
671    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
672
673    /* EXCLUDE + INCLUDE expected filter: source of 0 and 1 */
674    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
675    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
676    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
677    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
678    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
679    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
680    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
681    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
682    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
683    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
684    ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[3]);
685    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
686    ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[4]);
687    fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
688    i = 0;
689
690    pico_tree_foreach(index, &MCASTFilter)
691    {
692        if (++i > 2)
693            fail("MCASTFilter (EXCLUDE + INCLUDE) too many elements\n");
694
695        source = index->keyValue;
696        if (memcmp(&source->ip6, &mreq_source[0].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
697        }
698        else if (memcmp(&source->ip6, &mreq_source[1].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
699        }
700        else {
701            fail("MCASTFilter (EXCLUDE + INCLUDE) incorrect\n");
702        }
703    }
704    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
705    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
706    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
707    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
708
709    /* EXCLUDE + EXCLUDE expected filter: source of 3 and 4 */
710    ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
711    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
712    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
713    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
714    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
715    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
716    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
717    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
718    ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
719    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
720    ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
721    fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
722    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
723    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
724    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
725    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
726    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[5]);
727    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
728    ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[6]);
729    fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
730    i = 0;
731    pico_tree_foreach(index, &MCASTFilter)
732    {
733        if (++i > 2)
734            fail("MCASTFilter (EXCLUDE + EXCLUDE) too many elements\n");
735
736        source = index->keyValue;
737        if (memcmp(&source->ip6, &mreq_source[3].mcast_source_addr, sizeof(struct pico_ip6) == 0)) { /* OK */
738        }
739        else if (memcmp(&source->ip6, &mreq_source[4].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
740        }
741        else {
742            fail("MCASTFilter (EXCLUDE + EXCLUDE) incorrect\n");
743        }
744    }
745    ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
746    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
747    ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
748    fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
749
750
751    ret = pico_socket_close(s);
752    fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
753    ret = pico_socket_close(s1);
754    fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
755}
756END_TEST
757#endif
758
759
760#endif
761