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