Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / layers / gre.go
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/google/gopacket"
13 )
14
15 // GRE is a Generic Routing Encapsulation header.
16 type GRE struct {
17         BaseLayer
18         ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute bool
19         RecursionControl, Flags, Version                                           uint8
20         Protocol                                                                   EthernetType
21         Checksum, Offset                                                           uint16
22         Key, Seq                                                                   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.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]))
49         offset := 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])
53                 offset += 4
54         }
55         if g.KeyPresent {
56                 g.Key = binary.BigEndian.Uint32(data[offset : offset+4])
57                 offset += 4
58         }
59         if g.SeqPresent {
60                 g.Seq = binary.BigEndian.Uint32(data[offset : offset+4])
61                 offset += 4
62         }
63         if g.RoutingPresent {
64                 tail := &g.GRERouting
65                 for {
66                         sre := &GRERouting{
67                                 AddressFamily: binary.BigEndian.Uint16(data[offset : offset+2]),
68                                 SREOffset:     data[offset+2],
69                                 SRELength:     data[offset+3],
70                         }
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 {
74                                 break
75                         }
76                         (*tail) = sre
77                         tail = &sre.Next
78                 }
79         }
80         g.BaseLayer = BaseLayer{data[:offset], data[offset:]}
81         return nil
82 }
83
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 {
87         size := 4
88         if g.ChecksumPresent || g.RoutingPresent {
89                 size += 4
90         }
91         if g.KeyPresent {
92                 size += 4
93         }
94         if g.SeqPresent {
95                 size += 4
96         }
97         if g.RoutingPresent {
98                 r := g.GRERouting
99                 for r != nil {
100                         size += 4 + int(r.SRELength)
101                         r = r.Next
102                 }
103                 size += 4
104         }
105         buf, err := b.PrependBytes(size)
106         if err != nil {
107                 return err
108         }
109         // Reset any potentially dirty memory in the first 2 bytes, as these use OR to set flags.
110         buf[0] = 0
111         buf[1] = 0
112         if g.ChecksumPresent {
113                 buf[0] |= 0x80
114         }
115         if g.RoutingPresent {
116                 buf[0] |= 0x40
117         }
118         if g.KeyPresent {
119                 buf[0] |= 0x20
120         }
121         if g.SeqPresent {
122                 buf[0] |= 0x10
123         }
124         if g.StrictSourceRoute {
125                 buf[0] |= 0x08
126         }
127         buf[0] |= g.RecursionControl
128         buf[1] |= g.Flags << 3
129         buf[1] |= g.Version
130         binary.BigEndian.PutUint16(buf[2:4], uint16(g.Protocol))
131         offset := 4
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.
136                 buf[offset] = 0
137                 buf[offset+1] = 0
138                 binary.BigEndian.PutUint16(buf[offset+2:offset+4], g.Offset)
139                 offset += 4
140         }
141         if g.KeyPresent {
142                 binary.BigEndian.PutUint32(buf[offset:offset+4], g.Key)
143                 offset += 4
144         }
145         if g.SeqPresent {
146                 binary.BigEndian.PutUint32(buf[offset:offset+4], g.Seq)
147                 offset += 4
148         }
149         if g.RoutingPresent {
150                 sre := g.GRERouting
151                 for sre != nil {
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)
157                         sre = sre.Next
158                 }
159                 // Terminate routing field with a "NULL" SRE.
160                 binary.BigEndian.PutUint32(buf[offset:offset+4], 0)
161         }
162         if g.ChecksumPresent {
163                 if opts.ComputeChecksums {
164                         g.Checksum = tcpipChecksum(b.Bytes(), 0)
165                 }
166
167                 binary.BigEndian.PutUint16(buf[4:6], g.Checksum)
168         }
169         return nil
170 }
171
172 // CanDecode returns the set of layer types that this DecodingLayer can decode.
173 func (g *GRE) CanDecode() gopacket.LayerClass {
174         return LayerTypeGRE
175 }
176
177 // NextLayerType returns the layer type contained by this DecodingLayer.
178 func (g *GRE) NextLayerType() gopacket.LayerType {
179         return g.Protocol.LayerType()
180 }
181
182 func decodeGRE(data []byte, p gopacket.PacketBuilder) error {
183         g := &GRE{}
184         return decodingLayerDecoder(g, data, p)
185 }