packetgen 3.2.2 → 3.3.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/capture.rb +19 -8
- data/lib/packetgen/header/dns/name.rb +3 -3
- data/lib/packetgen/header/dns/rr.rb +2 -2
- data/lib/packetgen/header/dot11.rb +1 -1
- data/lib/packetgen/header/http/request.rb +1 -1
- data/lib/packetgen/header/http/response.rb +1 -1
- data/lib/packetgen/header/ip/option.rb +2 -2
- data/lib/packetgen/header/ipv6/addr.rb +1 -1
- data/lib/packetgen/header/ospfv2/lsa_header.rb +1 -1
- data/lib/packetgen/header/ospfv3/lsa_header.rb +1 -1
- data/lib/packetgen/header/tcp/options.rb +1 -1
- data/lib/packetgen/headerable.rb +1 -1
- data/lib/packetgen/inspect.rb +6 -3
- data/lib/packetgen/packet.rb +2 -0
- data/lib/packetgen/pcapng/file.rb +2 -2
- data/lib/packetgen/pcaprub_wrapper.rb +2 -2
- data/lib/packetgen/proto.rb +1 -1
- data/lib/packetgen/types/fields.rb +4 -2
- data/lib/packetgen/utils/arp_spoofer.rb +3 -1
- data/lib/packetgen/utils.rb +5 -5
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +3 -1
- metadata +7 -55
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: de85a6f18ac001823cdbd0802c8946ead811be724c9069266b78c493d99feb6b
|
|
4
|
+
data.tar.gz: ef73ca367e87bb47ca4f37ee387c7a73d0ad0f19cebaca151443560f42508559
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '01605812af7b7d53111bfdc0d4d095cb6f0df4975634db17700d7c15c6acc63ba82585e6c5a5d2d93c130d566f45bb62d9ff3709c27e0f7cf4ea0c20ba7c172f'
|
|
7
|
+
data.tar.gz: e4a54c74e032ee12d744f94c657416591c0f056a005da4b104c017294d73819596a28ec59c71597f8d0f2398da79a8b7784809d5e30cd5da9d53fc655101e2f4
|
data/lib/packetgen/capture.rb
CHANGED
|
@@ -27,6 +27,11 @@ module PacketGen
|
|
|
27
27
|
# @return [Array<String>]
|
|
28
28
|
attr_reader :raw_packets
|
|
29
29
|
|
|
30
|
+
# Get timestamps associated with {#packets} and {#raw_packets}
|
|
31
|
+
# @return [Array<Time>]
|
|
32
|
+
# @since 3.3.0
|
|
33
|
+
attr_reader :timestamps
|
|
34
|
+
|
|
30
35
|
# Get interface name
|
|
31
36
|
# @return [String]
|
|
32
37
|
attr_reader :iface
|
|
@@ -54,6 +59,7 @@ module PacketGen
|
|
|
54
59
|
|
|
55
60
|
@packets = []
|
|
56
61
|
@raw_packets = []
|
|
62
|
+
@timestamps = []
|
|
57
63
|
set_options iface, max, timeout, filter, promisc, parse, snaplen, monitor
|
|
58
64
|
end
|
|
59
65
|
|
|
@@ -61,16 +67,18 @@ module PacketGen
|
|
|
61
67
|
# @see {#initialize} for parameters
|
|
62
68
|
# @yieldparam [Packet,String] packet if a block is given, yield each
|
|
63
69
|
# captured packet (Packet or raw data String, depending on +:parse+ option)
|
|
70
|
+
# @yieldparam [Time] timestamp packet timestamp
|
|
64
71
|
# @since 3.0.0 arguments are kwargs and no more a hash
|
|
65
72
|
# @since 3.1.5 add monitor argument
|
|
73
|
+
# @since 3.3.0 add packet timestamp as second yield parameter
|
|
66
74
|
# @author Sylvain Daubert
|
|
67
75
|
# @author optix2000 - add monitor argument
|
|
68
76
|
def start(iface: nil, max: nil, timeout: nil, filter: nil, promisc: false, parse: true, snaplen: nil, monitor: nil, &block)
|
|
69
77
|
set_options iface, max, timeout, filter, promisc, parse, snaplen, monitor
|
|
70
78
|
|
|
71
79
|
@cap_thread = Thread.new do
|
|
72
|
-
PCAPRUBWrapper.capture(**capture_args) do |
|
|
73
|
-
add_packet(
|
|
80
|
+
PCAPRUBWrapper.capture(**capture_args) do |packet|
|
|
81
|
+
add_packet(packet, &block)
|
|
74
82
|
break if defined?(@max) && (raw_packets.size >= @max)
|
|
75
83
|
end
|
|
76
84
|
end
|
|
@@ -119,18 +127,21 @@ module PacketGen
|
|
|
119
127
|
PCAPRUBWrapper.filter_on(pcap: pcap, filter: filter)
|
|
120
128
|
end
|
|
121
129
|
|
|
122
|
-
def add_packet(
|
|
123
|
-
raw_packets << data
|
|
130
|
+
def add_packet(packet, &block)
|
|
131
|
+
raw_packets << packet.data
|
|
132
|
+
ts = Time.at(packet.time, packet.microsec.to_r, :usec)
|
|
133
|
+
timestamps << ts
|
|
134
|
+
|
|
124
135
|
if @parse
|
|
125
136
|
begin
|
|
126
|
-
packet = Packet.parse(data)
|
|
137
|
+
packet = Packet.parse(packet.data)
|
|
127
138
|
rescue ParseError
|
|
128
|
-
packet = UnknownPacket.new.parse(data)
|
|
139
|
+
packet = UnknownPacket.new.parse(packet.data)
|
|
129
140
|
end
|
|
130
141
|
packets << packet
|
|
131
|
-
block&.call(packet)
|
|
142
|
+
block&.call(packet, ts)
|
|
132
143
|
elsif block
|
|
133
|
-
yield data
|
|
144
|
+
yield data, ts
|
|
134
145
|
end
|
|
135
146
|
end
|
|
136
147
|
end
|
|
@@ -67,9 +67,9 @@ module PacketGen
|
|
|
67
67
|
@pointer = str[start, 2]
|
|
68
68
|
break
|
|
69
69
|
else
|
|
70
|
-
label = add_label_from(str[start
|
|
70
|
+
label = add_label_from(str[start..])
|
|
71
71
|
start += label.sz
|
|
72
|
-
break if label.
|
|
72
|
+
break if label.empty? || str[start..].empty?
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
# force resolution of compressed names
|
|
@@ -110,7 +110,7 @@ module PacketGen
|
|
|
110
110
|
ptr = index & mask
|
|
111
111
|
name = Name.new
|
|
112
112
|
name.dns = @dns
|
|
113
|
-
@pointer_name = name.read(self.dns.to_s[ptr
|
|
113
|
+
@pointer_name = name.read(self.dns.to_s[ptr..]).to_human
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
def record_from_hash(_hsh)
|
|
@@ -108,7 +108,7 @@ module PacketGen
|
|
|
108
108
|
name.dns = self[:name].dns
|
|
109
109
|
|
|
110
110
|
pref = Types::Int16.new.read(self[:rdata][0, 2])
|
|
111
|
-
exchange = name.read(self[:rdata][2
|
|
111
|
+
exchange = name.read(self[:rdata][2..]).to_human
|
|
112
112
|
|
|
113
113
|
'%u %s' % [pref.to_i, exchange]
|
|
114
114
|
end
|
|
@@ -118,7 +118,7 @@ module PacketGen
|
|
|
118
118
|
name = Name.new
|
|
119
119
|
name.dns = self[:name].dns
|
|
120
120
|
mname = name.read(self[:rdata]).dup
|
|
121
|
-
rname = name.read(self[:rdata][mname.sz
|
|
121
|
+
rname = name.read(self[:rdata][mname.sz..])
|
|
122
122
|
|
|
123
123
|
serial = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz, 4])
|
|
124
124
|
refresh = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz + 4, 4])
|
|
@@ -107,7 +107,7 @@ module PacketGen
|
|
|
107
107
|
|
|
108
108
|
def headers_and_payload_from_lines(lines)
|
|
109
109
|
if (data_index = lines.find_index(''))
|
|
110
|
-
data = lines[data_index + 1
|
|
110
|
+
data = lines[data_index + 1..].join("\n")
|
|
111
111
|
headers = lines[0..data_index - 1].join("\n")
|
|
112
112
|
else
|
|
113
113
|
headers = lines.join("\n")
|
|
@@ -126,7 +126,7 @@ module PacketGen
|
|
|
126
126
|
|
|
127
127
|
self[:version].read first_line[0]
|
|
128
128
|
self[:status_code].read first_line[1]
|
|
129
|
-
self[:status_mesg].read first_line[2
|
|
129
|
+
self[:status_mesg].read first_line[2..].join(' ')
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
def raise_on_bad_version_status
|
|
@@ -18,7 +18,7 @@ module PacketGen
|
|
|
18
18
|
# @return [self]
|
|
19
19
|
# array << '192.168.1.12'
|
|
20
20
|
def push(addr)
|
|
21
|
-
addr =
|
|
21
|
+
addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
|
|
22
22
|
super(addr)
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -77,7 +77,7 @@ module PacketGen
|
|
|
77
77
|
Option.constants.each do |cst|
|
|
78
78
|
next unless cst.to_s.end_with? '_TYPE'
|
|
79
79
|
|
|
80
|
-
optname = cst.to_s.sub(
|
|
80
|
+
optname = cst.to_s.sub('_TYPE', '')
|
|
81
81
|
@types[optname] = Option.const_get(cst)
|
|
82
82
|
end
|
|
83
83
|
@types
|
data/lib/packetgen/headerable.rb
CHANGED
|
@@ -46,7 +46,7 @@ module PacketGen
|
|
|
46
46
|
def method_name
|
|
47
47
|
return @method_name if defined? @method_name
|
|
48
48
|
|
|
49
|
-
@method_name = protocol_name.downcase.gsub(
|
|
49
|
+
@method_name = protocol_name.downcase.gsub('::', '_')
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# @abstract Should be redefined by subclasses. This method should check invariant
|
data/lib/packetgen/inspect.rb
CHANGED
|
@@ -36,7 +36,8 @@ module PacketGen
|
|
|
36
36
|
# @param [Integer] hexsize
|
|
37
37
|
# @return [String]
|
|
38
38
|
def self.int_dec_hex(value, hexsize)
|
|
39
|
-
"%-16s (0x%0#{hexsize}x)"
|
|
39
|
+
fmt = "%-16s (0x%0#{hexsize}x)"
|
|
40
|
+
fmt % [value.to_i, value.to_i]
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
# @param [String] str
|
|
@@ -44,7 +45,8 @@ module PacketGen
|
|
|
44
45
|
# @param [Integer] hexsize
|
|
45
46
|
# @return [String]
|
|
46
47
|
def self.enum_human_hex(str, int, hexsize)
|
|
47
|
-
"%-16s (0x%0#{hexsize}x)"
|
|
48
|
+
fmt = "%-16s (0x%0#{hexsize}x)"
|
|
49
|
+
fmt % [str, int]
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
# Simple formatter to inspect an attribute
|
|
@@ -90,7 +92,8 @@ module PacketGen
|
|
|
90
92
|
val = case attr
|
|
91
93
|
when RASN1::Types::Enumerated
|
|
92
94
|
hexsize = attr.value_size * 2
|
|
93
|
-
"%-16s (0x%0#{hexsize}x)"
|
|
95
|
+
fmt = "%-16s (0x%0#{hexsize}x)"
|
|
96
|
+
fmt % [attr.value, attr.to_i]
|
|
94
97
|
when RASN1::Types::Integer
|
|
95
98
|
int_dec_hex(attr.value, attr.value_size * 2)
|
|
96
99
|
when RASN1::Model
|
data/lib/packetgen/packet.rb
CHANGED
|
@@ -81,7 +81,9 @@ module PacketGen
|
|
|
81
81
|
# @see Capture#initialize
|
|
82
82
|
# @yieldparam [Packet,String] packet if a block is given, yield each
|
|
83
83
|
# captured packet (Packet or raw data String, depending on +:parse+ option)
|
|
84
|
+
# @yieldparam [Time] timestamp packet timestamp
|
|
84
85
|
# @return [Array<Packet>] captured packet
|
|
86
|
+
# @since 3.3.0 add packet timestamp as second yield parameter
|
|
85
87
|
def self.capture(**kwargs, &block)
|
|
86
88
|
capture = Capture.new(**kwargs)
|
|
87
89
|
if block
|
|
@@ -21,11 +21,11 @@ module PacketGen
|
|
|
21
21
|
}.freeze
|
|
22
22
|
|
|
23
23
|
# @private
|
|
24
|
-
BLOCK_TYPES = PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.
|
|
24
|
+
BLOCK_TYPES = PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.to_h do |c|
|
|
25
25
|
type_value = PcapNG.const_get(c).to_i
|
|
26
26
|
klass = PcapNG.const_get(c.to_s.delete_suffix('_TYPE'))
|
|
27
27
|
[type_value, klass]
|
|
28
|
-
end.
|
|
28
|
+
end.freeze
|
|
29
29
|
|
|
30
30
|
# Get file sections
|
|
31
31
|
# @return [Array]
|
|
@@ -44,7 +44,7 @@ module PacketGen
|
|
|
44
44
|
# @param [Boolean] promisc
|
|
45
45
|
# @param [String] filter BPF filter
|
|
46
46
|
# @param [Boolean] monitor
|
|
47
|
-
# @yieldparam [String] packet_data
|
|
47
|
+
# @yieldparam [String] packet_data packet data
|
|
48
48
|
# @return [void]
|
|
49
49
|
# @author Sylvain Daubert
|
|
50
50
|
# @author optix2000 - add support for setting monitor mode
|
|
@@ -52,7 +52,7 @@ module PacketGen
|
|
|
52
52
|
def self.capture(iface:, snaplen: DEFAULT_SNAPLEN, promisc: DEFAULT_PROMISC, filter: nil, monitor: nil, &block)
|
|
53
53
|
pcap = self.open_iface(iface: iface, snaplen: snaplen, promisc: promisc, monitor: monitor)
|
|
54
54
|
pcap.setfilter filter unless filter.nil?
|
|
55
|
-
pcap.
|
|
55
|
+
pcap.each_packet(&block)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
# Inject given data onto wire
|
data/lib/packetgen/proto.rb
CHANGED
|
@@ -19,7 +19,7 @@ module PacketGen
|
|
|
19
19
|
proto_constants = Socket.constants.grep(/IPPROTO_/)
|
|
20
20
|
@cache = {}
|
|
21
21
|
proto_constants.each do |const_sym|
|
|
22
|
-
name = const_sym.to_s[8
|
|
22
|
+
name = const_sym.to_s[8..].downcase
|
|
23
23
|
number = Socket.const_get(const_sym)
|
|
24
24
|
@cache[name] = number
|
|
25
25
|
end
|
|
@@ -322,12 +322,14 @@ module PacketGen
|
|
|
322
322
|
define << "def #{name}; self[:#{name}].to_i; end"
|
|
323
323
|
define << "def #{name}=(val) self[:#{name}].value = val; end"
|
|
324
324
|
else
|
|
325
|
+
# rubocop:disable Layout/LineContinuationLeadingSpace
|
|
325
326
|
define << "def #{name}\n" \
|
|
326
327
|
" to_and_from_human?(:#{name}) ? self[:#{name}].to_human : self[:#{name}]\n" \
|
|
327
328
|
'end'
|
|
328
329
|
define << "def #{name}=(val)\n" \
|
|
329
330
|
" to_and_from_human?(:#{name}) ? self[:#{name}].from_human(val) : self[:#{name}].read(val)\n" \
|
|
330
331
|
'end'
|
|
332
|
+
# rubocop:enable Layout/LineContinuationLeadingSpace
|
|
331
333
|
end
|
|
332
334
|
|
|
333
335
|
define.delete_at(1) if instance_methods.include? "#{name}=".to_sym
|
|
@@ -479,7 +481,7 @@ module PacketGen
|
|
|
479
481
|
fields.each do |field|
|
|
480
482
|
next unless present?(field)
|
|
481
483
|
|
|
482
|
-
obj = self[field].read str[start
|
|
484
|
+
obj = self[field].read str[start..]
|
|
483
485
|
start += self[field].sz
|
|
484
486
|
self[field] = obj unless obj == self[field]
|
|
485
487
|
end
|
|
@@ -523,7 +525,7 @@ module PacketGen
|
|
|
523
525
|
# Return object as a hash
|
|
524
526
|
# @return [Hash] keys: attributes, values: attribute values
|
|
525
527
|
def to_h
|
|
526
|
-
fields.
|
|
528
|
+
fields.to_h { |f| [f, @fields[f].to_human] }
|
|
527
529
|
end
|
|
528
530
|
|
|
529
531
|
# Get offset of given field in {Fields} structure.
|
|
@@ -112,9 +112,11 @@ module PacketGen
|
|
|
112
112
|
|
|
113
113
|
# Say if spoofing on given target is active or not
|
|
114
114
|
# @param [String] target_ip target IP address
|
|
115
|
-
# @return [Boolean
|
|
115
|
+
# @return [Boolean]
|
|
116
116
|
def active?(target_ip)
|
|
117
|
+
# rubocop:disable Style/ReturnNilInPredicateMethodDefinition
|
|
117
118
|
return unless @targets.key?(target_ip)
|
|
119
|
+
# rubocop:enable Style/ReturnNilInPredicateMethodDefinition
|
|
118
120
|
|
|
119
121
|
@targets[target_ip][:active]
|
|
120
122
|
end
|
data/lib/packetgen/utils.rb
CHANGED
|
@@ -19,11 +19,11 @@ module PacketGen
|
|
|
19
19
|
# @private
|
|
20
20
|
ARP_FILTER = 'arp src %<ipaddr>s and ether dst %<hwaddr>s'
|
|
21
21
|
# @private
|
|
22
|
-
MITM_FILTER = '((ip src %<target1>s and not ip dst %<local_ip>s) or' \
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
22
|
+
MITM_FILTER = '((ip src %<target1>s and not ip dst %<local_ip>s) or ' \
|
|
23
|
+
'(ip src %<target2>s and not ip dst %<local_ip>s) or ' \
|
|
24
|
+
'(ip dst %<target1>s and not ip src %<local_ip>s) or ' \
|
|
25
|
+
'(ip dst %<target2>s and not ip src %<local_ip>s)) ' \
|
|
26
|
+
'and ether dst %<local_mac>s'
|
|
27
27
|
|
|
28
28
|
# @private
|
|
29
29
|
ARP_PATH = '/usr/sbin/arp'
|
data/lib/packetgen/version.rb
CHANGED
data/lib/packetgen.rb
CHANGED
|
@@ -64,8 +64,10 @@ module PacketGen
|
|
|
64
64
|
# Shortcut for {Packet.capture}
|
|
65
65
|
# Same arguments as {Capture#initialize}
|
|
66
66
|
# @see Capture#initialize
|
|
67
|
-
# @yieldparam [Packet] packet
|
|
67
|
+
# @yieldparam [Packet,String] packet
|
|
68
|
+
# @yieldparam [Time] timestamp
|
|
68
69
|
# @return [Array<Packet>]
|
|
70
|
+
# @since 3.3.0 add packet timestamp as second yield parameter
|
|
69
71
|
def self.capture(**kwargs)
|
|
70
72
|
Packet.capture(**kwargs) { |packet| yield packet if block_given? }
|
|
71
73
|
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: 3.
|
|
4
|
+
version: 3.3.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:
|
|
11
|
+
date: 2023-08-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: interfacez
|
|
@@ -30,76 +30,28 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.
|
|
33
|
+
version: 0.13.0
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.
|
|
40
|
+
version: 0.13.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rasn1
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '0.
|
|
48
|
-
- - ">="
|
|
49
|
-
- !ruby/object:Gem::Version
|
|
50
|
-
version: 0.8.0
|
|
47
|
+
version: '0.12'
|
|
51
48
|
type: :runtime
|
|
52
49
|
prerelease: false
|
|
53
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
54
51
|
requirements:
|
|
55
52
|
- - "~>"
|
|
56
53
|
- !ruby/object:Gem::Version
|
|
57
|
-
version: '0.
|
|
58
|
-
- - ">="
|
|
59
|
-
- !ruby/object:Gem::Version
|
|
60
|
-
version: 0.8.0
|
|
61
|
-
- !ruby/object:Gem::Dependency
|
|
62
|
-
name: rake
|
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
|
64
|
-
requirements:
|
|
65
|
-
- - "~>"
|
|
66
|
-
- !ruby/object:Gem::Version
|
|
67
|
-
version: '13.0'
|
|
68
|
-
type: :development
|
|
69
|
-
prerelease: false
|
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - "~>"
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '13.0'
|
|
75
|
-
- !ruby/object:Gem::Dependency
|
|
76
|
-
name: rspec
|
|
77
|
-
requirement: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - "~>"
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: '3.7'
|
|
82
|
-
type: :development
|
|
83
|
-
prerelease: false
|
|
84
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
-
requirements:
|
|
86
|
-
- - "~>"
|
|
87
|
-
- !ruby/object:Gem::Version
|
|
88
|
-
version: '3.7'
|
|
89
|
-
- !ruby/object:Gem::Dependency
|
|
90
|
-
name: yard
|
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
|
92
|
-
requirements:
|
|
93
|
-
- - "~>"
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0.9'
|
|
96
|
-
type: :development
|
|
97
|
-
prerelease: false
|
|
98
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
99
|
-
requirements:
|
|
100
|
-
- - "~>"
|
|
101
|
-
- !ruby/object:Gem::Version
|
|
102
|
-
version: '0.9'
|
|
54
|
+
version: '0.12'
|
|
103
55
|
description: |
|
|
104
56
|
PacketGen is a network packet manipulation library. It allows reading, parsing
|
|
105
57
|
and sending network packets with fun.
|
|
@@ -260,7 +212,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
260
212
|
requirements:
|
|
261
213
|
- - ">="
|
|
262
214
|
- !ruby/object:Gem::Version
|
|
263
|
-
version: 2.
|
|
215
|
+
version: 2.6.0
|
|
264
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
265
217
|
requirements:
|
|
266
218
|
- - ">="
|