/src/ndpi/example/reader_util.c
Line | Count | Source |
1 | | /* |
2 | | * reader_util.c |
3 | | * |
4 | | * Copyright (C) 2011-25 - ntop.org |
5 | | * |
6 | | * This file is part of nDPI, an open source deep packet inspection |
7 | | * library based on the OpenDPI and PACE technology by ipoque GmbH |
8 | | * |
9 | | * nDPI is free software: you can redistribute it and/or modify |
10 | | * it under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation, either version 3 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * nDPI is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with nDPI. If not, see <http://www.gnu.org/licenses/>. |
21 | | * |
22 | | */ |
23 | | |
24 | | #include "ndpi_config.h" |
25 | | #include "ndpi_api.h" |
26 | | |
27 | | #include <stdlib.h> |
28 | | #include <math.h> |
29 | | #include <float.h> |
30 | | |
31 | | #ifdef WIN32 |
32 | | #include <winsock2.h> /* winsock.h is included automatically */ |
33 | | #include <windows.h> |
34 | | #include <ws2tcpip.h> |
35 | | #include <process.h> |
36 | | #include <io.h> |
37 | | #ifndef DISABLE_NPCAP |
38 | | #include <ip6_misc.h> |
39 | | #endif |
40 | | #else |
41 | | #include <unistd.h> |
42 | | #include <netinet/in.h> |
43 | | #include <netinet/ip.h> |
44 | | #endif |
45 | | #include <assert.h> |
46 | | #include <sys/stat.h> |
47 | | |
48 | | #include "reader_util.h" |
49 | | |
50 | 314k | #define SNAP 0XAA |
51 | 300k | #define BSTP 0x42 /* Bridge Spanning Tree Protocol */ |
52 | | |
53 | | /* Keep last 32 packets */ |
54 | 22.5M | #define DATA_ANALUYSIS_SLIDING_WINDOW 32 |
55 | | |
56 | | /* mask for FCF */ |
57 | 14.5k | #define WIFI_DATA 0x2 /* 0000 0010 */ |
58 | 14.5k | #define FCF_TYPE(fc) (((fc) >> 2) & 0x3) /* 0000 0011 = 0x3 */ |
59 | | #define FCF_SUBTYPE(fc) (((fc) >> 4) & 0xF) /* 0000 1111 = 0xF */ |
60 | 25.2k | #define FCF_TO_DS(fc) ((fc) & 0x0100) |
61 | 9.45k | #define FCF_FROM_DS(fc) ((fc) & 0x0200) |
62 | | |
63 | | /* mask for Bad FCF presence */ |
64 | 42.3k | #define BAD_FCS 0x50 /* 0101 0000 */ |
65 | | |
66 | 6.61M | #define GTP_U_V1_PORT 2152 |
67 | 6.43M | #define NDPI_CAPWAP_DATA_PORT 5247 |
68 | 6.46M | #define TZSP_PORT 37008 |
69 | | |
70 | | #ifndef DLT_LINUX_SLL |
71 | | #define DLT_LINUX_SLL 113 |
72 | | #endif |
73 | | |
74 | | #include "ndpi_main.h" |
75 | | #include "reader_util.h" |
76 | | #include "ndpi_classify.h" |
77 | | |
78 | | extern u_int8_t enable_flow_stats, enable_payload_analyzer; |
79 | | extern u_int8_t verbose, human_readeable_string_len; |
80 | | extern u_int8_t max_num_udp_dissected_pkts /* 24 */, max_num_tcp_dissected_pkts /* 80 */; |
81 | | static u_int32_t flow_id = 0; |
82 | | extern FILE *fingerprint_fp; |
83 | | extern char *addr_dump_path; |
84 | | extern u_int8_t enable_doh_dot_detection; |
85 | | extern int malloc_size_stats; |
86 | | extern int monitoring_enabled; |
87 | | |
88 | | /* ****************************************************** */ |
89 | | |
90 | | struct flow_id_stats { |
91 | | u_int32_t flow_id; |
92 | | UT_hash_handle hh; /* makes this structure hashable */ |
93 | | }; |
94 | | |
95 | | struct packet_id_stats { |
96 | | u_int32_t packet_id; |
97 | | UT_hash_handle hh; /* makes this structure hashable */ |
98 | | }; |
99 | | |
100 | | struct payload_stats { |
101 | | u_int8_t *pattern; |
102 | | u_int8_t pattern_len; |
103 | | u_int16_t num_occurrencies; |
104 | | struct flow_id_stats *flows; |
105 | | struct packet_id_stats *packets; |
106 | | UT_hash_handle hh; /* makes this structure hashable */ |
107 | | }; |
108 | | |
109 | | |
110 | | struct payload_stats *pstats = NULL; |
111 | | u_int32_t max_num_packets_per_flow = 10; /* ETTA requires min 10 pkts for record. */ |
112 | | u_int32_t max_packet_payload_dissection = 128; |
113 | | u_int32_t max_num_reported_top_payloads = 25; |
114 | | u_int16_t min_pattern_len = 4; |
115 | | u_int16_t max_pattern_len = 8; |
116 | | |
117 | | |
118 | | /* *********************************************************** */ |
119 | | |
120 | | int ndpi_analyze_payload(struct ndpi_flow_info *flow, |
121 | | u_int8_t *payload, |
122 | | u_int16_t payload_len, |
123 | 115M | u_int32_t packet_id) { |
124 | 115M | struct payload_stats *ret, *ret_found; |
125 | 115M | struct flow_id_stats *f, *f_found; |
126 | 115M | struct packet_id_stats *p, *p_found; |
127 | | |
128 | | #ifdef DEBUG_PAYLOAD |
129 | | u_int16_t i; |
130 | | for(i=0; i<payload_len; i++) |
131 | | printf("%c", ndpi_isprint(payload[i]) ? payload[i] : '.'); |
132 | | printf("\n"); |
133 | | #endif |
134 | | |
135 | 115M | HASH_FIND(hh, pstats, payload, payload_len, ret); |
136 | 115M | if(ret == NULL) { |
137 | 42.2M | if((ret = (struct payload_stats*)ndpi_calloc(1, sizeof(struct payload_stats))) == NULL) |
138 | 2.63M | return -1; /* OOM */ |
139 | | |
140 | 39.6M | if((ret->pattern = (u_int8_t*)ndpi_malloc(payload_len)) == NULL) { |
141 | 2.52M | ndpi_free(ret); |
142 | 2.52M | return -1; |
143 | 2.52M | } |
144 | | |
145 | 37.1M | memcpy(ret->pattern, payload, payload_len); |
146 | 37.1M | ret->pattern_len = payload_len; |
147 | 37.1M | ret->num_occurrencies = 1; |
148 | | |
149 | 37.1M | HASH_ADD(hh, pstats, pattern[0], payload_len, ret); |
150 | | |
151 | 37.1M | HASH_FIND(hh, pstats, payload, payload_len, ret_found); |
152 | 37.1M | if(ret_found == NULL) { /* The insertion failed (because of a memory allocation error) */ |
153 | 4.35k | ndpi_free(ret->pattern); |
154 | 4.35k | ndpi_free(ret); |
155 | 4.35k | return -1; |
156 | 4.35k | } |
157 | | |
158 | | #ifdef DEBUG_PAYLOAD |
159 | | printf("Added element [total: %u]\n", HASH_COUNT(pstats)); |
160 | | #endif |
161 | 72.8M | } else { |
162 | 72.8M | ret->num_occurrencies++; |
163 | | // printf("==> %u\n", ret->num_occurrencies); |
164 | 72.8M | } |
165 | | |
166 | 110M | HASH_FIND_INT(ret->flows, &flow->flow_id, f); |
167 | 110M | if(f == NULL) { |
168 | 60.9M | if((f = (struct flow_id_stats*)ndpi_calloc(1, sizeof(struct flow_id_stats))) == NULL) |
169 | 3.78M | return -1; /* OOM */ |
170 | | |
171 | 57.2M | f->flow_id = flow->flow_id; |
172 | 57.2M | HASH_ADD_INT(ret->flows, flow_id, f); |
173 | | |
174 | 57.2M | HASH_FIND_INT(ret->flows, &flow->flow_id, f_found); |
175 | 57.2M | if(f_found == NULL) { /* The insertion failed (because of a memory allocation error) */ |
176 | 4.46M | ndpi_free(f); |
177 | 4.46M | return -1; |
178 | 4.46M | } |
179 | 57.2M | } |
180 | | |
181 | 101M | HASH_FIND_INT(ret->packets, &packet_id, p); |
182 | 101M | if(p == NULL) { |
183 | 82.1M | if((p = (struct packet_id_stats*)ndpi_calloc(1, sizeof(struct packet_id_stats))) == NULL) |
184 | 5.14M | return -1; /* OOM */ |
185 | 76.9M | p->packet_id = packet_id; |
186 | | |
187 | 76.9M | HASH_ADD_INT(ret->packets, packet_id, p); |
188 | | |
189 | 76.9M | HASH_FIND_INT(ret->packets, &packet_id, p_found); |
190 | 76.9M | if(p_found == NULL) { /* The insertion failed (because of a memory allocation error) */ |
191 | 3.96M | ndpi_free(p); |
192 | 3.96M | } |
193 | 76.9M | } |
194 | 96.6M | return 0; |
195 | 101M | } |
196 | | |
197 | | /* *********************************************************** */ |
198 | | |
199 | | void ndpi_payload_analyzer(struct ndpi_flow_info *flow, |
200 | | u_int8_t *payload, u_int16_t payload_len, |
201 | 483k | u_int32_t packet_id) { |
202 | 483k | u_int16_t i, j; |
203 | 483k | u_int16_t scan_len = ndpi_min(max_packet_payload_dissection, payload_len); |
204 | | |
205 | 483k | if((flow->src2dst_packets+flow->dst2src_packets) <= max_num_packets_per_flow) { |
206 | | #ifdef DEBUG_PAYLOAD |
207 | | printf("[hashval: %u][proto: %u][vlan: %u][%s:%u <-> %s:%u][direction: %s][payload_len: %u]\n", |
208 | | flow->hashval, flow->protocol, flow->vlan_id, |
209 | | flow->src_name ? flow->src_name : "", |
210 | | flow->src_port, |
211 | | flow->dst_name ? flow->dst_name : "", |
212 | | flow->dst_port, |
213 | | src_to_dst_direction ? "s2d" : "d2s", |
214 | | payload_len); |
215 | | #endif |
216 | 291k | } else |
217 | 192k | return; |
218 | | |
219 | 24.2M | for(i=0; i<scan_len; i++) { |
220 | 143M | for(j=min_pattern_len; j <= max_pattern_len; j++) { |
221 | 119M | if((i+j) < payload_len) { |
222 | 115M | if(ndpi_analyze_payload(flow, &payload[i], j, packet_id) == -1) { |
223 | 18.5M | LOG(NDPI_LOG_ERROR, "Error ndpi_analyze_payload (allocation failure)\n"); |
224 | 18.5M | } |
225 | 115M | } |
226 | 119M | } |
227 | 23.9M | } |
228 | 291k | } |
229 | | |
230 | | /* ***************************************************** */ |
231 | | |
232 | 310M | static int payload_stats_sort_asc(void *_a, void *_b) { |
233 | 310M | struct payload_stats *a = (struct payload_stats *)_a; |
234 | 310M | struct payload_stats *b = (struct payload_stats *)_b; |
235 | | |
236 | | //return(a->num_occurrencies - b->num_occurrencies); |
237 | 310M | return(b->num_occurrencies - a->num_occurrencies); |
238 | 310M | } |
239 | | |
240 | | /* ***************************************************** */ |
241 | | |
242 | 386k | static void print_payload_stat(struct payload_stats *p, FILE *out) { |
243 | 386k | u_int i; |
244 | 386k | struct flow_id_stats *s, *tmp; |
245 | 386k | struct packet_id_stats *s1, *tmp1; |
246 | | |
247 | 386k | fprintf(out, "\t["); |
248 | | |
249 | 2.58M | for(i=0; i<p->pattern_len; i++) { |
250 | 2.20M | fprintf(out, "%c", ndpi_isprint(p->pattern[i]) ? p->pattern[i] : '.'); |
251 | 2.20M | } |
252 | | |
253 | 386k | fprintf(out, "]"); |
254 | 4.36M | for(; i<16; i++) fprintf(out, " "); |
255 | 386k | fprintf(out, "["); |
256 | | |
257 | 2.58M | for(i=0; i<p->pattern_len; i++) { |
258 | 2.20M | fprintf(out, "%s%02X", (i > 0) ? " " : "", ndpi_isprint(p->pattern[i]) ? p->pattern[i] : '.'); |
259 | 2.20M | } |
260 | | |
261 | 386k | fprintf(out, "]"); |
262 | | |
263 | 4.36M | for(; i<16; i++) fprintf(out, " "); |
264 | 1.27M | for(i=p->pattern_len; i<max_pattern_len; i++) fprintf(out, " "); |
265 | | |
266 | 386k | fprintf(out, "[len: %u][num_occurrencies: %u][flowId: ", |
267 | 386k | p->pattern_len, p->num_occurrencies); |
268 | | |
269 | 386k | i = 0; |
270 | 1.41M | HASH_ITER(hh, p->flows, s, tmp) { |
271 | 1.41M | fprintf(out, "%s%u", (i > 0) ? " " : "", s->flow_id); |
272 | 1.41M | i++; |
273 | 1.41M | } |
274 | | |
275 | 386k | fprintf(out, "][packetIds: "); |
276 | | |
277 | | /* ******************************** */ |
278 | | |
279 | 386k | i = 0; |
280 | 2.63M | HASH_ITER(hh, p->packets, s1, tmp1) { |
281 | 2.63M | fprintf(out, "%s%u", (i > 0) ? " " : "", s1->packet_id); |
282 | 2.63M | i++; |
283 | 2.63M | } |
284 | | |
285 | 386k | fprintf(out, "]\n"); |
286 | | |
287 | | |
288 | 386k | } |
289 | | |
290 | | /* ***************************************************** */ |
291 | | |
292 | 16.8k | void ndpi_report_payload_stats(FILE *out) { |
293 | 16.8k | struct payload_stats *p, *tmp; |
294 | 16.8k | u_int num = 0; |
295 | | |
296 | 16.8k | if(out) |
297 | 16.8k | fprintf(out, "\n\nPayload Analysis\n"); |
298 | | |
299 | 16.8k | HASH_SORT(pstats, payload_stats_sort_asc); |
300 | | |
301 | 37.1M | HASH_ITER(hh, pstats, p, tmp) { |
302 | 37.1M | if(out && num <= max_num_reported_top_payloads) |
303 | 386k | print_payload_stat(p, out); |
304 | | |
305 | 37.1M | ndpi_free(p->pattern); |
306 | | |
307 | 37.1M | { |
308 | 37.1M | struct flow_id_stats *p1, *tmp1; |
309 | | |
310 | 52.7M | HASH_ITER(hh, p->flows, p1, tmp1) { |
311 | 52.7M | HASH_DEL(p->flows, p1); |
312 | 52.7M | ndpi_free(p1); |
313 | 52.7M | } |
314 | 37.1M | } |
315 | | |
316 | 37.1M | { |
317 | 37.1M | struct packet_id_stats *p1, *tmp1; |
318 | | |
319 | 72.9M | HASH_ITER(hh, p->packets, p1, tmp1) { |
320 | 72.9M | HASH_DEL(p->packets, p1); |
321 | 72.9M | ndpi_free(p1); |
322 | 72.9M | } |
323 | 37.1M | } |
324 | | |
325 | 37.1M | HASH_DEL(pstats, p); |
326 | 37.1M | ndpi_free(p); |
327 | 37.1M | num++; |
328 | 37.1M | } |
329 | 16.8k | } |
330 | | |
331 | | /* ***************************************************** */ |
332 | | |
333 | 5.06M | void ndpi_free_flow_info_half(struct ndpi_flow_info *flow) { |
334 | 5.06M | if(flow->ndpi_flow) { ndpi_flow_free(flow->ndpi_flow); flow->ndpi_flow = NULL; } |
335 | 5.06M | } |
336 | | |
337 | | /* ***************************************************** */ |
338 | | |
339 | 8.07k | void ndpi_stats_free(ndpi_stats_t *s) { |
340 | 8.07k | if (s->protocol_counter) ndpi_free(s->protocol_counter); |
341 | 8.07k | if (s->protocol_counter_bytes) ndpi_free(s->protocol_counter_bytes); |
342 | 8.07k | if (s->protocol_flows) ndpi_free(s->protocol_flows); |
343 | 8.07k | if (s->fpc_protocol_counter) ndpi_free(s->fpc_protocol_counter); |
344 | 8.07k | if (s->fpc_protocol_counter_bytes) ndpi_free(s->fpc_protocol_counter_bytes); |
345 | 8.07k | if (s->fpc_protocol_flows) ndpi_free(s->fpc_protocol_flows); |
346 | | |
347 | 8.07k | s->num_protocols = 0; |
348 | 8.07k | } |
349 | | |
350 | 8.07k | int ndpi_stats_init(ndpi_stats_t *s, uint32_t num_protocols) { |
351 | 8.07k | memset(s, 0, sizeof(*s)); |
352 | 8.07k | s->num_protocols = num_protocols; |
353 | | |
354 | 8.07k | s->protocol_counter = ndpi_calloc(num_protocols, sizeof(u_int64_t)); |
355 | 8.07k | s->protocol_counter_bytes = ndpi_calloc(num_protocols, sizeof(u_int64_t)); |
356 | 8.07k | s->protocol_flows = ndpi_calloc(num_protocols, sizeof(u_int32_t)); |
357 | 8.07k | s->fpc_protocol_counter = ndpi_calloc(num_protocols, sizeof(u_int64_t)); |
358 | 8.07k | s->fpc_protocol_counter_bytes = ndpi_calloc(num_protocols, sizeof(u_int64_t)); |
359 | 8.07k | s->fpc_protocol_flows = ndpi_calloc(num_protocols, sizeof(u_int32_t)); |
360 | | |
361 | 8.07k | if(!s->protocol_counter || !s->protocol_counter_bytes || !s->protocol_flows || |
362 | 8.00k | !s->fpc_protocol_counter || !s->fpc_protocol_counter_bytes || !s->fpc_protocol_flows) { |
363 | | |
364 | 168 | LOG(NDPI_LOG_ERROR, "[NDPI] %s: error allocating memory for ndpi_stats\n", __FUNCTION__); |
365 | 168 | return 0; |
366 | 168 | } |
367 | 7.91k | return 1; |
368 | 8.07k | } |
369 | | |
370 | 7.91k | void ndpi_stats_reset(ndpi_stats_t *s) { |
371 | 7.91k | memset(s->flow_count, 0, sizeof(s->flow_count)); |
372 | 7.91k | s->guessed_flow_protocols = 0; |
373 | 7.91k | s->raw_packet_count = 0; |
374 | 7.91k | s->ip_packet_count = 0; |
375 | 7.91k | s->total_wire_bytes = 0; |
376 | 7.91k | s->total_ip_bytes = 0; |
377 | 7.91k | s->total_discarded_bytes = 0; |
378 | 7.91k | s->ndpi_flow_count = 0; |
379 | 7.91k | s->tcp_count = 0; |
380 | 7.91k | s->udp_count = 0; |
381 | 7.91k | s->mpls_count = 0; |
382 | 7.91k | s->pppoe_count = 0; |
383 | 7.91k | s->vlan_count = 0; |
384 | 7.91k | s->fragmented_count = 0; |
385 | 7.91k | s->max_packet_len = 0; |
386 | 7.91k | s->num_dissector_calls = 0; |
387 | | |
388 | 7.91k | memset(s->packet_len, 0, sizeof(s->packet_len)); |
389 | 7.91k | memset(s->dpi_packet_count, 0, sizeof(s->dpi_packet_count)); |
390 | 7.91k | memset(s->flow_confidence, 0, sizeof(s->flow_confidence)); |
391 | 7.91k | memset(s->fpc_flow_confidence, 0, sizeof(s->fpc_flow_confidence)); |
392 | 7.91k | memset(s->category_counter, 0, sizeof(s->category_counter)); |
393 | 7.91k | memset(s->category_counter_bytes, 0, sizeof(s->category_counter_bytes)); |
394 | 7.91k | memset(s->category_flows, 0, sizeof(s->category_flows)); |
395 | 7.91k | memset(s->lru_stats, 0, sizeof(s->lru_stats)); |
396 | 7.91k | memset(s->automa_stats, 0, sizeof(s->automa_stats)); |
397 | 7.91k | memset(s->patricia_stats, 0, sizeof(s->patricia_stats)); |
398 | 7.91k | memset(s->hash_stats, 0, sizeof(s->hash_stats)); |
399 | | |
400 | 7.91k | if (s->protocol_counter) memset(s->protocol_counter, 0, sizeof(u_int64_t) * s->num_protocols); |
401 | 7.91k | if (s->protocol_counter_bytes) memset(s->protocol_counter_bytes, 0, sizeof(u_int64_t) * s->num_protocols); |
402 | 7.91k | if (s->protocol_flows) memset(s->protocol_flows, 0, sizeof(u_int32_t) * s->num_protocols); |
403 | 7.91k | if (s->fpc_protocol_counter) memset(s->fpc_protocol_counter, 0, sizeof(u_int64_t) * s->num_protocols); |
404 | 7.91k | if (s->fpc_protocol_counter_bytes) memset(s->fpc_protocol_counter_bytes, 0, sizeof(u_int64_t) * s->num_protocols); |
405 | 7.91k | if (s->fpc_protocol_flows) memset(s->fpc_protocol_flows, 0, sizeof(u_int32_t) * s->num_protocols); |
406 | 7.91k | } |
407 | | |
408 | | /* ***************************************************** */ |
409 | | |
410 | | struct ndpi_workflow* ndpi_workflow_init(const struct ndpi_workflow_prefs * prefs, |
411 | | pcap_t * pcap_handle, int do_init_flows_root, |
412 | | ndpi_serialization_format serialization_format, |
413 | 8.14k | struct ndpi_global_context *g_ctx) { |
414 | 8.14k | struct ndpi_detection_module_struct * module; |
415 | 8.14k | struct ndpi_workflow * workflow; |
416 | | |
417 | 8.14k | module = ndpi_init_detection_module(g_ctx); |
418 | | |
419 | 8.14k | if(module == NULL) { |
420 | 51 | LOG(NDPI_LOG_ERROR, "global structure initialization failed\n"); |
421 | 51 | return NULL; |
422 | 51 | } |
423 | | |
424 | 8.09k | workflow = ndpi_calloc(1, sizeof(struct ndpi_workflow)); |
425 | 8.09k | if(workflow == NULL) { |
426 | 1 | LOG(NDPI_LOG_ERROR, "global structure initialization failed\n"); |
427 | 1 | ndpi_exit_detection_module(module); |
428 | 1 | return NULL; |
429 | 1 | } |
430 | | |
431 | 8.08k | workflow->pcap_handle = pcap_handle; |
432 | 8.08k | workflow->prefs = *prefs; |
433 | 8.08k | workflow->ndpi_struct = module; |
434 | | |
435 | 8.08k | ndpi_set_user_data(module, workflow); |
436 | | |
437 | 8.08k | if(do_init_flows_root) { |
438 | 8.07k | workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *)); |
439 | | |
440 | 8.07k | if(!workflow->ndpi_flows_root) { |
441 | 1 | ndpi_exit_detection_module(module); |
442 | 1 | ndpi_free(workflow); |
443 | 1 | return NULL; |
444 | 1 | } |
445 | 8.07k | } |
446 | | |
447 | 8.08k | workflow->ndpi_serialization_format = serialization_format; |
448 | | |
449 | 8.08k | return workflow; |
450 | 8.08k | } |
451 | | |
452 | | /* ***************************************************** */ |
453 | | |
454 | 4.35M | void ndpi_flow_info_freer(void *node) { |
455 | 4.35M | struct ndpi_flow_info *flow = (struct ndpi_flow_info*)node; |
456 | | |
457 | 4.35M | ndpi_flow_info_free_data(flow); |
458 | 4.35M | ndpi_free(flow); |
459 | 4.35M | } |
460 | | |
461 | | /* ***************************************************** */ |
462 | | |
463 | 4.51M | static void ndpi_free_flow_tls_data(struct ndpi_flow_info *flow) { |
464 | 4.51M | if(flow->dhcp_fingerprint) { |
465 | 1.72k | ndpi_free(flow->dhcp_fingerprint); |
466 | 1.72k | flow->dhcp_fingerprint = NULL; |
467 | 1.72k | } |
468 | | |
469 | 4.51M | if(flow->dhcp_class_ident) { |
470 | 1.16k | ndpi_free(flow->dhcp_class_ident); |
471 | 1.16k | flow->dhcp_class_ident = NULL; |
472 | 1.16k | } |
473 | | |
474 | 4.51M | if(flow->server_hostname) { |
475 | 553k | ndpi_free(flow->server_hostname); |
476 | 553k | flow->server_hostname = NULL; |
477 | 553k | } |
478 | | |
479 | 4.51M | if(flow->bittorent_hash) { |
480 | 2.60k | ndpi_free(flow->bittorent_hash); |
481 | 2.60k | flow->bittorent_hash = NULL; |
482 | 2.60k | } |
483 | | |
484 | 4.51M | if(flow->telnet.username) { |
485 | 595 | ndpi_free(flow->telnet.username); |
486 | 595 | flow->telnet.username = NULL; |
487 | 595 | } |
488 | | |
489 | 4.51M | if(flow->telnet.password) { |
490 | 242 | ndpi_free(flow->telnet.password); |
491 | 242 | flow->telnet.password = NULL; |
492 | 242 | } |
493 | | |
494 | 4.51M | if(flow->ssh_tls.server_names) { |
495 | 7.16k | ndpi_free(flow->ssh_tls.server_names); |
496 | 7.16k | flow->ssh_tls.server_names = NULL; |
497 | 7.16k | } |
498 | | |
499 | 4.51M | if(flow->ssh_tls.advertised_alpns) { |
500 | 40.5k | ndpi_free(flow->ssh_tls.advertised_alpns); |
501 | 40.5k | flow->ssh_tls.advertised_alpns = NULL; |
502 | 40.5k | } |
503 | | |
504 | 4.51M | if(flow->ssh_tls.negotiated_alpn) { |
505 | 6.18k | ndpi_free(flow->ssh_tls.negotiated_alpn); |
506 | 6.18k | flow->ssh_tls.negotiated_alpn = NULL; |
507 | 6.18k | } |
508 | | |
509 | 4.51M | if(flow->ssh_tls.tls_supported_versions) { |
510 | 27.8k | ndpi_free(flow->ssh_tls.tls_supported_versions); |
511 | 27.8k | flow->ssh_tls.tls_supported_versions = NULL; |
512 | 27.8k | } |
513 | | |
514 | 4.51M | if(flow->ssh_tls.tls_issuerDN) { |
515 | 9.33k | ndpi_free(flow->ssh_tls.tls_issuerDN); |
516 | 9.33k | flow->ssh_tls.tls_issuerDN = NULL; |
517 | 9.33k | } |
518 | | |
519 | 4.51M | if(flow->ssh_tls.tls_subjectDN) { |
520 | 10.2k | ndpi_free(flow->ssh_tls.tls_subjectDN); |
521 | 10.2k | flow->ssh_tls.tls_subjectDN = NULL; |
522 | 10.2k | } |
523 | | |
524 | 4.51M | if(flow->ssh_tls.ja4_client_raw) { |
525 | 49.1k | ndpi_free(flow->ssh_tls.ja4_client_raw); |
526 | 49.1k | flow->ssh_tls.ja4_client_raw = NULL; |
527 | 49.1k | } |
528 | | |
529 | 4.51M | if(flow->ndpi_fingerprint) { |
530 | 53.0k | ndpi_free(flow->ndpi_fingerprint); |
531 | 53.0k | flow->ndpi_fingerprint = NULL; |
532 | 53.0k | } |
533 | | |
534 | 4.51M | if(flow->stun.mapped_address.aps) { |
535 | 12.7k | ndpi_free(flow->stun.mapped_address.aps); |
536 | 12.7k | flow->stun.mapped_address.aps = NULL; |
537 | 12.7k | } |
538 | 4.51M | if(flow->stun.other_address.aps) { |
539 | 1.36k | ndpi_free(flow->stun.other_address.aps); |
540 | 1.36k | flow->stun.other_address.aps = NULL; |
541 | 1.36k | } |
542 | 4.51M | if(flow->stun.peer_address.aps) { |
543 | 6.13k | ndpi_free(flow->stun.peer_address.aps); |
544 | 6.13k | flow->stun.peer_address.aps = NULL; |
545 | 6.13k | } |
546 | 4.51M | if(flow->stun.relayed_address.aps) { |
547 | 4.19k | ndpi_free(flow->stun.relayed_address.aps); |
548 | 4.19k | flow->stun.relayed_address.aps = NULL; |
549 | 4.19k | } |
550 | 4.51M | if(flow->stun.response_origin.aps) { |
551 | 1.59k | ndpi_free(flow->stun.response_origin.aps); |
552 | 1.59k | flow->stun.response_origin.aps = NULL; |
553 | 1.59k | } |
554 | 4.51M | } |
555 | | |
556 | | /* ***************************************************** */ |
557 | | |
558 | 4.51M | static void ndpi_free_flow_data_analysis(struct ndpi_flow_info *flow) { |
559 | 4.51M | if(flow->iat_c_to_s) ndpi_free_data_analysis(flow->iat_c_to_s, 1); |
560 | 4.51M | if(flow->iat_s_to_c) ndpi_free_data_analysis(flow->iat_s_to_c, 1); |
561 | | |
562 | 4.51M | if(flow->pktlen_c_to_s) ndpi_free_data_analysis(flow->pktlen_c_to_s, 1); |
563 | 4.51M | if(flow->pktlen_s_to_c) ndpi_free_data_analysis(flow->pktlen_s_to_c, 1); |
564 | | |
565 | 4.51M | if(flow->iat_flow) ndpi_free_data_analysis(flow->iat_flow, 1); |
566 | | |
567 | 4.51M | if(flow->entropy) ndpi_free(flow->entropy); |
568 | 4.51M | if(flow->last_entropy) ndpi_free(flow->last_entropy); |
569 | 4.51M | } |
570 | | |
571 | | /* ***************************************************** */ |
572 | | |
573 | 4.51M | void ndpi_flow_info_free_data(struct ndpi_flow_info *flow) { |
574 | | |
575 | 4.51M | ndpi_free_flow_info_half(flow); |
576 | 4.51M | ndpi_term_serializer(&flow->ndpi_flow_serializer); |
577 | 4.51M | ndpi_free_flow_data_analysis(flow); |
578 | 4.51M | ndpi_free_flow_tls_data(flow); |
579 | | |
580 | | #ifdef DIRECTION_BINS |
581 | | ndpi_free_bin(&flow->payload_len_bin_src2dst); |
582 | | ndpi_free_bin(&flow->payload_len_bin_dst2src); |
583 | | #else |
584 | 4.51M | ndpi_free_bin(&flow->payload_len_bin); |
585 | 4.51M | #endif |
586 | | |
587 | 4.51M | if(flow->src_name) ndpi_free(flow->src_name); |
588 | 4.51M | if(flow->dst_name) ndpi_free(flow->dst_name); |
589 | 4.51M | if(flow->tcp_fingerprint) ndpi_free(flow->tcp_fingerprint); |
590 | 4.51M | if(flow->risk_str) ndpi_free(flow->risk_str); |
591 | 4.51M | if(flow->flow_payload) ndpi_free(flow->flow_payload); |
592 | 4.51M | } |
593 | | |
594 | | /* ***************************************************** */ |
595 | | |
596 | 8.07k | void ndpi_workflow_free(struct ndpi_workflow * workflow) { |
597 | 8.07k | u_int i; |
598 | | |
599 | 750k | for(i=0; i<workflow->prefs.num_roots; i++) |
600 | 742k | ndpi_tdestroy(workflow->ndpi_flows_root[i], ndpi_flow_info_freer); |
601 | | |
602 | 8.07k | if(addr_dump_path != NULL) |
603 | 8.07k | ndpi_cache_address_dump(workflow->ndpi_struct, addr_dump_path, 0); |
604 | | |
605 | 8.07k | ndpi_exit_detection_module(workflow->ndpi_struct); |
606 | 8.07k | ndpi_free(workflow->ndpi_flows_root); |
607 | | |
608 | 8.07k | ndpi_stats_free(&workflow->stats); |
609 | | |
610 | 8.07k | ndpi_free(workflow); |
611 | 8.07k | } |
612 | | |
613 | 20.7M | static inline int cmp_n32(uint32_t a,uint32_t b) { |
614 | 20.7M | return a == b ? 0 : ntohl(a) < ntohl(b) ? -1:1; |
615 | 20.7M | } |
616 | 16.4M | static inline int cmp_n16(uint16_t a,uint16_t b) { |
617 | 16.4M | return a == b ? 0 : ntohs(a) < ntohs(b) ? -1:1; |
618 | 16.4M | } |
619 | | |
620 | | /* ***************************************************** */ |
621 | | |
622 | 117M | int ndpi_workflow_node_cmp(const void *a, const void *b) { |
623 | 117M | const struct ndpi_flow_info *fa = (const struct ndpi_flow_info*)a; |
624 | 117M | const struct ndpi_flow_info *fb = (const struct ndpi_flow_info*)b; |
625 | | |
626 | 117M | if(fa->hashval < fb->hashval) return(-1); else if(fa->hashval > fb->hashval) return(1); |
627 | | |
628 | | /* Flows have the same hash */ |
629 | | |
630 | 13.2M | if(fa->vlan_id < fb->vlan_id ) return(-1); else { if(fa->vlan_id > fb->vlan_id ) return(1); } |
631 | 13.2M | if(fa->protocol < fb->protocol ) return(-1); else { if(fa->protocol > fb->protocol ) return(1); } |
632 | | |
633 | 13.2M | int r; |
634 | 13.2M | r = cmp_n32(fa->src_ip, fb->src_ip); if(r) return r; |
635 | 9.04M | r = cmp_n16(fa->src_port, fb->src_port) ; if(r) return r; |
636 | 7.46M | r = cmp_n32(fa->dst_ip, fb->dst_ip); if(r) return r; |
637 | 7.45M | r = cmp_n16(fa->dst_port, fb->dst_port); |
638 | | |
639 | 7.45M | return(r); |
640 | 7.46M | } |
641 | | |
642 | | /* ***************************************************** */ |
643 | | |
644 | | /** |
645 | | * \brief Update the byte count for the flow record. |
646 | | * \param f Flow data |
647 | | * \param x Data to use for update |
648 | | * \param len Length of the data (in bytes) |
649 | | * \return none |
650 | | */ |
651 | | static void |
652 | | ndpi_flow_update_byte_count(struct ndpi_flow_info *flow, const void *x, |
653 | 11.6M | unsigned int len, u_int8_t src_to_dst_direction) { |
654 | | /* |
655 | | * implementation note: The spec says that 4000 octets is enough of a |
656 | | * sample size to accurately reflect the byte distribution. Also, to avoid |
657 | | * wrapping of the byte count at the 16-bit boundry, we stop counting once |
658 | | * the 4000th octet has been seen for a flow. |
659 | | */ |
660 | | |
661 | 11.6M | if((flow->entropy->src2dst_pkt_count+flow->entropy->dst2src_pkt_count) <= max_num_packets_per_flow) { |
662 | | /* octet count was already incremented before processing this payload */ |
663 | 11.6M | u_int32_t current_count; |
664 | | |
665 | 11.6M | if(src_to_dst_direction) { |
666 | 9.27M | current_count = flow->entropy->src2dst_l4_bytes - len; |
667 | 9.27M | } else { |
668 | 2.37M | current_count = flow->entropy->dst2src_l4_bytes - len; |
669 | 2.37M | } |
670 | | |
671 | 11.6M | if(current_count < ETTA_MIN_OCTETS) { |
672 | 11.2M | u_int32_t i; |
673 | 11.2M | const unsigned char *data = x; |
674 | | |
675 | 2.63G | for(i=0; i<len; i++) { |
676 | 2.62G | if(src_to_dst_direction) { |
677 | 1.96G | flow->entropy->src2dst_byte_count[data[i]]++; |
678 | 1.96G | } else { |
679 | 662M | flow->entropy->dst2src_byte_count[data[i]]++; |
680 | 662M | } |
681 | 2.62G | current_count++; |
682 | 2.62G | if(current_count >= ETTA_MIN_OCTETS) { |
683 | 152k | break; |
684 | 152k | } |
685 | 2.62G | } |
686 | 11.2M | } |
687 | 11.6M | } |
688 | 11.6M | } |
689 | | |
690 | | /* ***************************************************** */ |
691 | | |
692 | | /** |
693 | | * \brief Update the byte distribution mean for the flow record. |
694 | | * \param f Flow record |
695 | | * \param x Data to use for update |
696 | | * \param len Length of the data (in bytes) |
697 | | * \return none |
698 | | */ |
699 | | static void |
700 | | ndpi_flow_update_byte_dist_mean_var(ndpi_flow_info_t *flow, const void *x, |
701 | 11.6M | unsigned int len, u_int8_t src_to_dst_direction) { |
702 | 11.6M | const unsigned char *data = x; |
703 | | |
704 | 11.6M | if((flow->entropy->src2dst_pkt_count+flow->entropy->dst2src_pkt_count) <= max_num_packets_per_flow) { |
705 | 11.6M | unsigned int i; |
706 | | |
707 | 3.57G | for(i=0; i<len; i++) { |
708 | 3.55G | double delta; |
709 | | |
710 | 3.55G | if(src_to_dst_direction) { |
711 | 2.61G | flow->entropy->src2dst_num_bytes += 1; |
712 | 2.61G | delta = ((double)data[i] - flow->entropy->src2dst_bd_mean); |
713 | 2.61G | flow->entropy->src2dst_bd_mean += delta/((double)flow->entropy->src2dst_num_bytes); |
714 | 2.61G | flow->entropy->src2dst_bd_variance += delta*((double)data[i] - flow->entropy->src2dst_bd_mean); |
715 | 2.61G | } else { |
716 | 943M | flow->entropy->dst2src_num_bytes += 1; |
717 | 943M | delta = ((double)data[i] - flow->entropy->dst2src_bd_mean); |
718 | 943M | flow->entropy->dst2src_bd_mean += delta/((double)flow->entropy->dst2src_num_bytes); |
719 | 943M | flow->entropy->dst2src_bd_variance += delta*((double)data[i] - flow->entropy->dst2src_bd_mean); |
720 | 943M | } |
721 | 3.55G | } |
722 | 11.6M | } |
723 | 11.6M | } |
724 | | |
725 | | /* ***************************************************** */ |
726 | | |
727 | | static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow, |
728 | | const u_int8_t version, |
729 | | u_int16_t vlan_id, |
730 | | ndpi_packet_tunnel tunnel_type, |
731 | | const struct ndpi_iphdr *iph, |
732 | | const struct ndpi_ipv6hdr *iph6, |
733 | | u_int16_t ipsize, |
734 | | u_int16_t l4_packet_len, |
735 | | u_int16_t l4_offset, |
736 | | struct ndpi_tcphdr **tcph, |
737 | | struct ndpi_udphdr **udph, |
738 | | u_int16_t *sport, u_int16_t *dport, |
739 | | u_int8_t *proto, |
740 | | u_int8_t **payload, |
741 | | u_int16_t *payload_len, |
742 | | u_int8_t *src_to_dst_direction, |
743 | 12.0M | pkt_timeval when) { |
744 | 12.0M | u_int32_t idx, hashval; |
745 | 12.0M | struct ndpi_flow_info flow; |
746 | 12.0M | void *ret; |
747 | 12.0M | const u_int8_t *l3, *l4; |
748 | 12.0M | u_int32_t l4_data_len = 0XFEEDFACE; |
749 | | |
750 | | /* |
751 | | Note: to keep things simple (ndpiReader is just a demo app) |
752 | | we handle IPv6 a-la-IPv4. |
753 | | */ |
754 | 12.0M | if(version == IPVERSION) { |
755 | 11.3M | if(ipsize < 20) |
756 | 44 | return NULL; |
757 | | |
758 | 11.3M | if((iph->ihl * 4) > ipsize || ipsize < ntohs(iph->tot_len) |
759 | 11.3M | /* || (iph->frag_off & htons(0x1FFF)) != 0 */) |
760 | 53.0k | return NULL; |
761 | | |
762 | 11.3M | l3 = (const u_int8_t*)iph; |
763 | 11.3M | } else { |
764 | 647k | if(l4_offset > ipsize) |
765 | 0 | return NULL; |
766 | | |
767 | 647k | l3 = (const u_int8_t*)iph6; |
768 | 647k | } |
769 | 11.9M | if(ipsize < l4_offset + l4_packet_len) |
770 | 2.54k | return NULL; |
771 | | |
772 | 11.9M | *proto = iph->protocol; |
773 | | |
774 | 11.9M | if(l4_packet_len < 64) |
775 | 5.55M | workflow->stats.packet_len[0]++; |
776 | 6.39M | else if(l4_packet_len >= 64 && l4_packet_len < 128) |
777 | 1.64M | workflow->stats.packet_len[1]++; |
778 | 4.74M | else if(l4_packet_len >= 128 && l4_packet_len < 256) |
779 | 1.75M | workflow->stats.packet_len[2]++; |
780 | 2.99M | else if(l4_packet_len >= 256 && l4_packet_len < 1024) |
781 | 1.84M | workflow->stats.packet_len[3]++; |
782 | 1.14M | else if(l4_packet_len >= 1024 && l4_packet_len < 1500) |
783 | 1.04M | workflow->stats.packet_len[4]++; |
784 | 107k | else if(l4_packet_len >= 1500) |
785 | 107k | workflow->stats.packet_len[5]++; |
786 | | |
787 | 11.9M | if(l4_packet_len > workflow->stats.max_packet_len) |
788 | 16.1k | workflow->stats.max_packet_len = l4_packet_len; |
789 | | |
790 | 11.9M | l4 =& ((const u_int8_t *) l3)[l4_offset]; |
791 | | |
792 | 11.9M | if(*proto == IPPROTO_TCP && l4_packet_len >= sizeof(struct ndpi_tcphdr)) { |
793 | 8.30M | u_int tcp_len; |
794 | | |
795 | | // TCP |
796 | 8.30M | workflow->stats.tcp_count++; |
797 | 8.30M | *tcph = (struct ndpi_tcphdr *)l4; |
798 | 8.30M | *sport = ntohs((*tcph)->source), *dport = ntohs((*tcph)->dest); |
799 | 8.30M | tcp_len = ndpi_min(4*(*tcph)->doff, l4_packet_len); |
800 | 8.30M | *payload = (u_int8_t*)&l4[tcp_len]; |
801 | 8.30M | *payload_len = ndpi_max(0, l4_packet_len-4*(*tcph)->doff); |
802 | 8.30M | l4_data_len = l4_packet_len - sizeof(struct ndpi_tcphdr); |
803 | 8.30M | } else if(*proto == IPPROTO_UDP && l4_packet_len >= sizeof(struct ndpi_udphdr)) { |
804 | | // UDP |
805 | 3.41M | workflow->stats.udp_count++; |
806 | 3.41M | *udph = (struct ndpi_udphdr *)l4; |
807 | 3.41M | *sport = ntohs((*udph)->source), *dport = ntohs((*udph)->dest); |
808 | 3.41M | *payload = (u_int8_t*)&l4[sizeof(struct ndpi_udphdr)]; |
809 | 3.41M | *payload_len = (l4_packet_len > sizeof(struct ndpi_udphdr)) ? l4_packet_len-sizeof(struct ndpi_udphdr) : 0; |
810 | 3.41M | l4_data_len = l4_packet_len - sizeof(struct ndpi_udphdr); |
811 | 3.41M | } else if(*proto == IPPROTO_ICMP) { |
812 | 61.1k | *payload = (u_int8_t*)&l4[sizeof(struct ndpi_icmphdr )]; |
813 | 61.1k | *payload_len = (l4_packet_len > sizeof(struct ndpi_icmphdr)) ? l4_packet_len-sizeof(struct ndpi_icmphdr) : 0; |
814 | 61.1k | l4_data_len = l4_packet_len - sizeof(struct ndpi_icmphdr); |
815 | 61.1k | *sport = *dport = 0; |
816 | 173k | } else if(*proto == IPPROTO_ICMPV6) { |
817 | 89.0k | *payload = (u_int8_t*)&l4[sizeof(struct ndpi_icmp6hdr)]; |
818 | 89.0k | *payload_len = (l4_packet_len > sizeof(struct ndpi_icmp6hdr)) ? l4_packet_len-sizeof(struct ndpi_icmp6hdr) : 0; |
819 | 89.0k | l4_data_len = l4_packet_len - sizeof(struct ndpi_icmp6hdr); |
820 | 89.0k | *sport = *dport = 0; |
821 | 89.0k | } else { |
822 | | // non tcp/udp protocols |
823 | 84.8k | *sport = *dport = 0; |
824 | 84.8k | l4_data_len = 0; |
825 | 84.8k | } |
826 | | |
827 | 11.9M | flow.protocol = iph->protocol, flow.vlan_id = vlan_id; |
828 | 11.9M | flow.src_ip = iph->saddr, flow.dst_ip = iph->daddr; |
829 | 11.9M | flow.src_port = htons(*sport), flow.dst_port = htons(*dport); |
830 | 11.9M | flow.hashval = hashval = flow.protocol + ntohl(flow.src_ip) + ntohl(flow.dst_ip) |
831 | 11.9M | + ntohs(flow.src_port) + ntohs(flow.dst_port); |
832 | | |
833 | | #if 0 |
834 | | { |
835 | | char ip1[48],ip2[48]; |
836 | | inet_ntop(AF_INET, &flow.src_ip, ip1, sizeof(ip1)); |
837 | | inet_ntop(AF_INET, &flow.dst_ip, ip2, sizeof(ip2)); |
838 | | printf("hashval=%u [%u][%u][%s:%u][%s:%u]\n", hashval, flow.protocol, flow.vlan_id, |
839 | | ip1, ntohs(flow.src_port), ip2, ntohs(flow.dst_port)); |
840 | | } |
841 | | #endif |
842 | | |
843 | 11.9M | idx = hashval % workflow->prefs.num_roots; |
844 | 11.9M | ret = ndpi_tfind(&flow, &workflow->ndpi_flows_root[idx], ndpi_workflow_node_cmp); |
845 | | |
846 | | /* to avoid two nodes in one binary tree for a flow */ |
847 | 11.9M | int is_changed = 0; |
848 | 11.9M | if(ret == NULL) { |
849 | 6.95M | u_int32_t orig_src_ip = flow.src_ip; |
850 | 6.95M | u_int16_t orig_src_port = flow.src_port; |
851 | 6.95M | u_int32_t orig_dst_ip = flow.dst_ip; |
852 | 6.95M | u_int16_t orig_dst_port = flow.dst_port; |
853 | | |
854 | 6.95M | flow.src_ip = orig_dst_ip; |
855 | 6.95M | flow.src_port = orig_dst_port; |
856 | 6.95M | flow.dst_ip = orig_src_ip; |
857 | 6.95M | flow.dst_port = orig_src_port; |
858 | | |
859 | 6.95M | is_changed = 1; |
860 | | |
861 | 6.95M | ret = ndpi_tfind(&flow, &workflow->ndpi_flows_root[idx], ndpi_workflow_node_cmp); |
862 | 6.95M | } |
863 | | |
864 | 11.9M | if(ret == NULL) { |
865 | 4.55M | if(workflow->stats.ndpi_flow_count == workflow->prefs.max_ndpi_flows) { |
866 | 519 | LOG(NDPI_LOG_ERROR, |
867 | 519 | "maximum flow count (%u) has been exceeded\n", |
868 | 519 | workflow->prefs.max_ndpi_flows); |
869 | 519 | return NULL; |
870 | 4.55M | } else { |
871 | 4.55M | struct ndpi_flow_info *newflow = (struct ndpi_flow_info*)ndpi_malloc(sizeof(struct ndpi_flow_info)); |
872 | | |
873 | 4.55M | if(newflow == NULL) { |
874 | 38.3k | LOG(NDPI_LOG_ERROR, "[NDPI] %s(1): not enough memory\n", __FUNCTION__); |
875 | 38.3k | return(NULL); |
876 | 38.3k | } else |
877 | 4.51M | workflow->num_allocated_flows++; |
878 | | |
879 | 4.51M | memset(newflow, 0, sizeof(struct ndpi_flow_info)); |
880 | 4.51M | newflow->flow_id = flow_id++; |
881 | 4.51M | newflow->hashval = hashval; |
882 | 4.51M | newflow->tunnel_type = tunnel_type; |
883 | 4.51M | newflow->protocol = iph->protocol, newflow->vlan_id = vlan_id; |
884 | 4.51M | newflow->src_ip = iph->saddr, newflow->dst_ip = iph->daddr; |
885 | 4.51M | newflow->src_port = htons(*sport), newflow->dst_port = htons(*dport); |
886 | 4.51M | newflow->ip_version = version; |
887 | 4.51M | newflow->iat_c_to_s = ndpi_alloc_data_analysis(DATA_ANALUYSIS_SLIDING_WINDOW), |
888 | 4.51M | newflow->iat_s_to_c = ndpi_alloc_data_analysis(DATA_ANALUYSIS_SLIDING_WINDOW); |
889 | 4.51M | newflow->pktlen_c_to_s = ndpi_alloc_data_analysis(DATA_ANALUYSIS_SLIDING_WINDOW), |
890 | 4.51M | newflow->pktlen_s_to_c = ndpi_alloc_data_analysis(DATA_ANALUYSIS_SLIDING_WINDOW), |
891 | 4.51M | newflow->iat_flow = ndpi_alloc_data_analysis(DATA_ANALUYSIS_SLIDING_WINDOW); |
892 | | |
893 | | #ifdef DIRECTION_BINS |
894 | | ndpi_init_bin(&newflow->payload_len_bin_src2dst, ndpi_bin_family8, PLEN_NUM_BINS); |
895 | | ndpi_init_bin(&newflow->payload_len_bin_dst2src, ndpi_bin_family8, PLEN_NUM_BINS); |
896 | | #else |
897 | 4.51M | ndpi_init_bin(&newflow->payload_len_bin, ndpi_bin_family8, PLEN_NUM_BINS); |
898 | 4.51M | #endif |
899 | | |
900 | 4.51M | if (version == 4 || version == 6) { |
901 | 4.51M | uint16_t inet_addrlen = (version == 4) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; |
902 | 4.51M | newflow->src_name = ndpi_malloc(inet_addrlen); |
903 | 4.51M | newflow->dst_name = ndpi_malloc(inet_addrlen); |
904 | | |
905 | 4.51M | if(version == 4) { |
906 | 4.36M | if (newflow->src_name) |
907 | 4.32M | inet_ntop(AF_INET, &newflow->src_ip, newflow->src_name, inet_addrlen); |
908 | 4.36M | if (newflow->dst_name) |
909 | 4.32M | inet_ntop(AF_INET, &newflow->dst_ip, newflow->dst_name, inet_addrlen); |
910 | 4.36M | } else if (version == 6) { |
911 | 150k | newflow->src_ip6 = *(struct ndpi_in6_addr *)&iph6->ip6_src; |
912 | 150k | newflow->dst_ip6 = *(struct ndpi_in6_addr *)&iph6->ip6_dst; |
913 | | |
914 | 150k | if (newflow->src_name) |
915 | 148k | inet_ntop(AF_INET6, &newflow->src_ip6, newflow->src_name, inet_addrlen); |
916 | 150k | if (newflow->dst_name) |
917 | 148k | inet_ntop(AF_INET6, &newflow->dst_ip6, newflow->dst_name, inet_addrlen); |
918 | | |
919 | | /* For consistency across platforms replace :0: with :: */ |
920 | 150k | if (newflow->src_name) ndpi_patchIPv6Address(newflow->src_name); |
921 | 150k | if (newflow->dst_name) ndpi_patchIPv6Address(newflow->dst_name); |
922 | 150k | } |
923 | 4.51M | } |
924 | | |
925 | 4.51M | if((newflow->ndpi_flow = ndpi_flow_malloc(SIZEOF_FLOW_STRUCT)) == NULL) { |
926 | 35.2k | LOG(NDPI_LOG_ERROR, "[NDPI] %s(2): not enough memory\n", __FUNCTION__); |
927 | 35.2k | ndpi_flow_info_free_data(newflow); |
928 | 35.2k | ndpi_free(newflow); |
929 | 35.2k | return(NULL); |
930 | 35.2k | } else |
931 | 4.47M | memset(newflow->ndpi_flow, 0, SIZEOF_FLOW_STRUCT); |
932 | | |
933 | 4.47M | if (workflow->ndpi_serialization_format != ndpi_serialization_format_unknown) |
934 | 4.47M | { |
935 | 4.47M | if (ndpi_init_serializer(&newflow->ndpi_flow_serializer, |
936 | 4.47M | workflow->ndpi_serialization_format) != 0) |
937 | 33.7k | { |
938 | 33.7k | LOG(NDPI_LOG_ERROR, "ndpi serializer init failed\n"); |
939 | 33.7k | ndpi_flow_info_free_data(newflow); |
940 | 33.7k | ndpi_free(newflow); |
941 | 33.7k | return(NULL); |
942 | 33.7k | } |
943 | 4.47M | } |
944 | | |
945 | 4.44M | if(ndpi_tsearch(newflow, &workflow->ndpi_flows_root[idx], ndpi_workflow_node_cmp) == NULL) { /* Add */ |
946 | 31.2k | ndpi_flow_info_free_data(newflow); |
947 | 31.2k | ndpi_free(newflow); |
948 | 31.2k | return(NULL); |
949 | 31.2k | } |
950 | 4.41M | workflow->stats.ndpi_flow_count++; |
951 | 4.41M | if(*proto == IPPROTO_TCP) |
952 | 3.42M | workflow->stats.flow_count[0]++; |
953 | 988k | else if(*proto == IPPROTO_UDP) |
954 | 942k | workflow->stats.flow_count[1]++; |
955 | 45.9k | else |
956 | 45.9k | workflow->stats.flow_count[2]++; |
957 | | |
958 | 4.41M | if(enable_flow_stats) { |
959 | 4.37M | newflow->entropy = ndpi_calloc(1, sizeof(struct ndpi_entropy)); |
960 | 4.37M | newflow->last_entropy = ndpi_calloc(1, sizeof(struct ndpi_entropy)); |
961 | 4.37M | if(!newflow->entropy || !newflow->last_entropy) { |
962 | 54.0k | ndpi_tdelete(newflow, &workflow->ndpi_flows_root[idx], ndpi_workflow_node_cmp); |
963 | 54.0k | ndpi_flow_info_free_data(newflow); |
964 | 54.0k | ndpi_free(newflow); |
965 | 54.0k | return(NULL); |
966 | 54.0k | } |
967 | 4.32M | newflow->entropy->src2dst_pkt_len[newflow->entropy->src2dst_pkt_count] = l4_data_len; |
968 | 4.32M | newflow->entropy->src2dst_pkt_time[newflow->entropy->src2dst_pkt_count] = when; |
969 | 4.32M | if(newflow->entropy->src2dst_pkt_count == 0) { |
970 | 4.32M | newflow->entropy->src2dst_start = when; |
971 | 4.32M | } |
972 | 4.32M | newflow->entropy->src2dst_pkt_count++; |
973 | | // Non zero app data. |
974 | 4.32M | if(l4_data_len != 0XFEEDFACE && l4_data_len != 0) { |
975 | 4.26M | newflow->entropy->src2dst_opackets++; |
976 | 4.26M | newflow->entropy->src2dst_l4_bytes += l4_data_len; |
977 | 4.26M | } |
978 | 4.32M | } |
979 | 4.35M | return newflow; |
980 | 4.41M | } |
981 | 7.39M | } else { |
982 | 7.39M | struct ndpi_flow_info *rflow = *(struct ndpi_flow_info**)ret; |
983 | | |
984 | 7.39M | if(is_changed) { |
985 | 2.40M | *src_to_dst_direction = 0, rflow->bidirectional |= 1; |
986 | 2.40M | } |
987 | 4.99M | else { |
988 | 4.99M | *src_to_dst_direction = 1; |
989 | 4.99M | } |
990 | 7.39M | if(enable_flow_stats) { |
991 | 7.32M | if(*src_to_dst_direction) { |
992 | 4.95M | if(rflow->entropy->src2dst_pkt_count < max_num_packets_per_flow) { |
993 | 4.95M | rflow->entropy->src2dst_pkt_len[rflow->entropy->src2dst_pkt_count] = l4_data_len; |
994 | 4.95M | rflow->entropy->src2dst_pkt_time[rflow->entropy->src2dst_pkt_count] = when; |
995 | 4.95M | rflow->entropy->src2dst_l4_bytes += l4_data_len; |
996 | 4.95M | rflow->entropy->src2dst_pkt_count++; |
997 | 4.95M | } |
998 | | // Non zero app data. |
999 | 4.95M | if(l4_data_len != 0XFEEDFACE && l4_data_len != 0) { |
1000 | 4.68M | rflow->entropy->src2dst_opackets++; |
1001 | 4.68M | } |
1002 | 4.95M | } else { |
1003 | 2.37M | if(rflow->entropy->dst2src_pkt_count < max_num_packets_per_flow) { |
1004 | 2.37M | rflow->entropy->dst2src_pkt_len[rflow->entropy->dst2src_pkt_count] = l4_data_len; |
1005 | 2.37M | rflow->entropy->dst2src_pkt_time[rflow->entropy->dst2src_pkt_count] = when; |
1006 | 2.37M | if(rflow->entropy->dst2src_pkt_count == 0) { |
1007 | 714k | rflow->entropy->dst2src_start = when; |
1008 | 714k | } |
1009 | 2.37M | rflow->entropy->dst2src_l4_bytes += l4_data_len; |
1010 | 2.37M | rflow->entropy->dst2src_pkt_count++; |
1011 | 2.37M | } |
1012 | | // Non zero app data. |
1013 | 2.37M | if(l4_data_len != 0XFEEDFACE && l4_data_len != 0) { |
1014 | 2.17M | rflow->entropy->dst2src_opackets++; |
1015 | 2.17M | } |
1016 | 2.37M | } |
1017 | 7.32M | } |
1018 | | |
1019 | 7.39M | return(rflow); |
1020 | 7.39M | } |
1021 | 11.9M | } |
1022 | | |
1023 | | /* ****************************************************** */ |
1024 | | |
1025 | | static struct ndpi_flow_info *get_ndpi_flow_info6(struct ndpi_workflow * workflow, |
1026 | | u_int16_t vlan_id, |
1027 | | ndpi_packet_tunnel tunnel_type, |
1028 | | const struct ndpi_ipv6hdr *iph6, |
1029 | | u_int16_t ipsize, |
1030 | | struct ndpi_tcphdr **tcph, |
1031 | | struct ndpi_udphdr **udph, |
1032 | | u_int16_t *sport, u_int16_t *dport, |
1033 | | u_int8_t *proto, |
1034 | | u_int8_t **payload, |
1035 | | u_int16_t *payload_len, |
1036 | | u_int8_t *src_to_dst_direction, |
1037 | 648k | pkt_timeval when) { |
1038 | 648k | struct ndpi_iphdr iph; |
1039 | | |
1040 | 648k | if(ipsize < 40) |
1041 | 89 | return(NULL); |
1042 | 648k | memset(&iph, 0, sizeof(iph)); |
1043 | 648k | iph.version = IPVERSION; |
1044 | 648k | iph.saddr = iph6->ip6_src.u6_addr.u6_addr32[2] + iph6->ip6_src.u6_addr.u6_addr32[3]; |
1045 | 648k | iph.daddr = iph6->ip6_dst.u6_addr.u6_addr32[2] + iph6->ip6_dst.u6_addr.u6_addr32[3]; |
1046 | 648k | u_int8_t l4proto = iph6->ip6_hdr.ip6_un1_nxt; |
1047 | 648k | u_int16_t ip_len = ntohs(iph6->ip6_hdr.ip6_un1_plen); |
1048 | 648k | const u_int8_t *l4ptr = (((const u_int8_t *) iph6) + sizeof(struct ndpi_ipv6hdr)); |
1049 | 648k | if(ipsize < sizeof(struct ndpi_ipv6hdr) + ip_len) |
1050 | 534 | return(NULL); |
1051 | 648k | if(ndpi_handle_ipv6_extension_headers(ipsize - sizeof(struct ndpi_ipv6hdr), &l4ptr, &ip_len, &l4proto) != 0) { |
1052 | 769 | return(NULL); |
1053 | 769 | } |
1054 | 647k | iph.protocol = l4proto; |
1055 | | |
1056 | 647k | return(get_ndpi_flow_info(workflow, 6, vlan_id, tunnel_type, |
1057 | 647k | &iph, iph6, ipsize, |
1058 | 647k | ip_len, l4ptr - (const u_int8_t *)iph6, |
1059 | 647k | tcph, udph, sport, dport, |
1060 | 647k | proto, payload, |
1061 | 647k | payload_len, src_to_dst_direction, when)); |
1062 | 648k | } |
1063 | | |
1064 | | /* ****************************************************** */ |
1065 | | |
1066 | 15.6M | u_int8_t is_ndpi_proto(struct ndpi_flow_info *flow, u_int16_t id) { |
1067 | 15.6M | if((flow->detected_protocol.proto.master_protocol == id) |
1068 | 15.2M | || (flow->detected_protocol.proto.app_protocol == id)) |
1069 | 702k | return(1); |
1070 | 14.9M | else |
1071 | 14.9M | return(0); |
1072 | 15.6M | } |
1073 | | |
1074 | | /* ****************************************************** */ |
1075 | | |
1076 | 74.5k | void correct_csv_data_field(char* data) { |
1077 | | /* Replace , with ; to avoid issues with CSVs */ |
1078 | 74.5k | u_int i; |
1079 | 1.13M | for(i=0; data[i] != '\0'; i++) if(data[i] == ',') data[i] = ';'; |
1080 | 74.5k | } |
1081 | | |
1082 | | /* ****************************************************** */ |
1083 | | |
1084 | 9.84M | u_int8_t plen2slot(u_int16_t plen) { |
1085 | | /* |
1086 | | Slots [32 bytes lenght] |
1087 | | 0..31, 32..63 ... |
1088 | | */ |
1089 | | |
1090 | 9.84M | if(plen > PLEN_MAX) |
1091 | 101k | return(PLEN_NUM_BINS-1); |
1092 | 9.74M | else |
1093 | 9.74M | return(plen/PLEN_BIN_LEN); |
1094 | 9.84M | } |
1095 | | |
1096 | | /* ****************************************************** */ |
1097 | | |
1098 | | static void dump_flow_fingerprint(struct ndpi_workflow * workflow, |
1099 | 42.8k | struct ndpi_flow_info *flow) { |
1100 | 42.8k | ndpi_serializer serializer; |
1101 | 42.8k | bool rc; |
1102 | | |
1103 | 42.8k | if(ndpi_init_serializer(&serializer, ndpi_serialization_format_json) == -1) |
1104 | 2.54k | return; |
1105 | | |
1106 | 40.2k | ndpi_serialize_start_of_block(&serializer, "fingerprint"); |
1107 | 40.2k | rc = ndpi_serialize_flow_fingerprint(workflow->ndpi_struct, flow->ndpi_flow, &serializer); |
1108 | 40.2k | ndpi_serialize_end_of_block(&serializer); |
1109 | | |
1110 | 40.2k | if(rc) { |
1111 | 1.79k | char buf[64], *buffer; |
1112 | 1.79k | u_int32_t buffer_len; |
1113 | | |
1114 | 1.79k | ndpi_serialize_string_uint32(&serializer, "proto", flow->protocol); |
1115 | 1.79k | ndpi_serialize_string_string(&serializer, "cli_ip", flow->src_name ? flow->src_name : ""); |
1116 | 1.79k | ndpi_serialize_string_uint32(&serializer, "cli_port", ntohs(flow->src_port)); |
1117 | 1.79k | ndpi_serialize_string_string(&serializer, "srv_ip", flow->dst_name ? flow->dst_name : ""); |
1118 | 1.79k | ndpi_serialize_string_uint32(&serializer, "srv_port", ntohs(flow->dst_port)); |
1119 | 1.79k | ndpi_serialize_string_string(&serializer, "proto", |
1120 | 1.79k | ndpi_protocol2name(workflow->ndpi_struct, |
1121 | 1.79k | flow->detected_protocol.proto, |
1122 | 1.79k | buf, sizeof(buf))); |
1123 | | |
1124 | 1.79k | if(flow->server_hostname) |
1125 | 223 | ndpi_serialize_string_string(&serializer, "server_hostname", flow->server_hostname); |
1126 | | |
1127 | 1.79k | buffer = ndpi_serializer_get_buffer(&serializer, &buffer_len); |
1128 | 1.79k | fprintf(fingerprint_fp, "%s\n", buffer); |
1129 | 1.79k | } |
1130 | | |
1131 | 40.2k | ndpi_term_serializer(&serializer); |
1132 | 40.2k | } |
1133 | | |
1134 | | |
1135 | | static void add_to_address_port_list(ndpi_address_port_list *list, ndpi_address_port *ap) |
1136 | 2.42M | { |
1137 | 2.42M | int new_num; |
1138 | 2.42M | void *new_buf; |
1139 | 2.42M | unsigned int i; |
1140 | | |
1141 | 2.42M | if(ap->port == 0) |
1142 | 2.32M | return; |
1143 | | |
1144 | | /* Avoid saving duplicates */ |
1145 | 162k | for(i = 0; i < list->num_aps; i++) |
1146 | 125k | if(memcmp(&list->aps[i], ap, sizeof(*ap)) == 0) |
1147 | 64.3k | return; |
1148 | | |
1149 | 37.3k | if(list->num_aps == list->num_aps_allocated) { |
1150 | 33.5k | new_num = 1 + list->num_aps_allocated * 2; |
1151 | 33.5k | new_buf = ndpi_realloc(list->aps, |
1152 | 33.5k | new_num * sizeof(ndpi_address_port)); |
1153 | 33.5k | if(!new_buf) |
1154 | 539 | return; |
1155 | 32.9k | list->aps = new_buf; |
1156 | 32.9k | list->num_aps_allocated = new_num; |
1157 | 32.9k | } |
1158 | 36.8k | memcpy(&list->aps[list->num_aps++], ap, sizeof(ndpi_address_port)); |
1159 | 36.8k | } |
1160 | | |
1161 | | /* ****************************************************** */ |
1162 | | |
1163 | 9.18M | static void process_ndpi_monitoring_info(struct ndpi_flow_info *flow) { |
1164 | 9.18M | if(!flow->ndpi_flow || !flow->ndpi_flow->monit) |
1165 | 8.70M | return; |
1166 | | |
1167 | 480k | if(flow->monitoring_state == 0 && |
1168 | 260k | flow->ndpi_flow->state == NDPI_STATE_MONITORING) { |
1169 | | /* We just moved to monitoring state */ |
1170 | 4.00k | flow->monitoring_state = 1; |
1171 | 4.00k | flow->num_packets_before_monitoring = flow->ndpi_flow->packet_direction_complete_counter[0] + flow->ndpi_flow->packet_direction_complete_counter[1]; |
1172 | 4.00k | } |
1173 | | |
1174 | | /* In theory, we should check only for STUN. |
1175 | | However since we sometimes might not have STUN in protocol classification |
1176 | | (because we have only two protocols in flow->ndpi_flow->detected_protocol_stack[]) |
1177 | | we need to check also for the other "master" protocols set by STUN dissector |
1178 | | See at the beginning of the STUN c file for further details |
1179 | | */ |
1180 | 480k | if(flow->detected_protocol.proto.app_protocol == NDPI_PROTOCOL_STUN || |
1181 | 453k | flow->detected_protocol.proto.master_protocol == NDPI_PROTOCOL_STUN || |
1182 | 192k | flow->detected_protocol.proto.app_protocol == NDPI_PROTOCOL_DTLS || |
1183 | 189k | flow->detected_protocol.proto.master_protocol == NDPI_PROTOCOL_DTLS || |
1184 | 119k | flow->detected_protocol.proto.app_protocol == NDPI_PROTOCOL_SRTP || |
1185 | 475k | flow->detected_protocol.proto.master_protocol == NDPI_PROTOCOL_SRTP) { |
1186 | | |
1187 | 475k | add_to_address_port_list(&flow->stun.mapped_address, &flow->ndpi_flow->monit->protos.dtls_stun_rtp.mapped_address); |
1188 | 475k | add_to_address_port_list(&flow->stun.other_address, &flow->ndpi_flow->monit->protos.dtls_stun_rtp.other_address); |
1189 | 475k | add_to_address_port_list(&flow->stun.peer_address, &flow->ndpi_flow->monit->protos.dtls_stun_rtp.peer_address); |
1190 | 475k | add_to_address_port_list(&flow->stun.relayed_address, &flow->ndpi_flow->monit->protos.dtls_stun_rtp.relayed_address); |
1191 | 475k | add_to_address_port_list(&flow->stun.response_origin, &flow->ndpi_flow->monit->protos.dtls_stun_rtp.response_origin); |
1192 | 475k | flow->multimedia_flow_types |= flow->ndpi_flow->flow_multimedia_types; |
1193 | | |
1194 | 475k | flow->stun.rtp_counters[0] = flow->ndpi_flow->stun.rtp_counters[0]; |
1195 | 475k | flow->stun.rtp_counters[1] = flow->ndpi_flow->stun.rtp_counters[1]; |
1196 | 475k | } |
1197 | 480k | } |
1198 | | |
1199 | | /* ****************************************************** */ |
1200 | | |
1201 | | static void serialize_monitoring_metadata(struct ndpi_flow_info *flow) |
1202 | 4.60k | { |
1203 | 4.60k | unsigned int i; |
1204 | 4.60k | char buf[64]; |
1205 | | |
1206 | 4.60k | if(!flow->ndpi_flow->monit) |
1207 | 597 | return; |
1208 | | |
1209 | 4.00k | ndpi_serialize_start_of_block(&flow->ndpi_flow_serializer, "monitoring"); |
1210 | | |
1211 | 4.00k | switch(flow->detected_protocol.proto.master_protocol ? flow->detected_protocol.proto.master_protocol : flow->detected_protocol.proto.app_protocol) { |
1212 | 2.26k | case NDPI_PROTOCOL_STUN: |
1213 | 2.88k | case NDPI_PROTOCOL_DTLS: |
1214 | 3.89k | case NDPI_PROTOCOL_SRTP: |
1215 | 3.89k | ndpi_serialize_start_of_block(&flow->ndpi_flow_serializer, "stun"); |
1216 | | |
1217 | 3.89k | if(flow->stun.mapped_address.num_aps > 0) { |
1218 | 2.45k | ndpi_serialize_start_of_list(&flow->ndpi_flow_serializer, "mapped_address"); |
1219 | 7.37k | for(i = 0; i < flow->stun.mapped_address.num_aps; i++) { |
1220 | 4.91k | if(flow->stun.mapped_address.aps[i].port > 0) { |
1221 | 4.91k | ndpi_serialize_string_string(&flow->ndpi_flow_serializer, "mapped_address", |
1222 | 4.91k | print_ndpi_address_port(&flow->stun.mapped_address.aps[i], buf, sizeof(buf))); |
1223 | 4.91k | } |
1224 | 4.91k | } |
1225 | 2.45k | ndpi_serialize_end_of_list(&flow->ndpi_flow_serializer); |
1226 | 2.45k | } |
1227 | | |
1228 | 3.89k | if(flow->stun.other_address.num_aps > 0) { |
1229 | 219 | ndpi_serialize_start_of_list(&flow->ndpi_flow_serializer, "other_address"); |
1230 | 587 | for(i = 0; i < flow->stun.other_address.num_aps; i++) { |
1231 | 368 | if(flow->stun.other_address.aps[i].port > 0) { |
1232 | 368 | ndpi_serialize_string_string(&flow->ndpi_flow_serializer, "other_address", |
1233 | 368 | print_ndpi_address_port(&flow->stun.other_address.aps[i], buf, sizeof(buf))); |
1234 | 368 | } |
1235 | 368 | } |
1236 | 219 | ndpi_serialize_end_of_list(&flow->ndpi_flow_serializer); |
1237 | 219 | } |
1238 | | |
1239 | 3.89k | if(flow->stun.peer_address.num_aps > 0) { |
1240 | 1.22k | ndpi_serialize_start_of_list(&flow->ndpi_flow_serializer, "peer_address"); |
1241 | 4.43k | for(i = 0; i < flow->stun.peer_address.num_aps; i++) { |
1242 | 3.21k | if(flow->stun.peer_address.aps[i].port > 0) { |
1243 | 3.21k | ndpi_serialize_string_string(&flow->ndpi_flow_serializer, "peer_address", |
1244 | 3.21k | print_ndpi_address_port(&flow->stun.peer_address.aps[i], buf, sizeof(buf))); |
1245 | 3.21k | } |
1246 | 3.21k | } |
1247 | 1.22k | ndpi_serialize_end_of_list(&flow->ndpi_flow_serializer); |
1248 | 1.22k | } |
1249 | | |
1250 | 3.89k | if(flow->stun.relayed_address.num_aps > 0) { |
1251 | 1.00k | ndpi_serialize_start_of_list(&flow->ndpi_flow_serializer, "relayed_address"); |
1252 | 2.27k | for(i = 0; i < flow->stun.relayed_address.num_aps; i++) { |
1253 | 1.26k | if(flow->stun.relayed_address.aps[i].port > 0) { |
1254 | 1.26k | ndpi_serialize_string_string(&flow->ndpi_flow_serializer, "relayed_address", |
1255 | 1.26k | print_ndpi_address_port(&flow->stun.relayed_address.aps[i], buf, sizeof(buf))); |
1256 | 1.26k | } |
1257 | 1.26k | } |
1258 | 1.00k | ndpi_serialize_end_of_list(&flow->ndpi_flow_serializer); |
1259 | 1.00k | } |
1260 | | |
1261 | 3.89k | if(flow->stun.response_origin.num_aps > 0) { |
1262 | 244 | ndpi_serialize_start_of_list(&flow->ndpi_flow_serializer, "response_origin"); |
1263 | 696 | for(i = 0; i < flow->stun.response_origin.num_aps; i++) { |
1264 | 452 | if(flow->stun.response_origin.aps[i].port > 0) { |
1265 | 452 | ndpi_serialize_string_string(&flow->ndpi_flow_serializer, "response_origin", |
1266 | 452 | print_ndpi_address_port(&flow->stun.response_origin.aps[i], buf, sizeof(buf))); |
1267 | 452 | } |
1268 | 452 | } |
1269 | 244 | ndpi_serialize_end_of_list(&flow->ndpi_flow_serializer); |
1270 | 244 | } |
1271 | | |
1272 | 3.89k | ndpi_serialize_end_of_block(&flow->ndpi_flow_serializer); /* stun */ |
1273 | | |
1274 | 3.89k | break; |
1275 | 4.00k | } |
1276 | | |
1277 | 4.00k | ndpi_serialize_end_of_block(&flow->ndpi_flow_serializer); |
1278 | 4.00k | } |
1279 | | |
1280 | | /* ****************************************************** */ |
1281 | | |
1282 | 4.88M | void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_flow_info *flow) { |
1283 | 4.88M | u_int i; |
1284 | 4.88M | char out[128], *s; |
1285 | | |
1286 | 4.88M | if(!flow->ndpi_flow) return; |
1287 | | |
1288 | 4.33M | flow->info_type = INFO_INVALID; |
1289 | | |
1290 | 4.33M | s = ndpi_get_flow_risk_info(flow->ndpi_flow, out, sizeof(out), 0 /* text */); |
1291 | | |
1292 | 4.33M | if(s != NULL) |
1293 | 2.74M | flow->risk_str = ndpi_strdup(s); |
1294 | | |
1295 | 4.33M | flow->confidence = flow->ndpi_flow->confidence; |
1296 | | |
1297 | 4.33M | flow->num_dissector_calls = flow->ndpi_flow->num_dissector_calls; |
1298 | | |
1299 | 4.33M | ndpi_snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", |
1300 | 4.33M | flow->ndpi_flow->host_server_name); |
1301 | | |
1302 | 4.33M | if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_MINING)) { |
1303 | 634 | ndpi_snprintf(flow->mining.currency, sizeof(flow->mining.currency), "%s", |
1304 | 634 | flow->ndpi_flow->protos.mining.currency); |
1305 | 634 | } |
1306 | | |
1307 | 4.33M | flow->risk = flow->ndpi_flow->risk; |
1308 | | |
1309 | 4.33M | if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_DHCP)) { |
1310 | 5.65k | if(flow->ndpi_flow->protos.dhcp.fingerprint[0] != '\0') |
1311 | 1.75k | flow->dhcp_fingerprint = ndpi_strdup(flow->ndpi_flow->protos.dhcp.fingerprint); |
1312 | | |
1313 | 5.65k | if(flow->ndpi_flow->protos.dhcp.class_ident[0] != '\0') |
1314 | 1.18k | flow->dhcp_class_ident = ndpi_strdup(flow->ndpi_flow->protos.dhcp.class_ident); |
1315 | 4.32M | } else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_BITTORRENT) && |
1316 | 1.59M | !ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_DNS) && |
1317 | 1.59M | !ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_TLS)) { |
1318 | 1.59M | u_int j; |
1319 | | |
1320 | 1.59M | if(flow->ndpi_flow->protos.bittorrent.hash[0] != '\0') { |
1321 | 2.71k | u_int avail = sizeof(flow->ndpi_flow->protos.bittorrent.hash) * 2 + 1; |
1322 | 2.71k | flow->bittorent_hash = ndpi_malloc(avail); |
1323 | | |
1324 | 2.71k | if(flow->bittorent_hash) { |
1325 | 54.6k | for(i=0, j = 0; i < sizeof(flow->ndpi_flow->protos.bittorrent.hash); i++) { |
1326 | 52.0k | snprintf(&flow->bittorent_hash[j], avail-j, "%02x", |
1327 | 52.0k | flow->ndpi_flow->protos.bittorrent.hash[i]); |
1328 | | |
1329 | 52.0k | j += 2; |
1330 | 52.0k | } |
1331 | | |
1332 | 2.60k | flow->bittorent_hash[j] = '\0'; |
1333 | 2.60k | } |
1334 | 2.71k | } |
1335 | 1.59M | } |
1336 | | /* TIVOCONNECT */ |
1337 | 2.72M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_TIVOCONNECT)) { |
1338 | 1.78k | flow->info_type = INFO_TIVOCONNECT; |
1339 | 1.78k | ndpi_snprintf(flow->tivoconnect.identity_uuid, sizeof(flow->tivoconnect.identity_uuid), |
1340 | 1.78k | "%s", flow->ndpi_flow->protos.tivoconnect.identity_uuid); |
1341 | 1.78k | ndpi_snprintf(flow->tivoconnect.machine, sizeof(flow->tivoconnect.machine), |
1342 | 1.78k | "%s", flow->ndpi_flow->protos.tivoconnect.machine); |
1343 | 1.78k | ndpi_snprintf(flow->tivoconnect.platform, sizeof(flow->tivoconnect.platform), |
1344 | 1.78k | "%s", flow->ndpi_flow->protos.tivoconnect.platform); |
1345 | 1.78k | ndpi_snprintf(flow->tivoconnect.services, sizeof(flow->tivoconnect.services), |
1346 | 1.78k | "%s", flow->ndpi_flow->protos.tivoconnect.services); |
1347 | 1.78k | } |
1348 | | /* SOFTETHER */ |
1349 | 2.72M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_SOFTETHER) && |
1350 | 2.65k | !ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_HTTP)) { |
1351 | 2.34k | flow->info_type = INFO_SOFTETHER; |
1352 | 2.34k | ndpi_snprintf(flow->softether.ip, sizeof(flow->softether.ip), "%s", |
1353 | 2.34k | flow->ndpi_flow->protos.softether.ip); |
1354 | 2.34k | ndpi_snprintf(flow->softether.port, sizeof(flow->softether.port), "%s", |
1355 | 2.34k | flow->ndpi_flow->protos.softether.port); |
1356 | 2.34k | ndpi_snprintf(flow->softether.hostname, sizeof(flow->softether.hostname), "%s", |
1357 | 2.34k | flow->ndpi_flow->protos.softether.hostname); |
1358 | 2.34k | ndpi_snprintf(flow->softether.fqdn, sizeof(flow->softether.fqdn), "%s", |
1359 | 2.34k | flow->ndpi_flow->protos.softether.fqdn); |
1360 | 2.34k | } |
1361 | | /* SERVICE_LOCATION */ |
1362 | 2.72M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_SERVICE_LOCATION)) { |
1363 | 81.9k | size_t i; |
1364 | | |
1365 | 81.9k | flow->info_type = INFO_GENERIC; |
1366 | 81.9k | flow->info[0] = 0; |
1367 | 81.9k | if (flow->ndpi_flow->protos.slp.url_count > 0) |
1368 | 11.2k | strncat(flow->info, "URL(s): ", sizeof(flow->info)-1); |
1369 | | |
1370 | 94.1k | for (i = 0; i < flow->ndpi_flow->protos.slp.url_count; ++i) { |
1371 | 12.2k | size_t length = strlen(flow->info); |
1372 | | |
1373 | 12.2k | strncat(flow->info + length, flow->ndpi_flow->protos.slp.url[i], |
1374 | 12.2k | sizeof(flow->info) - length); |
1375 | 12.2k | length = strlen(flow->info); |
1376 | | |
1377 | 12.2k | if (i < (size_t)flow->ndpi_flow->protos.slp.url_count - 1) |
1378 | 994 | strncat(flow->info + length, ", ", sizeof(flow->info) - length); |
1379 | 12.2k | } |
1380 | 81.9k | } |
1381 | | /* NATPMP */ |
1382 | 2.64M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_NATPMP)) { |
1383 | 3.57k | flow->info_type = INFO_NATPMP; |
1384 | 3.57k | flow->natpmp.result_code = flow->ndpi_flow->protos.natpmp.result_code; |
1385 | 3.57k | flow->natpmp.internal_port = flow->ndpi_flow->protos.natpmp.internal_port; |
1386 | 3.57k | flow->natpmp.external_port = flow->ndpi_flow->protos.natpmp.external_port; |
1387 | 3.57k | inet_ntop(AF_INET, &flow->ndpi_flow->protos.natpmp.external_address.ipv4, &flow->natpmp.ip[0], sizeof(flow->natpmp.ip)); |
1388 | 3.57k | } |
1389 | | /* DISCORD */ |
1390 | 2.63M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_DISCORD) && |
1391 | 9.37k | !ndpi_stack_is_tls_like(&flow->detected_protocol.protocol_stack) && |
1392 | 9.09k | flow->ndpi_flow->protos.discord.client_ip[0] != '\0') { |
1393 | 1.11k | flow->info_type = INFO_GENERIC; |
1394 | 1.11k | ndpi_snprintf(flow->info, sizeof(flow->info), "Client IP: %s", |
1395 | 1.11k | flow->ndpi_flow->protos.discord.client_ip); |
1396 | 1.11k | } |
1397 | | /* DNS */ |
1398 | 2.63M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_DNS)) { |
1399 | 84.9k | if(flow->ndpi_flow->protos.dns.is_rsp_addr_ipv6[0] == 0) |
1400 | 83.9k | { |
1401 | 83.9k | flow->info_type = INFO_GENERIC; |
1402 | 83.9k | inet_ntop(AF_INET, &flow->ndpi_flow->protos.dns.rsp_addr[0].ipv4, flow->info, sizeof(flow->info)); |
1403 | 83.9k | } else { |
1404 | 1.01k | flow->info_type = INFO_GENERIC; |
1405 | 1.01k | inet_ntop(AF_INET6, &flow->ndpi_flow->protos.dns.rsp_addr[0].ipv6, flow->info, sizeof(flow->info)); |
1406 | | |
1407 | | /* For consistency across platforms replace :0: with :: */ |
1408 | 1.01k | ndpi_patchIPv6Address(flow->info); |
1409 | 1.01k | } |
1410 | | |
1411 | 84.9k | if(flow->ndpi_flow->protos.dns.geolocation_iata_code[0] != '\0') |
1412 | 227 | strcpy(flow->dns.geolocation_iata_code, flow->ndpi_flow->protos.dns.geolocation_iata_code); |
1413 | | |
1414 | 84.9k | if(flow->ndpi_flow->protos.dns.ptr_domain_name[0] != '\0') |
1415 | 2.62k | strcpy(flow->dns.ptr_domain_name, flow->ndpi_flow->protos.dns.ptr_domain_name); |
1416 | | |
1417 | 84.9k | flow->dns.transaction_id = flow->ndpi_flow->protos.dns.transaction_id; |
1418 | | |
1419 | | #if 0 |
1420 | | if(0) { |
1421 | | u_int8_t i; |
1422 | | |
1423 | | for(i=0; i<flow->ndpi_flow->protos.dns.num_rsp_addr; i++) { |
1424 | | char buf[64]; |
1425 | | |
1426 | | if(flow->ndpi_flow->protos.dns.is_rsp_addr_ipv6[i] == 0) { |
1427 | | inet_ntop(AF_INET, &flow->ndpi_flow->protos.dns.rsp_addr[i].ipv4, buf, sizeof(buf)); |
1428 | | } else { |
1429 | | inet_ntop(AF_INET6, &flow->ndpi_flow->protos.dns.rsp_addr[i].ipv6, buf, sizeof(buf)); |
1430 | | } |
1431 | | |
1432 | | printf("(%s) %s [ttl: %u]\n", flow->host_server_name, buf, flow->ndpi_flow->protos.dns.rsp_addr_ttl[i]); |
1433 | | } |
1434 | | } |
1435 | | #endif |
1436 | 84.9k | } |
1437 | | /* MDNS */ |
1438 | 2.55M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_MDNS)) { |
1439 | 8.42k | flow->info_type = INFO_GENERIC; |
1440 | 8.42k | ndpi_snprintf(flow->info, sizeof(flow->info), "%s", flow->ndpi_flow->host_server_name); |
1441 | 8.42k | } |
1442 | | /* UBNTAC2 */ |
1443 | 2.54M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_UBNTAC2)) { |
1444 | 1.17k | flow->info_type = INFO_GENERIC; |
1445 | 1.17k | ndpi_snprintf(flow->info, sizeof(flow->info), "%s", flow->ndpi_flow->protos.ubntac2.version); |
1446 | 1.17k | } |
1447 | | /* FTP, IMAP, SMTP, POP3 */ |
1448 | 2.54M | else if(!ndpi_stack_is_tls_like(&flow->detected_protocol.protocol_stack) && |
1449 | 2.29M | (ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_FTP_CONTROL) || |
1450 | 2.29M | ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_MAIL_IMAP) || |
1451 | 2.28M | ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_MAIL_POP) || |
1452 | 2.28M | ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_MAIL_SMTP))) { |
1453 | 24.2k | flow->info_type = INFO_FTP_IMAP_POP_SMTP; |
1454 | 24.2k | ndpi_snprintf(flow->ftp_imap_pop_smtp.username, |
1455 | 24.2k | sizeof(flow->ftp_imap_pop_smtp.username), |
1456 | 24.2k | "%s", flow->ndpi_flow->l4.tcp.ftp_imap_pop_smtp.username); |
1457 | 24.2k | ndpi_snprintf(flow->ftp_imap_pop_smtp.password, |
1458 | 24.2k | sizeof(flow->ftp_imap_pop_smtp.password), |
1459 | 24.2k | "%s", flow->ndpi_flow->l4.tcp.ftp_imap_pop_smtp.password); |
1460 | 24.2k | flow->ftp_imap_pop_smtp.auth_failed = |
1461 | 24.2k | flow->ndpi_flow->l4.tcp.ftp_imap_pop_smtp.auth_failed; |
1462 | 24.2k | } |
1463 | | /* TFTP */ |
1464 | 2.51M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_TFTP)) { |
1465 | 2.71k | flow->info_type = INFO_GENERIC; |
1466 | 2.71k | if(flow->ndpi_flow->protos.tftp.filename[0] != '\0') |
1467 | 246 | ndpi_snprintf(flow->info, sizeof(flow->info), "Filename: %s", |
1468 | 246 | flow->ndpi_flow->protos.tftp.filename); |
1469 | 2.71k | } |
1470 | | /* KERBEROS */ |
1471 | 2.51M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_KERBEROS)) { |
1472 | 15.1k | flow->info_type = INFO_KERBEROS; |
1473 | 15.1k | ndpi_snprintf(flow->kerberos.domain, |
1474 | 15.1k | sizeof(flow->kerberos.domain), |
1475 | 15.1k | "%s", flow->ndpi_flow->protos.kerberos.domain); |
1476 | 15.1k | ndpi_snprintf(flow->kerberos.hostname, |
1477 | 15.1k | sizeof(flow->kerberos.hostname), |
1478 | 15.1k | "%s", flow->ndpi_flow->protos.kerberos.hostname); |
1479 | 15.1k | ndpi_snprintf(flow->kerberos.username, |
1480 | 15.1k | sizeof(flow->kerberos.username), |
1481 | 15.1k | "%s", flow->ndpi_flow->protos.kerberos.username); |
1482 | | /* COLLECTD */ |
1483 | 2.50M | } else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_COLLECTD)) { |
1484 | 467 | flow->info_type = INFO_GENERIC; |
1485 | 467 | if(flow->ndpi_flow->protos.collectd.client_username[0] != '\0') |
1486 | 37 | ndpi_snprintf(flow->info, sizeof(flow->info), "Username: %s", |
1487 | 37 | flow->ndpi_flow->protos.collectd.client_username); |
1488 | 467 | } |
1489 | | /* SIP */ |
1490 | 2.50M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_SIP)) { |
1491 | 5.97k | flow->info_type = INFO_SIP; |
1492 | 5.97k | if(flow->ndpi_flow->protos.sip.from) |
1493 | 2.95k | ndpi_snprintf(flow->sip.from, sizeof(flow->sip.from), "%s", flow->ndpi_flow->protos.sip.from); |
1494 | 5.97k | if(flow->ndpi_flow->protos.sip.from_imsi[0] != '\0') |
1495 | 2 | ndpi_snprintf(flow->sip.from_imsi, sizeof(flow->sip.from_imsi), "%s", flow->ndpi_flow->protos.sip.from_imsi); |
1496 | 5.97k | if(flow->ndpi_flow->protos.sip.to) |
1497 | 3.05k | ndpi_snprintf(flow->sip.to, sizeof(flow->sip.to), "%s", flow->ndpi_flow->protos.sip.to); |
1498 | 5.97k | if(flow->ndpi_flow->protos.sip.to_imsi[0] != '\0') |
1499 | 33 | ndpi_snprintf(flow->sip.to_imsi, sizeof(flow->sip.to_imsi), "%s", flow->ndpi_flow->protos.sip.to_imsi); |
1500 | 5.97k | } |
1501 | | /* BFCP */ |
1502 | 2.49M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_BFCP)) { |
1503 | 318 | flow->info_type = INFO_BFCP; |
1504 | 318 | flow->bfcp.conference_id = flow->ndpi_flow->protos.bfcp.conference_id; |
1505 | 318 | flow->bfcp.user_id = flow->ndpi_flow->protos.bfcp.user_id; |
1506 | 318 | } |
1507 | | /* TELNET */ |
1508 | 2.49M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_TELNET)) { |
1509 | 6.69k | if(flow->ndpi_flow->protos.telnet.username[0] != '\0') |
1510 | 604 | flow->telnet.username = ndpi_strdup(flow->ndpi_flow->protos.telnet.username); |
1511 | 6.69k | if(flow->ndpi_flow->protos.telnet.password[0] != '\0') |
1512 | 246 | flow->telnet.password = ndpi_strdup(flow->ndpi_flow->protos.telnet.password); |
1513 | 2.48M | } else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_SSH)) { |
1514 | 5.83k | ndpi_snprintf(flow->host_server_name, |
1515 | 5.83k | sizeof(flow->host_server_name), "%s", |
1516 | 5.83k | flow->ndpi_flow->protos.ssh.client_signature); |
1517 | 5.83k | ndpi_snprintf(flow->ssh_tls.server_info, sizeof(flow->ssh_tls.server_info), "%s", |
1518 | 5.83k | flow->ndpi_flow->protos.ssh.server_signature); |
1519 | 5.83k | ndpi_snprintf(flow->ssh_tls.client_hassh, sizeof(flow->ssh_tls.client_hassh), "%s", |
1520 | 5.83k | flow->ndpi_flow->protos.ssh.hassh_client); |
1521 | 5.83k | ndpi_snprintf(flow->ssh_tls.server_hassh, sizeof(flow->ssh_tls.server_hassh), "%s", |
1522 | 5.83k | flow->ndpi_flow->protos.ssh.hassh_server); |
1523 | 5.83k | } |
1524 | | /* TLS/QUIC/DTLS/MAIL_S/FTPS */ |
1525 | 2.48M | else if(ndpi_stack_is_tls_like(&flow->detected_protocol.protocol_stack)) { |
1526 | 246k | flow->ssh_tls.ssl_version = flow->ndpi_flow->protos.tls_quic.ssl_version; |
1527 | 246k | flow->ssh_tls.quic_version = flow->ndpi_flow->protos.tls_quic.quic_version; |
1528 | | |
1529 | 246k | if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_QUIC)) |
1530 | 62.7k | flow->idle_timeout_sec = flow->ndpi_flow->protos.tls_quic.quic_idle_timeout_sec; |
1531 | | |
1532 | 246k | if(flow->ndpi_flow->protos.tls_quic.server_names_len > 0 && flow->ndpi_flow->protos.tls_quic.server_names) |
1533 | 7.32k | flow->ssh_tls.server_names = ndpi_strdup(flow->ndpi_flow->protos.tls_quic.server_names); |
1534 | | |
1535 | 246k | flow->ssh_tls.notBefore = flow->ndpi_flow->protos.tls_quic.notBefore; |
1536 | 246k | flow->ssh_tls.notAfter = flow->ndpi_flow->protos.tls_quic.notAfter; |
1537 | 246k | ndpi_snprintf(flow->ssh_tls.ja4_client, sizeof(flow->ssh_tls.ja4_client), "%s", |
1538 | 246k | flow->ndpi_flow->protos.tls_quic.ja4_client); |
1539 | | |
1540 | 246k | if(flow->ndpi_flow->ndpi.fingerprint) |
1541 | 53.6k | flow->ndpi_fingerprint = ndpi_strdup(flow->ndpi_flow->ndpi.fingerprint); |
1542 | | |
1543 | 246k | if(flow->ndpi_flow->protos.tls_quic.ja4_client_raw) |
1544 | 49.7k | flow->ssh_tls.ja4_client_raw = ndpi_strdup(flow->ndpi_flow->protos.tls_quic.ja4_client_raw); |
1545 | | |
1546 | 246k | ndpi_snprintf(flow->ssh_tls.ja3_server, sizeof(flow->ssh_tls.ja3_server), "%s", |
1547 | 246k | flow->ndpi_flow->protos.tls_quic.ja3_server); |
1548 | 246k | flow->ssh_tls.server_unsafe_cipher = flow->ndpi_flow->protos.tls_quic.server_unsafe_cipher; |
1549 | 246k | flow->ssh_tls.server_cipher = flow->ndpi_flow->protos.tls_quic.server_cipher; |
1550 | | |
1551 | 246k | if(flow->ndpi_flow->protos.tls_quic.fingerprint_set) { |
1552 | 12.1k | memcpy(flow->ssh_tls.sha1_cert_fingerprint, |
1553 | 12.1k | flow->ndpi_flow->protos.tls_quic.sha1_certificate_fingerprint, 20); |
1554 | 12.1k | flow->ssh_tls.sha1_cert_fingerprint_set = 1; |
1555 | 12.1k | } |
1556 | | |
1557 | 246k | flow->ssh_tls.browser_heuristics = flow->ndpi_flow->protos.tls_quic.browser_heuristics; |
1558 | | |
1559 | 246k | if(flow->ndpi_flow->protos.tls_quic.issuerDN) |
1560 | 9.48k | flow->ssh_tls.tls_issuerDN = ndpi_strdup(flow->ndpi_flow->protos.tls_quic.issuerDN); |
1561 | | |
1562 | 246k | if(flow->ndpi_flow->protos.tls_quic.subjectDN) |
1563 | 10.4k | flow->ssh_tls.tls_subjectDN = ndpi_strdup(flow->ndpi_flow->protos.tls_quic.subjectDN); |
1564 | | |
1565 | 246k | flow->ssh_tls.encrypted_ch.version = flow->ndpi_flow->protos.tls_quic.encrypted_ch.version; |
1566 | | |
1567 | 246k | if(flow->ndpi_flow->protos.tls_quic.tls_supported_versions) { |
1568 | 28.0k | if((flow->ssh_tls.tls_supported_versions = ndpi_strdup(flow->ndpi_flow->protos.tls_quic.tls_supported_versions)) != NULL) |
1569 | 27.8k | correct_csv_data_field(flow->ssh_tls.tls_supported_versions); |
1570 | 28.0k | } |
1571 | | |
1572 | 246k | if(flow->ndpi_flow->protos.tls_quic.advertised_alpns) { |
1573 | 40.8k | if((flow->ssh_tls.advertised_alpns = ndpi_strdup(flow->ndpi_flow->protos.tls_quic.advertised_alpns)) != NULL) |
1574 | 40.5k | correct_csv_data_field(flow->ssh_tls.advertised_alpns); |
1575 | 40.8k | } |
1576 | | |
1577 | 246k | if(flow->ndpi_flow->protos.tls_quic.negotiated_alpn) { |
1578 | 6.27k | if((flow->ssh_tls.negotiated_alpn = ndpi_strdup(flow->ndpi_flow->protos.tls_quic.negotiated_alpn)) != NULL) |
1579 | 6.18k | correct_csv_data_field(flow->ssh_tls.negotiated_alpn); |
1580 | 6.27k | } |
1581 | | |
1582 | 246k | if(flow->protocol == IPPROTO_TCP) { |
1583 | 170k | if(enable_doh_dot_detection) { |
1584 | | /* For TLS we use TLS block lenght instead of payload lenght */ |
1585 | 1.74k | ndpi_reset_bin(&flow->payload_len_bin); |
1586 | | |
1587 | 1.74k | for(i=0; i<flow->ndpi_flow->l4.tcp.tls.num_tls_blocks; i++) { |
1588 | 0 | u_int16_t len = abs(flow->ndpi_flow->l4.tcp.tls.tls_blocks[i].len); |
1589 | | |
1590 | | /* printf("[TLS_LEN] %u\n", len); */ |
1591 | 0 | ndpi_inc_bin(&flow->payload_len_bin, plen2slot(len), 1); |
1592 | 0 | } |
1593 | 1.74k | } |
1594 | | |
1595 | 170k | flow->ssh_tls.num_blocks = flow->ndpi_flow->l4.tcp.tls.num_tls_blocks; |
1596 | 170k | memcpy(flow->ssh_tls.blocks, flow->ndpi_flow->l4.tcp.tls.tls_blocks, sizeof(flow->ndpi_flow->l4.tcp.tls.tls_blocks)); |
1597 | 170k | } |
1598 | 246k | } |
1599 | | /* FASTCGI */ |
1600 | 2.23M | else if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_FASTCGI)) { |
1601 | 1.50k | flow->info_type = INFO_FASTCGI; |
1602 | 1.50k | flow->fast_cgi.method = flow->ndpi_flow->protos.fast_cgi.method; |
1603 | 1.50k | ndpi_snprintf(flow->fast_cgi.user_agent, sizeof(flow->fast_cgi.user_agent), "%s", flow->ndpi_flow->protos.fast_cgi.user_agent); |
1604 | 1.50k | ndpi_snprintf(flow->fast_cgi.url, sizeof(flow->fast_cgi.url), "%s", flow->ndpi_flow->protos.fast_cgi.url); |
1605 | 1.50k | } |
1606 | | |
1607 | 4.33M | if(!monitoring_enabled) { |
1608 | 9.39k | add_to_address_port_list(&flow->stun.mapped_address, &flow->ndpi_flow->stun.mapped_address); |
1609 | 9.39k | add_to_address_port_list(&flow->stun.peer_address, &flow->ndpi_flow->stun.peer_address); |
1610 | 9.39k | add_to_address_port_list(&flow->stun.relayed_address, &flow->ndpi_flow->stun.relayed_address); |
1611 | 9.39k | add_to_address_port_list(&flow->stun.response_origin, &flow->ndpi_flow->stun.response_origin); |
1612 | 9.39k | add_to_address_port_list(&flow->stun.other_address, &flow->ndpi_flow->stun.other_address); |
1613 | 9.39k | } |
1614 | | |
1615 | 4.33M | flow->multimedia_flow_types |= flow->ndpi_flow->flow_multimedia_types; |
1616 | | |
1617 | 4.33M | if(flow->ndpi_flow->tcp.fingerprint) { |
1618 | 2.08M | char buf[128]; |
1619 | | |
1620 | 2.08M | snprintf(buf, sizeof(buf), "%s/%s", flow->ndpi_flow->tcp.fingerprint, |
1621 | 2.08M | ndpi_print_os_hint(flow->ndpi_flow->tcp.os_hint)); |
1622 | 2.08M | flow->tcp_fingerprint = ndpi_strdup(buf); |
1623 | 2.08M | } |
1624 | | |
1625 | | /* HTTP metadata are "global" not in `flow->ndpi_flow->protos` union; for example, we can have |
1626 | | HTTP/BitTorrent and in that case we want to export also HTTP attributes */ |
1627 | 4.33M | if(ndpi_stack_is_http_like(&flow->detected_protocol.protocol_stack)) { /* HTTP, HTTP_PROXY, HTTP_CONNECT */ |
1628 | 628k | if(flow->ndpi_flow->http.url != NULL) { |
1629 | 362k | ndpi_snprintf(flow->http.url, sizeof(flow->http.url), "%s", flow->ndpi_flow->http.url); |
1630 | 362k | } |
1631 | | |
1632 | 628k | flow->http.response_status_code = flow->ndpi_flow->http.response_status_code; |
1633 | 628k | ndpi_snprintf(flow->http.content_type, sizeof(flow->http.content_type), "%s", flow->ndpi_flow->http.content_type ? flow->ndpi_flow->http.content_type : ""); |
1634 | 628k | ndpi_snprintf(flow->http.server, sizeof(flow->http.server), "%s", flow->ndpi_flow->http.server ? flow->ndpi_flow->http.server : ""); |
1635 | 628k | ndpi_snprintf(flow->http.request_content_type, sizeof(flow->http.request_content_type), "%s", flow->ndpi_flow->http.request_content_type ? flow->ndpi_flow->http.request_content_type : ""); |
1636 | 628k | ndpi_snprintf(flow->http.nat_ip, sizeof(flow->http.nat_ip), "%s", flow->ndpi_flow->http.nat_ip ? flow->ndpi_flow->http.nat_ip : ""); |
1637 | 628k | ndpi_snprintf(flow->http.filename, sizeof(flow->http.filename), "%s", flow->ndpi_flow->http.filename ? flow->ndpi_flow->http.filename : ""); |
1638 | 628k | ndpi_snprintf(flow->http.username, sizeof(flow->http.username), "%s", flow->ndpi_flow->http.username ? flow->ndpi_flow->http.username : ""); |
1639 | 628k | ndpi_snprintf(flow->http.password, sizeof(flow->http.password), "%s", flow->ndpi_flow->http.password ? flow->ndpi_flow->http.password : ""); |
1640 | 628k | } |
1641 | | |
1642 | 4.33M | if(ndpi_stack_contains(&flow->detected_protocol.protocol_stack, NDPI_PROTOCOL_RTP)) |
1643 | 7.77k | memcpy(&flow->rtp, &flow->ndpi_flow->rtp, sizeof(flow->rtp)); |
1644 | | |
1645 | 4.33M | ndpi_snprintf(flow->http.user_agent, |
1646 | 4.33M | sizeof(flow->http.user_agent), |
1647 | 4.33M | "%s", (flow->ndpi_flow->http.user_agent ? flow->ndpi_flow->http.user_agent : "")); |
1648 | | |
1649 | 4.33M | { |
1650 | 4.33M | ndpi_ip_addr_t ip_addr; |
1651 | 4.33M | struct ndpi_address_cache_item *c; |
1652 | | |
1653 | 4.33M | memset(&ip_addr, 0, sizeof(ip_addr)); |
1654 | | |
1655 | 4.33M | if(flow->ip_version == 4) |
1656 | 4.19M | ip_addr.ipv4 = flow->dst_ip; |
1657 | 142k | else |
1658 | 142k | memcpy(&ip_addr.ipv6, &flow->dst_ip6, sizeof(struct ndpi_in6_addr)); |
1659 | | |
1660 | 4.33M | c = ndpi_cache_address_find(workflow->ndpi_struct, ip_addr); |
1661 | | |
1662 | 4.33M | if(c) { |
1663 | 556k | flow->server_hostname = ndpi_strdup(c->hostname); |
1664 | 556k | } |
1665 | 4.33M | } |
1666 | | |
1667 | 4.33M | if (workflow->ndpi_serialization_format != ndpi_serialization_format_unknown) { |
1668 | 4.33M | if (ndpi_flow2json(workflow->ndpi_struct, flow->ndpi_flow, |
1669 | 4.33M | flow->ip_version, flow->protocol, |
1670 | 4.33M | flow->vlan_id, |
1671 | 4.33M | flow->src_ip, flow->dst_ip, |
1672 | 4.33M | &flow->src_ip6, &flow->dst_ip6, |
1673 | 4.33M | flow->src_port, flow->dst_port, |
1674 | 4.33M | flow->detected_protocol, |
1675 | 4.33M | &flow->ndpi_flow_serializer) != 0) { |
1676 | 0 | LOG(NDPI_LOG_ERROR, "flow2json failed\n"); |
1677 | 0 | return; |
1678 | 0 | } |
1679 | | |
1680 | 4.33M | ndpi_serialize_string_uint32(&flow->ndpi_flow_serializer, "detection_completed", flow->detection_completed); |
1681 | 4.33M | ndpi_serialize_string_uint32(&flow->ndpi_flow_serializer, "check_extra_packets", flow->check_extra_packets); |
1682 | | |
1683 | 4.33M | if(flow->ndpi_flow->state == NDPI_STATE_MONITORING) { |
1684 | 4.60k | serialize_monitoring_metadata(flow); |
1685 | 4.60k | } |
1686 | | |
1687 | 4.33M | if(flow->server_hostname) |
1688 | 553k | ndpi_serialize_string_string(&flow->ndpi_flow_serializer, "server_hostname", flow->server_hostname); |
1689 | 4.33M | } |
1690 | | |
1691 | 4.33M | if(flow->detection_completed && (!flow->check_extra_packets)) { |
1692 | 557k | flow->flow_payload = flow->ndpi_flow->flow_payload, flow->flow_payload_len = flow->ndpi_flow->flow_payload_len; |
1693 | 557k | flow->ndpi_flow->flow_payload = NULL; /* We'll free the memory */ |
1694 | | |
1695 | 557k | if(workflow->flow_callback != NULL) |
1696 | 547k | workflow->flow_callback(workflow, flow, workflow->flow_callback_userdata); |
1697 | | |
1698 | 557k | if(fingerprint_fp) |
1699 | 42.8k | dump_flow_fingerprint(workflow, flow); |
1700 | | |
1701 | 557k | ndpi_free_flow_info_half(flow); |
1702 | 557k | } |
1703 | 4.33M | } |
1704 | | |
1705 | | /* ****************************************************** */ |
1706 | | |
1707 | | /** |
1708 | | * @brief Clear entropy stats if it meets prereq. |
1709 | | */ |
1710 | | static void |
1711 | 11.7M | ndpi_clear_entropy_stats(struct ndpi_flow_info *flow) { |
1712 | 11.7M | if(enable_flow_stats) { |
1713 | 11.6M | if(flow->entropy->src2dst_pkt_count + flow->entropy->dst2src_pkt_count == max_num_packets_per_flow) { |
1714 | 383k | memcpy(flow->last_entropy, flow->entropy, sizeof(struct ndpi_entropy)); |
1715 | 383k | memset(flow->entropy, 0x00, sizeof(struct ndpi_entropy)); |
1716 | 383k | } |
1717 | 11.6M | } |
1718 | 11.7M | } |
1719 | | |
1720 | 8.16M | void update_tcp_flags_count(struct ndpi_flow_info* flow, struct ndpi_tcphdr* tcp, u_int8_t src_to_dst_direction){ |
1721 | 8.16M | if(tcp->cwr){ |
1722 | 206k | flow->cwr_count++; |
1723 | 206k | src_to_dst_direction ? flow->src2dst_cwr_count++ : flow->dst2src_cwr_count++; |
1724 | 206k | } |
1725 | 8.16M | if(tcp->ece){ |
1726 | 270k | flow->ece_count++; |
1727 | 270k | src_to_dst_direction ? flow->src2dst_ece_count++ : flow->dst2src_ece_count++; |
1728 | 270k | } |
1729 | 8.16M | if(tcp->rst){ |
1730 | 342k | flow->rst_count++; |
1731 | 342k | src_to_dst_direction ? flow->src2dst_rst_count++ : flow->dst2src_rst_count++; |
1732 | 342k | } |
1733 | 8.16M | if(tcp->ack){ |
1734 | 4.79M | flow->ack_count++; |
1735 | 4.79M | src_to_dst_direction ? flow->src2dst_ack_count++ : flow->dst2src_ack_count++; |
1736 | 4.79M | } |
1737 | 8.16M | if(tcp->fin){ |
1738 | 442k | flow->fin_count++; |
1739 | 442k | src_to_dst_direction ? flow->src2dst_fin_count++ : flow->dst2src_fin_count++; |
1740 | 442k | } |
1741 | 8.16M | if(tcp->syn){ |
1742 | 3.41M | flow->syn_count++; |
1743 | 3.41M | src_to_dst_direction ? flow->src2dst_syn_count++ : flow->dst2src_syn_count++; |
1744 | 3.41M | } |
1745 | 8.16M | if(tcp->psh){ |
1746 | 2.82M | flow->psh_count++; |
1747 | 2.82M | src_to_dst_direction ? flow->src2dst_psh_count++ : flow->dst2src_psh_count++; |
1748 | 2.82M | } |
1749 | 8.16M | if(tcp->urg){ |
1750 | 293k | flow->urg_count++; |
1751 | 293k | src_to_dst_direction ? flow->src2dst_urg_count++ : flow->dst2src_urg_count++; |
1752 | 293k | } |
1753 | 8.16M | } |
1754 | | |
1755 | | /* ****************************************************** */ |
1756 | | |
1757 | | /** |
1758 | | Function to process the packet: |
1759 | | determine the flow of a packet and try to decode it |
1760 | | @return: 0 if success; else != 0 |
1761 | | |
1762 | | @Note: ipsize = header->len - ip_offset ; rawsize = header->len |
1763 | | */ |
1764 | | static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow, |
1765 | | const u_int64_t time_ms, |
1766 | | u_int16_t vlan_id, |
1767 | | ndpi_packet_tunnel tunnel_type, |
1768 | | const struct ndpi_iphdr *iph, |
1769 | | struct ndpi_ipv6hdr *iph6, |
1770 | | u_int16_t ipsize, u_int16_t rawsize, |
1771 | | const struct pcap_pkthdr *header, |
1772 | | const u_char *packet, |
1773 | | pkt_timeval when, |
1774 | | ndpi_risk *flow_risk, |
1775 | 12.0M | struct ndpi_flow_info **flow_ext) { |
1776 | 12.0M | struct ndpi_flow_info *flow = NULL; |
1777 | 12.0M | struct ndpi_flow_struct *ndpi_flow = NULL; |
1778 | 12.0M | u_int8_t proto; |
1779 | 12.0M | struct ndpi_tcphdr *tcph = NULL; |
1780 | 12.0M | struct ndpi_udphdr *udph = NULL; |
1781 | 12.0M | u_int16_t sport, dport, payload_len = 0; |
1782 | 12.0M | u_int8_t *payload; |
1783 | 12.0M | u_int8_t src_to_dst_direction = 1; |
1784 | 12.0M | u_int8_t begin_or_end_tcp = 0; |
1785 | 12.0M | struct ndpi_proto nproto; |
1786 | | |
1787 | 12.0M | memset(&nproto, '\0', sizeof(nproto)); |
1788 | | |
1789 | 12.0M | if(workflow->prefs.ignore_vlanid) |
1790 | 55.4k | vlan_id = 0; |
1791 | | |
1792 | 12.0M | if(iph) |
1793 | 11.3M | flow = get_ndpi_flow_info(workflow, IPVERSION, vlan_id, |
1794 | 11.3M | tunnel_type, iph, NULL, |
1795 | 11.3M | ipsize, |
1796 | 11.3M | ntohs(iph->tot_len) ? (ntohs(iph->tot_len) - (iph->ihl * 4)) : ipsize - (iph->ihl * 4) /* TSO */, |
1797 | 11.3M | iph->ihl * 4, |
1798 | 11.3M | &tcph, &udph, &sport, &dport, |
1799 | 11.3M | &proto, |
1800 | 11.3M | &payload, &payload_len, &src_to_dst_direction, when); |
1801 | 648k | else |
1802 | 648k | flow = get_ndpi_flow_info6(workflow, vlan_id, |
1803 | 648k | tunnel_type, iph6, ipsize, |
1804 | 648k | &tcph, &udph, &sport, &dport, |
1805 | 648k | &proto, |
1806 | 648k | &payload, &payload_len, &src_to_dst_direction, when); |
1807 | | |
1808 | 12.0M | if(flow != NULL) { |
1809 | 11.7M | pkt_timeval tdiff; |
1810 | | |
1811 | 11.7M | workflow->stats.ip_packet_count++; |
1812 | 11.7M | workflow->stats.total_wire_bytes += rawsize + 24 /* CRC etc */, |
1813 | 11.7M | workflow->stats.total_ip_bytes += rawsize; |
1814 | 11.7M | ndpi_flow = flow->ndpi_flow; |
1815 | | |
1816 | 11.7M | if(tcph != NULL){ |
1817 | 8.16M | update_tcp_flags_count(flow, tcph, src_to_dst_direction); |
1818 | 8.16M | if(tcph->syn && !flow->src2dst_bytes){ |
1819 | 2.19M | flow->c_to_s_init_win = rawsize; |
1820 | 5.96M | }else if(tcph->syn && tcph->ack && flow->src2dst_bytes == flow->c_to_s_init_win){ |
1821 | 96.0k | flow->s_to_c_init_win = rawsize; |
1822 | 96.0k | } |
1823 | 8.16M | } |
1824 | | |
1825 | 11.7M | if((tcph != NULL) && (tcph->fin || tcph->rst || tcph->syn)) |
1826 | 3.87M | begin_or_end_tcp = 1; |
1827 | | |
1828 | 11.7M | if(flow->flow_last_pkt_time.tv_sec) { |
1829 | 7.00M | ndpi_timer_sub(&when, &flow->flow_last_pkt_time, &tdiff); |
1830 | | |
1831 | 7.00M | if(flow->iat_flow |
1832 | 6.94M | && (tdiff.tv_sec >= 0) /* Discard backward time */ |
1833 | 7.00M | ) { |
1834 | 6.84M | u_int64_t ms = ndpi_timeval_to_milliseconds(tdiff); |
1835 | | |
1836 | 6.84M | if(ms > 0) |
1837 | 2.60M | ndpi_data_add_value(flow->iat_flow, ms); |
1838 | 6.84M | } |
1839 | 7.00M | } |
1840 | | |
1841 | 11.7M | memcpy(&flow->flow_last_pkt_time, &when, sizeof(when)); |
1842 | | |
1843 | 11.7M | if(src_to_dst_direction) { |
1844 | 9.35M | if(flow->src2dst_last_pkt_time.tv_sec) { |
1845 | 4.63M | ndpi_timer_sub(&when, &flow->src2dst_last_pkt_time, &tdiff); |
1846 | | |
1847 | 4.63M | if(flow->iat_c_to_s |
1848 | 4.59M | && (tdiff.tv_sec >= 0) /* Discard backward time */ |
1849 | 4.63M | ) { |
1850 | 4.51M | u_int64_t ms = ndpi_timeval_to_milliseconds(tdiff); |
1851 | | |
1852 | 4.51M | ndpi_data_add_value(flow->iat_c_to_s, ms); |
1853 | 4.51M | } |
1854 | 4.63M | } |
1855 | | |
1856 | 9.35M | ndpi_data_add_value(flow->pktlen_c_to_s, rawsize); |
1857 | 9.35M | flow->src2dst_packets++, flow->src2dst_bytes += rawsize, flow->src2dst_goodput_bytes += payload_len; |
1858 | 9.35M | memcpy(&flow->src2dst_last_pkt_time, &when, sizeof(when)); |
1859 | | |
1860 | | #ifdef DIRECTION_BINS |
1861 | | if(payload_len && (flow->src2dst_packets < MAX_NUM_BIN_PKTS)) |
1862 | | ndpi_inc_bin(&flow->payload_len_bin_src2dst, plen2slot(payload_len)); |
1863 | | #endif |
1864 | 9.35M | } else { |
1865 | 2.40M | if(flow->dst2src_last_pkt_time.tv_sec && (!begin_or_end_tcp)) { |
1866 | 1.57M | ndpi_timer_sub(&when, &flow->dst2src_last_pkt_time, &tdiff); |
1867 | | |
1868 | 1.57M | if(flow->iat_s_to_c) { |
1869 | 1.55M | u_int64_t ms = ndpi_timeval_to_milliseconds(tdiff); |
1870 | | |
1871 | 1.55M | ndpi_data_add_value(flow->iat_s_to_c, ms); |
1872 | 1.55M | } |
1873 | 1.57M | } |
1874 | 2.40M | ndpi_data_add_value(flow->pktlen_s_to_c, rawsize); |
1875 | 2.40M | flow->dst2src_packets++, flow->dst2src_bytes += rawsize, flow->dst2src_goodput_bytes += payload_len; |
1876 | 2.40M | flow->risk &= ~(1ULL << NDPI_UNIDIRECTIONAL_TRAFFIC); /* Clear bit */ |
1877 | 2.40M | memcpy(&flow->dst2src_last_pkt_time, &when, sizeof(when)); |
1878 | | |
1879 | | #ifdef DIRECTION_BINS |
1880 | | if(payload_len && (flow->dst2src_packets < MAX_NUM_BIN_PKTS)) |
1881 | | ndpi_inc_bin(&flow->payload_len_bin_dst2src, plen2slot(payload_len)); |
1882 | | #endif |
1883 | 2.40M | } |
1884 | | |
1885 | 11.7M | #ifndef DIRECTION_BINS |
1886 | 11.7M | if(payload_len && ((flow->src2dst_packets+flow->dst2src_packets) < MAX_NUM_BIN_PKTS)) { |
1887 | | #if 0 |
1888 | | /* Discard packets until the protocol is detected */ |
1889 | | if(flow->detected_protocol.proto.app_protocol != NDPI_PROTOCOL_UNKNOWN) |
1890 | | #endif |
1891 | 9.84M | ndpi_inc_bin(&flow->payload_len_bin, plen2slot(payload_len), 1); |
1892 | 9.84M | } |
1893 | 11.7M | #endif |
1894 | | |
1895 | 11.7M | if(enable_payload_analyzer && (payload_len > 0)) |
1896 | 483k | ndpi_payload_analyzer(flow, |
1897 | 483k | payload, payload_len, |
1898 | 483k | workflow->stats.ip_packet_count); |
1899 | | |
1900 | 11.7M | if(enable_flow_stats) { |
1901 | | /* Update BD, distribution and mean. */ |
1902 | 11.6M | ndpi_flow_update_byte_count(flow, payload, payload_len, src_to_dst_direction); |
1903 | 11.6M | ndpi_flow_update_byte_dist_mean_var(flow, payload, payload_len, src_to_dst_direction); |
1904 | | /* Update SPLT scores for first 32 packets. */ |
1905 | 11.6M | if((flow->entropy->src2dst_pkt_count+flow->entropy->dst2src_pkt_count) <= max_num_packets_per_flow) { |
1906 | 11.6M | if(flow->bidirectional) |
1907 | 4.29M | flow->entropy->score = ndpi_classify(flow->entropy->src2dst_pkt_len, flow->entropy->src2dst_pkt_time, |
1908 | 4.29M | flow->entropy->dst2src_pkt_len, flow->entropy->dst2src_pkt_time, |
1909 | 4.29M | flow->entropy->src2dst_start, flow->entropy->dst2src_start, |
1910 | 4.29M | max_num_packets_per_flow, ntohs(flow->src_port), ntohs(flow->dst_port), |
1911 | 4.29M | flow->src2dst_packets, flow->dst2src_packets, |
1912 | 4.29M | flow->entropy->src2dst_opackets, flow->entropy->dst2src_opackets, |
1913 | 4.29M | flow->entropy->src2dst_l4_bytes, flow->entropy->dst2src_l4_bytes, 1, |
1914 | 4.29M | flow->entropy->src2dst_byte_count, flow->entropy->dst2src_byte_count); |
1915 | 7.35M | else |
1916 | 7.35M | flow->entropy->score = ndpi_classify(flow->entropy->src2dst_pkt_len, flow->entropy->src2dst_pkt_time, |
1917 | 7.35M | NULL, NULL, flow->entropy->src2dst_start, flow->entropy->src2dst_start, |
1918 | 7.35M | max_num_packets_per_flow, ntohs(flow->src_port), ntohs(flow->dst_port), |
1919 | 7.35M | flow->src2dst_packets, 0, |
1920 | 7.35M | flow->entropy->src2dst_opackets, 0, |
1921 | 7.35M | flow->entropy->src2dst_l4_bytes, 0, 1, |
1922 | 7.35M | flow->entropy->src2dst_byte_count, NULL); |
1923 | 11.6M | } |
1924 | 11.6M | } |
1925 | | |
1926 | 11.7M | if(flow->first_seen_ms == 0) |
1927 | 4.35M | flow->first_seen_ms = time_ms; |
1928 | | |
1929 | 11.7M | flow->last_seen_ms = time_ms; |
1930 | | |
1931 | | /* Copy packets entropy if num packets count == 10 */ |
1932 | 11.7M | ndpi_clear_entropy_stats(flow); |
1933 | | /* Reset IAT reeference times (see https://github.com/ntop/nDPI/pull/1316) */ |
1934 | 11.7M | if(((flow->src2dst_packets + flow->dst2src_packets) % max_num_packets_per_flow) == 0) { |
1935 | 387k | memset(&flow->src2dst_last_pkt_time, '\0', sizeof(flow->src2dst_last_pkt_time)); |
1936 | 387k | memset(&flow->dst2src_last_pkt_time, '\0', sizeof(flow->dst2src_last_pkt_time)); |
1937 | 387k | memset(&flow->flow_last_pkt_time, '\0', sizeof(flow->flow_last_pkt_time)); |
1938 | 387k | } |
1939 | | |
1940 | 11.7M | if((human_readeable_string_len != 0) && (!flow->has_human_readeable_strings)) { |
1941 | 7.88M | u_int8_t skip = 0; |
1942 | | |
1943 | 7.88M | if(proto == IPPROTO_TCP && |
1944 | 5.83M | (is_ndpi_proto(flow, NDPI_PROTOCOL_TLS) || |
1945 | 5.24M | is_ndpi_proto(flow, NDPI_PROTOCOL_SSH))) { |
1946 | 630k | if((flow->src2dst_packets+flow->dst2src_packets) < 10 /* MIN_NUM_ENCRYPT_SKIP_PACKETS */) |
1947 | 190k | skip = 1; /* Skip initial negotiation packets */ |
1948 | 630k | } |
1949 | | |
1950 | 7.88M | if((!skip) && ((flow->src2dst_packets+flow->dst2src_packets) < 100)) { |
1951 | 7.46M | if(ndpi_has_human_readable_string((char*)packet, header->caplen, |
1952 | 7.46M | human_readeable_string_len, |
1953 | 7.46M | flow->human_readeable_string_buffer, |
1954 | 7.46M | sizeof(flow->human_readeable_string_buffer)) == 1) |
1955 | 1.83M | flow->has_human_readeable_strings = 1; |
1956 | 7.46M | } |
1957 | 7.88M | } else { |
1958 | 3.87M | if(proto == IPPROTO_TCP && |
1959 | 2.32M | (is_ndpi_proto(flow, NDPI_PROTOCOL_TLS) || |
1960 | 2.25M | is_ndpi_proto(flow, NDPI_PROTOCOL_SSH))) |
1961 | 71.7k | flow->has_human_readeable_strings = 0; |
1962 | 3.87M | } |
1963 | 11.7M | } else { // flow is NULL |
1964 | 250k | workflow->stats.total_discarded_bytes += header->len; |
1965 | 250k | return(nproto); |
1966 | 250k | } |
1967 | | |
1968 | 11.7M | if(!flow->detection_completed) { |
1969 | 9.26M | struct ndpi_flow_input_info input_info; |
1970 | | |
1971 | 9.26M | u_int enough_packets = |
1972 | 9.26M | ((proto == IPPROTO_UDP && (max_num_udp_dissected_pkts > 0 && flow->src2dst_packets + flow->dst2src_packets >= max_num_udp_dissected_pkts)) || |
1973 | 9.26M | (proto == IPPROTO_TCP && (max_num_tcp_dissected_pkts > 0 && flow->src2dst_packets + flow->dst2src_packets >= max_num_tcp_dissected_pkts))) ? 1 : 0; |
1974 | | |
1975 | | #if 0 |
1976 | | printf("%s()\n", __FUNCTION__); |
1977 | | #endif |
1978 | | |
1979 | 9.26M | if(proto == IPPROTO_TCP) |
1980 | 6.83M | workflow->stats.dpi_packet_count[0]++; |
1981 | 2.43M | else if(proto == IPPROTO_UDP) |
1982 | 2.37M | workflow->stats.dpi_packet_count[1]++; |
1983 | 61.8k | else |
1984 | 61.8k | workflow->stats.dpi_packet_count[2]++; |
1985 | 9.26M | flow->dpi_packets++; |
1986 | | |
1987 | 9.26M | memset(&input_info, '\0', sizeof(input_info)); /* To be sure to set to "unknown" any fields */ |
1988 | | /* Set here any information (easily) available; in this trivial example we don't have any */ |
1989 | 9.26M | input_info.in_pkt_dir = NDPI_IN_PKT_DIR_UNKNOWN; |
1990 | 9.26M | input_info.seen_flow_beginning = NDPI_FLOW_BEGINNING_UNKNOWN; |
1991 | 9.26M | malloc_size_stats = 1; |
1992 | 9.26M | flow->detected_protocol = ndpi_detection_process_packet(workflow->ndpi_struct, ndpi_flow, |
1993 | 9.26M | iph ? (uint8_t *)iph : (uint8_t *)iph6, |
1994 | 9.26M | ipsize, time_ms, &input_info); |
1995 | 9.26M | if(monitoring_enabled) |
1996 | 9.18M | process_ndpi_monitoring_info(flow); |
1997 | 9.26M | if(flow->detected_protocol.state == NDPI_STATE_CLASSIFIED || |
1998 | 8.70M | enough_packets) { |
1999 | | |
2000 | 557k | flow->detection_completed = 1; |
2001 | | |
2002 | 557k | if(flow->detected_protocol.state != NDPI_STATE_CLASSIFIED) { |
2003 | 6 | flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct, flow->ndpi_flow); |
2004 | 6 | } |
2005 | | |
2006 | 557k | if(flow->ndpi_flow->protocol_was_guessed) workflow->stats.guessed_flow_protocols++; |
2007 | 557k | process_ndpi_collected_info(workflow, flow); |
2008 | 557k | } |
2009 | | |
2010 | | /* Let's try to save client-server direction */ |
2011 | 9.26M | flow->current_pkt_from_client_to_server = input_info.in_pkt_dir; |
2012 | | |
2013 | 9.26M | malloc_size_stats = 0; |
2014 | 9.26M | } else { |
2015 | 2.48M | flow->current_pkt_from_client_to_server = NDPI_IN_PKT_DIR_UNKNOWN; /* Unknown */ |
2016 | 2.48M | } |
2017 | | |
2018 | | #if 0 |
2019 | | if(flow->risk != 0) { |
2020 | | FILE *r = fopen("/tmp/e", "a"); |
2021 | | |
2022 | | if(r) { |
2023 | | fprintf(r, "->>> %u [%08X]\n", flow->risk, flow->risk); |
2024 | | fclose(r); |
2025 | | } |
2026 | | } |
2027 | | #endif |
2028 | | |
2029 | 11.7M | *flow_risk = flow->risk; |
2030 | 11.7M | *flow_ext = flow; |
2031 | | |
2032 | 11.7M | return(flow->detected_protocol); |
2033 | 12.0M | } |
2034 | | |
2035 | | /* ****************************************************** */ |
2036 | | |
2037 | 214k | int ndpi_is_datalink_supported(int datalink_type) { |
2038 | | /* Keep in sync with the similar switch in ndpi_workflow_process_packet */ |
2039 | 214k | switch(datalink_type) { |
2040 | 20.8k | case DLT_NULL: |
2041 | 20.9k | case DLT_PPP_SERIAL: |
2042 | 21.3k | case DLT_C_HDLC: |
2043 | 23.2k | case DLT_PPP: |
2044 | 23.2k | #ifdef DLT_IPV4 |
2045 | 31.1k | case DLT_IPV4: |
2046 | 31.1k | #endif |
2047 | 31.1k | #ifdef DLT_IPV6 |
2048 | 33.4k | case DLT_IPV6: |
2049 | 33.4k | #endif |
2050 | 195k | case DLT_EN10MB: |
2051 | 203k | case DLT_LINUX_SLL: |
2052 | 203k | case DLT_IEEE802_11_RADIO: |
2053 | 213k | case DLT_RAW: |
2054 | 213k | case DLT_PPI: |
2055 | 213k | case LINKTYPE_LINUX_SLL2: |
2056 | 213k | return 1; |
2057 | 355 | default: |
2058 | 355 | return 0; |
2059 | 214k | } |
2060 | 214k | } |
2061 | | |
2062 | 3.20M | static bool ndpi_is_valid_vxlan(const struct pcap_pkthdr *header, const u_char *packet, u_int16_t ip_offset, u_int16_t ip_len){ |
2063 | 3.20M | if(header->caplen < ip_offset + ip_len + sizeof(struct ndpi_udphdr) + sizeof(struct ndpi_vxlanhdr)) { |
2064 | 103k | return false; |
2065 | 103k | } |
2066 | 3.10M | u_int32_t vxlan_dst_port = ntohs(4789); |
2067 | 3.10M | struct ndpi_udphdr *udp = (struct ndpi_udphdr *)&packet[ip_offset+ip_len]; |
2068 | 3.10M | u_int offset = ip_offset + ip_len + sizeof(struct ndpi_udphdr); |
2069 | | /** |
2070 | | * rfc-7348 |
2071 | | * VXLAN Header: This is an 8-byte field that has: |
2072 | | |
2073 | | - Flags (8 bits): where the I flag MUST be set to 1 for a valid |
2074 | | VXLAN Network ID (VNI). The other 7 bits (designated "R") are |
2075 | | reserved fields and MUST be set to zero on transmission and |
2076 | | ignored on receipt. |
2077 | | |
2078 | | - VXLAN Segment ID/VXLAN Network Identifier (VNI): this is a |
2079 | | 24-bit value used to designate the individual VXLAN overlay |
2080 | | network on which the communicating VMs are situated. VMs in |
2081 | | different VXLAN overlay networks cannot communicate with each |
2082 | | other. |
2083 | | |
2084 | | - Reserved fields (24 bits and 8 bits): MUST be set to zero on |
2085 | | transmission and ignored on receipt. |
2086 | | VXLAN Header: |
2087 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
2088 | | |R|R|R|R|I|R|R|R| Reserved | |
2089 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
2090 | | | VXLAN Network Identifier (VNI) | Reserved | |
2091 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
2092 | | */ |
2093 | 3.10M | if((udp->dest == vxlan_dst_port || udp->source == vxlan_dst_port) && |
2094 | 36.8k | (packet[offset] == 0x8) && |
2095 | 27.3k | (packet[offset + 1] == 0x0) && |
2096 | 25.8k | (packet[offset + 2] == 0x0) && |
2097 | 24.6k | (packet[offset + 3] == 0x0) && |
2098 | 23.6k | (packet[offset + 7] == 0x0)) { |
2099 | 21.9k | return true; |
2100 | 21.9k | } |
2101 | 3.07M | return false; |
2102 | 3.10M | } |
2103 | | |
2104 | 21.9k | static inline u_int ndpi_skip_vxlan(u_int16_t ip_offset, u_int16_t ip_len){ |
2105 | 21.9k | return ip_offset + ip_len + sizeof(struct ndpi_udphdr) + sizeof(struct ndpi_vxlanhdr); |
2106 | 21.9k | } |
2107 | | |
2108 | | static uint32_t ndpi_is_valid_gre_tunnel(const struct pcap_pkthdr *header, |
2109 | | const u_char *packet, const u_int16_t ip_offset, |
2110 | 21.6k | const u_int16_t ip_len) { |
2111 | 21.6k | uint32_t offset = ip_offset + ip_len; |
2112 | 21.6k | struct ndpi_gre_basehdr *grehdr = (struct ndpi_gre_basehdr*)&packet[offset]; |
2113 | 21.6k | offset += sizeof(struct ndpi_gre_basehdr); |
2114 | | /* |
2115 | | The GRE flags are encoded in the first two octets. Bit 0 is the |
2116 | | most significant bit, bit 15 is the least significant bit. Bits |
2117 | | 13 through 15 are reserved for the Version field. Bits 9 through |
2118 | | 12 are reserved for future use and MUST be transmitted as zero. |
2119 | | */ |
2120 | 21.6k | if(NDPI_GRE_IS_FLAGS(grehdr->flags)) |
2121 | 1.58k | return 0; |
2122 | 20.0k | if(NDPI_GRE_IS_REC(grehdr->flags)) |
2123 | 1.86k | return 0; |
2124 | | /*GRE rfc 2890 that update 1701*/ |
2125 | 18.1k | if(NDPI_GRE_IS_VERSION_0(grehdr->flags)) { |
2126 | 8.63k | if(NDPI_GRE_IS_CSUM(grehdr->flags)) { |
2127 | 2.16k | if(header->caplen < offset + 4) |
2128 | 152 | return 0; |
2129 | | /*checksum field and offset field*/ |
2130 | 2.01k | offset += 4; |
2131 | 2.01k | } |
2132 | 8.48k | if(NDPI_GRE_IS_KEY(grehdr->flags)) { |
2133 | 2.60k | if(header->caplen < offset + 4) |
2134 | 280 | return 0; |
2135 | 2.32k | offset += 4; |
2136 | 2.32k | } |
2137 | 8.20k | if(NDPI_GRE_IS_SEQ(grehdr->flags)) { |
2138 | 2.06k | if(header->caplen < offset + 4) |
2139 | 325 | return 0; |
2140 | 1.73k | offset += 4; |
2141 | 1.73k | } |
2142 | 9.54k | } else if(NDPI_GRE_IS_VERSION_1(grehdr->flags)) { /*rfc-2637 section 4.1 enhanced gre*/ |
2143 | 9.18k | if(NDPI_GRE_IS_CSUM(grehdr->flags)) |
2144 | 309 | return 0; |
2145 | 8.87k | if(NDPI_GRE_IS_ROUTING(grehdr->flags)) |
2146 | 405 | return 0; |
2147 | 8.47k | if(!NDPI_GRE_IS_KEY(grehdr->flags)) |
2148 | 1.42k | return 0; |
2149 | 7.04k | if(NDPI_GRE_IS_STRICT(grehdr->flags)) |
2150 | 247 | return 0; |
2151 | 6.80k | if(grehdr->protocol != NDPI_GRE_PROTO_PPP) |
2152 | 505 | return 0; |
2153 | | /*key field*/ |
2154 | 6.29k | if(header->caplen < offset + 4) |
2155 | 272 | return 0; |
2156 | 6.02k | offset += 4; |
2157 | 6.02k | if(NDPI_GRE_IS_SEQ(grehdr->flags)) { |
2158 | 1.54k | if(header->caplen < offset + 4) |
2159 | 303 | return 0; |
2160 | 1.24k | offset += 4; |
2161 | 1.24k | } |
2162 | 5.72k | if(NDPI_GRE_IS_ACK(grehdr->flags)) { |
2163 | 768 | if(header->caplen < offset + 4) |
2164 | 74 | return 0; |
2165 | 694 | offset += 4; |
2166 | 694 | } |
2167 | 5.72k | } else { /*support only ver 0, 1*/ |
2168 | 365 | return 0; |
2169 | 365 | } |
2170 | 13.5k | return offset; |
2171 | 18.1k | } |
2172 | | |
2173 | | /* ****************************************************** */ |
2174 | | |
2175 | | struct ndpi_proto ndpi_workflow_process_packet(struct ndpi_workflow * workflow, |
2176 | | const struct pcap_pkthdr *header, |
2177 | | const u_char *packet, |
2178 | | ndpi_risk *flow_risk, |
2179 | 12.8M | struct ndpi_flow_info **flow) { |
2180 | | /* |
2181 | | * Declare pointers to packet headers |
2182 | | */ |
2183 | | /* --- Ethernet header --- */ |
2184 | 12.8M | const struct ndpi_ethhdr *ethernet; |
2185 | | /* --- LLC header --- */ |
2186 | 12.8M | const struct ndpi_llc_header_snap *llc; |
2187 | | |
2188 | | /* --- Cisco HDLC header --- */ |
2189 | 12.8M | const struct ndpi_chdlc *chdlc; |
2190 | | |
2191 | | /* --- Radio Tap header --- */ |
2192 | 12.8M | const struct ndpi_radiotap_header *radiotap; |
2193 | | /* --- Wifi header --- */ |
2194 | 12.8M | const struct ndpi_wifi_header *wifi; |
2195 | | |
2196 | | /* --- MPLS header --- */ |
2197 | 12.8M | union mpls { |
2198 | 12.8M | uint32_t u32; |
2199 | 12.8M | struct ndpi_mpls_header mpls; |
2200 | 12.8M | } mpls; |
2201 | | |
2202 | | /** --- IP header --- **/ |
2203 | 12.8M | struct ndpi_iphdr *iph; |
2204 | | /** --- IPv6 header --- **/ |
2205 | 12.8M | struct ndpi_ipv6hdr *iph6; |
2206 | | |
2207 | 12.8M | struct ndpi_proto nproto; |
2208 | 12.8M | ndpi_packet_tunnel tunnel_type = ndpi_no_tunnel; |
2209 | | |
2210 | | /* lengths and offsets */ |
2211 | 12.8M | u_int32_t eth_offset = 0, dlt; |
2212 | 12.8M | u_int16_t radio_len, header_length; |
2213 | 12.8M | u_int16_t fc; |
2214 | 12.8M | u_int16_t type = 0; |
2215 | 12.8M | int wifi_len = 0; |
2216 | 12.8M | int pyld_eth_len = 0; |
2217 | 12.8M | int check; |
2218 | 12.8M | u_int64_t time_ms; |
2219 | 12.8M | u_int16_t ip_offset = 0, ip_len; |
2220 | 12.8M | u_int16_t frag_off = 0, vlan_id = 0; |
2221 | 12.8M | u_int8_t proto = 0, recheck_type; |
2222 | 12.8M | u_int8_t ip_ver, ppp_type; |
2223 | | /*u_int32_t label;*/ |
2224 | | |
2225 | | /* counters */ |
2226 | 12.8M | u_int8_t vlan_packet = 0; |
2227 | | |
2228 | 12.8M | *flow_risk = 0 /* NDPI_NO_RISK */; |
2229 | 12.8M | *flow = NULL; |
2230 | | |
2231 | 12.8M | memset(&nproto, '\0', sizeof(nproto)); |
2232 | | |
2233 | 12.8M | if((addr_dump_path != NULL) && (workflow->stats.raw_packet_count == 0)) { |
2234 | | /* At the first packet flush expired cached addresses */ |
2235 | 7.89k | ndpi_cache_address_flush_expired(workflow->ndpi_struct, header->ts.tv_sec); |
2236 | 7.89k | } |
2237 | | |
2238 | | /* Increment raw packet counter */ |
2239 | 12.8M | workflow->stats.raw_packet_count++; |
2240 | | |
2241 | | /* setting time */ |
2242 | 12.8M | time_ms = ((uint64_t) header->ts.tv_sec) * TICK_RESOLUTION + header->ts.tv_usec / (1000000 / TICK_RESOLUTION); |
2243 | | |
2244 | | /* safety check */ |
2245 | 12.8M | if(workflow->last_time > time_ms) { |
2246 | | /* printf("\nWARNING: timestamp bug in the pcap file (ts delta: %llu, repairing)\n", ndpi_thread_info[thread_id].last_time - time); */ |
2247 | 12.7M | time_ms = workflow->last_time; |
2248 | 12.7M | } |
2249 | | /* update last time value */ |
2250 | 12.8M | workflow->last_time = time_ms; |
2251 | | |
2252 | | /*** check Data Link type ***/ |
2253 | 12.8M | int datalink_type; |
2254 | | |
2255 | | #ifdef USE_DPDK |
2256 | | datalink_type = DLT_EN10MB; |
2257 | | #else |
2258 | 12.8M | datalink_type = (int)pcap_datalink(workflow->pcap_handle); |
2259 | 12.8M | #endif |
2260 | | |
2261 | 12.8M | datalink_check: |
2262 | | // 20 for min iph and 8 for min UDP |
2263 | 12.8M | if(header->caplen < eth_offset + 28) |
2264 | 354k | return(nproto); /* Too short */ |
2265 | | |
2266 | | /* Keep in sync with ndpi_is_datalink_supported() */ |
2267 | 12.5M | switch(datalink_type) { |
2268 | 620k | case DLT_NULL: |
2269 | 620k | if(ntohl(*((u_int32_t*)&packet[eth_offset])) == 2) |
2270 | 97.0k | type = ETH_P_IP; |
2271 | 523k | else |
2272 | 523k | type = ETH_P_IPV6; |
2273 | | |
2274 | 620k | ip_offset = 4 + eth_offset; |
2275 | 620k | break; |
2276 | | |
2277 | | /* Cisco PPP in HDLC-like framing - 50 */ |
2278 | 2.31k | case DLT_PPP_SERIAL: |
2279 | 2.31k | chdlc = (struct ndpi_chdlc *) &packet[eth_offset]; |
2280 | 2.31k | ip_offset = eth_offset + sizeof(struct ndpi_chdlc); /* CHDLC_OFF = 4 */ |
2281 | 2.31k | type = ntohs(chdlc->proto_code); |
2282 | 2.31k | break; |
2283 | | |
2284 | | /* Cisco PPP - 9 or 104 */ |
2285 | 4.44k | case DLT_C_HDLC: |
2286 | 17.0k | case DLT_PPP: |
2287 | 17.0k | if(packet[0] == 0x0f || packet[0] == 0x8f) { |
2288 | 9.89k | chdlc = (struct ndpi_chdlc *) &packet[eth_offset]; |
2289 | 9.89k | ip_offset = eth_offset + sizeof(struct ndpi_chdlc); /* CHDLC_OFF = 4 */ |
2290 | 9.89k | type = ntohs(chdlc->proto_code); |
2291 | 9.89k | } else { |
2292 | 7.16k | ip_offset = eth_offset + 2; |
2293 | 7.16k | ppp_type = ntohs(*((u_int16_t*)&packet[eth_offset])); |
2294 | 7.16k | if(ppp_type == 0x0021) |
2295 | 1.44k | type = ETH_P_IP; |
2296 | 5.71k | else if(ppp_type == 0x0057) |
2297 | 670 | type = ETH_P_IPV6; |
2298 | 5.04k | else |
2299 | 5.04k | return(nproto); |
2300 | 7.16k | } |
2301 | 12.0k | break; |
2302 | | |
2303 | 12.0k | #ifdef DLT_IPV4 |
2304 | 177k | case DLT_IPV4: |
2305 | 177k | type = ETH_P_IP; |
2306 | 177k | ip_offset = eth_offset; |
2307 | 177k | break; |
2308 | 0 | #endif |
2309 | | |
2310 | 0 | #ifdef DLT_IPV6 |
2311 | 33.5k | case DLT_IPV6: |
2312 | 33.5k | type = ETH_P_IPV6; |
2313 | 33.5k | ip_offset = eth_offset; |
2314 | 33.5k | break; |
2315 | 0 | #endif |
2316 | | |
2317 | | /* IEEE 802.3 Ethernet - 1 */ |
2318 | 11.4M | case DLT_EN10MB: |
2319 | 11.4M | ethernet = (struct ndpi_ethhdr *) &packet[eth_offset]; |
2320 | 11.4M | ip_offset = sizeof(struct ndpi_ethhdr) + eth_offset; |
2321 | 11.4M | check = ntohs(ethernet->h_proto); |
2322 | | |
2323 | 11.4M | if(check <= 1500) |
2324 | 107k | pyld_eth_len = check; |
2325 | 11.2M | else if(check >= 1536) |
2326 | 11.2M | type = check; |
2327 | | |
2328 | 11.4M | if(pyld_eth_len != 0) { |
2329 | 103k | llc = (struct ndpi_llc_header_snap *)(&packet[ip_offset]); |
2330 | | /* check for LLC layer with SNAP extension */ |
2331 | 103k | if(llc->dsap == SNAP || llc->ssap == SNAP) { |
2332 | 1.75k | type = llc->snap.proto_ID; |
2333 | 1.75k | ip_offset += + 8; |
2334 | 1.75k | } |
2335 | | /* No SNAP extension - Spanning Tree pkt must be discarted */ |
2336 | 101k | else if(llc->dsap == BSTP || llc->ssap == BSTP) { |
2337 | 4.41k | goto v4_warning; |
2338 | 4.41k | } |
2339 | 103k | } |
2340 | 11.4M | break; |
2341 | | |
2342 | | /* Linux Cooked Capture - 113 */ |
2343 | 11.4M | case DLT_LINUX_SLL: |
2344 | 140k | type = (packet[eth_offset+14] << 8) + packet[eth_offset+15]; |
2345 | 140k | ip_offset = 16 + eth_offset; |
2346 | 140k | break; |
2347 | | |
2348 | | /* Linux Cooked Capture v2 - 276 */ |
2349 | 2.43k | case LINKTYPE_LINUX_SLL2: |
2350 | 2.43k | type = (packet[eth_offset+10] << 8) + packet[eth_offset+11]; |
2351 | 2.43k | ip_offset = 20 + eth_offset; |
2352 | 2.43k | break; |
2353 | | |
2354 | | /* Radiotap link-layer - 127 */ |
2355 | 21.1k | case DLT_IEEE802_11_RADIO: |
2356 | 21.1k | radiotap = (struct ndpi_radiotap_header *) &packet[eth_offset]; |
2357 | 21.1k | radio_len = radiotap->len; |
2358 | | |
2359 | | /* Check Bad FCS presence */ |
2360 | 21.1k | if((radiotap->flags & BAD_FCS) == BAD_FCS) { |
2361 | 1.57k | workflow->stats.total_discarded_bytes += header->len; |
2362 | 1.57k | return(nproto); |
2363 | 1.57k | } |
2364 | | |
2365 | 19.6k | if(header->caplen < (eth_offset + radio_len + sizeof(struct ndpi_wifi_header))) |
2366 | 5.03k | return(nproto); |
2367 | | |
2368 | | /* Calculate 802.11 header length (variable) */ |
2369 | 14.5k | wifi = (struct ndpi_wifi_header*)( packet + eth_offset + radio_len); |
2370 | 14.5k | fc = wifi->fc; |
2371 | | |
2372 | | /* check wifi data presence */ |
2373 | 14.5k | if(FCF_TYPE(fc) == WIFI_DATA) { |
2374 | 9.45k | if((FCF_TO_DS(fc) && FCF_FROM_DS(fc) == 0x0) || |
2375 | 6.30k | (FCF_TO_DS(fc) == 0x0 && FCF_FROM_DS(fc))) |
2376 | 5.64k | wifi_len = 26; /* + 4 byte fcs */ |
2377 | 9.45k | } else /* no data frames */ |
2378 | 5.12k | return(nproto); |
2379 | | |
2380 | | /* Check ether_type from LLC */ |
2381 | 9.45k | if(header->caplen < (eth_offset + wifi_len + radio_len + sizeof(struct ndpi_llc_header_snap))) |
2382 | 3.32k | return(nproto); |
2383 | 6.12k | llc = (struct ndpi_llc_header_snap*)(packet + eth_offset + wifi_len + radio_len); |
2384 | 6.12k | if(llc->dsap == SNAP) |
2385 | 135 | type = ntohs(llc->snap.proto_ID); |
2386 | | |
2387 | | /* Set IP header offset */ |
2388 | 6.12k | ip_offset = wifi_len + radio_len + sizeof(struct ndpi_llc_header_snap) + eth_offset; |
2389 | 6.12k | break; |
2390 | | |
2391 | 99.3k | case DLT_RAW: |
2392 | 99.3k | ip_offset = eth_offset; |
2393 | | /* Heuristic: no explicit field with next protocol */ |
2394 | 99.3k | ip_ver = (packet[ip_offset] & 0xF0) >> 4; |
2395 | 99.3k | if(ip_ver == 4) |
2396 | 81.6k | type = ETH_P_IP; |
2397 | 17.6k | else if(ip_ver == 6) |
2398 | 13.3k | type = ETH_P_IPV6; |
2399 | 4.33k | else |
2400 | 4.33k | return(nproto); |
2401 | | |
2402 | 95.0k | break; |
2403 | | |
2404 | 95.0k | case DLT_PPI: |
2405 | 3.93k | header_length = le16toh(*(u_int16_t *)&packet[eth_offset + 2]); |
2406 | 3.93k | dlt = le32toh(*(u_int32_t *)&packet[eth_offset + 4]); |
2407 | 3.93k | if(dlt != DLT_EN10MB) /* Handle only standard ethernet, for the time being */ |
2408 | 2.87k | return(nproto); |
2409 | 1.06k | datalink_type = DLT_EN10MB; |
2410 | 1.06k | eth_offset += header_length; |
2411 | 1.06k | goto datalink_check; |
2412 | | |
2413 | 0 | default: |
2414 | | /* |
2415 | | * We shoudn't be here, because we already checked that this datalink is supported. |
2416 | | * Should ndpi_is_datalink_supported() be updated? |
2417 | | */ |
2418 | 0 | printf("Unknown datalink %d\n", datalink_type); |
2419 | 0 | return(nproto); |
2420 | 12.5M | } |
2421 | | |
2422 | 12.6M | ether_type_check: |
2423 | 12.6M | recheck_type = 0; |
2424 | | |
2425 | | /* check ether type */ |
2426 | 12.6M | switch(type) { |
2427 | 101k | case ETH_P_VLAN: |
2428 | 101k | if(ip_offset+4 >= (int)header->caplen) |
2429 | 143 | return(nproto); |
2430 | 101k | vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset+1]) & 0xFFF; |
2431 | 101k | type = (packet[ip_offset+2] << 8) + packet[ip_offset+3]; |
2432 | 101k | ip_offset += 4; |
2433 | 101k | vlan_packet = 1; |
2434 | | |
2435 | | // double tagging for 802.1Q |
2436 | 141k | while((type == 0x8100) && (((bpf_u_int32)ip_offset+4) < header->caplen)) { |
2437 | 40.3k | vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset+1]) & 0xFFF; |
2438 | 40.3k | type = (packet[ip_offset+2] << 8) + packet[ip_offset+3]; |
2439 | 40.3k | ip_offset += 4; |
2440 | 40.3k | } |
2441 | 101k | recheck_type = 1; |
2442 | 101k | break; |
2443 | | |
2444 | 1.58k | case ETH_P_MPLS_UNI: |
2445 | 2.40k | case ETH_P_MPLS_MULTI: |
2446 | 2.40k | if(ip_offset+4 >= (int)header->caplen) |
2447 | 371 | return(nproto); |
2448 | 2.03k | mpls.u32 = *((uint32_t *) &packet[ip_offset]); |
2449 | 2.03k | mpls.u32 = ntohl(mpls.u32); |
2450 | 2.03k | workflow->stats.mpls_count++; |
2451 | 2.03k | type = ETH_P_IP, ip_offset += 4; |
2452 | | |
2453 | 12.7k | while(!mpls.mpls.s && (((bpf_u_int32)ip_offset) + 4 < header->caplen)) { |
2454 | 10.6k | mpls.u32 = *((uint32_t *) &packet[ip_offset]); |
2455 | 10.6k | mpls.u32 = ntohl(mpls.u32); |
2456 | 10.6k | ip_offset += 4; |
2457 | 10.6k | } |
2458 | 2.03k | recheck_type = 1; |
2459 | 2.03k | break; |
2460 | | |
2461 | 9.15k | case ETH_P_PPPoE: |
2462 | 9.15k | workflow->stats.pppoe_count++; |
2463 | 9.15k | type = ETH_P_IP; |
2464 | 9.15k | ip_offset += 8; |
2465 | 9.15k | recheck_type = 1; |
2466 | 9.15k | break; |
2467 | | |
2468 | 11.1M | case ETH_P_IP: |
2469 | 12.2M | case ETH_P_IPV6: |
2470 | | /* Good let's keep decoding */ |
2471 | 12.2M | break; |
2472 | | |
2473 | 249k | default: |
2474 | 249k | return(nproto); |
2475 | 12.6M | } |
2476 | | |
2477 | 12.3M | if(recheck_type) |
2478 | 112k | goto ether_type_check; |
2479 | | |
2480 | 12.2M | workflow->stats.vlan_count += vlan_packet; |
2481 | | |
2482 | 12.2M | iph_check: |
2483 | | /* Check and set IP header size and total packet length */ |
2484 | 12.2M | if(header->caplen < ip_offset + sizeof(struct ndpi_iphdr)) |
2485 | 9.08k | return(nproto); /* Too short for next IP header*/ |
2486 | | |
2487 | 12.2M | iph = (struct ndpi_iphdr *) &packet[ip_offset]; |
2488 | | |
2489 | | /* just work on Ethernet packets that contain IP */ |
2490 | 12.2M | if(type == ETH_P_IP && header->caplen >= ip_offset) { |
2491 | 11.1M | frag_off = ntohs(iph->frag_off); |
2492 | | |
2493 | 11.1M | proto = iph->protocol; |
2494 | 11.1M | if(header->caplen < header->len) { |
2495 | 327k | static u_int8_t cap_warning_used = 0; |
2496 | | |
2497 | 327k | if(cap_warning_used == 0) { |
2498 | 11 | if(!workflow->prefs.quiet_mode) |
2499 | 11 | LOG(NDPI_LOG_DEBUG, |
2500 | 11 | "\n\nWARNING: packet capture size is smaller than packet size, DETECTION MIGHT NOT WORK CORRECTLY\n\n"); |
2501 | 11 | cap_warning_used = 1; |
2502 | 11 | } |
2503 | 327k | } |
2504 | 11.1M | } |
2505 | | |
2506 | 12.2M | if(iph->version == IPVERSION) { |
2507 | 11.5M | ip_len = ((u_int16_t)iph->ihl * 4); |
2508 | 11.5M | iph6 = NULL; |
2509 | | |
2510 | 11.5M | if(iph->protocol == IPPROTO_IPV6 |
2511 | 11.5M | || iph->protocol == NDPI_IPIP_PROTOCOL_TYPE |
2512 | 11.5M | ) { |
2513 | 9.29k | ip_offset += ip_len; |
2514 | 9.29k | if(ip_len > 0) |
2515 | 8.93k | goto iph_check; |
2516 | 9.29k | } |
2517 | | |
2518 | 11.5M | if((frag_off & 0x1FFF) != 0) { |
2519 | 104k | static u_int8_t ipv4_frags_warning_used = 0; |
2520 | 104k | workflow->stats.fragmented_count++; |
2521 | | |
2522 | 104k | if(ipv4_frags_warning_used == 0) { |
2523 | 11 | if(!workflow->prefs.quiet_mode) |
2524 | 11 | LOG(NDPI_LOG_DEBUG, "\n\nWARNING: IPv4 fragments are not handled by this demo (nDPI supports them)\n"); |
2525 | 11 | ipv4_frags_warning_used = 1; |
2526 | 11 | } |
2527 | | |
2528 | 104k | workflow->stats.total_discarded_bytes += header->len; |
2529 | 104k | return(nproto); |
2530 | 104k | } |
2531 | 11.5M | } else if(iph->version == 6) { |
2532 | 676k | if(header->caplen < ip_offset + sizeof(struct ndpi_ipv6hdr)) |
2533 | 2.76k | return(nproto); /* Too short for IPv6 header*/ |
2534 | | |
2535 | 673k | iph6 = (struct ndpi_ipv6hdr *)&packet[ip_offset]; |
2536 | 673k | proto = iph6->ip6_hdr.ip6_un1_nxt; |
2537 | 673k | ip_len = ntohs(iph6->ip6_hdr.ip6_un1_plen); |
2538 | | |
2539 | 673k | if(header->caplen < (ip_offset + sizeof(struct ndpi_ipv6hdr) + ntohs(iph6->ip6_hdr.ip6_un1_plen))) |
2540 | 9.22k | return(nproto); /* Too short for IPv6 payload*/ |
2541 | | |
2542 | 664k | const u_int8_t *l4ptr = (((const u_int8_t *) iph6) + sizeof(struct ndpi_ipv6hdr)); |
2543 | 664k | u_int16_t ipsize = header->caplen - ip_offset; |
2544 | | |
2545 | 664k | if(ndpi_handle_ipv6_extension_headers(ipsize - sizeof(struct ndpi_ipv6hdr), &l4ptr, &ip_len, &proto) != 0) { |
2546 | 11.4k | return(nproto); |
2547 | 11.4k | } |
2548 | | |
2549 | 652k | if(proto == IPPROTO_IPV6 |
2550 | 651k | || proto == NDPI_IPIP_PROTOCOL_TYPE |
2551 | 652k | ) { |
2552 | 3.52k | if(l4ptr > packet) { /* Better safe than sorry */ |
2553 | 3.52k | ip_offset = (l4ptr - packet); |
2554 | 3.52k | goto iph_check; |
2555 | 3.52k | } |
2556 | 3.52k | } |
2557 | | |
2558 | 649k | iph = NULL; |
2559 | 649k | } else { |
2560 | 47.3k | static u_int8_t ipv4_warning_used = 0; |
2561 | | |
2562 | 60.2k | v4_warning: |
2563 | 60.2k | if(ipv4_warning_used == 0) { |
2564 | 11 | if(!workflow->prefs.quiet_mode) |
2565 | 11 | LOG(NDPI_LOG_DEBUG, |
2566 | 11 | "\n\nWARNING: only IPv4/IPv6 packets are supported in this demo (nDPI supports both IPv4 and IPv6), all other packets will be discarded\n\n"); |
2567 | 11 | ipv4_warning_used = 1; |
2568 | 11 | } |
2569 | | |
2570 | 60.2k | workflow->stats.total_discarded_bytes += header->len; |
2571 | 60.2k | return(nproto); |
2572 | 47.3k | } |
2573 | | |
2574 | 12.0M | if(workflow->prefs.decode_tunnels && (proto == IPPROTO_UDP)) { |
2575 | 3.32M | if(header->caplen < ip_offset + ip_len + sizeof(struct ndpi_udphdr)) |
2576 | 1.36k | return(nproto); /* Too short for UDP header*/ |
2577 | 3.32M | else { |
2578 | 3.32M | struct ndpi_udphdr *udp = (struct ndpi_udphdr *)&packet[ip_offset+ip_len]; |
2579 | 3.32M | u_int16_t sport = ntohs(udp->source), dport = ntohs(udp->dest); |
2580 | | |
2581 | 3.32M | if(((sport == GTP_U_V1_PORT) || (dport == GTP_U_V1_PORT)) && |
2582 | 90.2k | (ip_offset + ip_len + sizeof(struct ndpi_udphdr) + 8 /* Minimum GTPv1 header len */ < header->caplen)) { |
2583 | | /* Check if it's GTPv1 */ |
2584 | 88.9k | u_int offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr); |
2585 | 88.9k | u_int8_t flags = packet[offset]; |
2586 | 88.9k | u_int8_t message_type = packet[offset+1]; |
2587 | 88.9k | u_int8_t exts_parsing_error = 0; |
2588 | | |
2589 | 88.9k | if((((flags & 0xE0) >> 5) == 1 /* GTPv1 */) && |
2590 | 61.6k | (message_type == 0xFF /* T-PDU */)) { |
2591 | | |
2592 | 58.1k | offset += 8; /* GTPv1 header len */ |
2593 | 58.1k | if(flags & 0x07) |
2594 | 33.9k | offset += 4; /* sequence_number + pdu_number + next_ext_header fields */ |
2595 | | /* Extensions parsing */ |
2596 | 58.1k | if(flags & 0x04) { |
2597 | 8.07k | unsigned int ext_length = 0; |
2598 | | |
2599 | 13.5k | while(offset < header->caplen) { |
2600 | 10.9k | ext_length = packet[offset] << 2; |
2601 | 10.9k | offset += ext_length; |
2602 | 10.9k | if(offset >= header->caplen || ext_length == 0) { |
2603 | 2.50k | exts_parsing_error = 1; |
2604 | 2.50k | break; |
2605 | 2.50k | } |
2606 | 8.48k | if(packet[offset - 1] == 0) |
2607 | 3.03k | break; |
2608 | 8.48k | } |
2609 | 8.07k | } |
2610 | | |
2611 | 58.1k | if(offset < header->caplen && !exts_parsing_error) { |
2612 | | /* Ok, valid GTP-U */ |
2613 | 33.3k | tunnel_type = ndpi_gtp_tunnel; |
2614 | 33.3k | ip_offset = offset; |
2615 | 33.3k | iph = (struct ndpi_iphdr *)&packet[ip_offset]; |
2616 | 33.3k | if(iph->version == 6) { |
2617 | 4.22k | iph6 = (struct ndpi_ipv6hdr *)&packet[ip_offset]; |
2618 | 4.22k | iph = NULL; |
2619 | 4.22k | if(header->caplen < ip_offset + sizeof(struct ndpi_ipv6hdr)) |
2620 | 1.51k | return(nproto); |
2621 | 29.0k | } else if(iph->version != IPVERSION) { |
2622 | | // printf("WARNING: not good (packet_id=%u)!\n", (unsigned int)workflow->stats.raw_packet_count); |
2623 | 8.46k | goto v4_warning; |
2624 | 20.6k | } else { |
2625 | 20.6k | if(header->caplen < ip_offset + sizeof(struct ndpi_iphdr)) |
2626 | 2.07k | return(nproto); |
2627 | 20.6k | } |
2628 | 33.3k | } |
2629 | 58.1k | } |
2630 | 3.23M | } else if((sport == TZSP_PORT) || (dport == TZSP_PORT)) { |
2631 | | /* https://en.wikipedia.org/wiki/TZSP */ |
2632 | 10.7k | if(header->caplen < ip_offset + ip_len + sizeof(struct ndpi_udphdr) + 4) |
2633 | 362 | return(nproto); /* Too short for TZSP*/ |
2634 | | |
2635 | 10.3k | u_int offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr); |
2636 | 10.3k | u_int8_t version = packet[offset]; |
2637 | 10.3k | u_int8_t ts_type = packet[offset+1]; |
2638 | 10.3k | u_int16_t encapsulates = ntohs(*((u_int16_t*)&packet[offset+2])); |
2639 | | |
2640 | 10.3k | tunnel_type = ndpi_tzsp_tunnel; |
2641 | | |
2642 | 10.3k | if((version == 1) && (ts_type == 0) && (encapsulates == 1)) { |
2643 | 1.28k | u_int8_t stop = 0; |
2644 | | |
2645 | 1.28k | offset += 4; |
2646 | | |
2647 | 1.28k | while((!stop) && (offset < header->caplen)) { |
2648 | 1.13k | u_int8_t tag_type = packet[offset]; |
2649 | 1.13k | u_int8_t tag_len; |
2650 | | |
2651 | 1.13k | switch(tag_type) { |
2652 | 289 | case 0: /* PADDING Tag */ |
2653 | 289 | tag_len = 1; |
2654 | 289 | break; |
2655 | 109 | case 1: /* END Tag */ |
2656 | 109 | tag_len = 1, stop = 1; |
2657 | 109 | break; |
2658 | 739 | default: |
2659 | 739 | if(offset + 1 >= header->caplen) |
2660 | 125 | return(nproto); /* Invalid packet */ |
2661 | 614 | tag_len = packet[offset+1]; |
2662 | 614 | break; |
2663 | 1.13k | } |
2664 | | |
2665 | 1.01k | offset += tag_len; |
2666 | | |
2667 | 1.01k | if(offset >= header->caplen) |
2668 | 349 | return(nproto); /* Invalid packet */ |
2669 | 663 | else { |
2670 | 663 | eth_offset = offset; |
2671 | 663 | goto datalink_check; |
2672 | 663 | } |
2673 | 1.01k | } |
2674 | 1.28k | } |
2675 | 3.22M | } else if((sport == NDPI_CAPWAP_DATA_PORT) || (dport == NDPI_CAPWAP_DATA_PORT)) { |
2676 | | /* We dissect ONLY CAPWAP traffic */ |
2677 | 20.1k | u_int offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr); |
2678 | | |
2679 | 20.1k | if((offset+1) < header->caplen) { |
2680 | 18.6k | uint8_t preamble = packet[offset]; |
2681 | | |
2682 | 18.6k | if((preamble & 0x0F) == 0) { /* CAPWAP header */ |
2683 | 14.3k | u_int16_t msg_len = (packet[offset+1] & 0xF8) >> 1; |
2684 | | |
2685 | 14.3k | offset += msg_len; |
2686 | | |
2687 | 14.3k | if((offset + 32 < header->caplen) && |
2688 | 9.97k | (packet[offset + 1] == 0x08)) { |
2689 | | /* IEEE 802.11 Data */ |
2690 | 2.60k | offset += 24; |
2691 | | /* LLC header is 8 bytes */ |
2692 | 2.60k | type = ntohs((u_int16_t)*((u_int16_t*)&packet[offset+6])); |
2693 | | |
2694 | 2.60k | ip_offset = offset + 8; |
2695 | | |
2696 | 2.60k | tunnel_type = ndpi_capwap_tunnel; |
2697 | 2.60k | goto iph_check; |
2698 | 2.60k | } |
2699 | 14.3k | } |
2700 | 18.6k | } |
2701 | 3.20M | }else if(ndpi_is_valid_vxlan(header, packet, ip_offset, ip_len)){ |
2702 | 21.9k | tunnel_type = ndpi_vxlan_tunnel; |
2703 | 21.9k | eth_offset = ndpi_skip_vxlan(ip_offset, ip_len); |
2704 | 21.9k | goto datalink_check; |
2705 | 21.9k | } |
2706 | 3.32M | } |
2707 | 8.74M | } else if(workflow->prefs.decode_tunnels && (proto == IPPROTO_GRE)) { |
2708 | 22.2k | if(header->caplen < ip_offset + ip_len + sizeof(struct ndpi_gre_basehdr)) |
2709 | 629 | return(nproto); /* Too short for GRE header*/ |
2710 | 21.6k | u_int32_t offset = 0; |
2711 | 21.6k | if((offset = ndpi_is_valid_gre_tunnel(header, packet, ip_offset, ip_len))) { |
2712 | 13.5k | tunnel_type = ndpi_gre_tunnel; |
2713 | 13.5k | struct ndpi_gre_basehdr *grehdr = (struct ndpi_gre_basehdr*)&packet[ip_offset + ip_len]; |
2714 | 13.5k | if(grehdr->protocol == ntohs(ETH_P_IP) || grehdr->protocol == ntohs(ETH_P_IPV6)) { |
2715 | 1.75k | ip_offset = offset; |
2716 | 1.75k | goto iph_check; |
2717 | 11.7k | } else if(grehdr->protocol == NDPI_GRE_PROTO_PPP) { // ppp protocol |
2718 | 5.72k | ip_offset = offset + NDPI_PPP_HDRLEN; |
2719 | 5.72k | goto iph_check; |
2720 | 6.04k | } else { |
2721 | 6.04k | eth_offset = offset; |
2722 | 6.04k | goto datalink_check; |
2723 | 6.04k | } |
2724 | 13.5k | } else { |
2725 | 8.11k | return(nproto); |
2726 | 8.11k | } |
2727 | 21.6k | } |
2728 | | |
2729 | | /* process the packet */ |
2730 | 12.0M | return(packet_processing(workflow, time_ms, vlan_id, tunnel_type, iph, iph6, |
2731 | 12.0M | header->caplen - ip_offset, |
2732 | 12.0M | header->caplen, header, packet, header->ts, |
2733 | 12.0M | flow_risk, flow)); |
2734 | 12.0M | } |
2735 | | |
2736 | | /* *********************************************** */ |
2737 | | |
2738 | | #ifdef USE_DPDK |
2739 | | |
2740 | | #include <rte_version.h> |
2741 | | #include <rte_ether.h> |
2742 | | |
2743 | | static const struct rte_eth_conf port_conf_default = { |
2744 | | #if(RTE_VERSION < RTE_VERSION_NUM(19, 8, 0, 0)) |
2745 | | .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN } |
2746 | | #else |
2747 | | .rxmode = { .max_rx_pkt_len = RTE_ETHER_MAX_LEN } |
2748 | | #endif |
2749 | | }; |
2750 | | |
2751 | | /* ************************************ */ |
2752 | | |
2753 | | int dpdk_port_init(int port, struct rte_mempool *mbuf_pool) { |
2754 | | struct rte_eth_conf port_conf = port_conf_default; |
2755 | | const u_int16_t rx_rings = 1, tx_rings = 1; |
2756 | | int retval; |
2757 | | u_int16_t q; |
2758 | | |
2759 | | /* 1 RX queue */ |
2760 | | retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); |
2761 | | |
2762 | | if(retval != 0) |
2763 | | return retval; |
2764 | | |
2765 | | for(q = 0; q < rx_rings; q++) { |
2766 | | retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL, mbuf_pool); |
2767 | | if(retval < 0) |
2768 | | return retval; |
2769 | | } |
2770 | | |
2771 | | for(q = 0; q < tx_rings; q++) { |
2772 | | retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); |
2773 | | if(retval < 0) |
2774 | | return retval; |
2775 | | } |
2776 | | |
2777 | | retval = rte_eth_dev_start(port); |
2778 | | |
2779 | | if(retval < 0) |
2780 | | return retval; |
2781 | | |
2782 | | rte_eth_promiscuous_enable(port); |
2783 | | |
2784 | | return 0; |
2785 | | } |
2786 | | |
2787 | | int dpdk_port_deinit(int port) { |
2788 | | rte_eth_dev_stop(port); |
2789 | | rte_eth_dev_close(port); |
2790 | | return 0; |
2791 | | } |
2792 | | |
2793 | | #endif |