ffi-pcap 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/.gitignore +2 -1
  2. data/.pkg_ignore +25 -0
  3. data/.rspec +1 -0
  4. data/.specopts +1 -0
  5. data/.yardopts +1 -0
  6. data/{ChangeLog.rdoc → ChangeLog.md} +15 -5
  7. data/LICENSE.txt +1 -4
  8. data/README.md +92 -0
  9. data/Rakefile +30 -20
  10. data/examples/em_selectable_pcap.rb +38 -0
  11. data/examples/em_timer.rb +26 -0
  12. data/examples/ipfw_divert.rb +28 -8
  13. data/examples/print_bytes.rb +5 -1
  14. data/examples/replay.rb +11 -0
  15. data/examples/selectable_pcap.rb +29 -0
  16. data/ffi-pcap.gemspec +60 -0
  17. data/gemspec.yml +23 -0
  18. data/lib/ffi/pcap.rb +7 -13
  19. data/lib/ffi/pcap/addr.rb +16 -15
  20. data/lib/ffi/pcap/bpf_instruction.rb +25 -0
  21. data/lib/ffi/pcap/bpf_program.rb +85 -0
  22. data/lib/ffi/pcap/bsd.rb +9 -98
  23. data/lib/ffi/pcap/bsd/af.rb +18 -0
  24. data/lib/ffi/pcap/bsd/in6_addr.rb +16 -0
  25. data/lib/ffi/pcap/bsd/in_addr.rb +18 -0
  26. data/lib/ffi/pcap/bsd/sock_addr.rb +19 -0
  27. data/lib/ffi/pcap/bsd/sock_addr_dl.rb +24 -0
  28. data/lib/ffi/pcap/bsd/sock_addr_family.rb +19 -0
  29. data/lib/ffi/pcap/bsd/sock_addr_in.rb +21 -0
  30. data/lib/ffi/pcap/bsd/sock_addr_in6.rb +20 -0
  31. data/lib/ffi/pcap/bsd/typedefs.rb +7 -0
  32. data/lib/ffi/pcap/capture_wrapper.rb +296 -256
  33. data/lib/ffi/pcap/common_wrapper.rb +152 -127
  34. data/lib/ffi/pcap/copy_handler.rb +32 -32
  35. data/lib/ffi/pcap/crt.rb +7 -10
  36. data/lib/ffi/pcap/data_link.rb +178 -153
  37. data/lib/ffi/pcap/dead.rb +42 -29
  38. data/lib/ffi/pcap/dumper.rb +39 -41
  39. data/lib/ffi/pcap/error_buffer.rb +21 -36
  40. data/lib/ffi/pcap/exceptions.rb +21 -15
  41. data/lib/ffi/pcap/file_header.rb +24 -18
  42. data/lib/ffi/pcap/in_addr.rb +4 -4
  43. data/lib/ffi/pcap/interface.rb +22 -20
  44. data/lib/ffi/pcap/live.rb +296 -252
  45. data/lib/ffi/pcap/offline.rb +50 -43
  46. data/lib/ffi/pcap/packet.rb +186 -143
  47. data/lib/ffi/pcap/packet_header.rb +20 -18
  48. data/lib/ffi/pcap/pcap.rb +269 -212
  49. data/lib/ffi/pcap/stat.rb +19 -49
  50. data/lib/ffi/pcap/stat_ex.rb +42 -0
  51. data/lib/ffi/pcap/time_val.rb +52 -38
  52. data/lib/ffi/pcap/typedefs.rb +16 -20
  53. data/spec/data_link_spec.rb +39 -35
  54. data/spec/dead_spec.rb +0 -4
  55. data/spec/error_buffer_spec.rb +7 -9
  56. data/spec/file_header_spec.rb +17 -14
  57. data/spec/live_spec.rb +12 -5
  58. data/spec/offline_spec.rb +10 -11
  59. data/spec/packet_behaviors.rb +20 -6
  60. data/spec/packet_injection_spec.rb +9 -8
  61. data/spec/packet_spec.rb +22 -26
  62. data/spec/pcap_spec.rb +52 -40
  63. data/spec/spec_helper.rb +16 -5
  64. data/spec/wrapper_behaviors.rb +0 -3
  65. data/tasks/doc.rake +69 -0
  66. data/tasks/gem.rake +200 -0
  67. data/tasks/git.rake +40 -0
  68. data/tasks/post_load.rake +34 -0
  69. data/tasks/rubyforge.rake +55 -0
  70. data/tasks/setup.rb +286 -0
  71. data/tasks/spec.rake +54 -0
  72. data/tasks/svn.rake +47 -0
  73. data/tasks/test.rake +40 -0
  74. metadata +142 -92
  75. data/README.rdoc +0 -30
  76. data/VERSION +0 -1
  77. data/lib/ffi/pcap/bpf.rb +0 -106
  78. data/lib/ffi/pcap/version.rb +0 -6
  79. data/tasks/rcov.rb +0 -6
  80. data/tasks/rdoc.rb +0 -17
  81. data/tasks/spec.rb +0 -9
  82. data/tasks/yard.rb +0 -21
