zoukankan      html  css  js  c++  java
  • 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}。

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

    主要流程图:


    也许有错误,希望指教。




  • 相关阅读:
    SPOJ1007 VLATTICE
    hdu 4746Mophues[莫比乌斯反演]
    [Offer收割]编程练习赛13 B.最大子矩阵[枚举]
    [SCOI2011]飞镖[数学模拟]
    2333: [SCOI2011]棘手的操作[离线线段树]
    hdu3507 Print Article[斜率优化dp入门题]
    react 日期
    使用arc进行code review
    css冲突2 要关闭的css在项目代码以外,但是是通过<link>标签引入的css(例如bootstrap):解决方法,在APP.css中使用全局样式
    <svg>标签
  • 原文地址:https://www.cnblogs.com/lxgeek/p/2024157.html
Copyright © 2011-2022 走看看