1 /*
2 * ndpi_main.c
3 *
4 * Copyright (C) 2011-21 - 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 <stdlib.h>
25 #include <errno.h>
26 #include <sys/types.h>
27
28 #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_UNKNOWN
29
30 #include "ndpi_config.h"
31 #include "ndpi_api.h"
32 #include "ahocorasick.h"
33 #include "libcache.h"
34
35 #ifdef HAVE_LIBGCRYPT
36 #include <gcrypt.h>
37 #endif
38
39 #include <time.h>
40 #ifndef WIN32
41 #include <unistd.h>
42 #endif
43
44 #if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __DragonFly__
45 #include <sys/endian.h>
46 #endif
47
48 #include "ndpi_content_match.c.inc"
49 #include "third_party/include/ndpi_patricia.h"
50 #include "third_party/include/ndpi_md5.h"
51
52 /* stun.c */
53 extern u_int32_t get_stun_lru_key(struct ndpi_flow_struct *flow, u_int8_t rev);
54
55 static int _ndpi_debug_callbacks = 0;
56
57 /* #define DGA_DEBUG 1 */
58 /* #define MATCH_DEBUG 1 */
59
60 u_int ndpi_verbose_dga_detection = 0;
61
62 /* ****************************************** */
63
64 static void *(*_ndpi_flow_malloc)(size_t size);
65 static void (*_ndpi_flow_free)(void *ptr);
66
67 static void *(*_ndpi_malloc)(size_t size);
68 static void (*_ndpi_free)(void *ptr);
69
70 /* ****************************************** */
71
72 static ndpi_risk_info ndpi_known_risks[] = {
73 { NDPI_NO_RISK, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE },
74 { NDPI_URL_POSSIBLE_XSS, NDPI_RISK_SEVERE, CLIENT_HIGH_RISK_PERCENTAGE },
75 { NDPI_URL_POSSIBLE_SQL_INJECTION, NDPI_RISK_SEVERE, CLIENT_HIGH_RISK_PERCENTAGE },
76 { NDPI_URL_POSSIBLE_RCE_INJECTION, NDPI_RISK_SEVERE, CLIENT_HIGH_RISK_PERCENTAGE },
77 { NDPI_BINARY_APPLICATION_TRANSFER, NDPI_RISK_SEVERE, CLIENT_FAIR_RISK_PERCENTAGE },
78 { NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE },
79 { NDPI_TLS_SELFSIGNED_CERTIFICATE, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
80 { NDPI_TLS_OBSOLETE_VERSION, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
81 { NDPI_TLS_WEAK_CIPHER, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
82 { NDPI_TLS_CERTIFICATE_EXPIRED, NDPI_RISK_HIGH, CLIENT_FAIR_RISK_PERCENTAGE },
83 { NDPI_TLS_CERTIFICATE_MISMATCH, NDPI_RISK_HIGH, CLIENT_FAIR_RISK_PERCENTAGE },
84 { NDPI_HTTP_SUSPICIOUS_USER_AGENT, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
85 { NDPI_HTTP_NUMERIC_IP_HOST, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE },
86 { NDPI_HTTP_SUSPICIOUS_URL, NDPI_RISK_HIGH, CLIENT_HIGH_RISK_PERCENTAGE },
87 { NDPI_HTTP_SUSPICIOUS_HEADER, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
88 { NDPI_TLS_NOT_CARRYING_HTTPS, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE },
89 { NDPI_SUSPICIOUS_DGA_DOMAIN, NDPI_RISK_HIGH, CLIENT_HIGH_RISK_PERCENTAGE },
90 { NDPI_MALFORMED_PACKET, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE },
91 { NDPI_SSH_OBSOLETE_CLIENT_VERSION_OR_CIPHER, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
92 { NDPI_SSH_OBSOLETE_SERVER_VERSION_OR_CIPHER, NDPI_RISK_MEDIUM, CLIENT_LOW_RISK_PERCENTAGE },
93 { NDPI_SMB_INSECURE_VERSION, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
94 { NDPI_TLS_SUSPICIOUS_ESNI_USAGE, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
95 { NDPI_UNSAFE_PROTOCOL, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE },
96 { NDPI_DNS_SUSPICIOUS_TRAFFIC, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
97 { NDPI_TLS_MISSING_SNI, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
98 { NDPI_HTTP_SUSPICIOUS_CONTENT, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
99 { NDPI_RISKY_ASN, NDPI_RISK_MEDIUM, CLIENT_FAIR_RISK_PERCENTAGE },
100 { NDPI_RISKY_DOMAIN, NDPI_RISK_MEDIUM, CLIENT_FAIR_RISK_PERCENTAGE },
101 { NDPI_MALICIOUS_JA3, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
102 { NDPI_MALICIOUS_SHA1_CERTIFICATE, NDPI_RISK_MEDIUM, CLIENT_FAIR_RISK_PERCENTAGE },
103 { NDPI_DESKTOP_OR_FILE_SHARING_SESSION, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE },
104 { NDPI_TLS_UNCOMMON_ALPN, NDPI_RISK_MEDIUM, CLIENT_HIGH_RISK_PERCENTAGE },
105 { NDPI_TLS_CERT_VALIDITY_TOO_LONG, NDPI_RISK_MEDIUM, CLIENT_FAIR_RISK_PERCENTAGE },
106 { NDPI_TLS_EXTENSION_SUSPICIOUS, NDPI_RISK_HIGH, CLIENT_HIGH_RISK_PERCENTAGE },
107
108 /* Leave this as last member */
109 { NDPI_MAX_RISK, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE }
110 };
111
112 /* ****************************************** */
113
114 /* Forward */
115 static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_str, ndpi_port_range *range,
116 ndpi_proto_defaults_t *def, u_int8_t customUserProto, ndpi_default_ports_tree_node_t **root,
117 const char *_func, int _line);
118
119 static int removeDefaultPort(ndpi_port_range *range, ndpi_proto_defaults_t *def, ndpi_default_ports_tree_node_t **root);
120
121 /* ****************************************** */
122
123 ndpi_custom_dga_predict_fctn ndpi_dga_function = NULL;
124
125 /* ****************************************** */
126
flow_is_proto(struct ndpi_flow_struct * flow,u_int16_t p)127 static inline uint8_t flow_is_proto(struct ndpi_flow_struct *flow, u_int16_t p) {
128 return((flow->detected_protocol_stack[0] == p) || (flow->detected_protocol_stack[1] == p));
129 }
130
131 /* ****************************************** */
132
ndpi_malloc(size_t size)133 void *ndpi_malloc(size_t size) {
134 return(_ndpi_malloc ? _ndpi_malloc(size) : malloc(size));
135 }
ndpi_flow_malloc(size_t size)136 void *ndpi_flow_malloc(size_t size) {
137 return(_ndpi_flow_malloc ? _ndpi_flow_malloc(size) : ndpi_malloc(size));
138 }
139
140 /* ****************************************** */
141
ndpi_calloc(unsigned long count,size_t size)142 void *ndpi_calloc(unsigned long count, size_t size) {
143 size_t len = count * size;
144 void *p = ndpi_malloc(len);
145
146 if(p)
147 memset(p, 0, len);
148
149 return(p);
150 }
151
152 /* ****************************************** */
153
ndpi_free(void * ptr)154 void ndpi_free(void *ptr) {
155 if(_ndpi_free) {
156 if(ptr)
157 _ndpi_free(ptr);
158 } else {
159 if(ptr)
160 free(ptr);
161 }
162 }
163
164 /* ****************************************** */
165
ndpi_flow_free(void * ptr)166 void ndpi_flow_free(void *ptr) {
167 if(_ndpi_flow_free)
168 _ndpi_flow_free(ptr);
169 else
170 ndpi_free_flow((struct ndpi_flow_struct *) ptr);
171 }
172
173 /* ****************************************** */
174
ndpi_realloc(void * ptr,size_t old_size,size_t new_size)175 void *ndpi_realloc(void *ptr, size_t old_size, size_t new_size) {
176 void *ret = ndpi_malloc(new_size);
177
178 if(!ret)
179 return(ret);
180 else {
181 if(ptr != NULL) {
182 memcpy(ret, ptr, old_size);
183 ndpi_free(ptr);
184 }
185 return(ret);
186 }
187 }
188 /* ****************************************** */
189
ndpi_strdup(const char * s)190 char *ndpi_strdup(const char *s) {
191 if(s == NULL ){
192 return NULL;
193 }
194
195 int len = strlen(s);
196 char *m = ndpi_malloc(len + 1);
197
198 if(m) {
199 memcpy(m, s, len);
200 m[len] = '\0';
201 }
202
203 return(m);
204 }
205
206 /* *********************************************************************************** */
207
208 /* Opaque structure defined here */
209 struct ndpi_ptree
210 {
211 ndpi_patricia_tree_t *v4;
212 ndpi_patricia_tree_t *v6;
213 };
214
215 /* *********************************************************************************** */
216
ndpi_detection_get_sizeof_ndpi_flow_struct(void)217 u_int32_t ndpi_detection_get_sizeof_ndpi_flow_struct(void) {
218 return(sizeof(struct ndpi_flow_struct));
219 }
220
221 /* *********************************************************************************** */
222
ndpi_detection_get_sizeof_ndpi_id_struct(void)223 u_int32_t ndpi_detection_get_sizeof_ndpi_id_struct(void) {
224 return(sizeof(struct ndpi_id_struct));
225 }
226
227 /* *********************************************************************************** */
228
ndpi_detection_get_sizeof_ndpi_flow_tcp_struct(void)229 u_int32_t ndpi_detection_get_sizeof_ndpi_flow_tcp_struct(void) {
230 return(sizeof(struct ndpi_flow_tcp_struct));
231 }
232
233 /* *********************************************************************************** */
234
ndpi_detection_get_sizeof_ndpi_flow_udp_struct(void)235 u_int32_t ndpi_detection_get_sizeof_ndpi_flow_udp_struct(void) {
236 return(sizeof(struct ndpi_flow_udp_struct));
237 }
238
239 /* *********************************************************************************** */
240
ndpi_get_proto_by_id(struct ndpi_detection_module_struct * ndpi_str,u_int id)241 char *ndpi_get_proto_by_id(struct ndpi_detection_module_struct *ndpi_str, u_int id) {
242 return((id >= ndpi_str->ndpi_num_supported_protocols) ? NULL : ndpi_str->proto_defaults[id].protoName);
243 }
244
245 /* *********************************************************************************** */
246
ndpi_get_proto_by_name(struct ndpi_detection_module_struct * ndpi_str,const char * name)247 u_int16_t ndpi_get_proto_by_name(struct ndpi_detection_module_struct *ndpi_str, const char *name) {
248 u_int16_t i, num = ndpi_get_num_supported_protocols(ndpi_str);
249
250 for(i = 0; i < num; i++)
251 if(strcasecmp(ndpi_get_proto_by_id(ndpi_str, i), name) == 0)
252 return(i);
253
254 return(NDPI_PROTOCOL_UNKNOWN);
255 }
256
257 /* ************************************************************************************* */
258
259 #ifdef CODE_UNUSED
ndpi_build_default_ports_range(ndpi_port_range * ports,u_int16_t portA_low,u_int16_t portA_high,u_int16_t portB_low,u_int16_t portB_high,u_int16_t portC_low,u_int16_t portC_high,u_int16_t portD_low,u_int16_t portD_high,u_int16_t portE_low,u_int16_t portE_high)260 ndpi_port_range *ndpi_build_default_ports_range(ndpi_port_range *ports, u_int16_t portA_low, u_int16_t portA_high,
261 u_int16_t portB_low, u_int16_t portB_high, u_int16_t portC_low,
262 u_int16_t portC_high, u_int16_t portD_low, u_int16_t portD_high,
263 u_int16_t portE_low, u_int16_t portE_high) {
264 int i = 0;
265
266 ports[i].port_low = portA_low, ports[i].port_high = portA_high;
267 i++;
268 ports[i].port_low = portB_low, ports[i].port_high = portB_high;
269 i++;
270 ports[i].port_low = portC_low, ports[i].port_high = portC_high;
271 i++;
272 ports[i].port_low = portD_low, ports[i].port_high = portD_high;
273 i++;
274 ports[i].port_low = portE_low, ports[i].port_high = portE_high;
275
276 return(ports);
277 }
278 #endif
279
280 /* *********************************************************************************** */
281
ndpi_build_default_ports(ndpi_port_range * ports,u_int16_t portA,u_int16_t portB,u_int16_t portC,u_int16_t portD,u_int16_t portE)282 ndpi_port_range *ndpi_build_default_ports(ndpi_port_range *ports, u_int16_t portA, u_int16_t portB, u_int16_t portC,
283 u_int16_t portD, u_int16_t portE) {
284 int i = 0;
285
286 ports[i].port_low = portA, ports[i].port_high = portA;
287 i++;
288 ports[i].port_low = portB, ports[i].port_high = portB;
289 i++;
290 ports[i].port_low = portC, ports[i].port_high = portC;
291 i++;
292 ports[i].port_low = portD, ports[i].port_high = portD;
293 i++;
294 ports[i].port_low = portE, ports[i].port_high = portE;
295
296 return(ports);
297 }
298
299 /* ********************************************************************************** */
300
ndpi_set_proto_breed(struct ndpi_detection_module_struct * ndpi_str,u_int16_t protoId,ndpi_protocol_breed_t breed)301 void ndpi_set_proto_breed(struct ndpi_detection_module_struct *ndpi_str, u_int16_t protoId, ndpi_protocol_breed_t breed) {
302 if(!ndpi_is_valid_protoId(protoId))
303 return;
304 else
305 ndpi_str->proto_defaults[protoId].protoBreed = breed;
306 }
307
308 /* ********************************************************************************** */
309
ndpi_set_proto_category(struct ndpi_detection_module_struct * ndpi_str,u_int16_t protoId,ndpi_protocol_category_t protoCategory)310 void ndpi_set_proto_category(struct ndpi_detection_module_struct *ndpi_str, u_int16_t protoId,
311 ndpi_protocol_category_t protoCategory) {
312 if(!ndpi_is_valid_protoId(protoId))
313 return;
314 else
315 ndpi_str->proto_defaults[protoId].protoCategory = protoCategory;
316 }
317
318 /* ********************************************************************************** */
319
320 /*
321 There are some (master) protocols that are informative, meaning that it shows
322 what is the subprotocol about, but also that the subprotocol isn't a real protocol.
323
324 Example:
325 - DNS is informative as if we see a DNS request for www.facebook.com, the
326 returned protocol is DNS.Facebook, but Facebook isn't a real subprotocol but
327 rather it indicates a query for Facebook and not Facebook traffic.
328 - HTTP/SSL are NOT informative as SSL.Facebook (likely) means that this is
329 SSL (HTTPS) traffic containg Facebook traffic.
330 */
ndpi_is_subprotocol_informative(struct ndpi_detection_module_struct * ndpi_str,u_int16_t protoId)331 u_int8_t ndpi_is_subprotocol_informative(struct ndpi_detection_module_struct *ndpi_str, u_int16_t protoId) {
332 if(!ndpi_is_valid_protoId(protoId))
333 return(0);
334
335 switch(protoId) {
336 /* All dissectors that have calls to ndpi_match_host_subprotocol() */
337 case NDPI_PROTOCOL_DNS:
338 return(1);
339 break;
340
341 default:
342 return(0);
343 }
344 }
345 /* ********************************************************************************** */
346
ndpi_exclude_protocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int16_t protocol_id,const char * _file,const char * _func,int _line)347 void ndpi_exclude_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
348 u_int16_t protocol_id, const char *_file, const char *_func, int _line) {
349 if(ndpi_is_valid_protoId(protocol_id)) {
350 #ifdef NDPI_ENABLE_DEBUG_MESSAGES
351 if(ndpi_str && ndpi_str->ndpi_log_level >= NDPI_LOG_DEBUG && ndpi_str->ndpi_debug_printf != NULL) {
352 (*(ndpi_str->ndpi_debug_printf))(protocol_id, ndpi_str, NDPI_LOG_DEBUG, _file, _func, _line, "exclude %s\n",
353 ndpi_get_proto_name(ndpi_str, protocol_id));
354 }
355 #endif
356 NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, protocol_id);
357 }
358 }
359
360 /* ********************************************************************************** */
361
ndpi_set_proto_subprotocols(struct ndpi_detection_module_struct * ndpi_str,int protoId,...)362 void ndpi_set_proto_subprotocols(struct ndpi_detection_module_struct *ndpi_str, int protoId, ...)
363 {
364 va_list ap;
365 int current_arg = protoId;
366
367 va_start(ap, protoId);
368 while (current_arg != NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS)
369 {
370 ndpi_str->proto_defaults[protoId].subprotocol_count++;
371 current_arg = va_arg(ap, int);
372 }
373 va_end(ap);
374
375 ndpi_str->proto_defaults[protoId].subprotocols = NULL;
376
377 /* The last protocol is not a subprotocol. */
378 ndpi_str->proto_defaults[protoId].subprotocol_count--;
379 /* No subprotocol was set before NDPI_NO_MORE_SUBPROTOCOLS. */
380 if (ndpi_str->proto_defaults[protoId].subprotocol_count == 0)
381 {
382 return;
383 }
384
385 ndpi_str->proto_defaults[protoId].subprotocols =
386 ndpi_malloc(sizeof(protoId) * ndpi_str->proto_defaults[protoId].subprotocol_count);
387
388 size_t i = 0;
389 va_start(ap, protoId);
390 current_arg = va_arg(ap, int);
391 while (current_arg != NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS)
392 {
393 ndpi_str->proto_defaults[protoId].subprotocols[i++] = current_arg;
394 current_arg = va_arg(ap, int);
395 }
396 va_end(ap);
397 }
398
399 /* ********************************************************************************** */
400
ndpi_set_proto_defaults(struct ndpi_detection_module_struct * ndpi_str,u_int8_t is_cleartext,ndpi_protocol_breed_t breed,u_int16_t protoId,char * protoName,ndpi_protocol_category_t protoCategory,ndpi_port_range * tcpDefPorts,ndpi_port_range * udpDefPorts)401 void ndpi_set_proto_defaults(struct ndpi_detection_module_struct *ndpi_str,
402 u_int8_t is_cleartext, ndpi_protocol_breed_t breed,
403 u_int16_t protoId, char *protoName, ndpi_protocol_category_t protoCategory,
404 ndpi_port_range *tcpDefPorts, ndpi_port_range *udpDefPorts) {
405 char *name;
406 int j;
407
408 if(!ndpi_is_valid_protoId(protoId)) {
409 #ifdef DEBUG
410 NDPI_LOG_ERR(ndpi_str, "[NDPI] %s/protoId=%d: INTERNAL ERROR\n", protoName, protoId);
411 #endif
412 return;
413 }
414
415 if(ndpi_str->proto_defaults[protoId].protoName != NULL) {
416 #ifdef DEBUG
417 NDPI_LOG_ERR(ndpi_str, "[NDPI] %s/protoId=%d: already initialized. Ignoring it\n", protoName, protoId);
418 #endif
419 return;
420 }
421
422 name = ndpi_strdup(protoName);
423
424 if(ndpi_str->proto_defaults[protoId].protoName)
425 ndpi_free(ndpi_str->proto_defaults[protoId].protoName);
426
427 ndpi_str->proto_defaults[protoId].isClearTextProto = is_cleartext;
428 ndpi_str->proto_defaults[protoId].protoName = name;
429 ndpi_str->proto_defaults[protoId].protoCategory = protoCategory;
430 ndpi_str->proto_defaults[protoId].protoId = protoId;
431 ndpi_str->proto_defaults[protoId].protoBreed = breed;
432 ndpi_str->proto_defaults[protoId].subprotocols = NULL;
433 ndpi_str->proto_defaults[protoId].subprotocol_count = 0;
434
435 for(j = 0; j < MAX_DEFAULT_PORTS; j++) {
436 if(udpDefPorts[j].port_low != 0)
437 addDefaultPort(ndpi_str, &udpDefPorts[j], &ndpi_str->proto_defaults[protoId], 0, &ndpi_str->udpRoot,
438 __FUNCTION__, __LINE__);
439
440 if(tcpDefPorts[j].port_low != 0)
441 addDefaultPort(ndpi_str, &tcpDefPorts[j], &ndpi_str->proto_defaults[protoId], 0, &ndpi_str->tcpRoot,
442 __FUNCTION__, __LINE__);
443
444 /* No port range, just the lower port */
445 ndpi_str->proto_defaults[protoId].tcp_default_ports[j] = tcpDefPorts[j].port_low;
446 ndpi_str->proto_defaults[protoId].udp_default_ports[j] = udpDefPorts[j].port_low;
447 }
448 }
449
450 /* ******************************************************************** */
451
ndpi_default_ports_tree_node_t_cmp(const void * a,const void * b)452 static int ndpi_default_ports_tree_node_t_cmp(const void *a, const void *b) {
453 ndpi_default_ports_tree_node_t *fa = (ndpi_default_ports_tree_node_t *) a;
454 ndpi_default_ports_tree_node_t *fb = (ndpi_default_ports_tree_node_t *) b;
455
456 //printf("[NDPI] %s(%d, %d)\n", __FUNCTION__, fa->default_port, fb->default_port);
457
458 return((fa->default_port == fb->default_port) ? 0 : ((fa->default_port < fb->default_port) ? -1 : 1));
459 }
460
461 /* ******************************************************************** */
462
ndpi_default_ports_tree_node_t_walker(const void * node,const ndpi_VISIT which,const int depth)463 void ndpi_default_ports_tree_node_t_walker(const void *node, const ndpi_VISIT which, const int depth) {
464 ndpi_default_ports_tree_node_t *f = *(ndpi_default_ports_tree_node_t **) node;
465
466 printf("<%d>Walk on node %s (%u)\n", depth,
467 which == ndpi_preorder ?
468 "ndpi_preorder" :
469 which == ndpi_postorder ?
470 "ndpi_postorder" :
471 which == ndpi_endorder ? "ndpi_endorder" : which == ndpi_leaf ? "ndpi_leaf" : "unknown",
472 f->default_port);
473 }
474
475 /* ******************************************************************** */
476
addDefaultPort(struct ndpi_detection_module_struct * ndpi_str,ndpi_port_range * range,ndpi_proto_defaults_t * def,u_int8_t customUserProto,ndpi_default_ports_tree_node_t ** root,const char * _func,int _line)477 static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_str, ndpi_port_range *range,
478 ndpi_proto_defaults_t *def, u_int8_t customUserProto, ndpi_default_ports_tree_node_t **root,
479 const char *_func, int _line) {
480 u_int16_t port;
481
482 for(port = range->port_low; port <= range->port_high; port++) {
483 ndpi_default_ports_tree_node_t *node =
484 (ndpi_default_ports_tree_node_t *) ndpi_malloc(sizeof(ndpi_default_ports_tree_node_t));
485 ndpi_default_ports_tree_node_t *ret;
486
487 if(!node) {
488 NDPI_LOG_ERR(ndpi_str, "%s:%d not enough memory\n", _func, _line);
489 break;
490 }
491
492 node->proto = def, node->default_port = port, node->customUserProto = customUserProto;
493 ret = (ndpi_default_ports_tree_node_t *) ndpi_tsearch(node, (void *) root, ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
494
495 if(ret != node) {
496 NDPI_LOG_DBG(ndpi_str, "[NDPI] %s:%d found duplicate for port %u: overwriting it with new value\n", _func,
497 _line, port);
498
499 ret->proto = def;
500 ndpi_free(node);
501 }
502 }
503 }
504
505 /* ****************************************************** */
506
507 /*
508 NOTE
509
510 This function must be called with a semaphore set, this in order to avoid
511 changing the datastructures while using them
512 */
removeDefaultPort(ndpi_port_range * range,ndpi_proto_defaults_t * def,ndpi_default_ports_tree_node_t ** root)513 static int removeDefaultPort(ndpi_port_range *range, ndpi_proto_defaults_t *def, ndpi_default_ports_tree_node_t **root) {
514 ndpi_default_ports_tree_node_t node;
515 u_int16_t port;
516
517 for(port = range->port_low; port <= range->port_high; port++) {
518 ndpi_default_ports_tree_node_t *ret;
519
520 node.proto = def, node.default_port = port;
521 ret = (ndpi_default_ports_tree_node_t *) ndpi_tdelete(
522 &node, (void *) root, ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
523
524 if(ret != NULL) {
525 ndpi_free((ndpi_default_ports_tree_node_t *) ret);
526 return(0);
527 }
528 }
529
530 return(-1);
531 }
532
533 /* ****************************************************** */
534
535 /*
536 This is a function used to see if we need to
537 add a trailer $ in case the string is complete
538 or is a string that can be matched in the
539 middle of a domain name
540
541 Example:
542 microsoft.com -> microsoft.com$
543 apple. -> apple.
544 */
ndpi_is_middle_string_char(char c)545 static u_int8_t ndpi_is_middle_string_char(char c) {
546 switch(c) {
547 case '.':
548 case '-':
549 return(1);
550 break;
551
552 default:
553 return(0);
554 }
555 }
556
557 /*******************************************************/
558
559 static const u_int8_t ndpi_domain_level_automat[4][4]= {
560 /* symbol,'.','-',inc */
561 { 2,1,2,0 }, // start state
562 { 2,0,0,0 }, // first char is '.'; disable .. or .-
563 { 2,3,2,0 }, // part of domain name
564 { 2,0,0,1 } // next level domain name; disable .. or .-
565 };
566
567 /*
568 * domain level
569 * a. = 1
570 * .a. = 1
571 * a.b = 2
572 */
573
ndpi_domain_level(const char * name)574 static u_int8_t ndpi_domain_level(const char *name) {
575 u_int8_t level = 1, state = 0;
576 char c;
577 while((c = *name++) != '\0') {
578 c = c == '-' ? 2 : (c == '.' ? 1:0);
579 level += ndpi_domain_level_automat[state][3];
580 state = ndpi_domain_level_automat[state][(uint8_t)c];
581 if(!state) break;
582 }
583 return state >= 2 ? level:0;
584 }
585
586 /* ****************************************************** */
587
ndpi_string_to_automa(struct ndpi_detection_module_struct * ndpi_str,AC_AUTOMATA_t * ac_automa,const char * value,u_int16_t protocol_id,ndpi_protocol_category_t category,ndpi_protocol_breed_t breed,uint8_t level,u_int8_t add_ends_with)588 static int ndpi_string_to_automa(struct ndpi_detection_module_struct *ndpi_str,
589 AC_AUTOMATA_t *ac_automa, const char *value,
590 u_int16_t protocol_id, ndpi_protocol_category_t category,
591 ndpi_protocol_breed_t breed, uint8_t level,
592 u_int8_t add_ends_with) {
593 AC_PATTERN_t ac_pattern;
594 AC_ERROR_t rc;
595 u_int len;
596 char *value_dup = NULL;
597
598 if(!ndpi_is_valid_protoId(protocol_id)) {
599 NDPI_LOG_ERR(ndpi_str, "[NDPI] protoId=%d: INTERNAL ERROR\n", protocol_id);
600 return(-1);
601 }
602
603 if((ac_automa == NULL) || (value == NULL) || !*value)
604 return(-2);
605
606 value_dup = ndpi_strdup(value);
607 if(!value_dup)
608 return(-1);
609
610 memset(&ac_pattern, 0, sizeof(ac_pattern));
611
612 len = strlen(value);
613
614 ac_pattern.astring = value_dup;
615 ac_pattern.length = len;
616 ac_pattern.rep.number = protocol_id;
617 ac_pattern.rep.category = (u_int16_t) category;
618 ac_pattern.rep.breed = (u_int16_t) breed;
619 ac_pattern.rep.level = level ? level : ndpi_domain_level(value);
620 ac_pattern.rep.at_end = add_ends_with && !ndpi_is_middle_string_char(value[len-1]); /* len != 0 */
621 ac_pattern.rep.dot = memchr(value,'.',len) != NULL;
622
623 #ifdef MATCH_DEBUG
624 printf("Adding to %s %lx [%s%s][protocol_id: %u][category: %u][breed: %u][level: %u]\n",
625 ac_automa->name,(unsigned long int)ac_automa,
626 ac_pattern.astring,ac_pattern.rep.at_end? "$":"", protocol_id, category, breed,ac_pattern.rep.level);
627 #endif
628
629 rc = ac_automata_add(ac_automa, &ac_pattern);
630
631 if(rc != ACERR_SUCCESS) {
632 ndpi_free(value_dup);
633
634 if(rc != ACERR_DUPLICATE_PATTERN)
635 return (-2);
636 }
637
638 return(0);
639 }
640
641 /* ****************************************************** */
642
ndpi_add_host_url_subprotocol(struct ndpi_detection_module_struct * ndpi_str,char * value,int protocol_id,ndpi_protocol_category_t category,ndpi_protocol_breed_t breed,uint8_t level)643 static int ndpi_add_host_url_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
644 char *value, int protocol_id,
645 ndpi_protocol_category_t category,
646 ndpi_protocol_breed_t breed, uint8_t level) {
647 #ifndef DEBUG
648 NDPI_LOG_DBG2(ndpi_str, "[NDPI] Adding [%s][%d]\n", value, protocol_id);
649 #endif
650
651 return ndpi_string_to_automa(ndpi_str, (AC_AUTOMATA_t *)ndpi_str->host_automa.ac_automa,
652 value, protocol_id, category, breed, level, 1);
653
654 }
655
656 /* ****************************************************** */
657
658 /*
659 NOTE
660
661 This function must be called with a semaphore set, this in order to avoid
662 changing the datastructures while using them
663 */
ndpi_remove_host_url_subprotocol(struct ndpi_detection_module_struct * ndpi_str,char * value,int protocol_id)664 static int ndpi_remove_host_url_subprotocol(struct ndpi_detection_module_struct *ndpi_str, char *value, int protocol_id) {
665 NDPI_LOG_ERR(ndpi_str, "[NDPI] Missing implementation for proto %s/%d\n", value, protocol_id);
666 return(-1);
667 }
668
669 /* ******************************************************************** */
670
ndpi_init_protocol_match(struct ndpi_detection_module_struct * ndpi_str,ndpi_protocol_match * match)671 void ndpi_init_protocol_match(struct ndpi_detection_module_struct *ndpi_str,
672 ndpi_protocol_match *match) {
673 ndpi_port_range ports_a[MAX_DEFAULT_PORTS], ports_b[MAX_DEFAULT_PORTS];
674
675 if(ndpi_str->proto_defaults[match->protocol_id].protoName == NULL) {
676 ndpi_str->proto_defaults[match->protocol_id].protoName = ndpi_strdup(match->proto_name);
677
678 ndpi_str->proto_defaults[match->protocol_id].protoId = match->protocol_id;
679 ndpi_str->proto_defaults[match->protocol_id].protoCategory = match->protocol_category;
680 ndpi_str->proto_defaults[match->protocol_id].protoBreed = match->protocol_breed;
681
682 ndpi_set_proto_defaults(ndpi_str,
683 ndpi_str->proto_defaults[match->protocol_id].isClearTextProto,
684 ndpi_str->proto_defaults[match->protocol_id].protoBreed,
685 ndpi_str->proto_defaults[match->protocol_id].protoId,
686 ndpi_str->proto_defaults[match->protocol_id].protoName,
687 ndpi_str->proto_defaults[match->protocol_id].protoCategory,
688 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
689 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
690 }
691
692 ndpi_add_host_url_subprotocol(ndpi_str, match->string_to_match,
693 match->protocol_id, match->protocol_category,
694 match->protocol_breed, match->level);
695 }
696
697 /* ******************************************************************** */
698
699 /* Self check function to be called only for testing purposes */
ndpi_self_check_host_match()700 void ndpi_self_check_host_match() {
701 u_int32_t i, j;
702
703 for(i = 0; host_match[i].string_to_match != NULL; i++) {
704 for(j = 0; host_match[j].string_to_match != NULL; j++) {
705 if((i != j) && (strcmp(host_match[i].string_to_match, host_match[j].string_to_match) == 0)) {
706 printf("[INTERNAL ERROR]: Duplicate string detected '%s' [id: %u, id %u]\n",
707 host_match[i].string_to_match, i, j);
708 printf("\nPlease fix host_match[] in ndpi_content_match.c.inc\n");
709 exit(0);
710 }
711 }
712 }
713 }
714
715 /* ******************************************************************** */
716
717 #define XGRAMS_C 26
718 static int ndpi_xgrams_inited = 0;
719 static unsigned int bigrams_bitmap[(XGRAMS_C*XGRAMS_C+31)/32];
720 static unsigned int imposible_bigrams_bitmap[(XGRAMS_C*XGRAMS_C+31)/32];
721 static unsigned int trigrams_bitmap[(XGRAMS_C*XGRAMS_C*XGRAMS_C+31)/32];
722
723
ndpi_xgrams_init(unsigned int * dst,size_t dn,const char ** src,size_t sn,int l)724 static void ndpi_xgrams_init(unsigned int *dst,size_t dn, const char **src,size_t sn,int l) {
725 unsigned int i,j,c;
726 for(i=0;i < sn && src[i]; i++) {
727 for(j=0,c=0; j < l; j++) {
728 unsigned char a = (unsigned char)src[i][j];
729 if(a < 'a' || a > 'z') { printf("%u: c%u %c\n",i,j,a); abort(); }
730 c *= XGRAMS_C;
731 c += a - 'a';
732 }
733 if(src[i][l]) { printf("%u: c[%d] != 0\n",i,l); abort(); }
734 if((c >> 3) >= dn) abort();
735 dst[c >> 5] |= 1u << (c & 0x1f);
736 }
737 }
738
init_string_based_protocols(struct ndpi_detection_module_struct * ndpi_str)739 static void init_string_based_protocols(struct ndpi_detection_module_struct *ndpi_str) {
740 int i;
741
742 for(i = 0; host_match[i].string_to_match != NULL; i++)
743 ndpi_init_protocol_match(ndpi_str, &host_match[i]);
744
745 /* ************************ */
746
747 for(i = 0; tls_certificate_match[i].string_to_match != NULL; i++) {
748
749 #if 0
750 printf("%s() %s / %u\n", __FUNCTION__,
751 tls_certificate_match[i].string_to_match,
752 tls_certificate_match[i].protocol_id);
753 #endif
754
755 /* Note: string_to_match is not malloc'ed here as ac_automata_release is
756 * called with free_pattern = 0 */
757 ndpi_add_string_value_to_automa(ndpi_str->tls_cert_subject_automa.ac_automa,
758 tls_certificate_match[i].string_to_match,
759 tls_certificate_match[i].protocol_id);
760 }
761
762 /* ************************ */
763
764 ndpi_enable_loaded_categories(ndpi_str);
765
766 #ifdef MATCH_DEBUG
767 // ac_automata_display(ndpi_str->host_automa.ac_automa, 'n');
768 #endif
769 if(!ndpi_xgrams_inited) {
770 ndpi_xgrams_inited = 1;
771 ndpi_xgrams_init(bigrams_bitmap,sizeof(bigrams_bitmap),
772 ndpi_en_bigrams,sizeof(ndpi_en_bigrams)/sizeof(ndpi_en_bigrams[0]), 2);
773
774 ndpi_xgrams_init(imposible_bigrams_bitmap,sizeof(imposible_bigrams_bitmap),
775 ndpi_en_impossible_bigrams,sizeof(ndpi_en_impossible_bigrams)/sizeof(ndpi_en_impossible_bigrams[0]), 2);
776 ndpi_xgrams_init(trigrams_bitmap,sizeof(trigrams_bitmap),
777 ndpi_en_trigrams,sizeof(ndpi_en_trigrams)/sizeof(ndpi_en_trigrams[0]), 3);
778 }
779 }
780
781 /* ******************************************************************** */
782
ndpi_set_detection_preferences(struct ndpi_detection_module_struct * ndpi_str,ndpi_detection_preference pref,int value)783 int ndpi_set_detection_preferences(struct ndpi_detection_module_struct *ndpi_str, ndpi_detection_preference pref,
784 int value) {
785 switch(pref) {
786 case ndpi_pref_direction_detect_disable:
787 ndpi_str->direction_detect_disable = (u_int8_t) value;
788 break;
789
790 case ndpi_pref_enable_tls_block_dissection:
791 /*
792 If this option is enabled only the TLS Application data blocks past the
793 certificate negotiation are considered
794 */
795 ndpi_str->num_tls_blocks_to_follow = NDPI_MAX_NUM_TLS_APPL_BLOCKS;
796 ndpi_str->skip_tls_blocks_until_change_cipher = 1;
797 break;
798
799 default:
800 return(-1);
801 }
802
803 return(0);
804 }
805
806 /* ******************************************************************** */
807
ndpi_validate_protocol_initialization(struct ndpi_detection_module_struct * ndpi_str)808 static void ndpi_validate_protocol_initialization(struct ndpi_detection_module_struct *ndpi_str) {
809 u_int i, val;
810
811 for(i = 0; i < (int) ndpi_str->ndpi_num_supported_protocols; i++) {
812 if(ndpi_str->proto_defaults[i].protoName == NULL) {
813 NDPI_LOG_ERR(ndpi_str,
814 "[NDPI] INTERNAL ERROR missing protoName initialization for [protoId=%d]: recovering\n", i);
815 } else {
816 if((i != NDPI_PROTOCOL_UNKNOWN) &&
817 (ndpi_str->proto_defaults[i].protoCategory == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)) {
818 NDPI_LOG_ERR(ndpi_str,
819 "[NDPI] INTERNAL ERROR missing category [protoId=%d/%s] initialization: recovering\n", i,
820 ndpi_str->proto_defaults[i].protoName ? ndpi_str->proto_defaults[i].protoName : "???");
821 }
822 }
823 }
824
825 /* Sanity check for risks initialization */
826 val = (sizeof(ndpi_known_risks) / sizeof(ndpi_risk_info)) - 1;
827 if(val != NDPI_MAX_RISK) {
828 NDPI_LOG_ERR(ndpi_str, "[NDPI] INTERNAL ERROR Invalid ndpi_known_risks[] initialization [%u != %u]\n", val, NDPI_MAX_RISK);
829 exit(0);
830 }
831 }
832
833 /* ******************************************************************** */
834
835 /* This function is used to map protocol name and default ports and it MUST
836 be updated whenever a new protocol is added to NDPI.
837
838 Do NOT add web services (NDPI_SERVICE_xxx) here.
839 */
ndpi_init_protocol_defaults(struct ndpi_detection_module_struct * ndpi_str)840 static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndpi_str) {
841 ndpi_port_range ports_a[MAX_DEFAULT_PORTS], ports_b[MAX_DEFAULT_PORTS];
842
843 /* Reset all settings */
844 memset(ndpi_str->proto_defaults, 0, sizeof(ndpi_str->proto_defaults));
845
846 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNRATED, NDPI_PROTOCOL_UNKNOWN,
847 "Unknown", NDPI_PROTOCOL_CATEGORY_UNSPECIFIED,
848 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
849 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
850 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_FTP_CONTROL,
851 "FTP_CONTROL", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
852 ndpi_build_default_ports(ports_a, 21, 0, 0, 0, 0) /* TCP */,
853 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
854 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_FTP_DATA,
855 "FTP_DATA", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
856 ndpi_build_default_ports(ports_a, 20, 0, 0, 0, 0) /* TCP */,
857 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
858 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_MAIL_POP,
859 "POP3", NDPI_PROTOCOL_CATEGORY_MAIL,
860 ndpi_build_default_ports(ports_a, 110, 0, 0, 0, 0) /* TCP */,
861 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
862 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_MAIL_POPS,
863 "POPS", NDPI_PROTOCOL_CATEGORY_MAIL,
864 ndpi_build_default_ports(ports_a, 995, 0, 0, 0, 0) /* TCP */,
865 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
866 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MAIL_SMTP,
867 "SMTP", NDPI_PROTOCOL_CATEGORY_MAIL,
868 ndpi_build_default_ports(ports_a, 25, 0, 0, 0, 0) /* TCP */,
869 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
870 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_MAIL_SMTPS,
871 "SMTPS", NDPI_PROTOCOL_CATEGORY_MAIL,
872 ndpi_build_default_ports(ports_a, 465, 587, 0, 0, 0) /* TCP */,
873 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
874 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_MAIL_IMAP,
875 "IMAP", NDPI_PROTOCOL_CATEGORY_MAIL,
876 ndpi_build_default_ports(ports_a, 143, 0, 0, 0, 0) /* TCP */,
877 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
878 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_MAIL_IMAPS,
879 "IMAPS", NDPI_PROTOCOL_CATEGORY_MAIL,
880 ndpi_build_default_ports(ports_a, 993, 0, 0, 0, 0) /* TCP */,
881 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
882 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DNS,
883 "DNS", NDPI_PROTOCOL_CATEGORY_NETWORK,
884 ndpi_build_default_ports(ports_a, 53, 0, 0, 0, 0) /* TCP */,
885 ndpi_build_default_ports(ports_b, 53, 0, 0, 0, 0) /* UDP */);
886 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_DNS,
887 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
888 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_DNS can have (content-matched) subprotocols */
889 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IPP,
890 "IPP", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
891 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
892 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
893 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IMO,
894 "IMO", NDPI_PROTOCOL_CATEGORY_VOIP,
895 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
896 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
897 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP,
898 "HTTP", NDPI_PROTOCOL_CATEGORY_WEB,
899 ndpi_build_default_ports(ports_a, 80, 0 /* ntop */, 0, 0, 0) /* TCP */,
900 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
901 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_HTTP,
902 NDPI_PROTOCOL_AIMINI, NDPI_PROTOCOL_CROSSFIRE,
903 NDPI_PROTOCOL_BITTORRENT, NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, NDPI_PROTOCOL_GNUTELLA,
904 NDPI_PROTOCOL_MAPLESTORY, NDPI_PROTOCOL_ZATTOO, NDPI_PROTOCOL_WORLDOFWARCRAFT,
905 NDPI_PROTOCOL_THUNDER, NDPI_PROTOCOL_IRC,
906 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
907 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_HTTP can have (content-matched) subprotocols */
908 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MDNS,
909 "MDNS", NDPI_PROTOCOL_CATEGORY_NETWORK,
910 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
911 ndpi_build_default_ports(ports_b, 5353, 5354, 0, 0, 0) /* UDP */);
912 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_MDNS,
913 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
914 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_MDNS can have (content-matched) subprotocols */
915 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NTP,
916 "NTP", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
917 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
918 ndpi_build_default_ports(ports_b, 123, 0, 0, 0, 0) /* UDP */);
919 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NETBIOS,
920 "NetBIOS", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
921 ndpi_build_default_ports(ports_a, 139, 0, 0, 0, 0) /* TCP */,
922 ndpi_build_default_ports(ports_b, 137, 138, 139, 0, 0) /* UDP */);
923 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NFS,
924 "NFS", NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER,
925 ndpi_build_default_ports(ports_a, 2049, 0, 0, 0, 0) /* TCP */,
926 ndpi_build_default_ports(ports_b, 2049, 0, 0, 0, 0) /* UDP */);
927 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SSDP,
928 "SSDP", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
929 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
930 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
931 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_BGP,
932 "BGP", NDPI_PROTOCOL_CATEGORY_NETWORK,
933 ndpi_build_default_ports(ports_a, 179, 2605, 0, 0, 0) /* TCP */,
934 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
935 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SNMP,
936 "SNMP", NDPI_PROTOCOL_CATEGORY_NETWORK,
937 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
938 ndpi_build_default_ports(ports_b, 161, 162, 0, 0, 0) /* UDP */);
939 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_XDMCP,
940 "XDMCP", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
941 ndpi_build_default_ports(ports_a, 177, 0, 0, 0, 0) /* TCP */,
942 ndpi_build_default_ports(ports_b, 177, 0, 0, 0, 0) /* UDP */);
943 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_DANGEROUS, NDPI_PROTOCOL_SMBV1,
944 "SMBv1", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
945 ndpi_build_default_ports(ports_a, 445, 0, 0, 0, 0) /* TCP */,
946 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
947 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SYSLOG,
948 "Syslog", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
949 ndpi_build_default_ports(ports_a, 514, 0, 0, 0, 0) /* TCP */,
950 ndpi_build_default_ports(ports_b, 514, 0, 0, 0, 0) /* UDP */);
951 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DHCP,
952 "DHCP", NDPI_PROTOCOL_CATEGORY_NETWORK,
953 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
954 ndpi_build_default_ports(ports_b, 67, 68, 0, 0, 0) /* UDP */);
955 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_POSTGRES,
956 "PostgreSQL", NDPI_PROTOCOL_CATEGORY_DATABASE,
957 ndpi_build_default_ports(ports_a, 5432, 0, 0, 0, 0) /* TCP */,
958 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
959 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MYSQL,
960 "MySQL", NDPI_PROTOCOL_CATEGORY_DATABASE,
961 ndpi_build_default_ports(ports_a, 3306, 0, 0, 0, 0) /* TCP */,
962 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
963 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK,
964 "Direct_Download_Link", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
965 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
966 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
967 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_APPLEJUICE,
968 "AppleJuice", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
969 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
970 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
971 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_DIRECTCONNECT,
972 "DirectConnect", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
973 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
974 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
975 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NATS,
976 "Nats", NDPI_PROTOCOL_CATEGORY_RPC,
977 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
978 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
979 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_AMONG_US,
980 "AmongUs", NDPI_PROTOCOL_CATEGORY_GAME,
981 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
982 ndpi_build_default_ports(ports_b, 22023, 0, 0, 0, 0) /* UDP */);
983 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_NTOP,
984 "ntop", NDPI_PROTOCOL_CATEGORY_NETWORK,
985 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
986 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
987 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_VMWARE,
988 "VMware", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
989 ndpi_build_default_ports(ports_a, 903, 0, 0, 0, 0) /* TCP */,
990 ndpi_build_default_ports(ports_b, 902, 903, 0, 0, 0) /* UDP */);
991 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_KONTIKI,
992 "Kontiki", NDPI_PROTOCOL_CATEGORY_MEDIA,
993 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
994 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
995 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_OPENFT,
996 "OpenFT", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
997 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
998 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
999 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_FASTTRACK,
1000 "FastTrack", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1001 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1002 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1003 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_GNUTELLA,
1004 "Gnutella", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1005 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1006 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1007 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_EDONKEY,
1008 "eDonkey", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1009 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1010 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1011 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_BITTORRENT,
1012 "BitTorrent", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1013 ndpi_build_default_ports(ports_a, 51413, 53646, 0, 0, 0) /* TCP */,
1014 ndpi_build_default_ports(ports_b, 6771, 51413, 0, 0, 0) /* UDP */);
1015 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKYPE_TEAMS,
1016 "Skype_Teams", NDPI_PROTOCOL_CATEGORY_VOIP,
1017 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1018 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1019 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKYPE_CALL,
1020 "SkypeCall", NDPI_PROTOCOL_CATEGORY_VOIP,
1021 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1022 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1023 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_TIKTOK,
1024 "TikTok", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK,
1025 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1026 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1027 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TEREDO,
1028 "Teredo", NDPI_PROTOCOL_CATEGORY_NETWORK,
1029 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1030 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1031 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WECHAT,
1032 "WeChat", NDPI_PROTOCOL_CATEGORY_CHAT,
1033 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1034 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1035 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MEMCACHED,
1036 "Memcached", NDPI_PROTOCOL_CATEGORY_NETWORK,
1037 ndpi_build_default_ports(ports_a, 11211, 0, 0, 0, 0) /* TCP */,
1038 ndpi_build_default_ports(ports_b, 11211, 0, 0, 0, 0) /* UDP */);
1039 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SMBV23,
1040 "SMBv23", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
1041 ndpi_build_default_ports(ports_a, 445, 0, 0, 0, 0) /* TCP */,
1042 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1043 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_MINING,
1044 "Mining", CUSTOM_CATEGORY_MINING,
1045 ndpi_build_default_ports(ports_a, 8333, 30303, 0, 0, 0) /* TCP */,
1046 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1047 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NEST_LOG_SINK,
1048 "NestLogSink", NDPI_PROTOCOL_CATEGORY_CLOUD,
1049 ndpi_build_default_ports(ports_a, 11095, 0, 0, 0, 0) /* TCP */,
1050 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1051 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MODBUS,
1052 "Modbus", NDPI_PROTOCOL_CATEGORY_IOT_SCADA,
1053 ndpi_build_default_ports(ports_a, 502, 0, 0, 0, 0) /* TCP */,
1054 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1055 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_CALL,
1056 "WhatsAppCall", NDPI_PROTOCOL_CATEGORY_VOIP,
1057 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1058 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1059 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DATASAVER,
1060 "DataSaver", NDPI_PROTOCOL_CATEGORY_WEB /* dummy */,
1061 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1062 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1063 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SIGNAL,
1064 "Signal", NDPI_PROTOCOL_CATEGORY_CHAT,
1065 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1066 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1067 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DOH_DOT,
1068 "DoH_DoT", NDPI_PROTOCOL_CATEGORY_NETWORK /* dummy */,
1069 ndpi_build_default_ports(ports_a, 853, 0, 0, 0, 0) /* TCP */,
1070 ndpi_build_default_ports(ports_b, 784, 0, 0, 0, 0) /* UDP */);
1071 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_REDDIT,
1072 "Reddit", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK,
1073 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1074 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1075 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WIREGUARD,
1076 "WireGuard", NDPI_PROTOCOL_CATEGORY_VPN,
1077 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1078 ndpi_build_default_ports(ports_b, 51820, 0, 0, 0, 0) /* UDP */);
1079 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_PPSTREAM,
1080 "PPStream", NDPI_PROTOCOL_CATEGORY_STREAMING,
1081 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1082 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1083 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_XBOX,
1084 "Xbox", NDPI_PROTOCOL_CATEGORY_GAME,
1085 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1086 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1087 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_PLAYSTATION,
1088 "Playstation", NDPI_PROTOCOL_CATEGORY_GAME,
1089 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1090 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1091 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_QQ,
1092 "QQ", NDPI_PROTOCOL_CATEGORY_CHAT,
1093 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1094 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1095 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_RTSP,
1096 "RTSP", NDPI_PROTOCOL_CATEGORY_MEDIA,
1097 ndpi_build_default_ports(ports_a, 554, 0, 0, 0, 0) /* TCP */,
1098 ndpi_build_default_ports(ports_b, 554, 0, 0, 0, 0) /* UDP */);
1099 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_ICECAST,
1100 "IceCast", NDPI_PROTOCOL_CATEGORY_MEDIA,
1101 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1102 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1103 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_CPHA,
1104 "CPHA", NDPI_PROTOCOL_CATEGORY_NETWORK,
1105 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1106 ndpi_build_default_ports(ports_b, 8116, 0, 0, 0, 0) /* UDP */);
1107 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_ZATTOO,
1108 "Zattoo", NDPI_PROTOCOL_CATEGORY_VIDEO,
1109 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1110 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1111 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SHOUTCAST,
1112 "ShoutCast", NDPI_PROTOCOL_CATEGORY_MUSIC,
1113 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1114 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1115 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SOPCAST,
1116 "Sopcast", NDPI_PROTOCOL_CATEGORY_VIDEO,
1117 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1118 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1119 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DISCORD,
1120 "Discord", NDPI_PROTOCOL_CATEGORY_COLLABORATIVE,
1121 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1122 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1123 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_TVUPLAYER,
1124 "TVUplayer", NDPI_PROTOCOL_CATEGORY_VIDEO,
1125 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1126 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1127 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_QQLIVE,
1128 "QQLive", NDPI_PROTOCOL_CATEGORY_VIDEO,
1129 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1130 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1131 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_THUNDER,
1132 "Thunder", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1133 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1134 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1135 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SOULSEEK,
1136 "Soulseek", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1137 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1138 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1139 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_PS_VUE,
1140 "PS_VUE", NDPI_PROTOCOL_CATEGORY_VIDEO,
1141 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1142 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1143 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_IRC,
1144 "IRC", NDPI_PROTOCOL_CATEGORY_CHAT,
1145 ndpi_build_default_ports(ports_a, 194, 0, 0, 0, 0) /* TCP */,
1146 ndpi_build_default_ports(ports_b, 194, 0, 0, 0, 0) /* UDP */);
1147 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AYIYA,
1148 "Ayiya", NDPI_PROTOCOL_CATEGORY_NETWORK,
1149 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1150 ndpi_build_default_ports(ports_b, 5072, 0, 0, 0, 0) /* UDP */);
1151 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_JABBER,
1152 "Jabber", NDPI_PROTOCOL_CATEGORY_WEB,
1153 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1154 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1155 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DISNEYPLUS,
1156 "DisneyPlus", NDPI_PROTOCOL_CATEGORY_STREAMING,
1157 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1158 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1159 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_VRRP,
1160 "VRRP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1161 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1162 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1163 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_STEAM,
1164 "Steam", NDPI_PROTOCOL_CATEGORY_GAME,
1165 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1166 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1167 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_HALFLIFE2,
1168 "HalfLife2", NDPI_PROTOCOL_CATEGORY_GAME,
1169 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1170 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1171 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WORLDOFWARCRAFT,
1172 "WorldOfWarcraft", NDPI_PROTOCOL_CATEGORY_GAME,
1173 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1174 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1175 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_HOTSPOT_SHIELD,
1176 "HotspotShield", NDPI_PROTOCOL_CATEGORY_VPN,
1177 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1178 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1179 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_TELNET,
1180 "Telnet", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
1181 ndpi_build_default_ports(ports_a, 23, 0, 0, 0, 0) /* TCP */,
1182 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1183 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_STUN,
1184 "STUN", NDPI_PROTOCOL_CATEGORY_NETWORK,
1185 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1186 ndpi_build_default_ports(ports_b, 3478, 0, 0, 0, 0) /* UDP */);
1187 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_IP_IPSEC,
1188 "IPsec", NDPI_PROTOCOL_CATEGORY_VPN,
1189 ndpi_build_default_ports(ports_a, 500, 0, 0, 0, 0) /* TCP */,
1190 ndpi_build_default_ports(ports_b, 500, 4500, 0, 0, 0) /* UDP */);
1191 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_GRE,
1192 "GRE", NDPI_PROTOCOL_CATEGORY_NETWORK,
1193 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1194 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1195 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_ICMP,
1196 "ICMP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1197 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1198 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1199 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_IGMP,
1200 "IGMP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1201 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1202 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1203 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_EGP,
1204 "EGP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1205 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1206 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1207 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_SCTP,
1208 "SCTP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1209 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1210 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1211 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_OSPF,
1212 "OSPF", NDPI_PROTOCOL_CATEGORY_NETWORK,
1213 ndpi_build_default_ports(ports_a, 2604, 0, 0, 0, 0) /* TCP */,
1214 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1215 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_IP_IN_IP,
1216 "IP_in_IP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1217 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1218 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1219 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RTP,
1220 "RTP", NDPI_PROTOCOL_CATEGORY_MEDIA,
1221 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1222 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1223 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RDP,
1224 "RDP", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
1225 ndpi_build_default_ports(ports_a, 3389, 0, 0, 0, 0) /* TCP */,
1226 ndpi_build_default_ports(ports_b, 3389, 0, 0, 0, 0) /* UDP */);
1227 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_VNC,
1228 "VNC", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
1229 ndpi_build_default_ports(ports_a, 5900, 5901, 5800, 0, 0) /* TCP */,
1230 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1231 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_TUMBLR,
1232 "Tumblr", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK,
1233 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1234 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1235 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ZOOM,
1236 "Zoom", NDPI_PROTOCOL_CATEGORY_VIDEO,
1237 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1238 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1239 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_FILES,
1240 "WhatsAppFiles", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1241 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1242 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1243 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP,
1244 "WhatsApp", NDPI_PROTOCOL_CATEGORY_CHAT,
1245 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1246 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1247 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_TLS,
1248 "TLS", NDPI_PROTOCOL_CATEGORY_WEB,
1249 ndpi_build_default_ports(ports_a, 443, 0, 0, 0, 0) /* TCP */,
1250 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1251 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_TLS,
1252 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
1253 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_TLS can have (content-matched) subprotocols */
1254 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_DTLS,
1255 "DTLS", NDPI_PROTOCOL_CATEGORY_WEB,
1256 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1257 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1258 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_DTLS,
1259 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
1260 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_DTLS can have (content-matched) subprotocols */
1261 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SSH,
1262 "SSH", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
1263 ndpi_build_default_ports(ports_a, 22, 0, 0, 0, 0) /* TCP */,
1264 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1265 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_USENET,
1266 "Usenet", NDPI_PROTOCOL_CATEGORY_WEB,
1267 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1268 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1269 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MGCP,
1270 "MGCP", NDPI_PROTOCOL_CATEGORY_VOIP,
1271 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1272 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1273 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IAX,
1274 "IAX", NDPI_PROTOCOL_CATEGORY_VOIP,
1275 ndpi_build_default_ports(ports_a, 4569, 0, 0, 0, 0) /* TCP */,
1276 ndpi_build_default_ports(ports_b, 4569, 0, 0, 0, 0) /* UDP */);
1277 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AFP,
1278 "AFP", NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER,
1279 ndpi_build_default_ports(ports_a, 548, 0, 0, 0, 0) /* TCP */,
1280 ndpi_build_default_ports(ports_b, 548, 0, 0, 0, 0) /* UDP */);
1281 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_HULU,
1282 "Hulu", NDPI_PROTOCOL_CATEGORY_STREAMING,
1283 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1284 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1285 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CHECKMK,
1286 "CHECKMK", NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER,
1287 ndpi_build_default_ports(ports_a, 6556, 0, 0, 0, 0) /* TCP */,
1288 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1289 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_STEALTHNET,
1290 "Stealthnet", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1291 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1292 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1293 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_AIMINI,
1294 "Aimini", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1295 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1296 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1297 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SIP,
1298 "SIP", NDPI_PROTOCOL_CATEGORY_VOIP,
1299 ndpi_build_default_ports(ports_a, 5060, 5061, 0, 0, 0) /* TCP */,
1300 ndpi_build_default_ports(ports_b, 5060, 5061, 0, 0, 0) /* UDP */);
1301 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TRUPHONE,
1302 "TruPhone", NDPI_PROTOCOL_CATEGORY_VOIP,
1303 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1304 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1305 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_ICMPV6,
1306 "ICMPV6", NDPI_PROTOCOL_CATEGORY_NETWORK,
1307 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1308 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1309 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DHCPV6,
1310 "DHCPV6", NDPI_PROTOCOL_CATEGORY_NETWORK,
1311 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1312 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1313 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_ARMAGETRON,
1314 "Armagetron", NDPI_PROTOCOL_CATEGORY_GAME,
1315 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1316 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1317 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_CROSSFIRE,
1318 "Crossfire", NDPI_PROTOCOL_CATEGORY_RPC,
1319 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1320 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1321 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DOFUS,
1322 "Dofus", NDPI_PROTOCOL_CATEGORY_GAME,
1323 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1324 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1325 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_FIESTA,
1326 "Fiesta", NDPI_PROTOCOL_CATEGORY_GAME,
1327 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1328 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1329 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_FLORENSIA,
1330 "Florensia", NDPI_PROTOCOL_CATEGORY_GAME,
1331 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1332 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1333 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_GUILDWARS,
1334 "Guildwars", NDPI_PROTOCOL_CATEGORY_GAME,
1335 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1336 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1337 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AMAZON_ALEXA,
1338 "AmazonAlexa", NDPI_PROTOCOL_CATEGORY_VIRTUAL_ASSISTANT,
1339 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1340 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1341 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_KERBEROS,
1342 "Kerberos", NDPI_PROTOCOL_CATEGORY_NETWORK,
1343 ndpi_build_default_ports(ports_a, 88, 0, 0, 0, 0) /* TCP */,
1344 ndpi_build_default_ports(ports_b, 88, 0, 0, 0, 0) /* UDP */);
1345 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_LDAP,
1346 "LDAP", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
1347 ndpi_build_default_ports(ports_a, 389, 0, 0, 0, 0) /* TCP */,
1348 ndpi_build_default_ports(ports_b, 389, 0, 0, 0, 0) /* UDP */);
1349 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_MAPLESTORY,
1350 "MapleStory", NDPI_PROTOCOL_CATEGORY_GAME,
1351 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1352 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1353 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MSSQL_TDS,
1354 "MsSQL-TDS", NDPI_PROTOCOL_CATEGORY_DATABASE,
1355 ndpi_build_default_ports(ports_a, 1433, 1434, 0, 0, 0) /* TCP */,
1356 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1357 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_PPTP,
1358 "PPTP", NDPI_PROTOCOL_CATEGORY_VPN,
1359 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1360 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1361 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WARCRAFT3,
1362 "Warcraft3", NDPI_PROTOCOL_CATEGORY_GAME,
1363 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1364 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1365 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WORLD_OF_KUNG_FU,
1366 "WorldOfKungFu", NDPI_PROTOCOL_CATEGORY_GAME,
1367 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1368 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1369 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DCERPC,
1370 "DCE_RPC", NDPI_PROTOCOL_CATEGORY_RPC,
1371 ndpi_build_default_ports(ports_a, 135, 0, 0, 0, 0) /* TCP */,
1372 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1373 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NETFLOW,
1374 "NetFlow", NDPI_PROTOCOL_CATEGORY_NETWORK,
1375 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1376 ndpi_build_default_ports(ports_b, 2055, 0, 0, 0, 0) /* UDP */);
1377 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SFLOW,
1378 "sFlow", NDPI_PROTOCOL_CATEGORY_NETWORK,
1379 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1380 ndpi_build_default_ports(ports_b, 6343, 0, 0, 0, 0) /* UDP */);
1381 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP_CONNECT,
1382 "HTTP_Connect", NDPI_PROTOCOL_CATEGORY_WEB,
1383 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1384 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1385 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_HTTP_CONNECT,
1386 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
1387 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_HTTP_CONNECT can have (content-matched) subprotocols */
1388 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP_PROXY,
1389 "HTTP_Proxy", NDPI_PROTOCOL_CATEGORY_WEB,
1390 ndpi_build_default_ports(ports_a, 8080, 3128, 0, 0, 0) /* TCP */,
1391 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1392 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_HTTP_PROXY,
1393 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
1394 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_HTTP_PROXY can have (content-matched) subprotocols */
1395 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CITRIX,
1396 "Citrix", NDPI_PROTOCOL_CATEGORY_NETWORK,
1397 ndpi_build_default_ports(ports_a, 1494, 2598, 0, 0, 0) /* TCP */,
1398 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1399 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WEBEX,
1400 "Webex", NDPI_PROTOCOL_CATEGORY_VOIP,
1401 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1402 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1403 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RADIUS,
1404 "Radius", NDPI_PROTOCOL_CATEGORY_NETWORK,
1405 ndpi_build_default_ports(ports_a, 1812, 1813, 0, 0, 0) /* TCP */,
1406 ndpi_build_default_ports(ports_b, 1812, 1813, 0, 0, 0) /* UDP */);
1407 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TEAMVIEWER,
1408 "TeamViewer", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
1409 ndpi_build_default_ports(ports_a, 5938, 0, 0, 0, 0) /* TCP */,
1410 ndpi_build_default_ports(ports_b, 5938, 0, 0, 0, 0) /* UDP */);
1411 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_LOTUS_NOTES,
1412 "LotusNotes", NDPI_PROTOCOL_CATEGORY_COLLABORATIVE,
1413 ndpi_build_default_ports(ports_a, 1352, 0, 0, 0, 0) /* TCP */,
1414 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1415 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SAP,
1416 "SAP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1417 ndpi_build_default_ports(ports_a, 3201, 0, 0, 0, 0) /* TCP */,
1418 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); /* Missing dissector: port based only */
1419 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_GTP,
1420 "GTP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1421 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1422 ndpi_build_default_ports(ports_b, 2152, 2123, 0, 0, 0) /* UDP */);
1423 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WSD,
1424 "WSD", NDPI_PROTOCOL_CATEGORY_NETWORK,
1425 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1426 ndpi_build_default_ports(ports_b, 3702, 0, 0, 0, 0) /* UDP */);
1427 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TELEGRAM,
1428 "Telegram", NDPI_PROTOCOL_CATEGORY_CHAT,
1429 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1430 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1431 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_QUIC,
1432 "QUIC", NDPI_PROTOCOL_CATEGORY_WEB,
1433 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1434 ndpi_build_default_ports(ports_b, 443, 80, 0, 0, 0) /* UDP */);
1435 ndpi_set_proto_subprotocols(ndpi_str, NDPI_PROTOCOL_QUIC,
1436 NDPI_PROTOCOL_MATCHED_BY_CONTENT,
1437 NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS); /* NDPI_PROTOCOL_QUIC can have (content-matched) subprotocols */
1438 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DIAMETER,
1439 "Diameter", NDPI_PROTOCOL_CATEGORY_NETWORK,
1440 ndpi_build_default_ports(ports_a, 3868, 0, 0, 0, 0) /* TCP */,
1441 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1442 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_APPLE_PUSH,
1443 "ApplePush", NDPI_PROTOCOL_CATEGORY_CLOUD,
1444 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1445 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1446 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DROPBOX,
1447 "Dropbox", NDPI_PROTOCOL_CATEGORY_CLOUD,
1448 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1449 ndpi_build_default_ports(ports_b, 17500, 0, 0, 0, 0) /* UDP */);
1450 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SPOTIFY,
1451 "Spotify", NDPI_PROTOCOL_CATEGORY_MUSIC,
1452 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1453 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1454 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MESSENGER,
1455 "Messenger", NDPI_PROTOCOL_CATEGORY_VOIP,
1456 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1457 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1458 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_LISP,
1459 "LISP", NDPI_PROTOCOL_CATEGORY_CLOUD,
1460 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1461 ndpi_build_default_ports(ports_b, 4342, 4341, 0, 0, 0) /* UDP */);
1462 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_EAQ,
1463 "EAQ", NDPI_PROTOCOL_CATEGORY_NETWORK,
1464 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1465 ndpi_build_default_ports(ports_b, 6000, 0, 0, 0, 0) /* UDP */);
1466 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_KAKAOTALK_VOICE,
1467 "KakaoTalk_Voice", NDPI_PROTOCOL_CATEGORY_VOIP,
1468 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1469 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1470 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_MPEGTS,
1471 "MPEG_TS", NDPI_PROTOCOL_CATEGORY_MEDIA,
1472 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1473 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1474 /* http://en.wikipedia.org/wiki/Link-local_Multicast_Name_Resolution */
1475 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_LLMNR,
1476 "LLMNR", NDPI_PROTOCOL_CATEGORY_NETWORK,
1477 ndpi_build_default_ports(ports_a, 5355, 0, 0, 0, 0) /* TCP */,
1478 ndpi_build_default_ports(ports_b, 5355, 0, 0, 0, 0) /* UDP */); /* Missing dissector: port based only */
1479 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_REMOTE_SCAN,
1480 "RemoteScan", NDPI_PROTOCOL_CATEGORY_NETWORK,
1481 ndpi_build_default_ports(ports_a, 6077, 0, 0, 0, 0) /* TCP */,
1482 ndpi_build_default_ports(ports_b, 6078, 0, 0, 0, 0) /* UDP */); /* Missing dissector: port based only */
1483 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_H323,
1484 "H323", NDPI_PROTOCOL_CATEGORY_VOIP,
1485 ndpi_build_default_ports(ports_a, 1719, 1720, 0, 0, 0) /* TCP */,
1486 ndpi_build_default_ports(ports_b, 1719, 1720, 0, 0, 0) /* UDP */);
1487 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_OPENVPN,
1488 "OpenVPN", NDPI_PROTOCOL_CATEGORY_VPN,
1489 ndpi_build_default_ports(ports_a, 1194, 0, 0, 0, 0) /* TCP */,
1490 ndpi_build_default_ports(ports_b, 1194, 0, 0, 0, 0) /* UDP */);
1491 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NOE,
1492 "NOE", NDPI_PROTOCOL_CATEGORY_VOIP,
1493 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1494 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1495 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CISCOVPN,
1496 "CiscoVPN", NDPI_PROTOCOL_CATEGORY_VPN,
1497 ndpi_build_default_ports(ports_a, 10000, 8008, 8009, 0, 0) /* TCP */,
1498 ndpi_build_default_ports(ports_b, 10000, 0, 0, 0, 0) /* UDP */);
1499 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TEAMSPEAK,
1500 "TeamSpeak", NDPI_PROTOCOL_CATEGORY_VOIP,
1501 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1502 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1503 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_TOR,
1504 "Tor", NDPI_PROTOCOL_CATEGORY_VPN,
1505 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1506 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1507 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKINNY,
1508 "CiscoSkinny", NDPI_PROTOCOL_CATEGORY_VOIP,
1509 ndpi_build_default_ports(ports_a, 2000, 0, 0, 0, 0) /* TCP */,
1510 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1511 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RTCP,
1512 "RTCP", NDPI_PROTOCOL_CATEGORY_VOIP,
1513 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1514 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1515 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RSYNC,
1516 "RSYNC", NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER,
1517 ndpi_build_default_ports(ports_a, 873, 0, 0, 0, 0) /* TCP */,
1518 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1519 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ORACLE,
1520 "Oracle", NDPI_PROTOCOL_CATEGORY_DATABASE,
1521 ndpi_build_default_ports(ports_a, 1521, 0, 0, 0, 0) /* TCP */,
1522 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1523 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CORBA,
1524 "Corba", NDPI_PROTOCOL_CATEGORY_RPC,
1525 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1526 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1527 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_UBUNTUONE,
1528 "UbuntuONE", NDPI_PROTOCOL_CATEGORY_CLOUD,
1529 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1530 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1531 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHOIS_DAS,
1532 "Whois-DAS", NDPI_PROTOCOL_CATEGORY_NETWORK,
1533 ndpi_build_default_ports(ports_a, 43, 4343, 0, 0, 0), /* TCP */
1534 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1535 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_COLLECTD,
1536 "Collectd", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
1537 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1538 ndpi_build_default_ports(ports_b, 25826, 0, 0, 0, 0)); /* UDP */
1539 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SOCKS,
1540 "SOCKS", NDPI_PROTOCOL_CATEGORY_WEB,
1541 ndpi_build_default_ports(ports_a, 1080, 0, 0, 0, 0), /* TCP */
1542 ndpi_build_default_ports(ports_b, 1080, 0, 0, 0, 0)); /* UDP */
1543 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TFTP,
1544 "TFTP", NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER,
1545 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1546 ndpi_build_default_ports(ports_b, 69, 0, 0, 0, 0)); /* UDP */
1547 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RTMP,
1548 "RTMP", NDPI_PROTOCOL_CATEGORY_MEDIA,
1549 ndpi_build_default_ports(ports_a, 1935, 0, 0, 0, 0), /* TCP */
1550 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1551 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_PINTEREST,
1552 "Pinterest", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK,
1553 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1554 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1555 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MEGACO,
1556 "Megaco", NDPI_PROTOCOL_CATEGORY_VOIP,
1557 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1558 ndpi_build_default_ports(ports_b, 2944, 0, 0, 0, 0)); /* UDP */
1559 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_REDIS,
1560 "Redis", NDPI_PROTOCOL_CATEGORY_DATABASE,
1561 ndpi_build_default_ports(ports_a, 6379, 0, 0, 0, 0), /* TCP */
1562 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1563 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ZMQ,
1564 "ZeroMQ", NDPI_PROTOCOL_CATEGORY_RPC,
1565 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1566 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1567 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_VHUA,
1568 "VHUA", NDPI_PROTOCOL_CATEGORY_VOIP,
1569 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1570 ndpi_build_default_ports(ports_b, 58267, 0, 0, 0, 0)); /* UDP */
1571 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_STARCRAFT,
1572 "Starcraft", NDPI_PROTOCOL_CATEGORY_GAME,
1573 ndpi_build_default_ports(ports_a, 1119, 0, 0, 0, 0), /* TCP */
1574 ndpi_build_default_ports(ports_b, 1119, 0, 0, 0, 0)); /* UDP */
1575 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_UBNTAC2,
1576 "UBNTAC2", NDPI_PROTOCOL_CATEGORY_NETWORK,
1577 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1578 ndpi_build_default_ports(ports_b, 10001, 0, 0, 0, 0)); /* UDP */
1579 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_VIBER,
1580 "Viber", NDPI_PROTOCOL_CATEGORY_VOIP,
1581 ndpi_build_default_ports(ports_a, 7985, 5242, 5243, 4244, 0), /* TCP */
1582 ndpi_build_default_ports(ports_b, 7985, 7987, 5242, 5243, 4244)); /* UDP */
1583 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_COAP,
1584 "COAP", NDPI_PROTOCOL_CATEGORY_RPC,
1585 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1586 ndpi_build_default_ports(ports_b, 5683, 5684, 0, 0, 0)); /* UDP */
1587 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MQTT,
1588 "MQTT", NDPI_PROTOCOL_CATEGORY_RPC,
1589 ndpi_build_default_ports(ports_a, 1883, 8883, 0, 0, 0), /* TCP */
1590 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1591 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SOMEIP,
1592 "SOMEIP", NDPI_PROTOCOL_CATEGORY_RPC,
1593 ndpi_build_default_ports(ports_a, 30491, 30501, 0, 0, 0), /* TCP */
1594 ndpi_build_default_ports(ports_b, 30491, 30501, 30490, 0, 0)); /* UDP */
1595 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RX,
1596 "RX", NDPI_PROTOCOL_CATEGORY_RPC,
1597 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1598 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1599 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_GIT,
1600 "Git", NDPI_PROTOCOL_CATEGORY_COLLABORATIVE,
1601 ndpi_build_default_ports(ports_a, 9418, 0, 0, 0, 0), /* TCP */
1602 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1603 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DRDA,
1604 "DRDA", NDPI_PROTOCOL_CATEGORY_DATABASE,
1605 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1606 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1607 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HANGOUT_DUO,
1608 "GoogleHangoutDuo", NDPI_PROTOCOL_CATEGORY_VOIP,
1609 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1610 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1611 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_BJNP,
1612 "BJNP", NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,
1613 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1614 ndpi_build_default_ports(ports_b, 8612, 0, 0, 0, 0) /* UDP */);
1615 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SMPP,
1616 "SMPP", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
1617 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1618 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1619 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_OOKLA,
1620 "Ookla", NDPI_PROTOCOL_CATEGORY_NETWORK,
1621 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1622 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1623 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AMQP,
1624 "AMQP", NDPI_PROTOCOL_CATEGORY_RPC,
1625 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1626 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1627 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_DNSCRYPT,
1628 "DNScrypt", NDPI_PROTOCOL_CATEGORY_NETWORK,
1629 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1630 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1631 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TINC,
1632 "TINC", NDPI_PROTOCOL_CATEGORY_VPN,
1633 ndpi_build_default_ports(ports_a, 655, 0, 0, 0, 0) /* TCP */,
1634 ndpi_build_default_ports(ports_b, 655, 0, 0, 0, 0) /* UDP */);
1635 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_FIX,
1636 "FIX", NDPI_PROTOCOL_CATEGORY_RPC,
1637 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1638 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1639 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_NINTENDO,
1640 "Nintendo", NDPI_PROTOCOL_CATEGORY_GAME,
1641 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1642 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1643 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_CSGO,
1644 "CSGO", NDPI_PROTOCOL_CATEGORY_GAME,
1645 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1646 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1647 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AJP,
1648 "AJP", NDPI_PROTOCOL_CATEGORY_WEB,
1649 ndpi_build_default_ports(ports_a, 8009, 8010, 0, 0, 0) /* TCP */,
1650 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1651 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TARGUS_GETDATA,
1652 "TargusDataspeed", NDPI_PROTOCOL_CATEGORY_NETWORK,
1653 ndpi_build_default_ports(ports_a, 5001, 5201, 0, 0, 0) /* TCP */,
1654 ndpi_build_default_ports(ports_b, 5001, 5201, 0, 0, 0) /* UDP */);
1655 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AMAZON_VIDEO,
1656 "AmazonVideo", NDPI_PROTOCOL_CATEGORY_CLOUD,
1657 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1658 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1659 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DNP3,
1660 "DNP3", NDPI_PROTOCOL_CATEGORY_IOT_SCADA,
1661 ndpi_build_default_ports(ports_a, 20000, 0, 0, 0, 0) /* TCP */,
1662 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1663 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IEC60870,
1664 "IEC60870", NDPI_PROTOCOL_CATEGORY_IOT_SCADA,
1665 ndpi_build_default_ports(ports_a, 2404, 0, 0, 0, 0) /* TCP */,
1666 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1667 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_BLOOMBERG,
1668 "Bloomberg", NDPI_PROTOCOL_CATEGORY_NETWORK,
1669 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1670 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1671 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CAPWAP,
1672 "CAPWAP", NDPI_PROTOCOL_CATEGORY_NETWORK,
1673 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1674 ndpi_build_default_ports(ports_b, 5246, 5247, 0, 0, 0) /* UDP */);
1675 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ZABBIX,
1676 "Zabbix", NDPI_PROTOCOL_CATEGORY_NETWORK,
1677 ndpi_build_default_ports(ports_a, 10050, 0, 0, 0, 0) /* TCP */,
1678 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1679 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_S7COMM,
1680 "s7comm", NDPI_PROTOCOL_CATEGORY_NETWORK,
1681 ndpi_build_default_ports(ports_a, 102, 0, 0, 0, 0) /* TCP */,
1682 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1683 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_MSTEAMS,
1684 "Teams", NDPI_PROTOCOL_CATEGORY_COLLABORATIVE,
1685 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1686 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1687 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WEBSOCKET,
1688 "WebSocket", NDPI_PROTOCOL_CATEGORY_WEB,
1689 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1690 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1691 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ANYDESK,
1692 "AnyDesk", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
1693 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1694 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1695 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SOAP,
1696 "SOAP", NDPI_PROTOCOL_CATEGORY_RPC,
1697 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1698 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1699 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MONGODB,
1700 "MongoDB", NDPI_PROTOCOL_CATEGORY_DATABASE,
1701 ndpi_build_default_ports(ports_a, 27017, 0, 0, 0, 0) /* TCP */,
1702 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1703 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_APPLE_SIRI,
1704 "AppleSiri", NDPI_PROTOCOL_CATEGORY_VIRTUAL_ASSISTANT,
1705 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1706 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1707 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SNAPCHAT_CALL,
1708 "SnapchatCall", NDPI_PROTOCOL_CATEGORY_VOIP,
1709 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1710 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1711 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HPVIRTGRP,
1712 "HP Virtual Machine Group Management", NDPI_PROTOCOL_CATEGORY_NETWORK,
1713 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1714 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1715 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_GENSHIN_IMPACT,
1716 "GenshinImpact", NDPI_PROTOCOL_CATEGORY_GAME,
1717 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1718 ndpi_build_default_ports(ports_b, 22102, 0, 0, 0, 0) /* UDP */);
1719 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_ACTIVISION,
1720 "Activision", NDPI_PROTOCOL_CATEGORY_GAME,
1721 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1722 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1723 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_FORTICLIENT,
1724 "FortiClient", NDPI_PROTOCOL_CATEGORY_VPN,
1725 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1726 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1727 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_Z3950,
1728 "Z39.50", NDPI_PROTOCOL_CATEGORY_NETWORK,
1729 ndpi_build_default_ports(ports_a, 210, 0, 0, 0, 0) /* TCP */,
1730 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1731 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_LIKEE,
1732 "Likee", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK,
1733 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1734 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1735 ndpi_set_proto_defaults(ndpi_str, 1 /* cleartext */, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_GITLAB,
1736 "GitLab", NDPI_PROTOCOL_CATEGORY_COLLABORATIVE,
1737 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
1738 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
1739 ndpi_set_proto_defaults(ndpi_str, 0 /* encrypted */, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_AVAST_SECUREDNS,
1740 "AVAST SecureDNS", NDPI_PROTOCOL_CATEGORY_NETWORK,
1741 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
1742 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */
1743
1744 #ifdef CUSTOM_NDPI_PROTOCOLS
1745 #include "../../../nDPI-custom/custom_ndpi_main.c"
1746 #endif
1747
1748 /* calling function for host and content matched protocols */
1749 init_string_based_protocols(ndpi_str);
1750
1751 ndpi_validate_protocol_initialization(ndpi_str);
1752 }
1753
1754 /* ****************************************************** */
1755
1756 #ifdef CUSTOM_NDPI_PROTOCOLS
1757 #include "../../../nDPI-custom/custom_ndpi_protocols.c"
1758 #endif
1759
1760 /* ****************************************************** */
1761
1762 #define MATCH_DEBUG_INFO(fmt, ...) if(txt->option & AC_FEATURE_DEBUG) printf(fmt, ##__VA_ARGS__)
1763
ac_domain_match_handler(AC_MATCH_t * m,AC_TEXT_t * txt,AC_REP_t * match)1764 static int ac_domain_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) {
1765 AC_PATTERN_t *pattern = m->patterns;
1766 int i,start,end = m->position;
1767
1768 for(i=0; i < m->match_num; i++,pattern++) {
1769 /*
1770 * See ac_automata_exact_match()
1771 * The bit is set if the pattern exactly matches AND
1772 * the length of the pattern is longer than that of the previous one.
1773 * Skip shorter (less precise) templates.
1774 */
1775 if(!(m->match_map & (1 << i)))
1776 continue;
1777 start = end - pattern->length;
1778
1779 MATCH_DEBUG_INFO("[NDPI] Searching: [to search: %.*s/%u][pattern: %s%.*s%s/%u l:%u] %d-%d\n",
1780 txt->length, txt->astring,(unsigned int) txt->length,
1781 m->patterns[0].rep.from_start ? "^":"",
1782 (unsigned int) pattern->length, pattern->astring,
1783 m->patterns[0].rep.at_end ? "$":"", (unsigned int) pattern->length,m->patterns[0].rep.level,
1784 start,end);
1785
1786 if(start == 0 && end == txt->length) {
1787 *match = pattern->rep; txt->match.last = pattern;
1788 MATCH_DEBUG_INFO("[NDPI] Searching: Found exact match. Proto %d \n",pattern->rep.number);
1789 return 1;
1790 }
1791 /* pattern is DOMAIN.NAME and string x.DOMAIN.NAME ? */
1792 if(start > 1 && !ndpi_is_middle_string_char(pattern->astring[0]) && pattern->rep.dot) {
1793 /*
1794 The patch below allows in case of pattern ws.amazon.com
1795 to avoid matching aws.amazon.com whereas a.ws.amazon.com
1796 has to match
1797 */
1798 if(ndpi_is_middle_string_char(txt->astring[start-1])) {
1799 if(!txt->match.last || txt->match.last->rep.level < pattern->rep.level) {
1800 txt->match.last = pattern; *match = pattern->rep;
1801 MATCH_DEBUG_INFO("[NDPI] Searching: Found domain match. Proto %d \n",pattern->rep.number);
1802 }
1803 }
1804 continue;
1805 }
1806
1807 if(!txt->match.last || txt->match.last->rep.level < pattern->rep.level) {
1808 txt->match.last = pattern; *match = pattern->rep;
1809 MATCH_DEBUG_INFO("[NDPI] Searching: matched. Proto %d \n",pattern->rep.number);
1810 }
1811 }
1812 return 0;
1813 }
1814
1815 /* ******************************************************************** */
1816
ndpi_patricia_get_maxbits(ndpi_patricia_tree_t * tree)1817 u_int16_t ndpi_patricia_get_maxbits(ndpi_patricia_tree_t *tree) {
1818 return(tree->maxbits);
1819 }
1820
1821 /* ******************************************************************** */
1822
ndpi_fill_prefix_v4(ndpi_prefix_t * p,const struct in_addr * a,int b,int mb)1823 int ndpi_fill_prefix_v4(ndpi_prefix_t *p, const struct in_addr *a, int b, int mb) {
1824 if(b < 0 || b > mb)
1825 return(-1);
1826
1827 memset(p, 0, sizeof(ndpi_prefix_t));
1828 memcpy(&p->add.sin, a, (mb + 7) / 8);
1829 p->family = AF_INET;
1830 p->bitlen = b;
1831 p->ref_count = 0;
1832
1833 return(0);
1834 }
1835
1836 /* ******************************************* */
1837
ndpi_fill_prefix_v6(ndpi_prefix_t * prefix,const struct in6_addr * addr,int bits,int maxbits)1838 int ndpi_fill_prefix_v6(ndpi_prefix_t *prefix, const struct in6_addr *addr, int bits, int maxbits) {
1839 if(bits < 0 || bits > maxbits)
1840 return -1;
1841
1842 memcpy(&prefix->add.sin6, addr, (maxbits + 7) / 8);
1843 prefix->family = AF_INET6, prefix->bitlen = bits, prefix->ref_count = 0;
1844
1845 return 0;
1846 }
1847
1848 /* ******************************************* */
1849
ndpi_fill_prefix_mac(ndpi_prefix_t * prefix,u_int8_t * mac,int bits,int maxbits)1850 int ndpi_fill_prefix_mac(ndpi_prefix_t *prefix, u_int8_t *mac, int bits, int maxbits) {
1851 if(bits < 0 || bits > maxbits)
1852 return -1;
1853
1854 memcpy(prefix->add.mac, mac, 6);
1855 prefix->family = AF_MAC, prefix->bitlen = bits, prefix->ref_count = 0;
1856
1857 return 0;
1858 }
1859
1860 /* ******************************************* */
1861
ndpi_patricia_get_node_prefix(ndpi_patricia_node_t * node)1862 ndpi_prefix_t *ndpi_patricia_get_node_prefix(ndpi_patricia_node_t *node) {
1863 return(node->prefix);
1864 }
1865
1866 /* ******************************************* */
1867
ndpi_patricia_get_node_bits(ndpi_patricia_node_t * node)1868 u_int16_t ndpi_patricia_get_node_bits(ndpi_patricia_node_t *node) {
1869 return(node->bit);
1870 }
1871
1872 /* ******************************************* */
1873
ndpi_patricia_set_node_data(ndpi_patricia_node_t * node,void * data)1874 void ndpi_patricia_set_node_data(ndpi_patricia_node_t *node, void *data) {
1875 node->data = data;
1876 }
1877
1878 /* ******************************************* */
1879
ndpi_patricia_get_node_data(ndpi_patricia_node_t * node)1880 void *ndpi_patricia_get_node_data(ndpi_patricia_node_t *node) {
1881 return(node->data);
1882 }
1883
1884 /* ******************************************* */
1885
ndpi_patricia_set_node_u64(ndpi_patricia_node_t * node,u_int64_t value)1886 void ndpi_patricia_set_node_u64(ndpi_patricia_node_t *node, u_int64_t value) {
1887 node->value.u.uv64 = value;
1888 }
1889
1890 /* ******************************************* */
1891
ndpi_patricia_get_node_u64(ndpi_patricia_node_t * node)1892 u_int64_t ndpi_patricia_get_node_u64(ndpi_patricia_node_t *node) {
1893 return(node->value.u.uv64);
1894 }
1895
1896 /* ******************************************* */
1897
ndpi_is_public_ipv4(u_int32_t a)1898 u_int8_t ndpi_is_public_ipv4(u_int32_t a /* host byte order */) {
1899 if( ((a & 0xFF000000) == 0x0A000000 /* 10.0.0.0/8 */)
1900 || ((a & 0xFFF00000) == 0xAC100000 /* 172.16.0.0/12 */)
1901 || ((a & 0xFFFF0000) == 0xC0A80000 /* 192.168.0.0/16 */)
1902 || ((a & 0xFF000000) == 0x7F000000 /* 127.0.0.0/8 */)
1903 || ((a & 0xF0000000) == 0xE0000000 /* 224.0.0.0/4 */)
1904 )
1905 return(0);
1906 else
1907 return(1);
1908 }
1909
1910 /* ******************************************* */
1911
ndpi_network_ptree_match(struct ndpi_detection_module_struct * ndpi_str,struct in_addr * pin)1912 u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str,
1913 struct in_addr *pin /* network byte order */) {
1914 ndpi_prefix_t prefix;
1915 ndpi_patricia_node_t *node;
1916
1917 if(ndpi_str->ndpi_num_custom_protocols == 0) {
1918 /*
1919 In case we don't have defined any custom protocol we check the ptree
1920 only in case of public IP addresses as in ndpi_content_match.c.inc
1921 we only have public IP addresses. Instead with custom protocols, users
1922 might have defined private protocols hence we should not skip
1923 the checks below
1924 */
1925
1926 if(ndpi_is_public_ipv4(ntohl(pin->s_addr)) == 0)
1927 return(NDPI_PROTOCOL_UNKNOWN); /* Non public IP */
1928 }
1929
1930 /* Make sure all in network byte order otherwise compares wont work */
1931 ndpi_fill_prefix_v4(&prefix, pin, 32, ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits);
1932 node = ndpi_patricia_search_best(ndpi_str->protocols_ptree, &prefix);
1933
1934 return(node ? node->value.u.uv32.user_value : NDPI_PROTOCOL_UNKNOWN);
1935 }
1936
1937 /* ******************************************* */
1938
ndpi_network_port_ptree_match(struct ndpi_detection_module_struct * ndpi_str,struct in_addr * pin,u_int16_t port)1939 u_int16_t ndpi_network_port_ptree_match(struct ndpi_detection_module_struct *ndpi_str,
1940 struct in_addr *pin /* network byte order */,
1941 u_int16_t port /* network byte order */) {
1942 ndpi_prefix_t prefix;
1943 ndpi_patricia_node_t *node;
1944
1945 /* Make sure all in network byte order otherwise compares wont work */
1946 ndpi_fill_prefix_v4(&prefix, pin, 32, ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits);
1947 node = ndpi_patricia_search_best(ndpi_str->protocols_ptree, &prefix);
1948
1949 if(node) {
1950 if((node->value.u.uv32.additional_user_value == 0)
1951 || (node->value.u.uv32.additional_user_value == port))
1952 return(node->value.u.uv32.user_value);
1953 }
1954
1955 return(NDPI_PROTOCOL_UNKNOWN);
1956 }
1957
1958 /* ******************************************* */
1959
1960 #if 0
1961 static u_int8_t tor_ptree_match(struct ndpi_detection_module_struct *ndpi_str, struct in_addr *pin) {
1962 return((ndpi_network_ptree_match(ndpi_str, pin) == NDPI_PROTOCOL_TOR) ? 1 : 0);
1963 }
1964 #endif
1965
1966 /* ******************************************* */
1967
ndpi_is_tor_flow(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow)1968 u_int8_t ndpi_is_tor_flow(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) {
1969 struct ndpi_packet_struct *packet = &flow->packet;
1970
1971 if(packet->tcp != NULL) {
1972 if(packet->iph) {
1973 if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_TOR)
1974 return(1);
1975 }
1976 }
1977
1978 return(0);
1979 }
1980
1981 /* ******************************************* */
1982
add_to_ptree(ndpi_patricia_tree_t * tree,int family,void * addr,int bits)1983 static ndpi_patricia_node_t* add_to_ptree(ndpi_patricia_tree_t *tree, int family, void *addr, int bits) {
1984 ndpi_prefix_t prefix;
1985 ndpi_patricia_node_t *node;
1986
1987 ndpi_fill_prefix_v4(&prefix, (struct in_addr *) addr, bits, tree->maxbits);
1988
1989 node = ndpi_patricia_lookup(tree, &prefix);
1990 if(node) memset(&node->value, 0, sizeof(node->value));
1991
1992 return(node);
1993 }
1994
1995 /* ******************************************* */
1996
1997 /*
1998 Load a file containing IPv4 addresses in CIDR format as 'protocol_id'
1999
2000 Return: the number of entries loaded or -1 in case of error
2001 */
ndpi_load_ipv4_ptree(struct ndpi_detection_module_struct * ndpi_str,const char * path,u_int16_t protocol_id)2002 int ndpi_load_ipv4_ptree(struct ndpi_detection_module_struct *ndpi_str,
2003 const char *path, u_int16_t protocol_id) {
2004 char buffer[128], *line, *addr, *cidr, *saveptr;
2005 FILE *fd;
2006 int len;
2007 u_int num_loaded = 0;
2008
2009 fd = fopen(path, "r");
2010
2011 if(fd == NULL) {
2012 NDPI_LOG_ERR(ndpi_str, "Unable to open file %s [%s]\n", path, strerror(errno));
2013 return(-1);
2014 }
2015
2016 while(1) {
2017 line = fgets(buffer, sizeof(buffer), fd);
2018
2019 if(line == NULL)
2020 break;
2021
2022 len = strlen(line);
2023
2024 if((len <= 1) || (line[0] == '#'))
2025 continue;
2026
2027 line[len - 1] = '\0';
2028 addr = strtok_r(line, "/", &saveptr);
2029
2030 if(addr) {
2031 struct in_addr pin;
2032 ndpi_patricia_node_t *node;
2033
2034 cidr = strtok_r(NULL, "\n", &saveptr);
2035
2036 pin.s_addr = inet_addr(addr);
2037 if((node = add_to_ptree(ndpi_str->protocols_ptree, AF_INET, &pin, cidr ? atoi(cidr) : 32 /* bits */)) != NULL) {
2038 node->value.u.uv32.user_value = protocol_id, node->value.u.uv32.additional_user_value = 0 /* port */;
2039 num_loaded++;
2040 }
2041 }
2042 }
2043
2044 fclose(fd);
2045 return(num_loaded);
2046 }
2047
2048 /* ******************************************* */
2049
ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct * ndpi_str,void * ptree,ndpi_network host_list[],u_int8_t skip_tor_hosts)2050 static void ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct *ndpi_str,
2051 void *ptree, ndpi_network host_list[],
2052 u_int8_t skip_tor_hosts) {
2053 int i;
2054
2055 for(i = 0; host_list[i].network != 0x0; i++) {
2056 struct in_addr pin;
2057 ndpi_patricia_node_t *node;
2058
2059 if(skip_tor_hosts && (host_list[i].value == NDPI_PROTOCOL_TOR))
2060 continue;
2061
2062 pin.s_addr = htonl(host_list[i].network);
2063 if((node = add_to_ptree(ptree, AF_INET, &pin, host_list[i].cidr /* bits */)) != NULL) {
2064 node->value.u.uv32.user_value = host_list[i].value, node->value.u.uv32.additional_user_value = 0;
2065 }
2066 }
2067 }
2068
2069 /* ******************************************* */
2070
ndpi_add_host_ip_subprotocol(struct ndpi_detection_module_struct * ndpi_str,char * value,u_int16_t protocol_id)2071 static int ndpi_add_host_ip_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
2072 char *value, u_int16_t protocol_id) {
2073 ndpi_patricia_node_t *node;
2074 struct in_addr pin;
2075 int bits = 32;
2076 char *ptr = strrchr(value, '/');
2077 u_int16_t port = 0; /* Format ip:8.248.73.247:443 */
2078 char *double_column;
2079
2080 if(ptr) {
2081 ptr[0] = '\0';
2082 ptr++;
2083
2084 if((double_column = strrchr(ptr, ':')) != NULL) {
2085 double_column[0] = '\0';
2086 port = atoi(&double_column[1]);
2087 }
2088
2089 if(atoi(ptr) >= 0 && atoi(ptr) <= 32)
2090 bits = atoi(ptr);
2091 } else {
2092 /*
2093 Let's check if there is the port defined
2094 Example: ip:8.248.73.247:443@AmazonPrime
2095 */
2096 double_column = strrchr(value, ':');
2097
2098 if(double_column) {
2099 double_column[0] = '\0';
2100 port = atoi(&double_column[1]);
2101 }
2102 }
2103
2104 inet_pton(AF_INET, value, &pin);
2105
2106 if((node = add_to_ptree(ndpi_str->protocols_ptree, AF_INET, &pin, bits)) != NULL) {
2107 node->value.u.uv32.user_value = protocol_id, node->value.u.uv32.additional_user_value = htons(port);
2108 }
2109
2110 return(0);
2111 }
2112
set_ndpi_malloc(void * (* __ndpi_malloc)(size_t size))2113 void set_ndpi_malloc(void *(*__ndpi_malloc)(size_t size)) {
2114 _ndpi_malloc = __ndpi_malloc;
2115 }
set_ndpi_flow_malloc(void * (* __ndpi_flow_malloc)(size_t size))2116 void set_ndpi_flow_malloc(void *(*__ndpi_flow_malloc)(size_t size)) {
2117 _ndpi_flow_malloc = __ndpi_flow_malloc;
2118 }
2119
set_ndpi_free(void (* __ndpi_free)(void * ptr))2120 void set_ndpi_free(void (*__ndpi_free)(void *ptr)) {
2121 _ndpi_free = __ndpi_free;
2122 }
set_ndpi_flow_free(void (* __ndpi_flow_free)(void * ptr))2123 void set_ndpi_flow_free(void (*__ndpi_flow_free)(void *ptr)) {
2124 _ndpi_flow_free = __ndpi_flow_free;
2125 }
2126
ndpi_debug_printf(unsigned int proto,struct ndpi_detection_module_struct * ndpi_str,ndpi_log_level_t log_level,const char * file_name,const char * func_name,int line_number,const char * format,...)2127 void ndpi_debug_printf(unsigned int proto, struct ndpi_detection_module_struct *ndpi_str, ndpi_log_level_t log_level,
2128 const char *file_name, const char *func_name, int line_number, const char *format, ...) {
2129 #ifdef NDPI_ENABLE_DEBUG_MESSAGES
2130 va_list args;
2131 #define MAX_STR_LEN 250
2132 char str[MAX_STR_LEN];
2133 if(ndpi_str != NULL && log_level > NDPI_LOG_ERROR && proto > 0 && proto < NDPI_MAX_SUPPORTED_PROTOCOLS &&
2134 !NDPI_ISSET(&ndpi_str->debug_bitmask, proto))
2135 return;
2136 va_start(args, format);
2137 vsnprintf(str, sizeof(str) - 1, format, args);
2138 va_end(args);
2139
2140 if(ndpi_str != NULL) {
2141 printf("%s:%s:%-3d - [%s]: %s", file_name, func_name, line_number, ndpi_get_proto_name(ndpi_str, proto), str);
2142 } else {
2143 printf("Proto: %u, %s", proto, str);
2144 }
2145 #endif
2146 }
2147
set_ndpi_debug_function(struct ndpi_detection_module_struct * ndpi_str,ndpi_debug_function_ptr ndpi_debug_printf)2148 void set_ndpi_debug_function(struct ndpi_detection_module_struct *ndpi_str, ndpi_debug_function_ptr ndpi_debug_printf) {
2149 #ifdef NDPI_ENABLE_DEBUG_MESSAGES
2150 ndpi_str->ndpi_debug_printf = ndpi_debug_printf;
2151 #endif
2152 }
2153
2154 /* ****************************************** */
2155
2156 /* Keep it in order and in sync with ndpi_protocol_category_t in ndpi_typedefs.h */
2157 static const char *categories[] = {
2158 "Unspecified",
2159 "Media",
2160 "VPN",
2161 "Email",
2162 "DataTransfer",
2163 "Web",
2164 "SocialNetwork",
2165 "Download",
2166 "Game",
2167 "Chat",
2168 "VoIP",
2169 "Database",
2170 "RemoteAccess",
2171 "Cloud",
2172 "Network",
2173 "Collaborative",
2174 "RPC",
2175 "Streaming",
2176 "System",
2177 "SoftwareUpdate",
2178 "",
2179 "",
2180 "",
2181 "",
2182 "",
2183 "Music",
2184 "Video",
2185 "Shopping",
2186 "Productivity",
2187 "FileSharing",
2188 "ConnCheck",
2189 "IoT-Scada",
2190 "VirtAssistant",
2191 "",
2192 "",
2193 "",
2194 "",
2195 "",
2196 "",
2197 "",
2198 "",
2199 "",
2200 "",
2201 "",
2202 "",
2203 "",
2204 "",
2205 "",
2206 "",
2207 "",
2208 "",
2209 "",
2210 "",
2211 "",
2212 "",
2213 "",
2214 "",
2215 "",
2216 "",
2217 "",
2218 "",
2219 "",
2220 "",
2221 "",
2222 "",
2223 "",
2224 "",
2225 "",
2226 "",
2227 "",
2228 "",
2229 "",
2230 "",
2231 "",
2232 "",
2233 "",
2234 "",
2235 "",
2236 "",
2237 "",
2238 "",
2239 "",
2240 "",
2241 "",
2242 "",
2243 "",
2244 "",
2245 "",
2246 "",
2247 "",
2248 "",
2249 "",
2250 "",
2251 "",
2252 "",
2253 "",
2254 "",
2255 "",
2256 "",
2257 "Mining", /* 99 */
2258 "Malware",
2259 "Advertisement",
2260 "Banned_Site",
2261 "Site_Unavailable",
2262 "Allowed_Site",
2263 "Antimalware",
2264 };
2265
2266 /* ******************************************************************** */
2267
2268 #ifdef TEST_LRU_HANDLER
test_lru_handler(ndpi_lru_cache_type cache_type,u_int32_t proto,u_int32_t app_proto)2269 void test_lru_handler(ndpi_lru_cache_type cache_type, u_int32_t proto, u_int32_t app_proto) {
2270
2271 printf("[test_lru_handler] %u / %u / %u\n", cache_type, proto, app_proto);
2272 }
2273 #endif
2274
2275 /* ******************************************************************** */
2276
ndpi_init_detection_module(ndpi_init_prefs prefs)2277 struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs prefs) {
2278 struct ndpi_detection_module_struct *ndpi_str = ndpi_malloc(sizeof(struct ndpi_detection_module_struct));
2279 int i;
2280
2281 if(ndpi_str == NULL) {
2282 /* Logging this error is a bit tricky. At this point, we can't use NDPI_LOG*
2283 functions yet, we don't have a custom log function and, as a library,
2284 we shouldn't use stdout/stderr. Since this error is quite unlikely,
2285 simply avoid any logs at all */
2286 return(NULL);
2287 }
2288
2289 memset(ndpi_str, 0, sizeof(struct ndpi_detection_module_struct));
2290
2291 #ifdef TEST_LRU_HANDLER
2292 ndpi_str->ndpi_notify_lru_add_handler_ptr = test_lru_handler;
2293 #endif
2294
2295 #ifdef NDPI_ENABLE_DEBUG_MESSAGES
2296 set_ndpi_debug_function(ndpi_str, (ndpi_debug_function_ptr) ndpi_debug_printf);
2297 NDPI_BITMASK_RESET(ndpi_str->debug_bitmask);
2298 #endif /* NDPI_ENABLE_DEBUG_MESSAGES */
2299
2300 if(prefs & ndpi_enable_ja3_plus)
2301 ndpi_str->enable_ja3_plus = 1;
2302
2303 #ifdef HAVE_LIBGCRYPT
2304 if(!(prefs & ndpi_dont_init_libgcrypt)) {
2305 if(!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
2306 const char *gcrypt_ver = gcry_check_version(NULL);
2307 if(!gcrypt_ver) {
2308 NDPI_LOG_ERR(ndpi_str, "Error initializing libgcrypt\n");
2309 ndpi_free(ndpi_str);
2310 return NULL;
2311 }
2312 NDPI_LOG_DBG(ndpi_str, "Libgcrypt %s\n", gcrypt_ver);
2313 /* Tell Libgcrypt that initialization has completed. */
2314 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
2315 }
2316 } else {
2317 NDPI_LOG_DBG(ndpi_str, "Libgcrypt initialization skipped\n");
2318 }
2319 #endif
2320
2321 if((ndpi_str->protocols_ptree = ndpi_patricia_new(32 /* IPv4 */)) != NULL)
2322 ndpi_init_ptree_ipv4(ndpi_str, ndpi_str->protocols_ptree, host_protocol_list, prefs & ndpi_dont_load_tor_hosts);
2323
2324 ndpi_str->ip_risk_mask_ptree = ndpi_patricia_new(32 /* IPv4 */);
2325
2326 NDPI_BITMASK_RESET(ndpi_str->detection_bitmask);
2327 #ifdef NDPI_ENABLE_DEBUG_MESSAGES
2328 ndpi_str->user_data = NULL;
2329 #endif
2330
2331 ndpi_str->ticks_per_second = 1000; /* ndpi_str->ticks_per_second */
2332 ndpi_str->tcp_max_retransmission_window_size = NDPI_DEFAULT_MAX_TCP_RETRANSMISSION_WINDOW_SIZE;
2333 ndpi_str->directconnect_connection_ip_tick_timeout =
2334 NDPI_DIRECTCONNECT_CONNECTION_IP_TICK_TIMEOUT * ndpi_str->ticks_per_second;
2335
2336 ndpi_str->rtsp_connection_timeout = NDPI_RTSP_CONNECTION_TIMEOUT * ndpi_str->ticks_per_second;
2337 ndpi_str->irc_timeout = NDPI_IRC_CONNECTION_TIMEOUT * ndpi_str->ticks_per_second;
2338 ndpi_str->gnutella_timeout = NDPI_GNUTELLA_CONNECTION_TIMEOUT * ndpi_str->ticks_per_second;
2339 ndpi_str->thunder_timeout = NDPI_THUNDER_CONNECTION_TIMEOUT * ndpi_str->ticks_per_second;
2340 ndpi_str->zattoo_connection_timeout = NDPI_ZATTOO_CONNECTION_TIMEOUT * ndpi_str->ticks_per_second;
2341 ndpi_str->jabber_stun_timeout = NDPI_JABBER_STUN_TIMEOUT * ndpi_str->ticks_per_second;
2342 ndpi_str->jabber_file_transfer_timeout = NDPI_JABBER_FT_TIMEOUT * ndpi_str->ticks_per_second;
2343 ndpi_str->soulseek_connection_ip_tick_timeout =
2344 NDPI_SOULSEEK_CONNECTION_IP_TICK_TIMEOUT * ndpi_str->ticks_per_second;
2345
2346 ndpi_str->ndpi_num_supported_protocols = NDPI_MAX_SUPPORTED_PROTOCOLS;
2347 ndpi_str->ndpi_num_custom_protocols = 0;
2348
2349 ndpi_str->host_automa.ac_automa = ac_automata_init(ac_domain_match_handler);
2350 ndpi_str->content_automa.ac_automa = ac_automata_init(ac_domain_match_handler);
2351 ndpi_str->host_risk_mask_automa.ac_automa = ac_automata_init(ac_domain_match_handler);
2352 ndpi_str->common_alpns_automa.ac_automa = ac_automata_init(ac_domain_match_handler);
2353 load_common_alpns(ndpi_str);
2354 ndpi_str->tls_cert_subject_automa.ac_automa = ac_automata_init(NULL);
2355 ndpi_str->malicious_ja3_automa.ac_automa = NULL; /* Initialized on demand */
2356 ndpi_str->malicious_sha1_automa.ac_automa = NULL; /* Initialized on demand */
2357 ndpi_str->risky_domain_automa.ac_automa = NULL; /* Initialized on demand */
2358
2359 if((sizeof(categories) / sizeof(char *)) != NDPI_PROTOCOL_NUM_CATEGORIES) {
2360 NDPI_LOG_ERR(ndpi_str, "[NDPI] invalid categories length: expected %u, got %u\n", NDPI_PROTOCOL_NUM_CATEGORIES,
2361 (unsigned int) (sizeof(categories) / sizeof(char *)));
2362 return(NULL);
2363 }
2364
2365 ndpi_str->custom_categories.hostnames.ac_automa = ac_automata_init(ac_domain_match_handler);
2366 ndpi_str->custom_categories.hostnames_shadow.ac_automa = ac_automata_init(ac_domain_match_handler);
2367
2368 ndpi_str->custom_categories.ipAddresses = ndpi_patricia_new(32 /* IPv4 */);
2369 ndpi_str->custom_categories.ipAddresses_shadow = ndpi_patricia_new(32 /* IPv4 */);
2370
2371 if(ndpi_str->host_automa.ac_automa)
2372 ac_automata_feature(ndpi_str->host_automa.ac_automa,AC_FEATURE_LC);
2373
2374 if(ndpi_str->custom_categories.hostnames.ac_automa)
2375 ac_automata_feature(ndpi_str->custom_categories.hostnames.ac_automa,AC_FEATURE_LC);
2376
2377 if(ndpi_str->custom_categories.hostnames_shadow.ac_automa)
2378 ac_automata_feature(ndpi_str->custom_categories.hostnames_shadow.ac_automa,AC_FEATURE_LC);
2379
2380 if(ndpi_str->tls_cert_subject_automa.ac_automa)
2381 ac_automata_feature(ndpi_str->tls_cert_subject_automa.ac_automa,AC_FEATURE_LC);
2382
2383 if(ndpi_str->content_automa.ac_automa)
2384 ac_automata_feature(ndpi_str->content_automa.ac_automa,AC_FEATURE_LC);
2385
2386 if(ndpi_str->host_risk_mask_automa.ac_automa)
2387 ac_automata_feature(ndpi_str->host_risk_mask_automa.ac_automa,AC_FEATURE_LC);
2388
2389 if(ndpi_str->common_alpns_automa.ac_automa)
2390 ac_automata_feature(ndpi_str->common_alpns_automa.ac_automa,AC_FEATURE_LC);
2391
2392 /* ahocorasick debug */
2393 /* Needed ac_automata_enable_debug(1) for show debug */
2394 if(ndpi_str->host_automa.ac_automa)
2395 ac_automata_name(ndpi_str->host_automa.ac_automa,"host",AC_FEATURE_DEBUG);
2396
2397 if(ndpi_str->custom_categories.hostnames.ac_automa)
2398 ac_automata_name(ndpi_str->custom_categories.hostnames.ac_automa,"ccat",0);
2399
2400 if(ndpi_str->custom_categories.hostnames_shadow.ac_automa)
2401 ac_automata_name(ndpi_str->custom_categories.hostnames_shadow.ac_automa,"ccat_sh",0);
2402
2403 if(ndpi_str->tls_cert_subject_automa.ac_automa)
2404 ac_automata_name(ndpi_str->tls_cert_subject_automa.ac_automa,"tls_cert",AC_FEATURE_DEBUG);
2405
2406 if(ndpi_str->content_automa.ac_automa)
2407 ac_automata_name(ndpi_str->content_automa.ac_automa,"content",AC_FEATURE_DEBUG);
2408
2409 if(ndpi_str->host_risk_mask_automa.ac_automa)
2410 ac_automata_name(ndpi_str->host_risk_mask_automa.ac_automa,"content",AC_FEATURE_DEBUG);
2411
2412 if(ndpi_str->common_alpns_automa.ac_automa)
2413 ac_automata_name(ndpi_str->common_alpns_automa.ac_automa,"content",AC_FEATURE_DEBUG);
2414
2415 if((ndpi_str->custom_categories.ipAddresses == NULL) || (ndpi_str->custom_categories.ipAddresses_shadow == NULL)) {
2416 NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating Patricia trees\n");
2417 return(NULL);
2418 }
2419
2420 ndpi_init_protocol_defaults(ndpi_str);
2421
2422 for(i = 0; i < NUM_CUSTOM_CATEGORIES; i++)
2423 snprintf(ndpi_str->custom_category_labels[i], CUSTOM_CATEGORY_LABEL_LEN, "User custom category %u",
2424 (unsigned int) (i + 1));
2425
2426 return(ndpi_str);
2427 }
2428
2429 /* *********************************************** */
2430
ndpi_finalize_initialization(struct ndpi_detection_module_struct * ndpi_str)2431 void ndpi_finalize_initialization(struct ndpi_detection_module_struct *ndpi_str) {
2432 u_int i;
2433
2434 if(ndpi_str->ac_automa_finalized) return;
2435
2436 for(i = 0; i < 99; i++) {
2437 ndpi_automa *automa;
2438
2439 switch(i) {
2440 case 0:
2441 automa = &ndpi_str->host_automa;
2442 break;
2443
2444 case 1:
2445 automa = &ndpi_str->content_automa;
2446 break;
2447
2448 case 2:
2449 automa = &ndpi_str->tls_cert_subject_automa;
2450 break;
2451
2452 case 3:
2453 automa = &ndpi_str->malicious_ja3_automa;
2454 break;
2455
2456 case 4:
2457 automa = &ndpi_str->malicious_sha1_automa;
2458 break;
2459
2460 case 5:
2461 automa = &ndpi_str->host_risk_mask_automa;
2462 break;
2463
2464 case 6:
2465 automa = &ndpi_str->common_alpns_automa;
2466 break;
2467
2468 default:
2469 ndpi_str->ac_automa_finalized = 1;
2470 return;
2471 }
2472
2473 if(automa && automa->ac_automa)
2474 ac_automata_finalize((AC_AUTOMATA_t *) automa->ac_automa);
2475 }
2476 }
2477
2478 /* *********************************************** */
2479
2480 /* Wrappers */
ndpi_init_automa(void)2481 void *ndpi_init_automa(void) {
2482 return(ac_automata_init(ac_domain_match_handler));
2483 }
2484
2485 /* ****************************************************** */
2486
ndpi_add_string_value_to_automa(void * _automa,char * str,u_int32_t num)2487 int ndpi_add_string_value_to_automa(void *_automa, char *str, u_int32_t num) {
2488 AC_PATTERN_t ac_pattern;
2489 AC_AUTOMATA_t *automa = (AC_AUTOMATA_t *) _automa;
2490 AC_ERROR_t rc;
2491
2492 if(automa == NULL)
2493 return(-1);
2494
2495 memset(&ac_pattern, 0, sizeof(ac_pattern));
2496 ac_pattern.astring = str;
2497 ac_pattern.rep.number = num;
2498 ac_pattern.length = strlen(ac_pattern.astring);
2499
2500 rc = ac_automata_add(automa, &ac_pattern);
2501 return(rc == ACERR_SUCCESS || rc == ACERR_DUPLICATE_PATTERN ? 0 : -1);
2502 }
2503
2504 /* ****************************************************** */
2505
ndpi_add_string_to_automa(void * _automa,char * str)2506 int ndpi_add_string_to_automa(void *_automa, char *str) {
2507 return(ndpi_add_string_value_to_automa(_automa, str, 1));
2508 }
2509
2510 /* ****************************************************** */
2511
ndpi_free_automa(void * _automa)2512 void ndpi_free_automa(void *_automa) {
2513 ac_automata_release((AC_AUTOMATA_t *) _automa, 1);
2514 }
2515
2516 /* ****************************************************** */
2517
ndpi_finalize_automa(void * _automa)2518 void ndpi_finalize_automa(void *_automa) {
2519 ac_automata_finalize((AC_AUTOMATA_t *) _automa);
2520 }
2521
2522 /* ****************************************************** */
2523
ndpi_match_string_common(AC_AUTOMATA_t * automa,char * string_to_match,size_t string_len,u_int32_t * protocol_id,ndpi_protocol_category_t * category,ndpi_protocol_breed_t * breed)2524 static int ndpi_match_string_common(AC_AUTOMATA_t *automa, char *string_to_match,size_t string_len,
2525 u_int32_t *protocol_id, ndpi_protocol_category_t *category,
2526 ndpi_protocol_breed_t *breed) {
2527 AC_REP_t match = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED };
2528 AC_TEXT_t ac_input_text;
2529 int rc;
2530
2531 if(protocol_id) *protocol_id = NDPI_PROTOCOL_UNKNOWN;
2532
2533 if((automa == NULL) || (string_to_match == NULL) || (string_to_match[0] == '\0')) {
2534 return(-2);
2535 }
2536
2537 if(automa->automata_open) {
2538 printf("[%s:%d] [NDPI] Internal error: please call ndpi_finalize_initialization()\n", __FILE__, __LINE__);
2539 return(-1);
2540 }
2541
2542 ac_input_text.astring = string_to_match, ac_input_text.length = string_len;
2543 ac_input_text.option = 0;
2544 rc = ac_automata_search(automa, &ac_input_text, &match);
2545
2546 if(protocol_id)
2547 *protocol_id = rc ? match.number : NDPI_PROTOCOL_UNKNOWN;
2548
2549 if(category)
2550 *category = rc ? match.category : 0;
2551
2552 if(breed)
2553 *breed = rc ? match.breed : 0;
2554
2555 return rc;
2556 }
2557
2558 /* ****************************************************** */
2559
ndpi_match_string(void * _automa,char * string_to_match)2560 int ndpi_match_string(void *_automa, char *string_to_match) {
2561 uint32_t proto_id;
2562 int rc;
2563
2564 if(!string_to_match)
2565 return(-2);
2566
2567 rc = ndpi_match_string_common(_automa, string_to_match,
2568 strlen(string_to_match),
2569 &proto_id, NULL, NULL);
2570 if(rc < 0) return rc;
2571
2572 return rc ? proto_id : NDPI_PROTOCOL_UNKNOWN;
2573 }
2574
2575 /* ****************************************************** */
2576
ndpi_match_string_protocol_id(void * automa,char * string_to_match,u_int match_len,u_int16_t * protocol_id,ndpi_protocol_category_t * category,ndpi_protocol_breed_t * breed)2577 int ndpi_match_string_protocol_id(void *automa, char *string_to_match,
2578 u_int match_len, u_int16_t *protocol_id,
2579 ndpi_protocol_category_t *category,
2580 ndpi_protocol_breed_t *breed) {
2581 u_int32_t proto_id;
2582 int rc = ndpi_match_string_common((AC_AUTOMATA_t*)automa, string_to_match,
2583 match_len, &proto_id, category, breed);
2584 if(rc < 0) return rc;
2585 *protocol_id = (u_int16_t)proto_id;
2586 return(proto_id != NDPI_PROTOCOL_UNKNOWN ? 0 : -1);
2587 }
2588
2589 /* ****************************************************** */
2590
ndpi_match_string_value(void * automa,char * string_to_match,u_int match_len,u_int32_t * num)2591 int ndpi_match_string_value(void *automa, char *string_to_match,
2592 u_int match_len, u_int32_t *num) {
2593
2594 int rc = ndpi_match_string_common((AC_AUTOMATA_t *)automa, string_to_match,
2595 match_len, num, NULL, NULL);
2596 if(rc < 0) return rc;
2597 return rc ? 0 : -1;
2598 }
2599
2600
2601 /* *********************************************** */
2602
ndpi_match_custom_category(struct ndpi_detection_module_struct * ndpi_str,char * name,u_int name_len,ndpi_protocol_category_t * category)2603 int ndpi_match_custom_category(struct ndpi_detection_module_struct *ndpi_str,
2604 char *name, u_int name_len,
2605 ndpi_protocol_category_t *category) {
2606 u_int32_t id;
2607 int rc = ndpi_match_string_common(ndpi_str->custom_categories.hostnames.ac_automa,
2608 name, name_len, &id, category, NULL);
2609 if(rc < 0) return rc;
2610 return(id != NDPI_PROTOCOL_UNKNOWN ? 0 : -1);
2611 }
2612
2613 /* *********************************************** */
2614
ndpi_get_custom_category_match(struct ndpi_detection_module_struct * ndpi_str,char * name_or_ip,u_int name_len,ndpi_protocol_category_t * id)2615 int ndpi_get_custom_category_match(struct ndpi_detection_module_struct *ndpi_str,
2616 char *name_or_ip, u_int name_len,
2617 ndpi_protocol_category_t *id) {
2618 char ipbuf[64], *ptr;
2619 struct in_addr pin;
2620 u_int cp_len = ndpi_min(sizeof(ipbuf) - 1, name_len);
2621
2622 if(!ndpi_str->custom_categories.categories_loaded)
2623 return(-1);
2624
2625 if(cp_len > 0) {
2626 memcpy(ipbuf, name_or_ip, cp_len);
2627 ipbuf[cp_len] = '\0';
2628 } else
2629 ipbuf[0] = '\0';
2630
2631 ptr = strrchr(ipbuf, '/');
2632
2633 if(ptr)
2634 ptr[0] = '\0';
2635
2636 if(inet_pton(AF_INET, ipbuf, &pin) == 1) {
2637 /* Search IP */
2638 ndpi_prefix_t prefix;
2639 ndpi_patricia_node_t *node;
2640
2641 /* Make sure all in network byte order otherwise compares wont work */
2642 ndpi_fill_prefix_v4(&prefix, &pin, 32, ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits);
2643 node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix);
2644
2645 if(node) {
2646 *id = node->value.u.uv32.user_value;
2647
2648 return(0);
2649 }
2650
2651 return(-1);
2652 } else {
2653 /* Search Host */
2654 return(ndpi_match_custom_category(ndpi_str, name_or_ip, name_len, id));
2655 }
2656 }
2657
2658 /* *********************************************** */
2659
free_ptree_data(void * data)2660 static void free_ptree_data(void *data) {
2661 ;
2662 }
2663
2664 /* ****************************************************** */
2665
ndpi_exit_detection_module(struct ndpi_detection_module_struct * ndpi_str)2666 void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) {
2667 if(ndpi_str != NULL) {
2668 int i;
2669
2670 for (i = 0; i < (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS); i++) {
2671 if (ndpi_str->proto_defaults[i].protoName)
2672 ndpi_free(ndpi_str->proto_defaults[i].protoName);
2673 if (ndpi_str->proto_defaults[i].subprotocols != NULL)
2674 ndpi_free(ndpi_str->proto_defaults[i].subprotocols);
2675 }
2676
2677 /* NDPI_PROTOCOL_TINC */
2678 if(ndpi_str->tinc_cache)
2679 cache_free((cache_t)(ndpi_str->tinc_cache));
2680
2681 if(ndpi_str->ookla_cache)
2682 ndpi_lru_free_cache(ndpi_str->ookla_cache);
2683
2684 if(ndpi_str->stun_cache)
2685 ndpi_lru_free_cache(ndpi_str->stun_cache);
2686
2687 if(ndpi_str->tls_cert_cache)
2688 ndpi_lru_free_cache(ndpi_str->tls_cert_cache);
2689
2690 if(ndpi_str->mining_cache)
2691 ndpi_lru_free_cache(ndpi_str->mining_cache);
2692
2693 if(ndpi_str->msteams_cache)
2694 ndpi_lru_free_cache(ndpi_str->msteams_cache);
2695
2696 if(ndpi_str->protocols_ptree)
2697 ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree, free_ptree_data);
2698
2699 if(ndpi_str->ip_risk_mask_ptree)
2700 ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->ip_risk_mask_ptree, free_ptree_data);
2701
2702 if(ndpi_str->udpRoot != NULL)
2703 ndpi_tdestroy(ndpi_str->udpRoot, ndpi_free);
2704 if(ndpi_str->tcpRoot != NULL)
2705 ndpi_tdestroy(ndpi_str->tcpRoot, ndpi_free);
2706
2707 if(ndpi_str->host_automa.ac_automa != NULL)
2708 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->host_automa.ac_automa,
2709 1 /* free patterns strings memory */);
2710
2711 if(ndpi_str->content_automa.ac_automa != NULL)
2712 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->content_automa.ac_automa, 0);
2713
2714 if(ndpi_str->risky_domain_automa.ac_automa != NULL)
2715 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->risky_domain_automa.ac_automa,
2716 1 /* free patterns strings memory */);
2717
2718 if(ndpi_str->tls_cert_subject_automa.ac_automa != NULL)
2719 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->tls_cert_subject_automa.ac_automa, 0);
2720
2721 if(ndpi_str->malicious_ja3_automa.ac_automa != NULL)
2722 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->malicious_ja3_automa.ac_automa,
2723 1 /* free patterns strings memory */);
2724
2725 if(ndpi_str->malicious_sha1_automa.ac_automa != NULL)
2726 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->malicious_sha1_automa.ac_automa,
2727 1 /* free patterns strings memory */);
2728
2729 if(ndpi_str->custom_categories.hostnames.ac_automa != NULL)
2730 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames.ac_automa,
2731 1 /* free patterns strings memory */);
2732
2733 if(ndpi_str->custom_categories.hostnames_shadow.ac_automa != NULL)
2734 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames_shadow.ac_automa,
2735 1 /* free patterns strings memory */);
2736
2737 if(ndpi_str->custom_categories.ipAddresses != NULL)
2738 ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data);
2739
2740 if(ndpi_str->custom_categories.ipAddresses_shadow != NULL)
2741 ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->custom_categories.ipAddresses_shadow, free_ptree_data);
2742
2743 if(ndpi_str->host_risk_mask_automa.ac_automa != NULL)
2744 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->host_risk_mask_automa.ac_automa,
2745 1 /* free patterns strings memory */);
2746
2747 if(ndpi_str->common_alpns_automa.ac_automa != NULL)
2748 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->common_alpns_automa.ac_automa,
2749 1 /* free patterns strings memory */);
2750
2751 #ifdef CUSTOM_NDPI_PROTOCOLS
2752 #include "../../../nDPI-custom/ndpi_exit_detection_module.c"
2753 #endif
2754
2755 ndpi_free_geoip(ndpi_str);
2756
2757 ndpi_free(ndpi_str);
2758 }
2759 }
2760
2761 /* ****************************************************** */
2762
ndpi_get_guessed_protocol_id(struct ndpi_detection_module_struct * ndpi_str,u_int8_t proto,u_int16_t sport,u_int16_t dport)2763 static ndpi_default_ports_tree_node_t *ndpi_get_guessed_protocol_id(struct ndpi_detection_module_struct *ndpi_str,
2764 u_int8_t proto, u_int16_t sport, u_int16_t dport) {
2765 ndpi_default_ports_tree_node_t node;
2766
2767 if(sport && dport) {
2768 int low = ndpi_min(sport, dport);
2769 int high = ndpi_max(sport, dport);
2770 const void *ret;
2771
2772 node.default_port = low; /* Check server port first */
2773 ret = ndpi_tfind(&node, (proto == IPPROTO_TCP) ? (void *) &ndpi_str->tcpRoot : (void *) &ndpi_str->udpRoot,
2774 ndpi_default_ports_tree_node_t_cmp);
2775
2776 if(ret == NULL) {
2777 node.default_port = high;
2778 ret = ndpi_tfind(&node, (proto == IPPROTO_TCP) ? (void *) &ndpi_str->tcpRoot : (void *) &ndpi_str->udpRoot,
2779 ndpi_default_ports_tree_node_t_cmp);
2780 }
2781
2782 if(ret)
2783 return(*(ndpi_default_ports_tree_node_t **) ret);
2784 }
2785
2786 return(NULL);
2787 }
2788
2789 /* ****************************************************** */
2790
2791 /*
2792 These are UDP protocols that must fit a single packet
2793 and thus that if have NOT been detected they cannot be guessed
2794 as they have been excluded
2795 */
is_udp_guessable_protocol(u_int16_t l7_guessed_proto)2796 u_int8_t is_udp_guessable_protocol(u_int16_t l7_guessed_proto) {
2797 switch(l7_guessed_proto) {
2798 case NDPI_PROTOCOL_QUIC:
2799 case NDPI_PROTOCOL_SNMP:
2800 case NDPI_PROTOCOL_NETFLOW:
2801 /* TODO: add more protocols (if any missing) */
2802 return(1);
2803 }
2804
2805 return(0);
2806 }
2807
2808 /* ****************************************************** */
2809
ndpi_guess_protocol_id(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int8_t proto,u_int16_t sport,u_int16_t dport,u_int8_t * user_defined_proto)2810 u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
2811 u_int8_t proto, u_int16_t sport, u_int16_t dport, u_int8_t *user_defined_proto) {
2812 *user_defined_proto = 0; /* Default */
2813
2814 if(sport && dport) {
2815 ndpi_default_ports_tree_node_t *found = ndpi_get_guessed_protocol_id(ndpi_str, proto, sport, dport);
2816
2817 if(found != NULL) {
2818 u_int16_t guessed_proto = found->proto->protoId;
2819
2820 /* We need to check if the guessed protocol isn't excluded by nDPI */
2821 if(flow && (proto == IPPROTO_UDP) &&
2822 NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, guessed_proto) &&
2823 is_udp_guessable_protocol(guessed_proto))
2824 return(NDPI_PROTOCOL_UNKNOWN);
2825 else {
2826 *user_defined_proto = found->customUserProto;
2827 return(guessed_proto);
2828 }
2829 }
2830 } else {
2831 /* No TCP/UDP */
2832
2833 switch(proto) {
2834 case NDPI_IPSEC_PROTOCOL_ESP:
2835 case NDPI_IPSEC_PROTOCOL_AH:
2836 return(NDPI_PROTOCOL_IP_IPSEC);
2837 break;
2838 case NDPI_GRE_PROTOCOL_TYPE:
2839 return(NDPI_PROTOCOL_IP_GRE);
2840 break;
2841 case NDPI_ICMP_PROTOCOL_TYPE:
2842 if(flow) {
2843 /* Run some basic consistency tests */
2844
2845 if(flow->packet.payload_packet_len < sizeof(struct ndpi_icmphdr))
2846 ndpi_set_risk(ndpi_str, flow, NDPI_MALFORMED_PACKET);
2847 else {
2848 u_int8_t icmp_type = (u_int8_t)flow->packet.payload[0];
2849 u_int8_t icmp_code = (u_int8_t)flow->packet.payload[1];
2850
2851 /* https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml */
2852 if(((icmp_type >= 44) && (icmp_type <= 252))
2853 || (icmp_code > 15))
2854 ndpi_set_risk(ndpi_str, flow, NDPI_MALFORMED_PACKET);
2855 }
2856 }
2857 return(NDPI_PROTOCOL_IP_ICMP);
2858 break;
2859 case NDPI_IGMP_PROTOCOL_TYPE:
2860 return(NDPI_PROTOCOL_IP_IGMP);
2861 break;
2862 case NDPI_EGP_PROTOCOL_TYPE:
2863 return(NDPI_PROTOCOL_IP_EGP);
2864 break;
2865 case NDPI_SCTP_PROTOCOL_TYPE:
2866 return(NDPI_PROTOCOL_IP_SCTP);
2867 break;
2868 case NDPI_OSPF_PROTOCOL_TYPE:
2869 return(NDPI_PROTOCOL_IP_OSPF);
2870 break;
2871 case NDPI_IPIP_PROTOCOL_TYPE:
2872 return(NDPI_PROTOCOL_IP_IP_IN_IP);
2873 break;
2874 case NDPI_ICMPV6_PROTOCOL_TYPE:
2875 if(flow) {
2876 /* Run some basic consistency tests */
2877
2878 if(flow->packet.payload_packet_len < sizeof(struct ndpi_icmphdr))
2879 ndpi_set_risk(ndpi_str, flow, NDPI_MALFORMED_PACKET);
2880 else {
2881 u_int8_t icmp6_type = (u_int8_t)flow->packet.payload[0];
2882 u_int8_t icmp6_code = (u_int8_t)flow->packet.payload[1];
2883
2884 /* https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol_for_IPv6 */
2885 if(((icmp6_type >= 5) && (icmp6_type <= 127))
2886 || (icmp6_type >= 156)
2887 || ((icmp6_code > 7) && (icmp6_type != 255)))
2888 ndpi_set_risk(ndpi_str, flow, NDPI_MALFORMED_PACKET);
2889 }
2890 }
2891 return(NDPI_PROTOCOL_IP_ICMPV6);
2892 break;
2893 case 112:
2894 return(NDPI_PROTOCOL_IP_VRRP);
2895 break;
2896 }
2897 }
2898
2899 return(NDPI_PROTOCOL_UNKNOWN);
2900 }
2901
2902 /* ******************************************************************** */
2903
ndpi_get_num_supported_protocols(struct ndpi_detection_module_struct * ndpi_str)2904 u_int ndpi_get_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_str) {
2905 return(ndpi_str->ndpi_num_supported_protocols);
2906 }
2907
2908 /* ******************************************************************** */
2909
2910 #ifdef WIN32
strsep(char ** sp,char * sep)2911 char *strsep(char **sp, char *sep) {
2912 char *p, *s;
2913 if(sp == NULL || *sp == NULL || **sp == '\0')
2914 return(NULL);
2915 s = *sp;
2916 p = s + strcspn(s, sep);
2917 if(*p != '\0')
2918 *p++ = '\0';
2919 *sp = p;
2920 return(s);
2921 }
2922 #endif
2923
2924 /* ******************************************************************** */
2925
ndpi_add_ip_risk_mask(struct ndpi_detection_module_struct * ndpi_str,char * ip,ndpi_risk mask)2926 int ndpi_add_ip_risk_mask(struct ndpi_detection_module_struct *ndpi_str,
2927 char *ip, ndpi_risk mask) {
2928 char *saveptr, *addr = strtok_r(ip, "/", &saveptr);
2929
2930 if(addr) {
2931 char *cidr = strtok_r(NULL, "\n", &saveptr);
2932 struct in_addr pin;
2933 ndpi_patricia_node_t *node;
2934
2935 pin.s_addr = inet_addr(addr);
2936 /* FIX: Add IPv6 support */
2937 if((node = add_to_ptree(ndpi_str->ip_risk_mask_ptree, AF_INET,
2938 &pin, cidr ? atoi(cidr) : 32 /* bits */)) != NULL) {
2939 node->value.u.uv64 = (u_int64_t)mask;
2940 return(0);
2941 } else
2942 return(-1);
2943 } else
2944 return(-2);
2945 }
2946
2947 /* ******************************************************************** */
2948
ndpi_add_host_risk_mask(struct ndpi_detection_module_struct * ndpi_str,char * host,ndpi_risk mask)2949 int ndpi_add_host_risk_mask(struct ndpi_detection_module_struct *ndpi_str,
2950 char *host, ndpi_risk mask) {
2951 AC_PATTERN_t ac_pattern;
2952 AC_ERROR_t rc;
2953 u_int len;
2954 char *host_dup = NULL;
2955
2956 if((ndpi_str->host_risk_mask_automa.ac_automa == NULL) || (host == NULL))
2957 return(-2);
2958
2959 /* Zap heading/trailing quotes */
2960 switch(host[0]) {
2961 case '"':
2962 case '\'':
2963 {
2964 int len;
2965
2966 host = &host[1];
2967 len = strlen(host);
2968 if(len > 0)
2969 host[len-1] = '\0';
2970 }
2971
2972 break;
2973 }
2974
2975 host_dup = ndpi_strdup(host);
2976 if(!host_dup)
2977 return(-1);
2978
2979 memset(&ac_pattern, 0, sizeof(ac_pattern));
2980
2981 len = strlen(host);
2982
2983 ac_pattern.astring = host_dup;
2984 ac_pattern.length = len;
2985 ac_pattern.rep.number64 = (ndpi_risk)mask;
2986 ac_pattern.rep.level = ndpi_domain_level(host);
2987 ac_pattern.rep.at_end = 0;
2988 ac_pattern.rep.dot = memchr(host,'.',len) != NULL;
2989
2990 rc = ac_automata_add(ndpi_str->host_risk_mask_automa.ac_automa, &ac_pattern);
2991
2992 if(rc != ACERR_SUCCESS) {
2993 ndpi_free(host_dup);
2994
2995 if(rc != ACERR_DUPLICATE_PATTERN)
2996 return (-2);
2997 }
2998
2999 return(0);
3000 }
3001
3002 /* ******************************************************************** */
3003
ndpi_handle_rule(struct ndpi_detection_module_struct * ndpi_str,char * rule,u_int8_t do_add)3004 int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str, char *rule, u_int8_t do_add) {
3005 char *at, *proto, *elem;
3006 ndpi_proto_defaults_t *def;
3007 u_int16_t subprotocol_id, i;
3008
3009 at = strrchr(rule, '@');
3010 if(at == NULL) {
3011 /* This looks like a mask rule or an invalid rule */
3012 char _rule[256], *rule_type, *key;
3013
3014 snprintf(_rule, sizeof(_rule), "%s", rule);
3015 rule_type = strtok(rule, ":");
3016
3017 if(!rule_type) {
3018 NDPI_LOG_ERR(ndpi_str, "Invalid rule '%s'\n", rule);
3019 return(-1);
3020 }
3021
3022 key = strtok(NULL, "=");
3023
3024 if(key) {
3025 char *mask = strtok(NULL, "=");
3026
3027 if(mask) {
3028 ndpi_risk risk_mask = (ndpi_risk)atoll(mask);
3029
3030 if(!strcmp(rule_type, "ip_risk_mask")) {
3031 return(ndpi_add_ip_risk_mask(ndpi_str, key, risk_mask));
3032 } else if(!strcmp(rule_type, "host_risk_mask")) {
3033 return(ndpi_add_host_risk_mask(ndpi_str, key, risk_mask));
3034 }
3035 }
3036 }
3037
3038 NDPI_LOG_ERR(ndpi_str, "Unknown rule '%s'\n", rule);
3039 return(-1);
3040 } else
3041 at[0] = 0, proto = &at[1];
3042
3043 for(i = 0; proto[i] != '\0'; i++) {
3044 switch(proto[i]) {
3045 case '/':
3046 case '&':
3047 case '^':
3048 case ':':
3049 case ';':
3050 case '\'':
3051 case '"':
3052 case ' ':
3053 proto[i] = '_';
3054 break;
3055 }
3056 }
3057
3058 for(i = 0, def = NULL; i < (int) ndpi_str->ndpi_num_supported_protocols; i++) {
3059 if(ndpi_str->proto_defaults[i].protoName
3060 && strcasecmp(ndpi_str->proto_defaults[i].protoName, proto) == 0) {
3061 def = &ndpi_str->proto_defaults[i];
3062 subprotocol_id = i;
3063 break;
3064 }
3065 }
3066
3067 if(def == NULL) {
3068 if(!do_add) {
3069 /* We need to remove a rule */
3070 NDPI_LOG_ERR(ndpi_str, "Unable to find protocol '%s': skipping rule '%s'\n", proto, rule);
3071 return(-3);
3072 } else {
3073 ndpi_port_range ports_a[MAX_DEFAULT_PORTS], ports_b[MAX_DEFAULT_PORTS];
3074
3075 if(ndpi_str->ndpi_num_custom_protocols >= (NDPI_MAX_NUM_CUSTOM_PROTOCOLS - 1)) {
3076 NDPI_LOG_ERR(ndpi_str, "Too many protocols defined (%u): skipping protocol %s\n",
3077 ndpi_str->ndpi_num_custom_protocols, proto);
3078 return(-2);
3079 }
3080
3081 ndpi_set_proto_defaults(ndpi_str, 1, NDPI_PROTOCOL_ACCEPTABLE,
3082 ndpi_str->ndpi_num_supported_protocols, proto,
3083 NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, /* TODO add protocol category support in rules */
3084 ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
3085 ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
3086 def = &ndpi_str->proto_defaults[ndpi_str->ndpi_num_supported_protocols];
3087 subprotocol_id = ndpi_str->ndpi_num_supported_protocols;
3088 ndpi_str->ndpi_num_supported_protocols++, ndpi_str->ndpi_num_custom_protocols++;
3089 }
3090 }
3091
3092 while((elem = strsep(&rule, ",")) != NULL) {
3093 char *attr = elem, *value = NULL;
3094 ndpi_port_range range;
3095 int is_tcp = 0, is_udp = 0, is_ip = 0;
3096
3097 if(strncmp(attr, "tcp:", 4) == 0)
3098 is_tcp = 1, value = &attr[4];
3099 else if(strncmp(attr, "udp:", 4) == 0)
3100 is_udp = 1, value = &attr[4];
3101 else if(strncmp(attr, "ip:", 3) == 0)
3102 is_ip = 1, value = &attr[3];
3103 else if(strncmp(attr, "host:", 5) == 0) {
3104 /* host:"<value>",host:"<value>",.....@<subproto> */
3105 u_int i, max_len;
3106
3107 value = &attr[5];
3108 if(value[0] == '"')
3109 value++; /* remove leading " */
3110
3111 max_len = strlen(value) - 1;
3112 if(value[max_len] == '"')
3113 value[max_len] = '\0'; /* remove trailing " */
3114
3115 for(i=0; i<max_len; i++) value[i] = tolower(value[i]);
3116 }
3117
3118 if(is_tcp || is_udp) {
3119 u_int p_low, p_high;
3120
3121 if(sscanf(value, "%u-%u", &p_low, &p_high) == 2)
3122 range.port_low = p_low, range.port_high = p_high;
3123 else
3124 range.port_low = range.port_high = atoi(&elem[4]);
3125
3126 if(do_add)
3127 addDefaultPort(ndpi_str, &range, def, 1 /* Custom user proto */,
3128 is_tcp ? &ndpi_str->tcpRoot : &ndpi_str->udpRoot, __FUNCTION__, __LINE__);
3129 else
3130 removeDefaultPort(&range, def, is_tcp ? &ndpi_str->tcpRoot : &ndpi_str->udpRoot);
3131 } else if(is_ip) {
3132 /* NDPI_PROTOCOL_TOR */
3133 ndpi_add_host_ip_subprotocol(ndpi_str, value, subprotocol_id);
3134 } else {
3135 if(do_add)
3136 ndpi_add_host_url_subprotocol(ndpi_str, value, subprotocol_id, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED,
3137 NDPI_PROTOCOL_ACCEPTABLE, 0);
3138 else
3139 ndpi_remove_host_url_subprotocol(ndpi_str, value, subprotocol_id);
3140 }
3141 }
3142
3143 return(0);
3144 }
3145
3146 /* ******************************************************************** */
3147
3148 /*
3149 * Format:
3150 *
3151 * <host|ip> <category_id>
3152 *
3153 * Notes:
3154 * - host and category are separated by a single TAB
3155 * - empty lines or lines starting with # are ignored
3156 */
ndpi_load_categories_file(struct ndpi_detection_module_struct * ndpi_str,const char * path)3157 int ndpi_load_categories_file(struct ndpi_detection_module_struct *ndpi_str, const char *path) {
3158 char buffer[512], *line, *name, *category, *saveptr;
3159 FILE *fd;
3160 int len, num = 0;
3161
3162 fd = fopen(path, "r");
3163
3164 if(fd == NULL) {
3165 NDPI_LOG_ERR(ndpi_str, "Unable to open file %s [%s]\n", path, strerror(errno));
3166 return(-1);
3167 }
3168
3169 while(1) {
3170 line = fgets(buffer, sizeof(buffer), fd);
3171
3172 if(line == NULL)
3173 break;
3174
3175 len = strlen(line);
3176
3177 if((len <= 1) || (line[0] == '#'))
3178 continue;
3179
3180 line[len - 1] = '\0';
3181 name = strtok_r(line, "\t", &saveptr);
3182
3183 if(name) {
3184 category = strtok_r(NULL, "\t", &saveptr);
3185
3186 if(category) {
3187 int rc = ndpi_load_category(ndpi_str, name, (ndpi_protocol_category_t) atoi(category));
3188
3189 if(rc >= 0)
3190 num++;
3191 }
3192 }
3193 }
3194
3195 fclose(fd);
3196 ndpi_enable_loaded_categories(ndpi_str);
3197
3198 return(num);
3199 }
3200
3201 /* ******************************************************************** */
3202
ndpi_load_risky_domain(struct ndpi_detection_module_struct * ndpi_str,char * domain_name)3203 static int ndpi_load_risky_domain(struct ndpi_detection_module_struct *ndpi_str,
3204 char* domain_name) {
3205 if(ndpi_str->risky_domain_automa.ac_automa == NULL) {
3206 ndpi_str->risky_domain_automa.ac_automa = ac_automata_init(ac_domain_match_handler);
3207 if(!ndpi_str->risky_domain_automa.ac_automa) return -1;
3208 ac_automata_feature(ndpi_str->risky_domain_automa.ac_automa,AC_FEATURE_LC);
3209 ac_automata_name(ndpi_str->risky_domain_automa.ac_automa, "risky", 0);
3210 }
3211
3212 if(!ndpi_str->risky_domain_automa.ac_automa)
3213 return -1;
3214
3215 return ndpi_string_to_automa(ndpi_str, (AC_AUTOMATA_t *)ndpi_str->risky_domain_automa.ac_automa,
3216 domain_name, 1, 0, 0, 0, 1); /* domain, protocol, category, breed, level , at_end */
3217 }
3218
3219 /* ******************************************************************** */
3220
3221 /*
3222 * Format:
3223 *
3224 * <domain name>
3225 *
3226 * Notes:
3227 * - you can add a .<domain name> to avoid mismatches
3228 */
ndpi_load_risk_domain_file(struct ndpi_detection_module_struct * ndpi_str,const char * path)3229 int ndpi_load_risk_domain_file(struct ndpi_detection_module_struct *ndpi_str, const char *path) {
3230 char buffer[128], *line;
3231 FILE *fd;
3232 int len, num = 0;
3233
3234 fd = fopen(path, "r");
3235
3236 if(fd == NULL) {
3237 NDPI_LOG_ERR(ndpi_str, "Unable to open file %s [%s]\n", path, strerror(errno));
3238 return(-1);
3239 }
3240
3241 while(1) {
3242 line = fgets(buffer, sizeof(buffer), fd);
3243
3244 if(line == NULL)
3245 break;
3246
3247 len = strlen(line);
3248
3249 if((len <= 1) || (line[0] == '#'))
3250 continue;
3251
3252 line[len - 1] = '\0';
3253
3254 if(ndpi_load_risky_domain(ndpi_str, line) >= 0)
3255 num++;
3256 }
3257
3258 fclose(fd);
3259
3260 if(ndpi_str->risky_domain_automa.ac_automa)
3261 ac_automata_finalize((AC_AUTOMATA_t *)ndpi_str->risky_domain_automa.ac_automa);
3262
3263 return(num);
3264 }
3265
3266 /* ******************************************************************** */
3267
3268 /*
3269 * Format:
3270 *
3271 * <ja3 hash>[,<other info>]
3272 *
3273 */
ndpi_load_malicious_ja3_file(struct ndpi_detection_module_struct * ndpi_str,const char * path)3274 int ndpi_load_malicious_ja3_file(struct ndpi_detection_module_struct *ndpi_str, const char *path) {
3275 char buffer[128], *line, *str;
3276 FILE *fd;
3277 int len, num = 0;
3278
3279 if(ndpi_str->malicious_ja3_automa.ac_automa == NULL)
3280 ndpi_str->malicious_ja3_automa.ac_automa = ac_automata_init(NULL);
3281 if(ndpi_str->malicious_ja3_automa.ac_automa)
3282 ac_automata_name(ndpi_str->malicious_ja3_automa.ac_automa,"ja3",0);
3283
3284 fd = fopen(path, "r");
3285
3286 if(fd == NULL) {
3287 NDPI_LOG_ERR(ndpi_str, "Unable to open file %s [%s]\n", path, strerror(errno));
3288 return(-1);
3289 }
3290
3291 while(1) {
3292 char *comma;
3293
3294 line = fgets(buffer, sizeof(buffer), fd);
3295
3296 if(line == NULL)
3297 break;
3298
3299 len = strlen(line);
3300
3301 if((len <= 1) || (line[0] == '#'))
3302 continue;
3303
3304 line[len - 1] = '\0';
3305
3306 if((comma = strchr(line, ',')) != NULL)
3307 comma[0] = '\0';
3308
3309 str = ndpi_strdup(line);
3310 if (str == NULL) {
3311 NDPI_LOG_ERR(ndpi_str, "Memory allocation failure\n");
3312 return -1;
3313 };
3314
3315 if(ndpi_add_string_to_automa(ndpi_str->malicious_ja3_automa.ac_automa, str) >= 0)
3316 num++;
3317 }
3318
3319 fclose(fd);
3320
3321 return(num);
3322 }
3323
3324 /* ******************************************************************** */
3325
3326 /*
3327 * Format:
3328 *
3329 * <sha1 hash>
3330 * <other info>,<sha1 hash>
3331 * <other info>,<sha1 hash>[,<other info>[...]]
3332 *
3333 */
ndpi_load_malicious_sha1_file(struct ndpi_detection_module_struct * ndpi_str,const char * path)3334 int ndpi_load_malicious_sha1_file(struct ndpi_detection_module_struct *ndpi_str, const char *path)
3335 {
3336 char buffer[128];
3337 char *first_comma, *second_comma, *str;
3338 FILE *fd;
3339 size_t len;
3340 int num = 0;
3341
3342 if (ndpi_str->malicious_sha1_automa.ac_automa == NULL)
3343 ndpi_str->malicious_sha1_automa.ac_automa = ac_automata_init(NULL);
3344 if(ndpi_str->malicious_sha1_automa.ac_automa)
3345 ac_automata_name(ndpi_str->malicious_sha1_automa.ac_automa,"sha1",0);
3346
3347 fd = fopen(path, "r");
3348
3349 if (fd == NULL) {
3350 NDPI_LOG_ERR(ndpi_str, "Unable to open file %s [%s]\n", path, strerror(errno));
3351 return -1;
3352 }
3353
3354 while (fgets(buffer, sizeof(buffer), fd) != NULL) {
3355 len = strlen(buffer);
3356
3357 if (len <= 1 || buffer[0] == '#')
3358 continue;
3359
3360 first_comma = strchr(buffer, ',');
3361 if (first_comma != NULL) {
3362 first_comma++;
3363 second_comma = strchr(first_comma, ',');
3364 if (second_comma == NULL)
3365 second_comma = &buffer[len - 1];
3366 } else {
3367 first_comma = &buffer[0];
3368 second_comma = &buffer[len - 1];
3369 }
3370
3371 if ((second_comma - first_comma) != 40)
3372 continue;
3373 second_comma[0] = '\0';
3374
3375 for (size_t i = 0; i < 40; ++i)
3376 first_comma[i] = toupper(first_comma[i]);
3377
3378 str = ndpi_strdup(first_comma);
3379 if (str == NULL) {
3380 NDPI_LOG_ERR(ndpi_str, "Memory allocation failure\n");
3381 return -1;
3382 };
3383
3384 if (ndpi_add_string_to_automa(ndpi_str->malicious_sha1_automa.ac_automa, str) >= 0)
3385 num++;
3386 }
3387
3388 return num;
3389 }
3390
3391 /* ******************************************************************** */
3392
3393 /*
3394 Format:
3395 <tcp|udp>:<port>,<tcp|udp>:<port>,.....@<proto>
3396
3397 Subprotocols Format:
3398 host:"<value>",host:"<value>",.....@<subproto>
3399
3400 IP based Subprotocols Format (<value> is IP or CIDR):
3401 ip:<value>,ip:<value>,.....@<subproto>
3402
3403 Example:
3404 tcp:80,tcp:3128@HTTP
3405 udp:139@NETBIOS
3406
3407 */
ndpi_load_protocols_file(struct ndpi_detection_module_struct * ndpi_str,const char * path)3408 int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_str, const char *path) {
3409 FILE *fd;
3410 char *buffer, *old_buffer;
3411 int chunk_len = 512, buffer_len = chunk_len, old_buffer_len;
3412 int i, rc = -1;
3413
3414 fd = fopen(path, "r");
3415
3416 if(fd == NULL) {
3417 NDPI_LOG_ERR(ndpi_str, "Unable to open file %s [%s]\n", path, strerror(errno));
3418 goto error;
3419 }
3420
3421 buffer = ndpi_malloc(buffer_len);
3422
3423 if(buffer == NULL) {
3424 NDPI_LOG_ERR(ndpi_str, "Memory allocation failure\n");
3425 goto close_fd;
3426 }
3427
3428 while(1) {
3429 char *line = buffer;
3430 int line_len = buffer_len;
3431
3432 while((line = fgets(line, line_len, fd)) != NULL && line[strlen(line) - 1] != '\n') {
3433 i = strlen(line);
3434 old_buffer = buffer;
3435 old_buffer_len = buffer_len;
3436 buffer_len += chunk_len;
3437
3438 buffer = ndpi_realloc(old_buffer, old_buffer_len, buffer_len);
3439
3440 if(buffer == NULL) {
3441 NDPI_LOG_ERR(ndpi_str, "Memory allocation failure\n");
3442 ndpi_free(old_buffer);
3443 goto close_fd;
3444 }
3445
3446 line = &buffer[i];
3447 line_len = chunk_len;
3448 }
3449
3450 if(!line) /* safety check */
3451 break;
3452
3453 i = strlen(buffer);
3454 if((i <= 1) || (buffer[0] == '#'))
3455 continue;
3456 else
3457 buffer[i - 1] = '\0';
3458
3459 ndpi_handle_rule(ndpi_str, buffer, 1);
3460 }
3461
3462 rc = 0;
3463
3464 ndpi_free(buffer);
3465
3466 close_fd:
3467 fclose(fd);
3468
3469 error:
3470 return(rc);
3471 }
3472
3473 /* ******************************************************************** */
3474
3475 /* ntop */
ndpi_set_bitmask_protocol_detection(char * label,struct ndpi_detection_module_struct * ndpi_str,const NDPI_PROTOCOL_BITMASK * detection_bitmask,const u_int32_t idx,u_int16_t ndpi_protocol_id,void (* func)(struct ndpi_detection_module_struct *,struct ndpi_flow_struct * flow),const NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_bitmask,u_int8_t b_save_bitmask_unknow,u_int8_t b_add_detection_bitmask)3476 void ndpi_set_bitmask_protocol_detection(char *label, struct ndpi_detection_module_struct *ndpi_str,
3477 const NDPI_PROTOCOL_BITMASK *detection_bitmask, const u_int32_t idx,
3478 u_int16_t ndpi_protocol_id,
3479 void (*func)(struct ndpi_detection_module_struct *,
3480 struct ndpi_flow_struct *flow),
3481 const NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_bitmask,
3482 u_int8_t b_save_bitmask_unknow, u_int8_t b_add_detection_bitmask) {
3483 /*
3484 Compare specify protocol bitmask with main detection bitmask
3485 */
3486 if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(*detection_bitmask, ndpi_protocol_id) != 0) {
3487 #ifdef DEBUG
3488 NDPI_LOG_DBG2(ndpi_str,
3489 "[NDPI] ndpi_set_bitmask_protocol_detection: %s : [callback_buffer] idx= %u, [proto_defaults] "
3490 "protocol_id=%u\n",
3491 label, idx, ndpi_protocol_id);
3492 #endif
3493
3494 if(ndpi_str->proto_defaults[ndpi_protocol_id].protoIdx != 0) {
3495 NDPI_LOG_DBG2(ndpi_str, "[NDPI] Internal error: protocol %s/%u has been already registered\n", label,
3496 ndpi_protocol_id);
3497 #ifdef DEBUG
3498 } else {
3499 NDPI_LOG_DBG2(ndpi_str, "[NDPI] Adding %s with protocol id %d\n", label, ndpi_protocol_id);
3500 #endif
3501 }
3502
3503 /*
3504 Set function and index protocol within proto_default structure for port protocol detection
3505 and callback_buffer function for DPI protocol detection
3506 */
3507 ndpi_str->proto_defaults[ndpi_protocol_id].protoIdx = idx;
3508 ndpi_str->proto_defaults[ndpi_protocol_id].func = ndpi_str->callback_buffer[idx].func = func;
3509 ndpi_str->callback_buffer[idx].ndpi_protocol_id = ndpi_protocol_id;
3510
3511 /*
3512 Set ndpi_selection_bitmask for protocol
3513 */
3514 ndpi_str->callback_buffer[idx].ndpi_selection_bitmask = ndpi_selection_bitmask;
3515
3516 /*
3517 Reset protocol detection bitmask via NDPI_PROTOCOL_UNKNOWN and than add specify protocol bitmast to callback
3518 buffer.
3519 */
3520 if(b_save_bitmask_unknow)
3521 NDPI_SAVE_AS_BITMASK(ndpi_str->callback_buffer[idx].detection_bitmask, NDPI_PROTOCOL_UNKNOWN);
3522 if(b_add_detection_bitmask)
3523 NDPI_ADD_PROTOCOL_TO_BITMASK(ndpi_str->callback_buffer[idx].detection_bitmask, ndpi_protocol_id);
3524
3525 NDPI_SAVE_AS_BITMASK(ndpi_str->callback_buffer[idx].excluded_protocol_bitmask, ndpi_protocol_id);
3526 }
3527 }
3528
3529 /* ******************************************************************** */
3530
ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct * ndpi_str,const NDPI_PROTOCOL_BITMASK * dbm)3531 void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_str,
3532 const NDPI_PROTOCOL_BITMASK *dbm) {
3533 NDPI_PROTOCOL_BITMASK detection_bitmask_local;
3534 NDPI_PROTOCOL_BITMASK *detection_bitmask = &detection_bitmask_local;
3535 u_int32_t a = 0;
3536
3537 NDPI_BITMASK_SET(detection_bitmask_local, *dbm);
3538 NDPI_BITMASK_SET(ndpi_str->detection_bitmask, *dbm);
3539
3540 /* set this here to zero to be interrupt safe */
3541 ndpi_str->callback_buffer_size = 0;
3542
3543 /* HTTP */
3544 init_http_dissector(ndpi_str, &a, detection_bitmask);
3545
3546 /* STARCRAFT */
3547 init_starcraft_dissector(ndpi_str, &a, detection_bitmask);
3548
3549 /* TLS+DTLS */
3550 init_tls_dissector(ndpi_str, &a, detection_bitmask);
3551
3552 /* STUN */
3553 init_stun_dissector(ndpi_str, &a, detection_bitmask);
3554
3555 /* RTP */
3556 init_rtp_dissector(ndpi_str, &a, detection_bitmask);
3557
3558 /* RTSP */
3559 init_rtsp_dissector(ndpi_str, &a, detection_bitmask);
3560
3561 /* RDP */
3562 init_rdp_dissector(ndpi_str, &a, detection_bitmask);
3563
3564 /* SIP */
3565 init_sip_dissector(ndpi_str, &a, detection_bitmask);
3566
3567 /* IMO */
3568 init_imo_dissector(ndpi_str, &a, detection_bitmask);
3569
3570 /* Teredo */
3571 init_teredo_dissector(ndpi_str, &a, detection_bitmask);
3572
3573 /* EDONKEY */
3574 init_edonkey_dissector(ndpi_str, &a, detection_bitmask);
3575
3576 /* FASTTRACK */
3577 init_fasttrack_dissector(ndpi_str, &a, detection_bitmask);
3578
3579 /* GNUTELLA */
3580 init_gnutella_dissector(ndpi_str, &a, detection_bitmask);
3581
3582 /* DIRECTCONNECT */
3583 init_directconnect_dissector(ndpi_str, &a, detection_bitmask);
3584
3585 /* NATS */
3586 init_nats_dissector(ndpi_str, &a, detection_bitmask);
3587
3588 /* APPLEJUICE */
3589 init_applejuice_dissector(ndpi_str, &a, detection_bitmask);
3590
3591 /* SOULSEEK */
3592 init_soulseek_dissector(ndpi_str, &a, detection_bitmask);
3593
3594 /* SOCKS */
3595 init_socks_dissector(ndpi_str, &a, detection_bitmask);
3596
3597 /* IRC */
3598 init_irc_dissector(ndpi_str, &a, detection_bitmask);
3599
3600 /* JABBER */
3601 init_jabber_dissector(ndpi_str, &a, detection_bitmask);
3602
3603 /* MAIL_POP */
3604 init_mail_pop_dissector(ndpi_str, &a, detection_bitmask);
3605
3606 /* MAIL_IMAP */
3607 init_mail_imap_dissector(ndpi_str, &a, detection_bitmask);
3608
3609 /* MAIL_SMTP */
3610 init_mail_smtp_dissector(ndpi_str, &a, detection_bitmask);
3611
3612 /* USENET */
3613 init_usenet_dissector(ndpi_str, &a, detection_bitmask);
3614
3615 /* DNS */
3616 init_dns_dissector(ndpi_str, &a, detection_bitmask);
3617
3618 /* VMWARE */
3619 init_vmware_dissector(ndpi_str, &a, detection_bitmask);
3620
3621 /* NON_TCP_UDP */
3622 init_non_tcp_udp_dissector(ndpi_str, &a, detection_bitmask);
3623
3624 /* SOPCAST */
3625 init_sopcast_dissector(ndpi_str, &a, detection_bitmask);
3626
3627 /* TVUPLAYER */
3628 init_tvuplayer_dissector(ndpi_str, &a, detection_bitmask);
3629
3630 /* PPSTREAM */
3631 init_ppstream_dissector(ndpi_str, &a, detection_bitmask);
3632
3633 /* IAX */
3634 init_iax_dissector(ndpi_str, &a, detection_bitmask);
3635
3636 /* MGPC */
3637 init_mgpc_dissector(ndpi_str, &a, detection_bitmask);
3638
3639 /* ZATTOO */
3640 init_zattoo_dissector(ndpi_str, &a, detection_bitmask);
3641
3642 /* QQ */
3643 init_qq_dissector(ndpi_str, &a, detection_bitmask);
3644
3645 /* SSH */
3646 init_ssh_dissector(ndpi_str, &a, detection_bitmask);
3647
3648 /* AYIYA */
3649 init_ayiya_dissector(ndpi_str, &a, detection_bitmask);
3650
3651 /* THUNDER */
3652 init_thunder_dissector(ndpi_str, &a, detection_bitmask);
3653
3654 /* VNC */
3655 init_vnc_dissector(ndpi_str, &a, detection_bitmask);
3656
3657 /* TEAMVIEWER */
3658 init_teamviewer_dissector(ndpi_str, &a, detection_bitmask);
3659
3660 /* DHCP */
3661 init_dhcp_dissector(ndpi_str, &a, detection_bitmask);
3662
3663 /* STEAM */
3664 init_steam_dissector(ndpi_str, &a, detection_bitmask);
3665
3666 /* HALFLIFE2 */
3667 init_halflife2_dissector(ndpi_str, &a, detection_bitmask);
3668
3669 /* XBOX */
3670 init_xbox_dissector(ndpi_str, &a, detection_bitmask);
3671
3672 /* SMB */
3673 init_smb_dissector(ndpi_str, &a, detection_bitmask);
3674
3675 /* MINING */
3676 init_mining_dissector(ndpi_str, &a, detection_bitmask);
3677
3678 /* TELNET */
3679 init_telnet_dissector(ndpi_str, &a, detection_bitmask);
3680
3681 /* NTP */
3682 init_ntp_dissector(ndpi_str, &a, detection_bitmask);
3683
3684 /* NFS */
3685 init_nfs_dissector(ndpi_str, &a, detection_bitmask);
3686
3687 /* SSDP */
3688 init_ssdp_dissector(ndpi_str, &a, detection_bitmask);
3689
3690 /* WORLD_OF_WARCRAFT */
3691 init_world_of_warcraft_dissector(ndpi_str, &a, detection_bitmask);
3692
3693 /* POSTGRES */
3694 init_postgres_dissector(ndpi_str, &a, detection_bitmask);
3695
3696 /* MYSQL */
3697 init_mysql_dissector(ndpi_str, &a, detection_bitmask);
3698
3699 /* BGP */
3700 init_bgp_dissector(ndpi_str, &a, detection_bitmask);
3701
3702 /* SNMP */
3703 init_snmp_dissector(ndpi_str, &a, detection_bitmask);
3704
3705 /* KONTIKI */
3706 init_kontiki_dissector(ndpi_str, &a, detection_bitmask);
3707
3708 /* ICECAST */
3709 init_icecast_dissector(ndpi_str, &a, detection_bitmask);
3710
3711 /* SHOUTCAST */
3712 init_shoutcast_dissector(ndpi_str, &a, detection_bitmask);
3713
3714 /* KERBEROS */
3715 init_kerberos_dissector(ndpi_str, &a, detection_bitmask);
3716
3717 /* OPENFT */
3718 init_openft_dissector(ndpi_str, &a, detection_bitmask);
3719
3720 /* SYSLOG */
3721 init_syslog_dissector(ndpi_str, &a, detection_bitmask);
3722
3723 /* DIRECT_DOWNLOAD_LINK */
3724 init_directdownloadlink_dissector(ndpi_str, &a, detection_bitmask);
3725
3726 /* NETBIOS */
3727 init_netbios_dissector(ndpi_str, &a, detection_bitmask);
3728
3729 /* IPP */
3730 init_ipp_dissector(ndpi_str, &a, detection_bitmask);
3731
3732 /* LDAP */
3733 init_ldap_dissector(ndpi_str, &a, detection_bitmask);
3734
3735 /* WARCRAFT3 */
3736 init_warcraft3_dissector(ndpi_str, &a, detection_bitmask);
3737
3738 /* XDMCP */
3739 init_xdmcp_dissector(ndpi_str, &a, detection_bitmask);
3740
3741 /* TFTP */
3742 init_tftp_dissector(ndpi_str, &a, detection_bitmask);
3743
3744 /* MSSQL_TDS */
3745 init_mssql_tds_dissector(ndpi_str, &a, detection_bitmask);
3746
3747 /* PPTP */
3748 init_pptp_dissector(ndpi_str, &a, detection_bitmask);
3749
3750 /* STEALTHNET */
3751 init_stealthnet_dissector(ndpi_str, &a, detection_bitmask);
3752
3753 /* DHCPV6 */
3754 init_dhcpv6_dissector(ndpi_str, &a, detection_bitmask);
3755
3756 /* AFP */
3757 init_afp_dissector(ndpi_str, &a, detection_bitmask);
3758
3759 /* check_mk */
3760 init_checkmk_dissector(ndpi_str, &a, detection_bitmask);
3761
3762 /* cpha */
3763 init_cpha_dissector(ndpi_str, &a, detection_bitmask);
3764
3765 /* AIMINI */
3766 init_aimini_dissector(ndpi_str, &a, detection_bitmask);
3767
3768 /* FLORENSIA */
3769 init_florensia_dissector(ndpi_str, &a, detection_bitmask);
3770
3771 /* MAPLESTORY */
3772 init_maplestory_dissector(ndpi_str, &a, detection_bitmask);
3773
3774 /* DOFUS */
3775 init_dofus_dissector(ndpi_str, &a, detection_bitmask);
3776
3777 /* WORLD_OF_KUNG_FU */
3778 init_world_of_kung_fu_dissector(ndpi_str, &a, detection_bitmask);
3779
3780 /* FIESTA */
3781 init_fiesta_dissector(ndpi_str, &a, detection_bitmask);
3782
3783 /* CROSSIFIRE */
3784 init_crossfire_dissector(ndpi_str, &a, detection_bitmask);
3785
3786 /* GUILDWARS */
3787 init_guildwars_dissector(ndpi_str, &a, detection_bitmask);
3788
3789 /* ARMAGETRON */
3790 init_armagetron_dissector(ndpi_str, &a, detection_bitmask);
3791
3792 /* DROPBOX */
3793 init_dropbox_dissector(ndpi_str, &a, detection_bitmask);
3794
3795 /* SPOTIFY */
3796 init_spotify_dissector(ndpi_str, &a, detection_bitmask);
3797
3798 /* RADIUS */
3799 init_radius_dissector(ndpi_str, &a, detection_bitmask);
3800
3801 /* CITRIX */
3802 init_citrix_dissector(ndpi_str, &a, detection_bitmask);
3803
3804 /* LOTUS_NOTES */
3805 init_lotus_notes_dissector(ndpi_str, &a, detection_bitmask);
3806
3807 /* GTP */
3808 init_gtp_dissector(ndpi_str, &a, detection_bitmask);
3809
3810 /* DCERPC */
3811 init_dcerpc_dissector(ndpi_str, &a, detection_bitmask);
3812
3813 /* NETFLOW */
3814 init_netflow_dissector(ndpi_str, &a, detection_bitmask);
3815
3816 /* SFLOW */
3817 init_sflow_dissector(ndpi_str, &a, detection_bitmask);
3818
3819 /* H323 */
3820 init_h323_dissector(ndpi_str, &a, detection_bitmask);
3821
3822 /* OPENVPN */
3823 init_openvpn_dissector(ndpi_str, &a, detection_bitmask);
3824
3825 /* NOE */
3826 init_noe_dissector(ndpi_str, &a, detection_bitmask);
3827
3828 /* CISCOVPN */
3829 init_ciscovpn_dissector(ndpi_str, &a, detection_bitmask);
3830
3831 /* TEAMSPEAK */
3832 init_teamspeak_dissector(ndpi_str, &a, detection_bitmask);
3833
3834 /* SKINNY */
3835 init_skinny_dissector(ndpi_str, &a, detection_bitmask);
3836
3837 /* RTCP */
3838 init_rtcp_dissector(ndpi_str, &a, detection_bitmask);
3839
3840 /* RSYNC */
3841 init_rsync_dissector(ndpi_str, &a, detection_bitmask);
3842
3843 /* WHOIS_DAS */
3844 init_whois_das_dissector(ndpi_str, &a, detection_bitmask);
3845
3846 /* ORACLE */
3847 init_oracle_dissector(ndpi_str, &a, detection_bitmask);
3848
3849 /* CORBA */
3850 init_corba_dissector(ndpi_str, &a, detection_bitmask);
3851
3852 /* RTMP */
3853 init_rtmp_dissector(ndpi_str, &a, detection_bitmask);
3854
3855 /* FTP_CONTROL */
3856 init_ftp_control_dissector(ndpi_str, &a, detection_bitmask);
3857
3858 /* FTP_DATA */
3859 init_ftp_data_dissector(ndpi_str, &a, detection_bitmask);
3860
3861 /* MEGACO */
3862 init_megaco_dissector(ndpi_str, &a, detection_bitmask);
3863
3864 /* REDIS */
3865 init_redis_dissector(ndpi_str, &a, detection_bitmask);
3866
3867 /* VHUA */
3868 init_vhua_dissector(ndpi_str, &a, detection_bitmask);
3869
3870 /* ZMQ */
3871 init_zmq_dissector(ndpi_str, &a, detection_bitmask);
3872
3873 /* TELEGRAM */
3874 init_telegram_dissector(ndpi_str, &a, detection_bitmask);
3875
3876 /* QUIC */
3877 init_quic_dissector(ndpi_str, &a, detection_bitmask);
3878
3879 /* DIAMETER */
3880 init_diameter_dissector(ndpi_str, &a, detection_bitmask);
3881
3882 /* APPLE_PUSH */
3883 init_apple_push_dissector(ndpi_str, &a, detection_bitmask);
3884
3885 /* EAQ */
3886 init_eaq_dissector(ndpi_str, &a, detection_bitmask);
3887
3888 /* KAKAOTALK_VOICE */
3889 init_kakaotalk_voice_dissector(ndpi_str, &a, detection_bitmask);
3890
3891 /* MPEGTS */
3892 init_mpegts_dissector(ndpi_str, &a, detection_bitmask);
3893
3894 /* UBNTAC2 */
3895 init_ubntac2_dissector(ndpi_str, &a, detection_bitmask);
3896
3897 /* COAP */
3898 init_coap_dissector(ndpi_str, &a, detection_bitmask);
3899
3900 /* MQTT */
3901 init_mqtt_dissector(ndpi_str, &a, detection_bitmask);
3902
3903 /* SOME/IP */
3904 init_someip_dissector(ndpi_str, &a, detection_bitmask);
3905
3906 /* RX */
3907 init_rx_dissector(ndpi_str, &a, detection_bitmask);
3908
3909 /* GIT */
3910 init_git_dissector(ndpi_str, &a, detection_bitmask);
3911
3912 /* HANGOUT */
3913 init_hangout_dissector(ndpi_str, &a, detection_bitmask);
3914
3915 /* DRDA */
3916 init_drda_dissector(ndpi_str, &a, detection_bitmask);
3917
3918 /* BJNP */
3919 init_bjnp_dissector(ndpi_str, &a, detection_bitmask);
3920
3921 /* SMPP */
3922 init_smpp_dissector(ndpi_str, &a, detection_bitmask);
3923
3924 /* TINC */
3925 init_tinc_dissector(ndpi_str, &a, detection_bitmask);
3926
3927 /* FIX */
3928 init_fix_dissector(ndpi_str, &a, detection_bitmask);
3929
3930 /* NINTENDO */
3931 init_nintendo_dissector(ndpi_str, &a, detection_bitmask);
3932
3933 /* MODBUS */
3934 init_modbus_dissector(ndpi_str, &a, detection_bitmask);
3935
3936 /* CAPWAP */
3937 init_capwap_dissector(ndpi_str, &a, detection_bitmask);
3938
3939 /* ZABBIX */
3940 init_zabbix_dissector(ndpi_str, &a, detection_bitmask);
3941
3942 /*** Put false-positive sensitive protocols at the end ***/
3943
3944 /* VIBER */
3945 init_viber_dissector(ndpi_str, &a, detection_bitmask);
3946
3947 /* SKYPE */
3948 init_skype_dissector(ndpi_str, &a, detection_bitmask);
3949
3950 /* BITTORRENT */
3951 init_bittorrent_dissector(ndpi_str, &a, detection_bitmask);
3952
3953 /* WHATSAPP */
3954 init_whatsapp_dissector(ndpi_str, &a, detection_bitmask);
3955
3956 /* OOKLA */
3957 init_ookla_dissector(ndpi_str, &a, detection_bitmask);
3958
3959 /* AMQP */
3960 init_amqp_dissector(ndpi_str, &a, detection_bitmask);
3961
3962 /* CSGO */
3963 init_csgo_dissector(ndpi_str, &a, detection_bitmask);
3964
3965 /* LISP */
3966 init_lisp_dissector(ndpi_str, &a, detection_bitmask);
3967
3968 /* AJP */
3969 init_ajp_dissector(ndpi_str, &a, detection_bitmask);
3970
3971 /* Memcached */
3972 init_memcached_dissector(ndpi_str, &a, detection_bitmask);
3973
3974 /* Nest Log Sink */
3975 init_nest_log_sink_dissector(ndpi_str, &a, detection_bitmask);
3976
3977 /* WireGuard VPN */
3978 init_wireguard_dissector(ndpi_str, &a, detection_bitmask);
3979
3980 /* Amazon_Video */
3981 init_amazon_video_dissector(ndpi_str, &a, detection_bitmask);
3982
3983 /* Targus Getdata */
3984 init_targus_getdata_dissector(ndpi_str, &a, detection_bitmask);
3985
3986 /* S7 comm */
3987 init_s7comm_dissector(ndpi_str, &a, detection_bitmask);
3988
3989 /* IEC 60870-5-104 */
3990 init_104_dissector(ndpi_str, &a, detection_bitmask);
3991
3992 /* DNP3 */
3993 init_dnp3_dissector(ndpi_str, &a, detection_bitmask);
3994
3995 /* WEBSOCKET */
3996 init_websocket_dissector(ndpi_str, &a, detection_bitmask);
3997
3998 /* SOAP */
3999 init_soap_dissector(ndpi_str, &a, detection_bitmask);
4000
4001 /* DNScrypt */
4002 init_dnscrypt_dissector(ndpi_str, &a, detection_bitmask);
4003
4004 /* MongoDB */
4005 init_mongodb_dissector(ndpi_str, &a, detection_bitmask);
4006
4007 /* AmongUS */
4008 init_among_us_dissector(ndpi_str, &a, detection_bitmask);
4009
4010 /* HP Virtual Machine Group Management */
4011 init_hpvirtgrp_dissector(ndpi_str, &a, detection_bitmask);
4012
4013 /* Genshin Impact */
4014 init_genshin_impact_dissector(ndpi_str, &a, detection_bitmask);
4015
4016 /* Z39.50 international standard client–server, application layer communications protocol */
4017 init_z3950_dissector(ndpi_str, &a, detection_bitmask);
4018
4019 /* AVAST SecureDNS */
4020 init_avast_securedns_dissector(ndpi_str, &a, detection_bitmask);
4021
4022 #ifdef CUSTOM_NDPI_PROTOCOLS
4023 #include "../../../nDPI-custom/custom_ndpi_main_init.c"
4024 #endif
4025
4026 /* ----------------------------------------------------------------- */
4027
4028 ndpi_str->callback_buffer_size = a;
4029
4030 NDPI_LOG_DBG2(ndpi_str, "callback_buffer_size is %u\n", ndpi_str->callback_buffer_size);
4031
4032 /* now build the specific buffer for tcp, udp and non_tcp_udp */
4033 ndpi_str->callback_buffer_size_tcp_payload = 0;
4034 ndpi_str->callback_buffer_size_tcp_no_payload = 0;
4035 for(a = 0; a < ndpi_str->callback_buffer_size; a++) {
4036 if((ndpi_str->callback_buffer[a].ndpi_selection_bitmask &
4037 (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP |
4038 NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC)) != 0) {
4039 if(_ndpi_debug_callbacks)
4040 NDPI_LOG_DBG2(ndpi_str, "callback_buffer_tcp_payload, adding buffer %u as entry %u\n", a,
4041 ndpi_str->callback_buffer_size_tcp_payload);
4042
4043 memcpy(&ndpi_str->callback_buffer_tcp_payload[ndpi_str->callback_buffer_size_tcp_payload],
4044 &ndpi_str->callback_buffer[a], sizeof(struct ndpi_call_function_struct));
4045 ndpi_str->callback_buffer_size_tcp_payload++;
4046
4047 if((ndpi_str->callback_buffer[a].ndpi_selection_bitmask & NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) ==
4048 0) {
4049 if(_ndpi_debug_callbacks)
4050 NDPI_LOG_DBG2(
4051 ndpi_str,
4052 "\tcallback_buffer_tcp_no_payload, additional adding buffer %u to no_payload process\n", a);
4053
4054 memcpy(&ndpi_str->callback_buffer_tcp_no_payload[ndpi_str->callback_buffer_size_tcp_no_payload],
4055 &ndpi_str->callback_buffer[a], sizeof(struct ndpi_call_function_struct));
4056 ndpi_str->callback_buffer_size_tcp_no_payload++;
4057 }
4058 }
4059 }
4060
4061 ndpi_str->callback_buffer_size_udp = 0;
4062 for(a = 0; a < ndpi_str->callback_buffer_size; a++) {
4063 if((ndpi_str->callback_buffer[a].ndpi_selection_bitmask &
4064 (NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP |
4065 NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC)) != 0) {
4066 if(_ndpi_debug_callbacks)
4067 NDPI_LOG_DBG2(ndpi_str, "callback_buffer_size_udp: adding buffer : %u as entry %u\n", a,
4068 ndpi_str->callback_buffer_size_udp);
4069
4070 memcpy(&ndpi_str->callback_buffer_udp[ndpi_str->callback_buffer_size_udp], &ndpi_str->callback_buffer[a],
4071 sizeof(struct ndpi_call_function_struct));
4072 ndpi_str->callback_buffer_size_udp++;
4073 }
4074 }
4075
4076 ndpi_str->callback_buffer_size_non_tcp_udp = 0;
4077 for(a = 0; a < ndpi_str->callback_buffer_size; a++) {
4078 if((ndpi_str->callback_buffer[a].ndpi_selection_bitmask &
4079 (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP |
4080 NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP)) == 0 ||
4081 (ndpi_str->callback_buffer[a].ndpi_selection_bitmask & NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC) !=
4082 0) {
4083 if(_ndpi_debug_callbacks)
4084 NDPI_LOG_DBG2(ndpi_str, "callback_buffer_non_tcp_udp: adding buffer : %u as entry %u\n", a,
4085 ndpi_str->callback_buffer_size_non_tcp_udp);
4086
4087 memcpy(&ndpi_str->callback_buffer_non_tcp_udp[ndpi_str->callback_buffer_size_non_tcp_udp],
4088 &ndpi_str->callback_buffer[a], sizeof(struct ndpi_call_function_struct));
4089 ndpi_str->callback_buffer_size_non_tcp_udp++;
4090 }
4091 }
4092 }
4093
4094 /* handle extension headers in IPv6 packets
4095 * arguments:
4096 * l4ptr: pointer to the byte following the initial IPv6 header
4097 * l4len: the length of the IPv6 packet excluding the IPv6 header
4098 * nxt_hdr: next header value from the IPv6 header
4099 * result:
4100 * l4ptr: pointer to the start of the actual packet payload
4101 * l4len: length of the actual payload
4102 * nxt_hdr: protocol of the actual payload
4103 * returns 0 upon success and 1 upon failure
4104 */
ndpi_handle_ipv6_extension_headers(struct ndpi_detection_module_struct * ndpi_str,const u_int8_t ** l4ptr,u_int16_t * l4len,u_int8_t * nxt_hdr)4105 int ndpi_handle_ipv6_extension_headers(struct ndpi_detection_module_struct *ndpi_str, const u_int8_t **l4ptr,
4106 u_int16_t *l4len, u_int8_t *nxt_hdr) {
4107 while((*nxt_hdr == 0 || *nxt_hdr == 43 || *nxt_hdr == 44 || *nxt_hdr == 60 || *nxt_hdr == 135 || *nxt_hdr == 59)) {
4108 u_int16_t ehdr_len;
4109
4110 // no next header
4111 if(*nxt_hdr == 59) {
4112 return(1);
4113 }
4114
4115 // fragment extension header has fixed size of 8 bytes and the first byte is the next header type
4116 if(*nxt_hdr == 44) {
4117 if(*l4len < 8) {
4118 return(1);
4119 }
4120
4121 *nxt_hdr = (*l4ptr)[0];
4122 *l4len -= 8;
4123 (*l4ptr) += 8;
4124 continue;
4125 }
4126
4127 // the other extension headers have one byte for the next header type
4128 // and one byte for the extension header length in 8 byte steps minus the first 8 bytes
4129 if(*l4len < 2) {
4130 return(1);
4131 }
4132
4133 ehdr_len = (*l4ptr)[1];
4134 ehdr_len *= 8;
4135 ehdr_len += 8;
4136
4137 if(*l4len < ehdr_len) {
4138 return(1);
4139 }
4140
4141 *nxt_hdr = (*l4ptr)[0];
4142
4143 if(*l4len < ehdr_len)
4144 return(1);
4145
4146 *l4len -= ehdr_len;
4147 (*l4ptr) += ehdr_len;
4148 }
4149
4150 return(0);
4151 }
4152
ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr * iph,const u_int16_t ipsize)4153 static u_int8_t ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr *iph, const u_int16_t ipsize) {
4154 /*
4155 returned value:
4156 0: fragmented
4157 1: not fragmented
4158 */
4159 //#ifdef REQUIRE_FULL_PACKETS
4160 if(ipsize < iph->ihl * 4 || ipsize < ntohs(iph->tot_len) || ntohs(iph->tot_len) < iph->ihl * 4 ||
4161 (iph->frag_off & htons(0x1FFF)) != 0) {
4162 return(0);
4163 }
4164 //#endif
4165
4166 return(1);
4167 }
4168
4169 /*
4170 extract the l4 payload, if available
4171 returned value:
4172 0: ok, extracted
4173 1: packet too small
4174 2,3: fragmented, ....
4175 else
4176 0: ok, extracted
4177 1: error or not available
4178 */
ndpi_detection_get_l4_internal(struct ndpi_detection_module_struct * ndpi_str,const u_int8_t * l3,u_int16_t l3_len,const u_int8_t ** l4_return,u_int16_t * l4_len_return,u_int8_t * l4_protocol_return,u_int32_t flags)4179 static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_struct *ndpi_str, const u_int8_t *l3,
4180 u_int16_t l3_len, const u_int8_t **l4_return, u_int16_t *l4_len_return,
4181 u_int8_t *l4_protocol_return, u_int32_t flags) {
4182 const struct ndpi_iphdr *iph = NULL;
4183 const struct ndpi_ipv6hdr *iph_v6 = NULL;
4184 u_int16_t l4len = 0;
4185 const u_int8_t *l4ptr = NULL;
4186 u_int8_t l4protocol = 0;
4187
4188 if(l3 == NULL || l3_len < sizeof(struct ndpi_iphdr))
4189 return(1);
4190
4191 if((iph = (const struct ndpi_iphdr *) l3) == NULL)
4192 return(1);
4193
4194 if(iph->version == IPVERSION && iph->ihl >= 5) {
4195 NDPI_LOG_DBG2(ndpi_str, "ipv4 header\n");
4196 }
4197 else if(iph->version == 6 && l3_len >= sizeof(struct ndpi_ipv6hdr)) {
4198 NDPI_LOG_DBG2(ndpi_str, "ipv6 header\n");
4199 iph_v6 = (const struct ndpi_ipv6hdr *) l3;
4200 iph = NULL;
4201 } else {
4202 return(1);
4203 }
4204
4205 if((flags & NDPI_DETECTION_ONLY_IPV6) && iph != NULL) {
4206 NDPI_LOG_DBG2(ndpi_str, "ipv4 header found but excluded by flag\n");
4207 return(1);
4208 } else if((flags & NDPI_DETECTION_ONLY_IPV4) && iph_v6 != NULL) {
4209 NDPI_LOG_DBG2(ndpi_str, "ipv6 header found but excluded by flag\n");
4210 return(1);
4211 }
4212
4213 /* 0: fragmented; 1: not fragmented */
4214 if(iph != NULL && ndpi_iph_is_valid_and_not_fragmented(iph, l3_len)) {
4215 u_int16_t len = ntohs(iph->tot_len);
4216 u_int16_t hlen = (iph->ihl * 4);
4217
4218 l4ptr = (((const u_int8_t *) iph) + iph->ihl * 4);
4219
4220 if(len == 0)
4221 len = l3_len;
4222
4223 l4len = (len > hlen) ? (len - hlen) : 0;
4224 l4protocol = iph->protocol;
4225 }
4226
4227 else if(iph_v6 != NULL && (l3_len - sizeof(struct ndpi_ipv6hdr)) >= ntohs(iph_v6->ip6_hdr.ip6_un1_plen)) {
4228 l4ptr = (((const u_int8_t *) iph_v6) + sizeof(struct ndpi_ipv6hdr));
4229 l4len = ntohs(iph_v6->ip6_hdr.ip6_un1_plen);
4230 l4protocol = iph_v6->ip6_hdr.ip6_un1_nxt;
4231
4232 // we need to handle IPv6 extension headers if present
4233 if(ndpi_handle_ipv6_extension_headers(ndpi_str, &l4ptr, &l4len, &l4protocol) != 0) {
4234 return(1);
4235 }
4236
4237 } else {
4238 return(1);
4239 }
4240
4241 if(l4_return != NULL) {
4242 *l4_return = l4ptr;
4243 }
4244
4245 if(l4_len_return != NULL) {
4246 *l4_len_return = l4len;
4247 }
4248
4249 if(l4_protocol_return != NULL) {
4250 *l4_protocol_return = l4protocol;
4251 }
4252
4253 return(0);
4254 }
4255
4256 /* ************************************************ */
4257
ndpi_apply_flow_protocol_to_packet(struct ndpi_flow_struct * flow,struct ndpi_packet_struct * packet)4258 void ndpi_apply_flow_protocol_to_packet(struct ndpi_flow_struct *flow, struct ndpi_packet_struct *packet) {
4259 memcpy(&packet->detected_protocol_stack, &flow->detected_protocol_stack, sizeof(packet->detected_protocol_stack));
4260 memcpy(&packet->protocol_stack_info, &flow->protocol_stack_info, sizeof(packet->protocol_stack_info));
4261 }
4262
4263 /* ****************************************************** */
4264
ndpi_free_flow_data(struct ndpi_flow_struct * flow)4265 void ndpi_free_flow_data(struct ndpi_flow_struct* flow) {
4266 if(flow) {
4267 if(flow->http.url)
4268 ndpi_free(flow->http.url);
4269
4270 if(flow->http.content_type)
4271 ndpi_free(flow->http.content_type);
4272
4273 if(flow->http.request_content_type)
4274 ndpi_free(flow->http.request_content_type);
4275
4276 if(flow->http.user_agent)
4277 ndpi_free(flow->http.user_agent);
4278
4279 if(flow->kerberos_buf.pktbuf)
4280 ndpi_free(flow->kerberos_buf.pktbuf);
4281
4282 if(flow_is_proto(flow, NDPI_PROTOCOL_QUIC) ||
4283 flow_is_proto(flow, NDPI_PROTOCOL_TLS) ||
4284 flow_is_proto(flow, NDPI_PROTOCOL_DTLS) ||
4285 flow_is_proto(flow, NDPI_PROTOCOL_MAIL_SMTPS) ||
4286 flow_is_proto(flow, NDPI_PROTOCOL_MAIL_POPS) ||
4287 flow_is_proto(flow, NDPI_PROTOCOL_MAIL_IMAPS)) {
4288 if(flow->protos.tls_quic_stun.tls_quic.server_names)
4289 ndpi_free(flow->protos.tls_quic_stun.tls_quic.server_names);
4290
4291 if(flow->protos.tls_quic_stun.tls_quic.alpn)
4292 ndpi_free(flow->protos.tls_quic_stun.tls_quic.alpn);
4293
4294 if(flow->protos.tls_quic_stun.tls_quic.tls_supported_versions)
4295 ndpi_free(flow->protos.tls_quic_stun.tls_quic.tls_supported_versions);
4296
4297 if(flow->protos.tls_quic_stun.tls_quic.issuerDN)
4298 ndpi_free(flow->protos.tls_quic_stun.tls_quic.issuerDN);
4299
4300 if(flow->protos.tls_quic_stun.tls_quic.subjectDN)
4301 ndpi_free(flow->protos.tls_quic_stun.tls_quic.subjectDN);
4302
4303 if(flow->protos.tls_quic_stun.tls_quic.encrypted_sni.esni)
4304 ndpi_free(flow->protos.tls_quic_stun.tls_quic.encrypted_sni.esni);
4305 }
4306
4307 if(flow->l4_proto == IPPROTO_TCP) {
4308 if(flow->l4.tcp.tls.message.buffer)
4309 ndpi_free(flow->l4.tcp.tls.message.buffer);
4310 }
4311
4312 if(flow->l4_proto == IPPROTO_UDP) {
4313 if(flow->l4.udp.quic_reasm_buf)
4314 ndpi_free(flow->l4.udp.quic_reasm_buf);
4315 }
4316 }
4317 }
4318
4319 /* ************************************************ */
4320
ndpi_init_packet_header(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,unsigned short packetlen)4321 static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str,
4322 struct ndpi_flow_struct *flow,
4323 unsigned short packetlen) {
4324 const struct ndpi_iphdr *decaps_iph = NULL;
4325 u_int16_t l3len;
4326 u_int16_t l4len;
4327 const u_int8_t *l4ptr;
4328 u_int8_t l4protocol;
4329 u_int8_t l4_result;
4330
4331 if(!flow)
4332 return(1);
4333
4334 /* reset payload_packet_len, will be set if ipv4 tcp or udp */
4335 flow->packet.payload_packet_len = 0;
4336 flow->packet.l4_packet_len = 0;
4337 flow->packet.l3_packet_len = packetlen;
4338
4339 flow->packet.tcp = NULL, flow->packet.udp = NULL;
4340 flow->packet.generic_l4_ptr = NULL;
4341 flow->packet.iphv6 = NULL;
4342
4343 ndpi_apply_flow_protocol_to_packet(flow, &flow->packet);
4344
4345 l3len = flow->packet.l3_packet_len;
4346
4347 if(flow->packet.iph != NULL)
4348 decaps_iph = flow->packet.iph;
4349
4350 if(decaps_iph && decaps_iph->version == IPVERSION && decaps_iph->ihl >= 5) {
4351 NDPI_LOG_DBG2(ndpi_str, "ipv4 header\n");
4352 } else if(decaps_iph && decaps_iph->version == 6 && l3len >= sizeof(struct ndpi_ipv6hdr) &&
4353 (ndpi_str->ip_version_limit & NDPI_DETECTION_ONLY_IPV4) == 0) {
4354 NDPI_LOG_DBG2(ndpi_str, "ipv6 header\n");
4355 flow->packet.iphv6 = (struct ndpi_ipv6hdr *) flow->packet.iph;
4356 flow->packet.iph = NULL;
4357 } else {
4358 flow->packet.iph = NULL;
4359 return(1);
4360 }
4361
4362 /* needed:
4363 * - unfragmented packets
4364 * - ip header <= packet len
4365 * - ip total length >= packet len
4366 */
4367
4368 l4ptr = NULL;
4369 l4len = 0;
4370 l4protocol = 0;
4371
4372 l4_result =
4373 ndpi_detection_get_l4_internal(ndpi_str, (const u_int8_t *) decaps_iph, l3len, &l4ptr, &l4len, &l4protocol, 0);
4374
4375 if(l4_result != 0) {
4376 return(1);
4377 }
4378
4379 flow->packet.l4_protocol = l4protocol;
4380 flow->packet.l4_packet_len = l4len;
4381 flow->l4_proto = l4protocol;
4382
4383 /* TCP / UDP detection */
4384 if(l4protocol == IPPROTO_TCP && flow->packet.l4_packet_len >= 20 /* min size of tcp */) {
4385 /* tcp */
4386 flow->packet.tcp = (struct ndpi_tcphdr *) l4ptr;
4387 if(flow->packet.l4_packet_len >= flow->packet.tcp->doff * 4) {
4388 flow->packet.payload_packet_len = flow->packet.l4_packet_len - flow->packet.tcp->doff * 4;
4389 flow->packet.actual_payload_len = flow->packet.payload_packet_len;
4390 flow->packet.payload = ((u_int8_t *) flow->packet.tcp) + (flow->packet.tcp->doff * 4);
4391
4392 /* check for new tcp syn packets, here
4393 * idea: reset detection state if a connection is unknown
4394 */
4395 if(flow->packet.tcp->syn != 0 && flow->packet.tcp->ack == 0 && flow->init_finished != 0 &&
4396 flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
4397
4398 u_int16_t guessed_protocol_id, guessed_host_protocol_id;
4399 u_int16_t packet_direction_counter[2];
4400 u_int8_t num_processed_pkts;
4401 struct packet_save {
4402 const struct ndpi_iphdr *iph;
4403 const struct ndpi_ipv6hdr *iphv6;
4404 const u_int8_t *payload;
4405 u_int64_t current_time_ms;
4406 u_int16_t l3_packet_len;
4407 u_int16_t l4_packet_len;
4408 u_int16_t payload_packet_len;
4409 u_int16_t actual_payload_len;
4410 u_int8_t l4_protocol;
4411 } packet;
4412
4413 #define flow_save(a) a = flow->a
4414 #define flow_restore(a) flow->a = a
4415
4416 flow_save(packet_direction_counter[0]);
4417 flow_save(packet_direction_counter[1]);
4418 flow_save(num_processed_pkts);
4419 flow_save(guessed_protocol_id);
4420 flow_save(guessed_host_protocol_id);
4421 flow_save(packet.iph);
4422 flow_save(packet.iphv6);
4423 flow_save(packet.payload);
4424 flow_save(packet.current_time_ms);
4425 flow_save(packet.l3_packet_len);
4426 flow_save(packet.l4_packet_len);
4427 flow_save(packet.payload_packet_len);
4428 flow_save(packet.actual_payload_len);
4429 flow_save(packet.l4_protocol);
4430
4431 ndpi_free_flow_data(flow);
4432 memset(flow, 0, sizeof(*(flow)));
4433
4434 /* Restore pointers */
4435 flow->packet.tcp = (struct ndpi_tcphdr *) l4ptr;
4436 flow->l4_proto = IPPROTO_TCP;
4437
4438 flow_restore(packet_direction_counter[0]);
4439 flow_restore(packet_direction_counter[1]);
4440 flow_restore(num_processed_pkts);
4441 flow_restore(guessed_protocol_id);
4442 flow_restore(guessed_host_protocol_id);
4443 flow_restore(packet.iph);
4444 flow_restore(packet.iphv6);
4445 flow_restore(packet.payload);
4446 flow_restore(packet.current_time_ms);
4447 flow_restore(packet.l3_packet_len);
4448 flow_restore(packet.l4_packet_len);
4449 flow_restore(packet.payload_packet_len);
4450 flow_restore(packet.actual_payload_len);
4451 flow_restore(packet.l4_protocol);
4452
4453 #undef flow_save
4454 #undef flow_restore
4455
4456 NDPI_LOG_DBG(ndpi_str, "tcp syn packet for unknown protocol, reset detection state\n");
4457 }
4458 } else {
4459 /* tcp header not complete */
4460 flow->packet.tcp = NULL;
4461 }
4462 } else if(l4protocol == IPPROTO_UDP && flow->packet.l4_packet_len >= 8 /* size of udp */) {
4463 flow->packet.udp = (struct ndpi_udphdr *) l4ptr;
4464 flow->packet.payload_packet_len = flow->packet.l4_packet_len - 8;
4465 flow->packet.payload = ((u_int8_t *) flow->packet.udp) + 8;
4466 } else if((l4protocol == IPPROTO_ICMP && flow->packet.l4_packet_len >= sizeof(struct ndpi_icmphdr))
4467 || (l4protocol == IPPROTO_ICMPV6 && flow->packet.l4_packet_len >= sizeof(struct ndpi_icmp6hdr))) {
4468 flow->packet.payload = ((u_int8_t *) l4ptr);
4469 flow->packet.payload_packet_len = flow->packet.l4_packet_len;
4470 } else {
4471 flow->packet.generic_l4_ptr = l4ptr;
4472 }
4473
4474 return(0);
4475 }
4476
4477 /* ************************************************ */
4478
4479
ndpi_connection_tracking(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow)4480 void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
4481 struct ndpi_flow_struct *flow) {
4482 if(!flow) {
4483 return;
4484 } else {
4485 /* const for gcc code optimization and cleaner code */
4486 struct ndpi_packet_struct *packet = &flow->packet;
4487 const struct ndpi_iphdr *iph = packet->iph;
4488 const struct ndpi_ipv6hdr *iphv6 = packet->iphv6;
4489 const struct ndpi_tcphdr *tcph = packet->tcp;
4490 const struct ndpi_udphdr *udph = packet->udp;
4491
4492 packet->tcp_retransmission = 0, packet->packet_direction = 0;
4493
4494 if(ndpi_str->direction_detect_disable) {
4495 packet->packet_direction = flow->packet_direction;
4496 } else {
4497 if(iph != NULL && ntohl(iph->saddr) < ntohl(iph->daddr))
4498 packet->packet_direction = 1;
4499
4500 if((iphv6 != NULL)
4501 && NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(&iphv6->ip6_src, &iphv6->ip6_dst) != 0)
4502 packet->packet_direction = 1;
4503 }
4504
4505 packet->packet_lines_parsed_complete = 0;
4506
4507 if(flow->init_finished == 0) {
4508 flow->init_finished = 1;
4509 flow->setup_packet_direction = packet->packet_direction;
4510 }
4511
4512 if(tcph != NULL) {
4513 /* reset retried bytes here before setting it */
4514 packet->num_retried_bytes = 0;
4515
4516 if(!ndpi_str->direction_detect_disable)
4517 packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 0;
4518
4519 if(tcph->syn != 0 && tcph->ack == 0 && flow->l4.tcp.seen_syn == 0 && flow->l4.tcp.seen_syn_ack == 0 &&
4520 flow->l4.tcp.seen_ack == 0) {
4521 flow->l4.tcp.seen_syn = 1;
4522 } else
4523 if(tcph->syn != 0 && tcph->ack != 0 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 0 &&
4524 flow->l4.tcp.seen_ack == 0) {
4525 flow->l4.tcp.seen_syn_ack = 1;
4526 } else
4527 if(tcph->syn == 0 && tcph->ack == 1 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 1 &&
4528 flow->l4.tcp.seen_ack == 0) {
4529 flow->l4.tcp.seen_ack = 1;
4530 }
4531
4532 if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0) ||
4533 (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0)) {
4534 /* initialize tcp sequence counters */
4535 /* the ack flag needs to be set to get valid sequence numbers from the other
4536 * direction. Usually it will catch the second packet syn+ack but it works
4537 * also for asymmetric traffic where it will use the first data packet
4538 *
4539 * if the syn flag is set add one to the sequence number,
4540 * otherwise use the payload length.
4541 */
4542 if(tcph->ack != 0) {
4543 flow->next_tcp_seq_nr[flow->packet.packet_direction] =
4544 ntohl(tcph->seq) + (tcph->syn ? 1 : packet->payload_packet_len);
4545
4546 /*
4547 Check to avoid discrepancies in case we analyze a flow that does not start with SYN...
4548 but that is already started when nDPI being to process it. See also (***) below
4549 */
4550 if(flow->num_processed_pkts > 1)
4551 flow->next_tcp_seq_nr[1 - flow->packet.packet_direction] = ntohl(tcph->ack_seq);
4552 }
4553 } else if(packet->payload_packet_len > 0) {
4554 /* check tcp sequence counters */
4555 if(((u_int32_t)(ntohl(tcph->seq) - flow->next_tcp_seq_nr[packet->packet_direction])) >
4556 ndpi_str->tcp_max_retransmission_window_size) {
4557 packet->tcp_retransmission = 1;
4558
4559 /* CHECK IF PARTIAL RETRY IS HAPPENING */
4560 if((flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq) <
4561 packet->payload_packet_len)) {
4562 /* num_retried_bytes actual_payload_len hold info about the partial retry
4563 analyzer which require this info can make use of this info
4564 Other analyzer can use packet->payload_packet_len */
4565 packet->num_retried_bytes =
4566 (u_int16_t)(flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq));
4567 packet->actual_payload_len = packet->payload_packet_len - packet->num_retried_bytes;
4568
4569 if(flow->num_processed_pkts > 1) /* See also (***) above */
4570 flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len;
4571 }
4572 }
4573
4574 /* normal path
4575 actual_payload_len is initialized to payload_packet_len during tcp header parsing itself.
4576 It will be changed only in case of retransmission */
4577 else {
4578 packet->num_retried_bytes = 0;
4579 flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len;
4580 }
4581 }
4582
4583 if(tcph->rst) {
4584 flow->next_tcp_seq_nr[0] = 0;
4585 flow->next_tcp_seq_nr[1] = 0;
4586 }
4587 } else if(udph != NULL) {
4588 if(!ndpi_str->direction_detect_disable)
4589 packet->packet_direction = (htons(udph->source) < htons(udph->dest)) ? 1 : 0;
4590 }
4591
4592 if(flow->packet_counter < MAX_PACKET_COUNTER && packet->payload_packet_len) {
4593 flow->packet_counter++;
4594 }
4595
4596 if(flow->packet_direction_counter[packet->packet_direction] < MAX_PACKET_COUNTER &&
4597 packet->payload_packet_len) {
4598 flow->packet_direction_counter[packet->packet_direction]++;
4599 }
4600
4601 if(flow->byte_counter[packet->packet_direction] + packet->payload_packet_len >
4602 flow->byte_counter[packet->packet_direction]) {
4603 flow->byte_counter[packet->packet_direction] += packet->payload_packet_len;
4604 }
4605 }
4606 }
4607
4608 /* ************************************************ */
4609
check_ndpi_detection_func(struct ndpi_detection_module_struct * const ndpi_str,struct ndpi_flow_struct * const flow,NDPI_SELECTION_BITMASK_PROTOCOL_SIZE const ndpi_selection_packet,struct ndpi_call_function_struct const * const callback_buffer,uint32_t callback_buffer_size)4610 static u_int32_t check_ndpi_detection_func(struct ndpi_detection_module_struct * const ndpi_str,
4611 struct ndpi_flow_struct * const flow,
4612 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE const ndpi_selection_packet,
4613 struct ndpi_call_function_struct const * const callback_buffer,
4614 uint32_t callback_buffer_size)
4615 {
4616 void *func = NULL;
4617 u_int8_t is_tcp_without_payload = (callback_buffer == ndpi_str->callback_buffer_tcp_no_payload);
4618 u_int32_t num_calls = (is_tcp_without_payload != 0 ? 1 : 0);
4619 u_int16_t proto_index = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoIdx;
4620 u_int16_t proto_id = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoId;
4621 NDPI_PROTOCOL_BITMASK detection_bitmask;
4622
4623 NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]);
4624
4625 if ((proto_id != NDPI_PROTOCOL_UNKNOWN) &&
4626 NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
4627 ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 &&
4628 NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[proto_index].detection_bitmask, detection_bitmask) != 0 &&
4629 (ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask & ndpi_selection_packet) ==
4630 ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask)
4631 {
4632 if ((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) &&
4633 (ndpi_str->proto_defaults[flow->guessed_protocol_id].func != NULL) &&
4634 (is_tcp_without_payload == 0 ||
4635 ((ndpi_str->callback_buffer[flow->guessed_protocol_id].ndpi_selection_bitmask &
4636 NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) == 0)))
4637 {
4638 ndpi_str->proto_defaults[flow->guessed_protocol_id].func(ndpi_str, flow);
4639 func = ndpi_str->proto_defaults[flow->guessed_protocol_id].func;
4640 num_calls++;
4641 }
4642 }
4643
4644 if (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN)
4645 {
4646 for (u_int32_t a = 0; a < callback_buffer_size; a++) {
4647 if ((func != callback_buffer[a].func) &&
4648 (callback_buffer[a].ndpi_selection_bitmask & ndpi_selection_packet) ==
4649 callback_buffer[a].ndpi_selection_bitmask &&
4650 NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
4651 callback_buffer[a].excluded_protocol_bitmask) == 0 &&
4652 NDPI_BITMASK_COMPARE(callback_buffer[a].detection_bitmask,
4653 detection_bitmask) != 0)
4654 {
4655 callback_buffer[a].func(ndpi_str, flow);
4656 num_calls++;
4657
4658 if (flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
4659 {
4660 break; /* Stop after the first detected protocol. */
4661 }
4662 }
4663 }
4664 }
4665
4666 /* Check for subprotocols. */
4667 for (u_int32_t a = 0; a < ndpi_str->proto_defaults[flow->detected_protocol_stack[0]].subprotocol_count; a++)
4668 {
4669 u_int16_t subproto_id = ndpi_str->proto_defaults[flow->detected_protocol_stack[0]].subprotocols[a];
4670 if (subproto_id == (uint16_t)NDPI_PROTOCOL_MATCHED_BY_CONTENT)
4671 {
4672 continue;
4673 }
4674
4675 u_int16_t subproto_index = ndpi_str->proto_defaults[subproto_id].protoIdx;
4676 if ((func != ndpi_str->proto_defaults[subproto_id].func) &&
4677 (ndpi_str->callback_buffer[subproto_index].ndpi_selection_bitmask & ndpi_selection_packet) ==
4678 ndpi_str->callback_buffer[subproto_index].ndpi_selection_bitmask &&
4679 NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
4680 ndpi_str->callback_buffer[subproto_index].excluded_protocol_bitmask) == 0 &&
4681 NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[subproto_index].detection_bitmask,
4682 detection_bitmask) != 0)
4683 {
4684 ndpi_str->callback_buffer[subproto_index].func(ndpi_str, flow);
4685 num_calls++;
4686 }
4687
4688 if (flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN)
4689 {
4690 break; /* Stop after the first detected subprotocol. */
4691 }
4692 }
4693
4694 return num_calls;
4695 }
4696
4697 /* ************************************************ */
4698
check_ndpi_other_flow_func(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,NDPI_SELECTION_BITMASK_PROTOCOL_SIZE * ndpi_selection_packet)4699 u_int32_t check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str,
4700 struct ndpi_flow_struct *flow,
4701 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet)
4702 {
4703 return check_ndpi_detection_func(ndpi_str, flow, *ndpi_selection_packet,
4704 ndpi_str->callback_buffer_non_tcp_udp,
4705 ndpi_str->callback_buffer_size_non_tcp_udp);
4706 }
4707
4708 /* ************************************************ */
4709
check_ndpi_udp_flow_func(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,NDPI_SELECTION_BITMASK_PROTOCOL_SIZE * ndpi_selection_packet)4710 static u_int32_t check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_str,
4711 struct ndpi_flow_struct *flow,
4712 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet)
4713 {
4714 return check_ndpi_detection_func(ndpi_str, flow, *ndpi_selection_packet,
4715 ndpi_str->callback_buffer_udp,
4716 ndpi_str->callback_buffer_size_udp);
4717 }
4718
4719 /* ************************************************ */
4720
check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,NDPI_SELECTION_BITMASK_PROTOCOL_SIZE * ndpi_selection_packet)4721 static u_int32_t check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_str,
4722 struct ndpi_flow_struct *flow,
4723 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet)
4724 {
4725 if (flow->packet.payload_packet_len != 0) {
4726 return check_ndpi_detection_func(ndpi_str, flow, *ndpi_selection_packet,
4727 ndpi_str->callback_buffer_tcp_payload,
4728 ndpi_str->callback_buffer_size_tcp_payload);
4729 } else {
4730 /* no payload */
4731 return check_ndpi_detection_func(ndpi_str, flow, *ndpi_selection_packet,
4732 ndpi_str->callback_buffer_tcp_no_payload,
4733 ndpi_str->callback_buffer_size_tcp_no_payload);
4734 }
4735 }
4736
4737 /* ********************************************************************************* */
4738
ndpi_check_flow_func(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,NDPI_SELECTION_BITMASK_PROTOCOL_SIZE * ndpi_selection_packet)4739 u_int32_t ndpi_check_flow_func(struct ndpi_detection_module_struct *ndpi_str,
4740 struct ndpi_flow_struct *flow,
4741 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
4742 if(!flow)
4743 return(0);
4744 else if(flow->packet.tcp != NULL)
4745 return(check_ndpi_tcp_flow_func(ndpi_str, flow, ndpi_selection_packet));
4746 else if(flow->packet.udp != NULL)
4747 return(check_ndpi_udp_flow_func(ndpi_str, flow, ndpi_selection_packet));
4748 else
4749 return(check_ndpi_other_flow_func(ndpi_str, flow, ndpi_selection_packet));
4750 }
4751
4752 /* ********************************************************************************* */
4753
ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow)4754 u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_str,
4755 struct ndpi_flow_struct *flow) {
4756 u_int16_t ret = NDPI_PROTOCOL_UNKNOWN;
4757
4758 if(flow->packet.iph) {
4759 struct in_addr addr;
4760 u_int16_t sport, dport;
4761
4762 addr.s_addr = flow->packet.iph->saddr;
4763
4764 if((flow->l4_proto == IPPROTO_TCP) && flow->packet.tcp)
4765 sport = flow->packet.tcp->source, dport = flow->packet.tcp->dest;
4766 else if((flow->l4_proto == IPPROTO_UDP) && flow->packet.udp)
4767 sport = flow->packet.udp->source, dport = flow->packet.udp->dest;
4768 else
4769 sport = dport = 0;
4770
4771 /* guess host protocol */
4772 ret = ndpi_network_port_ptree_match(ndpi_str, &addr, sport);
4773
4774 if(ret == NDPI_PROTOCOL_UNKNOWN) {
4775 addr.s_addr = flow->packet.iph->daddr;
4776 ret = ndpi_network_port_ptree_match(ndpi_str, &addr, dport);
4777 }
4778 }
4779
4780 return(ret);
4781 }
4782
4783 /* ********************************************************************************* */
4784
ndpi_detection_giveup(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int8_t enable_guess,u_int8_t * protocol_was_guessed)4785 ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
4786 u_int8_t enable_guess, u_int8_t *protocol_was_guessed) {
4787 ndpi_protocol ret = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED};
4788
4789 *protocol_was_guessed = 0;
4790
4791 if(flow == NULL)
4792 return(ret);
4793
4794 /* Init defaults */
4795 ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
4796 ret.category = flow->category;
4797
4798 /* Ensure that we don't change our mind if detection is already complete */
4799 if((ret.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN))
4800 return(ret);
4801
4802 if(ndpi_str->mining_cache && flow->packet.iph) {
4803 u_int16_t cached_proto;
4804 u_int32_t key = flow->packet.iph->saddr + flow->packet.iph->daddr;
4805
4806 if(ndpi_lru_find_cache(ndpi_str->mining_cache, key,
4807 &cached_proto, 0 /* Don't remove it as it can be used for other connections */)) {
4808 ndpi_set_detected_protocol(ndpi_str, flow, cached_proto, NDPI_PROTOCOL_UNKNOWN);
4809 ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
4810 return(ret);
4811 }
4812 }
4813
4814 /* TODO: add the remaining stage_XXXX protocols */
4815 if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
4816 u_int16_t guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN, guessed_host_protocol_id = NDPI_PROTOCOL_UNKNOWN;
4817
4818 if(flow->guessed_protocol_id == NDPI_PROTOCOL_STUN)
4819 goto check_stun_export;
4820 else if((flow->guessed_protocol_id == NDPI_PROTOCOL_HANGOUT_DUO) ||
4821 (flow->guessed_protocol_id == NDPI_PROTOCOL_MESSENGER) ||
4822 (flow->guessed_protocol_id == NDPI_PROTOCOL_WHATSAPP_CALL)) {
4823 *protocol_was_guessed = 1;
4824 ndpi_set_detected_protocol(ndpi_str, flow, flow->guessed_protocol_id, NDPI_PROTOCOL_UNKNOWN);
4825 }
4826 else if((flow->l4.tcp.tls.hello_processed == 1) &&
4827 (flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] != '\0')) {
4828 *protocol_was_guessed = 1;
4829 ndpi_set_detected_protocol(ndpi_str, flow, NDPI_PROTOCOL_TLS, NDPI_PROTOCOL_UNKNOWN);
4830 } else if(enable_guess) {
4831 if((flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) && (flow->packet.l4_protocol == IPPROTO_TCP) &&
4832 flow->l4.tcp.tls.hello_processed)
4833 flow->guessed_protocol_id = NDPI_PROTOCOL_TLS;
4834
4835 guessed_protocol_id = flow->guessed_protocol_id, guessed_host_protocol_id = flow->guessed_host_protocol_id;
4836
4837 if((guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) &&
4838 ((flow->packet.l4_protocol == IPPROTO_UDP) &&
4839 NDPI_ISSET(&flow->excluded_protocol_bitmask, guessed_host_protocol_id) &&
4840 is_udp_guessable_protocol(guessed_host_protocol_id)))
4841 flow->guessed_host_protocol_id = guessed_host_protocol_id = NDPI_PROTOCOL_UNKNOWN;
4842
4843 /* Ignore guessed protocol if they have been discarded */
4844 if((guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN)
4845 // && (guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN)
4846 && (flow->packet.l4_protocol == IPPROTO_UDP) &&
4847 NDPI_ISSET(&flow->excluded_protocol_bitmask, guessed_protocol_id) &&
4848 is_udp_guessable_protocol(guessed_protocol_id))
4849 flow->guessed_protocol_id = guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN;
4850
4851 if((guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) || (guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN)) {
4852 if((guessed_protocol_id == 0) && (flow->protos.tls_quic_stun.stun.num_binding_requests > 0) &&
4853 (flow->protos.tls_quic_stun.stun.num_processed_pkts > 0))
4854 guessed_protocol_id = NDPI_PROTOCOL_STUN;
4855
4856 if(flow->host_server_name[0] != '\0') {
4857 ndpi_protocol_match_result ret_match;
4858
4859 memset(&ret_match, 0, sizeof(ret_match));
4860
4861 ndpi_match_host_subprotocol(ndpi_str, flow, (char *) flow->host_server_name,
4862 strlen((const char *) flow->host_server_name), &ret_match,
4863 NDPI_PROTOCOL_DNS);
4864
4865 if(ret_match.protocol_id != NDPI_PROTOCOL_UNKNOWN)
4866 guessed_host_protocol_id = ret_match.protocol_id;
4867 }
4868
4869 *protocol_was_guessed = 1;
4870 ndpi_int_change_protocol(ndpi_str, flow, guessed_host_protocol_id, guessed_protocol_id);
4871 }
4872 }
4873 } else if(enable_guess) {
4874 if(flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
4875 *protocol_was_guessed = 1;
4876 flow->detected_protocol_stack[1] = flow->guessed_protocol_id;
4877 }
4878
4879 if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
4880 *protocol_was_guessed = 1;
4881 flow->detected_protocol_stack[0] = flow->guessed_host_protocol_id;
4882 }
4883
4884 if(flow->detected_protocol_stack[1] == flow->detected_protocol_stack[0]) {
4885 *protocol_was_guessed = 1;
4886 flow->detected_protocol_stack[1] = flow->guessed_host_protocol_id;
4887 }
4888 }
4889
4890 if((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) &&
4891 (flow->guessed_protocol_id == NDPI_PROTOCOL_STUN)) {
4892 check_stun_export:
4893 /* if(flow->protos.tls_quic_stun.stun.num_processed_pkts || flow->protos.tls_quic_stun.stun.num_udp_pkts) */
4894 {
4895 // if(/* (flow->protos.tls_quic_stun.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) */
4896 *protocol_was_guessed = 1;
4897 ndpi_set_detected_protocol(ndpi_str, flow, flow->guessed_host_protocol_id, NDPI_PROTOCOL_STUN);
4898 }
4899 }
4900
4901 ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
4902
4903 if(ret.master_protocol == NDPI_PROTOCOL_STUN) {
4904 if(ret.app_protocol == NDPI_PROTOCOL_FACEBOOK)
4905 ret.app_protocol = NDPI_PROTOCOL_MESSENGER;
4906 else if(ret.app_protocol == NDPI_PROTOCOL_GOOGLE) {
4907 /*
4908 As Google has recently introduced Duo,
4909 we need to distinguish between it and hangout
4910 thing that should be handled by the STUN dissector
4911 */
4912 ret.app_protocol = NDPI_PROTOCOL_HANGOUT_DUO;
4913 }
4914 }
4915
4916 if(ret.app_protocol != NDPI_PROTOCOL_UNKNOWN) {
4917 *protocol_was_guessed = 1;
4918 ndpi_fill_protocol_category(ndpi_str, flow, &ret);
4919 }
4920
4921 return(ret);
4922 }
4923
4924 /* ********************************************************************************* */
4925
ndpi_process_extra_packet(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,const unsigned char * packet,const unsigned short packetlen,const u_int64_t current_time_ms,struct ndpi_id_struct * src,struct ndpi_id_struct * dst)4926 void ndpi_process_extra_packet(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
4927 const unsigned char *packet, const unsigned short packetlen,
4928 const u_int64_t current_time_ms, struct ndpi_id_struct *src, struct ndpi_id_struct *dst) {
4929 if(flow == NULL)
4930 return;
4931
4932 if(flow->server_id == NULL)
4933 flow->server_id = dst; /* Default */
4934
4935 /* need at least 20 bytes for ip header */
4936 if(packetlen < 20) {
4937 return;
4938 }
4939
4940 flow->packet.current_time_ms = current_time_ms;
4941
4942 /* parse packet */
4943 flow->packet.iph = (struct ndpi_iphdr *) packet;
4944 /* we are interested in ipv4 packet */
4945
4946 /* set up the packet headers for the extra packet function to use if it wants */
4947 if(ndpi_init_packet_header(ndpi_str, flow, packetlen) != 0)
4948 return;
4949
4950 /* detect traffic for tcp or udp only */
4951 flow->src = src, flow->dst = dst;
4952
4953 ndpi_connection_tracking(ndpi_str, flow);
4954
4955 /* call the extra packet function (which may add more data/info to flow) */
4956 if(flow->extra_packets_func) {
4957 if((flow->extra_packets_func(ndpi_str, flow)) == 0)
4958 flow->check_extra_packets = 0;
4959
4960 if(++flow->num_extra_packets_checked == flow->max_extra_packets_to_check)
4961 flow->extra_packets_func = NULL; /* Enough packets detected */
4962 }
4963 }
4964
4965 /* ********************************************************************************* */
4966
ndpi_load_ip_category(struct ndpi_detection_module_struct * ndpi_str,const char * ip_address_and_mask,ndpi_protocol_category_t category)4967 int ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_str, const char *ip_address_and_mask,
4968 ndpi_protocol_category_t category) {
4969 ndpi_patricia_node_t *node;
4970 struct in_addr pin;
4971 int bits = 32;
4972 char *ptr;
4973 char ipbuf[64];
4974
4975 strncpy(ipbuf, ip_address_and_mask, sizeof(ipbuf));
4976 ipbuf[sizeof(ipbuf) - 1] = '\0';
4977
4978 ptr = strrchr(ipbuf, '/');
4979
4980 if(ptr) {
4981 *(ptr++) = '\0';
4982 if(atoi(ptr) >= 0 && atoi(ptr) <= 32)
4983 bits = atoi(ptr);
4984 }
4985
4986 if(inet_pton(AF_INET, ipbuf, &pin) != 1) {
4987 NDPI_LOG_DBG2(ndpi_str, "Invalid ip/ip+netmask: %s\n", ip_address_and_mask);
4988 return(-1);
4989 }
4990
4991 if((node = add_to_ptree(ndpi_str->custom_categories.ipAddresses_shadow, AF_INET, &pin, bits)) != NULL) {
4992 node->value.u.uv32.user_value = (u_int16_t)category, node->value.u.uv32.additional_user_value = 0;
4993 }
4994
4995 return(0);
4996 }
4997
4998
4999 /* ********************************************************************************* */
5000
ndpi_load_hostname_category(struct ndpi_detection_module_struct * ndpi_str,const char * name_to_add,ndpi_protocol_category_t category)5001 int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_str, const char *name_to_add,
5002 ndpi_protocol_category_t category) {
5003
5004 if(ndpi_str->custom_categories.hostnames_shadow.ac_automa == NULL)
5005 return(-1);
5006
5007 if(name_to_add == NULL)
5008 return(-1);
5009
5010 return ndpi_string_to_automa(ndpi_str,(AC_AUTOMATA_t *)ndpi_str->custom_categories.hostnames_shadow.ac_automa,
5011 name_to_add,category,category, 0, 0, 1); /* at_end */
5012 }
5013
5014 /* ********************************************************************************* */
5015
5016 /* Loads an IP or name category */
ndpi_load_category(struct ndpi_detection_module_struct * ndpi_struct,const char * ip_or_name,ndpi_protocol_category_t category)5017 int ndpi_load_category(struct ndpi_detection_module_struct *ndpi_struct, const char *ip_or_name,
5018 ndpi_protocol_category_t category) {
5019 int rv;
5020
5021 /* Try to load as IP address first */
5022 rv = ndpi_load_ip_category(ndpi_struct, ip_or_name, category);
5023
5024 if(rv < 0) {
5025 /* IP load failed, load as hostname */
5026 rv = ndpi_load_hostname_category(ndpi_struct, ip_or_name, category);
5027 }
5028
5029 return(rv);
5030 }
5031
5032 /* ********************************************************************************* */
5033
ndpi_enable_loaded_categories(struct ndpi_detection_module_struct * ndpi_str)5034 int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_str) {
5035 int i;
5036
5037 /* First add the nDPI known categories matches */
5038 for(i = 0; category_match[i].string_to_match != NULL; i++)
5039 ndpi_load_category(ndpi_str, category_match[i].string_to_match, category_match[i].protocol_category);
5040
5041 /* Free */
5042 ac_automata_release((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames.ac_automa,
5043 1 /* free patterns strings memory */);
5044
5045 /* Finalize */
5046 ac_automata_finalize((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames_shadow.ac_automa);
5047
5048 /* Swap */
5049 ndpi_str->custom_categories.hostnames.ac_automa = ndpi_str->custom_categories.hostnames_shadow.ac_automa;
5050
5051 /* Realloc */
5052 ndpi_str->custom_categories.hostnames_shadow.ac_automa = ac_automata_init(ac_domain_match_handler);
5053 if(ndpi_str->custom_categories.hostnames_shadow.ac_automa) {
5054 ac_automata_feature(ndpi_str->custom_categories.hostnames_shadow.ac_automa,AC_FEATURE_LC);
5055 ac_automata_name(ndpi_str->custom_categories.hostnames_shadow.ac_automa,"ccat_sh",0);
5056 }
5057
5058 if(ndpi_str->custom_categories.ipAddresses != NULL)
5059 ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data);
5060
5061 ndpi_str->custom_categories.ipAddresses = ndpi_str->custom_categories.ipAddresses_shadow;
5062 ndpi_str->custom_categories.ipAddresses_shadow = ndpi_patricia_new(32 /* IPv4 */);
5063
5064 ndpi_str->custom_categories.categories_loaded = 1;
5065
5066 return(0);
5067 }
5068
5069 /* ********************************************************************************* */
5070
ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct * ndpi_str,u_int32_t saddr,u_int32_t daddr,ndpi_protocol * ret)5071 int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str, u_int32_t saddr, u_int32_t daddr,
5072 ndpi_protocol *ret) {
5073 if(ndpi_str->custom_categories.categories_loaded) {
5074 ndpi_prefix_t prefix;
5075 ndpi_patricia_node_t *node;
5076
5077 if(saddr == 0)
5078 node = NULL;
5079 else {
5080 /* Make sure all in network byte order otherwise compares wont work */
5081 ndpi_fill_prefix_v4(&prefix, (struct in_addr *) &saddr, 32,
5082 ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits);
5083 node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix);
5084 }
5085
5086 if(!node) {
5087 if(daddr != 0) {
5088 ndpi_fill_prefix_v4(&prefix, (struct in_addr *) &daddr, 32,
5089 ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits);
5090 node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix);
5091 }
5092 }
5093
5094 if(node) {
5095 ret->category = (ndpi_protocol_category_t) node->value.u.uv32.user_value;
5096
5097 return(1);
5098 }
5099 }
5100
5101 ret->category = ndpi_get_proto_category(ndpi_str, *ret);
5102
5103 return(0);
5104 }
5105
5106 /* ********************************************************************************* */
5107
ndpi_fill_protocol_category(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,ndpi_protocol * ret)5108 void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
5109 ndpi_protocol *ret) {
5110 if((ret->master_protocol == NDPI_PROTOCOL_UNKNOWN) && (ret->app_protocol == NDPI_PROTOCOL_UNKNOWN))
5111 return;
5112
5113 if(ndpi_str->custom_categories.categories_loaded) {
5114 if(flow->guessed_header_category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) {
5115 flow->category = ret->category = flow->guessed_header_category;
5116 return;
5117 }
5118
5119 if(flow->host_server_name[0] != '\0') {
5120 u_int32_t id;
5121 int rc = ndpi_match_custom_category(ndpi_str, (char *) flow->host_server_name,
5122 strlen((char *) flow->host_server_name), &id);
5123
5124 if(rc == 0) {
5125 flow->category = ret->category = (ndpi_protocol_category_t) id;
5126 return;
5127 }
5128 }
5129
5130 if(flow->l4.tcp.tls.hello_processed == 1 &&
5131 flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] != '\0') {
5132 u_int32_t id;
5133 int rc = ndpi_match_custom_category(ndpi_str, (char *) flow->protos.tls_quic_stun.tls_quic.client_requested_server_name,
5134 strlen(flow->protos.tls_quic_stun.tls_quic.client_requested_server_name), &id);
5135
5136 if(rc == 0) {
5137 flow->category = ret->category = (ndpi_protocol_category_t) id;
5138 return;
5139 }
5140 }
5141 }
5142
5143 flow->category = ret->category = ndpi_get_proto_category(ndpi_str, *ret);
5144 }
5145
5146 /* ********************************************************************************* */
5147
ndpi_reset_packet_line_info(struct ndpi_packet_struct * packet)5148 static void ndpi_reset_packet_line_info(struct ndpi_packet_struct *packet) {
5149 packet->parsed_lines = 0, packet->empty_line_position_set = 0, packet->host_line.ptr = NULL,
5150 packet->host_line.len = 0, packet->referer_line.ptr = NULL, packet->referer_line.len = 0,
5151 packet->content_line.ptr = NULL, packet->content_line.len = 0, packet->accept_line.ptr = NULL,
5152 packet->accept_line.len = 0, packet->user_agent_line.ptr = NULL, packet->user_agent_line.len = 0,
5153 packet->http_url_name.ptr = NULL, packet->http_url_name.len = 0, packet->http_encoding.ptr = NULL,
5154 packet->http_encoding.len = 0, packet->http_transfer_encoding.ptr = NULL, packet->http_transfer_encoding.len = 0,
5155 packet->http_contentlen.ptr = NULL, packet->http_contentlen.len = 0, packet->content_disposition_line.ptr = NULL,
5156 packet->content_disposition_line.len = 0, packet->http_cookie.ptr = NULL,
5157 packet->http_cookie.len = 0, packet->http_origin.len = 0, packet->http_origin.ptr = NULL,
5158 packet->http_x_session_type.ptr = NULL, packet->http_x_session_type.len = 0, packet->server_line.ptr = NULL,
5159 packet->server_line.len = 0, packet->http_method.ptr = NULL, packet->http_method.len = 0,
5160 packet->http_response.ptr = NULL, packet->http_response.len = 0, packet->http_num_headers = 0,
5161 packet->forwarded_line.ptr = NULL, packet->forwarded_line.len = 0;
5162 }
5163
5164 /* ********************************************************************************* */
5165
ndpi_is_ntop_protocol(ndpi_protocol * ret)5166 static int ndpi_is_ntop_protocol(ndpi_protocol *ret) {
5167 if((ret->master_protocol == NDPI_PROTOCOL_HTTP) && (ret->app_protocol == NDPI_PROTOCOL_NTOP))
5168 return(1);
5169 else
5170 return(0);
5171 }
5172
5173 /* ********************************************************************************* */
5174
ndpi_check_protocol_port_mismatch_exceptions(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,ndpi_default_ports_tree_node_t * expected_proto,ndpi_protocol * returned_proto)5175 static int ndpi_check_protocol_port_mismatch_exceptions(struct ndpi_detection_module_struct *ndpi_str,
5176 struct ndpi_flow_struct *flow,
5177 ndpi_default_ports_tree_node_t *expected_proto,
5178 ndpi_protocol *returned_proto) {
5179 /*
5180 For TLS (and other protocols) it is not simple to guess the exact protocol so before
5181 triggering an alert we need to make sure what we have exhausted all the possible
5182 options available
5183 */
5184
5185 if(ndpi_is_ntop_protocol(returned_proto)) return(1);
5186
5187 if(returned_proto->master_protocol == NDPI_PROTOCOL_TLS) {
5188 switch(expected_proto->proto->protoId) {
5189 case NDPI_PROTOCOL_MAIL_IMAPS:
5190 case NDPI_PROTOCOL_MAIL_POPS:
5191 case NDPI_PROTOCOL_MAIL_SMTPS:
5192 return(1); /* This is a reasonable exception */
5193 break;
5194 }
5195 }
5196
5197 return(0);
5198 }
5199
5200 /* ********************************************************************************* */
5201
ndpi_reconcile_protocols(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,ndpi_protocol * ret)5202 static void ndpi_reconcile_protocols(struct ndpi_detection_module_struct *ndpi_str,
5203 struct ndpi_flow_struct *flow,
5204 ndpi_protocol *ret) {
5205
5206 #if 0
5207 if(flow) {
5208 /* Do not go for DNS when there is an application protocol. Example DNS.Apple */
5209 if((flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN)
5210 && (flow->detected_protocol_stack[0] /* app */ != flow->detected_protocol_stack[1] /* major */))
5211 NDPI_CLR_BIT(flow->risk, NDPI_SUSPICIOUS_DGA_DOMAIN);
5212 }
5213 #endif
5214
5215 // printf("====>> %u.%u [%u]\n", ret->master_protocol, ret->app_protocol, flow->detected_protocol_stack[0]);
5216
5217 switch(ret->app_protocol) {
5218 /*
5219 Skype for a host doing MS Teams means MS Teams
5220 (MS Teams uses Skype as transport protocol for voice/video)
5221 */
5222 case NDPI_PROTOCOL_MSTEAMS:
5223 if(flow->packet.iph && flow->packet.tcp) {
5224 // printf("====>> NDPI_PROTOCOL_MSTEAMS\n");
5225
5226 if(ndpi_str->msteams_cache == NULL)
5227 ndpi_str->msteams_cache = ndpi_lru_cache_init(1024);
5228
5229 if(ndpi_str->msteams_cache)
5230 ndpi_lru_add_to_cache(ndpi_str->msteams_cache,
5231 flow->packet.iph->saddr,
5232 (flow->packet.current_time_ms / 1000) & 0xFFFF /* 16 bit */);
5233 }
5234 break;
5235
5236 case NDPI_PROTOCOL_SKYPE_TEAMS:
5237 case NDPI_PROTOCOL_SKYPE_CALL:
5238 if(flow->packet.iph
5239 && flow->packet.udp
5240 && ndpi_str->msteams_cache) {
5241 u_int16_t when;
5242
5243 if(ndpi_lru_find_cache(ndpi_str->msteams_cache, flow->packet.iph->saddr,
5244 &when, 0 /* Don't remove it as it can be used for other connections */)) {
5245 u_int16_t tdiff = ((flow->packet.current_time_ms /1000) & 0xFFFF) - when;
5246
5247 if(tdiff < 60 /* sec */) {
5248 // printf("====>> NDPI_PROTOCOL_SKYPE(_CALL) -> NDPI_PROTOCOL_MSTEAMS [%u]\n", tdiff);
5249 ret->app_protocol = NDPI_PROTOCOL_MSTEAMS;
5250
5251 /* Refresh cache */
5252 ndpi_lru_add_to_cache(ndpi_str->msteams_cache,
5253 flow->packet.iph->saddr,
5254 (flow->packet.current_time_ms / 1000) & 0xFFFF /* 16 bit */);
5255 }
5256 }
5257 }
5258 break;
5259
5260 case NDPI_PROTOCOL_ANYDESK:
5261 if(flow->packet.tcp) /* TCP only */
5262 ndpi_set_risk(ndpi_str, flow, NDPI_DESKTOP_OR_FILE_SHARING_SESSION); /* Remote assistance */
5263 break;
5264 } /* switch */
5265
5266 if(flow) {
5267 switch(ndpi_get_proto_breed(ndpi_str, ret->app_protocol)) {
5268 case NDPI_PROTOCOL_UNSAFE:
5269 case NDPI_PROTOCOL_POTENTIALLY_DANGEROUS:
5270 case NDPI_PROTOCOL_DANGEROUS:
5271 ndpi_set_risk(ndpi_str, flow, NDPI_UNSAFE_PROTOCOL);
5272 break;
5273 default:
5274 /* Nothing to do */
5275 break;
5276 }
5277 }
5278
5279 }
5280
5281 /* ****************************************************** */
5282
ndpi_do_guess(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,ndpi_protocol * ret)5283 static int ndpi_do_guess(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, ndpi_protocol *ret) {
5284 ret->master_protocol = ret->app_protocol = NDPI_PROTOCOL_UNKNOWN, ret->category = 0;
5285
5286 if(flow->packet.iphv6 || flow->packet.iph) {
5287 u_int16_t sport, dport;
5288 u_int8_t protocol;
5289 u_int8_t user_defined_proto;
5290
5291 if(flow->packet.iphv6 != NULL) {
5292 protocol = flow->packet.iphv6->ip6_hdr.ip6_un1_nxt;
5293 } else
5294 protocol = flow->packet.iph->protocol;
5295
5296 if(flow->packet.udp)
5297 sport = ntohs(flow->packet.udp->source), dport = ntohs(flow->packet.udp->dest);
5298 else if(flow->packet.tcp)
5299 sport = ntohs(flow->packet.tcp->source), dport = ntohs(flow->packet.tcp->dest);
5300 else
5301 sport = dport = 0;
5302
5303 /* guess protocol */
5304 flow->guessed_protocol_id = (int16_t) ndpi_guess_protocol_id(ndpi_str, flow, protocol, sport, dport, &user_defined_proto);
5305 flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_str, flow);
5306
5307 if(ndpi_str->custom_categories.categories_loaded && flow->packet.iph) {
5308 if(ndpi_str->ndpi_num_custom_protocols != 0)
5309 ndpi_fill_ip_protocol_category(ndpi_str, flow->packet.iph->saddr, flow->packet.iph->daddr, ret);
5310 flow->guessed_header_category = ret->category;
5311 } else
5312 flow->guessed_header_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED;
5313
5314 if(flow->guessed_protocol_id >= NDPI_MAX_SUPPORTED_PROTOCOLS) {
5315 /* This is a custom protocol and it has priority over everything else */
5316 ret->master_protocol = NDPI_PROTOCOL_UNKNOWN,
5317 ret->app_protocol = flow->guessed_protocol_id ? flow->guessed_protocol_id : flow->guessed_host_protocol_id;
5318
5319 // if(ndpi_str->ndpi_num_custom_protocols != 0)
5320 ndpi_fill_protocol_category(ndpi_str, flow, ret);
5321 return(-1);
5322 }
5323
5324 if(user_defined_proto && flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
5325 if(flow->packet.iph) {
5326 if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
5327 u_int8_t protocol_was_guessed;
5328
5329 /* ret->master_protocol = flow->guessed_protocol_id , ret->app_protocol = flow->guessed_host_protocol_id; /\* ****** *\/ */
5330 *ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed);
5331 }
5332
5333 // if(ndpi_str->ndpi_num_custom_protocols != 0)
5334 ndpi_fill_protocol_category(ndpi_str, flow, ret);
5335 return(-1);
5336 }
5337 } else {
5338 /* guess host protocol */
5339 if(flow->packet.iph) {
5340 flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_str, flow);
5341
5342 /*
5343 We could implement a shortcut here skipping dissectors for
5344 protocols we have identified by other means such as with the IP
5345
5346 However we do NOT stop here and skip invoking the dissectors
5347 because we want to dissect the flow (e.g. dissect the TLS)
5348 and extract metadata.
5349 */
5350 #if SKIP_INVOKING_THE_DISSECTORS
5351 if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
5352 /*
5353 We have identified a protocol using the IP address so
5354 it is not worth to dissect the traffic as we already have
5355 the solution
5356 */
5357 ret->master_protocol = flow->guessed_protocol_id, ret->app_protocol = flow->guessed_host_protocol_id;
5358 }
5359 #endif
5360 }
5361 }
5362 }
5363
5364 if(flow->guessed_host_protocol_id >= NDPI_MAX_SUPPORTED_PROTOCOLS) {
5365 //u_int32_t num_calls;
5366 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_packet = {0};
5367
5368 /* This is a custom protocol and it has priority over everything else */
5369 ret->master_protocol = flow->guessed_protocol_id, ret->app_protocol = flow->guessed_host_protocol_id;
5370
5371 //num_calls =
5372 ndpi_check_flow_func(ndpi_str, flow, &ndpi_selection_packet);
5373
5374 //if(ndpi_str->ndpi_num_custom_protocols != 0)
5375 ndpi_fill_protocol_category(ndpi_str, flow, ret);
5376 return(-1);
5377 }
5378
5379 return(0);
5380 }
5381
5382 /* ********************************************************************************* */
5383
ndpi_detection_process_packet(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,const unsigned char * packet,const unsigned short packetlen,const u_int64_t current_time_ms,struct ndpi_id_struct * src,struct ndpi_id_struct * dst)5384 ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_str,
5385 struct ndpi_flow_struct *flow, const unsigned char *packet,
5386 const unsigned short packetlen, const u_int64_t current_time_ms,
5387 struct ndpi_id_struct *src, struct ndpi_id_struct *dst) {
5388 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_packet;
5389 u_int32_t a, num_calls = 0;
5390 ndpi_protocol ret = { flow->detected_protocol_stack[1], flow->detected_protocol_stack[0], flow->category };
5391
5392 if(ndpi_str->ndpi_log_level >= NDPI_LOG_TRACE)
5393 NDPI_LOG(flow ? flow->detected_protocol_stack[0] : NDPI_PROTOCOL_UNKNOWN, ndpi_str, NDPI_LOG_TRACE,
5394 "START packet processing\n");
5395
5396 if(flow == NULL)
5397 return(ret);
5398 else
5399 ret.category = flow->category;
5400
5401 if(flow->fail_with_unknown) {
5402 // printf("%s(): FAIL_WITH_UNKNOWN\n", __FUNCTION__);
5403 return(ret);
5404 }
5405
5406 flow->num_processed_pkts++;
5407
5408 /* Init default */
5409 ret.master_protocol = flow->detected_protocol_stack[1],
5410 ret.app_protocol = flow->detected_protocol_stack[0];
5411
5412 if(flow->server_id == NULL)
5413 flow->server_id = dst; /* Default */
5414
5415 if(flow->check_extra_packets) {
5416 ndpi_process_extra_packet(ndpi_str, flow, packet, packetlen, current_time_ms, src, dst);
5417 /* Update in case of new match */
5418 ret.master_protocol = flow->detected_protocol_stack[1],
5419 ret.app_protocol = flow->detected_protocol_stack[0],
5420 ret.category = flow->category;
5421 goto invalidate_ptr;
5422 } else if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
5423 goto ret_protocols;
5424
5425 /* need at least 20 bytes for ip header */
5426 if(packetlen < 20) {
5427 /* reset protocol which is normally done in init_packet_header */
5428 ndpi_int_reset_packet_protocol(&flow->packet);
5429 goto invalidate_ptr;
5430 }
5431
5432 flow->packet.current_time_ms = current_time_ms;
5433
5434 /* parse packet */
5435 flow->packet.iph = (struct ndpi_iphdr *) packet;
5436 /* we are interested in ipv4 packet */
5437
5438 if(ndpi_init_packet_header(ndpi_str, flow, packetlen) != 0)
5439 goto invalidate_ptr;
5440
5441 /* detect traffic for tcp or udp only */
5442 flow->src = src, flow->dst = dst;
5443
5444 ndpi_connection_tracking(ndpi_str, flow);
5445
5446 /* build ndpi_selection packet bitmask */
5447 ndpi_selection_packet = NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC;
5448 if(flow->packet.iph != NULL)
5449 ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6;
5450
5451 if(flow->packet.tcp != NULL)
5452 ndpi_selection_packet |=
5453 (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP);
5454
5455 if(flow->packet.udp != NULL)
5456 ndpi_selection_packet |=
5457 (NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP);
5458
5459 if(flow->packet.payload_packet_len != 0)
5460 ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD;
5461
5462 if(flow->packet.tcp_retransmission == 0)
5463 ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION;
5464
5465 if(flow->packet.iphv6 != NULL)
5466 ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6;
5467
5468 if(!flow->protocol_id_already_guessed) {
5469 flow->protocol_id_already_guessed = 1;
5470
5471 if(ndpi_do_guess(ndpi_str, flow, &ret) == -1)
5472 goto invalidate_ptr;
5473 }
5474
5475 num_calls = ndpi_check_flow_func(ndpi_str, flow, &ndpi_selection_packet);
5476
5477 a = flow->packet.detected_protocol_stack[0];
5478 if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_str->detection_bitmask, a) == 0)
5479 a = NDPI_PROTOCOL_UNKNOWN;
5480
5481 if(a != NDPI_PROTOCOL_UNKNOWN) {
5482 int i;
5483
5484 for(i = 0; i < sizeof(flow->host_server_name); i++) {
5485 if(flow->host_server_name[i] != '\0')
5486 flow->host_server_name[i] = tolower(flow->host_server_name[i]);
5487 else {
5488 flow->host_server_name[i] = '\0';
5489 break;
5490 }
5491 }
5492 }
5493
5494 ret_protocols:
5495 if(flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN) {
5496 ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
5497
5498 if(ret.app_protocol == ret.master_protocol)
5499 ret.master_protocol = NDPI_PROTOCOL_UNKNOWN;
5500 } else
5501 ret.app_protocol = flow->detected_protocol_stack[0];
5502
5503 /* Don't overwrite the category if already set */
5504 if((flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN))
5505 ndpi_fill_protocol_category(ndpi_str, flow, &ret);
5506 else
5507 ret.category = flow->category;
5508
5509 if((flow->num_processed_pkts == 1) && (ret.master_protocol == NDPI_PROTOCOL_UNKNOWN) &&
5510 (ret.app_protocol == NDPI_PROTOCOL_UNKNOWN) && flow->packet.tcp && (flow->packet.tcp->syn == 0) &&
5511 (flow->guessed_protocol_id == 0)) {
5512 u_int8_t protocol_was_guessed;
5513
5514 /*
5515 This is a TCP flow
5516 - whose first packet is NOT a SYN
5517 - no protocol has been detected
5518
5519 We don't see how future packets can match anything
5520 hence we giveup here
5521 */
5522 ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed);
5523 }
5524
5525 if((ret.master_protocol == NDPI_PROTOCOL_UNKNOWN) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN) &&
5526 (flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN)) {
5527 ret.master_protocol = ret.app_protocol;
5528 ret.app_protocol = flow->guessed_host_protocol_id;
5529 }
5530
5531 if((!flow->risk_checked)
5532 && ((ret.master_protocol != NDPI_PROTOCOL_UNKNOWN) || (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN))
5533 ) {
5534 ndpi_default_ports_tree_node_t *found;
5535 u_int16_t *default_ports, sport, dport;
5536
5537 if(flow->packet.udp)
5538 found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_UDP,
5539 sport = ntohs(flow->packet.udp->source),
5540 dport = ntohs(flow->packet.udp->dest)),
5541 default_ports = ndpi_str->proto_defaults[ret.master_protocol ? ret.master_protocol : ret.app_protocol].udp_default_ports;
5542 else if(flow->packet.tcp)
5543 found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_TCP,
5544 sport = ntohs(flow->packet.tcp->source),
5545 dport = ntohs(flow->packet.tcp->dest)),
5546 default_ports = ndpi_str->proto_defaults[ret.master_protocol ? ret.master_protocol : ret.app_protocol].tcp_default_ports;
5547 else
5548 found = NULL, default_ports = NULL, sport = dport = 0;
5549
5550 if(found
5551 && (found->proto->protoId != NDPI_PROTOCOL_UNKNOWN)
5552 && (found->proto->protoId != ret.master_protocol)
5553 && (found->proto->protoId != ret.app_protocol)
5554 ) {
5555 // printf("******** %u / %u\n", found->proto->protoId, ret.master_protocol);
5556
5557 if(!ndpi_check_protocol_port_mismatch_exceptions(ndpi_str, flow, found, &ret)) {
5558 /*
5559 Before triggering the alert we need to make some extra checks
5560 - the protocol found is not running on the port we have found (i.e. two or more protools share the same default port)
5561 */
5562 u_int8_t found = 0, i;
5563
5564 for(i=0; (i<MAX_DEFAULT_PORTS) && (default_ports[i] != 0); i++) {
5565 if(default_ports[i] == dport) {
5566 found = 1;
5567 break;
5568 }
5569 } /* for */
5570
5571 if(!found)
5572 ndpi_set_risk(ndpi_str, flow, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
5573 }
5574 } else if((!ndpi_is_ntop_protocol(&ret)) && default_ports && (default_ports[0] != 0)) {
5575 u_int8_t found = 0, i, num_loops = 0;
5576
5577 check_default_ports:
5578 for(i=0; (i<MAX_DEFAULT_PORTS) && (default_ports[i] != 0); i++) {
5579 if((default_ports[i] == sport) || (default_ports[i] == dport)) {
5580 found = 1;
5581 break;
5582 }
5583 } /* for */
5584
5585 if((num_loops == 0) && (!found)) {
5586 if(flow->packet.udp)
5587 default_ports = ndpi_str->proto_defaults[ret.app_protocol].udp_default_ports;
5588 else
5589 default_ports = ndpi_str->proto_defaults[ret.app_protocol].tcp_default_ports;
5590
5591 num_loops = 1;
5592 goto check_default_ports;
5593 }
5594
5595 if(!found) {
5596 // printf("******** Invalid default port\n");
5597 ndpi_set_risk(ndpi_str, flow, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
5598 }
5599 }
5600
5601 flow->risk_checked = 1;
5602 }
5603
5604 ndpi_reconcile_protocols(ndpi_str, flow, &ret);
5605
5606 if(num_calls == 0)
5607 flow->fail_with_unknown = 1;
5608
5609 invalidate_ptr:
5610 /*
5611 Invalidate packet memory to avoid accessing the pointers below
5612 when the packet is no longer accessible
5613 */
5614 flow->packet.iph = NULL, flow->packet.tcp = NULL, flow->packet.udp = NULL, flow->packet.payload = NULL;
5615 ndpi_reset_packet_line_info(&flow->packet);
5616
5617 return(ret);
5618 }
5619
5620 /* ********************************************************************************* */
5621
ndpi_bytestream_to_number(const u_int8_t * str,u_int16_t max_chars_to_read,u_int16_t * bytes_read)5622 u_int32_t ndpi_bytestream_to_number(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) {
5623 u_int32_t val;
5624 val = 0;
5625
5626 // cancel if eof, ' ' or line end chars are reached
5627 while(*str >= '0' && *str <= '9' && max_chars_to_read > 0) {
5628 val *= 10;
5629 val += *str - '0';
5630 str++;
5631 max_chars_to_read = max_chars_to_read - 1;
5632 *bytes_read = *bytes_read + 1;
5633 }
5634
5635 return(val);
5636 }
5637
5638 /* ********************************************************************************* */
5639
5640 #ifdef CODE_UNUSED
ndpi_bytestream_dec_or_hex_to_number(const u_int8_t * str,u_int16_t max_chars_to_read,u_int16_t * bytes_read)5641 u_int32_t ndpi_bytestream_dec_or_hex_to_number(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) {
5642 u_int32_t val;
5643 val = 0;
5644 if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') {
5645 return(ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read));
5646 } else {
5647 /*use base 16 system */
5648 str += 2;
5649 max_chars_to_read -= 2;
5650 *bytes_read = *bytes_read + 2;
5651
5652 while(max_chars_to_read > 0) {
5653 if(*str >= '0' && *str <= '9') {
5654 val *= 16;
5655 val += *str - '0';
5656 } else if(*str >= 'a' && *str <= 'f') {
5657 val *= 16;
5658 val += *str + 10 - 'a';
5659 } else if(*str >= 'A' && *str <= 'F') {
5660 val *= 16;
5661 val += *str + 10 - 'A';
5662 } else {
5663 break;
5664 }
5665 str++;
5666 max_chars_to_read = max_chars_to_read - 1;
5667 *bytes_read = *bytes_read + 1;
5668 }
5669 }
5670
5671 return(val);
5672 }
5673
5674 #endif
5675
5676 /* ********************************************************************************* */
5677
ndpi_bytestream_to_number64(const u_int8_t * str,u_int16_t max_chars_to_read,u_int16_t * bytes_read)5678 u_int64_t ndpi_bytestream_to_number64(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) {
5679 u_int64_t val;
5680 val = 0;
5681 // cancel if eof, ' ' or line end chars are reached
5682 while(max_chars_to_read > 0 && *str >= '0' && *str <= '9') {
5683 val *= 10;
5684 val += *str - '0';
5685 str++;
5686 max_chars_to_read = max_chars_to_read - 1;
5687 *bytes_read = *bytes_read + 1;
5688 }
5689 return(val);
5690 }
5691
5692 /* ********************************************************************************* */
5693
ndpi_bytestream_dec_or_hex_to_number64(const u_int8_t * str,u_int16_t max_chars_to_read,u_int16_t * bytes_read)5694 u_int64_t ndpi_bytestream_dec_or_hex_to_number64(const u_int8_t *str, u_int16_t max_chars_to_read,
5695 u_int16_t *bytes_read) {
5696 u_int64_t val;
5697 val = 0;
5698 if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') {
5699 return(ndpi_bytestream_to_number64(str, max_chars_to_read, bytes_read));
5700 } else {
5701 /*use base 16 system */
5702 str += 2;
5703 max_chars_to_read -= 2;
5704 *bytes_read = *bytes_read + 2;
5705 while(max_chars_to_read > 0) {
5706 if(*str >= '0' && *str <= '9') {
5707 val *= 16;
5708 val += *str - '0';
5709 } else if(*str >= 'a' && *str <= 'f') {
5710 val *= 16;
5711 val += *str + 10 - 'a';
5712 } else if(*str >= 'A' && *str <= 'F') {
5713 val *= 16;
5714 val += *str + 10 - 'A';
5715 } else {
5716 break;
5717 }
5718 str++;
5719 max_chars_to_read = max_chars_to_read - 1;
5720 *bytes_read = *bytes_read + 1;
5721 }
5722 }
5723 return(val);
5724 }
5725
5726 /* ********************************************************************************* */
5727
ndpi_bytestream_to_ipv4(const u_int8_t * str,u_int16_t max_chars_to_read,u_int16_t * bytes_read)5728 u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) {
5729 u_int32_t val;
5730 u_int16_t read = 0;
5731 u_int16_t oldread;
5732 u_int32_t c;
5733
5734 /* ip address must be X.X.X.X with each X between 0 and 255 */
5735 oldread = read;
5736 c = ndpi_bytestream_to_number(str, max_chars_to_read, &read);
5737 if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
5738 return(0);
5739
5740 read++;
5741 val = c << 24;
5742 oldread = read;
5743 c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
5744 if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
5745 return(0);
5746
5747 read++;
5748 val = val + (c << 16);
5749 oldread = read;
5750 c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
5751 if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
5752 return(0);
5753
5754 read++;
5755 val = val + (c << 8);
5756 oldread = read;
5757 c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
5758 if(c > 255 || oldread == read || max_chars_to_read == read)
5759 return(0);
5760
5761 val = val + c;
5762
5763 *bytes_read = *bytes_read + read;
5764
5765 return(htonl(val));
5766 }
5767
5768 /* ********************************************************************************* */
5769
5770 /* internal function for every detection to parse one packet and to increase the info buffer */
ndpi_parse_packet_line_info(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow)5771 void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) {
5772 u_int32_t a;
5773 struct ndpi_packet_struct *packet = &flow->packet;
5774
5775 if((packet->payload_packet_len < 3) || (packet->payload == NULL))
5776 return;
5777
5778 if(packet->packet_lines_parsed_complete != 0)
5779 return;
5780
5781 packet->packet_lines_parsed_complete = 1;
5782 ndpi_reset_packet_line_info(packet);
5783
5784 packet->line[packet->parsed_lines].ptr = packet->payload;
5785 packet->line[packet->parsed_lines].len = 0;
5786
5787 for(a = 0; ((a+1) < packet->payload_packet_len) && (packet->parsed_lines < NDPI_MAX_PARSE_LINES_PER_PACKET); a++) {
5788 if((packet->payload[a] == 0x0d) && (packet->payload[a+1] == 0x0a)) {
5789 /* If end of line char sequence CR+NL "\r\n", process line */
5790
5791 if(((a + 3) < packet->payload_packet_len)
5792 && (packet->payload[a+2] == 0x0d)
5793 && (packet->payload[a+3] == 0x0a)) {
5794 /* \r\n\r\n */
5795 int diff; /* No unsigned ! */
5796 u_int32_t a1 = a + 4;
5797
5798 diff = packet->payload_packet_len - a1;
5799
5800 if(diff > 0) {
5801 diff = ndpi_min(diff, sizeof(flow->initial_binary_bytes));
5802 memcpy(&flow->initial_binary_bytes, &packet->payload[a1], diff);
5803 flow->initial_binary_bytes_len = diff;
5804 }
5805 }
5806
5807 packet->line[packet->parsed_lines].len =
5808 (u_int16_t)(((size_t) &packet->payload[a]) - ((size_t) packet->line[packet->parsed_lines].ptr));
5809
5810 /* First line of a HTTP response parsing. Expected a "HTTP/1.? ???" */
5811 if(packet->parsed_lines == 0 && packet->line[0].len >= NDPI_STATICSTRING_LEN("HTTP/1.X 200 ") &&
5812 strncasecmp((const char *) packet->line[0].ptr, "HTTP/1.", NDPI_STATICSTRING_LEN("HTTP/1.")) == 0 &&
5813 packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.X ")] > '0' && /* response code between 000 and 699 */
5814 packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.X ")] < '6') {
5815 packet->http_response.ptr = &packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.1 ")];
5816 packet->http_response.len = packet->line[0].len - NDPI_STATICSTRING_LEN("HTTP/1.1 ");
5817 packet->http_num_headers++;
5818
5819 /* Set server HTTP response code */
5820 if(packet->payload_packet_len >= 12) {
5821 char buf[4];
5822
5823 /* Set server HTTP response code */
5824 strncpy(buf, (char *) &packet->payload[9], 3);
5825 buf[3] = '\0';
5826
5827 flow->http.response_status_code = atoi(buf);
5828 /* https://en.wikipedia.org/wiki/List_of_HTTP_status_codes */
5829 if((flow->http.response_status_code < 100) || (flow->http.response_status_code > 509))
5830 flow->http.response_status_code = 0; /* Out of range */
5831 }
5832 }
5833
5834 /* "Server:" header line in HTTP response */
5835 if(packet->line[packet->parsed_lines].len > NDPI_STATICSTRING_LEN("Server:") + 1 &&
5836 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr,
5837 "Server:", NDPI_STATICSTRING_LEN("Server:")) == 0) {
5838 // some stupid clients omit a space and place the servername directly after the colon
5839 if(packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")] == ' ') {
5840 packet->server_line.ptr =
5841 &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:") + 1];
5842 packet->server_line.len =
5843 packet->line[packet->parsed_lines].len - (NDPI_STATICSTRING_LEN("Server:") + 1);
5844 } else {
5845 packet->server_line.ptr = &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")];
5846 packet->server_line.len = packet->line[packet->parsed_lines].len - NDPI_STATICSTRING_LEN("Server:");
5847 }
5848 packet->http_num_headers++;
5849 }
5850 /* "Host:" header line in HTTP request */
5851 if(packet->line[packet->parsed_lines].len > 6 &&
5852 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Host:", 5) == 0) {
5853 // some stupid clients omit a space and place the hostname directly after the colon
5854 if(packet->line[packet->parsed_lines].ptr[5] == ' ') {
5855 packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[6];
5856 packet->host_line.len = packet->line[packet->parsed_lines].len - 6;
5857 } else {
5858 packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[5];
5859 packet->host_line.len = packet->line[packet->parsed_lines].len - 5;
5860 }
5861 packet->http_num_headers++;
5862 }
5863 /* "X-Forwarded-For:" header line in HTTP request. Commonly used for HTTP proxies. */
5864 if(packet->line[packet->parsed_lines].len > 17 &&
5865 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Forwarded-For:", 16) == 0) {
5866 // some stupid clients omit a space and place the hostname directly after the colon
5867 if(packet->line[packet->parsed_lines].ptr[16] == ' ') {
5868 packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[17];
5869 packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 17;
5870 } else {
5871 packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[16];
5872 packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 16;
5873 }
5874 packet->http_num_headers++;
5875 }
5876 /* "Content-Type:" header line in HTTP. */
5877 if(packet->line[packet->parsed_lines].len > 14 &&
5878 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Type: ", 14) == 0 ||
5879 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-type: ", 14) == 0)) {
5880 packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[14];
5881 packet->content_line.len = packet->line[packet->parsed_lines].len - 14;
5882
5883 while((packet->content_line.len > 0) && (packet->content_line.ptr[0] == ' '))
5884 packet->content_line.len--, packet->content_line.ptr++;
5885
5886 packet->http_num_headers++;
5887 }
5888 /* "Content-Type:" header line in HTTP AGAIN. Probably a bogus response without space after ":" */
5889 if((packet->content_line.len == 0) && (packet->line[packet->parsed_lines].len > 13) &&
5890 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-type:", 13) == 0)) {
5891 packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[13];
5892 packet->content_line.len = packet->line[packet->parsed_lines].len - 13;
5893 packet->http_num_headers++;
5894 }
5895
5896 if(packet->content_line.len > 0) {
5897 /* application/json; charset=utf-8 */
5898 char separator[] = {';', '\r', '\0'};
5899 int i;
5900
5901 for(i = 0; separator[i] != '\0'; i++) {
5902 char *c = memchr((char *) packet->content_line.ptr, separator[i], packet->content_line.len);
5903
5904 if(c != NULL)
5905 packet->content_line.len = c - (char *) packet->content_line.ptr;
5906 }
5907 }
5908
5909 /* "Accept:" header line in HTTP request. */
5910 if(packet->line[packet->parsed_lines].len > 8 &&
5911 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept: ", 8) == 0) {
5912 packet->accept_line.ptr = &packet->line[packet->parsed_lines].ptr[8];
5913 packet->accept_line.len = packet->line[packet->parsed_lines].len - 8;
5914 packet->http_num_headers++;
5915 }
5916 /* "Referer:" header line in HTTP request. */
5917 if(packet->line[packet->parsed_lines].len > 9 &&
5918 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Referer: ", 9) == 0) {
5919 packet->referer_line.ptr = &packet->line[packet->parsed_lines].ptr[9];
5920 packet->referer_line.len = packet->line[packet->parsed_lines].len - 9;
5921 packet->http_num_headers++;
5922 }
5923 /* "User-Agent:" header line in HTTP request. */
5924 if(packet->line[packet->parsed_lines].len > 12 &&
5925 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "User-Agent: ", 12) == 0 ||
5926 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "User-agent: ", 12) == 0)) {
5927 packet->user_agent_line.ptr = &packet->line[packet->parsed_lines].ptr[12];
5928 packet->user_agent_line.len = packet->line[packet->parsed_lines].len - 12;
5929 packet->http_num_headers++;
5930 }
5931 /* "Content-Encoding:" header line in HTTP response (and request?). */
5932 if(packet->line[packet->parsed_lines].len > 18 &&
5933 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Encoding: ", 18) == 0) {
5934 packet->http_encoding.ptr = &packet->line[packet->parsed_lines].ptr[18];
5935 packet->http_encoding.len = packet->line[packet->parsed_lines].len - 18;
5936 packet->http_num_headers++;
5937 }
5938 /* "Transfer-Encoding:" header line in HTTP. */
5939 if(packet->line[packet->parsed_lines].len > 19 &&
5940 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Transfer-Encoding: ", 19) == 0) {
5941 packet->http_transfer_encoding.ptr = &packet->line[packet->parsed_lines].ptr[19];
5942 packet->http_transfer_encoding.len = packet->line[packet->parsed_lines].len - 19;
5943 packet->http_num_headers++;
5944 }
5945 /* "Content-Length:" header line in HTTP. */
5946 if(packet->line[packet->parsed_lines].len > 16 &&
5947 ((strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Length: ", 16) == 0) ||
5948 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "content-length: ", 16) == 0))) {
5949 packet->http_contentlen.ptr = &packet->line[packet->parsed_lines].ptr[16];
5950 packet->http_contentlen.len = packet->line[packet->parsed_lines].len - 16;
5951 packet->http_num_headers++;
5952 }
5953 /* "Content-Disposition"*/
5954 if(packet->line[packet->parsed_lines].len > 21 &&
5955 ((strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Disposition: ", 21) == 0))) {
5956 packet->content_disposition_line.ptr = &packet->line[packet->parsed_lines].ptr[21];
5957 packet->content_disposition_line.len = packet->line[packet->parsed_lines].len - 21;
5958 packet->http_num_headers++;
5959 }
5960 /* "Cookie:" header line in HTTP. */
5961 if(packet->line[packet->parsed_lines].len > 8 &&
5962 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Cookie: ", 8) == 0) {
5963 packet->http_cookie.ptr = &packet->line[packet->parsed_lines].ptr[8];
5964 packet->http_cookie.len = packet->line[packet->parsed_lines].len - 8;
5965 packet->http_num_headers++;
5966 }
5967 /* "Origin:" header line in HTTP. */
5968 if(packet->line[packet->parsed_lines].len > 8 &&
5969 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Origin: ", 8) == 0) {
5970 packet->http_origin.ptr = &packet->line[packet->parsed_lines].ptr[8];
5971 packet->http_origin.len = packet->line[packet->parsed_lines].len - 8;
5972 packet->http_num_headers++;
5973 }
5974 /* "X-Session-Type:" header line in HTTP. */
5975 if(packet->line[packet->parsed_lines].len > 16 &&
5976 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Session-Type: ", 16) == 0) {
5977 packet->http_x_session_type.ptr = &packet->line[packet->parsed_lines].ptr[16];
5978 packet->http_x_session_type.len = packet->line[packet->parsed_lines].len - 16;
5979 packet->http_num_headers++;
5980 }
5981 /* Identification and counting of other HTTP headers.
5982 * We consider the most common headers, but there are many others,
5983 * which can be seen at references below:
5984 * - https://tools.ietf.org/html/rfc7230
5985 * - https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
5986 */
5987 if((packet->line[packet->parsed_lines].len > 6 &&
5988 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Date: ", 6) == 0 ||
5989 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Vary: ", 6) == 0 ||
5990 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "ETag: ", 6) == 0)) ||
5991 (packet->line[packet->parsed_lines].len > 8 &&
5992 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Pragma: ", 8) == 0) ||
5993 (packet->line[packet->parsed_lines].len > 9 &&
5994 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Expires: ", 9) == 0) ||
5995 (packet->line[packet->parsed_lines].len > 12 &&
5996 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Set-Cookie: ", 12) == 0 ||
5997 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Keep-Alive: ", 12) == 0 ||
5998 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Connection: ", 12) == 0)) ||
5999 (packet->line[packet->parsed_lines].len > 15 &&
6000 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Last-Modified: ", 15) == 0 ||
6001 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Ranges: ", 15) == 0)) ||
6002 (packet->line[packet->parsed_lines].len > 17 &&
6003 (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Language: ", 17) == 0 ||
6004 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Encoding: ", 17) == 0)) ||
6005 (packet->line[packet->parsed_lines].len > 27 &&
6006 strncasecmp((const char *) packet->line[packet->parsed_lines].ptr,
6007 "Upgrade-Insecure-Requests: ", 27) == 0)) {
6008 /* Just count. In the future, if needed, this if can be splited to parse these headers */
6009 packet->http_num_headers++;
6010 }
6011
6012 if(packet->line[packet->parsed_lines].len == 0) {
6013 packet->empty_line_position = a;
6014 packet->empty_line_position_set = 1;
6015 }
6016
6017 if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1))
6018 return;
6019
6020 packet->parsed_lines++;
6021 packet->line[packet->parsed_lines].ptr = &packet->payload[a + 2];
6022 packet->line[packet->parsed_lines].len = 0;
6023
6024 a++; /* next char in the payload */
6025 }
6026 }
6027
6028 if(packet->parsed_lines >= 1) {
6029 packet->line[packet->parsed_lines].len =
6030 (u_int16_t)(((size_t) &packet->payload[packet->payload_packet_len]) -
6031 ((size_t) packet->line[packet->parsed_lines].ptr));
6032 packet->parsed_lines++;
6033 }
6034 }
6035
6036 /* ********************************************************************************* */
6037
ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow)6038 void ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) {
6039 struct ndpi_packet_struct *packet = &flow->packet;
6040 u_int32_t a;
6041 u_int16_t end = packet->payload_packet_len;
6042
6043 if(packet->packet_lines_parsed_complete != 0)
6044 return;
6045
6046 packet->packet_lines_parsed_complete = 1;
6047 packet->parsed_lines = 0;
6048
6049 if(packet->payload_packet_len == 0)
6050 return;
6051
6052 packet->line[packet->parsed_lines].ptr = packet->payload;
6053 packet->line[packet->parsed_lines].len = 0;
6054
6055 for(a = 0; a < end; a++) {
6056 if(packet->payload[a] == 0x0a) {
6057 packet->line[packet->parsed_lines].len = (u_int16_t)(
6058 ((size_t) &packet->payload[a]) - ((size_t) packet->line[packet->parsed_lines].ptr));
6059
6060 if(a > 0 && packet->payload[a - 1] == 0x0d)
6061 packet->line[packet->parsed_lines].len--;
6062
6063 if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1))
6064 break;
6065
6066 packet->parsed_lines++;
6067 packet->line[packet->parsed_lines].ptr = &packet->payload[a + 1];
6068 packet->line[packet->parsed_lines].len = 0;
6069
6070 if((a + 1) >= packet->payload_packet_len)
6071 break;
6072
6073 //a++;
6074 }
6075 }
6076 }
6077
6078 /* ********************************************************************************* */
6079
ndpi_check_for_email_address(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int16_t counter)6080 u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
6081 u_int16_t counter) {
6082 struct ndpi_packet_struct *packet = &flow->packet;
6083
6084 NDPI_LOG_DBG2(ndpi_str, "called ndpi_check_for_email_address\n");
6085
6086 if(packet->payload_packet_len > counter && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') ||
6087 (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') ||
6088 (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') ||
6089 packet->payload[counter] == '-' || packet->payload[counter] == '_')) {
6090 NDPI_LOG_DBG2(ndpi_str, "first letter\n");
6091 counter++;
6092 while(packet->payload_packet_len > counter &&
6093 ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') ||
6094 (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') ||
6095 (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') ||
6096 packet->payload[counter] == '-' || packet->payload[counter] == '_' ||
6097 packet->payload[counter] == '.')) {
6098 NDPI_LOG_DBG2(ndpi_str, "further letter\n");
6099 counter++;
6100 if(packet->payload_packet_len > counter && packet->payload[counter] == '@') {
6101 NDPI_LOG_DBG2(ndpi_str, "@\n");
6102 counter++;
6103 while(packet->payload_packet_len > counter &&
6104 ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') ||
6105 (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') ||
6106 (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') ||
6107 packet->payload[counter] == '-' || packet->payload[counter] == '_')) {
6108 NDPI_LOG_DBG2(ndpi_str, "letter\n");
6109 counter++;
6110 if(packet->payload_packet_len > counter && packet->payload[counter] == '.') {
6111 NDPI_LOG_DBG2(ndpi_str, ".\n");
6112 counter++;
6113 if(packet->payload_packet_len > counter + 1 &&
6114 ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') &&
6115 (packet->payload[counter + 1] >= 'a' && packet->payload[counter + 1] <= 'z'))) {
6116 NDPI_LOG_DBG2(ndpi_str, "two letters\n");
6117 counter += 2;
6118 if(packet->payload_packet_len > counter &&
6119 (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) {
6120 NDPI_LOG_DBG2(ndpi_str, "whitespace1\n");
6121 return(counter);
6122 } else if(packet->payload_packet_len > counter && packet->payload[counter] >= 'a' &&
6123 packet->payload[counter] <= 'z') {
6124 NDPI_LOG_DBG2(ndpi_str, "one letter\n");
6125 counter++;
6126 if(packet->payload_packet_len > counter &&
6127 (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) {
6128 NDPI_LOG_DBG2(ndpi_str, "whitespace2\n");
6129 return(counter);
6130 } else if(packet->payload_packet_len > counter && packet->payload[counter] >= 'a' &&
6131 packet->payload[counter] <= 'z') {
6132 counter++;
6133 if(packet->payload_packet_len > counter &&
6134 (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) {
6135 NDPI_LOG_DBG2(ndpi_str, "whitespace3\n");
6136 return(counter);
6137 } else {
6138 return(0);
6139 }
6140 } else {
6141 return(0);
6142 }
6143 } else {
6144 return(0);
6145 }
6146 } else {
6147 return(0);
6148 }
6149 }
6150 }
6151 return(0);
6152 }
6153 }
6154 }
6155 return(0);
6156 }
6157
6158 #ifdef NDPI_ENABLE_DEBUG_MESSAGES
6159 /* ********************************************************************************* */
6160
ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct * ndpi_str,const char ** file,const char ** func,u_int32_t * line)6161 void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct *ndpi_str, const char **file,
6162 const char **func, u_int32_t *line) {
6163 *file = "";
6164 *func = "";
6165
6166 if(ndpi_str->ndpi_debug_print_file != NULL)
6167 *file = ndpi_str->ndpi_debug_print_file;
6168
6169 if(ndpi_str->ndpi_debug_print_function != NULL)
6170 *func = ndpi_str->ndpi_debug_print_function;
6171
6172 *line = ndpi_str->ndpi_debug_print_line;
6173 }
6174 #endif
6175
6176 /* ********************************************************************************* */
6177
ndpi_detection_get_l4(const u_int8_t * l3,u_int16_t l3_len,const u_int8_t ** l4_return,u_int16_t * l4_len_return,u_int8_t * l4_protocol_return,u_int32_t flags)6178 u_int8_t ndpi_detection_get_l4(const u_int8_t *l3, u_int16_t l3_len, const u_int8_t **l4_return,
6179 u_int16_t *l4_len_return, u_int8_t *l4_protocol_return, u_int32_t flags) {
6180 return(ndpi_detection_get_l4_internal(NULL, l3, l3_len, l4_return, l4_len_return, l4_protocol_return, flags));
6181 }
6182
6183 /* ********************************************************************************* */
6184
ndpi_set_detected_protocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int16_t upper_detected_protocol,u_int16_t lower_detected_protocol)6185 void ndpi_set_detected_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
6186 u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) {
6187 struct ndpi_id_struct *src = flow->src, *dst = flow->dst;
6188
6189 ndpi_int_change_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol);
6190
6191 if(src != NULL) {
6192 NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, upper_detected_protocol);
6193
6194 if(lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN)
6195 NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, lower_detected_protocol);
6196 }
6197
6198 if(dst != NULL) {
6199 NDPI_ADD_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, upper_detected_protocol);
6200
6201 if(lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN)
6202 NDPI_ADD_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, lower_detected_protocol);
6203 }
6204 }
6205
6206 /* ********************************************************************************* */
6207
ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow)6208 u_int16_t ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) {
6209 return(flow->detected_protocol_stack[1]);
6210 }
6211
6212 /* ********************************************************************************* */
6213
ndpi_int_change_flow_protocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int16_t upper_detected_protocol,u_int16_t lower_detected_protocol)6214 void ndpi_int_change_flow_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
6215 u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) {
6216 if(!flow)
6217 return;
6218
6219 flow->detected_protocol_stack[0] = upper_detected_protocol,
6220 flow->detected_protocol_stack[1] = lower_detected_protocol;
6221 }
6222
6223 /* ********************************************************************************* */
6224
ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int16_t upper_detected_protocol,u_int16_t lower_detected_protocol)6225 void ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
6226 u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) {
6227 struct ndpi_packet_struct *packet = &flow->packet;
6228 /* NOTE: everything below is identically to change_flow_protocol
6229 * except flow->packet If you want to change something here,
6230 * don't! Change it for the flow function and apply it here
6231 * as well */
6232
6233 if(!packet)
6234 return;
6235
6236 packet->detected_protocol_stack[0] = upper_detected_protocol,
6237 packet->detected_protocol_stack[1] = lower_detected_protocol;
6238 }
6239
6240 /* ********************************************************************************* */
6241
6242 /* generic function for changing the protocol
6243 *
6244 * what it does is:
6245 * 1.update the flow protocol stack with the new protocol
6246 * 2.update the packet protocol stack with the new protocol
6247 */
ndpi_int_change_protocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int16_t upper_detected_protocol,u_int16_t lower_detected_protocol)6248 void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
6249 u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) {
6250 if((upper_detected_protocol == NDPI_PROTOCOL_UNKNOWN) && (lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN))
6251 upper_detected_protocol = lower_detected_protocol;
6252
6253 if(upper_detected_protocol == lower_detected_protocol)
6254 lower_detected_protocol = NDPI_PROTOCOL_UNKNOWN;
6255
6256 if((upper_detected_protocol != NDPI_PROTOCOL_UNKNOWN) && (lower_detected_protocol == NDPI_PROTOCOL_UNKNOWN)) {
6257 if((flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) &&
6258 (upper_detected_protocol != flow->guessed_host_protocol_id)) {
6259 if(ndpi_str->proto_defaults[upper_detected_protocol].subprotocol_count > 0) {
6260 lower_detected_protocol = upper_detected_protocol;
6261 upper_detected_protocol = flow->guessed_host_protocol_id;
6262 }
6263 }
6264 }
6265
6266 ndpi_int_change_flow_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol);
6267 ndpi_int_change_packet_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol);
6268 }
6269
6270 /* ********************************************************************************* */
6271
ndpi_int_change_category(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,ndpi_protocol_category_t protocol_category)6272 void ndpi_int_change_category(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
6273 ndpi_protocol_category_t protocol_category) {
6274 flow->category = protocol_category;
6275 }
6276
6277 /* ********************************************************************************* */
6278
6279 /* turns a packet back to unknown */
ndpi_int_reset_packet_protocol(struct ndpi_packet_struct * packet)6280 void ndpi_int_reset_packet_protocol(struct ndpi_packet_struct *packet) {
6281 int a;
6282
6283 for(a = 0; a < NDPI_PROTOCOL_SIZE; a++)
6284 packet->detected_protocol_stack[a] = NDPI_PROTOCOL_UNKNOWN;
6285 }
6286
6287 /* ********************************************************************************* */
6288
ndpi_int_reset_protocol(struct ndpi_flow_struct * flow)6289 void ndpi_int_reset_protocol(struct ndpi_flow_struct *flow) {
6290 if(flow) {
6291 int a;
6292
6293 for(a = 0; a < NDPI_PROTOCOL_SIZE; a++)
6294 flow->detected_protocol_stack[a] = NDPI_PROTOCOL_UNKNOWN;
6295 }
6296 }
6297
6298 /* ********************************************************************************* */
6299
NDPI_PROTOCOL_IP_clear(ndpi_ip_addr_t * ip)6300 void NDPI_PROTOCOL_IP_clear(ndpi_ip_addr_t *ip) {
6301 memset(ip, 0, sizeof(ndpi_ip_addr_t));
6302 }
6303
6304 /* ********************************************************************************* */
6305
6306 #ifdef CODE_UNUSED
6307 /* NTOP */
NDPI_PROTOCOL_IP_is_set(const ndpi_ip_addr_t * ip)6308 int NDPI_PROTOCOL_IP_is_set(const ndpi_ip_addr_t *ip) {
6309 return(memcmp(ip, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(ndpi_ip_addr_t)) != 0);
6310 }
6311 #endif
6312
6313 /* ********************************************************************************* */
6314
6315 /* check if the source ip address in packet and ip are equal */
6316 /* NTOP */
ndpi_packet_src_ip_eql(const struct ndpi_packet_struct * packet,const ndpi_ip_addr_t * ip)6317 int ndpi_packet_src_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t *ip) {
6318 /* IPv6 */
6319 if(packet->iphv6 != NULL) {
6320 if(packet->iphv6->ip6_src.u6_addr.u6_addr32[0] == ip->ipv6.u6_addr.u6_addr32[0] &&
6321 packet->iphv6->ip6_src.u6_addr.u6_addr32[1] == ip->ipv6.u6_addr.u6_addr32[1] &&
6322 packet->iphv6->ip6_src.u6_addr.u6_addr32[2] == ip->ipv6.u6_addr.u6_addr32[2] &&
6323 packet->iphv6->ip6_src.u6_addr.u6_addr32[3] == ip->ipv6.u6_addr.u6_addr32[3])
6324 return(1);
6325 //else
6326 return(0);
6327 }
6328
6329 /* IPv4 */
6330 if(packet->iph->saddr == ip->ipv4)
6331 return(1);
6332 return(0);
6333 }
6334
6335 /* ********************************************************************************* */
6336
6337 /* check if the destination ip address in packet and ip are equal */
ndpi_packet_dst_ip_eql(const struct ndpi_packet_struct * packet,const ndpi_ip_addr_t * ip)6338 int ndpi_packet_dst_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t *ip) {
6339 /* IPv6 */
6340 if(packet->iphv6 != NULL) {
6341 if(packet->iphv6->ip6_dst.u6_addr.u6_addr32[0] == ip->ipv6.u6_addr.u6_addr32[0] &&
6342 packet->iphv6->ip6_dst.u6_addr.u6_addr32[1] == ip->ipv6.u6_addr.u6_addr32[1] &&
6343 packet->iphv6->ip6_dst.u6_addr.u6_addr32[2] == ip->ipv6.u6_addr.u6_addr32[2] &&
6344 packet->iphv6->ip6_dst.u6_addr.u6_addr32[3] == ip->ipv6.u6_addr.u6_addr32[3])
6345 return(1);
6346 //else
6347 return(0);
6348 }
6349
6350 /* IPv4 */
6351 if(packet->iph->saddr == ip->ipv4)
6352 return(1);
6353
6354 return(0);
6355 }
6356
6357 /* ********************************************************************************* */
6358
6359 /* get the source ip address from packet and put it into ip */
6360 /* NTOP */
ndpi_packet_src_ip_get(const struct ndpi_packet_struct * packet,ndpi_ip_addr_t * ip)6361 void ndpi_packet_src_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t *ip) {
6362 NDPI_PROTOCOL_IP_clear(ip);
6363
6364 /* IPv6 */
6365 if(packet->iphv6 != NULL) {
6366 ip->ipv6.u6_addr.u6_addr32[0] = packet->iphv6->ip6_src.u6_addr.u6_addr32[0];
6367 ip->ipv6.u6_addr.u6_addr32[1] = packet->iphv6->ip6_src.u6_addr.u6_addr32[1];
6368 ip->ipv6.u6_addr.u6_addr32[2] = packet->iphv6->ip6_src.u6_addr.u6_addr32[2];
6369 ip->ipv6.u6_addr.u6_addr32[3] = packet->iphv6->ip6_src.u6_addr.u6_addr32[3];
6370 } else {
6371 /* IPv4 */
6372 ip->ipv4 = packet->iph->saddr;
6373 }
6374 }
6375
6376 /* ********************************************************************************* */
6377
6378 /* get the destination ip address from packet and put it into ip */
6379 /* NTOP */
ndpi_packet_dst_ip_get(const struct ndpi_packet_struct * packet,ndpi_ip_addr_t * ip)6380 void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t *ip) {
6381 NDPI_PROTOCOL_IP_clear(ip);
6382
6383 if(packet->iphv6 != NULL) {
6384 ip->ipv6.u6_addr.u6_addr32[0] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[0];
6385 ip->ipv6.u6_addr.u6_addr32[1] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[1];
6386 ip->ipv6.u6_addr.u6_addr32[2] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[2];
6387 ip->ipv6.u6_addr.u6_addr32[3] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[3];
6388
6389 } else
6390 ip->ipv4 = packet->iph->daddr;
6391 }
6392
6393 /* ********************************************************************************* */
6394
ndpi_is_ipv6(const ndpi_ip_addr_t * ip)6395 u_int8_t ndpi_is_ipv6(const ndpi_ip_addr_t *ip) {
6396 return(ip->ipv6.u6_addr.u6_addr32[1] != 0 || ip->ipv6.u6_addr.u6_addr32[2] != 0 ||
6397 ip->ipv6.u6_addr.u6_addr32[3] != 0);
6398 }
6399
6400 /* ********************************************************************************* */
6401
ndpi_get_ip_string(const ndpi_ip_addr_t * ip,char * buf,u_int buf_len)6402 char *ndpi_get_ip_string(const ndpi_ip_addr_t *ip, char *buf, u_int buf_len) {
6403 const u_int8_t *a = (const u_int8_t *) &ip->ipv4;
6404
6405 if(ndpi_is_ipv6(ip)) {
6406 if(inet_ntop(AF_INET6, &ip->ipv6.u6_addr, buf, buf_len) == NULL)
6407 buf[0] = '\0';
6408
6409 return(buf);
6410 }
6411
6412 snprintf(buf, buf_len, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
6413
6414 return(buf);
6415 }
6416
6417 /* ****************************************************** */
6418
6419 /* Returns -1 on failutre, otherwise fills parsed_ip and returns the IP version */
ndpi_parse_ip_string(const char * ip_str,ndpi_ip_addr_t * parsed_ip)6420 int ndpi_parse_ip_string(const char *ip_str, ndpi_ip_addr_t *parsed_ip) {
6421 int rv = -1;
6422 memset(parsed_ip, 0, sizeof(*parsed_ip));
6423
6424 if(strchr(ip_str, '.')) {
6425 if(inet_pton(AF_INET, ip_str, &parsed_ip->ipv4) > 0)
6426 rv = 4;
6427 } else {
6428 if(inet_pton(AF_INET6, ip_str, &parsed_ip->ipv6) > 0)
6429 rv = 6;
6430 }
6431
6432 return(rv);
6433 }
6434
6435 /* ****************************************************** */
6436
ntohs_ndpi_bytestream_to_number(const u_int8_t * str,u_int16_t max_chars_to_read,u_int16_t * bytes_read)6437 u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t *str,
6438 u_int16_t max_chars_to_read, u_int16_t *bytes_read) {
6439 u_int16_t val = ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read);
6440 return(ntohs(val));
6441 }
6442
6443 /* ****************************************************** */
6444
ndpi_is_proto(ndpi_protocol proto,u_int16_t p)6445 u_int8_t ndpi_is_proto(ndpi_protocol proto, u_int16_t p) {
6446 return(((proto.app_protocol == p) || (proto.master_protocol == p)) ? 1 : 0);
6447 }
6448
6449 /* ****************************************************** */
6450
ndpi_get_lower_proto(ndpi_protocol proto)6451 u_int16_t ndpi_get_lower_proto(ndpi_protocol proto) {
6452 return((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) ? proto.master_protocol : proto.app_protocol);
6453 }
6454
6455 /* ****************************************************** */
6456
ndpi_get_upper_proto(ndpi_protocol proto)6457 u_int16_t ndpi_get_upper_proto(ndpi_protocol proto) {
6458 return((proto.app_protocol != NDPI_PROTOCOL_UNKNOWN) ? proto.app_protocol : proto.master_protocol);
6459 }
6460
6461 /* ****************************************************** */
6462
ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int8_t proto,u_int32_t shost,u_int16_t sport,u_int32_t dhost,u_int16_t dport)6463 ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_str,
6464 struct ndpi_flow_struct *flow, u_int8_t proto,
6465 u_int32_t shost /* host byte order */, u_int16_t sport,
6466 u_int32_t dhost /* host byte order */, u_int16_t dport) {
6467 u_int32_t rc;
6468 struct in_addr addr;
6469 ndpi_protocol ret = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED};
6470 u_int8_t user_defined_proto;
6471
6472 if((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) {
6473 rc = ndpi_search_tcp_or_udp_raw(ndpi_str, flow, proto, shost, dhost, sport, dport);
6474
6475 if(rc != NDPI_PROTOCOL_UNKNOWN) {
6476 if(flow && (proto == IPPROTO_UDP) &&
6477 NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_guessable_protocol(rc))
6478 ;
6479 else {
6480 ret.app_protocol = rc,
6481 ret.master_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto);
6482
6483 if(ret.app_protocol == ret.master_protocol)
6484 ret.master_protocol = NDPI_PROTOCOL_UNKNOWN;
6485
6486 ret.category = ndpi_get_proto_category(ndpi_str, ret);
6487 return(ret);
6488 }
6489 }
6490
6491 rc = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto);
6492 if(rc != NDPI_PROTOCOL_UNKNOWN) {
6493 if(flow && (proto == IPPROTO_UDP) &&
6494 NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_guessable_protocol(rc))
6495 ;
6496 else {
6497 ret.app_protocol = rc;
6498
6499 if(rc == NDPI_PROTOCOL_TLS)
6500 goto check_guessed_skype;
6501 else {
6502 ret.category = ndpi_get_proto_category(ndpi_str, ret);
6503 return(ret);
6504 }
6505 }
6506 }
6507
6508 check_guessed_skype:
6509 addr.s_addr = htonl(shost);
6510 if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE_TEAMS) {
6511 ret.app_protocol = NDPI_PROTOCOL_SKYPE_TEAMS;
6512 } else {
6513 addr.s_addr = htonl(dhost);
6514 if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE_TEAMS)
6515 ret.app_protocol = NDPI_PROTOCOL_SKYPE_TEAMS;
6516 }
6517 } else
6518 ret.app_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto);
6519
6520 ret.category = ndpi_get_proto_category(ndpi_str, ret);
6521 return(ret);
6522 }
6523
6524 /* ****************************************************** */
6525
ndpi_protocol2id(struct ndpi_detection_module_struct * ndpi_str,ndpi_protocol proto,char * buf,u_int buf_len)6526 char *ndpi_protocol2id(struct ndpi_detection_module_struct *ndpi_str,
6527 ndpi_protocol proto, char *buf, u_int buf_len) {
6528 if((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (proto.master_protocol != proto.app_protocol)) {
6529 if(proto.app_protocol != NDPI_PROTOCOL_UNKNOWN)
6530 snprintf(buf, buf_len, "%u.%u", proto.master_protocol, proto.app_protocol);
6531 else
6532 snprintf(buf, buf_len, "%u", proto.master_protocol);
6533 } else
6534 snprintf(buf, buf_len, "%u", proto.app_protocol);
6535
6536 return(buf);
6537 }
6538
6539 /* ****************************************************** */
6540
ndpi_protocol2name(struct ndpi_detection_module_struct * ndpi_str,ndpi_protocol proto,char * buf,u_int buf_len)6541 char *ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_str,
6542 ndpi_protocol proto, char *buf, u_int buf_len) {
6543 if((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (proto.master_protocol != proto.app_protocol)) {
6544 if(proto.app_protocol != NDPI_PROTOCOL_UNKNOWN)
6545 snprintf(buf, buf_len, "%s.%s", ndpi_get_proto_name(ndpi_str, proto.master_protocol),
6546 ndpi_get_proto_name(ndpi_str, proto.app_protocol));
6547 else
6548 snprintf(buf, buf_len, "%s", ndpi_get_proto_name(ndpi_str, proto.master_protocol));
6549 } else
6550 snprintf(buf, buf_len, "%s", ndpi_get_proto_name(ndpi_str, proto.app_protocol));
6551
6552 return(buf);
6553 }
6554
6555 /* ****************************************************** */
6556
ndpi_is_custom_category(ndpi_protocol_category_t category)6557 int ndpi_is_custom_category(ndpi_protocol_category_t category) {
6558 switch(category) {
6559 case NDPI_PROTOCOL_CATEGORY_CUSTOM_1:
6560 case NDPI_PROTOCOL_CATEGORY_CUSTOM_2:
6561 case NDPI_PROTOCOL_CATEGORY_CUSTOM_3:
6562 case NDPI_PROTOCOL_CATEGORY_CUSTOM_4:
6563 case NDPI_PROTOCOL_CATEGORY_CUSTOM_5:
6564 return(1);
6565 break;
6566
6567 default:
6568 return(0);
6569 break;
6570 }
6571 }
6572
6573 /* ****************************************************** */
6574
ndpi_category_set_name(struct ndpi_detection_module_struct * ndpi_str,ndpi_protocol_category_t category,char * name)6575 void ndpi_category_set_name(struct ndpi_detection_module_struct *ndpi_str,
6576 ndpi_protocol_category_t category,
6577 char *name) {
6578 if(!name)
6579 return;
6580
6581 switch(category) {
6582 case NDPI_PROTOCOL_CATEGORY_CUSTOM_1:
6583 snprintf(ndpi_str->custom_category_labels[0], CUSTOM_CATEGORY_LABEL_LEN, "%s", name);
6584 break;
6585
6586 case NDPI_PROTOCOL_CATEGORY_CUSTOM_2:
6587 snprintf(ndpi_str->custom_category_labels[1], CUSTOM_CATEGORY_LABEL_LEN, "%s", name);
6588 break;
6589
6590 case NDPI_PROTOCOL_CATEGORY_CUSTOM_3:
6591 snprintf(ndpi_str->custom_category_labels[2], CUSTOM_CATEGORY_LABEL_LEN, "%s", name);
6592 break;
6593
6594 case NDPI_PROTOCOL_CATEGORY_CUSTOM_4:
6595 snprintf(ndpi_str->custom_category_labels[3], CUSTOM_CATEGORY_LABEL_LEN, "%s", name);
6596 break;
6597
6598 case NDPI_PROTOCOL_CATEGORY_CUSTOM_5:
6599 snprintf(ndpi_str->custom_category_labels[4], CUSTOM_CATEGORY_LABEL_LEN, "%s", name);
6600 break;
6601
6602 default:
6603 break;
6604 }
6605 }
6606
6607 /* ****************************************************** */
6608
ndpi_category_get_name(struct ndpi_detection_module_struct * ndpi_str,ndpi_protocol_category_t category)6609 const char *ndpi_category_get_name(struct ndpi_detection_module_struct *ndpi_str,
6610 ndpi_protocol_category_t category) {
6611 if((!ndpi_str) || (category >= NDPI_PROTOCOL_NUM_CATEGORIES)) {
6612 static char b[24];
6613
6614 if(!ndpi_str)
6615 snprintf(b, sizeof(b), "NULL nDPI");
6616 else
6617 snprintf(b, sizeof(b), "Invalid category %d", (int) category);
6618 return(b);
6619 }
6620
6621 if((category >= NDPI_PROTOCOL_CATEGORY_CUSTOM_1) && (category <= NDPI_PROTOCOL_CATEGORY_CUSTOM_5)) {
6622 switch(category) {
6623 case NDPI_PROTOCOL_CATEGORY_CUSTOM_1:
6624 return(ndpi_str->custom_category_labels[0]);
6625 case NDPI_PROTOCOL_CATEGORY_CUSTOM_2:
6626 return(ndpi_str->custom_category_labels[1]);
6627 case NDPI_PROTOCOL_CATEGORY_CUSTOM_3:
6628 return(ndpi_str->custom_category_labels[2]);
6629 case NDPI_PROTOCOL_CATEGORY_CUSTOM_4:
6630 return(ndpi_str->custom_category_labels[3]);
6631 case NDPI_PROTOCOL_CATEGORY_CUSTOM_5:
6632 return(ndpi_str->custom_category_labels[4]);
6633 case NDPI_PROTOCOL_NUM_CATEGORIES:
6634 return("Code should not use this internal constant");
6635 default:
6636 return("Unspecified");
6637 }
6638 } else
6639 return(categories[category]);
6640 }
6641
6642 /* ****************************************************** */
6643
ndpi_get_proto_category(struct ndpi_detection_module_struct * ndpi_str,ndpi_protocol proto)6644 ndpi_protocol_category_t ndpi_get_proto_category(struct ndpi_detection_module_struct *ndpi_str,
6645 ndpi_protocol proto) {
6646 if(proto.category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)
6647 return(proto.category);
6648
6649 /* simple rule: sub protocol first, master after */
6650 else if((proto.master_protocol == NDPI_PROTOCOL_UNKNOWN) ||
6651 (ndpi_str->proto_defaults[proto.app_protocol].protoCategory != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)) {
6652 if(ndpi_is_valid_protoId(proto.app_protocol))
6653 return(ndpi_str->proto_defaults[proto.app_protocol].protoCategory);
6654 } else if(ndpi_is_valid_protoId(proto.master_protocol))
6655 return(ndpi_str->proto_defaults[proto.master_protocol].protoCategory);
6656
6657 return(NDPI_PROTOCOL_CATEGORY_UNSPECIFIED);
6658 }
6659
6660 /* ****************************************************** */
6661
ndpi_get_proto_name(struct ndpi_detection_module_struct * ndpi_str,u_int16_t proto_id)6662 char *ndpi_get_proto_name(struct ndpi_detection_module_struct *ndpi_str,
6663 u_int16_t proto_id) {
6664 if((proto_id >= ndpi_str->ndpi_num_supported_protocols)
6665 || (!ndpi_is_valid_protoId(proto_id))
6666 || (ndpi_str->proto_defaults[proto_id].protoName == NULL))
6667 proto_id = NDPI_PROTOCOL_UNKNOWN;
6668
6669 return(ndpi_str->proto_defaults[proto_id].protoName);
6670 }
6671
6672 /* ****************************************************** */
6673
ndpi_get_proto_breed(struct ndpi_detection_module_struct * ndpi_str,u_int16_t proto_id)6674 ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_str,
6675 u_int16_t proto_id) {
6676 if((proto_id >= ndpi_str->ndpi_num_supported_protocols) ||
6677 (!ndpi_is_valid_protoId(proto_id)) ||
6678 (ndpi_str->proto_defaults[proto_id].protoName == NULL))
6679 proto_id = NDPI_PROTOCOL_UNKNOWN;
6680
6681 return(ndpi_str->proto_defaults[proto_id].protoBreed);
6682 }
6683
6684 /* ****************************************************** */
6685
ndpi_get_proto_breed_name(struct ndpi_detection_module_struct * ndpi_str,ndpi_protocol_breed_t breed_id)6686 char *ndpi_get_proto_breed_name(struct ndpi_detection_module_struct *ndpi_str,
6687 ndpi_protocol_breed_t breed_id) {
6688 switch(breed_id) {
6689 case NDPI_PROTOCOL_SAFE:
6690 return("Safe");
6691 break;
6692 case NDPI_PROTOCOL_ACCEPTABLE:
6693 return("Acceptable");
6694 break;
6695 case NDPI_PROTOCOL_FUN:
6696 return("Fun");
6697 break;
6698 case NDPI_PROTOCOL_UNSAFE:
6699 return("Unsafe");
6700 break;
6701 case NDPI_PROTOCOL_POTENTIALLY_DANGEROUS:
6702 return("Potentially Dangerous");
6703 break;
6704 case NDPI_PROTOCOL_TRACKER_ADS:
6705 return("Tracker/Ads");
6706 break;
6707 case NDPI_PROTOCOL_DANGEROUS:
6708 return("Dangerous");
6709 break;
6710 case NDPI_PROTOCOL_UNRATED:
6711 return("Unrated");
6712 break;
6713 default:
6714 return("???");
6715 break;
6716 }
6717 }
6718
6719 /* ****************************************************** */
6720
ndpi_get_protocol_id(struct ndpi_detection_module_struct * ndpi_str,char * proto)6721 int ndpi_get_protocol_id(struct ndpi_detection_module_struct *ndpi_str, char *proto) {
6722 int i;
6723
6724 for(i = 0; i < (int) ndpi_str->ndpi_num_supported_protocols; i++)
6725 if(strcasecmp(proto, ndpi_str->proto_defaults[i].protoName) == 0)
6726 return(i);
6727
6728 return(-1);
6729 }
6730
6731 /* ****************************************************** */
6732
ndpi_get_category_id(struct ndpi_detection_module_struct * ndpi_str,char * cat)6733 int ndpi_get_category_id(struct ndpi_detection_module_struct *ndpi_str, char *cat) {
6734 int i;
6735
6736 for(i = 0; i < NDPI_PROTOCOL_NUM_CATEGORIES; i++) {
6737 const char *name = ndpi_category_get_name(ndpi_str, i);
6738
6739 if(strcasecmp(cat, name) == 0)
6740 return(i);
6741 }
6742
6743 return(-1);
6744 }
6745
6746 /* ****************************************************** */
6747
ndpi_dump_protocols(struct ndpi_detection_module_struct * ndpi_str)6748 void ndpi_dump_protocols(struct ndpi_detection_module_struct *ndpi_str) {
6749 int i;
6750
6751 for(i = 0; i < (int) ndpi_str->ndpi_num_supported_protocols; i++)
6752 printf("%3d %-22s %-8s %-12s %s\n", i, ndpi_str->proto_defaults[i].protoName,
6753 ndpi_get_l4_proto_name(ndpi_get_l4_proto_info(ndpi_str, i)),
6754 ndpi_get_proto_breed_name(ndpi_str, ndpi_str->proto_defaults[i].protoBreed),
6755 ndpi_category_get_name(ndpi_str, ndpi_str->proto_defaults[i].protoCategory));
6756 }
6757
6758 /* ****************************************************** */
6759
ndpi_dump_risks_score()6760 void ndpi_dump_risks_score() {
6761 u_int i;
6762
6763 printf("%3s %-48s %-8s %s %-8s %-8s\n",
6764 "Id", "Risk", "Severity", "Score", "CliScore", "SrvScore");
6765
6766 for(i = 1; i < NDPI_MAX_RISK; i++) {
6767 ndpi_risk_enum r = (ndpi_risk_enum)i;
6768 ndpi_risk risk = 2 << (r-1);
6769 ndpi_risk_info* info = ndpi_risk2severity(r);
6770 ndpi_risk_severity s =info->severity;
6771 u_int16_t client_score, server_score;
6772 u_int16_t score = ndpi_risk2score(risk, &client_score, &server_score);
6773
6774 printf("%3d %-48s %-8s %-8u %-8u %-8u\n",
6775 i, ndpi_risk2str(r),
6776 ndpi_severity2str(s),
6777 score,
6778 client_score, server_score);
6779 }
6780 }
6781
6782 /* ****************************************************** */
6783
6784 /*
6785 * Find the first occurrence of find in s, where the search is limited to the
6786 * first slen characters of s.
6787 */
ndpi_strnstr(const char * s,const char * find,size_t slen)6788 char *ndpi_strnstr(const char *s, const char *find, size_t slen) {
6789 char c;
6790 size_t len;
6791
6792 if((c = *find++) != '\0') {
6793 len = strnlen(find, slen);
6794 do {
6795 char sc;
6796
6797 do {
6798 if(slen-- < 1 || (sc = *s++) == '\0')
6799 return(NULL);
6800 } while(sc != c);
6801 if(len > slen)
6802 return(NULL);
6803 } while(strncmp(s, find, len) != 0);
6804 s--;
6805 }
6806
6807 return((char *) s);
6808 }
6809
6810 /* ****************************************************** */
6811
6812 /*
6813 * Same as ndpi_strnstr but case-insensitive
6814 */
ndpi_strncasestr(const char * str1,const char * str2,size_t len)6815 const char * ndpi_strncasestr(const char *str1, const char *str2, size_t len) {
6816 size_t str1_len = strnlen(str1, len);
6817 size_t str2_len = strlen(str2);
6818 size_t i;
6819
6820 for(i = 0; i < (str1_len - str2_len + 1); i++){
6821 if(str1[0] == '\0')
6822 return NULL;
6823 else if(strncasecmp(str1, str2, str2_len) == 0)
6824 return(str1);
6825
6826 str1++;
6827 }
6828
6829 return NULL;
6830 }
6831
6832 /* ****************************************************** */
6833
ndpi_match_prefix(const u_int8_t * payload,size_t payload_len,const char * str,size_t str_len)6834 int ndpi_match_prefix(const u_int8_t *payload,
6835 size_t payload_len, const char *str, size_t str_len) {
6836 int rc = str_len <= payload_len ? memcmp(payload, str, str_len) == 0 : 0;
6837
6838 return(rc);
6839 }
6840
6841 /* ****************************************************** */
6842
ndpi_match_string_subprotocol(struct ndpi_detection_module_struct * ndpi_str,char * string_to_match,u_int string_to_match_len,ndpi_protocol_match_result * ret_match,u_int8_t is_host_match)6843 int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_str, char *string_to_match,
6844 u_int string_to_match_len, ndpi_protocol_match_result *ret_match,
6845 u_int8_t is_host_match) {
6846 ndpi_automa *automa = is_host_match ? &ndpi_str->host_automa : &ndpi_str->content_automa;
6847 int rc;
6848
6849 if((automa->ac_automa == NULL) || (string_to_match_len == 0))
6850 return(NDPI_PROTOCOL_UNKNOWN);
6851
6852 rc = ndpi_match_string_common(((AC_AUTOMATA_t *) automa->ac_automa),
6853 string_to_match,string_to_match_len, &ret_match->protocol_id,
6854 &ret_match->protocol_category, &ret_match->protocol_breed);
6855 return rc < 0 ? rc : ret_match->protocol_id;
6856 }
6857
6858 /* **************************************** */
6859
ndpi_is_more_generic_protocol(u_int16_t previous_proto,u_int16_t new_proto)6860 static u_int8_t ndpi_is_more_generic_protocol(u_int16_t previous_proto, u_int16_t new_proto) {
6861 /* Sometimes certificates are more generic than previously identified protocols */
6862
6863 if((previous_proto == NDPI_PROTOCOL_UNKNOWN) || (previous_proto == new_proto))
6864 return(0);
6865
6866 switch(previous_proto) {
6867 case NDPI_PROTOCOL_WHATSAPP_CALL:
6868 case NDPI_PROTOCOL_WHATSAPP_FILES:
6869 if(new_proto == NDPI_PROTOCOL_WHATSAPP)
6870 return(1);
6871 }
6872
6873 return(0);
6874 }
6875
6876 /* ****************************************************** */
6877
ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,char * string_to_match,u_int string_to_match_len,u_int16_t master_protocol_id,ndpi_protocol_match_result * ret_match,u_int8_t is_host_match)6878 static u_int16_t ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
6879 struct ndpi_flow_struct *flow, char *string_to_match,
6880 u_int string_to_match_len, u_int16_t master_protocol_id,
6881 ndpi_protocol_match_result *ret_match, u_int8_t is_host_match) {
6882 int matching_protocol_id;
6883 struct ndpi_packet_struct *packet = &flow->packet;
6884
6885 matching_protocol_id =
6886 ndpi_match_string_subprotocol(ndpi_str, string_to_match, string_to_match_len, ret_match, is_host_match);
6887
6888 if(matching_protocol_id < 0)
6889 return NDPI_PROTOCOL_UNKNOWN;
6890
6891 #ifdef DEBUG
6892 {
6893 char m[256];
6894 int len = ndpi_min(sizeof(m), string_to_match_len);
6895
6896 strncpy(m, string_to_match, len);
6897 m[len] = '\0';
6898
6899 NDPI_LOG_DBG2(ndpi_str, "[NDPI] ndpi_match_host_subprotocol(%s): %s\n", m,
6900 ndpi_str->proto_defaults[matching_protocol_id].protoName);
6901 }
6902 #endif
6903
6904 if((matching_protocol_id != NDPI_PROTOCOL_UNKNOWN) &&
6905 (!ndpi_is_more_generic_protocol(packet->detected_protocol_stack[0], matching_protocol_id))) {
6906 /* Move the protocol on slot 0 down one position */
6907 packet->detected_protocol_stack[1] = master_protocol_id,
6908 packet->detected_protocol_stack[0] = matching_protocol_id;
6909
6910 flow->detected_protocol_stack[0] = packet->detected_protocol_stack[0],
6911 flow->detected_protocol_stack[1] = packet->detected_protocol_stack[1];
6912
6913 if(flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)
6914 flow->category = ret_match->protocol_category;
6915
6916 return(packet->detected_protocol_stack[0]);
6917 }
6918
6919 #ifdef DEBUG
6920 string_to_match[string_to_match_len] = '\0';
6921 NDPI_LOG_DBG2(ndpi_str, "[NTOP] Unable to find a match for '%s'\n", string_to_match);
6922 #endif
6923
6924 ret_match->protocol_id = NDPI_PROTOCOL_UNKNOWN, ret_match->protocol_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED,
6925 ret_match->protocol_breed = NDPI_PROTOCOL_UNRATED;
6926
6927 return(NDPI_PROTOCOL_UNKNOWN);
6928 }
6929
6930 /* ****************************************************** */
6931
ndpi_check_subprotocol_risk(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,u_int16_t subprotocol_id)6932 void ndpi_check_subprotocol_risk(struct ndpi_detection_module_struct *ndpi_str,
6933 struct ndpi_flow_struct *flow, u_int16_t subprotocol_id) {
6934 switch(subprotocol_id) {
6935 case NDPI_PROTOCOL_ANYDESK:
6936 ndpi_set_risk(ndpi_str, flow, NDPI_DESKTOP_OR_FILE_SHARING_SESSION); /* Remote assistance */
6937 break;
6938 }
6939 }
6940
6941 /* ****************************************************** */
6942
ndpi_match_host_subprotocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,char * string_to_match,u_int string_to_match_len,ndpi_protocol_match_result * ret_match,u_int16_t master_protocol_id)6943 u_int16_t ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
6944 struct ndpi_flow_struct *flow,
6945 char *string_to_match, u_int string_to_match_len,
6946 ndpi_protocol_match_result *ret_match,
6947 u_int16_t master_protocol_id) {
6948 u_int16_t rc;
6949 ndpi_protocol_category_t id;
6950
6951 rc = ndpi_automa_match_string_subprotocol(ndpi_str, flow, string_to_match, string_to_match_len,
6952 master_protocol_id, ret_match, 1);
6953 id = ret_match->protocol_category;
6954
6955 if(ndpi_get_custom_category_match(ndpi_str, string_to_match, string_to_match_len, &id) != -1) {
6956 /* if(id != -1) */ {
6957 flow->category = ret_match->protocol_category = id;
6958 rc = master_protocol_id;
6959 }
6960 }
6961
6962 if(ndpi_str->risky_domain_automa.ac_automa != NULL) {
6963 u_int32_t proto_id;
6964 u_int16_t rc1 = ndpi_match_string_common(ndpi_str->risky_domain_automa.ac_automa,
6965 string_to_match,string_to_match_len,
6966 &proto_id, NULL, NULL);
6967 if(rc1 > 0)
6968 ndpi_set_risk(ndpi_str, flow, NDPI_RISKY_DOMAIN);
6969 }
6970
6971 return(rc);
6972 }
6973
6974 /* **************************************** */
6975
ndpi_match_hostname_protocol(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow,u_int16_t master_protocol,char * name,u_int name_len)6976 int ndpi_match_hostname_protocol(struct ndpi_detection_module_struct *ndpi_struct,
6977 struct ndpi_flow_struct *flow,
6978 u_int16_t master_protocol, char *name, u_int name_len) {
6979 ndpi_protocol_match_result ret_match;
6980 u_int16_t subproto, what_len;
6981 char *what;
6982
6983 if((name_len > 2) && (name[0] == '*') && (name[1] == '.'))
6984 what = &name[1], what_len = name_len - 1;
6985 else
6986 what = name, what_len = name_len;
6987
6988 subproto = ndpi_match_host_subprotocol(ndpi_struct, flow, what, what_len,
6989 &ret_match, master_protocol);
6990
6991 if(subproto != NDPI_PROTOCOL_UNKNOWN) {
6992 ndpi_set_detected_protocol(ndpi_struct, flow, subproto, master_protocol);
6993 ndpi_int_change_category(ndpi_struct, flow, ret_match.protocol_category);
6994 return(1);
6995 } else
6996 return(0);
6997 }
6998
6999 /* ****************************************************** */
7000
ndpi_match_content_subprotocol(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,char * string_to_match,u_int string_to_match_len,ndpi_protocol_match_result * ret_match,u_int16_t master_protocol_id)7001 u_int16_t ndpi_match_content_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
7002 struct ndpi_flow_struct *flow,
7003 char *string_to_match, u_int string_to_match_len,
7004 ndpi_protocol_match_result *ret_match,
7005 u_int16_t master_protocol_id) {
7006 return(ndpi_automa_match_string_subprotocol(ndpi_str, flow, string_to_match, string_to_match_len,
7007 master_protocol_id, ret_match, 0));
7008 }
7009
7010 /* ****************************************************** */
7011
ndpi_match_xgram(unsigned int * map,int l,const char * str)7012 static inline int ndpi_match_xgram(unsigned int *map,int l,const char *str) {
7013 unsigned int i,c;
7014 for(i=0,c=0; *str && i < l; i++) {
7015 unsigned char a = (unsigned char)(*str++);
7016 if(a < 'a' || a > 'z') return 0;
7017 c *= XGRAMS_C;
7018 c += a-'a';
7019 }
7020 return (map[c >> 5] & (1u << (c & 0x1f))) != 0;
7021 }
ndpi_match_bigram(const char * str)7022 int ndpi_match_bigram(const char *str) {
7023 return ndpi_match_xgram(bigrams_bitmap, 2, str);
7024 }
7025
ndpi_match_impossible_bigram(const char * str)7026 int ndpi_match_impossible_bigram(const char *str) {
7027 return ndpi_match_xgram(imposible_bigrams_bitmap, 2, str);
7028 }
7029
7030 /* ****************************************************** */
7031
ndpi_match_trigram(const char * str)7032 int ndpi_match_trigram(const char *str) {
7033 return ndpi_match_xgram(trigrams_bitmap, 3, str);
7034 }
7035
7036
7037 /* ****************************************************** */
7038
ndpi_free_flow(struct ndpi_flow_struct * flow)7039 void ndpi_free_flow(struct ndpi_flow_struct *flow) {
7040 if(flow) {
7041 ndpi_free_flow_data(flow);
7042 ndpi_free(flow);
7043 }
7044 }
7045
7046 /* ****************************************************** */
7047
ndpi_revision()7048 char *ndpi_revision() {
7049 return(NDPI_GIT_RELEASE);
7050 }
7051
7052 /* ****************************************************** */
7053
7054 #ifdef WIN32
7055
7056 /* https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows */
gettimeofday(struct timeval * tp,struct timezone * tzp)7057 int gettimeofday(struct timeval *tp, struct timezone *tzp) {
7058 // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
7059 // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC)
7060 // until 00:00:00 January 1, 1970
7061 static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
7062
7063 SYSTEMTIME system_time;
7064 FILETIME file_time;
7065 uint64_t time;
7066
7067 GetSystemTime(&system_time);
7068 SystemTimeToFileTime(&system_time, &file_time);
7069 time = ((uint64_t) file_time.dwLowDateTime);
7070 time += ((uint64_t) file_time.dwHighDateTime) << 32;
7071
7072 tp->tv_sec = (long) ((time - EPOCH) / 10000000L);
7073 tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
7074 return(0);
7075 }
7076 #endif
7077
NDPI_BITMASK_COMPARE(NDPI_PROTOCOL_BITMASK a,NDPI_PROTOCOL_BITMASK b)7078 int NDPI_BITMASK_COMPARE(NDPI_PROTOCOL_BITMASK a, NDPI_PROTOCOL_BITMASK b) {
7079 int i;
7080
7081 for(i = 0; i < NDPI_NUM_FDS_BITS; i++) {
7082 if(a.fds_bits[i] & b.fds_bits[i])
7083 return(1);
7084 }
7085
7086 return(0);
7087 }
7088
7089 #ifdef CODE_UNUSED
NDPI_BITMASK_IS_EMPTY(NDPI_PROTOCOL_BITMASK a)7090 int NDPI_BITMASK_IS_EMPTY(NDPI_PROTOCOL_BITMASK a) {
7091 int i;
7092
7093 for(i = 0; i < NDPI_NUM_FDS_BITS; i++)
7094 if(a.fds_bits[i] != 0)
7095 return(0);
7096
7097 return(1);
7098 }
7099
NDPI_DUMP_BITMASK(NDPI_PROTOCOL_BITMASK a)7100 void NDPI_DUMP_BITMASK(NDPI_PROTOCOL_BITMASK a) {
7101 int i;
7102
7103 for(i = 0; i < NDPI_NUM_FDS_BITS; i++)
7104 printf("[%d=%u]", i, a.fds_bits[i]);
7105
7106 printf("\n");
7107 }
7108 #endif
7109
ndpi_get_api_version()7110 u_int16_t ndpi_get_api_version() {
7111 return(NDPI_API_VERSION);
7112 }
7113
ndpi_get_gcrypt_version(void)7114 const char *ndpi_get_gcrypt_version(void) {
7115 #ifdef HAVE_LIBGCRYPT
7116 return gcry_check_version(NULL);
7117 #endif
7118 return NULL;
7119 }
7120
ndpi_get_proto_defaults(struct ndpi_detection_module_struct * ndpi_str)7121 ndpi_proto_defaults_t *ndpi_get_proto_defaults(struct ndpi_detection_module_struct *ndpi_str) {
7122 return(ndpi_str->proto_defaults);
7123 }
7124
ndpi_get_ndpi_num_supported_protocols(struct ndpi_detection_module_struct * ndpi_str)7125 u_int ndpi_get_ndpi_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_str) {
7126 return(ndpi_str->ndpi_num_supported_protocols);
7127 }
7128
ndpi_get_ndpi_num_custom_protocols(struct ndpi_detection_module_struct * ndpi_str)7129 u_int ndpi_get_ndpi_num_custom_protocols(struct ndpi_detection_module_struct *ndpi_str) {
7130 return(ndpi_str->ndpi_num_custom_protocols);
7131 }
7132
ndpi_get_ndpi_detection_module_size()7133 u_int ndpi_get_ndpi_detection_module_size() {
7134 return(sizeof(struct ndpi_detection_module_struct));
7135 }
7136
ndpi_set_debug_bitmask(struct ndpi_detection_module_struct * ndpi_str,NDPI_PROTOCOL_BITMASK debug_bitmask)7137 void ndpi_set_debug_bitmask(struct ndpi_detection_module_struct *ndpi_str, NDPI_PROTOCOL_BITMASK debug_bitmask) {
7138 #ifdef NDPI_ENABLE_DEBUG_MESSAGES
7139 ndpi_str->debug_bitmask = debug_bitmask;
7140 #endif
7141 }
7142
ndpi_set_log_level(struct ndpi_detection_module_struct * ndpi_str,u_int l)7143 void ndpi_set_log_level(struct ndpi_detection_module_struct *ndpi_str, u_int l){
7144 ndpi_str->ndpi_log_level = l;
7145 }
7146
7147 /* ******************************************************************** */
7148
7149 /* LRU cache */
ndpi_lru_cache_init(u_int32_t num_entries)7150 struct ndpi_lru_cache *ndpi_lru_cache_init(u_int32_t num_entries) {
7151 struct ndpi_lru_cache *c = (struct ndpi_lru_cache *) ndpi_malloc(sizeof(struct ndpi_lru_cache));
7152
7153 if(!c)
7154 return(NULL);
7155
7156 c->entries = (struct ndpi_lru_cache_entry *) ndpi_calloc(num_entries, sizeof(struct ndpi_lru_cache_entry));
7157
7158 if(!c->entries) {
7159 ndpi_free(c);
7160 return(NULL);
7161 } else
7162 c->num_entries = num_entries;
7163
7164 return(c);
7165 }
7166
ndpi_lru_free_cache(struct ndpi_lru_cache * c)7167 void ndpi_lru_free_cache(struct ndpi_lru_cache *c) {
7168 ndpi_free(c->entries);
7169 ndpi_free(c);
7170 }
7171
ndpi_lru_find_cache(struct ndpi_lru_cache * c,u_int32_t key,u_int16_t * value,u_int8_t clean_key_when_found)7172 u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key,
7173 u_int16_t *value, u_int8_t clean_key_when_found) {
7174 u_int32_t slot = key % c->num_entries;
7175
7176 if(c->entries[slot].is_full && c->entries[slot].key == key) {
7177 *value = c->entries[slot].value;
7178 if(clean_key_when_found)
7179 c->entries[slot].is_full = 0;
7180 return(1);
7181 } else
7182 return(0);
7183 }
7184
ndpi_lru_add_to_cache(struct ndpi_lru_cache * c,u_int32_t key,u_int16_t value)7185 void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t value) {
7186 u_int32_t slot = key % c->num_entries;
7187
7188 c->entries[slot].is_full = 1, c->entries[slot].key = key, c->entries[slot].value = value;
7189 }
7190
7191 /* ******************************************************************** */
7192
7193 /*
7194 This function tells if it's possible to further dissect a given flow
7195 0 - All possible dissection has been completed
7196 1 - Additional dissection is possible
7197 */
ndpi_extra_dissection_possible(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow)7198 u_int8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndpi_str,
7199 struct ndpi_flow_struct *flow) {
7200 u_int16_t proto =
7201 flow->detected_protocol_stack[1] ? flow->detected_protocol_stack[1] : flow->detected_protocol_stack[0];
7202
7203 #if 0
7204 printf("[DEBUG] %s(%u.%u): %u\n", __FUNCTION__,
7205 flow->detected_protocol_stack[0],
7206 flow->detected_protocol_stack[1],
7207 proto);
7208 #endif
7209
7210 switch(proto) {
7211 case NDPI_PROTOCOL_TLS:
7212 case NDPI_PROTOCOL_DTLS:
7213 if(flow->l4.tcp.tls.certificate_processed) return(0);
7214
7215 if(flow->l4.tcp.tls.num_tls_blocks <= ndpi_str->num_tls_blocks_to_follow) {
7216 // printf("*** %u/%u\n", flow->l4.tcp.tls.num_tls_blocks, ndpi_str->num_tls_blocks_to_follow);
7217 return(1);
7218 }
7219 break;
7220
7221 case NDPI_PROTOCOL_HTTP:
7222 if((flow->host_server_name[0] == '\0') || (flow->http.response_status_code == 0))
7223 return(1);
7224 break;
7225
7226 case NDPI_PROTOCOL_DNS:
7227 case NDPI_PROTOCOL_MDNS:
7228 if(flow->protos.dns.num_answers == 0)
7229 return(1);
7230 break;
7231
7232 case NDPI_PROTOCOL_FTP_CONTROL:
7233 case NDPI_PROTOCOL_MAIL_POP:
7234 case NDPI_PROTOCOL_MAIL_IMAP:
7235 case NDPI_PROTOCOL_MAIL_SMTP:
7236 if(flow->protos.ftp_imap_pop_smtp.password[0] == '\0')
7237 return(1);
7238 break;
7239
7240 case NDPI_PROTOCOL_SSH:
7241 if((flow->protos.ssh.hassh_client[0] == '\0') || (flow->protos.ssh.hassh_server[0] == '\0'))
7242 return(1);
7243 break;
7244
7245 case NDPI_PROTOCOL_TELNET:
7246 if(!flow->protos.telnet.password_detected)
7247 return(1);
7248 break;
7249
7250 case NDPI_PROTOCOL_SKYPE_TEAMS:
7251 if(flow->extra_packets_func)
7252 return(1);
7253 break;
7254
7255 case NDPI_PROTOCOL_QUIC:
7256 if(flow->extra_packets_func)
7257 return(1);
7258 break;
7259 }
7260
7261 return(0);
7262 }
7263
7264 /* ******************************************************************** */
7265
ndpi_get_l4_proto_name(ndpi_l4_proto_info proto)7266 const char *ndpi_get_l4_proto_name(ndpi_l4_proto_info proto) {
7267 switch(proto) {
7268 case ndpi_l4_proto_unknown:
7269 return("");
7270 break;
7271
7272 case ndpi_l4_proto_tcp_only:
7273 return("TCP");
7274 break;
7275
7276 case ndpi_l4_proto_udp_only:
7277 return("UDP");
7278 break;
7279
7280 case ndpi_l4_proto_tcp_and_udp:
7281 return("TCP/UDP");
7282 break;
7283 }
7284
7285 return("");
7286 }
7287
7288 /* ******************************************************************** */
7289
ndpi_get_l4_proto_info(struct ndpi_detection_module_struct * ndpi_struct,u_int16_t ndpi_proto_id)7290 ndpi_l4_proto_info ndpi_get_l4_proto_info(struct ndpi_detection_module_struct *ndpi_struct,
7291 u_int16_t ndpi_proto_id) {
7292 if(ndpi_proto_id < ndpi_struct->ndpi_num_supported_protocols) {
7293 u_int16_t idx = ndpi_struct->proto_defaults[ndpi_proto_id].protoIdx;
7294 NDPI_SELECTION_BITMASK_PROTOCOL_SIZE bm = ndpi_struct->callback_buffer[idx].ndpi_selection_bitmask;
7295
7296 if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP)
7297 return(ndpi_l4_proto_tcp_only);
7298 else if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP)
7299 return(ndpi_l4_proto_udp_only);
7300 else if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP)
7301 return(ndpi_l4_proto_tcp_and_udp);
7302 }
7303
7304 return(ndpi_l4_proto_unknown); /* default */
7305 }
7306
7307 /* ******************************************************************** */
7308
ndpi_ptree_create(void)7309 ndpi_ptree_t *ndpi_ptree_create(void) {
7310 ndpi_ptree_t *tree = (ndpi_ptree_t *) ndpi_malloc(sizeof(ndpi_ptree_t));
7311
7312 if(tree) {
7313 tree->v4 = ndpi_patricia_new(32);
7314 tree->v6 = ndpi_patricia_new(128);
7315
7316 if((!tree->v4) || (!tree->v6)) {
7317 ndpi_ptree_destroy(tree);
7318 return(NULL);
7319 }
7320 }
7321
7322 return(tree);
7323 }
7324
7325 /* ******************************************************************** */
7326
ndpi_ptree_destroy(ndpi_ptree_t * tree)7327 void ndpi_ptree_destroy(ndpi_ptree_t *tree) {
7328 if(tree) {
7329 if(tree->v4)
7330 ndpi_patricia_destroy(tree->v4, free_ptree_data);
7331 if(tree->v6)
7332 ndpi_patricia_destroy(tree->v6, free_ptree_data);
7333
7334 ndpi_free(tree);
7335 }
7336 }
7337
7338 /* ******************************************************************** */
7339
ndpi_ptree_insert(ndpi_ptree_t * tree,const ndpi_ip_addr_t * addr,u_int8_t bits,u_int64_t user_data)7340 int ndpi_ptree_insert(ndpi_ptree_t *tree, const ndpi_ip_addr_t *addr,
7341 u_int8_t bits, u_int64_t user_data) {
7342 u_int8_t is_v6 = ndpi_is_ipv6(addr);
7343 ndpi_patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4;
7344 ndpi_prefix_t prefix;
7345 ndpi_patricia_node_t *node;
7346
7347 if(bits > ptree->maxbits)
7348 return(-1);
7349
7350 if(is_v6)
7351 ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits);
7352 else
7353 ndpi_fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits);
7354
7355 /* Verify that the node does not already exist */
7356 node = ndpi_patricia_search_best(ptree, &prefix);
7357
7358 if(node && (node->prefix->bitlen == bits))
7359 return(-2);
7360
7361 node = ndpi_patricia_lookup(ptree, &prefix);
7362
7363 if(node != NULL) {
7364 node->value.u.uv64 = user_data;
7365
7366 return(0);
7367 }
7368
7369 return(-3);
7370 }
7371
7372 /* ******************************************************************** */
7373
ndpi_ptree_match_addr(ndpi_ptree_t * tree,const ndpi_ip_addr_t * addr,u_int64_t * user_data)7374 int ndpi_ptree_match_addr(ndpi_ptree_t *tree,
7375 const ndpi_ip_addr_t *addr, u_int64_t *user_data) {
7376 u_int8_t is_v6 = ndpi_is_ipv6(addr);
7377 ndpi_patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4;
7378 ndpi_prefix_t prefix;
7379 ndpi_patricia_node_t *node;
7380 int bits = ptree->maxbits;
7381
7382 if(is_v6)
7383 ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits);
7384 else
7385 ndpi_fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits);
7386
7387 node = ndpi_patricia_search_best(ptree, &prefix);
7388
7389 if(node) {
7390 *user_data = node->value.u.uv64;
7391
7392 return(0);
7393 }
7394
7395 return(-1);
7396 }
7397
7398 /* ******************************************************************** */
7399
7400 /* Based on djb2 hash - http://www.cse.yorku.ca/~oz/hash.html */
ndpi_quick_hash(unsigned char * str,u_int str_len)7401 u_int32_t ndpi_quick_hash(unsigned char *str, u_int str_len) {
7402 u_int32_t hash = 5381, i;
7403
7404 for(i=0; i<str_len; i++)
7405 hash = ((hash << 5) + hash) + str[i]; /* hash * 33 + str[i] */
7406
7407 return hash;
7408 }
7409
7410 /* ******************************************************************** */
7411
ndpi_md5(const u_char * data,size_t data_len,u_char hash[16])7412 void ndpi_md5(const u_char *data, size_t data_len, u_char hash[16]) {
7413 ndpi_MD5_CTX ctx;
7414
7415 ndpi_MD5Init(&ctx);
7416 ndpi_MD5Update(&ctx, data, data_len);
7417 ndpi_MD5Final(hash, &ctx);
7418 }
7419
7420 /* ******************************************************************** */
7421
enough(int a,int b)7422 static int enough(int a, int b) {
7423 u_int8_t percentage = 20;
7424
7425 if(b <= 1) return(0);
7426 if(a == 0) return(1);
7427
7428 if(b > (((a+1)*percentage)/100)) return(1);
7429
7430 return(0);
7431 }
7432
7433 /* ******************************************************************** */
7434
endsWith(char * str,char * ends,u_int8_t ends_len)7435 static u_int8_t endsWith(char *str, char *ends, u_int8_t ends_len) {
7436 u_int str_len = str ? strlen(str) : 0;
7437 u_int8_t rc;
7438
7439 if(str_len < ends_len) return(0);
7440
7441 rc = (strncmp(&str[str_len-ends_len], ends, ends_len) != 0) ? 0 : 1;
7442
7443 #ifdef DGA_DEBUG
7444 printf("[DGA] %s / %s [rc: %u]\n", str, ends, rc);
7445 #endif
7446
7447 return(rc);
7448 }
7449
7450 /* ******************************************************************** */
7451
ndpi_is_trigram_char(char c)7452 static int ndpi_is_trigram_char(char c) {
7453 if(isdigit(c) || (c == '.') || (c == '-'))
7454 return(0);
7455 else
7456 return(1);
7457 }
7458
7459 /* ******************************************************************** */
7460
ndpi_is_vowel(char c)7461 static int ndpi_is_vowel(char c) {
7462 switch(c) {
7463 case 'a':
7464 case 'e':
7465 case 'i':
7466 case 'o':
7467 case 'u':
7468 case 'y': // Not a real vowel...
7469 case 'x': // Not a real vowel...
7470 return(1);
7471 break;
7472
7473 default:
7474 return(0);
7475 }
7476 }
7477
7478 /* ******************************************************************** */
7479
ndpi_check_dga_name(struct ndpi_detection_module_struct * ndpi_str,struct ndpi_flow_struct * flow,char * name,u_int8_t is_hostname)7480 int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str,
7481 struct ndpi_flow_struct *flow,
7482 char *name, u_int8_t is_hostname) {
7483 if(ndpi_dga_function != NULL) {
7484 /* A custom DGA function is defined */
7485 int rc = ndpi_dga_function(name, is_hostname);
7486
7487 if(rc) {
7488 if(flow)
7489 ndpi_set_risk(ndpi_str, flow, NDPI_SUSPICIOUS_DGA_DOMAIN);
7490 }
7491
7492 return(rc);
7493 } else {
7494 int len, rc = 0, trigram_char_skip = 0;
7495 u_int8_t max_num_char_repetitions = 0, last_char = 0, num_char_repetitions = 0, num_dots = 0, num_trigram_dots = 0;
7496 u_int8_t max_domain_element_len = 0, curr_domain_element_len = 0, first_element_is_numeric = 1;
7497
7498 if((!name)
7499 || (strchr(name, '_') != NULL)
7500 || (endsWith(name, "in-addr.arpa", 12))
7501 || (endsWith(name, "ip6.arpa", 8))
7502 /* Ignore TLD .local .lan and .home */
7503 || (endsWith(name, ".local", 6))
7504 || (endsWith(name, ".lan", 4))
7505 || (endsWith(name, ".home", 5))
7506 )
7507 return(0);
7508
7509 if(flow && (flow->packet.detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN))
7510 return(0); /* Ignore DGA check for protocols already fully detected */
7511
7512 if(strncmp(name, "www.", 4) == 0)
7513 name = &name[4];
7514
7515 if(ndpi_verbose_dga_detection)
7516 printf("[DGA check] %s\n", name);
7517
7518 len = strlen(name);
7519
7520 if(len >= 5) {
7521 int i, j, num_found = 0, num_impossible = 0, num_bigram_checks = 0,
7522 num_trigram_found = 0, num_trigram_checked = 0, num_dash = 0,
7523 num_digits = 0, num_vowels = 0, num_trigram_vowels = 0, num_words = 0, skip_next_bigram = 0;
7524 char tmp[128], *word, *tok_tmp;
7525 u_int max_tmp_len = sizeof(tmp)-1;
7526
7527 len = snprintf(tmp, max_tmp_len, "%s", name);
7528 if(len < 0) {
7529
7530 if(ndpi_verbose_dga_detection)
7531 printf("[DGA] Too short");
7532
7533 return(0);
7534 } else
7535 tmp[len < max_tmp_len ? len : max_tmp_len] = '\0';
7536
7537 for(i=0, j=0; (i<len) && (j<max_tmp_len); i++) {
7538 tmp[j] = tolower(name[i]);
7539
7540 if(tmp[j] == '.') {
7541 num_dots++;
7542 } else if(num_dots == 0) {
7543 if(!isdigit(tmp[j]))
7544 first_element_is_numeric = 0;
7545 }
7546
7547 if(ndpi_is_vowel(tmp[j]))
7548 num_vowels++;
7549
7550 if(last_char == tmp[j]) {
7551 if(++num_char_repetitions > max_num_char_repetitions)
7552 max_num_char_repetitions = num_char_repetitions;
7553 } else
7554 num_char_repetitions = 1, last_char = tmp[j];
7555
7556 if(isdigit(tmp[j])) {
7557 num_digits++;
7558
7559 if(((j+2)<len) && isdigit(tmp[j+1]) && (tmp[j+2] == '.')) {
7560 /* Check if there are too many digits */
7561 if(num_digits < 4)
7562 return(0); /* Double digits */
7563 }
7564 }
7565
7566 switch(tmp[j]) {
7567 case '.':
7568 case '-':
7569 case '_':
7570 case '/':
7571 case ')':
7572 case '(':
7573 case ';':
7574 case ':':
7575 case '[':
7576 case ']':
7577 case ' ':
7578 /*
7579 Domain/word separator chars
7580
7581 NOTE:
7582 this function is used also to detect other type of issues
7583 such as invalid/suspiciuous user agent
7584 */
7585 if(curr_domain_element_len > max_domain_element_len)
7586 max_domain_element_len = curr_domain_element_len;
7587
7588 curr_domain_element_len = 0;
7589 break;
7590
7591 default:
7592 curr_domain_element_len++;
7593 break;
7594 }
7595
7596 j++;
7597 }
7598
7599 if(num_dots == 0) /* Doesn't look like a domain name */
7600 return(0);
7601
7602 if(curr_domain_element_len > max_domain_element_len)
7603 max_domain_element_len = curr_domain_element_len;
7604
7605 if(ndpi_verbose_dga_detection)
7606 printf("[DGA] [max_num_char_repetitions: %u][max_domain_element_len: %u]\n",
7607 max_num_char_repetitions, max_domain_element_len);
7608
7609 if(
7610 (is_hostname
7611 && (num_dots > 5)
7612 && (!first_element_is_numeric)
7613 )
7614 || (max_num_char_repetitions > 5 /* num or consecutive repeated chars */)
7615 /*
7616 In case of a name with too many consecutive chars an alert is triggered
7617 This is the case for instance of the wildcard DNS query used by NetBIOS
7618 (ckaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) and that can be exploited
7619 for reflection attacks
7620 - https://www.akamai.com/uk/en/multimedia/documents/state-of-the-internet/ddos-reflection-netbios-name-server-rpc-portmap-sentinel-udp-threat-advisory.pdf
7621 - http://ubiqx.org/cifs/NetBIOS.html
7622 */
7623 || ((max_domain_element_len >= 19 /* word too long. Example bbcbedxhgjmdobdprmen.com */) && ((num_char_repetitions > 1) || (num_digits > 1)))
7624 ) {
7625 if(flow) ndpi_set_risk(ndpi_str, flow, NDPI_SUSPICIOUS_DGA_DOMAIN);
7626
7627 if(ndpi_verbose_dga_detection)
7628 printf("[DGA] Found!");
7629
7630 return(1);
7631 }
7632
7633 tmp[j] = '\0';
7634 len = j;
7635
7636 for(word = strtok_r(tmp, ".", &tok_tmp); ; word = strtok_r(NULL, ".", &tok_tmp)) {
7637 if(!word) break;
7638
7639 num_words++;
7640
7641 if(strlen(word) < 3) continue;
7642
7643 if(ndpi_verbose_dga_detection)
7644 printf("-> word(%s) [%s][len: %u]\n", word, name, (unsigned int)strlen(word));
7645
7646 trigram_char_skip = 0;
7647
7648 for(i = 0; word[i+1] != '\0'; i++) {
7649 switch(word[i]) {
7650 case '-':
7651 num_dash++;
7652 /*
7653 Let's check for double+consecutive --
7654 that are usually ok
7655 r2---sn-uxaxpu5ap5-2n5e.gvt1.com
7656 */
7657 if(word[i+1] == '-')
7658 return(0); /* Double dash */
7659
7660 case '_':
7661 case ':':
7662 continue;
7663 break;
7664
7665 case '.':
7666 continue;
7667 break;
7668 }
7669 num_bigram_checks++;
7670
7671 if(ndpi_verbose_dga_detection)
7672 printf("-> Checking %c%c\n", word[i], word[i+1]);
7673
7674 if(ndpi_match_impossible_bigram(&word[i])) {
7675 if(ndpi_verbose_dga_detection)
7676 printf("IMPOSSIBLE %s\n", &word[i]);
7677
7678 num_impossible++;
7679 } else {
7680 if(!skip_next_bigram) {
7681 if(ndpi_match_bigram(&word[i])) {
7682 num_found++, skip_next_bigram = 1;
7683 }
7684 } else
7685 skip_next_bigram = 0;
7686 }
7687
7688 if((num_trigram_dots < 2) && (word[i+2] != '\0')) {
7689 if(ndpi_verbose_dga_detection)
7690 printf("***> %s [trigram_char_skip: %u]\n", &word[i], trigram_char_skip);
7691
7692 if(ndpi_is_trigram_char(word[i]) && ndpi_is_trigram_char(word[i+1]) && ndpi_is_trigram_char(word[i+2])) {
7693 if(trigram_char_skip) {
7694 trigram_char_skip--;
7695 } else {
7696 num_trigram_checked++;
7697
7698 if(ndpi_match_trigram(&word[i]))
7699 num_trigram_found++, trigram_char_skip = 2 /* 1 char overlap */;
7700 else if(ndpi_verbose_dga_detection)
7701 printf("[NDPI] NO Trigram %c%c%c\n", word[i], word[i+1], word[i+2]);
7702
7703 /* Count vowels */
7704 num_trigram_vowels += ndpi_is_vowel(word[i]) + ndpi_is_vowel(word[i+1]) + ndpi_is_vowel(word[i+2]);
7705 }
7706 } else {
7707 if(word[i] == '.')
7708 num_trigram_dots++;
7709
7710 trigram_char_skip = 0;
7711 }
7712 }
7713 } /* for */
7714 } /* for */
7715
7716 if(ndpi_verbose_dga_detection)
7717 printf("[%s][num_found: %u][num_impossible: %u][num_digits: %u][num_bigram_checks: %u][num_vowels: %u/%u][num_trigram_vowels: %u][num_trigram_found: %u/%u][vowels: %u][rc: %u]\n",
7718 name, num_found, num_impossible, num_digits, num_bigram_checks, num_vowels, len, num_trigram_vowels,
7719 num_trigram_checked, num_trigram_found, num_vowels, rc);
7720
7721 if((len > 16) && (num_dots < 3) && ((num_vowels*4) < (len-num_dots))) {
7722 if((num_trigram_checked > 2) && (num_trigram_vowels >= (num_trigram_found-1)))
7723 ; /* skip me */
7724 else
7725 rc = 1;
7726 }
7727
7728 if(num_bigram_checks
7729 && (num_dots > 0)
7730 && ((num_found == 0) || ((num_digits > 5) && (num_words <= 3))
7731 || enough(num_found, num_impossible)
7732 || ((num_trigram_checked > 2)
7733 && ((num_trigram_found < (num_trigram_checked/2))
7734 || ((num_trigram_vowels < (num_trigram_found-1)) && (num_dash == 0) && (num_dots > 1) && (num_impossible > 0)))
7735 )
7736 )
7737 )
7738 rc = 1;
7739
7740 if((num_trigram_checked > 2) && (num_vowels == 0))
7741 rc = 1;
7742
7743 if(num_dash > 2)
7744 rc = 0;
7745
7746 if(ndpi_verbose_dga_detection) {
7747 if(rc)
7748 printf("DGA %s [num_found: %u][num_impossible: %u]\n",
7749 name, num_found, num_impossible);
7750 }
7751 }
7752
7753 if(ndpi_verbose_dga_detection)
7754 printf("[DGA] Result: %u\n", rc);
7755
7756 if(rc && flow)
7757 ndpi_set_risk(ndpi_str, flow, NDPI_SUSPICIOUS_DGA_DOMAIN);
7758
7759 return(rc);
7760 }
7761 }
7762
7763 /* ******************************************************************** */
7764
ndpi_risk2severity(ndpi_risk_enum risk)7765 ndpi_risk_info* ndpi_risk2severity(ndpi_risk_enum risk) {
7766 return(&ndpi_known_risks[risk]);
7767 }
7768