packetgen 2.5.2 → 2.6.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/base.rb +13 -0
- data/lib/packetgen/header/dns.rb +0 -6
- data/lib/packetgen/header/dns/name.rb +2 -0
- data/lib/packetgen/header/dns/question.rb +12 -2
- data/lib/packetgen/header/dns/rr.rb +21 -2
- data/lib/packetgen/header/http.rb +1 -0
- data/lib/packetgen/header/http/headers.rb +3 -4
- data/lib/packetgen/header/http/request.rb +18 -6
- data/lib/packetgen/header/http/response.rb +3 -3
- data/lib/packetgen/header/http/verbs.rb +22 -0
- data/lib/packetgen/header/mdns.rb +75 -0
- data/lib/packetgen/header/snmp.rb +13 -0
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df09d9bda17671562435fd055b6ab552aa3e19798251f953e1e260786bae168d
|
4
|
+
data.tar.gz: 79baa63b2cfa57534246b3806033dc6233ea9a2ae9da3c6aa0dc9dc803983d97
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6f3349f7d168b5b8391fa78e1ed90763295c7dc8db21bc0ee517195f96ca290172ad788c2c3fe4d2787809209fc502be4b05f00df6bc9f595709edf06136618
|
7
|
+
data.tar.gz: d218ba23d8c02253d75bd18f1ea552ce3aee8490895c0886504f443d87f18bbd0ed7c3e0ca13bc30f7bcf4db5fbb7abe7e4c0630bfc1f5fd36b750faa130e56c
|
data/lib/packetgen/header.rb
CHANGED
@@ -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
|
data/lib/packetgen/header/dns.rb
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
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 =
|
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}"
|
@@ -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
|
-
|
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
|
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
|
-
|
65
|
-
|
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
|
-
|
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) {
|
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
|
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
|
-
|
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
|
data/lib/packetgen/version.rb
CHANGED
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.
|
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.
|
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-
|
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.
|
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.
|
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
|