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