packetgen 3.0.2 → 3.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 +4 -4
- data/lib/packetgen/deprecation.rb +28 -2
- data/lib/packetgen/header/dhcp/option.rb +61 -129
- data/lib/packetgen/header/dhcp/options.rb +16 -8
- data/lib/packetgen/header/dns/option.rb +2 -8
- data/lib/packetgen/header/dot11/element.rb +4 -2
- data/lib/packetgen/header/http/request.rb +11 -8
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +5 -3
- data/lib/packetgen/packet.rb +1 -1
- data/lib/packetgen/types/abstract_tlv.rb +137 -0
- data/lib/packetgen/types/fields.rb +21 -16
- data/lib/packetgen/types/string.rb +2 -1
- data/lib/packetgen/types/tlv.rb +3 -0
- data/lib/packetgen/types.rb +2 -1
- data/lib/packetgen/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 877d57dd457d4cde03fca6e13c0042168c8630b08073533b7b7fb95da49632a0
|
4
|
+
data.tar.gz: 5c18abe50abcb423edf22571e88241cddb6095a0c626fb6018bfbafac49278b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09c0197e3f3d1bf72dffbaf97abc4007902ade04b94a6893d1a79e97944e6560eb16aad024726497a064b9fdc59fed5efd8e456cffcaa3f7bf64b7b0c7a2604c'
|
7
|
+
data.tar.gz: 575402b40e5be3c8bf6d68e8dfd01fa3b4a9d3e917fda6cefa17b0759f99193bb69a5e3b5734cfa839e149856d7d98ea88e13bb8fa273c9ac295a94a79e7502b
|
@@ -4,7 +4,19 @@ module PacketGen
|
|
4
4
|
# @author Sylvain Daubert
|
5
5
|
# @api private
|
6
6
|
module Deprecation
|
7
|
-
|
7
|
+
# Default remove version for deprecated classes/methods
|
8
|
+
# @since 3.1.0
|
9
|
+
REMOVE_VERSION = '4.0.0'
|
10
|
+
|
11
|
+
# Warn when using a deprecated method
|
12
|
+
# @param [Module] klass class/module of deprecated method
|
13
|
+
# @param [Symbol,String] deprecated_method
|
14
|
+
# @param [Symbol,String,nil] new_method method to use instead of deprecated one
|
15
|
+
# @param [Boolean] klass_method +deprecated_method+ is a class method (+true+)
|
16
|
+
# or a, instance one (+false+)
|
17
|
+
# @param [String] remove_version version from which +deprecated_method+ will
|
18
|
+
# no more exist.
|
19
|
+
def self.deprecated(klass, deprecated_method, new_method=nil, klass_method: false, remove_version: REMOVE_VERSION)
|
8
20
|
separator = klass_method ? '.' : '#'
|
9
21
|
base_name = klass.to_s + separator
|
10
22
|
complete_deprecated_method_name = base_name + deprecated_method.to_s
|
@@ -12,7 +24,21 @@ module PacketGen
|
|
12
24
|
|
13
25
|
file, line = caller(2).first.split(':')[0, 2]
|
14
26
|
message = +"#{file}:#{line}: #{complete_deprecated_method_name} is deprecated"
|
15
|
-
message << "in favor of #{complete_new_method_name}" unless new_method.nil?
|
27
|
+
message << " in favor of #{complete_new_method_name}" unless new_method.nil?
|
28
|
+
message << ". It will be remove in PacketGen #{remove_version}."
|
29
|
+
warn message
|
30
|
+
end
|
31
|
+
|
32
|
+
# Warn when using a deprecated method
|
33
|
+
# @param [Module] klass deprecated class/module
|
34
|
+
# @param [Module] new_klass class/module to use instead of +klass+
|
35
|
+
# @param [String] remove_version version from which +klass+ will
|
36
|
+
# no more exist.
|
37
|
+
# @since 3.1.0
|
38
|
+
def self.deprecated_class(klass, new_klass=nil, remove_version: REMOVE_VERSION)
|
39
|
+
file, line = caller(2..2).first.split(':')[0, 2]
|
40
|
+
message = +"#{file}:#{line}: #{klass} is deprecated"
|
41
|
+
message << " in favor od #{new_klass}" unless new_klass.nil?
|
16
42
|
message << ". It will be remove in PacketGen #{remove_version}."
|
17
43
|
warn message
|
18
44
|
end
|
@@ -8,54 +8,70 @@
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
10
|
class DHCP
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# as strings, and a hash passed to {Option#initialize}.
|
14
|
-
# @since 2.7.0
|
11
|
+
# Known DHCP options
|
12
|
+
# @since 3.1.0
|
15
13
|
DHCP_OPTIONS = {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
14
|
+
'pad' => 0,
|
15
|
+
'subnet_mask' => 1,
|
16
|
+
'time_zone' => 2,
|
17
|
+
'router' => 3,
|
18
|
+
'time_server' => 4,
|
19
|
+
'IEN_name_server' => 5,
|
20
|
+
'name_server' => 6,
|
21
|
+
'log_server' => 7,
|
22
|
+
'cookie_server' => 8,
|
23
|
+
'lpr_server' => 9,
|
24
|
+
'hostname' => 12,
|
25
|
+
'dump_path' => 14,
|
26
|
+
'domain' => 15,
|
27
|
+
'root_disk_path' => 17,
|
28
|
+
'default_ttl' => 23,
|
29
|
+
'pmtu_timeout' => 24,
|
30
|
+
'broadcast_address' => 28,
|
31
|
+
'NIS_domain' => 40,
|
32
|
+
'NIS_server' => 41,
|
33
|
+
'NTP_server' => 42,
|
34
|
+
'vendor_specific' => 43,
|
35
|
+
'NetBIOS_server' => 44,
|
36
|
+
'NetBIOS_dist_server' => 45,
|
37
|
+
'requested_addr' => 50,
|
38
|
+
'lease_time' => 51,
|
39
|
+
'message-type' => 53,
|
40
|
+
'server_id' => 54,
|
41
|
+
'param_req_list' => 55,
|
42
|
+
'error_message' => 56,
|
43
|
+
'max_dhcp_size' => 57,
|
44
|
+
'renewal_time' => 58,
|
45
|
+
'rebinding_time' => 59,
|
46
|
+
'vendor_class_id' => 60,
|
47
|
+
'client_id' => 61,
|
48
|
+
'NISplus_domain' => 64,
|
49
|
+
'NISplus_server' => 65,
|
50
|
+
'SMTP_server' => 69,
|
51
|
+
'POP3_server' => 70,
|
52
|
+
'NNTP_server' => 71,
|
53
|
+
'WWW_server' => 72,
|
54
|
+
'finger_server' => 73,
|
55
|
+
'IRC_server' => 74,
|
56
|
+
'end' => 255
|
57
57
|
}.freeze
|
58
58
|
|
59
|
+
# Option class with string value
|
60
|
+
Option = Types::AbstractTLV.create
|
61
|
+
Option.define_type_enum DHCP_OPTIONS
|
62
|
+
# Option class with IP address value
|
63
|
+
IPAddrOption = Types::AbstractTLV.create(value_class: IP::Addr)
|
64
|
+
IPAddrOption.define_type_enum DHCP_OPTIONS
|
65
|
+
# Option class with int8 value
|
66
|
+
Int8Option = Types::AbstractTLV.create(value_class: Types::Int8)
|
67
|
+
Int8Option.define_type_enum DHCP_OPTIONS
|
68
|
+
# Option class with int16 value
|
69
|
+
Int16Option = Types::AbstractTLV.create(value_class: Types::Int16)
|
70
|
+
Int16Option.define_type_enum DHCP_OPTIONS
|
71
|
+
# Option class with int32 value
|
72
|
+
Int32Option = Types::AbstractTLV.create(value_class: Types::Int32)
|
73
|
+
Int32Option.define_type_enum DHCP_OPTIONS
|
74
|
+
|
59
75
|
# Class to indicate DHCP options end
|
60
76
|
class End < Types::Int8
|
61
77
|
def initialize(value=255)
|
@@ -74,90 +90,6 @@ module PacketGen
|
|
74
90
|
super
|
75
91
|
end
|
76
92
|
end
|
77
|
-
|
78
|
-
# DHCP option
|
79
|
-
#
|
80
|
-
# A DHCP option is a {Types::TLV TLV}, so it has:
|
81
|
-
# * a {#type} ({Types::Int8}),
|
82
|
-
# * a {#length} ({Types::Int8}),
|
83
|
-
# * and a {#value}. Defalt type is {Types::String} but some options
|
84
|
-
# may use more suitable type (by example, a {IP::Addr} for +router+
|
85
|
-
# option).
|
86
|
-
# @author Sylvain Daubert
|
87
|
-
class Option < Types::TLV
|
88
|
-
# Option types
|
89
|
-
TYPES = Hash[DHCP_OPTIONS.to_a.map { |type, ary| [type, ary[0]] }]
|
90
|
-
|
91
|
-
# @param [Hash] options
|
92
|
-
# @option options [Integer] :type
|
93
|
-
# @option options [Integer] :length
|
94
|
-
# @option options [String] :value
|
95
|
-
def initialize(options={})
|
96
|
-
super
|
97
|
-
return unless DHCP_OPTIONS.key?(self.type)
|
98
|
-
|
99
|
-
h = DHCP_OPTIONS[self.type].last
|
100
|
-
return unless h.is_a? Hash
|
101
|
-
|
102
|
-
h.each do |k, v|
|
103
|
-
self.length = v if k == :length
|
104
|
-
if k == :v
|
105
|
-
self[:value] = v.new
|
106
|
-
self.value = options[:value] if options[:value]
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# @private
|
112
|
-
alias private_read read
|
113
|
-
|
114
|
-
# Populate object from a binary string
|
115
|
-
# @param [String] str
|
116
|
-
# @return [Option,End,Pad] may return another object than itself
|
117
|
-
def read(str)
|
118
|
-
read_type = str[0].unpack('C').first
|
119
|
-
if read_type.zero?
|
120
|
-
Pad.new.read(str)
|
121
|
-
elsif read_type == 255
|
122
|
-
End.new.read(str)
|
123
|
-
elsif DHCP_OPTIONS.key?(read_type)
|
124
|
-
Option.new(DHCP_OPTIONS[read_type][1] || {}).private_read(str)
|
125
|
-
else
|
126
|
-
super
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# @since 2.7.0
|
131
|
-
# @return [true]
|
132
|
-
def human_types?
|
133
|
-
true
|
134
|
-
end
|
135
|
-
|
136
|
-
# Get human-readable type
|
137
|
-
# @return [String]
|
138
|
-
def human_type
|
139
|
-
if DHCP_OPTIONS.key?(type)
|
140
|
-
DHCP_OPTIONS[type].first.dup
|
141
|
-
else
|
142
|
-
type.to_s
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# @return [String]
|
147
|
-
def to_human
|
148
|
-
s = human_type
|
149
|
-
if length > 0
|
150
|
-
s << if value.respond_to? :to_human
|
151
|
-
":#{value.to_human}"
|
152
|
-
elsif self[:value].is_a? Types::Int
|
153
|
-
":#{self.value.to_i}"
|
154
|
-
else
|
155
|
-
":#{value.inspect}"
|
156
|
-
end
|
157
|
-
end
|
158
|
-
s
|
159
|
-
end
|
160
|
-
end
|
161
93
|
end
|
162
94
|
end
|
163
95
|
end
|
@@ -26,15 +26,23 @@ module PacketGen
|
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
-
def
|
30
|
-
case
|
31
|
-
when
|
32
|
-
Pad
|
33
|
-
when
|
34
|
-
|
29
|
+
def real_type(obj)
|
30
|
+
case obj.type
|
31
|
+
when 0
|
32
|
+
Pad
|
33
|
+
when 1, 3, 4, 5, 6, 7, 8, 9, 28, 41, 42, 44, 45, 50, 54, 65, 69,
|
34
|
+
70, 71, 72, 73, 74
|
35
|
+
IPAddrOption
|
36
|
+
when 53
|
37
|
+
Int8Option
|
38
|
+
when 57
|
39
|
+
Int16Option
|
40
|
+
when 51, 58, 59
|
41
|
+
Int32Option
|
42
|
+
when 255
|
43
|
+
End
|
35
44
|
else
|
36
|
-
|
37
|
-
obj_klass.new(hsh)
|
45
|
+
Option
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
@@ -9,14 +9,8 @@ module PacketGen
|
|
9
9
|
module Header
|
10
10
|
class DNS
|
11
11
|
# DNS option
|
12
|
-
|
13
|
-
|
14
|
-
# Force {#type} and {#length} fields to be {Types::Int16}
|
15
|
-
# @see TLV#initialize
|
16
|
-
def initialize(options={})
|
17
|
-
super options.merge!(t: Types::Int16, l: Types::Int16)
|
18
|
-
end
|
19
|
-
end
|
12
|
+
Option = Types::AbstractTLV.create(type_class: Types::Int16,
|
13
|
+
length_class: Types::Int16)
|
20
14
|
end
|
21
15
|
end
|
22
16
|
end
|
@@ -12,8 +12,9 @@ module PacketGen
|
|
12
12
|
# IEEE 802.11 information element
|
13
13
|
#
|
14
14
|
# An {Element} is a piece of data contained in a Dot11 management frame.
|
15
|
-
|
16
|
-
|
15
|
+
Element = Types::AbstractTLV.create
|
16
|
+
|
17
|
+
class Element
|
17
18
|
# Known element types
|
18
19
|
TYPES = {
|
19
20
|
0 => 'SSID',
|
@@ -33,6 +34,7 @@ module PacketGen
|
|
33
34
|
221 => 'vendor'
|
34
35
|
}.freeze
|
35
36
|
end
|
37
|
+
Element.define_type_enum Element::TYPES.invert
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
@@ -9,7 +9,7 @@ module PacketGen
|
|
9
9
|
module Header
|
10
10
|
module HTTP
|
11
11
|
# An HTTP/1.1 Request packet consists of:
|
12
|
-
# * the http
|
12
|
+
# * the http verb ({Types::String}).
|
13
13
|
# * the path ({Types::String}).
|
14
14
|
# * the version ({Types::String}).
|
15
15
|
# * associated http headers ({HTTP::Headers}).
|
@@ -27,16 +27,19 @@ module PacketGen
|
|
27
27
|
#
|
28
28
|
# == HTTP Request attributes
|
29
29
|
# http_rqst.version = "HTTP/1.1"
|
30
|
-
# http_rqst.
|
30
|
+
# http_rqst.verb = "GET"
|
31
31
|
# http_rqst.path = "/meow.html"
|
32
32
|
# http_rqst.headers = "Host: tcpdump.org" # string or
|
33
33
|
# http_rqst.headers = { "Host": "tcpdump.org" } # even a hash
|
34
34
|
#
|
35
35
|
# @author Kent 'picat' Gruber
|
36
|
+
# @author Sylvain Daubert
|
37
|
+
# @since 3.1.0 Rename +#method+ into {#verb} to not mask +Object#method+.
|
36
38
|
class Request < Base
|
37
|
-
# @!attribute
|
39
|
+
# @!attribute verb
|
38
40
|
# @return [Types::String]
|
39
|
-
|
41
|
+
# @since 3.1.0
|
42
|
+
define_field :verb, Types::String
|
40
43
|
# @!attribute path
|
41
44
|
# @return [Types::String]
|
42
45
|
define_field :path, Types::String
|
@@ -52,7 +55,7 @@ module PacketGen
|
|
52
55
|
define_field :body, Types::String
|
53
56
|
|
54
57
|
# @param [Hash] options
|
55
|
-
# @option options [String] :
|
58
|
+
# @option options [String] :verb
|
56
59
|
# @option options [String] :path
|
57
60
|
# @option options [String] :version
|
58
61
|
# @option options [Hash] :headers
|
@@ -69,7 +72,7 @@ module PacketGen
|
|
69
72
|
str = vrb + str.split(vrb)[-1]
|
70
73
|
str = str.split("\n").map(&:chomp)
|
71
74
|
first_line = str.shift.split
|
72
|
-
self[:
|
75
|
+
self[:verb].read first_line[0]
|
73
76
|
self[:path].read first_line[1]
|
74
77
|
self[:version].read first_line[2]
|
75
78
|
# requests can sometimes have a payload
|
@@ -87,12 +90,12 @@ module PacketGen
|
|
87
90
|
# String representation of data.
|
88
91
|
# @return [String]
|
89
92
|
def to_s
|
90
|
-
raise FormatError, 'Missing #
|
93
|
+
raise FormatError, 'Missing #verb.' if self.verb.empty?
|
91
94
|
raise FormatError, 'Missing #path.' if self.path.empty?
|
92
95
|
raise FormatError, 'Missing #version.' if self.version.empty?
|
93
96
|
|
94
97
|
str = ''.dup # build 'dat string
|
95
|
-
str << self[:
|
98
|
+
str << self[:verb] << ' ' << self[:path] << ' ' << self[:version] << "\r\n" << self[:headers].to_s << self[:body]
|
96
99
|
end
|
97
100
|
end
|
98
101
|
end
|
@@ -8,9 +8,10 @@
|
|
8
8
|
module PacketGen
|
9
9
|
module Header
|
10
10
|
class IPv6
|
11
|
-
# Option for {HopByHop} IPv6 extension header
|
12
|
-
|
13
|
-
|
11
|
+
# Option for {HopByHop} IPv6 extension header.
|
12
|
+
Option = Types::AbstractTLV.create
|
13
|
+
|
14
|
+
class Option
|
14
15
|
# Known option types
|
15
16
|
TYPES = {
|
16
17
|
1 => 'padn',
|
@@ -27,6 +28,7 @@ module PacketGen
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
31
|
+
Option.define_type_enum Option::TYPES.invert
|
30
32
|
|
31
33
|
# Special option pad1, for {HopByHop} IPv6 extension header
|
32
34
|
# @author Sylvain Daubert
|
data/lib/packetgen/packet.rb
CHANGED
@@ -0,0 +1,137 @@
|
|
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 Types
|
11
|
+
# This class is an abstract class to define type-length-value data.
|
12
|
+
#
|
13
|
+
# This class supersede {TLV} class, which is not well defined on some corner
|
14
|
+
# cases.
|
15
|
+
#
|
16
|
+
# ===Usage
|
17
|
+
# To simply define a new TLV class, do:
|
18
|
+
# MyTLV = PacketGen::Types::AbstractTLV.create
|
19
|
+
# MyTLV.define_type_enum 'one' => 1, 'two' => 2
|
20
|
+
# This will define a new +MyTLV+ class, subclass of {Fields}. This class will
|
21
|
+
# define 3 fields:
|
22
|
+
# * +#type+, as a {Int8Enum} by default,
|
23
|
+
# * +#length+, as a {Int8} by default,
|
24
|
+
# * and +#value+, as a {String} by default.
|
25
|
+
# +.define_type_enum+ is, here, necessary to define enum hash to be used
|
26
|
+
# for +#type+ accessor, as this one is defined as an {Enum}.
|
27
|
+
#
|
28
|
+
# This class may then be used as older {TLV} class:
|
29
|
+
# tlv = MyTLV.new(type: 1, value: 'abcd') # automagically set #length from value
|
30
|
+
# tlv.type #=> 1
|
31
|
+
# tlv.human_type #=> 'one'
|
32
|
+
# tlv.length #=> 4
|
33
|
+
# tlv.value #=> "abcd"
|
34
|
+
#
|
35
|
+
# ===Advanced usage
|
36
|
+
# Each field's type may be change at generating TLV class:
|
37
|
+
# MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
|
38
|
+
# length_class: PacketGen::Types::Int16,
|
39
|
+
# value_class: PacketGen::Header::IP::Addr)
|
40
|
+
# tlv = MyTLV.new(type: 1, value: '1.2.3.4')
|
41
|
+
# tlv.type #=> 1
|
42
|
+
# tlv.length #=> 4
|
43
|
+
# tlv.value #=> 42
|
44
|
+
# tlv.to_s #=> "\x00\x01\x00\x04\x01\x02\x03\x04"
|
45
|
+
# @author Sylvain Daubert
|
46
|
+
# @since 3.1.0
|
47
|
+
class AbstractTLV < Types::Fields
|
48
|
+
# Generate a TLV class
|
49
|
+
# @param [Class] type_class Class to use for +type+
|
50
|
+
# @param [Class] length_class Class to use for +length+
|
51
|
+
# @param [Class] value_class Class to use for +value+
|
52
|
+
# @return [Class]
|
53
|
+
def self.create(type_class: Int8Enum, length_class: Int8, value_class: String)
|
54
|
+
raise Error, '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV' unless self.equal? AbstractTLV
|
55
|
+
|
56
|
+
klass = Class.new(self)
|
57
|
+
|
58
|
+
if type_class < Enum
|
59
|
+
klass.define_field :type, type_class, enum: {}
|
60
|
+
else
|
61
|
+
klass.define_field :type, type_class
|
62
|
+
end
|
63
|
+
klass.define_field :length, length_class
|
64
|
+
klass.define_field :value, value_class
|
65
|
+
|
66
|
+
klass
|
67
|
+
end
|
68
|
+
# @!attribute type
|
69
|
+
# @abstract Type attribute for real TLV class
|
70
|
+
# @return [Integer]
|
71
|
+
# @!attribute length
|
72
|
+
# @abstract Length attribute for real TLV class
|
73
|
+
# @return [Integer]
|
74
|
+
# @!attribute value
|
75
|
+
# @abstract Value attribute for real TLV class
|
76
|
+
# @return [Object]
|
77
|
+
|
78
|
+
# @abstract Should only be called on real TLV classes, created by {.create}.
|
79
|
+
# Set enum hash for {#type} field.
|
80
|
+
# @param [Hash] hsh enum hash
|
81
|
+
# @return [void]
|
82
|
+
def self.define_type_enum(hsh)
|
83
|
+
field_defs[:type][:enum].clear
|
84
|
+
field_defs[:type][:enum].merge!(hsh)
|
85
|
+
end
|
86
|
+
|
87
|
+
# @abstract Should only be called on real TLV classes, created by {.create}.
|
88
|
+
# @param [Hash] options
|
89
|
+
# @option options [Integer] :type
|
90
|
+
# @option options [Integer] :length
|
91
|
+
# @option options [Object] :value
|
92
|
+
def initialize(options={})
|
93
|
+
super
|
94
|
+
# used #value= defined below, which set length if needed
|
95
|
+
self.value = options[:value] if options[:value]
|
96
|
+
end
|
97
|
+
|
98
|
+
# @abstract Should only be called on real TLV class instances.
|
99
|
+
# Populate object from a binary string
|
100
|
+
# @param [String] str
|
101
|
+
# @return [Fields] self
|
102
|
+
def read(str)
|
103
|
+
idx = 0
|
104
|
+
self[:type].read str[idx, self[:type].sz]
|
105
|
+
idx += self[:type].sz
|
106
|
+
self[:length].read str[idx, self[:length].sz]
|
107
|
+
idx += self[:length].sz
|
108
|
+
self[:value].read str[idx, self.length]
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
# @abstract Should only be called on real TLV class instances.
|
113
|
+
# Set +value+. May set +length+ if value is a {Types::String}.
|
114
|
+
# @param [::String,Integer] val
|
115
|
+
# @return [::String,Integer]
|
116
|
+
def value=(val)
|
117
|
+
self[:value].from_human val
|
118
|
+
self.length = self[:value].sz
|
119
|
+
val
|
120
|
+
end
|
121
|
+
|
122
|
+
# @abstract Should only be called on real TLV class instances.
|
123
|
+
# Get human-readable type
|
124
|
+
# @return [String]
|
125
|
+
def human_type
|
126
|
+
self[:type].to_human.to_s
|
127
|
+
end
|
128
|
+
|
129
|
+
# @abstract Should only be called on real TLV class instances.
|
130
|
+
# @return [String]
|
131
|
+
def to_human
|
132
|
+
my_value = self[:value].is_a?(String) ? value.inspect : value.to_human
|
133
|
+
"type:%s,length:%u,value:#{my_value}" % [human_type, length]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -115,6 +115,11 @@ module PacketGen
|
|
115
115
|
@bit_fields = {}
|
116
116
|
|
117
117
|
class <<self
|
118
|
+
# Get field definitions for this class.
|
119
|
+
# @return [Hash]
|
120
|
+
# @since 3.1.0
|
121
|
+
attr_reader :field_defs
|
122
|
+
|
118
123
|
# On inheritage, create +@field_defs+ class variable
|
119
124
|
# @param [Class] klass
|
120
125
|
# @return [void]
|
@@ -188,15 +193,15 @@ module PacketGen
|
|
188
193
|
"end"
|
189
194
|
end
|
190
195
|
|
191
|
-
define.
|
192
|
-
define.
|
196
|
+
define.delete_at(1) if instance_methods.include? "#{name}=".to_sym
|
197
|
+
define.delete_at(0) if instance_methods.include? name
|
193
198
|
class_eval define.join("\n")
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
199
|
+
field_defs[name] = FieldDef.new(type,
|
200
|
+
options.delete(:default),
|
201
|
+
options.delete(:builder),
|
202
|
+
options.delete(:optional),
|
203
|
+
options.delete(:enum),
|
204
|
+
options)
|
200
205
|
fields << name
|
201
206
|
end
|
202
207
|
|
@@ -257,13 +262,13 @@ module PacketGen
|
|
257
262
|
# @raise [ArgumentError] unknown +field+
|
258
263
|
# @since 2.8.4
|
259
264
|
def update_field(field, options)
|
260
|
-
raise ArgumentError, "unkown #{field} field for #{self}" unless
|
265
|
+
raise ArgumentError, "unkown #{field} field for #{self}" unless field_defs.key?(field)
|
261
266
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
+
field_defs[field].default = options.delete(:default) if options.key?(:default)
|
268
|
+
field_defs[field].builder = options.delete(:builder) if options.key?(:builder)
|
269
|
+
field_defs[field].optional = options.delete(:optional) if options.key?(:optional)
|
270
|
+
field_defs[field].enum = options.delete(:enum) if options.key?(:enum)
|
271
|
+
field_defs[field].options.merge!(options)
|
267
272
|
end
|
268
273
|
|
269
274
|
# Define a bitfield on given attribute
|
@@ -286,7 +291,7 @@ module PacketGen
|
|
286
291
|
# by bitfield size. If no size is given, 1 bit is assumed.
|
287
292
|
# @return [void]
|
288
293
|
def define_bit_fields_on(attr, *args)
|
289
|
-
attr_def =
|
294
|
+
attr_def = field_defs[attr]
|
290
295
|
raise ArgumentError, "unknown #{attr} field" if attr_def.nil?
|
291
296
|
|
292
297
|
type = attr_def.type
|
@@ -366,7 +371,7 @@ module PacketGen
|
|
366
371
|
@fields = {}
|
367
372
|
@optional_fields = {}
|
368
373
|
|
369
|
-
field_defs = self.class.
|
374
|
+
field_defs = self.class.field_defs
|
370
375
|
self.class.fields.each do |field|
|
371
376
|
type = field_defs[field].type
|
372
377
|
default = field_defs[field].default
|
@@ -8,7 +8,8 @@
|
|
8
8
|
|
9
9
|
module PacketGen
|
10
10
|
module Types
|
11
|
-
# This class is just like regular String. It only adds {#read}
|
11
|
+
# This class is just like regular String. It only adds {#read}, {#sz},
|
12
|
+
# #{to_human} and {#from_human} methods
|
12
13
|
# to be compatible with others {Types}.
|
13
14
|
# @author Sylvain Daubert
|
14
15
|
class String < ::String
|
data/lib/packetgen/types/tlv.rb
CHANGED
@@ -28,6 +28,8 @@ module PacketGen
|
|
28
28
|
# * print human readable type using {#human_type},
|
29
29
|
# * set type as String with {#type=}.
|
30
30
|
# @author Sylvain Daubert
|
31
|
+
# @deprecated Use {AbstractTLV} instead.
|
32
|
+
# @since 3.1.0 deprecated
|
31
33
|
class TLV < Fields
|
32
34
|
# @!attribute type
|
33
35
|
# @return [Integer]
|
@@ -50,6 +52,7 @@ module PacketGen
|
|
50
52
|
# @option options [Class] :v {String} subclass for +:value+ attribute.
|
51
53
|
# Default: {Types::String}.
|
52
54
|
def initialize(options={})
|
55
|
+
Deprecation.deprecated_class(self.class, AbstractTLV)
|
53
56
|
super
|
54
57
|
self[:type] = options[:t].new(self.type) if options[:t]
|
55
58
|
self[:length] = options[:l].new(self.length) if options[:l]
|
data/lib/packetgen/types.rb
CHANGED
@@ -17,5 +17,6 @@ require_relative 'types/int_string'
|
|
17
17
|
require_relative 'types/cstring'
|
18
18
|
require_relative 'types/fields'
|
19
19
|
require_relative 'types/array'
|
20
|
-
require_relative 'types/tlv'
|
21
20
|
require_relative 'types/oui'
|
21
|
+
require_relative 'types/abstract_tlv'
|
22
|
+
require_relative 'types/tlv'
|
data/lib/packetgen/version.rb
CHANGED
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.0
|
4
|
+
version: 3.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: 2018-11-
|
11
|
+
date: 2018-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: interfacez
|
@@ -247,6 +247,7 @@ files:
|
|
247
247
|
- lib/packetgen/pcapng/unknown_block.rb
|
248
248
|
- lib/packetgen/proto.rb
|
249
249
|
- lib/packetgen/types.rb
|
250
|
+
- lib/packetgen/types/abstract_tlv.rb
|
250
251
|
- lib/packetgen/types/array.rb
|
251
252
|
- lib/packetgen/types/cstring.rb
|
252
253
|
- lib/packetgen/types/enum.rb
|