packetfu 1.1.10 → 1.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -0
  4. data/.gitignore +3 -0
  5. data/.travis.yml +8 -0
  6. data/CONTRIBUTING.md +47 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +1 -1
  9. data/README.rdoc +35 -30
  10. data/Rakefile +4 -4
  11. data/bench/octets.rb +9 -9
  12. data/examples/100kpackets.rb +12 -12
  13. data/examples/ackscan.rb +16 -16
  14. data/examples/arp.rb +35 -35
  15. data/examples/arphood.rb +36 -36
  16. data/examples/dissect_thinger.rb +6 -6
  17. data/examples/new-simple-stats.rb +23 -23
  18. data/examples/packetfu-shell.rb +25 -25
  19. data/examples/simple-sniffer.rb +9 -9
  20. data/examples/simple-stats.rb +23 -23
  21. data/examples/slammer.rb +3 -3
  22. data/gem-public_cert.pem +21 -0
  23. data/lib/packetfu.rb +149 -127
  24. data/lib/packetfu/capture.rb +169 -169
  25. data/lib/packetfu/config.rb +52 -52
  26. data/lib/packetfu/inject.rb +56 -56
  27. data/lib/packetfu/packet.rb +531 -528
  28. data/lib/packetfu/pcap.rb +579 -579
  29. data/lib/packetfu/protos/arp.rb +90 -90
  30. data/lib/packetfu/protos/arp/header.rb +158 -158
  31. data/lib/packetfu/protos/arp/mixin.rb +36 -36
  32. data/lib/packetfu/protos/eth.rb +44 -44
  33. data/lib/packetfu/protos/eth/header.rb +243 -243
  34. data/lib/packetfu/protos/eth/mixin.rb +3 -3
  35. data/lib/packetfu/protos/hsrp.rb +69 -69
  36. data/lib/packetfu/protos/hsrp/header.rb +107 -107
  37. data/lib/packetfu/protos/hsrp/mixin.rb +29 -29
  38. data/lib/packetfu/protos/icmp.rb +71 -71
  39. data/lib/packetfu/protos/icmp/header.rb +82 -82
  40. data/lib/packetfu/protos/icmp/mixin.rb +14 -14
  41. data/lib/packetfu/protos/invalid.rb +49 -49
  42. data/lib/packetfu/protos/ip.rb +69 -69
  43. data/lib/packetfu/protos/ip/header.rb +291 -291
  44. data/lib/packetfu/protos/ip/mixin.rb +40 -40
  45. data/lib/packetfu/protos/ipv6.rb +50 -50
  46. data/lib/packetfu/protos/ipv6/header.rb +188 -188
  47. data/lib/packetfu/protos/ipv6/mixin.rb +29 -29
  48. data/lib/packetfu/protos/tcp.rb +176 -176
  49. data/lib/packetfu/protos/tcp/ecn.rb +35 -35
  50. data/lib/packetfu/protos/tcp/flags.rb +74 -74
  51. data/lib/packetfu/protos/tcp/header.rb +268 -268
  52. data/lib/packetfu/protos/tcp/hlen.rb +32 -32
  53. data/lib/packetfu/protos/tcp/mixin.rb +46 -46
  54. data/lib/packetfu/protos/tcp/option.rb +321 -321
  55. data/lib/packetfu/protos/tcp/options.rb +95 -95
  56. data/lib/packetfu/protos/tcp/reserved.rb +35 -35
  57. data/lib/packetfu/protos/udp.rb +159 -123
  58. data/lib/packetfu/protos/udp/header.rb +91 -91
  59. data/lib/packetfu/protos/udp/mixin.rb +3 -3
  60. data/lib/packetfu/structfu.rb +280 -280
  61. data/lib/packetfu/utils.rb +292 -225
  62. data/lib/packetfu/version.rb +41 -41
  63. data/packetfu.gemspec +14 -3
  64. data/spec/arp_spec.rb +191 -0
  65. data/spec/eth_spec.rb +148 -0
  66. data/spec/icmp_spec.rb +97 -0
  67. data/spec/ip_spec.rb +78 -0
  68. data/spec/ipv6_spec.rb +81 -0
  69. data/spec/packet_spec.rb +61 -59
  70. data/spec/packet_subclasses_spec.rb +9 -10
  71. data/spec/packetfu_spec.rb +55 -62
  72. data/spec/sample3.pcap +0 -0
  73. data/spec/spec_helper.rb +44 -0
  74. data/spec/structfu_spec.rb +270 -271
  75. data/spec/tcp_spec.rb +76 -77
  76. data/spec/udp_spec.rb +32 -0
  77. data/spec/utils_spec.rb +95 -0
  78. data/test/all_tests.rb +14 -17
  79. data/test/func_lldp.rb +3 -3
  80. data/test/ptest.rb +2 -2
  81. data/test/test_capture.rb +45 -45
  82. data/test/test_eth.rb +70 -68
  83. data/test/test_hsrp.rb +9 -9
  84. data/test/test_inject.rb +18 -18
  85. data/test/test_invalid.rb +16 -16
  86. data/test/test_octets.rb +23 -21
  87. data/test/test_packet.rb +156 -154
  88. data/test/test_pcap.rb +172 -170
  89. data/test/test_structfu.rb +99 -97
  90. data/test/test_tcp.rb +322 -320
  91. data/test/test_udp.rb +78 -76
  92. metadata +108 -44
  93. metadata.gz.sig +2 -0
  94. data/spec/ethpacket_spec.rb +0 -74
  95. data/test/test_arp.rb +0 -135
  96. data/test/test_icmp.rb +0 -62
  97. data/test/test_ip.rb +0 -50
  98. data/test/test_ip6.rb +0 -68
