diff options
Diffstat (limited to 'epan/packet.c')
-rw-r--r-- | epan/packet.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/epan/packet.c b/epan/packet.c index e938884126..7fba6fb9d7 100644 --- a/epan/packet.c +++ b/epan/packet.c @@ -597,8 +597,11 @@ struct dissector_handle { * old style dissector : * length of the payload or 1 of the payload is empty * new dissector : - * >0 this protocol was successfully dissected and this was this protocol. + * >0 the protocol accepted the data, this is the number of bytes that were + * processed. If not equal to tvb_captured_length(), then the remaining + * data will be used for the next PDU (if reassembly is enabled). * 0 this packet did not match this protocol. + * <0 this protocol accepted the data, but needs more for a PDU. * * The only time this function will return 0 is if it is a new style dissector * and if the dissector rejected the packet. @@ -621,11 +624,37 @@ call_dissector_through_handle(dissector_handle_t handle, tvbuff_t *tvb, EP_CHECK_CANARY(("before calling handle->dissector.new_d for %s",handle->name)); ret = (*handle->dissector.new_d)(tvb, pinfo, tree, data); EP_CHECK_CANARY(("after calling handle->dissector.new_d for %s",handle->name)); + /* If the parent protocol can handle desegmentation (such as + * TCP), then set params according to the dissector return + * value, but *only* if desegment_len was not already set */ + if (!getenv("WS_DISABLE_EXPERIMENT")) + if (pinfo->can_desegment && pinfo->desegment_len == 0) { + if (ret < 0) { + /* need more bytes, so request another segment. + * Note that desegment_offset may be set if the + * dissector could already extract some PDUs */ + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; + } else if (ret > 0) { + /* succesfully dissected, check for more + * segments or verify boundary */ + guint caplen = tvb_captured_length(tvb); + + if (getenv("WS_BULLSHIT") && (guint) ret < caplen) { + /* not all data was consumed, assume + * that more data is necessary */ + pinfo->desegment_offset = ret; + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; + } else { + /* ret must not be larger than available */ + DISSECTOR_ASSERT((guint) ret <= caplen); + } + } + } } else { EP_CHECK_CANARY(("before calling handle->dissector.old for %s",handle->name)); (*handle->dissector.old)(tvb, pinfo, tree); EP_CHECK_CANARY(("after calling handle->dissector.old for %s",handle->name)); - ret = tvb_length(tvb); + ret = tvb_captured_length(tvb); if (ret == 0) { /* * XXX - a tvbuff can have 0 bytes of data in |