udp.go 3.4 KB

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