1 /* Tests for RAW sockets (LWIP) - by D.C. van Moolenbroek */
2 /* This test needs to be run as root: creating raw sockets is root-only. */
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stddef.h>
6 #include <sys/mman.h>
7 #include <sys/param.h>
8 #include <sys/socket.h>
9 #include <net/route.h>
10 #include <netinet/in.h>
11 #include <netinet/ip.h>
12 #include <netinet/udp.h>
13 #include <netinet/icmp6.h>
14 #include <netinet/in_pcb.h>
15 #include <netinet6/in6_pcb.h>
16 #include <arpa/inet.h>
17 #include <machine/vmparam.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <assert.h>
21
22 #include "common.h"
23 #include "socklib.h"
24
25 #define ITERATIONS 2
26
27 #define TEST_PROTO 253 /* from RFC 3692 */
28 #define TEST_ICMPV6_TYPE_A 200 /* from RFC 4443 */
29 #define TEST_ICMPV6_TYPE_B 201 /* from RFC 4443 */
30
31 static const enum state raw_states[] = {
32 S_NEW, S_N_SHUT_R, S_N_SHUT_W, S_N_SHUT_RW,
33 S_BOUND, S_CONNECTED, S_SHUT_R, S_SHUT_W,
34 S_SHUT_RW,
35 };
36
37 static const int raw_results[][__arraycount(raw_states)] = {
38 [C_ACCEPT] = {
39 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
40 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
41 -EOPNOTSUPP,
42 },
43 [C_BIND] = {
44 0, 0, 0, 0,
45 0, -EINVAL, -EINVAL, -EINVAL,
46 -EINVAL,
47 },
48 [C_CONNECT] = {
49 0, 0, 0, 0,
50 0, 0, 0, 0,
51 0,
52 },
53 [C_GETPEERNAME] = {
54 -ENOTCONN, -ENOTCONN, -ENOTCONN, -ENOTCONN,
55 -ENOTCONN, 0, 0, 0,
56 0,
57 },
58 [C_GETSOCKNAME] = {
59 0, 0, 0, 0,
60 0, 0, 0, 0,
61 0,
62 },
63 [C_GETSOCKOPT_ERR] = {
64 0, 0, 0, 0,
65 0, 0, 0, 0,
66 0,
67 },
68 [C_GETSOCKOPT_KA] = {
69 0, 0, 0, 0,
70 0, 0, 0, 0,
71 0,
72 },
73 [C_GETSOCKOPT_RB] = {
74 0, 0, 0, 0,
75 0, 0, 0, 0,
76 0,
77 },
78 [C_IOCTL_NREAD] = {
79 0, 0, 0, 0,
80 0, 0, 0, 0,
81 0,
82 },
83 [C_LISTEN] = {
84 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
85 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
86 -EOPNOTSUPP,
87 },
88 [C_RECV] = {
89 -EAGAIN, 0, -EAGAIN, 0,
90 -EAGAIN, -EAGAIN, 0, -EAGAIN,
91 0,
92 },
93 [C_RECVFROM] = {
94 -EAGAIN, 0, -EAGAIN, 0,
95 -EAGAIN, -EAGAIN, 0, -EAGAIN,
96 0,
97 },
98 [C_SEND] = {
99 -EDESTADDRREQ, -EDESTADDRREQ, -EPIPE, -EPIPE,
100 -EDESTADDRREQ, 1, 1, -EPIPE,
101 -EPIPE,
102 },
103 [C_SENDTO] = {
104 1, 1, -EPIPE, -EPIPE,
105 1, 1, 1, -EPIPE,
106 -EPIPE,
107 },
108 [C_SELECT_R] = {
109 0, 1, 0, 1,
110 0, 0, 1, 0,
111 1,
112 },
113 [C_SELECT_W] = {
114 1, 1, 1, 1,
115 1, 1, 1, 1,
116 1,
117 },
118 [C_SELECT_X] = {
119 0, 0, 0, 0,
120 0, 0, 0, 0,
121 0,
122 },
123 [C_SETSOCKOPT_BC] = {
124 0, 0, 0, 0,
125 0, 0, 0, 0,
126 0,
127 },
128 [C_SETSOCKOPT_KA] = {
129 0, 0, 0, 0,
130 0, 0, 0, 0,
131 0,
132 },
133 [C_SETSOCKOPT_L] = {
134 0, 0, 0, 0,
135 0, 0, 0, 0,
136 0,
137 },
138 [C_SETSOCKOPT_RA] = {
139 0, 0, 0, 0,
140 0, 0, 0, 0,
141 0,
142 },
143 [C_SHUTDOWN_R] = {
144 0, 0, 0, 0,
145 0, 0, 0, 0,
146 0,
147 },
148 [C_SHUTDOWN_RW] = {
149 0, 0, 0, 0,
150 0, 0, 0, 0,
151 0,
152 },
153 [C_SHUTDOWN_W] = {
154 0, 0, 0, 0,
155 0, 0, 0, 0,
156 0,
157 },
158 };
159
160 /*
161 * Set up a RAW socket file descriptor in the requested state and pass it to
162 * socklib_sweep_call() along with local and remote addresses and their length.
163 */
164 static int
raw_sweep(int domain,int type,int protocol,enum state state,enum call call)165 raw_sweep(int domain, int type, int protocol, enum state state,
166 enum call call)
167 {
168 struct sockaddr_in sinA, sinB;
169 struct sockaddr_in6 sin6A, sin6B;
170 struct sockaddr *addrA, *addrB;
171 socklen_t addr_len;
172 int r, fd, fd2;
173
174 if (domain == AF_INET) {
175 memset(&sinA, 0, sizeof(sinA));
176 sinA.sin_family = domain;
177 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
178
179 memcpy(&sinB, &sinA, sizeof(sinB));
180
181 addrA = (struct sockaddr *)&sinA;
182 addrB = (struct sockaddr *)&sinB;
183 addr_len = sizeof(sinA);
184 } else {
185 assert(domain == AF_INET6);
186
187 memset(&sin6A, 0, sizeof(sin6A));
188 sin6A.sin6_family = domain;
189 memcpy(&sin6A.sin6_addr, &in6addr_loopback,
190 sizeof(sin6A.sin6_addr));
191
192 memcpy(&sin6B, &sin6A, sizeof(sin6B));
193
194 addrA = (struct sockaddr *)&sin6A;
195 addrB = (struct sockaddr *)&sin6B;
196 addr_len = sizeof(sin6A);
197 }
198
199 /* Create a bound remote socket. */
200 if ((fd2 = socket(domain, type | SOCK_NONBLOCK, protocol)) < 0) e(0);
201
202 if (bind(fd2, addrB, addr_len) != 0) e(0);
203
204 switch (state) {
205 case S_NEW:
206 case S_N_SHUT_R:
207 case S_N_SHUT_W:
208 case S_N_SHUT_RW:
209 if ((fd = socket(domain, type | SOCK_NONBLOCK,
210 protocol)) < 0) e(0);
211
212 switch (state) {
213 case S_N_SHUT_R: if (shutdown(fd, SHUT_RD)) e(0); break;
214 case S_N_SHUT_W: if (shutdown(fd, SHUT_WR)) e(0); break;
215 case S_N_SHUT_RW: if (shutdown(fd, SHUT_RDWR)) e(0); break;
216 default: break;
217 }
218
219 break;
220
221 case S_BOUND:
222 case S_CONNECTED:
223 case S_SHUT_R:
224 case S_SHUT_W:
225 case S_SHUT_RW:
226 if ((fd = socket(domain, type | SOCK_NONBLOCK,
227 protocol)) < 0) e(0);
228
229 if (bind(fd, addrA, addr_len) != 0) e(0);
230
231 if (state == S_BOUND)
232 break;
233
234 if (connect(fd, addrB, addr_len) != 0) e(0);
235
236 switch (state) {
237 case S_SHUT_R: if (shutdown(fd, SHUT_RD)) e(0); break;
238 case S_SHUT_W: if (shutdown(fd, SHUT_WR)) e(0); break;
239 case S_SHUT_RW: if (shutdown(fd, SHUT_RDWR)) e(0); break;
240 default: break;
241 }
242
243 break;
244
245 default:
246 fd = -1;
247 e(0);
248 }
249
250 r = socklib_sweep_call(call, fd, addrA, addrB, addr_len);
251
252 if (close(fd) != 0) e(0);
253 if (fd2 != -1 && close(fd2) != 0) e(0);
254
255 return r;
256 }
257
258 /*
259 * Sweep test for socket calls versus socket states of RAW sockets.
260 */
261 static void
test92a(void)262 test92a(void)
263 {
264
265 subtest = 1;
266
267 socklib_sweep(AF_INET, SOCK_RAW, TEST_PROTO, raw_states,
268 __arraycount(raw_states), (const int *)raw_results, raw_sweep);
269
270 socklib_sweep(AF_INET6, SOCK_RAW, TEST_PROTO, raw_states,
271 __arraycount(raw_states), (const int *)raw_results, raw_sweep);
272 }
273
274 /*
275 * Basic I/O test for raw sockets.
276 */
277 static void
test92b(void)278 test92b(void)
279 {
280 struct sockaddr_in sinA, sinB, sinC;
281 struct sockaddr_in6 sin6A, sin6B, sin6C;
282 socklen_t len;
283 unsigned int i;
284 uint8_t buf[256], packet[5];
285 int fd, fd2;
286
287 subtest = 2;
288
289 /* First test IPv4. */
290 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
291
292 memset(&sinA, 0, sizeof(sinA));
293 sinA.sin_family = AF_INET;
294 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
295
296 for (i = 0; i < __arraycount(packet); i++)
297 packet[i] = (uint8_t)(-i);
298
299 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sinA,
300 sizeof(sinA)) != sizeof(packet)) e(0);
301
302 memset(buf, 0, sizeof(buf));
303 len = sizeof(sinB);
304 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sinB,
305 &len) != sizeof(struct ip) + sizeof(packet)) e(0);
306
307 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0);
308
309 if (len != sizeof(sinB)) e(0);
310 if (sinB.sin_len != sizeof(sinB)) e(0);
311 if (sinB.sin_family != AF_INET) e(0);
312 if (sinB.sin_port != htons(0)) e(0);
313 if (sinB.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) e(0);
314
315 /*
316 * Test two additional things:
317 *
318 * 1) a non-zero port number is ignored when sending;
319 * 2) multiple raw sockets may receive the same packet.
320 */
321 sinA.sin_port = htons(22);
322
323 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
324
325 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sinA,
326 sizeof(sinA)) != sizeof(packet)) e(0);
327
328 memset(buf, 0, sizeof(buf));
329 len = sizeof(sinC);
330 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sinC,
331 &len) != sizeof(struct ip) + sizeof(packet)) e(0);
332
333 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0);
334
335 if (len != sizeof(sinC)) e(0);
336 if (memcmp(&sinB, &sinC, sizeof(sinB)) != 0) e(0);
337
338 memset(buf, 0, sizeof(buf));
339 len = sizeof(sinC);
340 if (recvfrom(fd2, buf, sizeof(buf), 0, (struct sockaddr *)&sinC,
341 &len) != sizeof(struct ip) + sizeof(packet)) e(0);
342
343 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0);
344
345 if (len != sizeof(sinC)) e(0);
346 if (memcmp(&sinB, &sinC, sizeof(sinB)) != 0) e(0);
347
348 if (close(fd2) != 0) e(0);
349 if (close(fd) != 0) e(0);
350
351 /* Then test IPv6. */
352 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
353
354 memset(&sin6A, 0, sizeof(sin6A));
355 sin6A.sin6_family = AF_INET6;
356 memcpy(&sin6A.sin6_addr, &in6addr_loopback, sizeof(sin6A.sin6_addr));
357
358 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sin6A,
359 sizeof(sin6A)) != sizeof(packet)) e(0);
360
361 memset(buf, 0, sizeof(buf));
362 len = sizeof(sin6B);
363 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6B,
364 &len) != sizeof(packet)) e(0);
365
366 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0);
367
368 if (len != sizeof(sin6B)) e(0);
369 if (sin6B.sin6_len != sizeof(sin6B)) e(0);
370 if (sin6B.sin6_family != AF_INET6) e(0);
371 if (sin6B.sin6_port != htons(0)) e(0);
372 if (memcmp(&sin6B.sin6_addr, &in6addr_loopback,
373 sizeof(sin6B.sin6_addr)) != 0) e(0);
374
375 /* As above. */
376 sin6A.sin6_port = htons(22);
377
378 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
379
380 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sin6A,
381 sizeof(sin6A)) != sizeof(packet)) e(0);
382
383 memset(buf, 0, sizeof(buf));
384 len = sizeof(sin6C);
385 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6C,
386 &len) != sizeof(packet)) e(0);
387
388 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0);
389
390 if (len != sizeof(sin6C)) e(0);
391 if (memcmp(&sin6B, &sin6C, sizeof(sin6B)) != 0) e(0);
392
393 memset(buf, 0, sizeof(buf));
394 len = sizeof(sin6C);
395 if (recvfrom(fd2, buf, sizeof(buf), 0, (struct sockaddr *)&sin6C,
396 &len) != sizeof(packet)) e(0);
397
398 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0);
399
400 if (len != sizeof(sin6C)) e(0);
401 if (memcmp(&sin6B, &sin6C, sizeof(sin6B)) != 0) e(0);
402
403 if (close(fd2) != 0) e(0);
404 if (close(fd) != 0) e(0);
405 }
406
407 /*
408 * Test the IPV6_CHECKSUM socket option.
409 */
410 static void
test92c(void)411 test92c(void)
412 {
413 struct sockaddr_in6 sin6;
414 struct icmp6_hdr icmp6_hdr;
415 uint8_t buf[6], buf2[6], *buf3;
416 socklen_t len;
417 unsigned int i;
418 int fd, fd2, val;
419
420 subtest = 3;
421
422 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
423
424 if (shutdown(fd, SHUT_RD) != 0) e(0);
425
426 /* For non-ICMPv6 sockets, checksumming is disabled by default. */
427 len = sizeof(val);
428 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, &len) != 0) e(0);
429 if (len != sizeof(val)) e(0);
430 if (val != -1) e(0);
431
432 /* Test bad offsets. */
433 val = -2;
434 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
435 sizeof(val)) != -1) e(0);
436 if (errno != EINVAL) e(0);
437
438 val = 1;
439 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
440 sizeof(val)) != -1) e(0);
441 if (errno != EINVAL) e(0);
442
443 /* Now test real checksum computation. */
444 val = 0;
445 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
446 sizeof(val)) != 0) e(0);
447
448 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
449
450 if (shutdown(fd2, SHUT_WR) != 0) e(0);
451
452 memset(buf, 0, sizeof(buf));
453 buf[2] = 0xfe;
454 buf[3] = 0x95;
455 buf[4] = 0x4d;
456
457 memset(&sin6, 0, sizeof(sin6));
458 sin6.sin6_family = AF_INET6;
459 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
460
461 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5)
462 e(0);
463
464 if (recv(fd2, buf2, sizeof(buf2), 0) != 5) e(0);
465
466 if (buf2[0] != 0xb3 || buf2[1] != 0x65) e(0);
467 if (memcmp(&buf2[2], &buf[2], 3) != 0) e(0);
468
469 /* Turn on checksum verification on the receiving socket. */
470 val = 0;
471 if (setsockopt(fd2, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
472 sizeof(val)) != 0) e(0);
473
474 /*
475 * The current value of the checksum field should not be incorporated
476 * in the checksum, as that would result in an invalid checksum.
477 */
478 buf[0] = 0xab;
479 buf[1] = 0xcd;
480
481 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5)
482 e(0);
483
484 if (recv(fd2, buf2, sizeof(buf2), 0) != 5) e(0);
485
486 if (buf2[0] != 0xb3 || buf2[1] != 0x65) e(0);
487 if (memcmp(&buf2[2], &buf[2], 3) != 0) e(0);
488
489 /*
490 * Turn off checksum computation on the sending side, so that the
491 * packet ends up being dropped on the receiving side.
492 */
493 val = -1;
494 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
495 sizeof(val)) != 0) e(0);
496
497 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5)
498 e(0);
499
500 /* Send some packets that are too small to contain the checksum. */
501 if (sendto(fd, buf, 0, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 0)
502 e(0);
503 if (sendto(fd, buf, 1, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 1)
504 e(0);
505
506 /*
507 * If this recv call is "too soon" (it should not be) and the packets
508 * arrive later anyway, then we will get a failure below.
509 */
510 if (recv(fd2, buf2, sizeof(buf2), MSG_DONTWAIT) != -1) e(0);
511 if (errno != EWOULDBLOCK) e(0);
512
513 buf[0] = 0;
514 buf[1] = 0x67;
515 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6,
516 sizeof(sin6)) != 4) e(0);
517
518 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0);
519 if (memcmp(buf, buf2, 4) != 0) e(0);
520
521 /*
522 * We repeat some of the tests with a non-zero checksum offset, just to
523 * be sure.
524 */
525 val = 2;
526 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
527 sizeof(val)) != 0) e(0);
528
529 len = sizeof(val);
530 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, &len) != 0) e(0);
531 if (len != sizeof(val)) e(0);
532 if (val != 2) e(0);
533
534 buf[0] = 0x56;
535 buf[1] = 0x78;
536
537 for (i = 0; i <= 3; i++) {
538 if (sendto(fd, buf, i, 0, (struct sockaddr *)&sin6,
539 sizeof(sin6)) != -1) e(0);
540 if (errno != EINVAL) e(0);
541 }
542
543 val = 2;
544 if (setsockopt(fd2, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
545 sizeof(val)) != 0) e(0);
546
547 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6,
548 sizeof(sin6)) != 4) e(0);
549
550 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0);
551 if (memcmp(buf, buf2, 2) != 0) e(0);
552 if (buf2[2] != 0xa8 || buf2[3] != 0x84) e(0);
553
554 val = -1;
555 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
556 sizeof(val)) != 0) e(0);
557
558 buf[2] = 0xa8;
559 buf[3] = 0x85; /* deliberately bad checksum */
560
561 /* All these should be dropped on the receiver side. */
562 for (i = 0; i <= 4; i++) {
563 if (sendto(fd, buf, i, 0, (struct sockaddr *)&sin6,
564 sizeof(sin6)) != i) e(0);
565 }
566
567 buf[3] = 0x84; /* good checksum */
568 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 4)
569 e(0);
570
571 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0);
572 if (memcmp(buf, buf2, 4) != 0) e(0);
573
574 if (recv(fd2, buf2, sizeof(buf2), MSG_DONTWAIT) != -1) e(0);
575 if (errno != EWOULDBLOCK) e(0);
576
577 val = -1;
578 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
579 sizeof(val)) != 0) e(0);
580 if (setsockopt(fd2, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
581 sizeof(val)) != 0) e(0);
582
583 buf[3] = 0x85;
584 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 4)
585 e(0);
586
587 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0);
588 if (memcmp(buf, buf2, 4) != 0) e(0);
589
590 /*
591 * The following is a lwIP-specific test: lwIP does not support storing
592 * generated checksums beyond the first pbuf. We do not know the size
593 * of the first pbuf until we actually send a packet, so the setsockopt
594 * call will not fail, but sending the packet will. Depending on the
595 * buffer allocation strategy, the following test may or may not
596 * trigger this case; simply ensure that we do not crash the service.
597 */
598 if ((buf3 = malloc(4096)) == NULL) e(0);
599
600 val = 4094;
601 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
602 sizeof(val)) != 0) e(0);
603
604 /* This call may or may not fail, but if it fails, it yields EINVAL. */
605 if (sendto(fd, buf3, 4096, 0, (struct sockaddr *)&sin6,
606 sizeof(sin6)) == -1 && errno != EINVAL) e(0);
607
608 free(buf3);
609
610 if (close(fd2) != 0) e(0);
611 if (close(fd) != 0) e(0);
612
613 /* For ICMPv6 packets, checksumming is always enabled. */
614 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
615
616 len = sizeof(val);
617 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, &len) != 0) e(0);
618 if (len != sizeof(val)) e(0);
619 if (val != 2) e(0);
620
621 val = -1;
622 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
623 sizeof(val)) != -1) e(0);
624 if (errno != EINVAL) e(0);
625
626 memset(&icmp6_hdr, 0, sizeof(icmp6_hdr));
627 icmp6_hdr.icmp6_type = TEST_ICMPV6_TYPE_A;
628 icmp6_hdr.icmp6_code = 123;
629 icmp6_hdr.icmp6_cksum = htons(0);
630
631 len = offsetof(struct icmp6_hdr, icmp6_dataun);
632 if (sendto(fd, &icmp6_hdr, len, 0, (struct sockaddr *)&sin6,
633 sizeof(sin6)) != len) e(0);
634
635 if (recv(fd, &icmp6_hdr, sizeof(icmp6_hdr), 0) != len) e(0);
636
637 if (icmp6_hdr.icmp6_type != TEST_ICMPV6_TYPE_A) e(0);
638 if (icmp6_hdr.icmp6_code != 123) e(0);
639 if (ntohs(icmp6_hdr.icmp6_cksum) != 0x3744) e(0);
640
641 if (close(fd) != 0) e(0);
642
643 /* For IPv4 and non-RAW IPv6 sockets, the option does not work. */
644 for (i = 0; i <= 2; i++) {
645 switch (i) {
646 case 0: fd = socket(AF_INET6, SOCK_DGRAM, 0); break;
647 case 1: fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6); break;
648 case 2: fd = socket(AF_INET, SOCK_RAW, TEST_PROTO); break;
649 }
650 if (fd < 0) e(0);
651
652 val = -1;
653 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
654 sizeof(val)) != -1) e(0);
655 if (errno != ENOPROTOOPT) e(0);
656
657 len = sizeof(val);
658 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
659 &len) != -1) e(0);
660 if (errno != ENOPROTOOPT) e(0);
661
662 if (close(fd) != 0) e(0);
663 }
664 }
665
666 /*
667 * Test the ICMP6_FILTER socket option.
668 */
669 static void
test92d(void)670 test92d(void)
671 {
672 struct sockaddr_in6 sin6;
673 struct sockaddr_in sin;
674 struct icmp6_filter filter;
675 struct icmp6_hdr packet;
676 socklen_t len;
677 struct timeval tv;
678 unsigned int i;
679 int fd, fd2;
680
681 subtest = 4;
682
683 /*
684 * We use two different sockets to eliminate the possibility that the
685 * filter is also applied when sending packets--it should not be.
686 */
687 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
688
689 if (shutdown(fd, SHUT_WR) != 0) e(0);
690
691 len = sizeof(filter);
692 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0)
693 e(0);
694
695 /* We do not aim to test the ICMP6_FILTER macros here. */
696 for (i = 0; i <= UINT8_MAX; i++)
697 if (!ICMP6_FILTER_WILLPASS(i, &filter)) e(0);
698
699 if ((fd2 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
700
701 ICMP6_FILTER_SETBLOCKALL(&filter);
702 if (setsockopt(fd2, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
703 sizeof(filter)) != 0) e(0);
704
705 len = sizeof(filter);
706 if (getsockopt(fd2, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0)
707 e(0);
708
709 for (i = 0; i <= UINT8_MAX; i++)
710 if (ICMP6_FILTER_WILLPASS(i, &filter)) e(0);
711
712 ICMP6_FILTER_SETPASSALL(&filter);
713 ICMP6_FILTER_SETBLOCK(TEST_ICMPV6_TYPE_A, &filter);
714 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
715 sizeof(filter)) != 0) e(0);
716
717 memset(&sin6, 0, sizeof(sin6));
718 sin6.sin6_family = AF_INET6;
719 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
720
721 memset(&packet, 0, sizeof(packet));
722 packet.icmp6_type = TEST_ICMPV6_TYPE_A;
723 packet.icmp6_code = 12;
724
725 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
726 sizeof(sin6)) != sizeof(packet)) e(0);
727
728 packet.icmp6_type = TEST_ICMPV6_TYPE_B;
729 packet.icmp6_code = 34;
730
731 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
732 sizeof(sin6)) != sizeof(packet)) e(0);
733
734 memset(&packet, 0, sizeof(packet));
735
736 if (recv(fd, &packet, sizeof(packet), 0) != sizeof(packet)) e(0);
737 if (packet.icmp6_type != TEST_ICMPV6_TYPE_B) e(0);
738 if (packet.icmp6_code != 34) e(0);
739
740 if (recv(fd, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0);
741 if (errno != EWOULDBLOCK) e(0);
742
743 ICMP6_FILTER_SETBLOCKALL(&filter);
744 ICMP6_FILTER_SETPASS(TEST_ICMPV6_TYPE_A, &filter);
745 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
746 sizeof(filter)) != 0) e(0);
747
748 memset(&packet, 0, sizeof(packet));
749 packet.icmp6_type = TEST_ICMPV6_TYPE_B;
750 packet.icmp6_code = 56;
751
752 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
753 sizeof(sin6)) != sizeof(packet)) e(0);
754
755 packet.icmp6_type = TEST_ICMPV6_TYPE_A;
756 packet.icmp6_code = 78;
757
758 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
759 sizeof(sin6)) != sizeof(packet)) e(0);
760
761 /*
762 * RFC 3542 states that setting a zero-length filter resets the filter.
763 * This seems like one of those things that a standardization RFC
764 * should not mandate: it is redundant at the API level (one can set a
765 * PASSALL filter, which is the required default), it relies on an edge
766 * case (setsockopt taking a zero-length argument), and as a "shortcut"
767 * it does not even cover a case that is likely to occur (no actual
768 * program would reset its filter on a regular basis). Presumably it
769 * is a way to deallocate filter memory on some platforms, but was that
770 * worth the RFC inclusion? Anyhow, we support it; NetBSD does not.
771 */
772 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, NULL, 0) != 0) e(0);
773
774 packet.icmp6_type = TEST_ICMPV6_TYPE_B;
775 packet.icmp6_code = 90;
776
777 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
778 sizeof(sin6)) != sizeof(packet)) e(0);
779
780 memset(&packet, 0, sizeof(packet));
781
782 if (recv(fd, &packet, sizeof(packet), 0) != sizeof(packet)) e(0);
783 if (packet.icmp6_type != TEST_ICMPV6_TYPE_A) e(0);
784 if (packet.icmp6_code != 78) e(0);
785
786 if (recv(fd, &packet, sizeof(packet), 0) != sizeof(packet)) e(0);
787 if (packet.icmp6_type != TEST_ICMPV6_TYPE_B) e(0);
788 if (packet.icmp6_code != 90) e(0);
789
790 if (recv(fd, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0);
791 if (errno != EWOULDBLOCK) e(0);
792
793 if (recv(fd2, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0);
794 if (errno != EWOULDBLOCK) e(0);
795
796 len = sizeof(filter);
797 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0)
798 e(0);
799
800 for (i = 0; i <= UINT8_MAX; i++)
801 if (!ICMP6_FILTER_WILLPASS(i, &filter)) e(0);
802
803 if (close(fd2) != 0) e(0);
804
805 /*
806 * Let's get weird and send an ICMPv6 packet from an IPv4 socket.
807 * Currently, such packets are always dropped based on the rule that
808 * IPv6 sockets with checksumming enabled drop all IPv4 packets. As it
809 * happens, that is also all that is keeping this packet from arriving.
810 */
811 if ((fd2 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
812
813 ICMP6_FILTER_SETBLOCKALL(&filter);
814 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
815 sizeof(filter)) != 0) e(0);
816
817 memset(&sin, 0, sizeof(sin));
818 sin.sin_family = AF_INET;
819 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
820
821 memset(&packet, 0, sizeof(packet));
822 packet.icmp6_type = TEST_ICMPV6_TYPE_A;
823 packet.icmp6_code = 123;
824 packet.icmp6_cksum = htons(0); /* TODO: use valid checksum */
825
826 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin,
827 sizeof(sin)) != sizeof(packet)) e(0);
828
829 /*
830 * If the packet were to arrive at all, it should arrive instantly, so
831 * this is just an excuse to use SO_RCVTIMEO.
832 */
833 tv.tv_sec = 0;
834 tv.tv_usec = 100000;
835 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0)
836 e(0);
837
838 if (recv(fd, &packet, sizeof(packet), 0) != -1) e(0);
839 if (errno != EWOULDBLOCK) e(0);
840
841 if (close(fd2) != 0) e(0);
842
843 if (close(fd) != 0) e(0);
844
845 /* Make sure ICMP6_FILTER works on IPv6-ICMPv6 sockets only. */
846 for (i = 0; i <= 2; i++) {
847 switch (i) {
848 case 0: fd = socket(AF_INET6, SOCK_DGRAM, 0); break;
849 case 1: fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO); break;
850 case 2: fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6); break;
851 }
852 if (fd < 0) e(0);
853
854 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
855 sizeof(filter)) != -1) e(0);
856 if (errno != ENOPROTOOPT) e(0);
857
858 len = sizeof(filter);
859 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
860 &len) != -1) e(0);
861 if (errno != ENOPROTOOPT) e(0);
862
863 if (close(fd) != 0) e(0);
864 }
865 }
866
867 /*
868 * Test that IPPROTO_ICMPV6 has no special value on IPv4 raw sockets. In
869 * particular, test that no checksum is generated or verified. By now we have
870 * already tested that none of the IPv6 socket options work on such sockets.
871 */
872 static void
test92e(void)873 test92e(void)
874 {
875 char buf[sizeof(struct ip) + sizeof(struct icmp6_hdr)];
876 struct sockaddr_in sin;
877 struct icmp6_hdr packet;
878 int fd;
879
880 subtest = 5;
881
882 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
883
884 memset(&packet, 0, sizeof(packet));
885 packet.icmp6_type = TEST_ICMPV6_TYPE_A;
886 packet.icmp6_code = 123;
887 packet.icmp6_cksum = htons(0);
888
889 memset(&sin, 0, sizeof(sin));
890 sin.sin_family = AF_INET;
891 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
892
893 if (sendto(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&sin,
894 sizeof(sin)) != sizeof(packet)) e(0);
895
896 if (recv(fd, buf, sizeof(buf), 0) != sizeof(buf)) e(0);
897
898 memcpy(&packet, &buf[sizeof(struct ip)], sizeof(packet));
899 if (packet.icmp6_type != TEST_ICMPV6_TYPE_A) e(0);
900 if (packet.icmp6_code != 123) e(0);
901 if (packet.icmp6_cksum != htons(0)) e(0);
902
903 if (close(fd) != 0) e(0);
904 }
905
906 struct testpkt {
907 struct ip ip;
908 struct udphdr udp;
909 uint8_t data[6];
910 } __packed;
911
912 /*
913 * Test the IP_HDRINCL socket option.
914 */
915 static void
test92f(void)916 test92f(void)
917 {
918 struct sockaddr_in sin;
919 struct testpkt pkt, pkt2;
920 socklen_t len;
921 char buf[7];
922 unsigned int i;
923 int fd, fd2, val;
924
925 subtest = 6;
926
927 /* See if we can successfully feign a UDP packet. */
928 memset(&pkt, 0, sizeof(pkt));
929 pkt.ip.ip_v = IPVERSION;
930 pkt.ip.ip_hl = sizeof(pkt.ip) >> 2;
931 pkt.ip.ip_tos = 123;
932 pkt.ip.ip_len = sizeof(pkt); /* swapped by OS */
933 pkt.ip.ip_id = htons(456);
934 pkt.ip.ip_off = IP_DF; /* swapped by OS */
935 pkt.ip.ip_ttl = 78;
936 pkt.ip.ip_p = IPPROTO_UDP;
937 pkt.ip.ip_sum = htons(0); /* filled by OS */
938 pkt.ip.ip_src.s_addr = htonl(INADDR_LOOPBACK);
939 pkt.ip.ip_dst.s_addr = htonl(INADDR_LOOPBACK);
940 pkt.udp.uh_sport = htons(TEST_PORT_B);
941 pkt.udp.uh_dport = htons(TEST_PORT_A);
942 pkt.udp.uh_sum = htons(0); /* lazy.. */
943 pkt.udp.uh_ulen = htons(sizeof(pkt.udp) + sizeof(pkt.data));
944 memcpy(pkt.data, "Hello!", sizeof(pkt.data));
945
946 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) e(0);
947
948 if (shutdown(fd, SHUT_RD) != 0) e(0);
949
950 /* IP_HDRINCL is never enabled by default. */
951 len = sizeof(val);
952 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, &len) != 0) e(0);
953 if (len != sizeof(val)) e(0);
954 if (val != 0) e(0);
955
956 val = 1;
957 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0)
958 e(0);
959
960 len = sizeof(val);
961 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, &len) != 0) e(0);
962 if (len != sizeof(val)) e(0);
963 if (val != 1) e(0);
964
965 if ((fd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) e(0);
966
967 memset(&sin, 0, sizeof(sin));
968 sin.sin_family = AF_INET;
969 sin.sin_port = htons(TEST_PORT_A);
970 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
971
972 if (bind(fd2, (struct sockaddr *)&sin, sizeof(sin)) != 0) e(0);
973
974 sin.sin_port = htons(0);
975
976 if (sendto(fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sin,
977 sizeof(sin)) != sizeof(pkt)) e(0);
978
979 if (recv(fd2, &buf, sizeof(buf), 0) != sizeof(pkt.data)) e(0);
980 if (memcmp(buf, pkt.data, sizeof(pkt.data)) != 0) e(0);
981
982 if (close(fd2) != 0) e(0);
983 if (close(fd) != 0) e(0);
984
985 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
986
987 len = sizeof(val);
988 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, &len) != 0) e(0);
989 if (len != sizeof(val)) e(0);
990 if (val != 0) e(0);
991
992 if (shutdown(fd, SHUT_RD) != 0) e(0);
993
994 /* See if we can receive a packet for our own protocol. */
995 pkt.ip.ip_p = TEST_PROTO;
996
997 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
998
999 val = 1;
1000 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0)
1001 e(0);
1002
1003 if (sendto(fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sin,
1004 sizeof(sin)) != sizeof(pkt)) e(0);
1005
1006 if (recv(fd2, &pkt2, sizeof(pkt2), 0) != sizeof(pkt2)) e(0);
1007
1008 if (pkt2.ip.ip_v != pkt.ip.ip_v) e(0);
1009 if (pkt2.ip.ip_hl != pkt.ip.ip_hl) e(0);
1010 if (pkt2.ip.ip_tos != pkt.ip.ip_tos) e(0);
1011 if (pkt2.ip.ip_len != pkt.ip.ip_len) e(0);
1012 if (pkt2.ip.ip_id != pkt.ip.ip_id) e(0);
1013 if (pkt2.ip.ip_off != pkt.ip.ip_off) e(0);
1014 if (pkt2.ip.ip_ttl != pkt.ip.ip_ttl) e(0);
1015 if (pkt2.ip.ip_p != pkt.ip.ip_p) e(0);
1016 if (pkt2.ip.ip_sum == htons(0)) e(0);
1017 if (pkt2.ip.ip_src.s_addr != pkt.ip.ip_src.s_addr) e(0);
1018 if (pkt2.ip.ip_dst.s_addr != pkt.ip.ip_dst.s_addr) e(0);
1019
1020 /*
1021 * Test sending packets with weird sizes to ensure that we do not crash
1022 * the service. These packets would never arrive anyway.
1023 */
1024 if (sendto(fd, &pkt, 0, 0, (struct sockaddr *)&sin,
1025 sizeof(sin)) != -1) e(0);
1026 if (errno != EINVAL) e(0);
1027 if (sendto(fd, &pkt, sizeof(pkt.ip) - 1, 0, (struct sockaddr *)&sin,
1028 sizeof(sin)) != -1) e(0);
1029 if (errno != EINVAL) e(0);
1030 if (sendto(fd, &pkt, sizeof(pkt.ip), 0, (struct sockaddr *)&sin,
1031 sizeof(sin)) != sizeof(pkt.ip)) e(0);
1032
1033 if (recv(fd2, &pkt2, sizeof(pkt2), MSG_DONTWAIT) != -1) e(0);
1034 if (errno != EWOULDBLOCK) e(0);
1035
1036 if (close(fd2) != 0) e(0);
1037 if (close(fd) != 0) e(0);
1038
1039 /* Ensure that the socket option does not work on other types. */
1040 for (i = 0; i <= 1; i++) {
1041 switch (i) {
1042 case 0: fd = socket(AF_INET, SOCK_DGRAM, 0); break;
1043 case 1: fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO); break;
1044 }
1045 if (fd < 0) e(0);
1046
1047 len = sizeof(val);
1048 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val,
1049 &len) != -1) e(0);
1050 if (errno != ENOPROTOOPT) e(0);
1051
1052 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val,
1053 sizeof(val)) != -1) e(0);
1054 if (errno != ENOPROTOOPT) e(0);
1055
1056 if (close(fd) != 0) e(0);
1057 }
1058 }
1059
1060 /*
1061 * Test the IPPROTO_RAW socket protocol. This test mostly shows that the
1062 * IPPROTO_RAW protocol is nothing special: for both IPv4 and IPv6, it sends
1063 * and receives packets with that protocol number. We already tested earlier
1064 * that IP_HDRINCL is disabled by default on IPPROTO_RAW sockets, too.
1065 */
1066 static void
test92g(void)1067 test92g(void)
1068 {
1069 struct sockaddr_in sin;
1070 struct sockaddr_in6 sin6;
1071 char buf[sizeof(struct ip) + 1];
1072 int fd;
1073
1074 subtest = 7;
1075
1076 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) e(0);
1077
1078 memset(&sin, 0, sizeof(sin));
1079 sin.sin_family = AF_INET;
1080 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1081
1082 if (sendto(fd, "A", 1, 0, (struct sockaddr *)&sin,
1083 sizeof(sin)) != 1) e(0);
1084
1085 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != sizeof(buf)) e(0);
1086 if (buf[sizeof(struct ip)] != 'A') e(0);
1087
1088 if (close(fd) != 0) e(0);
1089
1090 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)) < 0) e(0);
1091
1092 memset(&sin6, 0, sizeof(sin6));
1093 sin6.sin6_family = AF_INET6;
1094 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
1095
1096 if (sendto(fd, "B", 1, 0, (struct sockaddr *)&sin6,
1097 sizeof(sin6)) != 1) e(0);
1098
1099 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != 1) e(0);
1100 if (buf[0] != 'B') e(0);
1101
1102 if (close(fd) != 0) e(0);
1103 }
1104
1105 /*
1106 * Test that connected raw sockets perform correct source-based filtering.
1107 */
1108 static void
test92h(void)1109 test92h(void)
1110 {
1111 struct sockaddr_in sinA, sinB;
1112 struct sockaddr_in6 sin6A, sin6B;
1113 struct sockaddr sa;
1114 socklen_t len;
1115 char buf[sizeof(struct ip) + 1];
1116 int fd, fd2;
1117
1118 subtest = 8;
1119
1120 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1121
1122 len = sizeof(sinB);
1123 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != -1) e(0);
1124 if (errno != ENOTCONN) e(0);
1125
1126 memset(&sinA, 0, sizeof(sinA));
1127 sinA.sin_family = AF_INET;
1128 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1129
1130 /*
1131 * First test that packets with the right source are accepted.
1132 * Unfortunately, source and destination are the same in this case, so
1133 * this test is far from perfect.
1134 */
1135 if (connect(fd, (struct sockaddr *)&sinA, sizeof(sinA)) != 0) e(0);
1136
1137 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != 0) e(0);
1138
1139 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1140
1141 if (sendto(fd2, "A", 1, 0, (struct sockaddr *)&sinA,
1142 sizeof(sinA)) != 1) e(0);
1143
1144 buf[0] = '\0';
1145 if (recv(fd2, buf, sizeof(buf), 0) != sizeof(struct ip) + 1) e(0);
1146 if (buf[sizeof(struct ip)] != 'A') e(0);
1147
1148 buf[0] = '\0';
1149 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) !=
1150 sizeof(struct ip) + 1) e(0);
1151 if (buf[sizeof(struct ip)] != 'A') e(0);
1152
1153 memset(&sa, 0, sizeof(sa));
1154 sa.sa_family = AF_UNSPEC;
1155
1156 sinA.sin_addr.s_addr = htonl(INADDR_NONE);
1157
1158 /* While here, test unconnecting the socket. */
1159 if (connect(fd, &sa, sizeof(sa)) != 0) e(0);
1160
1161 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != -1) e(0);
1162 if (errno != ENOTCONN) e(0);
1163
1164 /* Then test that packets with the wrong source are ignored. */
1165 if (connect(fd, (struct sockaddr *)&sinA, sizeof(sinA)) != 0) e(0);
1166
1167 if (sendto(fd2, "B", 1, 0, (struct sockaddr *)&sinB,
1168 sizeof(sinB)) != 1) e(0);
1169
1170 buf[0] = '\0';
1171 if (recv(fd2, buf, sizeof(buf), 0) != sizeof(struct ip) + 1) e(0);
1172 if (buf[sizeof(struct ip)] != 'B') e(0);
1173
1174 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != -1) e(0);
1175 if (errno != EWOULDBLOCK) e(0);
1176
1177 if (close(fd2) != 0) e(0);
1178 if (close(fd) != 0) e(0);
1179
1180 /* Repeat for IPv6, but now the other way around. */
1181 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1182
1183 len = sizeof(sin6B);
1184 if (getpeername(fd, (struct sockaddr *)&sin6B, &len) != -1) e(0);
1185 if (errno != ENOTCONN) e(0);
1186
1187 memset(&sin6A, 0, sizeof(sin6A));
1188 sin6A.sin6_family = AF_INET6;
1189 memcpy(&sin6A.sin6_addr, &in6addr_loopback, sizeof(sin6A.sin6_addr));
1190
1191 memcpy(&sin6B, &sin6A, sizeof(sin6B));
1192 if (inet_pton(AF_INET6, "::2", &sin6B.sin6_addr) != 1) e(0);
1193
1194 if (connect(fd, (struct sockaddr *)&sin6B, sizeof(sin6B)) != 0) e(0);
1195
1196 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1197
1198 if (sendto(fd2, "C", 1, 0, (struct sockaddr *)&sin6A,
1199 sizeof(sin6A)) != 1) e(0);
1200
1201 buf[0] = '\0';
1202 if (recv(fd2, buf, sizeof(buf), 0) != 1) e(0);
1203 if (buf[0] != 'C') e(0);
1204
1205 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != -1) e(0);
1206 if (errno != EWOULDBLOCK) e(0);
1207
1208 if (connect(fd, &sa, sizeof(sa)) != 0) e(0);
1209
1210 if (connect(fd, (struct sockaddr *)&sin6A, sizeof(sin6A)) != 0) e(0);
1211
1212 if (sendto(fd2, "D", 1, 0, (struct sockaddr *)&sin6A,
1213 sizeof(sin6A)) != 1) e(0);
1214
1215 buf[0] = '\0';
1216 if (recv(fd2, buf, sizeof(buf), 0) != 1) e(0);
1217 if (buf[0] != 'D') e(0);
1218
1219 buf[0] = '\0';
1220 if (recv(fd, buf, sizeof(buf), 0) != 1) e(0);
1221 if (buf[0] != 'D') e(0);
1222
1223 if (close(fd2) != 0) e(0);
1224 if (close(fd) != 0) e(0);
1225 }
1226
1227 /*
1228 * Test sending large and small RAW packets. This test is an altered copy of
1229 * test91e, but has been changed to IPv6 to cover a greater spectrum together.
1230 */
1231 static void
test92i(void)1232 test92i(void)
1233 {
1234 struct sockaddr_in6 sin6;
1235 struct msghdr msg;
1236 struct iovec iov;
1237 char *buf;
1238 unsigned int i, j;
1239 int r, fd, fd2, val;
1240
1241 subtest = 9;
1242
1243 if ((buf = malloc(65536)) == NULL) e(0);
1244
1245 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1246
1247 memset(&sin6, 0, sizeof(sin6));
1248 sin6.sin6_family = AF_INET6;
1249 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
1250
1251 if (bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) != 0) e(0);
1252
1253 val = 65536;
1254 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0)
1255 e(0);
1256
1257 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1258
1259 /*
1260 * A maximum send buffer size of a full packet size's worth may always
1261 * be set, although this is not necessarily the actual maximum.
1262 */
1263 val = 65535;
1264 if (setsockopt(fd2, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0)
1265 e(0);
1266
1267 /* Find the largest possible packet size that can actually be sent. */
1268 for (i = 0; i < val; i += sizeof(int)) {
1269 j = i ^ 0xdeadbeef;
1270 memcpy(&buf[i], &j, sizeof(j));
1271 }
1272
1273 for (val = 65536; val > 0; val--) {
1274 if ((r = sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6,
1275 sizeof(sin6))) == val)
1276 break;
1277 if (r != -1) e(0);
1278 if (errno != EMSGSIZE) e(0);
1279 }
1280
1281 if (val != 65535 - sizeof(struct ip6_hdr)) e(0);
1282
1283 memset(buf, 0, val);
1284 buf[val] = 'X';
1285
1286 memset(&iov, 0, sizeof(iov));
1287 iov.iov_base = buf;
1288 iov.iov_len = val + 1;
1289 memset(&msg, 0, sizeof(msg));
1290 msg.msg_iov = &iov;
1291 msg.msg_iovlen = 1;
1292 if (recvmsg(fd, &msg, 0) != val) e(0);
1293 if (msg.msg_flags != 0) e(0);
1294
1295 for (i = 0; i < val; i += sizeof(int)) {
1296 j = i ^ 0xdeadbeef;
1297 if (memcmp(&buf[i], &j, MIN(sizeof(j), val - i))) e(0);
1298 }
1299 if (buf[val] != 'X') e(0);
1300
1301 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) !=
1302 val) e(0);
1303
1304 /*
1305 * Make sure that there are no off-by-one errors in the receive code,
1306 * and that MSG_TRUNC is set (only) when not the whole packet was
1307 * received.
1308 */
1309 memset(&iov, 0, sizeof(iov));
1310 iov.iov_base = buf;
1311 iov.iov_len = val;
1312 memset(&msg, 0, sizeof(msg));
1313 msg.msg_iov = &iov;
1314 msg.msg_iovlen = 1;
1315 if (recvmsg(fd, &msg, 0) != val) e(0);
1316 if (msg.msg_flags != 0) e(0);
1317
1318 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) !=
1319 val) e(0);
1320
1321 buf[val - 1] = 'Y';
1322
1323 memset(&iov, 0, sizeof(iov));
1324 iov.iov_base = buf;
1325 iov.iov_len = val - 1;
1326 memset(&msg, 0, sizeof(msg));
1327 msg.msg_iov = &iov;
1328 msg.msg_iovlen = 1;
1329 if (recvmsg(fd, &msg, 0) != val - 1) e(0);
1330 if (msg.msg_flags != MSG_TRUNC) e(0);
1331
1332 for (i = 0; i < val - 1; i += sizeof(int)) {
1333 j = i ^ 0xdeadbeef;
1334 if (memcmp(&buf[i], &j, MIN(sizeof(j), val - 1 - i))) e(0);
1335 }
1336 if (buf[val - 1] != 'Y') e(0);
1337
1338 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) !=
1339 val) e(0);
1340
1341 buf[0] = 'Z';
1342
1343 memset(&iov, 0, sizeof(iov));
1344 iov.iov_base = buf;
1345 iov.iov_len = 0;
1346 memset(&msg, 0, sizeof(msg));
1347 msg.msg_iov = &iov;
1348 msg.msg_iovlen = 1;
1349 if (recvmsg(fd, &msg, 0) != 0) e(0);
1350 if (msg.msg_flags != MSG_TRUNC) e(0);
1351 if (buf[0] != 'Z') e(0);
1352
1353 /* Make sure that zero-sized packets can be sent and received. */
1354 if (sendto(fd2, buf, 0, 0, (struct sockaddr *)&sin6,
1355 sizeof(sin6)) != 0) e(0);
1356
1357 /*
1358 * Note how we currently assume that packets sent over localhost will
1359 * arrive immediately, so that we can use MSG_DONTWAIT to avoid that
1360 * the test freezes.
1361 */
1362 memset(&msg, 0, sizeof(msg));
1363 msg.msg_iov = &iov;
1364 msg.msg_iovlen = 1;
1365 if (recvmsg(fd, &msg, MSG_DONTWAIT) != 0) e(0);
1366 if (msg.msg_flags != 0) e(0);
1367 if (buf[0] != 'Z') e(0);
1368
1369 if (recv(fd, buf, val, MSG_DONTWAIT) != -1) e(0);
1370 if (errno != EWOULDBLOCK) e(0);
1371
1372 /*
1373 * When sending lots of small packets, ensure that fewer packets arrive
1374 * than we sent. This sounds weird, but we cannot actually check the
1375 * internal TCP/IP buffer granularity and yet we want to make sure that
1376 * the receive queue is measured in terms of buffers rather than packet
1377 * sizes. In addition, we check that older packets are favored,
1378 * instead discarding new ones when the receive buffer is full.
1379 */
1380 for (i = 0; i < 65536 / sizeof(j); i++) {
1381 j = i;
1382 if (sendto(fd2, &j, sizeof(j), 0, (struct sockaddr *)&sin6,
1383 sizeof(sin6)) != sizeof(j)) e(0);
1384 }
1385
1386 for (i = 0; i < 1025; i++) {
1387 r = recv(fd, &j, sizeof(j), MSG_DONTWAIT);
1388 if (r == -1) {
1389 if (errno != EWOULDBLOCK) e(0);
1390 break;
1391 }
1392 if (r != sizeof(j)) e(0);
1393 if (i != j) e(0);
1394 }
1395 if (i == 1025) e(0);
1396
1397 if (close(fd2) != 0) e(0);
1398 if (close(fd) != 0) e(0);
1399
1400 free(buf);
1401 }
1402
1403 /*
1404 * Test sending and receiving with bad pointers.
1405 */
1406 static void
test92j(void)1407 test92j(void)
1408 {
1409 struct sockaddr_in sin;
1410 char *ptr;
1411 int i, fd;
1412
1413 subtest = 10;
1414
1415 if ((ptr = mmap(NULL, PAGE_SIZE * 2, PROT_READ | PROT_WRITE,
1416 MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED) e(0);
1417
1418 if (munmap(&ptr[PAGE_SIZE], PAGE_SIZE) != 0) e(0);
1419
1420 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1421
1422 memset(&sin, 0, sizeof(sin));
1423 sin.sin_family = AF_INET;
1424 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1425
1426 if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) != 0) e(0);
1427
1428 memset(ptr, 'A', PAGE_SIZE);
1429
1430 if (sendto(fd, &ptr[PAGE_SIZE / 2], PAGE_SIZE, 0,
1431 (struct sockaddr *)&sin, sizeof(sin)) != -1) e(0);
1432 if (errno != EFAULT) e(0);
1433
1434 memset(ptr, 'B', PAGE_SIZE);
1435
1436 if (sendto(fd, ptr, PAGE_SIZE - sizeof(struct ip), 0,
1437 (struct sockaddr *)&sin, sizeof(sin)) !=
1438 PAGE_SIZE - sizeof(struct ip)) e(0);
1439
1440 memset(ptr, 0, PAGE_SIZE);
1441
1442 if (recvfrom(fd, &ptr[PAGE_SIZE / 2], PAGE_SIZE, 0, NULL, 0) != -1)
1443 e(0);
1444 if (errno != EFAULT) e(0);
1445
1446 if (recvfrom(fd, ptr, PAGE_SIZE * 2, 0, NULL, 0) != PAGE_SIZE) e(0);
1447 for (i = sizeof(struct ip); i < PAGE_SIZE; i++)
1448 if (ptr[i] != 'B') e(0);
1449
1450 if (close(fd) != 0) e(0);
1451
1452 if (munmap(ptr, PAGE_SIZE) != 0) e(0);
1453 }
1454
1455 /*
1456 * Test basic sysctl(2) socket enumeration support.
1457 */
1458 static void
test92k(void)1459 test92k(void)
1460 {
1461 struct kinfo_pcb ki;
1462 struct sockaddr_in lsin, rsin;
1463 struct sockaddr_in6 lsin6, rsin6;
1464 int fd, fd2, val;
1465
1466 subtest = 11;
1467
1468 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1469 &ki) != 0) e(0);
1470
1471 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1472
1473 memset(&lsin, 0, sizeof(lsin));
1474 lsin.sin_len = sizeof(lsin);
1475 lsin.sin_family = AF_INET;
1476
1477 memset(&rsin, 0, sizeof(rsin));
1478 rsin.sin_len = sizeof(rsin);
1479 rsin.sin_family = AF_INET;
1480
1481 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1482 &ki) != 1) e(0);
1483 if (ki.ki_type != SOCK_RAW) e(0);
1484 if (ki.ki_tstate != 0) e(0);
1485 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0);
1486 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0);
1487 if (ki.ki_sndq != 0) e(0);
1488 if (ki.ki_rcvq != 0) e(0);
1489
1490 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1491 &ki) != 0) e(0);
1492
1493 lsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1494
1495 if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) != 0) e(0);
1496
1497 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1498 &ki) != 1) e(0);
1499 if (ki.ki_type != SOCK_RAW) e(0);
1500 if (ki.ki_tstate != 0) e(0);
1501 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0);
1502 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0);
1503 if (ki.ki_sndq != 0) e(0);
1504 if (ki.ki_rcvq != 0) e(0);
1505 if (ki.ki_pflags & INP_HDRINCL) e(0);
1506
1507 rsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1508 if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) != 0) e(0);
1509
1510 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1511 &ki) != 1) e(0);
1512 if (ki.ki_type != SOCK_RAW) e(0);
1513 if (ki.ki_tstate != 0) e(0);
1514 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0);
1515 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0);
1516 if (ki.ki_sndq != 0) e(0);
1517 if (ki.ki_rcvq != 0) e(0);
1518
1519 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1520
1521 if (sendto(fd2, "ABC", 3, 0, (struct sockaddr *)&lsin,
1522 sizeof(lsin)) != 3) e(0);
1523
1524 if (close(fd2) != 0) e(0);
1525
1526 val = 1;
1527 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0)
1528 e(0);
1529
1530 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1531 &ki) != 1) e(0);
1532 if (ki.ki_type != SOCK_RAW) e(0);
1533 if (ki.ki_tstate != 0) e(0);
1534 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0);
1535 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0);
1536 if (ki.ki_sndq != 0) e(0);
1537 if (ki.ki_rcvq < 3) e(0); /* size is rounded up */
1538 if (!(ki.ki_pflags & INP_HDRINCL)) e(0);
1539
1540 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1541 &ki) != 0) e(0);
1542
1543 if (close(fd) != 0) e(0);
1544
1545 /* Test IPv6 sockets as well. */
1546 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1547
1548 memset(&lsin6, 0, sizeof(lsin6));
1549 lsin6.sin6_len = sizeof(lsin6);
1550 lsin6.sin6_family = AF_INET6;
1551
1552 memset(&rsin6, 0, sizeof(rsin6));
1553 rsin6.sin6_len = sizeof(rsin6);
1554 rsin6.sin6_family = AF_INET6;
1555
1556 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1557 &ki) != 1) e(0);
1558 if (ki.ki_type != SOCK_RAW) e(0);
1559 if (ki.ki_tstate != 0) e(0);
1560 if (memcmp(&ki.ki_src, &lsin6, sizeof(lsin6)) != 0) e(0);
1561 if (memcmp(&ki.ki_dst, &rsin6, sizeof(rsin6)) != 0) e(0);
1562 if (ki.ki_sndq != 0) e(0);
1563 if (ki.ki_rcvq != 0) e(0);
1564
1565 memcpy(&lsin6.sin6_addr, &in6addr_loopback, sizeof(lsin6.sin6_addr));
1566 if (bind(fd, (struct sockaddr *)&lsin6, sizeof(lsin6)) != 0) e(0);
1567
1568 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1569 &ki) != 1) e(0);
1570 if (ki.ki_type != SOCK_RAW) e(0);
1571 if (ki.ki_tstate != 0) e(0);
1572 if (memcmp(&ki.ki_src, &lsin6, sizeof(lsin6)) != 0) e(0);
1573 if (memcmp(&ki.ki_dst, &rsin6, sizeof(rsin6)) != 0) e(0);
1574 if (ki.ki_sndq != 0) e(0);
1575 if (ki.ki_rcvq != 0) e(0);
1576 if (!(ki.ki_pflags & IN6P_IPV6_V6ONLY)) e(0);
1577
1578 memcpy(&rsin6.sin6_addr, &in6addr_loopback, sizeof(rsin6.sin6_addr));
1579 if (connect(fd, (struct sockaddr *)&rsin6, sizeof(rsin6)) != 0)
1580 e(0);
1581
1582 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1583 &ki) != 1) e(0);
1584 if (ki.ki_type != SOCK_RAW) e(0);
1585 if (ki.ki_tstate != 0) e(0);
1586 if (memcmp(&ki.ki_src, &lsin6, sizeof(lsin6)) != 0) e(0);
1587 if (memcmp(&ki.ki_dst, &rsin6, sizeof(rsin6)) != 0) e(0);
1588 if (ki.ki_sndq != 0) e(0);
1589 if (ki.ki_rcvq != 0) e(0);
1590 if (!(ki.ki_pflags & IN6P_IPV6_V6ONLY)) e(0);
1591
1592 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1593 &ki) != 0) e(0);
1594
1595 if (close(fd) != 0) e(0);
1596
1597 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1598 &ki) != 0) e(0);
1599 }
1600
1601 /*
1602 * Test local and remote IPv6 address handling. In particular, test scope IDs
1603 * and IPv4-mapped IPv6 addresses.
1604 */
1605 static void
test92l(void)1606 test92l(void)
1607 {
1608
1609 subtest = 12;
1610
1611 socklib_test_addrs(SOCK_RAW, TEST_PROTO);
1612 }
1613
1614 /*
1615 * Test setting and retrieving basic multicast transmission options.
1616 */
1617 static void
test92m(void)1618 test92m(void)
1619 {
1620
1621 subtest = 13;
1622
1623 socklib_multicast_tx_options(SOCK_RAW);
1624 }
1625
1626 /*
1627 * Test multicast support.
1628 */
1629 static void
test92n(void)1630 test92n(void)
1631 {
1632
1633 subtest = 14;
1634
1635 socklib_test_multicast(SOCK_RAW, TEST_PROTO);
1636 }
1637
1638 /*
1639 * Test small and large ICMP echo ("ping") packets. This test aims to confirm
1640 * expected behavior resulting from the LWIP service's memory pool policies:
1641 * lwIP should reply to ICMP echo requests that fit in a single 512-byte buffer
1642 * (including space for ethernet headers, even on loopback interfaces), but not
1643 * to requests exceeding a single buffer.
1644 */
1645 static void
test92o(void)1646 test92o(void)
1647 {
1648 struct sockaddr_in6 sin6;
1649 struct icmp6_hdr packet;
1650 char buf[512];
1651 int fd;
1652
1653 subtest = 15;
1654
1655 /* IPv6 only for now, for simplicity reasons. */
1656 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
1657
1658 memset(&sin6, 0, sizeof(sin6));
1659 sin6.sin6_family = AF_INET6;
1660 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
1661
1662 memset(&packet, 0, sizeof(packet));
1663 packet.icmp6_type = ICMP6_ECHO_REQUEST;
1664 packet.icmp6_code = 0;
1665 packet.icmp6_id = getpid();
1666 packet.icmp6_seq = 1;
1667
1668 memset(buf, 'A', sizeof(buf));
1669 memcpy(buf, &packet, sizeof(packet));
1670
1671 if (sendto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6,
1672 sizeof(sin6)) != sizeof(buf)) e(0);
1673
1674 packet.icmp6_seq = 2;
1675
1676 memset(buf, 'B', sizeof(buf));
1677 memcpy(buf, &packet, sizeof(packet));
1678
1679 if (sendto(fd, buf, sizeof(buf) - 100, 0, (struct sockaddr *)&sin6,
1680 sizeof(sin6)) != sizeof(buf) - 100) e(0);
1681
1682 do {
1683 memset(buf, '\0', sizeof(buf));
1684
1685 if (recv(fd, buf, sizeof(buf), 0) <= 0) e(0);
1686
1687 memcpy(&packet, buf, sizeof(packet));
1688 } while (packet.icmp6_type == ICMP6_ECHO_REQUEST);
1689
1690 if (packet.icmp6_type != ICMP6_ECHO_REPLY) e(0);
1691 if (packet.icmp6_code != 0) e(0);
1692 if (packet.icmp6_id != getpid()) e(0);
1693 if (packet.icmp6_seq != 2) e(0);
1694 if (buf[sizeof(buf) - 101] != 'B') e(0);
1695
1696 if (close(fd) != 0) e(0);
1697 }
1698
1699 /*
1700 * Test program for LWIP RAW sockets.
1701 */
1702 int
main(int argc,char ** argv)1703 main(int argc, char ** argv)
1704 {
1705 int i, m;
1706
1707 start(92);
1708
1709 if (argc == 2)
1710 m = atoi(argv[1]);
1711 else
1712 m = 0xFFFF;
1713
1714 for (i = 0; i < ITERATIONS; i++) {
1715 if (m & 0x0001) test92a();
1716 if (m & 0x0002) test92b();
1717 if (m & 0x0004) test92c();
1718 if (m & 0x0008) test92d();
1719 if (m & 0x0010) test92e();
1720 if (m & 0x0020) test92f();
1721 if (m & 0x0040) test92g();
1722 if (m & 0x0080) test92h();
1723 if (m & 0x0100) test92i();
1724 if (m & 0x0200) test92j();
1725 if (m & 0x0400) test92k();
1726 if (m & 0x0400) test92k();
1727 if (m & 0x0800) test92l();
1728 if (m & 0x1000) test92m();
1729 if (m & 0x2000) test92n();
1730 if (m & 0x4000) test92o();
1731 }
1732
1733 quit();
1734 /* NOTREACHED */
1735 }
1736