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 8package layers 9 10import ( 11 "encoding/binary" 12 "encoding/hex" 13 "errors" 14 "fmt" 15 "net" 16 "time" 17 18 "github.com/google/gopacket" 19) 20 21// Based on RFC 4861 22 23// ICMPv6Opt indicate how to decode the data associated with each ICMPv6Option. 24type ICMPv6Opt uint8 25 26const ( 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. 58type ICMPv6Echo struct { 59 BaseLayer 60 Identifier uint16 61 SeqNumber uint16 62} 63 64// ICMPv6RouterSolicitation is sent by hosts to find routers. 65type ICMPv6RouterSolicitation struct { 66 BaseLayer 67 Options ICMPv6Options 68} 69 70// ICMPv6RouterAdvertisement is sent by routers in response to Solicitation. 71type 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. 83type ICMPv6NeighborSolicitation struct { 84 BaseLayer 85 TargetAddress net.IP 86 Options ICMPv6Options 87} 88 89// ICMPv6NeighborAdvertisement is sent by nodes in response to Solicitation. 90type 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. 99type 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. 107type ICMPv6Option struct { 108 Type ICMPv6Opt 109 Data []byte 110} 111 112// ICMPv6Options is a slice of ICMPv6Option. 113type ICMPv6Options []ICMPv6Option 114 115func (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. 133func (i *ICMPv6Echo) CanDecode() gopacket.LayerClass { 134 return LayerTypeICMPv6Echo 135} 136 137// LayerType returns LayerTypeICMPv6Echo. 138func (i *ICMPv6Echo) LayerType() gopacket.LayerType { 139 return LayerTypeICMPv6Echo 140} 141 142// NextLayerType returns the layer type contained by this DecodingLayer. 143func (i *ICMPv6Echo) NextLayerType() gopacket.LayerType { 144 return gopacket.LayerTypePayload 145} 146 147// DecodeFromBytes decodes the given bytes into this layer. 148func (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. 162func (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. 174func (i *ICMPv6RouterSolicitation) LayerType() gopacket.LayerType { 175 return LayerTypeICMPv6RouterSolicitation 176} 177 178// NextLayerType returns the layer type contained by this DecodingLayer. 179func (i *ICMPv6RouterSolicitation) NextLayerType() gopacket.LayerType { 180 return gopacket.LayerTypePayload 181} 182 183// DecodeFromBytes decodes the given bytes into this layer. 184func (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. 200func (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. 215func (i *ICMPv6RouterSolicitation) CanDecode() gopacket.LayerClass { 216 return LayerTypeICMPv6RouterSolicitation 217} 218 219// LayerType returns LayerTypeICMPv6RouterAdvertisement. 220func (i *ICMPv6RouterAdvertisement) LayerType() gopacket.LayerType { 221 return LayerTypeICMPv6RouterAdvertisement 222} 223 224// NextLayerType returns the layer type contained by this DecodingLayer. 225func (i *ICMPv6RouterAdvertisement) NextLayerType() gopacket.LayerType { 226 return gopacket.LayerTypePayload 227} 228 229// DecodeFromBytes decodes the given bytes into this layer. 230func (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. 253func (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. 272func (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. 278func (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. 284func (i *ICMPv6RouterAdvertisement) OtherConfig() bool { 285 return i.Flags&0x40 != 0 286} 287 288// LayerType returns LayerTypeICMPv6NeighborSolicitation. 289func (i *ICMPv6NeighborSolicitation) LayerType() gopacket.LayerType { 290 return LayerTypeICMPv6NeighborSolicitation 291} 292 293// NextLayerType returns the layer type contained by this DecodingLayer. 294func (i *ICMPv6NeighborSolicitation) NextLayerType() gopacket.LayerType { 295 return gopacket.LayerTypePayload 296} 297 298// DecodeFromBytes decodes the given bytes into this layer. 299func (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. 317func (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. 333func (i *ICMPv6NeighborSolicitation) CanDecode() gopacket.LayerClass { 334 return LayerTypeICMPv6NeighborSolicitation 335} 336 337// LayerType returns LayerTypeICMPv6NeighborAdvertisement. 338func (i *ICMPv6NeighborAdvertisement) LayerType() gopacket.LayerType { 339 return LayerTypeICMPv6NeighborAdvertisement 340} 341 342// NextLayerType returns the layer type contained by this DecodingLayer. 343func (i *ICMPv6NeighborAdvertisement) NextLayerType() gopacket.LayerType { 344 return gopacket.LayerTypePayload 345} 346 347// DecodeFromBytes decodes the given bytes into this layer. 348func (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. 367func (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. 384func (i *ICMPv6NeighborAdvertisement) CanDecode() gopacket.LayerClass { 385 return LayerTypeICMPv6NeighborAdvertisement 386} 387 388// Router indicates whether the sender is a router or not. 389func (i *ICMPv6NeighborAdvertisement) Router() bool { 390 return i.Flags&0x80 != 0 391} 392 393// Solicited indicates whether the advertisement was solicited or not. 394func (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. 400func (i *ICMPv6NeighborAdvertisement) Override() bool { 401 return i.Flags&0x20 != 0 402} 403 404// LayerType returns LayerTypeICMPv6Redirect. 405func (i *ICMPv6Redirect) LayerType() gopacket.LayerType { 406 return LayerTypeICMPv6Redirect 407} 408 409// NextLayerType returns the layer type contained by this DecodingLayer. 410func (i *ICMPv6Redirect) NextLayerType() gopacket.LayerType { 411 return gopacket.LayerTypePayload 412} 413 414// DecodeFromBytes decodes the given bytes into this layer. 415func (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. 434func (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. 451func (i *ICMPv6Redirect) CanDecode() gopacket.LayerClass { 452 return LayerTypeICMPv6Redirect 453} 454 455func (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. 497func (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. 534func (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 550func decodeICMPv6Echo(data []byte, p gopacket.PacketBuilder) error { 551 i := &ICMPv6Echo{} 552 return decodingLayerDecoder(i, data, p) 553} 554 555func decodeICMPv6RouterSolicitation(data []byte, p gopacket.PacketBuilder) error { 556 i := &ICMPv6RouterSolicitation{} 557 return decodingLayerDecoder(i, data, p) 558} 559 560func decodeICMPv6RouterAdvertisement(data []byte, p gopacket.PacketBuilder) error { 561 i := &ICMPv6RouterAdvertisement{} 562 return decodingLayerDecoder(i, data, p) 563} 564 565func decodeICMPv6NeighborSolicitation(data []byte, p gopacket.PacketBuilder) error { 566 i := &ICMPv6NeighborSolicitation{} 567 return decodingLayerDecoder(i, data, p) 568} 569 570func decodeICMPv6NeighborAdvertisement(data []byte, p gopacket.PacketBuilder) error { 571 i := &ICMPv6NeighborAdvertisement{} 572 return decodingLayerDecoder(i, data, p) 573} 574 575func decodeICMPv6Redirect(data []byte, p gopacket.PacketBuilder) error { 576 i := &ICMPv6Redirect{} 577 return decodingLayerDecoder(i, data, p) 578} 579