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