From a95cfcc98906c1807acf6707c838cc49d15ae39b Mon Sep 17 00:00:00 2001
From: aouinizied <aouinizied@gmail.com>
Date: Thu, 28 Nov 2019 03:09:13 +0100
Subject: Implement cffi bindings.

---
 python/ndpi.py | 1274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1274 insertions(+)
 create mode 100644 python/ndpi.py

(limited to 'python/ndpi.py')

diff --git a/python/ndpi.py b/python/ndpi.py
new file mode 100644
index 000000000..324fd7204
--- /dev/null
+++ b/python/ndpi.py
@@ -0,0 +1,1274 @@
+"""
+file: ndpi.py
+This file is part of nfstream.
+
+Copyright (C) 2019 - Zied Aouini <aouinizied@gmail.com>
+
+nfstream is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+nfstream is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with nfstream.
+If not, see <http://www.gnu.org/licenses/>.
+"""
+
+from os.path import abspath, dirname
+import cffi
+
+cc = """
+typedef enum {
+    ndpi_l4_proto_unknown = 0,
+    ndpi_l4_proto_tcp_only,
+    ndpi_l4_proto_udp_only,
+    ndpi_l4_proto_tcp_and_udp,
+} ndpi_l4_proto_info;
+typedef enum {
+    ndpi_no_tunnel = 0,
+    ndpi_gtp_tunnel,
+    ndpi_capwap_tunnel,
+    ndpi_tzsp_tunnel,
+    ndpi_l2tp_tunnel,
+} ndpi_packet_tunnel;
+
+typedef enum {
+    ndpi_url_no_problem = 0,
+    ndpi_url_possible_xss,
+    ndpi_url_possible_sql_injection
+} ndpi_url_risk;
+
+/* NDPI_VISIT */
+typedef enum {
+    ndpi_preorder,
+    ndpi_postorder,
+    ndpi_endorder,
+    ndpi_leaf
+} ndpi_VISIT;
+
+/* NDPI_NODE */
+typedef struct node_t {
+    char *key;
+    struct node_t *left, *right;
+} ndpi_node;
+
+/* NDPI_MASK_SIZE */
+typedef uint32_t ndpi_ndpi_mask;
+
+/* NDPI_PROTO_BITMASK_STRUCT */
+typedef struct ndpi_protocol_bitmask_struct {
+    ndpi_ndpi_mask fds_bits[16];
+} NDPI_PROTOCOL_BITMASK;
+
+typedef struct spinlock {
+    volatile int    val;
+} spinlock_t;
+
+typedef struct atomic {
+    volatile int counter;
+} atomic_t;
+
+typedef long int time_t;
+
+struct hash_ip4p_node {
+    struct hash_ip4p_node   *next,*prev;
+    time_t                  lchg;
+    uint16_t               port,count:12,flag:4;
+    uint32_t               ip;
+    // + 12 bytes for ipv6
+};
+
+struct hash_ip4p {
+    struct hash_ip4p_node   *top;
+    spinlock_t              lock;
+    size_t                  len;
+};
+
+struct hash_ip4p_table {
+    size_t                  size;
+    int			  ipv6;
+    spinlock_t              lock;
+    atomic_t                count;
+    struct hash_ip4p        tbl;
+};
+
+struct bt_announce {              // 192 bytes
+    uint32_t		hash[5];
+    uint32_t		ip[4];
+    uint32_t		time;
+    uint16_t		port;
+    uint8_t		name_len,
+    name[149];     // 149 bytes
+};
+
+/* NDPI_PROTOCOL_TINC */
+#define TINC_CACHE_MAX_SIZE 10
+
+typedef enum {
+    NDPI_HTTP_METHOD_UNKNOWN = 0,
+    NDPI_HTTP_METHOD_OPTIONS,
+    NDPI_HTTP_METHOD_GET,
+    NDPI_HTTP_METHOD_HEAD,
+    NDPI_HTTP_METHOD_PATCH,
+    NDPI_HTTP_METHOD_POST,
+    NDPI_HTTP_METHOD_PUT,
+    NDPI_HTTP_METHOD_DELETE,
+    NDPI_HTTP_METHOD_TRACE,
+    NDPI_HTTP_METHOD_CONNECT
+} ndpi_http_method;
+
+struct ndpi_lru_cache_entry {
+    uint32_t key; /* Store the whole key to avoid ambiguities */
+    uint32_t is_full:1, value:16, pad:15;
+};
+
+struct ndpi_lru_cache {
+    uint32_t num_entries;
+    struct ndpi_lru_cache_entry *entries;
+};
+
+"""
+
+cc_ndpi_network_headers = """
+struct ndpi_chdlc
+{
+    uint8_t addr;          /* 0x0F (Unicast) - 0x8F (Broadcast) */
+    uint8_t ctrl;          /* always 0x00                       */
+    uint16_t proto_code;   /* protocol type (e.g. 0x0800 IP)    */
+};
+
+/* SLARP - Serial Line ARP http://tinyurl.com/qa54e95 */
+struct ndpi_slarp
+{
+    /* address requests (0x00)
+    address replies  (0x01)
+    keep-alive       (0x02)
+    */
+    uint32_t slarp_type;
+    uint32_t addr_1;
+    uint32_t addr_2;
+};
+
+/* Cisco Discovery Protocol http://tinyurl.com/qa6yw9l */
+struct ndpi_cdp
+{
+    uint8_t version;
+    uint8_t ttl;
+    uint16_t checksum;
+    uint16_t type;
+    uint16_t length;
+};
+
+/* +++++++++++++++ Ethernet header (IEEE 802.3) +++++++++++++++ */
+struct ndpi_ethhdr
+{
+    uint8_t h_dest[6];       /* destination eth addr */
+    uint8_t h_source[6];     /* source ether addr    */
+    uint16_t h_proto;      /* data length (<= 1500) or type ID proto (>=1536) */
+};
+
+/* +++++++++++++++ ARP header +++++++++++++++ */
+struct ndpi_arphdr 
+{   
+    uint16_t ar_hrd;/* Format of hardware address.  */
+    uint16_t ar_pro;/* Format of protocol address.  */
+    uint8_t  ar_hln;/* Length of hardware address.  */
+    uint8_t  ar_pln;/* Length of protocol address.  */
+    uint16_t ar_op;/* ARP opcode (command).  */
+    uint8_t arp_sha[6];/* sender hardware address */
+    uint32_t arp_spa;/* sender protocol address */
+    uint8_t arp_tha[6];/* target hardware address */
+    uint32_t arp_tpa;/* target protocol address */
+};
+
+/* +++++++++++++++ DHCP header +++++++++++++++ */
+struct ndpi_dhcphdr {
+    uint8_t      msgType;
+    uint8_t      htype;
+    uint8_t      hlen;
+    uint8_t      hops;
+    uint32_t     xid;/* 4 */
+    uint16_t     secs;/* 8 */
+    uint16_t     flags;
+    uint32_t     ciaddr;/* 12 */
+    uint32_t     yiaddr;/* 16 */
+    uint32_t     siaddr;/* 20 */
+    uint32_t     giaddr;/* 24 */
+    uint8_t      chaddr[16]; /* 28 */
+    uint8_t      sname[64]; /* 44 */
+    uint8_t      file[128]; /* 108 */
+    uint32_t     magic; /* 236 */
+    uint8_t      options[308];
+};
+
+/* +++++++++++++++ MDNS rsp header +++++++++++++++ */
+struct ndpi_mdns_rsp_entry {
+    uint16_t rsp_type, rsp_class;
+    uint32_t ttl;
+    uint16_t data_len;
+};
+
+/* +++++++++++++++++++ LLC header (IEEE 802.2) ++++++++++++++++ */
+struct ndpi_snap_extension
+{
+    uint16_t   oui;
+    uint8_t    oui2;
+    uint16_t   proto_ID;
+};
+
+struct ndpi_llc_header_snap
+{
+    uint8_t    dsap;
+    uint8_t    ssap;
+    uint8_t    ctrl;
+    struct ndpi_snap_extension snap;
+};
+
+/* ++++++++++ RADIO TAP header (for IEEE 802.11) +++++++++++++ */
+struct ndpi_radiotap_header
+{
+    uint8_t  version;         /* set to 0 */
+    uint8_t  pad;
+    uint16_t len;
+    uint32_t present;
+    uint64_t MAC_timestamp;
+    uint8_t flags;
+};
+
+/* ++++++++++++ Wireless header (IEEE 802.11) ++++++++++++++++ */
+struct ndpi_wifi_header
+{
+    uint16_t fc;
+    uint16_t duration;
+    uint8_t rcvr[6];
+    uint8_t trsm[6];
+    uint8_t dest[6];
+    uint16_t seq_ctrl;
+    /* uint64_t ccmp - for data encryption only - check fc.flag */
+};
+
+/* +++++++++++++++++++++++ MPLS header +++++++++++++++++++++++ */
+struct ndpi_mpls_header
+{
+    uint32_t ttl:8, s:1, exp:3, label:20;
+};
+
+extern union mpls {
+  uint32_t u32;
+  struct ndpi_mpls_header mpls;
+} mpls;
+
+/* ++++++++++++++++++++++++ IP header ++++++++++++++++++++++++ */
+struct ndpi_iphdr {
+    uint8_t ihl:4, version:4;
+    uint8_t tos;
+    uint16_t tot_len;
+    uint16_t id;
+    uint16_t frag_off;
+    uint8_t ttl;
+    uint8_t protocol;
+    uint16_t check;
+    uint32_t saddr;
+    uint32_t daddr;
+};
+
+/* +++++++++++++++++++++++ IPv6 header +++++++++++++++++++++++ */
+/* rfc3542 */
+struct ndpi_in6_addr {
+    union {
+        uint8_t   u6_addr8[16];
+        uint16_t  u6_addr16[8];
+        uint32_t  u6_addr32[4];
+        uint64_t  u6_addr64[2];
+    } u6_addr;  /* 128-bit IP6 address */
+};
+
+struct ndpi_ip6_hdrctl {
+    uint32_t ip6_un1_flow;
+    uint16_t ip6_un1_plen;
+    uint8_t ip6_un1_nxt;
+    uint8_t ip6_un1_hlim;
+};
+
+struct ndpi_ipv6hdr {
+    struct ndpi_ip6_hdrctl ip6_hdr;
+    struct ndpi_in6_addr ip6_src;
+    struct ndpi_in6_addr ip6_dst;
+};
+
+/* +++++++++++++++++++++++ TCP header +++++++++++++++++++++++ */
+struct ndpi_tcphdr
+{
+    uint16_t source;
+    uint16_t dest;
+    uint32_t seq;
+    uint32_t ack_seq;
+    uint16_t res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1;
+    uint16_t window;
+    uint16_t check;
+    uint16_t urg_ptr;
+};
+
+/* +++++++++++++++++++++++ UDP header +++++++++++++++++++++++ */
+struct ndpi_udphdr
+{
+    uint16_t source;
+    uint16_t dest;
+    uint16_t len;
+    uint16_t check;
+};
+
+struct ndpi_dns_packet_header {
+    uint16_t tr_id;
+    uint16_t flags;
+    uint16_t num_queries;
+    uint16_t num_answers;
+    uint16_t authority_rrs;
+    uint16_t additional_rrs;
+};
+
+typedef union
+{
+    uint32_t ipv4;
+    uint8_t ipv4_uint8_t[4];
+    struct ndpi_in6_addr ipv6;
+} ndpi_ip_addr_t;
+
+
+/* +++++++++++++++++++++++ ICMP header +++++++++++++++++++++++ */
+struct ndpi_icmphdr {
+    uint8_t type;/* message type */
+    uint8_t code;/* type sub-code */
+    uint16_t checksum;
+    union {
+        struct {
+            uint16_t id;
+            uint16_t sequence;
+        } echo; /* echo datagram */
+
+        uint32_t gateway; /* gateway address */
+        struct {
+            uint16_t _unused;
+            uint16_t mtu;
+        } frag;/* path mtu discovery */
+    } un;
+};
+
+/* +++++++++++++++++++++++ ICMP6 header +++++++++++++++++++++++ */
+struct ndpi_icmp6hdr {
+  uint8_t     icmp6_type;   /* type field */
+  uint8_t     icmp6_code;   /* code field */
+  uint16_t    icmp6_cksum;  /* checksum field */
+  union {
+    uint32_t  icmp6_un_data32[1]; /* type-specific field */
+    uint16_t  icmp6_un_data16[2]; /* type-specific field */
+    uint8_t   icmp6_un_data8[4];  /* type-specific field */
+  } icmp6_dataun;
+};
+
+/* +++++++++++++++++++++++ VXLAN header +++++++++++++++++++++++ */
+struct ndpi_vxlanhdr {
+    uint16_t flags;
+    uint16_t groupPolicy;
+    uint32_t vni;
+};
+
+struct tinc_cache_entry {
+    uint32_t src_address;
+    uint32_t dst_address;
+    uint16_t dst_port;
+};
+"""
+
+cc_ndpi_id_struct = """
+struct ndpi_id_struct {
+    /** detected_protocol_bitmask:
+        access this bitmask to find out whether an id has used skype or not
+        if a flag is set here, it will not be reset
+        to compare this, use:
+    **/
+    NDPI_PROTOCOL_BITMASK detected_protocol_bitmask;
+    /* NDPI_PROTOCOL_RTSP */
+    ndpi_ip_addr_t rtsp_ip_address;
+    /* NDPI_PROTOCOL_YAHOO */
+    uint32_t yahoo_video_lan_timer;
+    /* NDPI_PROTOCOL_IRC_MAXPORT % 2 must be 0 */
+    /* NDPI_PROTOCOL_IRC */
+    #define NDPI_PROTOCOL_IRC_MAXPORT 8
+    uint16_t irc_port[NDPI_PROTOCOL_IRC_MAXPORT];
+    uint32_t last_time_port_used[NDPI_PROTOCOL_IRC_MAXPORT];
+    uint32_t irc_ts;
+    /* NDPI_PROTOCOL_GNUTELLA */
+    uint32_t gnutella_ts;
+    /* NDPI_PROTOCOL_BATTLEFIELD */
+    uint32_t battlefield_ts;
+    /* NDPI_PROTOCOL_THUNDER */
+    uint32_t thunder_ts;
+    /* NDPI_PROTOCOL_RTSP */
+    uint32_t rtsp_timer;
+    /* NDPI_PROTOCOL_OSCAR */
+    uint32_t oscar_last_safe_access_time;
+    /* NDPI_PROTOCOL_ZATTOO */
+    uint32_t zattoo_ts;
+    /* NDPI_PROTOCOL_UNENCRYPTED_JABBER */
+    uint32_t jabber_stun_or_ft_ts;
+    /* NDPI_PROTOCOL_DIRECTCONNECT */
+    uint32_t directconnect_last_safe_access_time;
+    /* NDPI_PROTOCOL_SOULSEEK */
+    uint32_t soulseek_last_safe_access_time;
+    /* NDPI_PROTOCOL_DIRECTCONNECT */
+    uint16_t detected_directconnect_port;
+    uint16_t detected_directconnect_udp_port;
+    uint16_t detected_directconnect_ssl_port;
+    /* NDPI_PROTOCOL_BITTORRENT */
+    #define NDPI_BT_PORTS 8
+    uint16_t bt_port_t[NDPI_BT_PORTS];
+    uint16_t bt_port_u[NDPI_BT_PORTS];
+    /* NDPI_PROTOCOL_UNENCRYPTED_JABBER */
+    #define JABBER_MAX_STUN_PORTS 6
+    uint16_t jabber_voice_stun_port[JABBER_MAX_STUN_PORTS];
+    uint16_t jabber_file_transfer_port[2];
+    /* NDPI_PROTOCOL_GNUTELLA */
+    uint16_t detected_gnutella_port;
+    /* NDPI_PROTOCOL_GNUTELLA */
+    uint16_t detected_gnutella_udp_port1;
+    uint16_t detected_gnutella_udp_port2;
+    /* NDPI_PROTOCOL_SOULSEEK */
+    uint16_t soulseek_listen_port;
+    /* NDPI_PROTOCOL_IRC */
+    uint8_t irc_number_of_port;
+    /* NDPI_PROTOCOL_OSCAR */
+    uint8_t oscar_ssl_session_id[33];  
+    /* NDPI_PROTOCOL_UNENCRYPTED_JABBER */
+    uint8_t jabber_voice_stun_used_ports;
+    /* NDPI_PROTOCOL_SIP */
+    /* NDPI_PROTOCOL_YAHOO */
+    uint32_t yahoo_video_lan_dir:1;
+    /* NDPI_PROTOCOL_YAHOO */
+    uint32_t yahoo_conf_logged_in:1;
+    uint32_t yahoo_voice_conf_logged_in:1;
+    /* NDPI_PROTOCOL_RTSP */
+    uint32_t rtsp_ts_set:1;
+};
+"""
+cc_ndpi_flow_tcp_struct = """
+struct ndpi_flow_tcp_struct {
+    /* NDPI_PROTOCOL_MAIL_SMTP */
+    uint16_t smtp_command_bitmask;
+    /* NDPI_PROTOCOL_MAIL_POP */
+    uint16_t pop_command_bitmask;
+    /* NDPI_PROTOCOL_QQ */
+    uint16_t qq_nxt_len;
+    /* NDPI_PROTOCOL_WHATSAPP */
+    uint8_t wa_matched_so_far;
+    /* NDPI_PROTOCOL_TDS */
+    uint8_t tds_login_version;
+
+    /* NDPI_PROTOCOL_IRC */
+    uint8_t irc_stage;
+    uint8_t irc_port;
+
+    /* NDPI_PROTOCOL_H323 */
+    uint8_t h323_valid_packets;
+
+    /* NDPI_PROTOCOL_GNUTELLA */
+    uint8_t gnutella_msg_id[3];
+
+    /* NDPI_PROTOCOL_IRC */
+    uint32_t irc_3a_counter:3;
+    uint32_t irc_stage2:5;
+    uint32_t irc_direction:2;
+    uint32_t irc_0x1000_full:1;
+
+    /* NDPI_PROTOCOL_SOULSEEK */
+    uint32_t soulseek_stage:2;
+
+    /* NDPI_PROTOCOL_TDS */
+    uint32_t tds_stage:3;
+
+    /* NDPI_PROTOCOL_USENET */
+    uint32_t usenet_stage:2;
+
+    /* NDPI_PROTOCOL_IMESH */
+    uint32_t imesh_stage:4;
+
+    /* NDPI_PROTOCOL_HTTP */
+    uint32_t http_setup_dir:2;
+    uint32_t http_stage:2;
+    uint32_t http_empty_line_seen:1;
+    uint32_t http_wait_for_retransmission:1;
+
+    /* NDPI_PROTOCOL_GNUTELLA */
+    uint32_t gnutella_stage:2;		       // 0 - 2
+    /* NDPI_CONTENT_MMS */
+    uint32_t mms_stage:2;
+    /* NDPI_PROTOCOL_YAHOO */
+    uint32_t yahoo_sip_comm:1;
+    uint32_t yahoo_http_proxy_stage:2;
+
+    /* NDPI_PROTOCOL_MSN */
+    uint32_t msn_stage:3;
+    uint32_t msn_ssl_ft:2;
+
+    /* NDPI_PROTOCOL_SSH */
+    uint32_t ssh_stage:3;
+
+    /* NDPI_PROTOCOL_VNC */
+    uint32_t vnc_stage:2;			// 0 - 3
+
+    /* NDPI_PROTOCOL_TELNET */
+    uint32_t telnet_stage:2;			// 0 - 2
+    void* tls_srv_cert_fingerprint_ctx;
+
+    /* NDPI_PROTOCOL_TLS */
+    uint8_t tls_seen_client_cert:1,
+    tls_seen_server_cert:1,
+    tls_seen_certificate:1,
+    tls_srv_cert_fingerprint_found:1,
+    tls_srv_cert_fingerprint_processed:1,
+    tls_stage:2, _pad:1; // 0 - 5
+    int16_t tls_record_offset, tls_fingerprint_len; /* Need to be signed */
+    uint8_t tls_sha1_certificate_fingerprint[20];
+
+    /* NDPI_PROTOCOL_POSTGRES */
+    uint32_t postgres_stage:3;
+
+    /* NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK */
+    uint32_t ddlink_server_direction:1;
+    uint32_t seen_syn:1;
+    uint32_t seen_syn_ack:1;
+    uint32_t seen_ack:1;
+
+    /* NDPI_PROTOCOL_ICECAST */
+    uint32_t icecast_stage:1;
+
+    /* NDPI_PROTOCOL_DOFUS */
+    uint32_t dofus_stage:1;
+
+    /* NDPI_PROTOCOL_FIESTA */
+    uint32_t fiesta_stage:2;
+
+    /* NDPI_PROTOCOL_WORLDOFWARCRAFT */
+    uint32_t wow_stage:2;
+
+    /* NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV */
+    uint32_t veoh_tv_stage:2;
+
+    /* NDPI_PROTOCOL_SHOUTCAST */
+    uint32_t shoutcast_stage:2;
+
+    /* NDPI_PROTOCOL_RTP */
+    uint32_t rtp_special_packets_seen:1;
+
+    /* NDPI_PROTOCOL_MAIL_POP */
+    uint32_t mail_pop_stage:2;
+
+    /* NDPI_PROTOCOL_MAIL_IMAP */
+    uint32_t mail_imap_stage:3, mail_imap_starttls:2;
+
+    /* NDPI_PROTOCOL_SKYPE */
+    uint8_t skype_packet_id;
+
+    /* NDPI_PROTOCOL_CITRIX */
+    uint8_t citrix_packet_id;
+    /* NDPI_PROTOCOL_LOTUS_NOTES */
+    uint8_t lotus_notes_packet_id;
+
+    /* NDPI_PROTOCOL_TEAMVIEWER */
+    uint8_t teamviewer_stage;
+
+    /* NDPI_PROTOCOL_ZMQ */
+    uint8_t prev_zmq_pkt_len;
+    uint8_t prev_zmq_pkt[10];
+
+    /* NDPI_PROTOCOL_PPSTREAM */
+    uint32_t ppstream_stage:3;
+
+    /* NDPI_PROTOCOL_MEMCACHED */
+    uint8_t memcached_matches;
+
+    /* NDPI_PROTOCOL_NEST_LOG_SINK */
+    uint8_t nest_log_sink_matches;
+};
+"""
+
+cc_ndpi_flow_udp_struct = """
+struct ndpi_flow_udp_struct {
+    /* NDPI_PROTOCOL_BATTLEFIELD */
+    uint32_t battlefield_msg_id;
+    /* NDPI_PROTOCOL_SNMP */
+    uint32_t snmp_msg_id;
+    /* NDPI_PROTOCOL_BATTLEFIELD */
+    uint32_t battlefield_stage:3;
+    /* NDPI_PROTOCOL_SNMP */
+    uint32_t snmp_stage:2;
+    /* NDPI_PROTOCOL_PPSTREAM */
+    uint32_t ppstream_stage:3;		  // 0 - 7
+    /* NDPI_PROTOCOL_HALFLIFE2 */
+    uint32_t halflife2_stage:2;		  // 0 - 2
+    /* NDPI_PROTOCOL_TFTP */
+    uint32_t tftp_stage:1;
+    /* NDPI_PROTOCOL_AIMINI */
+    uint32_t aimini_stage:5;
+    /* NDPI_PROTOCOL_XBOX */
+    uint32_t xbox_stage:1;
+    /* NDPI_PROTOCOL_WINDOWS_UPDATE */
+    uint32_t wsus_stage:1;
+    /* NDPI_PROTOCOL_SKYPE */
+    uint8_t skype_packet_id;
+    /* NDPI_PROTOCOL_TEAMVIEWER */
+    uint8_t teamviewer_stage;
+    /* NDPI_PROTOCOL_EAQ */
+    uint8_t eaq_pkt_id;
+    uint32_t eaq_sequence;
+    /* NDPI_PROTOCOL_RX */
+    uint32_t rx_conn_epoch;
+    uint32_t rx_conn_id;
+    /* NDPI_PROTOCOL_MEMCACHED */
+    uint8_t memcached_matches;
+    /* NDPI_PROTOCOL_WIREGUARD */
+    uint8_t wireguard_stage;
+    uint32_t wireguard_peer_index[2];
+};
+"""
+
+cc_ndpi_int_one_line_struct = """
+struct ndpi_int_one_line_struct {
+    const uint8_t *ptr;
+    uint16_t len;
+};
+"""
+
+cc_ndpi_packet_struct_stack = """
+struct ndpi_packet_struct_stack {
+    uint8_t detected_subprotocol_stack[2];
+    uint16_t protocol_stack_info;
+};
+struct ndpi_flow_struct_stack {
+    uint16_t detected_protocol_stack[2];
+    uint16_t protocol_stack_info;
+};
+"""
+
+cc_ndpi_packet_struct = """
+struct ndpi_packet_struct {
+    const struct ndpi_iphdr *iph;
+    const struct ndpi_ipv6hdr *iphv6;
+    const struct ndpi_tcphdr *tcp;
+    const struct ndpi_udphdr *udp;
+    const uint8_t *generic_l4_ptr;	/* is set only for non tcp-udp traffic */
+    const uint8_t *payload;
+    uint32_t tick_timestamp;
+    uint64_t tick_timestamp_l;
+    struct ndpi_packet_struct_stack ndpi_packet_stack;
+    struct ndpi_int_one_line_struct line[64];
+    /* HTTP headers */
+    struct ndpi_int_one_line_struct host_line;
+    struct ndpi_int_one_line_struct forwarded_line;
+    struct ndpi_int_one_line_struct referer_line;
+    struct ndpi_int_one_line_struct content_line;
+    struct ndpi_int_one_line_struct accept_line;
+    struct ndpi_int_one_line_struct user_agent_line;
+    struct ndpi_int_one_line_struct http_url_name;
+    struct ndpi_int_one_line_struct http_encoding;
+    struct ndpi_int_one_line_struct http_transfer_encoding;
+    struct ndpi_int_one_line_struct http_contentlen;
+    struct ndpi_int_one_line_struct http_cookie;
+    struct ndpi_int_one_line_struct http_origin;
+    struct ndpi_int_one_line_struct http_x_session_type;
+    struct ndpi_int_one_line_struct server_line;
+    struct ndpi_int_one_line_struct http_method;
+    struct ndpi_int_one_line_struct http_response; /* the first "word" in this pointer is the response code in the 
+                                                      packet (200, etc) */
+    uint8_t http_num_headers; /* number of found (valid) header lines in HTTP request or response */
+    uint16_t l3_packet_len;
+    uint16_t l4_packet_len;
+    uint16_t payload_packet_len;
+    uint16_t actual_payload_len;
+    uint16_t num_retried_bytes;
+    uint16_t parsed_lines;
+    uint16_t parsed_unix_lines;
+    uint16_t empty_line_position;
+    uint8_t tcp_retransmission;
+    uint8_t l4_protocol;
+    uint8_t tls_certificate_detected:4, tls_certificate_num_checks:4;
+    uint8_t packet_lines_parsed_complete:1,
+    packet_direction:1, empty_line_position_set:1, pad:5;
+};
+struct ndpi_detection_module_struct;
+struct ndpi_flow_struct;
+struct ndpi_call_function_struct {
+    NDPI_PROTOCOL_BITMASK detection_bitmask;
+    NDPI_PROTOCOL_BITMASK excluded_protocol_bitmask;
+    uint32_t ndpi_selection_bitmask;
+    void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
+    uint8_t detection_feature;
+};
+struct ndpi_subprotocol_conf_struct {
+    void (*func) (struct ndpi_detection_module_struct *, char *attr, char *value, int protocol_id);
+};
+
+typedef struct {
+    uint16_t port_low, port_high;
+} ndpi_port_range;
+
+typedef enum {
+    NDPI_PROTOCOL_SAFE = 0,              /* Surely doesn't provide risks for the network. (e.g., a news site) */
+    NDPI_PROTOCOL_ACCEPTABLE,            /* Probably doesn't provide risks, but could be malicious (e.g., Dropbox) */
+    NDPI_PROTOCOL_FUN,                   /* Pure fun protocol, which may be prohibited by the user policy (e.g., Netflix) */
+    NDPI_PROTOCOL_UNSAFE,                /* Probably provides risks, but could be a normal traffic. Unencrypted protocols with clear pass should be here (e.g., telnet) */
+    NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, /* Possibly dangerous (ex. Tor). */
+    NDPI_PROTOCOL_DANGEROUS,             /* Surely is dangerous (ex. smbv1). Be prepared to troubles */
+    NDPI_PROTOCOL_TRACKER_ADS,           /* Trackers, Advertisements... */
+    NDPI_PROTOCOL_UNRATED                /* No idea, not implemented or impossible to classify */
+} ndpi_protocol_breed_t;
+
+#define NUM_BREEDS 8
+
+/* Abstract categories to group the protocols. */
+typedef enum {
+    NDPI_PROTOCOL_CATEGORY_UNSPECIFIED = 0,   /* For general services and unknown protocols */
+    NDPI_PROTOCOL_CATEGORY_MEDIA,             /* Multimedia and streaming */
+    NDPI_PROTOCOL_CATEGORY_VPN,               /* Virtual Private Networks */
+    NDPI_PROTOCOL_CATEGORY_MAIL,              /* Protocols to send/receive/sync emails */
+    NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER,     /* AFS/NFS and similar protocols */
+    NDPI_PROTOCOL_CATEGORY_WEB,               /* Web/mobile protocols and services */
+    NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK,    /* Social networks */
+    NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,       /* Download, FTP, file transfer/sharing */
+    NDPI_PROTOCOL_CATEGORY_GAME,              /* Online games */
+    NDPI_PROTOCOL_CATEGORY_CHAT,              /* Instant messaging */
+    NDPI_PROTOCOL_CATEGORY_VOIP,              /* Real-time communications and conferencing */
+    NDPI_PROTOCOL_CATEGORY_DATABASE,          /* Protocols for database communication */
+    NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,     /* Remote access and control */
+    NDPI_PROTOCOL_CATEGORY_CLOUD,             /* Online cloud services */
+    NDPI_PROTOCOL_CATEGORY_NETWORK,           /* Network infrastructure protocols */
+    NDPI_PROTOCOL_CATEGORY_COLLABORATIVE,     /* Software for collaborative development, including Webmail */
+    NDPI_PROTOCOL_CATEGORY_RPC,               /* High level network communication protocols */
+    NDPI_PROTOCOL_CATEGORY_STREAMING,         /* Streaming protocols */
+    NDPI_PROTOCOL_CATEGORY_SYSTEM_OS,         /* System/Operating System level applications */
+    NDPI_PROTOCOL_CATEGORY_SW_UPDATE,         /* Software update */
+
+    /* See #define NUM_CUSTOM_CATEGORIES */
+    NDPI_PROTOCOL_CATEGORY_CUSTOM_1,          /* User custom category 1 */
+    NDPI_PROTOCOL_CATEGORY_CUSTOM_2,          /* User custom category 2 */
+    NDPI_PROTOCOL_CATEGORY_CUSTOM_3,          /* User custom category 3 */
+    NDPI_PROTOCOL_CATEGORY_CUSTOM_4,          /* User custom category 4 */
+    NDPI_PROTOCOL_CATEGORY_CUSTOM_5,          /* User custom category 5 */
+
+    /* Further categories... */
+    NDPI_PROTOCOL_CATEGORY_MUSIC,
+    NDPI_PROTOCOL_CATEGORY_VIDEO,
+    NDPI_PROTOCOL_CATEGORY_SHOPPING,
+    NDPI_PROTOCOL_CATEGORY_PRODUCTIVITY,
+    NDPI_PROTOCOL_CATEGORY_FILE_SHARING,
+
+    /* Some custom categories */
+    CUSTOM_CATEGORY_MINING           = 99,
+    CUSTOM_CATEGORY_MALWARE          = 100,
+    CUSTOM_CATEGORY_ADVERTISEMENT    = 101,
+    CUSTOM_CATEGORY_BANNED_SITE      = 102,
+    CUSTOM_CATEGORY_SITE_UNAVAILABLE = 103,
+    CUSTOM_CATEGORY_ALLOWED_SITE     = 104,
+    /*
+        The category below is used to track communications made by
+        security applications (e.g. sophosxl.net, spamhaus.org)
+        to track malware, spam etc.
+    */
+    CUSTOM_CATEGORY_ANTIMALWARE      = 105,
+    /*
+        IMPORTANT
+        Please keep in sync with
+        static const char* categories[] = { ..}
+        in ndpi_main.c
+    */
+    NDPI_PROTOCOL_NUM_CATEGORIES
+    /*
+        NOTE: Keep this as last member
+        Unused as value but useful to getting the number of elements
+        in this datastructure
+    */
+} ndpi_protocol_category_t;
+
+typedef enum {
+    ndpi_pref_direction_detect_disable = 0,
+    ndpi_pref_disable_metadata_export,
+} ndpi_detection_preference;
+
+/* ntop extensions */
+typedef struct ndpi_proto_defaults {
+    char *protoName;
+    ndpi_protocol_category_t protoCategory;
+    uint8_t can_have_a_subprotocol;
+    uint16_t protoId, protoIdx;
+    uint16_t master_tcp_protoId[2], master_udp_protoId[2]; /* The main protocols on which this sub-protocol sits on */
+    ndpi_protocol_breed_t protoBreed;
+    void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
+} ndpi_proto_defaults_t;
+
+typedef struct ndpi_default_ports_tree_node {
+    ndpi_proto_defaults_t *proto;
+    uint8_t customUserProto;
+    uint16_t default_port;
+} ndpi_default_ports_tree_node_t;
+
+typedef struct _ndpi_automa {
+    void *ac_automa; /* Real type is AC_AUTOMATA_t */
+    uint8_t ac_automa_finalized;
+} ndpi_automa;
+
+typedef struct ndpi_proto {
+    /*
+        Note
+        below we do not use ndpi_protocol_id_t as users can define their own
+        custom protocols and thus the typedef could be too short in size.
+    */
+    uint16_t master_protocol /* e.g. HTTP */, app_protocol /* e.g. FaceBook */;
+    ndpi_protocol_category_t category;
+} ndpi_protocol;
+
+#define NUM_CUSTOM_CATEGORIES      5
+#define CUSTOM_CATEGORY_LABEL_LEN 32
+
+typedef enum {
+    NDPI_LOG_ERROR,
+    NDPI_LOG_TRACE,
+    NDPI_LOG_DEBUG,
+    NDPI_LOG_DEBUG_EXTRA
+} ndpi_log_level_t;
+
+
+struct ndpi_detection_module_struct {
+    NDPI_PROTOCOL_BITMASK detection_bitmask;
+    NDPI_PROTOCOL_BITMASK generic_http_packet_bitmask;
+    uint32_t current_ts;
+    uint32_t ticks_per_second;
+    char custom_category_labels[NUM_CUSTOM_CATEGORIES][CUSTOM_CATEGORY_LABEL_LEN];
+    /* callback function buffer */
+    struct ndpi_call_function_struct callback_buffer[250];
+    uint32_t callback_buffer_size;
+    struct ndpi_call_function_struct callback_buffer_tcp_no_payload[250];
+    uint32_t callback_buffer_size_tcp_no_payload;
+    struct ndpi_call_function_struct callback_buffer_tcp_payload[250];
+    uint32_t callback_buffer_size_tcp_payload;
+    struct ndpi_call_function_struct callback_buffer_udp[250];
+    uint32_t callback_buffer_size_udp;
+    struct ndpi_call_function_struct callback_buffer_non_tcp_udp[250];
+    uint32_t callback_buffer_size_non_tcp_udp;
+    ndpi_default_ports_tree_node_t *tcpRoot, *udpRoot;
+    ndpi_log_level_t ndpi_log_level; /* default error */
+    /* misc parameters */
+    uint32_t tcp_max_retransmission_window_size;
+    uint32_t directconnect_connection_ip_tick_timeout;
+    /* subprotocol registration handler */
+    struct ndpi_subprotocol_conf_struct subprotocol_conf[250];
+    unsigned ndpi_num_supported_protocols;
+    unsigned ndpi_num_custom_protocols;
+    /* HTTP/DNS/HTTPS host matching */
+    ndpi_automa host_automa,                     /* Used for DNS/HTTPS */
+    content_automa,                            /* Used for HTTP subprotocol_detection */
+    subprotocol_automa,                        /* Used for HTTP subprotocol_detection */
+    bigrams_automa, impossible_bigrams_automa; /* TOR */
+    /* IMPORTANT: please update ndpi_finalize_initalization() whenever you add a new automa */
+
+    struct {
+        ndpi_automa hostnames, hostnames_shadow;
+        void *ipAddresses, *ipAddresses_shadow; /* Patricia */
+        uint8_t categories_loaded;
+    } custom_categories;
+
+    /* IP-based protocol detection */
+    void *protocols_ptree;
+
+    /* irc parameters */
+    uint32_t irc_timeout;
+    /* gnutella parameters */
+    uint32_t gnutella_timeout;
+    /* battlefield parameters */
+    uint32_t battlefield_timeout;
+    /* thunder parameters */
+    uint32_t thunder_timeout;
+    /* SoulSeek parameters */
+    uint32_t soulseek_connection_ip_tick_timeout;
+    /* rtsp parameters */
+    uint32_t rtsp_connection_timeout;
+    /* tvants parameters */
+    uint32_t tvants_connection_timeout;
+    /* rstp */
+    uint32_t orb_rstp_ts_timeout;
+    /* yahoo */
+    uint8_t yahoo_detect_http_connections;
+    uint32_t yahoo_lan_video_timeout;
+    uint32_t zattoo_connection_timeout;
+    uint32_t jabber_stun_timeout;
+    uint32_t jabber_file_transfer_timeout;
+    uint8_t ip_version_limit;
+    /* NDPI_PROTOCOL_BITTORRENT */
+    struct hash_ip4p_table *bt_ht;
+    struct hash_ip4p_table *bt6_ht;
+
+    /* BT_ANNOUNCE */
+    struct bt_announce *bt_ann;
+    int    bt_ann_len;
+
+    /* NDPI_PROTOCOL_OOKLA */
+    struct ndpi_lru_cache *ookla_cache;
+    /* NDPI_PROTOCOL_TINC */
+    struct cache *tinc_cache;
+    /* NDPI_PROTOCOL_STUN and subprotocols */
+    struct ndpi_lru_cache *stun_cache;
+    ndpi_proto_defaults_t proto_defaults[512];
+    uint8_t direction_detect_disable:1, /* disable internal detection of packet direction */
+    disable_metadata_export:1   /* No metadata is exported */
+    ;
+    void *hyperscan; /* Intel Hyperscan */
+};
+
+#define NDPI_CIPHER_SAFE                        0
+#define NDPI_CIPHER_WEAK                        1
+#define NDPI_CIPHER_INSECURE                    2
+
+typedef enum {
+    ndpi_cipher_safe = NDPI_CIPHER_SAFE,
+    ndpi_cipher_weak = NDPI_CIPHER_WEAK,
+    ndpi_cipher_insecure = NDPI_CIPHER_INSECURE
+} ndpi_cipher_weakness;
+
+struct ndpi_flow_struct {
+  struct ndpi_flow_struct_stack ndpi_flow_stack;
+  /* init parameter, internal used to set up timestamp,... */
+  uint16_t guessed_protocol_id, guessed_host_protocol_id, guessed_category, guessed_header_category;
+  uint8_t l4_proto, protocol_id_already_guessed:1, host_already_guessed:1, init_finished:1, setup_packet_direction:1, packet_direction:1, check_extra_packets:1;
+
+  /*
+    if ndpi_struct->direction_detect_disable == 1
+    tcp sequence number connection tracking
+  */
+  uint32_t next_tcp_seq_nr[2];
+
+  uint8_t max_extra_packets_to_check;
+  uint8_t num_extra_packets_checked;
+  uint8_t num_processed_pkts; /* <= WARNING it can wrap but we do expect people to giveup earlier */
+
+  int (*extra_packets_func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
+
+  /*
+    the tcp / udp / other l4 value union
+    used to reduce the number of bytes for tcp or udp protocol states
+  */
+  union {
+    struct ndpi_flow_tcp_struct tcp;
+    struct ndpi_flow_udp_struct udp;
+  } l4;
+
+  /*
+    Pointer to src or dst that identifies the
+    server of this connection
+  */
+  struct ndpi_id_struct *server_id;
+  /* HTTP host or DNS query */
+  uint8_t host_server_name[256];
+
+  /*
+    This structure below will not not stay inside the protos
+    structure below as HTTP is used by many subprotocols
+    such as FaceBook, Google... so it is hard to know
+    when to use it or not. Thus we leave it outside for the
+    time being.
+  */
+  struct {
+    ndpi_http_method method;
+    char *url, *content_type;
+    uint8_t num_request_headers, num_response_headers;
+    uint8_t request_version; /* 0=1.0 and 1=1.1. Create an enum for this? */
+    uint16_t response_status_code; /* 200, 404, etc. */
+  } http;
+
+  union {
+    /* the only fields useful for nDPI and ntopng */
+    struct {
+      uint8_t num_queries, num_answers, reply_code, is_query;
+      uint16_t query_type, query_class, rsp_type;
+      ndpi_ip_addr_t rsp_addr; /* The first address in a DNS response packet */
+    } dns;
+
+    struct {
+      uint8_t request_code;
+      uint8_t version;
+    } ntp;
+
+    struct {
+      char cname[24], realm[24];
+    } kerberos;
+
+    struct {
+      struct {
+	uint16_t ssl_version;
+	char client_certificate[64], server_certificate[64], server_organization[64];
+	uint32_t notBefore, notAfter;
+	char ja3_client[33], ja3_server[33];
+	uint16_t server_cipher;
+	ndpi_cipher_weakness server_unsafe_cipher;
+      } ssl;
+
+      struct {
+	uint8_t num_udp_pkts, num_processed_pkts, num_binding_requests;
+      } stun;
+
+      /* We can have STUN over SSL/TLS thus they need to live together */
+    } stun_ssl;
+
+    struct {
+      char client_signature[48], server_signature[48];
+      char hassh_client[33], hassh_server[33];
+    } ssh;
+
+    struct {
+      uint8_t last_one_byte_pkt, last_byte;
+    } imo;
+
+    struct {
+      char answer[96];
+    } mdns;
+
+    struct {
+      char version[32];
+    } ubntac2;
+
+    struct {
+      /* Via HTTP User-Agent */
+      uint8_t detected_os[32];
+      /* Via HTTP X-Forwarded-For */
+      uint8_t nat_ip[24];
+    } http;
+
+    struct {
+      /* Bittorrent hash */
+      uint8_t hash[20];
+    } bittorrent;
+
+    struct {
+      char fingerprint[48];
+      char class_ident[48];
+    } dhcp;
+  } protos;
+
+  /*** ALL protocol specific 64 bit variables here ***/
+
+  /* protocols which have marked a connection as this connection cannot be protocol XXX, multiple uint64_t */
+  NDPI_PROTOCOL_BITMASK excluded_protocol_bitmask;
+
+  ndpi_protocol_category_t category;
+
+  /* NDPI_PROTOCOL_REDIS */
+  uint8_t redis_s2d_first_char, redis_d2s_first_char;
+
+  uint16_t packet_counter;		      // can be 0 - 65000
+  uint16_t packet_direction_counter[2];
+  uint16_t byte_counter[2];
+  /* NDPI_PROTOCOL_BITTORRENT */
+  uint8_t bittorrent_stage;		      // can be 0 - 255
+
+  /* NDPI_PROTOCOL_DIRECTCONNECT */
+  uint8_t directconnect_stage:2;	      // 0 - 1
+
+  /* NDPI_PROTOCOL_YAHOO */
+  uint8_t sip_yahoo_voice:1;
+
+  /* NDPI_PROTOCOL_HTTP */
+  uint8_t http_detected:1;
+  uint16_t http_upper_protocol, http_lower_protocol;
+
+  /* NDPI_PROTOCOL_RTSP */
+  uint8_t rtsprdt_stage:2, rtsp_control_flow:1;
+
+  /* NDPI_PROTOCOL_YAHOO */
+  uint8_t yahoo_detection_finished:2;
+
+  /* NDPI_PROTOCOL_ZATTOO */
+  uint8_t zattoo_stage:3;
+
+  /* NDPI_PROTOCOL_QQ */
+  uint8_t qq_stage:3;
+
+  /* NDPI_PROTOCOL_THUNDER */
+  uint8_t thunder_stage:2;		        // 0 - 3
+
+  /* NDPI_PROTOCOL_OSCAR */
+  uint8_t oscar_ssl_voice_stage:3, oscar_video_voice:1;
+
+  /* NDPI_PROTOCOL_FLORENSIA */
+  uint8_t florensia_stage:1;
+
+  /* NDPI_PROTOCOL_SOCKS */
+  uint8_t socks5_stage:2, socks4_stage:2;      // 0 - 3
+
+  /* NDPI_PROTOCOL_EDONKEY */
+  uint8_t edonkey_stage:2;	                // 0 - 3
+
+  /* NDPI_PROTOCOL_FTP_CONTROL */
+  uint8_t ftp_control_stage:2;
+
+  /* NDPI_PROTOCOL_RTMP */
+  uint8_t rtmp_stage:2;
+
+  /* NDPI_PROTOCOL_PANDO */
+  uint8_t pando_stage:3;
+
+  /* NDPI_PROTOCOL_STEAM */
+  uint16_t steam_stage:3, steam_stage1:3, steam_stage2:2, steam_stage3:2;
+
+  /* NDPI_PROTOCOL_PPLIVE */
+  uint8_t pplive_stage1:3, pplive_stage2:2, pplive_stage3:2;
+
+  /* NDPI_PROTOCOL_STARCRAFT */
+  uint8_t starcraft_udp_stage : 3;	// 0-7
+
+  /* NDPI_PROTOCOL_OPENVPN */
+  uint8_t ovpn_session_id[8];
+  uint8_t ovpn_counter;
+
+  /* NDPI_PROTOCOL_TINC */
+  uint8_t tinc_state;
+  struct tinc_cache_entry tinc_cache_entry;
+
+  /* NDPI_PROTOCOL_CSGO */
+  uint8_t csgo_strid[18],csgo_state,csgo_s2;
+  uint32_t csgo_id2;
+
+  /* NDPI_PROTOCOL_1KXUN || NDPI_PROTOCOL_IQIYI */
+  uint16_t kxun_counter, iqiyi_counter;
+
+  /* internal structures to save functions calls */
+  struct ndpi_packet_struct packet;
+  struct ndpi_flow_struct *flow;
+  struct ndpi_id_struct *src;
+  struct ndpi_id_struct *dst;
+};
+typedef struct {
+    char *string_to_match, *string2_to_match, *pattern_to_match, *proto_name;
+    int protocol_id;
+    ndpi_protocol_category_t protocol_category;
+    ndpi_protocol_breed_t protocol_breed;
+} ndpi_protocol_match;
+
+typedef struct {
+    char *string_to_match, *hyperscan_string_to_match;
+    ndpi_protocol_category_t protocol_category;
+} ndpi_category_match;
+
+typedef struct {
+    uint32_t network;
+    uint8_t cidr;
+    uint8_t value;
+} ndpi_network;
+
+typedef uint32_t ndpi_init_prefs;
+
+typedef enum 
+{
+    ndpi_no_prefs = 0,
+    ndpi_dont_load_tor_hosts,
+} ndpi_prefs;
+
+typedef struct {
+    int protocol_id;
+    ndpi_protocol_category_t protocol_category;
+    ndpi_protocol_breed_t protocol_breed;
+} ndpi_protocol_match_result;
+
+#define DEFAULT_SERIES_LEN  64
+#define MAX_SERIES_LEN      512
+#define MIN_SERIES_LEN      8
+"""
+
+cc_ndpi_apis = """
+struct ndpi_detection_module_struct *ndpi_init_detection_module(void);
+void *memset(void *str, int c, size_t n);
+void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct, 
+                                          const NDPI_PROTOCOL_BITMASK * detection_bitmask);
+ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct,
+                                            struct ndpi_flow_struct *flow,
+                                            const unsigned char *packet,
+                                            const unsigned short packetlen,
+                                            const uint64_t current_tick,
+                                            struct ndpi_id_struct *src,
+                                            struct ndpi_id_struct *dst);
+ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_struct,
+                                    struct ndpi_flow_struct *flow,
+                                    uint8_t enable_guess,
+                                    uint8_t *protocol_was_guessed);
+
+void * ndpi_malloc(size_t size);
+void   ndpi_free(void *ptr);
+void * ndpi_flow_malloc(size_t size);
+void  ndpi_flow_free(void *ptr);
+void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_struct);
+char* ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol proto, char *buf, unsigned buf_len);
+const char* ndpi_category_get_name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol_category_t category);
+char* ndpi_revision(void);
+void ndpi_finalize_initalization(struct ndpi_detection_module_struct *ndpi_str);
+"""
+
+
+class NDPI():
+    def __init__(self, libpath=None):
+        self._ffi = cffi.FFI()
+        if libpath is None:
+            self._ndpi = self._ffi.dlopen(dirname(abspath(__file__)) + '/libs/libndpi.so')
+        else:
+            self._ndpi = self._ffi.dlopen(libpath)
+        self._ffi.cdef(cc)
+        self._ffi.cdef(cc_ndpi_network_headers, packed=True)
+        self._ffi.cdef(cc_ndpi_id_struct)
+        self._ffi.cdef(cc_ndpi_flow_tcp_struct, packed=True)
+        self._ffi.cdef(cc_ndpi_flow_udp_struct, packed=True)
+        self._ffi.cdef(cc_ndpi_int_one_line_struct)
+        self._ffi.cdef(cc_ndpi_packet_struct_stack, packed=True)
+        self._ffi.cdef(cc_ndpi_packet_struct)
+        self._ffi.cdef(cc_ndpi_apis)
+        self._mod = self._ndpi.ndpi_init_detection_module()
+        ndpi_revision = self._ffi.string(self._ndpi.ndpi_revision()).decode('utf-8', errors='ignore')
+        if ndpi_revision[:3] >= '3.1':
+            self._ndpi.ndpi_finalize_initalization(self._mod)
+        all = self._ffi.new('NDPI_PROTOCOL_BITMASK*')
+        self._ndpi.memset(self._ffi.cast("char *", all), 0xFF, self._ffi.sizeof("NDPI_PROTOCOL_BITMASK"))
+        self._ndpi.ndpi_set_protocol_detection_bitmask2(self._mod, all)
+        self.SIZEOF_FLOW_STRUCT = self._ffi.sizeof("struct ndpi_flow_struct")
+        self.SIZEOF_ID_STRUCT = self._ffi.sizeof("struct ndpi_id_struct")
+        self.NULL = self._ffi.NULL
+
+    def new_ndpi_flow(self):
+        f = self._ffi.cast('struct ndpi_flow_struct*', self._ndpi.ndpi_flow_malloc(self.SIZEOF_FLOW_STRUCT))
+        self._ndpi.memset(f, 0, self.SIZEOF_FLOW_STRUCT)
+        return f
+
+    def new_ndpi_id(self):
+        i = self._ffi.cast('struct ndpi_id_struct*', self._ndpi.ndpi_malloc(self.SIZEOF_ID_STRUCT))
+        self._ndpi.memset(i, 0, self.SIZEOF_ID_STRUCT)
+        return i
+
+    def ndpi_detection_process_packet(self, flow, packet, packetlen, current_tick, src, dst):
+        return self._ndpi.ndpi_detection_process_packet(self._mod, flow, packet, packetlen, current_tick, src, dst)
+
+    def ndpi_detection_giveup(self, flow):
+        return self._ndpi.ndpi_detection_giveup(self._mod, flow, 1, self._ffi.new("uint8_t*", 0))
+
+    def ndpi_flow_free(self, flow):
+        return self._ndpi.ndpi_flow_free(flow)
+
+    def ndpi_free(self, ptr):
+        return self._ndpi.ndpi_free(ptr)
+
+    def get_str_field(self, ptr):
+        return self._ffi.string(ptr).decode('utf-8', errors='ignore')
+
+    def ndpi_protocol2name(self, proto):
+        buf = self._ffi.new("char[32]")
+        self._ndpi.ndpi_protocol2name(self._mod, proto, buf, self._ffi.sizeof(buf))
+        return self._ffi.string(buf).decode('utf-8', errors='ignore')
+
+    def ndpi_category_get_name(self, category):
+        return self._ffi.string(self._ndpi.ndpi_category_get_name(self._mod, category)).decode('utf-8', errors='ignore')
+
+    def ndpi_exit_detection_module(self):
+        self._ndpi.ndpi_exit_detection_module(self._mod)
-- 
cgit v1.2.3