最近研究了ndpi的源代码,过程中看到关于这方面的资料很少,所以就想把自己的收获写下来分享一下,也让之后的同学有所参考。首先简单介绍一下ndpi源码中几个比较重要的结构体,这些结构体的定义一般都在ndpi_typedefs.h头文件中,有兴趣的同学可以参考。
1,ndpi_iphdr, ndpi_tcphdr,ndpi_udphdr, ndpi_ethdr(这几个是在 linux_compat.h头文件中)
这几个结构题比较简单,主要用于存储各层的数据包头信息。如果学过计算机网络都应该知道网络数据在传输时经过每一层都会加上相应的信息,比如IP包头一般有20个字节固定长度,下面是ndpi_iphdr结构体的定义,可以看出来是跟IP数据包格式一一对应的,在此不做过多解释。ndpi_ethdr是对应数据链路层。
struct ndpi_iphdr {
#if defined(__LITTLE_ENDIAN__)
u_int8_t ihl:4, version:4;
#elif defined(__BIG_ENDIAN__)
u_int8_t version:4, ihl:4;
#else
# error "Byte order must be defined"
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
2,ndpi_detection_module_struct
这个结构体比较重要,主要用于存储一些全局变量,由ndpi_init_detection_module()函数在初始化过程中返回。下面是该结构体定义,其中有一些我觉得不重要的内容删去了。关于这个结构体,可以参考这篇文章,里面详细介绍了ndpi在初始化过程中所完成的任务。之后的文章中我也会对这个结构体中一些重要的变量作详细介绍。
typedef struct ndpi_detection_module_struct {
NDPI_PROTOCOL_BITMASK detection_bitmask;
NDPI_PROTOCOL_BITMASK generic_http_packet_bitmask;
struct ndpi_call_function_struct callback_buffer[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
u_int32_t callback_buffer_size;
struct ndpi_call_function_struct callback_buffer_tcp_no_payload[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
u_int32_t callback_buffer_size_tcp_no_payload;
struct ndpi_call_function_struct callback_buffer_tcp_payload[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
u_int32_t callback_buffer_size_tcp_payload;
struct ndpi_call_function_struct callback_buffer_udp[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
u_int32_t callback_buffer_size_udp;
struct ndpi_call_function_struct callback_buffer_non_tcp_udp[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
u_int32_t callback_buffer_size_non_tcp_udp;
ndpi_default_ports_tree_node_t *tcpRoot, *udpRoot;
u_int32_t tcp_max_retransmission_window_size;
void *protocols_ptree;
ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS];
u_int8_t match_dns_host_names:1, http_dissect_response:1;
u_int8_t direction_detect_disable:1;
} ndpi_detection_module_struct_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
3,ndpi_packet_struct
这个结构体主要用于存储一个数据包的相关信息。
typedef struct ndpi_packet_struct {
const struct ndpi_iphdr *iph;
#ifdef NDPI_DETECTION_SUPPORT_IPV6
const struct ndpi_ipv6hdr *iphv6;
#endif
const struct ndpi_tcphdr *tcp;
const struct ndpi_udphdr *udp;
const u_int8_t *generic_l4_ptr;
const u_int8_t *payload;
u_int16_t detected_protocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
u_int8_t detected_subprotocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
struct ndpi_int_one_line_struct line[NDPI_MAX_PARSE_LINES_PER_PACKET];
struct ndpi_int_one_line_struct host_line;
......
u_int16_t l3_packet_len; u_int16_t l4_packet_len;
u_int16_t payload_packet_len; u_int16_t actual_payload_len;
u_int16_t num_retried_bytes; u_int16_t parsed_lines;
u_int16_t parsed_unix_lines; u_int16_t empty_line_position;
u_int8_t tcp_retransmission; u_int8_t l4_protocol;
u_int8_t ssl_certificate_detected:4, ssl_certificate_num_checks:4;
u_int8_t packet_lines_parsed_complete:1, packet_direction:1,
empty_line_position_set:1;
} ndpi_packet_struct_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
4,ndpi_flow_struct
这个结构体用于存储一个数据流的相关信息,一个数据流可能会有很多个数据包。正因如此,所以在此结构体中定义了很多标识变量(有初始赋值的),用于区别不同的数据包和减少重复多余的工作。此外,还针对不同协议定义了很多变量。
typedef struct ndpi_flow_struct {
u_int16_t detected_protocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
u_int16_t guessed_protocol_id;
u_int8_t protocol_id_already_guessed:1;
u_int8_t no_cache_protocol:1;
u_int8_t init_finished:1;
u_int8_t setup_packet_direction:1;
u_int8_t packet_direction:1;
u_int32_t next_tcp_seq_nr[2];
struct {
ndpi_http_method method;
char *url, *content_type;
} http;
union {
struct {
u_int8_t num_queries, num_answers, ret_code;
u_int8_t bad_packet ;
u_int16_t query_type, query_class, rsp_type;
} dns;
struct {
char client_certificate[48], server_certificate[48];
} ssl;
} protos;
NDPI_PROTOCOL_BITMASK excluded_protocol_bitmask;
struct ndpi_packet_struct packet;
struct ndpi_flow_struct *flow;
struct ndpi_id_struct *src;
struct ndpi_id_struct *dst;
} ndpi_flow_struct_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
好了,先把几个比较重要的结构体简单介绍了一下,接下来会对ndpi检测流程进行介绍。因为也是刚刚接触,可能有的变量含义理解有误,希望大家指正。