packetfu 1.1.9 → 1.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/bench/octets.rb +9 -9
  2. data/examples/100kpackets.rb +12 -12
  3. data/examples/ackscan.rb +16 -16
  4. data/examples/arp.rb +35 -35
  5. data/examples/arphood.rb +36 -36
  6. data/examples/dissect_thinger.rb +6 -6
  7. data/examples/new-simple-stats.rb +23 -23
  8. data/examples/packetfu-shell.rb +25 -25
  9. data/examples/simple-sniffer.rb +9 -9
  10. data/examples/simple-stats.rb +23 -23
  11. data/examples/slammer.rb +3 -3
  12. data/lib/packetfu.rb +127 -127
  13. data/lib/packetfu/capture.rb +169 -169
  14. data/lib/packetfu/config.rb +52 -52
  15. data/lib/packetfu/inject.rb +56 -56
  16. data/lib/packetfu/packet.rb +528 -528
  17. data/lib/packetfu/pcap.rb +579 -579
  18. data/lib/packetfu/protos/arp.rb +90 -90
  19. data/lib/packetfu/protos/arp/header.rb +158 -158
  20. data/lib/packetfu/protos/arp/mixin.rb +36 -36
  21. data/lib/packetfu/protos/eth.rb +44 -44
  22. data/lib/packetfu/protos/eth/header.rb +243 -243
  23. data/lib/packetfu/protos/eth/mixin.rb +3 -3
  24. data/lib/packetfu/protos/hsrp.rb +69 -69
  25. data/lib/packetfu/protos/hsrp/header.rb +107 -107
  26. data/lib/packetfu/protos/hsrp/mixin.rb +29 -29
  27. data/lib/packetfu/protos/icmp.rb +71 -71
  28. data/lib/packetfu/protos/icmp/header.rb +82 -82
  29. data/lib/packetfu/protos/icmp/mixin.rb +14 -14
  30. data/lib/packetfu/protos/invalid.rb +49 -49
  31. data/lib/packetfu/protos/ip.rb +69 -69
  32. data/lib/packetfu/protos/ip/header.rb +291 -291
  33. data/lib/packetfu/protos/ip/mixin.rb +40 -40
  34. data/lib/packetfu/protos/ipv6.rb +50 -50
  35. data/lib/packetfu/protos/ipv6/header.rb +188 -188
  36. data/lib/packetfu/protos/ipv6/mixin.rb +29 -29
  37. data/lib/packetfu/protos/tcp.rb +176 -176
  38. data/lib/packetfu/protos/tcp/ecn.rb +35 -35
  39. data/lib/packetfu/protos/tcp/flags.rb +74 -74
  40. data/lib/packetfu/protos/tcp/header.rb +268 -268
  41. data/lib/packetfu/protos/tcp/hlen.rb +32 -32
  42. data/lib/packetfu/protos/tcp/mixin.rb +46 -46
  43. data/lib/packetfu/protos/tcp/option.rb +321 -321
  44. data/lib/packetfu/protos/tcp/options.rb +95 -95
  45. data/lib/packetfu/protos/tcp/reserved.rb +35 -35
  46. data/lib/packetfu/protos/udp.rb +116 -116
  47. data/lib/packetfu/protos/udp/header.rb +91 -91
  48. data/lib/packetfu/protos/udp/mixin.rb +3 -3
  49. data/lib/packetfu/structfu.rb +280 -280
  50. data/lib/packetfu/utils.rb +226 -217
  51. data/lib/packetfu/version.rb +41 -41
  52. data/packetfu.gemspec +2 -1
  53. data/spec/ethpacket_spec.rb +48 -48
  54. data/spec/packet_spec.rb +57 -57
  55. data/spec/packet_subclasses_spec.rb +8 -8
  56. data/spec/packetfu_spec.rb +59 -59
  57. data/spec/structfu_spec.rb +268 -268
  58. data/spec/tcp_spec.rb +75 -75
  59. data/test/all_tests.rb +13 -13
  60. data/test/func_lldp.rb +3 -3
  61. data/test/ptest.rb +2 -2
  62. data/test/test_arp.rb +116 -116
  63. data/test/test_capture.rb +45 -45
  64. data/test/test_eth.rb +68 -68
  65. data/test/test_hsrp.rb +9 -9
  66. data/test/test_icmp.rb +52 -52
  67. data/test/test_inject.rb +18 -18
  68. data/test/test_invalid.rb +16 -16
  69. data/test/test_ip.rb +36 -36
  70. data/test/test_ip6.rb +48 -48
  71. data/test/test_octets.rb +21 -21
  72. data/test/test_packet.rb +154 -154
  73. data/test/test_pcap.rb +170 -170
  74. data/test/test_structfu.rb +97 -97
  75. data/test/test_tcp.rb +320 -320
  76. data/test/test_udp.rb +76 -76
  77. metadata +4 -3
