github.com/gopacket/gopacket@v1.1.0/layers/ctp.go (about)

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