1 /* $Id: server-t.c 10396 2020-11-12 20:19:41Z iulius $
2 *
3 * Test suite for network server functions.
4 *
5 * The canonical version of this file is maintained in the rra-c-util package,
6 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
7 *
8 * Written by Russ Allbery <eagle@eyrie.org>
9 * Copyright 2005, 2013, 2016-2018, 2020 Russ Allbery <eagle@eyrie.org>
10 * Copyright 2009-2013
11 * The Board of Trustees of the Leland Stanford Junior University
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 * DEALINGS IN THE SOFTWARE.
30 *
31 * SPDX-License-Identifier: MIT
32 */
33
34 #define LIBTEST_NEW_FORMAT 1
35
36 #include "config.h"
37 #include "portable/socket.h"
38 #include "clibrary.h"
39
40 #include <errno.h>
41 #include <signal.h>
42 #include <sys/wait.h>
43
44 #include "tap/basic.h"
45 #include "inn/fdflag.h"
46 #include "inn/macros.h"
47 #include "inn/messages.h"
48 #include "inn/network.h"
49
50
51 /*
52 * Check whether IPv6 actually works. On some systems (such as Solaris 8
53 * without IPv6 configured), it's possible to create an IPv6 socket, but
54 * binding the socket will fail. We therefore attempt an IPv6 socket creation
55 * and, if it fails, check errno for several errors that indicate that IPv6
56 * is supported but doesn't work. This will also handle the case where IPv6
57 * support is not configured, since network_bind_ipv6 will return
58 * INVALID_SOCKET.
59 */
60 static bool
ipv6_works(void)61 ipv6_works(void)
62 {
63 socket_type fd, client, server;
64
65 /*
66 * Create the socket and then try to connect to it with a short timeout
67 * and accept it on the server side. If this works, IPv6 is supported.
68 */
69 fd = network_bind_ipv6(SOCK_STREAM, "::1", 11119);
70 if (fd != INVALID_SOCKET) {
71 fdflag_nonblocking(fd, true);
72 client = network_connect_host("::1", 11119, NULL, 1);
73 if (client == INVALID_SOCKET) {
74 close(fd);
75 if (socket_errno == ETIMEDOUT || socket_errno == ENETUNREACH)
76 return false;
77 } else {
78 server = accept(fd, NULL, NULL);
79 close(fd);
80 if (server == INVALID_SOCKET) {
81 close(client);
82
83 /*
84 * Written as two separate if statements because gcc with
85 * -Werror=logical-op warns about identical expressions, and
86 * EAGAIN and EWOULDBLOCK are the same number on Linux (but
87 * not on some other platforms).
88 */
89 if (socket_errno == EAGAIN)
90 return false;
91 if (socket_errno == EWOULDBLOCK)
92 return false;
93 } else {
94 close(server);
95 close(client);
96 return true;
97 }
98 }
99 }
100
101 /* IPv6 not recognized, indicating no support. */
102 if (socket_errno == EAFNOSUPPORT || socket_errno == EPROTONOSUPPORT)
103 return false;
104
105 /* IPv6 is recognized but we can't actually use it. */
106 if (socket_errno == EADDRNOTAVAIL)
107 return false;
108
109 /*
110 * Some other error. Assume it's not related to IPv6. We'll probably
111 * fail later.
112 */
113 return true;
114 }
115
116
117 /*
118 * A client writer used to generate data for a server test. Connect to the
119 * given host on port 11119 and send a constant string to a socket. Takes the
120 * source address as well to pass into network_connect_host. If the flag is
121 * true, expects to succeed in connecting; otherwise, fail the test (by
122 * exiting with a non-zero status) if the connection is successful.
123 *
124 * If the succeed argument is true, this is guarateed to never return.
125 */
126 static void
client_writer(const char * host,const char * source,bool succeed)127 client_writer(const char *host, const char *source, bool succeed)
128 {
129 socket_type fd;
130 FILE *out;
131
132 fd = network_connect_host(host, 11119, source, 0);
133 if (fd == INVALID_SOCKET) {
134 if (succeed)
135 _exit(1);
136 else
137 return;
138 }
139 out = fdopen(fd, "w");
140 if (out == NULL)
141 sysdie("fdopen failed");
142 fputs("socket test\r\n", out);
143 fclose(out);
144 _exit(succeed ? 0 : 1);
145 }
146
147
148 /*
149 * A client writer for testing UDP. Sends a UDP packet to port 11119 on
150 * localhost, from the given source address, containing a constant string.
151 * This also verifies that network_client_create works properly.
152 */
153 __attribute__((__noreturn__)) static void
client_ipv4_udp_writer(const char * source)154 client_ipv4_udp_writer(const char *source)
155 {
156 socket_type fd;
157 struct sockaddr_in sin;
158
159 /* Create and bind the socket. */
160 fd = network_client_create(AF_INET, SOCK_DGRAM, source);
161 if (fd == INVALID_SOCKET)
162 _exit(1);
163
164 /* Connect to localhost port 11119. */
165 memset(&sin, 0, sizeof(sin));
166 sin.sin_family = AF_INET;
167 sin.sin_port = htons(11119);
168 sin.sin_addr.s_addr = htonl(0x7f000001UL);
169 if (connect(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
170 _exit(1);
171
172 /* Send our fixed UDP packet. */
173 if (send(fd, "socket test\r\n", 13, 0) < 13)
174 _exit(1);
175 _exit(0);
176 }
177
178
179 /*
180 * The same as client_ipv4_udp_writer, but sents the packet via IPv6 instead.
181 * If somehow this was called without IPv6 being available (which should be
182 * impossible), do nothing and exit with a non-zero status.
183 */
184 __attribute__((__noreturn__)) static void
client_ipv6_udp_writer(const char * source)185 client_ipv6_udp_writer(const char *source)
186 {
187 #ifdef HAVE_INET6
188 socket_type fd;
189 struct sockaddr_in6 sin6;
190
191 /* Create and bind the socket. */
192 fd = network_client_create(AF_INET6, SOCK_DGRAM, source);
193 if (fd == INVALID_SOCKET)
194 _exit(1);
195
196 /* Connect to localhost port 11119. */
197 memset(&sin6, 0, sizeof(sin6));
198 sin6.sin6_family = AF_INET6;
199 sin6.sin6_port = htons(11119);
200 if (inet_pton(AF_INET6, "::1", &sin6.sin6_addr) < 1)
201 sysbail("cannot convert ::1 to an in6_addr");
202 if (connect(fd, (struct sockaddr *) &sin6, sizeof(sin6)) < 0)
203 _exit(1);
204
205 /* Send our fixed UDP packet. */
206 if (send(fd, "socket test\r\n", 13, 0) < 13)
207 _exit(1);
208 _exit(0);
209 #else
210 _exit(1);
211 #endif
212 }
213
214
215 /*
216 * When testing the bind (server) functions, we create listening sockets, fork
217 * a child process to connect to it, and accept the connection and read the
218 * data in the server. The test reporting is therefore done by the listener.
219 * There are two listeners, depending on whether we're listening to a single
220 * socket or an array of sockets, both of which invoke this handler when the
221 * connection is accepted.
222 *
223 * Check that the result of accept, read data from the client, and ensure we
224 * got the expected data, reporting all results through the normal test
225 * reporting mechanism.
226 */
227 static void
test_server_connection(socket_type client)228 test_server_connection(socket_type client)
229 {
230 FILE *out;
231 char buffer[512];
232
233 /* Verify that the result of accept is good. */
234 if (client == INVALID_SOCKET) {
235 sysdiag("cannot accept connection from socket");
236 ok_block(2, 0, "...socket read test");
237 return;
238 }
239 ok(1, "...socket accept");
240
241 /* Read data from the client and ensure it matches our expectations. */
242 out = fdopen(client, "r");
243 if (fgets(buffer, sizeof(buffer), out) == NULL) {
244 sysdiag("cannot read from socket");
245 ok(0, "...socket read");
246 }
247 is_string("socket test\r\n", buffer, "...socket read");
248 fclose(out);
249 }
250
251
252 /*
253 * Test a single listening socket. Accepts one connection and invokes
254 * test_server_connection. For skipping purposes, this produces two tests.
255 */
256 static void
test_server_accept(socket_type fd)257 test_server_accept(socket_type fd)
258 {
259 socket_type client;
260
261 /* If there are firewalls that block connections, we could hang here. */
262 alarm(5);
263
264 /* Accept the connection and writes from the client. */
265 client = accept(fd, NULL, NULL);
266 test_server_connection(client);
267 socket_close(fd);
268
269 /* Cancel the alarm. */
270 alarm(0);
271 }
272
273
274 /*
275 * A variant version of the server portion of the test. Takes an array of
276 * sockets and the size of the sockets and accepts a connection on any of
277 * those sockets. Ensures that the client address information is stored
278 * correctly by checking that it is an IPv4 or IPv6 address. For skipping
279 * purposes, this produces three tests.
280 *
281 * Normally, the client address should be 127.0.0.1, but hosts with odd local
282 * networking setups may rewrite client IP addresses so that they appear to
283 * come from other addresses. Hosts that only have IPv6 interfaces will see a
284 * client connection on ::1 instead. Avoid checking if the client IP is
285 * 127.0.0.1 for that reason. Hopefully this won't hide bugs.
286 *
287 * saddr is allocated from the heap instead of using a local struct
288 * sockaddr_storage to work around a misdiagnosis of strict aliasing
289 * violations from gcc 4.4 (fixed in later versions).
290 */
291 static void
test_server_accept_any(socket_type fds[],unsigned int count)292 test_server_accept_any(socket_type fds[], unsigned int count)
293 {
294 socket_type client;
295 unsigned int i;
296 struct sockaddr *saddr;
297 socklen_t slen;
298
299 /* If there are firewalls that block connections, we could hang here. */
300 alarm(5);
301
302 /* Accept the connection and writes from the client. */
303 slen = sizeof(struct sockaddr_storage);
304 saddr = bcalloc(1, slen);
305 client = network_accept_any(fds, count, saddr, &slen);
306 test_server_connection(client);
307 if (saddr->sa_family == AF_INET)
308 is_int(AF_INET, saddr->sa_family, "...address family is IPv4");
309 else
310 is_int(AF_INET6, saddr->sa_family, "...address family is IPv6");
311 free(saddr);
312 for (i = 0; i < count; i++)
313 socket_close(fds[i]);
314
315 /* Cancel the alarm. */
316 alarm(0);
317 }
318
319
320 /*
321 * Bring up a server on port 11119 on the loopback address and test connecting
322 * to it via IPv4. Takes an optional source address to use for client
323 * connections. For skipping purposes, this produces four tests.
324 */
325 static void
test_ipv4(const char * source)326 test_ipv4(const char *source)
327 {
328 socket_type fd;
329 pid_t child;
330 int status;
331
332 /* Set up the server socket. */
333 fd = network_bind_ipv4(SOCK_STREAM, "127.0.0.1", 11119);
334 if (fd == INVALID_SOCKET)
335 sysbail("cannot create or bind socket");
336 ok(fd != INVALID_SOCKET, "IPv4 server test");
337 if (listen(fd, 1) < 0)
338 sysbail("cannot listen to socket");
339
340 /* Fork off a child writer and test the server accept. */
341 child = fork();
342 if (child < 0)
343 sysbail("cannot fork");
344 else if (child == 0) {
345 socket_close(fd);
346 client_writer("127.0.0.1", source, true);
347 } else {
348 test_server_accept(fd);
349 waitpid(child, &status, 0);
350 is_int(0, status, "client made correct connections");
351 }
352 }
353
354
355 /*
356 * Bring up a server on port 11119 on the loopback address and test connecting
357 * to it via IPv6. Takes an optional source address to use for client
358 * connections. For skipping purposes, this produces four tests.
359 */
360 static void
test_ipv6(const char * source)361 test_ipv6(const char *source)
362 {
363 socket_type fd;
364 pid_t child;
365 int status;
366
367 /* Set up the server socket. */
368 fd = network_bind_ipv6(SOCK_STREAM, "::1", 11119);
369 if (fd == INVALID_SOCKET)
370 sysbail("cannot create socket");
371 ok(fd != INVALID_SOCKET, "IPv6 server test");
372 if (listen(fd, 1) < 0)
373 sysbail("cannot listen to socket");
374
375 /*
376 * Fork off a child writer and test the server accept. If IPV6_V6ONLY is
377 * supported, we can also check that connecting to 127.0.0.1 will fail.
378 */
379 child = fork();
380 if (child < 0)
381 sysbail("cannot fork");
382 else if (child == 0) {
383 socket_close(fd);
384 #ifdef IPV6_V6ONLY
385 client_writer("127.0.0.1", NULL, false);
386 #endif
387 client_writer("::1", source, true);
388 } else {
389 test_server_accept(fd);
390 waitpid(child, &status, 0);
391 is_int(0, status, "client made correct connections");
392 }
393 }
394
395
396 /*
397 * Returns the struct sockaddr * corresponding to a local socket. Handles the
398 * initial allocation being too small and dynamically increasing it. Caller
399 * is responsible for freeing the allocated sockaddr.
400 */
401 static struct sockaddr *
get_sockaddr(socket_type fd)402 get_sockaddr(socket_type fd)
403 {
404 struct sockaddr *saddr;
405 socklen_t size;
406
407 saddr = bmalloc(sizeof(struct sockaddr_storage));
408 size = sizeof(struct sockaddr_storage);
409 if (getsockname(fd, saddr, &size) < 0)
410 sysbail("cannot getsockname");
411 if (size > sizeof(struct sockaddr)) {
412 free(saddr);
413 saddr = bmalloc(size);
414 if (getsockname(fd, saddr, &size) < 0)
415 sysbail("cannot getsockname");
416 }
417 return saddr;
418 }
419
420
421 /*
422 * Bring up a server on port 11119 on all addresses and try connecting to it
423 * via all of the available protocols. Takes an optional source address to
424 * use for client connections. For skipping purposes, this produces eight
425 * tests.
426 */
427 static void
test_all(const char * source_ipv4,const char * source_ipv6 UNUSED)428 test_all(const char *source_ipv4, const char *source_ipv6 UNUSED)
429 {
430 socket_type *fds, fd;
431 unsigned int count, i;
432 pid_t child;
433 struct sockaddr *saddr;
434 int status, family;
435
436 /* Bind sockets for all available local addresses. */
437 if (!network_bind_all(SOCK_STREAM, 11119, &fds, &count))
438 sysbail("cannot create or bind socket");
439
440 /*
441 * There should be at most two, one for IPv4 and one for IPv6, but allow
442 * for possible future weirdness in networking.
443 */
444 if (count > 2) {
445 diag("got more than two sockets, using just the first two");
446 count = 2;
447 }
448
449 /* We'll test each socket in turn by listening and trying to connect. */
450 for (i = 0; i < count; i++) {
451 fd = fds[i];
452 if (listen(fd, 1) < 0)
453 sysbail("cannot listen to socket %d", fd);
454 ok(fd != INVALID_SOCKET, "all address server test (part %u)", i + 1);
455
456 /* Get the socket type to determine what type of client to run. */
457 saddr = get_sockaddr(fd);
458 family = saddr->sa_family;
459 free(saddr);
460
461 /*
462 * Fork off a child writer and test the server accept. If IPV6_V6ONLY
463 * is supported, we can also check that connecting to 127.0.0.1 will
464 * fail.
465 */
466 child = fork();
467 if (child < 0)
468 sysbail("cannot fork");
469 else if (child == 0) {
470 if (family == AF_INET) {
471 client_writer("::1", source_ipv6, false);
472 client_writer("127.0.0.1", source_ipv4, true);
473 #ifdef HAVE_INET6
474 } else if (family == AF_INET6) {
475 # ifdef IPV6_V6ONLY
476 client_writer("127.0.0.1", source_ipv4, false);
477 # endif
478 client_writer("::1", source_ipv6, true);
479 #endif
480 } else {
481 die("unknown socket family %d", family);
482 }
483 } else {
484 test_server_accept(fd);
485 waitpid(child, &status, 0);
486 is_int(0, status, "client made correct connections");
487 }
488 }
489 network_bind_all_free(fds);
490
491 /* If we only got one listening socket, skip for consistent test count. */
492 if (count == 1)
493 skip_block(4, "only one listening socket");
494 }
495
496
497 /*
498 * Bring up a server on port 11119 on all addresses and try connecting to it
499 * via 127.0.0.1, using network_accept_any underneath. For skipping purposes,
500 * this runs three tests.
501 */
502 static void
test_any(void)503 test_any(void)
504 {
505 socket_type *fds;
506 unsigned int count, i;
507 pid_t child;
508 int status, family;
509 struct sockaddr *saddr;
510
511 /* Bind our socket.
512 *
513 * If the host has no IPv4 addresses, we may have only an IPv6 socket and
514 * thus can't us an IPv4 client. Determine the address family of the
515 * first socket so that we can use an appropriate client.
516 */
517 if (!network_bind_all(SOCK_STREAM, 11119, &fds, &count))
518 sysbail("cannot create or bind socket");
519 saddr = get_sockaddr(fds[0]);
520 family = saddr->sa_family;
521 free(saddr);
522 ok(1, "network_accept_any test");
523
524 /* Listen on all bound sockets. */
525 for (i = 0; i < count; i++)
526 if (listen(fds[i], 1) < 0)
527 sysbail("cannot listen to socket %d", fds[i]);
528
529 /* Write a packet from a client and receive it on the server. */
530 child = fork();
531 if (child < 0)
532 sysbail("cannot fork");
533 else if (child == 0) {
534 if (family == AF_INET)
535 client_writer("127.0.0.1", NULL, true);
536 else
537 client_writer("::1", NULL, true);
538 } else {
539 test_server_accept_any(fds, count);
540 waitpid(child, &status, 0);
541 is_int(0, status, "client made correct connections");
542 }
543 network_bind_all_free(fds);
544 }
545
546
547 /*
548 * Bring up a UDP server on port 11119 on all addresses and try connecting to
549 * it via 127.0.0.1, using network_wait_any underneath. This tests the bind
550 * functions for UDP sockets, network_client_create for UDP addresses, and
551 * network_wait_any.
552 */
553 static void
test_any_udp(void)554 test_any_udp(void)
555 {
556 socket_type *fds, fd;
557 unsigned int count, i;
558 pid_t child;
559 char buffer[BUFSIZ];
560 ssize_t length;
561 int status, family;
562 struct sockaddr_storage addr;
563 struct sockaddr *saddr;
564 socklen_t addrlen;
565
566 /*
567 * Bind our UDP socket.
568 *
569 * If the host has no IPv4 addresses, we may have only an IPv6 socket and
570 * thus can't us an IPv4 client. Determine the address family of the
571 * first socket so that we can use an appropriate client.
572 */
573 if (!network_bind_all(SOCK_DGRAM, 11119, &fds, &count))
574 sysbail("cannot create or bind socket");
575 saddr = get_sockaddr(fds[0]);
576 family = saddr->sa_family;
577 free(saddr);
578
579 /* Create a child that writes a single UDP packet to the server. */
580 child = fork();
581 if (child < 0)
582 sysbail("cannot fork");
583 else if (child == 0) {
584 if (family == AF_INET)
585 client_ipv4_udp_writer("127.0.0.1");
586 else
587 client_ipv6_udp_writer("::1");
588 }
589
590 /* Set an alarm, since if the client malfunctions, nothing happens. */
591 alarm(5);
592
593 /* Wait for the UDP packet and then read and confirm it. */
594 fd = network_wait_any(fds, count);
595 ok(fd != INVALID_SOCKET, "network_wait_any found UDP message");
596 if (fd == INVALID_SOCKET)
597 ok_block(3, false, "could not accept client");
598 else {
599 saddr = (struct sockaddr *) &addr;
600 addrlen = sizeof(addr);
601 length = recvfrom(fd, buffer, sizeof(buffer), 0, saddr, &addrlen);
602 is_int(13, length, "...of correct length");
603 is_int(family, saddr->sa_family, "...from correct family");
604 buffer[13] = '\0';
605 is_string("socket test\r\n", buffer, "...and correct contents");
606 }
607
608 /* Wait for the child and be sure it exited successfully. */
609 waitpid(child, &status, 0);
610 is_int(0, status, "client made correct connections");
611
612 /* Clean up. */
613 for (i = 0; i < count; i++)
614 socket_close(fds[i]);
615 network_bind_all_free(fds);
616 }
617
618
619 int
main(void)620 main(void)
621 {
622 /* Set up the plan. */
623 plan(42);
624
625 /* Test network_bind functions. */
626 test_ipv4(NULL);
627 test_ipv4("127.0.0.1");
628
629 /*
630 * Optionally test IPv6 support. If IPv6 support appears to be available
631 * but doesn't work, we have to explicitly skip test_all, since it will
632 * create a socket that we then can't connect to.
633 */
634 if (ipv6_works()) {
635 test_ipv6(NULL);
636 test_ipv6("::1");
637 test_all(NULL, NULL);
638 test_all("127.0.0.1", "::1");
639 } else {
640 skip_block(24, "IPv6 not configured");
641 }
642
643 /* Test network_accept_any. */
644 test_any();
645
646 /* Test UDP socket handling and network_wait_any. */
647 test_any_udp();
648 return 0;
649 }
650