tcp.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. "encoding/hex"
  11. "errors"
  12. "fmt"
  13. "github.com/google/gopacket"
  14. )
  15. // TCP is the layer for TCP headers.
  16. type TCP struct {
  17. BaseLayer
  18. SrcPort, DstPort TCPPort
  19. Seq uint32
  20. Ack uint32
  21. DataOffset uint8
  22. FIN, SYN, RST, PSH, ACK, URG, ECE, CWR, NS bool
  23. Window uint16
  24. Checksum uint16
  25. Urgent uint16
  26. sPort, dPort []byte
  27. Options []TCPOption
  28. Padding []byte
  29. opts [4]TCPOption
  30. tcpipchecksum
  31. }
  32. // TCPOptionKind represents a TCP option code.
  33. type TCPOptionKind uint8
  34. const (
  35. TCPOptionKindEndList = 0
  36. TCPOptionKindNop = 1
  37. TCPOptionKindMSS = 2 // len = 4
  38. TCPOptionKindWindowScale = 3 // len = 3
  39. TCPOptionKindSACKPermitted = 4 // len = 2
  40. TCPOptionKindSACK = 5 // len = n
  41. TCPOptionKindEcho = 6 // len = 6, obsolete
  42. TCPOptionKindEchoReply = 7 // len = 6, obsolete
  43. TCPOptionKindTimestamps = 8 // len = 10
  44. TCPOptionKindPartialOrderConnectionPermitted = 9 // len = 2, obsolete
  45. TCPOptionKindPartialOrderServiceProfile = 10 // len = 3, obsolete
  46. TCPOptionKindCC = 11 // obsolete
  47. TCPOptionKindCCNew = 12 // obsolete
  48. TCPOptionKindCCEcho = 13 // obsolete
  49. TCPOptionKindAltChecksum = 14 // len = 3, obsolete
  50. TCPOptionKindAltChecksumData = 15 // len = n, obsolete
  51. )
  52. func (k TCPOptionKind) String() string {
  53. switch k {
  54. case TCPOptionKindEndList:
  55. return "EndList"
  56. case TCPOptionKindNop:
  57. return "NOP"
  58. case TCPOptionKindMSS:
  59. return "MSS"
  60. case TCPOptionKindWindowScale:
  61. return "WindowScale"
  62. case TCPOptionKindSACKPermitted:
  63. return "SACKPermitted"
  64. case TCPOptionKindSACK:
  65. return "SACK"
  66. case TCPOptionKindEcho:
  67. return "Echo"
  68. case TCPOptionKindEchoReply:
  69. return "EchoReply"
  70. case TCPOptionKindTimestamps:
  71. return "Timestamps"
  72. case TCPOptionKindPartialOrderConnectionPermitted:
  73. return "PartialOrderConnectionPermitted"
  74. case TCPOptionKindPartialOrderServiceProfile:
  75. return "PartialOrderServiceProfile"
  76. case TCPOptionKindCC:
  77. return "CC"
  78. case TCPOptionKindCCNew:
  79. return "CCNew"
  80. case TCPOptionKindCCEcho:
  81. return "CCEcho"
  82. case TCPOptionKindAltChecksum:
  83. return "AltChecksum"
  84. case TCPOptionKindAltChecksumData:
  85. return "AltChecksumData"
  86. default:
  87. return fmt.Sprintf("Unknown(%d)", k)
  88. }
  89. }
  90. type TCPOption struct {
  91. OptionType TCPOptionKind
  92. OptionLength uint8
  93. OptionData []byte
  94. }
  95. func (t TCPOption) String() string {
  96. hd := hex.EncodeToString(t.OptionData)
  97. if len(hd) > 0 {
  98. hd = " 0x" + hd
  99. }
  100. switch t.OptionType {
  101. case TCPOptionKindMSS:
  102. return fmt.Sprintf("TCPOption(%s:%v%s)",
  103. t.OptionType,
  104. binary.BigEndian.Uint16(t.OptionData),
  105. hd)
  106. case TCPOptionKindTimestamps:
  107. if len(t.OptionData) == 8 {
  108. return fmt.Sprintf("TCPOption(%s:%v/%v%s)",
  109. t.OptionType,
  110. binary.BigEndian.Uint32(t.OptionData[:4]),
  111. binary.BigEndian.Uint32(t.OptionData[4:8]),
  112. hd)
  113. }
  114. }
  115. return fmt.Sprintf("TCPOption(%s:%s)", t.OptionType, hd)
  116. }
  117. // LayerType returns gopacket.LayerTypeTCP
  118. func (t *TCP) LayerType() gopacket.LayerType { return LayerTypeTCP }
  119. // SerializeTo writes the serialized form of this layer into the
  120. // SerializationBuffer, implementing gopacket.SerializableLayer.
  121. // See the docs for gopacket.SerializableLayer for more info.
  122. func (t *TCP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
  123. var optionLength int
  124. for _, o := range t.Options {
  125. switch o.OptionType {
  126. case 0, 1:
  127. optionLength += 1
  128. default:
  129. optionLength += 2 + len(o.OptionData)
  130. }
  131. }
  132. if opts.FixLengths {
  133. if rem := optionLength % 4; rem != 0 {
  134. t.Padding = lotsOfZeros[:4-rem]
  135. }
  136. t.DataOffset = uint8((len(t.Padding) + optionLength + 20) / 4)
  137. }
  138. bytes, err := b.PrependBytes(20 + optionLength + len(t.Padding))
  139. if err != nil {
  140. return err
  141. }
  142. binary.BigEndian.PutUint16(bytes, uint16(t.SrcPort))
  143. binary.BigEndian.PutUint16(bytes[2:], uint16(t.DstPort))
  144. binary.BigEndian.PutUint32(bytes[4:], t.Seq)
  145. binary.BigEndian.PutUint32(bytes[8:], t.Ack)
  146. binary.BigEndian.PutUint16(bytes[12:], t.flagsAndOffset())
  147. binary.BigEndian.PutUint16(bytes[14:], t.Window)
  148. binary.BigEndian.PutUint16(bytes[18:], t.Urgent)
  149. start := 20
  150. for _, o := range t.Options {
  151. bytes[start] = byte(o.OptionType)
  152. switch o.OptionType {
  153. case 0, 1:
  154. start++
  155. default:
  156. if opts.FixLengths {
  157. o.OptionLength = uint8(len(o.OptionData) + 2)
  158. }
  159. bytes[start+1] = o.OptionLength
  160. copy(bytes[start+2:start+len(o.OptionData)+2], o.OptionData)
  161. start += len(o.OptionData) + 2
  162. }
  163. }
  164. copy(bytes[start:], t.Padding)
  165. if opts.ComputeChecksums {
  166. // zero out checksum bytes in current serialization.
  167. bytes[16] = 0
  168. bytes[17] = 0
  169. csum, err := t.computeChecksum(b.Bytes(), IPProtocolTCP)
  170. if err != nil {
  171. return err
  172. }
  173. t.Checksum = csum
  174. }
  175. binary.BigEndian.PutUint16(bytes[16:], t.Checksum)
  176. return nil
  177. }
  178. func (t *TCP) ComputeChecksum() (uint16, error) {
  179. return t.computeChecksum(append(t.Contents, t.Payload...), IPProtocolTCP)
  180. }
  181. func (t *TCP) flagsAndOffset() uint16 {
  182. f := uint16(t.DataOffset) << 12
  183. if t.FIN {
  184. f |= 0x0001
  185. }
  186. if t.SYN {
  187. f |= 0x0002
  188. }
  189. if t.RST {
  190. f |= 0x0004
  191. }
  192. if t.PSH {
  193. f |= 0x0008
  194. }
  195. if t.ACK {
  196. f |= 0x0010
  197. }
  198. if t.URG {
  199. f |= 0x0020
  200. }
  201. if t.ECE {
  202. f |= 0x0040
  203. }
  204. if t.CWR {
  205. f |= 0x0080
  206. }
  207. if t.NS {
  208. f |= 0x0100
  209. }
  210. return f
  211. }
  212. func (tcp *TCP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
  213. if len(data) < 20 {
  214. df.SetTruncated()
  215. return fmt.Errorf("Invalid TCP header. Length %d less than 20", len(data))
  216. }
  217. tcp.SrcPort = TCPPort(binary.BigEndian.Uint16(data[0:2]))
  218. tcp.sPort = data[0:2]
  219. tcp.DstPort = TCPPort(binary.BigEndian.Uint16(data[2:4]))
  220. tcp.dPort = data[2:4]
  221. tcp.Seq = binary.BigEndian.Uint32(data[4:8])
  222. tcp.Ack = binary.BigEndian.Uint32(data[8:12])
  223. tcp.DataOffset = data[12] >> 4
  224. tcp.FIN = data[13]&0x01 != 0
  225. tcp.SYN = data[13]&0x02 != 0
  226. tcp.RST = data[13]&0x04 != 0
  227. tcp.PSH = data[13]&0x08 != 0
  228. tcp.ACK = data[13]&0x10 != 0
  229. tcp.URG = data[13]&0x20 != 0
  230. tcp.ECE = data[13]&0x40 != 0
  231. tcp.CWR = data[13]&0x80 != 0
  232. tcp.NS = data[12]&0x01 != 0
  233. tcp.Window = binary.BigEndian.Uint16(data[14:16])
  234. tcp.Checksum = binary.BigEndian.Uint16(data[16:18])
  235. tcp.Urgent = binary.BigEndian.Uint16(data[18:20])
  236. if tcp.Options == nil {
  237. // Pre-allocate to avoid allocating a slice.
  238. tcp.Options = tcp.opts[:0]
  239. } else {
  240. tcp.Options = tcp.Options[:0]
  241. }
  242. if tcp.DataOffset < 5 {
  243. return fmt.Errorf("Invalid TCP data offset %d < 5", tcp.DataOffset)
  244. }
  245. dataStart := int(tcp.DataOffset) * 4
  246. if dataStart > len(data) {
  247. df.SetTruncated()
  248. tcp.Payload = nil
  249. tcp.Contents = data
  250. return errors.New("TCP data offset greater than packet length")
  251. }
  252. tcp.Contents = data[:dataStart]
  253. tcp.Payload = data[dataStart:]
  254. // From here on, data points just to the header options.
  255. data = data[20:dataStart]
  256. for len(data) > 0 {
  257. tcp.Options = append(tcp.Options, TCPOption{OptionType: TCPOptionKind(data[0])})
  258. opt := &tcp.Options[len(tcp.Options)-1]
  259. switch opt.OptionType {
  260. case TCPOptionKindEndList: // End of options
  261. opt.OptionLength = 1
  262. tcp.Padding = data[1:]
  263. break
  264. case TCPOptionKindNop: // 1 byte padding
  265. opt.OptionLength = 1
  266. default:
  267. if len(data) < 2 {
  268. df.SetTruncated()
  269. return fmt.Errorf("Invalid TCP option length. Length %d less than 2", len(data))
  270. }
  271. opt.OptionLength = data[1]
  272. if opt.OptionLength < 2 {
  273. return fmt.Errorf("Invalid TCP option length %d < 2", opt.OptionLength)
  274. } else if int(opt.OptionLength) > len(data) {
  275. df.SetTruncated()
  276. return fmt.Errorf("Invalid TCP option length %d exceeds remaining %d bytes", opt.OptionLength, len(data))
  277. }
  278. opt.OptionData = data[2:opt.OptionLength]
  279. }
  280. data = data[opt.OptionLength:]
  281. }
  282. return nil
  283. }
  284. func (t *TCP) CanDecode() gopacket.LayerClass {
  285. return LayerTypeTCP
  286. }
  287. func (t *TCP) NextLayerType() gopacket.LayerType {
  288. lt := t.DstPort.LayerType()
  289. if lt == gopacket.LayerTypePayload {
  290. lt = t.SrcPort.LayerType()
  291. }
  292. return lt
  293. }
  294. func decodeTCP(data []byte, p gopacket.PacketBuilder) error {
  295. tcp := &TCP{}
  296. err := tcp.DecodeFromBytes(data, p)
  297. p.AddLayer(tcp)
  298. p.SetTransportLayer(tcp)
  299. if err != nil {
  300. return err
  301. }
  302. if p.DecodeOptions().DecodeStreamsAsDatagrams {
  303. return p.NextDecoder(tcp.NextLayerType())
  304. } else {
  305. return p.NextDecoder(gopacket.LayerTypePayload)
  306. }
  307. }
  308. func (t *TCP) TransportFlow() gopacket.Flow {
  309. return gopacket.NewFlow(EndpointTCPPort, t.sPort, t.dPort)
  310. }
  311. // For testing only
  312. func (t *TCP) SetInternalPortsForTesting() {
  313. t.sPort = make([]byte, 2)
  314. t.dPort = make([]byte, 2)
  315. binary.BigEndian.PutUint16(t.sPort, uint16(t.SrcPort))
  316. binary.BigEndian.PutUint16(t.dPort, uint16(t.DstPort))
  317. }