@@ -1,224 +1,233 @@
1
1
  # -*- coding: binary -*-
2
2
  require 'singleton'
3
+ require 'timeout'
3
4
  module PacketFu
4
5
 
5
- # Utils is a collection of various and sundry network utilities that are useful for packet
6
- # manipulation.
7
- class Utils
8
-
9
- # Returns the MAC address of an IP address, or nil if it's not responsive to arp. Takes
10
- # a dotted-octect notation of the target IP address, as well as a number of parameters:
11
- #
12
- # === Parameters
13
- # :iface
14
- # Interface. Defaults to "eth0"
15
- # :eth_saddr
16
- # Source MAC address. Defaults to "00:00:00:00:00:00".
17
- # :ip_saddr
18
- # Source IP address. Defaults to "0.0.0.0"
19
- # :flavor
20
- # The flavor of the ARP request. Defaults to :none.
21
- # :timeout
22
- # Timeout in seconds. Defaults to 3.
23
- #
24
- # === Example
25
- # PacketFu::Utils::arp("192.168.1.1") #=> "00:18:39:01:33:70"
26
- # PacketFu::Utils::arp("192.168.1.1", :iface => "wlan2", :timeout => 5, :flavor => :hp_deskjet)
27
- #
28
- # === Warning
29
- #
30
- # It goes without saying, spewing forged ARP packets on your network is a great way to really
31
- # irritate your co-workers.
32
- def self.arp(target_ip,args={})
33
- iface = args[:iface] || :eth0
34
- args[:config] ||= whoami?(:iface => iface)
35
- arp_pkt = PacketFu::ARPPacket.new(:flavor => (args[:flavor] || :none), :config => args[:config])
36
- arp_pkt.eth_daddr = "ff:ff:ff:ff:ff:ff"
37
- arp_pkt.arp_daddr_mac = "00:00:00:00:00:00"
38
- arp_pkt.arp_daddr_ip = target_ip
39
- # Stick the Capture object in its own thread.
40
- cap_thread = Thread.new do
41
- target_mac = nil
42
- cap = PacketFu::Capture.new(:iface => iface, :start => true,
43
- :filter => "arp src #{target_ip} and ether dst #{arp_pkt.eth_saddr}")
44
- arp_pkt.to_w(iface) # Shorthand for sending single packets to the default interface.
45
- timeout = 0
46
- while target_mac.nil? && timeout <= (args[:timeout] || 3)
47
- if cap.save > 0
48
- arp_response = PacketFu::Packet.parse(cap.array[0])
49
- target_mac = arp_response.arp_saddr_mac if arp_response.arp_saddr_ip = target_ip
50
- end
51
- timeout += 0.1
52
- sleep 0.1 # Check for a response ten times per second.
53
- end
54
- target_mac
55
- end # cap_thread
56
- cap_thread.value
57
- end
58
-
59
- # Since 177/8 is IANA reserved (for now), this network should
60
- # be handled by your default gateway and default interface.
61
- def self.rand_routable_daddr
62
- IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET)
63
- end
64
-
65
- # Discovers the local IP and Ethernet address, which is useful for writing
66
- # packets you expect to get a response to. Note, this is a noisy
67
- # operation; a UDP packet is generated and dropped on to the default (or named)
68
- # interface, and then captured (which means you need to be root to do this).
69
- #
70
- # whoami? returns a hash of :eth_saddr, :eth_src, :ip_saddr, :ip_src,
71
- # :ip_src_bin, :eth_dst, and :eth_daddr (the last two are usually suitable
72
- # for a gateway mac address). It's most useful as an argument to
73
- # PacketFu::Config.new, or as an argument to the many Packet constructors.
74
- #
75
- # Note that if you have multiple interfaces with the same route (such as when
76
- # wlan0 and eth0 are associated to the same network), the "first" one
77
- # according to Pcap.lookupdev will be used, regardless of which :iface you
78
- # pick.
79
- #
80
- # === Parameters
81
- # :iface => "eth0"
82
- # An interface to listen for packets on. Note that since we rely on the OS to send the probe packet,
83
- # you will need to specify a target which will use this interface.
84
- # :target => "1.2.3.4"
85
- # A target IP address. By default, a packet will be sent to a random address in the 177/8 network.
86
- def self.whoami?(args={})
87
- unless args.kind_of? Hash
88
- raise ArgumentError, "Argument to `whoami?' must be a Hash"
89
- end
90
- if args[:iface].to_s =~ /^lo/ # Linux loopback more or less. Need a switch for windows loopback, too.
91
- dst_host = "127.0.0.1"
92
- else
93
- dst_host = (args[:target] || rand_routable_daddr.to_s)
94
- end
95
-
96
- dst_port = rand(0xffff-1024)+1024
97
- msg = "PacketFu whoami? packet #{(Time.now.to_i + rand(0xffffff)+1)}"
98
- iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || :lo ).to_s
99
- cap = PacketFu::Capture.new(:iface => iface, :promisc => false, :start => true, :filter => "udp and dst host #{dst_host} and dst port #{dst_port}")
100
- udp_sock = UDPSocket.new
101
- udp_sock.send(msg,0,dst_host,dst_port)
102
- udp_sock = nil
103
- cap.save
104
- pkt = Packet.parse(cap.array[0]) unless cap.save.zero?
105
- timeout = 0
106
- while timeout < 1 # Sometimes packet generation can be a little pokey.
107
- if pkt
108
- timeout = 1.1 # Cancel the timeout
109
- if pkt.payload == msg
110
- my_data = {
111
- :iface => (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s,
112
- :pcapfile => args[:pcapfile] || "/tmp/out.pcap",
113
- :eth_saddr => pkt.eth_saddr,
114
- :eth_src => pkt.eth_src.to_s,
115
- :ip_saddr => pkt.ip_saddr,
116
- :ip_src => pkt.ip_src,
117
- :ip_src_bin => [pkt.ip_src].pack("N"),
118
- :eth_dst => pkt.eth_dst.to_s,
119
- :eth_daddr => pkt.eth_daddr
120
- }
121
- else raise SecurityError,
122
- "whoami() packet doesn't match sent data. Something fishy's going on."
123
- end
124
- else
125
- sleep 0.1; timeout += 0.1
126
- cap.save
127
- pkt = Packet.parse(cap.array[0]) unless cap.save.zero?
128
- end
129
- raise SocketError, "Didn't receive the whoami() packet, can't automatically configure." if !pkt
130
- cap = nil
131
- end
132
- my_data
133
- end
134
-
135
- # This is a brute-force approach at trying to find a suitable interface with an IP address.
136
- def self.lookupdev
137
- # XXX cycle through eth0-9 and wlan0-9, and if a cap start throws a RuntimeErorr (and we're
138
- # root), it's not a good interface. Boy, really ought to fix lookupdev directly with another
139
- # method that returns an array rather than just the first candidate.
140
- end
141
-
142
- # Handles ifconfig for various (okay, two) platforms.
143
- # Will have Windows done shortly.
144
- #
145
- # Takes an argument (either string or symbol) of the interface to look up, and
146
- # returns a hash which contains at least the :iface element, and if configured,
147
- # these additional elements:
148
- #
149
- # :eth_saddr # A human readable MAC address
150
- # :eth_src # A packed MAC address
151
- # :ip_saddr # A dotted-quad string IPv4 address
152
- # :ip_src # A packed IPv4 address
153
- # :ip4_obj # An IPAddr object with bitmask
154
- # :ip6_saddr # A colon-delimited hex IPv6 address, with bitmask
155
- # :ip6_obj # An IPAddr object with bitmask
156
- #
157
- # === Example
158
- # PacketFu::Utils.ifconfig :wlan0 # Not associated yet
159
- # #=> {:eth_saddr=>"00:1d:e0:73:9d:ff", :eth_src=>"\000\035\340s\235\377", :iface=>"wlan0"}
160
- # PacketFu::Utils.ifconfig("eth0") # Takes 'eth0' as default
161
- # #=> {:eth_saddr=>"00:1c:23:35:70:3b", :eth_src=>"\000\034#5p;", :ip_saddr=>"10.10.10.9", :ip4_obj=>#<IPAddr: IPv4:10.10.10.0/255.255.254.0>, :ip_src=>"\n\n\n\t", :iface=>"eth0", :ip6_saddr=>"fe80::21c:23ff:fe35:703b/64", :ip6_obj=>#<IPAddr: IPv6:fe80:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:0000:0000:0000:0000>}
162
- # PacketFu::Utils.ifconfig :lo
163
- # #=> {:ip_saddr=>"127.0.0.1", :ip4_obj=>#<IPAddr: IPv4:127.0.0.0/255.0.0.0>, :ip_src=>"\177\000\000\001", :iface=>"lo", :ip6_saddr=>"::1/128", :ip6_obj=>#<IPAddr: IPv6:0000:0000:0000:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>}
164
- def self.ifconfig(iface='eth0')
165
- ret = {}
166
- iface = iface.to_s.scan(/[0-9A-Za-z]/).join # Sanitizing input, no spaces, semicolons, etc.
167
- case RUBY_PLATFORM
168
- when /linux/i
169
- ifconfig_data = %x[ifconfig #{iface}]
170
- if ifconfig_data =~ /#{iface}/i
171
- ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
172
- else
173
- raise ArgumentError, "Cannot ifconfig #{iface}"
174
- end
175
- real_iface = ifconfig_data.first
176
- ret[:iface] = real_iface.split.first.downcase
177
- if real_iface =~ /[\s]HWaddr[\s]+([0-9a-fA-F:]{17})/i
178
- ret[:eth_saddr] = $1.downcase
179
- ret[:eth_src] = EthHeader.mac2str(ret[:eth_saddr])
180
- end
181
- ifconfig_data.each do |s|
182
- case s
183
- when /inet addr:[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))?/i
184
- ret[:ip_saddr] = $1
185
- ret[:ip_src] = [IPAddr.new($1).to_i].pack("N")
186
- ret[:ip4_obj] = IPAddr.new($1)
187
- ret[:ip4_obj] = ret[:ip4_obj].mask($3) if $3
188
- when /inet6 addr:[\s]*([0-9a-fA-F:\x2f]+)/
189
- ret[:ip6_saddr] = $1
190
- ret[:ip6_obj] = IPAddr.new($1)
191
- end
192
- end # linux
193
- when /darwin/i
194
- ifconfig_data = %x[ifconfig #{iface}]
195
- if ifconfig_data =~ /#{iface}/i
196
- ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
197
- else
198
- raise ArgumentError, "Cannot ifconfig #{iface}"
199
- end
200
- real_iface = ifconfig_data.first
201
- ret[:iface] = real_iface.split(':')[0]
202
- ifconfig_data.each do |s|
203
- case s
204
- when /ether[\s]([0-9a-fA-F:]{17})/i
205
- ret[:eth_saddr] = $1
206
- ret[:eth_src] = EthHeader.mac2str(ret[:eth_saddr])
207
- when /inet[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))?/i
208
- ret[:ip_saddr] = $1
209
- ret[:ip_src] = [IPAddr.new($1).to_i].pack("N")
210
- ret[:ip4_obj] = IPAddr.new($1)
211
- ret[:ip4_obj] = ret[:ip4_obj].mask($3) if $3
212
- when /inet6[\s]*([0-9a-fA-F:\x2f]+)/
213
- ret[:ip6_saddr] = $1
214
- ret[:ip6_obj] = IPAddr.new($1)
215
- end
216
- end # darwin
217
- end # RUBY_PLATFORM
218
- ret
219
- end
220
-
221
- end
6
+ # Utils is a collection of various and sundry network utilities that are useful for packet
7
+ # manipulation.
8
+ class Utils
9
+
10
+ # Returns the MAC address of an IP address, or nil if it's not responsive to arp. Takes
11
+ # a dotted-octect notation of the target IP address, as well as a number of parameters:
12
+ #
13
+ # === Parameters
14
+ # :iface
15
+ # Interface. Defaults to "eth0"
16
+ # :eth_saddr
17
+ # Source MAC address. Defaults to "00:00:00:00:00:00".
18
+ # :ip_saddr
19
+ # Source IP address. Defaults to "0.0.0.0"
20
+ # :flavor
21
+ # The flavor of the ARP request. Defaults to :none.
22
+ # :timeout
23
+ # Timeout in seconds. Defaults to 3.
24
+ #
25
+ # === Example
26
+ # PacketFu::Utils::arp("192.168.1.1") #=> "00:18:39:01:33:70"
27
+ # PacketFu::Utils::arp("192.168.1.1", :iface => "wlan2", :timeout => 5, :flavor => :hp_deskjet)
28
+ #
29
+ # === Warning
30
+ #
31
+ # It goes without saying, spewing forged ARP packets on your network is a great way to really
32
+ # irritate your co-workers.
33
+ def self.arp(target_ip,args={})
34
+ iface = args[:iface] || :eth0
35
+ args[:config] ||= whoami?(:iface => iface)
36
+ arp_pkt = PacketFu::ARPPacket.new(:flavor => (args[:flavor] || :none), :config => args[:config])
37
+ arp_pkt.eth_daddr = "ff:ff:ff:ff:ff:ff"
38
+ arp_pkt.arp_daddr_mac = "00:00:00:00:00:00"
39
+ arp_pkt.arp_daddr_ip = target_ip
40
+ # Stick the Capture object in its own thread.
41
+ cap_thread = Thread.new do
42
+ target_mac = nil
43
+ cap = PacketFu::Capture.new(:iface => iface, :start => true,
44
+ :filter => "arp src #{target_ip} and ether dst #{arp_pkt.eth_saddr}")
45
+ arp_pkt.to_w(iface) # Shorthand for sending single packets to the default interface.
46
+ timeout = 0
47
+ while target_mac.nil? && timeout <= (args[:timeout] || 3)
48
+ if cap.save > 0
49
+ arp_response = PacketFu::Packet.parse(cap.array[0])
50
+ target_mac = arp_response.arp_saddr_mac if arp_response.arp_saddr_ip = target_ip
51
+ end
52
+ timeout += 0.1
53
+ sleep 0.1 # Check for a response ten times per second.
54
+ end
55
+ target_mac
56
+ end # cap_thread
57
+ cap_thread.value
58
+ end
59
+
60
+ # Since 177/8 is IANA reserved (for now), this network should
61
+ # be handled by your default gateway and default interface.
62
+ def self.rand_routable_daddr
63
+ IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET)
64
+ end
65
+
66
+ # Discovers the local IP and Ethernet address, which is useful for writing
67
+ # packets you expect to get a response to. Note, this is a noisy
68
+ # operation; a UDP packet is generated and dropped on to the default (or named)
69
+ # interface, and then captured (which means you need to be root to do this).
70
+ #
71
+ # whoami? returns a hash of :eth_saddr, :eth_src, :ip_saddr, :ip_src,
72
+ # :ip_src_bin, :eth_dst, and :eth_daddr (the last two are usually suitable
73
+ # for a gateway mac address). It's most useful as an argument to
74
+ # PacketFu::Config.new, or as an argument to the many Packet constructors.
75
+ #
76
+ # Note that if you have multiple interfaces with the same route (such as when
77
+ # wlan0 and eth0 are associated to the same network), the "first" one
78
+ # according to Pcap.lookupdev will be used, regardless of which :iface you
79
+ # pick.
80
+ #
81
+ # === Parameters
82
+ # :iface => "eth0"
83
+ # An interface to listen for packets on. Note that since we rely on the OS to send the probe packet,
84
+ # you will need to specify a target which will use this interface.
85
+ # :target => "1.2.3.4"
86
+ # A target IP address. By default, a packet will be sent to a random address in the 177/8 network.
87
+ def self.whoami?(args={})
88
+ unless args.kind_of? Hash
89
+ raise ArgumentError, "Argument to `whoami?' must be a Hash"
90
+ end
91
+ if args[:iface].to_s =~ /^lo/ # Linux loopback more or less. Need a switch for windows loopback, too.
92
+ dst_host = "127.0.0.1"
93
+ else
94
+ dst_host = (args[:target] || rand_routable_daddr.to_s)
95
+ end
96
+
97
+ dst_port = rand(0xffff-1024)+1024
98
+ msg = "PacketFu whoami? packet #{(Time.now.to_i + rand(0xffffff)+1)}"
99
+ iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || :lo ).to_s
100
+ cap = PacketFu::Capture.new(:iface => iface, :promisc => false, :start => true, :filter => "udp and dst host #{dst_host} and dst port #{dst_port}")
101
+ udp_sock = UDPSocket.new
102
+ udp_sock.send(msg,0,dst_host,dst_port)
103
+ udp_sock = nil
104
+
105
+ my_data = nil
106
+
107
+ begin
108
+ Timeout::timeout(1) {
109
+ pkt = nil
110
+
111
+ while pkt.nil?
112
+ raw_pkt = cap.next
113
+ next if raw_pkt.nil?
114
+
115
+ pkt = Packet.parse(raw_pkt)
116
+
117
+ if pkt.payload == msg
118
+
119
+ my_data = {
120
+ :iface => (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s,
121
+ :pcapfile => args[:pcapfile] || "/tmp/out.pcap",
122
+ :eth_saddr => pkt.eth_saddr,
123
+ :eth_src => pkt.eth_src.to_s,
124
+ :ip_saddr => pkt.ip_saddr,
125
+ :ip_src => pkt.ip_src,
126
+ :ip_src_bin => [pkt.ip_src].pack("N"),
127
+ :eth_dst => pkt.eth_dst.to_s,
128
+ :eth_daddr => pkt.eth_daddr
129
+ }
130
+
131
+ else raise SecurityError,
132
+ "whoami() packet doesn't match sent data. Something fishy's going on."
133
+ end
134
+
135
+ end
136
+ }
137
+ rescue Timeout::Error
138
+ raise SocketError, "Didn't receive the whoami() packet, can't automatically configure."
139
+ end
140
+
141
+ my_data
142
+ end
143
+
144
+ # This is a brute-force approach at trying to find a suitable interface with an IP address.
145
+ def self.lookupdev
146
+ # XXX cycle through eth0-9 and wlan0-9, and if a cap start throws a RuntimeErorr (and we're
147
+ # root), it's not a good interface. Boy, really ought to fix lookupdev directly with another
148
+ # method that returns an array rather than just the first candidate.
149
+ end
150
+
151
+ # Handles ifconfig for various (okay, two) platforms.
152
+ # Will have Windows done shortly.
153
+ #
154
+ # Takes an argument (either string or symbol) of the interface to look up, and
155
+ # returns a hash which contains at least the :iface element, and if configured,
156
+ # these additional elements:
157
+ #
158
+ # :eth_saddr # A human readable MAC address
159
+ # :eth_src # A packed MAC address
160
+ # :ip_saddr # A dotted-quad string IPv4 address
161
+ # :ip_src # A packed IPv4 address
162
+ # :ip4_obj # An IPAddr object with bitmask
163
+ # :ip6_saddr # A colon-delimited hex IPv6 address, with bitmask
164
+ # :ip6_obj # An IPAddr object with bitmask
165
+ #
166
+ # === Example
167
+ # PacketFu::Utils.ifconfig :wlan0 # Not associated yet
168
+ # #=> {:eth_saddr=>"00:1d:e0:73:9d:ff", :eth_src=>"\000\035\340s\235\377", :iface=>"wlan0"}
169
+ # PacketFu::Utils.ifconfig("eth0") # Takes 'eth0' as default
170
+ # #=> {:eth_saddr=>"00:1c:23:35:70:3b", :eth_src=>"\000\034#5p;", :ip_saddr=>"10.10.10.9", :ip4_obj=>#<IPAddr: IPv4:10.10.10.0/255.255.254.0>, :ip_src=>"\n\n\n\t", :iface=>"eth0", :ip6_saddr=>"fe80::21c:23ff:fe35:703b/64", :ip6_obj=>#<IPAddr: IPv6:fe80:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:0000:0000:0000:0000>}
171
+ # PacketFu::Utils.ifconfig :lo
172
+ # #=> {:ip_saddr=>"127.0.0.1", :ip4_obj=>#<IPAddr: IPv4:127.0.0.0/255.0.0.0>, :ip_src=>"\177\000\000\001", :iface=>"lo", :ip6_saddr=>"::1/128", :ip6_obj=>#<IPAddr: IPv6:0000:0000:0000:0000:0000:0000:0000:0001/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>}
173
+ def self.ifconfig(iface='eth0')
174
+ ret = {}
175
+ iface = iface.to_s.scan(/[0-9A-Za-z]/).join # Sanitizing input, no spaces, semicolons, etc.
176
+ case RUBY_PLATFORM
177
+ when /linux/i
178
+ ifconfig_data = %x[ifconfig #{iface}]
179
+ if ifconfig_data =~ /#{iface}/i
180
+ ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
181
+ else
182
+ raise ArgumentError, "Cannot ifconfig #{iface}"
183
+ end
184
+ real_iface = ifconfig_data.first
185
+ ret[:iface] = real_iface.split.first.downcase
186
+ if real_iface =~ /[\s]HWaddr[\s]+([0-9a-fA-F:]{17})/i
187
+ ret[:eth_saddr] = $1.downcase
188
+ ret[:eth_src] = EthHeader.mac2str(ret[:eth_saddr])
189
+ end
190
+ ifconfig_data.each do |s|
191
+ case s
192
+ when /inet addr:[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))?/i
193
+ ret[:ip_saddr] = $1
194
+ ret[:ip_src] = [IPAddr.new($1).to_i].pack("N")
195
+ ret[:ip4_obj] = IPAddr.new($1)
196
+ ret[:ip4_obj] = ret[:ip4_obj].mask($3) if $3
197
+ when /inet6 addr:[\s]*([0-9a-fA-F:\x2f]+)/
198
+ ret[:ip6_saddr] = $1
199
+ ret[:ip6_obj] = IPAddr.new($1)
200
+ end
201
+ end # linux
202
+ when /darwin/i
203
+ ifconfig_data = %x[ifconfig #{iface}]
204
+ if ifconfig_data =~ /#{iface}/i
205
+ ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
206
+ else
207
+ raise ArgumentError, "Cannot ifconfig #{iface}"
208
+ end
209
+ real_iface = ifconfig_data.first
210
+ ret[:iface] = real_iface.split(':')[0]
211
+ ifconfig_data.each do |s|
212
+ case s
213
+ when /ether[\s]([0-9a-fA-F:]{17})/i
214
+ ret[:eth_saddr] = $1
215
+ ret[:eth_src] = EthHeader.mac2str(ret[:eth_saddr])
216
+ when /inet[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))?/i
217
+ ret[:ip_saddr] = $1
218
+ ret[:ip_src] = [IPAddr.new($1).to_i].pack("N")
219
+ ret[:ip4_obj] = IPAddr.new($1)
220
+ ret[:ip4_obj] = ret[:ip4_obj].mask($3) if $3
221
+ when /inet6[\s]*([0-9a-fA-F:\x2f]+)/
222
+ ret[:ip6_saddr] = $1
223
+ ret[:ip6_obj] = IPAddr.new($1)
224
+ end
225
+ end # darwin
226
+ end # RUBY_PLATFORM
227
+ ret
228
+ end
229
+
230
+ end
222
231
 
223
232
  end
224
233
 
@@ -1,51 +1,51 @@
1
1
  # -*- coding: binary -*-
2
2
  module PacketFu
3
3
 
4
- # Check the repo's for version release histories
5
- VERSION = "1.1.9"
4
+ # Check the repo's for version release histories
5
+ VERSION = "1.1.10"
6
6
 
7
- # Returns PacketFu::VERSION
8
- def self.version
9
- VERSION
10
- end
7
+ # Returns PacketFu::VERSION
8
+ def self.version
9
+ VERSION
10
+ end
11
11
 
12
- # Returns a version string in a binary format for easy comparisons.
13
- def self.binarize_version(str)
14
- if(str.respond_to?(:split) && str =~ /^[0-9]+(\.([0-9]+)(\.[0-9]+)?)?\..+$/)
15
- bin_major,bin_minor,bin_teeny = str.split(/\x2e/).map {|x| x.to_i}
16
- bin_version = (bin_major.to_i << 16) + (bin_minor.to_i << 8) + bin_teeny.to_i
17
- else
18
- raise ArgumentError, "Compare version malformed. Should be \x22x.y.z\x22"
19
- end
20
- end
12
+ # Returns a version string in a binary format for easy comparisons.
13
+ def self.binarize_version(str)
14
+ if(str.respond_to?(:split) && str =~ /^[0-9]+(\.([0-9]+)(\.[0-9]+)?)?\..+$/)
15
+ bin_major,bin_minor,bin_teeny = str.split(/\x2e/).map {|x| x.to_i}
16
+ bin_version = (bin_major.to_i << 16) + (bin_minor.to_i << 8) + bin_teeny.to_i
17
+ else
18
+ raise ArgumentError, "Compare version malformed. Should be \x22x.y.z\x22"
19
+ end
20
+ end
21
21
 
22
- # Returns true if the version is equal to or greater than the compare version.
23
- # If the current version of PacketFu is "0.3.1" for example:
24
- #
25
- # PacketFu.at_least? "0" # => true
26
- # PacketFu.at_least? "0.2.9" # => true
27
- # PacketFu.at_least? "0.3" # => true
28
- # PacketFu.at_least? "1" # => true after 1.0's release
29
- # PacketFu.at_least? "1.12" # => false
30
- # PacketFu.at_least? "2" # => false
31
- def self.at_least?(str)
32
- this_version = binarize_version(self.version)
33
- ask_version = binarize_version(str)
34
- this_version >= ask_version
35
- end
22
+ # Returns true if the version is equal to or greater than the compare version.
23
+ # If the current version of PacketFu is "0.3.1" for example:
24
+ #
25
+ # PacketFu.at_least? "0" # => true
26
+ # PacketFu.at_least? "0.2.9" # => true
27
+ # PacketFu.at_least? "0.3" # => true
28
+ # PacketFu.at_least? "1" # => true after 1.0's release
29
+ # PacketFu.at_least? "1.12" # => false
30
+ # PacketFu.at_least? "2" # => false
31
+ def self.at_least?(str)
32
+ this_version = binarize_version(self.version)
33
+ ask_version = binarize_version(str)
34
+ this_version >= ask_version
35
+ end
36
36
 
37
- # Returns true if the current version is older than the compare version.
38
- def self.older_than?(str)
39
- return false if str == self.version
40
- this_version = binarize_version(self.version)
41
- ask_version = binarize_version(str)
42
- this_version < ask_version
43
- end
37
+ # Returns true if the current version is older than the compare version.
38
+ def self.older_than?(str)
39
+ return false if str == self.version
40
+ this_version = binarize_version(self.version)
41
+ ask_version = binarize_version(str)
42
+ this_version < ask_version
43
+ end
44
44
 
45
- # Returns true if the current version is newer than the compare version.
46
- def self.newer_than?(str)
47
- return false if str == self.version
48
- !self.older_than?(str)
49
- end
45
+ # Returns true if the current version is newer than the compare version.
46
+ def self.newer_than?(str)
47
+ return false if str == self.version
48
+ !self.older_than?(str)
49
+ end
50
50
 
51
51
  end