Remove building with NOCRYPTO option
[minix.git] / minix / tests / test92.c
blobdf5c71d616d7cfe2dd189010462275e00abc23f4
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>
22 #include "common.h"
23 #include "socklib.h"
25 #define ITERATIONS 2
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 */
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,
37 static const int raw_results[][__arraycount(raw_states)] = {
38 [C_ACCEPT] = {
39 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
40 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
41 -EOPNOTSUPP,
43 [C_BIND] = {
44 0, 0, 0, 0,
45 0, -EINVAL, -EINVAL, -EINVAL,
46 -EINVAL,
48 [C_CONNECT] = {
49 0, 0, 0, 0,
50 0, 0, 0, 0,
53 [C_GETPEERNAME] = {
54 -ENOTCONN, -ENOTCONN, -ENOTCONN, -ENOTCONN,
55 -ENOTCONN, 0, 0, 0,
58 [C_GETSOCKNAME] = {
59 0, 0, 0, 0,
60 0, 0, 0, 0,
63 [C_GETSOCKOPT_ERR] = {
64 0, 0, 0, 0,
65 0, 0, 0, 0,
68 [C_GETSOCKOPT_KA] = {
69 0, 0, 0, 0,
70 0, 0, 0, 0,
73 [C_GETSOCKOPT_RB] = {
74 0, 0, 0, 0,
75 0, 0, 0, 0,
78 [C_IOCTL_NREAD] = {
79 0, 0, 0, 0,
80 0, 0, 0, 0,
83 [C_LISTEN] = {
84 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
85 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP,
86 -EOPNOTSUPP,
88 [C_RECV] = {
89 -EAGAIN, 0, -EAGAIN, 0,
90 -EAGAIN, -EAGAIN, 0, -EAGAIN,
93 [C_RECVFROM] = {
94 -EAGAIN, 0, -EAGAIN, 0,
95 -EAGAIN, -EAGAIN, 0, -EAGAIN,
98 [C_SEND] = {
99 -EDESTADDRREQ, -EDESTADDRREQ, -EPIPE, -EPIPE,
100 -EDESTADDRREQ, 1, 1, -EPIPE,
101 -EPIPE,
103 [C_SENDTO] = {
104 1, 1, -EPIPE, -EPIPE,
105 1, 1, 1, -EPIPE,
106 -EPIPE,
108 [C_SELECT_R] = {
109 0, 1, 0, 1,
110 0, 0, 1, 0,
113 [C_SELECT_W] = {
114 1, 1, 1, 1,
115 1, 1, 1, 1,
118 [C_SELECT_X] = {
119 0, 0, 0, 0,
120 0, 0, 0, 0,
123 [C_SETSOCKOPT_BC] = {
124 0, 0, 0, 0,
125 0, 0, 0, 0,
128 [C_SETSOCKOPT_KA] = {
129 0, 0, 0, 0,
130 0, 0, 0, 0,
133 [C_SETSOCKOPT_L] = {
134 0, 0, 0, 0,
135 0, 0, 0, 0,
138 [C_SETSOCKOPT_RA] = {
139 0, 0, 0, 0,
140 0, 0, 0, 0,
143 [C_SHUTDOWN_R] = {
144 0, 0, 0, 0,
145 0, 0, 0, 0,
148 [C_SHUTDOWN_RW] = {
149 0, 0, 0, 0,
150 0, 0, 0, 0,
153 [C_SHUTDOWN_W] = {
154 0, 0, 0, 0,
155 0, 0, 0, 0,
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.
164 static int
165 raw_sweep(int domain, int type, int protocol, enum state state,
166 enum call call)
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;
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);
179 memcpy(&sinB, &sinA, sizeof(sinB));
181 addrA = (struct sockaddr *)&sinA;
182 addrB = (struct sockaddr *)&sinB;
183 addr_len = sizeof(sinA);
184 } else {
185 assert(domain == AF_INET6);
187 memset(&sin6A, 0, sizeof(sin6A));
188 sin6A.sin6_family = domain;
189 memcpy(&sin6A.sin6_addr, &in6addr_loopback,
190 sizeof(sin6A.sin6_addr));
192 memcpy(&sin6B, &sin6A, sizeof(sin6B));
194 addrA = (struct sockaddr *)&sin6A;
195 addrB = (struct sockaddr *)&sin6B;
196 addr_len = sizeof(sin6A);
199 /* Create a bound remote socket. */
200 if ((fd2 = socket(domain, type | SOCK_NONBLOCK, protocol)) < 0) e(0);
202 if (bind(fd2, addrB, addr_len) != 0) e(0);
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);
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;
219 break;
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);
229 if (bind(fd, addrA, addr_len) != 0) e(0);
231 if (state == S_BOUND)
232 break;
234 if (connect(fd, addrB, addr_len) != 0) e(0);
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;
243 break;
245 default:
246 fd = -1;
247 e(0);
250 r = socklib_sweep_call(call, fd, addrA, addrB, addr_len);
252 if (close(fd) != 0) e(0);
253 if (fd2 != -1 && close(fd2) != 0) e(0);
255 return r;
259 * Sweep test for socket calls versus socket states of RAW sockets.
261 static void
262 test92a(void)
265 subtest = 1;
267 socklib_sweep(AF_INET, SOCK_RAW, TEST_PROTO, raw_states,
268 __arraycount(raw_states), (const int *)raw_results, raw_sweep);
270 socklib_sweep(AF_INET6, SOCK_RAW, TEST_PROTO, raw_states,
271 __arraycount(raw_states), (const int *)raw_results, raw_sweep);
275 * Basic I/O test for raw sockets.
277 static void
278 test92b(void)
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;
287 subtest = 2;
289 /* First test IPv4. */
290 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
292 memset(&sinA, 0, sizeof(sinA));
293 sinA.sin_family = AF_INET;
294 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
296 for (i = 0; i < __arraycount(packet); i++)
297 packet[i] = (uint8_t)(-i);
299 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sinA,
300 sizeof(sinA)) != sizeof(packet)) e(0);
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);
307 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0);
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);
316 * Test two additional things:
318 * 1) a non-zero port number is ignored when sending;
319 * 2) multiple raw sockets may receive the same packet.
321 sinA.sin_port = htons(22);
323 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
325 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sinA,
326 sizeof(sinA)) != sizeof(packet)) e(0);
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);
333 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0);
335 if (len != sizeof(sinC)) e(0);
336 if (memcmp(&sinB, &sinC, sizeof(sinB)) != 0) e(0);
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);
343 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0);
345 if (len != sizeof(sinC)) e(0);
346 if (memcmp(&sinB, &sinC, sizeof(sinB)) != 0) e(0);
348 if (close(fd2) != 0) e(0);
349 if (close(fd) != 0) e(0);
351 /* Then test IPv6. */
352 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
354 memset(&sin6A, 0, sizeof(sin6A));
355 sin6A.sin6_family = AF_INET6;
356 memcpy(&sin6A.sin6_addr, &in6addr_loopback, sizeof(sin6A.sin6_addr));
358 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sin6A,
359 sizeof(sin6A)) != sizeof(packet)) e(0);
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);
366 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0);
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);
375 /* As above. */
376 sin6A.sin6_port = htons(22);
378 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
380 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sin6A,
381 sizeof(sin6A)) != sizeof(packet)) e(0);
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);
388 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0);
390 if (len != sizeof(sin6C)) e(0);
391 if (memcmp(&sin6B, &sin6C, sizeof(sin6B)) != 0) e(0);
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);
398 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0);
400 if (len != sizeof(sin6C)) e(0);
401 if (memcmp(&sin6B, &sin6C, sizeof(sin6B)) != 0) e(0);
403 if (close(fd2) != 0) e(0);
404 if (close(fd) != 0) e(0);
408 * Test the IPV6_CHECKSUM socket option.
410 static void
411 test92c(void)
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;
420 subtest = 3;
422 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
424 if (shutdown(fd, SHUT_RD) != 0) e(0);
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);
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);
438 val = 1;
439 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
440 sizeof(val)) != -1) e(0);
441 if (errno != EINVAL) e(0);
443 /* Now test real checksum computation. */
444 val = 0;
445 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
446 sizeof(val)) != 0) e(0);
448 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
450 if (shutdown(fd2, SHUT_WR) != 0) e(0);
452 memset(buf, 0, sizeof(buf));
453 buf[2] = 0xfe;
454 buf[3] = 0x95;
455 buf[4] = 0x4d;
457 memset(&sin6, 0, sizeof(sin6));
458 sin6.sin6_family = AF_INET6;
459 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
461 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5)
462 e(0);
464 if (recv(fd2, buf2, sizeof(buf2), 0) != 5) e(0);
466 if (buf2[0] != 0xb3 || buf2[1] != 0x65) e(0);
467 if (memcmp(&buf2[2], &buf[2], 3) != 0) e(0);
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);
475 * The current value of the checksum field should not be incorporated
476 * in the checksum, as that would result in an invalid checksum.
478 buf[0] = 0xab;
479 buf[1] = 0xcd;
481 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5)
482 e(0);
484 if (recv(fd2, buf2, sizeof(buf2), 0) != 5) e(0);
486 if (buf2[0] != 0xb3 || buf2[1] != 0x65) e(0);
487 if (memcmp(&buf2[2], &buf[2], 3) != 0) e(0);
490 * Turn off checksum computation on the sending side, so that the
491 * packet ends up being dropped on the receiving side.
493 val = -1;
494 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
495 sizeof(val)) != 0) e(0);
497 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5)
498 e(0);
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);
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.
510 if (recv(fd2, buf2, sizeof(buf2), MSG_DONTWAIT) != -1) e(0);
511 if (errno != EWOULDBLOCK) e(0);
513 buf[0] = 0;
514 buf[1] = 0x67;
515 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6,
516 sizeof(sin6)) != 4) e(0);
518 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0);
519 if (memcmp(buf, buf2, 4) != 0) e(0);
522 * We repeat some of the tests with a non-zero checksum offset, just to
523 * be sure.
525 val = 2;
526 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
527 sizeof(val)) != 0) e(0);
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);
534 buf[0] = 0x56;
535 buf[1] = 0x78;
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);
543 val = 2;
544 if (setsockopt(fd2, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
545 sizeof(val)) != 0) e(0);
547 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6,
548 sizeof(sin6)) != 4) e(0);
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);
554 val = -1;
555 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
556 sizeof(val)) != 0) e(0);
558 buf[2] = 0xa8;
559 buf[3] = 0x85; /* deliberately bad checksum */
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);
567 buf[3] = 0x84; /* good checksum */
568 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 4)
569 e(0);
571 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0);
572 if (memcmp(buf, buf2, 4) != 0) e(0);
574 if (recv(fd2, buf2, sizeof(buf2), MSG_DONTWAIT) != -1) e(0);
575 if (errno != EWOULDBLOCK) e(0);
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);
583 buf[3] = 0x85;
584 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 4)
585 e(0);
587 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0);
588 if (memcmp(buf, buf2, 4) != 0) e(0);
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.
598 if ((buf3 = malloc(4096)) == NULL) e(0);
600 val = 4094;
601 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
602 sizeof(val)) != 0) e(0);
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);
608 free(buf3);
610 if (close(fd2) != 0) e(0);
611 if (close(fd) != 0) e(0);
613 /* For ICMPv6 packets, checksumming is always enabled. */
614 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
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);
621 val = -1;
622 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
623 sizeof(val)) != -1) e(0);
624 if (errno != EINVAL) e(0);
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);
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);
635 if (recv(fd, &icmp6_hdr, sizeof(icmp6_hdr), 0) != len) e(0);
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);
641 if (close(fd) != 0) e(0);
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;
650 if (fd < 0) e(0);
652 val = -1;
653 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
654 sizeof(val)) != -1) e(0);
655 if (errno != ENOPROTOOPT) e(0);
657 len = sizeof(val);
658 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val,
659 &len) != -1) e(0);
660 if (errno != ENOPROTOOPT) e(0);
662 if (close(fd) != 0) e(0);
667 * Test the ICMP6_FILTER socket option.
669 static void
670 test92d(void)
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;
681 subtest = 4;
684 * We use two different sockets to eliminate the possibility that the
685 * filter is also applied when sending packets--it should not be.
687 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
689 if (shutdown(fd, SHUT_WR) != 0) e(0);
691 len = sizeof(filter);
692 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0)
693 e(0);
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);
699 if ((fd2 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
701 ICMP6_FILTER_SETBLOCKALL(&filter);
702 if (setsockopt(fd2, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
703 sizeof(filter)) != 0) e(0);
705 len = sizeof(filter);
706 if (getsockopt(fd2, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0)
707 e(0);
709 for (i = 0; i <= UINT8_MAX; i++)
710 if (ICMP6_FILTER_WILLPASS(i, &filter)) e(0);
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);
717 memset(&sin6, 0, sizeof(sin6));
718 sin6.sin6_family = AF_INET6;
719 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
721 memset(&packet, 0, sizeof(packet));
722 packet.icmp6_type = TEST_ICMPV6_TYPE_A;
723 packet.icmp6_code = 12;
725 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
726 sizeof(sin6)) != sizeof(packet)) e(0);
728 packet.icmp6_type = TEST_ICMPV6_TYPE_B;
729 packet.icmp6_code = 34;
731 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
732 sizeof(sin6)) != sizeof(packet)) e(0);
734 memset(&packet, 0, sizeof(packet));
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);
740 if (recv(fd, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0);
741 if (errno != EWOULDBLOCK) e(0);
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);
748 memset(&packet, 0, sizeof(packet));
749 packet.icmp6_type = TEST_ICMPV6_TYPE_B;
750 packet.icmp6_code = 56;
752 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
753 sizeof(sin6)) != sizeof(packet)) e(0);
755 packet.icmp6_type = TEST_ICMPV6_TYPE_A;
756 packet.icmp6_code = 78;
758 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
759 sizeof(sin6)) != sizeof(packet)) e(0);
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.
772 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, NULL, 0) != 0) e(0);
774 packet.icmp6_type = TEST_ICMPV6_TYPE_B;
775 packet.icmp6_code = 90;
777 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6,
778 sizeof(sin6)) != sizeof(packet)) e(0);
780 memset(&packet, 0, sizeof(packet));
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);
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);
790 if (recv(fd, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0);
791 if (errno != EWOULDBLOCK) e(0);
793 if (recv(fd2, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0);
794 if (errno != EWOULDBLOCK) e(0);
796 len = sizeof(filter);
797 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0)
798 e(0);
800 for (i = 0; i <= UINT8_MAX; i++)
801 if (!ICMP6_FILTER_WILLPASS(i, &filter)) e(0);
803 if (close(fd2) != 0) e(0);
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.
811 if ((fd2 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
813 ICMP6_FILTER_SETBLOCKALL(&filter);
814 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
815 sizeof(filter)) != 0) e(0);
817 memset(&sin, 0, sizeof(sin));
818 sin.sin_family = AF_INET;
819 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
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 */
826 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin,
827 sizeof(sin)) != sizeof(packet)) e(0);
830 * If the packet were to arrive at all, it should arrive instantly, so
831 * this is just an excuse to use SO_RCVTIMEO.
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);
838 if (recv(fd, &packet, sizeof(packet), 0) != -1) e(0);
839 if (errno != EWOULDBLOCK) e(0);
841 if (close(fd2) != 0) e(0);
843 if (close(fd) != 0) e(0);
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;
852 if (fd < 0) e(0);
854 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
855 sizeof(filter)) != -1) e(0);
856 if (errno != ENOPROTOOPT) e(0);
858 len = sizeof(filter);
859 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
860 &len) != -1) e(0);
861 if (errno != ENOPROTOOPT) e(0);
863 if (close(fd) != 0) e(0);
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.
872 static void
873 test92e(void)
875 char buf[sizeof(struct ip) + sizeof(struct icmp6_hdr)];
876 struct sockaddr_in sin;
877 struct icmp6_hdr packet;
878 int fd;
880 subtest = 5;
882 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
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);
889 memset(&sin, 0, sizeof(sin));
890 sin.sin_family = AF_INET;
891 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
893 if (sendto(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&sin,
894 sizeof(sin)) != sizeof(packet)) e(0);
896 if (recv(fd, buf, sizeof(buf), 0) != sizeof(buf)) e(0);
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);
903 if (close(fd) != 0) e(0);
906 struct testpkt {
907 struct ip ip;
908 struct udphdr udp;
909 uint8_t data[6];
910 } __packed;
913 * Test the IP_HDRINCL socket option.
915 static void
916 test92f(void)
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;
925 subtest = 6;
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));
946 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) e(0);
948 if (shutdown(fd, SHUT_RD) != 0) e(0);
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);
956 val = 1;
957 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0)
958 e(0);
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);
965 if ((fd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) e(0);
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);
972 if (bind(fd2, (struct sockaddr *)&sin, sizeof(sin)) != 0) e(0);
974 sin.sin_port = htons(0);
976 if (sendto(fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sin,
977 sizeof(sin)) != sizeof(pkt)) e(0);
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);
982 if (close(fd2) != 0) e(0);
983 if (close(fd) != 0) e(0);
985 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
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);
992 if (shutdown(fd, SHUT_RD) != 0) e(0);
994 /* See if we can receive a packet for our own protocol. */
995 pkt.ip.ip_p = TEST_PROTO;
997 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
999 val = 1;
1000 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0)
1001 e(0);
1003 if (sendto(fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sin,
1004 sizeof(sin)) != sizeof(pkt)) e(0);
1006 if (recv(fd2, &pkt2, sizeof(pkt2), 0) != sizeof(pkt2)) e(0);
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);
1021 * Test sending packets with weird sizes to ensure that we do not crash
1022 * the service. These packets would never arrive anyway.
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);
1033 if (recv(fd2, &pkt2, sizeof(pkt2), MSG_DONTWAIT) != -1) e(0);
1034 if (errno != EWOULDBLOCK) e(0);
1036 if (close(fd2) != 0) e(0);
1037 if (close(fd) != 0) e(0);
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;
1045 if (fd < 0) e(0);
1047 len = sizeof(val);
1048 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val,
1049 &len) != -1) e(0);
1050 if (errno != ENOPROTOOPT) e(0);
1052 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val,
1053 sizeof(val)) != -1) e(0);
1054 if (errno != ENOPROTOOPT) e(0);
1056 if (close(fd) != 0) e(0);
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.
1066 static void
1067 test92g(void)
1069 struct sockaddr_in sin;
1070 struct sockaddr_in6 sin6;
1071 char buf[sizeof(struct ip) + 1];
1072 int fd;
1074 subtest = 7;
1076 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) e(0);
1078 memset(&sin, 0, sizeof(sin));
1079 sin.sin_family = AF_INET;
1080 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1082 if (sendto(fd, "A", 1, 0, (struct sockaddr *)&sin,
1083 sizeof(sin)) != 1) e(0);
1085 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != sizeof(buf)) e(0);
1086 if (buf[sizeof(struct ip)] != 'A') e(0);
1088 if (close(fd) != 0) e(0);
1090 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)) < 0) e(0);
1092 memset(&sin6, 0, sizeof(sin6));
1093 sin6.sin6_family = AF_INET6;
1094 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
1096 if (sendto(fd, "B", 1, 0, (struct sockaddr *)&sin6,
1097 sizeof(sin6)) != 1) e(0);
1099 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != 1) e(0);
1100 if (buf[0] != 'B') e(0);
1102 if (close(fd) != 0) e(0);
1106 * Test that connected raw sockets perform correct source-based filtering.
1108 static void
1109 test92h(void)
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;
1118 subtest = 8;
1120 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1122 len = sizeof(sinB);
1123 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != -1) e(0);
1124 if (errno != ENOTCONN) e(0);
1126 memset(&sinA, 0, sizeof(sinA));
1127 sinA.sin_family = AF_INET;
1128 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
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.
1135 if (connect(fd, (struct sockaddr *)&sinA, sizeof(sinA)) != 0) e(0);
1137 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != 0) e(0);
1139 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1141 if (sendto(fd2, "A", 1, 0, (struct sockaddr *)&sinA,
1142 sizeof(sinA)) != 1) e(0);
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);
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);
1153 memset(&sa, 0, sizeof(sa));
1154 sa.sa_family = AF_UNSPEC;
1156 sinA.sin_addr.s_addr = htonl(INADDR_NONE);
1158 /* While here, test unconnecting the socket. */
1159 if (connect(fd, &sa, sizeof(sa)) != 0) e(0);
1161 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != -1) e(0);
1162 if (errno != ENOTCONN) e(0);
1164 /* Then test that packets with the wrong source are ignored. */
1165 if (connect(fd, (struct sockaddr *)&sinA, sizeof(sinA)) != 0) e(0);
1167 if (sendto(fd2, "B", 1, 0, (struct sockaddr *)&sinB,
1168 sizeof(sinB)) != 1) e(0);
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);
1174 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != -1) e(0);
1175 if (errno != EWOULDBLOCK) e(0);
1177 if (close(fd2) != 0) e(0);
1178 if (close(fd) != 0) e(0);
1180 /* Repeat for IPv6, but now the other way around. */
1181 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1183 len = sizeof(sin6B);
1184 if (getpeername(fd, (struct sockaddr *)&sin6B, &len) != -1) e(0);
1185 if (errno != ENOTCONN) e(0);
1187 memset(&sin6A, 0, sizeof(sin6A));
1188 sin6A.sin6_family = AF_INET6;
1189 memcpy(&sin6A.sin6_addr, &in6addr_loopback, sizeof(sin6A.sin6_addr));
1191 memcpy(&sin6B, &sin6A, sizeof(sin6B));
1192 if (inet_pton(AF_INET6, "::2", &sin6B.sin6_addr) != 1) e(0);
1194 if (connect(fd, (struct sockaddr *)&sin6B, sizeof(sin6B)) != 0) e(0);
1196 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1198 if (sendto(fd2, "C", 1, 0, (struct sockaddr *)&sin6A,
1199 sizeof(sin6A)) != 1) e(0);
1201 buf[0] = '\0';
1202 if (recv(fd2, buf, sizeof(buf), 0) != 1) e(0);
1203 if (buf[0] != 'C') e(0);
1205 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != -1) e(0);
1206 if (errno != EWOULDBLOCK) e(0);
1208 if (connect(fd, &sa, sizeof(sa)) != 0) e(0);
1210 if (connect(fd, (struct sockaddr *)&sin6A, sizeof(sin6A)) != 0) e(0);
1212 if (sendto(fd2, "D", 1, 0, (struct sockaddr *)&sin6A,
1213 sizeof(sin6A)) != 1) e(0);
1215 buf[0] = '\0';
1216 if (recv(fd2, buf, sizeof(buf), 0) != 1) e(0);
1217 if (buf[0] != 'D') e(0);
1219 buf[0] = '\0';
1220 if (recv(fd, buf, sizeof(buf), 0) != 1) e(0);
1221 if (buf[0] != 'D') e(0);
1223 if (close(fd2) != 0) e(0);
1224 if (close(fd) != 0) e(0);
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.
1231 static void
1232 test92i(void)
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;
1241 subtest = 9;
1243 if ((buf = malloc(65536)) == NULL) e(0);
1245 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1247 memset(&sin6, 0, sizeof(sin6));
1248 sin6.sin6_family = AF_INET6;
1249 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
1251 if (bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) != 0) e(0);
1253 val = 65536;
1254 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0)
1255 e(0);
1257 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
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.
1263 val = 65535;
1264 if (setsockopt(fd2, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0)
1265 e(0);
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));
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);
1281 if (val != 65535 - sizeof(struct ip6_hdr)) e(0);
1283 memset(buf, 0, val);
1284 buf[val] = 'X';
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);
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);
1299 if (buf[val] != 'X') e(0);
1301 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) !=
1302 val) e(0);
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.
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);
1318 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) !=
1319 val) e(0);
1321 buf[val - 1] = 'Y';
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);
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);
1336 if (buf[val - 1] != 'Y') e(0);
1338 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) !=
1339 val) e(0);
1341 buf[0] = 'Z';
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);
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);
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.
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);
1369 if (recv(fd, buf, val, MSG_DONTWAIT) != -1) e(0);
1370 if (errno != EWOULDBLOCK) e(0);
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.
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);
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;
1392 if (r != sizeof(j)) e(0);
1393 if (i != j) e(0);
1395 if (i == 1025) e(0);
1397 if (close(fd2) != 0) e(0);
1398 if (close(fd) != 0) e(0);
1400 free(buf);
1404 * Test sending and receiving with bad pointers.
1406 static void
1407 test92j(void)
1409 struct sockaddr_in sin;
1410 char *ptr;
1411 int i, fd;
1413 subtest = 10;
1415 if ((ptr = mmap(NULL, PAGE_SIZE * 2, PROT_READ | PROT_WRITE,
1416 MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED) e(0);
1418 if (munmap(&ptr[PAGE_SIZE], PAGE_SIZE) != 0) e(0);
1420 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1422 memset(&sin, 0, sizeof(sin));
1423 sin.sin_family = AF_INET;
1424 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1426 if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) != 0) e(0);
1428 memset(ptr, 'A', PAGE_SIZE);
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);
1434 memset(ptr, 'B', PAGE_SIZE);
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);
1440 memset(ptr, 0, PAGE_SIZE);
1442 if (recvfrom(fd, &ptr[PAGE_SIZE / 2], PAGE_SIZE, 0, NULL, 0) != -1)
1443 e(0);
1444 if (errno != EFAULT) e(0);
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);
1450 if (close(fd) != 0) e(0);
1452 if (munmap(ptr, PAGE_SIZE) != 0) e(0);
1456 * Test basic sysctl(2) socket enumeration support.
1458 static void
1459 test92k(void)
1461 struct kinfo_pcb ki;
1462 struct sockaddr_in lsin, rsin;
1463 struct sockaddr_in6 lsin6, rsin6;
1464 int fd, fd2, val;
1466 subtest = 11;
1468 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1469 &ki) != 0) e(0);
1471 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1473 memset(&lsin, 0, sizeof(lsin));
1474 lsin.sin_len = sizeof(lsin);
1475 lsin.sin_family = AF_INET;
1477 memset(&rsin, 0, sizeof(rsin));
1478 rsin.sin_len = sizeof(rsin);
1479 rsin.sin_family = AF_INET;
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);
1490 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1491 &ki) != 0) e(0);
1493 lsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1495 if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) != 0) e(0);
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);
1507 rsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1508 if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) != 0) e(0);
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);
1519 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1521 if (sendto(fd2, "ABC", 3, 0, (struct sockaddr *)&lsin,
1522 sizeof(lsin)) != 3) e(0);
1524 if (close(fd2) != 0) e(0);
1526 val = 1;
1527 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0)
1528 e(0);
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);
1540 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1541 &ki) != 0) e(0);
1543 if (close(fd) != 0) e(0);
1545 /* Test IPv6 sockets as well. */
1546 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0);
1548 memset(&lsin6, 0, sizeof(lsin6));
1549 lsin6.sin6_len = sizeof(lsin6);
1550 lsin6.sin6_family = AF_INET6;
1552 memset(&rsin6, 0, sizeof(rsin6));
1553 rsin6.sin6_len = sizeof(rsin6);
1554 rsin6.sin6_family = AF_INET6;
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);
1565 memcpy(&lsin6.sin6_addr, &in6addr_loopback, sizeof(lsin6.sin6_addr));
1566 if (bind(fd, (struct sockaddr *)&lsin6, sizeof(lsin6)) != 0) e(0);
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);
1578 memcpy(&rsin6.sin6_addr, &in6addr_loopback, sizeof(rsin6.sin6_addr));
1579 if (connect(fd, (struct sockaddr *)&rsin6, sizeof(rsin6)) != 0)
1580 e(0);
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);
1592 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0,
1593 &ki) != 0) e(0);
1595 if (close(fd) != 0) e(0);
1597 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0,
1598 &ki) != 0) e(0);
1602 * Test local and remote IPv6 address handling. In particular, test scope IDs
1603 * and IPv4-mapped IPv6 addresses.
1605 static void
1606 test92l(void)
1609 subtest = 12;
1611 socklib_test_addrs(SOCK_RAW, TEST_PROTO);
1615 * Test setting and retrieving basic multicast transmission options.
1617 static void
1618 test92m(void)
1621 subtest = 13;
1623 socklib_multicast_tx_options(SOCK_RAW);
1627 * Test multicast support.
1629 static void
1630 test92n(void)
1633 subtest = 14;
1635 socklib_test_multicast(SOCK_RAW, TEST_PROTO);
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.
1645 static void
1646 test92o(void)
1648 struct sockaddr_in6 sin6;
1649 struct icmp6_hdr packet;
1650 char buf[512];
1651 int fd;
1653 subtest = 15;
1655 /* IPv6 only for now, for simplicity reasons. */
1656 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0);
1658 memset(&sin6, 0, sizeof(sin6));
1659 sin6.sin6_family = AF_INET6;
1660 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr));
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;
1668 memset(buf, 'A', sizeof(buf));
1669 memcpy(buf, &packet, sizeof(packet));
1671 if (sendto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6,
1672 sizeof(sin6)) != sizeof(buf)) e(0);
1674 packet.icmp6_seq = 2;
1676 memset(buf, 'B', sizeof(buf));
1677 memcpy(buf, &packet, sizeof(packet));
1679 if (sendto(fd, buf, sizeof(buf) - 100, 0, (struct sockaddr *)&sin6,
1680 sizeof(sin6)) != sizeof(buf) - 100) e(0);
1682 do {
1683 memset(buf, '\0', sizeof(buf));
1685 if (recv(fd, buf, sizeof(buf), 0) <= 0) e(0);
1687 memcpy(&packet, buf, sizeof(packet));
1688 } while (packet.icmp6_type == ICMP6_ECHO_REQUEST);
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);
1696 if (close(fd) != 0) e(0);
1700 * Test program for LWIP RAW sockets.
1703 main(int argc, char ** argv)
1705 int i, m;
1707 start(92);
1709 if (argc == 2)
1710 m = atoi(argv[1]);
1711 else
1712 m = 0xFFFF;
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();
1733 quit();
1734 /* NOTREACHED */