packetfu 1.0.5.pre → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Used mainly to test for memory leaks and to demo the preferred ways of
4
+ # reading and writing packets to and from pcap files.
5
+ require './examples' # For path setting slight-of-hand
6
+ require 'packetfu'
7
+
8
+ include PacketFu
9
+ puts "Generating packets... (#{Time.now.utc})"
10
+
11
+ File.unlink("/tmp/out.pcap") if File.exists? "/tmp/out.pcap"
12
+ start_time = Time.now.utc
13
+ count = 0
14
+
15
+ 100.times do
16
+ @pcaps = []
17
+ 1000.times do
18
+ u = UDPPacket.new
19
+ u.ip_src = [rand(2**32-1)].pack("N")
20
+ u.ip_dst = [rand(2**32-1)].pack("N")
21
+ u.recalc
22
+ @pcaps << u
23
+ end
24
+ pfile = PcapFile.new
25
+ res = pfile.array_to_file(:filename => "/tmp/out.pcap", :array => @pcaps, :append => true)
26
+ count += res.last
27
+ puts "Wrote #{count} packets in #{Time.now.utc - start_time} seconds"
28
+ end
29
+
30
+ read_bytes_start = Time.now.utc
31
+ puts "Reading packet bytes..."
32
+ packet_bytes = PcapFile.read_packet_bytes "/tmp/out.pcap"
33
+ puts "Read #{packet_bytes.size} packet byte blobs in #{Time.now.utc - read_bytes_start} seconds."
34
+
35
+ read_packets_start = Time.now.utc
36
+ puts "Reading packets..."
37
+ packet_bytes = PcapFile.read_packets "/tmp/out.pcap"
38
+ puts "Read #{packet_bytes.size} parsed packets in #{Time.now.utc - read_packets_start} seconds."
39
+
40
+
41
+
data/examples/ackscan.rb CHANGED
File without changes
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ require 'examples'
3
+ require 'packetfu'
4
+
5
+ puts "Simple sniffer for PacketFu #{PacketFu.version}"
6
+ include PacketFu
7
+ iface = ARGV[0] || "eth0"
8
+
9
+ def sniff(iface)
10
+ cap = Capture.new(:iface => iface, :start => true)
11
+ cap.stream.each do |p|
12
+ pkt = Packet.parse p
13
+ if pkt.is_ip?
14
+ next if pkt.ip_saddr == Utils.ifconfig[:ip_saddr]
15
+ packet_info = [pkt.ip_saddr, pkt.ip_daddr, pkt.size, pkt.proto.last]
16
+ puts "%-15s -> %-15s %-4d %s" % packet_info
17
+ end
18
+ end
19
+ end
20
+
21
+ sniff(iface)
22
+
23
+ =begin
24
+ Results look like this:
25
+ 145.58.33.95 -> 192.168.11.70 1514 TCP
26
+ 212.233.158.76 -> 192.168.11.70 110 UDP
27
+ 88.174.164.147 -> 192.168.11.70 110 UDP
28
+ 145.58.33.95 -> 192.168.11.70 1514 TCP
29
+ 145.58.33.95 -> 192.168.11.70 1514 TCP
30
+ 145.58.33.95 -> 192.168.11.70 1514 TCP
31
+ 145.58.33.95 -> 192.168.11.70 1514 TCP
32
+ 8.8.8.8 -> 192.168.11.70 143 UDP
33
+ 41.237.73.186 -> 192.168.11.70 60 TCP
34
+ 145.58.33.95 -> 192.168.11.70 1514 TCP
35
+ 145.58.33.95 -> 192.168.11.70 1514 TCP
36
+ 8.8.8.8 -> 192.168.11.70 143 UDP
37
+ 8.8.8.8 -> 192.168.11.70 128 UDP
38
+ 8.8.8.8 -> 192.168.11.70 187 UDP
39
+ 24.45.247.232 -> 192.168.11.70 70 TCP
40
+ =end
data/lib/packetfu.rb CHANGED
@@ -25,6 +25,11 @@ module PacketFu
25
25
  end
26
26
  end
27
27
 
28
+ # Deal with Ruby's encoding by ignoring it.
29
+ def self.force_binary(str)
30
+ str.force_encoding "binary" if str.respond_to? :force_encoding
31
+ end
32
+
28
33
  # Sets the expected byte order for a pcap file. See PacketFu::Read.set_byte_order
