OpenVAS Scanner 22.7.9
pcap_tests.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Greenbone AG
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6#include "pcap.c"
7
8#include <cgreen/cgreen.h>
9#include <cgreen/mocks.h>
10#include <gvm/base/hosts.h>
11
12Describe (pcap);
14{
15 cgreen_mocks_are (loose_mocks);
16}
18{
19}
20
21__attribute__ ((weak)) int
22__real_socket (__attribute__ ((unused)) int domain,
23 __attribute__ ((unused)) int type,
24 __attribute__ ((unused)) int protocol);
25
26__attribute__ ((weak)) int
27__real_setsockopt (__attribute__ ((unused)) int sockfd,
28 __attribute__ ((unused)) int level,
29 __attribute__ ((unused)) int optname,
30 __attribute__ ((unused)) const void *optval,
31 __attribute__ ((unused)) socklen_t optlen);
32
33bool g_socket_use_real = true;
34int
35__wrap_socket (__attribute__ ((unused)) int domain,
36 __attribute__ ((unused)) int type,
37 __attribute__ ((unused)) int protocol);
38
39int
40__wrap_socket (__attribute__ ((unused)) int domain,
41 __attribute__ ((unused)) int type,
42 __attribute__ ((unused)) int protocol)
43{
44 if (g_socket_use_real)
45 return __real_socket (domain, type, protocol);
46
47 return (int) mock (domain, type, protocol);
48}
49
51int
52__wrap_setsockopt (__attribute__ ((unused)) int sockfd,
53 __attribute__ ((unused)) int level,
54 __attribute__ ((unused)) int optname,
55 __attribute__ ((unused)) const void *optval,
56 __attribute__ ((unused)) socklen_t optlen);
57int
58__wrap_setsockopt (__attribute__ ((unused)) int sockfd,
59 __attribute__ ((unused)) int level,
60 __attribute__ ((unused)) int optname,
61 __attribute__ ((unused)) const void *optval,
62 __attribute__ ((unused)) socklen_t optlen)
63{
65 return __real_setsockopt (sockfd, level, optname, optval, optlen);
66
67 return (int) mock (sockfd, level, optname, optval, optlen);
68}
69
70/* If dst for routethrough() is localhost "lo" interface is returned. */
71Ensure (pcap, routethrough_dst_is_localhost)
72{
73 /* setup */
74 g_socket_use_real = false;
75 gchar *interface = NULL;
76 gchar *ipv4_str = "127.0.0.1";
77 gvm_host_t *gvm_host = NULL;
78 struct in6_addr dst6;
79 struct in6_addr *dst6_p = &dst6;
80 struct in_addr dst4;
81 struct in_addr *dst4_p = &dst4;
82 assert_that ((gvm_host = gvm_host_from_str (ipv4_str)), is_not_null);
83 assert_that (gvm_host_get_addr6 ((gvm_host_t *) gvm_host, dst6_p),
84 is_equal_to (0));
85 assert_that (dst6_p, is_not_null);
86 dst4.s_addr = dst6_p->s6_addr32[3];
87
88 interface = routethrough (dst4_p, NULL);
89 (void) interface;
90
91 /* dependent on local environment */
92 // assert_that ((interface = routethrough (dst4_p, NULL)), is_not_null);
93 // assert_that (interface, is_equal_to_string ("lo"));
94 g_socket_use_real = true;
95}
96
97/* If dst is not null for routethrough() then another interface than "lo" is
98 * returned. */
99Ensure (pcap, routethrough_dst_is_not_localhost)
100{
101 g_socket_use_real = false;
102 /* setup */
103 gchar *interface = NULL;
104 gchar *ipv4_str = "93.184.216.34"; /* example.com */
105 gvm_host_t *gvm_host = NULL;
106 struct in6_addr dst6;
107 struct in6_addr *dst6_p = &dst6;
108 struct in_addr dst4;
109 struct in_addr *dst4_p = &dst4;
110 assert_that ((gvm_host = gvm_host_from_str (ipv4_str)), is_not_null);
111 assert_that (gvm_host_get_addr6 ((gvm_host_t *) gvm_host, dst6_p),
112 is_equal_to (0));
113 assert_that (dst6_p, is_not_null);
114 dst4.s_addr = dst6_p->s6_addr32[3];
115
116 interface = routethrough (dst4_p, NULL);
117 assert_that (interface, is_not_equal_to_string ("lo"));
118 g_socket_use_real = true;
119}
120
121/* If neither dst nor src address are given to routethrough NULL is returned. */
122Ensure (pcap, routethrough_no_src_dst_given)
123{
124 gchar *interface = NULL;
125 assert_that ((interface = routethrough (NULL, NULL)), is_null);
126}
127
128/* If global_source_addr is present then routethrough writes it into src. */
129Ensure (pcap, routethrough_src_globalsource_set)
130{
131 /* setup */
132 g_socket_use_real = false;
133 cgreen_mocks_are (learning_mocks);
134
135 struct in_addr src = {.s_addr = 0}; /* ip src */
136 gchar *interface = NULL;
137 struct in_addr dst;
138 inet_pton (AF_INET, "93.184.216.34", &(dst.s_addr));
139
140 /* global source address set */
141 gvm_source_iface_init ("lo"); // lo is set but not really used after being set
142 /* dst not given */
143 assert_that ((interface = routethrough (NULL, &src)), is_null);
144 assert_that ((src.s_addr == INADDR_ANY));
145 /* dst localhost given */
146 src.s_addr = 0;
147
148 interface = routethrough (&dst, &src);
149 /* dependent on local environment */
150 // assert_that ((interface = routethrough (&dst, &src)), is_not_null);
151 assert_that (interface, is_not_equal_to_string ("lo"));
152 assert_that ((src.s_addr != INADDR_ANY));
153 g_socket_use_real = true;
154}
155
156/* If global_source_addr is not present then routethrough writes it into src. */
157Ensure (pcap, routethrough_src_globalsource_not_set)
158{
159 g_socket_use_real = false;
160
161 struct in_addr src = {.s_addr = 0}; /* ip src */
162 gchar *interface = NULL;
163 struct in_addr dst;
164 inet_pton (AF_INET, "127.0.0.1", &(dst.s_addr));
165
166 /* global source address not set */
167 gvm_source_iface_init (NULL);
168 /* dst not given */
169 assert_that ((interface = routethrough (NULL, &src)), is_null);
170 assert_that ((src.s_addr == INADDR_ANY));
171 /* dst localhost given */
172 src.s_addr = 0;
173
174 interface = routethrough (&dst, &src);
175 /* dependent on local environment */
176 // assert_that ((interface = routethrough (&dst, &src)), is_not_null);
177 // assert_that (interface, is_equal_to_string ("lo"));
178 assert_that ((src.s_addr != INADDR_ANY));
179 g_socket_use_real = true;
180}
181
183{
184 /* IPv4 */
185 struct in_addr addr;
186 struct sockaddr_in sin;
187 memset (&sin, 0, sizeof (struct sockaddr_in));
188 sin.sin_family = AF_INET;
189
190 /* example.com */
191 inet_pton (AF_INET, "93.184.216.34", &(addr.s_addr));
192
193 /* IPv6 */
194 struct in6_addr addr_6;
195
196 inet_pton (AF_INET6, "::FFFF:127.0.0.1", &(addr_6));
197 assert_that (v6_islocalhost (&addr_6), is_true);
198 inet_pton (AF_INET6, "::FFFF:0.0.0.0", &(addr_6));
199 assert_that (v6_islocalhost (&addr_6), is_true);
200 inet_pton (AF_INET6, "::FFFF:127.100.5.99", &(addr_6));
201 assert_that (v6_islocalhost (&addr_6), is_true);
202 /* loopback address */
203 inet_pton (AF_INET6, "0:0:0:0:0:0:0:1", &(addr_6));
204 assert_that (v6_islocalhost (&addr_6), is_true);
205
206 /* dependent on local environment */
207 // inet_pton (AF_INET6, <some local interface address>, &(addr_6));
208 // assert_that (v6_islocalhost (&addr_6), is_true);
209
210 /* example.com */
211 inet_pton (AF_INET6, "2606:2800:220:1:248:1893:25c8:1946", &(addr_6));
212 assert_that (v6_islocalhost (&addr_6), is_false);
213}
214
216{
217 /* IPv4 */
218 struct in_addr addr;
219
220 inet_pton (AF_INET, "127.0.0.1", &(addr.s_addr));
221 assert_that (islocalhost (&addr), is_true);
222 inet_pton (AF_INET, "0.0.0.0", &(addr.s_addr));
223 assert_that (islocalhost (&addr), is_true);
224 inet_pton (AF_INET, "127.100.5.99", &(addr.s_addr));
225 assert_that (islocalhost (&addr), is_true);
226
227 /* dependent on local environment */
228 // // inet_pton (AF_INET, <some local interface address>, &(addr));
229 // // assert_that (islocalhost (&addr), is_true);
230
231 /* example.com */
232 inet_pton (AF_INET, "93.184.216.34", &(addr.s_addr));
233 assert_that (islocalhost (&addr), is_false);
234}
235
243static void
244apply_ipv6_mask (struct in6_addr *network, struct in6_addr *dest,
245 struct in6_addr *mask)
246{
247 for (int i = 0; i < (int) sizeof (struct in6_addr); i++)
248 network->s6_addr[i] = dest->s6_addr[i] & mask->s6_addr[i];
249}
250
252{
253 struct in6_addr dest;
254 struct in6_addr result;
255 struct in6_addr mask;
256 struct in6_addr network;
257 const uint8_t byte_options[9] = {0xFF, 0x00, 0x80, 0xC0, 0xE0,
258 0xF0, 0xF8, 0xFC, 0xFE};
259
260 // create dst addr
261 const uint8_t addr_in[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
262 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
263 memcpy (dest.s6_addr, addr_in, sizeof addr_in);
264 // create expected result addr
265 const uint8_t result_in[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
266 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
267 0xFF, 0xFF, 0xFF, 0xFF};
268 memcpy (result.s6_addr, result_in, sizeof result_in);
269
270 // check every possible bit mask
271 for (int i = 128; i > 0; i--)
272 {
273 ipv6_prefix_to_mask (i, &mask);
274 apply_ipv6_mask (&network, &dest, &mask);
275 int byte_to_modify = i / 8;
276 if (byte_to_modify != 16)
277 result.s6_addr[byte_to_modify] = byte_options[(i % 8) + 1];
278
279 assert_that (IN6_ARE_ADDR_EQUAL (&network, &result));
280 }
281}
282
283static TestSuite *
285{
286 TestSuite *suite = create_test_suite ();
287 add_test_with_context (suite, pcap, routethrough_dst_is_localhost);
288 add_test_with_context (suite, pcap, routethrough_dst_is_not_localhost);
289 add_test_with_context (suite, pcap, routethrough_no_src_dst_given);
290 add_test_with_context (suite, pcap, routethrough_src_globalsource_set);
291 add_test_with_context (suite, pcap, routethrough_src_globalsource_not_set);
292 add_test_with_context (suite, pcap, v6_islocalhost);
293 add_test_with_context (suite, pcap, islocalhost);
294 add_test_with_context (suite, pcap, ipv6_prefix_to_mask);
295
296 return suite;
297}
298
299int
300main (int argc, char **argv)
301{
302 TestSuite *suite;
303
304 suite = create_test_suite ();
305 add_suite (suite, openvas_routethrough ());
306
307 if (argc > 1)
308 return run_single_test (suite, argv[1], create_text_reporter ());
309
310 return run_test_suite (suite, create_text_reporter ());
311}
u_char protocol
struct pseudo_udp_hdr __attribute__
int islocalhost(struct in_addr *addr)
Tests whether a packet sent to IP is LIKELY to route through the kernel localhost interface.
Definition: pcap.c:261
char * routethrough(struct in_addr *dest, struct in_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition: pcap.c:1060
int v6_islocalhost(struct in6_addr *addr)
Tests whether a packet sent to IP is LIKELY to route through the kernel localhost interface.
Definition: pcap.c:224
static int ipv6_prefix_to_mask(unsigned prefix, struct in6_addr *mask)
Generate an ipv6 mask from the given ipv6 prefix.
Definition: pcap.c:82
int __wrap_setsockopt(__attribute__((unused)) int sockfd, __attribute__((unused)) int level, __attribute__((unused)) int optname, __attribute__((unused)) const void *optval, __attribute__((unused)) socklen_t optlen)
Definition: pcap_tests.c:58
BeforeEach(pcap)
Definition: pcap_tests.c:13
AfterEach(pcap)
Definition: pcap_tests.c:17
Ensure(pcap, routethrough_dst_is_localhost)
Definition: pcap_tests.c:71
int main(int argc, char **argv)
Definition: pcap_tests.c:300
bool g_setsockopt_use_real
Definition: pcap_tests.c:50
Describe(pcap)
static void apply_ipv6_mask(struct in6_addr *network, struct in6_addr *dest, struct in6_addr *mask)
Apply mask to dest addr.
Definition: pcap_tests.c:244
static TestSuite * openvas_routethrough()
Definition: pcap_tests.c:284