pcaprub 0.11.3 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTM1M2U0NmViOTRlNDVkNDk3ZWU5Yzk5NDI4OTk5MmQ0ZDE5ZWJlMg==
5
+ data.tar.gz: !binary |-
6
+ MzcyNDk3YTY1YjUzNGE2ZDQyYTQ1MTU4YTk3YjcyOGY3NGIxODIxMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OGYwOWYxMTM1Y2VjOTE0NzBlOTA1NTljMzJkNmFlZWEyOWQ2MTI2MDE0ODVh
10
+ NDJkNjgxOTM3ODk4YzRhMjFlMDMwYTcxZjM3Mzk4OTJiNTI5ODhiOTU5NmVm
11
+ MTBhNGQxNTI0ZDMyNGJmMmRhNzJlYmUzNjZhZGEzNjFiYjAyMTA=
12
+ data.tar.gz: !binary |-
13
+ ODc3OGFhY2RjZmEwNzIzM2IwNGQ1OGNiMTQ5MzhmY2JiMDUyNDA5NDAxYTZm
14
+ MGJmZDJmNGVkNmM4YjY4MjMwZTYwODI2NTc3OGE4MTNmZDAyZTE3MGM3Y2Qy
15
+ YzBhNTcyYTMxOTZkZTQ4YmIzY2Y2ZWQyYmZkOWQ5Mjc1MWYxODE=
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ before_install:
3
+ - sudo apt-get install libpcap-dev -qq
4
+ rvm:
5
+ - 1.8.7
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - 2.1.0
9
+ # - ruby-head
10
+ script:
11
+ - rvmsudo bundle exec rake
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # No more static spec file
4
+
5
+ platforms :ruby_18 do
6
+ gem 'rdoc'
7
+ end
8
+
9
+ group :development, :test do
10
+ # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
11
+ gem 'minitest', '~> 4.7.0'
12
+ gem 'shoulda-context', '~> 1.1.6'
13
+ platforms :ruby_19, :ruby_20, :ruby_21 do
14
+ gem 'coveralls', :require => false
15
+ end
16
+ end
17
+
18
+ gem 'rake', '>= 0.9.2'
19
+ gem 'rake-compiler', '>= 0.6.0'
20
+ gem 'rubygems-tasks'
@@ -1,18 +1,36 @@
1
1
  = pcaprub
2
2
 
