packetfu 1.1.11 → 1.1.12.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.rspec +2 -0
  4. data/.travis.yml +2 -3
  5. data/README.md +127 -0
  6. data/examples/100kpackets.rb +11 -10
  7. data/examples/ackscan.rb +4 -1
  8. data/examples/arp.rb +4 -5
  9. data/examples/arphood.rb +5 -4
  10. data/examples/dissect_thinger.rb +10 -7
  11. data/examples/ethernet.rb +8 -3
  12. data/examples/ids.rb +22 -4
  13. data/examples/idsv2.rb +25 -6
  14. data/examples/ifconfig.rb +6 -3
  15. data/examples/new-simple-stats.rb +5 -6
  16. data/examples/packetfu-shell.rb +11 -48
  17. data/examples/pcap2pcapng.rb +32 -0
  18. data/examples/simple-sniffer.rb +9 -4
  19. data/examples/simple-stats.rb +7 -8
  20. data/examples/slammer.rb +2 -2
  21. data/examples/uniqpcap.rb +17 -7
  22. data/lib/packetfu.rb +10 -175
  23. data/lib/packetfu/capture.rb +2 -2
  24. data/lib/packetfu/common.rb +142 -0
  25. data/lib/packetfu/config.rb +8 -8
  26. data/lib/packetfu/inject.rb +3 -3
  27. data/lib/packetfu/packet.rb +22 -18
  28. data/lib/packetfu/pcap.rb +2 -1
  29. data/lib/packetfu/pcapng.rb +37 -0
  30. data/lib/packetfu/pcapng/block.rb +25 -0
  31. data/lib/packetfu/pcapng/epb.rb +112 -0
  32. data/lib/packetfu/pcapng/file.rb +316 -0
  33. data/lib/packetfu/pcapng/idb.rb +125 -0
  34. data/lib/packetfu/pcapng/shb.rb +146 -0
  35. data/lib/packetfu/pcapng/spb.rb +83 -0
  36. data/lib/packetfu/pcapng/unknown_block.rb +60 -0
  37. data/lib/packetfu/protos.rb +3 -0
  38. data/lib/packetfu/protos/arp.rb +10 -10
  39. data/lib/packetfu/protos/icmpv6.rb +131 -0
  40. data/lib/packetfu/protos/icmpv6/header.rb +69 -0
  41. data/lib/packetfu/protos/icmpv6/mixin.rb +14 -0
  42. data/lib/packetfu/protos/ip.rb +4 -5
  43. data/lib/packetfu/protos/ipv6/header.rb +2 -0
  44. data/lib/packetfu/protos/udp.rb +24 -12
  45. data/lib/packetfu/structfu.rb +27 -0
  46. data/lib/packetfu/utils.rb +55 -9
  47. data/lib/packetfu/version.rb +1 -1
  48. data/packetfu.gemspec +13 -7
  49. data/spec/arp_spec.rb +11 -5
  50. data/spec/eth_spec.rb +20 -11
  51. data/spec/fake_packets.rb +28 -0
  52. data/spec/hsrp_spec.rb +15 -0
  53. data/spec/icmp_spec.rb +12 -5
  54. data/spec/icmpv6_spec.rb +98 -0
  55. data/spec/invalid_spec.rb +28 -0
  56. data/spec/ip_spec.rb +10 -5
  57. data/spec/ipv4_icmp.pcap +0 -0
  58. data/spec/ipv4_udp.pcap +0 -0
  59. data/spec/ipv6_icmp.pcap +0 -0
  60. data/spec/ipv6_spec.rb +4 -0
  61. data/spec/ipv6_udp.pcap +0 -0
  62. data/spec/lldp_spec.rb +36 -0
  63. data/spec/octets_spec.rb +43 -0
  64. data/spec/packet_spec.rb +24 -0
  65. data/spec/packetfu_spec.rb +6 -1
  66. data/spec/pcap_spec.rb +286 -0
  67. data/spec/pcapng/epb_spec.rb +81 -0
  68. data/spec/pcapng/file_spec.rb +295 -0
  69. data/spec/pcapng/file_spec_helper.rb +45 -0
  70. data/spec/pcapng/idb_spec.rb +53 -0
  71. data/spec/pcapng/shb_spec.rb +42 -0
  72. data/spec/pcapng/spb_spec.rb +43 -0
  73. data/spec/pcapng/unknown_block_spec.rb +36 -0
  74. data/spec/spec_helper.rb +3 -31
  75. data/spec/tcp_spec.rb +4 -1
  76. data/spec/udp_spec.rb +149 -1
  77. data/spec/utils_spec.rb +98 -15
  78. data/test/pcapng-test/output_be/advanced/test100.pcapng +0 -0
  79. data/test/pcapng-test/output_be/advanced/test100.txt +11 -0
  80. data/test/pcapng-test/output_be/advanced/test101.pcapng +0 -0
  81. data/test/pcapng-test/output_be/advanced/test101.txt +11 -0
  82. data/test/pcapng-test/output_be/advanced/test102.pcapng +0 -0
  83. data/test/pcapng-test/output_be/advanced/test102.txt +14 -0
  84. data/test/pcapng-test/output_be/basic/test001.pcapng +0 -0
  85. data/test/pcapng-test/output_be/basic/test001.txt +9 -0
  86. data/test/pcapng-test/output_be/basic/test002.pcapng +0 -0
  87. data/test/pcapng-test/output_be/basic/test002.txt +7 -0
  88. data/test/pcapng-test/output_be/basic/test003.pcapng +0 -0
  89. data/test/pcapng-test/output_be/basic/test003.txt +8 -0
  90. data/test/pcapng-test/output_be/basic/test004.pcapng +0 -0
  91. data/test/pcapng-test/output_be/basic/test004.txt +9 -0
  92. data/test/pcapng-test/output_be/basic/test005.pcapng +0 -0
  93. data/test/pcapng-test/output_be/basic/test005.txt +9 -0
  94. data/test/pcapng-test/output_be/basic/test006.pcapng +0 -0
  95. data/test/pcapng-test/output_be/basic/test006.txt +9 -0
  96. data/test/pcapng-test/output_be/basic/test007.pcapng +0 -0
  97. data/test/pcapng-test/output_be/basic/test007.txt +9 -0
  98. data/test/pcapng-test/output_be/basic/test008.pcapng +0 -0
  99. data/test/pcapng-test/output_be/basic/test008.txt +9 -0
  100. data/test/pcapng-test/output_be/basic/test009.pcapng +0 -0
  101. data/test/pcapng-test/output_be/basic/test009.txt +9 -0
  102. data/test/pcapng-test/output_be/basic/test010.pcapng +0 -0
  103. data/test/pcapng-test/output_be/basic/test010.txt +9 -0
  104. data/test/pcapng-test/output_be/basic/test011.pcapng +0 -0
  105. data/test/pcapng-test/output_be/basic/test011.txt +10 -0
  106. data/test/pcapng-test/output_be/basic/test012.pcapng +0 -0
  107. data/test/pcapng-test/output_be/basic/test012.txt +10 -0
  108. data/test/pcapng-test/output_be/basic/test013.pcapng +0 -0
  109. data/test/pcapng-test/output_be/basic/test013.txt +9 -0
  110. data/test/pcapng-test/output_be/basic/test014.pcapng +0 -0
  111. data/test/pcapng-test/output_be/basic/test014.txt +9 -0
  112. data/test/pcapng-test/output_be/basic/test015.pcapng +0 -0
  113. data/test/pcapng-test/output_be/basic/test015.txt +9 -0
  114. data/test/pcapng-test/output_be/basic/test016.pcapng +0 -0
  115. data/test/pcapng-test/output_be/basic/test016.txt +11 -0
  116. data/test/pcapng-test/output_be/basic/test017.pcapng +0 -0
  117. data/test/pcapng-test/output_be/basic/test017.txt +9 -0
  118. data/test/pcapng-test/output_be/basic/test018.pcapng +0 -0
  119. data/test/pcapng-test/output_be/basic/test018.txt +12 -0
  120. data/test/pcapng-test/output_be/difficult/test200.pcapng +0 -0
  121. data/test/pcapng-test/output_be/difficult/test200.txt +8 -0
  122. data/test/pcapng-test/output_be/difficult/test201.pcapng +0 -0
  123. data/test/pcapng-test/output_be/difficult/test201.txt +11 -0
  124. data/test/pcapng-test/output_be/difficult/test202.pcapng +0 -0
  125. data/test/pcapng-test/output_be/difficult/test202.txt +14 -0
  126. data/test/pcapng-test/output_le/advanced/test100.pcapng +0 -0
  127. data/test/pcapng-test/output_le/advanced/test100.txt +11 -0
  128. data/test/pcapng-test/output_le/advanced/test101.pcapng +0 -0
  129. data/test/pcapng-test/output_le/advanced/test101.txt +11 -0
  130. data/test/pcapng-test/output_le/advanced/test102.pcapng +0 -0
  131. data/test/pcapng-test/output_le/advanced/test102.txt +14 -0
  132. data/test/pcapng-test/output_le/basic/test001.pcapng +0 -0
  133. data/test/pcapng-test/output_le/basic/test001.txt +9 -0
  134. data/test/pcapng-test/output_le/basic/test002.pcapng +0 -0
  135. data/test/pcapng-test/output_le/basic/test002.txt +7 -0
  136. data/test/pcapng-test/output_le/basic/test003.pcapng +0 -0
  137. data/test/pcapng-test/output_le/basic/test003.txt +8 -0
  138. data/test/pcapng-test/output_le/basic/test004.pcapng +0 -0
  139. data/test/pcapng-test/output_le/basic/test004.txt +9 -0
  140. data/test/pcapng-test/output_le/basic/test005.pcapng +0 -0
  141. data/test/pcapng-test/output_le/basic/test005.txt +9 -0
  142. data/test/pcapng-test/output_le/basic/test006.pcapng +0 -0
  143. data/test/pcapng-test/output_le/basic/test006.txt +9 -0
  144. data/test/pcapng-test/output_le/basic/test007.pcapng +0 -0
  145. data/test/pcapng-test/output_le/basic/test007.txt +9 -0
  146. data/test/pcapng-test/output_le/basic/test008.pcapng +0 -0
  147. data/test/pcapng-test/output_le/basic/test008.txt +9 -0
  148. data/test/pcapng-test/output_le/basic/test009.pcapng +0 -0
  149. data/test/pcapng-test/output_le/basic/test009.txt +9 -0
  150. data/test/pcapng-test/output_le/basic/test010.pcapng +0 -0
  151. data/test/pcapng-test/output_le/basic/test010.txt +9 -0
  152. data/test/pcapng-test/output_le/basic/test011.pcapng +0 -0
  153. data/test/pcapng-test/output_le/basic/test011.txt +10 -0
  154. data/test/pcapng-test/output_le/basic/test012.pcapng +0 -0
  155. data/test/pcapng-test/output_le/basic/test012.txt +10 -0
  156. data/test/pcapng-test/output_le/basic/test013.pcapng +0 -0
  157. data/test/pcapng-test/output_le/basic/test013.txt +9 -0
  158. data/test/pcapng-test/output_le/basic/test014.pcapng +0 -0
  159. data/test/pcapng-test/output_le/basic/test014.txt +9 -0
  160. data/test/pcapng-test/output_le/basic/test015.pcapng +0 -0
  161. data/test/pcapng-test/output_le/basic/test015.txt +9 -0
  162. data/test/pcapng-test/output_le/basic/test016.pcapng +0 -0
  163. data/test/pcapng-test/output_le/basic/test016.txt +11 -0
  164. data/test/pcapng-test/output_le/basic/test017.pcapng +0 -0
  165. data/test/pcapng-test/output_le/basic/test017.txt +9 -0
  166. data/test/pcapng-test/output_le/basic/test018.pcapng +0 -0
  167. data/test/pcapng-test/output_le/basic/test018.txt +12 -0
  168. data/test/pcapng-test/output_le/difficult/test200.pcapng +0 -0
  169. data/test/pcapng-test/output_le/difficult/test200.txt +8 -0
  170. data/test/pcapng-test/output_le/difficult/test201.pcapng +0 -0
  171. data/test/pcapng-test/output_le/difficult/test201.txt +11 -0
  172. data/test/pcapng-test/output_le/difficult/test202.pcapng +0 -0
  173. data/test/pcapng-test/output_le/difficult/test202.txt +14 -0
  174. data/test/sample-ipv6.pcapng +0 -0
  175. data/test/sample-spb.pcapng +0 -0
  176. data/test/sample.pcapng +0 -0
  177. data/test/sample2.pcapng +0 -0
  178. metadata +190 -68
  179. checksums.yaml.gz.sig +0 -0
  180. data.tar.gz.sig +0 -2
  181. data/INSTALL.rdoc +0 -40
  182. data/README.rdoc +0 -64
  183. data/examples/examples.rb +0 -4
  184. data/setup.rb +0 -1586
  185. data/test/func_lldp.rb +0 -25
  186. data/test/ptest.rb +0 -16
  187. data/test/test_eth.rb +0 -93
  188. data/test/test_hsrp.rb +0 -20
  189. data/test/test_invalid.rb +0 -28
  190. data/test/test_octets.rb +0 -36
  191. data/test/test_pcap.rb +0 -211
  192. data/test/test_udp.rb +0 -100
  193. metadata.gz.sig +0 -2
