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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d412e2595d6167eeef26384bc6c0a2d125b1053b
4
- data.tar.gz: 41408b62486f59daa0b702b8b5405d6626a753d2
3
+ metadata.gz: c0f4985dff6a759aee18e0ca94ec364686d58304
4
+ data.tar.gz: 5aed1f1d1075e6c00ccac6f76191fcbf537f0005
5
5
  SHA512:
6
- metadata.gz: 20c2421f674f009fccdd73496a609a8cac35f51ceba68c2398189b70f1d5d35f5238265074a718909119a98976fcf16b4c9fbac365f417519070508d9a77fede
7
- data.tar.gz: 187b90c6786d10451301f97d2a288a6b7921a1f2ca1a4ae83a2df43a5338d306844282833a2c62cf7dde922279d36cfbcd072f12003af10e71e8866791fe68e1
6
+ metadata.gz: ccc6f02e411f0f2632bb21b49859bb4efa4a7cf76c71a32e035796589dd4acddee1508ef47ed26afb426b6e1060b694a88d6872a4f019863274b4bf9573c2dcc
7
+ data.tar.gz: ea8b5f8819097303c3134b168fa4eaaa4de4fe00d23d7eb5631f1d1279a0b9bbbf0159c3e1fb6dfc71846ecbe1fc0929c4da010710dcb790ce1e5bdceb365d27
@@ -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
@@ -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[3].empty?
282
- ary[0].new(ary[3])
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.map { |f| force_binary @fields[f].to_s }.join
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
- attr_accessor :string
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, "String too short for type #{@length.type}"
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
@@ -8,5 +8,5 @@
8
8
  # @author Sylvain Daubert
9
9
  module PacketGen
10
10
  # PacketGen version
11
- VERSION = "2.0.1"
11
+ VERSION = "2.1.0"
12
12
  end
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.1
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-13 00:00:00.000000000 Z
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