29
34
  @byte_order = :little
30
35
 
@@ -93,6 +98,43 @@ module PacketFu
93
98
  @packet_classes.map {|p| p.to_s.split("::").last.to_s.downcase.gsub(/packet$/,"")}
94
99
  end
95
100
 
101
+ # The current inspect style. One of :hex, :dissect, or :default
102
+ # Note that :default means Ruby's default, which is usually
103
+ # far too long to be useful.
104
+ def self.inspect_style
105
+ @inspect_style ||= :dissect
106
+ end
107
+
108
+ # Setter for PacketFu's @inspect_style
109
+ def self.inspect_style=(arg)
110
+ @inspect_style = case arg
111
+ when :hex, :pretty
112
+ :hex
113
+ when :dissect, :verbose
114
+ :dissect
115
+ when :default, :ugly
116
+ :default
117
+ else
118
+ :dissect
119
+ end
120
+ end
121
+
122
+ # Switches inspect styles in a round-robin fashion between
123
+ # :dissect, :default, and :hex
124
+ def toggle_inspect
125
+ case @inspect_style
126
+ when :hex, :pretty
127
+ @inspect_style = :dissect
128
+ when :dissect, :verbose
129
+ @inspect_style = :default
130
+ when :default, :ugly
131
+ @inspect_style = :hex
132
+ else
133
+ @inspect_style = :dissect
134
+ end
135
+ end
136
+
137
+
96
138
  end
97
139
 
98
140
  require File.join(cwd,"packetfu","version")
@@ -31,7 +31,7 @@ module PacketFu
31
31
  def initialize(args={})
32
32
  @array = [] # Where the packet array goes.
33
33
  @stream = [] # Where the stream goes.
34
- @iface = args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo"
34
+ @iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s
35
35
  @snaplen = args[:snaplen] || 0xffff
36
36
  @promisc = args[:promisc] || false # Sensible for some Intel wifi cards
37
37
  @timeout = args[:timeout] || 1
@@ -36,17 +36,20 @@ module PacketFu
36
36
  @iface = args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo"
37
37
  end
38
38
  @pcapfile = "/tmp/out.pcap"
39
- args.each_pair { |k,v| self.instance_variable_set(("@" + k.to_s).intern,v) }
39
+ args.each_pair { |k,v| self.instance_variable_set(("@#{k}"),v) }
40
40
  end
41
41
 
42
42
  # Returns all instance variables as a hash (including custom variables set at initialization).
43
43
  def config(arg=nil)
44
- if arg.nil?
44
+ if arg
45
+ arg.each_pair {|k,v| self.instance_variable_set(("@" + k.to_s).intern, v)}
46
+ else
45
47
  config_hash = {}
46
- self.instance_variables.each { |v| config_hash[v.delete("@").intern] = self.instance_variable_get(v) }
48
+ self.instance_variables.each do |v|
49
+ key = v.to_s.gsub(/^@/,"").to_sym
50
+ config_hash[key] = self.instance_variable_get(v)
51
+ end
47
52
  config_hash
48
- else
49
- arg.each_pair {|k,v| self.instance_variable_set(("@" + k.to_s).intern, v)}
50
53
  end
51
54
  end
52
55
 
@@ -102,7 +102,7 @@ module PacketFu
102
102
  # Put the entire packet on the wire by creating a temporary PacketFu::Inject object.
103
103
  # TODO: Do something with auto-checksumming?
104
104
  def to_w(iface=nil)
105
- iface = iface || self.iface || PacketFu::Config.new.config[:iface]
105
+ iface = (iface || self.iface || PacketFu::Config.new.config[:iface]).to_s
106
106
  inj = PacketFu::Inject.new(:iface => iface)
107
107
  inj.array = [@headers[0].to_s]
108
108
  inj.inject
@@ -467,11 +467,7 @@ module PacketFu
467
467
  if self.class.name =~ /(::|^)PacketFu::Packet$/
468
468
  raise NoMethodError, "method `new' called for abstract class #{self.class.name}"
469
469
  end
470
- if args[:inspect_style]
471
- @inspect_style = args[:inspect_style]
472
- else
473
- @inspect_style = :dissect
474
- end
470
+ @inspect_style = args[:inspect_style] || PacketFu.inspect_style || :dissect
475
471
  if args[:config]
476
472
  args[:config].each_pair do |k,v|
477
473
  case k
@@ -484,6 +480,13 @@ module PacketFu
484
480
  end