@@ -0,0 +1,131 @@
1
+ # coding: binary
2
+ require 'packetfu/protos/eth/header'
3
+ require 'packetfu/protos/eth/mixin'
4
+
5
+ require 'packetfu/protos/ipv6/header'
6
+ require 'packetfu/protos/ipv6/mixin'
7
+
8
+ require 'packetfu/protos/icmpv6/header'
9
+ require 'packetfu/protos/icmpv6/mixin'
10
+
11
+ module PacketFu
12
+
13
+ # ICMPv6Packet is used to construct ICMPv6 Packets. They contain an EthHeader,
14
+ # an IPv6Header, and a ICMPv6Header.
15
+ #
16
+ # == Example
17
+ #
18
+ # icmpv6_pkt.new
19
+ # icmpv6_pkt.icmpv6_type = 8
20
+ # icmpv6_pkt.icmpv6_code = 0
21
+ # icmpv6_pkt.payload = "ABC, easy as 123. As simple as do-re-mi. ABC, 123, baby, you and me!"
22
+ #
23
+ # icmpv6_pkt.ipv6_saddr="2000::1234"
24
+ # icmpv6_pkt.ipv6_daddr="2000::5678"
25
+ #
26
+ # icmpv6_pkt.recalc
27
+ # icmpv6_pkt.to_f('/tmp/icmpv6.pcap')
28
+ #
29
+ # == Parameters
30
+ #
31
+ # :eth
32
+ # A pre-generated EthHeader object.
33
+ # :ipv6
34
+ # A pre-generated IPv6Header object.
35
+ # :icmpv6
36
+ # A pre-generated ICMPv6Header object.
37
+ class ICMPv6Packet < Packet
38
+ include ::PacketFu::EthHeaderMixin
39
+ include ::PacketFu::IPv6HeaderMixin
40
+ include ::PacketFu::ICMPv6HeaderMixin
41
+
42
+ attr_accessor :eth_header, :ipv6_header, :icmpv6_header
43
+
44
+ def self.can_parse?(str)
45
+ return false unless str.size >= 58
46
+ return false unless EthPacket.can_parse? str
47
+ return false unless IPv6Packet.can_parse? str
48
+ return false unless str[20,1] == [PacketFu::ICMPv6Header::PROTOCOL_NUMBER].pack('C')
49
+ return true
50
+ end
51
+
52
+ def read(str=nil, args={})
53
+ raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
54
+ @eth_header.read(str)
55
+ super(args)
56
+ self
57
+ end
58
+
59
+ def initialize(args={})
60
+ @eth_header = EthHeader.new(args).read(args[:eth])
61
+ @ipv6_header = IPv6Header.new(args).read(args[:ipv6])
62
+ @ipv6_header.ipv6_next = PacketFu::ICMPv6Header::PROTOCOL_NUMBER
63
+ @icmpv6_header = ICMPv6Header.new(args).read(args[:icmpv6])
64
+
65
+ @ipv6_header.body = @icmpv6_header
66
+ @eth_header.body = @ipv6_header
67
+
68
+ @headers = [@eth_header, @ipv6_header, @icmpv6_header]
69
+ super
70
+ icmpv6_calc_sum
71
+ end
72
+
73
+ # Calculates the checksum for the object.
74
+ def icmpv6_calc_sum
75
+ checksum = 0
76
+
77
+ # Compute sum on pseudo-header
78
+ [ipv6_src, ipv6_dst].each do |iaddr|
79
+ 8.times { |i| checksum += (iaddr >> (i*16)) & 0xffff }
80
+ end
81
+ checksum += PacketFu::ICMPv6Header::PROTOCOL_NUMBER
82
+ checksum += ipv6_len
83
+ # Then compute it on ICMPv6 header + payload
84
+ checksum += (icmpv6_type.to_i << 8) + icmpv6_code.to_i
85
+ chk_body = (payload.to_s.size % 2 == 0 ? payload.to_s : payload.to_s + "\x00")
86
+ if 1.respond_to? :ord
87
+ chk_body.split("").each_slice(2).map { |x| (x[0].ord << 8) + x[1].ord }.
88
+ each { |y| checksum += y }
89
+ else
90
+ chk_body.split("").each_slice(2).map { |x| (x[0] << 8) + x[1] }.
91
+ each { |y| checksum += y }
92
+ end
93
+ checksum = checksum % 0xffff
94
+ checksum = 0xffff - checksum
95
+ checksum == 0 ? 0xffff : checksum
96
+ end
97
+
98
+ # Recalculates the calculatable fields for ICMPv6.
99
+ def icmpv6_recalc(arg=:all)
100
+ arg = arg.intern if arg.respond_to? :intern
101
+ case arg
102
+ when :icmpv6_sum
103
+ self.icmpv6_sum = icmpv6_calc_sum
104
+ when :all
105
+ self.icmpv6_sum = icmpv6_calc_sum
106
+ else
107
+ raise ArgumentError, "No such field `#{arg}'"
108
+ end
109
+ end
110
+
111
+ # Peek provides summary data on packet contents.
112
+ def peek_format
113
+ peek_data = ["6C "]
114
+ peek_data << "%-5d" % self.to_s.size
115
+ type = case self.icmpv6_type.to_i
116
+ when 128
117
+ "ping"
118
+ when 129
119
+ "pong"
120
+ else
121
+ "%02x-%02x" % [self.icmpv6_type, self.icmpv6_code]
122
+ end
123
+ peek_data << "%-21s" % "#{self.ipv6_saddr}:#{type}"
124
+ peek_data << "->"
125
+ peek_data << "%21s" % "#{self.ipv6_daddr}"
126
+ peek_data.join
127
+ end
128
+
129
+ end
130
+
131
+ end
@@ -0,0 +1,69 @@
1
+ require 'packetfu/protos/ipv6/header'
2
+ require 'packetfu/protos/ipv6/mixin'
3
+
4
+ module PacketFu
5
+
6
+ # ICMPv6Header is a complete ICMPv6 struct, used in ICMPv6Packet.
7
+ # ICMPv6 is typically used for network administration and connectivity
8
+ # testing.
9
+ #
10
+ # For more on ICMP packets, see
11
+ # http://www.networksorcery.com/enp/protocol/icmpv6.htm
12
+ #
13
+ # ==== Header Definition
14
+ #
15
+ # Int8 :icmp_type # Type
16
+ # Int8 :icmp_code # Code
17
+ # Int16 :icmp_sum Default: calculated # Checksum
18
+ # String :body
19
+ class ICMPv6Header < Struct.new(:icmpv6_type, :icmpv6_code, :icmpv6_sum, :body)
20
+ include StructFu
21
+
22
+ PROTOCOL_NUMBER = 58
23
+
24
+ def initialize(args={})
25
+ super(
26
+ Int8.new(args[:icmpv6_type]),
27
+ Int8.new(args[:icmpv6_code]),
28
+ Int16.new(args[:icmpv6_sum]),
29
+ StructFu::String.new.read(args[:body])
30
+ )
31
+ end
32
+
33
+ # Returns the object in string form.
34
+ def to_s
35
+ self.to_a.map {|x| x.to_s}.join
36
+ end
37
+
38
+ # Reads a string to populate the object.
39
+ def read(str)
40
+ force_binary(str)
41
+ return self if str.nil?
42
+ self[:icmpv6_type].read(str[0,1])
43
+ self[:icmpv6_code].read(str[1,1])
44
+ self[:icmpv6_sum].read(str[2,2])
45
+ self[:body].read(str[4,str.size])
46
+ self
47
+ end
48
+
49
+ # Setter for the type.
50
+ def icmpv6_type=(i); typecast i; end
51
+ # Getter for the type.
52
+ def icmpv6_type; self[:icmpv6_type].to_i; end
53
+ # Setter for the code.
54
+ def icmpv6_code=(i); typecast i; end
55
+ # Getter for the code.
56
+ def icmpv6_code; self[:icmpv6_code].to_i; end
57
+ # Setter for the checksum. Note, this is calculated automatically with
58
+ # icmpv6_calc_sum.
59
+ def icmpv6_sum=(i); typecast i; end
60
+ # Getter for the checksum.
61
+ def icmpv6_sum; self[:icmpv6_sum].to_i; end
62
+
63
+ def icmpv6_sum_readable
64
+ "0x%04x" % icmpv6_sum
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,14 @@
1
+ module PacketFu
2
+ # This Mixin simplifies access to the ICMPv6Headers. Mix this in with your
3
+ # packet interface, and it will add methods that essentially delegate to
4
+ # the 'icmpv6_header' method (assuming that it is a ICMPv6Header object)
5
+ module ICMPv6HeaderMixin
6
+ def icmpv6_type=(v); self.icmpv6_header.icmpv6_type= v; end
7
+ def icmpv6_type; self.icmpv6_header.icmpv6_type; end
8
+ def icmpv6_code=(v); self.icmpv6_header.icmpv6_code= v; end
9
+ def icmpv6_code; self.icmpv6_header.icmpv6_code; end
10
+ def icmpv6_sum=(v); self.icmpv6_header.icmpv6_sum= v; end
11
+ def icmpv6_sum; self.icmpv6_header.icmpv6_sum; end
12
+ def icmpv6_sum_readable; self.icmpv6_header.icmpv6_sum_readable; end
13
+ end
14
+ end
@@ -1,7 +1,6 @@
1
1
  # -*- coding: binary -*-
