summaryrefslogtreecommitdiff
path: root/epan/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/packet.c')
-rw-r--r--epan/packet.c33
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