ip4.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. "errors"
  11. "fmt"
  12. "net"
  13. "strings"
  14. "github.com/google/gopacket"
  15. )
  16. type IPv4Flag uint8
  17. const (
  18. IPv4EvilBit IPv4Flag = 1 << 2 // http://tools.ietf.org/html/rfc3514 ;)
  19. IPv4DontFragment IPv4Flag = 1 << 1
  20. IPv4MoreFragments IPv4Flag = 1 << 0
  21. )
  22. func (f IPv4Flag) String() string {
  23. var s []string
  24. if f&IPv4EvilBit != 0 {
  25. s = append(s, "Evil")
  26. }
  27. if f&IPv4DontFragment != 0 {
  28. s = append(s, "DF")
  29. }
  30. if f&IPv4MoreFragments != 0 {
  31. s = append(s, "MF")
  32. }
  33. return strings.Join(s, "|")
  34. }
  35. // IPv4 is the header of an IP packet.
  36. type IPv4 struct {
  37. BaseLayer
  38. Version uint8
  39. IHL uint8
  40. TOS uint8
  41. Length uint16
  42. Id uint16
  43. Flags IPv4Flag
  44. FragOffset uint16
  45. TTL uint8
  46. Protocol IPProtocol
  47. Checksum uint16
  48. SrcIP net.IP
  49. DstIP net.IP
  50. Options []IPv4Option
  51. Padding []byte
  52. }
  53. // LayerType returns LayerTypeIPv4
  54. func (i *IPv4) LayerType() gopacket.LayerType { return LayerTypeIPv4 }
  55. func (i *IPv4) NetworkFlow() gopacket.Flow {
  56. return gopacket.NewFlow(EndpointIPv4, i.SrcIP, i.DstIP)
  57. }
  58. type IPv4Option struct {
  59. OptionType uint8
  60. OptionLength uint8
  61. OptionData []byte
  62. }
  63. func (i IPv4Option) String() string {
  64. return fmt.Sprintf("IPv4Option(%v:%v)", i.OptionType, i.OptionData)
  65. }
  66. // for the current ipv4 options, return the number of bytes (including
  67. // padding that the options used)
  68. func (ip *IPv4) getIPv4OptionSize() uint8 {
  69. optionSize := uint8(0)
  70. for _, opt := range ip.Options {
  71. switch opt.OptionType {
  72. case 0:
  73. // this is the end of option lists
  74. optionSize++
  75. case 1:
  76. // this is the padding
  77. optionSize++
  78. default:
  79. optionSize += opt.OptionLength
  80. }
  81. }
  82. // make sure the options are aligned to 32 bit boundary
  83. if (optionSize % 4) != 0 {
  84. optionSize += 4 - (optionSize % 4)
  85. }
  86. return optionSize
  87. }
  88. // SerializeTo writes the serialized form of this layer into the
  89. // SerializationBuffer, implementing gopacket.SerializableLayer.
  90. func (ip *IPv4) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
  91. optionLength := ip.getIPv4OptionSize()
  92. bytes, err := b.PrependBytes(20 + int(optionLength))
  93. if err != nil {
  94. return err
  95. }
  96. if opts.FixLengths {
  97. ip.IHL = 5 + (optionLength / 4)
  98. ip.Length = uint16(len(b.Bytes()))
  99. }
  100. bytes[0] = (ip.Version << 4) | ip.IHL
  101. bytes[1] = ip.TOS
  102. binary.BigEndian.PutUint16(bytes[2:], ip.Length)
  103. binary.BigEndian.PutUint16(bytes[4:], ip.Id)
  104. binary.BigEndian.PutUint16(bytes[6:], ip.flagsfrags())
  105. bytes[8] = ip.TTL
  106. bytes[9] = byte(ip.Protocol)
  107. if err := ip.AddressTo4(); err != nil {
  108. return err
  109. }
  110. copy(bytes[12:16], ip.SrcIP)
  111. copy(bytes[16:20], ip.DstIP)
  112. curLocation := 20
  113. // Now, we will encode the options
  114. for _, opt := range ip.Options {
  115. switch opt.OptionType {
  116. case 0:
  117. // this is the end of option lists
  118. bytes[curLocation] = 0
  119. curLocation++
  120. case 1:
  121. // this is the padding
  122. bytes[curLocation] = 1
  123. curLocation++
  124. default:
  125. bytes[curLocation] = opt.OptionType
  126. bytes[curLocation+1] = opt.OptionLength
  127. // sanity checking to protect us from buffer overrun
  128. if len(opt.OptionData) > int(opt.OptionLength-2) {
  129. return errors.New("option length is smaller than length of option data")
  130. }
  131. copy(bytes[curLocation+2:curLocation+int(opt.OptionLength)], opt.OptionData)
  132. curLocation += int(opt.OptionLength)
  133. }
  134. }
  135. if opts.ComputeChecksums {
  136. ip.Checksum = checksum(bytes)
  137. }
  138. binary.BigEndian.PutUint16(bytes[10:], ip.Checksum)
  139. return nil
  140. }
  141. func checksum(bytes []byte) uint16 {
  142. // Clear checksum bytes
  143. bytes[10] = 0
  144. bytes[11] = 0
  145. // Compute checksum
  146. var csum uint32
  147. for i := 0; i < len(bytes); i += 2 {
  148. csum += uint32(bytes[i]) << 8
  149. csum += uint32(bytes[i+1])
  150. }
  151. for {
  152. // Break when sum is less or equals to 0xFFFF
  153. if csum <= 65535 {
  154. break
  155. }
  156. // Add carry to the sum
  157. csum = (csum >> 16) + uint32(uint16(csum))
  158. }
  159. // Flip all the bits
  160. return ^uint16(csum)
  161. }
  162. func (ip *IPv4) flagsfrags() (ff uint16) {
  163. ff |= uint16(ip.Flags) << 13
  164. ff |= ip.FragOffset
  165. return
  166. }
  167. // DecodeFromBytes decodes the given bytes into this layer.
  168. func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
  169. if len(data) < 20 {
  170. df.SetTruncated()
  171. return fmt.Errorf("Invalid ip4 header. Length %d less than 20", len(data))
  172. }
  173. flagsfrags := binary.BigEndian.Uint16(data[6:8])
  174. ip.Version = uint8(data[0]) >> 4
  175. ip.IHL = uint8(data[0]) & 0x0F
  176. ip.TOS = data[1]
  177. ip.Length = binary.BigEndian.Uint16(data[2:4])
  178. ip.Id = binary.BigEndian.Uint16(data[4:6])
  179. ip.Flags = IPv4Flag(flagsfrags >> 13)
  180. ip.FragOffset = flagsfrags & 0x1FFF
  181. ip.TTL = data[8]
  182. ip.Protocol = IPProtocol(data[9])
  183. ip.Checksum = binary.BigEndian.Uint16(data[10:12])
  184. ip.SrcIP = data[12:16]
  185. ip.DstIP = data[16:20]
  186. ip.Options = ip.Options[:0]
  187. ip.Padding = nil
  188. // Set up an initial guess for contents/payload... we'll reset these soon.
  189. ip.BaseLayer = BaseLayer{Contents: data}
  190. // This code is added for the following enviroment:
  191. // * Windows 10 with TSO option activated. ( tested on Hyper-V, RealTek ethernet driver )
  192. if ip.Length == 0 {
  193. // If using TSO(TCP Segmentation Offload), length is zero.
  194. // The actual packet length is the length of data.
  195. ip.Length = uint16(len(data))
  196. }
  197. if ip.Length < 20 {
  198. return fmt.Errorf("Invalid (too small) IP length (%d < 20)", ip.Length)
  199. } else if ip.IHL < 5 {
  200. return fmt.Errorf("Invalid (too small) IP header length (%d < 5)", ip.IHL)
  201. } else if int(ip.IHL*4) > int(ip.Length) {
  202. return fmt.Errorf("Invalid IP header length > IP length (%d > %d)", ip.IHL, ip.Length)
  203. }
  204. if cmp := len(data) - int(ip.Length); cmp > 0 {
  205. data = data[:ip.Length]
  206. } else if cmp < 0 {
  207. df.SetTruncated()
  208. if int(ip.IHL)*4 > len(data) {
  209. return errors.New("Not all IP header bytes available")
  210. }
  211. }
  212. ip.Contents = data[:ip.IHL*4]
  213. ip.Payload = data[ip.IHL*4:]
  214. // From here on, data contains the header options.
  215. data = data[20 : ip.IHL*4]
  216. // Pull out IP options
  217. for len(data) > 0 {
  218. if ip.Options == nil {
  219. // Pre-allocate to avoid growing the slice too much.
  220. ip.Options = make([]IPv4Option, 0, 4)
  221. }
  222. opt := IPv4Option{OptionType: data[0]}
  223. switch opt.OptionType {
  224. case 0: // End of options
  225. opt.OptionLength = 1
  226. ip.Options = append(ip.Options, opt)
  227. ip.Padding = data[1:]
  228. return nil
  229. case 1: // 1 byte padding
  230. opt.OptionLength = 1
  231. data = data[1:]
  232. ip.Options = append(ip.Options, opt)
  233. default:
  234. if len(data) < 2 {
  235. df.SetTruncated()
  236. return fmt.Errorf("Invalid ip4 option length. Length %d less than 2", len(data))
  237. }
  238. opt.OptionLength = data[1]
  239. if len(data) < int(opt.OptionLength) {
  240. df.SetTruncated()
  241. return fmt.Errorf("IP option length exceeds remaining IP header size, option type %v length %v", opt.OptionType, opt.OptionLength)
  242. }
  243. if opt.OptionLength <= 2 {
  244. return fmt.Errorf("Invalid IP option type %v length %d. Must be greater than 2", opt.OptionType, opt.OptionLength)
  245. }
  246. opt.OptionData = data[2:opt.OptionLength]
  247. data = data[opt.OptionLength:]
  248. ip.Options = append(ip.Options, opt)
  249. }
  250. }
  251. return nil
  252. }
  253. func (i *IPv4) CanDecode() gopacket.LayerClass {
  254. return LayerTypeIPv4
  255. }
  256. func (i *IPv4) NextLayerType() gopacket.LayerType {
  257. if i.Flags&IPv4MoreFragments != 0 || i.FragOffset != 0 {
  258. return gopacket.LayerTypeFragment
  259. }
  260. return i.Protocol.LayerType()
  261. }
  262. func decodeIPv4(data []byte, p gopacket.PacketBuilder) error {
  263. ip := &IPv4{}
  264. err := ip.DecodeFromBytes(data, p)
  265. p.AddLayer(ip)
  266. p.SetNetworkLayer(ip)
  267. if err != nil {
  268. return err
  269. }
  270. return p.NextDecoder(ip.NextLayerType())
  271. }
  272. func checkIPv4Address(addr net.IP) (net.IP, error) {
  273. if c := addr.To4(); c != nil {
  274. return c, nil
  275. }
  276. if len(addr) == net.IPv6len {
  277. return nil, errors.New("address is IPv6")
  278. }
  279. return nil, fmt.Errorf("wrong length of %d bytes instead of %d", len(addr), net.IPv4len)
  280. }
  281. func (ip *IPv4) AddressTo4() error {
  282. var src, dst net.IP
  283. if addr, err := checkIPv4Address(ip.SrcIP); err != nil {
  284. return fmt.Errorf("Invalid source IPv4 address (%s)", err)
  285. } else {
  286. src = addr
  287. }
  288. if addr, err := checkIPv4Address(ip.DstIP); err != nil {
  289. return fmt.Errorf("Invalid destination IPv4 address (%s)", err)
  290. } else {
  291. dst = addr
  292. }
  293. ip.SrcIP = src
  294. ip.DstIP = dst
  295. return nil
  296. }