2
2
  require 'packetfu/protos/eth/header'
3
3
  require 'packetfu/protos/eth/mixin'
4
-
5
4
  require 'packetfu/protos/ip/header'
6
5
  require 'packetfu/protos/ip/mixin'
7
6
 
@@ -20,7 +19,7 @@ module PacketFu
20
19
  # ip_pkt.ip_ttl=64
21
20
  # ip_pkt.ip_payload="\x00\x00\x12\x34\x00\x01\x00\x01"+
22
21
  # "Lovingly hand-crafted echo responses delivered directly to your door."
23
- # ip_pkt.recalc
22
+ # ip_pkt.recalc
24
23
  # ip_pkt.to_f('/tmp/ip.pcap')
25
24
  #
26
25
  # == Parameters
@@ -49,7 +48,7 @@ module PacketFu
49
48
  else
50
49
  ipv = str[14,1][0] >> 4
51
50
  end
52
- return true if ipv == 4
51
+ return true if ipv == 4
53
52
  else
54
53
  return false
55
54
  end
@@ -58,11 +57,11 @@ module PacketFu
58
57
  def read(str=nil, args={})
59
58
  raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
60
59
  @eth_header.read(str)
61
- super(args)
60
+ super(args)
62
61
  self
63
62
  end
64
63
 
