packetfu 1.1.8 → 1.1.9

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