@@ -14,10 +14,10 @@ include PacketFu
14
14
 
15
15
  packets = PcapFile.file_to_array fname
16
16
  packets.each do |packet|
17
- puts "_" * 75
18
- puts packet.inspect
19
- puts "_" * 75
20
- pkt = Packet.parse(packet)
21
- puts pkt.dissect
22
- sleep sleep_interval
17
+ puts "_" * 75
18
+ puts packet.inspect
19
+ puts "_" * 75
20
+ pkt = Packet.parse(packet)
21
+ puts pkt.dissect
22
+ sleep sleep_interval
23
23
  end
@@ -13,38 +13,38 @@ require './examples' # For path setting slight-of-hand
13
13
  require 'packetfu'
14
14
 
15
15
  def print_results(stats)
16
- stats.each_pair { |k,v| puts "%-12s: %10d" % [k,v] }
16
+ stats.each_pair { |k,v| puts "%-12s: %10d" % [k,v] }
17
17
  end
18
18
 
19
19
  # Takes a file name, parses the packets, and records the packet
20
20
  # type based on its PacketFu class.
21
21
  def count_packet_types(file)
22
- stats = {}
23
- count = 0
24
- elapsed = 0
25
- start_time = Time.now
26
- PacketFu::PcapFile.read_packets(file) do |pkt|
27
- kind = pkt.proto.last.to_sym
28
- stats[kind] ? stats[kind] += 1 : stats[kind] = 1
29
- count += 1
30
- elapsed = (Time.now - start_time).to_i
31
- if count % 5_000 == 0
32
- puts "After #{count} packets (#{elapsed} seconds elapsed):"
33
- print_results(stats)
34
- end
35
- end
36
- puts "Final results for #{count} packets (#{elapsed} seconds elapsed):"
37
- print_results(stats)
22
+ stats = {}
23
+ count = 0
24
+ elapsed = 0
25
+ start_time = Time.now
26
+ PacketFu::PcapFile.read_packets(file) do |pkt|
27
+ kind = pkt.proto.last.to_sym
28
+ stats[kind] ? stats[kind] += 1 : stats[kind] = 1
29
+ count += 1
30
+ elapsed = (Time.now - start_time).to_i
31
+ if count % 5_000 == 0
32
+ puts "After #{count} packets (#{elapsed} seconds elapsed):"
33
+ print_results(stats)
34
+ end
35
+ end
36
+ puts "Final results for #{count} packets (#{elapsed} seconds elapsed):"
37
+ print_results(stats)
38
38
  end
