packetgen 2.8.7 → 3.0.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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -1
  3. data/README.md +5 -4
  4. data/lib/packetgen.rb +6 -12
  5. data/lib/packetgen/capture.rb +43 -39
  6. data/lib/packetgen/config.rb +0 -1
  7. data/lib/packetgen/deprecation.rb +1 -1
  8. data/lib/packetgen/header.rb +9 -9
  9. data/lib/packetgen/header/asn1_base.rb +10 -10
  10. data/lib/packetgen/header/base.rb +42 -101
  11. data/lib/packetgen/header/dhcp/option.rb +5 -11
  12. data/lib/packetgen/header/dhcpv6/duid.rb +2 -0
  13. data/lib/packetgen/header/dhcpv6/option.rb +2 -19
  14. data/lib/packetgen/header/dhcpv6/options.rb +7 -0
  15. data/lib/packetgen/header/dns.rb +5 -23
  16. data/lib/packetgen/header/dns/name.rb +1 -0
  17. data/lib/packetgen/header/dns/qdsection.rb +1 -0
  18. data/lib/packetgen/header/dns/question.rb +3 -7
  19. data/lib/packetgen/header/dns/rr.rb +3 -0
  20. data/lib/packetgen/header/dns/rrsection.rb +1 -0
  21. data/lib/packetgen/header/dot11.rb +1 -17
  22. data/lib/packetgen/header/dot1x.rb +1 -0
  23. data/lib/packetgen/header/eap.rb +4 -7
  24. data/lib/packetgen/header/eth.rb +2 -0
  25. data/lib/packetgen/header/http/headers.rb +3 -0
  26. data/lib/packetgen/header/http/request.rb +5 -4
  27. data/lib/packetgen/header/http/response.rb +5 -4
  28. data/lib/packetgen/header/icmp.rb +6 -0
  29. data/lib/packetgen/header/icmpv6.rb +6 -0
  30. data/lib/packetgen/header/igmpv3/mq.rb +2 -0
  31. data/lib/packetgen/header/ip.rb +32 -30
  32. data/lib/packetgen/header/ip/addr.rb +1 -0
  33. data/lib/packetgen/header/ip/option.rb +23 -20
  34. data/lib/packetgen/header/ip/options.rb +11 -24
  35. data/lib/packetgen/header/ipv6.rb +45 -34
  36. data/lib/packetgen/header/ipv6/addr.rb +2 -0
  37. data/lib/packetgen/header/ipv6/hop_by_hop.rb +7 -31
  38. data/lib/packetgen/header/mdns.rb +1 -0
  39. data/lib/packetgen/header/mldv2/mlq.rb +2 -0
  40. data/lib/packetgen/header/ospfv2/lsa.rb +15 -25
  41. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +1 -1
  42. data/lib/packetgen/header/ospfv3/lsa.rb +8 -25
  43. data/lib/packetgen/header/snmp.rb +2 -0
  44. data/lib/packetgen/header/tcp.rb +23 -2
  45. data/lib/packetgen/header/tcp/option.rb +51 -52
  46. data/lib/packetgen/header/tcp/options.rb +17 -52
  47. data/lib/packetgen/header/tftp.rb +3 -0
  48. data/lib/packetgen/header/udp.rb +8 -0
  49. data/lib/packetgen/packet.rb +119 -102
  50. data/lib/packetgen/pcapng/block.rb +4 -10
  51. data/lib/packetgen/pcapng/epb.rb +4 -4
  52. data/lib/packetgen/pcapng/file.rb +7 -3
  53. data/lib/packetgen/pcapng/idb.rb +2 -2
  54. data/lib/packetgen/pcapng/shb.rb +3 -3
  55. data/lib/packetgen/pcapng/spb.rb +1 -8
  56. data/lib/packetgen/pcapng/unknown_block.rb +0 -7
  57. data/lib/packetgen/types.rb +1 -0
  58. data/lib/packetgen/types/array.rb +73 -71
  59. data/lib/packetgen/types/cstring.rb +1 -1
  60. data/lib/packetgen/types/enum.rb +3 -3
  61. data/lib/packetgen/types/fields.rb +66 -106
  62. data/lib/packetgen/types/int.rb +9 -5
  63. data/lib/packetgen/types/length_from.rb +45 -0
  64. data/lib/packetgen/types/oui.rb +2 -0
  65. data/lib/packetgen/types/string.rb +10 -16
  66. data/lib/packetgen/types/tlv.rb +7 -15
  67. data/lib/packetgen/utils.rb +8 -8
  68. data/lib/packetgen/utils/arp_spoofer.rb +1 -2
  69. data/lib/packetgen/version.rb +1 -1
  70. metadata +3 -21
  71. data/lib/packetgen/header/crypto.rb +0 -62
  72. data/lib/packetgen/header/esp.rb +0 -413
  73. data/lib/packetgen/header/ike.rb +0 -243
  74. data/lib/packetgen/header/ike/auth.rb +0 -165
  75. data/lib/packetgen/header/ike/cert.rb +0 -76
  76. data/lib/packetgen/header/ike/certreq.rb +0 -66
  77. data/lib/packetgen/header/ike/id.rb +0 -99
  78. data/lib/packetgen/header/ike/ke.rb +0 -79
  79. data/lib/packetgen/header/ike/nonce.rb +0 -40
  80. data/lib/packetgen/header/ike/notify.rb +0 -176
  81. data/lib/packetgen/header/ike/payload.rb +0 -315
  82. data/lib/packetgen/header/ike/sa.rb +0 -561
  83. data/lib/packetgen/header/ike/sk.rb +0 -261
  84. data/lib/packetgen/header/ike/ts.rb +0 -270
  85. data/lib/packetgen/header/ike/vendor_id.rb +0 -39
  86. data/lib/packetgen/header/netbios.rb +0 -20
  87. data/lib/packetgen/header/netbios/datagram.rb +0 -105
  88. data/lib/packetgen/header/netbios/name.rb +0 -67
  89. data/lib/packetgen/header/netbios/session.rb +0 -64