65
- # Creates a new IPPacket object.
64
+ # Creates a new IPPacket object.
66
65
  def initialize(args={})
67
66
  @eth_header = EthHeader.new(args).read(args[:eth])
68
67
  @ip_header = IPHeader.new(args).read(args[:ip])
@@ -1,4 +1,6 @@
1
1
  # -*- coding: binary -*-
2
+ require 'ipaddr'
3
+
2
4
  module PacketFu
3
5
  # AddrIpv6 handles addressing for IPv6Header
4
6
  #
@@ -55,9 +55,12 @@ module PacketFu
55
55
  def self.can_parse?(str)
56
56
  return false unless str.size >= 28
57
57
  return false unless EthPacket.can_parse? str
58
- return false unless IPPacket.can_parse? str
59
- return false unless str[23,1] == "\x11"
60
- return true
58
+ if IPPacket.can_parse? str
59
+ return true if str[23,1] == "\x11"
60
+ elsif IPv6Packet.can_parse? str
61
+ return true if str[20,1] == "\x11"
62
+ end
63
+ false
61
64
  end
62
65
 
63
66
  def read(str=nil, args={})
@@ -157,19 +160,28 @@ module PacketFu
157
160
 
158
161
  # Peek provides summary data on packet contents.
159
162
  def peek_format
