packetgen 2.5.2 → 2.6.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
  SHA256:
3
- metadata.gz: 81bd9bfad83fea7f710f36b3b063385612bd457c5e6f91c8dd58c4dafdc71c81
4
- data.tar.gz: 9f12e1c56a87a4b01b5d0e228531d5de9f42a48f098253e72c07152d8adca14d
3
+ metadata.gz: df09d9bda17671562435fd055b6ab552aa3e19798251f953e1e260786bae168d
4
+ data.tar.gz: 79baa63b2cfa57534246b3806033dc6233ea9a2ae9da3c6aa0dc9dc803983d97
5
5
  SHA512:
6
- metadata.gz: be77a1686d765dd1fc03cc40e4be495bf4f1719da3e7a54578783280d03be4e45d4e910208bd39d160ae4af2bf9aae0e7a645b330702496cb5e7f4e84096f8b1
7
- data.tar.gz: 26da42851fdb12547c7744cbb52a325443c011c131b3e259b3c5cc111b0cf412bbd2b595ad5dca4c058299e82c99f4b9d87758fbeba873f81b7e03c4d02a88bd
6
+ metadata.gz: a6f3349f7d168b5b8391fa78e1ed90763295c7dc8db21bc0ee517195f96ca290172ad788c2c3fe4d2787809209fc502be4b05f00df6bc9f595709edf06136618
7
+ data.tar.gz: d218ba23d8c02253d75bd18f1ea552ce3aee8490895c0886504f443d87f18bbd0ed7c3e0ca13bc30f7bcf4db5fbb7abe7e4c0630bfc1f5fd36b750faa130e56c
@@ -113,3 +113,4 @@ require_relative 'header/mldv2'
113
113
  require_relative 'header/ospfv2'
114
114
  require_relative 'header/ospfv3'
115
115
  require_relative 'header/netbios'
116
+ require_relative 'header/mdns'
@@ -288,6 +288,19 @@ module PacketGen
288
288
  raise FormatError, 'no IP or IPv6 header in packet' if iph.nil?
289
289
  iph
290
290
  end
291
+
292
+ # @api private
293
+ # Get link layer header from given header
294
+ # @param [Header] header
295
+ # @return [Header]
296
+ # @raise FormatError no link layer header in packet
297
+ # @raise FormatError +header+ not in a packet
298
+ def ll_header(header)
299
+ hid = header_id(header)
300
+ llh = packet.headers[0...hid].reverse.find { |h| h.is_a? Eth or h.is_a? Dot11 }
301
+ raise FormatError, 'no link layer header in packet' if llh.nil?
302
+ llh
303
+ end
291
304
  end
292
305
  end
293
306
  end
@@ -269,12 +269,6 @@ module PacketGen
269
269
  end
270
270
  str
271
271
  end
272
-
273
- private
274
-
275
- def boolean2integer(bool)
276
- bool ? 1 : 0
277
- end
278
272
  end
279
273
 
280
274
  self.add_class DNS
@@ -70,6 +70,8 @@ module PacketGen
70
70
  break if label.length == 0 or str[start..-1].length == 0
71
71
  end
72
72
  end
73
+ # force resolution of compressed names
74
+ name_from_pointer
73
75
  self
74
76
  end
75
77
 
@@ -32,6 +32,7 @@ module PacketGen
32
32
  'MX' => 15,
33
33
  'TXT' => 16,
34
34
  'AAAA' => 28,
35
+ 'SRV' => 33,
35
36
  'NAPTR' => 35,
36
37
  'KX' => 36,
37
38
  'CERT' => 37,
@@ -109,12 +110,21 @@ module PacketGen
109
110
  # Get human readable class
110
111
  # @return [String]
111
112
  def human_rrclass
112
- self.class::CLASSES.key(self.rrclass) || "0x%04x" % self.rrclass
113
+ if self[:name].dns.is_a? MDNS
114
+ self.class::CLASSES.key(self.rrclass & 0x7fff) || "0x%04x" % (self.rrclass & 0x7fff)
115
+ else
116
+ self.class::CLASSES.key(self.rrclass) || "0x%04x" % self.rrclass
117
+ end
113
118
  end
114
119
 
115
120
  # @return [String]
116
121
  def to_human
117
- "#{human_type} #{human_rrclass} #{name}"
122
+ if self[:name].dns.is_a? MDNS
123
+ unicast_bit = (self.rrclass & 0x8000 == 0x8000) ? 'QU' : 'QM'
124
+ "#{human_type} #{human_rrclass} #{unicast_bit} #{name}"
125
+ else
126
+ "#{human_type} #{human_rrclass} #{name}"
127
+ end
118
128
  end
