- next_tvb = tvb_new_subset(tvb, offset, -1, -1);
- switch (type) {
- case GRE_PPP:
- call_dissector(ppp_handle, next_tvb, pinfo, tree);
- break;
- case GRE_IP:
- call_dissector(ip_handle, next_tvb, pinfo, tree);
- break;
- case GRE_WCCP:
- if (is_wccp2) {
- if (tree)
- dissect_gre_wccp2_redirect_header(tvb, offset, gre_tree);
- offset += 4;
- }
- call_dissector(ip_handle, next_tvb, pinfo, tree);
- break;
- case GRE_IPX:
- call_dissector(ipx_handle, next_tvb, pinfo, tree);
- break;
- case GRE_FR:
- call_dissector(fr_handle, next_tvb, pinfo, tree);
- break;
- default:
- dissect_data(next_tvb, 0, pinfo, gre_tree);
- break;
+ if (type == GRE_WCCP) {
+ if (is_wccp2) {
+ if (tree)
+ dissect_gre_wccp2_redirect_header(tvb, offset, gre_tree);
+ offset += 4;
+ }
+ }
+
+ /* If the S bit is not set, this packet might not have a payload, so
+ check whether there's any data left, first.
+
+ XXX - the S bit isn't in RFC 2784, which deprecates that bit
+ and some other bits in RFC 1701 and says that they should be
+ zero for RFC 2784-compliant GRE; as such, the absence of the
+ S bit doesn't necessarily mean there's no payload. */
+ if (!(flags_and_ver & GH_B_S)) {
+ if (tvb_reported_length_remaining(tvb, offset) <= 0)
+ return; /* no payload */