chunk.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. package vnet
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "strings"
  7. "sync/atomic"
  8. "time"
  9. )
  10. type tcpFlag uint8
  11. const (
  12. tcpFIN tcpFlag = 0x01
  13. tcpSYN tcpFlag = 0x02
  14. tcpRST tcpFlag = 0x04
  15. tcpPSH tcpFlag = 0x08
  16. tcpACK tcpFlag = 0x10
  17. )
  18. func (f tcpFlag) String() string {
  19. var sa []string
  20. if f&tcpFIN != 0 {
  21. sa = append(sa, "FIN")
  22. }
  23. if f&tcpSYN != 0 {
  24. sa = append(sa, "SYN")
  25. }
  26. if f&tcpRST != 0 {
  27. sa = append(sa, "RST")
  28. }
  29. if f&tcpPSH != 0 {
  30. sa = append(sa, "PSH")
  31. }
  32. if f&tcpACK != 0 {
  33. sa = append(sa, "ACK")
  34. }
  35. return strings.Join(sa, "-")
  36. }
  37. // Generate a base36-encoded unique tag
  38. // See: https://play.golang.org/p/0ZaAID1q-HN
  39. var assignChunkTag = func() func() string { //nolint:gochecknoglobals
  40. var tagCtr uint64
  41. return func() string {
  42. n := atomic.AddUint64(&tagCtr, 1)
  43. return strconv.FormatUint(n, 36)
  44. }
  45. }()
  46. // Chunk represents a packet passed around in the vnet
  47. type Chunk interface {
  48. setTimestamp() time.Time // used by router
  49. getTimestamp() time.Time // used by router
  50. getSourceIP() net.IP // used by router
  51. getDestinationIP() net.IP // used by router
  52. setSourceAddr(address string) error // used by nat
  53. setDestinationAddr(address string) error // used by nat
  54. SourceAddr() net.Addr
  55. DestinationAddr() net.Addr
  56. UserData() []byte
  57. Tag() string
  58. Clone() Chunk
  59. Network() string // returns "udp" or "tcp"
  60. String() string
  61. }
  62. type chunkIP struct {
  63. timestamp time.Time
  64. sourceIP net.IP
  65. destinationIP net.IP
  66. tag string
  67. }
  68. func (c *chunkIP) setTimestamp() time.Time {
  69. c.timestamp = time.Now()
  70. return c.timestamp
  71. }
  72. func (c *chunkIP) getTimestamp() time.Time {
  73. return c.timestamp
  74. }
  75. func (c *chunkIP) getDestinationIP() net.IP {
  76. return c.destinationIP
  77. }
  78. func (c *chunkIP) getSourceIP() net.IP {
  79. return c.sourceIP
  80. }
  81. func (c *chunkIP) Tag() string {
  82. return c.tag
  83. }
  84. type chunkUDP struct {
  85. chunkIP
  86. sourcePort int
  87. destinationPort int
  88. userData []byte
  89. }
  90. func newChunkUDP(srcAddr, dstAddr *net.UDPAddr) *chunkUDP {
  91. return &chunkUDP{
  92. chunkIP: chunkIP{
  93. sourceIP: srcAddr.IP,
  94. destinationIP: dstAddr.IP,
  95. tag: assignChunkTag(),
  96. },
  97. sourcePort: srcAddr.Port,
  98. destinationPort: dstAddr.Port,
  99. }
  100. }
  101. func (c *chunkUDP) SourceAddr() net.Addr {
  102. return &net.UDPAddr{
  103. IP: c.sourceIP,
  104. Port: c.sourcePort,
  105. }
  106. }
  107. func (c *chunkUDP) DestinationAddr() net.Addr {
  108. return &net.UDPAddr{
  109. IP: c.destinationIP,
  110. Port: c.destinationPort,
  111. }
  112. }
  113. func (c *chunkUDP) UserData() []byte {
  114. return c.userData
  115. }
  116. func (c *chunkUDP) Clone() Chunk {
  117. var userData []byte
  118. if c.userData != nil {
  119. userData = make([]byte, len(c.userData))
  120. copy(userData, c.userData)
  121. }
  122. return &chunkUDP{
  123. chunkIP: chunkIP{
  124. timestamp: c.timestamp,
  125. sourceIP: c.sourceIP,
  126. destinationIP: c.destinationIP,
  127. tag: c.tag,
  128. },
  129. sourcePort: c.sourcePort,
  130. destinationPort: c.destinationPort,
  131. userData: userData,
  132. }
  133. }
  134. func (c *chunkUDP) Network() string {
  135. return udpString
  136. }
  137. func (c *chunkUDP) String() string {
  138. src := c.SourceAddr()
  139. dst := c.DestinationAddr()
  140. return fmt.Sprintf("%s chunk %s %s => %s",
  141. src.Network(),
  142. c.tag,
  143. src.String(),
  144. dst.String(),
  145. )
  146. }
  147. func (c *chunkUDP) setSourceAddr(address string) error {
  148. addr, err := net.ResolveUDPAddr(udpString, address)
  149. if err != nil {
  150. return err
  151. }
  152. c.sourceIP = addr.IP
  153. c.sourcePort = addr.Port
  154. return nil
  155. }
  156. func (c *chunkUDP) setDestinationAddr(address string) error {
  157. addr, err := net.ResolveUDPAddr(udpString, address)
  158. if err != nil {
  159. return err
  160. }
  161. c.destinationIP = addr.IP
  162. c.destinationPort = addr.Port
  163. return nil
  164. }
  165. type chunkTCP struct {
  166. chunkIP
  167. sourcePort int
  168. destinationPort int
  169. flags tcpFlag // control bits
  170. userData []byte // only with PSH flag
  171. // seq uint32 // always starts with 0
  172. // ack uint32 // always starts with 0
  173. }
  174. func newChunkTCP(srcAddr, dstAddr *net.TCPAddr, flags tcpFlag) *chunkTCP {
  175. return &chunkTCP{
  176. chunkIP: chunkIP{
  177. sourceIP: srcAddr.IP,
  178. destinationIP: dstAddr.IP,
  179. tag: assignChunkTag(),
  180. },
  181. sourcePort: srcAddr.Port,
  182. destinationPort: dstAddr.Port,
  183. flags: flags,
  184. }
  185. }
  186. func (c *chunkTCP) SourceAddr() net.Addr {
  187. return &net.TCPAddr{
  188. IP: c.sourceIP,
  189. Port: c.sourcePort,
  190. }
  191. }
  192. func (c *chunkTCP) DestinationAddr() net.Addr {
  193. return &net.TCPAddr{
  194. IP: c.destinationIP,
  195. Port: c.destinationPort,
  196. }
  197. }
  198. func (c *chunkTCP) UserData() []byte {
  199. return c.userData
  200. }
  201. func (c *chunkTCP) Clone() Chunk {
  202. userData := make([]byte, len(c.userData))
  203. copy(userData, c.userData)
  204. return &chunkTCP{
  205. chunkIP: chunkIP{
  206. timestamp: c.timestamp,
  207. sourceIP: c.sourceIP,
  208. destinationIP: c.destinationIP,
  209. },
  210. sourcePort: c.sourcePort,
  211. destinationPort: c.destinationPort,
  212. userData: userData,
  213. }
  214. }
  215. func (c *chunkTCP) Network() string {
  216. return "tcp"
  217. }
  218. func (c *chunkTCP) String() string {
  219. src := c.SourceAddr()
  220. dst := c.DestinationAddr()
  221. return fmt.Sprintf("%s %s chunk %s %s => %s",
  222. src.Network(),
  223. c.flags.String(),
  224. c.tag,
  225. src.String(),
  226. dst.String(),
  227. )
  228. }
  229. func (c *chunkTCP) setSourceAddr(address string) error {
  230. addr, err := net.ResolveTCPAddr("tcp", address)
  231. if err != nil {
  232. return err
  233. }
  234. c.sourceIP = addr.IP
  235. c.sourcePort = addr.Port
  236. return nil
  237. }
  238. func (c *chunkTCP) setDestinationAddr(address string) error {
  239. addr, err := net.ResolveTCPAddr("tcp", address)
  240. if err != nil {
  241. return err
  242. }
  243. c.destinationIP = addr.IP
  244. c.destinationPort = addr.Port
  245. return nil
  246. }