@@ -1,261 +0,0 @@
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
- class IKE
12
- # This class handles encrypted payloads, denoted SK.
13
- #
14
- # The encrypted payload contains other payloads in encrypted form.
15
- # The Encrypted payload consists of the IKE generic payload header followed
16
- # by individual fields as follows:
17
- # 1 2 3
18
- # 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
19
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20
- # | Next Payload |C| RESERVED | Payload Length |
21
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22
- # | Initialization Vector |
23
- # | (length is block size for encryption algorithm) |
24
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
- # ~ Encrypted IKE Payloads ~
26
- # + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
- # | | Padding (0-255 octets) |
28
- # +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
29
- # | | Pad Length |
30
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31
- # ~ Integrity Checksum Data ~
32
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33
- # Encrypted payloads are set in {#content} field, as a {Types::String}.
34
- # All others fields are only set when decrypting a previously read SK
35
- # payload. They also may be set manually to encrypt IKE payloads.
36
- #
37
- # == Read and decrypt a SK payload
38
- # # Read a IKE packet
39
- # pkt = PacketGen.read(str)
40
- # # decrypt SK payload
41
- # cipher = OpenSSL::Cipher.new('aes-128-ctr')
42
- # cipher.decrypt
43
- # cipher_key = aes_key
44
- # hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
45
- # pkt.ike_sk.decrypt! cipher, intmode: hmac, icv_length: 16 # => true if authentication is verified
46
- # pkt.ike_sk.body # => kind of PacketGen::Header::IKE::Payload
47
- #
48
- # == Set and encrypt a SK payload
49
- # # Create a IKE packet
50
- # pkt = PacketGen.gen('IP').add('IP').add('UDP').add('IKE', init_spi: 0x123456789, resp_spi: 0x987654321, type: 'IKE_AUTH', message_id: 1)
51
- # # Add SK payload
52
- # pkt.add('IKE::SK', icv_length: 16)
53
- # # Add others unencrypted payloads
54
- # pkt.add('IKE::IDi').add('IKE::Auth').add('IKE::SA').add('IKE::TSi').add('IKE::TSr')
55
- # # encrypt SK payload
56
- # cipher = OpenSSL::Cipher.new('aes-128-ctr')
57
- # cipher.encrypt
58
- # cipher_key = aes_key
59
- # hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
60
- # pkt.ike_sk.encrypt! cipher, iv, salt: salt, intmode: hmac
61
- # pkt.ike_sk.body # => String
62
- # pkt.calc_length
63
- #
64
- # @author Sylvain Daubert
65
- class SK < Payload
66
- include Crypto
67
-
68
- # Payload type number
69
- PAYLOAD_TYPE = 46
70
-
71
- # ICV (Integrity Check Value) length
72
- # @return [Integer]
73
- attr_accessor :icv_length
74
-
75
- # @param [Hash] options
76
- # @option options [Integer] :icv_length ICV length
77
- def initialize(options={})
78
- @icv_length = options[:icv_length] || 0
79
- super
80
- end
81
-
82
- # Decrypt in-place SK payload.
83
- # @param [OpenSSL::Cipher] cipher keyed cipher
84
- # This cipher is confidentiality-only one, or AEAD one. To use a second
85
- # cipher to add integrity, use +:intmode+ option.
86
- # @param [Hash] options
87
- # @option options [Boolean] :parse parse deciphered payload to retrieve
88
- # headers (default: +true+)
89
- # @option options [Fixnum] :icv_length ICV length for captured packets,
90
- # or read from PCapNG files
91
- # @option options [String] :salt salt value for CTR and GCM modes
92
- # @option options [OpenSSL::HMAC] :intmode integrity mode to use with a
93
- # confidentiality-only cipher. Only HMAC are supported.
94
- # @return [Boolean] +true+ if SK payload is authenticated
95
- def decrypt!(cipher, options={})
96
- opt = { salt: '', parse: true }.merge!(options)
97
-
98
- set_crypto cipher, opt[:intmode]
99
-
100
- case confidentiality_mode
101
- when 'gcm'
102
- iv = self.content.slice!(0, 8)
103
- real_iv = force_binary(opt[:salt]) + iv
104
- when 'cbc'
105
- cipher.padding = 0
106
- real_iv = iv = self.content.slice!(0, 16)
107
- when 'ctr'
108
- iv = self.content.slice!(0, 8)
109
- real_iv = force_binary(opt[:salt]) + iv + [1].pack('N')
110
- else
111
- real_iv = iv = self.content.slice!(0, 16)
112
- end
113
- cipher.iv = real_iv
114
-
115
- if authenticated?
116
- if @icv_length.zero?
117
- @icv_length = opt[:icv_length].to_i if opt[:icv_length]
118
- raise ParseError, 'unknown ICV size' if @icv_length.zero?
119
- end
120
- icv = self.content.slice!(-@icv_length, @icv_length)
121
- end
122
-
123
- authenticate_if_needed iv, icv
124
- private_decrypt opt
125
- end
126
-
127
- # Encrypt in-place SK payload.
128
- # @param [OpenSSL::Cipher] cipher keyed cipher
129
- # This cipher is confidentiality-only one, or AEAD one. To use a second
130
- # cipher to add integrity, use +:intmode+ option.
131
- # @param [String] iv IV to encipher SK payload content
132
- # * CTR and GCM modes: +iv+ is 8-bytes long.
133
- # @param [Hash] options
134
- # @option options [Fixnum] :icv_length ICV length for captured packets,
135
- # or read from PCapNG files
136
- # @option options [String] :salt salt value for CTR and GCM modes
137
- # @option options [Fixnum] :pad_length set a padding length
138
- # @option options [String] :padding set a padding. No check with
139
- # +:pad_length+ is made. If +:pad_length+ is not set, +:padding+
140
- # length is shortened to correct padding length
141
- # @option options [OpenSSL::HMAC] :intmode integrity mode to use with a
142
- # confidentiality-only cipher. Only HMAC are supported.
143
- # @return [self]
144
- def encrypt!(cipher, iv, options={})
145
- opt = { salt: '' }.merge!(options)
146
-
147
- set_crypto cipher, opt[:intmode]
148
-
149
- real_iv = force_binary(opt[:salt]) + force_binary(iv)
150
- real_iv += [1].pack('N') if confidentiality_mode == 'ctr'
151
- cipher.iv = real_iv
152
-
153
- authenticate_if_needed iv
154
-
155
- if opt[:pad_length]
156
- pad_length = opt[:pad_length]
157
- padding = force_binary(opt[:padding] || ([0] * pad_length).pack('C*'))
158
- else
159
- pad_length = cipher.block_size
160
- pad_length = 16 if cipher.block_size == 1 # Some AES mode returns 1...
161
- pad_length -= (self.body.sz + iv.size + 1) % cipher.block_size
162
- pad_length = 0 if pad_length == 16
163
- padding = force_binary(opt[:padding] || ([0] * pad_length).pack('C*'))
164
- padding = padding[0, pad_length]
165
- end
166
- msg = self.body.to_s + padding + Types::Int8.new(pad_length).to_s
167
- encrypted_msg = encipher(msg)
168
- cipher.final # message is already padded. No need for mode padding
169
-
170
- if authenticated?
171
- @icv_length = opt[:icv_length] if opt[:icv_length]
172
- encrypted_msg << if @conf.authenticated?
173
- @conf.auth_tag[0, @icv_length]
174
- else
175
- @intg.digest[0, @icv_length]
176
- end
177
- end
178
- self[:content].read(iv + encrypted_msg)
179
-
180
- # Remove plain payloads
181
- self[:body] = Types::String.new
182
-
183
- # Remove enciphered payloads from packet
184
- id = header_id(self)
185
- if id < packet.headers.size - 1
186
- (packet.headers.size - 1).downto(id + 1) do |index|
187
- packet.headers.delete_at index
188
- end
189
- end
190
-
191
- self.calc_length
192
- self
193
- end
194
-
195
- private
196
-
197
- def authenticate_if_needed(iv, icv=nil)
198
- if @conf.authenticated?
199
- @conf.auth_tag = icv if icv
200
- @conf.auth_data = get_ad
201
- elsif @intg
202
- @intg.reset
203
- @intg.update get_ad
204
- @intg.update iv
205
- @icv = icv
206
- else
207
- @icv = nil
208
- end
209
- end
210
-
211
- # From RFC 7206, §5.1: The associated data MUST consist of the partial
212
- # contents of the IKEv2 message, starting from the first octet of the
213
- # Fixed IKE Header through the last octet of the Payload Header of the
214
- # Encrypted Payload (i.e., the fourth octet of the Encrypted Payload).
215
- def get_ad
216
- str = packet.ike.to_s[0, IKE.new.sz]
217
- current_payload = packet.ike.body
218
- until current_payload.is_a? SK
219
- str << current_payload.to_s[0, current_payload.length]
220
- current_payload = current_payload.body
221
- end
222
- str << self.to_s[0, SK.new.sz]
223
- end
224
-
225
- def private_decrypt(options)
226
- # decrypt
227
- plain_msg = decipher(content.to_s)
228
- # Remove cipher text
229
- self.content.read ''
230
-
231
- # check authentication tag
232
- if authenticated?
233
- return false unless authenticate!
234
- end
235
-
236
- # remove padding
237
- pad_len = Types::Int8.new.read(plain_msg[-1]).to_i
238
- payloads = plain_msg[0, plain_msg.size - 1 - pad_len]
239
-
240
- # parse IKE payloads
241
- if options[:parse]
242
- klass = IKE.constants.select do |c|
243
- cst = IKE.const_get(c)
244
- cst.is_a?(Class) && (cst < Payload) && (cst::PAYLOAD_TYPE == self.next)
245
- end
246
- klass = klass.nil? ? Payload : IKE.const_get(klass.first)
247
- firsth = klass.protocol_name
248
- pkt = Packet.parse(payloads, first_header: firsth)
249
- packet.encapsulate(pkt, parsing: true) unless pkt.nil?
250
- else
251
- self[:body].read payloads
252
- end
253
-
254
- true
255
- end
256
- end
257
- end
258
-
259
- self.add_class IKE::SK
260
- end
261
- end
@@ -1,270 +0,0 @@
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
- class IKE
12
- # TrafficSelector substructure, as defined in RFC 7296, §3.13.1:
13
- # 1 2 3
14
- # 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
15
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16
- # | TS Type |IP Protocol ID*| Selector Length |
17
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18
- # | Start Port* | End Port* |
19
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20
- # | |
21
- # ~ Starting Address* ~
22
- # | |
23
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24
- # | |
25
- # ~ Ending Address* ~
26
- # | |
27
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28
- # @author Sylvain Daubert
29
- class TrafficSelector < Types::Fields
30
- # IPv4 traffic selector type
31
- TS_IPV4_ADDR_RANGE = 7
32
- # IPv6 traffic selector type
33
- TS_IPV6_ADDR_RANGE = 8
34
-
35
- # @!attribute [r] type
36
- # 8-bit TS type
37
- # @return [Integer]
38
- define_field :type, Types::Int8, default: 7
39
- # @!attribute [r] protocol
40
- # 8-bit protocol ID
41
- # @return [Integer]
42
- define_field :protocol, Types::Int8, default: 0
43
- # @!attribute length
44
- # 16-bit Selector Length
45
- # @return [Integer]
46
- define_field :length, Types::Int16
47
- # @!attribute start_port
48
- # 16-bit Start port
49
- # @return [Integer]
50
- define_field :start_port, Types::Int16, default: 0
51
- # @!attribute end_port
52
- # 16-bit End port
53
- # @return [Integer]
54
- define_field :end_port, Types::Int16, default: 65_535
55
- # @!attribute start_addr
56
- # starting address
57
- # @return [IP::Addr, IPv6::Addr]
58
- define_field :start_addr, IP::Addr
59
- # @!attribute end_addr
60
- # starting address
61
- # @return [IP::Addr, IPv6::Addr]
62
- define_field :end_addr, IP::Addr
63
-
64
- # @param [Hash] options
65
- # @option [Range] :ports port range
66
- # @option [Integer] :start_port start port
67
- # @option [Integer] :end_port end port
68
- def initialize(options={})
69
- super
70
- select_addr options
71
- self[:start_addr].from_human(options[:start_addr]) if options[:start_addr]
72
- self[:end_addr].from_human(options[:end_addr]) if options[:end_addr]
73
- self[:length].value = sz unless options[:length]
74
- self.type = options[:type] if options[:type]
75
- self.protocol = options[:protocol] if options[:protocol]
76
-
77
- return unless options[:ports]
78
- self.start_port = options[:ports].begin
79
- self.end_port = options[:ports].end
80
- end
81
-
82
- # Populate object from a string
83
- # @param [String] str
84
- # @return [self]
85
- def read(str)
86
- super
87
- select_addr_from_type type
88
- super
89
- end
90
-
91
- # Set type
92
- # @param [Integer,String] value
93
- # @return [Integer]
94
- def type=(value)
95
- type = case value
96
- when Integer
97
- value
98
- else
99
- c = self.class.constants.grep(/TS_#{value.upcase}/).first
100
- c ? self.class.const_get(c) : nil
101
- end
102
- raise ArgumentError, "unknown type #{value.inspect}" unless type
103
- select_addr_from_type type
104
- self[:type].value = type
105
- end
106
-
107
- # Set protocol
108
- # @param [Integer,String] value
109
- # @return [Integer]
110
- def protocol=(value)
111
- protocol = case value
112
- when Integer
113
- value
114
- else
115
- Proto.getprotobyname(value)
116
- end
117
- raise ArgumentError, "unknown protocol #{value.inspect}" unless protocol
118
- self[:protocol].value = protocol
119
- end
120
-
121
- # Get a human readable string
122
- # @return [String]
123
- def to_human
124
- h = start_addr << '-' << end_addr
125
- unless human_protocol.empty?
126
- h << "/#{human_protocol}"
127
- h << "[#{start_port}-#{end_port}]" if (start_port..end_port) != (0..65_535)
128
- end
129
- h
130
- end
131
-
132
- # Get human readable protocol name. If protocol ID is 0, an empty string
133
- # is returned.
134
- # @return [String]
135
- def human_protocol
136
- if protocol.zero?
137
- ''
138
- else
139
- Proto.getprotobynumber(protocol) || protocol.to_s
140
- end
141
- end
142
-
143
- # Get human readable TS type
144
- # @return [String]
145
- def human_type
146
- case type
147
- when TS_IPV4_ADDR_RANGE
148
- 'IPv4'
149
- when TS_IPV6_ADDR_RANGE
150
- 'IPv6'
151
- else
152
- "type #{type}"
153
- end
154
- end
155
-
156
- private
157
-
158
- def select_addr_from_type(type)
159
- case type
160
- when TS_IPV4_ADDR_RANGE, 'IPV4', 'IPv4', 'ipv4', nil
161
- self[:start_addr] = IP::Addr.new unless self[:start_addr].is_a?(IP::Addr)
162
- self[:end_addr] = IP::Addr.new unless self[:end_addr].is_a?(IP::Addr)
163
- when TS_IPV6_ADDR_RANGE, 'IPV6', 'IPv6', 'ipv6'
164
- self[:start_addr] = IPv6::Addr.new unless self[:start_addr].is_a?(IPv6::Addr)
165
- self[:end_addr] = IPv6::Addr.new unless self[:end_addr].is_a?(IPv6::Addr)
166
- else
167
- raise ArgumentError, "unknown type #{type}"
168
- end
169
- end
170
-
171
- def select_addr(options)
172
- if options[:type]
173
- select_addr_from_type options[:type]
174
- elsif options[:start_addr]
175
- ipv4 = IPAddr.new(options[:start_addr]).ipv4?
176
- self.type = ipv4 ? TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE
177
- elsif options[:end_addr]
178
- ipv4 = IPAddr.new(options[:end_addr]).ipv4?
179
- self.type = ipv4 ? TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE
180
- end
181
- end
182
- end
183
-
184
- # Set of {TrafficSelector}, used by {TSi} and {TSr}.
185
- # @author Sylvain Daubert
186
- class TrafficSelectors < Types::Array
187
- set_of TrafficSelector
188
- end
189
-
190
- # This class handles Traffic Selector - Initiator payloads, denoted TSi.
191
- #
192
- # A TSi payload consists of the IKE generic payload header (see {Payload})
193
- # and some specific fields:
194
- # 1 2 3
195
- # 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
196
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
197
- # | Next Payload |C| RESERVED | Payload Length |
198
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
199
- # | Number of TSs | RESERVED |
200
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
201
- # | |
202
- # ~ <Traffic Selectors> ~
203
- # | |
204
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205
- # These specific fields are:
206
- # * {#num_ts},
207
- # * {#rsv1},
208
- # * {#rsv2},
209
- # * and {#traffic_selectors}.
210
- #
211
- # == Create a TSi payload
212
- # # Create a IKE packet with a TSi payload
213
- # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::TSi')
214
- # # add a traffic selector to this payload
215
- # pkt.ike_tsi.traffic_selectors << { protocol: 'tcp', ports: 1..1024, start_addr: '20.0.0.1', end_addr: '21.255.255.254' }
216
- # # add another traffic selector (IPv6, all protocols)
217
- # pkt.ike_tsi.traffic_selectors << { start_addr: '2001::1', end_addr: '200a:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
218
- # @author Sylvain Daubert
219
- class TSi < Payload
220
- # Payload type number
221
- PAYLOAD_TYPE = 44
222
-
223
- remove_field :content
224
-
225
- # @!attribute num_ts
226
- # 8-bit Number of TSs
227
- # @return [Integer]
228
- define_field_before :body, :num_ts, Types::Int8
229
- # @!attribute rsv
230
- # 24-bit RESERVED field
231
- # @return [Integer]
232
- define_field_before :body, :rsv, Types::Int24
233
-
234
- # @!attribute traffic_selectors
235
- # Set of {TrafficSelector}
236
- # @return {TrafficSelectors}
237
- define_field_before :body, :traffic_selectors, TrafficSelectors,
238
- builder: ->(h, t) { t.new(counter: h[:num_ts]) }
239
- alias selectors traffic_selectors
240
-
241
- # Populate object from a string
242
- # @param [String] str
243
- # @return [self]
244
- def read(str)
245
- super(str[0, 8])
246
- hlen = self.class.new.sz
247
- tslen = length - hlen
248
- selectors.read str[hlen, tslen]
249
- body.read str[hlen + tslen..-1]
250
- self
251
- end
252
-
253
- # Compute length and set {#length} field
254
- # @return [Integer] new length
255
- def calc_length
256
- selectors.each(&:calc_length)
257
- super
258
- end
259
- end
260
-
261
- class TSr < TSi
262
- # Payload type number
263
- PAYLOAD_TYPE = 45
264
- end
265
- end
266
-
267
- self.add_class IKE::TSi
268
- self.add_class IKE::TSr
269
- end
270
- end