Wireshark 插件:通过每个 UDP 帧多个数据包剖析有效负载

发布于 2024-09-04 02:25:16 字数 412 浏览 2 评论 0原文

我正在编写一个 Wireshark 插件来剖析将多个应用程序级数据包放入单个 UDP 帧中的协议。没有封闭协议来指示帧中有多少个数据包。因此,本质上,来自网络的有效负载将如下所示:

uint64  sequence1
uint64  data1
uint8  flags1
uint64  sequence2
uint64  data2
uint8  flags2
: : :
uint64  sequence_n
uint64  data_n
uint8  flags_n

在实际处理此信息的服务器代码中,我只是循环遍历帧,直到到达末尾。在查看wireshark源代码中包含的插件时,我没有看到任何协议执行这样的循环。

我知道其他协议每帧打包多个有效负载。在 Wireshark 解析器中处理此类协议的规范或标准方法是什么?

I am writing a Wireshark plugin to dissect a protocol that places multiple application-level packets in a single UDP frame. There is no enclosing protocol that indicates how many packets there are in the frame. So essentially, the payload coming down the wire will look like this:

uint64  sequence1
uint64  data1
uint8  flags1
uint64  sequence2
uint64  data2
uint8  flags2
: : :
uint64  sequence_n
uint64  data_n
uint8  flags_n

In my server code that actually processes this information, I simply loop through the frame until I reach the end. In looking through the plugins included with the wireshark source code, I didn't see any protocols that did any looping like this.

I know other protocols pack multiple payloads per frame. What is the cannonical or standard way to handle protocols like this in a Wireshark dissector?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

单身情人 2024-09-11 02:25:16

我找到了一个对我有用的答案。我只是在解析器中循环,对我处理的每个字段增加一个 offset 值,直到 offset > 。 tvb_reported_length(tvb)。在每个循环中,我向父树项目添加一个新的子树,以便框架内的每个单独的消息都位于其自己的树中。

编辑:为了您的娱乐,这里是完整的CQS的解剖代码,包括处理每个 UDP 帧多个数据包的代码:

