github.com/gopacket/gopacket@v1.1.0/layers/icmp6msg.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 "encoding/hex" 13 "errors" 14 "fmt" 15 "net" 16 "time" 17 18 "github.com/gopacket/gopacket" 19 ) 20 21 // Based on RFC 4861 22 23 // ICMPv6Opt indicate how to decode the data associated with each ICMPv6Option. 24 type ICMPv6Opt uint8 25 26 const ( 27 _ ICMPv6Opt = iota 28 29 // ICMPv6OptSourceAddress contains the link-layer address of the sender of 30 // the packet. It is used in the Neighbor Solicitation, Router 31 // Solicitation, and Router Advertisement packets. Must be ignored for other 32 // Neighbor discovery messages. 33 ICMPv6OptSourceAddress 34 35 // ICMPv6OptTargetAddress contains the link-layer address of the target. It 36 // is used in Neighbor Advertisement and Redirect packets. Must be ignored 37 // for other Neighbor discovery messages. 38 ICMPv6OptTargetAddress 39 40 // ICMPv6OptPrefixInfo provides hosts with on-link prefixes and prefixes 41 // for Address Autoconfiguration. The Prefix Information option appears in 42 // Router Advertisement packets and MUST be silently ignored for other 43 // messages. 44 ICMPv6OptPrefixInfo 45 46 // ICMPv6OptRedirectedHeader is used in Redirect messages and contains all 47 // or part of the packet that is being redirected. 48 ICMPv6OptRedirectedHeader 49 50 // ICMPv6OptMTU is used in Router Advertisement messages to ensure that all 51 // nodes on a link use the same MTU value in those cases where the link MTU 52 // is not well known. This option MUST be silently ignored for other 53 // Neighbor Discovery messages. 54 ICMPv6OptMTU 55 ) 56 57 // ICMPv6Echo represents the structure of a ping. 58 type ICMPv6Echo struct { 59 BaseLayer 60 Identifier uint16 61 SeqNumber uint16 62 } 63 64 // ICMPv6RouterSolicitation is sent by hosts to find routers. 65 type ICMPv6RouterSolicitation struct { 66 BaseLayer 67 Options ICMPv6Options 68 } 69 70 // ICMPv6RouterAdvertisement is sent by routers in response to Solicitation. 71 type ICMPv6RouterAdvertisement struct { 72 BaseLayer 73 HopLimit uint8 74 Flags uint8 75 RouterLifetime uint16 76 ReachableTime uint32 77 RetransTimer uint32 78 Options ICMPv6Options 79 } 80 81 // ICMPv6NeighborSolicitation is sent to request the link-layer address of a 82 // target node. 83 type ICMPv6NeighborSolicitation struct { 84 BaseLayer 85 TargetAddress net.IP 86 Options ICMPv6Options 87 } 88 89 // ICMPv6NeighborAdvertisement is sent by nodes in response to Solicitation. 90 type ICMPv6NeighborAdvertisement struct { 91 BaseLayer 92 Flags uint8 93 TargetAddress net.IP 94 Options ICMPv6Options 95 } 96 97 // ICMPv6Redirect is sent by routers to inform hosts of a better first-hop node 98 // on the path to a destination. 99 type ICMPv6Redirect struct { 100 BaseLayer 101 TargetAddress net.IP 102 DestinationAddress net.IP 103 Options ICMPv6Options 104 } 105 106 // ICMPv6Option contains the type and data for a single option. 107 type ICMPv6Option struct { 108 Type ICMPv6Opt 109 Data []byte 110 } 111 112 // ICMPv6Options is a slice of ICMPv6Option. 113 type ICMPv6Options []ICMPv6Option 114 115 func (i ICMPv6Opt) String() string { 116 switch i { 117 case ICMPv6OptSourceAddress: 118 return "SourceAddress" 119 case ICMPv6OptTargetAddress: 120 return "TargetAddress" 121 case ICMPv6OptPrefixInfo: 122 return "PrefixInfo" 123 case ICMPv6OptRedirectedHeader: 124 return "RedirectedHeader" 125 case ICMPv6OptMTU: 126 return "MTU" 127 default: 128 return fmt.Sprintf("Unknown(%d)", i) 129 } 130 } 131 132 // CanDecode returns the set of layer types that this DecodingLayer can decode. 133 func (i *ICMPv6Echo) CanDecode() gopacket.LayerClass { 134 return LayerTypeICMPv6Echo 135 } 136 137 // LayerType returns LayerTypeICMPv6Echo. 138 func (i *ICMPv6Echo) LayerType() gopacket.LayerType { 139 return LayerTypeICMPv6Echo 140 } 141 142 // NextLayerType returns the layer type contained by this DecodingLayer. 143 func (i *ICMPv6Echo) NextLayerType() gopacket.LayerType { 144 return gopacket.LayerTypePayload 145 } 146 147 // DecodeFromBytes decodes the given bytes into this layer. 148 func (i *ICMPv6Echo) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 149 if len(data) < 4 { 150 df.SetTruncated() 151 return errors.New("ICMP layer less then 4 bytes for ICMPv6 Echo") 152 } 153 i.Identifier = binary.BigEndian.Uint16(data[0:2]) 154 i.SeqNumber = binary.BigEndian.Uint16(data[2:4]) 155 156 return nil 157 } 158 159 // SerializeTo writes the serialized form of this layer into the 160 // SerializationBuffer, implementing gopacket.SerializableLayer. 161 // See the docs for gopacket.SerializableLayer for more info. 162 func (i *ICMPv6Echo) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 163 buf, err := b.PrependBytes(4) 164 if err != nil { 165 return err 166 } 167 168 binary.BigEndian.PutUint16(buf, i.Identifier) 169 binary.BigEndian.PutUint16(buf[2:], i.SeqNumber) 170 return nil 171 } 172 173 // LayerType returns LayerTypeICMPv6. 174 func (i *ICMPv6RouterSolicitation) LayerType() gopacket.LayerType { 175 return LayerTypeICMPv6RouterSolicitation 176 } 177 178 // NextLayerType returns the layer type contained by this DecodingLayer. 179 func (i *ICMPv6RouterSolicitation) NextLayerType() gopacket.LayerType { 180 return gopacket.LayerTypePayload 181 } 182 183 // DecodeFromBytes decodes the given bytes into this layer. 184 func (i *ICMPv6RouterSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 185 // first 4 bytes are reserved followed by options 186 if len(data) < 4 { 187 df.SetTruncated() 188 return errors.New("ICMP layer less then 4 bytes for ICMPv6 router solicitation") 189 } 190 191 // truncate old options 192 i.Options = i.Options[:0] 193 194 return i.Options.DecodeFromBytes(data[4:], df) 195 } 196 197 // SerializeTo writes the serialized form of this layer into the 198 // SerializationBuffer, implementing gopacket.SerializableLayer. 199 // See the docs for gopacket.SerializableLayer for more info. 200 func (i *ICMPv6RouterSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 201 if err := i.Options.SerializeTo(b, opts); err != nil { 202 return err 203 } 204 205 buf, err := b.PrependBytes(4) 206 if err != nil { 207 return err 208 } 209 210 copy(buf, lotsOfZeros[:4]) 211 return nil 212 } 213 214 // CanDecode returns the set of layer types that this DecodingLayer can decode. 215 func (i *ICMPv6RouterSolicitation) CanDecode() gopacket.LayerClass { 216 return LayerTypeICMPv6RouterSolicitation 217 } 218 219 // LayerType returns LayerTypeICMPv6RouterAdvertisement. 220 func (i *ICMPv6RouterAdvertisement) LayerType() gopacket.LayerType { 221 return LayerTypeICMPv6RouterAdvertisement 222 } 223 224 // NextLayerType returns the layer type contained by this DecodingLayer. 225 func (i *ICMPv6RouterAdvertisement) NextLayerType() gopacket.LayerType { 226 return gopacket.LayerTypePayload 227 } 228 229 // DecodeFromBytes decodes the given bytes into this layer. 230 func (i *ICMPv6RouterAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 231 if len(data) < 12 { 232 df.SetTruncated() 233 return errors.New("ICMP layer less then 12 bytes for ICMPv6 router advertisement") 234 } 235 236 i.HopLimit = uint8(data[0]) 237 // M, O bit followed by 6 reserved bits 238 i.Flags = uint8(data[1]) 239 i.RouterLifetime = binary.BigEndian.Uint16(data[2:4]) 240 i.ReachableTime = binary.BigEndian.Uint32(data[4:8]) 241 i.RetransTimer = binary.BigEndian.Uint32(data[8:12]) 242 i.BaseLayer = BaseLayer{data, nil} // assume no payload 243 244 // truncate old options 245 i.Options = i.Options[:0] 246 247 return i.Options.DecodeFromBytes(data[12:], df) 248 } 249 250 // SerializeTo writes the serialized form of this layer into the 251 // SerializationBuffer, implementing gopacket.SerializableLayer. 252 // See the docs for gopacket.SerializableLayer for more info. 253 func (i *ICMPv6RouterAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 254 if err := i.Options.SerializeTo(b, opts); err != nil { 255 return err 256 } 257 258 buf, err := b.PrependBytes(12) 259 if err != nil { 260 return err 261 } 262 263 buf[0] = byte(i.HopLimit) 264 buf[1] = byte(i.Flags) 265 binary.BigEndian.PutUint16(buf[2:], i.RouterLifetime) 266 binary.BigEndian.PutUint32(buf[4:], i.ReachableTime) 267 binary.BigEndian.PutUint32(buf[8:], i.RetransTimer) 268 return nil 269 } 270 271 // CanDecode returns the set of layer types that this DecodingLayer can decode. 272 func (i *ICMPv6RouterAdvertisement) CanDecode() gopacket.LayerClass { 273 return LayerTypeICMPv6RouterAdvertisement 274 } 275 276 // ManagedAddressConfig is true when addresses are available via DHCPv6. If 277 // set, the OtherConfig flag is redundant. 278 func (i *ICMPv6RouterAdvertisement) ManagedAddressConfig() bool { 279 return i.Flags&0x80 != 0 280 } 281 282 // OtherConfig is true when there is other configuration information available 283 // via DHCPv6. For example, DNS-related information. 284 func (i *ICMPv6RouterAdvertisement) OtherConfig() bool { 285 return i.Flags&0x40 != 0 286 } 287 288 // LayerType returns LayerTypeICMPv6NeighborSolicitation. 289 func (i *ICMPv6NeighborSolicitation) LayerType() gopacket.LayerType { 290 return LayerTypeICMPv6NeighborSolicitation 291 } 292 293 // NextLayerType returns the layer type contained by this DecodingLayer. 294 func (i *ICMPv6NeighborSolicitation) NextLayerType() gopacket.LayerType { 295 return gopacket.LayerTypePayload 296 } 297 298 // DecodeFromBytes decodes the given bytes into this layer. 299 func (i *ICMPv6NeighborSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 300 if len(data) < 20 { 301 df.SetTruncated() 302 return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor solicitation") 303 } 304 305 i.TargetAddress = net.IP(data[4:20]) 306 i.BaseLayer = BaseLayer{data, nil} // assume no payload 307 308 // truncate old options 309 i.Options = i.Options[:0] 310 311 return i.Options.DecodeFromBytes(data[20:], df) 312 } 313 314 // SerializeTo writes the serialized form of this layer into the 315 // SerializationBuffer, implementing gopacket.SerializableLayer. 316 // See the docs for gopacket.SerializableLayer for more info. 317 func (i *ICMPv6NeighborSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 318 if err := i.Options.SerializeTo(b, opts); err != nil { 319 return err 320 } 321 322 buf, err := b.PrependBytes(20) 323 if err != nil { 324 return err 325 } 326 327 copy(buf, lotsOfZeros[:4]) 328 copy(buf[4:], i.TargetAddress) 329 return nil 330 } 331 332 // CanDecode returns the set of layer types that this DecodingLayer can decode. 333 func (i *ICMPv6NeighborSolicitation) CanDecode() gopacket.LayerClass { 334 return LayerTypeICMPv6NeighborSolicitation 335 } 336 337 // LayerType returns LayerTypeICMPv6NeighborAdvertisement. 338 func (i *ICMPv6NeighborAdvertisement) LayerType() gopacket.LayerType { 339 return LayerTypeICMPv6NeighborAdvertisement 340 } 341 342 // NextLayerType returns the layer type contained by this DecodingLayer. 343 func (i *ICMPv6NeighborAdvertisement) NextLayerType() gopacket.LayerType { 344 return gopacket.LayerTypePayload 345 } 346 347 // DecodeFromBytes decodes the given bytes into this layer. 348 func (i *ICMPv6NeighborAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 349 if len(data) < 20 { 350 df.SetTruncated() 351 return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor advertisement") 352 } 353 354 i.Flags = uint8(data[0]) 355 i.TargetAddress = net.IP(data[4:20]) 356 i.BaseLayer = BaseLayer{data, nil} // assume no payload 357 358 // truncate old options 359 i.Options = i.Options[:0] 360 361 return i.Options.DecodeFromBytes(data[20:], df) 362 } 363 364 // SerializeTo writes the serialized form of this layer into the 365 // SerializationBuffer, implementing gopacket.SerializableLayer. 366 // See the docs for gopacket.SerializableLayer for more info. 367 func (i *ICMPv6NeighborAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 368 if err := i.Options.SerializeTo(b, opts); err != nil { 369 return err 370 } 371 372 buf, err := b.PrependBytes(20) 373 if err != nil { 374 return err 375 } 376 377 buf[0] = byte(i.Flags) 378 copy(buf[1:], lotsOfZeros[:3]) 379 copy(buf[4:], i.TargetAddress) 380 return nil 381 } 382 383 // CanDecode returns the set of layer types that this DecodingLayer can decode. 384 func (i *ICMPv6NeighborAdvertisement) CanDecode() gopacket.LayerClass { 385 return LayerTypeICMPv6NeighborAdvertisement 386 } 387 388 // Router indicates whether the sender is a router or not. 389 func (i *ICMPv6NeighborAdvertisement) Router() bool { 390 return i.Flags&0x80 != 0 391 } 392 393 // Solicited indicates whether the advertisement was solicited or not. 394 func (i *ICMPv6NeighborAdvertisement) Solicited() bool { 395 return i.Flags&0x40 != 0 396 } 397 398 // Override indicates whether the advertisement should Override an existing 399 // cache entry. 400 func (i *ICMPv6NeighborAdvertisement) Override() bool { 401 return i.Flags&0x20 != 0 402 } 403 404 // LayerType returns LayerTypeICMPv6Redirect. 405 func (i *ICMPv6Redirect) LayerType() gopacket.LayerType { 406 return LayerTypeICMPv6Redirect 407 } 408 409 // NextLayerType returns the layer type contained by this DecodingLayer. 410 func (i *ICMPv6Redirect) NextLayerType() gopacket.LayerType { 411 return gopacket.LayerTypePayload 412 } 413 414 // DecodeFromBytes decodes the given bytes into this layer. 415 func (i *ICMPv6Redirect) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 416 if len(data) < 36 { 417 df.SetTruncated() 418 return errors.New("ICMP layer less then 36 bytes for ICMPv6 redirect") 419 } 420 421 i.TargetAddress = net.IP(data[4:20]) 422 i.DestinationAddress = net.IP(data[20:36]) 423 i.BaseLayer = BaseLayer{data, nil} // assume no payload 424 425 // truncate old options 426 i.Options = i.Options[:0] 427 428 return i.Options.DecodeFromBytes(data[36:], df) 429 } 430 431 // SerializeTo writes the serialized form of this layer into the 432 // SerializationBuffer, implementing gopacket.SerializableLayer. 433 // See the docs for gopacket.SerializableLayer for more info. 434 func (i *ICMPv6Redirect) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 435 if err := i.Options.SerializeTo(b, opts); err != nil { 436 return err 437 } 438 439 buf, err := b.PrependBytes(36) 440 if err != nil { 441 return err 442 } 443 444 copy(buf, lotsOfZeros[:4]) 445 copy(buf[4:], i.TargetAddress) 446 copy(buf[20:], i.DestinationAddress) 447 return nil 448 } 449 450 // CanDecode returns the set of layer types that this DecodingLayer can decode. 451 func (i *ICMPv6Redirect) CanDecode() gopacket.LayerClass { 452 return LayerTypeICMPv6Redirect 453 } 454 455 func (i ICMPv6Option) String() string { 456 hd := hex.EncodeToString(i.Data) 457 if len(hd) > 0 { 458 hd = " 0x" + hd 459 } 460 461 switch i.Type { 462 case ICMPv6OptSourceAddress, ICMPv6OptTargetAddress: 463 return fmt.Sprintf("ICMPv6Option(%s:%v)", 464 i.Type, 465 net.HardwareAddr(i.Data)) 466 case ICMPv6OptPrefixInfo: 467 if len(i.Data) == 30 { 468 prefixLen := uint8(i.Data[0]) 469 onLink := (i.Data[1]&0x80 != 0) 470 autonomous := (i.Data[1]&0x40 != 0) 471 validLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[2:6])) * time.Second 472 preferredLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[6:10])) * time.Second 473 474 prefix := net.IP(i.Data[14:]) 475 476 return fmt.Sprintf("ICMPv6Option(%s:%v/%v:%t:%t:%v:%v)", 477 i.Type, 478 prefix, prefixLen, 479 onLink, autonomous, 480 validLifetime, preferredLifetime) 481 } 482 case ICMPv6OptRedirectedHeader: 483 // could invoke IP decoder on data... probably best not to 484 break 485 case ICMPv6OptMTU: 486 if len(i.Data) == 6 { 487 return fmt.Sprintf("ICMPv6Option(%s:%v)", 488 i.Type, 489 binary.BigEndian.Uint32(i.Data[2:])) 490 } 491 492 } 493 return fmt.Sprintf("ICMPv6Option(%s:%s)", i.Type, hd) 494 } 495 496 // DecodeFromBytes decodes the given bytes into this layer. 497 func (i *ICMPv6Options) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 498 for len(data) > 0 { 499 if len(data) < 2 { 500 df.SetTruncated() 501 return errors.New("ICMP layer less then 2 bytes for ICMPv6 message option") 502 } 503 504 // unit is 8 octets, convert to bytes 505 length := int(data[1]) * 8 506 507 if length == 0 { 508 df.SetTruncated() 509 return errors.New("ICMPv6 message option with length 0") 510 } 511 512 if len(data) < length { 513 df.SetTruncated() 514 return fmt.Errorf("ICMP layer only %v bytes for ICMPv6 message option with length %v", len(data), length) 515 } 516 517 o := ICMPv6Option{ 518 Type: ICMPv6Opt(data[0]), 519 Data: data[2:length], 520 } 521 522 // chop off option we just consumed 523 data = data[length:] 524 525 *i = append(*i, o) 526 } 527 528 return nil 529 } 530 531 // SerializeTo writes the serialized form of this layer into the 532 // SerializationBuffer, implementing gopacket.SerializableLayer. 533 // See the docs for gopacket.SerializableLayer for more info. 534 func (i *ICMPv6Options) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 535 for _, opt := range []ICMPv6Option(*i) { 536 length := len(opt.Data) + 2 537 buf, err := b.PrependBytes(length) 538 if err != nil { 539 return err 540 } 541 542 buf[0] = byte(opt.Type) 543 buf[1] = byte(length / 8) 544 copy(buf[2:], opt.Data) 545 } 546 547 return nil 548 } 549 550 func decodeICMPv6Echo(data []byte, p gopacket.PacketBuilder) error { 551 i := &ICMPv6Echo{} 552 return decodingLayerDecoder(i, data, p) 553 } 554 555 func decodeICMPv6RouterSolicitation(data []byte, p gopacket.PacketBuilder) error { 556 i := &ICMPv6RouterSolicitation{} 557 return decodingLayerDecoder(i, data, p) 558 } 559 560 func decodeICMPv6RouterAdvertisement(data []byte, p gopacket.PacketBuilder) error { 561 i := &ICMPv6RouterAdvertisement{} 562 return decodingLayerDecoder(i, data, p) 563 } 564 565 func decodeICMPv6NeighborSolicitation(data []byte, p gopacket.PacketBuilder) error { 566 i := &ICMPv6NeighborSolicitation{} 567 return decodingLayerDecoder(i, data, p) 568 } 569 570 func decodeICMPv6NeighborAdvertisement(data []byte, p gopacket.PacketBuilder) error { 571 i := &ICMPv6NeighborAdvertisement{} 572 return decodingLayerDecoder(i, data, p) 573 } 574 575 func decodeICMPv6Redirect(data []byte, p gopacket.PacketBuilder) error { 576 i := &ICMPv6Redirect{} 577 return decodingLayerDecoder(i, data, p) 578 }