From 6b72c5012d98e8d5000d7176166441f3e17fa81d Mon Sep 17 00:00:00 2001 From: Satoshi Matsumoto Date: Mon, 4 May 2015 13:56:19 +0900 Subject: [PATCH] Fix GRE header decoding - check if the optional fields exist before consuming data - `Routing` field is a list of SREs --- layers/gre.go | 51 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/layers/gre.go b/layers/gre.go index a94337c64..0276b55d7 100644 --- a/layers/gre.go +++ b/layers/gre.go @@ -19,12 +19,15 @@ type GRE struct { Protocol EthernetType Checksum, Offset uint16 Key, Seq uint32 - *GRERouting + GRERouting GRERouting } // GRERouting is GRE routing information, present if the RoutingPresent flag is // set. -type GRERouting struct { +type GRERouting []*GRESourceRouteEntry + +// GRESourceRouteEntry is GRE routing information entry. +type GRESourceRouteEntry struct { AddressFamily uint16 SREOffset, SRELength uint8 RoutingInformation []byte @@ -44,26 +47,36 @@ func (g *GRE) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { g.Flags = data[1] >> 3 g.Version = data[1] & 0x7 g.Protocol = EthernetType(binary.BigEndian.Uint16(data[2:4])) - g.Checksum = binary.BigEndian.Uint16(data[4:6]) - g.Offset = binary.BigEndian.Uint16(data[6:8]) - g.Key = binary.BigEndian.Uint32(data[8:12]) - g.Seq = binary.BigEndian.Uint32(data[12:16]) - g.BaseLayer = BaseLayer{data[:16], data[16:]} - // reset data to point to after the main gre header - rData := data[16:] + offset := 4 + if g.ChecksumPresent || g.RoutingPresent { + g.Checksum = binary.BigEndian.Uint16(data[offset : offset+2]) + g.Offset = binary.BigEndian.Uint16(data[offset+2 : offset+4]) + offset += 4 + } + if g.KeyPresent { + g.Key = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + if g.SeqPresent { + g.Seq = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + } if g.RoutingPresent { - g.GRERouting = &GRERouting{ - AddressFamily: binary.BigEndian.Uint16(rData[:2]), - SREOffset: rData[2], - SRELength: rData[3], + for { + sre := &GRESourceRouteEntry{ + AddressFamily: binary.BigEndian.Uint16(data[offset : offset+2]), + SREOffset: data[offset+2], + SRELength: data[offset+3], + } + sre.RoutingInformation = data[offset+4 : offset+4+int(sre.SRELength)] + offset += 4 + int(sre.SRELength) + if sre.AddressFamily == 0 && sre.SRELength == 0 { + break + } + g.GRERouting = append(g.GRERouting, sre) } - end := g.SRELength + 4 - g.RoutingInformation = rData[4:end] - g.Contents = data[:16+end] - g.Payload = data[16+end:] - } else { - g.GRERouting = nil } + g.BaseLayer = BaseLayer{data[:offset], data[offset:]} return nil }