ODPM 266: Go-libmemif + 2 examples.
[govpp.git] / vendor / github.com / google / gopacket / layers / udp.go
1 // Copyright 2012 Google, Inc. All rights reserved.
2 // Copyright 2009-2011 Andreas Krennmair. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style license
5 // that can be found in the LICENSE file in the root of the source
6 // tree.
7
8 package layers
9
10 import (
11         "encoding/binary"
12         "fmt"
13         "github.com/google/gopacket"
14 )
15
16 // UDP is the layer for UDP headers.
17 type UDP struct {
18         BaseLayer
19         SrcPort, DstPort UDPPort
20         Length           uint16
21         Checksum         uint16
22         sPort, dPort     []byte
23         tcpipchecksum
24 }
25
26 // LayerType returns gopacket.LayerTypeUDP
27 func (u *UDP) LayerType() gopacket.LayerType { return LayerTypeUDP }
28
29 func (udp *UDP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
30         udp.SrcPort = UDPPort(binary.BigEndian.Uint16(data[0:2]))
31         udp.sPort = data[0:2]
32         udp.DstPort = UDPPort(binary.BigEndian.Uint16(data[2:4]))
33         udp.dPort = data[2:4]
34         udp.Length = binary.BigEndian.Uint16(data[4:6])
35         udp.Checksum = binary.BigEndian.Uint16(data[6:8])
36         udp.BaseLayer = BaseLayer{Contents: data[:8]}
37         switch {
38         case udp.Length >= 8:
39                 hlen := int(udp.Length)
40                 if hlen > len(data) {
41                         df.SetTruncated()
42                         hlen = len(data)
43                 }
44                 udp.Payload = data[8:hlen]
45         case udp.Length == 0: // Jumbogram, use entire rest of data
46                 udp.Payload = data[8:]
47         default:
48                 return fmt.Errorf("UDP packet too small: %d bytes", udp.Length)
49         }
50         return nil
51 }
52
53 // SerializeTo writes the serialized form of this layer into the
54 // SerializationBuffer, implementing gopacket.SerializableLayer.
55 // See the docs for gopacket.SerializableLayer for more info.
56 func (u *UDP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
57         var jumbo bool
58
59         payload := b.Bytes()
60         if _, ok := u.pseudoheader.(*IPv6); ok {
61                 if len(payload)+8 > 65535 {
62                         jumbo = true
63                 }
64         }
65         bytes, err := b.PrependBytes(8)
66         if err != nil {
67                 return err
68         }
69         binary.BigEndian.PutUint16(bytes, uint16(u.SrcPort))
70         binary.BigEndian.PutUint16(bytes[2:], uint16(u.DstPort))
71         if opts.FixLengths {
72                 if jumbo {
73                         u.Length = 0
74                 } else {
75                         u.Length = uint16(len(payload)) + 8
76                 }
77         }
78         binary.BigEndian.PutUint16(bytes[4:], u.Length)
79         if opts.ComputeChecksums {
80                 // zero out checksum bytes
81                 bytes[6] = 0
82                 bytes[7] = 0
83                 csum, err := u.computeChecksum(b.Bytes(), IPProtocolUDP)
84                 if err != nil {
85                         return err
86                 }
87                 u.Checksum = csum
88         }
89         binary.BigEndian.PutUint16(bytes[6:], u.Checksum)
90         return nil
91 }
92
93 func (u *UDP) CanDecode() gopacket.LayerClass {
94         return LayerTypeUDP
95 }
96
97 // NextLayerType use the destination port to select the
98 // right next decoder. It tries first to decode via the
99 // destination port, then the source port.
100 func (u *UDP) NextLayerType() gopacket.LayerType {
101         if lt := u.DstPort.LayerType(); lt != gopacket.LayerTypePayload {
102                 return lt
103         }
104         return u.SrcPort.LayerType()
105 }
106
107 func decodeUDP(data []byte, p gopacket.PacketBuilder) error {
108         udp := &UDP{}
109         err := udp.DecodeFromBytes(data, p)
110         p.AddLayer(udp)
111         p.SetTransportLayer(udp)
112         if err != nil {
113                 return err
114         }
115         return p.NextDecoder(udp.NextLayerType())
116 }
117
118 func (u *UDP) TransportFlow() gopacket.Flow {
119         return gopacket.NewFlow(EndpointUDPPort, u.sPort, u.dPort)
120 }