@@ -1,15 +1,26 @@
1
1
  require 'rubygems'
2
- gem 'rspec', '>=1.3.0'
3
- require 'spec'
2
+
3
+ gem 'rspec', '~> 2.0'
4
+ require 'rspec'
4
5
 
5
6
  require 'ffi/pcap'
7
+ require 'pathname'
6
8
 
7
9
  include FFI
8
10
  include FFI::PCap
9
11
 
10
- PCAP_DEV = ENV['PCAP_DEV'] || 'lo0'
11
- PCAP_TESTFILE = ENV['PCAP_TESTFILE'] || File.expand_path(File.join(File.dirname(__FILE__), 'dumps', 'simple_tcp.pcap'))
12
- PCAP_TESTADDR = ENV['PCAP_TESTADDR'] || '127.0.0.1'
12
+ DEFAULT_PCAP_DEV = case RUBY_PLATFORM
13
+ when /linux/
14
+ 'lo'
15
+ when /(bsd|darwin)/
16
+ 'lo0'
17
+ end
18
+ DEFAULT_TESTFILE = Pathname.new(__FILE__).dirname.join('dumps','simple_tcp.pcap')
19
+ DEFAULT_TESTADDR = '127.0.0.1'
20
+
21
+ PCAP_DEV = (ENV['PCAP_DEV'] || DEFAULT_PCAP_DEV)
22
+ PCAP_TESTFILE = (ENV['PCAP_TESTFILE'] || DEFAULT_TESTFILE)
23
+ PCAP_TESTADDR = (ENV['PCAP_TESTADDR'] || DEFAULT_TESTADDR)
13
24
 
14
25
  $test_ping_pid = nil
15
26
 
@@ -67,11 +67,9 @@ shared_examples_for "FFI::PCap::CommonWrapper" do
67
67
  @pcap.close
68
68
  }.should_not raise_error(Exception)
69
69
  end
70
-
71
70
  end
72
71
 
73
72
  shared_examples_for "FFI::PCap::CaptureWrapper" do
74
-
75
73
  it "should pass packets to a block using loop()" do
76
74
  i = 0
77
75
  @pkt = nil
@@ -121,4 +119,3 @@ shared_examples_for "FFI::PCap::CaptureWrapper" do
121
119
 
122
120
  it_should_behave_like "FFI::PCap::CommonWrapper"
123
121
  end