static int dissect_cqs(tvbuff_t* tvb, 
                       packet_info* pinfo, 
                       proto_tree* tree)
{
    guint offset = 0;
    proto_item* ti = 0;
    char msgcat = '\0';
    gint field_sz;
    static const char soh = 0x01, us = 0x1F, etx = 0x03;
    proto_tree* cqs_tree, *frame_tree, *packet_tree;
    guint8 ts_hour, ts_minute,ts_second;
    char ts_msec_str[3];
    char cattype [2];
    int found = 0;
    guint i;
    char seq_str[9+1];
    guint32 seq;
    guint32 firstseq = 0, msgcount = 0;
    guint framegaps = 0;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CQS");
    col_clear(pinfo->cinfo, COL_INFO);

    ti = proto_tree_add_item(tree, proto_cqs, tvb, offset, -1, FALSE); 
    cqs_tree = proto_item_add_subtree(ti, ett_cqs);
    ti = proto_tree_add_item(cqs_tree, hf_cqs_frame_subtree, tvb, offset, -1, FALSE);
    frame_tree = proto_item_add_subtree(ti, ett_frame);

    /** APPEND THE LEADING CONTROL CHARACTER **/
    field_sz = 1;    ti = proto_tree_add_item(frame_tree, hf_cqs_ctrl, tvb, offset, field_sz, FALSE) ; offset += field_sz;


    while( offset < tvb_reported_length(tvb) )
    {
        /** get the message type, category & sequence number **/
        tvb_memcpy(tvb, cattype, offset, 2);
        tvb_memcpy(tvb, seq_str, offset+8, 9);
        seq_str[9] = 0;
        seq = atol(seq_str);

        ++msgcount;
        if( !firstseq )
            firstseq = seq;
        else
            framegaps += (seq - firstseq) - (msgcount - 1);

        ti = proto_tree_add_none_format(frame_tree, hf_cqs_packet_subtree, tvb, offset, 24, "CQS Packet [%ld]", seq);
        if( ti )    packet_tree = proto_item_add_subtree(ti, ett_packet);
        else        packet_tree = 0;

        /** dissect the packet header **/
        cattype[0] = tvb_get_guint8(tvb, offset);
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_msgcat, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        cattype[1] = tvb_get_guint8(tvb, offset);
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_msgtype, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_msgnet, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 2;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_retran, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_hdrid, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 2;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_rsv, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 9;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_seq, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_partid, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        ts_hour = tvb_get_guint8(tvb, offset) - '0';
        ts_minute = tvb_get_guint8(tvb, offset+1) - '0';
        ts_second = tvb_get_guint8(tvb, offset+2) - '0';
        ts_msec_str[0] = tvb_get_guint8(tvb, offset+3);
        ts_msec_str[1] = tvb_get_guint8(tvb, offset+4);
        ts_msec_str[2] = tvb_get_guint8(tvb, offset+5);
        field_sz = 6;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_time, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        if( tree )
        {
            proto_item_set_text(ti, "CQS Timestamp: %02d:%02d:%02d.%c%c%c %cM", (ts_hour > 11) ? (ts_hour-12) : ts_hour, ts_minute, ts_second, ts_msec_str[0], ts_msec_str[1], ts_msec_str[2], (ts_hour > 11) ? 'P' : 'A');
        }

        /** COUNT UP BYTES UNTIL WE FIND A CONTROL CHARACTER **/
        field_sz = 0;
        found = 0;
        for( i = 0; !found && offset+i < tvb_reported_length(tvb); ++i )
        {
            char c = tvb_get_guint8(tvb, offset+i);
            switch( c )
            {
            case 0x01 : /** SOH **/
            case 0x1F : /** US **/
            case 0x03 : /* ETX **/
                found = 1;
                break;
            default :
                ++field_sz;
                break;
            }
        }
        /** APPEND THE DATA PAYLOAD **/
        ti = proto_tree_add_item(packet_tree, hf_cqs_payload, tvb, offset, field_sz, FALSE) ; offset += field_sz;

        /** APPEND THE TRAILING CONTROL CHARACTER **/
        field_sz = 1;    ti = proto_tree_add_item(frame_tree, hf_cqs_ctrl, tvb, offset, field_sz, FALSE) ; offset += field_sz;
    }

    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_first_seq, tvb, 0, 0, firstseq);
    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_expected_seq, tvb, 0, 0, firstseq+msgcount);
    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_msgcount, tvb, 0, 0, msgcount);
    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_gaps, tvb, 0, 0, framegaps);


    return tvb_length(tvb);
}

I found an answer that worked for me. I simply loop within the dissector, incrementing an offset value with each field I process until offset > tvb_reported_length(tvb). In each loop I add a new subtree to the parent tree item, so that each individual message within the frame is in its own tree.

EDIT: For your amusement, here's the complete disscection code for CQS, including the code that handles multiple packets per UDP frame:

