github.com/gopacket/gopacket@v1.1.0/layers/ip6.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 "net" 15 16 "github.com/gopacket/gopacket" 17 ) 18 19 const ( 20 // IPv6HopByHopOptionJumbogram code as defined in RFC 2675 21 IPv6HopByHopOptionJumbogram = 0xC2 22 ) 23 24 const ( 25 ipv6MaxPayloadLength = 65535 26 ) 27 28 // IPv6 is the layer for the IPv6 header. 29 type IPv6 struct { 30 // http://www.networksorcery.com/enp/protocol/ipv6.htm 31 BaseLayer 32 Version uint8 33 TrafficClass uint8 34 FlowLabel uint32 35 Length uint16 36 NextHeader IPProtocol 37 HopLimit uint8 38 SrcIP net.IP 39 DstIP net.IP 40 HopByHop *IPv6HopByHop 41 // hbh will be pointed to by HopByHop if that layer exists. 42 hbh IPv6HopByHop 43 } 44 45 // LayerType returns LayerTypeIPv6 46 func (ipv6 *IPv6) LayerType() gopacket.LayerType { return LayerTypeIPv6 } 47 48 // NetworkFlow returns this new Flow (EndpointIPv6, SrcIP, DstIP) 49 func (ipv6 *IPv6) NetworkFlow() gopacket.Flow { 50 return gopacket.NewFlow(EndpointIPv6, ipv6.SrcIP, ipv6.DstIP) 51 } 52 53 // Search for Jumbo Payload TLV in IPv6HopByHop and return (length, true) if found 54 func getIPv6HopByHopJumboLength(hopopts *IPv6HopByHop) (uint32, bool, error) { 55 var tlv *IPv6HopByHopOption 56 57 for _, t := range hopopts.Options { 58 if t.OptionType == IPv6HopByHopOptionJumbogram { 59 tlv = t 60 break 61 } 62 } 63 if tlv == nil { 64 // Not found 65 return 0, false, nil 66 } 67 if len(tlv.OptionData) != 4 { 68 return 0, false, errors.New("Jumbo length TLV data must have length 4") 69 } 70 l := binary.BigEndian.Uint32(tlv.OptionData) 71 if l <= ipv6MaxPayloadLength { 72 return 0, false, fmt.Errorf("Jumbo length cannot be less than %d", ipv6MaxPayloadLength+1) 73 } 74 // Found 75 return l, true, nil 76 } 77 78 // Adds zero-valued Jumbo TLV to IPv6 header if it does not exist 79 // (if necessary add hop-by-hop header) 80 func addIPv6JumboOption(ip6 *IPv6) { 81 var tlv *IPv6HopByHopOption 82 83 if ip6.HopByHop == nil { 84 // Add IPv6 HopByHop 85 ip6.HopByHop = &IPv6HopByHop{} 86 ip6.HopByHop.NextHeader = ip6.NextHeader 87 ip6.HopByHop.HeaderLength = 0 88 ip6.NextHeader = IPProtocolIPv6HopByHop 89 } 90 for _, t := range ip6.HopByHop.Options { 91 if t.OptionType == IPv6HopByHopOptionJumbogram { 92 tlv = t 93 break 94 } 95 } 96 if tlv == nil { 97 // Add Jumbo TLV 98 tlv = &IPv6HopByHopOption{} 99 ip6.HopByHop.Options = append(ip6.HopByHop.Options, tlv) 100 } 101 tlv.SetJumboLength(0) 102 } 103 104 // Set jumbo length in serialized IPv6 payload (starting with HopByHop header) 105 func setIPv6PayloadJumboLength(hbh []byte) error { 106 pLen := len(hbh) 107 if pLen < 8 { 108 //HopByHop is minimum 8 bytes 109 return fmt.Errorf("Invalid IPv6 payload (length %d)", pLen) 110 } 111 hbhLen := int((hbh[1] + 1) * 8) 112 if hbhLen > pLen { 113 return fmt.Errorf("Invalid hop-by-hop length (length: %d, payload: %d", hbhLen, pLen) 114 } 115 offset := 2 //start with options 116 for offset < hbhLen { 117 opt := hbh[offset] 118 if opt == 0 { 119 //Pad1 120 offset++ 121 continue 122 } 123 optLen := int(hbh[offset+1]) 124 if opt == IPv6HopByHopOptionJumbogram { 125 if optLen == 4 { 126 binary.BigEndian.PutUint32(hbh[offset+2:], uint32(pLen)) 127 return nil 128 } 129 return fmt.Errorf("Jumbo TLV too short (%d bytes)", optLen) 130 } 131 offset += 2 + optLen 132 } 133 return errors.New("Jumbo TLV not found") 134 } 135 136 // SerializeTo writes the serialized form of this layer into the 137 // SerializationBuffer, implementing gopacket.SerializableLayer. 138 // See the docs for gopacket.SerializableLayer for more info. 139 func (ipv6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 140 var jumbo bool 141 var err error 142 143 payload := b.Bytes() 144 pLen := len(payload) 145 if pLen > ipv6MaxPayloadLength { 146 jumbo = true 147 if opts.FixLengths { 148 // We need to set the length later because the hop-by-hop header may 149 // not exist or else need padding, so pLen may yet change 150 addIPv6JumboOption(ipv6) 151 } else if ipv6.HopByHop == nil { 152 return fmt.Errorf("Cannot fit payload length of %d into IPv6 packet", pLen) 153 } else { 154 _, ok, err := getIPv6HopByHopJumboLength(ipv6.HopByHop) 155 if err != nil { 156 return err 157 } 158 if !ok { 159 return errors.New("Missing jumbo length hop-by-hop option") 160 } 161 } 162 } 163 164 hbhAlreadySerialized := false 165 if ipv6.HopByHop != nil { 166 for _, l := range b.Layers() { 167 if l == LayerTypeIPv6HopByHop { 168 hbhAlreadySerialized = true 169 break 170 } 171 } 172 } 173 if ipv6.HopByHop != nil && !hbhAlreadySerialized { 174 if ipv6.NextHeader != IPProtocolIPv6HopByHop { 175 // Just fix it instead of throwing an error 176 ipv6.NextHeader = IPProtocolIPv6HopByHop 177 } 178 err = ipv6.HopByHop.SerializeTo(b, opts) 179 if err != nil { 180 return err 181 } 182 payload = b.Bytes() 183 pLen = len(payload) 184 if opts.FixLengths && jumbo { 185 err := setIPv6PayloadJumboLength(payload) 186 if err != nil { 187 return err 188 } 189 } 190 } 191 192 if !jumbo && pLen > ipv6MaxPayloadLength { 193 return errors.New("Cannot fit payload into IPv6 header") 194 } 195 bytes, err := b.PrependBytes(40) 196 if err != nil { 197 return err 198 } 199 bytes[0] = (ipv6.Version << 4) | (ipv6.TrafficClass >> 4) 200 bytes[1] = (ipv6.TrafficClass << 4) | uint8(ipv6.FlowLabel>>16) 201 binary.BigEndian.PutUint16(bytes[2:], uint16(ipv6.FlowLabel)) 202 if opts.FixLengths { 203 if jumbo { 204 ipv6.Length = 0 205 } else { 206 ipv6.Length = uint16(pLen) 207 } 208 } 209 binary.BigEndian.PutUint16(bytes[4:], ipv6.Length) 210 bytes[6] = byte(ipv6.NextHeader) 211 bytes[7] = byte(ipv6.HopLimit) 212 if err := ipv6.AddressTo16(); err != nil { 213 return err 214 } 215 copy(bytes[8:], ipv6.SrcIP) 216 copy(bytes[24:], ipv6.DstIP) 217 return nil 218 } 219 220 // DecodeFromBytes implementation according to gopacket.DecodingLayer 221 func (ipv6 *IPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 222 if len(data) < 40 { 223 df.SetTruncated() 224 return fmt.Errorf("Invalid ip6 header. Length %d less than 40", len(data)) 225 } 226 ipv6.Version = uint8(data[0]) >> 4 227 ipv6.TrafficClass = uint8((binary.BigEndian.Uint16(data[0:2]) >> 4) & 0x00FF) 228 ipv6.FlowLabel = binary.BigEndian.Uint32(data[0:4]) & 0x000FFFFF 229 ipv6.Length = binary.BigEndian.Uint16(data[4:6]) 230 ipv6.NextHeader = IPProtocol(data[6]) 231 ipv6.HopLimit = data[7] 232 ipv6.SrcIP = data[8:24] 233 ipv6.DstIP = data[24:40] 234 ipv6.HopByHop = nil 235 ipv6.BaseLayer = BaseLayer{data[:40], data[40:]} 236 237 // We treat a HopByHop IPv6 option as part of the IPv6 packet, since its 238 // options are crucial for understanding what's actually happening per packet. 239 if ipv6.NextHeader == IPProtocolIPv6HopByHop { 240 err := ipv6.hbh.DecodeFromBytes(ipv6.Payload, df) 241 if err != nil { 242 return err 243 } 244 ipv6.HopByHop = &ipv6.hbh 245 pEnd, jumbo, err := getIPv6HopByHopJumboLength(ipv6.HopByHop) 246 if err != nil { 247 return err 248 } 249 if jumbo && ipv6.Length == 0 { 250 pEnd := int(pEnd) 251 if pEnd > len(ipv6.Payload) { 252 df.SetTruncated() 253 pEnd = len(ipv6.Payload) 254 } 255 ipv6.Payload = ipv6.Payload[:pEnd] 256 return nil 257 } else if jumbo && ipv6.Length != 0 { 258 return errors.New("IPv6 has jumbo length and IPv6 length is not 0") 259 } else if !jumbo && ipv6.Length == 0 { 260 return errors.New("IPv6 length 0, but HopByHop header does not have jumbogram option") 261 } else { 262 ipv6.Payload = ipv6.Payload[ipv6.hbh.ActualLength:] 263 } 264 } 265 266 if ipv6.Length == 0 { 267 return fmt.Errorf("IPv6 length 0, but next header is %v, not HopByHop", ipv6.NextHeader) 268 } 269 270 pEnd := int(ipv6.Length) 271 if pEnd > len(ipv6.Payload) { 272 df.SetTruncated() 273 pEnd = len(ipv6.Payload) 274 } 275 ipv6.Payload = ipv6.Payload[:pEnd] 276 277 return nil 278 } 279 280 // CanDecode implementation according to gopacket.DecodingLayer 281 func (ipv6 *IPv6) CanDecode() gopacket.LayerClass { 282 return LayerTypeIPv6 283 } 284 285 // NextLayerType implementation according to gopacket.DecodingLayer 286 func (ipv6 *IPv6) NextLayerType() gopacket.LayerType { 287 if ipv6.HopByHop != nil { 288 return ipv6.HopByHop.NextHeader.LayerType() 289 } 290 return ipv6.NextHeader.LayerType() 291 } 292 293 func decodeIPv6(data []byte, p gopacket.PacketBuilder) error { 294 ip6 := &IPv6{} 295 err := ip6.DecodeFromBytes(data, p) 296 p.AddLayer(ip6) 297 p.SetNetworkLayer(ip6) 298 if ip6.HopByHop != nil { 299 p.AddLayer(ip6.HopByHop) 300 } 301 if err != nil { 302 return err 303 } 304 return p.NextDecoder(ip6.NextLayerType()) 305 } 306 307 type ipv6HeaderTLVOption struct { 308 OptionType, OptionLength uint8 309 ActualLength int 310 OptionData []byte 311 OptionAlignment [2]uint8 // Xn+Y = [2]uint8{X, Y} 312 } 313 314 func (h *ipv6HeaderTLVOption) serializeTo(data []byte, fixLengths bool, dryrun bool) int { 315 if fixLengths { 316 h.OptionLength = uint8(len(h.OptionData)) 317 } 318 length := int(h.OptionLength) + 2 319 if !dryrun { 320 data[0] = h.OptionType 321 data[1] = h.OptionLength 322 copy(data[2:], h.OptionData) 323 } 324 return length 325 } 326 327 func decodeIPv6HeaderTLVOption(data []byte, df gopacket.DecodeFeedback) (h *ipv6HeaderTLVOption, _ error) { 328 if len(data) < 2 { 329 df.SetTruncated() 330 return nil, errors.New("IPv6 header option too small") 331 } 332 h = &ipv6HeaderTLVOption{} 333 if data[0] == 0 { 334 h.ActualLength = 1 335 return 336 } 337 h.OptionType = data[0] 338 h.OptionLength = data[1] 339 h.ActualLength = int(h.OptionLength) + 2 340 if len(data) < h.ActualLength { 341 df.SetTruncated() 342 return nil, errors.New("IPv6 header TLV option too small") 343 } 344 h.OptionData = data[2:h.ActualLength] 345 return 346 } 347 348 func serializeTLVOptionPadding(data []byte, padLength int) { 349 if padLength <= 0 { 350 return 351 } 352 if padLength == 1 { 353 data[0] = 0x0 354 return 355 } 356 tlvLength := uint8(padLength) - 2 357 data[0] = 0x1 358 data[1] = tlvLength 359 if tlvLength != 0 { 360 for k := range data[2:] { 361 data[k+2] = 0x0 362 } 363 } 364 return 365 } 366 367 // If buf is 'nil' do a serialize dry run 368 func serializeIPv6HeaderTLVOptions(buf []byte, options []*ipv6HeaderTLVOption, fixLengths bool) int { 369 var l int 370 371 dryrun := buf == nil 372 length := 2 373 for _, opt := range options { 374 if fixLengths { 375 x := int(opt.OptionAlignment[0]) 376 y := int(opt.OptionAlignment[1]) 377 if x != 0 { 378 n := length / x 379 offset := x*n + y 380 if offset < length { 381 offset += x 382 } 383 if length != offset { 384 pad := offset - length 385 if !dryrun { 386 serializeTLVOptionPadding(buf[length-2:], pad) 387 } 388 length += pad 389 } 390 } 391 } 392 if dryrun { 393 l = opt.serializeTo(nil, fixLengths, true) 394 } else { 395 l = opt.serializeTo(buf[length-2:], fixLengths, false) 396 } 397 length += l 398 } 399 if fixLengths { 400 pad := length % 8 401 if pad != 0 { 402 if !dryrun { 403 serializeTLVOptionPadding(buf[length-2:], pad) 404 } 405 length += pad 406 } 407 } 408 return length - 2 409 } 410 411 type ipv6ExtensionBase struct { 412 BaseLayer 413 NextHeader IPProtocol 414 HeaderLength uint8 415 ActualLength int 416 } 417 418 func decodeIPv6ExtensionBase(data []byte, df gopacket.DecodeFeedback) (i ipv6ExtensionBase, returnedErr error) { 419 if len(data) < 2 { 420 df.SetTruncated() 421 return ipv6ExtensionBase{}, fmt.Errorf("Invalid ip6-extension header. Length %d less than 2", len(data)) 422 } 423 i.NextHeader = IPProtocol(data[0]) 424 i.HeaderLength = data[1] 425 i.ActualLength = int(i.HeaderLength)*8 + 8 426 if len(data) < i.ActualLength { 427 return ipv6ExtensionBase{}, fmt.Errorf("Invalid ip6-extension header. Length %d less than specified length %d", len(data), i.ActualLength) 428 } 429 i.Contents = data[:i.ActualLength] 430 i.Payload = data[i.ActualLength:] 431 return 432 } 433 434 // IPv6ExtensionSkipper is a DecodingLayer which decodes and ignores v6 435 // extensions. You can use it with a DecodingLayerParser to handle IPv6 stacks 436 // which may or may not have extensions. 437 type IPv6ExtensionSkipper struct { 438 NextHeader IPProtocol 439 BaseLayer 440 } 441 442 // DecodeFromBytes implementation according to gopacket.DecodingLayer 443 func (i *IPv6ExtensionSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 444 extension, err := decodeIPv6ExtensionBase(data, df) 445 if err != nil { 446 return err 447 } 448 i.BaseLayer = BaseLayer{data[:extension.ActualLength], data[extension.ActualLength:]} 449 i.NextHeader = extension.NextHeader 450 return nil 451 } 452 453 // CanDecode implementation according to gopacket.DecodingLayer 454 func (i *IPv6ExtensionSkipper) CanDecode() gopacket.LayerClass { 455 return LayerClassIPv6Extension 456 } 457 458 // NextLayerType implementation according to gopacket.DecodingLayer 459 func (i *IPv6ExtensionSkipper) NextLayerType() gopacket.LayerType { 460 return i.NextHeader.LayerType() 461 } 462 463 // IPv6HopByHopOption is a TLV option present in an IPv6 hop-by-hop extension. 464 type IPv6HopByHopOption ipv6HeaderTLVOption 465 466 // IPv6HopByHop is the IPv6 hop-by-hop extension. 467 type IPv6HopByHop struct { 468 ipv6ExtensionBase 469 Options []*IPv6HopByHopOption 470 } 471 472 // LayerType returns LayerTypeIPv6HopByHop. 473 func (i *IPv6HopByHop) LayerType() gopacket.LayerType { return LayerTypeIPv6HopByHop } 474 475 // SerializeTo implementation according to gopacket.SerializableLayer 476 func (i *IPv6HopByHop) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 477 var bytes []byte 478 var err error 479 480 o := make([]*ipv6HeaderTLVOption, 0, len(i.Options)) 481 for _, v := range i.Options { 482 o = append(o, (*ipv6HeaderTLVOption)(v)) 483 } 484 485 l := serializeIPv6HeaderTLVOptions(nil, o, opts.FixLengths) 486 bytes, err = b.PrependBytes(l) 487 if err != nil { 488 return err 489 } 490 serializeIPv6HeaderTLVOptions(bytes, o, opts.FixLengths) 491 492 length := len(bytes) + 2 493 if length%8 != 0 { 494 return errors.New("IPv6HopByHop actual length must be multiple of 8") 495 } 496 bytes, err = b.PrependBytes(2) 497 if err != nil { 498 return err 499 } 500 bytes[0] = uint8(i.NextHeader) 501 if opts.FixLengths { 502 i.HeaderLength = uint8((length / 8) - 1) 503 } 504 bytes[1] = uint8(i.HeaderLength) 505 return nil 506 } 507 508 // DecodeFromBytes implementation according to gopacket.DecodingLayer 509 func (i *IPv6HopByHop) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 510 var err error 511 i.ipv6ExtensionBase, err = decodeIPv6ExtensionBase(data, df) 512 if err != nil { 513 return err 514 } 515 i.Options = i.Options[:0] 516 offset := 2 517 for offset < i.ActualLength { 518 opt, err := decodeIPv6HeaderTLVOption(data[offset:], df) 519 if err != nil { 520 return err 521 } 522 i.Options = append(i.Options, (*IPv6HopByHopOption)(opt)) 523 offset += opt.ActualLength 524 } 525 return nil 526 } 527 528 func decodeIPv6HopByHop(data []byte, p gopacket.PacketBuilder) error { 529 i := &IPv6HopByHop{} 530 err := i.DecodeFromBytes(data, p) 531 p.AddLayer(i) 532 if err != nil { 533 return err 534 } 535 return p.NextDecoder(i.NextHeader) 536 } 537 538 // SetJumboLength adds the IPv6HopByHopOptionJumbogram with the given length 539 func (o *IPv6HopByHopOption) SetJumboLength(len uint32) { 540 o.OptionType = IPv6HopByHopOptionJumbogram 541 o.OptionLength = 4 542 o.ActualLength = 6 543 if o.OptionData == nil { 544 o.OptionData = make([]byte, 4) 545 } 546 binary.BigEndian.PutUint32(o.OptionData, len) 547 o.OptionAlignment = [2]uint8{4, 2} 548 } 549 550 // IPv6Routing is the IPv6 routing extension. 551 type IPv6Routing struct { 552 ipv6ExtensionBase 553 RoutingType uint8 554 SegmentsLeft uint8 555 // This segment is supposed to be zero according to RFC2460, the second set of 556 // 4 bytes in the extension. 557 Reserved []byte 558 // SourceRoutingIPs is the set of IPv6 addresses requested for source routing, 559 // set only if RoutingType == 0. 560 SourceRoutingIPs []net.IP 561 } 562 563 // LayerType returns LayerTypeIPv6Routing. 564 func (i *IPv6Routing) LayerType() gopacket.LayerType { return LayerTypeIPv6Routing } 565 566 func decodeIPv6Routing(data []byte, p gopacket.PacketBuilder) error { 567 base, err := decodeIPv6ExtensionBase(data, p) 568 if err != nil { 569 return err 570 } 571 i := &IPv6Routing{ 572 ipv6ExtensionBase: base, 573 RoutingType: data[2], 574 SegmentsLeft: data[3], 575 Reserved: data[4:8], 576 } 577 switch i.RoutingType { 578 case 0: // Source routing 579 if (i.ActualLength-8)%16 != 0 { 580 return fmt.Errorf("Invalid IPv6 source routing, length of type 0 packet %d", i.ActualLength) 581 } 582 for d := i.Contents[8:]; len(d) >= 16; d = d[16:] { 583 i.SourceRoutingIPs = append(i.SourceRoutingIPs, net.IP(d[:16])) 584 } 585 default: 586 return fmt.Errorf("Unknown IPv6 routing header type %d", i.RoutingType) 587 } 588 p.AddLayer(i) 589 return p.NextDecoder(i.NextHeader) 590 } 591 592 // IPv6Fragment is the IPv6 fragment header, used for packet 593 // fragmentation/defragmentation. 594 type IPv6Fragment struct { 595 BaseLayer 596 NextHeader IPProtocol 597 // Reserved1 is bits [8-16), from least to most significant, 0-indexed 598 Reserved1 uint8 599 FragmentOffset uint16 600 // Reserved2 is bits [29-31), from least to most significant, 0-indexed 601 Reserved2 uint8 602 MoreFragments bool 603 Identification uint32 604 } 605 606 // LayerType returns LayerTypeIPv6Fragment. 607 func (i *IPv6Fragment) LayerType() gopacket.LayerType { return LayerTypeIPv6Fragment } 608 609 func decodeIPv6Fragment(data []byte, p gopacket.PacketBuilder) error { 610 if len(data) < 8 { 611 p.SetTruncated() 612 return fmt.Errorf("Invalid ip6-fragment header. Length %d less than 8", len(data)) 613 } 614 i := &IPv6Fragment{ 615 BaseLayer: BaseLayer{data[:8], data[8:]}, 616 NextHeader: IPProtocol(data[0]), 617 Reserved1: data[1], 618 FragmentOffset: binary.BigEndian.Uint16(data[2:4]) >> 3, 619 Reserved2: data[3] & 0x6 >> 1, 620 MoreFragments: data[3]&0x1 != 0, 621 Identification: binary.BigEndian.Uint32(data[4:8]), 622 } 623 p.AddLayer(i) 624 return p.NextDecoder(gopacket.DecodeFragment) 625 } 626 627 // IPv6DestinationOption is a TLV option present in an IPv6 destination options extension. 628 type IPv6DestinationOption ipv6HeaderTLVOption 629 630 // IPv6Destination is the IPv6 destination options header. 631 type IPv6Destination struct { 632 ipv6ExtensionBase 633 Options []*IPv6DestinationOption 634 } 635 636 // LayerType returns LayerTypeIPv6Destination. 637 func (i *IPv6Destination) LayerType() gopacket.LayerType { return LayerTypeIPv6Destination } 638 639 // DecodeFromBytes implementation according to gopacket.DecodingLayer 640 func (i *IPv6Destination) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 641 var err error 642 i.ipv6ExtensionBase, err = decodeIPv6ExtensionBase(data, df) 643 if err != nil { 644 return err 645 } 646 offset := 2 647 for offset < i.ActualLength { 648 opt, err := decodeIPv6HeaderTLVOption(data[offset:], df) 649 if err != nil { 650 return err 651 } 652 i.Options = append(i.Options, (*IPv6DestinationOption)(opt)) 653 offset += opt.ActualLength 654 } 655 return nil 656 } 657 658 func decodeIPv6Destination(data []byte, p gopacket.PacketBuilder) error { 659 i := &IPv6Destination{} 660 err := i.DecodeFromBytes(data, p) 661 p.AddLayer(i) 662 if err != nil { 663 return err 664 } 665 return p.NextDecoder(i.NextHeader) 666 } 667 668 // SerializeTo writes the serialized form of this layer into the 669 // SerializationBuffer, implementing gopacket.SerializableLayer. 670 // See the docs for gopacket.SerializableLayer for more info. 671 func (i *IPv6Destination) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 672 var bytes []byte 673 var err error 674 675 o := make([]*ipv6HeaderTLVOption, 0, len(i.Options)) 676 for _, v := range i.Options { 677 o = append(o, (*ipv6HeaderTLVOption)(v)) 678 } 679 680 l := serializeIPv6HeaderTLVOptions(nil, o, opts.FixLengths) 681 bytes, err = b.PrependBytes(l) 682 if err != nil { 683 return err 684 } 685 serializeIPv6HeaderTLVOptions(bytes, o, opts.FixLengths) 686 687 length := len(bytes) + 2 688 if length%8 != 0 { 689 return errors.New("IPv6Destination actual length must be multiple of 8") 690 } 691 bytes, err = b.PrependBytes(2) 692 if err != nil { 693 return err 694 } 695 bytes[0] = uint8(i.NextHeader) 696 if opts.FixLengths { 697 i.HeaderLength = uint8((length / 8) - 1) 698 } 699 bytes[1] = uint8(i.HeaderLength) 700 return nil 701 } 702 703 func checkIPv6Address(addr net.IP) error { 704 if len(addr) == net.IPv6len { 705 return nil 706 } 707 if len(addr) == net.IPv4len { 708 return errors.New("address is IPv4") 709 } 710 return fmt.Errorf("wrong length of %d bytes instead of %d", len(addr), net.IPv6len) 711 } 712 713 // AddressTo16 ensures IPv6.SrcIP and IPv6.DstIP are actually IPv6 addresses (i.e. 16 byte addresses) 714 func (ipv6 *IPv6) AddressTo16() error { 715 if err := checkIPv6Address(ipv6.SrcIP); err != nil { 716 return fmt.Errorf("Invalid source IPv6 address (%s)", err) 717 } 718 if err := checkIPv6Address(ipv6.DstIP); err != nil { 719 return fmt.Errorf("Invalid destination IPv6 address (%s)", err) 720 } 721 return nil 722 }