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 
12 Describe (pcap);
13 BeforeEach (pcap)
14 {
15  cgreen_mocks_are (loose_mocks);
16 }
17 AfterEach (pcap)
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 
33 bool g_socket_use_real = true;
34 int
35 __wrap_socket (__attribute__ ((unused)) int domain,
36  __attribute__ ((unused)) int type,
37  __attribute__ ((unused)) int protocol);
38 
39 int
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 
51 int
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);
57 int
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. */
71 Ensure (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. */
99 Ensure (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. */
122 Ensure (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. */
129 Ensure (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. */
157 Ensure (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 
243 static void
244 apply_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 
283 static 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 
299 int
300 main (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 }
openvas_routethrough
static TestSuite * openvas_routethrough()
Definition: pcap_tests.c:284
__attribute__
__attribute__((weak))
Definition: pcap_tests.c:21
BeforeEach
BeforeEach(pcap)
Definition: pcap_tests.c:13
ipv6_prefix_to_mask
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
protocol
u_char protocol
Definition: nasl_packet_forgery.c:3
g_setsockopt_use_real
bool g_setsockopt_use_real
Definition: pcap_tests.c:50
islocalhost
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
Describe
Describe(pcap)
Ensure
Ensure(pcap, routethrough_dst_is_localhost)
Definition: pcap_tests.c:71
AfterEach
AfterEach(pcap)
Definition: pcap_tests.c:17
v6_islocalhost
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
main
int main(int argc, char **argv)
Definition: pcap_tests.c:300
pcap.c
routethrough
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
apply_ipv6_mask
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
__wrap_setsockopt
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