123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- // 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)})
- }
|