OpenVAS Scanner 23.40.3
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 gvm_host_free (gvm_host);
97}
98
99/* If dst is not null for routethrough() then another interface than "lo" is
100 * returned. */
101Ensure (pcap, routethrough_dst_is_not_localhost)
102{
103 g_socket_use_real = false;
104 /* setup */
105 gchar *interface = NULL;
106 gchar *ipv4_str = "93.184.216.34"; /* example.com */
107 gvm_host_t *gvm_host = NULL;
108 struct in6_addr dst6;
109 struct in6_addr *dst6_p = &dst6;
110 struct in_addr dst4;
111 struct in_addr *dst4_p = &dst4;
112 assert_that ((gvm_host = gvm_host_from_str (ipv4_str)), is_not_null);
113 assert_that (gvm_host_get_addr6 ((gvm_host_t *) gvm_host, dst6_p),
114 is_equal_to (0));
115 assert_that (dst6_p, is_not_null);
116 dst4.s_addr = dst6_p->s6_addr32[3];
117
118 interface = routethrough (dst4_p, NULL);
119 assert_that (interface, is_not_equal_to_string ("lo"));
120 g_socket_use_real = true;
121
122 gvm_host_free (gvm_host);
123}
124
125/* If neither dst nor src address are given to routethrough NULL is returned. */
126Ensure (pcap, routethrough_no_src_dst_given)
127{
128 gchar *interface = NULL;
129 assert_that ((interface = routethrough (NULL, NULL)), is_null);
130}
131
132/* If global_source_addr is present then routethrough writes it into src. */
133Ensure (pcap, routethrough_src_globalsource_set)
134{
135 /* setup */
136 g_socket_use_real = false;
137 cgreen_mocks_are (learning_mocks);
138
139 struct in_addr src = {.s_addr = 0}; /* ip src */
140 gchar *interface = NULL;
141 struct in_addr dst;
142 inet_pton (AF_INET, "93.184.216.34", &(dst.s_addr));
143
144 /* global source address set */
145 gvm_source_iface_init ("lo"); // lo is set but not really used after being set
146 /* dst not given */
147 assert_that ((interface = routethrough (NULL, &src)), is_null);
148 assert_that ((src.s_addr == INADDR_ANY));
149 /* dst localhost given */
150 src.s_addr = 0;
151
152 interface = routethrough (&dst, &src);
153 /* dependent on local environment */
154 // assert_that ((interface = routethrough (&dst, &src)), is_not_null);
155 assert_that (interface, is_not_equal_to_string ("lo"));
156 assert_that ((src.s_addr != INADDR_ANY));
157 g_socket_use_real = true;
158}
159
160/* If global_source_addr is not present then routethrough writes it into src. */
161Ensure (pcap, routethrough_src_globalsource_not_set)
162{
163 g_socket_use_real = false;
164
165 struct in_addr src = {.s_addr = 0}; /* ip src */
166 gchar *interface = NULL;
167 struct in_addr dst;
168 inet_pton (AF_INET, "127.0.0.1", &(dst.s_addr));
169
170 /* global source address not set */
171 gvm_source_iface_init (NULL);
172 /* dst not given */
173 assert_that ((interface = routethrough (NULL, &src)), is_null);
174 assert_that ((src.s_addr == INADDR_ANY));
175 /* dst localhost given */
176 src.s_addr = 0;
177
178 interface = routethrough (&dst, &src);
179 /* dependent on local environment */
180 // assert_that ((interface = routethrough (&dst, &src)), is_not_null);
181 // assert_that (interface, is_equal_to_string ("lo"));
182 assert_that ((src.s_addr != INADDR_ANY));
183 g_socket_use_real = true;
184}
185
187{
188 /* IPv4 */
189 struct in_addr addr;
190 struct sockaddr_in sin;
191 memset (&sin, 0, sizeof (struct sockaddr_in));
192 sin.sin_family = AF_INET;
193
194 /* example.com */
195 inet_pton (AF_INET, "93.184.216.34", &(addr.s_addr));
196
197 /* IPv6 */
198 struct in6_addr addr_6;
199
200 inet_pton (AF_INET6, "::FFFF:127.0.0.1", &(addr_6));
201 assert_that (v6_islocalhost (&addr_6), is_true);
202 inet_pton (AF_INET6, "::FFFF:0.0.0.0", &(addr_6));
203 assert_that (v6_islocalhost (&addr_6), is_true);
204 inet_pton (AF_INET6, "::FFFF:127.100.5.99", &(addr_6));
205 assert_that (v6_islocalhost (&addr_6), is_true);
206 /* loopback address */
207 inet_pton (AF_INET6, "0:0:0:0:0:0:0:1", &(addr_6));
208 assert_that (v6_islocalhost (&addr_6), is_true);
209
210 /* dependent on local environment */
211 // inet_pton (AF_INET6, <some local interface address>, &(addr_6));
212 // assert_that (v6_islocalhost (&addr_6), is_true);
213
214 /* example.com */
215 inet_pton (AF_INET6, "2606:2800:220:1:248:1893:25c8:1946", &(addr_6));
216 assert_that (v6_islocalhost (&addr_6), is_false);
217}
218
220{
221 /* IPv4 */
222 struct in_addr addr;
223
224 inet_pton (AF_INET, "127.0.0.1", &(addr.s_addr));
225 assert_that (islocalhost (&addr), is_true);
226 inet_pton (AF_INET, "0.0.0.0", &(addr.s_addr));
227 assert_that (islocalhost (&addr), is_true);
228 inet_pton (AF_INET, "127.100.5.99", &(addr.s_addr));
229 assert_that (islocalhost (&addr), is_true);
230
231 /* dependent on local environment */
232 // // inet_pton (AF_INET, <some local interface address>, &(addr));
233 // // assert_that (islocalhost (&addr), is_true);
234
235 /* example.com */
236 inet_pton (AF_INET, "93.184.216.34", &(addr.s_addr));
237 assert_that (islocalhost (&addr), is_false);
238}
239
247static void
248apply_ipv6_mask (struct in6_addr *network, struct in6_addr *dest,
249 struct in6_addr *mask)
250{
251 for (int i = 0; i < (int) sizeof (struct in6_addr); i++)
252 network->s6_addr[i] = dest->s6_addr[i] & mask->s6_addr[i];
253}
254
256{
257 struct in6_addr dest;
258 struct in6_addr result;
259 struct in6_addr mask;
260 struct in6_addr network;
261 const uint8_t byte_options[9] = {0xFF, 0x00, 0x80, 0xC0, 0xE0,
262 0xF0, 0xF8, 0xFC, 0xFE};
263
264 // create dst addr
265 const uint8_t addr_in[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
266 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
267 memcpy (dest.s6_addr, addr_in, sizeof addr_in);
268 // create expected result addr
269 const uint8_t result_in[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
270 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
271 0xFF, 0xFF, 0xFF, 0xFF};
272 memcpy (result.s6_addr, result_in, sizeof result_in);
273
274 // check every possible bit mask
275 for (int i = 128; i > 0; i--)
276 {
277 ipv6_prefix_to_mask (i, &mask);
278 apply_ipv6_mask (&network, &dest, &mask);
279 int byte_to_modify = i / 8;
280 if (byte_to_modify != 16)
281 result.s6_addr[byte_to_modify] = byte_options[(i % 8) + 1];
282
283 assert_that (IN6_ARE_ADDR_EQUAL (&network, &result));
284 }
285}
286
287static TestSuite *
289{
290 TestSuite *suite = create_test_suite ();
291 add_test_with_context (suite, pcap, routethrough_dst_is_localhost);
292 add_test_with_context (suite, pcap, routethrough_dst_is_not_localhost);
293 add_test_with_context (suite, pcap, routethrough_no_src_dst_given);
294 add_test_with_context (suite, pcap, routethrough_src_globalsource_set);
295 add_test_with_context (suite, pcap, routethrough_src_globalsource_not_set);
296 add_test_with_context (suite, pcap, v6_islocalhost);
297 add_test_with_context (suite, pcap, islocalhost);
298 add_test_with_context (suite, pcap, ipv6_prefix_to_mask);
299
300 return suite;
301}
302
303int
304main (int argc, char **argv)
305{
306 int ret;
307 TestSuite *suite;
308
309 suite = create_test_suite ();
310 add_suite (suite, openvas_routethrough ());
311
312 if (argc > 1)
313 ret = run_single_test (suite, argv[1], create_text_reporter ());
314 else
315 ret = run_test_suite (suite, create_text_reporter ());
316
317 destroy_test_suite (suite);
318
319 return ret;
320}
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:271
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:1070
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:234
static int ipv6_prefix_to_mask(unsigned prefix, struct in6_addr *mask)
Generate an ipv6 mask from the given ipv6 prefix.
Definition pcap.c:89
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:304
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:248
static TestSuite * openvas_routethrough()
Definition pcap_tests.c:288