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