94 lines
2.8 KiB
Go
94 lines
2.8 KiB
Go
// Copyright 2012 Google, Inc. All rights reserved.
|
|
//
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file in the root of the source
|
|
// tree.
|
|
|
|
package layers
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"github.com/google/gopacket"
|
|
)
|
|
|
|
type RUDP struct {
|
|
BaseLayer
|
|
SYN, ACK, EACK, RST, NUL bool
|
|
Version uint8
|
|
HeaderLength uint8
|
|
SrcPort, DstPort RUDPPort
|
|
DataLength uint16
|
|
Seq, Ack, Checksum uint32
|
|
VariableHeaderArea []byte
|
|
// RUDPHeaderSyn contains SYN information for the RUDP packet,
|
|
// if the SYN flag is set
|
|
*RUDPHeaderSYN
|
|
// RUDPHeaderEack contains EACK information for the RUDP packet,
|
|
// if the EACK flag is set.
|
|
*RUDPHeaderEACK
|
|
}
|
|
|
|
type RUDPHeaderSYN struct {
|
|
MaxOutstandingSegments, MaxSegmentSize, OptionFlags uint16
|
|
}
|
|
|
|
type RUDPHeaderEACK struct {
|
|
SeqsReceivedOK []uint32
|
|
}
|
|
|
|
// LayerType returns gopacket.LayerTypeRUDP.
|
|
func (r *RUDP) LayerType() gopacket.LayerType { return LayerTypeRUDP }
|
|
|
|
func decodeRUDP(data []byte, p gopacket.PacketBuilder) error {
|
|
r := &RUDP{
|
|
SYN: data[0]&0x80 != 0,
|
|
ACK: data[0]&0x40 != 0,
|
|
EACK: data[0]&0x20 != 0,
|
|
RST: data[0]&0x10 != 0,
|
|
NUL: data[0]&0x08 != 0,
|
|
Version: data[0] & 0x3,
|
|
HeaderLength: data[1],
|
|
SrcPort: RUDPPort(data[2]),
|
|
DstPort: RUDPPort(data[3]),
|
|
DataLength: binary.BigEndian.Uint16(data[4:6]),
|
|
Seq: binary.BigEndian.Uint32(data[6:10]),
|
|
Ack: binary.BigEndian.Uint32(data[10:14]),
|
|
Checksum: binary.BigEndian.Uint32(data[14:18]),
|
|
}
|
|
if r.HeaderLength < 9 {
|
|
return fmt.Errorf("RUDP packet with too-short header length %d", r.HeaderLength)
|
|
}
|
|
hlen := int(r.HeaderLength) * 2
|
|
r.Contents = data[:hlen]
|
|
r.Payload = data[hlen : hlen+int(r.DataLength)]
|
|
r.VariableHeaderArea = data[18:hlen]
|
|
headerData := r.VariableHeaderArea
|
|
switch {
|
|
case r.SYN:
|
|
if len(headerData) != 6 {
|
|
return fmt.Errorf("RUDP packet invalid SYN header length: %d", len(headerData))
|
|
}
|
|
r.RUDPHeaderSYN = &RUDPHeaderSYN{
|
|
MaxOutstandingSegments: binary.BigEndian.Uint16(headerData[:2]),
|
|
MaxSegmentSize: binary.BigEndian.Uint16(headerData[2:4]),
|
|
OptionFlags: binary.BigEndian.Uint16(headerData[4:6]),
|
|
}
|
|
case r.EACK:
|
|
if len(headerData)%4 != 0 {
|
|
return fmt.Errorf("RUDP packet invalid EACK header length: %d", len(headerData))
|
|
}
|
|
r.RUDPHeaderEACK = &RUDPHeaderEACK{make([]uint32, len(headerData)/4)}
|
|
for i := 0; i < len(headerData); i += 4 {
|
|
r.SeqsReceivedOK[i/4] = binary.BigEndian.Uint32(headerData[i : i+4])
|
|
}
|
|
}
|
|
p.AddLayer(r)
|
|
p.SetTransportLayer(r)
|
|
return p.NextDecoder(gopacket.LayerTypePayload)
|
|
}
|
|
|
|
func (r *RUDP) TransportFlow() gopacket.Flow {
|
|
return gopacket.NewFlow(EndpointRUDPPort, []byte{byte(r.SrcPort)}, []byte{byte(r.DstPort)})
|
|
}
|