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