160
- peek_data = ["U "]
161
- peek_data << "%-5d" % self.to_s.size
162
- peek_data << "%-21s" % "#{self.ip_saddr}:#{self.udp_sport}"
163
- peek_data << "->"
164
- peek_data << "%21s" % "#{self.ip_daddr}:#{self.udp_dport}"
165
- peek_data << "%23s" % "I:"
166
- peek_data << "%04x" % self.ip_id
167
- peek_data.join
163
+ if self.ipv6?
164
+ peek_data = ["6U "]
165
+ peek_data << "%-5d" % self.to_s.size
166
+ peek_data << "%-31s" % "#{self.ipv6_saddr}:#{self.udp_sport}"
167
+ peek_data << "->"
168
+ peek_data << "%31s" % "#{self.ipv6_daddr}:#{self.udp_dport}"
169
+ peek_data.join
170
+ else
171
+ peek_data = ["U "]
172
+ peek_data << "%-5d" % self.to_s.size
173
+ peek_data << "%-21s" % "#{self.ip_saddr}:#{self.udp_sport}"
174
+ peek_data << "->"
175
+ peek_data << "%21s" % "#{self.ip_daddr}:#{self.udp_dport}"
176
+ peek_data << "%23s" % "I:"
177
+ peek_data << "%04x" % self.ip_id
178
+ peek_data.join
179
+ end
168
180
  end
