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. */
8 #include <sys/socket.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>
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
,
37 static const int raw_results
[][__arraycount(raw_states
)] = {
39 -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
,
40 -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
,
45 0, -EINVAL
, -EINVAL
, -EINVAL
,
54 -ENOTCONN
, -ENOTCONN
, -ENOTCONN
, -ENOTCONN
,
63 [C_GETSOCKOPT_ERR
] = {
84 -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
,
85 -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
, -EOPNOTSUPP
,
89 -EAGAIN
, 0, -EAGAIN
, 0,
90 -EAGAIN
, -EAGAIN
, 0, -EAGAIN
,
94 -EAGAIN
, 0, -EAGAIN
, 0,
95 -EAGAIN
, -EAGAIN
, 0, -EAGAIN
,
99 -EDESTADDRREQ
, -EDESTADDRREQ
, -EPIPE
, -EPIPE
,
100 -EDESTADDRREQ
, 1, 1, -EPIPE
,
104 1, 1, -EPIPE
, -EPIPE
,
123 [C_SETSOCKOPT_BC
] = {
128 [C_SETSOCKOPT_KA
] = {
138 [C_SETSOCKOPT_RA
] = {
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.
165 raw_sweep(int domain
, int type
, int protocol
, enum state state
,
168 struct sockaddr_in sinA
, sinB
;
169 struct sockaddr_in6 sin6A
, sin6B
;
170 struct sockaddr
*addrA
, *addrB
;
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
);
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);
209 if ((fd
= socket(domain
, type
| SOCK_NONBLOCK
,
210 protocol
)) < 0) e(0);
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;
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
)
234 if (connect(fd
, addrB
, addr_len
) != 0) e(0);
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;
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);
259 * Sweep test for socket calls versus socket states of RAW sockets.
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.
280 struct sockaddr_in sinA
, sinB
, sinC
;
281 struct sockaddr_in6 sin6A
, sin6B
, sin6C
;
284 uint8_t buf
[256], packet
[5];
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
));
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
));
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
));
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
));
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);
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
));
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
));
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.
413 struct sockaddr_in6 sin6
;
414 struct icmp6_hdr icmp6_hdr
;
415 uint8_t buf
[6], buf2
[6], *buf3
;
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. */
428 if (getsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
, &len
) != 0) e(0);
429 if (len
!= sizeof(val
)) e(0);
432 /* Test bad offsets. */
434 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
,
435 sizeof(val
)) != -1) e(0);
436 if (errno
!= EINVAL
) e(0);
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. */
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
));
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)
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. */
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.
481 if (sendto(fd
, buf
, 5, 0, (struct sockaddr
*)&sin6
, sizeof(sin6
)) != 5)
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.
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)
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)
503 if (sendto(fd
, buf
, 1, 0, (struct sockaddr
*)&sin6
, sizeof(sin6
)) != 1)
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);
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
526 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
,
527 sizeof(val
)) != 0) e(0);
530 if (getsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
, &len
) != 0) e(0);
531 if (len
!= sizeof(val
)) e(0);
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);
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);
555 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
,
556 sizeof(val
)) != 0) e(0);
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)
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);
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);
584 if (sendto(fd
, buf
, 4, 0, (struct sockaddr
*)&sin6
, sizeof(sin6
)) != 4)
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);
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);
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);
617 if (getsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
, &len
) != 0) e(0);
618 if (len
!= sizeof(val
)) e(0);
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
++) {
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;
653 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
,
654 sizeof(val
)) != -1) e(0);
655 if (errno
!= ENOPROTOOPT
) e(0);
658 if (getsockopt(fd
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
,
660 if (errno
!= ENOPROTOOPT
) e(0);
662 if (close(fd
) != 0) e(0);
667 * Test the ICMP6_FILTER socket option.
672 struct sockaddr_in6 sin6
;
673 struct sockaddr_in sin
;
674 struct icmp6_filter filter
;
675 struct icmp6_hdr packet
;
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)
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)
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)
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.
835 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
)) != 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
++) {
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;
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
,
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.
875 char buf
[sizeof(struct ip
) + sizeof(struct icmp6_hdr
)];
876 struct sockaddr_in sin
;
877 struct icmp6_hdr packet
;
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);
913 * Test the IP_HDRINCL socket option.
918 struct sockaddr_in sin
;
919 struct testpkt pkt
, pkt2
;
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;
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 */
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. */
952 if (getsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &val
, &len
) != 0) e(0);
953 if (len
!= sizeof(val
)) e(0);
957 if (setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &val
, sizeof(val
)) != 0)
961 if (getsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &val
, &len
) != 0) e(0);
962 if (len
!= sizeof(val
)) 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);
988 if (getsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &val
, &len
) != 0) e(0);
989 if (len
!= sizeof(val
)) 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);
1000 if (setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &val
, sizeof(val
)) != 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
++) {
1042 case 0: fd
= socket(AF_INET
, SOCK_DGRAM
, 0); break;
1043 case 1: fd
= socket(AF_INET6
, SOCK_RAW
, TEST_PROTO
); break;
1048 if (getsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &val
,
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.
1069 struct sockaddr_in sin
;
1070 struct sockaddr_in6 sin6
;
1071 char buf
[sizeof(struct ip
) + 1];
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.
1111 struct sockaddr_in sinA
, sinB
;
1112 struct sockaddr_in6 sin6A
, sin6B
;
1115 char buf
[sizeof(struct ip
) + 1];
1120 if ((fd
= socket(AF_INET
, SOCK_RAW
, TEST_PROTO
)) < 0) e(0);
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);
1145 if (recv(fd2
, buf
, sizeof(buf
), 0) != sizeof(struct ip
) + 1) e(0);
1146 if (buf
[sizeof(struct ip
)] != 'A') e(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);
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);
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);
1216 if (recv(fd2
, buf
, sizeof(buf
), 0) != 1) e(0);
1217 if (buf
[0] != 'D') e(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.
1234 struct sockaddr_in6 sin6
;
1239 int r
, fd
, fd2
, val
;
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);
1254 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &val
, sizeof(val
)) != 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.
1264 if (setsockopt(fd2
, SOL_SOCKET
, SO_SNDBUF
, &val
, sizeof(val
)) != 0)
1267 /* Find the largest possible packet size that can actually be sent. */
1268 for (i
= 0; i
< val
; i
+= sizeof(int)) {
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
)
1278 if (errno
!= EMSGSIZE
) e(0);
1281 if (val
!= 65535 - sizeof(struct ip6_hdr
)) e(0);
1283 memset(buf
, 0, val
);
1286 memset(&iov
, 0, sizeof(iov
));
1288 iov
.iov_len
= val
+ 1;
1289 memset(&msg
, 0, sizeof(msg
));
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)) {
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
)) !=
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
1309 memset(&iov
, 0, sizeof(iov
));
1312 memset(&msg
, 0, sizeof(msg
));
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
)) !=
1323 memset(&iov
, 0, sizeof(iov
));
1325 iov
.iov_len
= val
- 1;
1326 memset(&msg
, 0, sizeof(msg
));
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)) {
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
)) !=
1343 memset(&iov
, 0, sizeof(iov
));
1346 memset(&msg
, 0, sizeof(msg
));
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
1362 memset(&msg
, 0, sizeof(msg
));
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
++) {
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
);
1389 if (errno
!= EWOULDBLOCK
) e(0);
1392 if (r
!= sizeof(j
)) e(0);
1395 if (i
== 1025) e(0);
1397 if (close(fd2
) != 0) e(0);
1398 if (close(fd
) != 0) e(0);
1404 * Test sending and receiving with bad pointers.
1409 struct sockaddr_in sin
;
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)
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.
1461 struct kinfo_pcb ki
;
1462 struct sockaddr_in lsin
, rsin
;
1463 struct sockaddr_in6 lsin6
, rsin6
;
1468 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO
, 0, 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,
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,
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,
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,
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);
1527 if (setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &val
, sizeof(val
)) != 0)
1530 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO
, 0, 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,
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,
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,
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)
1582 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO
, 0, 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,
1595 if (close(fd
) != 0) e(0);
1597 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO
, 0, 0,
1602 * Test local and remote IPv6 address handling. In particular, test scope IDs
1603 * and IPv4-mapped IPv6 addresses.
1611 socklib_test_addrs(SOCK_RAW
, TEST_PROTO
);
1615 * Test setting and retrieving basic multicast transmission options.
1623 socklib_multicast_tx_options(SOCK_RAW
);
1627 * Test multicast support.
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.
1648 struct sockaddr_in6 sin6
;
1649 struct icmp6_hdr packet
;
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);
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
)
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();