ffi-packets 0.1.0
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 +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +20 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/ffi-packets.gemspec +67 -0
- data/lib/ffi/packets.rb +14 -0
- data/lib/ffi/packets/arp.rb +60 -0
- data/lib/ffi/packets/constants.rb +478 -0
- data/lib/ffi/packets/eth.rb +74 -0
- data/lib/ffi/packets/icmp.rb +294 -0
- data/lib/ffi/packets/ip.rb +227 -0
- data/lib/ffi/packets/tcp.rb +104 -0
- data/lib/ffi/packets/udp.rb +30 -0
- data/lib/ffi/packets/util.rb +54 -0
- data/spec/ffi-packets_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- metadata +103 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
|
2
|
+
module FFI::Packets
|
3
|
+
|
4
|
+
module Eth
|
5
|
+
class EthAddr < ::FFI::Struct
|
6
|
+
include ::FFI::DRY::StructHelper
|
7
|
+
|
8
|
+
# struct eth_addr { ... } eth_addr_t;
|
9
|
+
dsl_layout{ array :data, [:uchar, Constants::ETH_ADDR_LEN] }
|
10
|
+
|
11
|
+
# Adds the ability to initialize a new EthAddr with a mac address
|
12
|
+
# string such as 'de:ad:be:ef:ba:be'. This argument is only parsed
|
13
|
+
# if it is passed as the only String argument.
|
14
|
+
def initialize(*args)
|
15
|
+
if args.size == 1 and (s=args[0]).is_a? String
|
16
|
+
super()
|
17
|
+
self.addr = s
|
18
|
+
else
|
19
|
+
super(*args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def addr=(val)
|
24
|
+
unless val.to_s =~ /^#{Util::RX_MAC_ADDR}$/
|
25
|
+
raise(ArgumentError, "invalid mac address #{val.inspect}")
|
26
|
+
end
|
27
|
+
raw = Util.unhexify(val, /[:-]/)
|
28
|
+
self[:data].to_ptr.write_string(raw, ETH_ADDR_LEN)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the MAC address as an array of unsigned char values.
|
32
|
+
def chars; self[:data].to_a ; end
|
33
|
+
|
34
|
+
# Returns the MAC address as a string with colon-separated hex-bytes.
|
35
|
+
def string; chars.map {|x| "%0.2x" % x }.join(':'); end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
#
|
40
|
+
# struct :dst, EthAddr, :desc => 'destination address'
|
41
|
+
# struct :src, EthAddr, :desc => 'source address'
|
42
|
+
# field :etype, :ushort, :desc => 'ethernet payload type'
|
43
|
+
#
|
44
|
+
class Hdr < ::FFI::Struct
|
45
|
+
include ::FFI::DRY::NetStructHelper
|
46
|
+
|
47
|
+
module Etype
|
48
|
+
include ::FFI::DRY::ConstMap
|
49
|
+
slurp_constants Constants, "ETH_TYPE_"
|
50
|
+
def list; @@list ||= super(); end
|
51
|
+
end
|
52
|
+
|
53
|
+
dsl_layout do
|
54
|
+
struct :dst, EthAddr, :desc => 'destination address'
|
55
|
+
struct :src, EthAddr, :desc => 'source address'
|
56
|
+
field :etype, :ushort, :desc => 'ethernet payload type'
|
57
|
+
end
|
58
|
+
|
59
|
+
def lookup_etype
|
60
|
+
Etype[ self.etype ]
|
61
|
+
end
|
62
|
+
|
63
|
+
alias _divert_set_eth etype=
|
64
|
+
|
65
|
+
def etype=(val)
|
66
|
+
if val.kind_of? String or val.kind_of? Symbol
|
67
|
+
val = Etype[ val ] or raise(ArgumentError, "invalid eth type #{val}")
|
68
|
+
end
|
69
|
+
_divert_set_eth(val)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,294 @@
|
|
1
|
+
|
2
|
+
module FFI::Packets
|
3
|
+
module Icmp
|
4
|
+
|
5
|
+
# ICMP header structure
|
6
|
+
#
|
7
|
+
# struct icmp_hdr {
|
8
|
+
# uint8_t icmp_type; /* type of message */
|
9
|
+
# uint8_t icmp_code; /* type sub code */
|
10
|
+
# uint16_t icmp_cksum; /* ones complement cksum of struct */
|
11
|
+
# };
|
12
|
+
#
|
13
|
+
class Hdr < ::FFI::Struct
|
14
|
+
include ::FFI::DRY::NetStructHelper
|
15
|
+
|
16
|
+
dsl_layout do
|
17
|
+
field :icmp_type, :uint8
|
18
|
+
field :icmp_code, :uint8
|
19
|
+
field :icmp_cksum, :uint16
|
20
|
+
end
|
21
|
+
|
22
|
+
module IcmpType
|
23
|
+
include ::FFI::DRY::ConstFlagsMap
|
24
|
+
slurp_constants(Constants, "ICMP_TYPE_")
|
25
|
+
def list; @@list ||= super(); end
|
26
|
+
end
|
27
|
+
|
28
|
+
module IcmpCode
|
29
|
+
module UNREACH
|
30
|
+
include ::FFI::DRY::ConstFlagsMap
|
31
|
+
slurp_constants(Constants, "ICMP_UNREACH_")
|
32
|
+
def list; @@list ||= super(); end
|
33
|
+
end
|
34
|
+
|
35
|
+
module REDIRECT
|
36
|
+
include ::FFI::DRY::ConstFlagsMap
|
37
|
+
slurp_constants(Constants, "ICMP_REDIRECT_")
|
38
|
+
def list; @@list ||= super(); end
|
39
|
+
end
|
40
|
+
|
41
|
+
module RTRADVERT
|
42
|
+
include ::FFI::DRY::ConstFlagsMap
|
43
|
+
slurp_constants(Constants, "ICMP_RTRADVERT_")
|
44
|
+
def list; @@list ||= super(); end
|
45
|
+
end
|
46
|
+
|
47
|
+
module TIMEEXCEED
|
48
|
+
include ::FFI::DRY::ConstFlagsMap
|
49
|
+
slurp_constants(Constants, "ICMP_TIMEEXCEED_")
|
50
|
+
def list; @@list ||= super(); end
|
51
|
+
end
|
52
|
+
|
53
|
+
module PARAMPROB
|
54
|
+
include ::FFI::DRY::ConstFlagsMap
|
55
|
+
slurp_constants(Constants, "ICMP_PARAMPROB_")
|
56
|
+
def list; @@list ||= super(); end
|
57
|
+
end
|
58
|
+
|
59
|
+
module PHOTURIS
|
60
|
+
include ::FFI::DRY::ConstFlagsMap
|
61
|
+
slurp_constants(Constants, "ICMP_PHOTURIS_")
|
62
|
+
def list; @@list ||= super(); end
|
63
|
+
end
|
64
|
+
|
65
|
+
end # module IcmpCode
|
66
|
+
|
67
|
+
# Various ICMP message structures
|
68
|
+
module Msg
|
69
|
+
|
70
|
+
# Echo message data structure
|
71
|
+
#
|
72
|
+
# struct icmp_msg_echo {
|
73
|
+
# uint16_t icmp_id;
|
74
|
+
# uint16_t icmp_seq;
|
75
|
+
# uint8_t icmp_data __flexarr; /* optional data */
|
76
|
+
# };
|
77
|
+
#
|
78
|
+
class Echo < ::FFI::Struct
|
79
|
+
include ::FFI::DRY::NetStructHelper
|
80
|
+
|
81
|
+
dsl_layout do
|
82
|
+
field :icmp_id, :uint16
|
83
|
+
field :seq, :uint16
|
84
|
+
field :data, :uint8 # flexarr ... optional data
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Fragmentation-needed (unreachable) message data structure
|
89
|
+
#
|
90
|
+
# struct icmp_msg_needfrag {
|
91
|
+
# uint16_t icmp_void; /* must be zero */
|
92
|
+
# uint16_t icmp_mtu; /* MTU of next-hop network */
|
93
|
+
# uint8_t icmp_ip __flexarr; /* IP hdr + 8 bytes of pkt */
|
94
|
+
# };
|
95
|
+
#
|
96
|
+
class NeedFrag < ::FFI::Struct
|
97
|
+
include ::FFI::DRY::NetStructHelper
|
98
|
+
|
99
|
+
dsl_layout do
|
100
|
+
field :icmp_void, :uint16
|
101
|
+
field :mtu, :uint16
|
102
|
+
field :ip, :uint8 # flexarr ... IP hdr + 8 bytes of pkt
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Unreachable, source quench, redirect, time exceeded,
|
107
|
+
# parameter problem message data structure
|
108
|
+
#
|
109
|
+
# struct icmp_msg_quote {
|
110
|
+
# uint32_t icmp_void; /* must be zero */
|
111
|
+
# uint8_t icmp_ip __flexarr; /* IP hdr + 8 bytes of pkt */
|
112
|
+
# };
|
113
|
+
#
|
114
|
+
class Quote < ::FFI::Struct
|
115
|
+
include ::FFI::DRY::NetStructHelper
|
116
|
+
|
117
|
+
dsl_layout do
|
118
|
+
field :icmp_void, :uint32
|
119
|
+
field :ip, :uint8 # flexxarr ... IP hdr + 8 bytes of pkt
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Router advertisement message data structure, RFC 1256
|
124
|
+
#
|
125
|
+
# struct icmp_msg_rtradvert {
|
126
|
+
# uint8_t icmp_num_addrs; /* # of address / pref pairs */
|
127
|
+
# uint8_t icmp_wpa; /* words / address == 2 */
|
128
|
+
# uint16_t icmp_lifetime; /* route lifetime in seconds */
|
129
|
+
# struct icmp_msg_rtr_data {
|
130
|
+
# uint32_t icmp_void;
|
131
|
+
# uint32_t icmp_pref; /* router preference (usu 0) */
|
132
|
+
# } icmp_rtr __flexarr; /* variable # of routers */
|
133
|
+
# };
|
134
|
+
#
|
135
|
+
class RtrAdvert < ::FFI::Struct
|
136
|
+
include ::FFI::DRY::NetStructHelper
|
137
|
+
|
138
|
+
class RtrData < ::FFI::Struct
|
139
|
+
include ::FFI::DRY::NetStructHelper
|
140
|
+
|
141
|
+
dsl_layout do
|
142
|
+
field :icmp_void, :uint32
|
143
|
+
field :pref, :uint32
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
dsl_layout do
|
148
|
+
field :num_addrs, :uint8
|
149
|
+
field :wpa, :uint8
|
150
|
+
field :lifetime, :uint16
|
151
|
+
struct :router, RtrData # flexarr ... variable # of routers
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Timestamp message data structure
|
156
|
+
#
|
157
|
+
# struct icmp_msg_tstamp {
|
158
|
+
# uint32_t icmp_id; /* identifier */
|
159
|
+
# uint32_t icmp_seq; /* sequence number */
|
160
|
+
# uint32_t icmp_ts_orig; /* originate timestamp */
|
161
|
+
# uint32_t icmp_ts_rx; /* receive timestamp */
|
162
|
+
# uint32_t icmp_ts_tx; /* transmit timestamp */
|
163
|
+
# };
|
164
|
+
#
|
165
|
+
class Timestamp < ::FFI::Struct
|
166
|
+
include ::FFI::DRY::NetStructHelper
|
167
|
+
|
168
|
+
dsl_layout do
|
169
|
+
field :icmp_id, :uint32
|
170
|
+
field :seq, :uint32
|
171
|
+
field :ts_orig, :uint32
|
172
|
+
field :ts_rx, :uint32
|
173
|
+
field :ts_tx, :uint32
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Address mask message data structure, RFC 950
|
178
|
+
#
|
179
|
+
# struct icmp_msg_mask {
|
180
|
+
# uint32_t icmp_id; /* identifier */
|
181
|
+
# uint32_t icmp_seq; /* sequence number */
|
182
|
+
# uint32_t icmp_mask; /* address mask */
|
183
|
+
# };
|
184
|
+
#
|
185
|
+
class Mask < ::FFI::Struct
|
186
|
+
include ::FFI::DRY::NetStructHelper
|
187
|
+
|
188
|
+
dsl_layout do
|
189
|
+
field :icmp_id, :uint32
|
190
|
+
field :seq, :uint32
|
191
|
+
field :mask, :uint32
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Traceroute message data structure, RFC 1393, RFC 1812
|
196
|
+
#
|
197
|
+
# struct icmp_msg_traceroute {
|
198
|
+
# uint16_t icmp_id; /* identifier */
|
199
|
+
# uint16_t icmp_void; /* unused */
|
200
|
+
# uint16_t icmp_ohc; /* outbound hop count */
|
201
|
+
# uint16_t icmp_rhc; /* return hop count */
|
202
|
+
# uint32_t icmp_speed; /* link speed, bytes/sec */
|
203
|
+
# uint32_t icmp_mtu; /* MTU in bytes */
|
204
|
+
# };
|
205
|
+
#
|
206
|
+
class Traceroute < ::FFI::Struct
|
207
|
+
include ::FFI::DRY::NetStructHelper
|
208
|
+
|
209
|
+
dsl_layout do
|
210
|
+
field :icmp_id, :uint16
|
211
|
+
field :icmp_void, :uint16
|
212
|
+
field :ohc, :uint16
|
213
|
+
field :rhc, :uint16
|
214
|
+
field :speed, :uint16
|
215
|
+
field :mtu, :uint16
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Domain name reply message data structure, RFC 1788
|
220
|
+
#
|
221
|
+
# struct icmp_msg_dnsreply {
|
222
|
+
# uint16_t icmp_id; /* identifier */
|
223
|
+
# uint16_t icmp_seq; /* sequence number */
|
224
|
+
# uint32_t icmp_ttl; /* time-to-live */
|
225
|
+
# uint8_t icmp_names __flexarr; /* variable number of names */
|
226
|
+
# };
|
227
|
+
#
|
228
|
+
class DnsReply < ::FFI::Struct
|
229
|
+
include ::FFI::DRY::NetStructHelper
|
230
|
+
|
231
|
+
dsl_layout do
|
232
|
+
field :icmp_id, :uint16
|
233
|
+
field :seq, :uint16
|
234
|
+
field :ttl, :uint16
|
235
|
+
field :names, :uint8 # flexarr ... variable # of names
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Generic identifier, sequence number data structure
|
240
|
+
#
|
241
|
+
# struct icmp_msg_idseq {
|
242
|
+
# uint16_t icmp_id;
|
243
|
+
# uint16_t icmp_seq;
|
244
|
+
# };
|
245
|
+
#
|
246
|
+
class IdSeq < ::FFI::Struct
|
247
|
+
include ::FFI::DRY::NetStructHelper
|
248
|
+
|
249
|
+
dsl_layout do
|
250
|
+
field :icmp_id, :uint16
|
251
|
+
field :seq, :uint16
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
end # module Msg
|
256
|
+
end
|
257
|
+
|
258
|
+
# /*
|
259
|
+
# * ICMP message union
|
260
|
+
# */
|
261
|
+
# union icmp_msg {
|
262
|
+
# struct icmp_msg_echo echo; /* ICMP_ECHO{REPLY} */
|
263
|
+
# struct icmp_msg_quote unreach; /* ICMP_UNREACH */
|
264
|
+
# struct icmp_msg_needfrag needfrag; /* ICMP_UNREACH_NEEDFRAG */
|
265
|
+
# struct icmp_msg_quote srcquench; /* ICMP_SRCQUENCH */
|
266
|
+
# struct icmp_msg_quote redirect; /* ICMP_REDIRECT (set to 0) */
|
267
|
+
# uint32_t rtrsolicit; /* ICMP_RTRSOLICIT */
|
268
|
+
# struct icmp_msg_rtradvert rtradvert; /* ICMP_RTRADVERT */
|
269
|
+
# struct icmp_msg_quote timexceed; /* ICMP_TIMEXCEED */
|
270
|
+
# struct icmp_msg_quote paramprob; /* ICMP_PARAMPROB */
|
271
|
+
# struct icmp_msg_tstamp tstamp; /* ICMP_TSTAMP{REPLY} */
|
272
|
+
# struct icmp_msg_idseq info; /* ICMP_INFO{REPLY} */
|
273
|
+
# struct icmp_msg_mask mask; /* ICMP_MASK{REPLY} */
|
274
|
+
# struct icmp_msg_traceroute traceroute; /* ICMP_TRACEROUTE */
|
275
|
+
# struct icmp_msg_idseq dns; /* ICMP_DNS */
|
276
|
+
# struct icmp_msg_dnsreply dnsreply; /* ICMP_DNSREPLY */
|
277
|
+
# };
|
278
|
+
|
279
|
+
# #define icmp_pack_hdr(hdr, type, code) do { \
|
280
|
+
# struct icmp_hdr *icmp_pack_p = (struct icmp_hdr *)(hdr); \
|
281
|
+
# icmp_pack_p->icmp_type = type; icmp_pack_p->icmp_code = code; \
|
282
|
+
# } while (0)
|
283
|
+
|
284
|
+
# #define icmp_pack_hdr_echo(hdr, type, code, id, seq, data, len) do { \
|
285
|
+
# struct icmp_msg_echo *echo_pack_p = (struct icmp_msg_echo *) \
|
286
|
+
# ((uint8_t *)(hdr) + ICMP_HDR_LEN); \
|
287
|
+
# icmp_pack_hdr(hdr, type, code); \
|
288
|
+
# echo_pack_p->icmp_id = htons(id); \
|
289
|
+
# echo_pack_p->icmp_seq = htons(seq); \
|
290
|
+
# memmove(echo_pack_p->icmp_data, data, len); \
|
291
|
+
# } while (0)
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
|
2
|
+
module FFI::Packets
|
3
|
+
|
4
|
+
module Ip
|
5
|
+
# Protocols (proto) - http://www.iana.org/assignments/protocol-numbers
|
6
|
+
#
|
7
|
+
# Contains mappings for all the IP_PROTO_[A-Z].* constants
|
8
|
+
# (defined in constants.rb)
|
9
|
+
module Proto
|
10
|
+
include ::FFI::DRY::ConstMap
|
11
|
+
slurp_constants(Constants, "IP_PROTO_")
|
12
|
+
def self.list; @@list ||= super(); end
|
13
|
+
end
|
14
|
+
|
15
|
+
# IP header, without options
|
16
|
+
#
|
17
|
+
# field :v_hl, :uint8, :desc => 'v=vers(. & 0xf0) / '+
|
18
|
+
# 'hl=hdr len(. & 0x0f)'
|
19
|
+
# field :tos, :uint8, :desc => 'type of service'
|
20
|
+
# field :len, :uint16, :desc => 'total length (incl header)'
|
21
|
+
# field :id, :uint16, :desc => 'identification'
|
22
|
+
# field :off, :uint16, :desc => 'fragment offset and flags'
|
23
|
+
# field :ttl, :uint8, :desc => 'time to live'
|
24
|
+
# field :proto, :uint8, :desc => 'protocol'
|
25
|
+
# field :sum, :uint16, :desc => 'checksum'
|
26
|
+
# field :src, :uint32, :desc => 'source address'
|
27
|
+
# field :dst, :uint32, :desc => 'destination address'
|
28
|
+
#
|
29
|
+
class Hdr < ::FFI::Struct
|
30
|
+
include ::FFI::DRY::NetStructHelper
|
31
|
+
|
32
|
+
dsl_layout do
|
33
|
+
field :v_hl, :uint8, :desc => 'v=vers(. & 0xf0) / '+
|
34
|
+
'hl=hdr len(. & 0x0f)'
|
35
|
+
field :tos, :uint8, :desc => 'type of service'
|
36
|
+
field :len, :uint16, :desc => 'total length (incl header)'
|
37
|
+
field :id, :uint16, :desc => 'identification'
|
38
|
+
field :off, :uint16, :desc => 'fragment offset and flags'
|
39
|
+
field :ttl, :uint8, :desc => 'time to live'
|
40
|
+
field :proto, :uint8, :desc => 'protocol'
|
41
|
+
field :sum, :uint16, :desc => 'checksum'
|
42
|
+
field :src, :uint32, :desc => 'source address'
|
43
|
+
field :dst, :uint32, :desc => 'destination address'
|
44
|
+
end
|
45
|
+
|
46
|
+
# Overrides set_fields to supply a default value for the 'v_hl' field.
|
47
|
+
#
|
48
|
+
# v = 4
|
49
|
+
# hl = 5 # number of 32-bit words - 20 bytes (size of hdr without opts)
|
50
|
+
#
|
51
|
+
def set_fields(params=nil)
|
52
|
+
params ||= {}
|
53
|
+
super({:v_hl => 0x45}.merge(params))
|
54
|
+
end
|
55
|
+
|
56
|
+
# Sets the value of the hl field. This field is a 4-bit value occupying
|
57
|
+
# the lower 4 bits of the 'v_hl' field.
|
58
|
+
#
|
59
|
+
# This value is the size of the IP header (including opts if present)
|
60
|
+
# in 32-bit words. The byte size maximum is 15*4 - 60 bytes.
|
61
|
+
def hl=(val)
|
62
|
+
raise(ArgumentError, "value for header length too high") if val > 0xf
|
63
|
+
self[:v_hl] &= 0xf0
|
64
|
+
self[:v_hl] += val
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the value of the hl field. This field is a 4-bit value occupying
|
68
|
+
# the lower 4 bits of the 'v_hl' field.
|
69
|
+
#
|
70
|
+
# This value is the size of the IP header (including opts if present)
|
71
|
+
# in 32-bit words. The byte size maximum is 15*4 - 60 bytes.
|
72
|
+
def hl
|
73
|
+
self[:v_hl] & 0x0f
|
74
|
+
end
|
75
|
+
|
76
|
+
# Type of service (ip_tos), RFC 1349 ("obsoleted by RFC 2474")
|
77
|
+
#
|
78
|
+
# Contains mappings for all the IP_TOS_[A-Z].* flags constants
|
79
|
+
module Tos
|
80
|
+
include ::FFI::DRY::ConstFlagsMap
|
81
|
+
slurp_constants(Constants, "IP_TOS_")
|
82
|
+
def self.list; @@list ||= super(); end
|
83
|
+
end
|
84
|
+
|
85
|
+
def lookup_tos; Tos[ self.tos ]; end
|
86
|
+
|
87
|
+
# Alias to Ip::Proto
|
88
|
+
Proto = Ip::Proto
|
89
|
+
|
90
|
+
def lookup_proto; Proto[ self.proto ]; end
|
91
|
+
|
92
|
+
# Sets source IP address in the header from an IPv4 address string or
|
93
|
+
# 32-bit number.
|
94
|
+
def src=(val)
|
95
|
+
val = Util.ipv4_atol(val) if val.kind_of? String
|
96
|
+
self[:src] = Util.htonl(val)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the source IP address as an IPv4 address string as an IPv4
|
100
|
+
# address string.
|
101
|
+
def src
|
102
|
+
Util.ipv4_ltoa( Util.ntohl( self[:src] ))
|
103
|
+
end
|
104
|
+
|
105
|
+
# Sets destination IP address in the header from an IPv4 address string
|
106
|
+
# or 32-bit number.
|
107
|
+
def dst=(val)
|
108
|
+
val = Util.ipv4_atol(val) if val.kind_of? String
|
109
|
+
self[:dst] = Util.htonl(val)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns the destination IP address from the header as an IPv4 address
|
113
|
+
# string.
|
114
|
+
def dst
|
115
|
+
Util.ipv4_ltoa( Util.ntohl( self[:dst] ))
|
116
|
+
end
|
117
|
+
|
118
|
+
end # class Hdr
|
119
|
+
|
120
|
+
|
121
|
+
# IP option (following IP header)
|
122
|
+
#
|
123
|
+
# array :otype, :uint8, :desc => 'option type'
|
124
|
+
# array :len, :uint8, :desc => 'option length >= IP_OPE_LEN'
|
125
|
+
# array :data, [:uint8, DATA_LEN], :desc => 'option message data '
|
126
|
+
#
|
127
|
+
class Opt < ::FFI::Struct
|
128
|
+
include ::FFI::DRY::NetStructHelper
|
129
|
+
|
130
|
+
IP_OPT_LEN = Constants::IP_OPT_LEN
|
131
|
+
IP_OPT_LEN_MAX = Constants::IP_OPT_LEN_MAX
|
132
|
+
|
133
|
+
DATA_LEN = IP_OPT_LEN_MAX - IP_OPT_LEN
|
134
|
+
|
135
|
+
dsl_layout do
|
136
|
+
field :otype, :uint8, :desc => 'option type'
|
137
|
+
field :len, :uint8, :desc => 'option length >= IP_OPE_LEN'
|
138
|
+
array :data, [:uint8, DATA_LEN], :desc => 'option message data '
|
139
|
+
end
|
140
|
+
|
141
|
+
# Option types (otype) - http://www.iana.org/assignments/ip-parameters
|
142
|
+
#
|
143
|
+
# Contains mappings for all the IP_OTYPE_[A-Z].* constants
|
144
|
+
module Otype
|
145
|
+
include ::FFI::DRY::ConstMap
|
146
|
+
slurp_constants(Constants, "IP_OTYPE_")
|
147
|
+
def self.list; @@list ||= super(); end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Security option data - RFC 791, 3.1
|
151
|
+
#
|
152
|
+
# field :sec, :uint16, :desc => 'security'
|
153
|
+
# field :cpt, :uint16, :desc => 'compartments'
|
154
|
+
# field :hr, :uint16, :desc => 'handling restrictions'
|
155
|
+
# array :tcc, [:uint8, 3], :desc => 'transmission control code'
|
156
|
+
#
|
157
|
+
class DataSEC < ::FFI::Struct
|
158
|
+
include ::FFI::DRY::NetStructHelper
|
159
|
+
|
160
|
+
dsl_layout do
|
161
|
+
field :sec, :uint16, :desc => 'security'
|
162
|
+
field :cpt, :uint16, :desc => 'compartments'
|
163
|
+
field :hr, :uint16, :desc => 'handling restrictions'
|
164
|
+
array :tcc, [:uint8, 3], :desc => 'transmission control code'
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
# Timestamp option data - RFC 791, 3.1
|
170
|
+
#
|
171
|
+
# field :ptr, :uint8, :desc => 'from start of option'
|
172
|
+
# field :oflw_flg, :uint8, :desc => 'oflw = number of IPs skipped /'+
|
173
|
+
# 'flg = address/timestamp flag'
|
174
|
+
# field :iptspairs, :uint32, :desc => 'IP addr/ts pairs, var-length'
|
175
|
+
#
|
176
|
+
class DataTS < ::FFI::Struct
|
177
|
+
include ::FFI::DRY::NetStructHelper
|
178
|
+
|
179
|
+
dsl_layout do
|
180
|
+
field :ptr, :uint8, :desc => 'from start of option'
|
181
|
+
field :oflw_flg, :uint8, :desc => 'oflw = number of IPs skipped /'+
|
182
|
+
'flg = address/timestamp flag'
|
183
|
+
field :iptspairs, :uint32, :desc => 'IP addr/ts pairs, var-length'
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
# (Loose Source/Record/Strict Source) Route option data - RFC 791, 3.1
|
189
|
+
#
|
190
|
+
# field :ptr, :uint8, :desc => 'from start of option'
|
191
|
+
# field :iplist, :uint32, :desc => 'var-length list of IPs'
|
192
|
+
#
|
193
|
+
class DataRR < ::FFI::Struct
|
194
|
+
include ::FFI::DRY::NetStructHelper
|
195
|
+
|
196
|
+
dsl_layout do
|
197
|
+
field :ptr, :uint8, :desc => 'from start of option'
|
198
|
+
field :iplist, :uint32, :desc => 'var-length list of IPs'
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
# Traceroute option data - RFC 1393, 2.2
|
204
|
+
#
|
205
|
+
# struct ip_opt_data_tr {
|
206
|
+
# uint16_t id; /* ID number */
|
207
|
+
# uint16_t ohc; /* outbound hop count */
|
208
|
+
# uint16_t rhc; /* return hop count */
|
209
|
+
# uint32_t origip; /* originator IP address */
|
210
|
+
# } __attribute__((__packed__));
|
211
|
+
#
|
212
|
+
class DataTR < ::FFI::Struct
|
213
|
+
include ::FFI::DRY::NetStructHelper
|
214
|
+
|
215
|
+
dsl_layout do
|
216
|
+
field :id, :uint16, :desc => 'ID number'
|
217
|
+
field :ohc, :uint16, :desc => 'outbound hop count'
|
218
|
+
field :rhc, :uint16, :desc => 'return hop count'
|
219
|
+
field :origip, :uint32, :desc => 'originator IP address'
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end # class Opt
|
224
|
+
|
225
|
+
end # module Ip
|
226
|
+
end
|
227
|
+
|