aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/README10
-rw-r--r--python/flow_printer.py27
-rwxr-xr-xpython/ndpi_example.py151
-rw-r--r--python/ndpi_typestruct.py809
4 files changed, 570 insertions, 427 deletions
diff --git a/python/README b/python/README
index 61a689a77..f55139d0c 100644
--- a/python/README
+++ b/python/README
@@ -1,7 +1,11 @@
-This direcgory contains the Python bindings for nDPI
+This directory contains the Python3 bindings for nDPI
-Usage:
+Demo example:
- python3 ndpi_example.py <interface>
- python3 ndpi_example.py <pcap_file>
-Code courtesy of Massimo Puddu
+Additional example (using nfstream package):
+- python3 flow_printer.py <interface>
+- python3 flow_printer.py <pcap_file>
+
+Code courtesy of: Massimo Puddu, Zied Aouini
diff --git a/python/flow_printer.py b/python/flow_printer.py
new file mode 100644
index 000000000..a30ea79b9
--- /dev/null
+++ b/python/flow_printer.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+file: flow_printer.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 nfstream.streamer import Streamer
+import sys
+
+flow_streamer = Streamer(source=sys.argv[1])
+flows_count = 0
+for flow in flow_streamer:
+ print("flow[{}]: \n{}\n".format(flows_count, flow))
+ flows_count += 1
diff --git a/python/ndpi_example.py b/python/ndpi_example.py
index afbba43b5..d134d3947 100755
--- a/python/ndpi_example.py
+++ b/python/ndpi_example.py
@@ -1,43 +1,44 @@
#!/usr/bin/env python3
-#
-# ndpi_example.py
-#
-# Copyright (C) 2011-19 - ntop.org
-#
-# nDPI is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# nDPI 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with nDPI. If not, see <http://www.gnu.org/licenses/>.
-#
+# -*- coding: utf-8 -*-
+
+"""
+file: ndpi_example.py
+This file is part of nDPI.
+
+Copyright (C) 2011-19 - ntop.org
+Copyright (C) 2019 - Zied Aouini <aouinizied@gmail.com> (Incremental improvements)
+
+nDPI 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.
+
+nDPI 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 nDPI.
+If not, see <http://www.gnu.org/licenses/>.
+"""
from ndpi_typestruct import *
+from ctypes import *
from scapy.all import *
-
+import sys
# ------- return type & pcapstruct to declare -------
-class workflow(Structure):
+class WorkFlow(Structure):
_fields_ = [("src_ip", c_uint32),
("dst_ip", c_uint32),
("src_port", c_uint16),
("dst_port", c_uint16),
("protocol", c_uint8),
("packets", c_uint32),
- ("detected_protocol", ndpi_protocol),
+ ("detected_protocol", NDPIProtocol),
("detection_completed", c_uint8),
("id", c_uint32),
- ("src_id", POINTER(ndpi_id_struct)),
- ("dst_id", POINTER(ndpi_id_struct)),
- ("flow", POINTER(ndpi_flow_struct))]
+ ("src_id", POINTER(NDPIIdStruct)),
+ ("dst_id", POINTER(NDPIIdStruct)),
+ ("flow", POINTER(NDPIFlowStruct))]
CMCFUN = CFUNCTYPE(c_int, c_void_p, c_void_p)
@@ -48,17 +49,19 @@ FREE = CFUNCTYPE(None, c_void_p)
def node_proto_guess_walker(nodo, which, depth, user_data):
global ndpi_info_mod
- flow = cast(nodo, POINTER(POINTER(workflow))).contents.contents
- if which == 0 or which == 3: #execute only preorder operation of the tree
+ flow = cast(nodo, POINTER(POINTER(WorkFlow))).contents.contents
+ if which == 0 or which == 3: # execute only preorder operation of the tree
if flow.detection_completed == 0: # order for tree operation
- flow.detected_protocol = ndpi.ndpi_detection_giveup(ndpi_info_mod, flow.flow, flow.protocol,
- int(socket.ntohl(flow.src_ip)), 1)
+ flow.detected_protocol = ndpi.ndpi_detection_giveup(ndpi_info_mod,
+ flow.flow,
+ 1,
+ cast(addressof(c_uint8(0)), POINTER(c_uint8)))
count_protocol[flow.detected_protocol.app_protocol] += flow.packets
def py_cmp_fun(a, b):
- fa = cast(a, POINTER(workflow))
- fb = cast(b, POINTER(workflow))
+ fa = cast(a, POINTER(WorkFlow))
+ fb = cast(b, POINTER(WorkFlow))
if fa.contents.src_ip < fb.contents.src_ip: return -1
elif fa.contents.src_ip > fb.contents.src_ip: return 1
@@ -83,7 +86,7 @@ free_walk = FREE(freer)
# --------------------------------------
-# number of anylized packet
+# number of analyzed packet
packet_number = 0
flow_count = 0
max_num_udp_dissected_pkts = 16
@@ -103,6 +106,8 @@ if ndpi.ndpi_get_api_version() != ndpi.ndpi_wrap_get_api_version():
ndpi_info_mod = ndpi.ndpi_init_detection_module()
if ndpi_info_mod is None:
sys.exit(-1)
+else:
+ ndpi_ndpi_finalize_initalization(ndpi_info_mod)
def ip2int(ip):
@@ -113,30 +118,34 @@ def ip2int(ip):
return int(struct.unpack("!I", packedIP)[0])
-def get_flow(packet):
+def get_flow(pkt):
global flows_root
global flows_root_ref
global flow_count
- ip_packet = packet[1]
+ ip_packet = pkt[1]
ip_protocol = ip_packet.proto
transport_packet = None
- if ip_protocol == 6 or ip_protocol == 17: transport_packet = packet[2]
+ if ip_protocol == 6 or ip_protocol == 17:
+ transport_packet = pkt[2]
if transport_packet is not None:
# to avoid two nodes in one binary tree for a flow
ip_src = ip2int(ip_packet.src)
ip_dst = ip2int(ip_packet.dst)
src_port = transport_packet.sport
dst_port = transport_packet.dport
- else: return None
+ else:
+ return None
# set flows to correct type and data
- ndpi_flow = pointer(ndpi_flow_struct())
- memset(ndpi_flow, 0, sizeof(ndpi_flow_struct))
+ ndpi_flow = pointer(NDPIFlowStruct())
+ memset(ndpi_flow, 0, sizeof(NDPIFlowStruct))
if ip_src > ip_dst:
- flow = workflow(ip_src, ip_dst, src_port, dst_port, int(ip_packet.proto), 0, ndpi_protocol(), 0, 0, pointer(ndpi_id_struct()), pointer(ndpi_id_struct()), ndpi_flow)
+ flow = WorkFlow(ip_src, ip_dst, src_port, dst_port, int(ip_packet.proto), 0, NDPIProtocol(), 0, 0,
+ pointer(NDPIIdStruct()), pointer(NDPIIdStruct()), ndpi_flow)
else:
- flow = workflow(ip_dst, ip_src, dst_port, src_port, int(ip_packet.proto), 0, ndpi_protocol(), 0, 0, pointer(ndpi_id_struct()), pointer(ndpi_id_struct()), ndpi_flow)
+ flow = WorkFlow(ip_dst, ip_src, dst_port, src_port, int(ip_packet.proto), 0, NDPIProtocol(), 0, 0,
+ pointer(NDPIIdStruct()), pointer(NDPIIdStruct()), ndpi_flow)
flow_ref = pointer(flow)
res = ndpi.ndpi_tfind(flow_ref, flows_root_ref, cmp_func)
if res is None:
@@ -144,41 +153,45 @@ def get_flow(packet):
lista.append(flow)
flow_count += 1
return pointer(flow)
- flow = cast(res, POINTER(POINTER(workflow))).contents
+ flow = cast(res, POINTER(POINTER(WorkFlow))).contents
return flow
-def packetcaptured(packet):
+def packetcaptured(pkt):
global packet_number
- global start_time
global ndpi_info_mod
flow = None
- h = pcap_pkthdr()
+ h = PcapPktHdr()
- #getting flow
+ # getting flow
try:
- flow = get_flow(packet)
+ flow = get_flow(pkt)
except AttributeError:
- pass # ignore packet
+ pass # ignore packet
if flow is None: return
- #filling pcap_pkthdr
- h.len = h.caplen = len(packet)
- h.ts.tv_sec = int(packet["IP"].time/1000000)
- h.ts.tv_usec = int(packet["IP"].time)
+ # filling pcap_pkthdr
+ h.len = h.caplen = len(pkt)
+ h.ts.tv_sec = int(pkt["IP"].time/1000000)
+ h.ts.tv_usec = int(pkt["IP"].time)
# real work
- if int(packet[1].frag) == 0: # not fragmented packet
+ if int(pkt[1].frag) == 0: # not fragmented packet
flow.contents.packets += 1
packet_number += 1
# get ndpi_iphdr address
- iphdr_addr = cast(c_char_p(packet[1].build()), c_void_p)
+ iphdr_addr = cast(c_char_p(pkt[1].build()), c_void_p)
ndpi_flow = flow.contents.flow
if flow.contents.detection_completed is 0:
- flow.contents.detected_protocol = ndpi.ndpi_detection_process_packet(ndpi_info_mod, ndpi_flow, cast(iphdr_addr, POINTER(c_uint8)),
- int(packet[1].len), h.ts.tv_usec, flow.contents.src_id, flow.contents.dst_id)
+ flow.contents.detected_protocol = ndpi.ndpi_detection_process_packet(ndpi_info_mod,
+ ndpi_flow,
+ cast(iphdr_addr, POINTER(c_uint8)),
+ int(pkt[1].len),
+ h.ts.tv_usec,
+ flow.contents.src_id,
+ flow.contents.dst_id)
flow1 = flow.contents.detected_protocol
@@ -187,27 +200,32 @@ def packetcaptured(packet):
if flow.contents.protocol == 6: valid = flow.contents.packets > max_num_tcp_dissected_pkts
elif flow.contents.protocol == 17: valid = flow.contents.packets > max_num_udp_dissected_pkts
- #should we continue anylizing packet or not?
+ # should we continue anylizing packet or not?
if valid or flow1.app_protocol is not 0:
- if valid or flow1.master_protocol is not 91: #or # 91 is NDPI_PROTOCOL_TLS
- flow.contents.detection_completed = 1 #protocol found
+ if valid or flow1.master_protocol is not 91: # or # 91 is NDPI_PROTOCOL_TLS
+ flow.contents.detection_completed = 1 # protocol found
if flow1.app_protocol is 0:
- flow.contents.detected_protocol = ndpi.ndpi_detection_giveup(ndpi_info_mod, ndpi_flow, 1)
-
+ flow.contents.detected_protocol = ndpi.ndpi_detection_giveup(ndpi_info_mod,
+ ndpi_flow,
+ 1,
+ cast(addressof(c_uint8(0)),
+ POINTER(c_uint8)))
def result():
global flows_root_ref
global ndpi_info_mod
- print('\nnumber of anylized packet ' + str(packet_number))
- print('number of flows ' + str(flow_count))
+ print('\nnumber of analyzed packet: ' + str(packet_number))
+ print('number of flows: ' + str(flow_count))
ndpi.ndpi_twalk(flows_root_ref.contents, guess_walker, None)
print('\nDetected protocols:')
for i in range(0, ndpi.ndpi_get_num_supported_protocols(ndpi_info_mod)):
if count_protocol[i] > 0:
- print(cast(ndpi.ndpi_get_proto_name(ndpi_info_mod, i), c_char_p).value + ': '.encode('UTF-8') + str(count_protocol[i]).encode('UTF-8'))
+ print("{}: {} packets".format(
+ cast(ndpi.ndpi_get_proto_name(ndpi_info_mod, i), c_char_p).value.decode('utf-8'),
+ str(count_protocol[i])))
def free(ndpi_struct):
@@ -216,16 +234,16 @@ def free(ndpi_struct):
def initialize(ndpi_struct):
- all = NDPI_PROTOCOL_BITMASK()
+ all = NDPIProtocolBitMask()
ndpi.ndpi_wrap_NDPI_BITMASK_SET_ALL(pointer(all))
ndpi.ndpi_set_protocol_detection_bitmask2(ndpi_struct, pointer(all))
-print('Using nDPI ' + str(cast(ndpi.ndpi_revision(), c_char_p).value))
+print('Using nDPI ' + cast(ndpi.ndpi_revision(), c_char_p).value.decode("utf-8"))
initialize(ndpi_info_mod)
-if(len(sys.argv) != 2):
+if len(sys.argv) != 2:
print("\nUsage: ndpi_example.py <device>")
sys.exit(0)
@@ -247,6 +265,9 @@ else:
sniff(iface=sys.argv[1], prn=packetcaptured)
except KeyboardInterrupt:
print('\nInterrupted\n')
+ except PermissionError:
+ sys.exit('\nRoot privilege required for live capture on interface: {}\n'.format(sys.argv[1]))
+
result()
free(ndpi_info_mod)
diff --git a/python/ndpi_typestruct.py b/python/ndpi_typestruct.py
index 4f8c8c236..889257dea 100644
--- a/python/ndpi_typestruct.py
+++ b/python/ndpi_typestruct.py
@@ -1,343 +1,319 @@
-#
-# ndpi_typestruct.h
-#
-# Copyright (C) 2019 - ntop.org
-#
-# nDPI is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# nDPI 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with nDPI. If not, see <http://www.gnu.org/licenses/>.
-#
-
-
-import os
-from ctypes import *
-
-ndpi = CDLL('./ndpi_wrap.so')
-
-# NDPI_SELECTION_BITMASK_PROTOCOL_SIZE = c_uint32
-# ndpi_protocol_category_t, ndpi_protocol_breed_t e ndpi_log_level_t are enum and are imported as c_int
-
-class ndpi_detection_module_struct(Structure):
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+file: ndpi_typestruct.py
+This file is part of nDPI.
+
+Copyright (C) 2011-19 - ntop.org
+Copyright (C) 2019 - Zied Aouini <aouinizied@gmail.com> (Incremental improvements)
+
+nDPI 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.
+
+nDPI 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 nDPI.
+If not, see <http://www.gnu.org/licenses/>.
+"""
+
+from ctypes import CDLL, Structure, c_uint16, c_int, c_ulong, c_uint32, CFUNCTYPE, c_void_p, POINTER, c_char_p, c_uint8
+from ctypes import c_char, c_uint, c_int16, c_longlong, c_size_t, Union, c_ubyte, c_uint64, c_int32, c_ushort, cast
+from os.path import abspath, dirname
+ndpi = CDLL(dirname(abspath(__file__)) + '/ndpi_wrap.so')
+
+# ----------------------------------------------- Structures -----------------------------------------------------------
+
+
+class NDPIDetectionModuleStruct(Structure):
pass
-class ndpi_flow_struct(Structure):
+
+class NDPIFlowStruct(Structure):
pass
-class ndpi_protocol(Structure):
+
+class NDPIProtocol(Structure):
_fields_ = [
("master_protocol", c_uint16),
("app_protocol", c_uint16),
("category", c_int)
-
]
-class timeval(Structure):
+
+class TimeVal(Structure):
_fields_ = [("tv_sec", c_ulong), ("tv_usec", c_ulong)]
-class pcap_pkthdr(Structure):
- _fields_ = [("ts", timeval), ("caplen", c_uint32), ("len", c_uint32)]
-#dal file ../src/include/ndpi_tydedefs.h
-class ndpi_ndpi_mask(Structure):
+class PcapPktHdr(Structure):
+ _fields_ = [("ts", TimeVal), ("caplen", c_uint32), ("len", c_uint32)]
+
+
+class NDPIMask(Structure):
_fields_ = [("fds_bits", c_uint32)]
-class NDPI_PROTOCOL_BITMASK(Structure):
- _fields_ = [("fds_bits", ndpi_ndpi_mask * ndpi.ndpi_wrap_ndpi_num_fds_bits())]
-class ndpi_subprotocol_conf_struct(Structure):
- _fields_ = [("func", CFUNCTYPE(c_void_p,POINTER(ndpi_detection_module_struct),c_char_p,c_char_p,c_int))]
+class NDPIProtocolBitMask(Structure):
+ _fields_ = [("fds_bits", NDPIMask * ndpi.ndpi_wrap_ndpi_num_fds_bits())]
+
+
+class NDPISubprotocolConfStruct(Structure):
+ _fields_ = [("func", CFUNCTYPE(c_void_p, POINTER(NDPIDetectionModuleStruct), c_char_p, c_char_p, c_int))]
+
-class ndpi_automa(Structure):
+class NDPIAutoma(Structure):
_fields_ = [
- ("ac_automa", c_void_p), #Real type is AC_AUTOMATA_t
+ ("ac_automa", c_void_p),
("ac_automa_finalized", c_uint8)
]
-class struct_node_t(Structure):
+
+class NDPINode(Structure):
pass
-struct_node_t._fields_ = [
+
+
+NDPINode._fields_ = [
('key', POINTER(c_char)),
- ('left', POINTER(struct_node_t)),
- ('right', POINTER(struct_node_t)),
+ ('left', POINTER(NDPINode)),
+ ('right', POINTER(NDPINode)),
]
-class ndpi_call_function_struct(Structure):
+
+class NDPICallFunctionStruct(Structure):
_fields_ = [
- ("detection_bitmask", NDPI_PROTOCOL_BITMASK),
- ("excluded_protocol_bitmask",NDPI_PROTOCOL_BITMASK),
+ ("detection_bitmask", NDPIProtocolBitMask),
+ ("excluded_protocol_bitmask", NDPIProtocolBitMask),
("ndpi_selection_bitmask", c_uint32),
- ("func", CFUNCTYPE(None, POINTER(ndpi_detection_module_struct), POINTER(ndpi_flow_struct))),
+ ("func", CFUNCTYPE(None, POINTER(NDPIDetectionModuleStruct), POINTER(NDPIFlowStruct))),
("detection_feature", c_uint8)
]
-class ndpi_proto_defaults_t(Structure):
+
+class NDPIProtoDefaultsT(Structure):
_fields_ = [
- ("protoName", POINTER(c_char)),
- ("protoCategory",c_uint),
+ ("protoName", c_char_p),
+ ("protoCategory", c_uint),
("can_have_a_subprotocol", c_uint8),
("protoId", c_uint16),
("protoIdx", c_uint16),
("master_tcp_protoId", c_uint16 * 2),
("master_udp_protoId", c_uint16 * 2),
("protoBreed", c_uint),
- ("func", CFUNCTYPE(None, POINTER(ndpi_detection_module_struct), POINTER(ndpi_flow_struct))),
+ ("func", CFUNCTYPE(None, POINTER(NDPIDetectionModuleStruct), POINTER(NDPIFlowStruct))),
]
-class ndpi_default_ports_tree_node_t(Structure):
+
+class NDPIDefaultsPortsTreeNodeT(Structure):
_fields_ = [
- ("proto", ndpi_proto_defaults_t),
- ("customUserProto",c_uint8),
+ ("proto", NDPIProtoDefaultsT),
+ ("customUserProto", c_uint8),
("default_port", c_int16)
]
-# NDPI_PROTOCOL_BITTORRENT
-class spinlock_t(Structure):
- _fields_ = [("val", c_int)] #missing volatile
-class atomic_t(Structure):
- _fields_ = [("counter", c_int)] #missing volatile
+class SpinlockT(Structure):
+ _fields_ = [("val", c_int)]
+
+
+class AtomicT(Structure):
+ _fields_ = [("counter", c_int)]
+
-class time_t(Structure):
- _fields_ = [("counter", c_longlong)] # piattaform dependent
+class TimeT(Structure):
+ _fields_ = [("counter", c_longlong)]
-class hash_ip4p_node(Structure):
+
+class HashIp4pNode(Structure):
pass
-hash_ip4p_node._fields_ = [
- ("next", POINTER(hash_ip4p_node)),
- ("prev", POINTER(hash_ip4p_node)),
- ("lchg", time_t),
+
+HashIp4pNode._fields_ = [
+ ("next", POINTER(HashIp4pNode)),
+ ("prev", POINTER(HashIp4pNode)),
+ ("lchg", TimeT),
("port", c_uint16),
("count", c_uint16, 12),
("flag", c_uint16, 4),
("ip", c_uint32)
]
-class hash_ip4p(Structure):
+
+class HashIp4p(Structure):
_fields_ = [
- ("top", POINTER(hash_ip4p_node)),
- ("lock",spinlock_t),
+ ("top", POINTER(HashIp4pNode)),
+ ("lock",SpinlockT),
("len", c_size_t)
]
-class hash_ip4p_table(Structure):
+
+class HashIp4pTable(Structure):
_fields_ = [
("size", c_size_t),
- ("ipv6",c_int),
- ("lock", spinlock_t),
- ("count", atomic_t),
- ("tbl", hash_ip4p)
+ ("ipv6", c_int),
+ ("lock", SpinlockT),
+ ("count", AtomicT),
+ ("tbl", HashIp4p)
]
-class bt_announce(Structure): # 192 bytes
+
+class BtAnnounce(Structure):
_fields_ = [
("hash", c_uint32 * 5),
("ip", c_uint32 * 4),
("time", c_uint32),
("port", c_uint16),
("name_len", c_uint8),
- ("name", c_uint8 * 149) # 149 bytes
+ ("name", c_uint8 * 149)
+ ]
+
+
+class NDPILruCacheEntry(Structure):
+ _fields_ = [
+ ("key", c_uint32),
+ ("is_full", c_uint32, 1),
+ ("value", c_uint32, 16),
+ ("pad", c_uint32, 15)
]
-class ndpi_lru_cache(Structure): # 192 bytes
+
+class NDPILruCache(Structure):
_fields_ = [
("num_entries", c_uint32),
- ("entries", POINTER(c_uint32)),
+ ("entries", POINTER(NDPILruCacheEntry)),
]
-class cache_entry(Structure):
+
+class CacheEntry(Structure):
pass
-cache_entry._fields_ = [
+
+CacheEntry._fields_ = [
("item", c_void_p),
("item_size", c_uint32),
- ("prev", POINTER(cache_entry)),
- ("next", POINTER(cache_entry))
+ ("prev", POINTER(CacheEntry)),
+ ("next", POINTER(CacheEntry))
]
-class cache_entry_map(Structure):
+
+class CacheEntryMap(Structure):
pass
-cache_entry_map._fields_ = [
- ("entry", POINTER(cache_entry)),
- ("next", POINTER(cache_entry_map)),
+
+CacheEntryMap._fields_ = [
+ ("entry", POINTER(CacheEntry)),
+ ("next", POINTER(CacheEntryMap)),
]
-class cache(Structure): # 192 bytes
+
+class Cache(Structure):
_fields_ = [
("size", c_uint32),
("max_size", c_uint32),
- ("head", POINTER(cache_entry)),
- ("tail", POINTER(cache_entry)),
- ("map", POINTER(POINTER(cache_entry_map)))
- ]
-
-class custom_categories(Structure):
- _fields_ =[
- #Hyperscam
- #("hostnames", POINTER(hs)),
- #("num_to_load", c_uint),
- #("to_load", POINTER(hs_list)),
- ("hostnames", ndpi_automa),
- ("hostnames_shadow", ndpi_automa),
- ("hostnames_hash", c_void_p),
- ("ipAddresses", c_void_p),
- ("ipAddresses_shadow", c_void_p), # Patricia
- ("categories_loaded", c_uint8),
+ ("head", POINTER(CacheEntry)),
+ ("tail", POINTER(CacheEntry)),
+ ("map", POINTER(POINTER(CacheEntryMap)))
]
-ndpi_detection_module_struct._fields_ = [
- ("detection_bitmask", NDPI_PROTOCOL_BITMASK),
- ("generic_http_packet_bitmask", NDPI_PROTOCOL_BITMASK),
-
- ("current_ts", c_uint32),
-
- ("ticks_per_second", c_uint32),
-
- #("user_data", c_void_p), debug
+class CustomCategories(Structure):
+ _fields_ = [
+ ("hostnames", NDPIAutoma),
+ ("hostnames_shadow", NDPIAutoma),
+ ("ipAddresses", c_void_p),
+ ("ipAddresses_shadow", c_void_p),
+ ("categories_loaded", c_uint8),
+ ]
- ("custom_category_labels", (c_char * ndpi.ndpi_wrap_num_custom_categories()) * ndpi.ndpi_wrap_custom_category_label_len()),
- #callback function buffer
- ("callback_buffer", ndpi_call_function_struct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
+NDPIDetectionModuleStruct._fields_ = [
+ ("detection_bitmask", NDPIProtocolBitMask),
+ ("generic_http_packet_bitmask", NDPIProtocolBitMask),
+ ("current_ts", c_uint32),
+ ("ticks_per_second", c_uint32),
+ ("custom_category_labels",
+ (c_char * ndpi.ndpi_wrap_num_custom_categories()) * ndpi.ndpi_wrap_custom_category_label_len()),
+ ("callback_buffer", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
("callback_buffer_size", c_uint32),
-
- ("callback_buffer_tcp_no_payload", ndpi_call_function_struct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
+ ("callback_buffer_tcp_no_payload", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
("callback_buffer_size_tcp_no_payload", c_uint32),
-
- ("callback_buffer_tcp_payload", ndpi_call_function_struct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
+ ("callback_buffer_tcp_payload", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
("callback_buffer_size_tcp_payload", c_uint32),
-
- ("callback_buffer_udp", ndpi_call_function_struct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
+ ("callback_buffer_udp", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
("callback_buffer_size_udp", c_uint32),
-
- ("callback_buffer_non_tcp_udp", ndpi_call_function_struct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
+ ("callback_buffer_non_tcp_udp", NDPICallFunctionStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
("callback_buffer_size_non_tcp_udp", c_uint32),
-
- ("tcpRoot", POINTER(ndpi_default_ports_tree_node_t)),
- ("udpRoot", POINTER(ndpi_default_ports_tree_node_t)),
-
- ("ndpi_log_level", c_uint), #default error
-
- # ifdef NDPI_ENABLE_DEBUG_MESSAGES
- #debug callback, only set whendebug is used * /
- #ndpi_debug_function_ptr ndpi_debug_printf;
- #const char * ndpi_debug_print_file;
- #const char * ndpi_debug_print_function;
- #u_int32_t ndpi_debug_print_line;
- #NDPI_PROTOCOL_BITMASK debug_bitmask;
- # endif
-
- #misc parameters
- ("tcp_max_retransmission_window_size", c_uint32),
-
- ("directconnect_connection_ip_tick_timeout", c_uint32),
-
- #subprotocol registration handler
- ("subprotocol_conf", ndpi_subprotocol_conf_struct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
-
- ("ndpi_num_supported_protocols", c_uint),
+ ("tcpRoot", POINTER(NDPIDefaultsPortsTreeNodeT)),
+ ("udpRoot", POINTER(NDPIDefaultsPortsTreeNodeT)),
+ ("ndpi_log_level", c_uint),
+ ("tcp_max_retransmission_window_size", c_uint32),
+ ("directconnect_connection_ip_tick_timeout", c_uint32),
+ ("subprotocol_conf", NDPISubprotocolConfStruct * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + 1)),
+ ("ndpi_num_supported_protocols", c_uint),
("ndpi_num_custom_protocols", c_uint),
-
- #HTTP / DNS / HTTPS host matching * /
- ("host_automa", ndpi_automa), #Used for DNS / HTTPS
- ("content_automa", ndpi_automa), # Used for HTTP subprotocol_detection
- ("subprotocol_automa", ndpi_automa), # Used for HTTP subprotocol_detection
- ("bigrams_automa", ndpi_automa), #TOR
- ("impossible_bigrams_automa", ndpi_automa), # TOR
-
- ("custom_categories", custom_categories),
- #IP-based protocol detection
- ("protocols_ptree", c_void_p),
-
- #irc parameters
- ("irc_timeout", c_uint32),
- #gnutella parameters
- ("gnutella_timeout", c_uint32),
- #battlefield parameters
- ("battlefield_timeout", c_uint32),
- # thunder parameters
- ("thunder_timeout", c_uint32),
- # SoulSeek parameters
- ("soulseek_connection_ip_tick_timeout", c_uint32),
- # rtsp parameters
- ("rtsp_connection_timeout", c_uint32),
- # tvants parameters
- ("tvants_connection_timeout", c_uint32),
- # rstp
- ("orb_rstp_ts_timeout", c_uint32),
- # yahoo
- ("yahoo_detect_http_connections", c_uint8),
+ ("host_automa", NDPIAutoma),
+ ("content_automa", NDPIAutoma),
+ ("subprotocol_automa", NDPIAutoma),
+ ("bigrams_automa", NDPIAutoma),
+ ("impossible_bigrams_automa", NDPIAutoma),
+ ("custom_categories", CustomCategories),
+ ("protocols_ptree", c_void_p),
+ ("irc_timeout", c_uint32),
+ ("gnutella_timeout", c_uint32),
+ ("battlefield_timeout", c_uint32),
+ ("thunder_timeout", c_uint32),
+ ("soulseek_connection_ip_tick_timeout", c_uint32),
+ ("rtsp_connection_timeout", c_uint32),
+ ("tvants_connection_timeout", c_uint32),
+ ("orb_rstp_ts_timeout", c_uint32),
+ ("yahoo_detect_http_connections", c_uint8),
("yahoo_lan_video_timeout", c_uint32),
("zattoo_connection_timeout", c_uint32),
("jabber_stun_timeout", c_uint32),
("jabber_file_transfer_timeout", c_uint32),
-
- # ifdef NDPI_ENABLE_DEBUG_MESSAGES
- # define NDPI_IP_STRING_SIZE 40
- #char ip_string[NDPI_IP_STRING_SIZE];
- # endif
-
- ("ip_version_limit", c_uint8),
- #NDPI_PROTOCOL_BITTORRENT
- ("bt_ht", POINTER(hash_ip4p_table)),
- # ifdef NDPI_DETECTION_SUPPORT_IPV6
- ("bt6_ht", POINTER(hash_ip4p_table)),
- # endif
-
- # BT_ANNOUNCE
- ("bt_ann", POINTER(bt_announce)),
+ ("ip_version_limit", c_uint8),
+ ("bt_ht", POINTER(HashIp4pTable)),
+ ("bt6_ht", POINTER(HashIp4pTable)),
+ ("bt_ann", POINTER(BtAnnounce)),
("bt_ann_len", c_int),
-
- # NDPI_PROTOCOL_OOKLA
- ("ookla_cache", POINTER(ndpi_lru_cache)),
-
- # NDPI_PROTOCOL_TINC
- ("tinc_cache", POINTER(cache)),
-
- ("proto_defaults", ndpi_proto_defaults_t * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() + ndpi.ndpi_wrap_ndpi_max_num_custom_protocols())),
-
- ("http_dont_dissect_response", c_uint8, 1),
+ ("ookla_cache", POINTER(NDPILruCache)),
+ ("tinc_cache", POINTER(Cache)),
+ ("proto_defaults", NDPIProtoDefaultsT * (ndpi.ndpi_wrap_ndpi_max_supported_protocols() +
+ ndpi.ndpi_wrap_ndpi_max_num_custom_protocols())),
+ ("http_dont_dissect_response", c_uint8, 1),
("dns_dont_dissect_response", c_uint8, 1),
- ("direction_detect_disable", c_uint8, 1), # disable internal detection of packet direction
- ("disable_metadata_export", c_uint8, 1), # No metadata is exported
- ("enable_category_substring_match", c_uint8, 1), # Default is perfect match
-
- ("hyperscan", c_void_p) # Intel Hyperscan
+ ("direction_detect_disable", c_uint8, 1),
+ ("disable_metadata_export", c_uint8, 1),
+ ("hyperscan", c_void_p)
]
-class u6_addr(Union): # 128-bit IP6 address
+
+class U6Addr(Union):
_fields_ = [
- ("u6_addr8",c_uint8 * 16),
- ("u6_addr16",c_uint16 * 8),
- ("u6_addr32",c_uint32 * 4)
+ ("u6_addr8", c_uint8 * 16),
+ ("u6_addr16", c_uint16 * 8),
+ ("u6_addr32", c_uint32 * 4),
+ ("u6_addr64", c_uint64 * 2)
]
-class ndpi_in6_addr(Structure):
- _fields_ = [("u6_addr", u6_addr)]
+
+class NDPIIn6Addr(Structure):
+ _pack_ = 1
+ _fields_ = [("u6_addr", U6Addr)]
-class ndpi_ip_addr_t(Union):
+class NDPIIpAddrT(Union):
_fields_ = [
('ipv4', c_uint32),
('ipv4_u_int8_t', c_uint8 * 4),
- ('ipv6', ndpi_in6_addr),
+ ('ipv6', NDPIIn6Addr),
]
-class ndpi_id_struct(Structure):
+
+class NDPIIdStruct(Structure):
_fields_ = [
- ('detected_protocol_bitmask', NDPI_PROTOCOL_BITMASK),
- ('rtsp_ip_address', ndpi_ip_addr_t),
+ ('detected_protocol_bitmask', NDPIProtocolBitMask),
+ ('rtsp_ip_address', NDPIIpAddrT),
('yahoo_video_lan_timer', c_uint32),
('irc_port', c_uint16 * 8),
('last_time_port_used', c_uint32 * 8),
@@ -371,10 +347,10 @@ class ndpi_id_struct(Structure):
('rtsp_ts_set', c_uint32, 1),
]
-#struct flow
-class ndpi_flow_tcp_struct(Structure):
+
+class NDPIFlowTcpStruct(Structure):
+ _pack_ = 1
_fields_ = [
- # NDPI_PROTOCOL_MAIL_SMTP
('smtp_command_bitmask', c_uint16),
('pop_command_bitmask', c_uint16),
('qq_nxt_len', c_uint16),
@@ -405,10 +381,16 @@ class ndpi_flow_tcp_struct(Structure):
('ssh_stage', c_uint32, 3),
('vnc_stage', c_uint32, 2),
('telnet_stage', c_uint32, 2),
- ('ssl_seen_client_cert', c_uint8, 1),
- ('ssl_seen_server_cert', c_uint8, 1),
- ('ssl_seen_certificate', c_uint8, 1),
- ('ssl_stage', c_uint8, 2),
+ ('tls_srv_cert_fingerprint_ctx', c_void_p),
+ ('tls_seen_client_cert', c_uint8, 1),
+ ('tls_seen_server_cert', c_uint8, 1),
+ ('tls_seen_certificate', c_uint8, 1),
+ ('tls_srv_cert_fingerprint_found', c_uint8, 1),
+ ('tls_srv_cert_fingerprint_processed', c_uint8, 1),
+ ('tls_stage', c_uint8, 2),
+ ('tls_record_offset', c_int16),
+ ('tls_fingerprint_len', c_int16),
+ ('tls_sha1_certificate_fingerprint', c_uint8 * 20),
('postgres_stage', c_uint32, 3),
('ddlink_server_direction', c_uint32, 1),
('seen_syn', c_uint32, 1),
@@ -429,13 +411,15 @@ class ndpi_flow_tcp_struct(Structure):
('lotus_notes_packet_id', c_uint8),
('teamviewer_stage', c_uint8),
('prev_zmq_pkt_len', c_uint8),
- ('prev_zmq_pkt', c_ubyte * 10),
+ ('prev_zmq_pkt', c_char * 10),
('ppstream_stage', c_uint32, 3),
('memcached_matches', c_uint8),
('nest_log_sink_matches', c_uint8),
]
-class ndpi_flow_udp_struct(Structure):
+
+class NDPIFlowUdpStruct(Structure):
+ _pack_ = 1
_fields_ = [
('battlefield_msg_id', c_uint32),
('snmp_msg_id', c_uint32),
@@ -454,103 +438,152 @@ class ndpi_flow_udp_struct(Structure):
('rx_conn_epoch', c_uint32),
('rx_conn_id', c_uint32),
('memcached_matches', c_uint8),
+ ('wireguard_stage', c_uint8),
+ ('wireguard_peer_index', c_uint32 * 2),
]
-# the tcp / udp / other l4 value union used to reduce the number of bytes for tcp or udp protocol states
-class l4(Union):
- _fields_ = [("tcp", ndpi_flow_tcp_struct),("udp", ndpi_flow_udp_struct)]
-class http(Structure):
+class L4(Union):
+ _fields_ = [("tcp", NDPIFlowTcpStruct), ("udp", NDPIFlowUdpStruct)]
+
+
+class Http(Structure):
_fields_ = [
("method", c_int),
("url", c_char_p),
("content_type", c_char_p),
- ("num_request_headers", c_uint8), ("num_response_headers", c_uint8),
- ("request_version", c_uint8), # 0=1.0 and 1=1.1. Create an enum for this?
- ("response_status_code", c_uint16), # 200, 404, etc.
+ ("num_request_headers", c_uint8),
+ ("num_response_headers", c_uint8),
+ ("request_version", c_uint8),
+ ("response_status_code", c_uint16),
]
-class dns(Structure): # the only fields useful for nDPI and ntopng
+
+class Dns(Structure):
_fields_ = [
- ("num_queries", c_uint8), ("num_answers", c_uint8), ("reply_code", c_uint8),
- ("query_type", c_uint16), ("query_class", c_uint16), ("rsp_type", c_uint16),
- ("rsp_addr", ndpi_ip_addr_t) # The first address in a DNS response packet
+ ("num_queries", c_uint8),
+ ("num_answers", c_uint8),
+ ("reply_code", c_uint8),
+ ("is_query", c_uint8),
+ ("query_type", c_uint16),
+ ("query_class", c_uint16),
+ ("rsp_type", c_uint16),
+ ("rsp_addr", NDPIIpAddrT)
]
-class ntp(Structure):
- _fields_ = [("request_code", c_uint8), ("version", c_uint8)]
-class ssl(Structure):
+class Ntp(Structure):
+ _fields_ = [("request_code", c_uint8),
+ ("version", c_uint8)]
+
+
+class Kerberos(Structure):
+ _fields_ = [("cname", c_char * 24),
+ ("realm", c_char * 24)]
+
+
+class Ssl(Structure):
_fields_ = [
- ("ssl_version", c_uint8),
- ("client_certificate", c_char * 64), ("server_certificate", c_char * 64), ("server_organization", c_char * 64),
- ("ja3_client", c_char * 33), ("ja3_server", c_char * 33),
+ ("ssl_version", c_uint16),
+ ("client_certificate", c_char * 64),
+ ("server_certificate", c_char * 64),
+ ("server_organization", c_char * 64),
+ ('notBefore', c_uint32),
+ ('notAfter', c_uint32),
+ ("ja3_client", c_char * 33),
+ ("ja3_server", c_char * 33),
("server_cipher", c_uint16),
("server_unsafe_cipher", c_int)
]
-class stun(Structure):
+
+class Stun(Structure):
_fields_ = [
("num_udp_pkts", c_uint8),
("num_processed_pkts", c_uint8),
("num_binding_requests", c_uint8),
- ("is_skype", c_uint8)
]
-class stun_ssl(Union): # We can have STUN over SSL thus they need to live together
- _fields_ = [("ssl", ssl),("stun",stun)]
-class ssh(Structure):
- _fields_ = [("client_signature", c_char * 48), ("server_signature", c_char * 48)]
+class StunSsl(Structure):
+ _fields_ = [("ssl", Ssl), ("stun", Stun)]
+
+
+class Ssh(Structure):
+ _fields_ = [
+ ("client_signature", c_char * 48),
+ ("server_signature", c_char * 48),
+ ("hassh_client", c_char * 33),
+ ("hassh_server", c_char * 33)
+ ]
-class mdns(Structure):
+
+class Imo(Structure):
+ _fields_ = [
+ ("last_one_byte_pkt", c_uint8),
+ ("last_byte", c_uint8)
+ ]
+
+
+class Mdns(Structure):
_fields_ = [("answer", c_char * 96)]
-class ubntac2(Structure):
- _fields_ = [("version", c_char * 96)]
-class http2(Structure):
+class Ubntac2(Structure):
+ _fields_ = [("version", c_char * 32)]
+
+
+class Http2(Structure):
_fields_ = [
- ("detected_os", c_ubyte * 32), #Via HTTP User-Agent
- ("nat_ip", c_ubyte * 24)
+ ("detected_os", c_char * 32),
+ ("nat_ip", c_char * 24)
]
-class bittorrent(Structure): # Bittorrent hash
- _fields_ = [ ("hash", c_ubyte * 20) ]
-class dhcp(Structure):
+class Bittorrent(Structure):
+ _fields_ = [("hash", c_char * 20)]
+
+
+class Dhcp(Structure):
_fields_ = [
("fingerprint", c_char * 48),
- ("nat_ip", c_char * 48)
+ ("class_ident", c_char * 48)
]
-class protos(Union):
+
+class Protos(Union):
_fields_ = [
- ("dns", dns),
- ("ntp", ntp),
- ("stun_ssl", stun_ssl),
- ("ssh", ssh),
- ("mdns", mdns),
- ("ubntac2", ubntac2),
- ("http", http2),
- ("bittorrent", bittorrent),
- ("dhcp", dhcp)
+ ("dns", Dns),
+ ("kerberos", Kerberos),
+ ("stun_ssl", StunSsl),
+ ("ssh", Ssh),
+ ("imo", Imo),
+ ("mdns", Mdns),
+ ("ubntac2", Ubntac2),
+ ("http", Http2),
+ ("bittorrent", Bittorrent),
+ ("dhcp", Dhcp)
]
-class tinc_cache_entry(Structure):
+
+class TincCacheEntry(Structure):
+ _pack_ = 1
_fields_ = [
('src_address', c_uint32),
('dst_address', c_uint32),
('dst_port', c_uint16),
]
-class struct_ndpi_int_one_line_struct(Structure):
+
+class NDPIIntOneLineStruct(Structure):
_fields_ = [
('ptr', POINTER(c_uint8)),
('len', c_uint16),
]
-class struct_ndpi_iphdr_little_end(Structure):
+
+class NDPIIphdr(Structure):
+ _pack_ = 1
_fields_ = [
('ihl', c_uint8, 4),
('version', c_uint8, 4),
@@ -564,7 +597,9 @@ class struct_ndpi_iphdr_little_end(Structure):
('saddr', c_uint32),
('daddr', c_uint32)]
-class struct_ndpi_ip6_hdrctl(Structure):
+
+class NDPIIp6Hdrctl(Structure):
+ _pack_ = 1
_fields_ = [
('ip6_un1_flow', c_uint32),
('ip6_un1_plen', c_uint16),
@@ -572,14 +607,18 @@ class struct_ndpi_ip6_hdrctl(Structure):
('ip6_un1_hlim', c_uint8),
]
-class struct_ndpi_ipv6hdr(Structure):
+
+class NDPIIpv6hdr(Structure):
+ _pack_ = 1
_fields_ = [
- ('ip6_hdr', struct_ndpi_ip6_hdrctl),
- ('ip6_src', ndpi_in6_addr),
- ('ip6_dst', ndpi_in6_addr),
+ ('ip6_hdr', NDPIIp6Hdrctl),
+ ('ip6_src', NDPIIn6Addr),
+ ('ip6_dst', NDPIIn6Addr),
]
-class struct_ndpi_tcphdr(Structure):
+
+class NDPITcpHdr(Structure):
+ _pack_ = 1
_fields_ = [
('source', c_uint16),
('dest', c_uint16),
@@ -600,7 +639,9 @@ class struct_ndpi_tcphdr(Structure):
('urg_ptr', c_uint16),
]
-class struct_ndpi_udphdr(Structure):
+
+class NDPIUdpHdr(Structure):
+ _pack_ = 1
_fields_ = [
('source', c_uint16),
('dest', c_uint16),
@@ -608,36 +649,44 @@ class struct_ndpi_udphdr(Structure):
('check', c_uint16),
]
-class ndpi_packet_struct(Structure):
+
+class NDPIPacketStructStack(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ('detected_subprotocol_stack', c_uint8 * ndpi.ndpi_wrap_ndpi_procol_size()),
+ ('protocol_stack_info', c_uint16)
+ ]
+
+
+class NDPIPacketStruct(Structure):
_fields_ = [
- ('iph', POINTER(struct_ndpi_iphdr_little_end)),
- ('iphv6', POINTER(struct_ndpi_ipv6hdr)),
- ('tcp', POINTER(struct_ndpi_tcphdr)),
- ('udp', POINTER(struct_ndpi_udphdr)),
+ ('iph', POINTER(NDPIIphdr)),
+ ('iphv6', POINTER(NDPIIpv6hdr)),
+ ('tcp', POINTER(NDPITcpHdr)),
+ ('udp', POINTER(NDPIUdpHdr)),
('generic_l4_ptr', POINTER(c_uint8)),
('payload', POINTER(c_uint8)),
('tick_timestamp', c_uint32),
('tick_timestamp_l', c_uint64),
- ('detected_protocol_stack', c_uint16 * 2),
- ('detected_subprotocol_stack', c_uint8 * 2),
- ('protocol_stack_info', c_uint16),
- ('line', struct_ndpi_int_one_line_struct * 64),
- ('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', struct_ndpi_int_one_line_struct),
+ ('detected_protocol_stack', c_uint16 * ndpi.ndpi_wrap_ndpi_procol_size()),
+ ('ndpi_packet_stack', NDPIPacketStructStack),
+ ('line', NDPIIntOneLineStruct * 64),
+ ('host_line', NDPIIntOneLineStruct),
+ ('forwarded_line', NDPIIntOneLineStruct),
+ ('referer_line', NDPIIntOneLineStruct),
+ ('content_line', NDPIIntOneLineStruct),
+ ('accept_line', NDPIIntOneLineStruct),
+ ('user_agent_line', NDPIIntOneLineStruct),
+ ('http_url_name', NDPIIntOneLineStruct),
+ ('http_encoding', NDPIIntOneLineStruct),
+ ('http_transfer_encoding', NDPIIntOneLineStruct),
+ ('http_contentlen', NDPIIntOneLineStruct),
+ ('http_cookie', NDPIIntOneLineStruct),
+ ('http_origin', NDPIIntOneLineStruct),
+ ('http_x_session_type', NDPIIntOneLineStruct),
+ ('server_line', NDPIIntOneLineStruct),
+ ('http_method', NDPIIntOneLineStruct),
+ ('http_response', NDPIIntOneLineStruct),
('http_num_headers', c_uint8),
('l3_packet_len', c_uint16),
('l4_packet_len', c_uint16),
@@ -654,58 +703,43 @@ class ndpi_packet_struct(Structure):
('packet_lines_parsed_complete', c_uint8, 1),
('packet_direction', c_uint8, 1),
('empty_line_position_set', c_uint8, 1),
+ ('pad', c_uint8, 5),
+ ]
+
+
+class NDPIFlowStructStack(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("detected_protocol_stack", c_uint16 * ndpi.ndpi_wrap_ndpi_procol_size()),
+ ("protocol_stack_info", c_uint16)
]
-ndpi_flow_struct._fields_ = [
- ("detected_protocol_stack", c_uint16 * ndpi.ndpi_wrap_ndpi_procol_size()),
- ("protocol_stack_info", c_uint16),
- # init parameter, internal used to set up timestamp,...
+NDPIFlowStruct._fields_ = [
+ ("ndpi_flow_stack", NDPIFlowStructStack),
("guessed_protocol_id", c_uint16),
("guessed_host_protocol_id", c_uint16),
("guessed_category", c_uint16),
("guessed_header_category", c_uint16),
+ ("l4_proto", c_uint8),
("protocol_id_already_guessed", c_uint8, 1),
("host_already_guessed", c_uint8, 1),
("init_finished", c_uint8, 1),
("setup_packet_direction", c_uint8, 1),
("packet_direction", c_uint8, 1),
("check_extra_packets", c_uint8, 1),
-
- # if ndpi_struct->direction_detect_disable == 1 tcp sequence number connection tracking
("next_tcp_seq_nr", c_uint32 * 2),
-
("max_extra_packets_to_check", c_uint8),
("num_extra_packets_checked", c_uint8),
- ("num_processed_pkts", c_uint8), # <= WARNING it can wrap but we do expect people to giveup earlier
-
- ("extra_packets_func", CFUNCTYPE(c_int,POINTER(ndpi_detection_module_struct),POINTER(ndpi_flow_struct))),
-
- ("l4", l4),
-
- # Pointer to src or dst that identifies the server of this connection
- ("server_id", ndpi_id_struct),
- # HTTP host or DNS query
+ ("num_processed_pkts", c_uint8),
+ ("extra_packets_func", CFUNCTYPE(c_int, POINTER(NDPIDetectionModuleStruct), POINTER(NDPIFlowStruct))),
+ ("l4", L4),
+ ("server_id", POINTER(NDPIIdStruct)),
("host_server_name", c_ubyte * 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.
-
-
- ("http", http),
- ("protos", protos),
-
- # ALL protocol specific 64 bit variables here
-
- # protocols which have marked a connection as this connection cannot be protocol XXX, multiple u_int64_t
- ("excluded_protocol_bitmask", NDPI_PROTOCOL_BITMASK),
-
+ ("http", Http),
+ ("protos", Protos),
+ ("excluded_protocol_bitmask", NDPIProtocolBitMask),
("category", c_int),
-
('redis_s2d_first_char', c_uint8),
('redis_d2s_first_char', c_uint8),
('packet_counter', c_uint16),
@@ -742,32 +776,89 @@ ndpi_flow_struct._fields_ = [
('ovpn_session_id', c_uint8 * 8),
('ovpn_counter', c_uint8),
('tinc_state', c_uint8),
- ('tinc_cache_entry', tinc_cache_entry),
+ ('TincCacheEntry', TincCacheEntry),
('csgo_strid', c_uint8 * 18),
('csgo_state', c_uint8),
('csgo_s2', c_uint8),
('csgo_id2', c_uint32),
('kxun_counter', c_uint16),
('iqiyi_counter', c_uint16),
- ('packet', ndpi_packet_struct),
- ('flow', POINTER(ndpi_flow_struct)),
- ('src', POINTER(ndpi_id_struct)),
- ('dst', POINTER(ndpi_id_struct))
+ ('packet', NDPIPacketStruct),
+ ('flow', POINTER(NDPIFlowStruct)),
+ ('src', POINTER(NDPIIdStruct)),
+ ('dst', POINTER(NDPIIdStruct))
]
-
+# ----------------------------------------------- nDPI APIs ------------------------------------------------------------
+
+""" ndpi_detection_giveup: Function to be called before we give up with detection for a given flow.
+ This function reduces the NDPI_UNKNOWN_PROTOCOL detection. """
+ndpi.ndpi_detection_giveup.restype = NDPIProtocol
+ndpi.ndpi_detection_giveup.argtypes = [POINTER(NDPIDetectionModuleStruct),
+ POINTER(NDPIFlowStruct), c_uint8,
+ POINTER(c_uint8)]
+
+""" ndpi_detection_process_packet: Processes one packet and returns the ID of the detected protocol.
+ This is the MAIN PACKET PROCESSING FUNCTION. """
+ndpi.ndpi_detection_process_packet.restype = NDPIProtocol
+ndpi.ndpi_detection_process_packet.argtypes = [POINTER(NDPIDetectionModuleStruct),
+ POINTER(NDPIFlowStruct),
+ POINTER(c_ubyte),
+ c_ushort,
+ c_uint64,
+ POINTER(NDPIIdStruct),
+ POINTER(NDPIIdStruct)]
+
+""" ndpi_ssl_version2str : Converts ssl version to readable string """
+ndpi.ndpi_ssl_version2str.restype = c_char_p
+ndpi.ndpi_ssl_version2str.argtypes = [c_int16, POINTER(c_uint8)]
+
+""" ndpi_init_detection_module: Returns a new initialized detection module.
+ Note that before you can use it you can still load hosts and do other things. As soon as you are ready to use
+ it do not forget to call first ndpi_finalize_initalization() """
+ndpi.ndpi_init_detection_module.restype = POINTER(NDPIDetectionModuleStruct)
+
+
+def ndpi_ndpi_finalize_initalization(detection_module):
+ """ ndpi_finalize_initalization: Completes the initialization (ndpi_revision >= 3.1)"""
+ if cast(ndpi.ndpi_revision(), c_char_p).value.decode("utf-8")[:3] >= '3.1':
+ ndpi.ndpi_finalize_initalization.restype = c_void_p
+ ndpi.ndpi_finalize_initalization.argtypes = [POINTER(NDPIDetectionModuleStruct)]
+ return ndpi.ndpi_finalize_initalization(detection_module)
+ else:
+ # ignore it
+ return None
+
+
+""" ndpi_tfind: find a node, or return 0. """
ndpi.ndpi_tfind.restype = c_void_p
+
+""" ndpi_tsearch: ftp://ftp.cc.uoc.gr/mirrors/OpenBSD/src/lib/libc/stdlib/tsearch.c
+ find or insert datum into search tree. """
ndpi.ndpi_tsearch.restype = c_void_p
+ndpi.ndpi_tsearch.argtypes = [c_void_p, POINTER(c_void_p), CFUNCTYPE(c_int, c_void_p, c_void_p)]
+
+""" ndpi_revision: Get the nDPI version release. """
ndpi.ndpi_revision.restype = c_void_p
+
+""" ndpi_get_proto_name: Get the protocol name associated to the ID."""
ndpi.ndpi_get_proto_name.restype = c_void_p
+
+""" ndpi_category_get_name: Get protocol category as string."""
+ndpi.ndpi_category_get_name.restype = c_void_p
+
+""" ndpi_get_num_supported_protocols: Get the total number of the supported protocols."""
ndpi.ndpi_get_num_supported_protocols.restype = c_uint
-ndpi.ndpi_detection_process_packet.restype = ndpi_protocol
-ndpi.ndpi_init_detection_module.restype = POINTER(ndpi_detection_module_struct)
-ndpi.ndpi_wrap_NDPI_BITMASK_SET_ALL.argtypes = [POINTER(NDPI_PROTOCOL_BITMASK)]
-ndpi.ndpi_set_protocol_detection_bitmask2.argtypes = [POINTER(ndpi_detection_module_struct), POINTER(NDPI_PROTOCOL_BITMASK)]
-ndpi.ndpi_tsearch.argtypes = [c_void_p, POINTER(c_void_p), CFUNCTYPE(c_int, c_void_p, c_void_p)]
+
+""" ndpi_wrap_NDPI_BITMASK_SET_ALL: memset((char *)(p), 0xFF, sizeof(*(p)))"""
+ndpi.ndpi_wrap_NDPI_BITMASK_SET_ALL.argtypes = [POINTER(NDPIProtocolBitMask)]
+
+""" ndpi_set_protocol_detection_bitmask2: Sets the protocol bitmask2."""
+ndpi.ndpi_set_protocol_detection_bitmask2.argtypes = [POINTER(NDPIDetectionModuleStruct),
+ POINTER(NDPIProtocolBitMask)]
+
+""" ndpi_twalk: Walk the nodes of a tree. """
ndpi.ndpi_twalk.argtypes = [c_void_p, CFUNCTYPE(None, c_void_p, c_int32, c_int, c_void_p), c_void_p]
-ndpi.ndpi_tdestroy.argtypes = [c_void_p, CFUNCTYPE(None, c_void_p)]
-ndpi.ndpi_detection_giveup.restype = ndpi_protocol
-ndpi.ndpi_detection_giveup.argtypes = [POINTER(ndpi_detection_module_struct), POINTER(ndpi_flow_struct), c_uint8]
-ndpi.ndpi_detection_process_packet.argtypes = [POINTER(ndpi_detection_module_struct), POINTER(ndpi_flow_struct), POINTER(c_ubyte), c_ushort, c_uint64, POINTER(ndpi_id_struct), POINTER(ndpi_id_struct)]
+
+""" ndpi_tdestroy: node destroy. """
+ndpi.ndpi_tdestroy.argtypes = [c_void_p, CFUNCTYPE(None, c_void_p)] \ No newline at end of file