]>
git.saurik.com Git - apple/xnu.git/blob - tests/recvmsg_x_test.c
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 /* -*- compile-command: "xcrun --sdk iphoneos.internal make recvmsg_x_test" -*- */
32 #include <sys/errno.h>
33 #include <sys/fcntl.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
44 #include <darwintest.h>
45 #include <darwintest_utils.h>
48 #define BUFFERLEN 1000
50 T_GLOBAL_META(T_META_NAMESPACE("xnu.net"));
53 sendPackets(int s
, struct sockaddr
*dst
, unsigned int numMsg
, size_t bufferLen
)
56 struct msghdr msg
= {};
57 struct iovec vec
= {};
58 char *bytes
= calloc(1, bufferLen
);
60 err(EX_OSERR
, "calloc()");
64 vec
.iov_len
= bufferLen
;
66 msg
.msg_name
= (void *)dst
;
67 msg
.msg_namelen
= dst
->sa_len
;
72 for (unsigned int i
= 0; i
< numMsg
; i
++) {
74 T_QUIET
; T_EXPECT_POSIX_SUCCESS(n
= sendmsg(s
, &msg
, 0), "sendmsg()");
75 T_LOG("Sent %ld bytes\n", n
);
79 // Wait a bit to make sure the packets reach the receiver
82 T_LOG("Sent %ld packet\n", count
);
88 recvPackets_x(int s
, unsigned int numMsg
, size_t buflen
, socklen_t cmsgLen
)
90 struct msghdr_x
*msgList
;
91 struct sockaddr_in
*srcAddrs
;
96 T_QUIET
; T_ASSERT_NOTNULL(msgList
= calloc(numMsg
, sizeof(struct msghdr_x
)), "msgList calloc()");
97 T_QUIET
; T_ASSERT_NOTNULL(srcAddrs
= calloc(numMsg
, sizeof(struct sockaddr_in
)), "srcAddrs calloc()");
98 T_QUIET
; T_ASSERT_NOTNULL(vec
= calloc(numMsg
, sizeof(struct iovec
)), "vec calloc()");
99 T_QUIET
; T_ASSERT_NOTNULL(buffers
= calloc(numMsg
, buflen
), "buffers calloc()");
100 T_QUIET
; T_ASSERT_NOTNULL(cmsgBuf
= calloc(numMsg
, ALIGN(cmsgLen
)), "cmsgBuf calloc()");
105 * Wrap around when we've exhausted the list
107 if ((count
% numMsg
) == 0) {
108 for (unsigned int i
= 0; i
< numMsg
; i
++) {
109 struct msghdr_x
*msg
= &msgList
[i
];
110 msg
->msg_name
= &srcAddrs
[i
];
111 msg
->msg_namelen
= sizeof(srcAddrs
[i
]);
112 vec
[i
].iov_base
= buffers
+ (i
* buflen
);
113 vec
[i
].iov_len
= buflen
;
114 msg
->msg_iov
= &vec
[i
];
116 msg
->msg_control
= cmsgBuf
+ (i
* ALIGN(cmsgLen
));
117 msg
->msg_controllen
= cmsgLen
;
120 T_QUIET
; T_EXPECT_TRUE((uintptr_t)msg
->msg_control
% sizeof(uint32_t) == 0, NULL
);
124 ssize_t n
= recvmsg_x(s
, msgList
+ (count
% numMsg
), numMsg
- (count
% numMsg
), 0);
126 if (errno
== EINTR
) {
127 T_LOG("recvmsg_x(): %s", strerror(errno
));
130 if (errno
== EWOULDBLOCK
) {
131 T_LOG("recvmsg_x(): %s", strerror(errno
));
134 T_FAIL("recvmsg_x() failed: %s", strerror(errno
));
136 T_LOG("recvmsg_x returned %ld packets\n", n
);
138 for (unsigned int i
= count
; i
< count
+ (u_int
)n
; i
++) {
139 struct msghdr_x
*msg
= &msgList
[i
% numMsg
];
141 T_LOG("Received packet #%d %lu bytes with recvmsg_x(), msg_namelen = %u, msg_controllen = %d -> %d, msg_flags = 0x%x\n",
142 i
+ 1, msg
->msg_datalen
, msg
->msg_namelen
, cmsgLen
, msg
->msg_controllen
, msg
->msg_flags
);
144 struct cmsghdr
*cmsg
;
146 for (cmsg
= CMSG_FIRSTHDR(msg
); cmsg
; cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
147 T_QUIET
; T_EXPECT_TRUE((uintptr_t)cmsg
% sizeof(uint32_t) == 0, NULL
);
149 T_LOG("level = %d, type = %d, length = %d\n", cmsg
->cmsg_level
, cmsg
->cmsg_type
, cmsg
->cmsg_len
);
163 T_DECL(recvmsg_x_test
, "exercise revcmsg_x() with various parameter")
165 struct sockaddr_in addr
= {
166 .sin_len
= sizeof(addr
),
167 .sin_family
= AF_INET
,
168 .sin_addr
.s_addr
= htonl(0x7f000001),
173 T_QUIET
; T_EXPECT_POSIX_SUCCESS(recvSocket
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
), "socket()");
174 T_QUIET
; T_EXPECT_POSIX_SUCCESS(bind(recvSocket
, (const struct sockaddr
*)&addr
, sizeof(addr
)), "bind()");
176 socklen_t addrLen
= sizeof(addr
);
177 T_QUIET
; T_EXPECT_POSIX_SUCCESS(getsockname(recvSocket
, (struct sockaddr
*)&addr
, &addrLen
), "getsockname()");
180 T_QUIET
; T_EXPECT_POSIX_SUCCESS(setsockopt(recvSocket
, IPPROTO_IP
, IP_RECVPKTINFO
, (void *)&one
, sizeof(one
)), "setsockopt(IP_RECVPKTINFO)");
182 int flags
= fcntl(recvSocket
, F_GETFL
, 0);
183 T_QUIET
; T_EXPECT_POSIX_SUCCESS(fcntl(recvSocket
, F_SETFL
, flags
| O_NONBLOCK
), "fcntl()");
186 T_QUIET
; T_EXPECT_POSIX_SUCCESS(sendSocket
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
), "sendSocket socket()");
188 for (int dontTrunc
= 0; dontTrunc
<= 1; dontTrunc
++) {
189 T_QUIET
; T_EXPECT_POSIX_SUCCESS(setsockopt(recvSocket
, SOL_SOCKET
, SO_DONTTRUNC
, (void *)&dontTrunc
, sizeof(dontTrunc
)), "setsockopt(SO_DONTTRUNC)");
191 T_LOG("\n================= recvmsg_x() test =================\n");
192 sendPackets(sendSocket
, (struct sockaddr
*)&addr
, NMSGS
, BUFFERLEN
);
193 recvPackets_x(recvSocket
, NMSGS
, BUFFERLEN
, 50);
195 T_LOG("\n================= recvmsg_x() test =================\n");
196 sendPackets(sendSocket
, (struct sockaddr
*)&addr
, NMSGS
, BUFFERLEN
);
197 recvPackets_x(recvSocket
, NMSGS
, BUFFERLEN
* 2, 50);
199 T_LOG("\n================= recvmsg_x() test =================\n");
200 sendPackets(sendSocket
, (struct sockaddr
*)&addr
, NMSGS
, BUFFERLEN
);
201 recvPackets_x(recvSocket
, NMSGS
, BUFFERLEN
/ 2, 50);
203 T_LOG("\n================= recvmsg_x() test =================\n");
204 sendPackets(sendSocket
, (struct sockaddr
*)&addr
, NMSGS
, BUFFERLEN
);
205 recvPackets_x(recvSocket
, NMSGS
, BUFFERLEN
, 10);
207 T_LOG("\n================= recvmsg_x() test =================\n");
208 sendPackets(sendSocket
, (struct sockaddr
*)&addr
, NMSGS
, BUFFERLEN
);
209 recvPackets_x(recvSocket
, NMSGS
, BUFFERLEN
/ 2, 10);
215 T_LOG("\n================= PASS =================\n");