169
181
 
170
182
  # Is that packet an UDP on IPv6 packet ?
171
183
  def ipv6?
172
- @ipv6_header
184
+ not @ipv6_header.nil?
173
185
  end
174
186
 
175
187
  end
@@ -165,6 +165,33 @@ module StructFu
165
165
  end
166
166
  end
167
167
 
168
+ # Int64 is a eight byte value.
169
+ class Int64 < Int
170
+ def initialize(v=nil, e=:big)
171
+ super(v, e, w=4)
172
+ @packstr = (self.e == :big) ? 'Q>' : 'Q<'
173
+ end
174
+
175
+ # Returns a eight byte value as a packed string.
176
+ def to_s
177
+ @packstr = (self.e == :big) ? 'Q>' : 'Q<'
178
+ [(self.v || self.d)].pack(@packstr)
179
+ end
180
+ end
181
+
182
+ # Int64be is a eight byte value in big-endian format. The endianness cannot be altered.
183
+ class Int64be < Int64
184
+ undef :endian=
185
+ end
186
+
187
+ # Int64le is a eight byte value in little-endian format. The endianness cannot be altered.
188
+ class Int64le < Int64
189
+ undef :endian=
190
+ def initialize(v=nil, e=:little)
191
+ super(v,e)
192
+ end
193
+ end
194
+
168
195
  # Strings are just like regular strings, except it comes with a read() function
