1"""
2------------------------------------------------------------------------------------------------------------------------
3engine.py
4Copyright (C) 2019-22 - NFStream Developers
5This file is part of NFStream, a Flexible Network Data Analysis Framework (https://www.nfstream.org/).
6NFStream is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
7License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
8version.
9NFStream is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
10of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
11You should have received a copy of the GNU Lesser General Public License along with NFStream.
12If not, see <http://www.gnu.org/licenses/>.
13------------------------------------------------------------------------------------------------------------------------
14"""
15
16from _lib_engine import ffi, lib
17
18
19def setup_capture(
20 ffi, lib, source, snaplen, promisc, mode, error_child, group_id, socket_buffer_size
21):
22 capture = lib.capture_open(
23 bytes(source, "utf-8"), int(mode), error_child, socket_buffer_size
24 )
25 if capture == ffi.NULL:
26 return
27 fanout_set_failed = lib.capture_set_fanout(
28 capture, int(mode), error_child, group_id
29 )
30 if fanout_set_failed:
31 return
32 timeout_set_failed = lib.capture_set_timeout(capture, int(mode), error_child)
33 if timeout_set_failed:
34 return
35 promisc_set_failed = lib.capture_set_promisc(
36 capture, int(mode), error_child, int(promisc)
37 )
38 if promisc_set_failed:
39 return
40 snaplen_set_failed = lib.capture_set_snaplen(
41 capture, int(mode), error_child, snaplen
42 )
43 if snaplen_set_failed:
44 return
45 return capture
46
47
48def setup_filter(capture, lib, error_child, bpf_filter):
49 """Compile and setup BPF filter"""
50 if bpf_filter is not None:
51 filter_set_failed = lib.capture_set_filter(
52 capture, bytes(bpf_filter, "utf-8"), error_child
53 )
54 if filter_set_failed:
55 return False
56 return True
57
58
59def activate_capture(capture, lib, error_child, bpf_filter, mode):
60 """Capture activation function"""
61 activation_failed = lib.capture_activate(capture, int(mode), error_child)
62 if activation_failed:
63 return False
64 return setup_filter(capture, lib, error_child, bpf_filter)
65
66
67def setup_dissector(ffi, lib, n_dissections):
68 """Setup dissector according to n_dissections value"""
69 if n_dissections: # Dissection activated
70 # Check that headers and loaded library match and initiate dissector.
71 checker = ffi.new("struct dissector_checker *")
72 checker.flow_size = ffi.sizeof("struct ndpi_flow_struct")
73 checker.flow_tcp_size = ffi.sizeof("struct ndpi_flow_tcp_struct")
74 checker.flow_udp_size = ffi.sizeof("struct ndpi_flow_udp_struct")
75 dissector = lib.dissector_init(checker)
76 if dissector == ffi.NULL:
77 return ffi.NULL
78 # Configure it (activate bitmask to all protocols)
79 lib.dissector_configure(dissector)
80 return dissector
81 return ffi.NULL
82
83
84def is_interface(val):
85 """Check if val is a valid interface name and return it if true else None"""
86 intf = lib.capture_get_interface(val.encode("ascii"))
87 if intf == ffi.NULL:
88 return None
89 return ffi.string(intf).decode("ascii", "ignore")
90
91
92def create_engine():
93 """engine creation function, return the loaded native nfstream engine and it's ffi interface"""
94 return ffi, lib