pcaprub 0.11.3 → 0.12.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.
- checksums.yaml +15 -0
- data/.travis.yml +11 -0
- data/Gemfile +20 -0
- data/README.rdoc +57 -13
- data/Rakefile +71 -49
- data/ext/{pcaprub → pcaprub_c}/extconf.rb +20 -26
- data/ext/{pcaprub → pcaprub_c}/pcaprub.c +405 -139
- data/lib/pcaprub/ext.rb +15 -1
- data/lib/pcaprub/version.rb +7 -7
- data/test/helper.rb +8 -1
- data/test/test_pcaprub_unit.rb +111 -89
- metadata +106 -19
- data/pcaprub.gemspec +0 -60
checksums.yaml
ADDED
@@ -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=
|
data/.travis.yml
ADDED
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'
|
data/README.rdoc
CHANGED
@@ -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.
|
5
|
-
|
6
|
-
|
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
|
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 @
|
30
|
-
git clone git://github.com/
|
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
|
-
|
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
|
-
|
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
|
-
===
|
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
|
2
|
-
require '
|
3
|
-
require 'rake/clean'
|
4
|
-
require './lib/pcaprub/version'
|
1
|
+
#require "bundler/gem_tasks"
|
2
|
+
require './lib/pcaprub/version.rb'
|
5
3
|
|
6
|
-
|
7
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
86
|
+
task :test
|
76
87
|
|
77
|
-
|
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 = '
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
-
|
35
|
+
have_library("wpcap", "pcap_setnonblock")
|
34
36
|
else
|
35
|
-
have_library("pcap", "pcap_open_live")
|
36
|
-
|
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
|
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
|
-
|
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, "
|
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 =
|
639
|
-
rbpacket->pkt = (u_char *)
|
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
|
-
|
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
|
-
|
663
|
-
|
664
|
-
#if
|
665
|
-
fno =
|
872
|
+
if(! rbpcap_ready(rbp)) return self;
|
873
|
+
|
874
|
+
#if defined(WIN32)
|
875
|
+
fno = (int)pcap_getevent(rbp->pd);
|
666
876
|
#else
|
667
|
-
fno =
|
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
|
-
|
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
|
-
|
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 =
|
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
|
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
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
}
|