39
39
 
40
40
  if File.readable?(infile = (ARGV[0] || 'in.pcap'))
41
- title = "Packets by packet type in '#{infile}'"
42
- puts "-" * title.size
43
- puts title
44
- puts "-" * title.size
45
- count_packet_types(infile)
41
+ title = "Packets by packet type in '#{infile}'"
42
+ puts "-" * title.size
43
+ puts title
44
+ puts "-" * title.size
45
+ count_packet_types(infile)
46
46
  else
47
- raise RuntimeError, "Need an infile, like so: #{$0} in.pcap"
47
+ raise RuntimeError, "Need an infile, like so: #{$0} in.pcap"
48
48
  end
49
49
 
50
50
 
@@ -49,12 +49,12 @@ require './examples'
49
49
  require 'packetfu'
50
50
 
51
51
  module PacketFu
52
- def whoami?(args={})
53
- Utils.whoami?(args)
54
- end
55
- def arp(arg)
56
- Utils.arp(arg)
57
- end
52
+ def whoami?(args={})
53
+ Utils.whoami?(args)
54
+ end
55
+ def arp(arg)
56
+ Utils.arp(arg)
57
+ end
58
58
  end
59
59
 
60
60
  include PacketFu
@@ -64,7 +64,7 @@ include PacketFu
64
64
  # http://jisho.org/words?jap=+%E3%83%91%E3%82%B1%E3%83%83%E3%83%88%E3%83%95&eng=&dict=edict
65
65
  #
66
66
  def packetfu_ascii_art
67
- puts <<EOM
67
+ puts <<EOM
68
68
  _______ _______ _______ _ _______ _________ _______
