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