swrap: don't read the callers msg_control buffer in swrap_recvmsg_before_unix()
[socket_wrapper.git] / tests / test_echo_udp_sendmsg_recvmsg.c
1 #include <stdarg.h>
2 #include <stddef.h>
3 #include <setjmp.h>
4 #include <cmocka.h>
5
6 #include "config.h"
7 #include "torture.h"
8
9 #include <errno.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <unistd.h>
17
18 static int setup_echo_srv_udp_ipv4(void **state)
19 {
20         torture_setup_echo_srv_udp_ipv4(state);
21
22         return 0;
23 }
24
25 #ifdef HAVE_IPV6
26 static int setup_echo_srv_udp_ipv6(void **state)
27 {
28         torture_setup_echo_srv_udp_ipv6(state);
29
30         return 0;
31 }
32 #endif
33
34 static int teardown(void **state)
35 {
36         torture_teardown_echo_srv(state);
37
38         return 0;
39 }
40
41 static void test_sendmsg_recvmsg_ipv4(void **state)
42 {
43         struct torture_address addr = {
44                 .sa_socklen = sizeof(struct sockaddr_in),
45         };
46         char send_buf[64] = {0};
47         char recv_buf[64] = {0};
48         ssize_t ret;
49         int rc;
50         int i;
51         int s;
52
53         (void) state; /* unused */
54
55         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
56         assert_int_not_equal(s, -1);
57
58         addr.sa.in.sin_family = AF_INET;
59         addr.sa.in.sin_port = htons(torture_server_port());
60
61         rc = inet_pton(AF_INET,
62                        torture_server_address(AF_INET),
63                        &addr.sa.in.sin_addr);
64         assert_int_equal(rc, 1);
65
66         for (i = 0; i < 10; i++) {
67                 char ip[INET_ADDRSTRLEN] = {0};
68                 const char *a;
69                 struct torture_address srv_in = {
70                         .sa_socklen = sizeof(struct sockaddr_in),
71                 };
72                 struct msghdr s_msg;
73                 struct msghdr r_msg;
74                 struct iovec s_iov;
75                 struct iovec r_iov;
76
77                 snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
78
79                 ZERO_STRUCT(s_msg);
80
81                 s_msg.msg_name = &addr.sa.s;
82                 s_msg.msg_namelen = addr.sa_socklen;
83
84                 s_iov.iov_base = send_buf;
85                 s_iov.iov_len = sizeof(send_buf);
86
87                 s_msg.msg_iov = &s_iov;
88                 s_msg.msg_iovlen = 1;
89
90                 ret = sendmsg(s, &s_msg, 0);
91                 assert_int_not_equal(ret, -1);
92
93                 ZERO_STRUCT(r_msg);
94
95                 r_msg.msg_name = &srv_in.sa.s;
96                 r_msg.msg_namelen = srv_in.sa_socklen;
97
98                 r_iov.iov_base = recv_buf;
99                 r_iov.iov_len = sizeof(recv_buf);
100
101                 r_msg.msg_iov = &r_iov;
102                 r_msg.msg_iovlen = 1;
103
104                 ret = recvmsg(s, &r_msg, 0);
105                 assert_int_not_equal(ret, -1);
106
107                 assert_int_equal(r_msg.msg_namelen, sizeof(struct sockaddr_in));
108
109                 a = inet_ntop(AF_INET, &srv_in.sa.in.sin_addr, ip, sizeof(ip));
110                 assert_non_null(a);
111                 assert_string_equal(a, torture_server_address(AF_INET));
112
113                 assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
114         }
115
116         close(s);
117 }
118
119 #ifdef HAVE_IPV6
120 static void test_sendmsg_recvmsg_ipv6(void **state)
121 {
122         struct torture_address addr = {
123                 .sa_socklen = sizeof(struct sockaddr_in6),
124         };
125         char send_buf[64] = {0};
126         char recv_buf[64] = {0};
127         ssize_t ret;
128         int rc;
129         int i;
130         int s;
131
132         (void) state; /* unused */
133
134         s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
135         assert_int_not_equal(s, -1);
136
137         addr.sa.in6.sin6_family = AF_INET6;
138         addr.sa.in6.sin6_port = htons(torture_server_port());
139
140         rc = inet_pton(AF_INET6,
141                        torture_server_address(AF_INET6),
142                        &addr.sa.in6.sin6_addr);
143         assert_int_equal(rc, 1);
144
145         for (i = 0; i < 10; i++) {
146                 char ip[INET6_ADDRSTRLEN] = {0};
147                 const char *a;
148                 struct torture_address srv_in6 = {
149                         .sa_socklen = sizeof(struct sockaddr_in6),
150                 };
151                 struct msghdr s_msg;
152                 struct msghdr r_msg;
153                 struct iovec s_iov;
154                 struct iovec r_iov;
155
156                 snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
157
158                 ZERO_STRUCT(s_msg);
159
160                 s_msg.msg_name = &addr.sa.s;
161                 s_msg.msg_namelen = addr.sa_socklen;
162
163                 s_iov.iov_base = send_buf;
164                 s_iov.iov_len = sizeof(send_buf);
165
166                 s_msg.msg_iov = &s_iov;
167                 s_msg.msg_iovlen = 1;
168
169                 ret = sendmsg(s, &s_msg, 0);
170                 assert_int_not_equal(ret, -1);
171
172                 ZERO_STRUCT(r_msg);
173                 r_msg.msg_name = &srv_in6.sa.s;
174                 r_msg.msg_namelen = srv_in6.sa_socklen;
175
176                 r_iov.iov_base = recv_buf;
177                 r_iov.iov_len = sizeof(recv_buf);
178
179                 r_msg.msg_iov = &r_iov;
180                 r_msg.msg_iovlen = 1;
181
182                 ret = recvmsg(s, &r_msg, 0);
183                 assert_int_not_equal(ret, -1);
184
185                 assert_int_equal(r_msg.msg_namelen, sizeof(struct sockaddr_in6));
186
187                 a = inet_ntop(AF_INET6, &srv_in6.sa.in6.sin6_addr, ip, sizeof(ip));
188                 assert_non_null(a);
189                 assert_string_equal(a, torture_server_address(AF_INET6));
190
191                 assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
192         }
193
194         close(s);
195 }
196 #endif
197
198 static void test_sendmsg_recvmsg_ipv4_connected(void **state)
199 {
200         struct torture_address send_addr = {
201                 .sa_socklen = sizeof(struct sockaddr_storage),
202         };
203         struct torture_address r_addr = {
204                 .sa_socklen = sizeof(struct sockaddr_storage),
205         };
206         struct msghdr s_msg = {
207                 .msg_namelen = 0,
208         };
209         struct msghdr r_msg = {
210                 .msg_namelen = 0,
211         };
212         struct iovec iov;
213         char ip[INET_ADDRSTRLEN] = {0};
214         char payload[] = "PACKET";
215         const char *a;
216         ssize_t ret;
217         int rc;
218         int s;
219
220         (void)state; /* unused */
221
222         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
223         assert_int_not_equal(s, -1);
224
225         send_addr.sa.in.sin_family = AF_INET;
226         send_addr.sa.in.sin_port = htons(torture_server_port());
227
228         rc = inet_pton(AF_INET,
229                        torture_server_address(AF_INET),
230                        &send_addr.sa.in.sin_addr);
231         assert_int_equal(rc, 1);
232
233         rc = connect(s, &send_addr.sa.s, send_addr.sa_socklen);
234         assert_return_code(rc, errno);
235
236         iov.iov_base = (void *)payload;
237         iov.iov_len = sizeof(payload);
238
239         /* msg_name is NULL */
240
241         s_msg.msg_iov = &iov;
242         s_msg.msg_iovlen = 1;
243
244         ret = sendmsg(s, &s_msg, 0);
245         assert_int_not_equal(ret, -1);
246
247         r_msg.msg_name = &r_addr.sa.ss;
248         r_msg.msg_namelen = r_addr.sa_socklen;
249
250         memset(payload, 0, sizeof(payload));
251
252         r_msg.msg_iov = &iov;
253         r_msg.msg_iovlen = 1;
254
255         ret = recvmsg(s, &r_msg, 0);
256         assert_int_not_equal(ret, -1);
257
258         assert_int_equal(r_msg.msg_namelen, sizeof(struct sockaddr_in));
259
260         a = inet_ntop(AF_INET, &r_addr.sa.in.sin_addr, ip, sizeof(ip));
261         assert_non_null(a);
262         assert_string_equal(a, torture_server_address(AF_INET));
263
264         close(s);
265 }
266
267 static void test_sendmsg_recvmsg_ipv4_connected_null(void **state)
268 {
269         struct torture_address send_addr = {
270                 .sa_socklen = sizeof(struct sockaddr_storage),
271         };
272         struct msghdr s_msg = {
273                 .msg_namelen = 0,
274         };
275         struct msghdr r_msg = {
276                 .msg_namelen = 0,
277         };
278         struct iovec iov;
279         char payload[] = "PACKET";
280         ssize_t ret;
281         int rc;
282         int s;
283
284         (void)state; /* unused */
285
286         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
287         assert_int_not_equal(s, -1);
288
289         send_addr.sa.in.sin_family = AF_INET;
290         send_addr.sa.in.sin_port = htons(torture_server_port());
291
292         rc = inet_pton(AF_INET,
293                        torture_server_address(AF_INET),
294                        &send_addr.sa.in.sin_addr);
295         assert_int_equal(rc, 1);
296
297         rc = connect(s, &send_addr.sa.s, send_addr.sa_socklen);
298         assert_return_code(rc, errno);
299
300         /* msg_name = NULL */
301
302         iov.iov_base = (void *)payload;
303         iov.iov_len = sizeof(payload);
304
305         s_msg.msg_iov = &iov;
306         s_msg.msg_iovlen = 1;
307
308         ret = sendmsg(s, &s_msg, 0);
309         assert_int_not_equal(ret, -1);
310
311         /* msg_name = NULL */
312
313         memset(payload, 0, sizeof(payload));
314
315         r_msg.msg_iov = &iov;
316         r_msg.msg_iovlen = 1;
317
318         ret = recvmsg(s, &r_msg, 0);
319         assert_int_not_equal(ret, -1);
320
321         assert_int_equal(r_msg.msg_namelen, 0);
322         assert_null(r_msg.msg_name);
323
324         close(s);
325 }
326
327 static void test_sendmsg_recvmsg_ipv4_connected_namelen(void **state)
328 {
329         struct torture_address send_addr = {
330                 .sa_socklen = sizeof(struct sockaddr_storage),
331         };
332         struct msghdr s_msg = {
333                 .msg_namelen = 0,
334         };
335         struct msghdr r_msg = {
336                 .msg_namelen = sizeof(struct sockaddr_storage),
337         };
338         struct iovec iov;
339         char payload[] = "PACKET";
340         ssize_t ret;
341         int rc;
342         int s;
343
344         (void)state; /* unused */
345
346         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
347         assert_int_not_equal(s, -1);
348
349         send_addr.sa.in.sin_family = AF_INET;
350         send_addr.sa.in.sin_port = htons(torture_server_port());
351
352         rc = inet_pton(AF_INET,
353                        torture_server_address(AF_INET),
354                        &send_addr.sa.in.sin_addr);
355         assert_int_equal(rc, 1);
356
357         rc = connect(s, &send_addr.sa.s, send_addr.sa_socklen);
358         assert_return_code(rc, errno);
359
360         /* msg_name = NULL */
361
362         iov.iov_base = (void *)payload;
363         iov.iov_len = sizeof(payload);
364
365         s_msg.msg_iov = &iov;
366         s_msg.msg_iovlen = 1;
367
368         ret = sendmsg(s, &s_msg, 0);
369         assert_int_not_equal(ret, -1);
370
371         /* msg_name = NULL */
372
373         memset(payload, 0, sizeof(payload));
374
375         r_msg.msg_iov = &iov;
376         r_msg.msg_iovlen = 1;
377
378         ret = recvmsg(s, &r_msg, 0);
379         assert_int_not_equal(ret, -1);
380
381         close(s);
382 }
383
384 int main(void) {
385         int rc;
386
387         const struct CMUnitTest sendmsg_tests[] = {
388                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4,
389                                                 setup_echo_srv_udp_ipv4,
390                                                 teardown),
391 #ifdef HAVE_IPV6
392                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv6,
393                                                 setup_echo_srv_udp_ipv6,
394                                                 teardown),
395 #endif
396                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_connected,
397                                                 setup_echo_srv_udp_ipv4,
398                                                 teardown),
399                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_connected_null,
400                                                 setup_echo_srv_udp_ipv4,
401                                                 teardown),
402                 cmocka_unit_test_setup_teardown(test_sendmsg_recvmsg_ipv4_connected_namelen,
403                                                 setup_echo_srv_udp_ipv4,
404                                                 teardown),
405         };
406
407         rc = cmocka_run_group_tests(sendmsg_tests, NULL, NULL);
408
409         return rc;
410 }