Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / layers / icmp4.go
1 // Copyright 2012 Google, Inc. All rights reserved.
2 // Copyright 2009-2011 Andreas Krennmair. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style license
5 // that can be found in the LICENSE file in the root of the source
6 // tree.
7
8 package layers
9
10 import (
11         "encoding/binary"
12         "errors"
13         "fmt"
14         "reflect"
15
16         "github.com/google/gopacket"
17 )
18
19 const (
20         ICMPv4TypeEchoReply              = 0
21         ICMPv4TypeDestinationUnreachable = 3
22         ICMPv4TypeSourceQuench           = 4
23         ICMPv4TypeRedirect               = 5
24         ICMPv4TypeEchoRequest            = 8
25         ICMPv4TypeRouterAdvertisement    = 9
26         ICMPv4TypeRouterSolicitation     = 10
27         ICMPv4TypeTimeExceeded           = 11
28         ICMPv4TypeParameterProblem       = 12
29         ICMPv4TypeTimestampRequest       = 13
30         ICMPv4TypeTimestampReply         = 14
31         ICMPv4TypeInfoRequest            = 15
32         ICMPv4TypeInfoReply              = 16
33         ICMPv4TypeAddressMaskRequest     = 17
34         ICMPv4TypeAddressMaskReply       = 18
35 )
36
37 const (
38         // DestinationUnreachable
39         ICMPv4CodeNet                 = 0
40         ICMPv4CodeHost                = 1
41         ICMPv4CodeProtocol            = 2
42         ICMPv4CodePort                = 3
43         ICMPv4CodeFragmentationNeeded = 4
44         ICMPv4CodeSourceRoutingFailed = 5
45         ICMPv4CodeNetUnknown          = 6
46         ICMPv4CodeHostUnknown         = 7
47         ICMPv4CodeSourceIsolated      = 8
48         ICMPv4CodeNetAdminProhibited  = 9
49         ICMPv4CodeHostAdminProhibited = 10
50         ICMPv4CodeNetTOS              = 11
51         ICMPv4CodeHostTOS             = 12
52         ICMPv4CodeCommAdminProhibited = 13
53         ICMPv4CodeHostPrecedence      = 14
54         ICMPv4CodePrecedenceCutoff    = 15
55
56         // TimeExceeded
57         ICMPv4CodeTTLExceeded                    = 0
58         ICMPv4CodeFragmentReassemblyTimeExceeded = 1
59
60         // ParameterProblem
61         ICMPv4CodePointerIndicatesError = 0
62         ICMPv4CodeMissingOption         = 1
63         ICMPv4CodeBadLength             = 2
64
65         // Redirect
66         // ICMPv4CodeNet  = same as for DestinationUnreachable
67         // ICMPv4CodeHost = same as for DestinationUnreachable
68         ICMPv4CodeTOSNet  = 2
69         ICMPv4CodeTOSHost = 3
70 )
71
72 type icmpv4TypeCodeInfoStruct struct {
73         typeStr string
74         codeStr *map[uint8]string
75 }
76
77 var (
78         icmpv4TypeCodeInfo = map[uint8]icmpv4TypeCodeInfoStruct{
79                 ICMPv4TypeDestinationUnreachable: icmpv4TypeCodeInfoStruct{
80                         "DestinationUnreachable", &map[uint8]string{
81                                 ICMPv4CodeNet:                 "Net",
82                                 ICMPv4CodeHost:                "Host",
83                                 ICMPv4CodeProtocol:            "Protocol",
84                                 ICMPv4CodePort:                "Port",
85                                 ICMPv4CodeFragmentationNeeded: "FragmentationNeeded",
86                                 ICMPv4CodeSourceRoutingFailed: "SourceRoutingFailed",
87                                 ICMPv4CodeNetUnknown:          "NetUnknown",
88                                 ICMPv4CodeHostUnknown:         "HostUnknown",
89                                 ICMPv4CodeSourceIsolated:      "SourceIsolated",
90                                 ICMPv4CodeNetAdminProhibited:  "NetAdminProhibited",
91                                 ICMPv4CodeHostAdminProhibited: "HostAdminProhibited",
92                                 ICMPv4CodeNetTOS:              "NetTOS",
93                                 ICMPv4CodeHostTOS:             "HostTOS",
94                                 ICMPv4CodeCommAdminProhibited: "CommAdminProhibited",
95                                 ICMPv4CodeHostPrecedence:      "HostPrecedence",
96                                 ICMPv4CodePrecedenceCutoff:    "PrecedenceCutoff",
97                         },
98                 },
99                 ICMPv4TypeTimeExceeded: icmpv4TypeCodeInfoStruct{
100                         "TimeExceeded", &map[uint8]string{
101                                 ICMPv4CodeTTLExceeded:                    "TTLExceeded",
102                                 ICMPv4CodeFragmentReassemblyTimeExceeded: "FragmentReassemblyTimeExceeded",
103                         },
104                 },
105                 ICMPv4TypeParameterProblem: icmpv4TypeCodeInfoStruct{
106                         "ParameterProblem", &map[uint8]string{
107                                 ICMPv4CodePointerIndicatesError: "PointerIndicatesError",
108                                 ICMPv4CodeMissingOption:         "MissingOption",
109                                 ICMPv4CodeBadLength:             "BadLength",
110                         },
111                 },
112                 ICMPv4TypeSourceQuench: icmpv4TypeCodeInfoStruct{
113                         "SourceQuench", nil,
114                 },
115                 ICMPv4TypeRedirect: icmpv4TypeCodeInfoStruct{
116                         "Redirect", &map[uint8]string{
117                                 ICMPv4CodeNet:     "Net",
118                                 ICMPv4CodeHost:    "Host",
119                                 ICMPv4CodeTOSNet:  "TOS+Net",
120                                 ICMPv4CodeTOSHost: "TOS+Host",
121                         },
122                 },
123                 ICMPv4TypeEchoRequest: icmpv4TypeCodeInfoStruct{
124                         "EchoRequest", nil,
125                 },
126                 ICMPv4TypeEchoReply: icmpv4TypeCodeInfoStruct{
127                         "EchoReply", nil,
128                 },
129                 ICMPv4TypeTimestampRequest: icmpv4TypeCodeInfoStruct{
130                         "TimestampRequest", nil,
131                 },
132                 ICMPv4TypeTimestampReply: icmpv4TypeCodeInfoStruct{
133                         "TimestampReply", nil,
134                 },
135                 ICMPv4TypeInfoRequest: icmpv4TypeCodeInfoStruct{
136                         "InfoRequest", nil,
137                 },
138                 ICMPv4TypeInfoReply: icmpv4TypeCodeInfoStruct{
139                         "InfoReply", nil,
140                 },
141                 ICMPv4TypeRouterSolicitation: icmpv4TypeCodeInfoStruct{
142                         "RouterSolicitation", nil,
143                 },
144                 ICMPv4TypeRouterAdvertisement: icmpv4TypeCodeInfoStruct{
145                         "RouterAdvertisement", nil,
146                 },
147                 ICMPv4TypeAddressMaskRequest: icmpv4TypeCodeInfoStruct{
148                         "AddressMaskRequest", nil,
149                 },
150                 ICMPv4TypeAddressMaskReply: icmpv4TypeCodeInfoStruct{
151                         "AddressMaskReply", nil,
152                 },
153         }
154 )
155
156 type ICMPv4TypeCode uint16
157
158 // Type returns the ICMPv4 type field.
159 func (a ICMPv4TypeCode) Type() uint8 {
160         return uint8(a >> 8)
161 }
162
163 // Code returns the ICMPv4 code field.
164 func (a ICMPv4TypeCode) Code() uint8 {
165         return uint8(a)
166 }
167
168 func (a ICMPv4TypeCode) String() string {
169         t, c := a.Type(), a.Code()
170         strInfo, ok := icmpv4TypeCodeInfo[t]
171         if !ok {
172                 // Unknown ICMPv4 type field
173                 return fmt.Sprintf("%d(%d)", t, c)
174         }
175         typeStr := strInfo.typeStr
176         if strInfo.codeStr == nil && c == 0 {
177                 // The ICMPv4 type does not make use of the code field
178                 return fmt.Sprintf("%s", strInfo.typeStr)
179         }
180         if strInfo.codeStr == nil && c != 0 {
181                 // The ICMPv4 type does not make use of the code field, but it is present anyway
182                 return fmt.Sprintf("%s(Code: %d)", typeStr, c)
183         }
184         codeStr, ok := (*strInfo.codeStr)[c]
185         if !ok {
186                 // We don't know this ICMPv4 code; print the numerical value
187                 return fmt.Sprintf("%s(Code: %d)", typeStr, c)
188         }
189         return fmt.Sprintf("%s(%s)", typeStr, codeStr)
190 }
191
192 func (a ICMPv4TypeCode) GoString() string {
193         t := reflect.TypeOf(a)
194         return fmt.Sprintf("%s(%d, %d)", t.String(), a.Type(), a.Code())
195 }
196
197 // SerializeTo writes the ICMPv4TypeCode value to the 'bytes' buffer.
198 func (a ICMPv4TypeCode) SerializeTo(bytes []byte) {
199         binary.BigEndian.PutUint16(bytes, uint16(a))
200 }
201
202 // CreateICMPv4TypeCode is a convenience function to create an ICMPv4TypeCode
203 // gopacket type from the ICMPv4 type and code values.
204 func CreateICMPv4TypeCode(typ uint8, code uint8) ICMPv4TypeCode {
205         return ICMPv4TypeCode(binary.BigEndian.Uint16([]byte{typ, code}))
206 }
207
208 // ICMPv4 is the layer for IPv4 ICMP packet data.
209 type ICMPv4 struct {
210         BaseLayer
211         TypeCode ICMPv4TypeCode
212         Checksum uint16
213         Id       uint16
214         Seq      uint16
215 }
216
217 // LayerType returns LayerTypeICMPv4.
218 func (i *ICMPv4) LayerType() gopacket.LayerType { return LayerTypeICMPv4 }
219
220 // DecodeFromBytes decodes the given bytes into this layer.
221 func (i *ICMPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
222         if len(data) < 8 {
223                 df.SetTruncated()
224                 return errors.New("ICMP layer less then 8 bytes for ICMPv4 packet")
225         }
226         i.TypeCode = CreateICMPv4TypeCode(data[0], data[1])
227         i.Checksum = binary.BigEndian.Uint16(data[2:4])
228         i.Id = binary.BigEndian.Uint16(data[4:6])
229         i.Seq = binary.BigEndian.Uint16(data[6:8])
230         i.BaseLayer = BaseLayer{data[:8], data[8:]}
231         return nil
232 }
233
234 // SerializeTo writes the serialized form of this layer into the
235 // SerializationBuffer, implementing gopacket.SerializableLayer.
236 // See the docs for gopacket.SerializableLayer for more info.
237 func (i *ICMPv4) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
238         bytes, err := b.PrependBytes(8)
239         if err != nil {
240                 return err
241         }
242         i.TypeCode.SerializeTo(bytes)
243         binary.BigEndian.PutUint16(bytes[4:], i.Id)
244         binary.BigEndian.PutUint16(bytes[6:], i.Seq)
245         if opts.ComputeChecksums {
246                 bytes[2] = 0
247                 bytes[3] = 0
248                 i.Checksum = tcpipChecksum(b.Bytes(), 0)
249         }
250         binary.BigEndian.PutUint16(bytes[2:], i.Checksum)
251         return nil
252 }
253
254 // CanDecode returns the set of layer types that this DecodingLayer can decode.
255 func (i *ICMPv4) CanDecode() gopacket.LayerClass {
256         return LayerTypeICMPv4
257 }
258
259 // NextLayerType returns the layer type contained by this DecodingLayer.
260 func (i *ICMPv4) NextLayerType() gopacket.LayerType {
261         return gopacket.LayerTypePayload
262 }
263
264 func decodeICMPv4(data []byte, p gopacket.PacketBuilder) error {
265         i := &ICMPv4{}
266         return decodingLayerDecoder(i, data, p)
267 }