1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
// 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/gopacket/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)})
}
|