119
129
  end
120
130
  end
@@ -55,7 +55,8 @@ module PacketGen
55
55
  def human_rdata
56
56
  str = self[:rdata].inspect
57
57
 
58
- if self.rrclass == CLASSES['IN']
58
+ # Need to mask: mDNS uses leftmost bit as a flag (CACHE FLUSH)
59
+ if self.rrclass & 0x7fff == CLASSES['IN']
59
60
  case type
60
61
  when TYPES['A'], TYPES['AAAA']
61
62
  str = IPAddr.new_ntoh(self[:rdata]).to_s
@@ -63,7 +64,7 @@ module PacketGen
63
64
  end
64
65
 
65
66
  name = Name.new
66
- name.dns = @dns
67
+ name.dns = self[:name].dns
67
68
  case type
68
69
  when TYPES['NS'], TYPES['PTR'], TYPES['CNAME']
69
70
  str = name.read(self[:rdata]).to_human
@@ -81,11 +82,29 @@ module PacketGen
81
82
  pref = Types::Int16.new.read(self[:rdata][0, 2])
82
83
  exchange = name.read(self[:rdata][2..-1]).to_human
83
84
  str = '%u %s' % [pref.to_i, exchange]
85
+ when TYPES['SRV']
86
+ priority = Types::Int16.new.read(self[:rdata][0, 2])
87
+ weight = Types::Int16.new.read(self[:rdata][2, 2])
88
+ port = Types::Int16.new.read(self[:rdata][4, 2])
89
+ target = name.read(self[:rdata][6, self[:rdata].size]).to_human
90
+ str = "#{priority.to_i} #{weight.to_i} #{port.to_i} #{target}"
84
91
  end
85
92
 
86
93
  str
87
94
  end
88
95
 
96
+ def human_rrclass
97
+ # Get human readable class
98
+ # @return [String]
99
+ if self[:name].dns.is_a? MDNS
100
+ str = self.class::CLASSES.key(self.rrclass & 0x7fff) || "0x%04x" % (self.rrclass & 0x7fff)
101
+ str += ' CACHE-FLUSH' if self.rrclass & 0x8000 > 0
102
+ str
103
+ else
104
+ self.class::CLASSES.key(self.rrclass) || "0x%04x" % self.rrclass
105
+ end
106
+ end
107
+
89
108
  # @return [String]
90
109
  def to_human
91
110
  "#{human_type} #{human_rrclass} #{name} TTL #{ttl} #{human_rdata}"
@@ -4,5 +4,6 @@
4
4
  # This program is published under MIT license.
5
5
 
6
6
  require_relative 'http/headers'
7
+ require_relative 'http/verbs'
7
8
  require_relative 'http/response'
8
9
  require_relative 'http/request'
@@ -24,9 +24,10 @@ module PacketGen
24
24
  case s_or_h
25
25
  when String
26
26
  @data = s_or_h.split("\n").map do |h|
27
+ next unless h.include?(":")
27
28
  k, v = h.split(":", 2)
28
29
  [k, v.strip]
29
- end.to_h
30
+ end.reject(&:nil?).to_h
30
31
  when Hash
31
32
  @data = s_or_h
32
33
  end
@@ -39,9 +40,7 @@ module PacketGen
39
40
  return "\r\n" if @data.nil? || @data.empty?
40
41
  d = []
41
42
  @data.map do |k, v|
42
- str = ""
43
- str << k << ": " << v
44
- d << str
43
+ d << k + ": " + v
45
44
  end
46
45
  d.join("\r\n") << "\r\n\r\n"
47
46
  end
@@ -8,7 +8,7 @@
8
8
  module PacketGen
9
9
  module Header
10
10
  module HTTP
11
- # An HTTP/1.1 Request packet consits of:
11
+ # An HTTP/1.1 Request packet consists of:
12
12
  # * the http method ({Types::String}).
13
13
  # * the path ({Types::String}).
14
14
  # * the version ({Types::String}).
@@ -47,6 +47,9 @@ module PacketGen
47
47
  # associated http/1.1 headers
48
48
  # @return [HTTP::Headers]
49
49
  define_field :headers, HTTP::Headers
50
+ # @!attribute body
51
+ # @return [Types::String]
52
+ define_field :body, Types::String
50
53
 
51
54
  # @param [Hash] options
52
55
  # @option options [String] :method
@@ -61,14 +64,23 @@ module PacketGen
61
64
  # Read in the HTTP portion of the packet, and parse it.
62
65
  # @return [PacketGen::HTTP::Request]
63
66
  def read(str)
