source: web/old/remctl-2.14/tests/util/network-t.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 13.2 KB
Line 
1/*
2 * network test suite.
3 *
4 * Written by Russ Allbery <rra@stanford.edu>
5 * Copyright 2009 Board of Trustees, Leland Stanford Jr. University
6 * Copyright (c) 2004, 2005, 2006, 2007
7 *     by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
9 *     2002, 2003 by The Internet Software Consortium and Rich Salz
10 *
11 * See LICENSE for licensing terms.
12 */
13
14#include <config.h>
15#include <portable/system.h>
16#include <portable/socket.h>
17
18#include <ctype.h>
19#include <errno.h>
20#include <sys/wait.h>
21
22#include <tests/tap/basic.h>
23#include <util/util.h>
24
25/* Set this globally to 0 if IPv6 is available but doesn't work. */
26static int ipv6 = 1;
27
28/*
29 * The server portion of the test.  Listens to a socket and accepts a
30 * connection, making sure what is printed on that connection matches what the
31 * client is supposed to print.
32 */
33static void
34listener(int fd)
35{
36    int client;
37    FILE *out;
38    char buffer[512];
39
40    client = accept(fd, NULL, NULL);
41    close(fd);
42    if (client < 0) {
43        sysnotice("# cannot accept connection from socket");
44        ok_block(2, 0, "...socket read test");
45    }
46    ok(1, "...socket accept");
47    out = fdopen(client, "r");
48    if (fgets(buffer, sizeof(buffer), out) == NULL) {
49        sysnotice("# cannot read from socket");
50        ok(0, "...socket read");
51    }
52    is_string("socket test\r\n", buffer, "...socket read");
53    fclose(out);
54}
55
56
57/*
58 * Connect to the given host on port 11119 and send a constant string to a
59 * socket, used to do the client side of the testing.  Takes the source
60 * address as well to pass into network_connect_host.
61 */
62static void
63client(const char *host, const char *source)
64{
65    int fd;
66    FILE *out;
67
68    fd = network_connect_host(host, 11119, source);
69    if (fd < 0)
70        sysdie("connect failed");
71    out = fdopen(fd, "w");
72    if (out == NULL)
73        sysdie("fdopen failed");
74    fputs("socket test\r\n", out);
75    fclose(out);
76    _exit(0);
77}
78
79
80/*
81 * Bring up a server on port 11119 on the loopback address and test connecting
82 * to it via IPv4.  Takes an optional source address to use for client
83 * connections.
84 */
85static void
86test_ipv4(const char *source)
87{
88    int fd;
89    pid_t child;
90
91    fd = network_bind_ipv4("127.0.0.1", 11119);
92    if (fd < 0)
93        sysbail("cannot create or bind socket");
94    if (listen(fd, 1) < 0) {
95        sysnotice("# cannot listen to socket");
96        ok_block(3, 0, "IPv4 server test");
97    } else {
98        ok(1, "IPv4 server test");
99        child = fork();
100        if (child < 0)
101            sysbail("cannot fork");
102        else if (child == 0)
103            client("127.0.0.1", source);
104        else {
105            listener(fd);
106            waitpid(child, NULL, 0);
107        }
108    }
109}
110
111
112/*
113 * Bring up a server on port 11119 on the loopback address and test connecting
114 * to it via IPv6.  Takes an optional source address to use for client
115 * connections.
116 */
117#ifdef HAVE_INET6
118static void
119test_ipv6(const char *source)
120{
121    int fd;
122    pid_t child;
123
124    fd = network_bind_ipv6("::1", 11119);
125    if (fd < 0) {
126        if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT
127            || errno == EADDRNOTAVAIL) {
128            ipv6 = 0;
129            skip_block(3, "IPv6 not supported");
130        } else
131            sysbail("cannot create socket");
132    }
133    if (listen(fd, 1) < 0) {
134        sysnotice("# cannot listen to socket");
135        ok_block(3, 0, "IPv6 server test");
136    } else {
137        ok(1, "IPv6 server test");
138        child = fork();
139        if (child < 0)
140            sysbail("cannot fork");
141        else if (child == 0)
142            client("::1", source);
143        else {
144            listener(fd);
145            waitpid(child, NULL, 0);
146        }
147    }
148}
149#else /* !HAVE_INET6 */
150static void
151test_ipv6(const char *source UNUSED)
152{
153    skip_block(3, "IPv6 not supported");
154}
155#endif /* !HAVE_INET6 */
156
157
158/*
159 * Bring up a server on port 11119 on all addresses and try connecting to it
160 * via all of the available protocols.  Takes an optional source address to
161 * use for client connections.
162 */
163static void
164test_all(const char *source_ipv4, const char *source_ipv6)
165{
166    int *fds, count, fd, i;
167    pid_t child;
168    struct sockaddr_storage saddr;
169    socklen_t size = sizeof(saddr);
170
171    network_bind_all(11119, &fds, &count);
172    if (count == 0)
173        sysbail("cannot create or bind socket");
174    if (count > 2) {
175        notice("# got more than two sockets, using just the first two");
176        count = 2;
177    }
178    for (i = 0; i < count; i++) {
179        fd = fds[i];
180        if (listen(fd, 1) < 0) {
181            sysnotice("# cannot listen to socket %d", fd);
182            ok_block(3, 0, "all address server test");
183        } else {
184            ok(1, "all address server test (part %d)", i);
185            child = fork();
186            if (child < 0)
187                sysbail("cannot fork");
188            else if (child == 0) {
189                if (getsockname(fd, (struct sockaddr *) &saddr, &size) < 0)
190                    sysbail("cannot getsockname");
191                if (saddr.ss_family == AF_INET)
192                    client("127.0.0.1", source_ipv4);
193#ifdef HAVE_INET6
194                else if (saddr.ss_family == AF_INET6)
195                    client("::1", source_ipv6);
196#endif
197                else
198                    skip_block(2, "unknown socket family %d", saddr.ss_family);
199                size = sizeof(saddr);
200            } else {
201                listener(fd);
202                waitpid(child, NULL, 0);
203            }
204        }
205    }
206    if (count == 1)
207        skip_block(3, "only one listening socket");
208}
209
210
211/*
212 * Bring up a server on port 11119 on the loopback address and test connecting
213 * to it via IPv4 using network_client_create.  Takes an optional source
214 * address to use for client connections.
215 */
216static void
217test_create_ipv4(const char *source)
218{
219    int fd;
220    pid_t child;
221
222    fd = network_bind_ipv4("127.0.0.1", 11119);
223    if (fd < 0)
224        sysbail("cannot create or bind socket");
225    if (listen(fd, 1) < 0) {
226        sysnotice("# cannot listen to socket");
227        ok_block(3, 0, "IPv4 network client");
228    } else {
229        ok(1, "IPv4 network client");
230        child = fork();
231        if (child < 0)
232            sysbail("cannot fork");
233        else if (child == 0) {
234            struct sockaddr_in sin;
235            FILE *out;
236
237            fd = network_client_create(PF_INET, SOCK_STREAM, source);
238            if (fd < 0)
239                _exit(1);
240            sin.sin_family = AF_INET;
241            sin.sin_port = htons(11119);
242            sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
243            if (connect(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
244                _exit(1);
245            out = fdopen(fd, "w");
246            if (out == NULL)
247                _exit(1);
248            fputs("socket test\r\n", out);
249            fclose(out);
250            _exit(0);
251        } else {
252            listener(fd);
253            waitpid(child, NULL, 0);
254        }
255    }
256}
257
258
259/*
260 * Tests network_addr_compare.  Takes the expected result, the two addresses,
261 * and the mask.
262 */
263static void
264ok_addr(int expected, const char *a, const char *b, const char *mask)
265{
266    if (expected)
267        ok(network_addr_match(a, b, mask), "compare %s %s %s", a, b, mask);
268    else
269        ok(!network_addr_match(a, b, mask), "compare %s %s %s", a, b, mask);
270}
271
272
273int
274main(void)
275{
276    int status;
277    struct addrinfo *ai, *ai4;
278    struct addrinfo hints;
279    char addr[INET6_ADDRSTRLEN];
280    static const char *port = "119";
281
282#ifdef HAVE_INET6
283    struct addrinfo *ai6;
284    char *p;
285    static const char *ipv6_addr = "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210";
286#endif
287
288    plan(87);
289
290    /*
291     * If IPv6 support appears to be available but doesn't work, we have to
292     * skip the test_all tests since they'll create a socket that we then
293     * can't connect to.  This is the case on Solaris 8 without IPv6
294     * configured.
295     */
296    test_ipv4(NULL);
297    test_ipv6(NULL);
298    if (ipv6)
299        test_all(NULL, NULL);
300    else
301        skip_block(6, "IPv6 not configured");
302    test_create_ipv4(NULL);
303
304    /* This won't make a difference for loopback connections. */
305    test_ipv4("127.0.0.1");
306    test_ipv6("::1");
307    if (ipv6)
308        test_all("127.0.0.1", "::1");
309    else
310        skip_block(6, "IPv6 not configured");
311    test_create_ipv4("127.0.0.1");
312
313    /*
314     * Now, test network_sockaddr_sprint, network_sockaddr_equal, and
315     * network_sockaddr_port.
316     */
317    memset(&hints, 0, sizeof(hints));
318    hints.ai_flags = AI_NUMERICHOST;
319    hints.ai_socktype = SOCK_STREAM;
320    status = getaddrinfo("127.0.0.1", port, &hints, &ai4);
321    if (status != 0)
322        bail("getaddrinfo on 127.0.0.1 failed: %s", gai_strerror(status));
323    ok(network_sockaddr_sprint(addr, sizeof(addr), ai4->ai_addr),
324       "sprint of 127.0.0.1");
325    is_string("127.0.0.1", addr, "...with right results");
326    is_int(119, network_sockaddr_port(ai4->ai_addr),
327           "sockaddr_port");
328    ok(network_sockaddr_equal(ai4->ai_addr, ai4->ai_addr), "sockaddr_equal");
329    status = getaddrinfo("127.0.0.2", NULL, &hints, &ai);
330    if (status != 0)
331        bail("getaddrinfo on 127.0.0.2 failed: %s", gai_strerror(status));
332    ok(!network_sockaddr_equal(ai->ai_addr, ai4->ai_addr),
333       "sockaddr_equal of unequal addresses");
334    ok(!network_sockaddr_equal(ai4->ai_addr, ai->ai_addr),
335       "...and the other way around");
336
337    /* The same for IPv6. */
338#ifdef HAVE_INET6
339    status = getaddrinfo(ipv6_addr, port, &hints, &ai6);
340    if (status != 0)
341        bail("getaddr on %s failed: %s", ipv6_addr, gai_strerror(status));
342    ok(network_sockaddr_sprint(addr, sizeof(addr), ai6->ai_addr),
343       "sprint of IPv6 address");
344    for (p = addr; *p != '\0'; p++)
345        if (islower((unsigned char) *p))
346            *p = toupper((unsigned char) *p);
347    is_string(ipv6_addr, addr, "...with right results");
348    is_int(119, network_sockaddr_port(ai6->ai_addr), "sockaddr_port IPv6");
349    ok(network_sockaddr_equal(ai6->ai_addr, ai6->ai_addr),
350       "sockaddr_equal IPv6");
351    ok(!network_sockaddr_equal(ai4->ai_addr, ai6->ai_addr),
352       "...and not equal to IPv4");
353    ok(!network_sockaddr_equal(ai6->ai_addr, ai4->ai_addr),
354       "...other way around");
355
356    /* Test IPv4 mapped addresses. */
357    status = getaddrinfo("::ffff:7f00:1", NULL, &hints, &ai6);
358    if (status != 0)
359        bail("getaddr on ::ffff:7f00:1 failed: %s", gai_strerror(status));
360    ok(network_sockaddr_sprint(addr, sizeof(addr), ai6->ai_addr),
361       "sprint of IPv4-mapped address");
362    is_string("127.0.0.1", addr, "...with right IPv4 result");
363    ok(network_sockaddr_equal(ai4->ai_addr, ai6->ai_addr),
364       "sockaddr_equal of IPv4-mapped address");
365    ok(network_sockaddr_equal(ai6->ai_addr, ai4->ai_addr),
366       "...and other way around");
367    ok(!network_sockaddr_equal(ai->ai_addr, ai6->ai_addr),
368       "...but not some other address");
369    ok(!network_sockaddr_equal(ai6->ai_addr, ai->ai_addr),
370       "...and the other way around");
371    freeaddrinfo(ai6);
372#else
373    skip_block(12, "IPv6 not supported");
374#endif
375
376    /* Check the domains of functions and their error handling. */
377    ai4->ai_addr->sa_family = AF_UNIX;
378    ok(!network_sockaddr_equal(ai4->ai_addr, ai4->ai_addr),
379       "equal not equal with address mismatches");
380    is_int(0, network_sockaddr_port(ai4->ai_addr),
381           "port meaningless for AF_UNIX");
382
383    /* Tests for network_addr_compare. */
384    ok_addr(1, "127.0.0.1", "127.0.0.1",   NULL);
385    ok_addr(0, "127.0.0.1", "127.0.0.2",   NULL);
386    ok_addr(1, "127.0.0.1", "127.0.0.0",   "31");
387    ok_addr(0, "127.0.0.1", "127.0.0.0",   "32");
388    ok_addr(0, "127.0.0.1", "127.0.0.0",   "255.255.255.255");
389    ok_addr(1, "127.0.0.1", "127.0.0.0",   "255.255.255.254");
390    ok_addr(1, "10.10.4.5", "10.10.4.255", "24");
391    ok_addr(0, "10.10.4.5", "10.10.4.255", "25");
392    ok_addr(1, "10.10.4.5", "10.10.4.255", "255.255.255.0");
393    ok_addr(0, "10.10.4.5", "10.10.4.255", "255.255.255.128");
394    ok_addr(0, "129.0.0.0", "1.0.0.0",     "1");
395    ok_addr(1, "129.0.0.0", "1.0.0.0",     "0");
396    ok_addr(1, "129.0.0.0", "1.0.0.0",     "0.0.0.0");
397
398    /* Try some IPv6 addresses. */
399#ifdef HAVE_INET6
400    ok_addr(1, ipv6_addr,   ipv6_addr,     NULL);
401    ok_addr(1, ipv6_addr,   ipv6_addr,     "128");
402    ok_addr(1, ipv6_addr,   ipv6_addr,     "60");
403    ok_addr(1, "::127",     "0:0::127",    "128");
404    ok_addr(1, "::127",     "0:0::128",    "120");
405    ok_addr(0, "::127",     "0:0::128",    "128");
406    ok_addr(0, "::7fff",    "0:0::8000",   "113");
407    ok_addr(1, "::7fff",    "0:0::8000",   "112");
408    ok_addr(0, "::3:ffff",  "::2:ffff",    "120");
409    ok_addr(0, "::3:ffff",  "::2:ffff",    "119");
410    ok_addr(0, "ffff::1",   "7fff::1",     "1");
411    ok_addr(1, "ffff::1",   "7fff::1",     "0");
412    ok_addr(0, "fffg::1",   "fffg::1",     NULL);
413    ok_addr(0, "ffff::1",   "7fff::1",     "-1");
414    ok_addr(0, "ffff::1",   "ffff::1",     "-1");
415    ok_addr(0, "ffff::1",   "ffff::1",     "129");
416#else
417    skip_block(16, "IPv6 not supported");
418#endif
419
420    /* Test some invalid addresses. */
421    ok_addr(0, "fred",      "fred",        NULL);
422    ok_addr(0, "",          "",            NULL);
423    ok_addr(0, "",          "",            "0");
424    ok_addr(0, "127.0.0.1", "127.0.0.1",   "pete");
425    ok_addr(0, "127.0.0.1", "127.0.0.1",   "1p");
426    ok_addr(0, "127.0.0.1", "127.0.0.1",   "1p");
427    ok_addr(0, "127.0.0.1", "127.0.0.1",   "-1");
428    ok_addr(0, "127.0.0.1", "127.0.0.1",   "33");
429
430    return 0;
431}
Note: See TracBrowser for help on using the repository browser.