124
-
@@ -0,0 +1,69 @@
1
+
2
+ require 'rake/rdoctask'
3
+
4
+ begin
5
+ require 'yard'
6
+ YARD::Rake::YardocTask.new
7
+ doc_alias = 'doc:yard'
8
+ rescue LoadError
9
+ task :yard do
10
+ abort "YARD is not available. In order to run yardoc, you must install it"
11
+ end
12
+ end
13
+
14
+
15
+ namespace :doc do
16
+
17
+ desc 'Generate RDoc documentation'
18
+ Rake::RDocTask.new do |rd|
19
+ rdoc = PROJ.rdoc
20
+ rd.main = rdoc.main
21
+ rd.rdoc_dir = rdoc.dir
22
+
23
+ incl = Regexp.new(rdoc.include.join('|'))
24
+ excl = Regexp.new(rdoc.exclude.join('|'))
25
+ files = PROJ.gem.files.find_all do |fn|
26
+ case fn
27
+ when excl; false
28
+ when incl; true
29
+ else false end
30
+ end
31
+ rd.rdoc_files.push(*files)
32
+
33
+ name = PROJ.name
34
+ rf_name = PROJ.rubyforge.name
35
+
36
+ title = "#{name}-#{PROJ.version} Documentation"
37
+ title = "#{rf_name}'s " + title if rf_name.valid? and rf_name != name
38
+
39
+ rd.options << "-t #{title}"
40
+ rd.options.concat(rdoc.opts)
41
+ end
42
+
43
+ desc 'Generate ri locally for testing'
44
+ task :ri => :clobber_ri do
45
+ sh "#{RDOC} --ri -o ri ."
46
+ end
47
+
48
+ task :clobber_ri do
49
+ rm_r 'ri' rescue nil
50
+ end
51
+
52
+ desc 'Generate yardoc documentation'
53
+ task :yardoc => ['yard']
54
+
55
+ end # namespace :rdoc
56
+
57
+ doc_alias ||= 'doc:rdoc'
58
+
59
+ desc "Alias to #{doc_alias}"
60
+ task :doc => doc_alias
61
+
62
+ desc 'Remove all build products'
63
+ task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
64
+
65
+ remove_desc_for_task %w(doc:clobber_rdoc)
66
+ remove_desc_for_task %w(yard)
67
+
68
+
69
+ # EOF
@@ -0,0 +1,200 @@
1
+
2
+ require 'find'
3
+ require 'rake/packagetask'
4
+ require 'rubygems/user_interaction'
5
+ require 'rubygems/builder'
6
+
7
+ module Bones
8
+ class GemPackageTask < Rake::PackageTask
9
+ # Ruby GEM spec containing the metadata for this package. The
10
+ # name, version and package_files are automatically determined
11
+ # from the GEM spec and don't need to be explicitly provided.
12
+ #
13
+ attr_accessor :gem_spec
14
+
15
+ # Tasks from the Bones gem directory
16
+ attr_reader :bones_files
17
+
18
+ # Create a GEM Package task library. Automatically define the gem
19
+ # if a block is given. If no block is supplied, then +define+
20
+ # needs to be called to define the task.
21
+ #
22
+ def initialize(gem_spec)
23
+ init(gem_spec)
24
+ yield self if block_given?
25
+ define if block_given?
26
+ end
27
+
28
+ # Initialization tasks without the "yield self" or define
29
+ # operations.
30
+ #
31
+ def init(gem)
32
+ super(gem.name, gem.version)
33
+ @gem_spec = gem
34
+ @package_files += gem_spec.files if gem_spec.files
35
+ @bones_files = []
36
+
37
+ local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
38
+ if !test(?e, local_setup)
39
+ Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
40
+ end
41
+ end
42
+
43
+ # Create the Rake tasks and actions specified by this
44
+ # GemPackageTask. (+define+ is automatically called if a block is
45
+ # given to +new+).
46
+ #
47
+ def define
48
+ super
49
+ task :prereqs
50
+ task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
51
+ file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
52
+ when_writing("Creating GEM") {
53
+ chdir(package_dir_path) do
54
+ Gem::Builder.new(gem_spec).build
55
+ verbose(true) {
56
+ mv gem_file, "../#{gem_file}"
57
+ }
58
+ end
59
+ }
60
+ end
61
+
62
+ file package_dir_path => bones_files do
63
+ mkdir_p package_dir rescue nil
64
+
65
+ gem_spec.files = (gem_spec.files +
66
+ bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
67
+
68
+ bones_files.each do |fn|
69
+ base_fn = File.join('tasks', File.basename(fn))
70
+ f = File.join(package_dir_path, base_fn)
71
+ fdir = File.dirname(f)
72
+ mkdir_p(fdir) if !File.exist?(fdir)
73
+ if File.directory?(fn)
74
+ mkdir_p(f)
75
+ else
76
+ raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f)
77
+ safe_ln(fn, f)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def gem_file
84
+ if @gem_spec.platform == Gem::Platform::RUBY
85
+ "#{package_name}.gem"
86
+ else
87
+ "#{package_name}-#{@gem_spec.platform}.gem"
88
+ end
89
+ end
90
+ end # class GemPackageTask
91
+ end # module Bones
92
+
93
+ namespace :gem do
94
+
95
+ PROJ.gem._spec = Gem::Specification.new do |s|
96
+ s.name = PROJ.name
97
+ s.version = PROJ.version
98
+ s.summary = PROJ.summary
99
+ s.authors = Array(PROJ.authors)
100
+ s.email = PROJ.email
101
+ s.homepage = Array(PROJ.url).first
102
+
103
+ s.description = PROJ.description
104
+
105
+ PROJ.gem.dependencies.each do |dep|
106
+ s.add_dependency(*dep)
107
+ end
108
+
109
+ PROJ.gem.development_dependencies.each do |dep|
110
+ s.add_development_dependency(*dep)
111
+ end
112
+
113
+ s.files = PROJ.gem.files
114
+ s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
115
+ s.extensions = PROJ.gem.extensions
116
+
117
+ s.bindir = 'bin'
118
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
119
+ s.require_paths = dirs unless dirs.empty?
120
+
121
+ incl = Regexp.new(PROJ.rdoc.include.join('|'))
122
+ excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
123
+ excl = Regexp.new(excl.join('|'))
124
+ rdoc_files = PROJ.gem.files.find_all do |fn|
125
+ case fn
126
+ when excl; false
127
+ when incl; true
128
+ else false end
129
+ end
130
+ s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
131
+ s.extra_rdoc_files = rdoc_files
132
+ s.has_rdoc = true
133
+
134
+ if test ?f, PROJ.test.file
135
+ s.test_file = PROJ.test.file
136
+ else
137
+ s.test_files = PROJ.test.files.to_a
138
+ end
139
+
140
+ # Do any extra stuff the user wants
141
+ PROJ.gem.extras.each do |msg, val|
142
+ case val
143
+ when Proc
144
+ val.call(s.send(msg))
145
+ else
146
+ s.send "#{msg}=", val
147
+ end
148
+ end
149
+ end # Gem::Specification.new
150
+
151
+ Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg|
152
+ pkg.need_tar = PROJ.gem.need_tar
153
+ pkg.need_zip = PROJ.gem.need_zip
154
+ end
155
+
156
+ desc 'Show information about the gem'
157
+ task :debug => 'gem:prereqs' do
158
+ puts PROJ.gem._spec.to_ruby
159
+ end
160
+
161
+ desc 'Write the gemspec '
162
+ task :spec => 'gem:prereqs' do
163
+ File.open("#{PROJ.name}.gemspec", 'w') do |f|
164
+ f.write PROJ.gem._spec.to_ruby
165
+ end
166
+ end
167
+
168
+ desc 'Install the gem'
169
+ task :install => [:clobber, 'gem:package'] do
170
+ sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
171
+
172
+ # use this version of the command for rubygems > 1.0.0
173
+ #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
174
+ end
175
+
176
+ desc 'Uninstall the gem'
177
+ task :uninstall do
178
+ installed_list = Gem.source_index.find_name(PROJ.name)
179
+ if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
180
+ sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
181
+ end
182
+ end
183
+
184
+ desc 'Reinstall the gem'
185
+ task :reinstall => [:uninstall, :install]
186
+
187
+ desc 'Cleanup the gem'
188
+ task :cleanup do
189
+ sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
190
+ end
191
+ end # namespace :gem
192
+
193
+
194
+ desc 'Alias to gem:package'
195
+ task :gem => 'gem:package'
196
+
197
+ task :clobber => 'gem:clobber_package'
198
+ remove_desc_for_task 'gem:clobber_package'
199
+
200
+ # EOF
@@ -0,0 +1,40 @@
1
+
2
+ if HAVE_GIT
3
+
4
+ namespace :git do
5
+
6
+ # A prerequisites task that all other tasks depend upon
7
+ task :prereqs
8
+
9
+ desc 'Show tags from the Git repository'
10
+ task :show_tags => 'git:prereqs' do |t|
11
+ puts %x/git tag/
12
+ end
13
+
14
+ desc 'Create a new tag in the Git repository'
15
+ task :create_tag => 'git:prereqs' do |t|
16
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
17
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
18
+
19
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
20
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
21
+
22
+ puts "Creating Git tag '#{tag}'"
23
+ unless system "git tag -a -m '#{msg}' #{tag}"
24
+ abort "Tag creation failed"
25
+ end
26
+
27
+ if %x/git remote/ =~ %r/^origin\s*$/
28
+ unless system "git push origin #{tag}"
29
+ abort "Could not push tag to remote Git repository"
30
+ end
31
+ end
32
+ end
33
+
34
+ end # namespace :git
35
+
36
+ task 'gem:release' => 'git:create_tag'
37
+
38
+ end # if HAVE_GIT
39
+
40
+ # EOF
@@ -0,0 +1,34 @@
1
+
2
+ # This file does not define any rake tasks. It is used to load some project
3
+ # settings if they are not defined by the user.
4
+
5
+ PROJ.exclude << ["^#{Regexp.escape(PROJ.ann.file)}$",
6
+ "^#{Regexp.escape(PROJ.ignore_file)}$",
7
+ "^#{Regexp.escape(PROJ.rdoc.dir)}/",
8
+ "^#{Regexp.escape(PROJ.rcov.dir)}/"]
9
+
10
+ flatten_arrays = lambda do |this,os|
11
+ os.instance_variable_get(:@table).each do |key,val|
12
+ next if key == :dependencies \
13
+ or key == :development_dependencies
14
+ case val
15
+ when Array; val.flatten!
16
+ when OpenStruct; this.call(this,val)
17
+ end
18
+ end
19
+ end
20
+ flatten_arrays.call(flatten_arrays,PROJ)
21
+
22
+ PROJ.changes ||= paragraphs_of(PROJ.history_file, 0..1).join("\n\n")
23
+
24
+ PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
25
+
26
+ PROJ.summary ||= PROJ.description.split('.').first
27
+
28
+ PROJ.gem.files ||= manifest
29
+
30
+ PROJ.gem.executables ||= PROJ.gem.files.find_all {|fn| fn =~ %r/^bin/}
31
+
32
+ PROJ.rdoc.main ||= PROJ.readme_file
33
+
34
+ # EOF
@@ -0,0 +1,55 @@
1
+
2
+ if PROJ.rubyforge.name.valid? && HAVE_RUBYFORGE
3
+
4
+ require 'rubyforge'
5
+ require 'rake/contrib/sshpublisher'
6
+
7
+ namespace :gem do
8
+ desc 'Package and upload to RubyForge'
9
+ task :release => [:clobber, 'gem'] do |t|
10
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
11
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
12
+ pkg = "pkg/#{PROJ.gem._spec.full_name}"
13
+
14
+ if $DEBUG then
15
+ puts "release_id = rf.add_release #{PROJ.rubyforge.name.inspect}, #{PROJ.name.inspect}, #{PROJ.version.inspect}, \"#{pkg}.tgz\""
16
+ puts "rf.add_file #{PROJ.rubyforge.name.inspect}, #{PROJ.name.inspect}, release_id, \"#{pkg}.gem\""
17
+ end
18
+
19
+ rf = RubyForge.new
20
+ rf.configure rescue nil
21
+ puts 'Logging in'
22
+ rf.login
23
+
24
+ c = rf.userconfig
25
+ c['release_notes'] = PROJ.description if PROJ.description
26
+ c['release_changes'] = PROJ.changes if PROJ.changes
27
+ c['preformatted'] = true
28
+
29
+ files = Dir.glob("#{pkg}*.*")
30
+
31
+ puts "Releasing #{PROJ.name} v. #{PROJ.version}"
32
+ rf.add_release PROJ.rubyforge.name, PROJ.name, PROJ.version, *files
33
+ end
34
+ end # namespace :gem
35
+
36
+
37
+ namespace :doc do
38
+ desc "Publish RDoc to RubyForge"
39
+ task :release => %w(doc:clobber_rdoc doc:rdoc) do
40
+ config = YAML.load(
41
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
42
+ )
43
+
44
+ host = "#{config['username']}@rubyforge.org"
45
+ remote_dir = "/var/www/gforge-projects/#{PROJ.rubyforge.name}/"
46
+ remote_dir << PROJ.rdoc.remote_dir if PROJ.rdoc.remote_dir
47
+ local_dir = PROJ.rdoc.dir
48
+
49
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
50
+ end
51
+ end # namespace :doc
52
+
53
+ end # if HAVE_RUBYFORGE
54
+
55
+ # EOF