ipsec_parser/
ikev2.rs

1use crate::ikev2_notify::NotifyType;
2use crate::ikev2_transforms::*;
3use rusticata_macros::newtype_enum;
4use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
5
6/// Payload exchange type: SA, Auth, CreateChildSA, etc.
7#[derive(Copy, Clone, PartialEq, Eq)]
8pub struct IkeExchangeType(pub u8);
9
10newtype_enum! {
11impl debug IkeExchangeType {
12    IKE_SA_INIT     = 34,
13    IKE_AUTH        = 35,
14    CREATE_CHILD_SA = 36,
15    INFORMATIONAL   = 37,
16}
17}
18
19/// Protocol type: IKE, AH or ESP
20///
21/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3.1
22#[derive(Clone, Copy, PartialEq, Eq)]
23pub struct ProtocolID(pub u8);
24
25newtype_enum! {
26impl debug ProtocolID {
27    IKE = 1,
28    AH  = 2,
29    ESP = 3,
30}
31}
32
33pub const IKEV2_FLAG_INITIATOR: u8 = 0b1000;
34pub const IKEV2_FLAG_VERSION: u8 = 0b1_0000;
35pub const IKEV2_FLAG_RESPONSE: u8 = 0b10_0000;
36
37/// The IKE Header
38///
39/// IKE messages use UDP ports 500 and/or 4500, with one IKE message per
40/// UDP datagram.  Information from the beginning of the packet through
41/// the UDP header is largely ignored except that the IP addresses and
42/// UDP ports from the headers are reversed and used for return packets.
43/// When sent on UDP port 500, IKE messages begin immediately following
44/// the UDP header.  When sent on UDP port 4500, IKE messages have
45/// prepended four octets of zeros.  These four octets of zeros are not
46/// part of the IKE message and are not included in any of the length
47/// fields or checksums defined by IKE.  Each IKE message begins with the
48/// IKE header, denoted HDR in this document.  Following the header are
49/// one or more IKE payloads each identified by a Next Payload field in
50/// the preceding payload.  Payloads are identified in the order in which
51/// they appear in an IKE message by looking in the Next Payload field in
52/// the IKE header, and subsequently according to the Next Payload field
53/// in the IKE payload itself until a Next Payload field of zero
54/// indicates that no payloads follow.  If a payload of type "Encrypted"
55/// is found, that payload is decrypted and its contents parsed as
56/// additional payloads.  An Encrypted payload MUST be the last payload
57/// in a packet and an Encrypted payload MUST NOT contain another
58/// Encrypted payload.
59///
60/// The responder's SPI in the header identifies an instance of an IKE
61/// Security Association.  It is therefore possible for a single instance
62/// of IKE to multiplex distinct sessions with multiple peers, including
63/// multiple sessions per peer.
64///
65/// All multi-octet fields representing integers are laid out in big
66/// endian order (also known as "most significant byte first", or
67/// "network byte order").
68///
69/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.1
70#[derive(Clone, Debug, PartialEq)]
71pub struct IkeV2Header {
72    pub init_spi: u64,
73    pub resp_spi: u64,
74    pub next_payload: IkePayloadType,
75    pub maj_ver: u8,
76    pub min_ver: u8,
77    pub exch_type: IkeExchangeType,
78    pub flags: u8,
79    pub msg_id: u32,
80    pub length: u32,
81}
82
83/// Payload type
84#[derive(Clone, Copy, PartialEq, Eq)]
85pub struct IkePayloadType(pub u8);
86
87newtype_enum! {
88impl debug IkePayloadType {
89    NoNextPayload             = 0,
90    SecurityAssociation       = 33,
91    KeyExchange               = 34,
92    IdentInitiator            = 35,
93    IdentResponder            = 36,
94    Certificate               = 37,
95    CertificateRequest        = 38,
96    Authentication            = 39,
97    Nonce                     = 40,
98    Notify                    = 41,
99    Delete                    = 42,
100    VendorID                  = 43,
101    TrafficSelectorInitiator  = 44,
102    TrafficSelectorResponder  = 45,
103    EncryptedAndAuthenticated = 46,
104    Configuration             = 47,
105    ExtensibleAuthentication  = 48,
106}
107}
108
109/// Generic (unparsed payload)
110///
111/// Defined in [RFC7296]
112#[derive(Debug, PartialEq)]
113pub struct IkeV2GenericPayload<'a> {
114    pub hdr: IkeV2PayloadHeader,
115    pub payload: &'a [u8],
116}
117
118/// Ciphersuite Proposal
119///
120/// The Proposal structure contains within it a Proposal Num and an IPsec
121/// protocol ID.  Each structure MUST have a proposal number one (1)
122/// greater than the previous structure.  The first Proposal in the
123/// initiator's SA payload MUST have a Proposal Num of one (1).  One
124/// reason to use multiple proposals is to propose both standard crypto
125/// ciphers and combined-mode ciphers.  Combined-mode ciphers include
126/// both integrity and encryption in a single encryption algorithm, and
127/// MUST either offer no integrity algorithm or a single integrity
128/// algorithm of "NONE", with no integrity algorithm being the
129/// RECOMMENDED method.  If an initiator wants to propose both combined-
130/// mode ciphers and normal ciphers, it must include two proposals: one
131/// will have all the combined-mode ciphers, and the other will have all
132/// the normal ciphers with the integrity algorithms.  For example, one
133/// such proposal would have two proposal structures.  Proposal 1 is ESP
134/// with AES-128, AES-192, and AES-256 bits in Cipher Block Chaining
135/// (CBC) mode, with either HMAC-SHA1-96 or XCBC-96 as the integrity
136/// algorithm; Proposal 2 is AES-128 or AES-256 in GCM mode with an
137/// 8-octet Integrity Check Value (ICV).  Both proposals allow but do not
138/// require the use of ESNs (Extended Sequence Numbers).  This can be
139/// illustrated as:
140///
141/// ```ignore
142/// SA Payload
143///    |
144///    +--- Proposal #1 ( Proto ID = ESP(3), SPI size = 4,
145///    |     |            7 transforms,      SPI = 0x052357bb )
146///    |     |
147///    |     +-- Transform ENCR ( Name = ENCR_AES_CBC )
148///    |     |     +-- Attribute ( Key Length = 128 )
149///    |     |
150///    |     +-- Transform ENCR ( Name = ENCR_AES_CBC )
151///    |     |     +-- Attribute ( Key Length = 192 )
152///    |     |
153///    |     +-- Transform ENCR ( Name = ENCR_AES_CBC )
154///    |     |     +-- Attribute ( Key Length = 256 )
155///    |     |
156///    |     +-- Transform INTEG ( Name = AUTH_HMAC_SHA1_96 )
157///    |     +-- Transform INTEG ( Name = AUTH_AES_XCBC_96 )
158///    |     +-- Transform ESN ( Name = ESNs )
159///    |     +-- Transform ESN ( Name = No ESNs )
160///    |
161///    +--- Proposal #2 ( Proto ID = ESP(3), SPI size = 4,
162///          |            4 transforms,      SPI = 0x35a1d6f2 )
163///          |
164///          +-- Transform ENCR ( Name = AES-GCM with a 8 octet ICV )
165///          |     +-- Attribute ( Key Length = 128 )
166///          |
167///          +-- Transform ENCR ( Name = AES-GCM with a 8 octet ICV )
168///          |     +-- Attribute ( Key Length = 256 )
169///          |
170///          +-- Transform ESN ( Name = ESNs )
171///          +-- Transform ESN ( Name = No ESNs )
172/// ```
173///
174/// Each Proposal/Protocol structure is followed by one or more transform
175/// structures.  The number of different transforms is generally
176/// determined by the Protocol.  AH generally has two transforms:
177/// Extended Sequence Numbers (ESNs) and an integrity check algorithm.
178/// ESP generally has three: ESN, an encryption algorithm, and an
179/// integrity check algorithm.  IKE generally has four transforms: a
180/// Diffie-Hellman group, an integrity check algorithm, a PRF algorithm,
181/// and an encryption algorithm.  For each Protocol, the set of
182/// permissible transforms is assigned Transform ID numbers, which appear
183/// in the header of each transform.
184///
185/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.3.1
186#[derive(Clone, Debug, PartialEq)]
187pub struct IkeV2Proposal<'a> {
188    pub last: u8,
189    pub reserved: u8,
190    pub proposal_length: u16,
191    pub proposal_num: u8,
192    pub protocol_id: ProtocolID,
193    pub spi_size: u8,
194    pub num_transforms: u8,
195    pub spi: Option<&'a [u8]>,
196    pub transforms: Vec<IkeV2RawTransform<'a>>,
197}
198
199/// Key Exchange Payload
200///
201/// The Key Exchange payload, denoted KE in this document, is used to
202/// exchange Diffie-Hellman public numbers as part of a Diffie-Hellman
203/// key exchange.  The Key Exchange payload consists of the IKE generic
204/// payload header followed by the Diffie-Hellman public value itself.
205///
206/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.4
207#[derive(Debug, PartialEq)]
208pub struct KeyExchangePayload<'a> {
209    pub dh_group: IkeTransformDHType,
210    pub reserved: u16,
211    pub kex_data: &'a [u8],
212}
213
214/// Identification Payloads
215///
216/// The Identification payloads, denoted IDi and IDr in this document,
217/// allow peers to assert an identity to one another.  This identity may
218/// be used for policy lookup, but does not necessarily have to match
219/// anything in the CERT payload; both fields may be used by an
220/// implementation to perform access control decisions.  When using the
221/// ID_IPV4_ADDR/ID_IPV6_ADDR identity types in IDi/IDr payloads, IKEv2
222/// does not require this address to match the address in the IP header
223/// of IKEv2 packets, or anything in the TSi/TSr payloads.  The contents
224/// of IDi/IDr are used purely to fetch the policy and authentication
225/// data related to the other party.
226///
227/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.5
228#[derive(Debug, PartialEq)]
229pub struct IdentificationPayload<'a> {
230    pub id_type: IdentificationType,
231    pub reserved1: u8,
232    pub reserved2: u16,
233    pub ident_data: &'a [u8],
234}
235
236/// Type of Identification
237#[derive(Clone, Copy, Debug, PartialEq, Eq)]
238pub struct IdentificationType(pub u8);
239
240#[rustfmt::skip]
241impl IdentificationType {
242    /// A single four (4) octet IPv4 address.
243    pub const ID_IPV4_ADDR   : IdentificationType = IdentificationType(1);
244    /// A fully-qualified domain name string.  An example of an ID_FQDN
245    /// is "example.com".  The string MUST NOT contain any terminators
246    /// (e.g., NULL, CR, etc.).  All characters in the ID_FQDN are ASCII;
247    /// for an "internationalized domain name", the syntax is as defined
248    /// in [IDNA], for example "xn--tmonesimerkki-bfbb.example.net".
249    pub const ID_FQDN        : IdentificationType = IdentificationType(2);
250    /// A fully-qualified RFC 822 email address string.  An example of a
251    /// ID_RFC822_ADDR is "jsmith@example.com".  The string MUST NOT
252    /// contain any terminators.  Because of [EAI], implementations would
253    /// be wise to treat this field as UTF-8 encoded text, not as
254    /// pure ASCII.
255    pub const ID_RFC822_ADDR : IdentificationType = IdentificationType(3);
256    /// A single sixteen (16) octet IPv6 address.
257    pub const ID_IPV6_ADDR   : IdentificationType = IdentificationType(5);
258    /// The binary Distinguished Encoding Rules (DER) encoding of an ASN.1 X.500 Distinguished
259    /// Name.
260    pub const ID_DER_ASN1_DN : IdentificationType = IdentificationType(9);
261    /// The binary DER encoding of an ASN.1 X.509 GeneralName.
262    pub const ID_DER_ASN1_GN : IdentificationType = IdentificationType(10);
263    /// An opaque octet stream that may be used to pass vendor-specific information necessary to do
264    /// certain proprietary types of identification.
265    pub const ID_KEY_ID      : IdentificationType = IdentificationType(11);
266}
267
268/// Certificate Payload
269///
270/// The Certificate payload, denoted CERT in this document, provides a
271/// means to transport certificates or other authentication-related
272/// information via IKE.  Certificate payloads SHOULD be included in an
273/// exchange if certificates are available to the sender.  The Hash and
274/// URL formats of the Certificate payloads should be used in case the
275/// peer has indicated an ability to retrieve this information from
276/// elsewhere using an HTTP_CERT_LOOKUP_SUPPORTED Notify payload.  Note
277/// that the term "Certificate payload" is somewhat misleading, because
278/// not all authentication mechanisms use certificates and data other
279/// than certificates may be passed in this payload.
280///
281/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.6
282#[derive(Debug, PartialEq)]
283pub struct CertificatePayload<'a> {
284    pub cert_encoding: CertificateEncoding,
285    pub cert_data: &'a [u8],
286}
287
288/// Certificate Encoding
289///
290/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.6
291#[derive(Clone, Copy, Debug, PartialEq, Eq)]
292pub struct CertificateEncoding(pub u8);
293
294#[allow(non_upper_case_globals)]
295#[rustfmt::skip]
296impl CertificateEncoding {
297    /// PKCS #7 wrapped X.509 certificate
298    pub const Pkcs7_X509                  : CertificateEncoding = CertificateEncoding(1);
299    /// PGP Certificate
300    pub const PgpCert                     : CertificateEncoding = CertificateEncoding(2);
301    /// DNS Signed Key
302    pub const DnsKey                      : CertificateEncoding = CertificateEncoding(3);
303    /// X.509 Certificate - Signature
304    pub const X509Sig                     : CertificateEncoding = CertificateEncoding(4);
305    /// Kerberos Token
306    pub const Kerberos                    : CertificateEncoding = CertificateEncoding(6);
307    /// Certificate Revocation List (CRL)
308    pub const Crl                         : CertificateEncoding = CertificateEncoding(7);
309    /// Authority Revocation List (ARL)
310    pub const Arl                         : CertificateEncoding = CertificateEncoding(8);
311    /// SPKI Certificate
312    pub const SpkiCert                    : CertificateEncoding = CertificateEncoding(9);
313    /// X.509 Certificate - Attribute
314    pub const X509CertAttr                : CertificateEncoding = CertificateEncoding(10);
315    /// Deprecated (was Raw RSA Key)
316    pub const OldRsaKey                   : CertificateEncoding = CertificateEncoding(11);
317    /// Hash and URL of X.509 certificate
318    pub const X509Cert_HashUrl            : CertificateEncoding = CertificateEncoding(12);
319    /// Hash and URL of X.509 bundle
320    pub const X509Bundle_HashUrl          : CertificateEncoding = CertificateEncoding(13);
321    /// OCSP Content ([RFC4806](https://tools.ietf.org/html/rfc4806))
322    pub const OCSPContent                 : CertificateEncoding = CertificateEncoding(14);
323    /// Raw Public Key ([RFC7670](https://tools.ietf.org/html/rfc7670))
324    pub const RawPublicKey                : CertificateEncoding = CertificateEncoding(15);
325}
326
327/// Certificate Request Payload
328///
329/// The Certificate Request payload, denoted CERTREQ in this document,
330/// provides a means to request preferred certificates via IKE and can
331/// appear in the IKE_INIT_SA response and/or the IKE_AUTH request.
332/// Certificate Request payloads MAY be included in an exchange when the
333/// sender needs to get the certificate of the receiver.
334///
335/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.7
336#[derive(Debug, PartialEq)]
337pub struct CertificateRequestPayload<'a> {
338    pub cert_encoding: CertificateEncoding,
339    pub ca_data: &'a [u8],
340}
341
342/// Authentication Payload
343///
344/// The Authentication payload, denoted AUTH in this document, contains
345/// data used for authentication purposes.
346///
347/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.8
348#[derive(Debug, PartialEq)]
349pub struct AuthenticationPayload<'a> {
350    pub auth_method: AuthenticationMethod,
351    pub auth_data: &'a [u8],
352}
353
354/// Method of authentication used.
355///
356/// See also [IKEV2IANA](https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml) for the latest values.
357#[derive(Clone, Copy, Debug, PartialEq, Eq)]
358pub struct AuthenticationMethod(pub u8);
359
360#[allow(non_upper_case_globals)]
361#[rustfmt::skip]
362impl AuthenticationMethod {
363    /// RSA Digital Signature
364    pub const RsaSig          : AuthenticationMethod = AuthenticationMethod(1);
365    /// Shared Key Message Integrity Code
366    pub const SharedKeyMIC    : AuthenticationMethod = AuthenticationMethod(2);
367    /// DSS Digital Signature
368    pub const DssSig          : AuthenticationMethod = AuthenticationMethod(3);
369    /// ECDSA with SHA-256 on the P-256 curve
370    pub const EcdsaSha256P256 : AuthenticationMethod = AuthenticationMethod(9);
371    /// ECDSA with SHA-384 on the P-384 curve
372    pub const EcdsaSha384P384 : AuthenticationMethod = AuthenticationMethod(10);
373    /// ECDSA with SHA-512 on the P-512 curve
374    pub const EcdsaSha512P512 : AuthenticationMethod = AuthenticationMethod(11);
375    /// Generic Secure Password Authentication Method
376    pub const GenericPass     : AuthenticationMethod = AuthenticationMethod(12);
377    /// NULL Authentication
378    pub const Null            : AuthenticationMethod = AuthenticationMethod(13);
379    /// Digital Signature
380    pub const DigitalSig      : AuthenticationMethod = AuthenticationMethod(14);
381
382    /// Test if value is in unassigned range
383    pub fn is_unassigned(self) -> bool {
384        (self.0 >= 4 && self.0 <= 8) ||
385        (self.0 >= 15 && self.0 <= 200)
386    }
387
388    /// Test if value is in private use range
389    pub fn is_private_use(self) -> bool {
390        self.0 >= 201
391    }
392}
393
394/// Nonce Payload
395///
396/// The Nonce payload, denoted as Ni and Nr in this document for the
397/// initiator's and responder's nonce, respectively, contains random data used to guarantee
398/// liveness during an exchange and protect against replay attacks.
399///
400/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.9
401#[derive(PartialEq)]
402pub struct NoncePayload<'a> {
403    pub nonce_data: &'a [u8],
404}
405
406/// Notify Payload
407///
408/// The Notify payload, denoted N in this document, is used to transmit informational data, such as
409/// error conditions and state transitions, to an IKE peer.  A Notify payload may appear in a
410/// response message (usually specifying why a request was rejected), in an INFORMATIONAL exchange
411/// (to report an error not in an IKE request), or in any other message to indicate sender
412/// capabilities or to modify the meaning of the request.
413///
414/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.10
415#[derive(PartialEq)]
416pub struct NotifyPayload<'a> {
417    pub protocol_id: ProtocolID,
418    pub spi_size: u8,
419    pub notify_type: NotifyType,
420    pub spi: Option<&'a [u8]>,
421    pub notify_data: Option<&'a [u8]>,
422}
423
424/// Delete Payload
425///
426/// The Delete payload, denoted D in this document, contains a
427/// protocol-specific Security Association identifier that the sender has
428/// removed from its Security Association database and is, therefore, no
429/// longer valid.  Figure 17 shows the format of the Delete payload.  It
430/// is possible to send multiple SPIs in a Delete payload; however, each
431/// SPI MUST be for the same protocol.  Mixing of protocol identifiers
432/// MUST NOT be performed in the Delete payload.  It is permitted,
433/// however, to include multiple Delete payloads in a single
434/// INFORMATIONAL exchange where each Delete payload lists SPIs for a
435/// different protocol.
436///
437/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.11
438#[derive(Debug, PartialEq)]
439pub struct DeletePayload<'a> {
440    pub protocol_id: ProtocolID,
441    pub spi_size: u8,
442    pub num_spi: u16,
443    pub spi: &'a [u8],
444}
445
446/// Vendor ID Payload
447///
448/// The Vendor ID payload, denoted V in this document, contains a vendor-
449/// defined constant.  The constant is used by vendors to identify and
450/// recognize remote instances of their implementations.  This mechanism
451/// allows a vendor to experiment with new features while maintaining
452/// backward compatibility.
453///
454/// A Vendor ID payload MAY announce that the sender is capable of
455/// accepting certain extensions to the protocol, or it MAY simply
456/// identify the implementation as an aid in debugging.  A Vendor ID
457/// payload MUST NOT change the interpretation of any information defined
458/// in this specification (i.e., the critical bit MUST be set to 0).
459/// Multiple Vendor ID payloads MAY be sent.  An implementation is not
460/// required to send any Vendor ID payload at all.
461///
462/// A Vendor ID payload may be sent as part of any message.  Reception of
463/// a familiar Vendor ID payload allows an implementation to make use of
464/// private use numbers described throughout this document, such as
465/// private payloads, private exchanges, private notifications, etc.
466/// Unfamiliar Vendor IDs MUST be ignored.
467///
468/// Writers of documents who wish to extend this protocol MUST define a
469/// Vendor ID payload to announce the ability to implement the extension
470/// in the document.  It is expected that documents that gain acceptance
471/// and are standardized will be given "magic numbers" out of the Future
472/// Use range by IANA, and the requirement to use a Vendor ID will go
473/// away.
474///
475/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.12
476#[derive(Debug, PartialEq)]
477pub struct VendorIDPayload<'a> {
478    pub vendor_id: &'a [u8],
479}
480
481/// Type of Traffic Selector
482///
483/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13.1
484///
485/// See also [IKEV2IANA](https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml) for the latest values.
486#[derive(Clone, Copy, Debug, PartialEq, Eq)]
487pub struct TSType(pub u8);
488
489#[allow(non_upper_case_globals)]
490impl TSType {
491    /// A range of IPv4 addresses
492    pub const IPv4AddrRange: TSType = TSType(7);
493    /// A range of IPv6 addresses
494    pub const IPv6AddrRange: TSType = TSType(8);
495    /// Fibre Channel Traffic Selectors ([RFC4595](https://tools.ietf.org/html/rfc4595))
496    pub const FcAddrRange: TSType = TSType(9);
497}
498
499/// Traffic Selector
500///
501/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13.1
502#[derive(Debug, PartialEq)]
503pub struct TrafficSelector<'a> {
504    pub ts_type: TSType,
505    pub ip_proto_id: u8,
506    pub sel_length: u16,
507    pub start_port: u16,
508    pub end_port: u16,
509    pub start_addr: &'a [u8],
510    pub end_addr: &'a [u8],
511}
512
513fn ipv4_from_slice(b: &[u8]) -> Ipv4Addr {
514    Ipv4Addr::new(b[0], b[1], b[2], b[3])
515}
516
517fn ipv6_from_slice(b: &[u8]) -> Ipv6Addr {
518    Ipv6Addr::new(
519        (b[0] as u16) << 8 | (b[1] as u16),
520        (b[2] as u16) << 8 | (b[3] as u16),
521        (b[4] as u16) << 8 | (b[5] as u16),
522        (b[6] as u16) << 8 | (b[7] as u16),
523        (b[8] as u16) << 8 | (b[9] as u16),
524        (b[10] as u16) << 8 | (b[11] as u16),
525        (b[12] as u16) << 8 | (b[13] as u16),
526        (b[14] as u16) << 8 | (b[15] as u16),
527    )
528}
529
530impl<'a> TrafficSelector<'a> {
531    pub fn get_ts_type(&self) -> TSType {
532        self.ts_type
533    }
534
535    pub fn get_start_addr(&self) -> Option<IpAddr> {
536        match self.ts_type {
537            TSType::IPv4AddrRange => Some(IpAddr::V4(ipv4_from_slice(self.start_addr))),
538            TSType::IPv6AddrRange => Some(IpAddr::V6(ipv6_from_slice(self.start_addr))),
539            _ => None,
540        }
541    }
542
543    pub fn get_end_addr(&self) -> Option<IpAddr> {
544        match self.ts_type {
545            TSType::IPv4AddrRange => Some(IpAddr::V4(ipv4_from_slice(self.end_addr))),
546            TSType::IPv6AddrRange => Some(IpAddr::V6(ipv6_from_slice(self.end_addr))),
547            _ => None,
548        }
549    }
550}
551
552/// Traffic Selector Payload
553///
554/// The Traffic Selector payload, denoted TS in this document, allows
555/// peers to identify packet flows for processing by IPsec security
556/// services.  The Traffic Selector payload consists of the IKE generic
557/// payload header followed by individual Traffic Selectors.
558///
559/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.13
560#[derive(Debug, PartialEq)]
561pub struct TrafficSelectorPayload<'a> {
562    pub num_ts: u8,
563    pub reserved: &'a [u8], // 3 bytes
564    pub ts: Vec<TrafficSelector<'a>>,
565}
566
567/// Encrypted Payload
568///
569/// The Encrypted payload, denoted SK {...} in this document, contains
570/// other payloads in encrypted form.  The Encrypted payload, if present
571/// in a message, MUST be the last payload in the message.  Often, it is
572/// the only payload in the message.  This payload is also called the
573/// "Encrypted and Authenticated" payload.
574#[derive(Debug, PartialEq)]
575pub struct EncryptedPayload<'a>(pub &'a [u8]);
576
577/// IKE Message Payload Content
578///
579/// The content of an IKE message is one of the defined payloads.
580///
581/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.2
582#[derive(Debug, PartialEq)]
583pub enum IkeV2PayloadContent<'a> {
584    SA(Vec<IkeV2Proposal<'a>>),
585    KE(KeyExchangePayload<'a>),
586    IDi(IdentificationPayload<'a>),
587    IDr(IdentificationPayload<'a>),
588    Certificate(CertificatePayload<'a>),
589    CertificateRequest(CertificateRequestPayload<'a>),
590    Authentication(AuthenticationPayload<'a>),
591    Nonce(NoncePayload<'a>),
592    Notify(NotifyPayload<'a>),
593    Delete(DeletePayload<'a>),
594    VendorID(VendorIDPayload<'a>),
595    TSi(TrafficSelectorPayload<'a>),
596    TSr(TrafficSelectorPayload<'a>),
597    Encrypted(EncryptedPayload<'a>),
598
599    Unknown(&'a [u8]),
600
601    Dummy,
602}
603
604/// Generic Payload Header
605///
606/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3.2
607#[derive(Clone, Debug, PartialEq)]
608pub struct IkeV2PayloadHeader {
609    pub next_payload_type: IkePayloadType,
610    pub critical: bool,
611    pub reserved: u8,
612    pub payload_length: u16,
613}
614
615/// IKE Message Payload
616///
617/// Defined in [RFC7296](https://tools.ietf.org/html/rfc7296) section 3
618#[derive(Debug, PartialEq)]
619pub struct IkeV2Payload<'a> {
620    pub hdr: IkeV2PayloadHeader,
621    pub content: IkeV2PayloadContent<'a>,
622}