github.com/gopacket/gopacket@v1.1.0/layers/rudp.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  type RUDP struct {
    17  	BaseLayer
    18  	SYN, ACK, EACK, RST, NUL bool
    19  	Version                  uint8
    20  	HeaderLength             uint8
    21  	SrcPort, DstPort         RUDPPort
    22  	DataLength               uint16
    23  	Seq, Ack, Checksum       uint32
    24  	VariableHeaderArea       []byte
    25  	// RUDPHeaderSyn contains SYN information for the RUDP packet,
    26  	// if the SYN flag is set
    27  	*RUDPHeaderSYN
    28  	// RUDPHeaderEack contains EACK information for the RUDP packet,
    29  	// if the EACK flag is set.
    30  	*RUDPHeaderEACK
    31  }
    32  
    33  type RUDPHeaderSYN struct {
    34  	MaxOutstandingSegments, MaxSegmentSize, OptionFlags uint16
    35  }
    36  
    37  type RUDPHeaderEACK struct {
    38  	SeqsReceivedOK []uint32
    39  }
    40  
    41  // LayerType returns gopacket.LayerTypeRUDP.
    42  func (r *RUDP) LayerType() gopacket.LayerType { return LayerTypeRUDP }
    43  
    44  func decodeRUDP(data []byte, p gopacket.PacketBuilder) error {
    45  	r := &RUDP{
    46  		SYN:          data[0]&0x80 != 0,
    47  		ACK:          data[0]&0x40 != 0,
    48  		EACK:         data[0]&0x20 != 0,
    49  		RST:          data[0]&0x10 != 0,
    50  		NUL:          data[0]&0x08 != 0,
    51  		Version:      data[0] & 0x3,
    52  		HeaderLength: data[1],
    53  		SrcPort:      RUDPPort(data[2]),
    54  		DstPort:      RUDPPort(data[3]),
    55  		DataLength:   binary.BigEndian.Uint16(data[4:6]),
    56  		Seq:          binary.BigEndian.Uint32(data[6:10]),
    57  		Ack:          binary.BigEndian.Uint32(data[10:14]),
    58  		Checksum:     binary.BigEndian.Uint32(data[14:18]),
    59  	}
    60  	if r.HeaderLength < 9 {
    61  		return fmt.Errorf("RUDP packet with too-short header length %d", r.HeaderLength)
    62  	}
    63  	hlen := int(r.HeaderLength) * 2
    64  	r.Contents = data[:hlen]
    65  	r.Payload = data[hlen : hlen+int(r.DataLength)]
    66  	r.VariableHeaderArea = data[18:hlen]
    67  	headerData := r.VariableHeaderArea
    68  	switch {
    69  	case r.SYN:
    70  		if len(headerData) != 6 {
    71  			return fmt.Errorf("RUDP packet invalid SYN header length: %d", len(headerData))
    72  		}
    73  		r.RUDPHeaderSYN = &RUDPHeaderSYN{
    74  			MaxOutstandingSegments: binary.BigEndian.Uint16(headerData[:2]),
    75  			MaxSegmentSize:         binary.BigEndian.Uint16(headerData[2:4]),
    76  			OptionFlags:            binary.BigEndian.Uint16(headerData[4:6]),
    77  		}
    78  	case r.EACK:
    79  		if len(headerData)%4 != 0 {
    80  			return fmt.Errorf("RUDP packet invalid EACK header length: %d", len(headerData))
    81  		}
    82  		r.RUDPHeaderEACK = &RUDPHeaderEACK{make([]uint32, len(headerData)/4)}
    83  		for i := 0; i < len(headerData); i += 4 {
    84  			r.SeqsReceivedOK[i/4] = binary.BigEndian.Uint32(headerData[i : i+4])
    85  		}
    86  	}
    87  	p.AddLayer(r)
    88  	p.SetTransportLayer(r)
    89  	return p.NextDecoder(gopacket.LayerTypePayload)
    90  }
    91  
    92  func (r *RUDP) TransportFlow() gopacket.Flow {
    93  	return gopacket.NewFlow(EndpointRUDPPort, []byte{byte(r.SrcPort)}, []byte{byte(r.DstPort)})
    94  }