485
481
  end
486
482
 
483
+ # Delegate to PacketFu's inspect_style, since the
484
+ # class variable name is the same. Yay for namespace
485
+ # pollution!
486
+ def inspect_style=()
487
+ PacketFu.inspect_style(arg)
488
+ end
489
+
487
490
  #method_missing() delegates protocol-specific field actions to the apporpraite
488
491
  #class variable (which contains the associated packet type)
489
492
  #This register-of-protocols style switch will work for the
@@ -525,21 +528,6 @@ module PacketFu
525
528
  end
526
529
 
527
530
  end # class Packet
528
-
529
- # Switches inspect styles between :dissect, :default, and :hex
530
- def toggle_inspect
531
- case @inspect_style
532
- when :hex, :pretty
533
- @inspect_style = :dissect
534
- when :dissect, :verbose
535
- @inspect_style = :default
536
- when :default, :ugly
537
- @inspect_style = :hex
538
- else
539
- @inspect_style = :dissect
540
- end
541
- end
542
-
543
531
  end
544
532
 
545
533
  # vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
data/lib/packetfu/pcap.rb CHANGED
@@ -246,34 +246,32 @@ module PacketFu
246
246
 
247
247
  # Takes a given file name, and reads out the packets. If given a block,
248
248
  # it will yield back a PcapPacket object per packet found.
249
- def read(fname,&block)
249
+ def read(fname,&block)
250
+ file_header = PcapHeader.new
251
+ pcap_packets = PcapPackets.new
252
+ unless File.readable? fname
253
+ raise ArgumentError, "Cannot read file `#{fname}'"
254
+ end
250
255
  begin
251
- file_handle = File.open(fname, "rb")
252
- pcap_packets = PcapPackets.new unless block
253
- file_header = PcapHeader.new
254
- file_header.read file_handle.read(24)
255
- packet_count = 0
256
- pcap_packet = PcapPacket.new(:endian => file_header.endian)
257
- while pcap_packet.read file_handle.read(16) do
258
- len = pcap_packet.incl_len
259
- pcap_packet.data = StructFu::String.new.read(file_handle.read(len.to_i))
260
- packet_count += 1
261
- if pcap_packet.data.size < len.to_i
262
- warn "Packet ##{packet_count} is corrupted: expected #{len.to_i}, got #{pcap_packet.data.size}. Exiting."
263
- break
264
- end
265
- if block
266
- yield pcap_packet
267
- else
268
- pcap_packets << pcap_packet
269
- end
270
- end
271
- unless block
272
- return pcap_packets
256
+ file_handle = File.open(fname, "rb")
257
+ file_header.read file_handle.read(24)
258
+ packet_count = 0
259
+ pcap_packet = PcapPacket.new(:endian => file_header.endian)
260
+ while pcap_packet.read file_handle.read(16) do
261
+ len = pcap_packet.incl_len
262
+ pcap_packet.data = StructFu::String.new.read(file_handle.read(len.to_i))
263
+ packet_count += 1
264
+ if pcap_packet.data.size < len.to_i
265
+ warn "Packet ##{packet_count} is corrupted: expected #{len.to_i}, got #{pcap_packet.data.size}. Exiting."
266
+ break
273
267
  end
268
+ pcap_packets << pcap_packet.clone
269
+ yield pcap_packets.last if block
270
+ end
274
271
  ensure
275
272
  file_handle.close
276
273
  end
274
+ block ? packet_count : pcap_packets
277
275
  end
278
276
 
279
277
  # Takes a filename, and an optional block. If a block is given,
@@ -453,7 +451,11 @@ module PacketFu
453
451
  end
454
452
  append = args[:append]
455
453
  if append
456
- File.open(filename,'ab') {|file| file.write(self.body.to_s)}
454
+ if File.exists? filename
455
+ File.open(filename,'ab') {|file| file.write(self.body.to_s)}
456
+ else
457
+ File.open(filename,'wb') {|file| file.write(self.to_s)}
458
+ end
457
459
  else
458
460
  File.open(filename,'wb') {|file| file.write(self.to_s)}
459
461
  end
@@ -26,14 +26,17 @@ module PacketFu
26
26
  include StructFu
27
27
 
28
28
  def initialize(args={})
