我正在编写一个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解剖器中处理这样的协议的经典或标准方法是什么?
答案 0 :(得分:3)
我找到了一个对我有用的答案。我只是在解剖器中循环,为我处理的每个字段递增offset
值,直到offset > tvb_reported_length(tvb)
。在每个循环中,我向父树项添加一个新的子树,以便框架中的每个单独的消息都在它自己的树中。
编辑:为了您的娱乐,这里是完整的disscection code for 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);
}