169
196
  # so that it behaves like other StructFu elements.
170
197
  class String < ::String
@@ -1,7 +1,6 @@
1
1
  # -*- coding: binary -*-
2
2
  require 'singleton'
3
3
  require 'timeout'
4
- require 'network_interface'
5
4
 
6
5
  module PacketFu
7
6
 
@@ -23,6 +22,9 @@ module PacketFu
23
22
  # The flavor of the ARP request. Defaults to :none.
24
23
  # :timeout
25
24
  # Timeout in seconds. Defaults to 3.
25
+ # :no_cache
26
+ # Do not query ARP cache and always send an ARP request. Defaults to
27
+ # false.
26
28
  #
27
29
  # === Example
28
30
  # PacketFu::Utils::arp("192.168.1.1") #=> "00:18:39:01:33:70"
@@ -33,6 +35,11 @@ module PacketFu
33
35
  # It goes without saying, spewing forged ARP packets on your network is a great way to really
34
36
  # irritate your co-workers.
35
37
  def self.arp(target_ip,args={})
38
+ unless args[:no_cache]
39
+ cache = self.arp_cache
40
+ return cache[target_ip].first if cache[target_ip]
41
+ end
42
+
36
43
  iface = args[:iface] || :eth0
37
44
  args[:config] ||= whoami?(:iface => iface)
