github.com/gopacket/gopacket@v1.1.0/layers/gre.go (about) 1 // Copyright 2012 Google, Inc. All rights reserved. 2 // 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 5 // tree. 6 7 package layers 8 9 import ( 10 "encoding/binary" 11 12 "github.com/gopacket/gopacket" 13 ) 14 15 // GRE is a Generic Routing Encapsulation header. 16 type GRE struct { 17 BaseLayer 18 ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute, AckPresent bool 19 RecursionControl, Flags, Version uint8 20 Protocol EthernetType 21 Checksum, Offset uint16 22 Key, Seq, Ack uint32 23 *GRERouting 24 } 25 26 // GRERouting is GRE routing information, present if the RoutingPresent flag is 27 // set. 28 type GRERouting struct { 29 AddressFamily uint16 30 SREOffset, SRELength uint8 31 RoutingInformation []byte 32 Next *GRERouting 33 } 34 35 // LayerType returns gopacket.LayerTypeGRE. 36 func (g *GRE) LayerType() gopacket.LayerType { return LayerTypeGRE } 37 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.AckPresent = data[1]&0x80 != 0 46 g.RecursionControl = data[0] & 0x7 47 g.Flags = data[1] >> 3 48 g.Version = data[1] & 0x7 49 g.Protocol = EthernetType(binary.BigEndian.Uint16(data[2:4])) 50 offset := 4 51 if g.ChecksumPresent || g.RoutingPresent { 52 g.Checksum = binary.BigEndian.Uint16(data[offset : offset+2]) 53 g.Offset = binary.BigEndian.Uint16(data[offset+2 : offset+4]) 54 offset += 4 55 } 56 if g.KeyPresent { 57 g.Key = binary.BigEndian.Uint32(data[offset : offset+4]) 58 offset += 4 59 } 60 if g.SeqPresent { 61 g.Seq = binary.BigEndian.Uint32(data[offset : offset+4]) 62 offset += 4 63 } 64 if g.RoutingPresent { 65 tail := &g.GRERouting 66 for { 67 sre := &GRERouting{ 68 AddressFamily: binary.BigEndian.Uint16(data[offset : offset+2]), 69 SREOffset: data[offset+2], 70 SRELength: data[offset+3], 71 } 72 sre.RoutingInformation = data[offset+4 : offset+4+int(sre.SRELength)] 73 offset += 4 + int(sre.SRELength) 74 if sre.AddressFamily == 0 && sre.SRELength == 0 { 75 break 76 } 77 (*tail) = sre 78 tail = &sre.Next 79 } 80 } 81 if g.AckPresent { 82 g.Ack = binary.BigEndian.Uint32(data[offset : offset+4]) 83 offset += 4 84 } 85 g.BaseLayer = BaseLayer{data[:offset], data[offset:]} 86 return nil 87 } 88 89 // SerializeTo writes the serialized form of this layer into the SerializationBuffer, 90 // implementing gopacket.SerializableLayer. See the docs for gopacket.SerializableLayer for more info. 91 func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 92 size := 4 93 if g.ChecksumPresent || g.RoutingPresent { 94 size += 4 95 } 96 if g.KeyPresent { 97 size += 4 98 } 99 if g.SeqPresent { 100 size += 4 101 } 102 if g.RoutingPresent { 103 r := g.GRERouting 104 for r != nil { 105 size += 4 + int(r.SRELength) 106 r = r.Next 107 } 108 size += 4 109 } 110 if g.AckPresent { 111 size += 4 112 } 113 buf, err := b.PrependBytes(size) 114 if err != nil { 115 return err 116 } 117 // Reset any potentially dirty memory in the first 2 bytes, as these use OR to set flags. 118 buf[0] = 0 119 buf[1] = 0 120 if g.ChecksumPresent { 121 buf[0] |= 0x80 122 } 123 if g.RoutingPresent { 124 buf[0] |= 0x40 125 } 126 if g.KeyPresent { 127 buf[0] |= 0x20 128 } 129 if g.SeqPresent { 130 buf[0] |= 0x10 131 } 132 if g.StrictSourceRoute { 133 buf[0] |= 0x08 134 } 135 if g.AckPresent { 136 buf[1] |= 0x80 137 } 138 buf[0] |= g.RecursionControl 139 buf[1] |= g.Flags << 3 140 buf[1] |= g.Version 141 binary.BigEndian.PutUint16(buf[2:4], uint16(g.Protocol)) 142 offset := 4 143 if g.ChecksumPresent || g.RoutingPresent { 144 // Don't write the checksum value yet, as we may need to compute it, 145 // which requires the entire header be complete. 146 // Instead we zeroize the memory in case it is dirty. 147 buf[offset] = 0 148 buf[offset+1] = 0 149 binary.BigEndian.PutUint16(buf[offset+2:offset+4], g.Offset) 150 offset += 4 151 } 152 if g.KeyPresent { 153 binary.BigEndian.PutUint32(buf[offset:offset+4], g.Key) 154 offset += 4 155 } 156 if g.SeqPresent { 157 binary.BigEndian.PutUint32(buf[offset:offset+4], g.Seq) 158 offset += 4 159 } 160 if g.RoutingPresent { 161 sre := g.GRERouting 162 for sre != nil { 163 binary.BigEndian.PutUint16(buf[offset:offset+2], sre.AddressFamily) 164 buf[offset+2] = sre.SREOffset 165 buf[offset+3] = sre.SRELength 166 copy(buf[offset+4:offset+4+int(sre.SRELength)], sre.RoutingInformation) 167 offset += 4 + int(sre.SRELength) 168 sre = sre.Next 169 } 170 // Terminate routing field with a "NULL" SRE. 171 binary.BigEndian.PutUint32(buf[offset:offset+4], 0) 172 } 173 if g.AckPresent { 174 binary.BigEndian.PutUint32(buf[offset:offset+4], g.Ack) 175 offset += 4 176 } 177 if g.ChecksumPresent { 178 if opts.ComputeChecksums { 179 g.Checksum = tcpipChecksum(b.Bytes(), 0) 180 } 181 182 binary.BigEndian.PutUint16(buf[4:6], g.Checksum) 183 } 184 return nil 185 } 186 187 // CanDecode returns the set of layer types that this DecodingLayer can decode. 188 func (g *GRE) CanDecode() gopacket.LayerClass { 189 return LayerTypeGRE 190 } 191 192 // NextLayerType returns the layer type contained by this DecodingLayer. 193 func (g *GRE) NextLayerType() gopacket.LayerType { 194 return g.Protocol.LayerType() 195 } 196 197 func decodeGRE(data []byte, p gopacket.PacketBuilder) error { 198 g := &GRE{} 199 return decodingLayerDecoder(g, data, p) 200 }