packetgen 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/packetgen/header/arp.rb +54 -125
- data/lib/packetgen/header/base.rb +175 -0
- data/lib/packetgen/header/dns/name.rb +110 -0
- data/lib/packetgen/header/dns/opt.rb +137 -0
- data/lib/packetgen/header/dns/option.rb +17 -0
- data/lib/packetgen/header/dns/qdsection.rb +39 -0
- data/lib/packetgen/header/dns/question.rb +129 -0
- data/lib/packetgen/header/dns/rr.rb +89 -0
- data/lib/packetgen/header/dns/rrsection.rb +72 -0
- data/lib/packetgen/header/dns.rb +276 -0
- data/lib/packetgen/header/esp.rb +38 -70
- data/lib/packetgen/header/eth.rb +35 -106
- data/lib/packetgen/header/icmp.rb +19 -70
- data/lib/packetgen/header/icmpv6.rb +3 -3
- data/lib/packetgen/header/ip.rb +54 -210
- data/lib/packetgen/header/ipv6.rb +73 -164
- data/lib/packetgen/header/tcp/option.rb +34 -50
- data/lib/packetgen/header/tcp/options.rb +19 -20
- data/lib/packetgen/header/tcp.rb +66 -129
- data/lib/packetgen/header/udp.rb +31 -88
- data/lib/packetgen/header.rb +5 -10
- data/lib/packetgen/inspect.rb +5 -4
- data/lib/packetgen/packet.rb +74 -57
- data/lib/packetgen/pcapng/block.rb +49 -7
- data/lib/packetgen/pcapng/epb.rb +36 -34
- data/lib/packetgen/pcapng/file.rb +24 -8
- data/lib/packetgen/pcapng/idb.rb +28 -33
- data/lib/packetgen/pcapng/shb.rb +35 -39
- data/lib/packetgen/pcapng/spb.rb +18 -27
- data/lib/packetgen/pcapng/unknown_block.rb +11 -21
- data/lib/packetgen/pcapng.rb +9 -7
- data/lib/packetgen/types/array.rb +56 -0
- data/lib/packetgen/types/fields.rb +325 -0
- data/lib/packetgen/types/int.rb +164 -0
- data/lib/packetgen/types/int_string.rb +69 -0
- data/lib/packetgen/types/string.rb +36 -0
- data/lib/packetgen/types/tlv.rb +41 -0
- data/lib/packetgen/types.rb +13 -0
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +1 -1
- metadata +19 -6
- data/lib/packetgen/header/header_class_methods.rb +0 -106
- data/lib/packetgen/header/header_methods.rb +0 -73
- data/lib/packetgen/structfu.rb +0 -363
@@ -4,41 +4,59 @@ module PacketGen
|
|
4
4
|
|
5
5
|
# Base class to describe a TCP option
|
6
6
|
# @author Sylvain Daubert
|
7
|
-
class Option <
|
8
|
-
include StructFu
|
7
|
+
class Option < Base
|
9
8
|
|
9
|
+
# EOL option value
|
10
10
|
EOL_KIND = 0
|
11
|
+
# NOP option value
|
11
12
|
NOP_KIND = 1
|
13
|
+
# MSS option value
|
12
14
|
MSS_KIND = 2
|
15
|
+
# WS option value
|
13
16
|
WS_KIND = 3
|
17
|
+
# SACKOK option value
|
14
18
|
SACKOK_KIND = 4
|
19
|
+
# SACK option value
|
15
20
|
SACK_KIND = 5
|
21
|
+
# ECHO option value
|
16
22
|
ECHO_KIND = 6
|
23
|
+
# ECHOREPLY option value
|
17
24
|
ECHOREPLY_KIND = 7
|
25
|
+
# TS option value
|
18
26
|
TS_KIND = 8
|
19
27
|
|
28
|
+
# @!attribute kind
|
29
|
+
# Option kind
|
30
|
+
# @return [Integer] 8-bit option kind
|
31
|
+
define_field :kind, Types::Int8
|
32
|
+
# @!attribute length
|
33
|
+
# Option length
|
34
|
+
# @return [Integer] 8-bit option length
|
35
|
+
define_field :length, Types::Int8
|
36
|
+
# @!attribute value
|
37
|
+
# @return [Integer,String] option value
|
38
|
+
define_field :value, Types::String
|
39
|
+
|
20
40
|
# @param [hash] options
|
21
41
|
# @option options [Integer] :kind
|
22
42
|
# @option options [Integer] :length
|
23
43
|
# @option options [Integer,String] :value
|
24
44
|
def initialize(options={})
|
25
|
-
super
|
26
|
-
Int8.new(options[:length])
|
27
|
-
|
45
|
+
super
|
28
46
|
case options[:value]
|
29
47
|
when Integer
|
30
48
|
klass = case self[:length].to_i
|
31
|
-
when 3; Int8
|
32
|
-
when 4; Int16
|
33
|
-
when 6; Int32
|
49
|
+
when 3; Types::Int8
|
50
|
+
when 4; Types::Int16
|
51
|
+
when 6; Types::Int32
|
34
52
|
else
|
35
53
|
raise ArgumentError, 'impossible length'
|
36
54
|
end
|
37
55
|
self[:value] = klass.new(options[:value])
|
38
56
|
when NilClass
|
39
|
-
self[:value] =
|
57
|
+
self[:value] = Types::String.new
|
40
58
|
else
|
41
|
-
self[:value] =
|
59
|
+
self[:value] = Types::String.new.read(options[:value])
|
42
60
|
self[:length].read(self[:value].sz + 2) unless options[:length]
|
43
61
|
end
|
44
62
|
end
|
@@ -59,33 +77,6 @@ module PacketGen
|
|
59
77
|
self
|
60
78
|
end
|
61
79
|
|
62
|
-
# Getter for kind attribute
|
63
|
-
# @return [Integer]
|
64
|
-
def kind
|
65
|
-
self[:kind].to_i
|
66
|
-
end
|
67
|
-
|
68
|
-
# Setter for kind attribute
|
69
|
-
# @param [Integer] i
|
70
|
-
# @return [Integer]
|
71
|
-
def kind=(i)
|
72
|
-
self[:kind].read i
|
73
|
-
end
|
74
|
-
|
75
|
-
# Getter for length attribute
|
76
|
-
# @return [Integer]
|
77
|
-
def length
|
78
|
-
self[:length].to_i
|
79
|
-
end
|
80
|
-
|
81
|
-
# Setter for length attribute
|
82
|
-
# @param [Integer] i
|
83
|
-
# @return [Integer]
|
84
|
-
def length=(i)
|
85
|
-
self[:length].read i
|
86
|
-
end
|
87
|
-
|
88
|
-
# Say if option has a length
|
89
80
|
# @return [Boolean]
|
90
81
|
def has_length?
|
91
82
|
self[:kind].value && kind >= 2
|
@@ -95,20 +86,13 @@ module PacketGen
|
|
95
86
|
# @return [String, Integer]
|
96
87
|
def value
|
97
88
|
case self[:value]
|
98
|
-
when
|
89
|
+
when Types::Int
|
99
90
|
self[:value].to_i
|
100
91
|
else
|
101
92
|
self[:value].to_s
|
102
93
|
end
|
103
94
|
end
|
104
95
|
|
105
|
-
# Setter for value attribute
|
106
|
-
# @param [String, Integer] v
|
107
|
-
# @return [String, Integer]
|
108
|
-
def value=(v)
|
109
|
-
self[:value].read v
|
110
|
-
end
|
111
|
-
|
112
96
|
# Get binary string
|
113
97
|
# @return [String]
|
114
98
|
def to_s
|
@@ -160,7 +144,7 @@ module PacketGen
|
|
160
144
|
# @see Option#initialize
|
161
145
|
def initialize(options={})
|
162
146
|
super options.merge!(kind: MSS_KIND, length: 4)
|
163
|
-
self[:value] = Int16.new(options[:value])
|
147
|
+
self[:value] = Types::Int16.new(options[:value])
|
164
148
|
end
|
165
149
|
|
166
150
|
# @return [String]
|
@@ -175,7 +159,7 @@ module PacketGen
|
|
175
159
|
# @see Option#initialize
|
176
160
|
def initialize(options={})
|
177
161
|
super options.merge!(kind: WS_KIND, length: 3)
|
178
|
-
self[:value] = Int8.new(options[:value])
|
162
|
+
self[:value] = Types::Int8.new(options[:value])
|
179
163
|
end
|
180
164
|
|
181
165
|
# @return [String]
|
@@ -209,7 +193,7 @@ module PacketGen
|
|
209
193
|
# @see Option#initialize
|
210
194
|
def initialize(options={})
|
211
195
|
super options.merge!(kind: ECHO_KIND, length: 6)
|
212
|
-
self[:value] = Int32.new(options[:value])
|
196
|
+
self[:value] = Types::Int32.new(options[:value])
|
213
197
|
end
|
214
198
|
|
215
199
|
# @return [String]
|
@@ -224,7 +208,7 @@ module PacketGen
|
|
224
208
|
# @see Option#initialize
|
225
209
|
def initialize(options={})
|
226
210
|
super options.merge!(kind: ECHOREPLY_KIND, length: 6)
|
227
|
-
self[:value] = Int32.new(options[:value])
|
211
|
+
self[:value] = Types::Int32.new(options[:value])
|
228
212
|
end
|
229
213
|
|
230
214
|
# @return [String]
|
@@ -239,7 +223,7 @@ module PacketGen
|
|
239
223
|
# @see Option#initialize
|
240
224
|
def initialize(options={})
|
241
225
|
super options.merge!(kind: TS_KIND, length: 10)
|
242
|
-
self[:value] =
|
226
|
+
self[:value] = Types::String.new.read(options[:value] || "\0" * 8)
|
243
227
|
end
|
244
228
|
|
245
229
|
# @return [String]
|
@@ -4,7 +4,7 @@ module PacketGen
|
|
4
4
|
|
5
5
|
# Container for TCP options in {TCP TCP header}.
|
6
6
|
# @author Sylvain Daubert
|
7
|
-
class Options < Array
|
7
|
+
class Options < Types::Array
|
8
8
|
|
9
9
|
# Get {Option} subclasses
|
10
10
|
# @return [Array<Class>]
|
@@ -47,36 +47,35 @@ module PacketGen
|
|
47
47
|
self
|
48
48
|
end
|
49
49
|
|
50
|
+
# @deprecated use {#push} or {#<<}
|
50
51
|
# Add a well-known option
|
51
52
|
# @param [String] opt option name
|
52
53
|
# @param [Object] value
|
53
54
|
# @return [self]
|
54
55
|
# @raise [ArgumentError] unknown option
|
55
56
|
def add(opt, value=nil)
|
56
|
-
|
57
|
-
klass = TCP.const_get(opt)
|
58
|
-
raise ArgumentError "unknown option #{opt}" unless klass < Option
|
59
|
-
option = klass.new(value: value)
|
57
|
+
option = record_from_hash(opt: opt, value: value)
|
60
58
|
self << option
|
61
59
|
self
|
62
60
|
end
|
63
61
|
|
64
|
-
|
65
|
-
# @return [String]
|
66
|
-
def to_s
|
67
|
-
map(&:to_s).join
|
68
|
-
end
|
69
|
-
|
70
|
-
# Get a human readable string
|
71
|
-
# @return [String]
|
72
|
-
def to_human
|
73
|
-
map(&:to_human).join(', ')
|
74
|
-
end
|
62
|
+
private
|
75
63
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
64
|
+
def record_from_hash(hsh)
|
65
|
+
if hsh.has_key? :opt
|
66
|
+
klassname = hsh.delete(:opt)
|
67
|
+
if TCP.const_defined?(klassname)
|
68
|
+
klass = TCP.const_get(klassname)
|
69
|
+
unless klass < Option
|
70
|
+
raise ArgumentError, 'opt should be a TCP::Option subclass'
|
71
|
+
end
|
72
|
+
klass.new(hsh)
|
73
|
+
else
|
74
|
+
raise ArgumentError, 'opt should be a TCP::Option subclass'
|
75
|
+
end
|
76
|
+
else
|
77
|
+
hsh
|
78
|
+
end
|
80
79
|
end
|
81
80
|
end
|
82
81
|
end
|
data/lib/packetgen/header/tcp.rb
CHANGED
@@ -2,9 +2,9 @@ module PacketGen
|
|
2
2
|
module Header
|
3
3
|
|
4
4
|
# A TCP header consists of:
|
5
|
-
# * a source port ({#sport}, {Int16} type),
|
5
|
+
# * a source port ({#sport}, {Types::Int16} type),
|
6
6
|
# * a destination port ({#dport}, +Int16+ type),
|
7
|
-
# * a sequence number ({#seqnum}, {Int32} type),
|
7
|
+
# * a sequence number ({#seqnum}, {Types::Int32} type),
|
8
8
|
# * an acknownledge number ({#acknum}, +Int32+ type),
|
9
9
|
# * a 16-bit field ({#u16}, +Int16+ type) composed of:
|
10
10
|
# * a 4-bit {#data_offset} value,
|
@@ -14,7 +14,7 @@ module PacketGen
|
|
14
14
|
# * a {#checksum} field (+Int16+ type),
|
15
15
|
# * a urgent pointer ({#urg_pointer}, +Int16+ type),
|
16
16
|
# * an optional {#options} field ({Options} type),
|
17
|
-
# * and a {#body} ({String} type).
|
17
|
+
# * and a {#body} ({Types::String} type).
|
18
18
|
#
|
19
19
|
# == Create a TCP header
|
20
20
|
# # standalone
|
@@ -43,14 +43,10 @@ module PacketGen
|
|
43
43
|
# == Options
|
44
44
|
# {#options} TCP attribute is a {Options}. {Option} may added to it:
|
45
45
|
# tcph.options << PacketGen::Header::TCP::MSS.new(1250)
|
46
|
-
#
|
47
|
-
# tcph.options
|
46
|
+
# or:
|
47
|
+
# tcph.options << { opt: 'MSS', value: 1250 }
|
48
48
|
# @author Sylvain Daubert
|
49
|
-
class TCP <
|
50
|
-
:window, :checksum, :urg_pointer, :options, :body)
|
51
|
-
include StructFu
|
52
|
-
include HeaderMethods
|
53
|
-
extend HeaderClassMethods
|
49
|
+
class TCP < Base
|
54
50
|
end
|
55
51
|
end
|
56
52
|
end
|
@@ -65,6 +61,61 @@ module PacketGen
|
|
65
61
|
# IP protocol number for TCP
|
66
62
|
IP_PROTOCOL = 6
|
67
63
|
|
64
|
+
# @!attribute sport
|
65
|
+
# 16-bit TCP source port
|
66
|
+
# @return [Integer]
|
67
|
+
define_field :sport, Types::Int16
|
68
|
+
# @!attribute dport
|
69
|
+
# 16-bit TCP destination port
|
70
|
+
# @return [Integer]
|
71
|
+
define_field :dport, Types::Int16
|
72
|
+
# @!attribute seqnum
|
73
|
+
# 32-bit TCP sequence number
|
74
|
+
# @return [Integer]
|
75
|
+
define_field :seqnum, Types::Int32, default: -> { rand(2**32) }
|
76
|
+
# @!attribute acknum
|
77
|
+
# 32-bit TCP acknowledgement number
|
78
|
+
# @return [Integer]
|
79
|
+
define_field :acknum, Types::Int32
|
80
|
+
# @!attribute u16
|
81
|
+
# @return [Integer] 16-bit word used by flags and bit fields
|
82
|
+
define_field :u16, Types::Int16
|
83
|
+
# @!attribute window
|
84
|
+
# 16-bit TCP window size
|
85
|
+
# @return [Integer]
|
86
|
+
define_field :window, Types::Int16
|
87
|
+
# @!attribute checksum
|
88
|
+
# 16-bit TCP checksum
|
89
|
+
# @return [Integer]
|
90
|
+
define_field :checksum, Types::Int16
|
91
|
+
# @!attribute urg_pointer
|
92
|
+
# 16-bit TCP urgent data pointer
|
93
|
+
# @return [Integer]
|
94
|
+
define_field :urg_pointer, Types::Int16
|
95
|
+
# @!attribute options
|
96
|
+
# TCP options
|
97
|
+
# @return [Options]
|
98
|
+
define_field :options, TCP::Options
|
99
|
+
# @!attribute body
|
100
|
+
# @return [Types::String,Header::Base]
|
101
|
+
define_field :body, Types::String
|
102
|
+
|
103
|
+
alias source_port sport
|
104
|
+
alias source_port= sport=
|
105
|
+
alias destination_port dport
|
106
|
+
alias destination_port= dport=
|
107
|
+
alias sequence_number seqnum
|
108
|
+
alias sequence_number= seqnum=
|
109
|
+
alias acknowledgement_number acknum
|
110
|
+
alias acknowledgement_number= acknum=
|
111
|
+
alias wsize window
|
112
|
+
alias wsize= window=
|
113
|
+
|
114
|
+
# Call {Base#initialize), then handle specific options to set +u16+ by part:
|
115
|
+
# * +:data_offset+
|
116
|
+
# * +:hlen+
|
117
|
+
# * +:reserved+
|
118
|
+
# * +:flags+
|
68
119
|
# @param [Hash] options
|
69
120
|
# @option options [Integer] :sport
|
70
121
|
# @option options [Integer] :dport
|
@@ -78,21 +129,8 @@ module PacketGen
|
|
78
129
|
# @option options [Integer] :urg_pointer
|
79
130
|
# @option options [String] :body
|
80
131
|
def initialize(options={})
|
81
|
-
|
82
|
-
|
83
|
-
Int32.new(options[:seqnum] || rand(2**32)),
|
84
|
-
Int32.new(options[:acknum]),
|
85
|
-
Int16.new,
|
86
|
-
Int16.new(options[:window] || options[:wsize]),
|
87
|
-
Int16.new(options[:checksum]),
|
88
|
-
Int16.new(options[:urg_pointer]),
|
89
|
-
Options.new,
|
90
|
-
StructFu::String.new.read(options[:body])
|
91
|
-
|
92
|
-
doff = options[:data_offset] || options[:hlen] || 5
|
93
|
-
rsv = options[:reserved] || 0
|
94
|
-
flgs = options[:flags] || 0
|
95
|
-
self.u16.read (((doff << 3) | rsv) << 9) | flgs
|
132
|
+
opts = { data_offset: 5 }.merge!(options)
|
133
|
+
super(opts)
|
96
134
|
end
|
97
135
|
|
98
136
|
# @!attribute data_offset
|
@@ -130,7 +168,6 @@ module PacketGen
|
|
130
168
|
# @return [self]
|
131
169
|
def read(str)
|
132
170
|
return self if str.nil?
|
133
|
-
raise ParseError, 'string too short for TCP' if str.size < self.sz
|
134
171
|
force_binary str
|
135
172
|
self[:sport].read str[0, 2]
|
136
173
|
self[:dport].read str[2, 2]
|
@@ -142,6 +179,7 @@ module PacketGen
|
|
142
179
|
self[:urg_pointer].read str[18, 2]
|
143
180
|
self[:options].read str[20, (self.data_offset - 5) * 4] if self.data_offset > 5
|
144
181
|
self[:body].read str[self.data_offset * 4..-1]
|
182
|
+
self
|
145
183
|
end
|
146
184
|
|
147
185
|
# Compute checksum and set +checksum+ field
|
@@ -167,109 +205,8 @@ module PacketGen
|
|
167
205
|
self[:data_offset] = 5 + self[:options].sz / 4
|
168
206
|
end
|
169
207
|
|
170
|
-
|
171
|
-
|
172
|
-
def sport
|
173
|
-
self[:sport].to_i
|
174
|
-
end
|
175
|
-
alias :source_port :sport
|
176
|
-
|
177
|
-
# Setter for source port
|
178
|
-
# @param [Integer] port
|
179
|
-
# @return [Integer]
|
180
|
-
def sport=(port)
|
181
|
-
self[:sport].read port
|
182
|
-
end
|
183
|
-
alias :source_port= :sport=
|
184
|
-
|
185
|
-
# Getter for destination port
|
186
|
-
# @return [Integer]
|
187
|
-
def dport
|
188
|
-
self[:dport].to_i
|
189
|
-
end
|
190
|
-
alias :destination_port :dport
|
191
|
-
|
192
|
-
# Setter for destination port
|
193
|
-
# @param [Integer] port
|
194
|
-
# @return [Integer]
|
195
|
-
def dport=(port)
|
196
|
-
self[:dport].read port
|
197
|
-
end
|
198
|
-
alias :destination_port= :dport=
|
199
|
-
|
200
|
-
# Getter for seqnum attribuute
|
201
|
-
# @return [Integer]
|
202
|
-
def seqnum
|
203
|
-
self[:seqnum].to_i
|
204
|
-
end
|
205
|
-
alias :sequence_number :seqnum
|
206
|
-
|
207
|
-
# Setter for seqnum attribuute
|
208
|
-
# @param [Integer] seq
|
209
|
-
# @return [Integer]
|
210
|
-
def seqnum=(seq)
|
211
|
-
self[:seqnum].read seq
|
212
|
-
end
|
213
|
-
alias :sequence_number= :seqnum=
|
214
|
-
|
215
|
-
# Getter for acknum attribuute
|
216
|
-
# @return [Integer]
|
217
|
-
def acknum
|
218
|
-
self[:acknum].to_i
|
219
|
-
end
|
220
|
-
alias :acknowledgment_number :acknum
|
221
|
-
|
222
|
-
# Setter for acknum attribuute
|
223
|
-
# @param [Integer] ack
|
224
|
-
# @return [Integer]
|
225
|
-
def acknum=(ack)
|
226
|
-
self[:acknum].read ack
|
227
|
-
end
|
228
|
-
alias :acknowledgment_number= :acknum=
|
229
|
-
|
230
|
-
alias :hlen :data_offset
|
231
|
-
alias :hlen= :data_offset=
|
232
|
-
|
233
|
-
# Getter for window attribuute
|
234
|
-
# @return [Integer]
|
235
|
-
def window
|
236
|
-
self[:window].to_i
|
237
|
-
end
|
238
|
-
alias :wsize :window
|
239
|
-
|
240
|
-
# Setter for window attribuute
|
241
|
-
# @param [Integer] window
|
242
|
-
# @return [Integer]
|
243
|
-
def window=(window)
|
244
|
-
self[:window].read window
|
245
|
-
end
|
246
|
-
alias :wsize= :window=
|
247
|
-
|
248
|
-
# Getter for checksum attribuute
|
249
|
-
# @return [Integer]
|
250
|
-
def checksum
|
251
|
-
self[:checksum].to_i
|
252
|
-
end
|
253
|
-
|
254
|
-
# Setter for checksum attribuute
|
255
|
-
# @param [Integer] sum
|
256
|
-
# @return [Integer]
|
257
|
-
def checksum=(sum)
|
258
|
-
self[:checksum].read sum
|
259
|
-
end
|
260
|
-
|
261
|
-
# Getter for urg_pointer attribuute
|
262
|
-
# @return [Integer]
|
263
|
-
def urg_pointer
|
264
|
-
self[:urg_pointer].to_i
|
265
|
-
end
|
266
|
-
|
267
|
-
# Setter for urg_pointer attribuute
|
268
|
-
# @param [Integer] urg
|
269
|
-
# @return [Integer]
|
270
|
-
def urg_pointer=(urg)
|
271
|
-
self[:urg_pointer].read urg
|
272
|
-
end
|
208
|
+
alias hlen data_offset
|
209
|
+
alias hlen= data_offset=
|
273
210
|
|
274
211
|
# @return [String]
|
275
212
|
def inspect
|
data/lib/packetgen/header/udp.rb
CHANGED
@@ -7,7 +7,7 @@ module PacketGen
|
|
7
7
|
module Header
|
8
8
|
|
9
9
|
# A UDP header consists of:
|
10
|
-
# * a source port field ({#sport}, {Int16} type),
|
10
|
+
# * a source port field ({#sport}, {Types::Int16} type),
|
11
11
|
# * a destination port field ({#dport}, +Int16+ type),
|
12
12
|
# * a UDP length field ({#length}, +Int16+ type),
|
13
13
|
# * a {#checksum} field (+Int16+ type),
|
@@ -29,42 +29,41 @@ module PacketGen
|
|
29
29
|
# udp.body.read 'this is a UDP body'
|
30
30
|
#
|
31
31
|
# @author Sylvain Daubert
|
32
|
-
class UDP <
|
33
|
-
include StructFu
|
34
|
-
include HeaderMethods
|
35
|
-
extend HeaderClassMethods
|
32
|
+
class UDP < Base
|
36
33
|
|
37
34
|
# IP protocol number for UDP
|
38
35
|
IP_PROTOCOL = 17
|
39
36
|
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
|
44
|
-
#
|
37
|
+
# @!attribute sport
|
38
|
+
# 16-bit UDP source port
|
39
|
+
# @return [Integer]
|
40
|
+
define_field :sport, Types::Int16
|
41
|
+
# @!attribute dport
|
42
|
+
# 16-bit UDP destination port
|
43
|
+
# @return [Integer]
|
44
|
+
define_field :dport, Types::Int16
|
45
|
+
# @!attribute length
|
46
|
+
# 16-bit UDP length
|
47
|
+
# @return [Integer]
|
48
|
+
define_field :length, Types::Int16, default: 8
|
49
|
+
# @!attribute checksum
|
50
|
+
# 16-bit UDP checksum
|
51
|
+
# @return [Integer]
|
52
|
+
define_field :checksum, Types::Int16
|
53
|
+
# @!attribute body
|
54
|
+
# @return [Types::String,Header::Base]
|
55
|
+
define_field :body, Types::String
|
56
|
+
|
57
|
+
alias source_port sport
|
58
|
+
alias source_port= sport=
|
59
|
+
alias destination_port dport
|
60
|
+
alias destination_port= dport=
|
61
|
+
|
62
|
+
# Call {Base#initialize), and automagically compute +length+ if +:body+
|
63
|
+
# option is set.
|
45
64
|
def initialize(options={})
|
46
|
-
super
|
47
|
-
|
48
|
-
Int16.new(options[:length]),
|
49
|
-
Int16.new(options[:checksum]),
|
50
|
-
StructFu::String.new.read(options[:body])
|
51
|
-
unless options[:length]
|
52
|
-
calc_length
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Read a IP header from a string
|
57
|
-
# @param [String] str binary string
|
58
|
-
# @return [self]
|
59
|
-
def read(str)
|
60
|
-
return self if str.nil?
|
61
|
-
raise ParseError, 'string too short for UDP' if str.size < self.sz
|
62
|
-
force_binary str
|
63
|
-
self[:sport].read str[0, 2]
|
64
|
-
self[:dport].read str[2, 2]
|
65
|
-
self[:length].read str[4, 2]
|
66
|
-
self[:checksum].read str[6, 2]
|
67
|
-
self[:body].read str[8..-1]
|
65
|
+
super
|
66
|
+
self.length += self[:body].sz if self[:body].sz > 0
|
68
67
|
end
|
69
68
|
|
70
69
|
# Compute checksum and set +checksum+ field
|
@@ -93,62 +92,6 @@ module PacketGen
|
|
93
92
|
def calc_length
|
94
93
|
self[:length].value = self.sz
|
95
94
|
end
|
96
|
-
|
97
|
-
# Getter for source port
|
98
|
-
# @return [Integer]
|
99
|
-
def sport
|
100
|
-
self[:sport].to_i
|
101
|
-
end
|
102
|
-
alias :source_port :sport
|
103
|
-
|
104
|
-
# Setter for source port
|
105
|
-
# @param [Integer] port
|
106
|
-
# @return [Integer]
|
107
|
-
def sport=(port)
|
108
|
-
self[:sport].read port
|
109
|
-
end
|
110
|
-
alias :source_port= :sport=
|
111
|
-
|
112
|
-
# Getter for destination port
|
113
|
-
# @return [Integer]
|
114
|
-
def dport
|
115
|
-
self[:dport].to_i
|
116
|
-
end
|
117
|
-
alias :destination_port :dport
|
118
|
-
|
119
|
-
# Setter for destination port
|
120
|
-
# @param [Integer] port
|
121
|
-
# @return [Integer]
|
122
|
-
def dport=(port)
|
123
|
-
self[:dport].read port
|
124
|
-
end
|
125
|
-
alias :destination_port= :dport=
|
126
|
-
|
127
|
-
# Getter for length attribuute
|
128
|
-
# @return [Integer]
|
129
|
-
def length
|
130
|
-
self[:length].to_i
|
131
|
-
end
|
132
|
-
|
133
|
-
# Setter for length attribuute
|
134
|
-
# @param [Integer] len
|
135
|
-
# @return [Integer]
|
136
|
-
def length=(len)
|
137
|
-
self[:length].read len
|
138
|
-
end
|
139
|
-
|
140
|
-
# Getter for checksum attribuute
|
141
|
-
# @return [Integer]
|
142
|
-
def checksum
|
143
|
-
self[:checksum].to_i
|
144
|
-
end
|
145
|
-
|
146
|
-
# Setter for checksum attribuute
|
147
|
-
# @param [Integer] checksum
|
148
|
-
# @return [Integer]
|
149
|
-
def checksum=(checksum)
|
150
|
-
self[:checksum].read checksum
|
151
|
-
end
|
152
95
|
end
|
153
96
|
|
154
97
|
self.add_class UDP
|
data/lib/packetgen/header.rb
CHANGED
@@ -10,11 +10,7 @@ module PacketGen
|
|
10
10
|
# Since v1.1.0, PacketGen permits adding you own header classes.
|
11
11
|
# First, define the new header class. By example:
|
12
12
|
# module MyModule
|
13
|
-
# class MyHeader <
|
14
|
-
# include PacketGen::StructFu
|
15
|
-
# include PacketGen::Header::HeaderMethods
|
16
|
-
# extend PacketGen::Header::HeaderClassMethods
|
17
|
-
#
|
13
|
+
# class MyHeader < PacketGen::Header::Base
|
18
14
|
# def initialize(options={})
|
19
15
|
# super Int32.new(options[:field1]), Int32.new(options[:field2])
|
20
16
|
# end
|
@@ -47,8 +43,7 @@ module PacketGen
|
|
47
43
|
|
48
44
|
# Add a foreign header class to known header classes. This is
|
49
45
|
# needed by {Packet.gen} and {Packet#add}.
|
50
|
-
# @param [Class] klass a header class
|
51
|
-
# {Header::HeaderMethods} and {Header::HeaderClassMethods}
|
46
|
+
# @param [Class] klass a header class
|
52
47
|
# @return [void]
|
53
48
|
# @since 1.1.0
|
54
49
|
def self.add_class(klass)
|
@@ -57,7 +52,7 @@ module PacketGen
|
|
57
52
|
@header_classes = nil
|
58
53
|
end
|
59
54
|
|
60
|
-
# Remove a foreign header (previously added by {.add_header_class}
|
55
|
+
# Remove a foreign header (previously added by {.add_header_class}
|
61
56
|
# from known header classes.
|
62
57
|
# @param [Class] klass
|
63
58
|
# @return [void]
|
@@ -82,8 +77,7 @@ module PacketGen
|
|
82
77
|
end
|
83
78
|
end
|
84
79
|
|
85
|
-
require_relative 'header/
|
86
|
-
require_relative 'header/header_methods'
|
80
|
+
require_relative 'header/base'
|
87
81
|
require_relative 'header/eth'
|
88
82
|
require_relative 'header/ip'
|
89
83
|
require_relative 'header/icmp'
|
@@ -93,3 +87,4 @@ require_relative 'header/icmpv6'
|
|
93
87
|
require_relative 'header/udp'
|
94
88
|
require_relative 'header/tcp'
|
95
89
|
require_relative 'header/esp'
|
90
|
+
require_relative 'header/dns'
|