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/intf.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Dnet
|
4
|
+
|
5
|
+
# Bindings and interface to dnet(3)'s api for network interfaces
|
6
|
+
module Intf
|
7
|
+
|
8
|
+
# An interface table entry
|
9
|
+
#
|
10
|
+
# field :len, :uint, :desc => 'length of entry'
|
11
|
+
# array :if_name, [:uint8, INTF_NAME_LEN], :desc => 'interface name'
|
12
|
+
# field :itype, :ushort, :desc => 'interface type'
|
13
|
+
# field :flags, :ushort, :desc => 'interface flags'
|
14
|
+
# field :mtu, :uint, :desc => 'interface MTU'
|
15
|
+
# struct :if_addr, ::Dnet::Addr, :desc => 'interface address'
|
16
|
+
# struct :dst_addr, ::Dnet::Addr, :desc => 'point-to-point dst'
|
17
|
+
# struct :link_addr, ::Dnet::Addr, :desc => 'link-layer address'
|
18
|
+
# field :alias_num, :uint, :desc => 'number of aliases'
|
19
|
+
# # :if_aliases, ::Dnet::Addr ) ## variable-length array of aliases
|
20
|
+
#
|
21
|
+
class Entry < ::FFI::Struct
|
22
|
+
include ::FFI::DRY::StructHelper
|
23
|
+
|
24
|
+
dsl_layout do
|
25
|
+
field :len, :uint, :desc => 'length of entry'
|
26
|
+
array :if_name, [:uint8, INTF_NAME_LEN], :desc => 'interface name'
|
27
|
+
field :itype, :ushort, :desc => 'interface type'
|
28
|
+
field :flags, :ushort, :desc => 'interface flags'
|
29
|
+
field :mtu, :uint, :desc => 'interface MTU'
|
30
|
+
struct :if_addr, ::Dnet::Addr, :desc => 'interface address'
|
31
|
+
struct :dst_addr, ::Dnet::Addr, :desc => 'point-to-point dst'
|
32
|
+
struct :link_addr, ::Dnet::Addr, :desc => 'link-layer address'
|
33
|
+
field :alias_num, :uint, :desc => 'number of aliases'
|
34
|
+
# :if_aliases, ::Dnet::Addr ) ## variable-length array of aliases
|
35
|
+
end
|
36
|
+
|
37
|
+
# Constants map for interface flags. This is a map of flags, so
|
38
|
+
# lookups for integers using [nnn] return a list of flags present in nnn.
|
39
|
+
# Lookups for names using ["XX"], ["xx"] or [:xx] still return the value
|
40
|
+
# of the constant named XX.
|
41
|
+
module Flags
|
42
|
+
include ::FFI::DRY::ConstFlagsMap
|
43
|
+
slurp_constants(::Dnet, "INTF_FLAG_")
|
44
|
+
def self.list; @@list ||= super(); end
|
45
|
+
end
|
46
|
+
|
47
|
+
def lookup_flags; Flags[self[:flags]]; end
|
48
|
+
|
49
|
+
# Constants map for interface types
|
50
|
+
module Itype
|
51
|
+
include ::FFI::DRY::ConstMap
|
52
|
+
slurp_constants(::Dnet, "INTF_TYPE_")
|
53
|
+
def self.list; @@list ||= super(); end
|
54
|
+
end
|
55
|
+
|
56
|
+
def lookup_itype; Itype[self[:itype]]; end
|
57
|
+
|
58
|
+
# Returns a newly instantiated and allocated copy of this interface entry
|
59
|
+
def copy
|
60
|
+
xtra = (::Dnet::Addr.size * self.alias_num)
|
61
|
+
if self.len == (Entry.size + xtra)
|
62
|
+
super(xtra)
|
63
|
+
else
|
64
|
+
super()
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# returns an array containing all the aliases for this interface
|
69
|
+
def aliases
|
70
|
+
ary = []
|
71
|
+
asz = ::Dnet::Addr.size
|
72
|
+
p = (self.to_ptr() + Entry.size) # start at end of struct
|
73
|
+
self[:alias_num].times do
|
74
|
+
ary << ::Dnet::Addr.new(p)
|
75
|
+
p += asz
|
76
|
+
end
|
77
|
+
return ary
|
78
|
+
end
|
79
|
+
|
80
|
+
# returns the interface name string of this object
|
81
|
+
def if_name; self[:if_name].to_ptr.read_string; end
|
82
|
+
|
83
|
+
# sets the interface name string on this object.
|
84
|
+
def if_name=(val)
|
85
|
+
name = ::Dnet.truncate_cstr(val, INTF_NAME_LEN)
|
86
|
+
self[:if_name].to_ptr.write_string_length(name.to_s, len)
|
87
|
+
end
|
88
|
+
alias set_name if_name=
|
89
|
+
|
90
|
+
end # class Entry
|
91
|
+
|
92
|
+
# A handle to the network interface configuration.
|
93
|
+
# This class manages a dnet(3) intf_t handle through intf_open() and
|
94
|
+
# intf_close() and wraps several libdnet functions as ruby methods.
|
95
|
+
class Handle < ::Dnet::LoopableHandle
|
96
|
+
|
97
|
+
# Obtains a handle to access the network interface configuration.
|
98
|
+
def initialize
|
99
|
+
if (@handle = ::Dnet.intf_open).address == 0
|
100
|
+
raise H_ERR.new("unable to open interface handle")
|
101
|
+
end
|
102
|
+
_handle_opened!
|
103
|
+
end
|
104
|
+
|
105
|
+
# Closes the handle. Uses dnet(3)'s arp_close() function under the hood
|
106
|
+
def close
|
107
|
+
_do_if_open { _handle_closed!; ::Dnet.intf_close(@handle) }
|
108
|
+
end
|
109
|
+
|
110
|
+
# Iterates over all network interfaces, yielding each entry (cast as an
|
111
|
+
# Intf::Entry) to a block. Uses dnet(3)'s intf_loop() function under the
|
112
|
+
# hood.
|
113
|
+
def loop &block
|
114
|
+
_loop ::Dnet, :intf_loop, Entry, &block
|
115
|
+
end
|
116
|
+
|
117
|
+
# intf_get() retrieves an interface configuration entry, keyed on
|
118
|
+
# intf_name. For all intf_get() functions, intf_len should be set to the
|
119
|
+
# size of the buffer pointed to by entry (usually sizeof(struct
|
120
|
+
# intf_entry), but should be larger to accomodate any interface alias
|
121
|
+
# addresses.
|
122
|
+
#
|
123
|
+
# int intf_get(intf_t *i, struct intf_entry *entry);
|
124
|
+
#
|
125
|
+
def get(name, ie=nil)
|
126
|
+
_check_open!
|
127
|
+
ie ||= Entry.new
|
128
|
+
ie.if_name = name.to_s
|
129
|
+
return ie if ::Dnet.intf_get(@handle, ie) == 0
|
130
|
+
end
|
131
|
+
|
132
|
+
# retrieves the configuration for the interface whose primary address
|
133
|
+
# matches the specified src.
|
134
|
+
#
|
135
|
+
# int intf_get_src(intf_t *i, struct intf_entry *entry, struct addr *src);
|
136
|
+
def get_src(addr, ie=nil)
|
137
|
+
_check_open!
|
138
|
+
src = Addr.new(addr.to_s)
|
139
|
+
ie ||= Entry.new
|
140
|
+
return ie if ::Dnet.intf_get_src(@handle, ie, src) == 0
|
141
|
+
end
|
142
|
+
|
143
|
+
# Retrieves the configuration for the best interface with which to reach
|
144
|
+
# the specified destination.
|
145
|
+
#
|
146
|
+
# int intf_get_dst(intf_t *i, struct intf_entry *entry, struct addr *dst);
|
147
|
+
def get_dst(addr, ie=nil)
|
148
|
+
_check_open!
|
149
|
+
dst = Addr.new(addr.to_s)
|
150
|
+
ie ||= Entry.new
|
151
|
+
return ie if ::Dnet.intf_get_dst(@handle, ie, dst) == 0
|
152
|
+
end
|
153
|
+
|
154
|
+
# Sets the interface configuration entry. Usually requires 'root'
|
155
|
+
# privileges.
|
156
|
+
#
|
157
|
+
# int intf_set(intf_t *i, const struct intf_entry *entry);
|
158
|
+
def set(entry)
|
159
|
+
_check_open!
|
160
|
+
return true if ::Dnet.intf_set(@handle, entry) == 0
|
161
|
+
end
|
162
|
+
|
163
|
+
end # Handle
|
164
|
+
|
165
|
+
def self.open(*args)
|
166
|
+
Handle.open(*args) {|*y| yield(*y) if block_given? }
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.each_entry(*args)
|
170
|
+
Intf::Handle.each_entry(*args){|*y| yield(*y) }
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.entries
|
174
|
+
Intf::Handle.entries
|
175
|
+
end
|
176
|
+
|
177
|
+
end # Intf
|
178
|
+
|
179
|
+
# Alias for Intf::Handle
|
180
|
+
IntfHandle = Intf::Handle
|
181
|
+
|
182
|
+
|
183
|
+
callback :intf_handler, [Intf::Entry, :ulong] , :int
|
184
|
+
|
185
|
+
attach_function :intf_open, [], :intf_t
|
186
|
+
attach_function :intf_get, [:intf_t, Intf::Entry], :int
|
187
|
+
attach_function :intf_get_src, [:intf_t, Intf::Entry, Addr], :int
|
188
|
+
attach_function :intf_get_dst, [:intf_t, Intf::Entry, Addr], :int
|
189
|
+
attach_function :intf_set, [:intf_t, Intf::Entry], :int
|
190
|
+
attach_function :intf_loop, [:intf_t, :intf_handler, :ulong], :int
|
191
|
+
attach_function :intf_close, [:intf_t], :intf_t
|
192
|
+
|
193
|
+
end
|
194
|
+
|
data/lib/dnet/ip.rb
ADDED
@@ -0,0 +1,315 @@
|
|
1
|
+
|
2
|
+
### libdnet's IP interface
|
3
|
+
|
4
|
+
module Dnet
|
5
|
+
|
6
|
+
module Ip
|
7
|
+
# Protocols (proto) - http://www.iana.org/assignments/protocol-numbers
|
8
|
+
#
|
9
|
+
# Contains mappings for all the IP_PROTO_[A-Z].* constants
|
10
|
+
# (defined in constants.rb)
|
11
|
+
module Proto
|
12
|
+
include ::FFI::DRY::ConstMap
|
13
|
+
slurp_constants(::Dnet, "IP_PROTO_")
|
14
|
+
def self.list; @@list ||= super(); end
|
15
|
+
end
|
16
|
+
|
17
|
+
# IP header, without options
|
18
|
+
#
|
19
|
+
# field :v_hl, :uint8, :desc => 'v=vers(. & 0xf0) / '+
|
20
|
+
# 'hl=hdr len(. & 0x0f)'
|
21
|
+
# field :tos, :uint8, :desc => 'type of service'
|
22
|
+
# field :len, :uint16, :desc => 'total length (incl header)'
|
23
|
+
# field :id, :uint16, :desc => 'identification'
|
24
|
+
# field :off, :uint16, :desc => 'fragment offset and flags'
|
25
|
+
# field :ttl, :uint8, :desc => 'time to live'
|
26
|
+
# field :proto, :uint8, :desc => 'protocol'
|
27
|
+
# field :sum, :uint16, :desc => 'checksum'
|
28
|
+
# field :src, :uint32, :desc => 'source address'
|
29
|
+
# field :dst, :uint32, :desc => 'destination address'
|
30
|
+
#
|
31
|
+
class Hdr < ::FFI::Struct
|
32
|
+
include ::FFI::DRY::StructHelper
|
33
|
+
include ::Dnet::NetEndianHelper
|
34
|
+
|
35
|
+
dsl_layout do
|
36
|
+
field :v_hl, :uint8, :desc => 'v=vers(. & 0xf0) / '+
|
37
|
+
'hl=hdr len(. & 0x0f)'
|
38
|
+
field :tos, :uint8, :desc => 'type of service'
|
39
|
+
field :len, :uint16, :desc => 'total length (incl header)'
|
40
|
+
field :id, :uint16, :desc => 'identification'
|
41
|
+
field :off, :uint16, :desc => 'fragment offset and flags'
|
42
|
+
field :ttl, :uint8, :desc => 'time to live'
|
43
|
+
field :proto, :uint8, :desc => 'protocol'
|
44
|
+
field :sum, :uint16, :desc => 'checksum'
|
45
|
+
field :src, :uint32, :desc => 'source address'
|
46
|
+
field :dst, :uint32, :desc => 'destination address'
|
47
|
+
end
|
48
|
+
|
49
|
+
# Overrides set_fields to supply a default value for the 'v_hl' field.
|
50
|
+
#
|
51
|
+
# v = 4
|
52
|
+
# hl = 5 # number of 32-bit words - 20 bytes (size of hdr without opts)
|
53
|
+
#
|
54
|
+
def set_fields(params=nil)
|
55
|
+
params ||= {}
|
56
|
+
super({:v_hl => 0x45}.merge(params))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Sets the value of the hl field. This field is a 4-bit value occupying
|
60
|
+
# the lower 4 bits of the 'v_hl' field.
|
61
|
+
#
|
62
|
+
# This value is the size of the IP header (including opts if present)
|
63
|
+
# in 32-bit words. The byte size maximum is 15*4 - 60 bytes.
|
64
|
+
def hl=(val)
|
65
|
+
raise(ArgumentError, "value for header length too high") if val > 0xf
|
66
|
+
self[:v_hl] &= 0xf0
|
67
|
+
self[:v_hl] += val
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the value of the hl field. This field is a 4-bit value occupying
|
71
|
+
# the lower 4 bits of the 'v_hl' field.
|
72
|
+
#
|
73
|
+
# This value is the size of the IP header (including opts if present)
|
74
|
+
# in 32-bit words. The byte size maximum is 15*4 - 60 bytes.
|
75
|
+
def hl
|
76
|
+
self[:v_hl] & 0x0f
|
77
|
+
end
|
78
|
+
|
79
|
+
# Type of service (ip_tos), RFC 1349 ("obsoleted by RFC 2474")
|
80
|
+
#
|
81
|
+
# Contains mappings for all the IP_TOS_[A-Z].* flags constants
|
82
|
+
module Tos
|
83
|
+
include ::FFI::DRY::ConstFlagsMap
|
84
|
+
slurp_constants(::Dnet, "IP_TOS_")
|
85
|
+
def self.list; @@list ||= super(); end
|
86
|
+
end
|
87
|
+
|
88
|
+
def lookup_tos; Tos[ self.tos ]; end
|
89
|
+
|
90
|
+
# Alias to ::Dnet::Ip::Proto
|
91
|
+
Proto = ::Dnet::Ip::Proto
|
92
|
+
|
93
|
+
def lookup_proto; Proto[ self.proto ]; end
|
94
|
+
|
95
|
+
# Sets source IP address in the header from an IPv4 address string or
|
96
|
+
# 32-bit number.
|
97
|
+
def src=(val)
|
98
|
+
val = ::Dnet::Util.ipv4_atol(val) if val.kind_of? String
|
99
|
+
self[:src] = ::Dnet.htonl(val)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns the source IP address as an IPv4 address string as an IPv4
|
103
|
+
# address string.
|
104
|
+
def src
|
105
|
+
::Dnet::Util.ipv4_ltoa( ::Dnet.ntohl( self[:src] ))
|
106
|
+
end
|
107
|
+
|
108
|
+
# Sets destination IP address in the header from an IPv4 address string
|
109
|
+
# or 32-bit number.
|
110
|
+
def dst=(val)
|
111
|
+
val = ::Dnet::Util.ipv4_atol(val) if val.kind_of? String
|
112
|
+
self[:dst] = ::Dnet.htonl(val)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the destination IP address from the header as an IPv4 address
|
116
|
+
# string.
|
117
|
+
def dst
|
118
|
+
::Dnet::Util.ipv4_ltoa( ::Dnet.ntohl( self[:dst] ))
|
119
|
+
end
|
120
|
+
|
121
|
+
end # class Hdr
|
122
|
+
|
123
|
+
|
124
|
+
# IP option (following IP header)
|
125
|
+
#
|
126
|
+
# array :otype, :uint8, :desc => 'option type'
|
127
|
+
# array :len, :uint8, :desc => 'option length >= IP_OPE_LEN'
|
128
|
+
# array :data, [:uint8, DATA_LEN], :desc => 'option message data '
|
129
|
+
#
|
130
|
+
class Opt < ::FFI::Struct
|
131
|
+
include ::FFI::DRY::StructHelper
|
132
|
+
include ::Dnet::NetEndianHelper
|
133
|
+
|
134
|
+
DATA_LEN = IP_OPT_LEN_MAX - IP_OPT_LEN
|
135
|
+
|
136
|
+
dsl_layout do
|
137
|
+
field :otype, :uint8, :desc => 'option type'
|
138
|
+
field :len, :uint8, :desc => 'option length >= IP_OPE_LEN'
|
139
|
+
array :data, [:uint8, DATA_LEN], :desc => 'option message data '
|
140
|
+
end
|
141
|
+
|
142
|
+
# Option types (otype) - http://www.iana.org/assignments/ip-parameters
|
143
|
+
#
|
144
|
+
# Contains mappings for all the IP_OTYPE_[A-Z].* constants
|
145
|
+
module Otype
|
146
|
+
include ::FFI::DRY::ConstMap
|
147
|
+
slurp_constants(::Dnet, "IP_OTYPE_")
|
148
|
+
def self.list; @@list ||= super(); end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Security option data - RFC 791, 3.1
|
152
|
+
#
|
153
|
+
# field :sec, :uint16, :desc => 'security'
|
154
|
+
# field :cpt, :uint16, :desc => 'compartments'
|
155
|
+
# field :hr, :uint16, :desc => 'handling restrictions'
|
156
|
+
# array :tcc, [:uint8, 3], :desc => 'transmission control code'
|
157
|
+
#
|
158
|
+
class DataSEC < ::FFI::Struct
|
159
|
+
include ::FFI::DRY::StructHelper
|
160
|
+
include ::Dnet::NetEndianHelper
|
161
|
+
|
162
|
+
dsl_layout do
|
163
|
+
field :sec, :uint16, :desc => 'security'
|
164
|
+
field :cpt, :uint16, :desc => 'compartments'
|
165
|
+
field :hr, :uint16, :desc => 'handling restrictions'
|
166
|
+
array :tcc, [:uint8, 3], :desc => 'transmission control code'
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
# Timestamp option data - RFC 791, 3.1
|
172
|
+
#
|
173
|
+
# field :ptr, :uint8, :desc => 'from start of option'
|
174
|
+
# field :oflw_flg, :uint8, :desc => 'oflw = number of IPs skipped /'+
|
175
|
+
# 'flg = address/timestamp flag'
|
176
|
+
# field :iptspairs, :uint32, :desc => 'IP addr/ts pairs, var-length'
|
177
|
+
#
|
178
|
+
class DataTS < ::FFI::Struct
|
179
|
+
include ::FFI::DRY::StructHelper
|
180
|
+
include ::Dnet::NetEndianHelper
|
181
|
+
dsl_layout do
|
182
|
+
field :ptr, :uint8, :desc => 'from start of option'
|
183
|
+
field :oflw_flg, :uint8, :desc => 'oflw = number of IPs skipped /'+
|
184
|
+
'flg = address/timestamp flag'
|
185
|
+
field :iptspairs, :uint32, :desc => 'IP addr/ts pairs, var-length'
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
# (Loose Source/Record/Strict Source) Route option data - RFC 791, 3.1
|
191
|
+
#
|
192
|
+
# field :ptr, :uint8, :desc => 'from start of option'
|
193
|
+
# field :iplist, :uint32, :desc => 'var-length list of IPs'
|
194
|
+
#
|
195
|
+
class DataRR < ::FFI::Struct
|
196
|
+
include ::FFI::DRY::StructHelper
|
197
|
+
include ::Dnet::NetEndianHelper
|
198
|
+
|
199
|
+
dsl_layout do
|
200
|
+
field :ptr, :uint8, :desc => 'from start of option'
|
201
|
+
field :iplist, :uint32, :desc => 'var-length list of IPs'
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
# Traceroute option data - RFC 1393, 2.2
|
207
|
+
#
|
208
|
+
# struct ip_opt_data_tr {
|
209
|
+
# uint16_t id; /* ID number */
|
210
|
+
# uint16_t ohc; /* outbound hop count */
|
211
|
+
# uint16_t rhc; /* return hop count */
|
212
|
+
# uint32_t origip; /* originator IP address */
|
213
|
+
# } __attribute__((__packed__));
|
214
|
+
#
|
215
|
+
class DataTR < ::FFI::Struct
|
216
|
+
include ::FFI::DRY::StructHelper
|
217
|
+
include ::Dnet::NetEndianHelper
|
218
|
+
|
219
|
+
dsl_layout do
|
220
|
+
field :id, :uint16, :desc => 'ID number'
|
221
|
+
field :ohc, :uint16, :desc => 'outbound hop count'
|
222
|
+
field :rhc, :uint16, :desc => 'return hop count'
|
223
|
+
field :origip, :uint32, :desc => 'originator IP address'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
end # class Opt
|
228
|
+
|
229
|
+
|
230
|
+
# Abstraction around dnet(3)'s ip_t handle for transmitting raw IP packets
|
231
|
+
# routed by the kernel.
|
232
|
+
class Handle < ::Dnet::Handle
|
233
|
+
|
234
|
+
# Obtains a handle to transmit raw IP packets, routed by the kernel.
|
235
|
+
# Uses dnet(3)'s ip_open() function under the hood.
|
236
|
+
def initialize
|
237
|
+
if (@handle=::Dnet.ip_open).address == 0
|
238
|
+
raise H_ERR.new("unable to open IP raw packet handle")
|
239
|
+
end
|
240
|
+
_handle_opened!
|
241
|
+
end
|
242
|
+
|
243
|
+
# Transmits len bytes of the IP packet 'buf'. Len can be left
|
244
|
+
# blank for String objects, which will use the size of the string.
|
245
|
+
def ip_send(buf, len=nil)
|
246
|
+
pbuf, sz = ::Dnet::Util.derive_pointer(buf, len)
|
247
|
+
::Dnet.ip_send(@handle, pbuf, sz)
|
248
|
+
end
|
249
|
+
|
250
|
+
# closes the IP raw packet handle
|
251
|
+
def close
|
252
|
+
_do_if_open { _handle_closed!; ::Dnet.ip_close(@handle) }
|
253
|
+
end
|
254
|
+
|
255
|
+
# Transmits len bytes of the IP packet pointed to by buf through a
|
256
|
+
# temporary Ip::Handle which is closed immediately after sending.
|
257
|
+
#
|
258
|
+
# See also Ip::Handle#ip_send
|
259
|
+
def self.ip_send(buf, len=nil)
|
260
|
+
open {|h| h.ip_send(buf, len)}
|
261
|
+
end
|
262
|
+
|
263
|
+
# Instance alias to ::Dnet.ip_add_option()
|
264
|
+
def add_option(*args); ::Dnet::Ip.ip_add_option(*args); end
|
265
|
+
|
266
|
+
# Instance alias to ::Dnet.ip_checksum()
|
267
|
+
def checksum(*args); ::Dnet::Ip.ip_checksum(*args); end
|
268
|
+
|
269
|
+
end # class Handle
|
270
|
+
|
271
|
+
|
272
|
+
# Adds the header option for the protocol proto specified
|
273
|
+
# by 'optbuf' of length 'osz' and appends it to the appropriate header of
|
274
|
+
# the IP packet contained in 'buf' of size 'bsz', shifting any existing
|
275
|
+
# payload and adding NOPs to pad the option to a word boundary if necessary.
|
276
|
+
#
|
277
|
+
# The buf and/or optbuf can be String or FFI::Pointer objects. Pointers
|
278
|
+
# must also include the associated size in bsz or osz respectively.
|
279
|
+
#
|
280
|
+
# sizes are required for buffer
|
281
|
+
#
|
282
|
+
# ssize_t ip_add_option(void *buf, size_t len, int proto,
|
283
|
+
# const void *optbuf, size_t optlen);
|
284
|
+
def self.add_option(buf, proto, optbuf, bsz = nil, osz = nil)
|
285
|
+
bufp, blen = ::Dnet::Util.derive_pointer(buf, bsz)
|
286
|
+
optbufp, olen = ::Dnet::Util.derive_pointer(optbuf, osz)
|
287
|
+
::Dnet.ip_add_option(bufp, proto, blen, optbufp, olen)
|
288
|
+
end
|
289
|
+
|
290
|
+
# Sets the IP checksum and any appropriate transport protocol
|
291
|
+
# checksum for the IP packet pointed to by buf of length len
|
292
|
+
#
|
293
|
+
# returns [buf-pointer, buf-length]
|
294
|
+
#
|
295
|
+
# void ip_checksum(void *buf, size_t len);
|
296
|
+
def self.checksum(buf, len=nil)
|
297
|
+
bufp, plen = ::Dnet::Util.derive_pointer(buf, len)
|
298
|
+
::Dnet.ip_checksum bufp, plen
|
299
|
+
return [bufp, plen]
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
end # module Ip
|
304
|
+
|
305
|
+
# Alias for Ip::Handle
|
306
|
+
IpHandle = Ip::Handle
|
307
|
+
|
308
|
+
attach_function :ip_open, [], :ip_t
|
309
|
+
attach_function :ip_add_option, [:pointer, :size_t, :int, :pointer, :size_t], :ssize_t
|
310
|
+
attach_function :ip_checksum, [:pointer, :size_t], :void
|
311
|
+
attach_function :ip_send, [:ip_t, :pointer, :size_t], :ssize_t
|
312
|
+
attach_function :ip_close, [:ip_t], :ip_t
|
313
|
+
|
314
|
+
end
|
315
|
+
|