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