packetgen 2.0.1 → 2.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.
- checksums.yaml +4 -4
- data/lib/packetgen/header.rb +1 -0
- data/lib/packetgen/header/gre.rb +90 -0
- data/lib/packetgen/packet.rb +1 -1
- data/lib/packetgen/types/fields.rb +35 -5
- data/lib/packetgen/types/int_string.rb +10 -2
- data/lib/packetgen/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0f4985dff6a759aee18e0ca94ec364686d58304
|
4
|
+
data.tar.gz: 5aed1f1d1075e6c00ccac6f76191fcbf537f0005
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccc6f02e411f0f2632bb21b49859bb4efa4a7cf76c71a32e035796589dd4acddee1508ef47ed26afb426b6e1060b694a88d6872a4f019863274b4bf9573c2dcc
|
7
|
+
data.tar.gz: ea8b5f8819097303c3134b168fa4eaaa4de4fe00d23d7eb5631f1d1279a0b9bbbf0159c3e1fb6dfc71846ecbe1fc0929c4da010710dcb790ce1e5bdceb365d27
|
data/lib/packetgen/header.rb
CHANGED
@@ -90,6 +90,7 @@ require_relative 'header/icmp'
|
|
90
90
|
require_relative 'header/arp'
|
91
91
|
require_relative 'header/ipv6'
|
92
92
|
require_relative 'header/icmpv6'
|
93
|
+
require_relative 'header/gre'
|
93
94
|
require_relative 'header/udp'
|
94
95
|
require_relative 'header/tcp'
|
95
96
|
require_relative 'header/esp'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
|
9
|
+
# Generic Routing Encapsulation (RFC 2784 and 2890)
|
10
|
+
# 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
|
11
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
12
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
13
|
+
# |C| |K|S| Reserved0 | Ver | Protocol Type |
|
14
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
15
|
+
# | Checksum (optional) | Reserved1 (Optional) |
|
16
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
17
|
+
# | Key (optional) |
|
18
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
19
|
+
# | Sequence Number (Optional) |
|
20
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
21
|
+
# @author Sylvain Daubert
|
22
|
+
class GRE < Base
|
23
|
+
|
24
|
+
# IP protocol number for GRE
|
25
|
+
IP_PROTOCOL = 47
|
26
|
+
|
27
|
+
define_field :u16, Types::Int16
|
28
|
+
|
29
|
+
# @!attribute c
|
30
|
+
# @return [Boolean]
|
31
|
+
# @!attribute k
|
32
|
+
# @return [Boolean]
|
33
|
+
# @!attribute s
|
34
|
+
# @return [Boolean]
|
35
|
+
# @!attribute reserved0
|
36
|
+
# @return [Integer]
|
37
|
+
# @!attribute ver
|
38
|
+
# @return [Integer]
|
39
|
+
define_bit_fields_on :u16, :c, :r, :k, :s, :reserved0, 9, :ver, 3
|
40
|
+
|
41
|
+
# @!attribute protocol_type
|
42
|
+
# @return [Integer]
|
43
|
+
define_field :protocol_type, Types::Int16
|
44
|
+
# @!attribute checksum
|
45
|
+
# @return [Integer]
|
46
|
+
define_field :checksum, Types::Int16, default: 0, optional: ->(gre) { gre.c? }
|
47
|
+
# @!attribute reserved1
|
48
|
+
# @return [Integer]
|
49
|
+
define_field :reserved1, Types::Int16, default: 0, optional: ->(gre) { gre.c? }
|
50
|
+
# @!attribute key
|
51
|
+
# @return [Integer]
|
52
|
+
define_field :key, Types::Int32, optional: ->(gre) { gre.k? }
|
53
|
+
# @!attribute sequence_number
|
54
|
+
# @return [Integer]
|
55
|
+
define_field :sequence_number, Types::Int32, optional: ->(gre) { gre.s? }
|
56
|
+
# @!attribute body
|
57
|
+
# @return [Types::String,Header::Base]
|
58
|
+
define_field :body, Types::String
|
59
|
+
|
60
|
+
alias seqnum sequence_number
|
61
|
+
alias seqnum= sequence_number=
|
62
|
+
|
63
|
+
def initialize(options={})
|
64
|
+
opts = { r: false, reserved0: 0, version: 0 }.merge(options)
|
65
|
+
super(opts)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Compute checksum and set +checksum+ field
|
69
|
+
# @return [Integer]
|
70
|
+
def calc_checksum
|
71
|
+
str = to_s
|
72
|
+
str << "\x00" if str.length % 2 == 1
|
73
|
+
sum = str.unpack('n*').reduce(:+)
|
74
|
+
|
75
|
+
while sum > 0xffff do
|
76
|
+
sum = (sum & 0xffff) + (sum >> 16)
|
77
|
+
end
|
78
|
+
sum = ~sum & 0xffff
|
79
|
+
self[:checksum].value = (sum == 0) ? 0xffff : sum
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
self.add_class GRE
|
84
|
+
IP.bind_header GRE, protocol: GRE::IP_PROTOCOL
|
85
|
+
IPv6.bind_header GRE, next: GRE::IP_PROTOCOL
|
86
|
+
|
87
|
+
GRE.bind_header IP, protocol_type: IP::ETHERTYPE
|
88
|
+
GRE.bind_header IPv6, protocol_type: IPv6::ETHERTYPE
|
89
|
+
end
|
90
|
+
end
|
data/lib/packetgen/packet.rb
CHANGED
@@ -203,7 +203,7 @@ module PacketGen
|
|
203
203
|
# @return [Array] see return from {PcapNG::File#to_file}
|
204
204
|
# @see File
|
205
205
|
def to_f(filename)
|
206
|
-
File.new.array_to_file(filename: filename, array: [self])
|
206
|
+
PcapNG::File.new.array_to_file(filename: filename, array: [self])
|
207
207
|
end
|
208
208
|
alias :write :to_f
|
209
209
|
|
@@ -58,7 +58,9 @@ module PacketGen
|
|
58
58
|
# * +:default+ gives default field value. It may be a simple value (an Integer
|
59
59
|
# for an Int field, for example) or a lambda,
|
60
60
|
# * +:builder+ to give a builder/constructor lambda to create field. The lambda
|
61
|
-
# takes one argument: {Fields} subclass object owning field
|
61
|
+
# takes one argument: {Fields} subclass object owning field,
|
62
|
+
# * +:optional+ to define this field as optional. This option takes a lambda
|
63
|
+
# parameter used to say if this field is present or not.
|
62
64
|
# For example:
|
63
65
|
# # 32-bit integer field defaulting to 1
|
64
66
|
# define_field :type, PacketGen::Types::Int32, default: 1
|
@@ -128,6 +130,9 @@ module PacketGen
|
|
128
130
|
# @option options [Object] :default default value
|
129
131
|
# @option options [Lambda] :builder lambda to construct this field.
|
130
132
|
# Parameter to this lambda is the caller object.
|
133
|
+
# @option options [Lambda] :optional define this field as optional. Given lambda
|
134
|
+
# is used to known if this field is present or not. Parameter to this lambda is
|
135
|
+
# the being defined Field object.
|
131
136
|
# @return [void]
|
132
137
|
def self.define_field(name, type, options={})
|
133
138
|
define = []
|
@@ -147,7 +152,7 @@ module PacketGen
|
|
147
152
|
define.delete(0) if type.instance_methods.include? name
|
148
153
|
class_eval define.join("\n")
|
149
154
|
@field_defs[name] = [type, options.delete(:default), options.delete(:builder),
|
150
|
-
options]
|
155
|
+
options.delete(:optional), options]
|
151
156
|
@ordered_fields << name
|
152
157
|
end
|
153
158
|
|
@@ -274,12 +279,14 @@ module PacketGen
|
|
274
279
|
# attributes, as defined by {.define_field} and by {.define_bit_fields_on}.
|
275
280
|
def initialize(options={})
|
276
281
|
@fields = {}
|
282
|
+
@optional_fields = {}
|
283
|
+
|
277
284
|
self.class.class_eval { @field_defs }.each do |field, ary|
|
278
285
|
default = ary[1].is_a?(Proc) ? ary[1].call : ary[1]
|
279
286
|
@fields[field] = if ary[2]
|
280
287
|
ary[2].call(self)
|
281
|
-
elsif !ary[
|
282
|
-
ary[0].new(ary[
|
288
|
+
elsif !ary[4].empty?
|
289
|
+
ary[0].new(ary[4])
|
283
290
|
else
|
284
291
|
ary[0].new
|
285
292
|
end
|
@@ -292,6 +299,8 @@ module PacketGen
|
|
292
299
|
else
|
293
300
|
@fields[field].from_human(value) if @fields[field].respond_to? :from_human
|
294
301
|
end
|
302
|
+
|
303
|
+
@optional_fields[field] = ary[3] if ary[3]
|
295
304
|
end
|
296
305
|
self.class.class_eval { @bit_fields }.each do |bit_field|
|
297
306
|
self.send "#{bit_field}=", options[bit_field] if options[bit_field]
|
@@ -319,6 +328,24 @@ module PacketGen
|
|
319
328
|
@ordered_fields ||= self.class.class_eval { @ordered_fields }
|
320
329
|
end
|
321
330
|
|
331
|
+
# Get all optional field name
|
332
|
+
def optional_fields
|
333
|
+
fields.select { |f| is_optional?(f) }
|
334
|
+
end
|
335
|
+
|
336
|
+
# Say if this field is optional
|
337
|
+
# @return [Boolean]
|
338
|
+
def is_optional?(field)
|
339
|
+
@optional_fields.has_key? field
|
340
|
+
end
|
341
|
+
|
342
|
+
# Say if an optional field is present
|
343
|
+
# @return [Boolean]
|
344
|
+
def is_present?(field)
|
345
|
+
return true unless is_optional?(field)
|
346
|
+
@optional_fields[field].call(self)
|
347
|
+
end
|
348
|
+
|
322
349
|
# Populate object from a binary string
|
323
350
|
# @param [String] str
|
324
351
|
# @return [Fields] self
|
@@ -327,6 +354,7 @@ module PacketGen
|
|
327
354
|
force_binary str
|
328
355
|
start = 0
|
329
356
|
fields.each do |field|
|
357
|
+
next unless is_present?(field)
|
330
358
|
if self[field].respond_to? :width
|
331
359
|
width = self[field].width
|
332
360
|
self[field].read str[start, width]
|
@@ -350,6 +378,7 @@ module PacketGen
|
|
350
378
|
str = Inspect.dashed_line(self.class, 2)
|
351
379
|
fields.each do |attr|
|
352
380
|
next if attr == :body
|
381
|
+
next unless is_present?(attr)
|
353
382
|
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
354
383
|
end
|
355
384
|
str
|
@@ -358,7 +387,8 @@ module PacketGen
|
|
358
387
|
# Return object as a binary string
|
359
388
|
# @return [String]
|
360
389
|
def to_s
|
361
|
-
fields.
|
390
|
+
fields.select { |f| is_present?(f) }.
|
391
|
+
map! { |f| force_binary @fields[f].to_s }.join
|
362
392
|
end
|
363
393
|
|
364
394
|
# Size of object as binary string
|
@@ -14,7 +14,7 @@ module PacketGen
|
|
14
14
|
|
15
15
|
# internal string
|
16
16
|
# @return [String]
|
17
|
-
|
17
|
+
attr_reader :string
|
18
18
|
|
19
19
|
# @param [::String] str
|
20
20
|
# @param [Class] len_type should be a {Int} subclass
|
@@ -28,7 +28,8 @@ module PacketGen
|
|
28
28
|
# @return [IntString] self
|
29
29
|
def read(str)
|
30
30
|
unless str[0, @length.width].size == @length.width
|
31
|
-
raise ParseError,
|
31
|
+
raise ParseError,
|
32
|
+
"String too short for type #{@length.class.to_s.gsub(/.*::/, '')}"
|
32
33
|
end
|
33
34
|
@length.read str[0, @length.width]
|
34
35
|
@string.read str[@length.width, @length.to_i]
|
@@ -47,6 +48,13 @@ module PacketGen
|
|
47
48
|
@length.to_i
|
48
49
|
end
|
49
50
|
|
51
|
+
# @param [#to_s] s
|
52
|
+
# @return [String]
|
53
|
+
def string=(s)
|
54
|
+
@length.value = s.to_s.size
|
55
|
+
@string = s.to_s
|
56
|
+
end
|
57
|
+
|
50
58
|
# Get binary string
|
51
59
|
# @return [::String]
|
52
60
|
def to_s
|
data/lib/packetgen/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-08-
|
11
|
+
date: 2017-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pcaprub
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- lib/packetgen/header/dot1x.rb
|
198
198
|
- lib/packetgen/header/esp.rb
|
199
199
|
- lib/packetgen/header/eth.rb
|
200
|
+
- lib/packetgen/header/gre.rb
|
200
201
|
- lib/packetgen/header/icmp.rb
|
201
202
|
- lib/packetgen/header/icmpv6.rb
|
202
203
|
- lib/packetgen/header/ike.rb
|