38
45
  arp_pkt = PacketFu::ARPPacket.new(:flavor => (args[:flavor] || :none), :config => args[:config])
@@ -59,6 +66,25 @@ module PacketFu
59
66
  cap_thread.value
60
67
  end
61
68
 
69
+ # Determine ARP cache data string
70
+ def self.arp_cache_raw
71
+ %x(/usr/sbin/arp -na)
72
+ end
73
+
74
+ # Get ARP cache.
75
+ # More rubyish than PAcketFu::Utils.arp_cache_data_string
76
+ def self.arp_cache
77
+ arp_cache = {}
78
+ arp_table = arp_cache_raw
79
+ arp_table.split(/\n/).each do |line|
80
+ match = line.match(/\? \((?<ip>\d+\.\d+\.\d+\.\d+)\) at (?<mac>([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2})(?: \[ether\])? on (?<int>[a-zA-Z0-9]+)/)
81
+ if match
82
+ arp_cache[match[:ip]] = [match[:mac], match[:int]]
83
+ end
84
+ end
85
+ arp_cache
86
+ end
87
+
62
88
  # Since 177/8 is IANA reserved (for now), this network should
63
89
  # be handled by your default gateway and default interface.
64
90
  def self.rand_routable_daddr
@@ -166,13 +192,10 @@ module PacketFu
166
192
  def self.default_int
167
193
  ip = default_ip
168
194
 
169
- NetworkInterface.interfaces.each do |interface|
170
- NetworkInterface.addresses(interface).values.each do |addresses|
171
- addresses.each do |address|
172
- next if address["addr"].nil?
173
- return interface if address["addr"] == ip
174
- end
175
- end
195
+ Socket.getifaddrs.each do |ifaddr|
196
+ next unless ifaddr.addr.ip?
197
+
198
+ return ifaddr.name if ifaddr.addr.ip_address == ip
176
199
  end
177
200
 
178
201
  # Fall back to libpcap as last resort
@@ -182,7 +205,7 @@ module PacketFu
182
205
  # Determine the ifconfig data string for a given interface
183
206
  def self.ifconfig_data_string(iface=default_int)
184
207
  # Make sure to only get interface data for a real interface
185
- unless NetworkInterface.interfaces.include?(iface)
208
+ unless Socket.getifaddrs.any? {|ifaddr| ifaddr.name == iface}
186
209
  raise ArgumentError, "#{iface} interface does not exist"
187
210
  end
188
211
  return %x[ifconfig #{iface}]
@@ -290,6 +313,29 @@ module PacketFu
290
313
  ret[:ip6_obj] = IPAddr.new($1)
291
314
  end
292
315
  end # freebsd
316
+ when /openbsd/i
317
+ ifconfig_data = ifconfig_data_string(iface)
318
+ if ifconfig_data =~ /#{iface}/
319
+ ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
320
+ else
321
+ raise ArgumentError, "Cannot ifconfig #{iface}"
322
+ end
323
+ ret[:iface] = iface
324
+ ifconfig_data.each do |s|
325
+ case s
326
+ when /lladdr[\s]*([0-9a-fA-F:]{17})/
327
+ ret[:eth_saddr] = $1.downcase
328
+ ret[:eth_src] = EthHeader.mac2str(ret[:eth_saddr])
329
+ when /inet[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*netmask[\s]*(0x[0-9a-fA-F]{8}))?/
330
+ ret[:ip_saddr] = $1
331
+ ret[:ip_src] = [IPAddr.new($1).to_i].pack("N")
332
+ ret[:ip4_obj] = IPAddr.new($1)
333
+ ret[:ip4_obj] = ret[:ip4_obj].mask(($3.hex.to_s(2) =~ /0*$/)) if $3
334
+ when /inet6[\s]*([0-9a-fA-F:\x2f]+)/
335
+ ret[:ip6_saddr] = $1
336
+ ret[:ip6_obj] = IPAddr.new($1)
337
+ end
338
+ end # openbsd
293
339
  end # RUBY_PLATFORM
294
340
  ret
295
341
  end