dakrone-pcap-ffi 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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