29
+ src_mac = args[:arp_src_mac] || (args[:config][:eth_src] if args[:config])
30
+ src_ip_bin = args[:arp_src_ip] || (args[:config][:ip_src_bin] if args[:config])
31
+
29
32
  super(
30
33
  Int16.new(args[:arp_hw] || 1),
31
34
  Int16.new(args[:arp_proto] ||0x0800),
32
35
  Int8.new(args[:arp_hw_len] || 6),
33
36
  Int8.new(args[:arp_proto_len] || 4),
34
37
  Int16.new(args[:arp_opcode] || 1),
35
- EthMac.new.read(args[:arp_src_mac]),
36
- Octets.new.read(args[:arp_src_ip]),
38
+ EthMac.new.read(src_mac),
39
+ Octets.new.read(src_ip_bin),
37
40
  EthMac.new.read(args[:arp_dst_mac]),
38
41
  Octets.new.read(args[:arp_dst_ip]),
39
42
  StructFu::String.new.read(args[:body])
@@ -132,6 +132,12 @@ module PacketFu
132
132
  # For more on the construction on MAC addresses, see
133
133
  # http://en.wikipedia.org/wiki/MAC_address
134
134
  #
135
+ # TODO: Need to come up with a good way of dealing with vlan
136
+ # tagging. Having a usually empty struct member seems weird,
137
+ # but there may not be another way to do it if I want to preserve
138
+ # the Eth-ness of vlan-tagged 802.1Q packets. Also, may as well
139
+ # deal with 0x88a8 as well (http://en.wikipedia.org/wiki/802.1ad)
140
+ #
135
141
  # ==== Header Definition
136
142
  #
137
143
  # EthMac :eth_dst # See EthMac
@@ -251,11 +257,17 @@ module PacketFu
251
257
  # eth_pkt.eth_daddr="00:1c:24:aa:bb:cc"
252
258
  #
253
259
  # eth_pkt.to_w('eth0') # Inject on the wire. (require root)
260
+ #
254
261
  class EthPacket < Packet
255
262
  attr_accessor :eth_header
256
263
 
257
264
  def self.can_parse?(str)
258
- str.size >= 14
265
+ # XXX Temporary fix. Need to extend the EthHeader class to handle more.
266
+ valid_eth_types = [0x0800, 0x0806, 0x86dd]
267
+ return false unless str.size >= 14
268
+ type = str[12,2].unpack("n").first rescue nil
269
+ return false unless valid_eth_types.include? type
270
+ true
259
271
  end
260
272
 
261
273
  def read(str=nil,args={})
@@ -1,9 +1,10 @@
1
1
  module PacketFu
2
2
 
3
- # ICMPHeader is a complete ICMP struct, used in ICMPPacket. ICMP is typically used for network
4
- # administration and connectivity testing.
3
+ # ICMPHeader is a complete ICMP struct, used in ICMPPacket. ICMP is
4
+ # typically used for network administration and connectivity testing.
5
5
  #
6
- # For more on ICMP packets, see http://www.networksorcery.com/enp/protocol/icmp.htm
6
+ # For more on ICMP packets, see
7
+ # http://www.networksorcery.com/enp/protocol/icmp.htm
7
8
  #
8
9
  # ==== Header Definition
9
10
  #
@@ -162,11 +162,29 @@ module PacketFu
162
162
  # Getter for the checksum.
163
163
  def ip_sum; self[:ip_sum].to_i; end
164
164
  # Setter for the source IP address.
165
- def ip_src=(i); typecast i; end
165
+ def ip_src=(i)
166
+ case i
167
+ when Numeric
168
+ self[:ip_src] = Octets.new.read([i].pack("N"))
169
+ when Octets
170
+ self[:ip_src] = i
171
+ else
172
+ typecast i
173
+ end
174
+ end
166
175
  # Getter for the source IP address.
167
176
  def ip_src; self[:ip_src].to_i; end
168
177
  # Setter for the destination IP address.
169
- def ip_dst=(i); typecast i; end
178
+ def ip_dst=(i)
179
+ case i
180
+ when Numeric
181
+ self[:ip_dst] = Octets.new.read([i].pack("N"))
182
+ when Octets
183
+ self[:ip_dst] = i
184
+ else
185
+ typecast i
186
+ end
187
+ end
170
188
  # Getter for the destination IP address.
171
189
  def ip_dst; self[:ip_dst].to_i; end
172
190
 
@@ -546,14 +546,10 @@ module PacketFu
546
546
  opts
547
547
  end
548
548
 
549
- def force_binary(str)
550
- str.force_encoding "binary" if str.respond_to? :force_encoding
551
- end
552
-
553
549
  # Reads a string to populate the object.
554
550
  def read(str)
555
- self.clear if self.size > 0
556
- force_binary(str)
551
+ self.clear
552
+ PacketFu.force_binary(str)
557
553
  return self if(!str.respond_to? :to_s || str.nil?)
558
554
  i = 0
559
555
  while i < str.to_s.size
@@ -33,9 +33,13 @@ module StructFu
33
33
  end
34
34
  end
35
35
 
36
- # Handle deep copies correctly
36
+ # Handle deep copies correctly. Marshal in 1.9, re-read myself on 1.8
37
37
  def clone
38
- Marshal.load(Marshal.dump(self))
38
+ begin
39
+ Marshal.load(Marshal.dump(self))
40
+ rescue
41
+ self.class.new.read(self.to_s)
42
+ end
39
43
  end
40
44
 
41
45
  # Ints all have a value, an endianness, and a default value.
@@ -282,7 +286,7 @@ class Struct
282
286
  # Monkeypatch for Struct to include some string safety -- anything that uses
283
287
  # Struct is going to presume binary strings anyway.
284
288
  def force_binary(str)
285
- str.force_encoding "binary" if str.respond_to? :force_encoding
289
+ PacketFu.force_binary(str)
286
290
  end
287
291
 
288
292
  end
@@ -27,13 +27,12 @@ module PacketFu
27
27
  # It goes without saying, spewing forged ARP packets on your network is a great way to really
28
28
  # irritate your co-workers.
29
29
  def self.arp(target_ip,args={})
30
- arp_pkt = PacketFu::ARPPacket.new(:flavor => (args[:flavor] || :none))
31
- arp_pkt.eth_saddr = arp_pkt.arp_saddr_mac = (args[:eth_saddr] || ($packetfu_default.config[:eth_saddr] if $packetfu_default) || "00:00:00:00:00:00" )
30
+ iface = args[:iface] || :eth0
31
+ args[:config] ||= whoami?(:iface => iface)
32
+ arp_pkt = PacketFu::ARPPacket.new(:flavor => (args[:flavor] || :none), :config => args[:config])
32
33
  arp_pkt.eth_daddr = "ff:ff:ff:ff:ff:ff"
33
34
  arp_pkt.arp_daddr_mac = "00:00:00:00:00:00"
34
- arp_pkt.arp_saddr_ip = (args[:ip_saddr] || ($packetfu_default.config[:ip_saddr] if $packetfu_default) || "0.0.0.0")
35
- arp_pkt.arp_daddr_ip = target_ip
36
- iface = (args[:iface] || ($packetfu_default.iface if $packetfu_default) || "eth0")
35
+ arp_pkt.arp_daddr_ip = target_ip
37
36
  # Stick the Capture object in its own thread.
38
37
  cap_thread = Thread.new do
39
38
  target_mac = nil
@@ -59,9 +58,15 @@ module PacketFu
59
58
  # operation; a UDP packet is generated and dropped on to the default (or named)
60
59
  # interface, and then captured (which means you need to be root to do this).
61
60
  #
62
- # whoami? returns a hash of :eth_saddr, :eth_src, :ip_saddr, :ip_src,
63
- # :eth_dst, and :eth_daddr (the last two are usually suitable for a
64
- # gateway mac address). It's most useful as an argument to PacketFu::Config.new.
61
+ # whoami? returns a hash of :eth_saddr, :eth_src, :ip_saddr, :ip_src,
62
+ # :ip_src_bin, :eth_dst, and :eth_daddr (the last two are usually suitable
63
+ # for a gateway mac address). It's most useful as an argument to
64
+ # PacketFu::Config.new, or as an argument to the many Packet constructors.
65
+ #
66
+ # Note that if you have multiple interfaces with the same route (such as when
67
+ # wlan0 and eth0 are associated to the same network), the "first" one
68
+ # according to Pcap.lookupdev will be used, regardless of which :iface you
69
+ # pick.
65
70
  #
66
71
  # === Parameters
67
72
  # :iface => "eth0"
@@ -72,7 +77,10 @@ module PacketFu
72
77
  # Since this network is IANA reserved (for now), this network should be handled by your default gateway
73
78
  # and default interface.
74
79
  def self.whoami?(args={})
75
- if args[:iface] =~ /^lo/ # Linux loopback more or less. Need a switch for windows loopback, too.
80
+ unless args.kind_of? Hash
81
+ raise ArgumentError, "Argument to `whoami?' must be a Hash"
82
+ end
83
+ if args[:iface].to_s =~ /^lo/ # Linux loopback more or less. Need a switch for windows loopback, too.
76
84
  dst_host = "127.0.0.1"
77
85
  else
78
86
  dst_host = (args[:target] || IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET).to_s)
