packetgen 1.4.3 → 2.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.
@@ -0,0 +1,105 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # This class handles Certificate payloads.
7
+ #
8
+ # A Cert payload consists of the IKE generic payload header (see {Payload})
9
+ # and some specific fields:
10
+ # 1 2 3
11
+ # 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
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # | Next Payload |C| RESERVED | Payload Length |
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | Cert Encoding | |
16
+ # +-+-+-+-+-+-+-+-+ +
17
+ # | |
18
+ # ~ Certificate Data ~
19
+ # | |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # These specific fields are:
22
+ # * {#encoding},
23
+ # * and {#content} (Certificate Data).
24
+ #
25
+ # == Create a Cert payload
26
+ # # Create a IKE packet with a Cert payload
27
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Cert', encoding: 'X509_CERT_SIG')
28
+ # certs = cert.to_der << ca_cert.to_der
29
+ # pkt.ike_cert.content.read certs
30
+ # pkt.calc_length
31
+ # @author Sylvain Daubert
32
+ class Cert < Payload
33
+
34
+ # Payload type number
35
+ PAYLOAD_TYPE = 37
36
+
37
+ ENCODING_PKCS7_WRAPPED_X509 = 1
38
+ ENCODING_PGP = 2
39
+ ENCODING_DNS_SIGNED_KEY = 3
40
+ ENCODING_X509_CERT_SIG = 4
41
+ ENCODING_KERBEROS_TOKEN = 6
42
+ ENCODING_X509_CRL = 7
43
+ ENCODING_X509_ARL = 8
44
+ ENCODING_SPKI_CERT = 9
45
+ ENCODING_X509_CERT_ATTR = 10
46
+ ENCODING_HASH_URL_X509_CERT = 12
47
+ ENCODING_HASH_URL_X509_BUNDLE = 13
48
+
49
+ # @attribute encoding
50
+ # 8-bit certificate encoding
51
+ # @return [Integer]
52
+ define_field_before :content, :encoding, Types::Int8
53
+
54
+ def initialize(options={})
55
+ super
56
+ self.encoding = options[:encoding] if options[:encoding]
57
+ end
58
+
59
+ # Set encoding
60
+ # @param [Integer,String] value
61
+ # @return [Integer]
62
+ def encoding=(value)
63
+ encoding = case value
64
+ when Integer
65
+ value
66
+ else
67
+ c = self.class.constants.grep(/ENCODING_#{value}/).first
68
+ c ? self.class.const_get(c) : nil
69
+ end
70
+ raise ArgumentError, "unknown ID encoding #{value.inspect}" unless encoding
71
+ self[:encoding].value = encoding
72
+ end
73
+
74
+ # Get encoding name
75
+ # @return [String]
76
+ def human_encoding
77
+ name = self.class.constants.grep(/ENCODING_/).
78
+ select { |c| self.class.const_get(c) == encoding }.
79
+ first || "encoding #{encoding}"
80
+ name.to_s.sub(/ENCODING_/, '')
81
+ end
82
+
83
+ # @return [String]
84
+ def inspect
85
+ str = Inspect.dashed_line(self.class, 2)
86
+ fields.each do |attr|
87
+ case attr
88
+ when :body
89
+ next
90
+ when :encoding
91
+ str << Inspect.shift_level(2)
92
+ str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''), attr,
93
+ human_encoding]
94
+ else
95
+ str << Inspect.inspect_attribute(attr, self[attr], 2)
96
+ end
97
+ end
98
+ str
99
+ end
100
+ end
101
+ end
102
+
103
+ self.add_class IKE::Cert
104
+ end
105
+ end
@@ -0,0 +1,69 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # This class handles Certificate Request payloads.
7
+ #
8
+ # A CertReq payload consists of the IKE generic payload header (see {Payload})
9
+ # and some specific fields:
10
+ # 1 2 3
11
+ # 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
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # | Next Payload |C| RESERVED | Payload Length |
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | Cert Encoding | |
16
+ # +-+-+-+-+-+-+-+-+ +
17
+ # | |
18
+ # ~ Certification Authority ~
19
+ # | |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # These specific fields are:
22
+ # * {#encoding},
23
+ # * and {#content} (Certification Authority).
24
+ #
25
+ # == Create a CertReq payload
26
+ # # Create a IKE packet with a CertReq payload
27
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::CertReq', encoding: 'X509_CERT_SIG')
28
+ # pkt.ike_certreq.content.read OpenSSL::Digest::SHA1.digest(ca_cert.to_der)
29
+ # pkt.calc_length
30
+ # @author Sylvain Daubert
31
+ class CertReq < Cert
32
+
33
+ # Payload type number
34
+ PAYLOAD_TYPE = 38
35
+
36
+ # Get list of 20-byte string (SHA-1 hashes)
37
+ # @return [String]
38
+ def human_content
39
+ strs = []
40
+ idx = 0
41
+ while idx < content.size do
42
+ strs << content[idx, 20]
43
+ idx += 20
44
+ end
45
+ strs.map(&:inspect).join(',')
46
+ end
47
+
48
+ # @return [String]
49
+ def inspect
50
+ str = Inspect.dashed_line(self.class, 2)
51
+ fields.each do |attr|
52
+ case attr
53
+ when :body
54
+ next
55
+ when :content
56
+ str << Inspect.shift_level(2)
57
+ str << Inspect::FMT_ATTR % ['hashes', :content, human_content]
58
+ else
59
+ str << Inspect.inspect_attribute(attr, self[attr], 2)
60
+ end
61
+ end
62
+ str
63
+ end
64
+ end
65
+ end
66
+
67
+ self.add_class IKE::CertReq
68
+ end
69
+ end
@@ -0,0 +1,131 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # This class handles Identification - Initiator payloads, denoted IDi
7
+ # (see RFC 7296, §3.5).
8
+ #
9
+ # A ID payload consists of the IKE generic payload header (see {Payload})
10
+ # and some specific fields:
11
+ # 1 2 3
12
+ # 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
13
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14
+ # | Next Payload |C| RESERVED | Payload Length |
15
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16
+ # | ID Type | RESERVED |
17
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18
+ # | |
19
+ # ~ Identification Data ~
20
+ # | |
21
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22
+ # These specific fields are:
23
+ # * {#type} (ID type),
24
+ # * {#reserved},
25
+ # * and {#content} (Identification Data).
26
+ #
27
+ # == Create a IDi payload
28
+ # # Create a IKE packet with a IDi payload
29
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::IDi', type: 'FQDN')
30
+ # pkt.ike_idi.content.read 'fqdn.example.org'
31
+ # pkt.calc_length
32
+ # @author Sylvain Daubert
33
+ class IDi < Payload
34
+
35
+ # Payload type number
36
+ PAYLOAD_TYPE = 35
37
+
38
+ TYPE_IPV4_ADDR = 1
39
+ TYPE_FQDN = 2
40
+ TYPE_RFC822_ADDR = 3
41
+ TYPE_IPV6_ADDR = 5
42
+ TYPE_DER_ASN1_DN = 9
43
+ TYPE_DER_ASN1_GN = 10
44
+ TYPE_KEY_ID = 11
45
+
46
+ # @attribute :u32
47
+ # 32-bit word including ID Type and RESERVED fields
48
+ # @return [Integer]
49
+ define_field_before :content, :u32, Types::Int32
50
+ # @attribute [r] type
51
+ # 8-bit ID type
52
+ # @return [Integer]
53
+ # @attribute reserved
54
+ # 24-bit reserved field
55
+ # @return [Integer]
56
+ define_bit_fields_on :u32, :type, 8, :reserved, 24
57
+
58
+ # Set ID type
59
+ # @param [Integer,String] value
60
+ # @return [Integer]
61
+ def type=(value)
62
+ type = case value
63
+ when Integer
64
+ value
65
+ else
66
+ c = self.class.constants.grep(/TYPE_#{value}/).first
67
+ c ? self.class.const_get(c) : nil
68
+ end
69
+ raise ArgumentError, "unknown ID type #{value.inspect}" unless type
70
+ self[:u32].value = (self[:u32].to_i & 0xffffff) | (type << 24)
71
+ end
72
+
73
+ # Get ID type name
74
+ # @return [String]
75
+ def human_type
76
+ name = self.class.constants.grep(/TYPE_/).
77
+ select { |c| self.class.const_get(c) == type }.
78
+ first || "type #{type}"
79
+ name.to_s.sub(/TYPE_/, '')
80
+ end
81
+
82
+ # Get human readable content, from {#type}
83
+ # @return [String]
84
+ def human_content
85
+ case type
86
+ when TYPE_IPV4_ADDR, TYPE_IPV4_ADDR
87
+ IPAddr.ntop(content)
88
+ when TYPE_DER_ASN1_DN, TYPE_DER_ASN1_GN
89
+ OpenSSL::X509::Name.new(content).to_s
90
+ else
91
+ content.inspect
92
+ end
93
+ end
94
+
95
+ # @return [String]
96
+ def inspect
97
+ str = Inspect.dashed_line(self.class, 2)
98
+ fields.each do |attr|
99
+ case attr
100
+ when :body
101
+ next
102
+ when :u32
103
+ str << Inspect.shift_level(2)
104
+ str << Inspect::FMT_ATTR % ['Int8', :type, human_type]
105
+ str << Inspect.inspect_attribute(:reserved, self.reserved, 2)
106
+ else
107
+ str << Inspect.inspect_attribute(attr, self[attr], 2)
108
+ end
109
+ end
110
+ str
111
+ end
112
+ end
113
+
114
+ # This class handles Identification - Responder payloads, denoted IDr.
115
+ # See {IDi}.
116
+ #
117
+ # == Create a IDr payload
118
+ # # Create a IKE packet with a IDr payload
119
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::IDr', type: 'FQDN')
120
+ # pkt.ike_idr.content.read 'fqdn.example.org'
121
+ # @author Sylvain Daubert
122
+ class IDr < IDi
123
+ # Payload type number
124
+ PAYLOAD_TYPE = 36
125
+ end
126
+ end
127
+
128
+ self.add_class IKE::IDi
129
+ self.add_class IKE::IDr
130
+ end
131
+ end
@@ -0,0 +1,74 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # This class handles Key Exchange payloads, as defined in RFC 7296 §3.4
7
+ #
8
+ # A KE payload contains a generic payload header (see {Payload}) and some
9
+ # specific fields:
10
+ # 1 2 3
11
+ # 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
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # | Next Payload |C| RESERVED | Payload Length |
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | Diffie-Hellman Group Num | RESERVED |
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | |
18
+ # ~ Key Exchange Data ~
19
+ # | |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # These specific fields are:
22
+ # * {#group_num} (type {Types::Int16}),
23
+ # * {#reserved} (type {Types::Int16}),
24
+ # * and {#content} (type {Types::String}).
25
+ #
26
+ # == Create a KE payload
27
+ # # Create a IKE packet with a KE payload
28
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE')
29
+ # # group name is taken from Transform::DH_* constants
30
+ # pkt.add('IKE::KE', group: 'MODP4096')
31
+ # # group number may also be used
32
+ # pkt.ike_ke.group = 1
33
+ # pkt.calc_length
34
+ # @author Sylvain Daubert
35
+ class KE < Payload
36
+
37
+ # Payload type number
38
+ PAYLOAD_TYPE = 34
39
+
40
+ # @!attribute group_num
41
+ # 16-bit DH group number
42
+ # @return [Integer]
43
+ define_field_before :content, :group_num, Types::Int16
44
+ # @!attribute reserved
45
+ # 16-bit reserved field
46
+ # @return [Integer]
47
+ define_field_before :content, :reserved, Types::Int16, default: 0
48
+
49
+ def initialize(options={})
50
+ super
51
+ self.group = options[:group] if options[:group]
52
+ end
53
+
54
+ # Set group
55
+ # @param [Integer,String] value may be a String taken from
56
+ # {Transform}+::DH_*+ constant names.
57
+ # @return [Integer]
58
+ def group=(value)
59
+ group = case value
60
+ when Integer
61
+ value
62
+ else
63
+ cname = "DH_#{value}"
64
+ Transform.const_defined?(cname) ? Transform.const_get(cname) : nil
65
+ end
66
+ raise ArgumentError, "unknown group #{value.inspect}" unless group
67
+ self[:group_num].value = group
68
+ end
69
+ end
70
+ end
71
+
72
+ self.add_class IKE::KE
73
+ end
74
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # This class handles Nonce payloads, as defined in RFC 7296 §3.9.
7
+ #
8
+ # A Nonce payload contains a generic payload header (see {Payload}) and
9
+ # data field (type {Types::String}):
10
+ # 1 2 3
11
+ # 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
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # | Next Payload |C| RESERVED | Payload Length |
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | |
16
+ # ~ Nonce Data ~
17
+ # | |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ #
20
+ # == Create a Nonce payload
21
+ # # Create a IKE packet with a Nonce payload
22
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE')
23
+ # pkt.add('IKE::Nonce', data: "abcdefgh")
24
+ # pkt.calc_length
25
+ # @author Sylvain Daubert
26
+ class Nonce < Payload
27
+
28
+ # Payload type number
29
+ PAYLOAD_TYPE = 40
30
+ end
31
+ end
32
+
33
+ self.add_class IKE::Nonce
34
+ end
35
+ end
@@ -0,0 +1,220 @@
1
+ # coding: utf-8
2
+ module PacketGen
3
+ module Header
4
+ class IKE
5
+
6
+ # This class handles Notify payloads, as defined in RFC 7296 §3.10.
7
+ #
8
+ # A Notify payload contains a generic payload header (see {Payload}) and
9
+ # some specific fields:
10
+ # 1 2 3
11
+ # 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
12
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+ # | Next Payload |C| RESERVED | Payload Length |
14
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15
+ # | Protocol ID | SPI Size | Notify Message Type |
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | |
18
+ # ~ Security Parameter Index (SPI) ~
19
+ # | |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # | |
22
+ # ~ Notification Data ~
23
+ # | |
24
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
+ # These specific fields are:
26
+ # * {#protocol} (type {Types::Int8}),
27
+ # * {#spi_size} (type {Types::Int8}),
28
+ # * {#message_type} (type {Types::Int16}),
29
+ # * {#spi} (type {Types::String}),
30
+ # * {#content} (type {Types::String}).
31
+ #
32
+ # == Create a Notify payload
33
+ # # Create a IKE packet with a Notify payload
34
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Notify', protocol: 'IKE', type: 'INVALID_SYNTAX')
35
+ # pkt.ike_notify.spi # => ""
36
+ # pkt.ike_notify.content # => ""
37
+ # pkt.calc_length
38
+ # == Create a Notify payload with a SPI
39
+ # # Create a IKE packet with a Notify payload
40
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Notify', protocol: 'ESP', spi_size: 4, type: 'INVALID_SYNTAX')
41
+ # pkt.ike_notify.spi.read PacketGen::Types::Int32.new(0x12345678).to_s
42
+ # pkt.calc_length
43
+ # @author Sylvain Daubert
44
+ class Notify < Payload
45
+
46
+ # Payload type number
47
+ PAYLOAD_TYPE = 41
48
+
49
+ # Unsupported critical payload
50
+ TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1
51
+ # Invalid IKE SPI
52
+ TYPE_INVALID_IKE_SPI = 4
53
+ # Invalid major version
54
+ TYPE_INVALID_MAJOR_VERSION = 5
55
+ # Invalid syntax
56
+ TYPE_INVALID_SYNTAX = 7
57
+ # Invalid message ID
58
+ TYPE_INVALID_MESSAGE_ID = 9
59
+ # Invalid SPI
60
+ TYPE_INVALID_SPI = 11
61
+ # No proposal chosen (none of the proposed crypto suites was acceptable)
62
+ TYPE_NO_PROPOSAL_CHOSEN = 14
63
+ # Invalid KE payload
64
+ TYPE_INVALID_KE_PAYLOAD = 17
65
+ # Authentication failed
66
+ TYPE_AUTHENTICATION_FAILED = 24
67
+ # Single pair required
68
+ TYPE_SINGLE_PAIR_REQUIRED = 34
69
+ # No additional SAs
70
+ TYPE_NO_ADDITIONAL_SAS = 35
71
+ # Internal address failture
72
+ TYPE_INTERNAL_ADDRESS_FAILURE = 36
73
+ # Failed CP required
74
+ TYPE_FAILED_CP_REQUIRED = 37
75
+ # traffic selectors unacceptable
76
+ TYPE_TS_UNACCEPTABLE = 38
77
+ # invalid selectors
78
+ TYPE_INVALID_SELECTORS = 39
79
+ # Temporary failure
80
+ TYPE_TEMPORARY_FAILURE = 43
81
+ # Child SA not found
82
+ TYPE_CHILD_SA_NOT_FOUND = 44
83
+ # Initial contact
84
+ TYPE_INITIAL_CONTACT = 16384
85
+ # Set window size
86
+ TYPE_SET_WINDOW_SIZE = 16385
87
+ # Additional traffic selector possible
88
+ TYPE_ADDITIONAL_TS_POSSIBLE = 16386
89
+ # IPcomp supported
90
+ TYPE_IPCOMP_SUPPORTED = 16387
91
+ # NAT detection source IP
92
+ TYPE_NAT_DETECTION_SOURCE_IP = 16388
93
+ # NAT detection destination IP
94
+ TYPE_NAT_DETECTION_DESTINATION_IP = 16389
95
+ # Cookie
96
+ TYPE_COOKIE = 16390
97
+ # Use transport mode (tunnel mode is default)
98
+ TYPE_USE_TRANSPORT_MODE = 16391
99
+ # HTTP certificate look up supported
100
+ TYPE_HTTP_CERT_LOOKUP_SUPPORTED = 16392
101
+ # Rekey SA
102
+ TYPE_REKEY_SA = 16393
103
+ # ESP TFC paddin not supported
104
+ TYPE_ESP_TFC_PADDING_NOT_SUPPORTED = 16394
105
+ # Non-first fragment also
106
+ TYPE_NON_FIRST_FRAGMENTS_ALSO = 16395
107
+
108
+ # @!attribute [r] protocol
109
+ # 8-bit protocol ID. If this notification concerns an existing
110
+ # SA whose SPI is given in the SPI field, this field indicates the
111
+ # type of that SA. For notifications concerning Child SAs, this
112
+ # field MUST contain either (2) to indicate AH or (3) to indicate
113
+ # ESP. Of the notifications defined in this document, the SPI is
114
+ # included only with INVALID_SELECTORS, REKEY_SA, and
115
+ # CHILD_SA_NOT_FOUND. If the SPI field is empty, this field MUST be
116
+ # sent as zero and MUST be ignored on receipt.
117
+ # @return [Integer]
118
+ define_field_before :content, :protocol, Types::Int8
119
+ # @!attribute spi_size
120
+ # 8-bit SPI size. Give size of SPI field. Length in octets of the SPI as
121
+ # defined by the IPsec protocol ID or zero if no SPI is applicable. For a
122
+ # notification concerning the IKE SA, the SPI Size MUST be zero and
123
+ # the field must be empty.Set to 0 for an initial IKE SA
124
+ # negotiation, as SPI is obtained from outer header.
125
+ # @return [Integer]
126
+ define_field_before :content, :spi_size, Types::Int8, default: 0
127
+ # @!attribute message_type
128
+ # 16-bit notify message type. Specifies the type of notification message.
129
+ # @return [Integer]
130
+ define_field_before :content, :message_type, Types::Int16
131
+ # @!attribute spi
132
+ # the sending entity's SPI. When the {#spi_size} field is zero,
133
+ # this field is not present in the proposal.
134
+ # @return [String]
135
+ define_field_before :content, :spi, Types::String,
136
+ builder: ->(t) { Types::String.new('', length_from: t[:spi_size]) }
137
+
138
+ alias type message_type
139
+
140
+ def initialize(options={})
141
+ if options[:spi] and options[:spi_size].nil?
142
+ options[:spi_size] = options[:spi].size
143
+ end
144
+ super
145
+ self.protocol = options[:protocol] if options[:protocol]
146
+ self.message_type = options[:message_type] if options[:message_type]
147
+ self.type = options[:type] if options[:type]
148
+ end
149
+
150
+ # Set protocol
151
+ # @param [Integer,String] value
152
+ # @return [Integer]
153
+ def protocol=(value)
154
+ proto = case value
155
+ when Integer
156
+ value
157
+ else
158
+ c = IKE.constants.grep(/PROTO_#{value}/).first
159
+ c ? IKE.const_get(c) : nil
160
+ end
161
+ raise ArgumentError, "unknown protocol #{value.inspect}" unless proto
162
+ self[:protocol].value = proto
163
+ end
164
+
165
+ # Set message type
166
+ # @param [Integer,String] value
167
+ # @return [Integer]
168
+ def message_type=(value)
169
+ type = case value
170
+ when Integer
171
+ value
172
+ else
173
+ c = self.class.constants.grep(/TYPE_#{value}/).first
174
+ c ? self.class.const_get(c) : nil
175
+ end
176
+ raise ArgumentError, "unknown message type #{value.inspect}" unless type
177
+ self[:message_type].value = type
178
+ end
179
+ alias type= message_type=
180
+
181
+ # Get protocol name
182
+ # @return [String]
183
+ def human_protocol
184
+ name = IKE.constants.grep(/PROTO/).
185
+ select { |c| IKE.const_get(c) == protocol }.
186
+ first || "proto #{protocol}"
187
+ name.to_s.sub(/PROTO_/, '')
188
+ end
189
+
190
+ # Get message type name
191
+ # @return [String]
192
+ def human_message_type
193
+ name = self.class.constants.grep(/TYPE_/).
194
+ select { |c| self.class.const_get(c) == type }.
195
+ first || "type #{type}"
196
+ name.to_s.sub(/TYPE_/, '')
197
+ end
198
+ alias human_type human_message_type
199
+
200
+ # @return [String]
201
+ def inspect
202
+ str = Inspect.dashed_line(self.class, 2)
203
+ fields.each do |attr|
204
+ next if attr == :body
205
+ if %i(protocol message_type).include? attr
206
+ str << Inspect.shift_level(2)
207
+ str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''), attr,
208
+ send("human_#{attr}")]
209
+ else
210
+ str << Inspect.inspect_attribute(attr, self[attr], 2)
211
+ end
212
+ end
213
+ str
214
+ end
215
+ end
216
+ end
217
+
218
+ self.add_class IKE::Nonce
219
+ end
220
+ end