diff options
author | Uli Heilmeier <uh@heilmeier.eu> | 2017-12-17 18:40:17 +0100 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2018-01-01 21:12:27 +0000 |
commit | 404d004907228c14fe66959f5d34d52d0cae3f13 (patch) | |
tree | ed82b87b6885d3370209d366e427e312d043744e | |
parent | 3d58a16038731bfe3f234756830ab300cf5c4dea (diff) |
IPv6: Add segmentation offload (TSO) support
When capturing on hardware with segmentation offload enabled IPv6
payload size can be reported as zero.
This commit adds a preference to dissect such frames.
Heavily based on the TSO code of packet-ip.c
Bug: 14155
Change-Id: Ibec3c35c739d8673fa655bde4f66198a22f567c4
Reviewed-on: https://code.wireshark.org/review/24900
Petri-Dish: João Valverde <j@v6e.pt>
Tested-by: Petri Dish Buildbot
Reviewed-by: Michael Mann <mmann78@netscape.net>
-rw-r--r-- | epan/dissectors/packet-ipv6.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/epan/dissectors/packet-ipv6.c b/epan/dissectors/packet-ipv6.c index a94e5d5375..5ef9efab43 100644 --- a/epan/dissectors/packet-ipv6.c +++ b/epan/dissectors/packet-ipv6.c @@ -346,6 +346,7 @@ static expert_field ei_ipv6_opt_unknown_data = EI_INIT; static expert_field ei_ipv6_opt_deprecated = EI_INIT; static expert_field ei_ipv6_hopopts_not_first = EI_INIT; static expert_field ei_ipv6_plen_exceeds_framing = EI_INIT; +static expert_field ei_ipv6_plen_zero = EI_INIT; static expert_field ei_ipv6_bogus_ipv6_version = EI_INIT; static expert_field ei_ipv6_invalid_header = EI_INIT; static expert_field ei_ipv6_opt_header_mismatch = EI_INIT; @@ -551,6 +552,9 @@ static gboolean ipv6_exthdr_under_root = FALSE; /* Hide extension header generated field for length */ static gboolean ipv6_exthdr_hide_len_oct_field = FALSE; +/* Assume TSO and correct zero-length IP packets */ +static gboolean ipv6_tso_supported = FALSE; + /* * defragmentation of IPv6 */ @@ -2308,13 +2312,28 @@ dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ proto_tree_add_item_ret_uint(ipv6_tree, hf_ipv6_flow, tvb, offset + IP6H_CTL_FLOW, 4, ENC_BIG_ENDIAN, &ip6_flow); - ti_ipv6_plen = proto_tree_add_item(ipv6_tree, hf_ipv6_plen, tvb, - offset + IP6H_CTL_PLEN, 2, ENC_BIG_ENDIAN); ipv6_pinfo->ip6_plen = tvb_get_guint16(tvb, offset + IP6H_CTL_PLEN, ENC_BIG_ENDIAN); + + ip6_nxt = tvb_get_guint8(tvb, offset + IP6H_CTL_NXT); + + if (ipv6_tso_supported && ipv6_pinfo->ip6_plen == 0 && ip6_nxt != IP_PROTO_HOPOPTS && ip6_nxt != IP_PROTO_NONE) { + ipv6_pinfo->ip6_plen = tvb_reported_length(tvb) - IPv6_HDR_SIZE; + pi = proto_tree_add_uint_format_value(ipv6_tree, hf_ipv6_plen, tvb, offset + IP6H_CTL_PLEN, 2, + ipv6_pinfo->ip6_plen, + "%u bytes (reported as 0, presumed to be because of \"TCP segmentation offload\" (TSO))", + ipv6_pinfo->ip6_plen); + PROTO_ITEM_SET_GENERATED(pi); + } else { + ti_ipv6_plen = proto_tree_add_item(ipv6_tree, hf_ipv6_plen, tvb, + offset + IP6H_CTL_PLEN, 2, ENC_BIG_ENDIAN); + if (ipv6_pinfo->ip6_plen == 0 && ip6_nxt != IP_PROTO_HOPOPTS && ip6_nxt != IP_PROTO_NONE) { + expert_add_info(pinfo, ti_ipv6_plen, &ei_ipv6_plen_zero); + } + } + ipv6_pinfo->frag_plen = ipv6_pinfo->ip6_plen; proto_tree_add_item(ipv6_tree, hf_ipv6_nxt, tvb, offset + IP6H_CTL_NXT, 1, ENC_NA); - ip6_nxt = tvb_get_guint8(tvb, offset + IP6H_CTL_NXT); proto_tree_add_item(ipv6_tree, hf_ipv6_hlim, tvb, offset + IP6H_CTL_HLIM, 1, ENC_BIG_ENDIAN); @@ -3421,6 +3440,10 @@ proto_register_ipv6(void) { "ipv6.plen_exceeds_framing", PI_PROTOCOL, PI_WARN, "IPv6 payload length does not match expected framing length", EXPFILL } }, + { &ei_ipv6_plen_zero, + { "ipv6.plen_zero", PI_PROTOCOL, PI_CHAT, + "IPv6 payload length equals 0 (maybe because of \"TCP segmentation offload\" (TSO))", EXPFILL } + }, { &ei_ipv6_bogus_ipv6_version, { "ipv6.bogus_ipv6_version", PI_MALFORMED, PI_ERROR, "Bogus IP version", EXPFILL } @@ -3593,6 +3616,11 @@ proto_register_ipv6(void) "If enabled the Length field in octets will be hidden", &ipv6_exthdr_hide_len_oct_field); + prefs_register_bool_preference(ipv6_module, "tso_support", + "Support packet-capture from IPv6 TSO-enabled hardware", + "Whether to correct for TSO-enabled (TCP segmentation offload) hardware " + "captures, such as spoofing the IPv6 packet length", &ipv6_tso_supported); + ipv6_handle = register_dissector("ipv6", dissect_ipv6, proto_ipv6); reassembly_table_register(&ipv6_reassembly_table, &addresses_reassembly_table_functions); |