ctp.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright 2012 Google, Inc. All rights reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the LICENSE file in the root of the source
  5. // tree.
  6. package layers
  7. import (
  8. "encoding/binary"
  9. "fmt"
  10. "github.com/google/gopacket"
  11. )
  12. // EthernetCTPFunction is the function code used by the EthernetCTP protocol to identify each
  13. // EthernetCTP layer.
  14. type EthernetCTPFunction uint16
  15. // EthernetCTPFunction values.
  16. const (
  17. EthernetCTPFunctionReply EthernetCTPFunction = 1
  18. EthernetCTPFunctionForwardData EthernetCTPFunction = 2
  19. )
  20. // EthernetCTP implements the EthernetCTP protocol, see http://www.mit.edu/people/jhawk/ctp.html.
  21. // We split EthernetCTP up into the top-level EthernetCTP layer, followed by zero or more
  22. // EthernetCTPForwardData layers, followed by a final EthernetCTPReply layer.
  23. type EthernetCTP struct {
  24. BaseLayer
  25. SkipCount uint16
  26. }
  27. // LayerType returns gopacket.LayerTypeEthernetCTP.
  28. func (c *EthernetCTP) LayerType() gopacket.LayerType {
  29. return LayerTypeEthernetCTP
  30. }
  31. // EthernetCTPForwardData is the ForwardData layer inside EthernetCTP. See EthernetCTP's docs for more
  32. // details.
  33. type EthernetCTPForwardData struct {
  34. BaseLayer
  35. Function EthernetCTPFunction
  36. ForwardAddress []byte
  37. }
  38. // LayerType returns gopacket.LayerTypeEthernetCTPForwardData.
  39. func (c *EthernetCTPForwardData) LayerType() gopacket.LayerType {
  40. return LayerTypeEthernetCTPForwardData
  41. }
  42. // ForwardEndpoint returns the EthernetCTPForwardData ForwardAddress as an endpoint.
  43. func (c *EthernetCTPForwardData) ForwardEndpoint() gopacket.Endpoint {
  44. return gopacket.NewEndpoint(EndpointMAC, c.ForwardAddress)
  45. }
  46. // EthernetCTPReply is the Reply layer inside EthernetCTP. See EthernetCTP's docs for more details.
  47. type EthernetCTPReply struct {
  48. BaseLayer
  49. Function EthernetCTPFunction
  50. ReceiptNumber uint16
  51. Data []byte
  52. }
  53. // LayerType returns gopacket.LayerTypeEthernetCTPReply.
  54. func (c *EthernetCTPReply) LayerType() gopacket.LayerType {
  55. return LayerTypeEthernetCTPReply
  56. }
  57. // Payload returns the EthernetCTP reply's Data bytes.
  58. func (c *EthernetCTPReply) Payload() []byte { return c.Data }
  59. func decodeEthernetCTP(data []byte, p gopacket.PacketBuilder) error {
  60. c := &EthernetCTP{
  61. SkipCount: binary.LittleEndian.Uint16(data[:2]),
  62. BaseLayer: BaseLayer{data[:2], data[2:]},
  63. }
  64. if c.SkipCount%2 != 0 {
  65. return fmt.Errorf("EthernetCTP skip count is odd: %d", c.SkipCount)
  66. }
  67. p.AddLayer(c)
  68. return p.NextDecoder(gopacket.DecodeFunc(decodeEthernetCTPFromFunctionType))
  69. }
  70. // decodeEthernetCTPFromFunctionType reads in the first 2 bytes to determine the EthernetCTP
  71. // layer type to decode next, then decodes based on that.
  72. func decodeEthernetCTPFromFunctionType(data []byte, p gopacket.PacketBuilder) error {
  73. function := EthernetCTPFunction(binary.LittleEndian.Uint16(data[:2]))
  74. switch function {
  75. case EthernetCTPFunctionReply:
  76. reply := &EthernetCTPReply{
  77. Function: function,
  78. ReceiptNumber: binary.LittleEndian.Uint16(data[2:4]),
  79. Data: data[4:],
  80. BaseLayer: BaseLayer{data, nil},
  81. }
  82. p.AddLayer(reply)
  83. p.SetApplicationLayer(reply)
  84. return nil
  85. case EthernetCTPFunctionForwardData:
  86. forward := &EthernetCTPForwardData{
  87. Function: function,
  88. ForwardAddress: data[2:8],
  89. BaseLayer: BaseLayer{data[:8], data[8:]},
  90. }
  91. p.AddLayer(forward)
  92. return p.NextDecoder(gopacket.DecodeFunc(decodeEthernetCTPFromFunctionType))
  93. }
  94. return fmt.Errorf("Unknown EthernetCTP function type %v", function)
  95. }