static int dissect_cqs(tvbuff_t* tvb, 
                       packet_info* pinfo, 
                       proto_tree* tree)
{
    guint offset = 0;
    proto_item* ti = 0;
    char msgcat = '\0';
    gint field_sz;
    static const char soh = 0x01, us = 0x1F, etx = 0x03;
    proto_tree* cqs_tree, *frame_tree, *packet_tree;
    guint8 ts_hour, ts_minute,ts_second;
    char ts_msec_str[3];
    char cattype [2];
    int found = 0;
    guint i;
    char seq_str[9+1];
    guint32 seq;
    guint32 firstseq = 0, msgcount = 0;
    guint framegaps = 0;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CQS");
    col_clear(pinfo->cinfo, COL_INFO);

    ti = proto_tree_add_item(tree, proto_cqs, tvb, offset, -1, FALSE); 
    cqs_tree = proto_item_add_subtree(ti, ett_cqs);
    ti = proto_tree_add_item(cqs_tree, hf_cqs_frame_subtree, tvb, offset, -1, FALSE);
    frame_tree = proto_item_add_subtree(ti, ett_frame);

    /** APPEND THE LEADING CONTROL CHARACTER **/
    field_sz = 1;    ti = proto_tree_add_item(frame_tree, hf_cqs_ctrl, tvb, offset, field_sz, FALSE) ; offset += field_sz;


    while( offset < tvb_reported_length(tvb) )
    {
        /** get the message type, category & sequence number **/
        tvb_memcpy(tvb, cattype, offset, 2);
        tvb_memcpy(tvb, seq_str, offset+8, 9);
        seq_str[9] = 0;
        seq = atol(seq_str);

        ++msgcount;
        if( !firstseq )
            firstseq = seq;
        else
            framegaps += (seq - firstseq) - (msgcount - 1);

        ti = proto_tree_add_none_format(frame_tree, hf_cqs_packet_subtree, tvb, offset, 24, "CQS Packet [%ld]", seq);
        if( ti )    packet_tree = proto_item_add_subtree(ti, ett_packet);
        else        packet_tree = 0;

        /** dissect the packet header **/
        cattype[0] = tvb_get_guint8(tvb, offset);
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_msgcat, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        cattype[1] = tvb_get_guint8(tvb, offset);
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_msgtype, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_msgnet, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 2;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_retran, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_hdrid, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 2;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_rsv, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 9;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_seq, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        field_sz = 1;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_partid, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        ts_hour = tvb_get_guint8(tvb, offset) - '0';
        ts_minute = tvb_get_guint8(tvb, offset+1) - '0';
        ts_second = tvb_get_guint8(tvb, offset+2) - '0';
        ts_msec_str[0] = tvb_get_guint8(tvb, offset+3);
        ts_msec_str[1] = tvb_get_guint8(tvb, offset+4);
        ts_msec_str[2] = tvb_get_guint8(tvb, offset+5);
        field_sz = 6;    ti = proto_tree_add_item(packet_tree, hf_cqs_hdr_time, tvb, offset, field_sz, FALSE) ; offset += field_sz;
        if( tree )
        {
            proto_item_set_text(ti, "CQS Timestamp: %02d:%02d:%02d.%c%c%c %cM", (ts_hour > 11) ? (ts_hour-12) : ts_hour, ts_minute, ts_second, ts_msec_str[0], ts_msec_str[1], ts_msec_str[2], (ts_hour > 11) ? 'P' : 'A');
        }

        /** COUNT UP BYTES UNTIL WE FIND A CONTROL CHARACTER **/
        field_sz = 0;
        found = 0;
        for( i = 0; !found && offset+i < tvb_reported_length(tvb); ++i )
        {
            char c = tvb_get_guint8(tvb, offset+i);
            switch( c )
            {
            case 0x01 : /** SOH **/
            case 0x1F : /** US **/
            case 0x03 : /* ETX **/
                found = 1;
                break;
            default :
                ++field_sz;
                break;
            }
        }
        /** APPEND THE DATA PAYLOAD **/
        ti = proto_tree_add_item(packet_tree, hf_cqs_payload, tvb, offset, field_sz, FALSE) ; offset += field_sz;

        /** APPEND THE TRAILING CONTROL CHARACTER **/
        field_sz = 1;    ti = proto_tree_add_item(frame_tree, hf_cqs_ctrl, tvb, offset, field_sz, FALSE) ; offset += field_sz;
    }

    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_first_seq, tvb, 0, 0, firstseq);
    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_expected_seq, tvb, 0, 0, firstseq+msgcount);
    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_msgcount, tvb, 0, 0, msgcount);
    ti = proto_tree_add_uint(cqs_tree, hf_cqs_frame_gaps, tvb, 0, 0, framegaps);


    return tvb_length(tvb);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文