ip4.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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. flagsfrags := binary.BigEndian.Uint16(data[6:8])
  170. ip.Version = uint8(data[0]) >> 4
  171. ip.IHL = uint8(data[0]) & 0x0F
  172. ip.TOS = data[1]
  173. ip.Length = binary.BigEndian.Uint16(data[2:4])
  174. ip.Id = binary.BigEndian.Uint16(data[4:6])
  175. ip.Flags = IPv4Flag(flagsfrags >> 13)
  176. ip.FragOffset = flagsfrags & 0x1FFF
  177. ip.TTL = data[8]
  178. ip.Protocol = IPProtocol(data[9])
  179. ip.Checksum = binary.BigEndian.Uint16(data[10:12])
  180. ip.SrcIP = data[12:16]
  181. ip.DstIP = data[16:20]
  182. ip.Options = ip.Options[:0]
  183. // Set up an initial guess for contents/payload... we'll reset these soon.
  184. ip.BaseLayer = BaseLayer{Contents: data}
  185. // This code is added for the following enviroment:
  186. // * Windows 10 with TSO option activated. ( tested on Hyper-V, RealTek ethernet driver )
  187. if ip.Length == 0 {
  188. // If using TSO(TCP Segmentation Offload), length is zero.
  189. // The actual packet length is the length of data.
  190. ip.Length = uint16(len(data))
  191. }
  192. if ip.Length < 20 {
  193. return fmt.Errorf("Invalid (too small) IP length (%d < 20)", ip.Length)
  194. } else if ip.IHL < 5 {
  195. return fmt.Errorf("Invalid (too small) IP header length (%d < 5)", ip.IHL)
  196. } else if int(ip.IHL*4) > int(ip.Length) {
  197. return fmt.Errorf("Invalid IP header length > IP length (%d > %d)", ip.IHL, ip.Length)
  198. }
  199. if cmp := len(data) - int(ip.Length); cmp > 0 {
  200. data = data[:ip.Length]
  201. } else if cmp < 0 {
  202. df.SetTruncated()
  203. if int(ip.IHL)*4 > len(data) {
  204. return errors.New("Not all IP header bytes available")
  205. }
  206. }
  207. ip.Contents = data[:ip.IHL*4]
  208. ip.Payload = data[ip.IHL*4:]
  209. // From here on, data contains the header options.
  210. data = data[20 : ip.IHL*4]
  211. // Pull out IP options
  212. for len(data) > 0 {
  213. if ip.Options == nil {
  214. // Pre-allocate to avoid growing the slice too much.
  215. ip.Options = make([]IPv4Option, 0, 4)
  216. }
  217. opt := IPv4Option{OptionType: data[0]}
  218. switch opt.OptionType {
  219. case 0: // End of options
  220. opt.OptionLength = 1
  221. ip.Options = append(ip.Options, opt)
  222. ip.Padding = data[1:]
  223. break
  224. case 1: // 1 byte padding
  225. opt.OptionLength = 1
  226. default:
  227. opt.OptionLength = data[1]
  228. opt.OptionData = data[2:opt.OptionLength]
  229. }
  230. if len(data) >= int(opt.OptionLength) {
  231. data = data[opt.OptionLength:]
  232. } else {
  233. return fmt.Errorf("IP option length exceeds remaining IP header size, option type %v length %v", opt.OptionType, opt.OptionLength)
  234. }
  235. ip.Options = append(ip.Options, opt)
  236. }
  237. return nil
  238. }
  239. func (i *IPv4) CanDecode() gopacket.LayerClass {
  240. return LayerTypeIPv4
  241. }
  242. func (i *IPv4) NextLayerType() gopacket.LayerType {
  243. if i.Flags&IPv4MoreFragments != 0 || i.FragOffset != 0 {
  244. return gopacket.LayerTypeFragment
  245. }
  246. return i.Protocol.LayerType()
  247. }
  248. func decodeIPv4(data []byte, p gopacket.PacketBuilder) error {
  249. ip := &IPv4{}
  250. err := ip.DecodeFromBytes(data, p)
  251. p.AddLayer(ip)
  252. p.SetNetworkLayer(ip)
  253. if err != nil {
  254. return err
  255. }
  256. return p.NextDecoder(ip.NextLayerType())
  257. }
  258. func checkIPv4Address(addr net.IP) (net.IP, error) {
  259. if c := addr.To4(); c != nil {
  260. return c, nil
  261. }
  262. if len(addr) == net.IPv6len {
  263. return nil, errors.New("address is IPv6")
  264. }
  265. return nil, fmt.Errorf("wrong length of %d bytes instead of %d", len(addr), net.IPv4len)
  266. }
  267. func (ip *IPv4) AddressTo4() error {
  268. var src, dst net.IP
  269. if addr, err := checkIPv4Address(ip.SrcIP); err != nil {
  270. return fmt.Errorf("Invalid source IPv4 address (%s)", err)
  271. } else {
  272. src = addr
  273. }
  274. if addr, err := checkIPv4Address(ip.DstIP); err != nil {
  275. return fmt.Errorf("Invalid destination IPv4 address (%s)", err)
  276. } else {
  277. dst = addr
  278. }
  279. ip.SrcIP = src
  280. ip.DstIP = dst
  281. return nil
  282. }