caper 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/History.rdoc +31 -0
- data/LICENSE.ffi-pcap +23 -0
- data/README.rdoc +55 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/examples/ipfw_divert.rb +45 -0
- data/examples/print_bytes.rb +17 -0
- data/examples/test_loop.rb +48 -0
- data/lib/caper.rb +40 -0
- data/lib/caper/addr.rb +19 -0
- data/lib/caper/bpf.rb +104 -0
- data/lib/caper/bsd.rb +96 -0
- data/lib/caper/capture_wrapper.rb +287 -0
- data/lib/caper/common_wrapper.rb +173 -0
- data/lib/caper/copy_handler.rb +36 -0
- data/lib/caper/crt.rb +13 -0
- data/lib/caper/data_link.rb +171 -0
- data/lib/caper/dead.rb +35 -0
- data/lib/caper/dumper.rb +53 -0
- data/lib/caper/error_buffer.rb +42 -0
- data/lib/caper/exceptions.rb +19 -0
- data/lib/caper/file_header.rb +24 -0
- data/lib/caper/in_addr.rb +7 -0
- data/lib/caper/interface.rb +27 -0
- data/lib/caper/live.rb +301 -0
- data/lib/caper/offline.rb +51 -0
- data/lib/caper/packet.rb +163 -0
- data/lib/caper/packet_header.rb +23 -0
- data/lib/caper/pcap.rb +250 -0
- data/lib/caper/stat.rb +56 -0
- data/lib/caper/time_val.rb +46 -0
- data/lib/caper/typedefs.rb +25 -0
- data/lib/caper/version.rb +4 -0
- data/spec/data_link_spec.rb +65 -0
- data/spec/dead_spec.rb +34 -0
- data/spec/dumps/http.pcap +0 -0
- data/spec/dumps/simple_tcp.pcap +0 -0
- data/spec/error_buffer_spec.rb +17 -0
- data/spec/file_header_spec.rb +28 -0
- data/spec/live_spec.rb +87 -0
- data/spec/offline_spec.rb +61 -0
- data/spec/packet_behaviors.rb +68 -0
- data/spec/packet_injection_spec.rb +38 -0
- data/spec/packet_spec.rb +111 -0
- data/spec/pcap_spec.rb +149 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/wrapper_behaviors.rb +110 -0
- data/tasks/rcov.rb +6 -0
- data/tasks/rdoc.rb +17 -0
- data/tasks/spec.rb +9 -0
- data/tasks/yard.rb +16 -0
- metadata +140 -0
data/.gitignore
ADDED
data/History.rdoc
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
=== 0.2.0 / 2010-04-22
|
2
|
+
* Renamed library to 'caper' using Caper as the ruby namespace instead of
|
3
|
+
FFI::PCap
|
4
|
+
* Fully branched as a separate project under the new caper name.
|
5
|
+
|
6
|
+
=== 0.1.4 / 2010-04-20
|
7
|
+
* Fixes and example for pcap dumper
|
8
|
+
|
9
|
+
=== 0.1.3 / 2010-03-05
|
10
|
+
* Minor fixes for ruby 1.9 compatability
|
11
|
+
|
12
|
+
=== 0.1.2 / 2010-01-03
|
13
|
+
|
14
|
+
* Branched from sophsec/ffi-pcap by emonti
|
15
|
+
* Using ffi_dry for common struct interface
|
16
|
+
* Redesigned the pcap-specific pcap_pkthdr struct.
|
17
|
+
* Dismantled all other network packet parsing code.
|
18
|
+
* 'Handlers' have been split out into type-specific 'Wrappers' by features.
|
19
|
+
* The namespace 'Handler' has been reused instead for pcap_handler abstraction
|
20
|
+
* Added filtering support and interfaces for compiling filters into bpf code.
|
21
|
+
* Added packet injection on Live pcap interfaces.
|
22
|
+
* Tackled some minor Jruby compatability issues.
|
23
|
+
* Lots of documentation added throughout with yardoc tags.
|
24
|
+
* Lots of misc namespace mods and such, and some general refactoring.
|
25
|
+
* Lots of other stuff I'm probably forgetting.
|
26
|
+
* specs all pass on OS X, Linux, and Win32(except 1 which is a known issue)
|
27
|
+
|
28
|
+
=== 0.1.0 / 2009-04-29
|
29
|
+
|
30
|
+
* Initial release. (sophsec/ffi-pcap)
|
31
|
+
|
data/LICENSE.ffi-pcap
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
The MIT License
|
3
|
+
|
4
|
+
Copyright (c) 2009-2010 Hal Brodigan
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
'Software'), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
20
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
21
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
22
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
23
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
= caper
|
2
|
+
|
3
|
+
* http://github.com/emonti/caper
|
4
|
+
* Eric Monti (esmonti at gmail dot com)
|
5
|
+
|
6
|
+
This started as a fork of ffi-pcap by postmodern but has diverged
|
7
|
+
significantly from its original version.
|
8
|
+
|
9
|
+
* http://github.com/sophsec/ffi-pcap/
|
10
|
+
* Postmodern (postmodern.mod3 at gmail.com)
|
11
|
+
|
12
|
+
== DESCRIPTION:
|
13
|
+
|
14
|
+
Ruby FFI bindings for libpcap.
|
15
|
+
|
16
|
+
== FEATURES:
|
17
|
+
|
18
|
+
== EXAMPLES:
|
19
|
+
|
20
|
+
== REQUIREMENTS:
|
21
|
+
|
22
|
+
* libpcap [http://www.tcpdump.org/]
|
23
|
+
* ffi >= 0.5.3 [http://github.com/ffi/ffi]
|
24
|
+
* ffi_dry [http://github.com/emonti/ffi_dry]
|
25
|
+
|
26
|
+
== INSTALL:
|
27
|
+
|
28
|
+
$ sudo gem install caper
|
29
|
+
|
30
|
+
== LICENSE:
|
31
|
+
|
32
|
+
(please see LICENSE.ffi-pcap for the original ffi-pcap license)
|
33
|
+
|
34
|
+
The MIT License
|
35
|
+
|
36
|
+
Copyright (c) 2010 Eric Monti
|
37
|
+
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
39
|
+
a copy of this software and associated documentation files (the
|
40
|
+
'Software'), to deal in the Software without restriction, including
|
41
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
42
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
43
|
+
permit persons to whom the Software is furnished to do so, subject to
|
44
|
+
the following conditions:
|
45
|
+
|
46
|
+
The above copyright notice and this permission notice shall be
|
47
|
+
included in all copies or substantial portions of the Software.
|
48
|
+
|
49
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
52
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
53
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
54
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
55
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
Dir["tasks/*.rb"].each {|rt| require rt }
|
5
|
+
require 'rake/clean'
|
6
|
+
require './lib/caper/version.rb'
|
7
|
+
|
8
|
+
# Generate a gem using jeweler
|
9
|
+
begin
|
10
|
+
require 'jeweler'
|
11
|
+
Jeweler::Tasks.new do |gemspec|
|
12
|
+
gemspec.rubyforge_project = 'caper'
|
13
|
+
gemspec.name = "caper"
|
14
|
+
gemspec.summary = "FFI bindings for libpcap"
|
15
|
+
gemspec.email = "postmodern.mod3@gmail.com"
|
16
|
+
gemspec.homepage = "http://github.com/postmodern/caper"
|
17
|
+
gemspec.description = "Bindings to sniff packets using the FFI interface in Ruby."
|
18
|
+
gemspec.authors = ["Postmodern, Dakrone", "Eric Monti"]
|
19
|
+
gemspec.add_dependency "ffi"
|
20
|
+
gemspec.add_dependency "ffi_dry", ">= 0.1.9"
|
21
|
+
end
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
24
|
+
end
|
25
|
+
|
26
|
+
# vim: syntax=Ruby
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# ipfw add tee 6666 tcp from 192.168.63.128 to any
|
3
|
+
# ipfw add tee 6666 tcp from any to 192.168.63.128
|
4
|
+
|
5
|
+
require 'caper'
|
6
|
+
require "socket"
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
unless Process::Sys.getuid == 0
|
10
|
+
$stderr.puts "Must run #{$0} as root."
|
11
|
+
exit!
|
12
|
+
end
|
13
|
+
|
14
|
+
IPPROTO_DIVERT = 254
|
15
|
+
|
16
|
+
outfile = ARGV.shift
|
17
|
+
#outfile = "test_#{$$}.pcap"
|
18
|
+
|
19
|
+
# create a dummy pcap handle for dumping
|
20
|
+
pcap = Caper.open_dead(:datalink => :raw)
|
21
|
+
pcap_dumper = pcap.open_dump(outfile)
|
22
|
+
|
23
|
+
begin
|
24
|
+
divert_sock = Socket.open(Socket::PF_INET, Socket::SOCK_RAW, IPPROTO_DIVERT)
|
25
|
+
sockaddr = Socket.pack_sockaddr_in( 6666, '0.0.0.0' )
|
26
|
+
divert_sock.bind(sockaddr)
|
27
|
+
|
28
|
+
puts "ready and waiting...."
|
29
|
+
|
30
|
+
while IO.select([divert_sock], nil, nil)
|
31
|
+
data = divert_sock.recv(65535) # or MTU?
|
32
|
+
pp data
|
33
|
+
pcap_dumper.write_pkt( Caper::Packet.from_string(data) )
|
34
|
+
pcap_dumper.flush
|
35
|
+
end
|
36
|
+
rescue Errno::EPERM
|
37
|
+
$stderr.puts "Must run #{$0} as root."
|
38
|
+
exit!
|
39
|
+
ensure
|
40
|
+
puts "Closing socket."
|
41
|
+
divert_sock.close
|
42
|
+
puts "Closing pcap dumper."
|
43
|
+
pcap_dumper.close
|
44
|
+
pcap.close
|
45
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'caper'
|
5
|
+
|
6
|
+
pcap =
|
7
|
+
Caper::Live.new(:dev => 'en0',
|
8
|
+
:promisc => true,
|
9
|
+
:handler => Caper::Handler)
|
10
|
+
|
11
|
+
pcap.loop() do |this,pkt|
|
12
|
+
puts "#{pkt.time}:"
|
13
|
+
|
14
|
+
pkt.captured.times {|i| print ' %.2x' % pkt.body_ptr.get_uchar(i) }
|
15
|
+
putc "\n"
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'caper'
|
5
|
+
require 'rbkb/extends'
|
6
|
+
require 'ffi/packets'
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
include FFI
|
10
|
+
|
11
|
+
pcap =
|
12
|
+
Caper::Live.new( :dev => 'en0',
|
13
|
+
:promisc => true )
|
14
|
+
|
15
|
+
tblk = lambda do |this,pkt|
|
16
|
+
puts "#{pkt.time.asctime}:"
|
17
|
+
|
18
|
+
puts pkt.body.hexdump
|
19
|
+
putc "\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
wrap_blk = lambda do |id, phdr, buf|
|
23
|
+
tblk.call(pcap, Caper::Packet.new(phdr, buf))
|
24
|
+
end
|
25
|
+
#Caper.pcap_loop(pcap.pcap, 10, wrap_blk, nil)
|
26
|
+
puts "-"*70
|
27
|
+
|
28
|
+
pcap.loop(:count => 3, :handler => Caper::Handler.new, &tblk)
|
29
|
+
puts "-"*70
|
30
|
+
|
31
|
+
class Parser < Caper::Handler
|
32
|
+
def receive_pcap(*args)
|
33
|
+
pcap, pkt = super(*args)
|
34
|
+
p = pkt.body_ptr
|
35
|
+
parsed = []
|
36
|
+
eth = Packets::Eth::Hdr.new(p)
|
37
|
+
parsed << Packets::Eth::Hdr.new(p)
|
38
|
+
parsed << Packets::Ip::Hdr.new(p += eth.size) if eth.lookup_etype == "IP"
|
39
|
+
|
40
|
+
[pkt, parsed]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
pcap.loop(:count => 10, :parser => Parser) {|pkt, frames|
|
44
|
+
pp frames.map {|x| x.class}
|
45
|
+
pp({ frames[1].src => frames[1].dst })
|
46
|
+
}
|
47
|
+
|
48
|
+
|
data/lib/caper.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
begin; require 'rubygems'; rescue LoadError; end
|
2
|
+
|
3
|
+
require 'ffi_dry'
|
4
|
+
|
5
|
+
module Caper
|
6
|
+
extend FFI::Library
|
7
|
+
|
8
|
+
begin
|
9
|
+
ffi_lib "wpcap"
|
10
|
+
rescue LoadError
|
11
|
+
ffi_lib "pcap"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'caper/crt'
|
16
|
+
|
17
|
+
require 'caper/version'
|
18
|
+
require 'caper/exceptions'
|
19
|
+
|
20
|
+
# FFI typedefs, pointer wrappers, and struct
|
21
|
+
require 'caper/typedefs'
|
22
|
+
require 'caper/bsd'
|
23
|
+
require 'caper/addr'
|
24
|
+
require 'caper/interface'
|
25
|
+
require 'caper/file_header'
|
26
|
+
require 'caper/time_val'
|
27
|
+
require 'caper/packet_header'
|
28
|
+
require 'caper/stat'
|
29
|
+
require 'caper/bpf'
|
30
|
+
require 'caper/dumper'
|
31
|
+
|
32
|
+
# Ruby FFI function bindings, sugar, and misc wrappers
|
33
|
+
require 'caper/error_buffer'
|
34
|
+
require 'caper/pcap'
|
35
|
+
require 'caper/data_link'
|
36
|
+
require 'caper/packet'
|
37
|
+
require 'caper/live'
|
38
|
+
require 'caper/offline'
|
39
|
+
require 'caper/dead'
|
40
|
+
|
data/lib/caper/addr.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module Caper
|
3
|
+
|
4
|
+
# Representation of an interface address.
|
5
|
+
#
|
6
|
+
# See pcap_addr struct in pcap.h
|
7
|
+
class Addr < FFI::Struct
|
8
|
+
include FFI::DRY::StructHelper
|
9
|
+
|
10
|
+
dsl_layout do
|
11
|
+
p_struct :next, ::Caper::Addr
|
12
|
+
p_struct :addr, ::Caper::SockAddr, :desc => 'address'
|
13
|
+
p_struct :netmask, ::Caper::SockAddr, :desc => 'netmask of the address'
|
14
|
+
p_struct :broadcast, ::Caper::SockAddr, :desc => 'broadcast for the address'
|
15
|
+
p_struct :dest_addr, ::Caper::SockAddr, :desc => 'p2p destination for address'
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/caper/bpf.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
|
2
|
+
module Caper
|
3
|
+
|
4
|
+
# Includes structures defined in pcap-bpf.h
|
5
|
+
|
6
|
+
# Berkeley Packet Filter instruction data structure.
|
7
|
+
#
|
8
|
+
# See bpf_insn struct in pcap-bpf.h
|
9
|
+
class BPFInstruction < FFI::Struct
|
10
|
+
include FFI::DRY::StructHelper
|
11
|
+
|
12
|
+
dsl_layout do
|
13
|
+
field :code, :ushort
|
14
|
+
field :jt, :uchar
|
15
|
+
field :jf, :uchar
|
16
|
+
field :k, :bpf_int32
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
# Structure for pcap_compile(), pcap_setfilter(), etc.
|
22
|
+
#
|
23
|
+
# See bpf_program struct in pcap-bpf.h
|
24
|
+
class BPFProgram < FFI::Struct
|
25
|
+
include FFI::DRY::StructHelper
|
26
|
+
|
27
|
+
dsl_layout do
|
28
|
+
field :bf_len, :uint
|
29
|
+
field :bf_insn, :pointer
|
30
|
+
end
|
31
|
+
|
32
|
+
def instructions
|
33
|
+
i = 0
|
34
|
+
sz = BPFInstruction.size()
|
35
|
+
Array.new(self.bf_len) do
|
36
|
+
ins = BPFInstruction.new( self[:bf_insn] + i )
|
37
|
+
i += sz
|
38
|
+
ins
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def free!
|
43
|
+
unless @closed
|
44
|
+
@freed = true
|
45
|
+
Caper.pcap_freecode(self)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def freed?
|
50
|
+
return @freed == true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Compiles a bpf filter without a pcap device being open. Downside is
|
54
|
+
# no error messages are available, whereas they are when you use
|
55
|
+
# open_dead() and use compile() on the resulting Dead.
|
56
|
+
#
|
57
|
+
# @param [Hash] opts
|
58
|
+
# Additional options for compile
|
59
|
+
#
|
60
|
+
# @option opts [optional, DataLink, Integer, String, Symbol] :datalink
|
61
|
+
# DataLink layer type. The argument type will be resolved to a DataLink
|
62
|
+
# value if possible. Defaults to data-link layer type NULL.
|
63
|
+
#
|
64
|
+
# @option opts [optional, Integer] :snaplen
|
65
|
+
# The snapshot length for the filter. Defaults to SNAPLEN
|
66
|
+
#
|
67
|
+
# @option opts [optional, Integer] :optimize
|
68
|
+
# Optimization flag. 0 means don't optimize. Defaults to 1.
|
69
|
+
#
|
70
|
+
# @option opts [optional, Integer] :netmask
|
71
|
+
# A 32-bit number representing the IPv4 netmask of the network on which
|
72
|
+
# packets are being captured. It is only used when checking for IPv4
|
73
|
+
# broadcast addresses in the filter program. Default: 0 (unspecified
|
74
|
+
# netmask)
|
75
|
+
#
|
76
|
+
# @return [BPFProgram]
|
77
|
+
# If no errors occur, a compiled BPFProgram is returned.
|
78
|
+
#
|
79
|
+
def self.compile(expr, opts={})
|
80
|
+
datalink = (opts[:datalink] || 1)
|
81
|
+
dl = datalink.kind_of?(DataLink) ? datalink : DataLink.new(datalink)
|
82
|
+
slen = (opts[:snaplen] || DEFAULT_SNAPLEN)
|
83
|
+
optimize = (opts[:optimize] || 1)
|
84
|
+
mask = (opts[:netmask] || 0)
|
85
|
+
code = BPFProgram.new()
|
86
|
+
r = Caper.pcap_compile_nopcap(slen, dl.value, code, expr, optimize, mask)
|
87
|
+
raise(LibError, "pcap_compile_nopcap(): unspecified error") if r < 0
|
88
|
+
return code
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
attach_function :pcap_compile_nopcap, [:int, :int, BPFProgram, :string, :int, :bpf_uint32], :int
|
95
|
+
|
96
|
+
attach_function :bpf_filter, [BPFInstruction, :pointer, :uint, :uint], :uint
|
97
|
+
attach_function :bpf_validate, [BPFInstruction, :int], :int
|
98
|
+
attach_function :bpf_image, [BPFInstruction, :int], :string
|
99
|
+
attach_function :bpf_dump, [BPFProgram, :int], :void
|
100
|
+
attach_function :pcap_freecode, [BPFProgram], :void
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
|
data/lib/caper/bsd.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# Here's where various BSD sockets typedefs and structures go
|
2
|
+
# ... good to have around
|
3
|
+
# cribbed from dnet-ffi - EM
|
4
|
+
|
5
|
+
require 'socket'
|
6
|
+
|
7
|
+
module Caper
|
8
|
+
typedef :uint8, :sa_family_t
|
9
|
+
typedef :uint32, :in_addr_t
|
10
|
+
typedef :uint16, :in_port_t
|
11
|
+
|
12
|
+
# contains AF_* constants culled from Ruby's ::Socket
|
13
|
+
module AF
|
14
|
+
include ::FFI::DRY::ConstMap
|
15
|
+
slurp_constants(::Socket, "AF_")
|
16
|
+
def self.list; @@list ||= super() ; end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Common abstract superclass for all sockaddr struct classes
|
20
|
+
#
|
21
|
+
class SockAddrFamily < ::FFI::Struct
|
22
|
+
include ::FFI::DRY::StructHelper
|
23
|
+
|
24
|
+
# returns an address family name for the :family struct member value
|
25
|
+
def lookup_family
|
26
|
+
AF[ self[:family] ]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# generic sockaddr, always good to have around
|
31
|
+
#
|
32
|
+
class SockAddr < SockAddrFamily
|
33
|
+
dsl_layout do
|
34
|
+
field :len, :uint8, :desc => 'total length of struct'
|
35
|
+
field :family, :sa_family_t, :desc => 'address family (AF_*)'
|
36
|
+
field :data, :char, :desc => 'variable length bound by :len'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# Used to represent a 32-bit IPv4 address in a sock_addr_in structure
|
42
|
+
#
|
43
|
+
class InAddr < ::FFI::Struct
|
44
|
+
include ::FFI::DRY::StructHelper
|
45
|
+
dsl_layout { field :in_addr, :in_addr_t, :desc => 'inet address' }
|
46
|
+
end
|
47
|
+
|
48
|
+
# sockaddr inet, always good to have around
|
49
|
+
#
|
50
|
+
class SockAddrIn < SockAddrFamily
|
51
|
+
dsl_layout do
|
52
|
+
field :len, :uint8, :desc => 'length of structure (16)'
|
53
|
+
field :family, :sa_family_t, :desc => 'address family (AF_INET)'
|
54
|
+
field :port, :in_port_t, :desc => '16-bit TCP or UDP port number'
|
55
|
+
field :addr, :in_addr_t, :desc => '32-bit IPv4 address'
|
56
|
+
array :_sa_zero, [:uint8,8], :desc => 'unused'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Used to represent an IPv6 address in a sock_addr_in6 structure
|
61
|
+
#
|
62
|
+
class In6Addr < ::FFI::Struct
|
63
|
+
include ::FFI::DRY::StructHelper
|
64
|
+
dsl_layout { array :s6_addr, [:uint8, 16], :desc => 'IPv6 address' }
|
65
|
+
end
|
66
|
+
|
67
|
+
# IPv6 socket address
|
68
|
+
#
|
69
|
+
class SockAddrIn6 < SockAddrFamily
|
70
|
+
dsl_layout do
|
71
|
+
field :len, :uint8, :desc => 'length of structure(24)'
|
72
|
+
field :family, :sa_family_t, :desc => 'address family (AF_INET6)'
|
73
|
+
field :port, :in_port_t, :desc => 'transport layer port'
|
74
|
+
field :flowinfo, :uint32, :desc => 'priority & flow label'
|
75
|
+
struct :addr, ::Caper::In6Addr, :desc => 'IPv6 address'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
# data-link socket address
|
81
|
+
#
|
82
|
+
class SockAddrDl < SockAddrFamily
|
83
|
+
dsl_layout do
|
84
|
+
field :len, :uint8, :desc => 'length of structure(variable)'
|
85
|
+
field :family, :sa_family_t, :desc => 'address family (AF_LINK)'
|
86
|
+
field :sdl_index, :uint16, :desc => 'system assigned index, if > 0'
|
87
|
+
field :dltype, :uint8, :desc => 'IFT_ETHER, etc. from net/if_types.h'
|
88
|
+
field :nlen, :uint8, :desc => 'name length, from :_data'
|
89
|
+
field :alen, :uint8, :desc => 'link-layer addres-length'
|
90
|
+
field :slen, :uint8, :desc => 'link-layer selector length'
|
91
|
+
field :_data, :char, :desc => 'minimum work area=12, can be larger'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|