@@ -80,8 +88,11 @@ module PacketFu
80
88
 
81
89
  dst_port = rand(0xffff-1024)+1024
82
90
  msg = "PacketFu whoami? packet #{(Time.now.to_i + rand(0xffffff)+1)}"
83
- cap = PacketFu::Capture.new(:iface => (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo" ), :start => true, :filter => "udp and dst host #{dst_host} and dst port #{dst_port}")
84
- UDPSocket.open.send(msg,0,dst_host,dst_port)
91
+ iface = (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || :lo ).to_s
92
+ cap = PacketFu::Capture.new(:iface => iface, :promisc => false, :start => true, :filter => "udp and dst host #{dst_host} and dst port #{dst_port}")
93
+ udp_sock = UDPSocket.new
94
+ udp_sock.send(msg,0,dst_host,dst_port)
95
+ udp_sock = nil
85
96
  cap.save
86
97
  pkt = Packet.parse(cap.array[0]) unless cap.save.zero?
87
98
  timeout = 0
@@ -90,12 +101,13 @@ module PacketFu
90
101
  timeout = 1.1 # Cancel the timeout
91
102
  if pkt.payload == msg
92
103
  my_data = {
93
- :iface => args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo",
104
+ :iface => (args[:iface] || ENV['IFACE'] || Pcap.lookupdev || "lo").to_s,
94
105
  :pcapfile => args[:pcapfile] || "/tmp/out.pcap",
95
106
  :eth_saddr => pkt.eth_saddr,
96
107
  :eth_src => pkt.eth_src.to_s,
97
108
  :ip_saddr => pkt.ip_saddr,
98
- :ip_src => pkt.ip_src.to_s,
109
+ :ip_src => pkt.ip_src,
110
+ :ip_src_bin => [pkt.ip_src].pack("N"),
99
111
  :eth_dst => pkt.eth_dst.to_s,
100
112
  :eth_daddr => pkt.eth_daddr
101
113
  }
@@ -107,7 +119,7 @@ module PacketFu
107
119
  cap.save
108
120
  pkt = Packet.parse(cap.array[0]) unless cap.save.zero?
109
121
  end
110
- raise SocketError, "Didn't receive the whomi() packet." if !pkt
122
+ raise SocketError, "Didn't receive the whomi() packet, can't automatically configure." if !pkt
111
123
  cap = nil
112
124
  end
113
125
  my_data
@@ -161,7 +173,7 @@ module PacketFu
161
173
  end
162
174
  ifconfig_data.each do |s|
163
175
  case s
164
- when /inet addr:[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9])(.*Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]))?/i
176
+ when /inet addr:[\s]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(.*Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+))?/i
165
177
  ret[:ip_saddr] = $1
