udp.go 3.3 KB

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