Reassembly: add helper macros
Add REASSEMBLE_ITEMS_DEFINE, REASSEMBLE_INIT_HF_ITEMS and REASSEMBLE_INIT_ETT_ITEMS helper macros to define and initialize hf and ett items of reassembly much easier. Make packet-http.c to use these macros.
This commit is contained in:
parent
d7eedba8e2
commit
cd3275c1b5
|
@ -137,18 +137,6 @@ static int hf_http_unknown_header = -1;
|
|||
static int hf_http_http2_settings_uri = -1;
|
||||
static int hf_http_path_segment = -1;
|
||||
static int hf_http_path_sub_segment = -1;
|
||||
static int hf_http_body_fragments = -1;
|
||||
static int hf_http_body_fragment = -1;
|
||||
static int hf_http_body_fragment_overlap = -1;
|
||||
static int hf_http_body_fragment_overlap_conflicts = -1;
|
||||
static int hf_http_body_fragment_multiple_tails = -1;
|
||||
static int hf_http_body_fragment_too_long_fragment = -1;
|
||||
static int hf_http_body_fragment_error = -1;
|
||||
static int hf_http_body_fragment_count = -1;
|
||||
static int hf_http_body_reassembled_in = -1;
|
||||
static int hf_http_body_reassembled_length = -1;
|
||||
static int hf_http_body_reassembled_data = -1;
|
||||
static int hf_http_body_segment = -1;
|
||||
|
||||
static gint ett_http = -1;
|
||||
static gint ett_http_ntlmssp = -1;
|
||||
|
@ -162,8 +150,6 @@ static gint ett_http_encoded_entity = -1;
|
|||
static gint ett_http_header_item = -1;
|
||||
static gint ett_http_http2_settings_item = -1;
|
||||
static gint ett_http_path = -1;
|
||||
static gint ett_http_body_fragment = -1;
|
||||
static gint ett_http_body_fragments = -1;
|
||||
|
||||
static expert_field ei_http_chat = EI_INIT;
|
||||
static expert_field ei_http_te_and_length = EI_INIT;
|
||||
|
@ -194,24 +180,7 @@ static ws_mempbrk_pattern pbrk_sub_delims;
|
|||
/* reassembly table for streaming chunk mode */
|
||||
static reassembly_table http_streaming_reassembly_table;
|
||||
|
||||
static const fragment_items http_body_fragment_items = {
|
||||
/* Fragment subtrees */
|
||||
&ett_http_body_fragment,
|
||||
&ett_http_body_fragments,
|
||||
/* Fragment fields */
|
||||
&hf_http_body_fragments,
|
||||
&hf_http_body_fragment,
|
||||
&hf_http_body_fragment_overlap,
|
||||
&hf_http_body_fragment_overlap_conflicts,
|
||||
&hf_http_body_fragment_multiple_tails,
|
||||
&hf_http_body_fragment_too_long_fragment,
|
||||
&hf_http_body_fragment_error,
|
||||
&hf_http_body_fragment_count,
|
||||
&hf_http_body_reassembled_in,
|
||||
&hf_http_body_reassembled_length,
|
||||
&hf_http_body_reassembled_data,
|
||||
"Reassembled HTTP Chunked Body fragments"
|
||||
};
|
||||
REASSEMBLE_ITEMS_DEFINE(http_body, "HTTP Chunked Body");
|
||||
|
||||
/* HTTP chunk virtual frame number (similar to HTTP2 frame num) */
|
||||
#define get_http_chunk_frame_num get_virtual_frame_num64
|
||||
|
@ -4433,66 +4402,7 @@ proto_register_http(void)
|
|||
NULL, HFILL } },
|
||||
|
||||
/* Body fragments */
|
||||
{ &hf_http_body_fragments,
|
||||
{ "Reassembled HTTP Chunked Body fragments", "http.body.fragments",
|
||||
FT_NONE, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_fragment,
|
||||
{ "Body fragment", "http.body.fragment",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_fragment_overlap,
|
||||
{ "Body fragment overlap", "http.body.fragment.overlap",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_fragment_overlap_conflicts,
|
||||
{ "Body fragment overlapping with conflicting data", "http.body.fragment.overlap.conflicts",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_fragment_multiple_tails,
|
||||
{ "Body has multiple tail fragments", "http.body.fragment.multiple_tails",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_fragment_too_long_fragment,
|
||||
{ "Body fragment too long", "http.body.fragment.too_long_fragment",
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_fragment_error,
|
||||
{ "Body defragment error", "http.body.fragment.error",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_fragment_count,
|
||||
{ "Body fragment count", "http.body.fragment.count",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL }
|
||||
},
|
||||
{ &hf_http_body_reassembled_in,
|
||||
{ "Reassembled body in frame", "http.body.reassembled.in",
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
||||
"Reassembled body in frame number", HFILL }
|
||||
},
|
||||
{ &hf_http_body_reassembled_length,
|
||||
{ "Reassembled body length", "http.body.reassembled.length",
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0,
|
||||
"Reassembled body in frame number", HFILL }
|
||||
},
|
||||
{ &hf_http_body_reassembled_data,
|
||||
{ "Reassembled body data", "http.body.reassembled.data",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0,
|
||||
"Reassembled body data for multisegment PDU spanning across DATAs", HFILL }
|
||||
},
|
||||
{ &hf_http_body_segment,
|
||||
{ "Body segment", "http.body.segment",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0,
|
||||
"A body segment used in reassembly", HFILL}
|
||||
},
|
||||
REASSEMBLE_INIT_HF_ITEMS(http_body, "HTTP Chunked Body", "http.body"),
|
||||
};
|
||||
static gint *ett[] = {
|
||||
&ett_http,
|
||||
|
@ -4506,8 +4416,7 @@ proto_register_http(void)
|
|||
&ett_http_encoded_entity,
|
||||
&ett_http_header_item,
|
||||
&ett_http_http2_settings_item,
|
||||
&ett_http_body_fragment,
|
||||
&ett_http_body_fragments,
|
||||
REASSEMBLE_INIT_ETT_ITEMS(http_body),
|
||||
&ett_http_path
|
||||
};
|
||||
|
||||
|
|
|
@ -531,6 +531,196 @@ extern void
|
|||
reassembly_table_cleanup(void);
|
||||
|
||||
/* ===================== Streaming data reassembly helper ===================== */
|
||||
/**
|
||||
* Macro to help to define ett or hf items variables for reassembly (especially for streaming reassembly).
|
||||
* The statement:
|
||||
*
|
||||
* REASSEMBLE_ITEMS_DEFINE(foo_body, "Foo Body"); // in global scope
|
||||
*
|
||||
* will create global variables:
|
||||
*
|
||||
* static gint ett_foo_body_fragment = -1;
|
||||
* static gint ett_foo_body_fragments = -1;
|
||||
* static int hf_foo_body_fragment = -1;
|
||||
* static int hf_foo_body_fragments = -1;
|
||||
* static int hf_foo_body_fragment_overlap = -1;
|
||||
* ...
|
||||
* static int hf_foo_body_segment = -1;
|
||||
*
|
||||
* static const fragment_items foo_body_fragment_items = {
|
||||
* &ett_foo_body_fragment,
|
||||
* &ett_foo_body_fragments,
|
||||
* &hf_foo_body_fragments,
|
||||
* &hf_foo_body_fragment,
|
||||
* &hf_foo_body_fragment_overlap,
|
||||
* ...
|
||||
* "Foo Body fragments"
|
||||
* };
|
||||
*/
|
||||
#define REASSEMBLE_ITEMS_DEFINE(var_prefix, name_prefix) \
|
||||
static gint ett_##var_prefix##_fragment = -1; \
|
||||
static gint ett_##var_prefix##_fragments = -1; \
|
||||
static int hf_##var_prefix##_fragments = -1; \
|
||||
static int hf_##var_prefix##_fragment = -1; \
|
||||
static int hf_##var_prefix##_fragment_overlap = -1; \
|
||||
static int hf_##var_prefix##_fragment_overlap_conflicts = -1; \
|
||||
static int hf_##var_prefix##_fragment_multiple_tails = -1; \
|
||||
static int hf_##var_prefix##_fragment_too_long_fragment = -1; \
|
||||
static int hf_##var_prefix##_fragment_error = -1; \
|
||||
static int hf_##var_prefix##_fragment_count = -1; \
|
||||
static int hf_##var_prefix##_reassembled_in = -1; \
|
||||
static int hf_##var_prefix##_reassembled_length = -1; \
|
||||
static int hf_##var_prefix##_reassembled_data = -1; \
|
||||
static int hf_##var_prefix##_segment = -1; \
|
||||
static const fragment_items var_prefix##_fragment_items = { \
|
||||
&ett_##var_prefix##_fragment, \
|
||||
&ett_##var_prefix##_fragments, \
|
||||
&hf_##var_prefix##_fragments, \
|
||||
&hf_##var_prefix##_fragment, \
|
||||
&hf_##var_prefix##_fragment_overlap, \
|
||||
&hf_##var_prefix##_fragment_overlap_conflicts, \
|
||||
&hf_##var_prefix##_fragment_multiple_tails, \
|
||||
&hf_##var_prefix##_fragment_too_long_fragment, \
|
||||
&hf_##var_prefix##_fragment_error, \
|
||||
&hf_##var_prefix##_fragment_count, \
|
||||
&hf_##var_prefix##_reassembled_in, \
|
||||
&hf_##var_prefix##_reassembled_length, \
|
||||
&hf_##var_prefix##_reassembled_data, \
|
||||
name_prefix " fragments" \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro to help to initialize hf (head field) items for reassembly.
|
||||
* The statement:
|
||||
*
|
||||
* void proto_register_foo(void) {
|
||||
* static hf_register_info hf[] = {
|
||||
* ...
|
||||
* { &hf_proto_foo_payload,
|
||||
* { "Payload", "foo.payload",
|
||||
* FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
|
||||
* },
|
||||
*
|
||||
* // Add fragments items
|
||||
* REASSEMBLE_INIT_HF_ITEMS(foo_body, "Foo Body", "foo.body"),
|
||||
* ...
|
||||
* };
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* will expand like:
|
||||
*
|
||||
* void proto_register_foo(void) {
|
||||
* static hf_register_info hf[] = {
|
||||
* ...
|
||||
* { &hf_proto_foo_payload,
|
||||
* { "Payload", "foo.payload",
|
||||
* FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
|
||||
* },
|
||||
*
|
||||
* // Add fragments items
|
||||
* { &hf_foo_body_fragments, \
|
||||
* { "Reassembled Foo Body fragments", "foo.body.fragments", \
|
||||
* FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
* },
|
||||
* { &hf_foo_body_fragment, \
|
||||
* { "Foo Body fragment", "foo.body.fragment", \
|
||||
* FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
* },
|
||||
* { &hf_foo_body_fragment_overlap, \
|
||||
* { "Foo Body fragment overlap", "foo.body.fragment.overlap", \
|
||||
* FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
* },
|
||||
* ...
|
||||
* };
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
#define REASSEMBLE_INIT_HF_ITEMS(var_prefix, name_prefix, abbrev_prefix) \
|
||||
{ &hf_##var_prefix##_fragments, \
|
||||
{ "Reassembled " name_prefix " fragments", abbrev_prefix ".fragments", \
|
||||
FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_fragment, \
|
||||
{ name_prefix " fragment", abbrev_prefix ".fragment", \
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_fragment_overlap, \
|
||||
{ name_prefix " fragment overlap", abbrev_prefix ".fragment.overlap", \
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_fragment_overlap_conflicts, \
|
||||
{ name_prefix " fragment overlapping with conflicting data", abbrev_prefix ".fragment.overlap.conflicts", \
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_fragment_multiple_tails, \
|
||||
{ name_prefix " has multiple tail fragments", abbrev_prefix ".fragment.multiple_tails", \
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_fragment_too_long_fragment, \
|
||||
{ name_prefix " fragment too long", abbrev_prefix ".fragment.too_long_fragment", \
|
||||
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_fragment_error, \
|
||||
{ name_prefix " defragment error", abbrev_prefix ".fragment.error", \
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_fragment_count, \
|
||||
{ name_prefix " fragment count", abbrev_prefix ".fragment.count", \
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_reassembled_in, \
|
||||
{ "Reassembled in", abbrev_prefix ".reassembled.in", \
|
||||
FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_reassembled_length, \
|
||||
{ "Reassembled length", abbrev_prefix ".reassembled.length", \
|
||||
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_reassembled_data, \
|
||||
{ "Reassembled data", abbrev_prefix ".reassembled.data", \
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } \
|
||||
}, \
|
||||
{ &hf_##var_prefix##_segment, \
|
||||
{ name_prefix " segment", abbrev_prefix ".segment", \
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro to help to initialize protocol subtree (ett) items for reassembly.
|
||||
* The statement:
|
||||
*
|
||||
* void proto_register_foo(void) {
|
||||
* ...
|
||||
* static gint* ett[] = {
|
||||
* &ett_foo_abc,
|
||||
* ...
|
||||
* // Add ett items
|
||||
* REASSEMBLE_INIT_ETT_ITEMS(foo_body),
|
||||
* ...
|
||||
* };
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* will expand like:
|
||||
*
|
||||
* void proto_register_foo(void) {
|
||||
* ...
|
||||
* static gint* ett[] = {
|
||||
* &ett_foo_abc,
|
||||
* ...
|
||||
* // Add ett items
|
||||
* &ett_foo_body_fragment,
|
||||
* &ett_foo_body_fragments,
|
||||
* ...
|
||||
* };
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
#define REASSEMBLE_INIT_ETT_ITEMS(var_prefix) \
|
||||
&ett_##var_prefix##_fragment, \
|
||||
&ett_##var_prefix##_fragments
|
||||
|
||||
/** a private structure for keeping streaming reassembly information */
|
||||
typedef struct streaming_reassembly_info_t streaming_reassembly_info_t;
|
||||
|
||||
|
@ -643,7 +833,7 @@ streaming_reassembly_info_new(void);
|
|||
* pinfo->desegment_offset = offset;
|
||||
* // calculate how many additional bytes needed to parse head of a ProtoB message
|
||||
* pinfo->desegment_len = PROTO_B_MESSAGE_HEAD_LEN - (tvb_len - offset);
|
||||
* return tvb_len;
|
||||
* return offset; // return the length handled by ProtoB
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
|
@ -657,12 +847,13 @@ streaming_reassembly_info_new(void);
|
|||
* pinfo->desegment_offset = offset;
|
||||
* // caculate how many additional bytes need to parsing body of a ProtoB message
|
||||
* pinfo->desegment_len = body_len - (tvb_len - offset - PROTO_B_MESSAGE_HEAD_LEN);
|
||||
* return tvb_len;
|
||||
* return offset;
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* return tvb_len; // all bytes of this tvb are parsed
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
|
@ -792,6 +983,67 @@ streaming_reassembly_info_new(void);
|
|||
* }
|
||||
* </code>
|
||||
*
|
||||
* Alternatively, the code of ProtoA (packet-proto-a.c) can be made simpler with helper macros:
|
||||
* <code>
|
||||
* // file packet-proto-a.c
|
||||
* ...
|
||||
* // reassembly table for streaming chunk mode
|
||||
* static reassembly_table proto_a_streaming_reassembly_table;
|
||||
* // reassembly head field items definition
|
||||
* REASSEMBLE_ITEMS_DEFINE(proto_a_body, "ProtoA Body");
|
||||
* ...
|
||||
* static int
|
||||
* dissect_proto_a(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
|
||||
* {
|
||||
* ...
|
||||
* streaming_reassembly_info_t* streaming_reassembly_info = NULL;
|
||||
* ...
|
||||
* proto_a_tree = proto_item_add_subtree(ti, ett_proto_a);
|
||||
* ...
|
||||
* if (!PINFO_FD_VISITED(pinfo)) {
|
||||
* streaming_reassembly_info = streaming_reassembly_info_new();
|
||||
* // save streaming reassembly info in the stream conversation or something like that
|
||||
* save_reassembly_info(pinfo, stream_id, flow_dir, streaming_reassembly_info);
|
||||
* } else {
|
||||
* streaming_reassembly_info = get_reassembly_info(pinfo, stream_id, flow_dir);
|
||||
* }
|
||||
* ...
|
||||
* while (offset < tvb_len)
|
||||
* {
|
||||
* ...
|
||||
* payload_len = xxx;
|
||||
* ...
|
||||
* if (dissecting_in_streaming_mode) {
|
||||
* // reassemble and call subdissector
|
||||
* reassemble_streaming_data_and_call_subdissector(tvb, pinfo, offset,
|
||||
* payload_len, proto_a_tree, proto_tree_get_parent_tree(proto_a_tree),
|
||||
* proto_a_streaming_reassembly_table, streaming_reassembly_info,
|
||||
* get_virtual_frame_num64(tvb, pinfo, offset), subdissector_handle,
|
||||
* proto_tree_get_parent_tree(tree), NULL, "ProtoA Body",
|
||||
* &proto_a_body_fragment_items, hf_proto_a_body_segment);
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
* void proto_register_proto_a(void) {
|
||||
* ...
|
||||
* static hf_register_info hf[] = {
|
||||
* ...
|
||||
* REASSEMBLE_INIT_HF_ITEMS(proto_a_body, "ProtoA Body", "protoa.body")
|
||||
* }
|
||||
* ...
|
||||
* static gint *ett[] = {
|
||||
* ...
|
||||
* REASSEMBLE_INIT_ETT_ITEMS(proto_a_body)
|
||||
* }
|
||||
* ...
|
||||
* reassembly_table_register(&proto_a_streaming_reassembly_table,
|
||||
* &addresses_ports_reassembly_table_functions);
|
||||
* ...
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @param tvb TVB contains (ProtoA) payload which will be passed to subdissector.
|
||||
* @param pinfo Packet information.
|
||||
* @param offset The beginning offset of payload in TVB.
|
||||
|
|
Loading…
Reference in New Issue