1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4"""
5file: ndpi_typestruct.py
6This file is part of nDPI.
7
8Copyright (C) 2011-19 - ntop.org
9Copyright (C) 2019 - Zied Aouini <aouinizied@gmail.com> (Incremental improvements)
10
11nDPI is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
13
14nDPI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along with nDPI.
18If not, see <http://www.gnu.org/licenses/>.
19"""
20
21from ctypes import CDLL, Structure, c_uint16, c_int, c_ulong, c_uint32, CFUNCTYPE, c_void_p, POINTER, c_char_p, c_uint8
22from ctypes import c_char, c_uint, c_int16, c_longlong, c_size_t, Union, c_ubyte, c_uint64, c_int32, c_ushort, cast
23from os.path import abspath, dirname
24ndpi = CDLL(dirname(abspath(__file__)) + '/ndpi_wrap.so')
25
26# ----------------------------------------------- Structures -----------------------------------------------------------
27
28
29class NDPIDetectionModuleStruct(Structure):
30    pass
31
32
33class NDPIFlowStruct(Structure):
34    pass
35
36
37class NDPIProtocol(Structure):
38    _fields_ = [
39        ("master_protocol", c_uint16),
40        ("app_protocol", c_uint16),
41        ("category", c_int)
42    ]
43
44
45class TimeVal(Structure):
46    _fields_ = [("tv_sec", c_ulong), ("tv_usec", c_ulong)]
47
48
49class PcapPktHdr(Structure):
50    _fields_ = [("ts", TimeVal), ("caplen", c_uint32), ("len", c_uint32)]
51
52
53class NDPIMask(Structure):
54    _fields_ = [("fds_bits", c_uint32)]
55
56
57class NDPIProtocolBitMask(Structure):
58    _fields_ = [("fds_bits", NDPIMask * ndpi.ndpi_wrap_ndpi_num_fds_bits())]
59
60
61class NDPISubprotocolConfStruct(Structure):
62    _fields_ = [("func", CFUNCTYPE(c_void_p, POINTER(NDPIDetectionModuleStruct), c_char_p, c_char_p, c_int))]
63
64
65class NDPIAutoma(Structure):
66    _fields_ = [
67        ("ac_automa", c_void_p),
68        ("ac_automa_finalized", c_uint8)
69    ]
70
71
72class NDPINode(Structure):
73    pass
74
75
76NDPINode._fields_ = [
77    ('key', POINTER(c_char)),
78    ('left', POINTER(NDPINode)),
79    ('right', POINTER(NDPINode)),
80]
81
82
83class NDPICallFunctionStruct(Structure):
84    _fields_ = [
85        ("detection_bitmask", NDPIProtocolBitMask),
86        ("excluded_protocol_bitmask", NDPIProtocolBitMask),
87        ("ndpi_selection_bitmask", c_uint32),
88        ("func", CFUNCTYPE(None, POINTER(NDPIDetectionModuleStruct), POINTER(NDPIFlowStruct))),
89        ("detection_feature", c_uint8)
90    ]
91
92
93class NDPIProtoDefaultsT(Structure):
94    _fields_ = [
95        ("protoName", c_char_p),
96        ("protoCategory", c_uint),
97        ("subprotocols", c_uint16_p),
98        ("subprotocol_count", c_uint32),
99        ("protoId", c_uint16),
100        ("protoIdx", c_uint16),
101        ("protoBreed", c_uint),
102        ("func", CFUNCTYPE(None, POINTER(NDPIDetectionModuleStruct), POINTER(NDPIFlowStruct))),
103    ]
104
105
106class NDPIDefaultsPortsTreeNodeT(Structure):
107    _fields_ = [
108        ("proto", NDPIProtoDefaultsT),
109        ("customUserProto", c_uint8),
110        ("default_port", c_int16)
111    ]
112
113
114class SpinlockT(Structure):
115    _fields_ = [("val", c_int)]
116
117
118class AtomicT(Structure):
119    _fields_ = [("counter", c_int)]
120
121
122class TimeT(Structure):
123    _fields_ = [("counter", c_longlong)]
124
125
126class HashIp4pNode(Structure):
127    pass
128
129
130HashIp4pNode._fields_ = [
131    ("next", POINTER(HashIp4pNode)),
132    ("prev", POINTER(HashIp4pNode)),
133    ("lchg", TimeT),
134    ("port", c_uint16),
135    ("count", c_uint16, 12),
136    ("flag", c_uint16, 4),
137    ("ip", c_uint32)
138]
139
140
141class HashIp4p(Structure):
142    _fields_ = [
143        ("top", POINTER(HashIp4pNode)),
144        ("lock",SpinlockT),
145        ("len", c_size_t)
146    ]
147
148
149class HashIp4pTable(Structure):
150    _fields_ = [
151        ("size", c_size_t),
152        ("ipv6", c_int),
153        ("lock", SpinlockT),
154        ("count", AtomicT),
155        ("tbl", HashIp4p)
156    ]
157
158
159class BtAnnounce(Structure):
160    _fields_ = [
161        ("hash", c_uint32 * 5),
162        ("ip", c_uint32 * 4),
163        ("time", c_uint32),
164        ("port", c_uint16),
165        ("name_len", c_uint8),
166        ("name", c_uint8 * 149)
167    ]
168
169
170class NDPILruCacheEntry(Structure):
171    _fields_ = [
172        ("key", c_uint32),
173        ("is_full", c_uint32, 1),
174        ("value", c_uint32, 16),
175        ("pad", c_uint32, 15)
176    ]
177
178
179class NDPILruCache(Structure):
180    _fields_ = [
181        ("num_entries", c_uint32),
182        ("entries", POINTER(NDPILruCacheEntry)),
183    ]
184
185
186class CacheEntry(Structure):
187    pass
188
189
190CacheEntry._fields_ = [
191    ("item", c_void_p),
192    ("item_size", c_uint32),
193    ("prev", POINTER(CacheEntry)),
194    ("next", POINTER(CacheEntry))
195]
196
197
198class CacheEntryMap(Structure):
199    pass
200
201
202CacheEntryMap._fields_ = [
203    ("entry", POINTER(CacheEntry)),
204    ("next", POINTER(CacheEntryMap)),
205]
206
207
208class Cache(Structure):
209    _fields_ = [
210        ("size", c_uint32),
211        ("max_size", c_uint32),
212        ("head", POINTER(CacheEntry)),
213        ("tail", POINTER(CacheEntry)),
214        ("map", POINTER(POINTER(CacheEntryMap)))
215    ]
216
217
218class CustomCategories(Structure):
219    _fields_ = [
220        ("hostnames", NDPIAutoma),
221        ("hostnames_shadow", NDPIAutoma),
222        ("ipAddresses", c_void_p),
223        ("ipAddresses_shadow", c_void_p),
224        ("categories_loaded", c_uint8),
225    ]
226
227
228NDPIDetectionModuleStruct._fields_ = [
229    ("detection_bitmask", NDPIProtocolBitMask),
230    ("generic_http_packet_bitmask", NDPIProtocolBitMask),
231    ("current_ts", c_uint32),
232    ("ticks_per_second", c_uint32),
233    ("custom_category_labels",
234     (c_char * ndpi.ndpi_wrap_num_custom_categories()) * ndpi.ndpi_wrap_custom_category_label_len()),
235    ("callback_buffer", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
236    ("callback_buffer_size", c_uint32),
237    ("callback_buffer_tcp_no_payload", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
238    ("callback_buffer_size_tcp_no_payload", c_uint32),
239    ("callback_buffer_tcp_payload", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
240    ("callback_buffer_size_tcp_payload", c_uint32),
241    ("callback_buffer_udp", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
242    ("callback_buffer_size_udp", c_uint32),
243    ("callback_buffer_non_tcp_udp", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
244    ("callback_buffer_size_non_tcp_udp", c_uint32),
245    ("tcpRoot", POINTER(NDPIDefaultsPortsTreeNodeT)),
246    ("udpRoot", POINTER(NDPIDefaultsPortsTreeNodeT)),
247    ("ndpi_log_level", c_uint),
248    ("tcp_max_retransmission_window_size", c_uint32),
249    ("directconnect_connection_ip_tick_timeout", c_uint32),
250    ("subprotocol_conf", NDPISubprotocolConfStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
251    ("ndpi_num_supported_protocols", c_uint),
252    ("ndpi_num_custom_protocols", c_uint),
253    ("host_automa", NDPIAutoma),
254    ("content_automa", NDPIAutoma),
255    ("subprotocol_automa", NDPIAutoma),
256    ("bigrams_automa", NDPIAutoma),
257    ("impossible_bigrams_automa", NDPIAutoma),
258    ("custom_categories", CustomCategories),
259    ("protocols_ptree", c_void_p),
260    ("irc_timeout", c_uint32),
261    ("gnutella_timeout", c_uint32),
262    ("battlefield_timeout", c_uint32),
263    ("thunder_timeout", c_uint32),
264    ("soulseek_connection_ip_tick_timeout", c_uint32),
265    ("rtsp_connection_timeout", c_uint32),
266    ("tvants_connection_timeout", c_uint32),
267    ("orb_rstp_ts_timeout", c_uint32),
268    ("yahoo_detect_http_connections", c_uint8),
269    ("yahoo_lan_video_timeout", c_uint32),
270    ("zattoo_connection_timeout", c_uint32),
271    ("jabber_stun_timeout", c_uint32),
272    ("jabber_file_transfer_timeout", c_uint32),
273    ("ip_version_limit", c_uint8),
274    ("bt_ht", POINTER(HashIp4pTable)),
275    ("bt6_ht", POINTER(HashIp4pTable)),
276    ("bt_ann", POINTER(BtAnnounce)),
277    ("bt_ann_len", c_int),
278    ("ookla_cache", POINTER(NDPILruCache)),
279    ("tinc_cache", POINTER(Cache)),
280    ("proto_defaults", NDPIProtoDefaultsT * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() +
281                                             ndpi.ndpi_wrap_ndpi_max_num_custom_protocols())),
282    ("http_dont_dissect_response", c_uint8, 1),
283    ("dns_dont_dissect_response", c_uint8, 1),
284    ("direction_detect_disable", c_uint8, 1),
285    ("disable_metadata_export", c_uint8, 1),
286    ("hyperscan", c_void_p)
287]
288
289
290class U6Addr(Union):
291    _fields_ = [
292        ("u6_addr8", c_uint8 * 16),
293        ("u6_addr16", c_uint16 * 8),
294        ("u6_addr32", c_uint32 * 4),
295        ("u6_addr64", c_uint64 * 2)
296    ]
297
298
299class NDPIIn6Addr(Structure):
300    _pack_ = 1
301    _fields_ = [("u6_addr", U6Addr)]
302
303
304class NDPIIpAddrT(Union):
305    _fields_ = [
306        ('ipv4', c_uint32),
307        ('ipv4_u_int8_t', c_uint8 * 4),
308        ('ipv6', NDPIIn6Addr),
309    ]
310
311
312class NDPIIdStruct(Structure):
313    _fields_ = [
314        ('detected_protocol_bitmask', NDPIProtocolBitMask),
315        ('rtsp_ip_address', NDPIIpAddrT),
316        ('yahoo_video_lan_timer', c_uint32),
317        ('irc_port', c_uint16 * 8),
318        ('last_time_port_used', c_uint32 * 8),
319        ('irc_ts', c_uint32),
320        ('gnutella_ts', c_uint32),
321        ('battlefield_ts', c_uint32),
322        ('thunder_ts', c_uint32),
323        ('rtsp_timer', c_uint32),
324        ('oscar_last_safe_access_time', c_uint32),
325        ('zattoo_ts', c_uint32),
326        ('jabber_stun_or_ft_ts', c_uint32),
327        ('directconnect_last_safe_access_time', c_uint32),
328        ('soulseek_last_safe_access_time', c_uint32),
329        ('detected_directconnect_port', c_uint16),
330        ('detected_directconnect_udp_port', c_uint16),
331        ('detected_directconnect_ssl_port', c_uint16),
332        ('bt_port_t', c_uint16 * 8),
333        ('bt_port_u', c_uint16 * 8),
334        ('jabber_voice_stun_port', c_uint16 * 6),
335        ('jabber_file_transfer_port', c_uint16 * 2),
336        ('detected_gnutella_port', c_uint16),
337        ('detected_gnutella_udp_port1', c_uint16),
338        ('detected_gnutella_udp_port2', c_uint16),
339        ('soulseek_listen_port', c_uint16),
340        ('irc_number_of_port', c_uint8),
341        ('oscar_ssl_session_id', c_uint8 * 33),
342        ('jabber_voice_stun_used_ports', c_uint8),
343        ('yahoo_video_lan_dir', c_uint32, 1),
344        ('yahoo_conf_logged_in', c_uint32, 1),
345        ('yahoo_voice_conf_logged_in', c_uint32, 1),
346        ('rtsp_ts_set', c_uint32, 1),
347    ]
348
349
350class NDPIFlowTcpStruct(Structure):
351    _pack_ = 1
352    _fields_ = [
353        ('smtp_command_bitmask', c_uint16),
354        ('pop_command_bitmask', c_uint16),
355        ('qq_nxt_len', c_uint16),
356        ('wa_matched_so_far', c_uint8),
357        ('tds_login_version', c_uint8),
358        ('irc_stage', c_uint8),
359        ('irc_port', c_uint8),
360        ('h323_valid_packets', c_uint8),
361        ('gnutella_msg_id', c_uint8 * 3),
362        ('irc_3a_counter', c_uint32, 3),
363        ('irc_stage2', c_uint32, 5),
364        ('irc_direction', c_uint32, 2),
365        ('irc_0x1000_full', c_uint32, 1),
366        ('soulseek_stage', c_uint32, 2),
367        ('tds_stage', c_uint32, 3),
368        ('usenet_stage', c_uint32, 2),
369        ('imesh_stage', c_uint32, 4),
370        ('http_setup_dir', c_uint32, 2),
371        ('http_stage', c_uint32, 2),
372        ('http_empty_line_seen', c_uint32, 1),
373        ('http_wait_for_retransmission', c_uint32, 1),
374        ('gnutella_stage', c_uint32, 2),
375        ('mms_stage', c_uint32, 2),
376        ('yahoo_sip_comm', c_uint32, 1),
377        ('yahoo_http_proxy_stage', c_uint32, 2),
378        ('msn_stage', c_uint32, 3),
379        ('msn_ssl_ft', c_uint32, 2),
380        ('ssh_stage', c_uint32, 3),
381        ('vnc_stage', c_uint32, 2),
382        ('telnet_stage', c_uint32, 2),
383        ('tls_srv_cert_fingerprint_ctx', c_void_p),
384        ('tls_seen_client_cert', c_uint8, 1),
385        ('tls_seen_server_cert', c_uint8, 1),
386        ('tls_seen_certificate', c_uint8, 1),
387        ('tls_srv_cert_fingerprint_found', c_uint8, 1),
388        ('tls_srv_cert_fingerprint_processed', c_uint8, 1),
389        ('tls_stage', c_uint8, 2),
390        ('tls_record_offset', c_int16),
391        ('tls_fingerprint_len', c_int16),
392        ('tls_sha1_certificate_fingerprint', c_uint8 * 20),
393        ('postgres_stage', c_uint32, 3),
394        ('ddlink_server_direction', c_uint32, 1),
395        ('seen_syn', c_uint32, 1),
396        ('seen_syn_ack', c_uint32, 1),
397        ('seen_ack', c_uint32, 1),
398        ('icecast_stage', c_uint32, 1),
399        ('dofus_stage', c_uint32, 1),
400        ('fiesta_stage', c_uint32, 2),
401        ('wow_stage', c_uint32, 2),
402        ('veoh_tv_stage', c_uint32, 2),
403        ('shoutcast_stage', c_uint32, 2),
404        ('rtp_special_packets_seen', c_uint32, 1),
405        ('mail_pop_stage', c_uint32, 2),
406        ('mail_imap_stage', c_uint32, 3),
407        ('mail_imap_starttls', c_uint32, 2),
408        ('skype_packet_id', c_uint8),
409        ('citrix_packet_id', c_uint8),
410        ('lotus_notes_packet_id', c_uint8),
411        ('teamviewer_stage', c_uint8),
412        ('prev_zmq_pkt_len', c_uint8),
413        ('prev_zmq_pkt', c_char * 10),
414        ('ppstream_stage', c_uint32, 3),
415        ('memcached_matches', c_uint8),
416        ('nest_log_sink_matches', c_uint8),
417    ]
418
419
420class NDPIFlowUdpStruct(Structure):
421    _pack_ = 1
422    _fields_ = [
423        ('battlefield_msg_id', c_uint32),
424        ('snmp_msg_id', c_uint32),
425        ('battlefield_stage', c_uint32, 3),
426        ('snmp_stage', c_uint32, 2),
427        ('ppstream_stage', c_uint32, 3),
428        ('halflife2_stage', c_uint32, 2),
429        ('tftp_stage', c_uint32, 2),
430        ('aimini_stage', c_uint32, 5),
431        ('xbox_stage', c_uint32, 1),
432        ('wsus_stage', c_uint32, 1),
433        ('skype_packet_id', c_uint8),
434        ('teamviewer_stage', c_uint8),
435        ('eaq_pkt_id', c_uint8),
436        ('eaq_sequence', c_uint32),
437        ('rx_conn_epoch', c_uint32),
438        ('rx_conn_id', c_uint32),
439        ('memcached_matches', c_uint8),
440        ('wireguard_stage', c_uint8),
441        ('wireguard_peer_index', c_uint32 * 2),
442    ]
443
444
445class L4(Union):
446    _fields_ = [("tcp", NDPIFlowTcpStruct), ("udp", NDPIFlowUdpStruct)]
447
448
449class Http(Structure):
450    _fields_ = [
451        ("method", c_int),
452        ("url", c_char_p),
453        ("content_type", c_char_p),
454        ("num_request_headers", c_uint8),
455        ("num_response_headers", c_uint8),
456        ("request_version", c_uint8),
457        ("response_status_code", c_uint16),
458        ("detected_os", c_char * 32),
459    ]
460
461
462class Dns(Structure):
463    _fields_ = [
464        ("num_queries", c_uint8),
465        ("num_answers", c_uint8),
466        ("reply_code", c_uint8),
467        ("is_query", c_uint8),
468        ("query_type", c_uint16),
469        ("query_class", c_uint16),
470        ("rsp_type", c_uint16),
471        ("rsp_addr", NDPIIpAddrT)
472    ]
473
474
475class Ntp(Structure):
476    _fields_ = [("request_code", c_uint8),
477                ("version", c_uint8)]
478
479
480class Kerberos(Structure):
481    _fields_ = [("cname", c_char * 24),
482                ("realm", c_char * 24)]
483
484
485class Ssl(Structure):
486    _fields_ = [
487        ("ssl_version", c_uint16),
488        ("client_certificate", c_char * 64),
489        ("server_certificate", c_char * 64),
490        ("server_organization",  c_char * 64),
491        ('notBefore', c_uint32),
492        ('notAfter', c_uint32),
493        ("ja3_client", c_char * 33),
494        ("ja3_server", c_char * 33),
495        ("server_cipher", c_uint16),
496        ("server_unsafe_cipher", c_int)
497    ]
498
499
500class Stun(Structure):
501    _fields_ = [
502        ("num_udp_pkts", c_uint8),
503        ("num_processed_pkts", c_uint8),
504        ("num_binding_requests", c_uint8),
505    ]
506
507
508class StunSsl(Structure):
509    _fields_ = [("ssl", Ssl), ("stun", Stun)]
510
511
512class Ssh(Structure):
513    _fields_ = [
514        ("client_signature", c_char * 48),
515        ("server_signature", c_char * 48),
516        ("hassh_client", c_char * 33),
517        ("hassh_server", c_char * 33)
518    ]
519
520
521class Imo(Structure):
522    _fields_ = [
523        ("last_one_byte_pkt", c_uint8),
524        ("last_byte", c_uint8)
525    ]
526
527
528class Mdns(Structure):
529    _fields_ = [("answer", c_char * 96)]
530
531
532class Ubntac2(Structure):
533    _fields_ = [("version", c_char * 32)]
534
535
536class Http2(Structure):
537    _fields_ = [
538        ("nat_ip", c_char * 24)
539    ]
540
541
542class Bittorrent(Structure):
543    _fields_ = [("hash", c_char * 20)]
544
545
546class Dhcp(Structure):
547    _fields_ = [
548        ("fingerprint", c_char * 48),
549        ("class_ident", c_char * 48)
550    ]
551
552
553class Protos(Union):
554    _fields_ = [
555        ("dns", Dns),
556        ("kerberos", Kerberos),
557        ("stun_ssl", StunSsl),
558        ("ssh", Ssh),
559        ("imo", Imo),
560        ("mdns", Mdns),
561        ("ubntac2", Ubntac2),
562        ("http", Http2),
563        ("bittorrent", Bittorrent),
564        ("dhcp", Dhcp)
565    ]
566
567
568class TincCacheEntry(Structure):
569    _pack_ = 1
570    _fields_ = [
571        ('src_address', c_uint32),
572        ('dst_address', c_uint32),
573        ('dst_port', c_uint16),
574    ]
575
576
577class NDPIIntOneLineStruct(Structure):
578    _fields_ = [
579        ('ptr', POINTER(c_uint8)),
580        ('len', c_uint16),
581    ]
582
583
584class NDPIIphdr(Structure):
585    _pack_ = 1
586    _fields_ = [
587        ('ihl', c_uint8, 4),
588        ('version', c_uint8, 4),
589        ('tos', c_uint8),
590        ('tot_len', c_uint16),
591        ('id', c_uint16),
592        ('frag_off', c_uint16),
593        ('ttl', c_uint8),
594        ('protocol', c_uint8),
595        ('check', c_uint16),
596        ('saddr', c_uint32),
597        ('daddr', c_uint32)]
598
599
600class NDPIIp6Hdrctl(Structure):
601    _pack_ = 1
602    _fields_ = [
603        ('ip6_un1_flow', c_uint32),
604        ('ip6_un1_plen', c_uint16),
605        ('ip6_un1_nxt', c_uint8),
606        ('ip6_un1_hlim', c_uint8),
607    ]
608
609
610class NDPIIpv6hdr(Structure):
611    _pack_ = 1
612    _fields_ = [
613        ('ip6_hdr', NDPIIp6Hdrctl),
614        ('ip6_src', NDPIIn6Addr),
615        ('ip6_dst', NDPIIn6Addr),
616    ]
617
618
619class NDPITcpHdr(Structure):
620    _pack_ = 1
621    _fields_ = [
622        ('source', c_uint16),
623        ('dest', c_uint16),
624        ('seq', c_uint32),
625        ('ack_seq', c_uint32),
626        ('res1', c_uint16, 4),
627        ('doff', c_uint16, 4),
628        ('fin', c_uint16, 1),
629        ('syn', c_uint16, 1),
630        ('rst', c_uint16, 1),
631        ('psh', c_uint16, 1),
632        ('ack', c_uint16, 1),
633        ('urg', c_uint16, 1),
634        ('ece', c_uint16, 1),
635        ('cwr', c_uint16, 1),
636        ('window', c_uint16),
637        ('check', c_uint16),
638        ('urg_ptr', c_uint16),
639    ]
640
641
642class NDPIUdpHdr(Structure):
643    _pack_ = 1
644    _fields_ = [
645        ('source', c_uint16),
646        ('dest', c_uint16),
647        ('len', c_uint16),
648        ('check', c_uint16),
649    ]
650
651
652class NDPIPacketStructStack(Structure):
653    _pack_ = 1
654    _fields_ = [
655        ('protocol_stack_info', c_uint16)
656    ]
657
658
659class NDPIPacketStruct(Structure):
660    _fields_ = [
661        ('iph', POINTER(NDPIIphdr)),
662        ('iphv6', POINTER(NDPIIpv6hdr)),
663        ('tcp', POINTER(NDPITcpHdr)),
664        ('udp', POINTER(NDPIUdpHdr)),
665        ('generic_l4_ptr', POINTER(c_uint8)),
666        ('payload', POINTER(c_uint8)),
667        ('tick_timestamp', c_uint32),
668        ('tick_timestamp_l', c_uint64),
669        ('detected_protocol_stack', c_uint16 * ndpi.ndpi_wrap_ndpi_procol_size()),
670        ('ndpi_packet_stack', NDPIPacketStructStack),
671        ('line', NDPIIntOneLineStruct * 64),
672        ('host_line', NDPIIntOneLineStruct),
673        ('forwarded_line', NDPIIntOneLineStruct),
674        ('referer_line', NDPIIntOneLineStruct),
675        ('content_line', NDPIIntOneLineStruct),
676        ('accept_line', NDPIIntOneLineStruct),
677        ('user_agent_line', NDPIIntOneLineStruct),
678        ('http_url_name', NDPIIntOneLineStruct),
679        ('http_encoding', NDPIIntOneLineStruct),
680        ('http_transfer_encoding', NDPIIntOneLineStruct),
681        ('http_contentlen', NDPIIntOneLineStruct),
682        ('http_cookie', NDPIIntOneLineStruct),
683        ('http_origin', NDPIIntOneLineStruct),
684        ('http_x_session_type', NDPIIntOneLineStruct),
685        ('server_line', NDPIIntOneLineStruct),
686        ('http_method', NDPIIntOneLineStruct),
687        ('http_response', NDPIIntOneLineStruct),
688        ('http_num_headers', c_uint8),
689        ('l3_packet_len', c_uint16),
690        ('l4_packet_len', c_uint16),
691        ('payload_packet_len', c_uint16),
692        ('actual_payload_len', c_uint16),
693        ('num_retried_bytes', c_uint16),
694        ('parsed_lines', c_uint16),
695        ('parsed_unix_lines', c_uint16),
696        ('empty_line_position', c_uint16),
697        ('tcp_retransmission', c_uint8),
698        ('l4_protocol', c_uint8),
699        ('ssl_certificate_detected', c_uint8, 4),
700        ('ssl_certificate_num_checks', c_uint8, 4),
701        ('packet_lines_parsed_complete', c_uint8, 1),
702        ('packet_direction', c_uint8, 1),
703        ('empty_line_position_set', c_uint8, 1),
704        ('pad', c_uint8, 5),
705    ]
706
707
708class NDPIFlowStructStack(Structure):
709    _pack_ = 1
710    _fields_ = [
711        ("detected_protocol_stack", c_uint16 * ndpi.ndpi_wrap_ndpi_procol_size()),
712        ("protocol_stack_info", c_uint16)
713    ]
714
715
716NDPIFlowStruct._fields_ = [
717    ("ndpi_flow_stack", NDPIFlowStructStack),
718    ("guessed_protocol_id", c_uint16),
719    ("guessed_host_protocol_id", c_uint16),
720    ("guessed_category", c_uint16),
721    ("guessed_header_category", c_uint16),
722    ("l4_proto", c_uint8),
723    ("protocol_id_already_guessed", c_uint8, 1),
724    ("host_already_guessed", c_uint8, 1),
725    ("init_finished", c_uint8, 1),
726    ("setup_packet_direction", c_uint8, 1),
727    ("packet_direction", c_uint8, 1),
728    ("check_extra_packets", c_uint8, 1),
729    ("next_tcp_seq_nr", c_uint32 * 2),
730    ("max_extra_packets_to_check", c_uint8),
731    ("num_extra_packets_checked", c_uint8),
732    ("num_processed_pkts", c_uint8),
733    ("extra_packets_func", CFUNCTYPE(c_int, POINTER(NDPIDetectionModuleStruct), POINTER(NDPIFlowStruct))),
734    ("l4", L4),
735    ("server_id", POINTER(NDPIIdStruct)),
736    ("host_server_name", c_ubyte * 256),
737    ("http", Http),
738    ("protos", Protos),
739    ("excluded_protocol_bitmask", NDPIProtocolBitMask),
740    ("category", c_int),
741    ('redis_s2d_first_char', c_uint8),
742    ('redis_d2s_first_char', c_uint8),
743    ('packet_counter', c_uint16),
744    ('packet_direction_counter', c_uint16 * 2),
745    ('byte_counter', c_uint16 * 2),
746    ('bittorrent_stage', c_uint8),
747    ('directconnect_stage', c_uint8, 2),
748    ('sip_yahoo_voice', c_uint8, 1),
749    ('http_detected', c_uint8, 1),
750    ('http_upper_protocol', c_uint16),
751    ('http_lower_protocol', c_uint16),
752    ('rtsprdt_stage', c_uint8, 2),
753    ('rtsp_control_flow', c_uint8, 1),
754    ('yahoo_detection_finished', c_uint8, 2),
755    ('zattoo_stage', c_uint8, 3),
756    ('qq_stage', c_uint8, 3),
757    ('thunder_stage', c_uint8, 2),
758    ('oscar_ssl_voice_stage', c_uint8, 3),
759    ('oscar_video_voice', c_uint8, 1),
760    ('florensia_stage', c_uint8, 1),
761    ('socks5_stage', c_uint8, 2),
762    ('socks4_stage', c_uint8, 2),
763    ('edonkey_stage', c_uint8, 2),
764    ('ftp_control_stage', c_uint8, 2),
765    ('rtmp_stage', c_uint8, 2),
766    ('pando_stage', c_uint8, 3),
767    ('steam_stage1', c_uint16, 3),
768    ('steam_stage2', c_uint16, 2),
769    ('steam_stage3', c_uint16, 2),
770    ('pplive_stage1', c_uint8, 3),
771    ('pplive_stage2', c_uint8, 2),
772    ('pplive_stage3', c_uint8, 2),
773    ('starcraft_udp_stage', c_uint8, 3),
774    ('ovpn_session_id', c_uint8 * 8),
775    ('ovpn_counter', c_uint8),
776    ('tinc_state', c_uint8),
777    ('TincCacheEntry', TincCacheEntry),
778    ('csgo_strid', c_uint8 * 18),
779    ('csgo_state', c_uint8),
780    ('csgo_s2', c_uint8),
781    ('csgo_id2', c_uint32),
782    ('kxun_counter', c_uint16),
783    ('iqiyi_counter', c_uint16),
784    ('packet', NDPIPacketStruct),
785    ('flow', POINTER(NDPIFlowStruct)),
786    ('src', POINTER(NDPIIdStruct)),
787    ('dst', POINTER(NDPIIdStruct))
788]
789
790# ----------------------------------------------- nDPI APIs ------------------------------------------------------------
791
792""" ndpi_detection_giveup: Function to be called before we give up with detection for a given flow.
793                           This function reduces the NDPI_UNKNOWN_PROTOCOL detection. """
794ndpi.ndpi_detection_giveup.restype = NDPIProtocol
795ndpi.ndpi_detection_giveup.argtypes = [POINTER(NDPIDetectionModuleStruct),
796                                      POINTER(NDPIFlowStruct), c_uint8,
797                                      POINTER(c_uint8)]
798
799""" ndpi_detection_process_packet: Processes one packet and returns the ID of the detected protocol.
800                                   This is the MAIN PACKET PROCESSING FUNCTION. """
801ndpi.ndpi_detection_process_packet.restype = NDPIProtocol
802ndpi.ndpi_detection_process_packet.argtypes = [POINTER(NDPIDetectionModuleStruct),
803                                               POINTER(NDPIFlowStruct),
804                                               POINTER(c_ubyte),
805                                               c_ushort,
806                                               c_uint64,
807                                               POINTER(NDPIIdStruct),
808                                               POINTER(NDPIIdStruct)]
809
810""" ndpi_ssl_version2str : Converts ssl version to readable string """
811ndpi.ndpi_ssl_version2str.restype = c_char_p
812ndpi.ndpi_ssl_version2str.argtypes = [c_int16, POINTER(c_uint8)]
813
814""" ndpi_init_detection_module: Returns a new initialized detection module.
815    Note that before you can use it you can still load hosts and do other things. As soon as you are ready to use
816    it do not forget to call first ndpi_finalize_initalization() """
817ndpi.ndpi_init_detection_module.restype = POINTER(NDPIDetectionModuleStruct)
818
819
820def ndpi_ndpi_finalize_initalization(detection_module):
821    """ ndpi_finalize_initalization: Completes the initialization (ndpi_revision >= 3.1)"""
822    if cast(ndpi.ndpi_revision(), c_char_p).value.decode("utf-8")[:3] >= '3.1':
823        ndpi.ndpi_finalize_initalization.restype = c_void_p
824        ndpi.ndpi_finalize_initalization.argtypes = [POINTER(NDPIDetectionModuleStruct)]
825        return ndpi.ndpi_finalize_initalization(detection_module)
826    else:
827        # ignore it
828        return None
829
830
831""" ndpi_tfind: find a node, or return 0. """
832ndpi.ndpi_tfind.restype = c_void_p
833
834""" ndpi_tsearch: ftp://ftp.cc.uoc.gr/mirrors/OpenBSD/src/lib/libc/stdlib/tsearch.c
835                  find or insert datum into search tree. """
836ndpi.ndpi_tsearch.restype = c_void_p
837ndpi.ndpi_tsearch.argtypes = [c_void_p, POINTER(c_void_p), CFUNCTYPE(c_int, c_void_p, c_void_p)]
838
839""" ndpi_revision: Get the nDPI version release. """
840ndpi.ndpi_revision.restype = c_void_p
841
842""" ndpi_get_proto_name: Get the protocol name associated to the ID."""
843ndpi.ndpi_get_proto_name.restype = c_void_p
844
845""" ndpi_category_get_name: Get protocol category as string."""
846ndpi.ndpi_category_get_name.restype = c_void_p
847
848""" ndpi_get_num_supported_protocols: Get the total number of the supported protocols."""
849ndpi.ndpi_get_num_supported_protocols.restype = c_uint
850
851""" ndpi_wrap_NDPI_BITMASK_SET_ALL: memset((char *)(p), 0xFF, sizeof(*(p)))"""
852ndpi.ndpi_wrap_NDPI_BITMASK_SET_ALL.argtypes = [POINTER(NDPIProtocolBitMask)]
853
854""" ndpi_set_protocol_detection_bitmask2: Sets the protocol bitmask2."""
855ndpi.ndpi_set_protocol_detection_bitmask2.argtypes = [POINTER(NDPIDetectionModuleStruct),
856                                                      POINTER(NDPIProtocolBitMask)]
857
858""" ndpi_twalk: Walk the nodes of a tree. """
859ndpi.ndpi_twalk.argtypes = [c_void_p, CFUNCTYPE(None, c_void_p, c_int32, c_int, c_void_p), c_void_p]
860
861""" ndpi_tdestroy: node destroy. """
862ndpi.ndpi_tdestroy.argtypes = [c_void_p, CFUNCTYPE(None, c_void_p)]
863