github.com/gopacket/gopacket@v1.1.0/layers/icmp4.go (about) 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/gopacket/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 }