1 /*
2 * Test network address functions for IPv4.
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, 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 "inn/network.h"
40 #include "tap/basic.h"
41
42
43 /*
44 * Tests network_addr_compare. Takes the expected result, the two addresses,
45 * and the mask.
46 */
47 static void
is_addr_compare(bool expected,const char * a,const char * b,const char * mask)48 is_addr_compare(bool expected, const char *a, const char *b, const char *mask)
49 {
50 const char *smask = (mask == NULL) ? "(null)" : mask;
51
52 if (expected)
53 ok(network_addr_match(a, b, mask), "compare %s %s %s", a, b, smask);
54 else
55 ok(!network_addr_match(a, b, mask), "compare %s %s %s", a, b, smask);
56 }
57
58
59 int
main(void)60 main(void)
61 {
62 #ifdef SO_REUSEADDR
63 int flag;
64 socklen_t flaglen;
65 #endif
66 int status;
67 struct addrinfo *ai, *ai2;
68 struct addrinfo hints;
69 char addr[INET6_ADDRSTRLEN];
70 socket_type fd;
71 static const char *port = "119";
72
73 /* Set up the plan. */
74 plan(31);
75
76 /* Get a sockaddr to use for subsequent tests. */
77 memset(&hints, 0, sizeof(hints));
78 hints.ai_flags = AI_NUMERICHOST;
79 hints.ai_socktype = SOCK_STREAM;
80 status = getaddrinfo("127.0.0.1", port, &hints, &ai);
81 if (status != 0)
82 bail("getaddrinfo on 127.0.0.1 failed: %s", gai_strerror(status));
83
84 /* Test network_sockaddr_sprint. */
85 ok(network_sockaddr_sprint(addr, sizeof(addr), ai->ai_addr),
86 "sprint of 127.0.0.1");
87 is_string("127.0.0.1", addr, "...with right results");
88
89 /* Test network_sockaddr_port. */
90 is_int(119, network_sockaddr_port(ai->ai_addr), "sockaddr_port");
91
92 /* Test network_sockaddr_equal. */
93 ok(network_sockaddr_equal(ai->ai_addr, ai->ai_addr), "sockaddr_equal");
94 status = getaddrinfo("127.0.0.2", NULL, &hints, &ai2);
95 if (status != 0)
96 bail("getaddrinfo on 127.0.0.2 failed: %s", gai_strerror(status));
97 ok(!network_sockaddr_equal(ai->ai_addr, ai2->ai_addr),
98 "sockaddr_equal of unequal addresses");
99 ok(!network_sockaddr_equal(ai2->ai_addr, ai->ai_addr),
100 "...and the other way around");
101 freeaddrinfo(ai2);
102
103 /* Check the domains of functions and their error handling. */
104 ai->ai_addr->sa_family = AF_UNIX;
105 ok(!network_sockaddr_equal(ai->ai_addr, ai->ai_addr),
106 "network_sockaddr_equal returns false for equal AF_UNIX addresses");
107 is_int(0, network_sockaddr_port(ai->ai_addr),
108 "port meaningless for AF_UNIX");
109 freeaddrinfo(ai);
110
111 /* Tests for network_addr_compare. */
112 /* clang-format off */
113 is_addr_compare(1, "127.0.0.1", "127.0.0.1", NULL);
114 is_addr_compare(0, "127.0.0.1", "127.0.0.2", NULL);
115 is_addr_compare(1, "127.0.0.1", "127.0.0.0", "31");
116 is_addr_compare(0, "127.0.0.1", "127.0.0.0", "32");
117 is_addr_compare(0, "127.0.0.1", "127.0.0.0", "255.255.255.255");
118 is_addr_compare(1, "127.0.0.1", "127.0.0.0", "255.255.255.254");
119 is_addr_compare(1, "10.10.4.5", "10.10.4.255", "24");
120 is_addr_compare(0, "10.10.4.5", "10.10.4.255", "25");
121 is_addr_compare(1, "10.10.4.5", "10.10.4.255", "255.255.255.0");
122 is_addr_compare(0, "10.10.4.5", "10.10.4.255", "255.255.255.128");
123 is_addr_compare(0, "129.0.0.0", "1.0.0.0", "1");
124 is_addr_compare(1, "129.0.0.0", "1.0.0.0", "0");
125 is_addr_compare(1, "129.0.0.0", "1.0.0.0", "0.0.0.0");
126 /* clang-format on */
127
128 /* Test some invalid addresses. */
129 /* clang-format off */
130 is_addr_compare(0, "fred", "fred", NULL);
131 is_addr_compare(0, "", "", NULL);
132 is_addr_compare(0, "", "", "0");
133 is_addr_compare(0, "127.0.0.1", "127.0.0.1", "pete");
134 is_addr_compare(0, "127.0.0.1", "127.0.0.1", "1p");
135 is_addr_compare(0, "127.0.0.1", "127.0.0.1", "1p");
136 is_addr_compare(0, "127.0.0.1", "127.0.0.1", "-1");
137 is_addr_compare(0, "127.0.0.1", "127.0.0.1", "33");
138 /* clang-format on */
139
140 /* Test setting various socket options. */
141 fd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
142 if (fd == INVALID_SOCKET)
143 sysbail("cannot create socket");
144 network_set_reuseaddr(fd);
145 #ifdef SO_REUSEADDR
146 flag = 0;
147 flaglen = sizeof(flag);
148 is_int(0, getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, &flaglen),
149 "Getting SO_REUSEADDR works");
150 ok(flag, "...and it is set");
151 #else
152 skip_block(2, "SO_REUSEADDR not supported");
153 #endif
154 close(fd);
155 return 0;
156 }
157