ip6.go 19 KB

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