69
69
  ( ____ )( ___ )( ____ \\| \\ /\\( ____ \\\\__ __/( ____ \\|\\ /|
70
70
  | ( )|| ( ) || ( \\/| \\ / /| ( \\/ ) ( | ( \\/| ) ( |
@@ -82,33 +82,33 @@ def packetfu_ascii_art
82
82
  a mid-level packet manipulation library for ruby
83
83
 
84
84
  EOM
85
- end
85
+ end
86
86
 
87
87
  @pcaprub_loaded = PacketFu.pcaprub_loaded?
88
88
  # Displays a helpful banner.
89
89
  def banner
90
- packetfu_ascii_art
91
- puts ">>> PacketFu Shell #{PacketFu.version}."
92
- if Process.euid.zero? && @pcaprub_loaded
93
- puts ">>> Use $packetfu_default.config for salient networking details."
94
- print "IP: %-15s Mac: %s" % [$packetfu_default.ip_saddr, $packetfu_default.eth_saddr]
95
- puts " Gateway: %s" % $packetfu_default.eth_daddr
96
- print "Net: %-15s" % [Pcap.lookupnet($packetfu_default.iface)][0]
97
- print " " * 13
98
- puts "Iface: %s" % [($packetfu_default.iface)]
99
- puts ">>> Packet capturing/injecting enabled."
100
- else
101
- print ">>> Packet capturing/injecting disabled. "
102
- puts Process.euid.zero? ? "(no PcapRub)" : "(not root)"
103
- end
104
- puts "<>" * 36
90
+ packetfu_ascii_art
91
+ puts ">>> PacketFu Shell #{PacketFu.version}."
92
+ if Process.euid.zero? && @pcaprub_loaded
93
+ puts ">>> Use $packetfu_default.config for salient networking details."
94
+ print "IP: %-15s Mac: %s" % [$packetfu_default.ip_saddr, $packetfu_default.eth_saddr]
95
+ puts " Gateway: %s" % $packetfu_default.eth_daddr
96
+ print "Net: %-15s" % [Pcap.lookupnet($packetfu_default.iface)][0]
97
+ print " " * 13
98
+ puts "Iface: %s" % [($packetfu_default.iface)]
99
+ puts ">>> Packet capturing/injecting enabled."
100
+ else
101
+ print ">>> Packet capturing/injecting disabled. "
102
+ puts Process.euid.zero? ? "(no PcapRub)" : "(not root)"
103
+ end
104
+ puts "<>" * 36
105
105
  end
106
106
 
107
107
  # Silly wlan0 workaround
108
108
  begin
109
- $packetfu_default = PacketFu::Config.new(Utils.whoami?) if(@pcaprub_loaded && Process.euid.zero?)
109
+ $packetfu_default = PacketFu::Config.new(Utils.whoami?) if(@pcaprub_loaded && Process.euid.zero?)
110
110
  rescue RuntimeError
111
- $packetfu_default = PacketFu::Config.new(Utils.whoami?(:iface => 'wlan0')) if(@pcaprub_loaded && Process.euid.zero?)
111
+ $packetfu_default = PacketFu::Config.new(Utils.whoami?(:iface => 'wlan0')) if(@pcaprub_loaded && Process.euid.zero?)
112
112
  end
113
113
 
114
114
  banner
@@ -8,15 +8,15 @@ include PacketFu
8
8
  iface = ARGV[0] || "eth0"
9
9
 
10
10
  def sniff(iface)
11
- cap = Capture.new(:iface => iface, :start => true)
12
- cap.stream.each do |p|
13
- pkt = Packet.parse p
14
- if pkt.is_ip?
15
- next if pkt.ip_saddr == Utils.ifconfig(iface)[:ip_saddr]
16
- packet_info = [pkt.ip_saddr, pkt.ip_daddr, pkt.size, pkt.proto.last]
17
- puts "%-15s -> %-15s %-4d %s" % packet_info
18
- end
19
- end
11
+ cap = Capture.new(:iface => iface, :start => true)
12
+ cap.stream.each do |p|
13
+ pkt = Packet.parse p
14
+ if pkt.is_ip?
15
+ next if pkt.ip_saddr == Utils.ifconfig(iface)[:ip_saddr]
16
+ packet_info = [pkt.ip_saddr, pkt.ip_daddr, pkt.size, pkt.proto.last]
17
+ puts "%-15s -> %-15s %-4d %s" % packet_info
18
+ end
19
+ end
20
20
  end
21
21
 
22
22
  sniff(iface)
@@ -16,33 +16,33 @@ require 'packetfu'
16
16
  # Takes a file name, parses the packets, and records the packet
17
17
  # type based on its PacketFu class.
18
18
  def count_packet_types(file)
19
- file = File.open(file) {|f| f.read}
20
- stats = {}
21
- count = 0
22
- pcapfile = PacketFu::PcapPackets.new
23
- pcapfile.read(file)
24
- pcapfile.each do |p|
25
- # Now it's a PacketFu packet struct.
26
- pkt = PacketFu::Packet.parse(p.data)
27
- kind = pkt.class.to_s.split("::").last
28
- if stats[kind]
29
- stats[kind] += 1
30
- else
31
- stats[kind] = 0
32
- end
33
- count += 1
34
- break if count >= 1_000
35
- end
36
- stats.each_pair { |k,v| puts "%-12s: %4d" % [k,v] }
19
+ file = File.open(file) {|f| f.read}
20
+ stats = {}
21
+ count = 0
22
+ pcapfile = PacketFu::PcapPackets.new
23
+ pcapfile.read(file)
24
+ pcapfile.each do |p|
25
+ # Now it's a PacketFu packet struct.
26
+ pkt = PacketFu::Packet.parse(p.data)
27
+ kind = pkt.class.to_s.split("::").last
28
+ if stats[kind]
29
+ stats[kind] += 1
30
+ else
31
+ stats[kind] = 0
32
+ end
33
+ count += 1
34
+ break if count >= 1_000
35
+ end
36
+ stats.each_pair { |k,v| puts "%-12s: %4d" % [k,v] }
37
37
  end
38
38
 
39
39
  if File.readable?(infile = (ARGV[0] || 'in.pcap'))
40
- title = "Packets by packet type in '#{infile}'"
41
- puts title
42
- puts "-" * title.size
43
- count_packet_types(infile)
40
+ title = "Packets by packet type in '#{infile}'"
41
+ puts title
42
+ puts "-" * title.size
43
+ count_packet_types(infile)
44
44
  else
45
- raise RuntimeError, "Need an infile, like so: #{$0} in.pcap"
45
+ raise RuntimeError, "Need an infile, like so: #{$0} in.pcap"
46
46
  end
47
47
 
48
48
 
@@ -14,7 +14,7 @@ include PacketFu
14
14
  slammer = "\004\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001" + "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\334\311\260B\353\016" + "\001\001\001\001\001\001\001p\256B\001p\256B\220\220\220\220\220\220\220\220h\334\311\260B\270\001\001" + "\001\0011\311\261\030P\342\3755\001\001\001\005P\211\345Qh.dllhel32hkernQhounthickChGetTf" + "\271llQh32.dhws2_f\271etQhsockf\271toQhsend\276\030\020\256B\215E\324P\377\026P\215E\340P\215E\360P\377" + "\026P\276\020\020\256B\213\036\213\003=U\213\354Qt\005\276\034\020\256B\377\026\377\3201\311QQP\201\361" + "\003\001\004\233\201\361\001\001\001\001Q\215E\314P\213E\300P\377\026j\021j\002j\002\377\320P\215E\304P" + "\213E\300P\377\026\211\306\t\333\201\363<a\331\377\213E\264\215\f@\215\024\210\301\342\004\001\302\301" + "\342\b)\302\215\004\220\001\330\211E\264j\020\215E\260P1\311Qf\201\361x\001Q\215E\003P\213E\254P\377\326" + "\353\312"
15
15
 
16
16
  def rand_source_ip
17
- [rand(0xffffffff)].pack("N")
17
+ [rand(0xffffffff)].pack("N")
18
18
  end
19
19
 
20
20
  kill_packet = UDPPacket.new
@@ -26,9 +26,9 @@ kill_packet.recalc
26
26
  kill_packet.payload = slammer
27
27
 
28
28
  if action == 'file'.downcase
29
- puts kill_packet.to_f
29
+ puts kill_packet.to_f
30
30
  else
31
- puts kill_packet.to_w(action.downcase)
31
+ puts kill_packet.to_w(action.downcase)
32
32
  end
33
33
 
34
34
 
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDbDCCAlSgAwIBAgIBATANBgkqhkiG9w0BAQUFADA+MQ0wCwYDVQQDDAR0b2Ri
3
+ MRgwFgYKCZImiZPyLGQBGRYIcGFja2V0ZnUxEzARBgoJkiaJk/IsZAEZFgNjb20w
4
+ HhcNMTUwODI1MTQ1MzQ2WhcNMTYwODI0MTQ1MzQ2WjA+MQ0wCwYDVQQDDAR0b2Ri
5
+ MRgwFgYKCZImiZPyLGQBGRYIcGFja2V0ZnUxEzARBgoJkiaJk/IsZAEZFgNjb20w
6
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDl/jdqB/u4WnnAV7ds6U7r
7
+ kffHRJCMc1+s0lvjnWMnZuegjJkuElm0jNQnkUzNqhJGI2NVDc1COoT6VHsEPRi8
8
+ uD8po+7pisLwqUHIyx8PFu+pGSRGawEgAPT5DfEf9MwGTob1G9vm1Hv7rTMN+S1X
9
+ nMIxpFwiMilhLKdoTEZAo0moFbWEVK4ZuEaNkPXGxFKEdnpyb8Fi+/akzwWtwRp1
10
+ ByJktlF3YIZgAimvY/PtV0V1n+Mktoz+706EUDe/ZnD8M+o6orzqryCiQrqdzJyk
11
+ cPv7u1RuG1VPC8mK5TmB9lqlMPi/hxbjC4LfhJsZYoO1AF6baZ8HzqCISInBLwyd
12
+ AgMBAAGjdTBzMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBS/B6/d
13
+ CN84yx061Q/xqilGxY4qqTAcBgNVHREEFTATgRF0b2RiQHBhY2tldGZ1LmNvbTAc
14
+ BgNVHRIEFTATgRF0b2RiQHBhY2tldGZ1LmNvbTANBgkqhkiG9w0BAQUFAAOCAQEA
15
+ Oz/R618bt2/QxwL1wM6bP/yb+xNd/DR8aOUeKZwarfWuo6zhVY03qiydlElHU0YJ
16
+ Rl0/JGQIHNVUzIr3J/QXv225LUECYTejPKC8LcELdfjSfUwzTd75zrGisL0//a4m
17
+ +Zcv8PSfdOCug3jj5EDMVZe/sX7G4vEqM81SaQaUYFltKGk2YUrlYJsNGW6Yp4As
18
+ c4y7lD0Rc4OsaoWT5ozhFBJv1qSuoL1y1qySsVazbc0jYjxm6HkVWqOd1cO5zO74
19
+ AFvBtuFFTUDdrs3M/q6ktx295osXr2XpaygJmhkMLj81xoIX9G8eEjPc/XQWDlI1
20
+ ma/kCj5vaQ3hma/0DsajCg==
21
+ -----END CERTIFICATE-----
@@ -13,133 +13,155 @@ require 'rubygems' if RUBY_VERSION =~ /^1\.[0-8]/
13
13
 
14
14
  module PacketFu
15
15
 
16
- # Picks up all the protocols defined in the protos subdirectory
17
- def self.require_protos(cwd)
18
- protos_dir = File.join(cwd, "packetfu", "protos")
19
- Dir.new(protos_dir).each do |fname|
20
- next unless fname[/\.rb$/]
21
- begin
22
- require File.join(protos_dir,fname)
23
- rescue
24
- warn "Warning: Could not load `#{fname}'. Skipping."
25
- end
26
- end
27
- end
28
-
29
- # Deal with Ruby's encoding by ignoring it.
30
- def self.force_binary(str)
31
- str.force_encoding Encoding::BINARY if str.respond_to? :force_encoding
32
- end
33
-
34
- # Sets the expected byte order for a pcap file. See PacketFu::Read.set_byte_order
35
- @byte_order = :little
36
-
37
- # Checks if pcaprub is loaded correctly.
38
- @pcaprub_loaded = false
39
-
40
- # PacketFu works best with Pcaprub version 0.8-dev (at least)
41
- # The current (Aug 01, 2010) pcaprub gem is 0.9, so should be fine.
42
- def self.pcaprub_platform_require
43
- begin
44
- require 'pcaprub'
45
- rescue LoadError
46
- return false
47
- end
48
- @pcaprub_loaded = true
49
- end
50
-
51
- pcaprub_platform_require
52
-
53
- if @pcaprub_loaded
54
- pcaprub_regex = /[0-9]\.([8-9]|[1-7][0-9])(-dev)?/ # Regex for 0.8 and beyond.
55
- if Pcap.version !~ pcaprub_regex
56
- @pcaprub_loaded = false # Don't bother with broken versions
57
- raise LoadError, "PcapRub not at a minimum version of 0.8-dev"
58
- end
59
- require "packetfu/capture"
60
- require "packetfu/inject"
61
- end
62
-
63
- # Returns the status of pcaprub
64
- def self.pcaprub_loaded?
65
- @pcaprub_loaded
66
- end
67
-
68
- # Returns an array of classes defined in PacketFu
69
- def self.classes
70
- constants.map { |const| const_get(const) if const_get(const).kind_of? Class}.compact
71
- end
72
-
73
- # Adds the class to PacketFu's list of packet classes -- used in packet parsing.
74
- def self.add_packet_class(klass)
75
- raise "Need a class" unless klass.kind_of? Class
76
- if klass.name !~ /[A-Za-z0-9]Packet/
77
- raise "Packet classes should be named 'ProtoPacket'"
78
- end
79
- @packet_classes ||= []
80
- @packet_classes << klass
81
- @packet_classes_dirty = true
82
- @packet_classes.sort! {|x,y| x.name <=> y.name}
83
- end
84
-
85
- # Presumably, there may be a time where you'd like to remove a packet class.
86
- def self.remove_packet_class(klass)
87
- raise "Need a class" unless klass.kind_of? Class
88
- @packet_classes ||= []
89
- @packet_classes.delete klass
90
- @packet_classes_dirty = true
91
- @packet_classes
92
- end
93
-
94
- # Returns an array of packet classes
95
- def self.packet_classes
96
- @packet_classes || []
97
- end
98
-
99
- # Returns an array of packet types by packet prefix.
100
- def self.packet_prefixes
101
- return [] if @packet_classes.nil?
102
- return @packet_class_prefixes if @packet_classes_dirty == false
103
- @packet_classes_dirty = false
104
- @packet_class_prefixes = @packet_classes.map {|p| p.to_s.split("::").last.to_s.downcase.gsub(/packet$/,"")}
105
- return @packet_class_prefixes
106
- end
107
-
108
- # The current inspect style. One of :hex, :dissect, or :default
109
- # Note that :default means Ruby's default, which is usually
110
- # far too long to be useful.
111
- def self.inspect_style
112
- @inspect_style ||= :dissect
113
- end
114
-
115
- # Setter for PacketFu's @inspect_style
116
- def self.inspect_style=(arg)
117
- @inspect_style = case arg
118
- when :hex, :pretty
119
- :hex
120
- when :dissect, :verbose
121
- :dissect
122
- when :default, :ugly
123
- :default
124
- else
125
- :dissect
126
- end
127
- end
128
-
129
- # Switches inspect styles in a round-robin fashion between
130
- # :dissect, :default, and :hex
131
- def toggle_inspect
132
- case @inspect_style
133
- when :hex, :pretty
134
- @inspect_style = :dissect
135
- when :dissect, :verbose
136
- @inspect_style = :default
137
- when :default, :ugly
138
- @inspect_style = :hex
139
- else
140
- @inspect_style = :dissect
141
- end
142
- end
16
+ # Picks up all the protocols defined in the protos subdirectory
17
+ def self.require_protos(cwd)
18
+ protos_dir = File.join(cwd, "packetfu", "protos")
19
+ Dir.new(protos_dir).each do |fname|
20
+ next unless fname[/\.rb$/]
21
+ begin
22
+ require File.join(protos_dir,fname)
23
+ rescue
24
+ warn "Warning: Could not load `#{fname}'. Skipping."
25
+ end
26
+ end
27
+ end
28
+
29
+ # Deal with Ruby's encoding by ignoring it.
30
+ def self.force_binary(str)
31
+ str.force_encoding Encoding::BINARY if str.respond_to? :force_encoding
32
+ end
33
+
34
+ # Sets the expected byte order for a pcap file. See PacketFu::Read.set_byte_order
35
+ @byte_order = :little
36
+
37
+ # Checks if pcaprub is loaded correctly.
38
+ @pcaprub_loaded = false
39
+
40
+ # PacketFu works best with Pcaprub version 0.8-dev (at least)
41
+ # The current (Aug 01, 2010) pcaprub gem is 0.9, so should be fine.
42
+ def self.pcaprub_platform_require
43
+ begin
44
+ require 'pcaprub'
45
+ rescue LoadError
46
+ return false
47
+ end
48
+ @pcaprub_loaded = true
49
+ end
50
+
51
+ pcaprub_platform_require
52
+
53
+ if @pcaprub_loaded
54
+ pcaprub_regex = /[0-9]\.([8-9]|[1-7][0-9])(-dev)?/ # Regex for 0.8 and beyond.
55
+ if Pcap.version !~ pcaprub_regex
56
+ @pcaprub_loaded = false # Don't bother with broken versions
57
+ raise LoadError, "PcapRub not at a minimum version of 0.8-dev"
58
+ end
59
+ require "packetfu/capture"
60
+ require "packetfu/inject"
61
+ end
62
+
63
+ # Returns the status of pcaprub
64
+ def self.pcaprub_loaded?
65
+ @pcaprub_loaded
66
+ end
67
+
68
+ # Returns an array of classes defined in PacketFu
69
+ def self.classes
70
+ constants.map { |const| const_get(const) if const_get(const).kind_of? Class}.compact
71
+ end
72
+
73
+ # Adds the class to PacketFu's list of packet classes -- used in packet parsing.
74
+ def self.add_packet_class(klass)
75
+ raise "Need a class" unless klass.kind_of? Class
76
+ if klass.name !~ /[A-Za-z0-9]Packet/
77
+ raise "Packet classes should be named 'ProtoPacket'"
78
+ end
79
+ @packet_classes ||= []
80
+ @packet_classes << klass
81
+ self.clear_packet_groups
82
+ @packet_classes.sort_by! { |x| x.name }
83
+ end
84
+
85
+ # Presumably, there may be a time where you'd like to remove a packet class.
86
+ def self.remove_packet_class(klass)
87
+ raise "Need a class" unless klass.kind_of? Class
88
+ @packet_classes ||= []
89
+ @packet_classes.delete klass
90
+ self.clear_packet_groups
91
+ @packet_classes
92
+ end
93
+
94
+ # Returns an array of packet classes
95
+ def self.packet_classes
96
+ @packet_classes || []
97
+ end
98
+
99
+ # Returns an array of packet types by packet prefix.
100
+ def self.packet_prefixes
101
+ return [] if @packet_classes.nil?
102
+ self.reset_packet_groups unless @packet_class_prefixes
103
+ @packet_class_prefixes
104
+ end
105
+
106
+ def self.packet_classes_by_layer
107
+ return [] if @packet_classes.nil?
108
+ self.reset_packet_groups unless @packet_classes_by_layer
109
+ @packet_classes_by_layer
110
+ end
111
+
112
+ def self.packet_classes_by_layer_without_application
113
+ return [] if @packet_classes.nil?
114
+ self.reset_packet_groups unless @packet_classes_by_layer_without_application
115
+ @packet_classes_by_layer_without_application
116
+ end
117
+
118
+ def self.clear_packet_groups
119
+ @packet_class_prefixes = nil
120
+ @packet_classes_by_layer = nil
121
+ @packet_classes_by_layer_without_application = nil
122
+ end
123
+
124
+ def self.reset_packet_groups
125
+ @packet_class_prefixes = @packet_classes.map {|p| p.to_s.split("::").last.to_s.downcase.gsub(/packet$/,"")}
126
+ @packet_classes_by_layer = @packet_classes.sort_by { |pclass| pclass.layer }.reverse
127
+ @packet_classes_by_layer_without_application = @packet_classes_by_layer.reject { |pclass| pclass.layer_symbol == :application }
128
+ end
129
+
130
+ # The current inspect style. One of :hex, :dissect, or :default
131
+ # Note that :default means Ruby's default, which is usually
132
+ # far too long to be useful.
133
+ def self.inspect_style
134
+ @inspect_style ||= :dissect
135
+ end
136
+
137
+ # Setter for PacketFu's @inspect_style
138
+ def self.inspect_style=(arg)
139
+ @inspect_style = case arg
140
+ when :hex, :pretty
141
+ :hex
142
+ when :dissect, :verbose
143
+ :dissect
144
+ when :default, :ugly
145
+ :default
146
+ else
147
+ :dissect
148
+ end
149
+ end
150
+
151
+ # Switches inspect styles in a round-robin fashion between
152
+ # :dissect, :default, and :hex
153
+ def toggle_inspect
154
+ case @inspect_style
155
+ when :hex, :pretty
156
+ @inspect_style = :dissect
157
+ when :dissect, :verbose
158
+ @inspect_style = :default
159
+ when :default, :ugly
160
+ @inspect_style = :hex
161
+ else
162
+ @inspect_style = :dissect
163
+ end
164
+ end
143
165
 
144
166
 
145
167
  end