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
};
  • 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;
//回調數組,當檢測協議時會逐個進行遍歷,調用相應協議檢測函數。這是總的,下面又分爲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;
  • 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;//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;
  • 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; /* 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;
  • 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檢測流程進行介紹。因爲也是剛剛接觸,可能有的變量含義理解有誤,希望大家指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章