netflower 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luiz Henrique
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: netflower
3
+ Version: 1.0.0
4
+ Summary: High-performance network flow extractor with live capture support for edge devices
5
+ Author-email: Luiz Henrique <luizlinkezio@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Luiz Henrique
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Repository, https://github.com/luiz-linkezio/pcapflower
29
+ Keywords: pcap,pcapng,network,flow,CICFlowMeter,ids,intrusion detection,live capture
30
+ Classifier: Development Status :: 5 - Production/Stable
31
+ Classifier: Intended Audience :: Science/Research
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3.10
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Topic :: System :: Networking :: Monitoring
39
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
40
+ Classifier: Operating System :: OS Independent
41
+ Requires-Python: >=3.10
42
+ Description-Content-Type: text/markdown
43
+ License-File: LICENSE
44
+ Requires-Dist: dpkt>=1.9.8
45
+ Provides-Extra: dev
46
+ Requires-Dist: pytest; extra == "dev"
47
+ Requires-Dist: ruff; extra == "dev"
48
+ Dynamic: license-file
49
+
50
+ <p align="center">
51
+ <img src="assets/icon.png" alt="netflower" width="128" />
52
+ </p>
53
+
54
+ <h1 align="center">netflower</h1>
55
+
56
+ <p align="center">High-performance network flow extractor for edge devices.</p>
57
+
58
+ **netflower** extracts bidirectional network flows — either from a live interface or from `.pcap` / `.pcapng` files — and produces 82 features compatible with the [CICFlowMeter](https://www.unb.ca/cic/research/applications.html) feature set.
59
+
60
+ ## Features
61
+
62
+ - **Live capture** — capture flows in real time from a network interface; flows are emitted only when complete (TCP FIN/RST or idle timeout), never cut by an arbitrary boundary
63
+ - **PCAP flows to CSV** — convert `.pcap` / `.pcapng` files to flow-based CSV, with optional parallel processing
64
+ - **Edge-optimized** — `dpkt` for packet parsing (~10–25× faster than Scapy on ARM), Welford's online algorithm for O(1) memory per flow, batch-buffered CSV output
65
+ - **No extra pip dependencies** for live capture — libpcap is accessed via `ctypes`
66
+
67
+ ## Installation
68
+
69
+ ```bash
70
+ pip install netflower
71
+ ```
72
+
73
+ Live capture requires libpcap on the system:
74
+
75
+ ```bash
76
+ # Linux
77
+ sudo apt install libpcap-dev
78
+
79
+ # macOS
80
+ brew install libpcap
81
+ ```
82
+
83
+ ## Usage
84
+
85
+ ### Live capture
86
+
87
+ Captures packets from a network interface and emits each flow the moment it completes.
88
+
89
+ ```python
90
+ from netflower import capture_live
91
+
92
+ def on_flow(flow):
93
+ print(flow["src_ip"], flow["dst_ip"], flow["flow_duration"])
94
+
95
+ handle = capture_live("eth0", on_flow=on_flow)
96
+ handle.start()
97
+
98
+ # ... rest of your program ...
99
+
100
+ handle.stop()
101
+ ```
102
+
103
+ As a context manager:
104
+
105
+ ```python
106
+ with capture_live("eth0", on_flow=on_flow) as handle:
107
+ handle.start()
108
+ import time; time.sleep(60)
109
+ ```
110
+
111
+ > **Note:** live capture requires root or `CAP_NET_RAW` privilege.
112
+
113
+ ### PCAP flows to CSV
114
+
115
+ Converts a `.pcap` or `.pcapng` file into a flow-based CSV.
116
+
117
+ ```python
118
+ from netflower import convert_pcap_to_csv
119
+
120
+ n = convert_pcap_to_csv("capture.pcap", "flows.csv")
121
+ print(f"Extracted {n} flows")
122
+
123
+ # Parallel — use all available CPUs
124
+ n = convert_pcap_to_csv("capture.pcap", "flows.csv", n_jobs=-1)
125
+ ```
126
+
127
+ ## API
128
+
129
+ ### `capture_live(interface, on_flow, **kwargs) → CaptureHandle`
130
+
131
+ | Parameter | Default | Description |
132
+ |-----------|---------|-------------|
133
+ | `interface` | — | Network interface name (e.g. `"eth0"`) |
134
+ | `on_flow` | — | Callable receiving a flow `dict` when a flow completes |
135
+ | `idle_timeout` | `30.0` | Seconds of inactivity before a flow is emitted |
136
+ | `flow_timeout` | `120.0` | Absolute max flow duration before forced emit |
137
+ | `save_pcap` | `False` | Save raw packets of each completed flow to a `.pcap` file |
138
+ | `pcap_dir` | `None` | Directory for `.pcap` files (required when `save_pcap=True`) |
139
+
140
+ `CaptureHandle` exposes `.start()`, `.stop()`, and context manager support.
141
+
142
+ ### `convert_pcap_to_csv(input_path, output_path, **kwargs) → int`
143
+
144
+ | Parameter | Default | Description |
145
+ |-----------|---------|-------------|
146
+ | `input_path` | — | Path to `.pcap` or `.pcapng` file |
147
+ | `output_path` | — | Path for the output `.csv` (created or overwritten) |
148
+ | `flow_timeout` | `120.0` | Seconds of inactivity before a flow is evicted |
149
+ | `gc_interval` | `1000` | Run idle-flow GC every N packets |
150
+ | `buffer_rows` | `500` | Rows buffered in memory before flushing to disk |
151
+ | `n_jobs` | `1` | Worker processes. `-1` uses all available CPUs |
152
+
153
+ Returns the number of flow rows written.
154
+
155
+ ## Flow features
156
+
157
+ Both APIs produce the same **82 features** per flow:
158
+
159
+ - Flow identity: source/destination IP, port, protocol, timestamp
160
+ - Duration, bytes/s, and packets/s (forward, backward, combined)
161
+ - Packet length statistics (mean, std, min, max, variance)
162
+ - Inter-arrival time statistics (flow, forward, backward)
163
+ - TCP flag counts (FIN, SYN, RST, PSH, ACK, URG, ECE, CWR)
164
+ - Active/idle period statistics
165
+ - Bulk transfer metrics (forward and backward)
166
+ - Subflow metrics
167
+ - Initial TCP window sizes
168
+
169
+ ## Supported formats
170
+
171
+ - **pcap** — standard libpcap format
172
+ - **pcapng** — next-generation capture format
173
+
174
+ Only **IPv4 TCP and UDP** flows are extracted; other protocols are silently skipped.
175
+
176
+ ## License
177
+
178
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,129 @@
1
+ <p align="center">
2
+ <img src="assets/icon.png" alt="netflower" width="128" />
3
+ </p>
4
+
5
+ <h1 align="center">netflower</h1>
6
+
7
+ <p align="center">High-performance network flow extractor for edge devices.</p>
8
+
9
+ **netflower** extracts bidirectional network flows — either from a live interface or from `.pcap` / `.pcapng` files — and produces 82 features compatible with the [CICFlowMeter](https://www.unb.ca/cic/research/applications.html) feature set.
10
+
11
+ ## Features
12
+
13
+ - **Live capture** — capture flows in real time from a network interface; flows are emitted only when complete (TCP FIN/RST or idle timeout), never cut by an arbitrary boundary
14
+ - **PCAP flows to CSV** — convert `.pcap` / `.pcapng` files to flow-based CSV, with optional parallel processing
15
+ - **Edge-optimized** — `dpkt` for packet parsing (~10–25× faster than Scapy on ARM), Welford's online algorithm for O(1) memory per flow, batch-buffered CSV output
16
+ - **No extra pip dependencies** for live capture — libpcap is accessed via `ctypes`
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install netflower
22
+ ```
23
+
24
+ Live capture requires libpcap on the system:
25
+
26
+ ```bash
27
+ # Linux
28
+ sudo apt install libpcap-dev
29
+
30
+ # macOS
31
+ brew install libpcap
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Live capture
37
+
38
+ Captures packets from a network interface and emits each flow the moment it completes.
39
+
40
+ ```python
41
+ from netflower import capture_live
42
+
43
+ def on_flow(flow):
44
+ print(flow["src_ip"], flow["dst_ip"], flow["flow_duration"])
45
+
46
+ handle = capture_live("eth0", on_flow=on_flow)
47
+ handle.start()
48
+
49
+ # ... rest of your program ...
50
+
51
+ handle.stop()
52
+ ```
53
+
54
+ As a context manager:
55
+
56
+ ```python
57
+ with capture_live("eth0", on_flow=on_flow) as handle:
58
+ handle.start()
59
+ import time; time.sleep(60)
60
+ ```
61
+
62
+ > **Note:** live capture requires root or `CAP_NET_RAW` privilege.
63
+
64
+ ### PCAP flows to CSV
65
+
66
+ Converts a `.pcap` or `.pcapng` file into a flow-based CSV.
67
+
68
+ ```python
69
+ from netflower import convert_pcap_to_csv
70
+
71
+ n = convert_pcap_to_csv("capture.pcap", "flows.csv")
72
+ print(f"Extracted {n} flows")
73
+
74
+ # Parallel — use all available CPUs
75
+ n = convert_pcap_to_csv("capture.pcap", "flows.csv", n_jobs=-1)
76
+ ```
77
+
78
+ ## API
79
+
80
+ ### `capture_live(interface, on_flow, **kwargs) → CaptureHandle`
81
+
82
+ | Parameter | Default | Description |
83
+ |-----------|---------|-------------|
84
+ | `interface` | — | Network interface name (e.g. `"eth0"`) |
85
+ | `on_flow` | — | Callable receiving a flow `dict` when a flow completes |
86
+ | `idle_timeout` | `30.0` | Seconds of inactivity before a flow is emitted |
87
+ | `flow_timeout` | `120.0` | Absolute max flow duration before forced emit |
88
+ | `save_pcap` | `False` | Save raw packets of each completed flow to a `.pcap` file |
89
+ | `pcap_dir` | `None` | Directory for `.pcap` files (required when `save_pcap=True`) |
90
+
91
+ `CaptureHandle` exposes `.start()`, `.stop()`, and context manager support.
92
+
93
+ ### `convert_pcap_to_csv(input_path, output_path, **kwargs) → int`
94
+
95
+ | Parameter | Default | Description |
96
+ |-----------|---------|-------------|
97
+ | `input_path` | — | Path to `.pcap` or `.pcapng` file |
98
+ | `output_path` | — | Path for the output `.csv` (created or overwritten) |
99
+ | `flow_timeout` | `120.0` | Seconds of inactivity before a flow is evicted |
100
+ | `gc_interval` | `1000` | Run idle-flow GC every N packets |
101
+ | `buffer_rows` | `500` | Rows buffered in memory before flushing to disk |
102
+ | `n_jobs` | `1` | Worker processes. `-1` uses all available CPUs |
103
+
104
+ Returns the number of flow rows written.
105
+
106
+ ## Flow features
107
+
108
+ Both APIs produce the same **82 features** per flow:
109
+
110
+ - Flow identity: source/destination IP, port, protocol, timestamp
111
+ - Duration, bytes/s, and packets/s (forward, backward, combined)
112
+ - Packet length statistics (mean, std, min, max, variance)
113
+ - Inter-arrival time statistics (flow, forward, backward)
114
+ - TCP flag counts (FIN, SYN, RST, PSH, ACK, URG, ECE, CWR)
115
+ - Active/idle period statistics
116
+ - Bulk transfer metrics (forward and backward)
117
+ - Subflow metrics
118
+ - Initial TCP window sizes
119
+
120
+ ## Supported formats
121
+
122
+ - **pcap** — standard libpcap format
123
+ - **pcapng** — next-generation capture format
124
+
125
+ Only **IPv4 TCP and UDP** flows are extracted; other protocols are silently skipped.
126
+
127
+ ## License
128
+
129
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,5 @@
1
+ from ._convert import convert_pcap_to_csv
2
+ from ._capture import capture_live
3
+
4
+ __all__ = ["convert_pcap_to_csv", "capture_live"]
5
+ __version__ = "1.0.0"
@@ -0,0 +1,222 @@
1
+ """
2
+ Live packet capture using system libpcap via ctypes.
3
+
4
+ Usage:
5
+ from netflower import capture_live
6
+
7
+ handle = capture_live("eth0", on_flow=lambda flow: print(flow), idle_timeout=30)
8
+ handle.start()
9
+ # ... do work ...
10
+ handle.stop()
11
+ """
12
+
13
+ import ctypes
14
+ import threading
15
+
16
+ from ._libpcap import (
17
+ PcapHandler_cb, PktHdr,
18
+ pcap_open_live, pcap_loop, pcap_breakloop, pcap_close,
19
+ pcap_dump_open, pcap_dump, pcap_dump_close,
20
+ )
21
+ from ._parser import _parse_packet
22
+ from ._session import FlowSession
23
+ from ._constants import FLOW_TIMEOUT
24
+
25
+
26
+ class CallbackWriter:
27
+ """Writer that calls on_flow(dict) instead of writing to a CSV file."""
28
+
29
+ def __init__(self, on_flow: callable) -> None:
30
+ self._on_flow = on_flow
31
+
32
+ def write(self, flow_dict: dict) -> None:
33
+ self._on_flow(flow_dict)
34
+
35
+
36
+ class _PcapSavingWriter:
37
+ """
38
+ Wraps on_flow callable. When a flow is emitted, also dumps its raw packets
39
+ to a .pcap file in pcap_dir before clearing the buffer.
40
+ """
41
+
42
+ def __init__(self, on_flow: callable, pcap_dir: str, pcap_handle) -> None:
43
+ self._on_flow = on_flow
44
+ self._pcap_dir = pcap_dir
45
+ self._pcap_handle = pcap_handle
46
+ # flow_key -> list of (PktHdr, bytes)
47
+ self._buffers: dict[tuple, list] = {}
48
+
49
+ def write(self, flow_dict: dict) -> None:
50
+ key = (
51
+ flow_dict.get("protocol"),
52
+ flow_dict.get("src_ip"),
53
+ flow_dict.get("dst_ip"),
54
+ flow_dict.get("src_port"),
55
+ flow_dict.get("dst_port"),
56
+ )
57
+ packets = self._buffers.pop(key, [])
58
+ if packets:
59
+ ts_us = int(flow_dict.get("timestamp", 0) * 1_000_000)
60
+ fname = (
61
+ f"{self._pcap_dir}/"
62
+ f"{flow_dict.get('src_ip')}-{flow_dict.get('src_port')}-"
63
+ f"{flow_dict.get('dst_ip')}-{flow_dict.get('dst_port')}-"
64
+ f"{flow_dict.get('protocol')}-{ts_us}.pcap"
65
+ ).encode()
66
+ dumper = pcap_dump_open(self._pcap_handle, fname)
67
+ if dumper:
68
+ for hdr, data in packets:
69
+ pcap_dump(dumper, ctypes.byref(hdr), data)
70
+ pcap_dump_close(dumper)
71
+ self._on_flow(flow_dict)
72
+
73
+ def buffer_packet(self, key: tuple, hdr: PktHdr, data: bytes) -> None:
74
+ if key not in self._buffers:
75
+ self._buffers[key] = []
76
+ self._buffers[key].append((hdr, data))
77
+
78
+
79
+ class CaptureHandle:
80
+ """
81
+ Handle returned by capture_live(). Controls start/stop of capture thread.
82
+
83
+ Parameters
84
+ ----------
85
+ interface: Network interface name as bytes (e.g. b"eth0").
86
+ on_flow: Callable receiving a flow dict when a flow completes.
87
+ idle_timeout: Seconds of inactivity before a flow is emitted.
88
+ flow_timeout: Absolute max flow duration before forced emit.
89
+ save_pcap: If True, save raw packets of each completed flow to pcap_dir.
90
+ pcap_dir: Directory path for .pcap files. Required when save_pcap=True.
91
+ """
92
+
93
+ _GC_INTERVAL = 1000
94
+
95
+ def __init__(
96
+ self,
97
+ interface: bytes,
98
+ on_flow: callable,
99
+ idle_timeout: float,
100
+ flow_timeout: float,
101
+ save_pcap: bool,
102
+ pcap_dir: str | None,
103
+ ) -> None:
104
+ if save_pcap and pcap_dir is None:
105
+ raise ValueError("pcap_dir is required when save_pcap=True")
106
+ self._interface = interface
107
+ self._on_flow = on_flow
108
+ self._idle_timeout = idle_timeout
109
+ self._flow_timeout = flow_timeout
110
+ self._save_pcap = save_pcap
111
+ self._pcap_dir = pcap_dir
112
+ self._handle = None
113
+ self._thread: threading.Thread | None = None
114
+ self._session = None
115
+ self._writer = None
116
+ self._callback = None
117
+
118
+ def start(self) -> None:
119
+ errbuf = ctypes.create_string_buffer(256)
120
+ self._handle = pcap_open_live(self._interface, 65535, 1, 1000, errbuf)
121
+ if not self._handle:
122
+ raise RuntimeError(f"pcap_open_live failed: {errbuf.value.decode()}")
123
+
124
+ if self._save_pcap:
125
+ self._writer = _PcapSavingWriter(self._on_flow, self._pcap_dir, self._handle)
126
+ else:
127
+ self._writer = CallbackWriter(self._on_flow)
128
+
129
+ self._session = FlowSession(self._writer, self._flow_timeout)
130
+ self._pkt_counter = 0
131
+
132
+ @PcapHandler_cb
133
+ def _callback(user, pkthdr_p, pkt_data):
134
+ hdr = pkthdr_p.contents
135
+ ts = hdr.ts_sec + hdr.ts_usec / 1_000_000
136
+ buf = ctypes.string_at(pkt_data, hdr.caplen)
137
+ parsed = _parse_packet(buf)
138
+ if parsed is None:
139
+ return
140
+ src_ip, dst_ip, src_port, dst_port, proto, pkt_len, hdr_len, pay_len, flags, win = parsed
141
+ if self._save_pcap:
142
+ fwd_key = (proto, src_ip, dst_ip, src_port, dst_port)
143
+ bwd_key = (proto, dst_ip, src_ip, dst_port, src_port)
144
+ key = fwd_key if (fwd_key in self._session._flows
145
+ or bwd_key not in self._session._flows) else bwd_key
146
+ self._writer.buffer_packet(key, hdr, buf)
147
+ self._session.process(ts, src_ip, dst_ip, src_port, dst_port,
148
+ proto, pkt_len, hdr_len, pay_len, flags, win)
149
+ self._pkt_counter += 1
150
+ if self._pkt_counter % self._GC_INTERVAL == 0:
151
+ self._session.gc(ts)
152
+
153
+ # Keep reference to prevent ctypes GC
154
+ self._callback = _callback
155
+
156
+ self._thread = threading.Thread(
157
+ target=pcap_loop,
158
+ args=(self._handle, -1, self._callback, None),
159
+ daemon=True,
160
+ )
161
+ self._thread.start()
162
+
163
+ def stop(self) -> None:
164
+ if self._handle:
165
+ pcap_breakloop(self._handle)
166
+ if self._thread:
167
+ self._thread.join(timeout=5)
168
+ if self._session:
169
+ self._session.flush_all()
170
+ if self._handle:
171
+ pcap_close(self._handle)
172
+ self._handle = None
173
+
174
+ def __enter__(self):
175
+ return self
176
+
177
+ def __exit__(self, *_):
178
+ self.stop()
179
+
180
+
181
+ def capture_live(
182
+ interface: str,
183
+ on_flow: callable,
184
+ idle_timeout: float = 30.0,
185
+ flow_timeout: float = FLOW_TIMEOUT,
186
+ save_pcap: bool = False,
187
+ pcap_dir: str | None = None,
188
+ ) -> CaptureHandle:
189
+ """
190
+ Capture live packets from a network interface and emit completed flows.
191
+
192
+ Requires root or CAP_NET_RAW privilege.
193
+
194
+ Parameters
195
+ ----------
196
+ interface: Network interface name (e.g. "eth0").
197
+ on_flow: Called with a flow dict (82 fields) when a flow completes.
198
+ Same column names as convert_pcap_to_csv output.
199
+ idle_timeout: Seconds of inactivity before a flow is emitted (default 30).
200
+ flow_timeout: Absolute max flow duration in seconds (default 120).
201
+ save_pcap: Save raw packets of each completed flow to a .pcap file.
202
+ pcap_dir: Directory for .pcap files. Required when save_pcap=True.
203
+
204
+ Returns
205
+ -------
206
+ CaptureHandle — call .start() to begin capture, .stop() to end.
207
+
208
+ Example
209
+ -------
210
+ >>> handle = capture_live("eth0", on_flow=lambda f: print(f["flow_duration"]))
211
+ >>> handle.start()
212
+ >>> import time; time.sleep(60)
213
+ >>> handle.stop()
214
+ """
215
+ return CaptureHandle(
216
+ interface=interface.encode() if isinstance(interface, str) else interface,
217
+ on_flow=on_flow,
218
+ idle_timeout=idle_timeout,
219
+ flow_timeout=flow_timeout,
220
+ save_pcap=save_pcap,
221
+ pcap_dir=pcap_dir,
222
+ )
@@ -0,0 +1,18 @@
1
+ FLOW_TIMEOUT = 120.0 # seconds of inactivity before a flow is flushed
2
+ ACTIVE_TIMEOUT = 5.0 # gap > this separates active from idle periods
3
+ CLUMP_TIMEOUT = 1.0 # gap > this starts a new subflow
4
+ BULK_BOUND = 4 # minimum packets required to register a bulk transfer
5
+ CSV_BUFFER_ROWS = 500 # rows buffered in memory before writing to disk
6
+
7
+ # TCP flag bitmasks (RFC 793 / RFC 3168)
8
+ TCP_FIN = 0x01
9
+ TCP_SYN = 0x02
10
+ TCP_RST = 0x04
11
+ TCP_PSH = 0x08
12
+ TCP_ACK = 0x10
13
+ TCP_URG = 0x20
14
+ TCP_ECE = 0x40
15
+ TCP_CWR = 0x80
16
+
17
+ FORWARD = 0
18
+ BACKWARD = 1