opendpi 源码分析(二)

opendpi 源码分析(二)

先介绍opendpi如何设置各个协议的处理,然后介绍如何处理每一个包,最后是软件的流程图。

第一:首先看下要用到的重要的宏

View Code
     
     
#define IPOQUE_SAVE_AS_BITMASK(bitmask,value) (bitmask)=(((IPOQUE_PROTOCOL_BITMASK)1)<<(value)) #define IPOQUE_BITMASK_COMPARE(a,b) ((a) & (b)) #define IPOQUE_BITMASK_MATCH(x,y) ((x) == (y)) #define IPOQUE_BITMASK_COMPARE(a,b) ((a) & (b)) #define IPOQUE_COMPARE_PROTOCOL_TO_BITMASK(bmask,value) IPOQUE_BITMASK_COMPARE(bmask,IPOQUE_CONVERT_PROTOCOL_TO_BITMASK(value)) #define IPOQUE_CONVERT_PROTOCOL_TO_BITMASK(p) ( ((IPOQUE_PROTOCOL_BITMASK)1) << (p) ) #define IPOQUE_ADD_PROTOCOL_TO_BITMASK(bmask,value) IPOQUE_BITMASK_ADD(bmask,IPOQUE_CONVERT_PROTOCOL_TO_BITMASK(value)) #define IPOQUE_BITMASK_ADD(a,b) (a)|=(b) #define IPOQUE_BITMASK_SET(a,b) (a)=(b) #define IPOQUE_DEL_PROTOCOL_FROM_BITMASK(bmask,value) IPOQUE_BITMASK_DEL(bmask,IPOQUE_CONVERT_PROTOCOL_TO_BITMASK(value)) #define IPOQUE_BITMASK_DEL(a,b) (a)=((a) & (~(b))) #define IPOQUE_BITMASK_SET_ALL(a) (a) = ((IPOQUE_PROTOCOL_BITMASK)0xFFFFFFFFFFFFFFFFULL) #define IPOQUE_BITMASK_RESET(a) (a) = 0

然后是标识协议掩码的数据结构:

复制代码
    
    
#if IPOQUE_MAX_SUPPORTED_PROTOCOLS >= 128 typedef struct ipoque_protocol_bitmask_struct { u64 bitmask[ 3 ]; } ipoque_protocol_bitmask_struct_t; #define IPOQUE_PROTOCOL_BITMASK struct ipoque_protocol_bitmask_struct #elif IPOQUE_MAX_SUPPORTED_PROTOCOLS >= 64 typedef struct ipoque_protocol_bitmask_struct { u64 bitmask[ 2 ]; } ipoque_protocol_bitmask_struct_t; #define IPOQUE_PROTOCOL_BITMASK struct ipoque_protocol_bitmask_struct #if IPOQUE_MAX_SUPPORTED_PROTOCOLS >= 128 typedef struct ipoque_protocol_bitmask_struct { u64 bitmask[ 3 ]; } ipoque_protocol_bitmask_struct_t; #define IPOQUE_PROTOCOL_BITMASK struct ipoque_protocol_bitmask_struct #elif IPOQUE_MAX_SUPPORTED_PROTOCOLS >= 64 typedef struct ipoque_protocol_bitmask_struct { u64 bitmask[ 2 ]; } ipoque_protocol_bitmask_struct_t; #define IPOQUE_PROTOCOL_BITMASK struct ipoque_protocol_bitmask_struct #else #define IPOQUE_PROTOCOL_BITMASK u64 #endif #ifndef u64 #define u64 unsigned long long #endif #ifndef u32 #define u32 unsigned int #endif #ifndef u16 #define u16 unsigned short #endif #ifndef u8 #define u8 unsigned char #endif
复制代码

我开始的时候一直以为 IPOQUE_PROTOCOL_BITMASK是整型,没想到是个结构体。

在函数ipoque_set_protocol_detection_bitmask2中开启了对某个固定协议的处理,比如这样就开启了所有协议来检测包:

    
    
// enable all protocols IPOQUE_BITMASK_SET_ALL(all); ipoque_set_protocol_detection_bitmask2(ipoque_struct, & all);

在具体的一种协议的实现中是这样处理的,比如YAHOO:

View Code
     
     
#ifdef IPOQUE_PROTOCOL_YAHOO if (IPOQUE_COMPARE_PROTOCOL_TO_BITMASK( * detection_bitmask, IPOQUE_PROTOCOL_YAHOO) != 0 ) { ipoque_struct -> callback_buffer[a].func = ipoque_search_yahoo; ipoque_struct -> callback_buffer[a].ipq_selection_bitmask = IPQ_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP; IPOQUE_SAVE_AS_BITMASK(ipoque_struct -> callback_buffer[a].detection_bitmask, IPOQUE_PROTOCOL_UNKNOWN); IPOQUE_ADD_PROTOCOL_TO_BITMASK(ipoque_struct -> callback_buffer[a].detection_bitmask, IPOQUE_PROTOCOL_YAHOO); IPOQUE_SAVE_AS_BITMASK(ipoque_struct -> callback_buffer[a].excluded_protocol_bitmask, IPOQUE_PROTOCOL_YAHOO); a ++ ; }