64
- # prepare data to parse
65
- str = str.split("\n").map(&:strip).reject(&:empty?)
67
+ str = str.bytes.map!(&:chr).join unless str.valid_encoding?
68
+ vrb = HTTP::VERBS.detect { |verb| str.include?(verb) }
69
+ str = vrb + str.split(vrb)[-1]
70
+ str = str.split("\n").map(&:chomp)
66
71
  first_line = str.shift.split
67
72
  self[:method] = first_line[0]
68
73
  self[:path] = first_line[1]
69
74
  self[:version] = first_line[2]
70
- headers = str.join("\n")
75
+ # requests can sometimes have a payload
76
+ if data_index = str.find_index("")
77
+ data = str[data_index+1..-1].join("\n")
78
+ headers = str[0..data_index-1].join("\n")
79
+ else
80
+ headers = str.join("\n")
81
+ end
71
82
  self[:headers].read(headers)
83
+ self[:body] = data
72
84
  self
73
85
  end
74
86
 
@@ -79,12 +91,12 @@ module PacketGen
79
91
  raise FormatError, "Missing #path." if self.path.empty?
80
92
  raise FormatError, "Missing #version." if self.version.empty?
81
93
  str = "".dup # build 'dat string
82
- str << self[:method] << " " << self[:path] << " " << self[:version] << "\r\n" << self[:headers].to_s
94
+ str << self[:method] << " " << self[:path] << " " << self[:version] << "\r\n" << self[:headers].to_s << self[:body]
83
95
  end
84
96
  end
85
97
  end
86
98
 
87
99
  self.add_class HTTP::Request
88
- TCP.bind_header HTTP::Request, body: ->(b) { /^(CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PUT)/ =~ b }
100
+ TCP.bind_header HTTP::Request, body: ->(b) { HTTP::REQUEST_REGEX =~ b.chars.select(&:valid_encoding?).join }
89
101
  end
90
102
  end
@@ -8,7 +8,7 @@
8
8
  module PacketGen
9
9
  module Header
10
10
  module HTTP
11
- # An HTTP/1.1 Response packet consits of:
11
+ # An HTTP/1.1 Response packet consists of:
12
12
  # * the version ({Types::String}).
13
13
  # * the status code ({Types::String}).
14
14
  # * the status message ({Types::String}).
@@ -67,7 +67,7 @@ module PacketGen
67
67
  # Read in the HTTP portion of the packet, and parse it.
68
68
  # @return [PacketGen::HTTP::Response]
69
69
  def read(str)
70
- # prepare data to parse
70
+ str = str.bytes.map!(&:chr).join unless str.valid_encoding?
71
71
  arr = str.split("\r\n")
72
72
  headers = [] # header stream
73
73
  data = [] # data stream
@@ -113,6 +113,6 @@ module PacketGen
113
113
  end
114
114
 
115
115
  self.add_class HTTP::Response
116
- TCP.bind_header HTTP::Response, body: ->(b) { /^HTTP\/1\.1\s\d{3,}\s.+/ =~ b }
116
+ TCP.bind_header HTTP::Response, body: ->(b) { /^HTTP\/1\.1\s\d{3,}\s.+/ =~ b.chars.select(&:valid_encoding?).join }
117
117
  end
118
118
  end