166
178
  ret[:ip_src] = [IPAddr.new($1).to_i].pack("N")
167
179
  ret[:ip4_obj] = IPAddr.new($1)
@@ -1,7 +1,7 @@
1
1
  module PacketFu
2
2
 
3
3
  # Check the repo's for version release histories
4
- VERSION = "1.0.4"
4
+ VERSION = "1.1.0"
5
5
 
6
6
  # Returns PacketFu::VERSION
7
7
  def self.version
data/test/all_tests.rb CHANGED
@@ -19,6 +19,7 @@
19
19
 
20
20
  $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib/")
21
21
  require 'packetfu'
22
+ puts "Testing PacketFu v#{PacketFu::VERSION}"
22
23
  dir = Dir.new(File.dirname(__FILE__))
23
24
 
24
25
  dir.each { |file|
@@ -0,0 +1,74 @@
1
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
+ require 'packetfu'
3
+
4
+ include PacketFu
5
+
6
+ describe EthPacket, "when read from a pcap file" do
7
+
8
+ before :all do
9
+ parsed_packets = PcapFile.read_packets(File.join(".","sample.pcap"))
10
+ @eth_packet = parsed_packets.first
11
+ end
12
+
13
+ context "is a regular ethernet packet" do
14
+
15
+ subject { @eth_packet }
16
+
17
+ it "should be an EthPacket kind of packet" do
18
+ subject.should be_kind_of EthPacket
19
+ end
20
+
21
+ it "should have a dest mac address" do
22
+ subject.eth_daddr.should == "00:03:2f:1a:74:de"
23
+ end
24
+
25
+ it "should have a source mac address" do
26
+ subject.eth_saddr.should == "00:1b:11:51:b7:ce"
27
+ end
28
+
29
+ its(:size) { should == 78 }
30
+
31
+ it "should have a payload in its first header" do
32
+ subject.headers.first.body.should_not be_nil
33
+ end
34
+
35
+ context "an EthPacket's first header" do
36
+
37
+ subject { @eth_packet.headers.first }
38
+
39
+ it "should be 64 bytes" do
40
+ subject.body.sz.should == 64
41
+ end
42
+
43
+ context "EthHeader struct members" do
44
+ if RUBY_VERSION =~ /^1\.8/
45
+ its(:members) { should include :eth_dst.to_s }
46
+ its(:members) { should include :eth_src.to_s }
47
+ its(:members) { should include :eth_proto.to_s }
48
+ its(:members) { should include :body.to_s }
49
+ else
50
+ its(:members) { should include :eth_dst }
51
+ its(:members) { should include :eth_src }
52
+ its(:members) { should include :eth_proto }
53
+ its(:members) { should include :body }
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ context "isn't a regular Ethernet packet" do
62
+
63
+ subject {
64
+ parsed_packets = PcapFile.read_packets(File.join(".","vlan-pcapr.cap"))
65
+ parsed_packets.first
66
+ }
67
+
68
+ it "should not be an EthPacket" do
69
+ subject.should_not be_kind_of EthPacket
70
+ end
71
+
72
+ end
73
+
74
+ end
data/test/icmp_test.pcap CHANGED
Binary file
data/test/ip_test.pcap CHANGED
Binary file
data/test/packet_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
- require File.join("..","lib","packetfu")
1
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
+ require 'packetfu'
2
3
 
3
4
  describe PacketFu::Packet, "abstract packet class behavior" do
4
5
 
@@ -1,4 +1,5 @@
1
- require File.join("..","lib","packetfu")
1
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
+ require 'packetfu'
2
3
 
3
4
  PacketFu.packet_classes.each do |pclass|
4
5
  describe pclass, "peek format" do
@@ -1,4 +1,5 @@
1
- require File.join("..","lib","packetfu")
1
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
+ require 'packetfu'
2
3
 
3
4
  unless %x{#{$0} --version} =~ /^2\.6/
4
5
  puts "PacketFu needs rspec 2.6 or so."
@@ -1,4 +1,5 @@
1
- require File.join("..","lib","packetfu")
1
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
+ require 'packetfu'
2
3
 
3
4
  describe StructFu, "mixin methods" do
4
5
 
data/test/tcp_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
- require File.join("..","lib","packetfu")
1
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
2
+ require 'packetfu'
2
3
 
3
4
  include PacketFu
4
5
 
data/test/tcp_test.pcap CHANGED
Binary file
data/test/test_arp.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
  class ArpTest < Test::Unit::TestCase
6
6
  include PacketFu
data/test/test_eth.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
  puts "Testing #{PacketFu.version}: #{$0}"
6
6
 
data/test/test_hsrp.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class HSRPTest < Test::Unit::TestCase
data/test/test_icmp.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class ICMPTest < Test::Unit::TestCase
data/test/test_inject.rb CHANGED
@@ -1,11 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
-
4
2
  require 'test/unit'
5
-
6
- # Needed if you're using the gem version of pcaprub. Obviated in 1.9.
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
7
4
  require 'packetfu'
8
5
 
6
+
9
7
  class InjectTest < Test::Unit::TestCase
10
8
 
11
9
  def test_cap
data/test/test_invalid.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class InvalidTest < Test::Unit::TestCase
data/test/test_ip.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class OctetsTest < Test::Unit::TestCase
data/test/test_ip6.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class IPv6AddrTest < Test::Unit::TestCase
data/test/test_octets.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class OctetTest < Test::Unit::TestCase
data/test/test_packet.rb CHANGED
@@ -2,7 +2,6 @@
2
2
  require 'test/unit'
3
3
  $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
4
4
  require 'packetfu'
5
- puts "Testing #{PacketFu.version}: #{$0}"
6
5
 
7
6
  class NewPacketTest < Test::Unit::TestCase
8
7
  include PacketFu
data/test/test_pcap.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  require 'test/unit'
4
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
5
4
  require 'packetfu'
6
5
 
7
6
  class PcapHeaderTest < Test::Unit::TestCase
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  # Whee unit testing.
data/test/test_tcp.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class String
data/test/test_udp.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
- $: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
3
+ $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
4
4
  require 'packetfu'
5
5
 
6
6
  class UDPTest < Test::Unit::TestCase
data/test/udp_test.pcap CHANGED
Binary file
Binary file
metadata CHANGED
@@ -1,14 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packetfu
3
3
  version: !ruby/object:Gem::Version
4
- hash: -1329738657
5
- prerelease: 6
6
- segments:
7
- - 1
8
- - 0
9
- - 5
10
- - pre
11
- version: 1.0.5.pre
4
+ prerelease:
5
+ version: 1.1.0
12
6
  platform: ruby
13
7
  authors:
14
8
  - Tod Beardsley
@@ -16,7 +10,7 @@ autorequire:
16
10
  bindir: bin
17
11
  cert_chain: []
18
12
 
19
- date: 2011-06-06 00:00:00 -05:00
13
+ date: 2011-06-11 00:00:00 -05:00
20
14
  default_executable:
21
15
  dependencies:
22
16
  - !ruby/object:Gem::Dependency
@@ -27,11 +21,6 @@ dependencies:
27
21
  requirements:
28
22
  - - ">="
29
23
  - !ruby/object:Gem::Version
30
- hash: 63
31
- segments:
32
- - 0
33
- - 9
34
- - 2
35
24
  version: 0.9.2
36
25
  type: :development
37
26
  version_requirements: *id001
@@ -43,7 +32,6 @@ extensions: []
43
32
 
44
33
  extra_rdoc_files:
45
34
  - README
46
- - INSTALL
47
35
  - .document
48
36
  files:
49
37
  - lib/packetfu.rb
@@ -89,7 +77,9 @@ files:
89
77
  - test/arp_test.pcap
90
78
  - test/test_inject.rb
91
79
  - test/test_eth.rb
80
+ - test/ethpacket_spec.rb
92
81
  - test/packet_spec.rb
82
+ - test/vlan-pcapr.cap
93
83
  - test/sample-ipv6.pcap
94
84
  - test/test_hsrp.rb
95
85
  - test/test_structfu.rb
@@ -105,6 +95,7 @@ files:
105
95
  - examples/examples.rb
106
96
  - examples/simple-stats.rb
107
97
  - examples/arphood.rb
98
+ - examples/simple-sniffer.rb
108
99
  - examples/ethernet.rb
109
100
  - examples/arp.rb
110
101
  - examples/slammer.rb
@@ -113,8 +104,9 @@ files:
113
104
  - examples/ackscan.rb
114
105
  - examples/ids.rb
115
106
  - examples/new-simple-stats.rb
107
+ - examples/100kpackets.rb
116
108
  has_rdoc: true
117
- homepage: http://code.google.com/p/packetfu/
109
+ homepage: https://github.com/todb/packetfu
118
110
  licenses:
119
111
  - BSD
120
112
  post_install_message:
@@ -127,27 +119,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
119
  requirements:
128
120
  - - ">="
129
121
  - !ruby/object:Gem::Version
130
- hash: 3
131
- segments:
132
- - 0
133
122
  version: "0"
134
123
  required_rubygems_version: !ruby/object:Gem::Requirement
135
124
  none: false
136
125
  requirements:
137
- - - ">"
126
+ - - ">="
138
127
  - !ruby/object:Gem::Version
139
- hash: 25
140
- segments:
141
- - 1
142
- - 3
143
- - 1
144
- version: 1.3.1
128
+ version: "0"
145
129
  requirements:
146
130
  - sdoc, for generating local documentation
147
131
  - rspec, v2.6.2 or later, for testing
148
132
  - pcaprub v0.9.2 or later, for packet capture/inject
149
133
  rubyforge_project: packetfu
150
- rubygems_version: 1.4.2
134
+ rubygems_version: 1.6.2
151
135
  signing_key:
152
136
  specification_version: 3
153
137
  summary: PacketFu is a mid-level packet manipulation library.