@@ -79,6 +79,8 @@ type Parsed struct {
7979 // length is the total length of the packet.
8080 // This is not the same as len(b) because b can have trailing zeros.
8181 length int
82+ // truncated indicates if the packet was truncated.
83+ trunc bool
8284
8385 // IPVersion is the IP protocol version of the packet (4 or
8486 // 6), or 0 if the packet doesn't look like IPv4 or IPv6.
@@ -116,12 +118,21 @@ func (p *Parsed) String() string {
116118 return string (b )
117119}
118120
121+ func (q * Parsed ) Decode (b []byte ) {
122+ q .decode (b , false /*truncated*/ )
123+ }
124+
125+ func (q * Parsed ) DecodeTrunc (b []byte , trunc bool ) {
126+ q .decode (b , trunc /*truncated*/ )
127+ }
128+
119129// Decode extracts data from the packet in b into q.
120130// It performs extremely simple packet decoding for basic IPv4 and IPv6 packet types.
121131// It extracts only the subprotocol id, IP addresses, and (if any) ports,
122132// and shouldn't need any memory allocation.
123- func (q * Parsed ) Decode (b []byte ) {
133+ func (q * Parsed ) decode (b []byte , trunc bool ) {
124134 q .b = b
135+ q .trunc = trunc
125136 q .CaptureMeta = CaptureMeta {} // Clear any capture metadata if it exists.
126137
127138 if len (b ) < 1 {
@@ -152,7 +163,7 @@ func (q *Parsed) decode4(b []byte) {
152163 // Check that it's IPv4.
153164 q .IPProto = Proto (b [9 ])
154165 q .length = int (binary .BigEndian .Uint16 (b [2 :4 ]))
155- if len (b ) < q .length {
166+ if ! q . trunc && len (b ) < q .length {
156167 // Packet was cut off before full IPv4 length.
157168 q .IPProto = unknown
158169 return
@@ -283,7 +294,7 @@ func (q *Parsed) decode6(b []byte) {
283294
284295 q .IPProto = Proto (b [6 ])
285296 q .length = int (binary .BigEndian .Uint16 (b [4 :6 ])) + IP6HeaderLength
286- if len (b ) < q .length {
297+ if ! q . trunc && len (b ) < q .length {
287298 // Packet was cut off before the full IPv6 length.
288299 q .IPProto = unknown
289300 return
@@ -394,7 +405,7 @@ func (q *Parsed) ICMPHeaderString() string {
394405 case ICMPv6 :
395406 return fmt .Sprintf ("%v" , q .ICMP6Header ())
396407 }
397- return "ICMP{???}"
408+ return "ICMP" + string ( q . IPVersion ) + " {???}"
398409}
399410
400411func (q * Parsed ) ICMP4Header () ICMP4Header {
@@ -429,13 +440,19 @@ func (q *Parsed) Buffer() []byte {
429440
430441// Payload returns the payload of the IP subprotocol section.
431442// This is a read-only view; that is, q retains the ownership of the buffer.
432- func (q * Parsed ) Payload () []byte {
443+ func (q * Parsed ) Payload () ( []byte , bool ) {
433444 // If the packet is truncated, return nothing instead of crashing.
434- if q .length > len (q .b ) || q .dataofs > len (q .b ) {
435- return nil
445+ if q .dataofs > len (q .b ) {
446+ return nil , q .trunc
447+ }
448+ if q .length > len (q .b ) {
449+ if q .trunc {
450+ return q .b [q .dataofs :], true
451+ }
452+ return nil , q .trunc
436453 }
437454
438- return q .b [q .dataofs :q .length ]
455+ return q .b [q .dataofs :q .length ], false
439456}
440457
441458// Transport returns the transport header and payload (IP subprotocol, such as TCP or UDP).
0 commit comments