dnet-ffi 0.1.3
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.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +37 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/dnet-ffi.gemspec +99 -0
- data/lib/dnet.rb +35 -0
- data/lib/dnet/addr.rb +204 -0
- data/lib/dnet/arp.rb +168 -0
- data/lib/dnet/blob.rb +246 -0
- data/lib/dnet/bsd.rb +123 -0
- data/lib/dnet/constants.rb +555 -0
- data/lib/dnet/eth.rb +143 -0
- data/lib/dnet/fw.rb +106 -0
- data/lib/dnet/helpers.rb +164 -0
- data/lib/dnet/icmp.rb +304 -0
- data/lib/dnet/intf.rb +194 -0
- data/lib/dnet/ip.rb +315 -0
- data/lib/dnet/ip6.rb +59 -0
- data/lib/dnet/rand.rb +33 -0
- data/lib/dnet/route.rb +103 -0
- data/lib/dnet/tcp.rb +103 -0
- data/lib/dnet/tun.rb +24 -0
- data/lib/dnet/typedefs.rb +12 -0
- data/lib/dnet/udp.rb +31 -0
- data/lib/dnet/util.rb +70 -0
- data/samples/eth_send_raw.rb +29 -0
- data/samples/ifconfig-alike.rb +44 -0
- data/samples/udp_send_raw.rb +74 -0
- data/spec/addr_spec.rb +15 -0
- data/spec/arp_spec.rb +95 -0
- data/spec/blob_spec.rb +15 -0
- data/spec/bsd_spec.rb +60 -0
- data/spec/dnet-ffi_spec.rb +31 -0
- data/spec/eth_spec.rb +47 -0
- data/spec/fw_spec.rb +15 -0
- data/spec/intf_spec.rb +98 -0
- data/spec/ip6_spec.rb +15 -0
- data/spec/ip_spec.rb +15 -0
- data/spec/rand_spec.rb +15 -0
- data/spec/route_spec.rb +94 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/tun_spec.rb +15 -0
- metadata +121 -0
data/lib/dnet/arp.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# Address resolution Protocol
|
2
|
+
|
3
|
+
module Dnet
|
4
|
+
module Arp
|
5
|
+
# ARP header
|
6
|
+
#
|
7
|
+
# field :hrd, :uint16, :desc => 'format of hardware address'
|
8
|
+
# field :pro, :uint16, :desc => 'format of protocol address'
|
9
|
+
# field :hln, :uint16, :desc => 'length of hw address (ETH_ADDR_LEN)'
|
10
|
+
# field :pln, :uint16, :desc => 'length of proto address (IP_ADDR_LEN)'
|
11
|
+
# field :op, :uint16, :desc => 'operation'
|
12
|
+
class Hdr < ::FFI::Struct
|
13
|
+
include ::FFI::DRY::StructHelper
|
14
|
+
include ::Dnet::NetEndianHelper
|
15
|
+
|
16
|
+
dsl_layout do
|
17
|
+
field :hrd, :uint16, :desc => 'format of hardware address'
|
18
|
+
field :pro, :uint16, :desc => 'format of protocol address'
|
19
|
+
field :hln, :uint16, :desc => 'length of hw address (ETH_ADDR_LEN)'
|
20
|
+
field :pln, :uint16, :desc => 'length of proto address (IP_ADDR_LEN)'
|
21
|
+
field :op, :uint16, :desc => 'operation'
|
22
|
+
end
|
23
|
+
|
24
|
+
# ARP operations
|
25
|
+
module Op
|
26
|
+
::Dnet.constants.grep(/^(ARP_OP_([A-Z][A-Z0-9_]+))$/) do
|
27
|
+
self.const_set $2, ::Dnet.const_get($1)
|
28
|
+
end
|
29
|
+
|
30
|
+
module_function
|
31
|
+
def list
|
32
|
+
@@list ||= constants.inject({}){|h,c| h.merge! c => const_get(c) }
|
33
|
+
end
|
34
|
+
end # Op
|
35
|
+
end # Hdr
|
36
|
+
|
37
|
+
# Ethernet/IP ARP message
|
38
|
+
#
|
39
|
+
# array :sha, [:uint8, ETH_ADDR_LEN], :desc => 'sender hardware address'
|
40
|
+
# array :spa, [:uint8, IP_ADDR_LEN], :desc => 'sender protocol address'
|
41
|
+
# array :tha, [:uint8, ETH_ADDR_LEN], :desc => 'target hardware address'
|
42
|
+
# array :tpa, [:uint8, IP_ADDR_LEN], :desc => 'target protocol address'
|
43
|
+
#
|
44
|
+
class Ethip < ::FFI::Struct
|
45
|
+
include ::FFI::DRY::StructHelper
|
46
|
+
include ::Dnet::NetEndianHelper
|
47
|
+
|
48
|
+
dsl_layout do
|
49
|
+
array :sha, [:uint8, ETH_ADDR_LEN], :desc => 'sender hardware address'
|
50
|
+
array :spa, [:uint8, IP_ADDR_LEN], :desc => 'sender protocol address'
|
51
|
+
array :tha, [:uint8, ETH_ADDR_LEN], :desc => 'target hardware address'
|
52
|
+
array :tpa, [:uint8, IP_ADDR_LEN], :desc => 'target protocol address'
|
53
|
+
end
|
54
|
+
|
55
|
+
end # Ethip
|
56
|
+
|
57
|
+
|
58
|
+
# FFI mapping to libdnet's "arp_entry" struct.
|
59
|
+
#
|
60
|
+
# dnet(3)'s ARP cache entries are described by the following C structure:
|
61
|
+
#
|
62
|
+
# struct :pa, ::Dnet::Addr, :desc => 'protocol address'
|
63
|
+
# struct :ha, ::Dnet::Addr, :desc => 'hardware address'
|
64
|
+
#
|
65
|
+
class Entry < ::FFI::Struct
|
66
|
+
include ::FFI::DRY::StructHelper
|
67
|
+
|
68
|
+
dsl_layout do
|
69
|
+
struct :pa, ::Dnet::Addr, :desc => 'protocol address'
|
70
|
+
struct :ha, ::Dnet::Addr, :desc => 'hardware address'
|
71
|
+
end
|
72
|
+
|
73
|
+
end # Entry
|
74
|
+
|
75
|
+
# A handle for accessing the kernel arp(4) cache. This does not require
|
76
|
+
# root privileges.
|
77
|
+
class Handle < LoopableHandle
|
78
|
+
|
79
|
+
# Obtains a handle to access the kernel arp(4) cache. Uses dnet(3)'s
|
80
|
+
# arp_open() function under the hood.
|
81
|
+
def initialize
|
82
|
+
if (@handle = ::Dnet.arp_open).address == 0
|
83
|
+
raise H_ERR.new("unable to open arp handle")
|
84
|
+
end
|
85
|
+
_handle_opened!
|
86
|
+
end
|
87
|
+
|
88
|
+
# Closes the handle. Uses dnet(3)'s arp_close() function under the hood.
|
89
|
+
def close
|
90
|
+
_do_if_open { _handle_closed!; ::Dnet.arp_close(@handle) }
|
91
|
+
end
|
92
|
+
|
93
|
+
# Iterates over the kernel arp cache, yielding each entry (cast as an
|
94
|
+
# Entry) to a block. Uses dnet(3)'s arp_loop() function under the hood.
|
95
|
+
def loop &block
|
96
|
+
_loop ::Dnet, :arp_loop, Entry, &block
|
97
|
+
end
|
98
|
+
|
99
|
+
# Retrieves the ARP entry for the protocol address specified by 'addr'
|
100
|
+
# (supplied as a String). Uses dnet(3)'s addr_aton() function to parse
|
101
|
+
# 'addr' and arp_get() to retrieve a result, which is cast as an Entry
|
102
|
+
# instance.
|
103
|
+
def get(addr)
|
104
|
+
_check_open!
|
105
|
+
ae = Entry.new
|
106
|
+
return ae if ae.pa.set_string(addr) and
|
107
|
+
::Dnet.arp_get(@handle, ae) == 0
|
108
|
+
end
|
109
|
+
|
110
|
+
# Adds a new ARP entry specified as an Entry object. Uses dnet(3)'s
|
111
|
+
# arp_add() function under the hood.
|
112
|
+
def add(entry)
|
113
|
+
_check_open!
|
114
|
+
::Dnet.arp_add(@handle, entry)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Deletes the ARP entry for the protocol address specified by
|
118
|
+
# 'entry' supplied as an Entry object. Uses dnet(3)'s arp_delete()
|
119
|
+
# function under the hood.
|
120
|
+
def delete(entry)
|
121
|
+
_check_open!
|
122
|
+
::Dnet.arp_delete(@handle, entry)
|
123
|
+
end
|
124
|
+
|
125
|
+
end # Handle
|
126
|
+
|
127
|
+
# #define arp_pack_hdr_ethip(hdr, op, sha, spa, tha, tpa) do { \
|
128
|
+
# struct arp_hdr *pack_arp_p = (struct arp_hdr *)(hdr); \
|
129
|
+
# struct arp_ethip *pack_ethip_p = (struct arp_ethip *) \
|
130
|
+
# ((uint8_t *)(hdr) + ARP_HDR_LEN); \
|
131
|
+
# pack_arp_p->ar_hrd = htons(ARP_HRD_ETH); \
|
132
|
+
# pack_arp_p->ar_pro = htons(ARP_PRO_IP); \
|
133
|
+
# pack_arp_p->ar_hln = ETH_ADDR_LEN; \
|
134
|
+
# pack_arp_p->ar_pln = IP_ADDR_LEN; \
|
135
|
+
# pack_arp_p->ar_op = htons(op); \
|
136
|
+
# memmove(pack_ethip_p->ar_sha, &(sha), ETH_ADDR_LEN); \
|
137
|
+
# memmove(pack_ethip_p->ar_spa, &(spa), IP_ADDR_LEN); \
|
138
|
+
# memmove(pack_ethip_p->ar_tha, &(tha), ETH_ADDR_LEN); \
|
139
|
+
# memmove(pack_ethip_p->ar_tpa, &(tpa), IP_ADDR_LEN); \
|
140
|
+
# } while (0)
|
141
|
+
|
142
|
+
def self.open(*args)
|
143
|
+
Handle.open(*args) {|*y| yield(*y) if block_given? }
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.each_entry(*args)
|
147
|
+
Handle.each_entry(*args) {|*y| yield(*y) }
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.entries(*args)
|
151
|
+
Handle.entries(*args)
|
152
|
+
end
|
153
|
+
|
154
|
+
end # Arp
|
155
|
+
|
156
|
+
# This is just an alias for Arp::Handle
|
157
|
+
ArpHandle = Arp::Handle
|
158
|
+
|
159
|
+
typedef :pointer, :arp_t
|
160
|
+
callback :arp_handler, [Arp::Entry, :ulong], :int
|
161
|
+
attach_function :arp_open, [], :arp_t
|
162
|
+
attach_function :arp_add, [:arp_t, Arp::Entry], :int
|
163
|
+
attach_function :arp_delete, [:arp_t, Arp::Entry], :int
|
164
|
+
attach_function :arp_get, [:arp_t, Arp::Entry], :int
|
165
|
+
attach_function :arp_loop, [:arp_t, :arp_handler, :ulong], :int
|
166
|
+
attach_function :arp_close, [:arp_t], :arp_t
|
167
|
+
|
168
|
+
end
|
data/lib/dnet/blob.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
|
2
|
+
## blob is dnet(3)'s name for binary buffers
|
3
|
+
|
4
|
+
module Dnet
|
5
|
+
|
6
|
+
# FFI mapping to dnet(3)'s "blob_t" binary buffer struct.
|
7
|
+
#
|
8
|
+
# field :base, :pointer, :desc => 'start of data'
|
9
|
+
# field :off, :pointer, :desc => 'offset into data'
|
10
|
+
# field :end, :pointer, :desc => 'end of data'
|
11
|
+
# field :size, :pointer, :desc => 'size of allocation'
|
12
|
+
#
|
13
|
+
class Blob < FFI::ManagedStruct
|
14
|
+
include ::FFI::DRY::StructHelper
|
15
|
+
include HandleHelpers
|
16
|
+
|
17
|
+
dsl_layout do
|
18
|
+
field :base, :pointer, :desc => 'start of data'
|
19
|
+
field :off, :int, :desc => 'offset into data'
|
20
|
+
field :end, :int, :desc => 'end of data'
|
21
|
+
field :size, :int, :desc => 'size of allocation'
|
22
|
+
end
|
23
|
+
|
24
|
+
# Initializes a new Blob using dnet(3)'s blob_new under the hood.
|
25
|
+
#
|
26
|
+
# blob_new is used to allocate a new dynamic binary buffer, returning
|
27
|
+
# NULL on failure.
|
28
|
+
#
|
29
|
+
# Below is the dnet(3) C function definition:
|
30
|
+
#
|
31
|
+
# blob_t * blob_new(void);
|
32
|
+
#
|
33
|
+
def initialize
|
34
|
+
super(::Dnet.blob_new())
|
35
|
+
_handle_opened!
|
36
|
+
end
|
37
|
+
|
38
|
+
# Called by the garbage collector for ::FFI:ManagedStruct objects
|
39
|
+
def self.release(blob)
|
40
|
+
blob.release()
|
41
|
+
end
|
42
|
+
|
43
|
+
def base_ptr
|
44
|
+
self[:base]
|
45
|
+
end
|
46
|
+
|
47
|
+
def curr_ptr
|
48
|
+
safe[:base] + self[:off]
|
49
|
+
end
|
50
|
+
|
51
|
+
def end_ptr
|
52
|
+
self[:base] + self[:end]
|
53
|
+
end
|
54
|
+
|
55
|
+
# This method calls dnet(3)'s blob_free behind the scenes. It should
|
56
|
+
# automatically get run by the garbage collector when a blob is no longer
|
57
|
+
# referenced.
|
58
|
+
#
|
59
|
+
# blob_free deallocates the memory associated with blob b and returns NULL.
|
60
|
+
def release
|
61
|
+
_do_if_open { _handle_closed! ; ::Dnet.blob_free(self) }
|
62
|
+
end
|
63
|
+
|
64
|
+
# blob_pack converts and writes, and blob_unpack() reads and converts data
|
65
|
+
# in blob b according to the given format fmt as described below, returning
|
66
|
+
# 0 on success, and -1 on failure.
|
67
|
+
#
|
68
|
+
# The format string is composed of zero or more directives: ordinary
|
69
|
+
# characters (not % ), which are copied to / read from the blob, and
|
70
|
+
# conversion specifications, each of which results in reading / writing
|
71
|
+
# zero or more subsequent arguments.
|
72
|
+
#
|
73
|
+
# Each conversion specification is introduced by the character %, and may
|
74
|
+
# be prefixed by length specifier. The arguments must correspond properly
|
75
|
+
# (after type promotion) with the length and conversion specifiers.
|
76
|
+
#
|
77
|
+
# The length specifier is either a a decimal digit string specifying the
|
78
|
+
# length of the following argument, or the literal character * indicating
|
79
|
+
# that the length should be read from an integer argument for the argument
|
80
|
+
# following it.
|
81
|
+
#
|
82
|
+
# The conversion specifiers and their meanings are:
|
83
|
+
#
|
84
|
+
# D An unsigned 32-bit integer in network byte order.
|
85
|
+
# H An unsigned 16-bit integer in network byte order.
|
86
|
+
# b A binary buffer (length specifier required).
|
87
|
+
# c An unsigned character.
|
88
|
+
# d An unsigned 32-bit integer in host byte order.
|
89
|
+
# h An unsigned 16-bit integer in host byte order.
|
90
|
+
# s A C-style null-terminated string, whose maximum length must be
|
91
|
+
# specified when unpacking.
|
92
|
+
#
|
93
|
+
# Custom conversion routines and their specifiers may be registered via
|
94
|
+
# blob_register_pack, currently undocumented.
|
95
|
+
#
|
96
|
+
# TODO add ruby wrapper for blob_register_pack.
|
97
|
+
#
|
98
|
+
# XXX want to wrap varargs FFI for easier type casting?
|
99
|
+
def pack(sfmt, *args)
|
100
|
+
_check_open!
|
101
|
+
(fmt = ::FFI::MemoryPointer.from_string(sfmt)).autorelease=true
|
102
|
+
::Dnet.blob_pack(self, fmt, *args)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Uses dnet(3)s 'blob_unpack' under the hood. See pack() for more
|
106
|
+
# information.
|
107
|
+
#
|
108
|
+
# XXX TODO - want to wrap varargs FFI for easier type casting?
|
109
|
+
def unpack(sfmt, *args)
|
110
|
+
_check_open!
|
111
|
+
(fmt = ::FFI::MemoryPointer.from_string(sfmt)).autorelease=true
|
112
|
+
::Dnet.blob_unpack(self, fmt, *args)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Writes the data supplied from a string or pointer to the blob at the
|
116
|
+
# current offset. If a pointer is supplied, a size must accompany it.
|
117
|
+
# Uses dnet(3)'s "blob_write" under the hood.
|
118
|
+
def write(buf, bsz=nil)
|
119
|
+
_check_open!
|
120
|
+
ptr, psz = ::Dnet::Util.derive_pointer(buf, bsz)
|
121
|
+
::Dnet.blob_write(self, ptr, psz)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Reads 'len' bytes out of the blob from the current offset. If len is nil
|
125
|
+
# (the default) then all remaining bytes are read. Moves the offset
|
126
|
+
# accordingly. This method uses dnet(3)'s "blob_read" under the hood.
|
127
|
+
def read(len=nil)
|
128
|
+
_check_open!
|
129
|
+
len ||= self[:end] - self[:off]
|
130
|
+
(buf = ::FFI::MemoryPointer.new("\x00", len)).autorelease = true
|
131
|
+
if rlen=::Dnet.blob_read(self, buf, len)
|
132
|
+
return buf.read_string_length(rlen)
|
133
|
+
else
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns the entirety of the blob from beginning to end.
|
139
|
+
# Note, this will also move the offset to the end of the buffer.
|
140
|
+
def string()
|
141
|
+
_check_open!
|
142
|
+
rewind()
|
143
|
+
read()
|
144
|
+
end
|
145
|
+
|
146
|
+
# rewinds the blob buffer offset to the beginning
|
147
|
+
def rewind
|
148
|
+
_check_open!
|
149
|
+
::Dnet.blob_seek(self, 0, 0)
|
150
|
+
end
|
151
|
+
|
152
|
+
# sets the blob buffer offset to p. returns -1 on failure
|
153
|
+
def pos=(p)
|
154
|
+
_check_open!
|
155
|
+
::Dnet.blob_seek(self, p.to_i, 0)
|
156
|
+
end
|
157
|
+
|
158
|
+
# base pointer - start of data
|
159
|
+
def base;
|
160
|
+
_check_open!
|
161
|
+
self[:base]
|
162
|
+
end
|
163
|
+
|
164
|
+
# size of allocated data - aka self[:size]
|
165
|
+
def blob_size;
|
166
|
+
_check_open!
|
167
|
+
self[:size]
|
168
|
+
end
|
169
|
+
|
170
|
+
# returns the current position offset of the blob buffer - aka self[:off]
|
171
|
+
def pos
|
172
|
+
_check_open!
|
173
|
+
self[:off]
|
174
|
+
end
|
175
|
+
|
176
|
+
# returns the end of the blob buffer in use - aka self[:end]
|
177
|
+
def blob_end
|
178
|
+
_check_open!
|
179
|
+
self[:end]
|
180
|
+
end
|
181
|
+
|
182
|
+
# This method calls dnet(3)'s blob_seek under the hood.
|
183
|
+
#
|
184
|
+
# blob_seek repositions the offset within blob b to off, according to the
|
185
|
+
# directive whence (see lseek(2) for details), returning the new absolute
|
186
|
+
# offset, or -1 on failure.
|
187
|
+
def seek(off, whence=0)
|
188
|
+
_check_open!
|
189
|
+
::Dnet.blob_seek(self, off.to_i, whence.to_i)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Uses dnet(3)'s "blob_index" under the hood. An additional 'rewind'
|
193
|
+
# argument was added which can be used to force a rewind before searching.
|
194
|
+
# The default value for "rewind" is "false". nil is returned on a failed
|
195
|
+
# search.
|
196
|
+
def index(bstr, rewind=false)
|
197
|
+
_check_open!
|
198
|
+
self.rewind() if rewind
|
199
|
+
(buf = ::FFI::MemoryPointer.from_string(bstr)).autorelease=true
|
200
|
+
if (i=::Dnet.blob_index(self, buf, bstr.size)) > -1
|
201
|
+
return i
|
202
|
+
else
|
203
|
+
return nil
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Uses dnet(3)'s "blob_rindex" under the hood. An additional 'rewind'
|
208
|
+
# argument was added which can be used to force a rewind before searching.
|
209
|
+
# The default value for "rewind" is "false". nil is returned on a failed
|
210
|
+
# search.
|
211
|
+
def rindex(buf, rewind=false)
|
212
|
+
_check_open!
|
213
|
+
self.rewind() if rewind
|
214
|
+
(buf = ::FFI::MemoryPointer.from_string(bstr)).autorelease=true
|
215
|
+
if (i=::Dnet.blob_rindex(self, buf, bstr.size)) > -1
|
216
|
+
return i
|
217
|
+
else
|
218
|
+
return nil
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Prints a hexdump on standard output using dnet(3)'s "blob_print" under
|
223
|
+
# the hood. Can optionally rewind the blob before dumping using the
|
224
|
+
# 'rewind' argument (default: rewind=true).
|
225
|
+
#
|
226
|
+
# NOTE: len does not appear to do anything at all for blob_print
|
227
|
+
def print_dump(rewind=true, len=nil)
|
228
|
+
_check_open!
|
229
|
+
self.rewind if rewind==true
|
230
|
+
len ||= self[:end] - self[:off]
|
231
|
+
Dnet.blob_print(self, "hexl", len.to_i)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
attach_function :blob_new, [], :pointer
|
236
|
+
attach_function :blob_read, [Blob, :pointer, :int], :int
|
237
|
+
attach_function :blob_write, [Blob, :pointer, :int], :int
|
238
|
+
attach_function :blob_seek, [Blob, :int, :int], :int
|
239
|
+
attach_function :blob_index, [Blob, :pointer, :int], :int
|
240
|
+
attach_function :blob_rindex, [Blob, :string, :int], :int
|
241
|
+
attach_function :blob_pack, [Blob, :string, :varargs], :int
|
242
|
+
attach_function :blob_unpack, [Blob, :string, :varargs], :int
|
243
|
+
attach_function :blob_print, [Blob, :string, :int], :int
|
244
|
+
attach_function :blob_free, [Blob], :pointer
|
245
|
+
end
|
246
|
+
|
data/lib/dnet/bsd.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
# Here's where various BSD sockets typedefs and structures go
|
2
|
+
# ... good to have around
|
3
|
+
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
module Dnet
|
7
|
+
typedef :uint8, :sa_family_t
|
8
|
+
typedef :uint32, :in_addr_t
|
9
|
+
typedef :uint16, :in_port_t
|
10
|
+
|
11
|
+
# contains AF_* constants culled from Ruby's ::Socket
|
12
|
+
module AF
|
13
|
+
include ::FFI::DRY::ConstMap
|
14
|
+
slurp_constants(::Socket, "AF_")
|
15
|
+
def self.list; @@list ||= super() ; end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Common superclass for all sockaddr struct classes
|
19
|
+
#
|
20
|
+
class SockAddrFamily < ::FFI::Struct
|
21
|
+
include ::FFI::DRY::StructHelper
|
22
|
+
|
23
|
+
# returns an address family name for the :family struct member value
|
24
|
+
def lookup_family
|
25
|
+
::Dnet::AF[ self[:family] ]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# generic sockaddr, always good to have around
|
30
|
+
#
|
31
|
+
# field :len, :uint8, :desc => 'total length of struct'
|
32
|
+
# field :family, :sa_family_t, :desc => 'address family (AF_*)'
|
33
|
+
# field :data, :char, :desc => 'variable length bound by :len'
|
34
|
+
#
|
35
|
+
class SockAddr < SockAddrFamily
|
36
|
+
dsl_layout do
|
37
|
+
field :len, :uint8, :desc => 'total length of struct'
|
38
|
+
field :family, :sa_family_t, :desc => 'address family (AF_*)'
|
39
|
+
field :data, :char, :desc => 'variable length bound by :len'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Used to represent a 32-bit IPv4 address in a sock_addr_in structure
|
45
|
+
#
|
46
|
+
# field :in_addr, :in_addr_t, :desc => 'inet address' }
|
47
|
+
#
|
48
|
+
class InAddr < ::FFI::Struct
|
49
|
+
include ::FFI::DRY::StructHelper
|
50
|
+
dsl_layout { field :in_addr, :in_addr_t, :desc => 'inet address' }
|
51
|
+
end
|
52
|
+
|
53
|
+
# sockaddr inet, always good to have around
|
54
|
+
#
|
55
|
+
# field :len, :uint8, :desc => 'length of structure (16)'
|
56
|
+
# field :family, :sa_family_t, :desc => 'address family (AF_INET)'
|
57
|
+
# field :port, :in_port_t, :desc => '16-bit TCP or UDP port number'
|
58
|
+
# field :addr, :in_addr_t, :desc => '32-bit IPv4 address'
|
59
|
+
# field :_sa_zero, [:uint8,8], :desc => 'unused'
|
60
|
+
#
|
61
|
+
class SockAddrIn < SockAddrFamily
|
62
|
+
dsl_layout do
|
63
|
+
field :len, :uint8, :desc => 'length of structure (16)'
|
64
|
+
field :family, :sa_family_t, :desc => 'address family (AF_INET)'
|
65
|
+
field :port, :in_port_t, :desc => '16-bit TCP or UDP port number'
|
66
|
+
field :addr, :in_addr_t, :desc => '32-bit IPv4 address'
|
67
|
+
array :_sa_zero, [:uint8,8], :desc => 'unused'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Used to represent an IPv6 address in a sock_addr_in6 structure
|
72
|
+
#
|
73
|
+
# field :s6_addr, [:uint, 16], :desc => 'IPv6 address'
|
74
|
+
#
|
75
|
+
class In6Addr < ::FFI::Struct
|
76
|
+
include ::FFI::DRY::StructHelper
|
77
|
+
dsl_layout { array :s6_addr, [:uint8, 16], :desc => 'IPv6 address' }
|
78
|
+
end
|
79
|
+
|
80
|
+
# IPv6 socket address
|
81
|
+
#
|
82
|
+
# field :len, :uint8, :desc => 'length of structure(24)'
|
83
|
+
# field :family, :sa_family_t, :desc => 'address family (AF_INET6)'
|
84
|
+
# field :port, :in_port_t, :desc => 'transport layer port'
|
85
|
+
# field :flowinfo, :uint32, :desc => 'priority & flow label'
|
86
|
+
# struct :addr, In6Addr :desc => 'IPv6 address'
|
87
|
+
#
|
88
|
+
class SockAddrIn6 < SockAddrFamily
|
89
|
+
dsl_layout do
|
90
|
+
field :len, :uint8, :desc => 'length of structure(24)'
|
91
|
+
field :family, :sa_family_t, :desc => 'address family (AF_INET6)'
|
92
|
+
field :port, :in_port_t, :desc => 'transport layer port'
|
93
|
+
field :flowinfo, :uint32, :desc => 'priority & flow label'
|
94
|
+
struct :addr, In6Addr, :desc => 'IPv6 address'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
# data-link socket address
|
100
|
+
#
|
101
|
+
# field :len, :uint8, :desc => 'length of structure(variable)'
|
102
|
+
# field :family,:sa_family_t, :desc => 'address family (AF_LINK)'
|
103
|
+
# field :sdl_index, :uint16, :desc => 'system assigned index, if > 0'
|
104
|
+
# field :dltype, :uint8, :desc => 'IFT_ETHER, etc. from net/if_types.h'
|
105
|
+
# field :nlen, :uint8, :desc => 'name length, from :_data'
|
106
|
+
# field :alen, :uint8, :desc => 'link-layer addres-length'
|
107
|
+
# field :slen, :uint8, :desc => 'link-layer selector length'
|
108
|
+
# field :_data, :char, :desc => 'minimum work area=12, can be larger'
|
109
|
+
#
|
110
|
+
class SockAddrDl < SockAddrFamily
|
111
|
+
dsl_layout do
|
112
|
+
field :len, :uint8, :desc => 'length of structure(variable)'
|
113
|
+
field :family, :sa_family_t, :desc => 'address family (AF_LINK)'
|
114
|
+
field :sdl_index, :uint16, :desc => 'system assigned index, if > 0'
|
115
|
+
field :dltype, :uint8, :desc => 'IFT_ETHER, etc. from net/if_types.h'
|
116
|
+
field :nlen, :uint8, :desc => 'name length, from :_data'
|
117
|
+
field :alen, :uint8, :desc => 'link-layer addres-length'
|
118
|
+
field :slen, :uint8, :desc => 'link-layer selector length'
|
119
|
+
field :_data, :char, :desc => 'minimum work area=12, can be larger'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|