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