tcp.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. Copyright 2019 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // Partially copied from https://github.com/bowei/lighthouse/blob/master/pkg/probe/tcp.go
  14. package main
  15. import (
  16. "bytes"
  17. "encoding/binary"
  18. "log"
  19. "net"
  20. )
  21. const (
  22. tcpHeaderSize = 20
  23. tcpProtoNum = 6
  24. )
  25. const (
  26. // FIN is a TCP flag
  27. FIN uint16 = 1 << iota
  28. // SYN is a TCP flag
  29. SYN
  30. // RST is a TCP flag
  31. RST
  32. // PSH is a TCP flag
  33. PSH
  34. // ACK is a TCP flag
  35. ACK
  36. // URG is a TCP flag
  37. URG
  38. // ECE is a TCP flag
  39. ECE
  40. // CWR is a TCP flag
  41. CWR
  42. // NS is a TCP flag
  43. NS
  44. )
  45. type tcpPacket struct {
  46. SrcPort uint16 // 0
  47. DestPort uint16 // 2
  48. Seq uint32 // 4
  49. Ack uint32 // 8
  50. Flags uint16 // 13
  51. WindowSize uint16 // 14
  52. Checksum uint16 // 16
  53. UrgentPtr uint16 // 18
  54. // 20
  55. }
  56. func (t *tcpPacket) decode(pkt []byte) ([]byte, error) {
  57. err := binary.Read(bytes.NewReader(pkt), binary.BigEndian, t)
  58. if err != nil {
  59. return nil, err
  60. }
  61. return pkt[t.DataOffset():], nil
  62. }
  63. func (t *tcpPacket) DataOffset() int {
  64. return int((t.Flags >> 12) * 4)
  65. }
  66. func (t *tcpPacket) FlagString() string {
  67. out := ""
  68. if t.Flags&FIN != 0 {
  69. out += "FIN "
  70. }
  71. if t.Flags&SYN != 0 {
  72. out += "SYN "
  73. }
  74. if t.Flags&RST != 0 {
  75. out += "RST "
  76. }
  77. if t.Flags&PSH != 0 {
  78. out += "PSH "
  79. }
  80. if t.Flags&ACK != 0 {
  81. out += "ACK "
  82. }
  83. if t.Flags&URG != 0 {
  84. out += "URG "
  85. }
  86. if t.Flags&ECE != 0 {
  87. out += "ECE "
  88. }
  89. if t.Flags&CWR != 0 {
  90. out += "CWR "
  91. }
  92. if t.Flags&NS != 0 {
  93. out += "NS "
  94. }
  95. return out
  96. }
  97. func (t *tcpPacket) encode(src, dest net.IP, data []byte) []byte {
  98. pkt := make([]byte, 20, 20+len(data))
  99. encoder := binary.BigEndian
  100. encoder.PutUint16(pkt, t.SrcPort)
  101. encoder.PutUint16(pkt[2:], t.DestPort)
  102. encoder.PutUint32(pkt[4:], t.Seq)
  103. encoder.PutUint32(pkt[8:], t.Ack)
  104. encoder.PutUint16(pkt[12:], t.Flags)
  105. encoder.PutUint16(pkt[14:], t.WindowSize)
  106. encoder.PutUint16(pkt[18:], t.UrgentPtr)
  107. checksum := checksumTCP(src, dest, pkt[:tcpHeaderSize], data)
  108. pkt[16] = uint8(checksum & 0xff)
  109. pkt[17] = uint8(checksum >> 8)
  110. pkt = append(pkt, data...)
  111. return pkt
  112. }
  113. func checksumTCP(src, dest net.IP, tcpHeader, data []byte) uint16 {
  114. log.Printf("calling checksumTCP: %v %v %v %v", src, dest, tcpHeader, data)
  115. chk := &tcpChecksumer{}
  116. // Encode pseudoheader.
  117. chk.add(src.To4())
  118. chk.add(dest.To4())
  119. var pseudoHeader [4]byte
  120. pseudoHeader[1] = tcpProtoNum
  121. binary.BigEndian.PutUint16(pseudoHeader[2:], uint16(len(data)+len(tcpHeader)))
  122. chk.add(pseudoHeader[:])
  123. chk.add(tcpHeader)
  124. chk.add(data)
  125. log.Printf("checksumer: %+v", chk)
  126. return chk.finalize()
  127. }
  128. type tcpChecksumer struct {
  129. sum uint32
  130. oddByte byte
  131. length int
  132. }
  133. func (c *tcpChecksumer) finalize() uint16 {
  134. ret := c.sum
  135. if c.length%2 > 0 {
  136. ret += uint32(c.oddByte)
  137. }
  138. log.Println("ret: ", ret)
  139. for ret>>16 > 0 {
  140. ret = ret&0xffff + ret>>16
  141. log.Println("ret: ", ret)
  142. }
  143. log.Println("ret: ", ret)
  144. return ^uint16(ret)
  145. }
  146. func (c *tcpChecksumer) add(data []byte) {
  147. if len(data) == 0 {
  148. return
  149. }
  150. haveOddByte := c.length%2 > 0
  151. c.length += len(data)
  152. if haveOddByte {
  153. data = append([]byte{c.oddByte}, data...)
  154. }
  155. for i := 0; i < len(data)-1; i += 2 {
  156. c.sum += uint32(data[i]) + uint32(data[i+1])<<8
  157. }
  158. if c.length%2 > 0 {
  159. c.oddByte = data[len(data)-1]
  160. }
  161. }