3
+ {<img src="https://travis-ci.org/pcaprub/pcaprub.png" alt="Build Status" />}[https://travis-ci.org/pcaprub/pcaprub]
4
+ {<img src="https://codeclimate.com/github/pcaprub/pcaprub.png" />}[https://codeclimate.com/github/pcaprub/pcaprub]
5
+ {<img src="https://badge.fury.io/rb/pcaprub.png" alt="Gem Version" />}[http://badge.fury.io/rb/pcaprub]
6
+ {<img src="https://gemnasium.com/pcaprub/pcaprub.svg" alt="Dependency Status" />}[https://gemnasium.com/pcaprub/pcaprub]
7
+
3
8
  This goal of this project is to provide a consistent interface
4
- to LBL's libpcap packet capture library. This project was created
5
- because the currently available ruby-pcap library is poorly designed
6
- and has been unmaintained since 2000.
9
+ to LBL's libpcap packet capture library.
10
+
11
+ == Limitations
7
12
 
8
13
  This does not provide packet processing functionality, it simply provides
9
14
  the interface for capturing packets, and passing yielding those packets.
10
15
 
11
- For true packet processing capability look at PCAPFU PCAPLET etc..
16
+ For packet processing capability look at ruby gems PCAPFU, PCAPLET, etc..
17
+
18
+ == Requirements
19
+
20
+ MRI POSIX Ruby (Native compilation)
21
+ Ruby 1.8.7 (EOL June 2014)
22
+ Ruby 1.9.3 or higher
23
+ Ruby 2.x or higher
12
24
 
13
- Requirements:
14
25
  libpcap - http://www.tcpdump.org
15
26
 
27
+ MRI Windows Ruby (Native compilation)
28
+ Ruby 1.8.7 (EOL June 2014)
29
+ Ruby 1.9.3 or higher
30
+ Ruby 2.x or higher
31
+
32
+ WinPcap - http://www.winpcap.org
33
+
16
34
  == Installation
17
35
 
18
36
  gem install pcaprub
@@ -26,10 +44,12 @@ Requirements:
26
44
 
27
45
  == Current Repository for Gemcutter source
28
46
 
29
- The Git Repo on Github @shadowbq is forked from the Metasploit SVN repo
30
- git clone git://github.com/shadowbq/pcaprub.git
47
+ The Git Repo on Github @pcaprub is forked from the Metasploit SVN repo
48
+ git clone git://github.com/pcaprub/pcaprub.git
49
+
50
+ == Additionals
31
51
 
32
- == Notes on 11.x series and beyond.
52
+ === Notes on 0.11.x series and beyond.
33
53
 
34
54
  The gem is now a module. The module is autoincluded, but this helps with name collisions and additional growth.
35
55
 
@@ -42,7 +62,7 @@ The file handling in dumper is now attached to the Capture Class and not the Mod
42
62
  { ... }
43
63
  capture.dump_close
44
64
 
45
- == Timstamps from the PCAP Header
65
+ === Timstamps from the PCAP Header
46
66
 
47
67
  Timestamps are now available when yeilding packets instead of strings
48
68
 
@@ -52,7 +72,29 @@ Timestamps are now available when yeilding packets instead of strings
52
72
  puts "micro => #{packet.microsec}"
53
73
  end
54
74
 
55
- === Notes on other repositories
75
+ === Ruby 1.8.7 & WinPcap
76
+
77
+ On Ruby 1.8 with winpcap, rb_thread_polling pauses for 100 milliseconds between reads. This may mean some packets are missed.
78
+
79
+
80
+ == LICENSE
81
+
82
+ GNU Lesser General Public License v2.1 (LGPL-2.1)
83
+
84
+ https://www.tldrlegal.com/l/lgpl2
85
+
86
+ See LICENCE for details
87
+
88
+ Copyright © 2010 - 2014
89
+
90
+ === Notes on other repositories in compliance with LGPL-2.1
91
+
92
+ All original code maintains its copyright from its original authors and licensing.
93
+
94
+ On March 2014 this project was migrated to https://github.com/pcaprub/pcaprub from https://github.com/shadowbq/pcaprub
95
+
96
+ The Git Repo on Github @pcaprub is a forked merge from the Metasploit SVN repo
97
+ git clone git://github.com/shadowbq/pcaprub.git (moved)
56
98
 
57
99
  The Metasploit Project also provides a Subversion repository: (0.9-dev)
58
100
  svn checkout http://metasploit.com/svn/framework3/trunk/external/pcaprub/
@@ -60,14 +102,16 @@ The Metasploit Project also provides a Subversion repository: (0.9-dev)
60
102
  Packetfu Project also provides a listing (0.9-dev)
61
103
  http://code.google.com/p/packetfu/source/browse/#svn/trunk/pcaprub_linux
62
104
 
63
- The Outdate RubyForge svn version can be obtained from Subversion: (0.7-dev)
105
+ The Marshall Beddoe's Outdate RubyForge svn version can be obtained from Subversion: (0.7-dev)
64
106
  svn checkout http://pcaprub.rubyforge.org/svn/trunk/
65
107
  http download Public Rubyforge (0.6)
108
+ https://github.com/unmarshal/pcaprub
66
109
 
67
110
  SourceForge Masaki Fukushima 2000 (0.6) -- Object Creation Heavy Implementation (PCAPLET integrated)
68
111
  http://sourceforge.net/apps/trac/rubypcap/
69
112
 
70
113
  Additonal Github Repos
71
- github.com/dxoigmn/pcaprub (0.8-dev)
72
- github.com/spox /pcaprub-spox (0.8-dev+)
114
+ https://github.com/dxoigmn/pcaprub (0.8-dev)
115
+ https://github.com/spox /pcaprub-spox (0.8-dev+)
116
+
73
117
 
data/Rakefile CHANGED
@@ -1,56 +1,67 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require 'rake/clean'
4
- require './lib/pcaprub/version'
1
+ #require "bundler/gem_tasks"
2
+ require './lib/pcaprub/version.rb'
5
3
 
6
- desc "Build the extension:"
7
- task :compile => %W[ext/pcaprub/Makefile ext/pcaprub/pcaprub.c]
4
+ def java?
5
+ /java/ === RUBY_PLATFORM
6
+ end
8
7
 
8
+ ENV['LANG'] = "en_US.UTF-8"
9
9
 
10
- file "ext/pcaprub/Makefile" => ["ext/pcaprub/extconf.rb"] do
11
- Dir.chdir("ext/pcaprub") do
12
- ruby "extconf.rb"
13
- sh "make"
14
- end
15
- cp "ext/pcaprub/pcaprub.so", "lib"
16
- end
17
10
 
18
- CLEAN.include 'ext/**/Makefile'
19
- CLEAN.include 'ext/**/*.o'
20
- CLEAN.include 'ext/**/mkmf.log'
21
- CLEAN.include 'ext/**/*.so'
22
- CLEAN.include 'lib/**/*.so'
11
+ @gemspec = Gem::Specification.new do |spec|
12
+ spec.name = "pcaprub"
13
+ spec.version = PCAPRUB::Pcap.version
14
+ spec.authors = ["shadowbq", "crondaemon", "jmcavinee", "unmarshal"]
15
+ spec.email = "shadowbq@gmail.com"
16
+ spec.description = "libpcap bindings for ruby with Ruby1.8, Ruby1.9, Ruby 2.x"
17
+ spec.summary = "libpcap bindings for ruby"
18
+ spec.homepage = "https://github.com/pcaprub/pcaprub"
19
+ spec.requirements = "libpcap"
20
+ spec.license = "LGPL-2.1"
23
21
 
24
- begin
25
- require 'jeweler'
26
- jeweler_tasks = Jeweler::Tasks.new do |gem|
27
- gem.name = "pcaprub"
28
- gem.summary = "libpcap bindings for ruby"
29
- gem.description = "libpcap bindings for ruby compat with JRUBY Ruby1.8 Ruby1.9"
30
- gem.email = "shadowbq@gmail.com"
31
- gem.homepage = "http://github.com/shadowbq/pcaprub"
32
- gem.authors = ["shadowbq"]
33
- gem.extensions = FileList['ext/**/extconf.rb']
34
- gem.rubyforge_project = 'pcaprub'
35
- gem.version = PCAPRUB::VERSION::STRING
36
- gem.files.include('lib/pcaprub.*') # add native stuff
37
- gem.extra_rdoc_files = FileList['README*', 'ChangeLog*', 'LICENSE*', 'FAQ*', 'USAGE*', 'ext/**/*.c']
38
- end
39
-
40
- $gemspec = jeweler_tasks.gemspec
41
- $gemspec.version = jeweler_tasks.jeweler.version
42
-
43
- Jeweler::GemcutterTasks.new
44
- rescue LoadError
45
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
46
- end
22
+ spec.files = [
23
+ ".document",
24
+ ".travis.yml",
25
+ "FAQ.rdoc",
26
+ "Gemfile",
27
+ "LICENSE",
28
+ "README.rdoc",
29
+ "Rakefile",
30
+ "USAGE.rdoc",
31
+ "examples/dead_cap.rb",
32
+ "examples/file_cap.rb",
33
+ "examples/simple_cap.rb",
34
+ "examples/telnet-raw.pcap",
35
+ "ext/pcaprub_c/extconf.rb",
36
+ "ext/pcaprub_c/pcaprub.c",
37
+ "lib/pcaprub.rb",
38
+ "lib/pcaprub/common.rb",
39
+ "lib/pcaprub/ext.rb",
40
+ "lib/pcaprub/version.rb",
41
+ "test/helper.rb",
42
+ "test/test_pcaprub.rb",
43
+ "test/test_pcaprub_unit.rb"
44
+ ]
47
45
 
48
- require "rubygems/package_task"
49
- Gem::PackageTask.new($gemspec) do |package|
50
- package.need_zip = false
51
- package.need_tar = false
52
- end
46
+ spec.extra_rdoc_files = [
47
+ "FAQ.rdoc",
48
+ "LICENSE",
49
+ "README.rdoc",
50
+ "USAGE.rdoc",
51
+ "ext/pcaprub_c/pcaprub.c"
52
+ ]
53
+ spec.extensions = FileList["ext/**/extconf.rb"]
54
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
55
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
56
+ spec.require_paths = ["lib"]
57
+
58
+ spec.add_development_dependency "bundler", "~> 1.3"
59
+ spec.add_development_dependency "rake", '>= 0.9.2'
60
+ spec.add_development_dependency "rake-compiler", '>= 0.6.0'
61
+ spec.add_development_dependency "shoulda-context", '~> 1.1.6'
62
+ spec.add_development_dependency "minitest", '~> 4.7.0'
53
63
 
64
+ end
54
65
 
55
66
  require 'rake/testtask'
56
67
  Rake::TestTask.new(:test) do |test|
@@ -72,13 +83,21 @@ rescue LoadError
72
83
  end
73
84
  end
74
85
 
75
- task :test => :check_dependencies
86
+ task :test
76
87
 
77
- task :default => %w[clean compile test]
88
+ require 'rubygems/package_task'
89
+ Gem::PackageTask.new(@gemspec) do |pkg|
90
+ pkg.need_zip = false
91
+ pkg.need_tar = false
92
+ end
93
+
94
+ require 'rake/extensiontask'
95
+ Rake::ExtensionTask.new('pcaprub_c', @gemspec)
96
+
97
+ task :default => [:compile, :test]
78
98
 
79
99
  require 'rdoc/task'
80
100
  RDoc::Task.new do |rdoc|
81
-
82
101
  version = PCAPRUB::VERSION::STRING
83
102
  rdoc.rdoc_dir = 'rdoc'
84
103
  rdoc.title = "pcaprub #{version}"
@@ -88,3 +107,6 @@ RDoc::Task.new do |rdoc|
88
107
  rdoc.rdoc_files.include('lib/**/*.rb')
89
108
  rdoc.rdoc_files.include('ext/**/*.c')
90
109
  end
110
+
111
+ require 'rubygems/tasks'
112
+ Gem::Tasks.new
@@ -1,27 +1,29 @@
1
1
  require 'mkmf'
2
- extension_name = 'pcaprub'
2
+ extension_name = 'pcaprub_c'
3
3
 
4
4
  puts "\n[*] Running checks for #{extension_name} code..."
5
5
  puts("platform is #{RUBY_PLATFORM}")
6
6
 
7
7
  if /i386-mingw32/ =~ RUBY_PLATFORM
8
-
9
- unless have_library("ws2_32" ) and
10
- have_library("iphlpapi") and
11
- have_header("windows.h") and
12
- have_header("winsock2.h") and
13
- have_header("iphlpapi.h")
14
- puts "\nNot all dependencies are satisfied for #{RUBY_PLATFORM} platform requirements"
15
- exit
16
- end
17
-
18
- pcap_dir = with_config("pcap-dir", "C:/WpdPack")
8
+
9
+ unless have_library("ws2_32" ) and
10
+ have_library("iphlpapi") and
11
+ have_header("windows.h") and
12
+ have_header("winsock2.h") and
13
+ have_header("iphlpapi.h")
14
+ puts "\nNot all dependencies are satisfied for #{RUBY_PLATFORM} platform requirements"
15
+ exit
16
+ end
17
+
18
+ pcap_dir = with_config("pcap-dir", "C:/WpdPack")
19
19
  pcap_includedir = with_config("pcap-includedir", pcap_dir + "/include")
20
20
  pcap_libdir = with_config("pcap-libdir", pcap_dir + "/lib")
21
-
21
+ $CFLAGS = "-DWIN32 -I#{pcap_includedir}"
22
+ $LDFLAGS = "-L#{pcap_libdir}"
23
+
22
24
  have_library("wpcap", "pcap_open_live")
23
- have_library("wpcap", "pcap_setnonblock")
24
-
25
+ have_library("wpcap", "pcap_setnonblock")
26
+
25
27
  elsif /i386-mswin32/ =~ RUBY_PLATFORM
26
28
  pcap_dir = with_config("pcap-dir", "C:\\WpdPack")
27
29
  pcap_includedir = with_config("pcap-includedir", pcap_dir + "\\include")
@@ -30,18 +32,10 @@ elsif /i386-mswin32/ =~ RUBY_PLATFORM
30
32
  $CFLAGS = "-DWIN32 -I#{pcap_includedir}"
31
33
  $LDFLAGS = "/link /LIBPATH:#{pcap_libdir}"
32
34
  have_library("wpcap", "pcap_open_live")
33
- have_library("wpcap", "pcap_setnonblock")
35
+ have_library("wpcap", "pcap_setnonblock")
34
36
  else
35
- have_library("pcap", "pcap_open_live")
36
- have_library("pcap", "pcap_setnonblock")
37
+ have_library("pcap", "pcap_open_live", ["pcap.h"])
38
+ have_library("pcap", "pcap_setnonblock", ["pcap.h"])
37
39
  end
38
40
 
39
- if ( RUBY_VERSION =~ /^1\.8/ && !defined?(JRUBY_VERSION) )
40
- $CFLAGS += " -DMAKE_TRAP"
41
- end
42
-
43
-
44
- dir_config(extension_name)
45
41
  create_makefile(extension_name)
46
-
47
-
@@ -6,6 +6,9 @@
6
6
 
7
7
 
8
8
  #include <pcap.h>
9
+ #if defined(WIN32)
10
+ #include <Win32-Extensions.h>
11
+ #endif
9
12
 
10
13
  #if !defined(WIN32)
11
14
  #include <netinet/in.h>
@@ -17,6 +20,10 @@ static VALUE mPCAP;
17
20
  static VALUE rb_cPcap, rb_cPkt;
18
21
  static VALUE ePCAPRUBError, eDumperError, eBindingError, eBPFilterError;
19
22
 
23
+ #if defined(WIN32)
24
+ static VALUE rbpcap_thread_wait_handle(HANDLE fno);
25
+ #endif
26
+
20
27
  // Now defined in Native Ruby
21
28
  // #define PCAPRUB_VERSION "*.*.*"
22
29
 
@@ -25,8 +32,8 @@ static VALUE ePCAPRUBError, eDumperError, eBindingError, eBPFilterError;
25
32
 
26
33
  #if !defined(PCAP_NETMASK_UNKNOWN)
27
34
  /*
28
- * Version of libpcap < 1.1
29
- * Value to pass to pcap_compile() as the netmask if you dont know what the netmask is.
35
+ * Version of libpcap < 1.1
36
+ * Value to pass to pcap_compile() as the netmask if you dont know what the netmask is.
30
37
  */
31
38
  #define PCAP_NETMASK_UNKNOWN 0xffffffff
32
39
  #endif
@@ -46,7 +53,7 @@ typedef struct rbpcapjob {
46
53
  } rbpcapjob_t;
47
54
 
48
55
  typedef struct rbpacket {
49
- struct pcap_pkthdr* hdr;
56
+ struct pcap_pkthdr hdr;
50
57
  u_char* pkt;
51
58
  } rbpacket_t;
52
59
 
@@ -61,7 +68,7 @@ rbpcap_s_lookupdev(VALUE self)
61
68
  char *dev = NULL;
62
69
  char eb[PCAP_ERRBUF_SIZE];
63
70
  VALUE ret_dev; /* device string to return */
64
- #if defined(WIN32) /* pcap_lookupdev is broken on windows */
71
+ #if defined(WIN32) /* pcap_lookupdev is broken on windows */
65
72
  pcap_if_t *alldevs;
66
73
  pcap_if_t *d;
67
74
 
@@ -77,7 +84,7 @@ rbpcap_s_lookupdev(VALUE self)
77
84
  break;
78
85
  }
79
86
  }
80
-
87
+
81
88
  if (dev == NULL) {
82
89
  rb_raise(eBindingError,"%s","No valid interfaces found, Make sure WinPcap is installed.\n");
83
90
  }
@@ -104,7 +111,7 @@ rbpcap_s_lookupnet(VALUE self, VALUE dev)
104
111
  struct in_addr addr;
105
112
  char eb[PCAP_ERRBUF_SIZE];
106
113
  VALUE list;
107
-
114
+
108
115
  Check_Type(dev, T_STRING);
109
116
  if (pcap_lookupnet(StringValuePtr(dev), &net, &mask, eb) == -1) {
110
117
  rb_raise(rb_eRuntimeError, "%s", eb);
@@ -119,7 +126,7 @@ rbpcap_s_lookupnet(VALUE self, VALUE dev)
119
126
  }
120
127
 
121
128
  /*
122
- * Check if PCAP file or device is bound and loaded
129
+ * Check if PCAP file or device is bound and loaded
123
130
  */
124
131
  static int rbpcap_ready(rbpcap_t *rbp) {
125
132
  if(! rbp->pd) {
@@ -130,14 +137,13 @@ static int rbpcap_ready(rbpcap_t *rbp) {
130
137
  }
131
138
 
132
139
 
133
-
134
140
  /*
135
141
  * Automated Garbage Collection for Pcap Class
136
142
  */
137
143
  static void rbpcap_free(rbpcap_t *rbp) {
138
144
  if (rbp->pd)
139
145
  pcap_close(rbp->pd);
140
-
146
+
141
147
  if (rbp->pdt)
142
148
  pcap_dump_close(rbp->pdt);
143
149
 
@@ -151,15 +157,11 @@ static void rbpcap_free(rbpcap_t *rbp) {
151
157
  */
152
158
  static void rbpacket_free(rbpacket_t *rbpacket)
153
159
  {
154
-
155
- if(rbpacket->hdr != NULL) {
156
- rbpacket->hdr = NULL;
157
- }
158
-
160
+
159
161
  if(rbpacket->pkt != NULL) {
160
162
  rbpacket->pkt = NULL;
161
163
  }
162
-
164
+
163
165
  free(rbpacket);
164
166
  }
165
167
 
@@ -199,16 +201,129 @@ rbpacket_new_s(VALUE class)
199
201
  return self;
200
202
  }
201
203
 
204
+
205
+ /*
206
+ * call-seq:
207
+ * setmonitor(true)
208
+ *
209
+ * Set monitor mode for the capture.
210
+ *
211
+ * Returns the object itself.
212
+ */
213
+ static VALUE
214
+ rbpcap_setmonitor(VALUE self, VALUE mode)
215
+ {
216
+ rbpcap_t *rbp;
217
+ int rfmon_mode = 0;
218
+ Data_Get_Struct(self, rbpcap_t, rbp);
219
+ if (mode == Qtrue) {
220
+ rfmon_mode = 1;
221
+ } else if (mode == Qfalse) {
222
+ rfmon_mode = 0;
223
+ } else {
224
+ rb_raise(rb_eArgError, "Monitor mode must be a boolean");
225
+ }
226
+
227
+ #if defined(WIN32)
228
+ // monitor mode support was disabled in WinPcap 4.0.2
229
+ rb_raise(ePCAPRUBError, "set monitor mode not supported in WinPcap");
230
+ #else
231
+ if (pcap_set_rfmon(rbp->pd, rfmon_mode) == 0) {
232
+ return self;
233
+ } else {
234
+ rb_raise(ePCAPRUBError, "unable to set monitor mode");
235
+ }
236
+ #endif
237
+ }
238
+
239
+ /*
240
+ * call-seq:
241
+ * settimeout(1234)
242
+ *
243
+ * Set timeout for the capture.
244
+ *
245
+ * Returns the object itself.
246
+ */
247
+ static VALUE
248
+ rbpcap_settimeout(VALUE self, VALUE timeout)
249
+ {
250
+ rbpcap_t *rbp;
251
+ Data_Get_Struct(self, rbpcap_t, rbp);
252
+
253
+ if(TYPE(timeout) != T_FIXNUM)
254
+ rb_raise(rb_eArgError, "timeout must be a fixnum");
255
+
256
+ if (pcap_set_timeout(rbp->pd, NUM2INT(timeout)) == 0) {
257
+ return self;
258
+ } else {
259
+ rb_raise(ePCAPRUBError, "unable to set timeout");
260
+ }
261
+ }
262
+
263
+
264
+ /*
265
+ * call-seq:
266
+ * setsnaplen(true)
267
+ *
268
+ * Set snap length for the capture.
269
+ *
270
+ * Returns the object itself.
271
+ */
272
+ static VALUE
273
+ rbpcap_setsnaplen(VALUE self, VALUE snaplen)
274
+ {
275
+ rbpcap_t *rbp;
276
+ Data_Get_Struct(self, rbpcap_t, rbp);
277
+
278
+ if(TYPE(snaplen) != T_FIXNUM)
279
+ rb_raise(rb_eArgError, "snaplen must be a fixnum");
280
+
281
+ if (pcap_set_snaplen(rbp->pd, NUM2INT(snaplen)) == 0) {
282
+ return self;
283
+ } else {
284
+ rb_raise(ePCAPRUBError, "unable to set snap length");
285
+ }
286
+ }
287
+
288
+ /*
289
+ * call-seq:
290
+ * setpromisc(true)
291
+ *
292
+ * Set promiscuous mode for the capture.
293
+ *
294
+ * Returns the object itself.
295
+ */
296
+ static VALUE
297
+ rbpcap_setpromisc(VALUE self, VALUE mode)
298
+ {
299
+ rbpcap_t *rbp;
300
+ int promisc_mode = 0;
301
+ Data_Get_Struct(self, rbpcap_t, rbp);
302
+ if (mode == Qtrue) {
303
+ promisc_mode = 1;
304
+ } else if (mode == Qfalse) {
305
+ promisc_mode = 0;
306
+ } else {
307
+ rb_raise(rb_eArgError, "Promisc mode must be a boolean");
308
+ }
309
+
310
+ if (pcap_set_promisc(rbp->pd, promisc_mode) == 0) {
311
+ return self;
312
+ } else {
313
+ rb_raise(ePCAPRUBError, "unable to set promiscuous mode");
314
+ }
315
+ }
316
+
202
317
  /*
203
318
  * call-seq:
204
319
  * setfilter(filter)
205
320
  *
206
321
  * Provide a valid bpf-filter to apply to the packet capture
207
- *
322
+ *
208
323
  * # Show me all SYN packets:
209
324
  * bpf-filter = "tcp[13] & 2 != 0"
210
325
  * capture.setfilter(bpf-filter)
211
- *
326
+ *
212
327
  * Examples:
213
328
  * * "net 10.0.0.0/8"
214
329
  * * "not tcp and dst host 192.168.1.1"
@@ -228,8 +343,8 @@ rbpcap_setfilter(VALUE self, VALUE filter)
228
343
  if(TYPE(filter) != T_STRING)
229
344
  rb_raise(eBPFilterError, "filter must be a string");
230
345
 
231
- if(! rbpcap_ready(rbp)) return self;
232
-
346
+ if(! rbpcap_ready(rbp)) return self;
347
+
233
348
  if(rbp->type == LIVE)
234
349
  if(pcap_lookupnet(rbp->iface, &netid, &mask, eb) < 0) {
235
350
  netid = 0;
@@ -246,6 +361,93 @@ rbpcap_setfilter(VALUE self, VALUE filter)
246
361
  return self;
247
362
  }
248
363
 
364
+ /*
365
+ * Activate the interface
366
+ *
367
+ * call-seq:
368
+ * activate() -> self
369
+ *
370
+ * Returns the object itself.
371
+ */
372
+ static VALUE
373
+ rbpcap_activate(VALUE self)
374
+ {
375
+ rbpcap_t *rbp;
376
+ int errcode;
377
+ Data_Get_Struct(self, rbpcap_t, rbp);
378
+
379
+ if ((errcode = pcap_activate(rbp->pd)) == 0) {
380
+ return self;
381
+ } else {
382
+ rb_raise(ePCAPRUBError, "unable to activate interface: %d, %s", errcode, rbp->iface);
383
+ }
384
+ }
385
+
386
+
387
+ /*
388
+ * Close the interface
389
+ *
390
+ * call-seq:
391
+ * activate() -> self
392
+ *
393
+ * Returns the object itself.
394
+ */
395
+ static VALUE
396
+ rbpcap_close(VALUE self)
397
+ {
398
+ rbpcap_t *rbp;
399
+ Data_Get_Struct(self, rbpcap_t, rbp);
400
+
401
+ pcap_close(rbp->pd);
402
+ rbp->pd = NULL;
403
+ return self;
404
+ }
405
+
406
+ static VALUE
407
+ rbpcap_create(VALUE self, VALUE iface)
408
+ {
409
+ rbpcap_t *rbp;
410
+ char eb[PCAP_ERRBUF_SIZE];
411
+
412
+ Data_Get_Struct(self, rbpcap_t, rbp);
413
+
414
+ rbp->type = LIVE;
415
+ memset(rbp->iface, 0, sizeof(rbp->iface));
416
+ strncpy(rbp->iface, RSTRING_PTR(iface), sizeof(rbp->iface) - 1);
417
+
418
+ if(rbp->pd) {
419
+ pcap_close(rbp->pd);
420
+ }
421
+
422
+ rbp->pd = pcap_create(
423
+ RSTRING_PTR(iface),
424
+ eb
425
+ );
426
+
427
+ if(!rbp->pd)
428
+ rb_raise(rb_eRuntimeError, "%s", eb);
429
+
430
+ return self;
431
+ }
432
+
433
+ /*
434
+ *
435
+ * call-seq:
436
+ * create(iface) -> self
437
+ *
438
+ * capture = ::Pcap.create(@dev)
439
+ *
440
+ * Returns the object itself.
441
+ */
442
+ static VALUE
443
+ rbpcap_create_s(VALUE class, VALUE iface)
444
+ {
445
+ VALUE iPcap = rb_funcall(rb_cPcap, rb_intern("new"), 0);
446
+ return rbpcap_create(iPcap, iface);
447
+ }
448
+
449
+
450
+
249
451
  // transparent method
250
452
  static VALUE
251
453
  rbpcap_open_live(VALUE self, VALUE iface,VALUE snaplen,VALUE promisc, VALUE timeout)
@@ -281,7 +483,7 @@ rbpcap_open_live(VALUE self, VALUE iface,VALUE snaplen,VALUE promisc, VALUE time
281
483
 
282
484
 
283
485
  if(rbp->pd) {
284
- pcap_close(rbp->pd);
486
+ pcap_close(rbp->pd);
285
487
  }
286
488
 
287
489
  rbp->pd = pcap_open_live(
@@ -299,13 +501,13 @@ rbpcap_open_live(VALUE self, VALUE iface,VALUE snaplen,VALUE promisc, VALUE time
299
501
  }
300
502
 
301
503
  /*
302
- *
504
+ *
303
505
  * call-seq:
304
506
  * open_live(iface, snaplen, promisc, timeout) -> self
305
507
  *
306
508
  * capture = ::Pcap.open_live(@dev, @snaplength, @promiscous_mode, @timeout)
307
509
  *
308
- * Returns the object itself.
510
+ * Returns the object itself.
309
511
  */
310
512
  static VALUE
311
513
  rbpcap_open_live_s(VALUE class, VALUE iface, VALUE snaplen, VALUE promisc, VALUE timeout)
@@ -341,11 +543,11 @@ rbpcap_open_offline(VALUE self, VALUE filename)
341
543
  }
342
544
 
343
545
  /*
344
- *
546
+ *
345
547
  * call-seq:
346
548
  * open_offline(filename) -> self
347
549
  *
348
- * capture = ::Pcap.open_offline(filename)
550
+ * capture = ::Pcap.open_offline(filename)
349
551
  *
350
552
  * Returns the object itself.
351
553
  */
@@ -357,7 +559,7 @@ rbpcap_open_offline_s(VALUE class, VALUE filename)
357
559
  return rbpcap_open_offline(iPcap, filename);
358
560
  }
359
561
 
360
- // transparent method
562
+ // transparent method
361
563
  static VALUE
362
564
  rbpcap_open_dead(VALUE self, VALUE linktype, VALUE snaplen)
363
565
  {
@@ -384,7 +586,7 @@ rbpcap_open_dead(VALUE self, VALUE linktype, VALUE snaplen)
384
586
 
385
587
 
386
588
  /*
387
- *
589
+ *
388
590
  * call-seq:
389
591
  * open_dead(linktype, snaplen) -> self
390
592
  *
@@ -420,19 +622,19 @@ rbpcap_dump_open(VALUE self, VALUE filename)
420
622
 
421
623
  if(TYPE(filename) != T_STRING)
422
624
  rb_raise(rb_eArgError, "filename must be a string");
423
-
625
+
424
626
  Data_Get_Struct(self, rbpcap_t, rbp);
425
-
627
+
426
628
  if(! rbpcap_ready(rbp)) return self;
427
-
629
+
428
630
  rbp->pdt = pcap_dump_open(
429
631
  rbp->pd,
430
632
  RSTRING_PTR(filename)
431
633
  );
432
-
634
+
433
635
  if(!rbp->pdt)
434
636
  rb_raise(eDumperError, "Stream could not be initialized or opened.");
435
-
637
+
436
638
  return self;
437
639
  }
438
640
 
@@ -446,21 +648,21 @@ static VALUE
446
648
  rbpcap_dump_close(VALUE self)
447
649
  {
448
650
  rbpcap_t *rbp;
449
-
651
+
450
652
  Data_Get_Struct(self, rbpcap_t, rbp);
451
-
653
+
452
654
  if(! rbpcap_ready(rbp)) return self;
453
-
655
+
454
656
  if(!rbp->pdt)
455
657
  rb_raise(eDumperError, "Stream is already closed.");
456
-
658
+
457
659
  if (rbp->pdt)
458
660
  pcap_dump_close(rbp->pdt);
459
-
460
- rbp->pdt = NULL;
661
+
662
+ rbp->pdt = NULL;
461
663
 
462
664
  return self;
463
-
665
+
464
666
  }
465
667
 
466
668
 
@@ -488,17 +690,21 @@ rbpcap_dump(VALUE self, VALUE caplen, VALUE pktlen, VALUE packet)
488
690
  rb_raise(rb_eArgError, "pktlen must be a fixnum");
489
691
 
490
692
  Data_Get_Struct(self, rbpcap_t, rbp);
491
-
693
+
492
694
  gettimeofday(&pcap_hdr.ts, NULL);
493
695
  pcap_hdr.caplen = NUM2UINT(caplen);
494
696
  pcap_hdr.len = NUM2UINT(pktlen);
495
697
 
496
- //capture.next is yeilding an 8Bit ASCII string
698
+ if(!rbp->pdt) {
699
+ rb_raise(rb_eRuntimeError, "pcap_dumper not defined. You must open a dump file first");
700
+ }
701
+
702
+ //capture.next is yeilding an 8Bit ASCII string
497
703
  // -> return rb_str_new((char *) job.pkt, job.hdr.caplen);
498
704
  //Call dump such that capture.next{|pk| capture.dump(pk.length, pk.length, pk)}
499
705
 
500
- pcap_dump(
501
- (u_char*)rbp->pdt,
706
+ pcap_dump(
707
+ (u_char*)rbp->pdt,
502
708
  &pcap_hdr,
503
709
  (unsigned char *)RSTRING_PTR(packet)
504
710
  );
@@ -512,8 +718,8 @@ rbpcap_dump(VALUE self, VALUE caplen, VALUE pktlen, VALUE packet)
512
718
  * call-seq:
513
719
  * inject(payload)
514
720
  *
515
- * inject() transmit a raw packet through the network interface
516
- *
721
+ * inject() transmit a raw packet through the network interface
722
+ *
517
723
  * Returns the number of bytes written on success else raise failure.
518
724
  */
519
725
  static VALUE
@@ -522,13 +728,13 @@ rbpcap_inject(VALUE self, VALUE payload)
522
728
  rbpcap_t *rbp;
523
729
 
524
730
  if(TYPE(payload) != T_STRING)
525
- rb_raise(rb_eArgError, "payload must be a string");
731
+ rb_raise(rb_eArgError, "pupayload must be a string");
526
732
 
527
733
  Data_Get_Struct(self, rbpcap_t, rbp);
528
734
 
529
- if(! rbpcap_ready(rbp)) return self;
530
- #if defined(WIN32)
531
- /* WinPcap does not have a pcap_inject call we use pcap_sendpacket, if it suceedes
735
+ if(! rbpcap_ready(rbp)) return self;
736
+ #if defined(WIN32)
737
+ /* WinPcap does not have a pcap_inject call we use pcap_sendpacket, if it suceedes
532
738
  * we simply return the amount of packets request to inject, else we fail.
533
739
  */
534
740
  if(pcap_sendpacket(rbp->pd, RSTRING_PTR(payload), RSTRING_LEN(payload)) != 0) {
@@ -555,7 +761,7 @@ static void rbpcap_handler(rbpcapjob_t *job, struct pcap_pkthdr *hdr, u_char *pk
555
761
  /*
556
762
  **
557
763
  * Returns the next packet from the packet capture device.
558
- *
764
+ *
559
765
  * Returns a string with the packet data.
560
766
  *
561
767
  * If the next_data() is unsuccessful, Null is returned.
@@ -566,11 +772,11 @@ rbpcap_next_data(VALUE self)
566
772
  rbpcap_t *rbp;
567
773
  rbpcapjob_t job;
568
774
  char eb[PCAP_ERRBUF_SIZE];
569
- int ret;
570
-
775
+ int ret;
776
+
571
777
  Data_Get_Struct(self, rbpcap_t, rbp);
572
-
573
- if(! rbpcap_ready(rbp)) return self;
778
+
779
+ if(! rbpcap_ready(rbp)) return self;
574
780
  pcap_setnonblock(rbp->pd, 1, eb);
575
781
 
576
782
  #ifdef MAKE_TRAP
@@ -584,7 +790,7 @@ rbpcap_next_data(VALUE self)
584
790
  TRAP_END;
585
791
  #endif
586
792
 
587
- if(rbp->type == OFFLINE && ret <= 0)
793
+ if(rbp->type == OFFLINE && ret <= 0)
588
794
  return Qnil;
589
795
 
590
796
  if(ret > 0 && job.hdr.caplen > 0)
@@ -597,7 +803,7 @@ rbpcap_next_data(VALUE self)
597
803
  /*
598
804
  *
599
805
  * Returns the next packet from the packet capture device.
600
- *
806
+ *
601
807
  * Returns a string with the packet data.
602
808
  *
603
809
  * If the next_packet() is unsuccessful, Null is returned.
@@ -605,38 +811,38 @@ rbpcap_next_data(VALUE self)
605
811
 
606
812
  static VALUE
607
813
  rbpcap_next_packet(VALUE self)
608
- {
814
+ {
609
815
  rbpcap_t *rbp;
610
816
  rbpcapjob_t job;
611
817
  char eb[PCAP_ERRBUF_SIZE];
612
- int ret;
613
-
818
+ int ret;
819
+
614
820
  rbpacket_t* rbpacket;
615
-
821
+
616
822
  Data_Get_Struct(self, rbpcap_t, rbp);
617
-
618
- if(! rbpcap_ready(rbp)) return self;
823
+
824
+ if(! rbpcap_ready(rbp)) return self;
619
825
 
620
826
  pcap_setnonblock(rbp->pd, 1, eb);
621
827
 
622
828
  #ifdef MAKE_TRAP
623
829
  TRAP_BEG;
624
830
  #endif
625
-
831
+
626
832
  ret = pcap_dispatch(rbp->pd, 1, (pcap_handler) rbpcap_handler, (u_char *)&job);
627
833
 
628
834
  #ifdef MAKE_TRAP
629
835
  TRAP_END;
630
836
  #endif
631
837
 
632
- if(rbp->type == OFFLINE && ret <= 0)
838
+ if(rbp->type == OFFLINE && ret <= 0)
633
839
  return Qnil;
634
840
 
635
841
  if(ret > 0 && job.hdr.caplen > 0)
636
842
  {
637
843
  rbpacket = ALLOC(rbpacket_t);
638
- rbpacket->hdr = &job.hdr;
639
- rbpacket->pkt = (u_char *)&job.pkt;
844
+ rbpacket->hdr = job.hdr;
845
+ rbpacket->pkt = (u_char *)job.pkt;
640
846
  return Data_Wrap_Struct(rb_cPkt, 0, rbpacket_free, rbpacket);
641
847
  }
642
848
 
@@ -646,7 +852,7 @@ rbpcap_next_packet(VALUE self)
646
852
 
647
853
  /*
648
854
  * call-seq:
649
- * each_data() { |packet| ... }
855
+ * each_data() { |packet| ... }
650
856
  *
651
857
  * Yields each packet from the capture to the passed-in block in turn.
652
858
  *
@@ -655,22 +861,30 @@ static VALUE
655
861
  rbpcap_each_data(VALUE self)
656
862
  {
657
863
  rbpcap_t *rbp;
658
- int fno = -1;
659
-
864
+ #if defined(WIN32)
865
+ HANDLE fno;
866
+ #else
867
+ int fno = -1;
868
+ #endif
869
+
660
870
  Data_Get_Struct(self, rbpcap_t, rbp);
661
871
 
662
- if(! rbpcap_ready(rbp)) return self;
663
-
664
- #if !defined(WIN32)
665
- fno = pcap_get_selectable_fd(rbp->pd);
872
+ if(! rbpcap_ready(rbp)) return self;
873
+
874
+ #if defined(WIN32)
875
+ fno = (int)pcap_getevent(rbp->pd);
666
876
  #else
667
- fno = pcap_fileno(rbp->pd);
877
+ fno = pcap_get_selectable_fd(rbp->pd);
668
878
  #endif
669
879
 
670
880
  for(;;) {
671
881
  VALUE packet = rbpcap_next_data(self);
672
882
  if(packet == Qnil && rbp->type == OFFLINE) break;
883
+ #if defined(WIN32)
884
+ packet == Qnil ? rbpcap_thread_wait_handle(fno) : rb_yield(packet);
885
+ #else
673
886
  packet == Qnil ? rb_thread_wait_fd(fno) : rb_yield(packet);
887
+ #endif
674
888
  }
675
889
 
676
890
  return self;
@@ -679,7 +893,7 @@ rbpcap_each_data(VALUE self)
679
893
 
680
894
  /*
681
895
  * call-seq:
682
- * each_packet() { |packet| ... }
896
+ * each_packet() { |packet| ... }
683
897
  *
684
898
  * Yields a PCAP::Packet from the capture to the passed-in block in turn.
685
899
  *
@@ -688,22 +902,30 @@ static VALUE
688
902
  rbpcap_each_packet(VALUE self)
689
903
  {
690
904
  rbpcap_t *rbp;
691
- int fno = -1;
692
-
905
+
906
+ #if defined(WIN32)
907
+ HANDLE fno;
908
+ #else
909
+ int fno = -1;
910
+ #endif
911
+
693
912
  Data_Get_Struct(self, rbpcap_t, rbp);
913
+ if(! rbpcap_ready(rbp)) return self;
694
914
 
695
- if(! rbpcap_ready(rbp)) return self;
696
-
697
- #if !defined(WIN32)
698
- fno = pcap_get_selectable_fd(rbp->pd);
915
+ #if defined(WIN32)
916
+ fno = (int)pcap_getevent(rbp->pd);
699
917
  #else
700
- fno = pcap_fileno(rbp->pd);
918
+ fno = pcap_get_selectable_fd(rbp->pd);
701
919
  #endif
702
920
 
703
921
  for(;;) {
704
922
  VALUE packet = rbpcap_next_packet(self);
705
923
  if(packet == Qnil && rbp->type == OFFLINE) break;
924
+ #if defined(WIN32)
925
+ packet == Qnil ? rbpcap_thread_wait_handle(fno) : rb_yield(packet);
926
+ #else
706
927
  packet == Qnil ? rb_thread_wait_fd(fno) : rb_yield(packet);
928
+ #endif
707
929
  }
708
930
 
709
931
  return self;
@@ -714,8 +936,8 @@ rbpcap_each_packet(VALUE self)
714
936
  * call-seq:
715
937
  * datalink()
716
938
  *
717
- * Returns the integer datalink value unless capture
718
- *
939
+ * Returns the integer datalink value unless capture
940
+ *
719
941
  * foo.bar unless capture.datalink == Pcap::DLT_EN10MB
720
942
  */
721
943
  static VALUE
@@ -726,7 +948,7 @@ rbpcap_datalink(VALUE self)
726
948
  Data_Get_Struct(self, rbpcap_t, rbp);
727
949
 
728
950
  if(! rbpcap_ready(rbp)) return self;
729
-
951
+
730
952
  return INT2NUM(pcap_datalink(rbp->pd));
731
953
  }
732
954
 
@@ -734,8 +956,8 @@ rbpcap_datalink(VALUE self)
734
956
  * call-seq:
735
957
  * pcap_major_version()
736
958
  *
737
- * Returns the integer PCAP MAJOR LIBRARY value unless capture
738
- *
959
+ * Returns the integer PCAP MAJOR LIBRARY value unless capture
960
+ *
739
961
  */
740
962
  static VALUE
741
963
  rbpcap_major_version(VALUE self)
@@ -743,9 +965,9 @@ rbpcap_major_version(VALUE self)
743
965
  rbpcap_t *rbp;
744
966
 
745
967
  Data_Get_Struct(self, rbpcap_t, rbp);
746
-
968
+
747
969
  if(! rbpcap_ready(rbp)) return self;
748
-
970
+
749
971
  return INT2NUM(pcap_major_version(rbp->pd));
750
972
  }
751
973
 
@@ -753,8 +975,8 @@ rbpcap_major_version(VALUE self)
753
975
  * call-seq:
754
976
  * pcap_minor_version()
755
977
  *
756
- * Returns the integer PCAP MINOR LIBRARY value unless capture
757
- *
978
+ * Returns the integer PCAP MINOR LIBRARY value unless capture
979
+ *
758
980
  */
759
981
  static VALUE
760
982
  rbpcap_minor_version(VALUE self)
@@ -762,9 +984,9 @@ rbpcap_minor_version(VALUE self)
762
984
  rbpcap_t *rbp;
763
985
 
764
986
  Data_Get_Struct(self, rbpcap_t, rbp);
765
-
987
+
766
988
  if(! rbpcap_ready(rbp)) return self;
767
-
989
+
768
990
  return INT2NUM(pcap_minor_version(rbp->pd));
769
991
  }
770
992
 
@@ -773,7 +995,7 @@ rbpcap_minor_version(VALUE self)
773
995
  * snapshot()
774
996
  *
775
997
  * Returns the snapshot length, which is the number of bytes to save for each packet captured.
776
- *
998
+ *
777
999
  */
778
1000
  static VALUE
779
1001
  rbpcap_snapshot(VALUE self)
@@ -783,7 +1005,7 @@ rbpcap_snapshot(VALUE self)
783
1005
  Data_Get_Struct(self, rbpcap_t, rbp);
784
1006
 
785
1007
  if(! rbpcap_ready(rbp)) return self;
786
-
1008
+
787
1009
  return INT2NUM(pcap_snapshot(rbp->pd));
788
1010
  }
789
1011
 
@@ -794,9 +1016,9 @@ rbpcap_snapshot(VALUE self)
794
1016
  * Returns a hash with statistics of the packet capture
795
1017
  *
796
1018
  * - ["recv"] # number of packets received
797
- * - ["drop"] # number of packets dropped
1019
+ * - ["drop"] # number of packets dropped
798
1020
  * - ["idrop"] # number of packets dropped by interface
799
- *
1021
+ *
800
1022
  */
801
1023
  static VALUE
802
1024
  rbpcap_stats(VALUE self)
@@ -804,14 +1026,14 @@ rbpcap_stats(VALUE self)
804
1026
  rbpcap_t *rbp;
805
1027
  struct pcap_stat stat;
806
1028
  VALUE hash;
807
-
1029
+
808
1030
  Data_Get_Struct(self, rbpcap_t, rbp);
809
1031
 
810
1032
  if(! rbpcap_ready(rbp)) return self;
811
-
1033
+
812
1034
  if (pcap_stats(rbp->pd, &stat) == -1)
813
1035
  return Qnil;
814
-
1036
+
815
1037
  hash = rb_hash_new();
816
1038
  rb_hash_aset(hash, rb_str_new2("recv"), UINT2NUM(stat.ps_recv));
817
1039
  rb_hash_aset(hash, rb_str_new2("drop"), UINT2NUM(stat.ps_drop));
@@ -820,110 +1042,145 @@ rbpcap_stats(VALUE self)
820
1042
 
821
1043
  //#if defined(WIN32)
822
1044
  // rb_hash_aset(hash, rb_str_new2("bs_capt"), UINT2NUM(stat.bs_capt));
823
- //#endif
824
-
1045
+ //#endif
1046
+
825
1047
  return hash;
826
1048
  }
827
1049
 
828
1050
  /*
829
1051
  *
830
- * Returns the EPOCH integer from the ts.tv_sec record in the PCAP::Packet header
831
- *
1052
+ * Returns the EPOCH integer from the ts.tv_sec record in the PCAP::Packet header
1053
+ *
832
1054
  */
833
- static VALUE
1055
+ static VALUE
834
1056
  rbpacket_time(VALUE self)
835
1057
  {
836
1058
  rbpacket_t* rbpacket;
837
1059
  Data_Get_Struct(self, rbpacket_t, rbpacket);
838
- return INT2NUM(rbpacket->hdr->ts.tv_sec);
1060
+ return INT2NUM(rbpacket->hdr.ts.tv_sec);
839
1061
  }
840
1062
 
841
1063
  /*
842
1064
  *
843
- * Returns the tv_usec integer from the ts.tv_usec record in the PCAP::Packet header
844
- * timestamp microseconds
845
- * the microseconds when this packet was captured, as an offset to ts_sec.
846
- * Beware: this value shouldn't reach 1 second (1 000 000), in this case ts_sec must be increased instead!
1065
+ * Returns the tv_usec integer from the ts.tv_usec record in the PCAP::Packet header
1066
+ * timestamp microseconds
1067
+ * the microseconds when this packet was captured, as an offset to ts_sec.
1068
+ * Beware: this value shouldn't reach 1 second (1 000 000), in this case ts_sec must be increased instead!
847
1069
  *
848
1070
  * Ruby Microsecond Handling
849
1071
  * Time.at(946684800.2).usec #=> 200000
850
1072
  * Time.now.usec
851
1073
  */
852
1074
 
853
- static VALUE
1075
+ static VALUE
854
1076
  rbpacket_microsec(VALUE self)
855
1077
  {
856
1078
  rbpacket_t* rbpacket;
857
1079
  Data_Get_Struct(self, rbpacket_t, rbpacket);
858
- return INT2NUM(rbpacket->hdr->ts.tv_usec);
1080
+ return INT2NUM(rbpacket->hdr.ts.tv_usec);
859
1081
  }
860
1082
 
861
1083
 
862
1084
  /*
863
1085
  *
864
- * Returns the integer length of packet length field from the in the PCAP::Packet header
865
- *
1086
+ * Returns the integer length of packet length field from the in the PCAP::Packet header
1087
+ *
866
1088
  */
867
- static VALUE
1089
+ static VALUE
868
1090
  rbpacket_length(VALUE self)
869
1091
  {
870
1092
  rbpacket_t* rbpacket;
871
1093
  Data_Get_Struct(self, rbpacket_t, rbpacket);
872
- return INT2NUM(rbpacket->hdr->len);
1094
+ return INT2NUM(rbpacket->hdr.len);
873
1095
  }
874
1096
 
875
1097
  /*
876
1098
  *
877
- * Returns the integer length of capture len from the in the PCAP::Packet header
878
- *
1099
+ * Returns the integer length of capture len from the in the PCAP::Packet header
1100
+ *
879
1101
  */
880
- static VALUE
1102
+ static VALUE
881
1103
  rbpacket_caplen(VALUE self)
882
1104
  {
883
1105
  rbpacket_t* rbpacket;
884
1106
  Data_Get_Struct(self, rbpacket_t, rbpacket);
885
- return INT2NUM(rbpacket->hdr->caplen);
1107
+
1108
+ //test incorrect case
1109
+ if (rbpacket->hdr.caplen > rbpacket->hdr.len)
1110
+ return INT2NUM(rbpacket->hdr.len);
1111
+
1112
+ return INT2NUM(rbpacket->hdr.caplen);
886
1113
  }
887
1114
 
888
1115
  /*
889
1116
  *
890
- * Returns the integer PCAP MINOR LIBRARY value unless capture
891
- *
1117
+ * Returns the integer PCAP MINOR LIBRARY value unless capture
1118
+ *
892
1119
  */
893
- static VALUE
1120
+ static VALUE
894
1121
  rbpacket_data(VALUE self)
895
1122
  {
896
1123
  rbpacket_t* rbpacket;
897
1124
  Data_Get_Struct(self, rbpacket_t, rbpacket);
898
-
899
- if(rbpacket->pkt == NULL)
1125
+
1126
+ if ((rbpacket->pkt == NULL) || (rbpacket->hdr.caplen > rbpacket->hdr.len))
900
1127
  return Qnil;
901
-
902
- return rb_str_new((char *) rbpacket->pkt, rbpacket->hdr->caplen);
1128
+
1129
+ return rb_str_new((char *) rbpacket->pkt, rbpacket->hdr.caplen);
903
1130
  }
904
1131
 
1132
+ #if defined(WIN32)
1133
+ static VALUE
1134
+ rbpcap_thread_wait_handle_blocking(void *data)
1135
+ {
1136
+ VALUE result;
1137
+ result = (VALUE)WaitForSingleObject(data, 100);
1138
+ return result;
1139
+ }
1140
+
1141
+ /*
1142
+ *
1143
+ * Waits for the HANDLE returned by pcap_getevent to have data
1144
+ *
1145
+ */
1146
+ static VALUE
1147
+ rbpcap_thread_wait_handle(HANDLE fno)
1148
+ {
1149
+ VALUE result;
1150
+ #if MAKE_TRAP
1151
+ // Ruby 1.8 doesn't support rb_thread_blocking_region
1152
+ result = rb_thread_polling();
1153
+ #else
1154
+ result = (VALUE)rb_thread_blocking_region(
1155
+ rbpcap_thread_wait_handle_blocking,
1156
+ fno, RUBY_UBF_IO, 0);
1157
+ #endif
1158
+ return result;
1159
+ }
1160
+ #endif
1161
+
905
1162
 
906
1163
  void
907
- Init_pcaprub()
1164
+ Init_pcaprub_c()
908
1165
  {
909
1166
  /*
910
1167
  * Document-class: Pcap
911
- *
1168
+ *
912
1169
  * Main class defined by the pcaprub extension.
913
1170
  */
914
1171
  mPCAP = rb_define_module("PCAPRUB");
915
-
1172
+
916
1173
  rb_cPcap = rb_define_class_under(mPCAP,"Pcap", rb_cObject);
917
1174
  rb_cPkt = rb_define_class_under(mPCAP,"Packet", rb_cObject);
918
-
1175
+
919
1176
  ePCAPRUBError = rb_path2class("PCAPRUB::PCAPRUBError");
920
1177
  eBindingError = rb_path2class("PCAPRUB::BindingError");
921
1178
  eBPFilterError = rb_path2class("PCAPRUB::BPFError");
922
1179
  eDumperError = rb_path2class("PCAPRUB::DumperError");
923
-
924
- rb_define_module_function(rb_cPcap, "lookupdev", rbpcap_s_lookupdev, 0);
1180
+
1181
+ rb_define_module_function(rb_cPcap, "lookupdev", rbpcap_s_lookupdev, 0);
925
1182
  rb_define_module_function(rb_cPcap, "lookupnet", rbpcap_s_lookupnet, 1);
926
-
1183
+
927
1184
  rb_define_const(rb_cPcap, "DLT_NULL", INT2NUM(DLT_NULL));
928
1185
  rb_define_const(rb_cPcap, "DLT_EN10MB", INT2NUM(DLT_EN10MB));
929
1186
  rb_define_const(rb_cPcap, "DLT_EN3MB", INT2NUM(DLT_EN3MB));
@@ -945,7 +1202,7 @@ Init_pcaprub()
945
1202
  rb_define_const(rb_cPcap, "DLT_LINUX_SLL", INT2NUM(DLT_LINUX_SLL));
946
1203
  rb_define_const(rb_cPcap, "DLT_PRISM_HEADER", INT2NUM(DLT_PRISM_HEADER));
947
1204
  rb_define_const(rb_cPcap, "DLT_AIRONET_HEADER", INT2NUM(DLT_AIRONET_HEADER));
948
- /* Pcap Error Codes
1205
+ /* Pcap Error Codes
949
1206
  * Error codes for the pcap API.
950
1207
  * These will all be negative, so you can check for the success or
951
1208
  * failure of a call that returns these codes by checking for a
@@ -977,11 +1234,11 @@ Init_pcaprub()
977
1234
 
978
1235
 
979
1236
  rb_define_singleton_method(rb_cPcap, "new", rbpcap_new_s, 0);
980
-
1237
+ rb_define_singleton_method(rb_cPcap, "create", rbpcap_create_s, 1);
981
1238
  rb_define_singleton_method(rb_cPcap, "open_live", rbpcap_open_live_s, 4);
982
1239
  rb_define_singleton_method(rb_cPcap, "open_offline", rbpcap_open_offline_s, 1);
983
1240
  rb_define_singleton_method(rb_cPcap, "open_dead", rbpcap_open_dead_s, 2);
984
-
1241
+
985
1242
  rb_define_method(rb_cPcap, "dump_open", rbpcap_dump_open, 1);
986
1243
  rb_define_method(rb_cPcap, "dump_close", rbpcap_dump_close, 0);
987
1244
  rb_define_method(rb_cPcap, "dump", rbpcap_dump, 3);
@@ -989,6 +1246,7 @@ Init_pcaprub()
989
1246
  rb_define_method(rb_cPcap, "next_data", rbpcap_next_data, 0);
990
1247
  rb_define_method(rb_cPcap, "each_packet", rbpcap_each_packet, 0);
991
1248
  rb_define_method(rb_cPcap, "next_packet", rbpcap_next_packet, 0);
1249
+
992
1250
  /*
993
1251
  * Document-method: each
994
1252
  * Alias of each_data
@@ -998,22 +1256,30 @@ Init_pcaprub()
998
1256
  * Document-method: next
999
1257
  * Alias of next_data
1000
1258
  */
1259
+
1001
1260
  rb_define_method(rb_cPcap, "next", rbpcap_next_data, 0);
1002
1261
  rb_define_method(rb_cPcap, "setfilter", rbpcap_setfilter, 1);
1262
+ rb_define_method(rb_cPcap, "setmonitor", rbpcap_setmonitor, 1);
1263
+ rb_define_method(rb_cPcap, "setsnaplen", rbpcap_setsnaplen, 1);
1264
+ rb_define_method(rb_cPcap, "settimeout", rbpcap_settimeout, 1);
1265
+ rb_define_method(rb_cPcap, "setpromisc", rbpcap_setpromisc, 1);
1266
+ rb_define_method(rb_cPcap, "activate", rbpcap_activate, 0);
1003
1267
  rb_define_method(rb_cPcap, "inject", rbpcap_inject, 1);
1004
1268
  rb_define_method(rb_cPcap, "datalink", rbpcap_datalink, 0);
1005
1269
  rb_define_method(rb_cPcap, "pcap_major_version", rbpcap_major_version, 0);
1006
1270
  rb_define_method(rb_cPcap, "pcap_minor_version", rbpcap_minor_version, 0);
1007
1271
  rb_define_method(rb_cPcap, "snapshot", rbpcap_snapshot, 0);
1272
+ rb_define_method(rb_cPcap, "close", rbpcap_close, 0);
1273
+
1008
1274
  /*
1009
1275
  * Document-method: snaplen
1010
1276
  * Alias of snapshot
1011
1277
  */
1012
1278
  rb_define_method(rb_cPcap, "snaplen", rbpcap_snapshot, 0);
1013
1279
  rb_define_method(rb_cPcap, "stats", rbpcap_stats, 0);
1014
-
1280
+
1015
1281
  rb_define_singleton_method(rb_cPkt, "new", rbpacket_new_s, 0);
1016
-
1282
+
1017
1283
  rb_define_method(rb_cPkt, "time", rbpacket_time, 0);
1018
1284
  rb_define_method(rb_cPkt, "microsec", rbpacket_microsec, 0);
1019
1285
  rb_define_method(rb_cPkt, "length", rbpacket_length, 0);
@@ -1025,5 +1291,5 @@ Init_pcaprub()
1025
1291
  */
1026
1292
  rb_define_method(rb_cPkt, "to_s", rbpacket_data, 0);
1027
1293
 
1028
-
1294
+
1029
1295
  }