packetgen 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|