packetfu 1.0.5.pre → 1.1.0

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.
@@ -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.