dakrone-pcap-ffi 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/History.txt +4 -0
- data/Manifest.txt +40 -0
- data/README.txt +41 -0
- data/Rakefile +24 -0
- data/VERSION +1 -0
- data/examples/print_bytes.rb +17 -0
- data/lib/pcap/addr.rb +37 -0
- data/lib/pcap/data_link.rb +53 -0
- data/lib/pcap/dumper.rb +39 -0
- data/lib/pcap/error_buffer.rb +26 -0
- data/lib/pcap/exceptions/read_error.rb +6 -0
- data/lib/pcap/exceptions.rb +1 -0
- data/lib/pcap/ffi.rb +78 -0
- data/lib/pcap/file_header.rb +17 -0
- data/lib/pcap/handler.rb +170 -0
- data/lib/pcap/if.rb +36 -0
- data/lib/pcap/in_addr.rb +13 -0
- data/lib/pcap/packet_header.rb +26 -0
- data/lib/pcap/packets/ethernet.rb +40 -0
- data/lib/pcap/packets/ip.rb +119 -0
- data/lib/pcap/packets/tcp.rb +172 -0
- data/lib/pcap/packets/typedefs.rb +7 -0
- data/lib/pcap/packets.rb +3 -0
- data/lib/pcap/pcap.rb +85 -0
- data/lib/pcap/sock_addr.rb +17 -0
- data/lib/pcap/sock_addr_in.rb +25 -0
- data/lib/pcap/stat.rb +23 -0
- data/lib/pcap/time_val.rb +29 -0
- data/lib/pcap/typedefs.rb +16 -0
- data/lib/pcap/version.rb +6 -0
- data/lib/pcap.rb +10 -0
- data/pcap-ffi.gemspec +86 -0
- data/spec/data_link_spec.rb +29 -0
- data/spec/dumps/simple_tcp.pcap +0 -0
- data/spec/error_buffer.rb +18 -0
- data/spec/handler_examples.rb +71 -0
- data/spec/handler_spec.rb +80 -0
- data/spec/helpers/dumps.rb +3 -0
- data/spec/pcap_spec.rb +51 -0
- data/spec/spec_helper.rb +8 -0
- data/tasks/spec.rb +9 -0
- metadata +101 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
Rakefile
|
4
|
+
README.txt
|
5
|
+
examples/print_bytes.rb
|
6
|
+
lib/pcap.rb
|
7
|
+
lib/pcap/exceptions.rb
|
8
|
+
lib/pcap/exceptions/read_error.rb
|
9
|
+
lib/pcap/typedefs.rb
|
10
|
+
lib/pcap/time_val.rb
|
11
|
+
lib/pcap/in_addr.rb
|
12
|
+
lib/pcap/sock_addr.rb
|
13
|
+
lib/pcap/sock_addr_in.rb
|
14
|
+
lib/pcap/if.rb
|
15
|
+
lib/pcap/addr.rb
|
16
|
+
lib/pcap/file_header.rb
|
17
|
+
lib/pcap/packet_header.rb
|
18
|
+
lib/pcap/packet.rb
|
19
|
+
lib/pcap/packets.rb
|
20
|
+
lib/pcap/packets/typedefs.rb
|
21
|
+
lib/pcap/packets/ethernet.rb
|
22
|
+
lib/pcap/packets/ip.rb
|
23
|
+
lib/pcap/packets/tcp.rb
|
24
|
+
lib/pcap/stat.rb
|
25
|
+
lib/pcap/data_link.rb
|
26
|
+
lib/pcap/error_buffer.rb
|
27
|
+
lib/pcap/handler.rb
|
28
|
+
lib/pcap/dumper.rb
|
29
|
+
lib/pcap/version.rb
|
30
|
+
lib/pcap/ffi.rb
|
31
|
+
lib/pcap/pcap.rb
|
32
|
+
tasks/spec.rb
|
33
|
+
spec/spec_helper.rb
|
34
|
+
spec/helpers/dumps.rb
|
35
|
+
spec/dumps/simple_tcp.pcap
|
36
|
+
spec/error_buffer.rb
|
37
|
+
spec/data_link_spec.rb
|
38
|
+
spec/handler_examples.rb
|
39
|
+
spec/handler_spec.rb
|
40
|
+
spec/pcap_spec.rb
|
data/README.txt
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
= pcap-ffi
|
2
|
+
|
3
|
+
* http://github.com/postmodern/pcap-ffi/
|
4
|
+
* Postmodern (postmodern.mod3 at gmail.com)
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
Ruby FFI bindings for libpcap.
|
9
|
+
|
10
|
+
== FEATURES:
|
11
|
+
|
12
|
+
== EXAMPLES:
|
13
|
+
|
14
|
+
== INSTALL:
|
15
|
+
|
16
|
+
$ sudo gem install pcap-ffi
|
17
|
+
|
18
|
+
== LICENSE:
|
19
|
+
|
20
|
+
The MIT License
|
21
|
+
|
22
|
+
Copyright (c) 2009 Hal Brodigan
|
23
|
+
|
24
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
25
|
+
a copy of this software and associated documentation files (the
|
26
|
+
'Software'), to deal in the Software without restriction, including
|
27
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
28
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
29
|
+
permit persons to whom the Software is furnished to do so, subject to
|
30
|
+
the following conditions:
|
31
|
+
|
32
|
+
The above copyright notice and this permission notice shall be
|
33
|
+
included in all copies or substantial portions of the Software.
|
34
|
+
|
35
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
36
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
37
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
38
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
39
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
40
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
41
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require './lib/pcap/version.rb'
|
5
|
+
require './tasks/spec.rb'
|
6
|
+
|
7
|
+
# Generate a gem using jeweler
|
8
|
+
begin
|
9
|
+
require 'jeweler'
|
10
|
+
Jeweler::Tasks.new do |gemspec|
|
11
|
+
gemspec.rubyforge_project = 'pcap-ffi'
|
12
|
+
gemspec.name = "pcap-ffi"
|
13
|
+
gemspec.summary = "FFI bindings for libpcap"
|
14
|
+
gemspec.email = "postmodern.mod3@gmail.com"
|
15
|
+
gemspec.homepage = "http://github.com/postmodern/pcap-ffi"
|
16
|
+
gemspec.description = "Bindings to sniff packets using the FFI interface in Ruby."
|
17
|
+
gemspec.authors = ["Postmodern, Dakrone"]
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# vim: syntax=Ruby
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'pcap'
|
5
|
+
|
6
|
+
include FFI
|
7
|
+
|
8
|
+
pcap = PCap.open_live(:device => ARGV[0]) do |user,header,bytes|
|
9
|
+
puts "#{header.timestamp}:"
|
10
|
+
|
11
|
+
header.captured.times { |i|
|
12
|
+
print ' %.2x' % bytes.get_uchar(i)
|
13
|
+
}
|
14
|
+
putc "\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
pcap.loop
|
data/lib/pcap/addr.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'pcap/typedefs'
|
2
|
+
require 'pcap/sock_addr'
|
3
|
+
|
4
|
+
require 'ffi/struct'
|
5
|
+
|
6
|
+
module FFI
|
7
|
+
module PCap
|
8
|
+
class Addr < FFI::Struct
|
9
|
+
layout :next, :pointer,
|
10
|
+
:addr, :pointer,
|
11
|
+
:netmask, :pointer,
|
12
|
+
:broadaddr, :pointer,
|
13
|
+
:dstaddr, :pointer
|
14
|
+
|
15
|
+
def next
|
16
|
+
Addr.new(self[:next])
|
17
|
+
end
|
18
|
+
|
19
|
+
def addr
|
20
|
+
SockAddr.new(self[:addr])
|
21
|
+
end
|
22
|
+
|
23
|
+
def netmask
|
24
|
+
SockAddr.new(self[:netmask])
|
25
|
+
end
|
26
|
+
|
27
|
+
def broadcast
|
28
|
+
SockAddr.new(self[:broadaddr])
|
29
|
+
end
|
30
|
+
|
31
|
+
def dest_addr
|
32
|
+
SockAddr.new(self[:destaddr])
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module FFI
|
2
|
+
module PCap
|
3
|
+
class DataLink
|
4
|
+
|
5
|
+
# PCap datalink numeric value
|
6
|
+
attr_reader :value
|
7
|
+
|
8
|
+
# DataLink name
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
#
|
12
|
+
# Creates a new DataLink object with the specified _value_.
|
13
|
+
#
|
14
|
+
def initialize(value)
|
15
|
+
@value = value
|
16
|
+
@name = PCap.pcap_datalink_val_to_name(@value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.[](name)
|
20
|
+
PCap.pcap_datalink_name_to_val(name.to_s.downcase)
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Returns the description of the datalink.
|
25
|
+
#
|
26
|
+
def description
|
27
|
+
PCap.pcap_datalink_val_to_description(@value)
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Returns the numeric value of the datalink.
|
32
|
+
#
|
33
|
+
def to_i
|
34
|
+
@value
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Returns the String form of the datalink.
|
39
|
+
#
|
40
|
+
def to_s
|
41
|
+
@name
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Inspects the datalink.
|
46
|
+
#
|
47
|
+
def inspect
|
48
|
+
"#<#{self.class}: #{@name}>"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/pcap/dumper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pcap/ffi'
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
|
5
|
+
module FFI
|
6
|
+
module PCap
|
7
|
+
class Dumper < FFI::MemoryPointer
|
8
|
+
|
9
|
+
def initialize(dumper)
|
10
|
+
@dumper = dumper
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(header,bytes)
|
14
|
+
PCap.pcap_dump(@dumper,header,bytes)
|
15
|
+
end
|
16
|
+
|
17
|
+
def tell
|
18
|
+
PCap.pcap_dump_ftell(@dumper)
|
19
|
+
end
|
20
|
+
|
21
|
+
def flush
|
22
|
+
PCap.pcap_dump_flush(@dumper)
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
PCap.pcap_dump_close(@dumper)
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_ptr
|
30
|
+
@dumper
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"#<#{self.class}: 0x#{@dumper.address.to_s(16)}>"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
module PCap
|
5
|
+
class ErrorBuffer < FFI::Buffer
|
6
|
+
|
7
|
+
# Size of the error buffers
|
8
|
+
SIZE = 256
|
9
|
+
|
10
|
+
#
|
11
|
+
# Creates a new ErrorBuffer object.
|
12
|
+
#
|
13
|
+
def initialize
|
14
|
+
super(SIZE)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Returns the error message within the error buffer.
|
19
|
+
#
|
20
|
+
def to_s
|
21
|
+
get_string(SIZE)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'pcap/exceptions/read_error'
|
data/lib/pcap/ffi.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'pcap/typedefs'
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
|
5
|
+
module FFI
|
6
|
+
module PCap
|
7
|
+
extend FFI::Library
|
8
|
+
|
9
|
+
ffi_lib 'libpcap'
|
10
|
+
|
11
|
+
enum :pcap_direction, [
|
12
|
+
:pcap_d_inout,
|
13
|
+
:pcap_d_in,
|
14
|
+
:pcap_d_out
|
15
|
+
]
|
16
|
+
|
17
|
+
callback :pcap_handler, [:pointer, :pointer, :pointer], :void
|
18
|
+
|
19
|
+
attach_function :pcap_lookupdev, [:pointer], :string
|
20
|
+
attach_function :pcap_lookupnet, [:string, :pointer, :pointer, :pointer], :int
|
21
|
+
attach_function :pcap_open_live, [:string, :int, :int, :int, :pointer], :pointer
|
22
|
+
attach_function :pcap_open_dead, [:int, :int], :pointer
|
23
|
+
attach_function :pcap_open_offline, [:string, :pointer], :pointer
|
24
|
+
attach_function :pcap_fopen_offline, [:pointer, :string], :pointer
|
25
|
+
attach_function :pcap_close, [:pointer], :void
|
26
|
+
attach_function :pcap_loop, [:pointer, :int, :pcap_handler, :pointer], :int
|
27
|
+
attach_function :pcap_dispatch, [:pointer, :int, :pcap_handler, :pointer], :int
|
28
|
+
attach_function :pcap_next, [:pointer, :pointer], :pointer
|
29
|
+
attach_function :pcap_next_ex, [:pointer, :pointer, :pointer], :int
|
30
|
+
attach_function :pcap_breakloop, [:pointer], :void
|
31
|
+
attach_function :pcap_stats, [:pointer, :pointer], :int
|
32
|
+
attach_function :pcap_setfilter, [:pointer, :pointer], :int
|
33
|
+
attach_function :pcap_setdirection, [:pointer, :pcap_direction], :int
|
34
|
+
attach_function :pcap_getnonblock, [:pointer, :pointer], :int
|
35
|
+
attach_function :pcap_setnonblock, [:pointer, :int, :pointer], :int
|
36
|
+
attach_function :pcap_perror, [:pointer, :string], :void
|
37
|
+
attach_function :pcap_inject, [:pointer, :pointer, :int], :int
|
38
|
+
attach_function :pcap_sendpacket, [:pointer, :pointer, :int], :int
|
39
|
+
attach_function :pcap_strerror, [:int], :string
|
40
|
+
attach_function :pcap_geterr, [:pointer], :string
|
41
|
+
attach_function :pcap_compile, [:pointer, :pointer, :string, :int, :bpf_uint32], :int
|
42
|
+
attach_function :pcap_compile_nopcap, [:int, :int, :pointer, :string, :int, :bpf_uint32], :int
|
43
|
+
attach_function :pcap_freecode, [:pointer], :void
|
44
|
+
attach_function :pcap_datalink, [:pointer], :int
|
45
|
+
attach_function :pcap_list_datalinks, [:pointer, :pointer], :int
|
46
|
+
attach_function :pcap_set_datalink, [:pointer, :int], :int
|
47
|
+
attach_function :pcap_datalink_name_to_val, [:string], :int
|
48
|
+
attach_function :pcap_datalink_val_to_name, [:int], :string
|
49
|
+
attach_function :pcap_datalink_val_to_description, [:int], :string
|
50
|
+
attach_function :pcap_snapshot, [:pointer], :int
|
51
|
+
attach_function :pcap_is_swapped, [:pointer], :int
|
52
|
+
attach_function :pcap_major_version, [:pointer], :int
|
53
|
+
attach_function :pcap_minor_version, [:pointer], :int
|
54
|
+
|
55
|
+
attach_function :pcap_file, [:pointer], :pointer
|
56
|
+
attach_function :pcap_fileno, [:pointer], :int
|
57
|
+
|
58
|
+
attach_function :pcap_dump_open, [:pointer, :string], :pointer
|
59
|
+
attach_function :pcap_dump_fopen, [:pointer, :pointer], :pointer
|
60
|
+
attach_function :pcap_dump_file, [:pointer], :pointer
|
61
|
+
attach_function :pcap_dump_ftell, [:pointer], :long
|
62
|
+
attach_function :pcap_dump_flush, [:pointer], :int
|
63
|
+
attach_function :pcap_dump_close, [:pointer], :void
|
64
|
+
attach_function :pcap_dump, [:pointer, :pointer, :pointer], :void
|
65
|
+
|
66
|
+
attach_function :pcap_findalldevs, [:pointer, :pointer], :int
|
67
|
+
attach_function :pcap_freealldevs, [:pointer], :void
|
68
|
+
|
69
|
+
attach_function :pcap_lib_version, [], :string
|
70
|
+
|
71
|
+
attach_function :bpf_filter, [:pointer, :pointer, :uint, :uint], :uint
|
72
|
+
attach_function :bpf_validate, [:pointer, :int], :int
|
73
|
+
attach_function :bpf_image, [:pointer, :int], :string
|
74
|
+
attach_function :bpf_dump, [:pointer, :int], :void
|
75
|
+
|
76
|
+
# TODO: WIN32/MSDOS/UN*X specific definitions
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'pcap/typedefs'
|
2
|
+
|
3
|
+
require 'ffi/struct'
|
4
|
+
|
5
|
+
module FFI
|
6
|
+
module PCap
|
7
|
+
class FileHeader < FFI::Struct
|
8
|
+
layout :magic, :bpf_uint32,
|
9
|
+
:version_major, :ushort,
|
10
|
+
:version_minor, :ushort,
|
11
|
+
:thiszone, :bpf_int32,
|
12
|
+
:sigfigs, :bpf_uint32,
|
13
|
+
:snaplen, :bpf_uint32,
|
14
|
+
:linktype, :bpf_uint32
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/pcap/handler.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'pcap/exceptions/read_error'
|
2
|
+
require 'pcap/ffi'
|
3
|
+
require 'pcap/error_buffer'
|
4
|
+
require 'pcap/data_link'
|
5
|
+
require 'pcap/packet_header'
|
6
|
+
require 'pcap/stat'
|
7
|
+
|
8
|
+
require 'ffi'
|
9
|
+
|
10
|
+
module FFI
|
11
|
+
module PCap
|
12
|
+
class Handler
|
13
|
+
|
14
|
+
include Enumerable
|
15
|
+
|
16
|
+
# Default snaplen
|
17
|
+
SNAPLEN = 65535
|
18
|
+
|
19
|
+
# Pointer to the pcap opaque type
|
20
|
+
attr_reader :pcap
|
21
|
+
|
22
|
+
# Number of packets to sniff
|
23
|
+
attr_accessor :count
|
24
|
+
|
25
|
+
def initialize(pcap,options={},&block)
|
26
|
+
@pcap = pcap
|
27
|
+
@closed = false
|
28
|
+
|
29
|
+
# Default is to infinitely loop over packets.
|
30
|
+
@count = (options[:count] || -1)
|
31
|
+
|
32
|
+
if options[:direction]
|
33
|
+
self.direction = options[:direction]
|
34
|
+
end
|
35
|
+
|
36
|
+
@callback_wrapper = Proc.new do |user,header,bytes|
|
37
|
+
if @callback
|
38
|
+
@callback.call(user,PacketHeader.new(header),bytes)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
callback(&block)
|
43
|
+
|
44
|
+
trap('SIGINT') { self.close }
|
45
|
+
end
|
46
|
+
|
47
|
+
def datalink
|
48
|
+
DataLink.new(PCap.pcap_datalink(@pcap))
|
49
|
+
end
|
50
|
+
|
51
|
+
def callback(&block)
|
52
|
+
@callback = block
|
53
|
+
return @callback
|
54
|
+
end
|
55
|
+
|
56
|
+
def direction=(dir)
|
57
|
+
directions = PCap.enum_type(:pcap_direction)
|
58
|
+
|
59
|
+
return PCap.pcap_setdirection(@pcap,directions[:"pcap_d_#{dir}"])
|
60
|
+
end
|
61
|
+
|
62
|
+
def non_blocking=(mode)
|
63
|
+
errbuf = ErrorBuffer.new
|
64
|
+
mode = if mode
|
65
|
+
1
|
66
|
+
else
|
67
|
+
0
|
68
|
+
end
|
69
|
+
|
70
|
+
if PCap.pcap_setnonblock(@pcap,mode,errbuf) == -1
|
71
|
+
raise(RuntimeError,errbuf.to_s,caller)
|
72
|
+
end
|
73
|
+
|
74
|
+
return mode == 1
|
75
|
+
end
|
76
|
+
|
77
|
+
def non_blocking?
|
78
|
+
errbuf = ErrorBuffer.new
|
79
|
+
mode = PCap.pcap_getnonblock(@pcap,errbuf)
|
80
|
+
|
81
|
+
if mode == -1
|
82
|
+
raise(RuntimeError,errbuf.to_s,caller)
|
83
|
+
end
|
84
|
+
|
85
|
+
return mode == 1
|
86
|
+
end
|
87
|
+
|
88
|
+
def loop(data=nil,&block)
|
89
|
+
callback(&block) if block
|
90
|
+
|
91
|
+
PCap.pcap_loop(@pcap,@count,@callback_wrapper,data)
|
92
|
+
end
|
93
|
+
|
94
|
+
alias each loop
|
95
|
+
|
96
|
+
def dispatch(data=nil,&block)
|
97
|
+
callback(&block) if block
|
98
|
+
|
99
|
+
return PCap.pcap_dispatch(@pcap,@count,@callback_wrapper,data)
|
100
|
+
end
|
101
|
+
|
102
|
+
def next
|
103
|
+
header = PacketHeader.new
|
104
|
+
data = PCap.pcap_next(@pcap,header)
|
105
|
+
|
106
|
+
return [nil, nil] if data.null?
|
107
|
+
return [header, data]
|
108
|
+
end
|
109
|
+
|
110
|
+
def next_extra
|
111
|
+
header_ptr = MemoryPointer.new(:pointer)
|
112
|
+
data_ptr = MemoryPointer.new(:pointer)
|
113
|
+
|
114
|
+
case PCap.pcap_next_ex(@pcap,header_ptr,data_ptr)
|
115
|
+
when -1
|
116
|
+
raise(ReadError,"an error occurred while reading the packet",caller)
|
117
|
+
when -2
|
118
|
+
raise(ReadError,"the 'savefile' contains no more packets",caller)
|
119
|
+
end
|
120
|
+
|
121
|
+
return [header_ptr.get_pointer(0), data_ptr.get_pointer(0)]
|
122
|
+
end
|
123
|
+
|
124
|
+
def open_dump(path)
|
125
|
+
dump_ptr = PCap.pcap_dump_open(@pcap,File.expand_path(path))
|
126
|
+
|
127
|
+
if dump_ptr.null?
|
128
|
+
raise(RuntimeError,error,caller)
|
129
|
+
end
|
130
|
+
|
131
|
+
return Dumper.new(dump_ptr)
|
132
|
+
end
|
133
|
+
|
134
|
+
def stats
|
135
|
+
stats = Stat.new
|
136
|
+
|
137
|
+
PCap.pcap_stats(@pcap,stats)
|
138
|
+
return stats
|
139
|
+
end
|
140
|
+
|
141
|
+
def error
|
142
|
+
PCap.pcap_geterr(@pcap)
|
143
|
+
end
|
144
|
+
|
145
|
+
def stop
|
146
|
+
PCap.pcap_breakloop(@pcap)
|
147
|
+
end
|
148
|
+
|
149
|
+
def closed?
|
150
|
+
@closed == true
|
151
|
+
end
|
152
|
+
|
153
|
+
def close
|
154
|
+
unless @closed
|
155
|
+
@closed = true
|
156
|
+
PCap.pcap_close(@pcap)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def to_ptr
|
161
|
+
@pcap
|
162
|
+
end
|
163
|
+
|
164
|
+
def inspect
|
165
|
+
"#<#{self.class}: 0x#{@pcap.address.to_s(16)}>"
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
data/lib/pcap/if.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'pcap/typedefs'
|
2
|
+
require 'pcap/addr'
|
3
|
+
|
4
|
+
require 'ffi/struct'
|
5
|
+
|
6
|
+
module FFI
|
7
|
+
module PCap
|
8
|
+
class IF < FFI::Struct
|
9
|
+
# interface is loopback
|
10
|
+
LOOPBACK = 0x00000001
|
11
|
+
|
12
|
+
layout :next, :pointer,
|
13
|
+
:name, :string,
|
14
|
+
:description, :string,
|
15
|
+
:addresses, :pointer,
|
16
|
+
:flags, :bpf_uint32
|
17
|
+
|
18
|
+
def next
|
19
|
+
IF.new(self[:next])
|
20
|
+
end
|
21
|
+
|
22
|
+
def name
|
23
|
+
self[:name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def addresses
|
27
|
+
Addr.new(self[:addresses])
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
self[:name]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/pcap/in_addr.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'pcap/typedefs'
|
2
|
+
require 'pcap/time_val'
|
3
|
+
|
4
|
+
require 'ffi/struct'
|
5
|
+
|
6
|
+
module FFI
|
7
|
+
module PCap
|
8
|
+
class PacketHeader < FFI::Struct
|
9
|
+
layout :ts, TimeVal,
|
10
|
+
:caplen, :bpf_uint32,
|
11
|
+
:len, :bpf_uint32
|
12
|
+
|
13
|
+
def timestamp
|
14
|
+
self[:ts]
|
15
|
+
end
|
16
|
+
|
17
|
+
def captured
|
18
|
+
self[:caplen]
|
19
|
+
end
|
20
|
+
|
21
|
+
def length
|
22
|
+
self[:len]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'pcap/packets/typedefs'
|
2
|
+
require 'pcap/packet'
|
3
|
+
|
4
|
+
require 'ffi'
|
5
|
+
|
6
|
+
module FFI
|
7
|
+
module PCap
|
8
|
+
module Packets
|
9
|
+
class Ethernet < FFI::Struct
|
10
|
+
|
11
|
+
include Packet
|
12
|
+
|
13
|
+
# Number of bytes for an ethernet address
|
14
|
+
ADDR_LEN = 6
|
15
|
+
|
16
|
+
# Size of an Ethernet header
|
17
|
+
SIZE = 14
|
18
|
+
|
19
|
+
layout :ether_dhost, [:uchar, ADDR_LEN],
|
20
|
+
:ether_shost, [:uchar, ADDR_LEN],
|
21
|
+
:ether_type, :ushort
|
22
|
+
|
23
|
+
#
|
24
|
+
# Returns the source MAC address.
|
25
|
+
#
|
26
|
+
def src_mac
|
27
|
+
self[:ether_shost]
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Returns the destination MAC address.
|
32
|
+
#
|
33
|
+
def dest_mac
|
34
|
+
self[:ether_dhost]
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|