OpenVAS Scanner  22.7.9
capture_packet.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2023 Greenbone AG
2  * SPDX-FileCopyrightText: 2002-2004 Tenable Network Security
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include "capture_packet.h"
8 
9 #include "../misc/bpf_share.h" /* for bpf_datalink */
10 #include "../misc/pcap_openvas.h" /* for get_datalink_size */
11 
12 #include <arpa/inet.h> /* for inet_ntoa */
13 #include <glib.h> /* for gfree */
14 #include <netinet/ip.h>
15 #include <pcap.h>
16 #include <sys/param.h>
17 #ifdef __FreeBSD__
18 #include <sys/socket.h>
19 #endif
20 
21 extern int
22 islocalhost (struct in_addr *);
23 
30 int
31 init_capture_device (struct in_addr src, struct in_addr dest, char *filter)
32 {
33  int ret = -1;
34  char *interface = NULL;
35  char *a_dst, *a_src;
36  char errbuf[PCAP_ERRBUF_SIZE];
37  int free_filter = 0;
38  pcap_if_t *alldevsp = NULL; /* list of capture devices */
39 
40  a_src = g_strdup (inet_ntoa (src));
41  a_dst = g_strdup (inet_ntoa (dest));
42 
43  if ((filter == NULL) || (filter[0] == '\0') || (filter[0] == '0'))
44  {
45  filter = g_malloc0 (256);
46  free_filter = 1;
47  if (islocalhost (&src) == 0)
48  snprintf (filter, 256, "ip and (src host %s and dst host %s)", a_src,
49  a_dst);
50  }
51  else
52  {
53  if (islocalhost (&src) == 0)
54  filter = g_strdup (filter);
55  else
56  filter = g_malloc0 (1);
57  free_filter = 1;
58  }
59 
60  g_free (a_dst);
61  g_free (a_src);
62 
63  if ((interface = routethrough (&src, &dest)))
64  {
65  ret = bpf_open_live (interface, filter);
66  }
67  else
68  {
69  if (pcap_findalldevs (&alldevsp, errbuf) < 0)
70  g_message ("Error for pcap_findalldevs(): %s", errbuf);
71  if (alldevsp != NULL)
72  interface = alldevsp->name;
73  ret = bpf_open_live (interface, filter);
74  }
75 
76  if (free_filter != 0)
77  g_free (filter);
78 
79  if (alldevsp != NULL)
80  pcap_freealldevs (alldevsp);
81 
82  return ret;
83 }
84 
95 char *
96 capture_next_frame (int bpf, int timeout, int *sz, int dl_layer_only)
97 {
98  int len;
99  int dl_len;
100  char *frame = NULL;
101  char *ret = NULL;
102  struct timeval past, now, then;
103  struct timezone tz;
104 
105  if (bpf < 0)
106  return NULL;
107 
108  dl_len = get_datalink_size (bpf_datalink (bpf));
109  memset (&past, '\0', sizeof (past));
110  memset (&now, '\0', sizeof (now));
111  gettimeofday (&then, &tz);
112  for (;;)
113  {
114  memcpy (&past, &then, sizeof (then));
115  frame = (char *) bpf_next (bpf, &len);
116  if (frame != NULL)
117  break;
118  gettimeofday (&now, &tz);
119 
120  if (now.tv_usec < past.tv_usec)
121  {
122  past.tv_sec++;
123  now.tv_usec += 1000000;
124  }
125 
126  if (timeout > 0)
127  {
128  if ((now.tv_sec - past.tv_sec) >= timeout)
129  break;
130  }
131  else
132  break;
133  }
134 
135  if (frame != NULL)
136  {
137  if (dl_layer_only == 1)
138  {
139  ret = g_malloc0 (dl_len);
140  memcpy (ret, frame, dl_len);
141  if (sz != NULL)
142  *sz = dl_len;
143  }
144  else
145  {
146  ret = g_malloc0 (len);
147  memcpy (ret, frame, len);
148  if (sz != NULL)
149  *sz = len;
150  }
151  }
152 
153  return ret;
154 }
155 
156 struct ip *
157 capture_next_packet (int bpf, int timeout, int *sz)
158 {
159  int len;
160  int dl_len;
161  char *packet = NULL;
162  char *ret = NULL;
163  struct timeval past, now, then;
164  struct timezone tz;
165 
166  if (bpf < 0)
167  return NULL;
168 
169  dl_len = get_datalink_size (bpf_datalink (bpf));
170  memset (&past, '\0', sizeof (past));
171  memset (&now, '\0', sizeof (now));
172  gettimeofday (&then, &tz);
173  for (;;)
174  {
175  memcpy (&past, &then, sizeof (then));
176  packet = (char *) bpf_next (bpf, &len);
177  if (packet != NULL)
178  break;
179  gettimeofday (&now, &tz);
180 
181  if (now.tv_usec < past.tv_usec)
182  {
183  past.tv_sec++;
184  now.tv_usec += 1000000;
185  }
186 
187  if (timeout > 0)
188  {
189  if ((now.tv_sec - past.tv_sec) >= timeout)
190  break;
191  }
192  else
193  break;
194  }
195 
196  if (packet != NULL)
197  {
198  struct ip *ip;
199 
200  ip = (struct ip *) (packet + dl_len);
201 #ifdef BSD_BYTE_ORDERING
202  ip->ip_len = ntohs (ip->ip_len);
203  ip->ip_off = ntohs (ip->ip_off);
204 #endif
205  ip->ip_id = ntohs (ip->ip_id);
206  ret = g_malloc0 (len - dl_len);
207  memcpy (ret, ip, len - dl_len);
208  if (sz != NULL)
209  *sz = len - dl_len;
210  }
211  return ((struct ip *) ret);
212 }
213 
214 int
215 init_v6_capture_device (struct in6_addr src, struct in6_addr dest, char *filter)
216 {
217  int ret = -1;
218  char *interface = NULL;
219  char *a_dst, *a_src;
220  int free_filter = 0;
221  char name[INET6_ADDRSTRLEN];
222  char errbuf[PCAP_ERRBUF_SIZE];
223  pcap_if_t *alldevsp = NULL; /* list of capture devices */
224 
225  a_src = g_strdup (inet_ntop (AF_INET6, &src, name, INET6_ADDRSTRLEN));
226  a_dst = g_strdup (inet_ntop (AF_INET6, &dest, name, INET6_ADDRSTRLEN));
227 
228  if ((filter == NULL) || (filter[0] == '\0') || (filter[0] == '0'))
229  {
230  filter = g_malloc0 (256);
231  free_filter = 1;
232  if (v6_islocalhost (&src) == 0)
233  snprintf (filter, 256, "ip and (src host %s and dst host %s", a_src,
234  a_dst);
235  }
236  else
237  {
238  if (v6_islocalhost (&src) == 0)
239  filter = g_strdup (filter);
240  else
241  filter = g_malloc0 (1);
242  free_filter = 1;
243  }
244 
245  g_free (a_dst);
246  g_free (a_src);
247 
248  if ((interface = v6_routethrough (&src, &dest)))
249  {
250  ret = bpf_open_live (interface, filter);
251  }
252  else
253  {
254  if (pcap_findalldevs (&alldevsp, errbuf) < 0)
255  g_message ("Error for pcap_findalldevs(): %s", errbuf);
256  if (alldevsp != NULL)
257  interface = alldevsp->name;
258  ret = bpf_open_live (interface, filter);
259  }
260 
261  if (free_filter != 0)
262  g_free (filter);
263 
264  if (alldevsp != NULL)
265  pcap_freealldevs (alldevsp);
266 
267  return ret;
268 }
269 
270 struct ip6_hdr *
271 capture_next_v6_packet (int bpf, int timeout, int *sz)
272 {
273  int len;
274  int dl_len;
275  char *packet = NULL;
276  char *ret = NULL;
277  struct timeval past, now, then;
278  struct timezone tz;
279 
280  if (bpf < 0)
281  return NULL;
282 
283  dl_len = get_datalink_size (bpf_datalink (bpf));
284  memset (&past, '\0', sizeof (past));
285  memset (&now, '\0', sizeof (now));
286  gettimeofday (&then, &tz);
287 
288  for (;;)
289  {
290  memcpy (&past, &then, sizeof (then));
291  packet = (char *) bpf_next (bpf, &len);
292 
293  if (packet != NULL)
294  break;
295 
296  gettimeofday (&now, &tz);
297  if (now.tv_usec < past.tv_usec)
298  {
299  past.tv_sec++;
300  now.tv_usec += 1000000;
301  }
302 
303  if (timeout > 0)
304  {
305  if ((now.tv_sec - past.tv_sec) >= timeout)
306  break;
307  }
308  else
309  break;
310  }
311 
312  if (packet != NULL)
313  {
314  struct ip6_hdr *ip6;
315  ip6 = (struct ip6_hdr *) (packet + dl_len);
316 #ifdef BSD_BYTE_ORDERING
317  ip6->ip6_plen = ntohs (ip6->ip6_plen);
318 #endif
319  ret = g_malloc0 (len - dl_len);
320  memcpy (ret, ip6, len - dl_len);
321  if (sz != NULL)
322  *sz = len - dl_len;
323  }
324 
325  return ((struct ip6_hdr *) ret);
326 }
capture_next_frame
char * capture_next_frame(int bpf, int timeout, int *sz, int dl_layer_only)
Capture a link layer frame.
Definition: capture_packet.c:96
bpf_open_live
int bpf_open_live(char *iface, char *filter)
Definition: bpf_share.c:39
capture_packet.h
v6_routethrough
char * v6_routethrough(struct in6_addr *dest, struct in6_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition: pcap.c:841
islocalhost
int islocalhost(struct in_addr *)
Tests whether a packet sent to IP is LIKELY to route through the kernel localhost interface.
Definition: pcap.c:261
name
const char * name
Definition: nasl_init.c:411
init_capture_device
int init_capture_device(struct in_addr src, struct in_addr dest, char *filter)
Set up the pcap filter, and select the correct interface.
Definition: capture_packet.c:31
len
uint8_t len
Definition: nasl_packet_forgery.c:1
bpf_datalink
int bpf_datalink(int bpf)
Definition: bpf_share.c:158
timeval
static struct timeval timeval(unsigned long val)
Definition: nasl_builtin_synscan.c:94
capture_next_packet
struct ip * capture_next_packet(int bpf, int timeout, int *sz)
Definition: capture_packet.c:157
get_datalink_size
int get_datalink_size(int datalink)
Definition: pcap.c:288
capture_next_v6_packet
struct ip6_hdr * capture_next_v6_packet(int bpf, int timeout, int *sz)
Definition: capture_packet.c:271
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
bpf_next
u_char * bpf_next(int bpf, int *caplen)
Definition: bpf_share.c:150
init_v6_capture_device
int init_v6_capture_device(struct in6_addr src, struct in6_addr dest, char *filter)
Definition: capture_packet.c:215
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