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 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} 94