@@ -0,0 +1,22 @@
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
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Header
10
+ # @since 2.2.0
11
+ module HTTP
12
+ # @abstract Collection of useful HTTP verbs.
13
+ # @author Kent 'picat' Gruber
14
+
15
+ # Valid HTTP Verbs
16
+ VERBS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']
17
+
18
+ # Identifiable HTTP request regular expression.
19
+ REQUEST_REGEX = Regexp.new("(" + VERBS.dup.join("|") + ")" + '\s+\S+\s+HTTP/1.1')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,75 @@
1
+ # coding: utf-8
2
+ # This file is part of PacketGen
3
+ # See https://github.com/sdaubert/packetgen for more informations
4
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
5
+ # This program is published under MIT license.
6
+
7
+ # frozen_string_literal: true
8
+
9
+ module PacketGen
10
+ module Header
11
+
12
+ # Multicast DNS.
13
+ #
14
+ # See {DNS} for header format.
15
+ # @author Sylvain Daubert
16
+ class MDNS < DNS
17
+ # Port number for mDNS over UDP
18
+ UDP_PORT = 5353
19
+
20
+ # Fixup IP header according to RFC 6762:
21
+ # * set ethernet multicast address to +01:00:5E:00:00:FB+ (for IPv4)
22
+ # or +33:33:00:00:00:FB+ (for IPv6),
23
+ # * set IPv4 address to 224.0.0.251 or IPv6 address to ff02::fb.
24
+ # This method may be called as:
25
+ # # first way
26
+ # pkt.mdns.mdnsize
27
+ # # second way
28
+ # pkt.mdnsize
29
+ def mdnsize
30
+ iph = ip_header(self)
31
+ case iph
32
+ when IP
33
+ iph.dst = '224.0.0.251'
34
+ llh = ll_header(self)
35
+ mac = case llh
36
+ when Eth
37
+ llh[:dst]
38
+ when Dot11
39
+ if llh.to_ds?
40
+ llh[:mac3]
41
+ else
42
+ llh[:mac1]
43
+ end
44
+ end
45
+ mac.from_human('01:00:5E:00:00:FB')
46
+ when IPv6
47
+ iph.dst = 'ff02::fb'
48
+ llh = ll_header(self)
49
+ mac = case llh
50
+ when Eth
51
+ llh[:dst]
52
+ when Dot11
53
+ if llh.to_ds?
54
+ llh[:mac3]
55
+ else
56
+ llh[:mac1]
57
+ end
58
+ end
59
+ mac.from_human('33:33:00:00:00:FB')
60
+ end
61
+ end
62
+
63
+ # @api private
64
+ # @note This method is used internally by PacketGen and should not be
65
+ # directly called
66
+ def added_to_packet(packet)
67
+ mdns_idx = packet.headers.size
68
+ packet.instance_eval "def mdnsize() @headers[#{mdns_idx}].mdnsize; end"
69
+ end
70
+ end
71
+
72
+ self.add_class MDNS
73
+ UDP.bind_header MDNS, dport: MDNS::UDP_PORT, sport: MDNS::UDP_PORT
74
+ end
75
+ end
@@ -251,6 +251,19 @@ module PacketGen
251
251
 
252
252
  define_attributes :version, :community
253
253
 
254
+ # @param [Hash] options
255
+ # @option options [Integer,String] :version
256
+ # @option options [String] :community
257
+ # @option options [Integer] :chosen_pdu Set PDU type
258
+ # @option options [Hash] :pdu Set PDU content
259
+ def initialize(options={})
260
+ super
261
+ data.chosen = options[:chosen_pdu] if options[:chosen_pdu]
262
+ if options[:pdu]
263
+ data.root.value[data.chosen] = data.root.chosen_value.class.new(options[:pdu])
264
+ end
265
+ end
266
+
254
267
  # accessor to data payload
255
268
  # @return [GetRequest]
256
269
  def data
@@ -10,5 +10,5 @@
10
10
  # @author Sylvain Daubert
11
11
  module PacketGen
12
12
  # PacketGen version
13
- VERSION = '2.5.2'
13
+ VERSION = '2.6.0'
14
14
  end
data/packetgen.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_dependency 'pcaprub', '~>0.12.4'
27
27
  spec.add_dependency 'interfacez', '~>1.0'
28
- spec.add_dependency 'rasn1', '~>0.5', '>= 0.6.0'
28
+ spec.add_dependency 'rasn1', '~>0.5', '>= 0.6.3'
29
29
 
30
30
  spec.add_development_dependency 'bundler', '~> 1.7'
31
31
  spec.add_development_dependency 'rake', '~> 12.0'
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.5.2
4
+ version: 2.6.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: 2018-06-26 00:00:00.000000000 Z
11
+ date: 2018-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pcaprub
@@ -47,7 +47,7 @@ dependencies:
47
47
  version: '0.5'
48
48
  - - ">="
49
49
  - !ruby/object:Gem::Version
50
- version: 0.6.0
50
+ version: 0.6.3
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
@@ -57,7 +57,7 @@ dependencies:
57
57
  version: '0.5'
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 0.6.0
60
+ version: 0.6.3
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: bundler
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -188,6 +188,7 @@ files:
188
188
  - lib/packetgen/header/http/headers.rb
189
189
  - lib/packetgen/header/http/request.rb
190
190
  - lib/packetgen/header/http/response.rb
191
+ - lib/packetgen/header/http/verbs.rb
191
192
  - lib/packetgen/header/icmp.rb
192
193
  - lib/packetgen/header/icmpv6.rb
193
194
  - lib/packetgen/header/igmp.rb
@@ -217,6 +218,7 @@ files:
217
218
  - lib/packetgen/header/ipv6/extension.rb
218
219
  - lib/packetgen/header/ipv6/hop_by_hop.rb
219
220
  - lib/packetgen/header/llc.rb
221
+ - lib/packetgen/header/mdns.rb
220
222
  - lib/packetgen/header/mld.rb
221
223
  - lib/packetgen/header/mldv2.rb
222
224
  - lib/packetgen/header/mldv2/mcast_address_record.rb