forked from osmocom/wireshark
IPv6: Register fragment header dissector handle
Change-Id: Ie49c8cdc010630c8963a730562aaf33f61236058 Reviewed-on: https://code.wireshark.org/review/16443 Petri-Dish: João Valverde <j@v6e.pt> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: João Valverde <j@v6e.pt>
This commit is contained in:
parent
18d5bccede
commit
4bf78ca75b
|
@ -112,6 +112,9 @@ typedef struct {
|
|||
guint32 jumbo_length;
|
||||
guint32 payload_length;
|
||||
gint hop_limit;
|
||||
guint16 frag_off;
|
||||
gboolean frag_flg;
|
||||
guint32 frag_ident;
|
||||
} ipv6_meta_t;
|
||||
|
||||
static int ipv6_tap = -1;
|
||||
|
@ -708,6 +711,43 @@ ipv6_reassemble_init(void)
|
|||
&addresses_reassembly_table_functions);
|
||||
}
|
||||
|
||||
/* Returns 'show_data' */
|
||||
static gboolean
|
||||
ipv6_reassemble_do(tvbuff_t **tvb_ptr, gint *offset_ptr, packet_info *pinfo, proto_tree *ipv6_tree, guint32 plen)
|
||||
{
|
||||
ipv6_meta_t *ipv6_info = get_ipv6_meta_data(pinfo);
|
||||
fragment_head *ipfd_head;
|
||||
tvbuff_t *next_tvb;
|
||||
gboolean update_col_info = TRUE;
|
||||
|
||||
pinfo->fragmented = TRUE;
|
||||
if (!ipv6_reassemble) {
|
||||
/* not reassembling */
|
||||
if (ipv6_info->frag_off != 0) {
|
||||
/* not in the first fragment */
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* reassembling */
|
||||
if (tvb_bytes_exist(*tvb_ptr, *offset_ptr, plen)) {
|
||||
ipfd_head = fragment_add_check(&ipv6_reassembly_table,
|
||||
*tvb_ptr, *offset_ptr, pinfo, ipv6_info->frag_ident, NULL,
|
||||
ipv6_info->frag_off, plen, ipv6_info->frag_flg);
|
||||
next_tvb = process_reassembled_data(*tvb_ptr, *offset_ptr, pinfo, "Reassembled IPv6",
|
||||
ipfd_head, &ipv6_frag_items, &update_col_info, ipv6_tree);
|
||||
if (next_tvb) {
|
||||
/* Process post-fragment headers after reassembly */
|
||||
*offset_ptr = 0;
|
||||
*tvb_ptr = next_tvb;
|
||||
pinfo->fragmented = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6_reassemble_cleanup(void)
|
||||
{
|
||||
|
@ -1092,23 +1132,23 @@ dissect_routing6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
|
|||
}
|
||||
|
||||
static int
|
||||
dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
|
||||
guint16 *frag_off, gboolean *frag_flg, guint32 *frag_ident) {
|
||||
dissect_fraghdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
|
||||
proto_item *pi, *ti;
|
||||
proto_tree *frag_tree;
|
||||
guint8 nxt;
|
||||
guint16 offlg;
|
||||
gint offset = 0;
|
||||
ipv6_meta_t *ipv6_info;
|
||||
|
||||
ipv6_info = get_ipv6_meta_data(pinfo);
|
||||
|
||||
nxt = tvb_get_guint8(tvb, offset);
|
||||
offlg = tvb_get_ntohs(tvb, offset + 2);
|
||||
*frag_off = offlg & IP6F_OFF_MASK; /* offset in bytes */
|
||||
*frag_flg = offlg & IP6F_MORE_FRAG;
|
||||
*frag_ident = tvb_get_ntohl(tvb, offset + 4);
|
||||
ipv6_info->frag_off = offlg & IP6F_OFF_MASK; /* offset in bytes */
|
||||
ipv6_info->frag_flg = offlg & IP6F_MORE_FRAG;
|
||||
ipv6_info->frag_ident = tvb_get_ntohl(tvb, offset + 4);
|
||||
col_add_fstr(pinfo->cinfo, COL_INFO, "IPv6 fragment (off=%u more=%s ident=0x%08x nxt=%u)",
|
||||
*frag_off, *frag_flg ? "y" : "n", *frag_ident, nxt);
|
||||
ipv6_info->frag_off, ipv6_info->frag_flg ? "y" : "n", ipv6_info->frag_ident, nxt);
|
||||
|
||||
/* IPv6 Fragmentation Header has fixed length of 8 bytes */
|
||||
pi = proto_tree_add_item(tree, proto_ipv6_fraghdr, tvb, offset, 8, ENC_NA);
|
||||
|
@ -1126,7 +1166,7 @@ dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
|
|||
offset += 1;
|
||||
|
||||
ti = proto_tree_add_item(frag_tree, hf_ipv6_fraghdr_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
proto_item_append_text(ti, " (%d bytes)", *frag_off);
|
||||
proto_item_append_text(ti, " (%d bytes)", ipv6_info->frag_off);
|
||||
|
||||
proto_tree_add_item(frag_tree, hf_ipv6_fraghdr_reserved_bits, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
|
||||
|
@ -1738,17 +1778,13 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
|
|||
proto_item *ipv6_item, *ti, *pi;
|
||||
proto_item *ti_ipv6_plen = NULL, *ti_ipv6_version;
|
||||
guint8 nxt, tfc;
|
||||
guint8 nxt_saved;
|
||||
int advance;
|
||||
guint32 plen;
|
||||
guint16 frag_off;
|
||||
gboolean frag_flg;
|
||||
guint32 frag_ident;
|
||||
int offset;
|
||||
fragment_head *ipfd_head;
|
||||
tvbuff_t *next_tvb, *options_tvb;
|
||||
gboolean update_col_info = TRUE;
|
||||
gboolean save_fragmented;
|
||||
gboolean show_data = FALSE;
|
||||
gboolean show_data = FALSE, loop = TRUE;
|
||||
guint8 *mac_addr;
|
||||
const char *name;
|
||||
dissector_handle_t nxt_handle;
|
||||
|
@ -2093,67 +2129,33 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
|
|||
plen -= advance;
|
||||
save_fragmented = pinfo->fragmented;
|
||||
|
||||
again:
|
||||
while (loop && !show_data) {
|
||||
/* Get a tvbuff for the options. */
|
||||
options_tvb = tvb_new_subset_remaining(tvb, offset);
|
||||
nxt_handle = dissector_get_uint_handle(ipv6_next_header_dissector_table, nxt);
|
||||
|
||||
/* Get a tvbuff for the options. */
|
||||
options_tvb = tvb_new_subset_remaining(tvb, offset);
|
||||
nxt_handle = dissector_get_uint_handle(ipv6_next_header_dissector_table, nxt);
|
||||
|
||||
if ((nxt_handle) &&
|
||||
((advance = call_dissector_with_data(nxt_handle, options_tvb, pinfo, ipv6_exthdr_tree, &iph)) > 0)) {
|
||||
nxt = tvb_get_guint8(tvb, offset);
|
||||
offset += advance;
|
||||
plen -= advance;
|
||||
goto again;
|
||||
} else {
|
||||
switch (nxt) {
|
||||
case IP_PROTO_FRAGMENT:
|
||||
advance = dissect_frag6(tvb, offset, pinfo, ipv6_exthdr_tree,
|
||||
&frag_off, &frag_flg, &frag_ident);
|
||||
if ((nxt_handle) &&
|
||||
((advance = call_dissector_with_data(nxt_handle, options_tvb, pinfo, ipv6_exthdr_tree, &iph)) > 0)) {
|
||||
nxt_saved = nxt;
|
||||
nxt = tvb_get_guint8(tvb, offset);
|
||||
offset += advance;
|
||||
plen -= advance;
|
||||
if ((frag_off == 0) && !frag_flg) {
|
||||
goto again;
|
||||
}
|
||||
pinfo->fragmented = TRUE;
|
||||
if (ipv6_reassemble) {
|
||||
/* reassembling */
|
||||
if (tvb_bytes_exist(tvb, offset, plen)) {
|
||||
ipfd_head = fragment_add_check(&ipv6_reassembly_table,
|
||||
tvb, offset, pinfo, frag_ident, NULL,
|
||||
frag_off, plen, frag_flg);
|
||||
next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv6",
|
||||
ipfd_head, &ipv6_frag_items, &update_col_info, ipv6_tree);
|
||||
if (next_tvb) { /* Process post-fragment headers after reassembly... */
|
||||
offset = 0;
|
||||
tvb = next_tvb;
|
||||
pinfo->fragmented = FALSE;
|
||||
goto again;
|
||||
}
|
||||
if (nxt_saved == IP_PROTO_FRAGMENT) {
|
||||
if ((ipv6_info->frag_off != 0) || ipv6_info->frag_flg) {
|
||||
show_data = ipv6_reassemble_do(&tvb, &offset, pinfo, ipv6_tree, plen);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* not reassembling */
|
||||
if (frag_off == 0) /* ... or in the first fragment */
|
||||
goto again;
|
||||
}
|
||||
show_data = TRUE;
|
||||
break;
|
||||
case IP_PROTO_NONE:
|
||||
} else if (nxt == IP_PROTO_NONE) {
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "IPv6 no next header");
|
||||
show_data = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((ipv6extprotostr(nxt) != NULL) &&
|
||||
} else if ((ipv6extprotostr(nxt) != NULL) &&
|
||||
!dissector_get_uint_handle(ip_dissector_table, nxt)) {
|
||||
advance = dissect_unknown_exthdr(tvb, offset, ipv6_exthdr_tree);
|
||||
nxt = tvb_get_guint8(tvb, offset);
|
||||
offset += advance;
|
||||
plen -= advance;
|
||||
goto again;
|
||||
}
|
||||
advance = dissect_unknown_exthdr(tvb, offset, ipv6_exthdr_tree);
|
||||
nxt = tvb_get_guint8(tvb, offset);
|
||||
offset += advance;
|
||||
plen -= advance;
|
||||
} else {
|
||||
loop = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3237,6 +3239,7 @@ proto_reg_handoff_ipv6(void)
|
|||
dissector_handle_t ipv6_handle;
|
||||
dissector_handle_t ipv6_hopopts_handle;
|
||||
dissector_handle_t ipv6_routing_handle;
|
||||
dissector_handle_t ipv6_fraghdr_handle;
|
||||
dissector_handle_t ipv6_dstopts_handle;
|
||||
|
||||
ipv6_handle = find_dissector("ipv6");
|
||||
|
@ -3263,11 +3266,16 @@ proto_reg_handoff_ipv6(void)
|
|||
|
||||
dissector_add_for_decode_as("udp.port", ipv6_handle);
|
||||
|
||||
ipv6_hopopts_handle = create_dissector_handle(dissect_hopopts, proto_ipv6_hopopts );
|
||||
ipv6_hopopts_handle = create_dissector_handle(dissect_hopopts, proto_ipv6_hopopts);
|
||||
dissector_add_uint("ipv6.nxt", IP_PROTO_HOPOPTS, ipv6_hopopts_handle);
|
||||
ipv6_routing_handle = create_dissector_handle(dissect_routing6, proto_ipv6_routing );
|
||||
|
||||
ipv6_routing_handle = create_dissector_handle(dissect_routing6, proto_ipv6_routing);
|
||||
dissector_add_uint("ipv6.nxt", IP_PROTO_ROUTING, ipv6_routing_handle);
|
||||
ipv6_dstopts_handle = create_dissector_handle(dissect_dstopts, proto_ipv6_dstopts );
|
||||
|
||||
ipv6_fraghdr_handle = create_dissector_handle(dissect_fraghdr, proto_ipv6_fraghdr);
|
||||
dissector_add_uint("ipv6.nxt", IP_PROTO_FRAGMENT, ipv6_fraghdr_handle);
|
||||
|
||||
ipv6_dstopts_handle = create_dissector_handle(dissect_dstopts, proto_ipv6_dstopts);
|
||||
dissector_add_uint("ipv6.nxt", IP_PROTO_DSTOPTS, ipv6_dstopts_handle);
|
||||
|
||||
ip_dissector_table = find_dissector_table("ip.proto");
|
||||
|
|
Loading…
Reference in New Issue