ip6.go 17 KB

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