1 // Copyright 2012 Google, Inc. All rights reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
12 "github.com/google/gopacket"
15 // GRE is a Generic Routing Encapsulation header.
18 ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute bool
19 RecursionControl, Flags, Version uint8
21 Checksum, Offset uint16
26 // GRERouting is GRE routing information, present if the RoutingPresent flag is
28 type GRERouting struct {
30 SREOffset, SRELength uint8
31 RoutingInformation []byte
35 // LayerType returns gopacket.LayerTypeGRE.
36 func (g *GRE) LayerType() gopacket.LayerType { return LayerTypeGRE }
38 // DecodeFromBytes decodes the given bytes into this layer.
39 func (g *GRE) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
40 g.ChecksumPresent = data[0]&0x80 != 0
41 g.RoutingPresent = data[0]&0x40 != 0
42 g.KeyPresent = data[0]&0x20 != 0
43 g.SeqPresent = data[0]&0x10 != 0
44 g.StrictSourceRoute = data[0]&0x08 != 0
45 g.RecursionControl = data[0] & 0x7
46 g.Flags = data[1] >> 3
47 g.Version = data[1] & 0x7
48 g.Protocol = EthernetType(binary.BigEndian.Uint16(data[2:4]))
50 if g.ChecksumPresent || g.RoutingPresent {
51 g.Checksum = binary.BigEndian.Uint16(data[offset : offset+2])
52 g.Offset = binary.BigEndian.Uint16(data[offset+2 : offset+4])
56 g.Key = binary.BigEndian.Uint32(data[offset : offset+4])
60 g.Seq = binary.BigEndian.Uint32(data[offset : offset+4])
67 AddressFamily: binary.BigEndian.Uint16(data[offset : offset+2]),
68 SREOffset: data[offset+2],
69 SRELength: data[offset+3],
71 sre.RoutingInformation = data[offset+4 : offset+4+int(sre.SRELength)]
72 offset += 4 + int(sre.SRELength)
73 if sre.AddressFamily == 0 && sre.SRELength == 0 {
80 g.BaseLayer = BaseLayer{data[:offset], data[offset:]}
84 // SerializeTo writes the serialized form of this layer into the SerializationBuffer,
85 // implementing gopacket.SerializableLayer. See the docs for gopacket.SerializableLayer for more info.
86 func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
88 if g.ChecksumPresent || g.RoutingPresent {
100 size += 4 + int(r.SRELength)
105 buf, err := b.PrependBytes(size)
109 // Reset any potentially dirty memory in the first 2 bytes, as these use OR to set flags.
112 if g.ChecksumPresent {
115 if g.RoutingPresent {
124 if g.StrictSourceRoute {
127 buf[0] |= g.RecursionControl
128 buf[1] |= g.Flags << 3
130 binary.BigEndian.PutUint16(buf[2:4], uint16(g.Protocol))
132 if g.ChecksumPresent || g.RoutingPresent {
133 // Don't write the checksum value yet, as we may need to compute it,
134 // which requires the entire header be complete.
135 // Instead we zeroize the memory in case it is dirty.
138 binary.BigEndian.PutUint16(buf[offset+2:offset+4], g.Offset)
142 binary.BigEndian.PutUint32(buf[offset:offset+4], g.Key)
146 binary.BigEndian.PutUint32(buf[offset:offset+4], g.Seq)
149 if g.RoutingPresent {
152 binary.BigEndian.PutUint16(buf[offset:offset+2], sre.AddressFamily)
153 buf[offset+2] = sre.SREOffset
154 buf[offset+3] = sre.SRELength
155 copy(buf[offset+4:offset+4+int(sre.SRELength)], sre.RoutingInformation)
156 offset += 4 + int(sre.SRELength)
159 // Terminate routing field with a "NULL" SRE.
160 binary.BigEndian.PutUint32(buf[offset:offset+4], 0)
162 if g.ChecksumPresent {
163 if opts.ComputeChecksums {
164 g.Checksum = tcpipChecksum(b.Bytes(), 0)
167 binary.BigEndian.PutUint16(buf[4:6], g.Checksum)
172 // CanDecode returns the set of layer types that this DecodingLayer can decode.
173 func (g *GRE) CanDecode() gopacket.LayerClass {
177 // NextLayerType returns the layer type contained by this DecodingLayer.
178 func (g *GRE) NextLayerType() gopacket.LayerType {
179 return g.Protocol.LayerType()
182 func decodeGRE(data []byte, p gopacket.PacketBuilder) error {
184 return decodingLayerDecoder(g, data, p)