swrap: always check new fd's against socket_fds_max and use libc_close() for cleanup
[socket_wrapper.git] / tests / test_echo_udp_sendto_recvfrom.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_sendto_recvfrom_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
73                 snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
74
75                 ret = sendto(s,
76                              send_buf,
77                              sizeof(send_buf),
78                              0,
79                              &addr.sa.s,
80                              addr.sa_socklen);
81                 assert_return_code(ret, errno);
82
83                 ret = recvfrom(s,
84                                recv_buf,
85                                sizeof(recv_buf),
86                                0,
87                                &srv_in.sa.s,
88                                &srv_in.sa_socklen);
89                 assert_return_code(ret, errno);
90
91                 a = inet_ntop(AF_INET, &srv_in.sa.in.sin_addr, ip, sizeof(ip));
92                 assert_non_null(a);
93                 assert_string_equal(a, torture_server_address(AF_INET));
94
95                 assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
96         }
97
98         ret = sendto(s,
99                      send_buf,
100                      sizeof(send_buf),
101                      0,
102                      &addr.sa.s,
103                      addr.sa_socklen);
104         assert_return_code(ret, errno);
105
106         ret = recvfrom(s,
107                        recv_buf,
108                        sizeof(recv_buf),
109                        0,
110                        NULL,
111                        NULL);
112         assert_return_code(ret, errno);
113
114         close(s);
115 }
116
117 #ifdef HAVE_IPV6
118 static void test_sendto_recvfrom_ipv6(void **state)
119 {
120         struct torture_address addr = {
121                 .sa_socklen = sizeof(struct sockaddr_in6),
122         };
123         char send_buf[64] = {0};
124         char recv_buf[64] = {0};
125         ssize_t ret;
126         int rc;
127         int i;
128         int s;
129
130         (void) state; /* unused */
131
132         s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
133         assert_int_not_equal(s, -1);
134
135         addr.sa.in6.sin6_family = AF_INET6;
136         addr.sa.in6.sin6_port = htons(torture_server_port());
137
138         rc = inet_pton(AF_INET6,
139                        torture_server_address(AF_INET6),
140                        &addr.sa.in6.sin6_addr);
141         assert_int_equal(rc, 1);
142
143         for (i = 0; i < 10; i++) {
144                 char ip[INET6_ADDRSTRLEN] = {0};
145                 const char *a;
146                 struct torture_address srv_in6 = {
147                         .sa_socklen = sizeof(struct sockaddr_in6),
148                 };
149
150                 snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
151
152                 ret = sendto(s,
153                              send_buf,
154                              sizeof(send_buf),
155                              0,
156                              &addr.sa.s,
157                              addr.sa_socklen);
158                 assert_return_code(ret, errno);
159
160                 ret = recvfrom(s,
161                                recv_buf,
162                                sizeof(recv_buf),
163                                0,
164                                &srv_in6.sa.s,
165                                &srv_in6.sa_socklen);
166                 assert_return_code(ret, errno);
167
168                 a = inet_ntop(AF_INET6, &srv_in6.sa.in6.sin6_addr, ip, sizeof(ip));
169                 assert_non_null(a);
170                 assert_string_equal(a, torture_server_address(AF_INET6));
171
172                 assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
173         }
174
175         ret = sendto(s,
176                      send_buf,
177                      sizeof(send_buf),
178                      0,
179                      &addr.sa.s,
180                      addr.sa_socklen);
181         assert_return_code(ret, errno);
182
183         ret = recvfrom(s,
184                        recv_buf,
185                        sizeof(recv_buf),
186                        0,
187                        NULL,
188                        NULL);
189         assert_return_code(ret, errno);
190
191         close(s);
192 }
193 #endif
194
195 static void test_connect_sendto_ipv4(void **state)
196 {
197         struct torture_address addr = {
198                 .sa_socklen = sizeof(struct sockaddr_in),
199         };
200         char send_buf[] = "packet.0";
201         char recv_buf[64] = {0};
202         ssize_t ret;
203         int rc;
204         int s;
205
206         (void) state; /* unused */
207
208         addr.sa.in.sin_family = AF_INET;
209         addr.sa.in.sin_port = htons(torture_server_port());
210
211         rc = inet_pton(AF_INET,
212                        torture_server_address(AF_INET),
213                        &addr.sa.in.sin_addr);
214         assert_int_equal(rc, 1);
215
216         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
217         assert_int_not_equal(s, -1);
218
219         /* Now, connect */
220         rc = connect(s, &addr.sa.s, addr.sa_socklen);
221         assert_return_code(rc, errno);
222
223         ret = sendto(s,
224                      send_buf,
225                      sizeof(send_buf),
226                      0,
227                      &addr.sa.s,
228                      addr.sa_socklen);
229         assert_return_code(ret, errno);
230
231         ret = recvfrom(s,
232                        recv_buf,
233                        sizeof(recv_buf),
234                        0,
235                        NULL,
236                        0);
237         assert_return_code(ret, errno);
238
239         assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
240
241         close(s);
242 }
243
244 static void test_connect_sendto_null_ipv4(void **state)
245 {
246         struct torture_address addr = {
247                 .sa_socklen = sizeof(struct sockaddr_in),
248         };
249         char send_buf[] = "packet.0";
250         char recv_buf[64] = {0};
251         ssize_t ret;
252         int rc;
253         int s;
254
255         (void) state; /* unused */
256
257         addr.sa.in.sin_family = AF_INET;
258         addr.sa.in.sin_port = htons(torture_server_port());
259
260         rc = inet_pton(AF_INET,
261                        torture_server_address(AF_INET),
262                        &addr.sa.in.sin_addr);
263         assert_int_equal(rc, 1);
264
265         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
266         assert_int_not_equal(s, -1);
267
268         /* Now, connect */
269         rc = connect(s, &addr.sa.s, addr.sa_socklen);
270         assert_return_code(rc, errno);
271
272         ret = sendto(s,
273                      send_buf,
274                      sizeof(send_buf),
275                      0,
276                      NULL,
277                      0);
278         assert_return_code(ret, errno);
279
280         ret = recvfrom(s,
281                        recv_buf,
282                        sizeof(recv_buf),
283                        0,
284                        NULL,
285                        0);
286         assert_return_code(ret, errno);
287
288         assert_memory_equal(send_buf, recv_buf, sizeof(send_buf));
289
290         close(s);
291 }
292
293 int main(void) {
294         int rc;
295
296         const struct CMUnitTest sendto_tests[] = {
297                 cmocka_unit_test_setup_teardown(test_sendto_recvfrom_ipv4,
298                                                 setup_echo_srv_udp_ipv4,
299                                                 teardown),
300 #ifdef HAVE_IPV6
301                 cmocka_unit_test_setup_teardown(test_sendto_recvfrom_ipv6,
302                                                 setup_echo_srv_udp_ipv6,
303                                                 teardown),
304 #endif
305                 cmocka_unit_test_setup_teardown(test_connect_sendto_ipv4,
306                                                 setup_echo_srv_udp_ipv4,
307                                                 teardown),
308                 cmocka_unit_test_setup_teardown(test_connect_sendto_null_ipv4,
309                                                 setup_echo_srv_udp_ipv4,
310                                                 teardown),
311         };
312
313         rc = cmocka_run_group_tests(sendto_tests, NULL, NULL);
314
315         return rc;
316 }