dakrone-pcap-ffi 0.0.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.
@@ -0,0 +1,119 @@
1
+ require 'pcap/packet'
2
+ require 'pcap/in_addr'
3
+
4
+ require 'ffi'
5
+
6
+ module FFI
7
+ module PCap
8
+ module Packets
9
+ class IPv4 < FFI::Struct
10
+
11
+ include Packet
12
+
13
+ # IPv4 flags
14
+ FLAGS = [
15
+ # Reserved fragment flag
16
+ RESERVED_FRAGMENT = 0x8000,
17
+
18
+ # Dont fragment flag
19
+ DONT_FRAGMENT = 0x4000,
20
+
21
+ # More fragments flag
22
+ MORE_FRAGMENTS = 0x2000
23
+ ]
24
+
25
+ # Mask for fragment flags
26
+ FRAGMENT_MASK = 0x1fff
27
+
28
+ layout :ip_vhl, :uchar,
29
+ :ip_tos, :uchar,
30
+ :ip_len, :ushort,
31
+ :ip_id, :ushort,
32
+ :ip_off, :ushort,
33
+ :ip_ttl, :uchar,
34
+ :ip_p, :uchar,
35
+ :ip_sum, :ushort,
36
+ :ip_src, InAddr,
37
+ :ip_dst, InAddr
38
+
39
+ #
40
+ # Returns the version of the IP packet.
41
+ #
42
+ def version
43
+ self[:ip_vhl] >> 4
44
+ end
45
+
46
+ #
47
+ # Returns the header length of the packet.
48
+ #
49
+ def header_length
50
+ self[:ip_vhl] & 0x0f
51
+ end
52
+
53
+ #
54
+ # Returns the Type of Service (TOS).
55
+ #
56
+ def tos
57
+ self[:ip_tos]
58
+ end
59
+
60
+ #
61
+ # Returns the total packet length.
62
+ #
63
+ def packet_length
64
+ self[:ip_len]
65
+ end
66
+
67
+ #
68
+ # Returns the packet id.
69
+ #
70
+ def id
71
+ self[:ip_id]
72
+ end
73
+
74
+ #
75
+ # Returns the fragment offset.
76
+ #
77
+ def offset
78
+ self[:ip_off]
79
+ end
80
+
81
+ #
82
+ # Returns the Time to Live (TTL).
83
+ #
84
+ def ttl
85
+ self[:ip_ttl]
86
+ end
87
+
88
+ #
89
+ # Returns the protocol number.
90
+ #
91
+ def protocol
92
+ self[:ip_p]
93
+ end
94
+
95
+ #
96
+ # Returns the packet checksum.
97
+ #
98
+ def checksum
99
+ self[:ip_sum]
100
+ end
101
+
102
+ #
103
+ # Returns the source IP address.
104
+ #
105
+ def src
106
+ self[:ip_src]
107
+ end
108
+
109
+ #
110
+ # Returns the destination IP address.
111
+ #
112
+ def dest
113
+ self[:ip_dest]
114
+ end
115
+
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,172 @@
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 TCP < FFI::Struct
10
+
11
+ include Packet
12
+
13
+ # TCP flags
14
+ FLAGS = [
15
+ # Null flags
16
+ NULL = 0x00,
17
+
18
+ # Final packet flag
19
+ FIN = 0x01,
20
+
21
+ # Synchronization packet flag
22
+ SYN = 0x02,
23
+
24
+ # Reset packet flag
25
+ RST = 0x04,
26
+
27
+ # Push packet flag
28
+ PUSH = 0x08,
29
+
30
+ # Acknowledgement packet flag
31
+ ACK = 0x10,
32
+
33
+ # Urgent data packet flag
34
+ URG = 0x20,
35
+
36
+ # ECE packet flag
37
+ ECE = 0x40,
38
+
39
+ # CWR packet flag
40
+ CWR = 0x80,
41
+
42
+ # All combined flags
43
+ XMAS = (FIN | SYN | RST | PUSH | ACK | URG | ECE | CWR)
44
+ ]
45
+
46
+ layout :th_sport, :ushort,
47
+ :th_dport, :ushort,
48
+ :th_seq, :tcp_seq,
49
+ :th_ack, :tcp_seq,
50
+ :th_offx2, :uchar,
51
+ :th_flags, :uchar,
52
+ :th_win, :ushort,
53
+ :th_sum, :ushort,
54
+ :th_urp, :ushort
55
+
56
+ #
57
+ # Returns the source port.
58
+ #
59
+ def src_port
60
+ self[:th_sport]
61
+ end
62
+
63
+ #
64
+ # Returns the destination port.
65
+ #
66
+ def dest_port
67
+ self[:th_dport]
68
+ end
69
+
70
+ #
71
+ # Returns the sequence number of the packet.
72
+ #
73
+ def seq
74
+ self[:th_seq]
75
+ end
76
+
77
+ #
78
+ # Returns the acknowledgement number of the packet.
79
+ #
80
+ def ack
81
+ self[:th_ack]
82
+ end
83
+
84
+ #
85
+ # Returns the data offset for the packet.
86
+ #
87
+ def offset
88
+ (self[:th_offx2] & 0xf0) >> 4
89
+ end
90
+
91
+ #
92
+ # Returns +true+ if the packet has no flags set, +false+ otherwise.
93
+ #
94
+ def null?
95
+ self[:th_flags] == NULL
96
+ end
97
+
98
+ #
99
+ # Returns +true+ if the packet has the FIN flag set, returns
100
+ # +false+ otherwise.
101
+ #
102
+ def fin?
103
+ (self[:th_flags] & FIN) != 0
104
+ end
105
+
106
+ #
107
+ # Returns +true+ if the packet has the SYN flag set, returns
108
+ # +false+ otherwise.
109
+ #
110
+ def syn?
111
+ (self[:th_flags] & SYN) != 0
112
+ end
113
+
114
+ #
115
+ # Returns +true+ if the packet has the RST flag set, returns
116
+ # +false+ otherwise.
117
+ #
118
+ def rst?
119
+ (self[:th_flags] & RST) != 0
120
+ end
121
+
122
+ #
123
+ # Returns +true+ if the packet has the PUSH flag set, returns
124
+ # +false+ otherwise.
125
+ #
126
+ def push?
127
+ (self[:th_flags] & PUSH) != 0
128
+ end
129
+
130
+ #
131
+ # Returns +true+ if the packet has the ACK flag set, returns
132
+ # +false+ otherwise.
133
+ #
134
+ def ack?
135
+ (self[:th_flags] & ACK) != 0
136
+ end
137
+
138
+ #
139
+ # Returns +true+ if the packet has the URG flag set, returns
140
+ # +false+ otherwise.
141
+ #
142
+ def urg?
143
+ (self[:th_flags] & URG) != 0
144
+ end
145
+
146
+ #
147
+ # Returns +true+ if the packet has the ECE flag set, returns
148
+ # +false+ otherwise.
149
+ #
150
+ def ece?
151
+ (self[:th_flags] & ECE) != 0
152
+ end
153
+
154
+ #
155
+ # Returns +true+ if the packet has the CWR flag set, returns
156
+ # +false+ otherwise.
157
+ #
158
+ def cwr?
159
+ (self[:th_flags] & CWR) != 0
160
+ end
161
+
162
+ #
163
+ # Returns +true+ if the packet has all flags set, +false+ otherwise.
164
+ #
165
+ def xmas?
166
+ (self[:th_flags] & XMAS) == XMAS
167
+ end
168
+
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,7 @@
1
+ require 'pcap/typedefs'
2
+
3
+ module FFI
4
+
5
+ alias_type :uint32, :tcp_seq
6
+
7
+ end
@@ -0,0 +1,3 @@
1
+ require 'pcap/packets/typedefs'
2
+ require 'pcap/packets/ip'
3
+ require 'pcap/packets/tcp'
data/lib/pcap/pcap.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'pcap/ffi'
2
+ require 'pcap/data_link'
3
+ require 'pcap/if'
4
+ require 'pcap/handler'
5
+ require 'pcap/error_buffer'
6
+
7
+ module FFI
8
+ module PCap
9
+ def PCap.lib_version
10
+ PCap.pcap_lib_version
11
+ end
12
+
13
+ def PCap.device
14
+ errbuf = ErrorBuffer.new
15
+
16
+ unless (name = PCap.pcap_lookupdev(errbuf))
17
+ raise(StandardError,errbuf.to_s,caller)
18
+ end
19
+
20
+ return name
21
+ end
22
+
23
+ def PCap.each_device(&block)
24
+ devices = MemoryPointer.new(:pointer)
25
+ errbuf = ErrorBuffer.new
26
+
27
+ PCap.pcap_findalldevs(devices,errbuf)
28
+ node = devices.get_pointer(0)
29
+
30
+ if node.null?
31
+ raise(StandardError,errbuf.to_s,caller)
32
+ end
33
+
34
+ device = IF.new(node)
35
+
36
+ until device
37
+ block.call(device) if block
38
+ device = device.next
39
+ end
40
+
41
+ PCap.pcap_freealldevs(node)
42
+ return nil
43
+ end
44
+
45
+ def PCap.open_live(options={},&block)
46
+ device = options[:device]
47
+ promisc = if options[:promisc]
48
+ 1
49
+ else
50
+ 0
51
+ end
52
+ snaplen = (options[:snaplen] || Handler::SNAPLEN)
53
+ to_ms = (options[:timeout] || 0)
54
+ errbuf = ErrorBuffer.new
55
+
56
+ ptr = PCap.pcap_open_live(device,snaplen,promisc,to_ms,nil)
57
+
58
+ if ptr.null?
59
+ raise(StandardError,errbuf.to_s,caller)
60
+ end
61
+
62
+ return Handler.new(ptr,options,&block)
63
+ end
64
+
65
+ def PCap.open_dead(datalink,options={})
66
+ datalink = DataLink[datalink]
67
+ snaplen = (options[:snaplen] || Handler::SNAPLEN)
68
+
69
+ return Handler.new(PCap.pcap_open_dead(datalink,snaplen),options)
70
+ end
71
+
72
+ def PCap.open_offline(path,options={})
73
+ path = File.expand_path(path)
74
+ errbuf = ErrorBuffer.new
75
+
76
+ ptr = PCap.pcap_open_offline(path,errbuf)
77
+
78
+ if ptr.null?
79
+ raise(StandardError,errbuf.to_s,caller)
80
+ end
81
+
82
+ return Handler.new(ptr,options)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,17 @@
1
+ require 'pcap/typedefs'
2
+
3
+ require 'ffi'
4
+
5
+ module FFI
6
+ module PCap
7
+ class SockAddr < FFI::Struct
8
+ layout :sa_family, :sa_family_t,
9
+ :sa_data, [:char, 14]
10
+
11
+ def family
12
+ self[:sa_family]
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ require 'pcap/typedefs'
2
+ require 'pcap/in_addr'
3
+
4
+ require 'ffi'
5
+
6
+ module FFI
7
+ module PCap
8
+ class SockAddrIn < FFI::Struct
9
+
10
+ layout :sin_family, :sa_family_t,
11
+ :sin_port, :in_port_t,
12
+ :sin_addr, InAddr,
13
+ :sin_zero, [:char, ]
14
+
15
+ def family
16
+ self[:sin_family]
17
+ end
18
+
19
+ def addr
20
+ InAddr.new(self[:sin_addr])
21
+ end
22
+
23
+ end
24
+ end
25
+ end
data/lib/pcap/stat.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'ffi/struct'
2
+
3
+ module FFI
4
+ module PCap
5
+ class Stat < FFI::Struct
6
+ layout :ps_recv, :uint,
7
+ :ps_drop, :uint,
8
+ :ps_ifdrop, :uint
9
+
10
+ def received
11
+ self[:ps_recv]
12
+ end
13
+
14
+ def dropped
15
+ self[:ps_drop]
16
+ end
17
+
18
+ def interface_dropped
19
+ self[:ps_ifdrop]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ require 'pcap/typedefs'
2
+
3
+ require 'ffi/struct'
4
+
5
+ module FFI
6
+ module PCap
7
+ class TimeVal < FFI::Struct
8
+ layout :tv_sec, :time_t,
9
+ :tv_usec, :suseconds_t
10
+
11
+ def sec
12
+ self[:tv_sec]
13
+ end
14
+
15
+ def usec
16
+ self[:tv_usec]
17
+ end
18
+
19
+ def to_time
20
+ Time.at(self[:tv_sec],self[:tv_usec])
21
+ end
22
+
23
+ def to_s
24
+ to_time.to_s
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'ffi'
3
+
4
+ module FFI
5
+ def self.alias_type(type,aliased)
6
+ add_typedef(find_type(type),aliased.to_sym)
7
+ end
8
+
9
+ alias_type :long, :time_t
10
+ alias_type :long, :suseconds_t
11
+ alias_type :ushort, :sa_family_t
12
+ alias_type :uint16, :in_port_t
13
+ alias_type :uint32, :in_addr_t
14
+ alias_type :int, :bpf_int32
15
+ alias_type :uint, :bpf_uint32
16
+ end
@@ -0,0 +1,6 @@
1
+ module FFI
2
+ module PCap
3
+ # pcap-ffi version
4
+ VERSION = '0.1.0'
5
+ end
6
+ end
data/lib/pcap.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'pcap/if'
2
+ require 'pcap/addr'
3
+ require 'pcap/file_header'
4
+ require 'pcap/packet_header'
5
+ require 'pcap/stat'
6
+ require 'pcap/data_link'
7
+ require 'pcap/handler'
8
+ require 'pcap/version'
9
+ require 'pcap/ffi'
10
+ require 'pcap/pcap'
data/pcap-ffi.gemspec ADDED
@@ -0,0 +1,86 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{pcap-ffi}
5
+ s.version = "0.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Postmodern, Dakrone"]
9
+ s.date = %q{2009-05-27}
10
+ s.description = %q{Bindings to sniff packets using the FFI interface in Ruby.}
11
+ s.email = %q{postmodern.mod3@gmail.com}
12
+ s.extra_rdoc_files = [
13
+ "README.txt"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "History.txt",
18
+ "Manifest.txt",
19
+ "README.txt",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "examples/print_bytes.rb",
23
+ "lib/pcap.rb",
24
+ "lib/pcap/addr.rb",
25
+ "lib/pcap/data_link.rb",
26
+ "lib/pcap/dumper.rb",
27
+ "lib/pcap/error_buffer.rb",
28
+ "lib/pcap/exceptions.rb",
29
+ "lib/pcap/exceptions/read_error.rb",
30
+ "lib/pcap/ffi.rb",
31
+ "lib/pcap/file_header.rb",
32
+ "lib/pcap/handler.rb",
33
+ "lib/pcap/if.rb",
34
+ "lib/pcap/in_addr.rb",
35
+ "lib/pcap/packet_header.rb",
36
+ "lib/pcap/packets.rb",
37
+ "lib/pcap/packets/ethernet.rb",
38
+ "lib/pcap/packets/ip.rb",
39
+ "lib/pcap/packets/tcp.rb",
40
+ "lib/pcap/packets/typedefs.rb",
41
+ "lib/pcap/pcap.rb",
42
+ "lib/pcap/sock_addr.rb",
43
+ "lib/pcap/sock_addr_in.rb",
44
+ "lib/pcap/stat.rb",
45
+ "lib/pcap/time_val.rb",
46
+ "lib/pcap/typedefs.rb",
47
+ "lib/pcap/version.rb",
48
+ "pcap-ffi.gemspec",
49
+ "spec/data_link_spec.rb",
50
+ "spec/dumps/simple_tcp.pcap",
51
+ "spec/error_buffer.rb",
52
+ "spec/handler_examples.rb",
53
+ "spec/handler_spec.rb",
54
+ "spec/helpers/dumps.rb",
55
+ "spec/pcap_spec.rb",
56
+ "spec/spec_helper.rb",
57
+ "tasks/spec.rb"
58
+ ]
59
+ s.has_rdoc = true
60
+ s.homepage = %q{http://github.com/postmodern/pcap-ffi}
61
+ s.rdoc_options = ["--charset=UTF-8"]
62
+ s.require_paths = ["lib"]
63
+ s.rubyforge_project = %q{pcap-ffi}
64
+ s.rubygems_version = %q{1.3.1}
65
+ s.summary = %q{FFI bindings for libpcap}
66
+ s.test_files = [
67
+ "spec/pcap_spec.rb",
68
+ "spec/data_link_spec.rb",
69
+ "spec/error_buffer.rb",
70
+ "spec/spec_helper.rb",
71
+ "spec/handler_spec.rb",
72
+ "spec/handler_examples.rb",
73
+ "spec/helpers/dumps.rb",
74
+ "examples/print_bytes.rb"
75
+ ]
76
+
77
+ if s.respond_to? :specification_version then
78
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
79
+ s.specification_version = 2
80
+
81
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
82
+ else
83
+ end
84
+ else
85
+ end
86
+ end
@@ -0,0 +1,29 @@
1
+ require 'pcap/data_link'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe DataLink do
6
+ before(:all) do
7
+ @datalink = DataLink.new(0)
8
+ end
9
+
10
+ it "should be initialized from a pcap datalink value" do
11
+ @datalink.name.should == 'NULL'
12
+ end
13
+
14
+ it "should map datalink names to pcap datalink values" do
15
+ DataLink[:en10mb].should == 1
16
+ end
17
+
18
+ it "should have a description" do
19
+ @datalink.description.should_not be_empty
20
+ end
21
+
22
+ it "should be able to convert to an Integer" do
23
+ @datalink.to_i.should == 0
24
+ end
25
+
26
+ it "should be able to convert to a String" do
27
+ @datalink.to_s.should == 'NULL'
28
+ end
29
+ end
Binary file
@@ -0,0 +1,18 @@
1
+ require 'pcap/error_buffer'
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PCap::ErrorBuffer do
6
+ before(:all) do
7
+ @errbuf = PCap::ErrorBuffer.new
8
+ end
9
+
10
+ it "should have a size of 256" do
11
+ @errbuf.size.should == 256
12
+ end
13
+
14
+ it "should return the error message for to_s" do
15
+ @errbuf.write_string('test')
16
+ @errbuf.to_s.should == 'test'
17
+ end
18
+ end