ndpi源码分析一--几个重要的结构体

最近研究了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;//源IP
  u_int32_t daddr;//目的IP
};

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;
//回调数组,当检测协议时会逐个进行遍历,调用相应协议检测函数。这是总的,下面又分为tcp/udp
  struct ndpi_call_function_struct callback_buffer[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
  u_int32_t callback_buffer_size;//=150,下面数字也都是调试过程中得到,可能不同版本支持协议数不同
//基于tcp协议且不带负载,共有11种
  struct ndpi_call_function_struct callback_buffer_tcp_no_payload[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
  u_int32_t callback_buffer_size_tcp_no_payload;
//基于tcp且带负载协议的应用,共113种
  struct ndpi_call_function_struct callback_buffer_tcp_payload[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
  u_int32_t callback_buffer_size_tcp_payload;
//基于udp协议的应用,共73种
  struct ndpi_call_function_struct callback_buffer_udp[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
  u_int32_t callback_buffer_size_udp;
//既不是基于tcp也不是基于udp协议类型,共10种;
  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;
  /* IP-based protocol detection */
  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; /* disable internal detection of packet direction */
} ndpi_detection_module_struct_t;

3,ndpi_packet_struct
这个结构体主要用于存储一个数据包的相关信息。

typedef struct ndpi_packet_struct {
  const struct ndpi_iphdr *iph;//ip层信息
#ifdef NDPI_DETECTION_SUPPORT_IPV6
  const struct ndpi_ipv6hdr *iphv6;
#endif
  const struct ndpi_tcphdr *tcp;//tcp协议头
  const struct ndpi_udphdr *udp;//udp协议头
  const u_int8_t *generic_l4_ptr;   /* is set only for non tcp-udp traffic */
  const u_int8_t *payload;//负载。数据包再除去数据链路层信息后,接下来是ip层信息,在接下来是传输层信息,即tcp/udp/generic_l4_ptr,再接下来就是负载信息。
  u_int16_t detected_protocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
  u_int8_t detected_subprotocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
//接下来是有关http协议的一些变量定义,不全部列出
  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;

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; /* if ndpi_struct->direction_detect_disable == 1 */
  /* tcp sequence number connection tracking */
  u_int32_t next_tcp_seq_nr[2];
//http协议相关信息
  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 /* the received packet looks bad */;
      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;

  /* 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;
} ndpi_flow_struct_t;

好了,先把几个比较重要的结构体简单介绍了一下,接下来会对ndpi检测流程进行介绍。因为也是刚刚接触,可能有的变量含义理解有误,希望大家指正。

你可能感兴趣的:(源码,ndpi)