swrap: Add support for openat64()
[socket_wrapper.git] / tests / test_echo_tcp_get_peer_sock_name.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_tcp_ipv4(void **state)
19 {
20         torture_setup_echo_srv_tcp_ipv4(state);
21         setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "20", 1);
22
23         return 0;
24 }
25
26 static int teardown(void **state)
27 {
28         torture_teardown_echo_srv(state);
29
30         return 0;
31 }
32
33 static void _assert_sockaddr_equal(struct torture_address *addr, const char *a,
34                                    const char * const file, const int line)
35 {
36 #ifdef HAVE_IPV6
37         char ip[INET6_ADDRSTRLEN] = { 0 };
38 #else
39         char ip[INET_ADDRSTRLEN] = { 0 };
40 #endif
41         const char *p;
42
43 #ifdef HAVE_IPV6
44         p = inet_ntop(addr->sa.ss.ss_family,
45                       addr->sa.ss.ss_family == AF_INET6 ?
46                           (void *)&addr->sa.in6.sin6_addr :
47                           (void *)&addr->sa.in.sin_addr,
48                       ip,
49                       sizeof(ip));
50 #else
51         p = inet_ntop(addr->sa.ss.ss_family,
52                       (void *)&addr->sa.in.sin_addr,
53                       ip,
54                       sizeof(ip));
55 #endif
56         _assert_true(cast_ptr_to_largest_integral_type(p),
57                      "inet_ntop: Failed to convert IP address", file, line);
58
59         _assert_string_equal(ip, a, file, line);
60 }
61
62 #define assert_sockaddr_equal(ss, a) \
63         _assert_sockaddr_equal(ss, a, __FILE__, __LINE__)
64
65 static void _assert_sockaddr_port_equal(struct torture_address *addr,
66                                         const char *a,
67                                         uint16_t port,
68                                         const char * const file, const int line)
69 {
70         uint16_t n_port;
71
72         _assert_sockaddr_equal(addr, a, file, line);
73
74         switch(addr->sa.ss.ss_family) {
75         case AF_INET:
76                 n_port = addr->sa.in.sin_port;
77                 break;
78 #ifdef HAVE_IPV6
79         case AF_INET6:
80                 n_port = addr->sa.in6.sin6_port;
81                 break;
82 #endif
83         default:
84                 return;
85         }
86
87         _assert_int_equal(ntohs(n_port), port, file, line);
88 }
89
90 #define assert_sockaddr_port_equal(ss, a, prt) \
91         _assert_sockaddr_port_equal(ss, a, prt, __FILE__, __LINE__)
92
93 static void _assert_sockaddr_port_range_equal(struct torture_address *addr,
94                                               const char *a,
95                                               uint16_t min_port, uint16_t max_port,
96                                               const char * const file, const int line)
97 {
98         uint16_t n_port;
99
100         _assert_sockaddr_equal(addr, a, file, line);
101
102         switch(addr->sa.ss.ss_family) {
103         case AF_INET:
104                 n_port = addr->sa.in.sin_port;
105                 break;
106 #ifdef HAVE_IPV6
107         case AF_INET6:
108                 n_port = addr->sa.in6.sin6_port;
109                 break;
110 #endif
111         default:
112                 return;
113         }
114
115         _assert_in_range(ntohs(n_port),
116                          min_port,
117                          max_port,
118                          file,
119                          line);
120 }
121
122 #define assert_sockaddr_port_range_equal(ss, a, min_prt, max_prt) \
123         _assert_sockaddr_port_range_equal(ss, a, min_prt, max_prt, __FILE__, __LINE__)
124
125 static void test_connect_getsockname_getpeername(void **state)
126 {
127         struct torture_address addr = {
128                 .sa_socklen = sizeof(struct sockaddr_in),
129         };
130         struct torture_address cli_addr = {
131                 .sa_socklen = sizeof(struct sockaddr_storage),
132         };
133         struct torture_address srv_addr = {
134                 .sa_socklen = sizeof(struct sockaddr_storage),
135         };
136         int rc;
137         int s;
138
139         (void) state; /* unused */
140
141         s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
142         assert_return_code(s, errno);
143
144         /* Bind client address to wildcard address */
145         addr.sa.in.sin_family = AF_INET;
146
147         rc = inet_pton(AF_INET, "127.0.0.20", &addr.sa.in.sin_addr);
148         assert_int_equal(rc, 1);
149
150         rc = bind(s, &addr.sa.s, addr.sa_socklen);
151         assert_return_code(rc, errno);
152
153         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
154         assert_return_code(rc, errno);
155         assert_sockaddr_port_range_equal(&cli_addr, "127.0.0.20", 1024, 65535);
156
157         rc = getpeername(s, &addr.sa.s, &addr.sa_socklen);
158         assert_int_equal(rc, -1);
159         assert_int_equal(errno, ENOTCONN);
160
161         /* connect */
162         addr = (struct torture_address) {
163                 .sa_socklen = sizeof(struct sockaddr_in),
164                 .sa.in = (struct sockaddr_in) {
165                         .sin_family = AF_INET,
166                         .sin_port = htons(torture_server_port()),
167                 },
168         };
169         rc = inet_pton(AF_INET,
170                        torture_server_address(AF_INET),
171                        &addr.sa.in.sin_addr);
172         assert_int_equal(rc, 1);
173
174         /* Connect */
175         rc = connect(s, &addr.sa.s, addr.sa_socklen);
176         assert_return_code(rc, errno);
177
178         cli_addr = (struct torture_address) {
179                 .sa_socklen = sizeof(struct sockaddr_storage),
180         };
181
182         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
183         assert_return_code(rc, errno);
184         assert_sockaddr_port_range_equal(&cli_addr, "127.0.0.20", 1024, 65535);
185
186         srv_addr = (struct torture_address) {
187                 .sa_socklen = sizeof(struct sockaddr_storage),
188         };
189
190         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
191         assert_return_code(rc, errno);
192         assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
193
194         close(s);
195 }
196
197 static void test_connect_getsockname_getpeername_port(void **state)
198 {
199         struct torture_address addr = {
200                 .sa_socklen = sizeof(struct sockaddr_in),
201         };
202         struct torture_address cli_addr = {
203                 .sa_socklen = sizeof(struct sockaddr_storage),
204         };
205         struct torture_address srv_addr = {
206                 .sa_socklen = sizeof(struct sockaddr_storage),
207         };
208         int rc;
209         int s;
210
211         (void) state; /* unused */
212
213         s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
214         assert_return_code(s, errno);
215
216         /* Bind client address to wildcard address */
217         addr.sa.in.sin_family = AF_INET;
218
219         rc = inet_pton(AF_INET, "127.0.0.20", &addr.sa.in.sin_addr);
220         assert_int_equal(rc, 1);
221         addr.sa.in.sin_port = htons(12345);
222
223         rc = bind(s, &addr.sa.s, addr.sa_socklen);
224         assert_return_code(rc, errno);
225
226         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
227         assert_return_code(rc, errno);
228         assert_sockaddr_port_equal(&cli_addr, "127.0.0.20", 12345);
229
230         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
231         assert_int_equal(rc, -1);
232         assert_int_equal(errno, ENOTCONN);
233
234         /* connect */
235         addr = (struct torture_address) {
236                 .sa_socklen = sizeof(struct sockaddr_in),
237                 .sa.in = (struct sockaddr_in) {
238                         .sin_family = AF_INET,
239                         .sin_port = htons(torture_server_port()),
240                 },
241         };
242
243         rc = inet_pton(AF_INET,
244                        torture_server_address(AF_INET),
245                        &addr.sa.in.sin_addr);
246         assert_int_equal(rc, 1);
247
248         /* Connect */
249         rc = connect(s, &addr.sa.s, addr.sa_socklen);
250         assert_return_code(rc, errno);
251
252         cli_addr = (struct torture_address) {
253                 .sa_socklen = sizeof(struct sockaddr_storage),
254         };
255
256         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
257         assert_return_code(rc, errno);
258         assert_sockaddr_port_equal(&cli_addr, "127.0.0.20", 12345);
259
260         srv_addr = (struct torture_address) {
261                 .sa_socklen = sizeof(struct sockaddr_storage),
262         };
263
264         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
265         assert_return_code(rc, errno);
266         assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
267
268         close(s);
269 }
270
271 static void test_connect_getsockname_getpeername_any(void **state)
272 {
273         struct torture_address addr = {
274                 .sa_socklen = sizeof(struct sockaddr_in),
275         };
276         struct torture_address cli_addr = {
277                 .sa_socklen = sizeof(struct sockaddr_storage),
278         };
279         struct torture_address srv_addr = {
280                 .sa_socklen = sizeof(struct sockaddr_storage),
281         };
282         int rc;
283         int s;
284
285         (void) state; /* unused */
286
287         s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
288         assert_return_code(s, errno);
289
290         /* Bind client address to wildcard address */
291         addr.sa.in.sin_family = AF_INET;
292         addr.sa.in.sin_addr.s_addr = htonl(INADDR_ANY);
293
294         rc = bind(s, &addr.sa.s, addr.sa_socklen);
295         assert_return_code(rc, errno);
296
297         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
298         assert_return_code(rc, errno);
299         assert_sockaddr_port_range_equal(&cli_addr, "0.0.0.0", 1024, 65535);
300
301         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
302         assert_int_equal(rc, -1);
303         assert_int_equal(errno, ENOTCONN);
304
305         /* connect */
306         addr.sa.in.sin_family = AF_INET;
307         addr.sa.in.sin_port = htons(torture_server_port());
308         rc = inet_pton(AF_INET,
309                        torture_server_address(AF_INET),
310                        &addr.sa.in.sin_addr);
311         assert_int_equal(rc, 1);
312
313         /* Connect */
314         rc = connect(s, &addr.sa.s, addr.sa_socklen);
315         assert_return_code(rc, errno);
316
317         cli_addr = (struct torture_address) {
318                 .sa_socklen = sizeof(struct sockaddr_storage),
319         };
320
321         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
322         assert_return_code(rc, errno);
323         assert_sockaddr_port_range_equal(&cli_addr, "127.0.0.20", 1024, 65535);
324
325         srv_addr = (struct torture_address) {
326                 .sa_socklen = sizeof(struct sockaddr_storage),
327         };
328
329         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
330         assert_return_code(rc, errno);
331         assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
332
333         close(s);
334 }
335
336 static void test_connect_getsockname_getpeername_any_port(void **state)
337 {
338         struct torture_address addr = {
339                 .sa_socklen = sizeof(struct sockaddr_in),
340         };
341         struct torture_address cli_addr = {
342                 .sa_socklen = sizeof(struct sockaddr_storage),
343         };
344         struct torture_address srv_addr = {
345                 .sa_socklen = sizeof(struct sockaddr_storage),
346         };
347         int rc;
348         int s;
349
350         (void) state; /* unused */
351
352         s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
353         assert_return_code(s, errno);
354
355         /* Bind client address to wildcard address */
356         addr.sa.in.sin_family = AF_INET;
357         addr.sa.in.sin_addr.s_addr = htonl(INADDR_ANY);
358         addr.sa.in.sin_port = htons(12345);
359
360         rc = bind(s, &addr.sa.s, addr.sa_socklen);
361         assert_return_code(rc, errno);
362
363         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
364         assert_return_code(rc, errno);
365         assert_sockaddr_port_equal(&cli_addr, "0.0.0.0", 12345);
366
367         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
368         assert_int_equal(rc, -1);
369         assert_int_equal(errno, ENOTCONN);
370
371         /* connect */
372         addr.sa.in.sin_family = AF_INET;
373         addr.sa.in.sin_port = htons(torture_server_port());
374         rc = inet_pton(AF_INET,
375                        torture_server_address(AF_INET),
376                        &addr.sa.in.sin_addr);
377         assert_int_equal(rc, 1);
378
379         /* Connect */
380         rc = connect(s, &addr.sa.s, addr.sa_socklen);
381         assert_return_code(rc, errno);
382
383         cli_addr = (struct torture_address) {
384                 .sa_socklen = sizeof(struct sockaddr_storage),
385         };
386
387         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
388         assert_return_code(rc, errno);
389         assert_sockaddr_port_equal(&cli_addr, "127.0.0.20", 12345);
390
391         srv_addr = (struct torture_address) {
392                 .sa_socklen = sizeof(struct sockaddr_storage),
393         };
394
395         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
396         assert_return_code(rc, errno);
397         assert_sockaddr_port_equal(&srv_addr, "127.0.0.10", 7);
398
399         close(s);
400 }
401
402 static void test_connect_getsockname_getpeername_len(void **state)
403 {
404         struct torture_address addr = {
405                 .sa_socklen = sizeof(struct sockaddr_in),
406         };
407         struct torture_address cli_addr = {
408                 .sa_socklen = sizeof(struct sockaddr_storage),
409         };
410         struct torture_address srv_addr = {
411                 .sa_socklen = sizeof(struct sockaddr_storage),
412         };
413         socklen_t tmp_len;
414         int rc;
415         int s;
416
417         (void) state; /* unused */
418
419         s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
420         assert_return_code(s, errno);
421
422         /* connect */
423         addr.sa.in.sin_family = AF_INET;
424         addr.sa.in.sin_port = htons(torture_server_port());
425         rc = inet_pton(AF_INET,
426                        torture_server_address(AF_INET),
427                        &addr.sa.in.sin_addr);
428         assert_int_equal(rc, 1);
429
430         /* Connect */
431         rc = connect(s, &addr.sa.s, addr.sa_socklen);
432         assert_return_code(rc, errno);
433
434         /* Check with len=0 */
435         cli_addr.sa_socklen = 0;
436         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
437         assert_return_code(rc, errno);
438
439         srv_addr.sa_socklen = 0;
440         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
441         assert_return_code(rc, errno);
442
443         /* Check with len=too small */
444         cli_addr = (struct torture_address) {
445                 .sa_socklen = sizeof(struct sockaddr_in) - 2,
446         };
447
448         tmp_len = cli_addr.sa_socklen;
449         rc = getsockname(s, &cli_addr.sa.s, &cli_addr.sa_socklen);
450         assert_return_code(rc, errno);
451         assert_int_equal(tmp_len + 2, cli_addr.sa_socklen);
452
453         srv_addr = (struct torture_address) {
454                 .sa_socklen = sizeof(struct sockaddr_in) - 2,
455         };
456
457         tmp_len = srv_addr.sa_socklen;
458         rc = getpeername(s, &srv_addr.sa.s, &srv_addr.sa_socklen);
459         assert_return_code(rc, errno);
460         assert_int_equal(tmp_len + 2, srv_addr.sa_socklen);
461
462         close(s);
463 }
464
465 int main(void) {
466         int rc;
467
468         const struct CMUnitTest sock_name_tests[] = {
469                 cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername,
470                                                 setup_echo_srv_tcp_ipv4,
471                                                 teardown),
472                 cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_port,
473                                                 setup_echo_srv_tcp_ipv4,
474                                                 teardown),
475                 cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_any,
476                                                 setup_echo_srv_tcp_ipv4,
477                                                 teardown),
478                 cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_any_port,
479                                                 setup_echo_srv_tcp_ipv4,
480                                                 teardown),
481                 cmocka_unit_test_setup_teardown(test_connect_getsockname_getpeername_len,
482                                                 setup_echo_srv_tcp_ipv4,
483                                                 teardown),
484         };
485
486         rc = cmocka_run_group_tests(sock_name_tests,
487                                     NULL,
488                                     NULL);
489
490         return rc;
491 }