packetgen 2.0.1 → 2.1.0

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