而函数ipoque_search_yahoo就是存在于目录protocol中,对于YAHOO的具体检查,实现如下:

View Code
     
     
void ipoque_search_yahoo( struct ipoque_detection_module_struct * ipoque_struct) { struct ipoque_packet_struct * packet = & ipoque_struct -> packet; struct ipoque_flow_struct * flow = ipoque_struct -> flow; IPQ_LOG(IPOQUE_PROTOCOL_YAHOO, ipoque_struct, IPQ_LOG_DEBUG, " search yahoo\n " ); if (packet -> payload_packet_len > 0 && flow -> yahoo_detection_finished == 0 ) { if (packet -> tcp != NULL && packet -> tcp_retransmission == 0 ) { #ifdef IPOQUE_PROTOCOL_HTTP if (packet -> detected_protocol == IPOQUE_PROTOCOL_UNKNOWN || packet -> detected_protocol == IPOQUE_PROTOCOL_HTTP) #else if (packet -> detected_protocol == IPOQUE_PROTOCOL_UNKNOWN) #endif { ipoque_search_yahoo_tcp(ipoque_struct); } } else if (packet -> udp != NULL) { ipoque_search_yahoo_udp(ipoque_struct); } } if (packet -> payload_packet_len > 0 && flow -> yahoo_detection_finished == 2 ) { if (packet -> tcp != NULL && packet -> tcp_retransmission == 0 ) { ipoque_search_yahoo_tcp(ipoque_struct); } } }

这个函数检查了YAHOO是基于UDP还是TCP,还有没有payload长度是不是等于0.

这样就建立了一个匹配的模式数据库。

第二:对于每一个包,在这个函数中从pcap文件中获得:

    
    
// executed for each packet in the pcap file static void pcap_packet_callback(u_char * args, const struct pcap_pkthdr * header, const u_char * packet)
然后在函数
    
    
// here the actual detection is performed protocol = ipoque_detection_process_packet(ipoque_struct, ipq_flow, (uint8_t * ) iph, ipsize, time, src, dst);

这是对每个包的具体处理,而返回值就是我们所想要知道的,这个包所属于的协议号。

在函数 ipoque_detection_process_packet中最重要的是如下的代码:

复制代码
    
    
if (flow != NULL && ipoque_struct -> packet.tcp != NULL) { if (ipoque_struct -> packet.payload_packet_len != 0 ) { for (a = 0 ; a < ipoque_struct -> callback_buffer_size_tcp_payload; a ++ ) { if ((ipoque_struct -> callback_buffer_tcp_payload[a].ipq_selection_bitmask & ipq_selection_packet) == ipoque_struct -> callback_buffer_tcp_payload[a].ipq_selection_bitmask && IPOQUE_BITMASK_COMPARE(ipoque_struct -> flow -> excluded_protocol_bitmask, ipoque_struct -> callback_buffer_tcp_payload[a].excluded_protocol_bitmask) == 0 && IPOQUE_BITMASK_COMPARE(ipoque_struct -> callback_buffer_tcp_payload[a].detection_bitmask, detection_bitmask) != 0 ) { ipoque_struct -> callback_buffer_tcp_payload[a].func(ipoque_struct); } }
复制代码

首先判断了payload,而ipq_selection_packet依赖于下面的这些判断:

View Code
     
     
/* build ipq_selction packet bitmask */ ipq_selection_packet = IPQ_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC; if (ipoque_struct -> packet.iph != NULL) { ipq_selection_packet |= IPQ_SELECTION_BITMASK_PROTOCOL_IP | IPQ_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6; } if (ipoque_struct -> packet.tcp != NULL) { ipq_selection_packet |= (IPQ_SELECTION_BITMASK_PROTOCOL_INT_TCP | IPQ_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP); } if (ipoque_struct -> packet.udp != NULL) { ipq_selection_packet |= (IPQ_SELECTION_BITMASK_PROTOCOL_INT_UDP | IPQ_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP); } if (ipoque_struct -> packet.payload_packet_len != 0 ) { ipq_selection_packet |= IPQ_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD; } if (ipoque_struct -> packet.tcp_retransmission == 0 ) { ipq_selection_packet |= IPQ_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION; }

excluded_protocol_bitmask是设置不需要检查的协议,我们上面已经设置为all。

detection_bitmask通过这样初始化:

View Code
     
     
#define IPOQUE_CONVERT_PROTOCOL_TO_BITMASK(p) ( ((IPOQUE_PROTOCOL_BITMASK)1) << (p) ) IPOQUE_SAVE_AS_BITMASK(detection_bitmask, ipoque_struct -> packet.detected_protocol);

通过gdb可以查看 detection_bitmask的值是:bitmask = {1, 0}。

这样就把每一个包放入已有的协议模式去匹配。

主要流程图:


也许有错误,希望指教。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值