xref: /aosp_15_r20/external/tcpdump/print-isakmp.c (revision 05b00f6010a2396e3db2409989fc67270046269f)
1*05b00f60SXin Li /*
2*05b00f60SXin Li  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3*05b00f60SXin Li  * All rights reserved.
4*05b00f60SXin Li  *
5*05b00f60SXin Li  * Redistribution and use in source and binary forms, with or without
6*05b00f60SXin Li  * modification, are permitted provided that the following conditions
7*05b00f60SXin Li  * are met:
8*05b00f60SXin Li  * 1. Redistributions of source code must retain the above copyright
9*05b00f60SXin Li  *    notice, this list of conditions and the following disclaimer.
10*05b00f60SXin Li  * 2. Redistributions in binary form must reproduce the above copyright
11*05b00f60SXin Li  *    notice, this list of conditions and the following disclaimer in the
12*05b00f60SXin Li  *    documentation and/or other materials provided with the distribution.
13*05b00f60SXin Li  * 3. Neither the name of the project nor the names of its contributors
14*05b00f60SXin Li  *    may be used to endorse or promote products derived from this software
15*05b00f60SXin Li  *    without specific prior written permission.
16*05b00f60SXin Li  *
17*05b00f60SXin Li  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18*05b00f60SXin Li  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*05b00f60SXin Li  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*05b00f60SXin Li  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21*05b00f60SXin Li  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*05b00f60SXin Li  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*05b00f60SXin Li  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*05b00f60SXin Li  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*05b00f60SXin Li  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*05b00f60SXin Li  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*05b00f60SXin Li  * SUCH DAMAGE.
28*05b00f60SXin Li  *
29*05b00f60SXin Li  */
30*05b00f60SXin Li 
31*05b00f60SXin Li /* \summary: Internet Security Association and Key Management Protocol (ISAKMP) printer */
32*05b00f60SXin Li 
33*05b00f60SXin Li /* specification: RFC 2407, RFC 2408, RFC 5996 */
34*05b00f60SXin Li 
35*05b00f60SXin Li #ifdef HAVE_CONFIG_H
36*05b00f60SXin Li #include <config.h>
37*05b00f60SXin Li #endif
38*05b00f60SXin Li 
39*05b00f60SXin Li /* The functions from print-esp.c used in this file are only defined when both
40*05b00f60SXin Li  * OpenSSL and evp.h are detected. Employ the same preprocessor device here.
41*05b00f60SXin Li  */
42*05b00f60SXin Li #ifndef HAVE_OPENSSL_EVP_H
43*05b00f60SXin Li #undef HAVE_LIBCRYPTO
44*05b00f60SXin Li #endif
45*05b00f60SXin Li 
46*05b00f60SXin Li #include "netdissect-stdinc.h"
47*05b00f60SXin Li 
48*05b00f60SXin Li #include <string.h>
49*05b00f60SXin Li 
50*05b00f60SXin Li #include "netdissect-ctype.h"
51*05b00f60SXin Li 
52*05b00f60SXin Li #include "netdissect.h"
53*05b00f60SXin Li #include "addrtoname.h"
54*05b00f60SXin Li #include "extract.h"
55*05b00f60SXin Li 
56*05b00f60SXin Li #include "ip.h"
57*05b00f60SXin Li #include "ip6.h"
58*05b00f60SXin Li #include "ipproto.h"
59*05b00f60SXin Li 
60*05b00f60SXin Li typedef nd_byte cookie_t[8];
61*05b00f60SXin Li typedef nd_byte msgid_t[4];
62*05b00f60SXin Li 
63*05b00f60SXin Li #define PORT_ISAKMP 500
64*05b00f60SXin Li 
65*05b00f60SXin Li /* 3.1 ISAKMP Header Format (IKEv1 and IKEv2)
66*05b00f60SXin Li          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
67*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68*05b00f60SXin Li         !                          Initiator                            !
69*05b00f60SXin Li         !                            Cookie                             !
70*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71*05b00f60SXin Li         !                          Responder                            !
72*05b00f60SXin Li         !                            Cookie                             !
73*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74*05b00f60SXin Li         !  Next Payload ! MjVer ! MnVer ! Exchange Type !     Flags     !
75*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76*05b00f60SXin Li         !                          Message ID                           !
77*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78*05b00f60SXin Li         !                            Length                             !
79*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80*05b00f60SXin Li */
81*05b00f60SXin Li struct isakmp {
82*05b00f60SXin Li 	cookie_t i_ck;		/* Initiator Cookie */
83*05b00f60SXin Li 	cookie_t r_ck;		/* Responder Cookie */
84*05b00f60SXin Li 	nd_uint8_t np;		/* Next Payload Type */
85*05b00f60SXin Li 	nd_uint8_t vers;
86*05b00f60SXin Li #define ISAKMP_VERS_MAJOR	0xf0
87*05b00f60SXin Li #define ISAKMP_VERS_MAJOR_SHIFT	4
88*05b00f60SXin Li #define ISAKMP_VERS_MINOR	0x0f
89*05b00f60SXin Li #define ISAKMP_VERS_MINOR_SHIFT	0
90*05b00f60SXin Li 	nd_uint8_t etype;	/* Exchange Type */
91*05b00f60SXin Li 	nd_uint8_t flags;	/* Flags */
92*05b00f60SXin Li 	msgid_t msgid;
93*05b00f60SXin Li 	nd_uint32_t len;	/* Length */
94*05b00f60SXin Li };
95*05b00f60SXin Li 
96*05b00f60SXin Li /* Next Payload Type */
97*05b00f60SXin Li #define ISAKMP_NPTYPE_NONE   0 /* NONE*/
98*05b00f60SXin Li #define ISAKMP_NPTYPE_SA     1 /* Security Association */
99*05b00f60SXin Li #define ISAKMP_NPTYPE_P      2 /* Proposal */
100*05b00f60SXin Li #define ISAKMP_NPTYPE_T      3 /* Transform */
101*05b00f60SXin Li #define ISAKMP_NPTYPE_KE     4 /* Key Exchange */
102*05b00f60SXin Li #define ISAKMP_NPTYPE_ID     5 /* Identification */
103*05b00f60SXin Li #define ISAKMP_NPTYPE_CERT   6 /* Certificate */
104*05b00f60SXin Li #define ISAKMP_NPTYPE_CR     7 /* Certificate Request */
105*05b00f60SXin Li #define ISAKMP_NPTYPE_HASH   8 /* Hash */
106*05b00f60SXin Li #define ISAKMP_NPTYPE_SIG    9 /* Signature */
107*05b00f60SXin Li #define ISAKMP_NPTYPE_NONCE 10 /* Nonce */
108*05b00f60SXin Li #define ISAKMP_NPTYPE_N     11 /* Notification */
109*05b00f60SXin Li #define ISAKMP_NPTYPE_D     12 /* Delete */
110*05b00f60SXin Li #define ISAKMP_NPTYPE_VID   13 /* Vendor ID */
111*05b00f60SXin Li #define ISAKMP_NPTYPE_v2E   46 /* v2 Encrypted payload */
112*05b00f60SXin Li 
113*05b00f60SXin Li #define IKEv1_MAJOR_VERSION  1
114*05b00f60SXin Li #define IKEv1_MINOR_VERSION  0
115*05b00f60SXin Li 
116*05b00f60SXin Li #define IKEv2_MAJOR_VERSION  2
117*05b00f60SXin Li #define IKEv2_MINOR_VERSION  0
118*05b00f60SXin Li 
119*05b00f60SXin Li /* Flags */
120*05b00f60SXin Li #define ISAKMP_FLAG_E 0x01 /* Encryption Bit */
121*05b00f60SXin Li #define ISAKMP_FLAG_C 0x02 /* Commit Bit */
122*05b00f60SXin Li #define ISAKMP_FLAG_extra 0x04
123*05b00f60SXin Li 
124*05b00f60SXin Li /* IKEv2 */
125*05b00f60SXin Li #define ISAKMP_FLAG_I (1 << 3)  /* (I)nitiator */
126*05b00f60SXin Li #define ISAKMP_FLAG_V (1 << 4)  /* (V)ersion   */
127*05b00f60SXin Li #define ISAKMP_FLAG_R (1 << 5)  /* (R)esponse  */
128*05b00f60SXin Li 
129*05b00f60SXin Li 
130*05b00f60SXin Li /* 3.2 Payload Generic Header
131*05b00f60SXin Li          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
132*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133*05b00f60SXin Li         ! Next Payload  !   RESERVED    !         Payload Length        !
134*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135*05b00f60SXin Li */
136*05b00f60SXin Li struct isakmp_gen {
137*05b00f60SXin Li 	nd_uint8_t  np;       /* Next Payload */
138*05b00f60SXin Li 	nd_uint8_t  critical; /* bit 7 - critical, rest is RESERVED */
139*05b00f60SXin Li 	nd_uint16_t len;      /* Payload Length */
140*05b00f60SXin Li };
141*05b00f60SXin Li 
142*05b00f60SXin Li /* 3.3 Data Attributes
143*05b00f60SXin Li          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
144*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145*05b00f60SXin Li         !A!       Attribute Type        !    AF=0  Attribute Length     !
146*05b00f60SXin Li         !F!                             !    AF=1  Attribute Value      !
147*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148*05b00f60SXin Li         .                   AF=0  Attribute Value                       .
149*05b00f60SXin Li         .                   AF=1  Not Transmitted                       .
150*05b00f60SXin Li         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151*05b00f60SXin Li */
152*05b00f60SXin Li struct isakmp_data {
153*05b00f60SXin Li 	nd_uint16_t type;     /* defined by DOI-spec, and Attribute Format */
154*05b00f60SXin Li 	nd_uint16_t lorv;     /* if f equal 1, Attribute Length */
155*05b00f60SXin Li 	                      /* if f equal 0, Attribute Value */
156*05b00f60SXin Li 	/* if f equal 1, Attribute Value */
157*05b00f60SXin Li };
158*05b00f60SXin Li 
159*05b00f60SXin Li /* 3.4 Security Association Payload */
160*05b00f60SXin Li 	/* MAY NOT be used, because of being defined in ipsec-doi. */
161*05b00f60SXin Li 	/*
162*05b00f60SXin Li 	If the current payload is the last in the message,
163*05b00f60SXin Li 	then the value of the next payload field will be 0.
164*05b00f60SXin Li 	This field MUST NOT contain the
165*05b00f60SXin Li 	values for the Proposal or Transform payloads as they are considered
166*05b00f60SXin Li 	part of the security association negotiation.  For example, this
167*05b00f60SXin Li 	field would contain the value "10" (Nonce payload) in the first
168*05b00f60SXin Li 	message of a Base Exchange (see Section 4.4) and the value "0" in the
169*05b00f60SXin Li 	first message of an Identity Protect Exchange (see Section 4.5).
170*05b00f60SXin Li 	*/
171*05b00f60SXin Li struct ikev1_pl_sa {
172*05b00f60SXin Li 	struct isakmp_gen h;
173*05b00f60SXin Li 	nd_uint32_t doi; /* Domain of Interpretation */
174*05b00f60SXin Li 	nd_uint32_t sit; /* Situation */
175*05b00f60SXin Li };
176*05b00f60SXin Li 
177*05b00f60SXin Li /* 3.5 Proposal Payload */
178*05b00f60SXin Li 	/*
179*05b00f60SXin Li 	The value of the next payload field MUST only contain the value "2"
180*05b00f60SXin Li 	or "0".  If there are additional Proposal payloads in the message,
181*05b00f60SXin Li 	then this field will be 2.  If the current Proposal payload is the
182*05b00f60SXin Li 	last within the security association proposal, then this field will
183*05b00f60SXin Li 	be 0.
184*05b00f60SXin Li 	*/
185*05b00f60SXin Li struct ikev1_pl_p {
186*05b00f60SXin Li 	struct isakmp_gen h;
187*05b00f60SXin Li 	nd_uint8_t p_no;      /* Proposal # */
188*05b00f60SXin Li 	nd_uint8_t prot_id;   /* Protocol */
189*05b00f60SXin Li 	nd_uint8_t spi_size;  /* SPI Size */
190*05b00f60SXin Li 	nd_uint8_t num_t;     /* Number of Transforms */
191*05b00f60SXin Li 	/* SPI */
192*05b00f60SXin Li };
193*05b00f60SXin Li 
194*05b00f60SXin Li /* 3.6 Transform Payload */
195*05b00f60SXin Li 	/*
196*05b00f60SXin Li 	The value of the next payload field MUST only contain the value "3"
197*05b00f60SXin Li 	or "0".  If there are additional Transform payloads in the proposal,
198*05b00f60SXin Li 	then this field will be 3.  If the current Transform payload is the
199*05b00f60SXin Li 	last within the proposal, then this field will be 0.
200*05b00f60SXin Li 	*/
201*05b00f60SXin Li struct ikev1_pl_t {
202*05b00f60SXin Li 	struct isakmp_gen h;
203*05b00f60SXin Li 	nd_uint8_t  t_no;        /* Transform # */
204*05b00f60SXin Li 	nd_uint8_t  t_id;        /* Transform-Id */
205*05b00f60SXin Li 	nd_byte     reserved[2]; /* RESERVED2 */
206*05b00f60SXin Li 	/* SA Attributes */
207*05b00f60SXin Li };
208*05b00f60SXin Li 
209*05b00f60SXin Li /* 3.7 Key Exchange Payload */
210*05b00f60SXin Li struct ikev1_pl_ke {
211*05b00f60SXin Li 	struct isakmp_gen h;
212*05b00f60SXin Li 	/* Key Exchange Data */
213*05b00f60SXin Li };
214*05b00f60SXin Li 
215*05b00f60SXin Li /* 3.8 Identification Payload */
216*05b00f60SXin Li 	/* MUST NOT to be used, because of being defined in ipsec-doi. */
217*05b00f60SXin Li struct ikev1_pl_id {
218*05b00f60SXin Li 	struct isakmp_gen h;
219*05b00f60SXin Li 	union {
220*05b00f60SXin Li 		nd_uint8_t  id_type;   /* ID Type */
221*05b00f60SXin Li 		nd_uint32_t doi_data;  /* DOI Specific ID Data */
222*05b00f60SXin Li 	} d;
223*05b00f60SXin Li 	/* Identification Data */
224*05b00f60SXin Li };
225*05b00f60SXin Li 
226*05b00f60SXin Li /* 3.9 Certificate Payload */
227*05b00f60SXin Li struct ikev1_pl_cert {
228*05b00f60SXin Li 	struct isakmp_gen h;
229*05b00f60SXin Li 	nd_uint8_t encode; /* Cert Encoding */
230*05b00f60SXin Li 	nd_uint8_t cert;   /* Certificate Data */
231*05b00f60SXin Li 		/*
232*05b00f60SXin Li 		This field indicates the type of
233*05b00f60SXin Li 		certificate or certificate-related information contained in the
234*05b00f60SXin Li 		Certificate Data field.
235*05b00f60SXin Li 		*/
236*05b00f60SXin Li };
237*05b00f60SXin Li 
238*05b00f60SXin Li /* 3.10 Certificate Request Payload */
239*05b00f60SXin Li struct ikev1_pl_cr {
240*05b00f60SXin Li 	struct isakmp_gen h;
241*05b00f60SXin Li 	nd_uint8_t num_cert; /* # Cert. Types */
242*05b00f60SXin Li 	/*
243*05b00f60SXin Li 	Certificate Types (variable length)
244*05b00f60SXin Li 	  -- Contains a list of the types of certificates requested,
245*05b00f60SXin Li 	  sorted in order of preference.  Each individual certificate
246*05b00f60SXin Li 	  type is 1 octet.  This field is NOT requiredo
247*05b00f60SXin Li 	*/
248*05b00f60SXin Li 	/* # Certificate Authorities (1 octet) */
249*05b00f60SXin Li 	/* Certificate Authorities (variable length) */
250*05b00f60SXin Li };
251*05b00f60SXin Li 
252*05b00f60SXin Li /* 3.11 Hash Payload */
253*05b00f60SXin Li 	/* may not be used, because of having only data. */
254*05b00f60SXin Li struct ikev1_pl_hash {
255*05b00f60SXin Li 	struct isakmp_gen h;
256*05b00f60SXin Li 	/* Hash Data */
257*05b00f60SXin Li };
258*05b00f60SXin Li 
259*05b00f60SXin Li /* 3.12 Signature Payload */
260*05b00f60SXin Li 	/* may not be used, because of having only data. */
261*05b00f60SXin Li struct ikev1_pl_sig {
262*05b00f60SXin Li 	struct isakmp_gen h;
263*05b00f60SXin Li 	/* Signature Data */
264*05b00f60SXin Li };
265*05b00f60SXin Li 
266*05b00f60SXin Li /* 3.13 Nonce Payload */
267*05b00f60SXin Li 	/* may not be used, because of having only data. */
268*05b00f60SXin Li struct ikev1_pl_nonce {
269*05b00f60SXin Li 	struct isakmp_gen h;
270*05b00f60SXin Li 	/* Nonce Data */
271*05b00f60SXin Li };
272*05b00f60SXin Li 
273*05b00f60SXin Li /* 3.14 Notification Payload */
274*05b00f60SXin Li struct ikev1_pl_n {
275*05b00f60SXin Li 	struct isakmp_gen h;
276*05b00f60SXin Li 	nd_uint32_t doi;      /* Domain of Interpretation */
277*05b00f60SXin Li 	nd_uint8_t  prot_id;  /* Protocol-ID */
278*05b00f60SXin Li 	nd_uint8_t  spi_size; /* SPI Size */
279*05b00f60SXin Li 	nd_uint16_t type;     /* Notify Message Type */
280*05b00f60SXin Li 	/* SPI */
281*05b00f60SXin Li 	/* Notification Data */
282*05b00f60SXin Li };
283*05b00f60SXin Li 
284*05b00f60SXin Li /* 3.14.1 Notify Message Types */
285*05b00f60SXin Li /* NOTIFY MESSAGES - ERROR TYPES */
286*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE           1
287*05b00f60SXin Li #define ISAKMP_NTYPE_DOI_NOT_SUPPORTED              2
288*05b00f60SXin Li #define ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED        3
289*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_COOKIE                 4
290*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_MAJOR_VERSION          5
291*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_MINOR_VERSION          6
292*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE          7
293*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_FLAGS                  8
294*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_MESSAGE_ID             9
295*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_PROTOCOL_ID            10
296*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_SPI                    11
297*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_TRANSFORM_ID           12
298*05b00f60SXin Li #define ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED       13
299*05b00f60SXin Li #define ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN             14
300*05b00f60SXin Li #define ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX            15
301*05b00f60SXin Li #define ISAKMP_NTYPE_PAYLOAD_MALFORMED              16
302*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_KEY_INFORMATION        17
303*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_ID_INFORMATION         18
304*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_CERT_ENCODING          19
305*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_CERTIFICATE            20
306*05b00f60SXin Li #define ISAKMP_NTYPE_BAD_CERT_REQUEST_SYNTAX        21
307*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_CERT_AUTHORITY         22
308*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_HASH_INFORMATION       23
309*05b00f60SXin Li #define ISAKMP_NTYPE_AUTHENTICATION_FAILED          24
310*05b00f60SXin Li #define ISAKMP_NTYPE_INVALID_SIGNATURE              25
311*05b00f60SXin Li #define ISAKMP_NTYPE_ADDRESS_NOTIFICATION           26
312*05b00f60SXin Li 
313*05b00f60SXin Li /* 3.15 Delete Payload */
314*05b00f60SXin Li struct ikev1_pl_d {
315*05b00f60SXin Li 	struct isakmp_gen h;
316*05b00f60SXin Li 	nd_uint32_t doi;      /* Domain of Interpretation */
317*05b00f60SXin Li 	nd_uint8_t  prot_id;  /* Protocol-Id */
318*05b00f60SXin Li 	nd_uint8_t  spi_size; /* SPI Size */
319*05b00f60SXin Li 	nd_uint16_t num_spi;  /* # of SPIs */
320*05b00f60SXin Li 	/* SPI(es) */
321*05b00f60SXin Li };
322*05b00f60SXin Li 
323*05b00f60SXin Li /* IKEv2 (RFC4306) */
324*05b00f60SXin Li 
325*05b00f60SXin Li /* 3.3  Security Association Payload -- generic header */
326*05b00f60SXin Li /* 3.3.1.  Proposal Substructure */
327*05b00f60SXin Li struct ikev2_p {
328*05b00f60SXin Li 	struct isakmp_gen h;
329*05b00f60SXin Li 	nd_uint8_t p_no;      /* Proposal # */
330*05b00f60SXin Li 	nd_uint8_t prot_id;   /* Protocol */
331*05b00f60SXin Li 	nd_uint8_t spi_size;  /* SPI Size */
332*05b00f60SXin Li 	nd_uint8_t num_t;     /* Number of Transforms */
333*05b00f60SXin Li };
334*05b00f60SXin Li 
335*05b00f60SXin Li /* 3.3.2.  Transform Substructure */
336*05b00f60SXin Li struct ikev2_t {
337*05b00f60SXin Li 	struct isakmp_gen h;
338*05b00f60SXin Li 	nd_uint8_t  t_type;    /* Transform Type (ENCR,PRF,INTEG,etc.*/
339*05b00f60SXin Li 	nd_byte     res2;      /* reserved byte */
340*05b00f60SXin Li 	nd_uint16_t t_id;     /* Transform ID */
341*05b00f60SXin Li };
342*05b00f60SXin Li 
343*05b00f60SXin Li enum ikev2_t_type {
344*05b00f60SXin Li 	IV2_T_ENCR = 1,
345*05b00f60SXin Li 	IV2_T_PRF  = 2,
346*05b00f60SXin Li 	IV2_T_INTEG= 3,
347*05b00f60SXin Li 	IV2_T_DH   = 4,
348*05b00f60SXin Li 	IV2_T_ESN  = 5
349*05b00f60SXin Li };
350*05b00f60SXin Li 
351*05b00f60SXin Li /* 3.4.  Key Exchange Payload */
352*05b00f60SXin Li struct ikev2_ke {
353*05b00f60SXin Li 	struct isakmp_gen h;
354*05b00f60SXin Li 	nd_uint16_t  ke_group;
355*05b00f60SXin Li 	nd_uint16_t  ke_res1;
356*05b00f60SXin Li 	/* KE data */
357*05b00f60SXin Li };
358*05b00f60SXin Li 
359*05b00f60SXin Li 
360*05b00f60SXin Li /* 3.5.  Identification Payloads */
361*05b00f60SXin Li enum ikev2_id_type {
362*05b00f60SXin Li 	ID_IPV4_ADDR=1,
363*05b00f60SXin Li 	ID_FQDN=2,
364*05b00f60SXin Li 	ID_RFC822_ADDR=3,
365*05b00f60SXin Li 	ID_IPV6_ADDR=5,
366*05b00f60SXin Li 	ID_DER_ASN1_DN=9,
367*05b00f60SXin Li 	ID_DER_ASN1_GN=10,
368*05b00f60SXin Li 	ID_KEY_ID=11
369*05b00f60SXin Li };
370*05b00f60SXin Li struct ikev2_id {
371*05b00f60SXin Li 	struct isakmp_gen h;
372*05b00f60SXin Li 	nd_uint8_t type;        /* ID type */
373*05b00f60SXin Li 	nd_byte    res1;
374*05b00f60SXin Li 	nd_byte    res2[2];
375*05b00f60SXin Li 	/* SPI */
376*05b00f60SXin Li 	/* Notification Data */
377*05b00f60SXin Li };
378*05b00f60SXin Li 
379*05b00f60SXin Li /* 3.10 Notification Payload */
380*05b00f60SXin Li struct ikev2_n {
381*05b00f60SXin Li 	struct isakmp_gen h;
382*05b00f60SXin Li 	nd_uint8_t  prot_id;  /* Protocol-ID */
383*05b00f60SXin Li 	nd_uint8_t  spi_size; /* SPI Size */
384*05b00f60SXin Li 	nd_uint16_t type;     /* Notify Message Type */
385*05b00f60SXin Li };
386*05b00f60SXin Li 
387*05b00f60SXin Li enum ikev2_n_type {
388*05b00f60SXin Li 	IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD            = 1,
389*05b00f60SXin Li 	IV2_NOTIFY_INVALID_IKE_SPI                         = 4,
390*05b00f60SXin Li 	IV2_NOTIFY_INVALID_MAJOR_VERSION                   = 5,
391*05b00f60SXin Li 	IV2_NOTIFY_INVALID_SYNTAX                          = 7,
392*05b00f60SXin Li 	IV2_NOTIFY_INVALID_MESSAGE_ID                      = 9,
393*05b00f60SXin Li 	IV2_NOTIFY_INVALID_SPI                             =11,
394*05b00f60SXin Li 	IV2_NOTIFY_NO_PROPOSAL_CHOSEN                      =14,
395*05b00f60SXin Li 	IV2_NOTIFY_INVALID_KE_PAYLOAD                      =17,
396*05b00f60SXin Li 	IV2_NOTIFY_AUTHENTICATION_FAILED                   =24,
397*05b00f60SXin Li 	IV2_NOTIFY_SINGLE_PAIR_REQUIRED                    =34,
398*05b00f60SXin Li 	IV2_NOTIFY_NO_ADDITIONAL_SAS                       =35,
399*05b00f60SXin Li 	IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE                =36,
400*05b00f60SXin Li 	IV2_NOTIFY_FAILED_CP_REQUIRED                      =37,
401*05b00f60SXin Li 	IV2_NOTIFY_INVALID_SELECTORS                       =39,
402*05b00f60SXin Li 	IV2_NOTIFY_INITIAL_CONTACT                         =16384,
403*05b00f60SXin Li 	IV2_NOTIFY_SET_WINDOW_SIZE                         =16385,
404*05b00f60SXin Li 	IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE                  =16386,
405*05b00f60SXin Li 	IV2_NOTIFY_IPCOMP_SUPPORTED                        =16387,
406*05b00f60SXin Li 	IV2_NOTIFY_NAT_DETECTION_SOURCE_IP                 =16388,
407*05b00f60SXin Li 	IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP            =16389,
408*05b00f60SXin Li 	IV2_NOTIFY_COOKIE                                  =16390,
409*05b00f60SXin Li 	IV2_NOTIFY_USE_TRANSPORT_MODE                      =16391,
410*05b00f60SXin Li 	IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED              =16392,
411*05b00f60SXin Li 	IV2_NOTIFY_REKEY_SA                                =16393,
412*05b00f60SXin Li 	IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED           =16394,
413*05b00f60SXin Li 	IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO                =16395
414*05b00f60SXin Li };
415*05b00f60SXin Li 
416*05b00f60SXin Li struct notify_messages {
417*05b00f60SXin Li 	uint16_t type;
418*05b00f60SXin Li 	char     *msg;
419*05b00f60SXin Li };
420*05b00f60SXin Li 
421*05b00f60SXin Li /* 3.8 Authentication Payload */
422*05b00f60SXin Li struct ikev2_auth {
423*05b00f60SXin Li 	struct isakmp_gen h;
424*05b00f60SXin Li 	nd_uint8_t  auth_method;  /* Protocol-ID */
425*05b00f60SXin Li 	nd_byte     reserved[3];
426*05b00f60SXin Li 	/* authentication data */
427*05b00f60SXin Li };
428*05b00f60SXin Li 
429*05b00f60SXin Li enum ikev2_auth_type {
430*05b00f60SXin Li 	IV2_RSA_SIG = 1,
431*05b00f60SXin Li 	IV2_SHARED  = 2,
432*05b00f60SXin Li 	IV2_DSS_SIG = 3
433*05b00f60SXin Li };
434*05b00f60SXin Li 
435*05b00f60SXin Li /* refer to RFC 2409 */
436*05b00f60SXin Li 
437*05b00f60SXin Li #if 0
438*05b00f60SXin Li /* isakmp sa structure */
439*05b00f60SXin Li struct oakley_sa {
440*05b00f60SXin Li 	uint8_t  proto_id;            /* OAKLEY */
441*05b00f60SXin Li 	vchar_t   *spi;                /* spi */
442*05b00f60SXin Li 	uint8_t  dhgrp;               /* DH; group */
443*05b00f60SXin Li 	uint8_t  auth_t;              /* method of authentication */
444*05b00f60SXin Li 	uint8_t  prf_t;               /* type of prf */
445*05b00f60SXin Li 	uint8_t  hash_t;              /* type of hash */
446*05b00f60SXin Li 	uint8_t  enc_t;               /* type of cipher */
447*05b00f60SXin Li 	uint8_t  life_t;              /* type of duration of lifetime */
448*05b00f60SXin Li 	uint32_t ldur;                /* life duration */
449*05b00f60SXin Li };
450*05b00f60SXin Li #endif
451*05b00f60SXin Li 
452*05b00f60SXin Li /* refer to RFC 2407 */
453*05b00f60SXin Li 
454*05b00f60SXin Li #define IPSEC_DOI 1
455*05b00f60SXin Li 
456*05b00f60SXin Li /* 4.2 IPSEC Situation Definition */
457*05b00f60SXin Li #define IPSECDOI_SIT_IDENTITY_ONLY           0x00000001
458*05b00f60SXin Li #define IPSECDOI_SIT_SECRECY                 0x00000002
459*05b00f60SXin Li #define IPSECDOI_SIT_INTEGRITY               0x00000004
460*05b00f60SXin Li 
461*05b00f60SXin Li /* 4.4.1 IPSEC Security Protocol Identifiers */
462*05b00f60SXin Li   /* 4.4.2 IPSEC ISAKMP Transform Values */
463*05b00f60SXin Li #define IPSECDOI_PROTO_ISAKMP                        1
464*05b00f60SXin Li #define   IPSECDOI_KEY_IKE                             1
465*05b00f60SXin Li 
466*05b00f60SXin Li /* 4.4.1 IPSEC Security Protocol Identifiers */
467*05b00f60SXin Li #define IPSECDOI_PROTO_IPSEC_AH                      2
468*05b00f60SXin Li   /* 4.4.3 IPSEC AH Transform Values */
469*05b00f60SXin Li #define   IPSECDOI_AH_MD5                              2
470*05b00f60SXin Li #define   IPSECDOI_AH_SHA                              3
471*05b00f60SXin Li #define   IPSECDOI_AH_DES                              4
472*05b00f60SXin Li #define   IPSECDOI_AH_SHA2_256                         5
473*05b00f60SXin Li #define   IPSECDOI_AH_SHA2_384                         6
474*05b00f60SXin Li #define   IPSECDOI_AH_SHA2_512                         7
475*05b00f60SXin Li 
476*05b00f60SXin Li /* 4.4.1 IPSEC Security Protocol Identifiers */
477*05b00f60SXin Li #define IPSECDOI_PROTO_IPSEC_ESP                     3
478*05b00f60SXin Li   /* 4.4.4 IPSEC ESP Transform Identifiers */
479*05b00f60SXin Li #define   IPSECDOI_ESP_DES_IV64                        1
480*05b00f60SXin Li #define   IPSECDOI_ESP_DES                             2
481*05b00f60SXin Li #define   IPSECDOI_ESP_3DES                            3
482*05b00f60SXin Li #define   IPSECDOI_ESP_RC5                             4
483*05b00f60SXin Li #define   IPSECDOI_ESP_IDEA                            5
484*05b00f60SXin Li #define   IPSECDOI_ESP_CAST                            6
485*05b00f60SXin Li #define   IPSECDOI_ESP_BLOWFISH                        7
486*05b00f60SXin Li #define   IPSECDOI_ESP_3IDEA                           8
487*05b00f60SXin Li #define   IPSECDOI_ESP_DES_IV32                        9
488*05b00f60SXin Li #define   IPSECDOI_ESP_RC4                            10
489*05b00f60SXin Li #define   IPSECDOI_ESP_NULL                           11
490*05b00f60SXin Li #define   IPSECDOI_ESP_RIJNDAEL				12
491*05b00f60SXin Li #define   IPSECDOI_ESP_AES				12
492*05b00f60SXin Li 
493*05b00f60SXin Li /* 4.4.1 IPSEC Security Protocol Identifiers */
494*05b00f60SXin Li #define IPSECDOI_PROTO_IPCOMP                        4
495*05b00f60SXin Li   /* 4.4.5 IPSEC IPCOMP Transform Identifiers */
496*05b00f60SXin Li #define   IPSECDOI_IPCOMP_OUI                          1
497*05b00f60SXin Li #define   IPSECDOI_IPCOMP_DEFLATE                      2
498*05b00f60SXin Li #define   IPSECDOI_IPCOMP_LZS                          3
499*05b00f60SXin Li 
500*05b00f60SXin Li /* 4.5 IPSEC Security Association Attributes */
501*05b00f60SXin Li #define IPSECDOI_ATTR_SA_LTYPE                1 /* B */
502*05b00f60SXin Li #define   IPSECDOI_ATTR_SA_LTYPE_DEFAULT        1
503*05b00f60SXin Li #define   IPSECDOI_ATTR_SA_LTYPE_SEC            1
504*05b00f60SXin Li #define   IPSECDOI_ATTR_SA_LTYPE_KB             2
505*05b00f60SXin Li #define IPSECDOI_ATTR_SA_LDUR                 2 /* V */
506*05b00f60SXin Li #define   IPSECDOI_ATTR_SA_LDUR_DEFAULT         28800 /* 8 hours */
507*05b00f60SXin Li #define IPSECDOI_ATTR_GRP_DESC                3 /* B */
508*05b00f60SXin Li #define IPSECDOI_ATTR_ENC_MODE                4 /* B */
509*05b00f60SXin Li 	/* default value: host dependent */
510*05b00f60SXin Li #define   IPSECDOI_ATTR_ENC_MODE_TUNNEL         1
511*05b00f60SXin Li #define   IPSECDOI_ATTR_ENC_MODE_TRNS           2
512*05b00f60SXin Li #define IPSECDOI_ATTR_AUTH                    5 /* B */
513*05b00f60SXin Li 	/* 0 means not to use authentication. */
514*05b00f60SXin Li #define   IPSECDOI_ATTR_AUTH_HMAC_MD5           1
515*05b00f60SXin Li #define   IPSECDOI_ATTR_AUTH_HMAC_SHA1          2
516*05b00f60SXin Li #define   IPSECDOI_ATTR_AUTH_DES_MAC            3
517*05b00f60SXin Li #define   IPSECDOI_ATTR_AUTH_KPDK               4 /*RFC-1826(Key/Pad/Data/Key)*/
518*05b00f60SXin Li 	/*
519*05b00f60SXin Li 	 * When negotiating ESP without authentication, the Auth
520*05b00f60SXin Li 	 * Algorithm attribute MUST NOT be included in the proposal.
521*05b00f60SXin Li 	 * When negotiating ESP without confidentiality, the Auth
522*05b00f60SXin Li 	 * Algorithm attribute MUST be included in the proposal and
523*05b00f60SXin Li 	 * the ESP transform ID must be ESP_NULL.
524*05b00f60SXin Li 	*/
525*05b00f60SXin Li #define IPSECDOI_ATTR_KEY_LENGTH              6 /* B */
526*05b00f60SXin Li #define IPSECDOI_ATTR_KEY_ROUNDS              7 /* B */
527*05b00f60SXin Li #define IPSECDOI_ATTR_COMP_DICT_SIZE          8 /* B */
528*05b00f60SXin Li #define IPSECDOI_ATTR_COMP_PRIVALG            9 /* V */
529*05b00f60SXin Li 
530*05b00f60SXin Li /* 4.6.1 Security Association Payload */
531*05b00f60SXin Li struct ipsecdoi_sa {
532*05b00f60SXin Li 	struct isakmp_gen h;
533*05b00f60SXin Li 	nd_uint32_t doi; /* Domain of Interpretation */
534*05b00f60SXin Li 	nd_uint32_t sit; /* Situation */
535*05b00f60SXin Li };
536*05b00f60SXin Li 
537*05b00f60SXin Li struct ipsecdoi_secrecy_h {
538*05b00f60SXin Li 	nd_uint16_t len;
539*05b00f60SXin Li 	nd_uint16_t reserved;
540*05b00f60SXin Li };
541*05b00f60SXin Li 
542*05b00f60SXin Li /* 4.6.2.1 Identification Type Values */
543*05b00f60SXin Li struct ipsecdoi_id {
544*05b00f60SXin Li 	struct isakmp_gen h;
545*05b00f60SXin Li 	nd_uint8_t  type;	/* ID Type */
546*05b00f60SXin Li 	nd_uint8_t  proto_id;	/* Protocol ID */
547*05b00f60SXin Li 	nd_uint16_t port;	/* Port */
548*05b00f60SXin Li 	/* Identification Data */
549*05b00f60SXin Li };
550*05b00f60SXin Li 
551*05b00f60SXin Li #define IPSECDOI_ID_IPV4_ADDR                        1
552*05b00f60SXin Li #define IPSECDOI_ID_FQDN                             2
553*05b00f60SXin Li #define IPSECDOI_ID_USER_FQDN                        3
554*05b00f60SXin Li #define IPSECDOI_ID_IPV4_ADDR_SUBNET                 4
555*05b00f60SXin Li #define IPSECDOI_ID_IPV6_ADDR                        5
556*05b00f60SXin Li #define IPSECDOI_ID_IPV6_ADDR_SUBNET                 6
557*05b00f60SXin Li #define IPSECDOI_ID_IPV4_ADDR_RANGE                  7
558*05b00f60SXin Li #define IPSECDOI_ID_IPV6_ADDR_RANGE                  8
559*05b00f60SXin Li #define IPSECDOI_ID_DER_ASN1_DN                      9
560*05b00f60SXin Li #define IPSECDOI_ID_DER_ASN1_GN                      10
561*05b00f60SXin Li #define IPSECDOI_ID_KEY_ID                           11
562*05b00f60SXin Li 
563*05b00f60SXin Li /* 4.6.3 IPSEC DOI Notify Message Types */
564*05b00f60SXin Li /* Notify Messages - Status Types */
565*05b00f60SXin Li #define IPSECDOI_NTYPE_RESPONDER_LIFETIME                  24576
566*05b00f60SXin Li #define IPSECDOI_NTYPE_REPLAY_STATUS                       24577
567*05b00f60SXin Li #define IPSECDOI_NTYPE_INITIAL_CONTACT                     24578
568*05b00f60SXin Li 
569*05b00f60SXin Li #define DECLARE_PRINTER(func) static const u_char *ike##func##_print( \
570*05b00f60SXin Li 		netdissect_options *ndo, u_char tpay,	              \
571*05b00f60SXin Li 		const struct isakmp_gen *ext,			      \
572*05b00f60SXin Li 		u_int item_len, \
573*05b00f60SXin Li 		const u_char *end_pointer, \
574*05b00f60SXin Li 		uint32_t phase,\
575*05b00f60SXin Li 		uint32_t doi0, \
576*05b00f60SXin Li 		uint32_t proto0, int depth)
577*05b00f60SXin Li 
578*05b00f60SXin Li DECLARE_PRINTER(v1_sa);
579*05b00f60SXin Li DECLARE_PRINTER(v1_p);
580*05b00f60SXin Li DECLARE_PRINTER(v1_t);
581*05b00f60SXin Li DECLARE_PRINTER(v1_ke);
582*05b00f60SXin Li DECLARE_PRINTER(v1_id);
583*05b00f60SXin Li DECLARE_PRINTER(v1_cert);
584*05b00f60SXin Li DECLARE_PRINTER(v1_cr);
585*05b00f60SXin Li DECLARE_PRINTER(v1_sig);
586*05b00f60SXin Li DECLARE_PRINTER(v1_hash);
587*05b00f60SXin Li DECLARE_PRINTER(v1_nonce);
588*05b00f60SXin Li DECLARE_PRINTER(v1_n);
589*05b00f60SXin Li DECLARE_PRINTER(v1_d);
590*05b00f60SXin Li DECLARE_PRINTER(v1_vid);
591*05b00f60SXin Li 
592*05b00f60SXin Li DECLARE_PRINTER(v2_sa);
593*05b00f60SXin Li DECLARE_PRINTER(v2_ke);
594*05b00f60SXin Li DECLARE_PRINTER(v2_ID);
595*05b00f60SXin Li DECLARE_PRINTER(v2_cert);
596*05b00f60SXin Li DECLARE_PRINTER(v2_cr);
597*05b00f60SXin Li DECLARE_PRINTER(v2_auth);
598*05b00f60SXin Li DECLARE_PRINTER(v2_nonce);
599*05b00f60SXin Li DECLARE_PRINTER(v2_n);
600*05b00f60SXin Li DECLARE_PRINTER(v2_d);
601*05b00f60SXin Li DECLARE_PRINTER(v2_vid);
602*05b00f60SXin Li DECLARE_PRINTER(v2_TS);
603*05b00f60SXin Li DECLARE_PRINTER(v2_cp);
604*05b00f60SXin Li DECLARE_PRINTER(v2_eap);
605*05b00f60SXin Li 
606*05b00f60SXin Li static const u_char *ikev2_e_print(netdissect_options *ndo,
607*05b00f60SXin Li 				   const struct isakmp *base,
608*05b00f60SXin Li 				   u_char tpay,
609*05b00f60SXin Li 				   const struct isakmp_gen *ext,
610*05b00f60SXin Li 				   u_int item_len,
611*05b00f60SXin Li 				   const u_char *end_pointer,
612*05b00f60SXin Li 				   uint32_t phase,
613*05b00f60SXin Li 				   uint32_t doi0,
614*05b00f60SXin Li 				   uint32_t proto0, int depth);
615*05b00f60SXin Li 
616*05b00f60SXin Li 
617*05b00f60SXin Li static const u_char *ike_sub0_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
618*05b00f60SXin Li 	const u_char *,	uint32_t, uint32_t, uint32_t, int);
619*05b00f60SXin Li static const u_char *ikev1_sub_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
620*05b00f60SXin Li 	const u_char *, uint32_t, uint32_t, uint32_t, int);
621*05b00f60SXin Li 
622*05b00f60SXin Li static const u_char *ikev2_sub_print(netdissect_options *ndo,
623*05b00f60SXin Li 				     const struct isakmp *base,
624*05b00f60SXin Li 				     u_char np, const struct isakmp_gen *ext,
625*05b00f60SXin Li 				     const u_char *ep, uint32_t phase,
626*05b00f60SXin Li 				     uint32_t doi, uint32_t proto,
627*05b00f60SXin Li 				     int depth);
628*05b00f60SXin Li 
629*05b00f60SXin Li 
630*05b00f60SXin Li static char *numstr(u_int);
631*05b00f60SXin Li 
632*05b00f60SXin Li static void
633*05b00f60SXin Li ikev1_print(netdissect_options *ndo,
634*05b00f60SXin Li 	    const u_char *bp,  u_int length,
635*05b00f60SXin Li 	    const u_char *bp2, const struct isakmp *base);
636*05b00f60SXin Li 
637*05b00f60SXin Li #define MAXINITIATORS	20
638*05b00f60SXin Li static int ninitiator = 0;
639*05b00f60SXin Li union inaddr_u {
640*05b00f60SXin Li 	nd_ipv4 in4;
641*05b00f60SXin Li 	nd_ipv6 in6;
642*05b00f60SXin Li };
643*05b00f60SXin Li static struct {
644*05b00f60SXin Li 	cookie_t initiator;
645*05b00f60SXin Li 	u_int version;
646*05b00f60SXin Li 	union inaddr_u iaddr;
647*05b00f60SXin Li 	union inaddr_u raddr;
648*05b00f60SXin Li } cookiecache[MAXINITIATORS];
649*05b00f60SXin Li 
650*05b00f60SXin Li /* protocol id */
651*05b00f60SXin Li static const char *protoidstr[] = {
652*05b00f60SXin Li 	NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
653*05b00f60SXin Li };
654*05b00f60SXin Li 
655*05b00f60SXin Li /* isakmp->np */
656*05b00f60SXin Li static const char *npstr[] = {
657*05b00f60SXin Li 	"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash", /* 0 - 8 */
658*05b00f60SXin Li 	"sig", "nonce", "n", "d", "vid",      /* 9 - 13 */
659*05b00f60SXin Li 	"pay14", "pay15", "pay16", "pay17", "pay18", /* 14- 18 */
660*05b00f60SXin Li 	"pay19", "pay20", "pay21", "pay22", "pay23", /* 19- 23 */
661*05b00f60SXin Li 	"pay24", "pay25", "pay26", "pay27", "pay28", /* 24- 28 */
662*05b00f60SXin Li 	"pay29", "pay30", "pay31", "pay32",          /* 29- 32 */
663*05b00f60SXin Li 	"v2sa",  "v2ke",  "v2IDi", "v2IDr", "v2cert",/* 33- 37 */
664*05b00f60SXin Li 	"v2cr",  "v2auth","v2nonce", "v2n",   "v2d",   /* 38- 42 */
665*05b00f60SXin Li 	"v2vid", "v2TSi", "v2TSr", "v2e",   "v2cp",  /* 43- 47 */
666*05b00f60SXin Li 	"v2eap",                                     /* 48 */
667*05b00f60SXin Li 
668*05b00f60SXin Li };
669*05b00f60SXin Li 
670*05b00f60SXin Li /* isakmp->np */
671*05b00f60SXin Li static const u_char *(*npfunc[])(netdissect_options *ndo, u_char tpay,
672*05b00f60SXin Li 				 const struct isakmp_gen *ext,
673*05b00f60SXin Li 				 u_int item_len,
674*05b00f60SXin Li 				 const u_char *end_pointer,
675*05b00f60SXin Li 				 uint32_t phase,
676*05b00f60SXin Li 				 uint32_t doi0,
677*05b00f60SXin Li 				 uint32_t proto0, int depth) = {
678*05b00f60SXin Li 	NULL,
679*05b00f60SXin Li 	ikev1_sa_print,
680*05b00f60SXin Li 	ikev1_p_print,
681*05b00f60SXin Li 	ikev1_t_print,
682*05b00f60SXin Li 	ikev1_ke_print,
683*05b00f60SXin Li 	ikev1_id_print,
684*05b00f60SXin Li 	ikev1_cert_print,
685*05b00f60SXin Li 	ikev1_cr_print,
686*05b00f60SXin Li 	ikev1_hash_print,
687*05b00f60SXin Li 	ikev1_sig_print,
688*05b00f60SXin Li 	ikev1_nonce_print,
689*05b00f60SXin Li 	ikev1_n_print,
690*05b00f60SXin Li 	ikev1_d_print,
691*05b00f60SXin Li 	ikev1_vid_print,                  /* 13 */
692*05b00f60SXin Li 	NULL, NULL, NULL, NULL, NULL,     /* 14- 18 */
693*05b00f60SXin Li 	NULL, NULL, NULL, NULL, NULL,     /* 19- 23 */
694*05b00f60SXin Li 	NULL, NULL, NULL, NULL, NULL,     /* 24- 28 */
695*05b00f60SXin Li 	NULL, NULL, NULL, NULL,           /* 29- 32 */
696*05b00f60SXin Li 	ikev2_sa_print,                 /* 33 */
697*05b00f60SXin Li 	ikev2_ke_print,                 /* 34 */
698*05b00f60SXin Li 	ikev2_ID_print,                 /* 35 */
699*05b00f60SXin Li 	ikev2_ID_print,                 /* 36 */
700*05b00f60SXin Li 	ikev2_cert_print,               /* 37 */
701*05b00f60SXin Li 	ikev2_cr_print,                 /* 38 */
702*05b00f60SXin Li 	ikev2_auth_print,               /* 39 */
703*05b00f60SXin Li 	ikev2_nonce_print,              /* 40 */
704*05b00f60SXin Li 	ikev2_n_print,                  /* 41 */
705*05b00f60SXin Li 	ikev2_d_print,                  /* 42 */
706*05b00f60SXin Li 	ikev2_vid_print,                /* 43 */
707*05b00f60SXin Li 	ikev2_TS_print,                 /* 44 */
708*05b00f60SXin Li 	ikev2_TS_print,                 /* 45 */
709*05b00f60SXin Li 	NULL, /* ikev2_e_print,*/       /* 46 - special */
710*05b00f60SXin Li 	ikev2_cp_print,                 /* 47 */
711*05b00f60SXin Li 	ikev2_eap_print,                /* 48 */
712*05b00f60SXin Li };
713*05b00f60SXin Li 
714*05b00f60SXin Li /* isakmp->etype */
715*05b00f60SXin Li static const char *etypestr[] = {
716*05b00f60SXin Li /* IKEv1 exchange types */
717*05b00f60SXin Li 	"none", "base", "ident", "auth", "agg", "inf", NULL, NULL,  /* 0-7 */
718*05b00f60SXin Li 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /*  8-15 */
719*05b00f60SXin Li 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /* 16-23 */
720*05b00f60SXin Li 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  /* 24-31 */
721*05b00f60SXin Li 	"oakley-quick", "oakley-newgroup",               /* 32-33 */
722*05b00f60SXin Li /* IKEv2 exchange types */
723*05b00f60SXin Li 	"ikev2_init", "ikev2_auth", "child_sa", "inf2"   /* 34-37 */
724*05b00f60SXin Li };
725*05b00f60SXin Li 
726*05b00f60SXin Li #define STR_OR_ID(x, tab) \
727*05b00f60SXin Li 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)])	? tab[(x)] : numstr(x))
728*05b00f60SXin Li #define PROTOIDSTR(x)	STR_OR_ID(x, protoidstr)
729*05b00f60SXin Li #define NPSTR(x)	STR_OR_ID(x, npstr)
730*05b00f60SXin Li #define ETYPESTR(x)	STR_OR_ID(x, etypestr)
731*05b00f60SXin Li 
732*05b00f60SXin Li #define CHECKLEN(p, np)							\
733*05b00f60SXin Li 		if (ep < (const u_char *)(p)) {				\
734*05b00f60SXin Li 			ND_PRINT(" [|%s]", NPSTR(np));		\
735*05b00f60SXin Li 			goto done;					\
736*05b00f60SXin Li 		}
737*05b00f60SXin Li 
738*05b00f60SXin Li 
739*05b00f60SXin Li #define NPFUNC(x) \
740*05b00f60SXin Li 	(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
741*05b00f60SXin Li 		? npfunc[(x)] : NULL)
742*05b00f60SXin Li 
743*05b00f60SXin Li static int
iszero(netdissect_options * ndo,const u_char * p,size_t l)744*05b00f60SXin Li iszero(netdissect_options *ndo, const u_char *p, size_t l)
745*05b00f60SXin Li {
746*05b00f60SXin Li 	while (l != 0) {
747*05b00f60SXin Li 		if (GET_U_1(p))
748*05b00f60SXin Li 			return 0;
749*05b00f60SXin Li 		p++;
750*05b00f60SXin Li 		l--;
751*05b00f60SXin Li 	}
752*05b00f60SXin Li 	return 1;
753*05b00f60SXin Li }
754*05b00f60SXin Li 
755*05b00f60SXin Li /* find cookie from initiator cache */
756*05b00f60SXin Li static int
cookie_find(const cookie_t * in)757*05b00f60SXin Li cookie_find(const cookie_t *in)
758*05b00f60SXin Li {
759*05b00f60SXin Li 	int i;
760*05b00f60SXin Li 
761*05b00f60SXin Li 	for (i = 0; i < MAXINITIATORS; i++) {
762*05b00f60SXin Li 		if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
763*05b00f60SXin Li 			return i;
764*05b00f60SXin Li 	}
765*05b00f60SXin Li 
766*05b00f60SXin Li 	return -1;
767*05b00f60SXin Li }
768*05b00f60SXin Li 
769*05b00f60SXin Li /* record initiator */
770*05b00f60SXin Li static void
cookie_record(netdissect_options * ndo,const cookie_t * in,const u_char * bp2)771*05b00f60SXin Li cookie_record(netdissect_options *ndo, const cookie_t *in, const u_char *bp2)
772*05b00f60SXin Li {
773*05b00f60SXin Li 	int i;
774*05b00f60SXin Li 	const struct ip *ip;
775*05b00f60SXin Li 	const struct ip6_hdr *ip6;
776*05b00f60SXin Li 
777*05b00f60SXin Li 	i = cookie_find(in);
778*05b00f60SXin Li 	if (0 <= i) {
779*05b00f60SXin Li 		ninitiator = (i + 1) % MAXINITIATORS;
780*05b00f60SXin Li 		return;
781*05b00f60SXin Li 	}
782*05b00f60SXin Li 
783*05b00f60SXin Li 	ip = (const struct ip *)bp2;
784*05b00f60SXin Li 	switch (IP_V(ip)) {
785*05b00f60SXin Li 	case 4:
786*05b00f60SXin Li 		cookiecache[ninitiator].version = 4;
787*05b00f60SXin Li 		UNALIGNED_MEMCPY(&cookiecache[ninitiator].iaddr.in4,
788*05b00f60SXin Li 				 ip->ip_src, sizeof(nd_ipv4));
789*05b00f60SXin Li 		UNALIGNED_MEMCPY(&cookiecache[ninitiator].raddr.in4,
790*05b00f60SXin Li 				 ip->ip_dst, sizeof(nd_ipv4));
791*05b00f60SXin Li 		break;
792*05b00f60SXin Li 	case 6:
793*05b00f60SXin Li 		ip6 = (const struct ip6_hdr *)bp2;
794*05b00f60SXin Li 		cookiecache[ninitiator].version = 6;
795*05b00f60SXin Li 		UNALIGNED_MEMCPY(&cookiecache[ninitiator].iaddr.in6,
796*05b00f60SXin Li 				 ip6->ip6_src, sizeof(nd_ipv6));
797*05b00f60SXin Li 		UNALIGNED_MEMCPY(&cookiecache[ninitiator].raddr.in6,
798*05b00f60SXin Li 				 ip6->ip6_dst, sizeof(nd_ipv6));
799*05b00f60SXin Li 		break;
800*05b00f60SXin Li 	default:
801*05b00f60SXin Li 		return;
802*05b00f60SXin Li 	}
803*05b00f60SXin Li 	UNALIGNED_MEMCPY(&cookiecache[ninitiator].initiator, in, sizeof(*in));
804*05b00f60SXin Li 	ninitiator = (ninitiator + 1) % MAXINITIATORS;
805*05b00f60SXin Li }
806*05b00f60SXin Li 
807*05b00f60SXin Li #define cookie_isinitiator(ndo, x, y)	cookie_sidecheck(ndo, (x), (y), 1)
808*05b00f60SXin Li #define cookie_isresponder(ndo, x, y)	cookie_sidecheck(ndo, (x), (y), 0)
809*05b00f60SXin Li static int
cookie_sidecheck(netdissect_options * ndo,int i,const u_char * bp2,int initiator)810*05b00f60SXin Li cookie_sidecheck(netdissect_options *ndo, int i, const u_char *bp2, int initiator)
811*05b00f60SXin Li {
812*05b00f60SXin Li 	const struct ip *ip;
813*05b00f60SXin Li 	const struct ip6_hdr *ip6;
814*05b00f60SXin Li 
815*05b00f60SXin Li 	ip = (const struct ip *)bp2;
816*05b00f60SXin Li 	switch (IP_V(ip)) {
817*05b00f60SXin Li 	case 4:
818*05b00f60SXin Li 		if (cookiecache[i].version != 4)
819*05b00f60SXin Li 			return 0;
820*05b00f60SXin Li 		if (initiator) {
821*05b00f60SXin Li 			if (UNALIGNED_MEMCMP(ip->ip_src, &cookiecache[i].iaddr.in4, sizeof(nd_ipv4)) == 0)
822*05b00f60SXin Li 				return 1;
823*05b00f60SXin Li 		} else {
824*05b00f60SXin Li 			if (UNALIGNED_MEMCMP(ip->ip_src, &cookiecache[i].raddr.in4, sizeof(nd_ipv4)) == 0)
825*05b00f60SXin Li 				return 1;
826*05b00f60SXin Li 		}
827*05b00f60SXin Li 		break;
828*05b00f60SXin Li 	case 6:
829*05b00f60SXin Li 		if (cookiecache[i].version != 6)
830*05b00f60SXin Li 			return 0;
831*05b00f60SXin Li 		ip6 = (const struct ip6_hdr *)bp2;
832*05b00f60SXin Li 		if (initiator) {
833*05b00f60SXin Li 			if (UNALIGNED_MEMCMP(ip6->ip6_src, &cookiecache[i].iaddr.in6, sizeof(nd_ipv6)) == 0)
834*05b00f60SXin Li 				return 1;
835*05b00f60SXin Li 		} else {
836*05b00f60SXin Li 			if (UNALIGNED_MEMCMP(ip6->ip6_src, &cookiecache[i].raddr.in6, sizeof(nd_ipv6)) == 0)
837*05b00f60SXin Li 				return 1;
838*05b00f60SXin Li 		}
839*05b00f60SXin Li 		break;
840*05b00f60SXin Li 	default:
841*05b00f60SXin Li 		break;
842*05b00f60SXin Li 	}
843*05b00f60SXin Li 
844*05b00f60SXin Li 	return 0;
845*05b00f60SXin Li }
846*05b00f60SXin Li 
847*05b00f60SXin Li static void
hexprint(netdissect_options * ndo,const uint8_t * loc,size_t len)848*05b00f60SXin Li hexprint(netdissect_options *ndo, const uint8_t *loc, size_t len)
849*05b00f60SXin Li {
850*05b00f60SXin Li 	const uint8_t *p;
851*05b00f60SXin Li 	size_t i;
852*05b00f60SXin Li 
853*05b00f60SXin Li 	p = loc;
854*05b00f60SXin Li 	for (i = 0; i < len; i++)
855*05b00f60SXin Li 		ND_PRINT("%02x", p[i] & 0xff);
856*05b00f60SXin Li }
857*05b00f60SXin Li 
858*05b00f60SXin Li static int
rawprint(netdissect_options * ndo,const uint8_t * loc,size_t len)859*05b00f60SXin Li rawprint(netdissect_options *ndo, const uint8_t *loc, size_t len)
860*05b00f60SXin Li {
861*05b00f60SXin Li 	ND_TCHECK_LEN(loc, len);
862*05b00f60SXin Li 
863*05b00f60SXin Li 	hexprint(ndo, loc, len);
864*05b00f60SXin Li 	return 1;
865*05b00f60SXin Li trunc:
866*05b00f60SXin Li 	return 0;
867*05b00f60SXin Li }
868*05b00f60SXin Li 
869*05b00f60SXin Li 
870*05b00f60SXin Li /*
871*05b00f60SXin Li  * returns false if we run out of data buffer
872*05b00f60SXin Li  */
ike_show_somedata(netdissect_options * ndo,const u_char * cp,const u_char * ep)873*05b00f60SXin Li static int ike_show_somedata(netdissect_options *ndo,
874*05b00f60SXin Li 			     const u_char *cp, const u_char *ep)
875*05b00f60SXin Li {
876*05b00f60SXin Li 	/* there is too much data, just show some of it */
877*05b00f60SXin Li 	const u_char *end = ep - 20;
878*05b00f60SXin Li 	size_t  elen = 20;
879*05b00f60SXin Li 	size_t  len = ep - cp;
880*05b00f60SXin Li 	if(len > 10) {
881*05b00f60SXin Li 		len = 10;
882*05b00f60SXin Li 	}
883*05b00f60SXin Li 
884*05b00f60SXin Li 	/* really shouldn't happen because of above */
885*05b00f60SXin Li 	if(end < cp + len) {
886*05b00f60SXin Li 		end = cp+len;
887*05b00f60SXin Li 		elen = ep - end;
888*05b00f60SXin Li 	}
889*05b00f60SXin Li 
890*05b00f60SXin Li 	ND_PRINT(" data=(");
891*05b00f60SXin Li 	if(!rawprint(ndo, (const uint8_t *)(cp), len)) goto trunc;
892*05b00f60SXin Li 	ND_PRINT("...");
893*05b00f60SXin Li 	if(elen) {
894*05b00f60SXin Li 		if(!rawprint(ndo, (const uint8_t *)(end), elen)) goto trunc;
895*05b00f60SXin Li 	}
896*05b00f60SXin Li 	ND_PRINT(")");
897*05b00f60SXin Li 	return 1;
898*05b00f60SXin Li 
899*05b00f60SXin Li trunc:
900*05b00f60SXin Li 	return 0;
901*05b00f60SXin Li }
902*05b00f60SXin Li 
903*05b00f60SXin Li struct attrmap {
904*05b00f60SXin Li 	const char *type;
905*05b00f60SXin Li 	u_int nvalue;
906*05b00f60SXin Li 	const char *value[30];	/*XXX*/
907*05b00f60SXin Li };
908*05b00f60SXin Li 
909*05b00f60SXin Li static const u_char *
ikev1_attrmap_print(netdissect_options * ndo,const u_char * p,const u_char * ep2,const struct attrmap * map,size_t nmap)910*05b00f60SXin Li ikev1_attrmap_print(netdissect_options *ndo,
911*05b00f60SXin Li 		    const u_char *p, const u_char *ep2,
912*05b00f60SXin Li 		    const struct attrmap *map, size_t nmap)
913*05b00f60SXin Li {
914*05b00f60SXin Li 	u_int totlen;
915*05b00f60SXin Li 	uint32_t t, v;
916*05b00f60SXin Li 
917*05b00f60SXin Li 	if (GET_U_1(p) & 0x80)
918*05b00f60SXin Li 		totlen = 4;
919*05b00f60SXin Li 	else {
920*05b00f60SXin Li 		totlen = 4 + GET_BE_U_2(p + 2);
921*05b00f60SXin Li 	}
922*05b00f60SXin Li 	if (ep2 < p + totlen) {
923*05b00f60SXin Li 		ND_PRINT("[|attr]");
924*05b00f60SXin Li 		return ep2 + 1;
925*05b00f60SXin Li 	}
926*05b00f60SXin Li 
927*05b00f60SXin Li 	ND_PRINT("(");
928*05b00f60SXin Li 	t = GET_BE_U_2(p) & 0x7fff;
929*05b00f60SXin Li 	if (map && t < nmap && map[t].type)
930*05b00f60SXin Li 		ND_PRINT("type=%s ", map[t].type);
931*05b00f60SXin Li 	else
932*05b00f60SXin Li 		ND_PRINT("type=#%u ", t);
933*05b00f60SXin Li 	if (GET_U_1(p) & 0x80) {
934*05b00f60SXin Li 		ND_PRINT("value=");
935*05b00f60SXin Li 		v = GET_BE_U_2(p + 2);
936*05b00f60SXin Li 		if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
937*05b00f60SXin Li 			ND_PRINT("%s", map[t].value[v]);
938*05b00f60SXin Li 		else {
939*05b00f60SXin Li 			if (!rawprint(ndo, (const uint8_t *)(p + 2), 2)) {
940*05b00f60SXin Li 				ND_PRINT(")");
941*05b00f60SXin Li 				goto trunc;
942*05b00f60SXin Li 			}
943*05b00f60SXin Li 		}
944*05b00f60SXin Li 	} else {
945*05b00f60SXin Li 		ND_PRINT("len=%u value=", totlen - 4);
946*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(p + 4), totlen - 4)) {
947*05b00f60SXin Li 			ND_PRINT(")");
948*05b00f60SXin Li 			goto trunc;
949*05b00f60SXin Li 		}
950*05b00f60SXin Li 	}
951*05b00f60SXin Li 	ND_PRINT(")");
952*05b00f60SXin Li 	return p + totlen;
953*05b00f60SXin Li 
954*05b00f60SXin Li trunc:
955*05b00f60SXin Li 	return NULL;
956*05b00f60SXin Li }
957*05b00f60SXin Li 
958*05b00f60SXin Li static const u_char *
ikev1_attr_print(netdissect_options * ndo,const u_char * p,const u_char * ep2)959*05b00f60SXin Li ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep2)
960*05b00f60SXin Li {
961*05b00f60SXin Li 	u_int totlen;
962*05b00f60SXin Li 	uint32_t t;
963*05b00f60SXin Li 
964*05b00f60SXin Li 	if (GET_U_1(p) & 0x80)
965*05b00f60SXin Li 		totlen = 4;
966*05b00f60SXin Li 	else {
967*05b00f60SXin Li 		totlen = 4 + GET_BE_U_2(p + 2);
968*05b00f60SXin Li 	}
969*05b00f60SXin Li 	if (ep2 < p + totlen) {
970*05b00f60SXin Li 		ND_PRINT("[|attr]");
971*05b00f60SXin Li 		return ep2 + 1;
972*05b00f60SXin Li 	}
973*05b00f60SXin Li 
974*05b00f60SXin Li 	ND_PRINT("(");
975*05b00f60SXin Li 	t = GET_BE_U_2(p) & 0x7fff;
976*05b00f60SXin Li 	ND_PRINT("type=#%u ", t);
977*05b00f60SXin Li 	if (GET_U_1(p) & 0x80) {
978*05b00f60SXin Li 		ND_PRINT("value=");
979*05b00f60SXin Li 		t = GET_U_1(p + 2);
980*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(p + 2), 2)) {
981*05b00f60SXin Li 			ND_PRINT(")");
982*05b00f60SXin Li 			goto trunc;
983*05b00f60SXin Li 		}
984*05b00f60SXin Li 	} else {
985*05b00f60SXin Li 		ND_PRINT("len=%u value=", totlen - 4);
986*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(p + 4), totlen - 4)) {
987*05b00f60SXin Li 			ND_PRINT(")");
988*05b00f60SXin Li 			goto trunc;
989*05b00f60SXin Li 		}
990*05b00f60SXin Li 	}
991*05b00f60SXin Li 	ND_PRINT(")");
992*05b00f60SXin Li 	return p + totlen;
993*05b00f60SXin Li 
994*05b00f60SXin Li trunc:
995*05b00f60SXin Li 	return NULL;
996*05b00f60SXin Li }
997*05b00f60SXin Li 
998*05b00f60SXin Li static const u_char *
ikev1_sa_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep,uint32_t phase,uint32_t doi0 _U_,uint32_t proto0,int depth)999*05b00f60SXin Li ikev1_sa_print(netdissect_options *ndo, u_char tpay _U_,
1000*05b00f60SXin Li 	       const struct isakmp_gen *ext,
1001*05b00f60SXin Li 		u_int item_len _U_,
1002*05b00f60SXin Li 		const u_char *ep, uint32_t phase, uint32_t doi0 _U_,
1003*05b00f60SXin Li 		uint32_t proto0, int depth)
1004*05b00f60SXin Li {
1005*05b00f60SXin Li 	const struct ikev1_pl_sa *p;
1006*05b00f60SXin Li 	uint32_t doi, sit, ident;
1007*05b00f60SXin Li 	const u_char *cp, *np;
1008*05b00f60SXin Li 	int t;
1009*05b00f60SXin Li 
1010*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_SA));
1011*05b00f60SXin Li 
1012*05b00f60SXin Li 	p = (const struct ikev1_pl_sa *)ext;
1013*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1014*05b00f60SXin Li 	doi = GET_BE_U_4(p->doi);
1015*05b00f60SXin Li 	sit = GET_BE_U_4(p->sit);
1016*05b00f60SXin Li 	if (doi != 1) {
1017*05b00f60SXin Li 		ND_PRINT(" doi=%u", doi);
1018*05b00f60SXin Li 		ND_PRINT(" situation=%u", sit);
1019*05b00f60SXin Li 		return (const u_char *)(p + 1);
1020*05b00f60SXin Li 	}
1021*05b00f60SXin Li 
1022*05b00f60SXin Li 	ND_PRINT(" doi=ipsec");
1023*05b00f60SXin Li 	ND_PRINT(" situation=");
1024*05b00f60SXin Li 	t = 0;
1025*05b00f60SXin Li 	if (sit & 0x01) {
1026*05b00f60SXin Li 		ND_PRINT("identity");
1027*05b00f60SXin Li 		t++;
1028*05b00f60SXin Li 	}
1029*05b00f60SXin Li 	if (sit & 0x02) {
1030*05b00f60SXin Li 		ND_PRINT("%ssecrecy", t ? "+" : "");
1031*05b00f60SXin Li 		t++;
1032*05b00f60SXin Li 	}
1033*05b00f60SXin Li 	if (sit & 0x04)
1034*05b00f60SXin Li 		ND_PRINT("%sintegrity", t ? "+" : "");
1035*05b00f60SXin Li 
1036*05b00f60SXin Li 	np = (const u_char *)ext + sizeof(struct ikev1_pl_sa);
1037*05b00f60SXin Li 	if (sit != 0x01) {
1038*05b00f60SXin Li 		ident = GET_BE_U_4(ext + 1);
1039*05b00f60SXin Li 		ND_PRINT(" ident=%u", ident);
1040*05b00f60SXin Li 		np += sizeof(ident);
1041*05b00f60SXin Li 	}
1042*05b00f60SXin Li 
1043*05b00f60SXin Li 	ext = (const struct isakmp_gen *)np;
1044*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1045*05b00f60SXin Li 
1046*05b00f60SXin Li 	cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
1047*05b00f60SXin Li 		depth);
1048*05b00f60SXin Li 
1049*05b00f60SXin Li 	return cp;
1050*05b00f60SXin Li trunc:
1051*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
1052*05b00f60SXin Li 	return NULL;
1053*05b00f60SXin Li }
1054*05b00f60SXin Li 
1055*05b00f60SXin Li static const u_char *
ikev1_p_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep,uint32_t phase,uint32_t doi0,uint32_t proto0 _U_,int depth)1056*05b00f60SXin Li ikev1_p_print(netdissect_options *ndo, u_char tpay _U_,
1057*05b00f60SXin Li 	      const struct isakmp_gen *ext, u_int item_len _U_,
1058*05b00f60SXin Li 	       const u_char *ep, uint32_t phase, uint32_t doi0,
1059*05b00f60SXin Li 	       uint32_t proto0 _U_, int depth)
1060*05b00f60SXin Li {
1061*05b00f60SXin Li 	const struct ikev1_pl_p *p;
1062*05b00f60SXin Li 	const u_char *cp;
1063*05b00f60SXin Li 	uint8_t spi_size;
1064*05b00f60SXin Li 
1065*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_P));
1066*05b00f60SXin Li 
1067*05b00f60SXin Li 	p = (const struct ikev1_pl_p *)ext;
1068*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1069*05b00f60SXin Li 	ND_PRINT(" #%u protoid=%s transform=%u",
1070*05b00f60SXin Li 		  GET_U_1(p->p_no), PROTOIDSTR(GET_U_1(p->prot_id)),
1071*05b00f60SXin Li 		  GET_U_1(p->num_t));
1072*05b00f60SXin Li 	spi_size = GET_U_1(p->spi_size);
1073*05b00f60SXin Li 	if (spi_size) {
1074*05b00f60SXin Li 		ND_PRINT(" spi=");
1075*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
1076*05b00f60SXin Li 			goto trunc;
1077*05b00f60SXin Li 	}
1078*05b00f60SXin Li 
1079*05b00f60SXin Li 	ext = (const struct isakmp_gen *)((const u_char *)(p + 1) + spi_size);
1080*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1081*05b00f60SXin Li 
1082*05b00f60SXin Li 	cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
1083*05b00f60SXin Li 			     GET_U_1(p->prot_id), depth);
1084*05b00f60SXin Li 
1085*05b00f60SXin Li 	return cp;
1086*05b00f60SXin Li trunc:
1087*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
1088*05b00f60SXin Li 	return NULL;
1089*05b00f60SXin Li }
1090*05b00f60SXin Li 
1091*05b00f60SXin Li static const char *ikev1_p_map[] = {
1092*05b00f60SXin Li 	NULL, "ike",
1093*05b00f60SXin Li };
1094*05b00f60SXin Li 
1095*05b00f60SXin Li static const char *ikev2_t_type_map[]={
1096*05b00f60SXin Li 	NULL, "encr", "prf", "integ", "dh", "esn"
1097*05b00f60SXin Li };
1098*05b00f60SXin Li 
1099*05b00f60SXin Li static const char *ah_p_map[] = {
1100*05b00f60SXin Li 	NULL, "(reserved)", "md5", "sha", "1des",
1101*05b00f60SXin Li 	"sha2-256", "sha2-384", "sha2-512",
1102*05b00f60SXin Li };
1103*05b00f60SXin Li 
1104*05b00f60SXin Li static const char *prf_p_map[] = {
1105*05b00f60SXin Li 	NULL, "hmac-md5", "hmac-sha", "hmac-tiger",
1106*05b00f60SXin Li 	"aes128_xcbc"
1107*05b00f60SXin Li };
1108*05b00f60SXin Li 
1109*05b00f60SXin Li static const char *integ_p_map[] = {
1110*05b00f60SXin Li 	NULL, "hmac-md5", "hmac-sha", "dec-mac",
1111*05b00f60SXin Li 	"kpdk-md5", "aes-xcbc"
1112*05b00f60SXin Li };
1113*05b00f60SXin Li 
1114*05b00f60SXin Li static const char *esn_p_map[] = {
1115*05b00f60SXin Li 	"no-esn", "esn"
1116*05b00f60SXin Li };
1117*05b00f60SXin Li 
1118*05b00f60SXin Li static const char *dh_p_map[] = {
1119*05b00f60SXin Li 	NULL, "modp768",
1120*05b00f60SXin Li 	"modp1024",    /* group 2 */
1121*05b00f60SXin Li 	"EC2N 2^155",  /* group 3 */
1122*05b00f60SXin Li 	"EC2N 2^185",  /* group 4 */
1123*05b00f60SXin Li 	"modp1536",    /* group 5 */
1124*05b00f60SXin Li 	"iana-grp06", "iana-grp07", /* reserved */
1125*05b00f60SXin Li 	"iana-grp08", "iana-grp09",
1126*05b00f60SXin Li 	"iana-grp10", "iana-grp11",
1127*05b00f60SXin Li 	"iana-grp12", "iana-grp13",
1128*05b00f60SXin Li 	"modp2048",    /* group 14 */
1129*05b00f60SXin Li 	"modp3072",    /* group 15 */
1130*05b00f60SXin Li 	"modp4096",    /* group 16 */
1131*05b00f60SXin Li 	"modp6144",    /* group 17 */
1132*05b00f60SXin Li 	"modp8192",    /* group 18 */
1133*05b00f60SXin Li };
1134*05b00f60SXin Li 
1135*05b00f60SXin Li static const char *esp_p_map[] = {
1136*05b00f60SXin Li 	NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
1137*05b00f60SXin Li 	"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
1138*05b00f60SXin Li };
1139*05b00f60SXin Li 
1140*05b00f60SXin Li static const char *ipcomp_p_map[] = {
1141*05b00f60SXin Li 	NULL, "oui", "deflate", "lzs",
1142*05b00f60SXin Li };
1143*05b00f60SXin Li 
1144*05b00f60SXin Li static const struct attrmap ipsec_t_map[] = {
1145*05b00f60SXin Li 	{ NULL,	0, { NULL } },
1146*05b00f60SXin Li 	{ "lifetype", 3, { NULL, "sec", "kb", }, },
1147*05b00f60SXin Li 	{ "life", 0, { NULL } },
1148*05b00f60SXin Li 	{ "group desc", 18,	{ NULL, "modp768",
1149*05b00f60SXin Li 				  "modp1024",    /* group 2 */
1150*05b00f60SXin Li 				  "EC2N 2^155",  /* group 3 */
1151*05b00f60SXin Li 				  "EC2N 2^185",  /* group 4 */
1152*05b00f60SXin Li 				  "modp1536",    /* group 5 */
1153*05b00f60SXin Li 				  "iana-grp06", "iana-grp07", /* reserved */
1154*05b00f60SXin Li 				  "iana-grp08", "iana-grp09",
1155*05b00f60SXin Li 				  "iana-grp10", "iana-grp11",
1156*05b00f60SXin Li 				  "iana-grp12", "iana-grp13",
1157*05b00f60SXin Li 				  "modp2048",    /* group 14 */
1158*05b00f60SXin Li 				  "modp3072",    /* group 15 */
1159*05b00f60SXin Li 				  "modp4096",    /* group 16 */
1160*05b00f60SXin Li 				  "modp6144",    /* group 17 */
1161*05b00f60SXin Li 				  "modp8192",    /* group 18 */
1162*05b00f60SXin Li 		}, },
1163*05b00f60SXin Li 	{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
1164*05b00f60SXin Li 	{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
1165*05b00f60SXin Li 	{ "keylen", 0, { NULL } },
1166*05b00f60SXin Li 	{ "rounds", 0, { NULL } },
1167*05b00f60SXin Li 	{ "dictsize", 0, { NULL } },
1168*05b00f60SXin Li 	{ "privalg", 0, { NULL } },
1169*05b00f60SXin Li };
1170*05b00f60SXin Li 
1171*05b00f60SXin Li static const struct attrmap encr_t_map[] = {
1172*05b00f60SXin Li 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 0, 1 */
1173*05b00f60SXin Li 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 2, 3 */
1174*05b00f60SXin Li 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 4, 5 */
1175*05b00f60SXin Li 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 6, 7 */
1176*05b00f60SXin Li 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 8, 9 */
1177*05b00f60SXin Li 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 10,11*/
1178*05b00f60SXin Li 	{ NULL,	0, { NULL } },	{ NULL,	0, { NULL } },  /* 12,13*/
1179*05b00f60SXin Li 	{ "keylen", 14, { NULL }},
1180*05b00f60SXin Li };
1181*05b00f60SXin Li 
1182*05b00f60SXin Li static const struct attrmap oakley_t_map[] = {
1183*05b00f60SXin Li 	{ NULL,	0, { NULL } },
1184*05b00f60SXin Li 	{ "enc", 8,	{ NULL, "1des", "idea", "blowfish", "rc5",
1185*05b00f60SXin Li 			  "3des", "cast", "aes", }, },
1186*05b00f60SXin Li 	{ "hash", 7,	{ NULL, "md5", "sha1", "tiger",
1187*05b00f60SXin Li 			  "sha2-256", "sha2-384", "sha2-512", }, },
1188*05b00f60SXin Li 	{ "auth", 6,	{ NULL, "preshared", "dss", "rsa sig", "rsa enc",
1189*05b00f60SXin Li 			  "rsa enc revised", }, },
1190*05b00f60SXin Li 	{ "group desc", 18,	{ NULL, "modp768",
1191*05b00f60SXin Li 				  "modp1024",    /* group 2 */
1192*05b00f60SXin Li 				  "EC2N 2^155",  /* group 3 */
1193*05b00f60SXin Li 				  "EC2N 2^185",  /* group 4 */
1194*05b00f60SXin Li 				  "modp1536",    /* group 5 */
1195*05b00f60SXin Li 				  "iana-grp06", "iana-grp07", /* reserved */
1196*05b00f60SXin Li 				  "iana-grp08", "iana-grp09",
1197*05b00f60SXin Li 				  "iana-grp10", "iana-grp11",
1198*05b00f60SXin Li 				  "iana-grp12", "iana-grp13",
1199*05b00f60SXin Li 				  "modp2048",    /* group 14 */
1200*05b00f60SXin Li 				  "modp3072",    /* group 15 */
1201*05b00f60SXin Li 				  "modp4096",    /* group 16 */
1202*05b00f60SXin Li 				  "modp6144",    /* group 17 */
1203*05b00f60SXin Li 				  "modp8192",    /* group 18 */
1204*05b00f60SXin Li 		}, },
1205*05b00f60SXin Li 	{ "group type", 4,	{ NULL, "MODP", "ECP", "EC2N", }, },
1206*05b00f60SXin Li 	{ "group prime", 0, { NULL } },
1207*05b00f60SXin Li 	{ "group gen1", 0, { NULL } },
1208*05b00f60SXin Li 	{ "group gen2", 0, { NULL } },
1209*05b00f60SXin Li 	{ "group curve A", 0, { NULL } },
1210*05b00f60SXin Li 	{ "group curve B", 0, { NULL } },
1211*05b00f60SXin Li 	{ "lifetype", 3,	{ NULL, "sec", "kb", }, },
1212*05b00f60SXin Li 	{ "lifeduration", 0, { NULL } },
1213*05b00f60SXin Li 	{ "prf", 0, { NULL } },
1214*05b00f60SXin Li 	{ "keylen", 0, { NULL } },
1215*05b00f60SXin Li 	{ "field", 0, { NULL } },
1216*05b00f60SXin Li 	{ "order", 0, { NULL } },
1217*05b00f60SXin Li };
1218*05b00f60SXin Li 
1219*05b00f60SXin Li static const u_char *
ikev1_t_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto,int depth _U_)1220*05b00f60SXin Li ikev1_t_print(netdissect_options *ndo, u_char tpay _U_,
1221*05b00f60SXin Li 	      const struct isakmp_gen *ext, u_int item_len,
1222*05b00f60SXin Li 	      const u_char *ep, uint32_t phase _U_, uint32_t doi _U_,
1223*05b00f60SXin Li 	      uint32_t proto, int depth _U_)
1224*05b00f60SXin Li {
1225*05b00f60SXin Li 	const struct ikev1_pl_t *p;
1226*05b00f60SXin Li 	const u_char *cp;
1227*05b00f60SXin Li 	const char *idstr;
1228*05b00f60SXin Li 	const struct attrmap *map;
1229*05b00f60SXin Li 	size_t nmap;
1230*05b00f60SXin Li 	const u_char *ep2;
1231*05b00f60SXin Li 
1232*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_T));
1233*05b00f60SXin Li 
1234*05b00f60SXin Li 	p = (const struct ikev1_pl_t *)ext;
1235*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1236*05b00f60SXin Li 
1237*05b00f60SXin Li 	switch (proto) {
1238*05b00f60SXin Li 	case 1:
1239*05b00f60SXin Li 		idstr = STR_OR_ID(GET_U_1(p->t_id), ikev1_p_map);
1240*05b00f60SXin Li 		map = oakley_t_map;
1241*05b00f60SXin Li 		nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1242*05b00f60SXin Li 		break;
1243*05b00f60SXin Li 	case 2:
1244*05b00f60SXin Li 		idstr = STR_OR_ID(GET_U_1(p->t_id), ah_p_map);
1245*05b00f60SXin Li 		map = ipsec_t_map;
1246*05b00f60SXin Li 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
1247*05b00f60SXin Li 		break;
1248*05b00f60SXin Li 	case 3:
1249*05b00f60SXin Li 		idstr = STR_OR_ID(GET_U_1(p->t_id), esp_p_map);
1250*05b00f60SXin Li 		map = ipsec_t_map;
1251*05b00f60SXin Li 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
1252*05b00f60SXin Li 		break;
1253*05b00f60SXin Li 	case 4:
1254*05b00f60SXin Li 		idstr = STR_OR_ID(GET_U_1(p->t_id), ipcomp_p_map);
1255*05b00f60SXin Li 		map = ipsec_t_map;
1256*05b00f60SXin Li 		nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
1257*05b00f60SXin Li 		break;
1258*05b00f60SXin Li 	default:
1259*05b00f60SXin Li 		idstr = NULL;
1260*05b00f60SXin Li 		map = NULL;
1261*05b00f60SXin Li 		nmap = 0;
1262*05b00f60SXin Li 		break;
1263*05b00f60SXin Li 	}
1264*05b00f60SXin Li 
1265*05b00f60SXin Li 	if (idstr)
1266*05b00f60SXin Li 		ND_PRINT(" #%u id=%s ", GET_U_1(p->t_no), idstr);
1267*05b00f60SXin Li 	else
1268*05b00f60SXin Li 		ND_PRINT(" #%u id=%u ", GET_U_1(p->t_no), GET_U_1(p->t_id));
1269*05b00f60SXin Li 	cp = (const u_char *)(p + 1);
1270*05b00f60SXin Li 	ep2 = (const u_char *)p + item_len;
1271*05b00f60SXin Li 	while (cp < ep && cp < ep2) {
1272*05b00f60SXin Li 		if (map && nmap)
1273*05b00f60SXin Li 			cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
1274*05b00f60SXin Li 		else
1275*05b00f60SXin Li 			cp = ikev1_attr_print(ndo, cp, ep2);
1276*05b00f60SXin Li 		if (cp == NULL)
1277*05b00f60SXin Li 			goto trunc;
1278*05b00f60SXin Li 	}
1279*05b00f60SXin Li 	if (ep < ep2)
1280*05b00f60SXin Li 		ND_PRINT("...");
1281*05b00f60SXin Li 	return cp;
1282*05b00f60SXin Li trunc:
1283*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
1284*05b00f60SXin Li 	return NULL;
1285*05b00f60SXin Li }
1286*05b00f60SXin Li 
1287*05b00f60SXin Li static const u_char *
ikev1_ke_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)1288*05b00f60SXin Li ikev1_ke_print(netdissect_options *ndo, u_char tpay _U_,
1289*05b00f60SXin Li 	       const struct isakmp_gen *ext, u_int item_len,
1290*05b00f60SXin Li 	       const u_char *ep _U_, uint32_t phase _U_, uint32_t doi _U_,
1291*05b00f60SXin Li 	       uint32_t proto _U_, int depth _U_)
1292*05b00f60SXin Li {
1293*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_KE));
1294*05b00f60SXin Li 
1295*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1296*05b00f60SXin Li 	/*
1297*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1298*05b00f60SXin Li 	 */
1299*05b00f60SXin Li 	ND_PRINT(" key len=%u", item_len - 4);
1300*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && item_len > 4) {
1301*05b00f60SXin Li 		/* Print the entire payload in hex */
1302*05b00f60SXin Li 		ND_PRINT(" ");
1303*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1304*05b00f60SXin Li 			goto trunc;
1305*05b00f60SXin Li 	}
1306*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1307*05b00f60SXin Li trunc:
1308*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
1309*05b00f60SXin Li 	return NULL;
1310*05b00f60SXin Li }
1311*05b00f60SXin Li 
1312*05b00f60SXin Li static const u_char *
ikev1_id_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)1313*05b00f60SXin Li ikev1_id_print(netdissect_options *ndo, u_char tpay _U_,
1314*05b00f60SXin Li 	       const struct isakmp_gen *ext, u_int item_len,
1315*05b00f60SXin Li 	       const u_char *ep _U_, uint32_t phase, uint32_t doi _U_,
1316*05b00f60SXin Li 	       uint32_t proto _U_, int depth _U_)
1317*05b00f60SXin Li {
1318*05b00f60SXin Li #define USE_IPSECDOI_IN_PHASE1	1
1319*05b00f60SXin Li 	const struct ikev1_pl_id *p;
1320*05b00f60SXin Li 	static const char *idtypestr[] = {
1321*05b00f60SXin Li 		"IPv4", "IPv4net", "IPv6", "IPv6net",
1322*05b00f60SXin Li 	};
1323*05b00f60SXin Li 	static const char *ipsecidtypestr[] = {
1324*05b00f60SXin Li 		NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
1325*05b00f60SXin Li 		"IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
1326*05b00f60SXin Li 		"keyid",
1327*05b00f60SXin Li 	};
1328*05b00f60SXin Li 	u_int len;
1329*05b00f60SXin Li 	const u_char *data;
1330*05b00f60SXin Li 
1331*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_ID));
1332*05b00f60SXin Li 
1333*05b00f60SXin Li 	p = (const struct ikev1_pl_id *)ext;
1334*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1335*05b00f60SXin Li 	if (sizeof(*p) < item_len) {
1336*05b00f60SXin Li 		data = (const u_char *)(p + 1);
1337*05b00f60SXin Li 		len = item_len - sizeof(*p);
1338*05b00f60SXin Li 	} else {
1339*05b00f60SXin Li 		data = NULL;
1340*05b00f60SXin Li 		len = 0;
1341*05b00f60SXin Li 	}
1342*05b00f60SXin Li 
1343*05b00f60SXin Li #if 0 /*debug*/
1344*05b00f60SXin Li 	ND_PRINT(" [phase=%u doi=%u proto=%u]", phase, doi, proto);
1345*05b00f60SXin Li #endif
1346*05b00f60SXin Li 	switch (phase) {
1347*05b00f60SXin Li #ifndef USE_IPSECDOI_IN_PHASE1
1348*05b00f60SXin Li 	case 1:
1349*05b00f60SXin Li #endif
1350*05b00f60SXin Li 	default:
1351*05b00f60SXin Li 		ND_PRINT(" idtype=%s",
1352*05b00f60SXin Li 			 STR_OR_ID(GET_U_1(p->d.id_type), idtypestr));
1353*05b00f60SXin Li 		ND_PRINT(" doi_data=%u",
1354*05b00f60SXin Li 			  GET_BE_U_4(p->d.doi_data) & 0xffffff);
1355*05b00f60SXin Li 		break;
1356*05b00f60SXin Li 
1357*05b00f60SXin Li #ifdef USE_IPSECDOI_IN_PHASE1
1358*05b00f60SXin Li 	case 1:
1359*05b00f60SXin Li #endif
1360*05b00f60SXin Li 	case 2:
1361*05b00f60SXin Li 	    {
1362*05b00f60SXin Li 		const struct ipsecdoi_id *doi_p;
1363*05b00f60SXin Li 		const char *p_name;
1364*05b00f60SXin Li 		uint8_t type, proto_id;
1365*05b00f60SXin Li 
1366*05b00f60SXin Li 		doi_p = (const struct ipsecdoi_id *)ext;
1367*05b00f60SXin Li 		ND_TCHECK_SIZE(doi_p);
1368*05b00f60SXin Li 		type = GET_U_1(doi_p->type);
1369*05b00f60SXin Li 		ND_PRINT(" idtype=%s", STR_OR_ID(type, ipsecidtypestr));
1370*05b00f60SXin Li 		/* A protocol ID of 0 DOES NOT mean IPPROTO_IP! */
1371*05b00f60SXin Li 		proto_id = GET_U_1(doi_p->proto_id);
1372*05b00f60SXin Li 		if (!ndo->ndo_nflag && proto_id && (p_name = netdb_protoname(proto_id)) != NULL)
1373*05b00f60SXin Li 			ND_PRINT(" protoid=%s", p_name);
1374*05b00f60SXin Li 		else
1375*05b00f60SXin Li 			ND_PRINT(" protoid=%u", proto_id);
1376*05b00f60SXin Li 		ND_PRINT(" port=%u", GET_BE_U_2(doi_p->port));
1377*05b00f60SXin Li 		if (!len)
1378*05b00f60SXin Li 			break;
1379*05b00f60SXin Li 		if (data == NULL)
1380*05b00f60SXin Li 			goto trunc;
1381*05b00f60SXin Li 		ND_TCHECK_LEN(data, len);
1382*05b00f60SXin Li 		switch (type) {
1383*05b00f60SXin Li 		case IPSECDOI_ID_IPV4_ADDR:
1384*05b00f60SXin Li 			if (len < 4)
1385*05b00f60SXin Li 				ND_PRINT(" len=%u [bad: < 4]", len);
1386*05b00f60SXin Li 			else
1387*05b00f60SXin Li 				ND_PRINT(" len=%u %s", len, GET_IPADDR_STRING(data));
1388*05b00f60SXin Li 			len = 0;
1389*05b00f60SXin Li 			break;
1390*05b00f60SXin Li 		case IPSECDOI_ID_FQDN:
1391*05b00f60SXin Li 		case IPSECDOI_ID_USER_FQDN:
1392*05b00f60SXin Li 		    {
1393*05b00f60SXin Li 			u_int i;
1394*05b00f60SXin Li 			ND_PRINT(" len=%u ", len);
1395*05b00f60SXin Li 			for (i = 0; i < len; i++)
1396*05b00f60SXin Li 				fn_print_char(ndo, GET_U_1(data + i));
1397*05b00f60SXin Li 			len = 0;
1398*05b00f60SXin Li 			break;
1399*05b00f60SXin Li 		    }
1400*05b00f60SXin Li 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
1401*05b00f60SXin Li 		    {
1402*05b00f60SXin Li 			const u_char *mask;
1403*05b00f60SXin Li 			if (len < 8)
1404*05b00f60SXin Li 				ND_PRINT(" len=%u [bad: < 8]", len);
1405*05b00f60SXin Li 			else {
1406*05b00f60SXin Li 				mask = data + sizeof(nd_ipv4);
1407*05b00f60SXin Li 				ND_PRINT(" len=%u %s/%u.%u.%u.%u", len,
1408*05b00f60SXin Li 					  GET_IPADDR_STRING(data),
1409*05b00f60SXin Li 					  GET_U_1(mask), GET_U_1(mask + 1),
1410*05b00f60SXin Li 					  GET_U_1(mask + 2),
1411*05b00f60SXin Li 					  GET_U_1(mask + 3));
1412*05b00f60SXin Li 			}
1413*05b00f60SXin Li 			len = 0;
1414*05b00f60SXin Li 			break;
1415*05b00f60SXin Li 		    }
1416*05b00f60SXin Li 		case IPSECDOI_ID_IPV6_ADDR:
1417*05b00f60SXin Li 			if (len < 16)
1418*05b00f60SXin Li 				ND_PRINT(" len=%u [bad: < 16]", len);
1419*05b00f60SXin Li 			else
1420*05b00f60SXin Li 				ND_PRINT(" len=%u %s", len, GET_IP6ADDR_STRING(data));
1421*05b00f60SXin Li 			len = 0;
1422*05b00f60SXin Li 			break;
1423*05b00f60SXin Li 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
1424*05b00f60SXin Li 		    {
1425*05b00f60SXin Li 			const u_char *mask;
1426*05b00f60SXin Li 			if (len < 32)
1427*05b00f60SXin Li 				ND_PRINT(" len=%u [bad: < 32]", len);
1428*05b00f60SXin Li 			else {
1429*05b00f60SXin Li 				mask = (const u_char *)(data + sizeof(nd_ipv6));
1430*05b00f60SXin Li 				/*XXX*/
1431*05b00f60SXin Li 				ND_PRINT(" len=%u %s/0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", len,
1432*05b00f60SXin Li 					  GET_IP6ADDR_STRING(data),
1433*05b00f60SXin Li 					  GET_U_1(mask), GET_U_1(mask + 1),
1434*05b00f60SXin Li 					  GET_U_1(mask + 2),
1435*05b00f60SXin Li 					  GET_U_1(mask + 3),
1436*05b00f60SXin Li 					  GET_U_1(mask + 4),
1437*05b00f60SXin Li 					  GET_U_1(mask + 5),
1438*05b00f60SXin Li 					  GET_U_1(mask + 6),
1439*05b00f60SXin Li 					  GET_U_1(mask + 7),
1440*05b00f60SXin Li 					  GET_U_1(mask + 8),
1441*05b00f60SXin Li 					  GET_U_1(mask + 9),
1442*05b00f60SXin Li 					  GET_U_1(mask + 10),
1443*05b00f60SXin Li 					  GET_U_1(mask + 11),
1444*05b00f60SXin Li 					  GET_U_1(mask + 12),
1445*05b00f60SXin Li 					  GET_U_1(mask + 13),
1446*05b00f60SXin Li 					  GET_U_1(mask + 14),
1447*05b00f60SXin Li 					  GET_U_1(mask + 15));
1448*05b00f60SXin Li 			}
1449*05b00f60SXin Li 			len = 0;
1450*05b00f60SXin Li 			break;
1451*05b00f60SXin Li 		    }
1452*05b00f60SXin Li 		case IPSECDOI_ID_IPV4_ADDR_RANGE:
1453*05b00f60SXin Li 			if (len < 8)
1454*05b00f60SXin Li 				ND_PRINT(" len=%u [bad: < 8]", len);
1455*05b00f60SXin Li 			else {
1456*05b00f60SXin Li 				ND_PRINT(" len=%u %s-%s", len,
1457*05b00f60SXin Li 					  GET_IPADDR_STRING(data),
1458*05b00f60SXin Li 					  GET_IPADDR_STRING(data + sizeof(nd_ipv4)));
1459*05b00f60SXin Li 			}
1460*05b00f60SXin Li 			len = 0;
1461*05b00f60SXin Li 			break;
1462*05b00f60SXin Li 		case IPSECDOI_ID_IPV6_ADDR_RANGE:
1463*05b00f60SXin Li 			if (len < 32)
1464*05b00f60SXin Li 				ND_PRINT(" len=%u [bad: < 32]", len);
1465*05b00f60SXin Li 			else {
1466*05b00f60SXin Li 				ND_PRINT(" len=%u %s-%s", len,
1467*05b00f60SXin Li 					  GET_IP6ADDR_STRING(data),
1468*05b00f60SXin Li 					  GET_IP6ADDR_STRING(data + sizeof(nd_ipv6)));
1469*05b00f60SXin Li 			}
1470*05b00f60SXin Li 			len = 0;
1471*05b00f60SXin Li 			break;
1472*05b00f60SXin Li 		case IPSECDOI_ID_DER_ASN1_DN:
1473*05b00f60SXin Li 		case IPSECDOI_ID_DER_ASN1_GN:
1474*05b00f60SXin Li 		case IPSECDOI_ID_KEY_ID:
1475*05b00f60SXin Li 			break;
1476*05b00f60SXin Li 		}
1477*05b00f60SXin Li 		break;
1478*05b00f60SXin Li 	    }
1479*05b00f60SXin Li 	}
1480*05b00f60SXin Li 	if (data && len) {
1481*05b00f60SXin Li 		ND_PRINT(" len=%u", len);
1482*05b00f60SXin Li 		if (2 < ndo->ndo_vflag) {
1483*05b00f60SXin Li 			ND_PRINT(" ");
1484*05b00f60SXin Li 			if (!rawprint(ndo, (const uint8_t *)data, len))
1485*05b00f60SXin Li 				goto trunc;
1486*05b00f60SXin Li 		}
1487*05b00f60SXin Li 	}
1488*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1489*05b00f60SXin Li trunc:
1490*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
1491*05b00f60SXin Li 	return NULL;
1492*05b00f60SXin Li }
1493*05b00f60SXin Li 
1494*05b00f60SXin Li static const u_char *
ikev1_cert_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi0 _U_,uint32_t proto0 _U_,int depth _U_)1495*05b00f60SXin Li ikev1_cert_print(netdissect_options *ndo, u_char tpay _U_,
1496*05b00f60SXin Li 		 const struct isakmp_gen *ext, u_int item_len,
1497*05b00f60SXin Li 		 const u_char *ep _U_, uint32_t phase _U_,
1498*05b00f60SXin Li 		 uint32_t doi0 _U_,
1499*05b00f60SXin Li 		 uint32_t proto0 _U_, int depth _U_)
1500*05b00f60SXin Li {
1501*05b00f60SXin Li 	const struct ikev1_pl_cert *p;
1502*05b00f60SXin Li 	static const char *certstr[] = {
1503*05b00f60SXin Li 		"none",	"pkcs7", "pgp", "dns",
1504*05b00f60SXin Li 		"x509sign", "x509ke", "kerberos", "crl",
1505*05b00f60SXin Li 		"arl", "spki", "x509attr",
1506*05b00f60SXin Li 	};
1507*05b00f60SXin Li 
1508*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
1509*05b00f60SXin Li 
1510*05b00f60SXin Li 	p = (const struct ikev1_pl_cert *)ext;
1511*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1512*05b00f60SXin Li 	/*
1513*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1514*05b00f60SXin Li 	 */
1515*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
1516*05b00f60SXin Li 	ND_PRINT(" type=%s", STR_OR_ID(GET_U_1(p->encode), certstr));
1517*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1518*05b00f60SXin Li 		/* Print the entire payload in hex */
1519*05b00f60SXin Li 		ND_PRINT(" ");
1520*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1521*05b00f60SXin Li 			goto trunc;
1522*05b00f60SXin Li 	}
1523*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1524*05b00f60SXin Li trunc:
1525*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
1526*05b00f60SXin Li 	return NULL;
1527*05b00f60SXin Li }
1528*05b00f60SXin Li 
1529*05b00f60SXin Li static const u_char *
ikev1_cr_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi0 _U_,uint32_t proto0 _U_,int depth _U_)1530*05b00f60SXin Li ikev1_cr_print(netdissect_options *ndo, u_char tpay _U_,
1531*05b00f60SXin Li 	       const struct isakmp_gen *ext, u_int item_len,
1532*05b00f60SXin Li 	       const u_char *ep _U_, uint32_t phase _U_, uint32_t doi0 _U_,
1533*05b00f60SXin Li 	       uint32_t proto0 _U_, int depth _U_)
1534*05b00f60SXin Li {
1535*05b00f60SXin Li 	const struct ikev1_pl_cert *p;
1536*05b00f60SXin Li 	static const char *certstr[] = {
1537*05b00f60SXin Li 		"none",	"pkcs7", "pgp", "dns",
1538*05b00f60SXin Li 		"x509sign", "x509ke", "kerberos", "crl",
1539*05b00f60SXin Li 		"arl", "spki", "x509attr",
1540*05b00f60SXin Li 	};
1541*05b00f60SXin Li 
1542*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_CR));
1543*05b00f60SXin Li 
1544*05b00f60SXin Li 	p = (const struct ikev1_pl_cert *)ext;
1545*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1546*05b00f60SXin Li 	/*
1547*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1548*05b00f60SXin Li 	 */
1549*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
1550*05b00f60SXin Li 	ND_PRINT(" type=%s", STR_OR_ID(GET_U_1(p->encode), certstr));
1551*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1552*05b00f60SXin Li 		/* Print the entire payload in hex */
1553*05b00f60SXin Li 		ND_PRINT(" ");
1554*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1555*05b00f60SXin Li 			goto trunc;
1556*05b00f60SXin Li 	}
1557*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1558*05b00f60SXin Li trunc:
1559*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
1560*05b00f60SXin Li 	return NULL;
1561*05b00f60SXin Li }
1562*05b00f60SXin Li 
1563*05b00f60SXin Li static const u_char *
ikev1_hash_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)1564*05b00f60SXin Li ikev1_hash_print(netdissect_options *ndo, u_char tpay _U_,
1565*05b00f60SXin Li 		 const struct isakmp_gen *ext, u_int item_len,
1566*05b00f60SXin Li 		 const u_char *ep _U_, uint32_t phase _U_, uint32_t doi _U_,
1567*05b00f60SXin Li 		 uint32_t proto _U_, int depth _U_)
1568*05b00f60SXin Li {
1569*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
1570*05b00f60SXin Li 
1571*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1572*05b00f60SXin Li 	/*
1573*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1574*05b00f60SXin Li 	 */
1575*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
1576*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1577*05b00f60SXin Li 		/* Print the entire payload in hex */
1578*05b00f60SXin Li 		ND_PRINT(" ");
1579*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1580*05b00f60SXin Li 			goto trunc;
1581*05b00f60SXin Li 	}
1582*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1583*05b00f60SXin Li trunc:
1584*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
1585*05b00f60SXin Li 	return NULL;
1586*05b00f60SXin Li }
1587*05b00f60SXin Li 
1588*05b00f60SXin Li static const u_char *
ikev1_sig_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)1589*05b00f60SXin Li ikev1_sig_print(netdissect_options *ndo, u_char tpay _U_,
1590*05b00f60SXin Li 		const struct isakmp_gen *ext, u_int item_len,
1591*05b00f60SXin Li 		const u_char *ep _U_, uint32_t phase _U_, uint32_t doi _U_,
1592*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
1593*05b00f60SXin Li {
1594*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
1595*05b00f60SXin Li 
1596*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1597*05b00f60SXin Li 	/*
1598*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1599*05b00f60SXin Li 	 */
1600*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
1601*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1602*05b00f60SXin Li 		/* Print the entire payload in hex */
1603*05b00f60SXin Li 		ND_PRINT(" ");
1604*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1605*05b00f60SXin Li 			goto trunc;
1606*05b00f60SXin Li 	}
1607*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1608*05b00f60SXin Li trunc:
1609*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
1610*05b00f60SXin Li 	return NULL;
1611*05b00f60SXin Li }
1612*05b00f60SXin Li 
1613*05b00f60SXin Li static const u_char *
ikev1_nonce_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)1614*05b00f60SXin Li ikev1_nonce_print(netdissect_options *ndo, u_char tpay _U_,
1615*05b00f60SXin Li 		  const struct isakmp_gen *ext,
1616*05b00f60SXin Li 		  u_int item_len,
1617*05b00f60SXin Li 		  const u_char *ep,
1618*05b00f60SXin Li 		  uint32_t phase _U_, uint32_t doi _U_,
1619*05b00f60SXin Li 		  uint32_t proto _U_, int depth _U_)
1620*05b00f60SXin Li {
1621*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
1622*05b00f60SXin Li 
1623*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1624*05b00f60SXin Li 	/*
1625*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1626*05b00f60SXin Li 	 */
1627*05b00f60SXin Li 	ND_PRINT(" n len=%u", item_len - 4);
1628*05b00f60SXin Li 	if (item_len > 4) {
1629*05b00f60SXin Li 		if (ndo->ndo_vflag > 2) {
1630*05b00f60SXin Li 			ND_PRINT(" ");
1631*05b00f60SXin Li 			if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1632*05b00f60SXin Li 				goto trunc;
1633*05b00f60SXin Li 		} else if (ndo->ndo_vflag > 1) {
1634*05b00f60SXin Li 			ND_PRINT(" ");
1635*05b00f60SXin Li 			if (!ike_show_somedata(ndo, (const u_char *)(ext + 1), ep))
1636*05b00f60SXin Li 				goto trunc;
1637*05b00f60SXin Li 		}
1638*05b00f60SXin Li 	}
1639*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1640*05b00f60SXin Li trunc:
1641*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
1642*05b00f60SXin Li 	return NULL;
1643*05b00f60SXin Li }
1644*05b00f60SXin Li 
1645*05b00f60SXin Li static const u_char *
ikev1_n_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep,uint32_t phase _U_,uint32_t doi0 _U_,uint32_t proto0 _U_,int depth _U_)1646*05b00f60SXin Li ikev1_n_print(netdissect_options *ndo, u_char tpay _U_,
1647*05b00f60SXin Li 	      const struct isakmp_gen *ext, u_int item_len,
1648*05b00f60SXin Li 	      const u_char *ep, uint32_t phase _U_, uint32_t doi0 _U_,
1649*05b00f60SXin Li 	      uint32_t proto0 _U_, int depth _U_)
1650*05b00f60SXin Li {
1651*05b00f60SXin Li 	const struct ikev1_pl_n *p;
1652*05b00f60SXin Li 	const u_char *cp;
1653*05b00f60SXin Li 	const u_char *ep2;
1654*05b00f60SXin Li 	uint32_t doi;
1655*05b00f60SXin Li 	uint32_t proto;
1656*05b00f60SXin Li 	uint16_t type;
1657*05b00f60SXin Li 	uint8_t spi_size;
1658*05b00f60SXin Li 	static const char *notify_error_str[] = {
1659*05b00f60SXin Li 		NULL,				"INVALID-PAYLOAD-TYPE",
1660*05b00f60SXin Li 		"DOI-NOT-SUPPORTED",		"SITUATION-NOT-SUPPORTED",
1661*05b00f60SXin Li 		"INVALID-COOKIE",		"INVALID-MAJOR-VERSION",
1662*05b00f60SXin Li 		"INVALID-MINOR-VERSION",	"INVALID-EXCHANGE-TYPE",
1663*05b00f60SXin Li 		"INVALID-FLAGS",		"INVALID-MESSAGE-ID",
1664*05b00f60SXin Li 		"INVALID-PROTOCOL-ID",		"INVALID-SPI",
1665*05b00f60SXin Li 		"INVALID-TRANSFORM-ID",		"ATTRIBUTES-NOT-SUPPORTED",
1666*05b00f60SXin Li 		"NO-PROPOSAL-CHOSEN",		"BAD-PROPOSAL-SYNTAX",
1667*05b00f60SXin Li 		"PAYLOAD-MALFORMED",		"INVALID-KEY-INFORMATION",
1668*05b00f60SXin Li 		"INVALID-ID-INFORMATION",	"INVALID-CERT-ENCODING",
1669*05b00f60SXin Li 		"INVALID-CERTIFICATE",		"CERT-TYPE-UNSUPPORTED",
1670*05b00f60SXin Li 		"INVALID-CERT-AUTHORITY",	"INVALID-HASH-INFORMATION",
1671*05b00f60SXin Li 		"AUTHENTICATION-FAILED",	"INVALID-SIGNATURE",
1672*05b00f60SXin Li 		"ADDRESS-NOTIFICATION",		"NOTIFY-SA-LIFETIME",
1673*05b00f60SXin Li 		"CERTIFICATE-UNAVAILABLE",	"UNSUPPORTED-EXCHANGE-TYPE",
1674*05b00f60SXin Li 		"UNEQUAL-PAYLOAD-LENGTHS",
1675*05b00f60SXin Li 	};
1676*05b00f60SXin Li 	static const char *ipsec_notify_error_str[] = {
1677*05b00f60SXin Li 		"RESERVED",
1678*05b00f60SXin Li 	};
1679*05b00f60SXin Li 	static const char *notify_status_str[] = {
1680*05b00f60SXin Li 		"CONNECTED",
1681*05b00f60SXin Li 	};
1682*05b00f60SXin Li 	static const char *ipsec_notify_status_str[] = {
1683*05b00f60SXin Li 		"RESPONDER-LIFETIME",		"REPLAY-STATUS",
1684*05b00f60SXin Li 		"INITIAL-CONTACT",
1685*05b00f60SXin Li 	};
1686*05b00f60SXin Li /* NOTE: these macro must be called with x in proper range */
1687*05b00f60SXin Li 
1688*05b00f60SXin Li /* 0 - 8191 */
1689*05b00f60SXin Li #define NOTIFY_ERROR_STR(x) \
1690*05b00f60SXin Li 	STR_OR_ID((x), notify_error_str)
1691*05b00f60SXin Li 
1692*05b00f60SXin Li /* 8192 - 16383 */
1693*05b00f60SXin Li #define IPSEC_NOTIFY_ERROR_STR(x) \
1694*05b00f60SXin Li 	STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
1695*05b00f60SXin Li 
1696*05b00f60SXin Li /* 16384 - 24575 */
1697*05b00f60SXin Li #define NOTIFY_STATUS_STR(x) \
1698*05b00f60SXin Li 	STR_OR_ID((u_int)((x) - 16384), notify_status_str)
1699*05b00f60SXin Li 
1700*05b00f60SXin Li /* 24576 - 32767 */
1701*05b00f60SXin Li #define IPSEC_NOTIFY_STATUS_STR(x) \
1702*05b00f60SXin Li 	STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
1703*05b00f60SXin Li 
1704*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_N));
1705*05b00f60SXin Li 
1706*05b00f60SXin Li 	p = (const struct ikev1_pl_n *)ext;
1707*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1708*05b00f60SXin Li 	doi = GET_BE_U_4(p->doi);
1709*05b00f60SXin Li 	proto = GET_U_1(p->prot_id);
1710*05b00f60SXin Li 	if (doi != 1) {
1711*05b00f60SXin Li 		ND_PRINT(" doi=%u", doi);
1712*05b00f60SXin Li 		ND_PRINT(" proto=%u", proto);
1713*05b00f60SXin Li 		type = GET_BE_U_2(p->type);
1714*05b00f60SXin Li 		if (type < 8192)
1715*05b00f60SXin Li 			ND_PRINT(" type=%s", NOTIFY_ERROR_STR(type));
1716*05b00f60SXin Li 		else if (type < 16384)
1717*05b00f60SXin Li 			ND_PRINT(" type=%s", numstr(type));
1718*05b00f60SXin Li 		else if (type < 24576)
1719*05b00f60SXin Li 			ND_PRINT(" type=%s", NOTIFY_STATUS_STR(type));
1720*05b00f60SXin Li 		else
1721*05b00f60SXin Li 			ND_PRINT(" type=%s", numstr(type));
1722*05b00f60SXin Li 		spi_size = GET_U_1(p->spi_size);
1723*05b00f60SXin Li 		if (spi_size) {
1724*05b00f60SXin Li 			ND_PRINT(" spi=");
1725*05b00f60SXin Li 			if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
1726*05b00f60SXin Li 				goto trunc;
1727*05b00f60SXin Li 		}
1728*05b00f60SXin Li 		return (const u_char *)(p + 1) + spi_size;
1729*05b00f60SXin Li 	}
1730*05b00f60SXin Li 
1731*05b00f60SXin Li 	ND_PRINT(" doi=ipsec");
1732*05b00f60SXin Li 	ND_PRINT(" proto=%s", PROTOIDSTR(proto));
1733*05b00f60SXin Li 	type = GET_BE_U_2(p->type);
1734*05b00f60SXin Li 	if (type < 8192)
1735*05b00f60SXin Li 		ND_PRINT(" type=%s", NOTIFY_ERROR_STR(type));
1736*05b00f60SXin Li 	else if (type < 16384)
1737*05b00f60SXin Li 		ND_PRINT(" type=%s", IPSEC_NOTIFY_ERROR_STR(type));
1738*05b00f60SXin Li 	else if (type < 24576)
1739*05b00f60SXin Li 		ND_PRINT(" type=%s", NOTIFY_STATUS_STR(type));
1740*05b00f60SXin Li 	else if (type < 32768)
1741*05b00f60SXin Li 		ND_PRINT(" type=%s", IPSEC_NOTIFY_STATUS_STR(type));
1742*05b00f60SXin Li 	else
1743*05b00f60SXin Li 		ND_PRINT(" type=%s", numstr(type));
1744*05b00f60SXin Li 	spi_size = GET_U_1(p->spi_size);
1745*05b00f60SXin Li 	if (spi_size) {
1746*05b00f60SXin Li 		ND_PRINT(" spi=");
1747*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
1748*05b00f60SXin Li 			goto trunc;
1749*05b00f60SXin Li 	}
1750*05b00f60SXin Li 
1751*05b00f60SXin Li 	cp = (const u_char *)(p + 1) + spi_size;
1752*05b00f60SXin Li 	ep2 = (const u_char *)p + item_len;
1753*05b00f60SXin Li 
1754*05b00f60SXin Li 	if (cp < ep) {
1755*05b00f60SXin Li 		switch (type) {
1756*05b00f60SXin Li 		case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
1757*05b00f60SXin Li 		    {
1758*05b00f60SXin Li 			const struct attrmap *map = oakley_t_map;
1759*05b00f60SXin Li 			size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
1760*05b00f60SXin Li 			ND_PRINT(" attrs=(");
1761*05b00f60SXin Li 			while (cp < ep && cp < ep2) {
1762*05b00f60SXin Li 				cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
1763*05b00f60SXin Li 				if (cp == NULL) {
1764*05b00f60SXin Li 					ND_PRINT(")");
1765*05b00f60SXin Li 					goto trunc;
1766*05b00f60SXin Li 				}
1767*05b00f60SXin Li 			}
1768*05b00f60SXin Li 			ND_PRINT(")");
1769*05b00f60SXin Li 			break;
1770*05b00f60SXin Li 		    }
1771*05b00f60SXin Li 		case IPSECDOI_NTYPE_REPLAY_STATUS:
1772*05b00f60SXin Li 			ND_PRINT(" status=(");
1773*05b00f60SXin Li 			ND_PRINT("replay detection %sabled",
1774*05b00f60SXin Li 				  GET_BE_U_4(cp) ? "en" : "dis");
1775*05b00f60SXin Li 			ND_PRINT(")");
1776*05b00f60SXin Li 			break;
1777*05b00f60SXin Li 		default:
1778*05b00f60SXin Li 			/*
1779*05b00f60SXin Li 			 * XXX - fill in more types here; see, for example,
1780*05b00f60SXin Li 			 * draft-ietf-ipsec-notifymsg-04.
1781*05b00f60SXin Li 			 */
1782*05b00f60SXin Li 			if (ndo->ndo_vflag > 3) {
1783*05b00f60SXin Li 				ND_PRINT(" data=(");
1784*05b00f60SXin Li 				if (!rawprint(ndo, (const uint8_t *)(cp), ep - cp))
1785*05b00f60SXin Li 					goto trunc;
1786*05b00f60SXin Li 				ND_PRINT(")");
1787*05b00f60SXin Li 			} else {
1788*05b00f60SXin Li 				if (!ike_show_somedata(ndo, cp, ep))
1789*05b00f60SXin Li 					goto trunc;
1790*05b00f60SXin Li 			}
1791*05b00f60SXin Li 			break;
1792*05b00f60SXin Li 		}
1793*05b00f60SXin Li 	}
1794*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1795*05b00f60SXin Li trunc:
1796*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
1797*05b00f60SXin Li 	return NULL;
1798*05b00f60SXin Li }
1799*05b00f60SXin Li 
1800*05b00f60SXin Li static const u_char *
ikev1_d_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len _U_,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi0 _U_,uint32_t proto0 _U_,int depth _U_)1801*05b00f60SXin Li ikev1_d_print(netdissect_options *ndo, u_char tpay _U_,
1802*05b00f60SXin Li 	      const struct isakmp_gen *ext, u_int item_len _U_,
1803*05b00f60SXin Li 	      const u_char *ep _U_, uint32_t phase _U_, uint32_t doi0 _U_,
1804*05b00f60SXin Li 	      uint32_t proto0 _U_, int depth _U_)
1805*05b00f60SXin Li {
1806*05b00f60SXin Li 	const struct ikev1_pl_d *p;
1807*05b00f60SXin Li 	const uint8_t *q;
1808*05b00f60SXin Li 	uint32_t doi;
1809*05b00f60SXin Li 	uint32_t proto;
1810*05b00f60SXin Li 	uint8_t spi_size;
1811*05b00f60SXin Li 	uint16_t num_spi;
1812*05b00f60SXin Li 	u_int i;
1813*05b00f60SXin Li 
1814*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_D));
1815*05b00f60SXin Li 
1816*05b00f60SXin Li 	p = (const struct ikev1_pl_d *)ext;
1817*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1818*05b00f60SXin Li 	doi = GET_BE_U_4(p->doi);
1819*05b00f60SXin Li 	proto = GET_U_1(p->prot_id);
1820*05b00f60SXin Li 	if (doi != 1) {
1821*05b00f60SXin Li 		ND_PRINT(" doi=%u", doi);
1822*05b00f60SXin Li 		ND_PRINT(" proto=%u", proto);
1823*05b00f60SXin Li 	} else {
1824*05b00f60SXin Li 		ND_PRINT(" doi=ipsec");
1825*05b00f60SXin Li 		ND_PRINT(" proto=%s", PROTOIDSTR(proto));
1826*05b00f60SXin Li 	}
1827*05b00f60SXin Li 	spi_size = GET_U_1(p->spi_size);
1828*05b00f60SXin Li 	ND_PRINT(" spilen=%u", spi_size);
1829*05b00f60SXin Li 	num_spi = GET_BE_U_2(p->num_spi);
1830*05b00f60SXin Li 	ND_PRINT(" nspi=%u", num_spi);
1831*05b00f60SXin Li 	ND_PRINT(" spi=");
1832*05b00f60SXin Li 	q = (const uint8_t *)(p + 1);
1833*05b00f60SXin Li 	for (i = 0; i < num_spi; i++) {
1834*05b00f60SXin Li 		if (i != 0)
1835*05b00f60SXin Li 			ND_PRINT(",");
1836*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)q, spi_size))
1837*05b00f60SXin Li 			goto trunc;
1838*05b00f60SXin Li 		q += spi_size;
1839*05b00f60SXin Li 	}
1840*05b00f60SXin Li 	return q;
1841*05b00f60SXin Li trunc:
1842*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
1843*05b00f60SXin Li 	return NULL;
1844*05b00f60SXin Li }
1845*05b00f60SXin Li 
1846*05b00f60SXin Li static const u_char *
ikev1_vid_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)1847*05b00f60SXin Li ikev1_vid_print(netdissect_options *ndo, u_char tpay _U_,
1848*05b00f60SXin Li 		const struct isakmp_gen *ext,
1849*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
1850*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
1851*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
1852*05b00f60SXin Li {
1853*05b00f60SXin Li 	ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_VID));
1854*05b00f60SXin Li 
1855*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1856*05b00f60SXin Li 	/*
1857*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1858*05b00f60SXin Li 	 */
1859*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
1860*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1861*05b00f60SXin Li 		/* Print the entire payload in hex */
1862*05b00f60SXin Li 		ND_PRINT(" ");
1863*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1864*05b00f60SXin Li 			goto trunc;
1865*05b00f60SXin Li 	}
1866*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1867*05b00f60SXin Li trunc:
1868*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
1869*05b00f60SXin Li 	return NULL;
1870*05b00f60SXin Li }
1871*05b00f60SXin Li 
1872*05b00f60SXin Li /************************************************************/
1873*05b00f60SXin Li /*                                                          */
1874*05b00f60SXin Li /*              IKE v2 - rfc4306 - dissector                */
1875*05b00f60SXin Li /*                                                          */
1876*05b00f60SXin Li /************************************************************/
1877*05b00f60SXin Li 
1878*05b00f60SXin Li static void
ikev2_pay_print(netdissect_options * ndo,const char * payname,uint8_t critical)1879*05b00f60SXin Li ikev2_pay_print(netdissect_options *ndo, const char *payname, uint8_t critical)
1880*05b00f60SXin Li {
1881*05b00f60SXin Li 	ND_PRINT("%s%s:", payname, critical&0x80 ? "[C]" : "");
1882*05b00f60SXin Li }
1883*05b00f60SXin Li 
1884*05b00f60SXin Li static const u_char *
ikev2_gen_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len)1885*05b00f60SXin Li ikev2_gen_print(netdissect_options *ndo, u_char tpay,
1886*05b00f60SXin Li 		const struct isakmp_gen *ext, u_int item_len)
1887*05b00f60SXin Li {
1888*05b00f60SXin Li 	const struct isakmp_gen *p = (const struct isakmp_gen *)ext;
1889*05b00f60SXin Li 
1890*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
1891*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(p->critical));
1892*05b00f60SXin Li 
1893*05b00f60SXin Li 	/*
1894*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
1895*05b00f60SXin Li 	 */
1896*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
1897*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < item_len) {
1898*05b00f60SXin Li 		/* Print the entire payload in hex */
1899*05b00f60SXin Li 		ND_PRINT(" ");
1900*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
1901*05b00f60SXin Li 			goto trunc;
1902*05b00f60SXin Li 	}
1903*05b00f60SXin Li 	return (const u_char *)ext + item_len;
1904*05b00f60SXin Li trunc:
1905*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
1906*05b00f60SXin Li 	return NULL;
1907*05b00f60SXin Li }
1908*05b00f60SXin Li 
1909*05b00f60SXin Li static const u_char *
ikev2_t_print(netdissect_options * ndo,int tcount,const struct isakmp_gen * ext,u_int item_len,const u_char * ep)1910*05b00f60SXin Li ikev2_t_print(netdissect_options *ndo, int tcount,
1911*05b00f60SXin Li 	      const struct isakmp_gen *ext, u_int item_len,
1912*05b00f60SXin Li 	      const u_char *ep)
1913*05b00f60SXin Li {
1914*05b00f60SXin Li 	const struct ikev2_t *p;
1915*05b00f60SXin Li 	uint16_t  t_id;
1916*05b00f60SXin Li 	uint8_t t_type;
1917*05b00f60SXin Li 	const u_char *cp;
1918*05b00f60SXin Li 	const char *idstr;
1919*05b00f60SXin Li 	const struct attrmap *map;
1920*05b00f60SXin Li 	size_t nmap;
1921*05b00f60SXin Li 	const u_char *ep2;
1922*05b00f60SXin Li 
1923*05b00f60SXin Li 	p = (const struct ikev2_t *)ext;
1924*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
1925*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_T), GET_U_1(p->h.critical));
1926*05b00f60SXin Li 
1927*05b00f60SXin Li 	t_id = GET_BE_U_2(p->t_id);
1928*05b00f60SXin Li 
1929*05b00f60SXin Li 	map = NULL;
1930*05b00f60SXin Li 	nmap = 0;
1931*05b00f60SXin Li 
1932*05b00f60SXin Li 	t_type = GET_U_1(p->t_type);
1933*05b00f60SXin Li 	switch (t_type) {
1934*05b00f60SXin Li 	case IV2_T_ENCR:
1935*05b00f60SXin Li 		idstr = STR_OR_ID(t_id, esp_p_map);
1936*05b00f60SXin Li 		map = encr_t_map;
1937*05b00f60SXin Li 		nmap = sizeof(encr_t_map)/sizeof(encr_t_map[0]);
1938*05b00f60SXin Li 		break;
1939*05b00f60SXin Li 
1940*05b00f60SXin Li 	case IV2_T_PRF:
1941*05b00f60SXin Li 		idstr = STR_OR_ID(t_id, prf_p_map);
1942*05b00f60SXin Li 		break;
1943*05b00f60SXin Li 
1944*05b00f60SXin Li 	case IV2_T_INTEG:
1945*05b00f60SXin Li 		idstr = STR_OR_ID(t_id, integ_p_map);
1946*05b00f60SXin Li 		break;
1947*05b00f60SXin Li 
1948*05b00f60SXin Li 	case IV2_T_DH:
1949*05b00f60SXin Li 		idstr = STR_OR_ID(t_id, dh_p_map);
1950*05b00f60SXin Li 		break;
1951*05b00f60SXin Li 
1952*05b00f60SXin Li 	case IV2_T_ESN:
1953*05b00f60SXin Li 		idstr = STR_OR_ID(t_id, esn_p_map);
1954*05b00f60SXin Li 		break;
1955*05b00f60SXin Li 
1956*05b00f60SXin Li 	default:
1957*05b00f60SXin Li 		idstr = NULL;
1958*05b00f60SXin Li 		break;
1959*05b00f60SXin Li 	}
1960*05b00f60SXin Li 
1961*05b00f60SXin Li 	if (idstr)
1962*05b00f60SXin Li 		ND_PRINT(" #%u type=%s id=%s ", tcount,
1963*05b00f60SXin Li 			  STR_OR_ID(t_type, ikev2_t_type_map),
1964*05b00f60SXin Li 			  idstr);
1965*05b00f60SXin Li 	else
1966*05b00f60SXin Li 		ND_PRINT(" #%u type=%s id=%u ", tcount,
1967*05b00f60SXin Li 			  STR_OR_ID(t_type, ikev2_t_type_map),
1968*05b00f60SXin Li 			  t_id);
1969*05b00f60SXin Li 	cp = (const u_char *)(p + 1);
1970*05b00f60SXin Li 	ep2 = (const u_char *)p + item_len;
1971*05b00f60SXin Li 	while (cp < ep && cp < ep2) {
1972*05b00f60SXin Li 		if (map && nmap) {
1973*05b00f60SXin Li 			cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
1974*05b00f60SXin Li 		} else
1975*05b00f60SXin Li 			cp = ikev1_attr_print(ndo, cp, ep2);
1976*05b00f60SXin Li 		if (cp == NULL)
1977*05b00f60SXin Li 			goto trunc;
1978*05b00f60SXin Li 	}
1979*05b00f60SXin Li 	if (ep < ep2)
1980*05b00f60SXin Li 		ND_PRINT("...");
1981*05b00f60SXin Li 	return cp;
1982*05b00f60SXin Li trunc:
1983*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
1984*05b00f60SXin Li 	return NULL;
1985*05b00f60SXin Li }
1986*05b00f60SXin Li 
1987*05b00f60SXin Li static const u_char *
ikev2_p_print(netdissect_options * ndo,u_char tpay _U_,int pcount _U_,const struct isakmp_gen * ext,u_int oprop_length,const u_char * ep,int depth)1988*05b00f60SXin Li ikev2_p_print(netdissect_options *ndo, u_char tpay _U_, int pcount _U_,
1989*05b00f60SXin Li 	      const struct isakmp_gen *ext, u_int oprop_length,
1990*05b00f60SXin Li 	      const u_char *ep, int depth)
1991*05b00f60SXin Li {
1992*05b00f60SXin Li 	const struct ikev2_p *p;
1993*05b00f60SXin Li 	u_int prop_length;
1994*05b00f60SXin Li 	uint8_t spi_size;
1995*05b00f60SXin Li 	const u_char *cp;
1996*05b00f60SXin Li 	int i;
1997*05b00f60SXin Li 	int tcount;
1998*05b00f60SXin Li 	u_char np;
1999*05b00f60SXin Li 	u_int item_len;
2000*05b00f60SXin Li 
2001*05b00f60SXin Li 	p = (const struct ikev2_p *)ext;
2002*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
2003*05b00f60SXin Li 
2004*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_P), GET_U_1(p->h.critical));
2005*05b00f60SXin Li 
2006*05b00f60SXin Li 	/*
2007*05b00f60SXin Li 	 * ikev2_sa_print() guarantees that this is >= 4.
2008*05b00f60SXin Li 	 */
2009*05b00f60SXin Li 	prop_length = oprop_length - 4;
2010*05b00f60SXin Li 	ND_PRINT(" #%u protoid=%s transform=%u len=%u",
2011*05b00f60SXin Li 		  GET_U_1(p->p_no),  PROTOIDSTR(GET_U_1(p->prot_id)),
2012*05b00f60SXin Li 		  GET_U_1(p->num_t), oprop_length);
2013*05b00f60SXin Li 	cp = (const u_char *)(p + 1);
2014*05b00f60SXin Li 
2015*05b00f60SXin Li 	spi_size = GET_U_1(p->spi_size);
2016*05b00f60SXin Li 	if (spi_size) {
2017*05b00f60SXin Li 		if (prop_length < spi_size)
2018*05b00f60SXin Li 			goto toolong;
2019*05b00f60SXin Li 		ND_PRINT(" spi=");
2020*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)cp, spi_size))
2021*05b00f60SXin Li 			goto trunc;
2022*05b00f60SXin Li 		cp += spi_size;
2023*05b00f60SXin Li 		prop_length -= spi_size;
2024*05b00f60SXin Li 	}
2025*05b00f60SXin Li 
2026*05b00f60SXin Li 	/*
2027*05b00f60SXin Li 	 * Print the transforms.
2028*05b00f60SXin Li 	 */
2029*05b00f60SXin Li 	tcount = 0;
2030*05b00f60SXin Li 	for (np = ISAKMP_NPTYPE_T; np != 0; np = GET_U_1(ext->np)) {
2031*05b00f60SXin Li 		tcount++;
2032*05b00f60SXin Li 		ext = (const struct isakmp_gen *)cp;
2033*05b00f60SXin Li 		if (prop_length < sizeof(*ext))
2034*05b00f60SXin Li 			goto toolong;
2035*05b00f60SXin Li 		ND_TCHECK_SIZE(ext);
2036*05b00f60SXin Li 
2037*05b00f60SXin Li 		/*
2038*05b00f60SXin Li 		 * Since we can't have a payload length of less than 4 bytes,
2039*05b00f60SXin Li 		 * we need to bail out here if the generic header is nonsensical
2040*05b00f60SXin Li 		 * or truncated, otherwise we could loop forever processing
2041*05b00f60SXin Li 		 * zero-length items or otherwise misdissect the packet.
2042*05b00f60SXin Li 		 */
2043*05b00f60SXin Li 		item_len = GET_BE_U_2(ext->len);
2044*05b00f60SXin Li 		if (item_len <= 4)
2045*05b00f60SXin Li 			goto trunc;
2046*05b00f60SXin Li 
2047*05b00f60SXin Li 		if (prop_length < item_len)
2048*05b00f60SXin Li 			goto toolong;
2049*05b00f60SXin Li 		ND_TCHECK_LEN(cp, item_len);
2050*05b00f60SXin Li 
2051*05b00f60SXin Li 		depth++;
2052*05b00f60SXin Li 		ND_PRINT("\n");
2053*05b00f60SXin Li 		for (i = 0; i < depth; i++)
2054*05b00f60SXin Li 			ND_PRINT("    ");
2055*05b00f60SXin Li 		ND_PRINT("(");
2056*05b00f60SXin Li 		if (np == ISAKMP_NPTYPE_T) {
2057*05b00f60SXin Li 			cp = ikev2_t_print(ndo, tcount, ext, item_len, ep);
2058*05b00f60SXin Li 			if (cp == NULL) {
2059*05b00f60SXin Li 				/* error, already reported */
2060*05b00f60SXin Li 				return NULL;
2061*05b00f60SXin Li 			}
2062*05b00f60SXin Li 		} else {
2063*05b00f60SXin Li 			ND_PRINT("%s", NPSTR(np));
2064*05b00f60SXin Li 			cp += item_len;
2065*05b00f60SXin Li 		}
2066*05b00f60SXin Li 		ND_PRINT(")");
2067*05b00f60SXin Li 		depth--;
2068*05b00f60SXin Li 		prop_length -= item_len;
2069*05b00f60SXin Li 	}
2070*05b00f60SXin Li 	return cp;
2071*05b00f60SXin Li toolong:
2072*05b00f60SXin Li 	/*
2073*05b00f60SXin Li 	 * Skip the rest of the proposal.
2074*05b00f60SXin Li 	 */
2075*05b00f60SXin Li 	cp += prop_length;
2076*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
2077*05b00f60SXin Li 	return cp;
2078*05b00f60SXin Li trunc:
2079*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
2080*05b00f60SXin Li 	return NULL;
2081*05b00f60SXin Li }
2082*05b00f60SXin Li 
2083*05b00f60SXin Li static const u_char *
ikev2_sa_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext1,u_int osa_length,const u_char * ep,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth)2084*05b00f60SXin Li ikev2_sa_print(netdissect_options *ndo, u_char tpay,
2085*05b00f60SXin Li 		const struct isakmp_gen *ext1,
2086*05b00f60SXin Li 		u_int osa_length, const u_char *ep,
2087*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2088*05b00f60SXin Li 		uint32_t proto _U_, int depth)
2089*05b00f60SXin Li {
2090*05b00f60SXin Li 	const struct isakmp_gen *ext;
2091*05b00f60SXin Li 	u_int sa_length;
2092*05b00f60SXin Li 	const u_char *cp;
2093*05b00f60SXin Li 	int i;
2094*05b00f60SXin Li 	int pcount;
2095*05b00f60SXin Li 	u_char np;
2096*05b00f60SXin Li 	u_int item_len;
2097*05b00f60SXin Li 
2098*05b00f60SXin Li 	ND_TCHECK_SIZE(ext1);
2099*05b00f60SXin Li 	ikev2_pay_print(ndo, "sa", GET_U_1(ext1->critical));
2100*05b00f60SXin Li 
2101*05b00f60SXin Li 	/*
2102*05b00f60SXin Li 	 * ikev2_sub0_print() guarantees that this is >= 4.
2103*05b00f60SXin Li 	 */
2104*05b00f60SXin Li 	osa_length= GET_BE_U_2(ext1->len);
2105*05b00f60SXin Li 	sa_length = osa_length - 4;
2106*05b00f60SXin Li 	ND_PRINT(" len=%u", sa_length);
2107*05b00f60SXin Li 
2108*05b00f60SXin Li 	/*
2109*05b00f60SXin Li 	 * Print the payloads.
2110*05b00f60SXin Li 	 */
2111*05b00f60SXin Li 	cp = (const u_char *)(ext1 + 1);
2112*05b00f60SXin Li 	pcount = 0;
2113*05b00f60SXin Li 	for (np = ISAKMP_NPTYPE_P; np != 0; np = GET_U_1(ext->np)) {
2114*05b00f60SXin Li 		pcount++;
2115*05b00f60SXin Li 		ext = (const struct isakmp_gen *)cp;
2116*05b00f60SXin Li 		if (sa_length < sizeof(*ext))
2117*05b00f60SXin Li 			goto toolong;
2118*05b00f60SXin Li 		ND_TCHECK_SIZE(ext);
2119*05b00f60SXin Li 
2120*05b00f60SXin Li 		/*
2121*05b00f60SXin Li 		 * Since we can't have a payload length of less than 4 bytes,
2122*05b00f60SXin Li 		 * we need to bail out here if the generic header is nonsensical
2123*05b00f60SXin Li 		 * or truncated, otherwise we could loop forever processing
2124*05b00f60SXin Li 		 * zero-length items or otherwise misdissect the packet.
2125*05b00f60SXin Li 		 */
2126*05b00f60SXin Li 		item_len = GET_BE_U_2(ext->len);
2127*05b00f60SXin Li 		if (item_len <= 4)
2128*05b00f60SXin Li 			goto trunc;
2129*05b00f60SXin Li 
2130*05b00f60SXin Li 		if (sa_length < item_len)
2131*05b00f60SXin Li 			goto toolong;
2132*05b00f60SXin Li 		ND_TCHECK_LEN(cp, item_len);
2133*05b00f60SXin Li 
2134*05b00f60SXin Li 		depth++;
2135*05b00f60SXin Li 		ND_PRINT("\n");
2136*05b00f60SXin Li 		for (i = 0; i < depth; i++)
2137*05b00f60SXin Li 			ND_PRINT("    ");
2138*05b00f60SXin Li 		ND_PRINT("(");
2139*05b00f60SXin Li 		if (np == ISAKMP_NPTYPE_P) {
2140*05b00f60SXin Li 			cp = ikev2_p_print(ndo, np, pcount, ext, item_len,
2141*05b00f60SXin Li 					   ep, depth);
2142*05b00f60SXin Li 			if (cp == NULL) {
2143*05b00f60SXin Li 				/* error, already reported */
2144*05b00f60SXin Li 				return NULL;
2145*05b00f60SXin Li 			}
2146*05b00f60SXin Li 		} else {
2147*05b00f60SXin Li 			ND_PRINT("%s", NPSTR(np));
2148*05b00f60SXin Li 			cp += item_len;
2149*05b00f60SXin Li 		}
2150*05b00f60SXin Li 		ND_PRINT(")");
2151*05b00f60SXin Li 		depth--;
2152*05b00f60SXin Li 		sa_length -= item_len;
2153*05b00f60SXin Li 	}
2154*05b00f60SXin Li 	return cp;
2155*05b00f60SXin Li toolong:
2156*05b00f60SXin Li 	/*
2157*05b00f60SXin Li 	 * Skip the rest of the SA.
2158*05b00f60SXin Li 	 */
2159*05b00f60SXin Li 	cp += sa_length;
2160*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2161*05b00f60SXin Li 	return cp;
2162*05b00f60SXin Li trunc:
2163*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2164*05b00f60SXin Li 	return NULL;
2165*05b00f60SXin Li }
2166*05b00f60SXin Li 
2167*05b00f60SXin Li static const u_char *
ikev2_ke_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2168*05b00f60SXin Li ikev2_ke_print(netdissect_options *ndo, u_char tpay,
2169*05b00f60SXin Li 		const struct isakmp_gen *ext,
2170*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2171*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2172*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2173*05b00f60SXin Li {
2174*05b00f60SXin Li 	const struct ikev2_ke *k;
2175*05b00f60SXin Li 
2176*05b00f60SXin Li 	k = (const struct ikev2_ke *)ext;
2177*05b00f60SXin Li 	ND_TCHECK_SIZE(k);
2178*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(k->h.critical));
2179*05b00f60SXin Li 
2180*05b00f60SXin Li 	if (item_len < 8) {
2181*05b00f60SXin Li 		ND_PRINT(" len=%u < 8", item_len);
2182*05b00f60SXin Li 		return (const u_char *)ext + item_len;
2183*05b00f60SXin Li 	}
2184*05b00f60SXin Li 	ND_PRINT(" len=%u group=%s", item_len - 8,
2185*05b00f60SXin Li 		  STR_OR_ID(GET_BE_U_2(k->ke_group), dh_p_map));
2186*05b00f60SXin Li 
2187*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 8 < item_len) {
2188*05b00f60SXin Li 		ND_PRINT(" ");
2189*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(k + 1), item_len - 8))
2190*05b00f60SXin Li 			goto trunc;
2191*05b00f60SXin Li 	}
2192*05b00f60SXin Li 	return (const u_char *)ext + item_len;
2193*05b00f60SXin Li trunc:
2194*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2195*05b00f60SXin Li 	return NULL;
2196*05b00f60SXin Li }
2197*05b00f60SXin Li 
2198*05b00f60SXin Li static const u_char *
ikev2_ID_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2199*05b00f60SXin Li ikev2_ID_print(netdissect_options *ndo, u_char tpay,
2200*05b00f60SXin Li 		const struct isakmp_gen *ext,
2201*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2202*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2203*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2204*05b00f60SXin Li {
2205*05b00f60SXin Li 	const struct ikev2_id *idp;
2206*05b00f60SXin Li 	u_int idtype_len, i;
2207*05b00f60SXin Li 	unsigned int dumpascii, dumphex;
2208*05b00f60SXin Li 	const unsigned char *typedata;
2209*05b00f60SXin Li 
2210*05b00f60SXin Li 	idp = (const struct ikev2_id *)ext;
2211*05b00f60SXin Li 	ND_TCHECK_SIZE(idp);
2212*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(idp->h.critical));
2213*05b00f60SXin Li 
2214*05b00f60SXin Li 	/*
2215*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
2216*05b00f60SXin Li 	 */
2217*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
2218*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < item_len) {
2219*05b00f60SXin Li 		/* Print the entire payload in hex */
2220*05b00f60SXin Li 		ND_PRINT(" ");
2221*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
2222*05b00f60SXin Li 			goto trunc;
2223*05b00f60SXin Li 	}
2224*05b00f60SXin Li 
2225*05b00f60SXin Li 	idtype_len =item_len - sizeof(struct ikev2_id);
2226*05b00f60SXin Li 	dumpascii = 0;
2227*05b00f60SXin Li 	dumphex   = 0;
2228*05b00f60SXin Li 	typedata  = (const unsigned char *)(ext)+sizeof(struct ikev2_id);
2229*05b00f60SXin Li 
2230*05b00f60SXin Li 	switch(GET_U_1(idp->type)) {
2231*05b00f60SXin Li 	case ID_IPV4_ADDR:
2232*05b00f60SXin Li 		ND_PRINT(" ipv4:");
2233*05b00f60SXin Li 		dumphex=1;
2234*05b00f60SXin Li 		break;
2235*05b00f60SXin Li 	case ID_FQDN:
2236*05b00f60SXin Li 		ND_PRINT(" fqdn:");
2237*05b00f60SXin Li 		dumpascii=1;
2238*05b00f60SXin Li 		break;
2239*05b00f60SXin Li 	case ID_RFC822_ADDR:
2240*05b00f60SXin Li 		ND_PRINT(" rfc822:");
2241*05b00f60SXin Li 		dumpascii=1;
2242*05b00f60SXin Li 		break;
2243*05b00f60SXin Li 	case ID_IPV6_ADDR:
2244*05b00f60SXin Li 		ND_PRINT(" ipv6:");
2245*05b00f60SXin Li 		dumphex=1;
2246*05b00f60SXin Li 		break;
2247*05b00f60SXin Li 	case ID_DER_ASN1_DN:
2248*05b00f60SXin Li 		ND_PRINT(" dn:");
2249*05b00f60SXin Li 		dumphex=1;
2250*05b00f60SXin Li 		break;
2251*05b00f60SXin Li 	case ID_DER_ASN1_GN:
2252*05b00f60SXin Li 		ND_PRINT(" gn:");
2253*05b00f60SXin Li 		dumphex=1;
2254*05b00f60SXin Li 		break;
2255*05b00f60SXin Li 	case ID_KEY_ID:
2256*05b00f60SXin Li 		ND_PRINT(" keyid:");
2257*05b00f60SXin Li 		dumphex=1;
2258*05b00f60SXin Li 		break;
2259*05b00f60SXin Li 	}
2260*05b00f60SXin Li 
2261*05b00f60SXin Li 	if(dumpascii) {
2262*05b00f60SXin Li 		ND_TCHECK_LEN(typedata, idtype_len);
2263*05b00f60SXin Li 		for(i=0; i<idtype_len; i++) {
2264*05b00f60SXin Li 			if(ND_ASCII_ISPRINT(GET_U_1(typedata + i))) {
2265*05b00f60SXin Li 				ND_PRINT("%c", GET_U_1(typedata + i));
2266*05b00f60SXin Li 			} else {
2267*05b00f60SXin Li 				ND_PRINT(".");
2268*05b00f60SXin Li 			}
2269*05b00f60SXin Li 		}
2270*05b00f60SXin Li 	}
2271*05b00f60SXin Li 	if(dumphex) {
2272*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)typedata, idtype_len))
2273*05b00f60SXin Li 			goto trunc;
2274*05b00f60SXin Li 	}
2275*05b00f60SXin Li 
2276*05b00f60SXin Li 	return (const u_char *)ext + item_len;
2277*05b00f60SXin Li trunc:
2278*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2279*05b00f60SXin Li 	return NULL;
2280*05b00f60SXin Li }
2281*05b00f60SXin Li 
2282*05b00f60SXin Li static const u_char *
ikev2_cert_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2283*05b00f60SXin Li ikev2_cert_print(netdissect_options *ndo, u_char tpay,
2284*05b00f60SXin Li 		const struct isakmp_gen *ext,
2285*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2286*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2287*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2288*05b00f60SXin Li {
2289*05b00f60SXin Li 	return ikev2_gen_print(ndo, tpay, ext, item_len);
2290*05b00f60SXin Li }
2291*05b00f60SXin Li 
2292*05b00f60SXin Li static const u_char *
ikev2_cr_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2293*05b00f60SXin Li ikev2_cr_print(netdissect_options *ndo, u_char tpay,
2294*05b00f60SXin Li 		const struct isakmp_gen *ext,
2295*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2296*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2297*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2298*05b00f60SXin Li {
2299*05b00f60SXin Li 	return ikev2_gen_print(ndo, tpay, ext, item_len);
2300*05b00f60SXin Li }
2301*05b00f60SXin Li 
2302*05b00f60SXin Li static const u_char *
ikev2_auth_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2303*05b00f60SXin Li ikev2_auth_print(netdissect_options *ndo, u_char tpay,
2304*05b00f60SXin Li 		const struct isakmp_gen *ext,
2305*05b00f60SXin Li 		u_int item_len, const u_char *ep,
2306*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2307*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2308*05b00f60SXin Li {
2309*05b00f60SXin Li 	const struct ikev2_auth *p;
2310*05b00f60SXin Li 	const char *v2_auth[]={ "invalid", "rsasig",
2311*05b00f60SXin Li 				"shared-secret", "dsssig" };
2312*05b00f60SXin Li 	const u_char *authdata = (const u_char *)ext + sizeof(struct ikev2_auth);
2313*05b00f60SXin Li 
2314*05b00f60SXin Li 	ND_TCHECK_LEN(ext, sizeof(struct ikev2_auth));
2315*05b00f60SXin Li 	p = (const struct ikev2_auth *)ext;
2316*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(p->h.critical));
2317*05b00f60SXin Li 
2318*05b00f60SXin Li 	/*
2319*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
2320*05b00f60SXin Li 	 */
2321*05b00f60SXin Li 	ND_PRINT(" len=%u method=%s", item_len-4,
2322*05b00f60SXin Li 		  STR_OR_ID(GET_U_1(p->auth_method), v2_auth));
2323*05b00f60SXin Li 	if (item_len > 4) {
2324*05b00f60SXin Li 		if (ndo->ndo_vflag > 1) {
2325*05b00f60SXin Li 			ND_PRINT(" authdata=(");
2326*05b00f60SXin Li 			if (!rawprint(ndo, (const uint8_t *)authdata, item_len - sizeof(struct ikev2_auth)))
2327*05b00f60SXin Li 				goto trunc;
2328*05b00f60SXin Li 			ND_PRINT(") ");
2329*05b00f60SXin Li 		} else if (ndo->ndo_vflag) {
2330*05b00f60SXin Li 			if (!ike_show_somedata(ndo, authdata, ep))
2331*05b00f60SXin Li 				goto trunc;
2332*05b00f60SXin Li 		}
2333*05b00f60SXin Li 	}
2334*05b00f60SXin Li 
2335*05b00f60SXin Li 	return (const u_char *)ext + item_len;
2336*05b00f60SXin Li trunc:
2337*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2338*05b00f60SXin Li 	return NULL;
2339*05b00f60SXin Li }
2340*05b00f60SXin Li 
2341*05b00f60SXin Li static const u_char *
ikev2_nonce_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2342*05b00f60SXin Li ikev2_nonce_print(netdissect_options *ndo, u_char tpay,
2343*05b00f60SXin Li 		const struct isakmp_gen *ext,
2344*05b00f60SXin Li 		u_int item_len, const u_char *ep,
2345*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2346*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2347*05b00f60SXin Li {
2348*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
2349*05b00f60SXin Li 	ikev2_pay_print(ndo, "nonce", GET_U_1(ext->critical));
2350*05b00f60SXin Li 
2351*05b00f60SXin Li 	/*
2352*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
2353*05b00f60SXin Li 	 */
2354*05b00f60SXin Li 	ND_PRINT(" len=%u", item_len - 4);
2355*05b00f60SXin Li 	if (1 < ndo->ndo_vflag && 4 < item_len) {
2356*05b00f60SXin Li 		ND_PRINT(" nonce=(");
2357*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
2358*05b00f60SXin Li 			goto trunc;
2359*05b00f60SXin Li 		ND_PRINT(") ");
2360*05b00f60SXin Li 	} else if(ndo->ndo_vflag && 4 < item_len) {
2361*05b00f60SXin Li 		if(!ike_show_somedata(ndo, (const u_char *)(ext+1), ep)) goto trunc;
2362*05b00f60SXin Li 	}
2363*05b00f60SXin Li 
2364*05b00f60SXin Li 	return (const u_char *)ext + item_len;
2365*05b00f60SXin Li trunc:
2366*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2367*05b00f60SXin Li 	return NULL;
2368*05b00f60SXin Li }
2369*05b00f60SXin Li 
2370*05b00f60SXin Li /* notify payloads */
2371*05b00f60SXin Li static const u_char *
ikev2_n_print(netdissect_options * ndo,u_char tpay _U_,const struct isakmp_gen * ext,u_int item_len,const u_char * ep,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2372*05b00f60SXin Li ikev2_n_print(netdissect_options *ndo, u_char tpay _U_,
2373*05b00f60SXin Li 		const struct isakmp_gen *ext,
2374*05b00f60SXin Li 		u_int item_len, const u_char *ep,
2375*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2376*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2377*05b00f60SXin Li {
2378*05b00f60SXin Li 	const struct ikev2_n *p;
2379*05b00f60SXin Li 	uint16_t type;
2380*05b00f60SXin Li 	uint8_t spi_size;
2381*05b00f60SXin Li 	const u_char *cp;
2382*05b00f60SXin Li 	u_char showspi, showsomedata;
2383*05b00f60SXin Li 	const char *notify_name;
2384*05b00f60SXin Li 
2385*05b00f60SXin Li 	p = (const struct ikev2_n *)ext;
2386*05b00f60SXin Li 	ND_TCHECK_SIZE(p);
2387*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_N), GET_U_1(p->h.critical));
2388*05b00f60SXin Li 
2389*05b00f60SXin Li 	showspi = 1;
2390*05b00f60SXin Li 	showsomedata=0;
2391*05b00f60SXin Li 	notify_name=NULL;
2392*05b00f60SXin Li 
2393*05b00f60SXin Li 	ND_PRINT(" prot_id=%s", PROTOIDSTR(GET_U_1(p->prot_id)));
2394*05b00f60SXin Li 
2395*05b00f60SXin Li 	type = GET_BE_U_2(p->type);
2396*05b00f60SXin Li 
2397*05b00f60SXin Li 	/* notify space is annoying sparse */
2398*05b00f60SXin Li 	switch(type) {
2399*05b00f60SXin Li 	case IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD:
2400*05b00f60SXin Li 		notify_name = "unsupported_critical_payload";
2401*05b00f60SXin Li 		showspi = 0;
2402*05b00f60SXin Li 		break;
2403*05b00f60SXin Li 
2404*05b00f60SXin Li 	case IV2_NOTIFY_INVALID_IKE_SPI:
2405*05b00f60SXin Li 		notify_name = "invalid_ike_spi";
2406*05b00f60SXin Li 		showspi = 1;
2407*05b00f60SXin Li 		break;
2408*05b00f60SXin Li 
2409*05b00f60SXin Li 	case IV2_NOTIFY_INVALID_MAJOR_VERSION:
2410*05b00f60SXin Li 		notify_name = "invalid_major_version";
2411*05b00f60SXin Li 		showspi = 0;
2412*05b00f60SXin Li 		break;
2413*05b00f60SXin Li 
2414*05b00f60SXin Li 	case IV2_NOTIFY_INVALID_SYNTAX:
2415*05b00f60SXin Li 		notify_name = "invalid_syntax";
2416*05b00f60SXin Li 		showspi = 1;
2417*05b00f60SXin Li 		break;
2418*05b00f60SXin Li 
2419*05b00f60SXin Li 	case IV2_NOTIFY_INVALID_MESSAGE_ID:
2420*05b00f60SXin Li 		notify_name = "invalid_message_id";
2421*05b00f60SXin Li 		showspi = 1;
2422*05b00f60SXin Li 		break;
2423*05b00f60SXin Li 
2424*05b00f60SXin Li 	case IV2_NOTIFY_INVALID_SPI:
2425*05b00f60SXin Li 		notify_name = "invalid_spi";
2426*05b00f60SXin Li 		showspi = 1;
2427*05b00f60SXin Li 		break;
2428*05b00f60SXin Li 
2429*05b00f60SXin Li 	case IV2_NOTIFY_NO_PROPOSAL_CHOSEN:
2430*05b00f60SXin Li 		notify_name = "no_protocol_chosen";
2431*05b00f60SXin Li 		showspi = 1;
2432*05b00f60SXin Li 		break;
2433*05b00f60SXin Li 
2434*05b00f60SXin Li 	case IV2_NOTIFY_INVALID_KE_PAYLOAD:
2435*05b00f60SXin Li 		notify_name = "invalid_ke_payload";
2436*05b00f60SXin Li 		showspi = 1;
2437*05b00f60SXin Li 		break;
2438*05b00f60SXin Li 
2439*05b00f60SXin Li 	case IV2_NOTIFY_AUTHENTICATION_FAILED:
2440*05b00f60SXin Li 		notify_name = "authentication_failed";
2441*05b00f60SXin Li 		showspi = 1;
2442*05b00f60SXin Li 		break;
2443*05b00f60SXin Li 
2444*05b00f60SXin Li 	case IV2_NOTIFY_SINGLE_PAIR_REQUIRED:
2445*05b00f60SXin Li 		notify_name = "single_pair_required";
2446*05b00f60SXin Li 		showspi = 1;
2447*05b00f60SXin Li 		break;
2448*05b00f60SXin Li 
2449*05b00f60SXin Li 	case IV2_NOTIFY_NO_ADDITIONAL_SAS:
2450*05b00f60SXin Li 		notify_name = "no_additional_sas";
2451*05b00f60SXin Li 		showspi = 0;
2452*05b00f60SXin Li 		break;
2453*05b00f60SXin Li 
2454*05b00f60SXin Li 	case IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE:
2455*05b00f60SXin Li 		notify_name = "internal_address_failure";
2456*05b00f60SXin Li 		showspi = 0;
2457*05b00f60SXin Li 		break;
2458*05b00f60SXin Li 
2459*05b00f60SXin Li 	case IV2_NOTIFY_FAILED_CP_REQUIRED:
2460*05b00f60SXin Li 		notify_name = "failed:cp_required";
2461*05b00f60SXin Li 		showspi = 0;
2462*05b00f60SXin Li 		break;
2463*05b00f60SXin Li 
2464*05b00f60SXin Li 	case IV2_NOTIFY_INVALID_SELECTORS:
2465*05b00f60SXin Li 		notify_name = "invalid_selectors";
2466*05b00f60SXin Li 		showspi = 0;
2467*05b00f60SXin Li 		break;
2468*05b00f60SXin Li 
2469*05b00f60SXin Li 	case IV2_NOTIFY_INITIAL_CONTACT:
2470*05b00f60SXin Li 		notify_name = "initial_contact";
2471*05b00f60SXin Li 		showspi = 0;
2472*05b00f60SXin Li 		break;
2473*05b00f60SXin Li 
2474*05b00f60SXin Li 	case IV2_NOTIFY_SET_WINDOW_SIZE:
2475*05b00f60SXin Li 		notify_name = "set_window_size";
2476*05b00f60SXin Li 		showspi = 0;
2477*05b00f60SXin Li 		break;
2478*05b00f60SXin Li 
2479*05b00f60SXin Li 	case IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE:
2480*05b00f60SXin Li 		notify_name = "additional_ts_possible";
2481*05b00f60SXin Li 		showspi = 0;
2482*05b00f60SXin Li 		break;
2483*05b00f60SXin Li 
2484*05b00f60SXin Li 	case IV2_NOTIFY_IPCOMP_SUPPORTED:
2485*05b00f60SXin Li 		notify_name = "ipcomp_supported";
2486*05b00f60SXin Li 		showspi = 0;
2487*05b00f60SXin Li 		break;
2488*05b00f60SXin Li 
2489*05b00f60SXin Li 	case IV2_NOTIFY_NAT_DETECTION_SOURCE_IP:
2490*05b00f60SXin Li 		notify_name = "nat_detection_source_ip";
2491*05b00f60SXin Li 		showspi = 1;
2492*05b00f60SXin Li 		break;
2493*05b00f60SXin Li 
2494*05b00f60SXin Li 	case IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP:
2495*05b00f60SXin Li 		notify_name = "nat_detection_destination_ip";
2496*05b00f60SXin Li 		showspi = 1;
2497*05b00f60SXin Li 		break;
2498*05b00f60SXin Li 
2499*05b00f60SXin Li 	case IV2_NOTIFY_COOKIE:
2500*05b00f60SXin Li 		notify_name = "cookie";
2501*05b00f60SXin Li 		showspi = 1;
2502*05b00f60SXin Li 		showsomedata= 1;
2503*05b00f60SXin Li 		break;
2504*05b00f60SXin Li 
2505*05b00f60SXin Li 	case IV2_NOTIFY_USE_TRANSPORT_MODE:
2506*05b00f60SXin Li 		notify_name = "use_transport_mode";
2507*05b00f60SXin Li 		showspi = 0;
2508*05b00f60SXin Li 		break;
2509*05b00f60SXin Li 
2510*05b00f60SXin Li 	case IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED:
2511*05b00f60SXin Li 		notify_name = "http_cert_lookup_supported";
2512*05b00f60SXin Li 		showspi = 0;
2513*05b00f60SXin Li 		break;
2514*05b00f60SXin Li 
2515*05b00f60SXin Li 	case IV2_NOTIFY_REKEY_SA:
2516*05b00f60SXin Li 		notify_name = "rekey_sa";
2517*05b00f60SXin Li 		showspi = 1;
2518*05b00f60SXin Li 		break;
2519*05b00f60SXin Li 
2520*05b00f60SXin Li 	case IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED:
2521*05b00f60SXin Li 		notify_name = "tfc_padding_not_supported";
2522*05b00f60SXin Li 		showspi = 0;
2523*05b00f60SXin Li 		break;
2524*05b00f60SXin Li 
2525*05b00f60SXin Li 	case IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO:
2526*05b00f60SXin Li 		notify_name = "non_first_fragment_also";
2527*05b00f60SXin Li 		showspi = 0;
2528*05b00f60SXin Li 		break;
2529*05b00f60SXin Li 
2530*05b00f60SXin Li 	default:
2531*05b00f60SXin Li 		if (type < 8192) {
2532*05b00f60SXin Li 			notify_name="error";
2533*05b00f60SXin Li 		} else if(type < 16384) {
2534*05b00f60SXin Li 			notify_name="private-error";
2535*05b00f60SXin Li 		} else if(type < 40960) {
2536*05b00f60SXin Li 			notify_name="status";
2537*05b00f60SXin Li 		} else {
2538*05b00f60SXin Li 			notify_name="private-status";
2539*05b00f60SXin Li 		}
2540*05b00f60SXin Li 	}
2541*05b00f60SXin Li 
2542*05b00f60SXin Li 	if(notify_name) {
2543*05b00f60SXin Li 		ND_PRINT(" type=%u(%s)", type, notify_name);
2544*05b00f60SXin Li 	}
2545*05b00f60SXin Li 
2546*05b00f60SXin Li 
2547*05b00f60SXin Li 	spi_size = GET_U_1(p->spi_size);
2548*05b00f60SXin Li 	if (showspi && spi_size) {
2549*05b00f60SXin Li 		ND_PRINT(" spi=");
2550*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
2551*05b00f60SXin Li 			goto trunc;
2552*05b00f60SXin Li 	}
2553*05b00f60SXin Li 
2554*05b00f60SXin Li 	cp = (const u_char *)(p + 1) + spi_size;
2555*05b00f60SXin Li 
2556*05b00f60SXin Li 	if (cp < ep) {
2557*05b00f60SXin Li 		if (ndo->ndo_vflag > 3 || (showsomedata && ep-cp < 30)) {
2558*05b00f60SXin Li 			ND_PRINT(" data=(");
2559*05b00f60SXin Li 			if (!rawprint(ndo, (const uint8_t *)(cp), ep - cp))
2560*05b00f60SXin Li 				goto trunc;
2561*05b00f60SXin Li 
2562*05b00f60SXin Li 			ND_PRINT(")");
2563*05b00f60SXin Li 		} else if (showsomedata) {
2564*05b00f60SXin Li 			if (!ike_show_somedata(ndo, cp, ep))
2565*05b00f60SXin Li 				goto trunc;
2566*05b00f60SXin Li 		}
2567*05b00f60SXin Li 	}
2568*05b00f60SXin Li 
2569*05b00f60SXin Li 	return (const u_char *)ext + item_len;
2570*05b00f60SXin Li trunc:
2571*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
2572*05b00f60SXin Li 	return NULL;
2573*05b00f60SXin Li }
2574*05b00f60SXin Li 
2575*05b00f60SXin Li static const u_char *
ikev2_d_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2576*05b00f60SXin Li ikev2_d_print(netdissect_options *ndo, u_char tpay,
2577*05b00f60SXin Li 		const struct isakmp_gen *ext,
2578*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2579*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2580*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2581*05b00f60SXin Li {
2582*05b00f60SXin Li 	return ikev2_gen_print(ndo, tpay, ext, item_len);
2583*05b00f60SXin Li }
2584*05b00f60SXin Li 
2585*05b00f60SXin Li static const u_char *
ikev2_vid_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2586*05b00f60SXin Li ikev2_vid_print(netdissect_options *ndo, u_char tpay,
2587*05b00f60SXin Li 		const struct isakmp_gen *ext,
2588*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2589*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2590*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2591*05b00f60SXin Li {
2592*05b00f60SXin Li 	const u_char *vid;
2593*05b00f60SXin Li 	u_int i, len;
2594*05b00f60SXin Li 
2595*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
2596*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(ext->critical));
2597*05b00f60SXin Li 
2598*05b00f60SXin Li 	/*
2599*05b00f60SXin Li 	 * Our caller has ensured that the length is >= 4.
2600*05b00f60SXin Li 	 */
2601*05b00f60SXin Li 	ND_PRINT(" len=%u vid=", item_len - 4);
2602*05b00f60SXin Li 
2603*05b00f60SXin Li 	vid = (const u_char *)(ext+1);
2604*05b00f60SXin Li 	len = item_len - 4;
2605*05b00f60SXin Li 	ND_TCHECK_LEN(vid, len);
2606*05b00f60SXin Li 	for(i=0; i<len; i++) {
2607*05b00f60SXin Li 		if(ND_ASCII_ISPRINT(GET_U_1(vid + i)))
2608*05b00f60SXin Li 			ND_PRINT("%c", GET_U_1(vid + i));
2609*05b00f60SXin Li 		else ND_PRINT(".");
2610*05b00f60SXin Li 	}
2611*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < len) {
2612*05b00f60SXin Li 		/* Print the entire payload in hex */
2613*05b00f60SXin Li 		ND_PRINT(" ");
2614*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
2615*05b00f60SXin Li 			goto trunc;
2616*05b00f60SXin Li 	}
2617*05b00f60SXin Li 	return (const u_char *)ext + item_len;
2618*05b00f60SXin Li trunc:
2619*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2620*05b00f60SXin Li 	return NULL;
2621*05b00f60SXin Li }
2622*05b00f60SXin Li 
2623*05b00f60SXin Li static const u_char *
ikev2_TS_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2624*05b00f60SXin Li ikev2_TS_print(netdissect_options *ndo, u_char tpay,
2625*05b00f60SXin Li 		const struct isakmp_gen *ext,
2626*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2627*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2628*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2629*05b00f60SXin Li {
2630*05b00f60SXin Li 	return ikev2_gen_print(ndo, tpay, ext, item_len);
2631*05b00f60SXin Li }
2632*05b00f60SXin Li 
2633*05b00f60SXin Li static const u_char *
ikev2_e_print(netdissect_options * ndo,_U_ const struct isakmp * base,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,_U_ uint32_t phase,_U_ uint32_t doi,_U_ uint32_t proto,_U_ int depth)2634*05b00f60SXin Li ikev2_e_print(netdissect_options *ndo,
2635*05b00f60SXin Li #ifndef HAVE_LIBCRYPTO
2636*05b00f60SXin Li 	      _U_
2637*05b00f60SXin Li #endif
2638*05b00f60SXin Li 	      const struct isakmp *base,
2639*05b00f60SXin Li 	      u_char tpay,
2640*05b00f60SXin Li 	      const struct isakmp_gen *ext,
2641*05b00f60SXin Li 	      u_int item_len, const u_char *ep _U_,
2642*05b00f60SXin Li #ifndef HAVE_LIBCRYPTO
2643*05b00f60SXin Li 	      _U_
2644*05b00f60SXin Li #endif
2645*05b00f60SXin Li 	      uint32_t phase,
2646*05b00f60SXin Li #ifndef HAVE_LIBCRYPTO
2647*05b00f60SXin Li 	      _U_
2648*05b00f60SXin Li #endif
2649*05b00f60SXin Li 	      uint32_t doi,
2650*05b00f60SXin Li #ifndef HAVE_LIBCRYPTO
2651*05b00f60SXin Li 	      _U_
2652*05b00f60SXin Li #endif
2653*05b00f60SXin Li 	      uint32_t proto,
2654*05b00f60SXin Li #ifndef HAVE_LIBCRYPTO
2655*05b00f60SXin Li 	      _U_
2656*05b00f60SXin Li #endif
2657*05b00f60SXin Li 	      int depth)
2658*05b00f60SXin Li {
2659*05b00f60SXin Li 	const u_char *dat;
2660*05b00f60SXin Li 	u_int dlen;
2661*05b00f60SXin Li #ifdef HAVE_LIBCRYPTO
2662*05b00f60SXin Li 	uint8_t np;
2663*05b00f60SXin Li #endif
2664*05b00f60SXin Li 
2665*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
2666*05b00f60SXin Li 	ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(ext->critical));
2667*05b00f60SXin Li 
2668*05b00f60SXin Li 	dlen = item_len-4;
2669*05b00f60SXin Li 
2670*05b00f60SXin Li 	ND_PRINT(" len=%u", dlen);
2671*05b00f60SXin Li 	if (2 < ndo->ndo_vflag && 4 < dlen) {
2672*05b00f60SXin Li 		ND_PRINT(" ");
2673*05b00f60SXin Li 		if (!rawprint(ndo, (const uint8_t *)(ext + 1), dlen))
2674*05b00f60SXin Li 			goto trunc;
2675*05b00f60SXin Li 	}
2676*05b00f60SXin Li 
2677*05b00f60SXin Li 	dat = (const u_char *)(ext+1);
2678*05b00f60SXin Li 	ND_TCHECK_LEN(dat, dlen);
2679*05b00f60SXin Li 
2680*05b00f60SXin Li #ifdef HAVE_LIBCRYPTO
2681*05b00f60SXin Li 	np = GET_U_1(ext->np);
2682*05b00f60SXin Li 
2683*05b00f60SXin Li 	/* try to decrypt it! */
2684*05b00f60SXin Li 	if(esp_decrypt_buffer_by_ikev2_print(ndo,
2685*05b00f60SXin Li 					     GET_U_1(base->flags) & ISAKMP_FLAG_I,
2686*05b00f60SXin Li 					     base->i_ck, base->r_ck,
2687*05b00f60SXin Li 					     dat, dat+dlen)) {
2688*05b00f60SXin Li 
2689*05b00f60SXin Li 		ext = (const struct isakmp_gen *)ndo->ndo_packetp;
2690*05b00f60SXin Li 
2691*05b00f60SXin Li 		/* got it decrypted, print stuff inside. */
2692*05b00f60SXin Li 		ikev2_sub_print(ndo, base, np, ext,
2693*05b00f60SXin Li 				ndo->ndo_snapend, phase, doi, proto, depth+1);
2694*05b00f60SXin Li 
2695*05b00f60SXin Li 		/*
2696*05b00f60SXin Li 		 * esp_decrypt_buffer_by_ikev2_print pushed information
2697*05b00f60SXin Li 		 * on the buffer stack; we're done with the buffer, so
2698*05b00f60SXin Li 		 * pop it (which frees the buffer)
2699*05b00f60SXin Li 		 */
2700*05b00f60SXin Li 		nd_pop_packet_info(ndo);
2701*05b00f60SXin Li 	}
2702*05b00f60SXin Li #endif
2703*05b00f60SXin Li 
2704*05b00f60SXin Li 
2705*05b00f60SXin Li 	/* always return NULL, because E must be at end, and NP refers
2706*05b00f60SXin Li 	 * to what was inside.
2707*05b00f60SXin Li 	 */
2708*05b00f60SXin Li 	return NULL;
2709*05b00f60SXin Li trunc:
2710*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(tpay));
2711*05b00f60SXin Li 	return NULL;
2712*05b00f60SXin Li }
2713*05b00f60SXin Li 
2714*05b00f60SXin Li static const u_char *
ikev2_cp_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2715*05b00f60SXin Li ikev2_cp_print(netdissect_options *ndo, u_char tpay,
2716*05b00f60SXin Li 		const struct isakmp_gen *ext,
2717*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2718*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2719*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2720*05b00f60SXin Li {
2721*05b00f60SXin Li 	return ikev2_gen_print(ndo, tpay, ext, item_len);
2722*05b00f60SXin Li }
2723*05b00f60SXin Li 
2724*05b00f60SXin Li static const u_char *
ikev2_eap_print(netdissect_options * ndo,u_char tpay,const struct isakmp_gen * ext,u_int item_len,const u_char * ep _U_,uint32_t phase _U_,uint32_t doi _U_,uint32_t proto _U_,int depth _U_)2725*05b00f60SXin Li ikev2_eap_print(netdissect_options *ndo, u_char tpay,
2726*05b00f60SXin Li 		const struct isakmp_gen *ext,
2727*05b00f60SXin Li 		u_int item_len, const u_char *ep _U_,
2728*05b00f60SXin Li 		uint32_t phase _U_, uint32_t doi _U_,
2729*05b00f60SXin Li 		uint32_t proto _U_, int depth _U_)
2730*05b00f60SXin Li {
2731*05b00f60SXin Li 	return ikev2_gen_print(ndo, tpay, ext, item_len);
2732*05b00f60SXin Li }
2733*05b00f60SXin Li 
2734*05b00f60SXin Li static const u_char *
ike_sub0_print(netdissect_options * ndo,u_char np,const struct isakmp_gen * ext,const u_char * ep,uint32_t phase,uint32_t doi,uint32_t proto,int depth)2735*05b00f60SXin Li ike_sub0_print(netdissect_options *ndo,
2736*05b00f60SXin Li 		 u_char np, const struct isakmp_gen *ext, const u_char *ep,
2737*05b00f60SXin Li 
2738*05b00f60SXin Li 	       uint32_t phase, uint32_t doi, uint32_t proto, int depth)
2739*05b00f60SXin Li {
2740*05b00f60SXin Li 	const u_char *cp;
2741*05b00f60SXin Li 	u_int item_len;
2742*05b00f60SXin Li 
2743*05b00f60SXin Li 	cp = (const u_char *)ext;
2744*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
2745*05b00f60SXin Li 
2746*05b00f60SXin Li 	/*
2747*05b00f60SXin Li 	 * Since we can't have a payload length of less than 4 bytes,
2748*05b00f60SXin Li 	 * we need to bail out here if the generic header is nonsensical
2749*05b00f60SXin Li 	 * or truncated, otherwise we could loop forever processing
2750*05b00f60SXin Li 	 * zero-length items or otherwise misdissect the packet.
2751*05b00f60SXin Li 	 */
2752*05b00f60SXin Li 	item_len = GET_BE_U_2(ext->len);
2753*05b00f60SXin Li 	if (item_len <= 4)
2754*05b00f60SXin Li 		return NULL;
2755*05b00f60SXin Li 
2756*05b00f60SXin Li 	if (NPFUNC(np)) {
2757*05b00f60SXin Li 		/*
2758*05b00f60SXin Li 		 * XXX - what if item_len is too short, or too long,
2759*05b00f60SXin Li 		 * for this payload type?
2760*05b00f60SXin Li 		 */
2761*05b00f60SXin Li 		cp = (*npfunc[np])(ndo, np, ext, item_len, ep, phase, doi, proto, depth);
2762*05b00f60SXin Li 	} else {
2763*05b00f60SXin Li 		ND_PRINT("%s", NPSTR(np));
2764*05b00f60SXin Li 		cp += item_len;
2765*05b00f60SXin Li 	}
2766*05b00f60SXin Li 
2767*05b00f60SXin Li 	return cp;
2768*05b00f60SXin Li trunc:
2769*05b00f60SXin Li 	nd_print_trunc(ndo);
2770*05b00f60SXin Li 	return NULL;
2771*05b00f60SXin Li }
2772*05b00f60SXin Li 
2773*05b00f60SXin Li static const u_char *
ikev1_sub_print(netdissect_options * ndo,u_char np,const struct isakmp_gen * ext,const u_char * ep,uint32_t phase,uint32_t doi,uint32_t proto,int depth)2774*05b00f60SXin Li ikev1_sub_print(netdissect_options *ndo,
2775*05b00f60SXin Li 		u_char np, const struct isakmp_gen *ext, const u_char *ep,
2776*05b00f60SXin Li 		uint32_t phase, uint32_t doi, uint32_t proto, int depth)
2777*05b00f60SXin Li {
2778*05b00f60SXin Li 	const u_char *cp;
2779*05b00f60SXin Li 	int i;
2780*05b00f60SXin Li 	u_int item_len;
2781*05b00f60SXin Li 
2782*05b00f60SXin Li 	cp = (const u_char *)ext;
2783*05b00f60SXin Li 
2784*05b00f60SXin Li 	while (np) {
2785*05b00f60SXin Li 		ND_TCHECK_SIZE(ext);
2786*05b00f60SXin Li 
2787*05b00f60SXin Li 		item_len = GET_BE_U_2(ext->len);
2788*05b00f60SXin Li 		ND_TCHECK_LEN(ext, item_len);
2789*05b00f60SXin Li 
2790*05b00f60SXin Li 		depth++;
2791*05b00f60SXin Li 		ND_PRINT("\n");
2792*05b00f60SXin Li 		for (i = 0; i < depth; i++)
2793*05b00f60SXin Li 			ND_PRINT("    ");
2794*05b00f60SXin Li 		ND_PRINT("(");
2795*05b00f60SXin Li 		cp = ike_sub0_print(ndo, np, ext, ep, phase, doi, proto, depth);
2796*05b00f60SXin Li 		ND_PRINT(")");
2797*05b00f60SXin Li 		depth--;
2798*05b00f60SXin Li 
2799*05b00f60SXin Li 		if (cp == NULL) {
2800*05b00f60SXin Li 			/* Zero-length subitem */
2801*05b00f60SXin Li 			return NULL;
2802*05b00f60SXin Li 		}
2803*05b00f60SXin Li 
2804*05b00f60SXin Li 		np = GET_U_1(ext->np);
2805*05b00f60SXin Li 		ext = (const struct isakmp_gen *)cp;
2806*05b00f60SXin Li 	}
2807*05b00f60SXin Li 	return cp;
2808*05b00f60SXin Li trunc:
2809*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(np));
2810*05b00f60SXin Li 	return NULL;
2811*05b00f60SXin Li }
2812*05b00f60SXin Li 
2813*05b00f60SXin Li static char *
numstr(u_int x)2814*05b00f60SXin Li numstr(u_int x)
2815*05b00f60SXin Li {
2816*05b00f60SXin Li 	static char buf[20];
2817*05b00f60SXin Li 	snprintf(buf, sizeof(buf), "#%u", x);
2818*05b00f60SXin Li 	return buf;
2819*05b00f60SXin Li }
2820*05b00f60SXin Li 
2821*05b00f60SXin Li static void
ikev1_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2,const struct isakmp * base)2822*05b00f60SXin Li ikev1_print(netdissect_options *ndo,
2823*05b00f60SXin Li 	    const u_char *bp,  u_int length,
2824*05b00f60SXin Li 	    const u_char *bp2, const struct isakmp *base)
2825*05b00f60SXin Li {
2826*05b00f60SXin Li 	const struct isakmp *p;
2827*05b00f60SXin Li 	const u_char *ep;
2828*05b00f60SXin Li 	u_int flags;
2829*05b00f60SXin Li 	u_char np;
2830*05b00f60SXin Li 	int i;
2831*05b00f60SXin Li 	u_int phase;
2832*05b00f60SXin Li 
2833*05b00f60SXin Li 	p = (const struct isakmp *)bp;
2834*05b00f60SXin Li 	ep = ndo->ndo_snapend;
2835*05b00f60SXin Li 
2836*05b00f60SXin Li 	phase = (GET_BE_U_4(base->msgid) == 0) ? 1 : 2;
2837*05b00f60SXin Li 	if (phase == 1)
2838*05b00f60SXin Li 		ND_PRINT(" phase %u", phase);
2839*05b00f60SXin Li 	else
2840*05b00f60SXin Li 		ND_PRINT(" phase %u/others", phase);
2841*05b00f60SXin Li 
2842*05b00f60SXin Li 	i = cookie_find(&base->i_ck);
2843*05b00f60SXin Li 	if (i < 0) {
2844*05b00f60SXin Li 		if (iszero(ndo, base->r_ck, sizeof(base->r_ck))) {
2845*05b00f60SXin Li 			/* the first packet */
2846*05b00f60SXin Li 			ND_PRINT(" I");
2847*05b00f60SXin Li 			if (bp2)
2848*05b00f60SXin Li 				cookie_record(ndo, &base->i_ck, bp2);
2849*05b00f60SXin Li 		} else
2850*05b00f60SXin Li 			ND_PRINT(" ?");
2851*05b00f60SXin Li 	} else {
2852*05b00f60SXin Li 		if (bp2 && cookie_isinitiator(ndo, i, bp2))
2853*05b00f60SXin Li 			ND_PRINT(" I");
2854*05b00f60SXin Li 		else if (bp2 && cookie_isresponder(ndo, i, bp2))
2855*05b00f60SXin Li 			ND_PRINT(" R");
2856*05b00f60SXin Li 		else
2857*05b00f60SXin Li 			ND_PRINT(" ?");
2858*05b00f60SXin Li 	}
2859*05b00f60SXin Li 
2860*05b00f60SXin Li 	ND_PRINT(" %s", ETYPESTR(GET_U_1(base->etype)));
2861*05b00f60SXin Li 	flags = GET_U_1(base->flags);
2862*05b00f60SXin Li 	if (flags) {
2863*05b00f60SXin Li 		ND_PRINT("[%s%s]", flags & ISAKMP_FLAG_E ? "E" : "",
2864*05b00f60SXin Li 			  flags & ISAKMP_FLAG_C ? "C" : "");
2865*05b00f60SXin Li 	}
2866*05b00f60SXin Li 
2867*05b00f60SXin Li 	if (ndo->ndo_vflag) {
2868*05b00f60SXin Li 		const struct isakmp_gen *ext;
2869*05b00f60SXin Li 
2870*05b00f60SXin Li 		ND_PRINT(":");
2871*05b00f60SXin Li 
2872*05b00f60SXin Li 		np = GET_U_1(base->np);
2873*05b00f60SXin Li 
2874*05b00f60SXin Li 		/* regardless of phase... */
2875*05b00f60SXin Li 		if (flags & ISAKMP_FLAG_E) {
2876*05b00f60SXin Li 			/*
2877*05b00f60SXin Li 			 * encrypted, nothing we can do right now.
2878*05b00f60SXin Li 			 * we hope to decrypt the packet in the future...
2879*05b00f60SXin Li 			 */
2880*05b00f60SXin Li 			ND_PRINT(" [encrypted %s]", NPSTR(np));
2881*05b00f60SXin Li 			goto done;
2882*05b00f60SXin Li 		}
2883*05b00f60SXin Li 
2884*05b00f60SXin Li 		CHECKLEN(p + 1, np);
2885*05b00f60SXin Li 		ext = (const struct isakmp_gen *)(p + 1);
2886*05b00f60SXin Li 		ikev1_sub_print(ndo, np, ext, ep, phase, 0, 0, 0);
2887*05b00f60SXin Li 	}
2888*05b00f60SXin Li 
2889*05b00f60SXin Li done:
2890*05b00f60SXin Li 	if (ndo->ndo_vflag) {
2891*05b00f60SXin Li 		if (GET_BE_U_4(base->len) != length) {
2892*05b00f60SXin Li 			ND_PRINT(" (len mismatch: isakmp %u/ip %u)",
2893*05b00f60SXin Li 				  GET_BE_U_4(base->len), length);
2894*05b00f60SXin Li 		}
2895*05b00f60SXin Li 	}
2896*05b00f60SXin Li }
2897*05b00f60SXin Li 
2898*05b00f60SXin Li static const u_char *
ikev2_sub0_print(netdissect_options * ndo,const struct isakmp * base,u_char np,const struct isakmp_gen * ext,const u_char * ep,uint32_t phase,uint32_t doi,uint32_t proto,int depth)2899*05b00f60SXin Li ikev2_sub0_print(netdissect_options *ndo, const struct isakmp *base,
2900*05b00f60SXin Li 		 u_char np,
2901*05b00f60SXin Li 		 const struct isakmp_gen *ext, const u_char *ep,
2902*05b00f60SXin Li 		 uint32_t phase, uint32_t doi, uint32_t proto, int depth)
2903*05b00f60SXin Li {
2904*05b00f60SXin Li 	const u_char *cp;
2905*05b00f60SXin Li 	u_int item_len;
2906*05b00f60SXin Li 
2907*05b00f60SXin Li 	cp = (const u_char *)ext;
2908*05b00f60SXin Li 	ND_TCHECK_SIZE(ext);
2909*05b00f60SXin Li 
2910*05b00f60SXin Li 	/*
2911*05b00f60SXin Li 	 * Since we can't have a payload length of less than 4 bytes,
2912*05b00f60SXin Li 	 * we need to bail out here if the generic header is nonsensical
2913*05b00f60SXin Li 	 * or truncated, otherwise we could loop forever processing
2914*05b00f60SXin Li 	 * zero-length items or otherwise misdissect the packet.
2915*05b00f60SXin Li 	 */
2916*05b00f60SXin Li 	item_len = GET_BE_U_2(ext->len);
2917*05b00f60SXin Li 	if (item_len <= 4)
2918*05b00f60SXin Li 		return NULL;
2919*05b00f60SXin Li 
2920*05b00f60SXin Li 	if (np == ISAKMP_NPTYPE_v2E) {
2921*05b00f60SXin Li 		cp = ikev2_e_print(ndo, base, np, ext, item_len,
2922*05b00f60SXin Li 				   ep, phase, doi, proto, depth);
2923*05b00f60SXin Li 	} else if (NPFUNC(np)) {
2924*05b00f60SXin Li 		/*
2925*05b00f60SXin Li 		 * XXX - what if item_len is too short, or too long,
2926*05b00f60SXin Li 		 * for this payload type?
2927*05b00f60SXin Li 		 */
2928*05b00f60SXin Li 		cp = (*npfunc[np])(ndo, np, ext, item_len,
2929*05b00f60SXin Li 				   ep, phase, doi, proto, depth);
2930*05b00f60SXin Li 	} else {
2931*05b00f60SXin Li 		ND_PRINT("%s", NPSTR(np));
2932*05b00f60SXin Li 		cp += item_len;
2933*05b00f60SXin Li 	}
2934*05b00f60SXin Li 
2935*05b00f60SXin Li 	return cp;
2936*05b00f60SXin Li trunc:
2937*05b00f60SXin Li 	nd_print_trunc(ndo);
2938*05b00f60SXin Li 	return NULL;
2939*05b00f60SXin Li }
2940*05b00f60SXin Li 
2941*05b00f60SXin Li static const u_char *
ikev2_sub_print(netdissect_options * ndo,const struct isakmp * base,u_char np,const struct isakmp_gen * ext,const u_char * ep,uint32_t phase,uint32_t doi,uint32_t proto,int depth)2942*05b00f60SXin Li ikev2_sub_print(netdissect_options *ndo,
2943*05b00f60SXin Li 		const struct isakmp *base,
2944*05b00f60SXin Li 		u_char np, const struct isakmp_gen *ext, const u_char *ep,
2945*05b00f60SXin Li 		uint32_t phase, uint32_t doi, uint32_t proto, int depth)
2946*05b00f60SXin Li {
2947*05b00f60SXin Li 	const u_char *cp;
2948*05b00f60SXin Li 	int i;
2949*05b00f60SXin Li 
2950*05b00f60SXin Li 	cp = (const u_char *)ext;
2951*05b00f60SXin Li 	while (np) {
2952*05b00f60SXin Li 		ND_TCHECK_SIZE(ext);
2953*05b00f60SXin Li 
2954*05b00f60SXin Li 		ND_TCHECK_LEN(ext, GET_BE_U_2(ext->len));
2955*05b00f60SXin Li 
2956*05b00f60SXin Li 		depth++;
2957*05b00f60SXin Li 		ND_PRINT("\n");
2958*05b00f60SXin Li 		for (i = 0; i < depth; i++)
2959*05b00f60SXin Li 			ND_PRINT("    ");
2960*05b00f60SXin Li 		ND_PRINT("(");
2961*05b00f60SXin Li 		cp = ikev2_sub0_print(ndo, base, np,
2962*05b00f60SXin Li 				      ext, ep, phase, doi, proto, depth);
2963*05b00f60SXin Li 		ND_PRINT(")");
2964*05b00f60SXin Li 		depth--;
2965*05b00f60SXin Li 
2966*05b00f60SXin Li 		if (cp == NULL) {
2967*05b00f60SXin Li 			/* Zero-length subitem */
2968*05b00f60SXin Li 			return NULL;
2969*05b00f60SXin Li 		}
2970*05b00f60SXin Li 
2971*05b00f60SXin Li 		np = GET_U_1(ext->np);
2972*05b00f60SXin Li 		ext = (const struct isakmp_gen *)cp;
2973*05b00f60SXin Li 	}
2974*05b00f60SXin Li 	return cp;
2975*05b00f60SXin Li trunc:
2976*05b00f60SXin Li 	ND_PRINT(" [|%s]", NPSTR(np));
2977*05b00f60SXin Li 	return NULL;
2978*05b00f60SXin Li }
2979*05b00f60SXin Li 
2980*05b00f60SXin Li static void
ikev2_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2 _U_,const struct isakmp * base)2981*05b00f60SXin Li ikev2_print(netdissect_options *ndo,
2982*05b00f60SXin Li 	    const u_char *bp,  u_int length,
2983*05b00f60SXin Li 	    const u_char *bp2 _U_, const struct isakmp *base)
2984*05b00f60SXin Li {
2985*05b00f60SXin Li 	const struct isakmp *p;
2986*05b00f60SXin Li 	const u_char *ep;
2987*05b00f60SXin Li 	uint8_t flags;
2988*05b00f60SXin Li 	u_char np;
2989*05b00f60SXin Li 	u_int phase;
2990*05b00f60SXin Li 
2991*05b00f60SXin Li 	p = (const struct isakmp *)bp;
2992*05b00f60SXin Li 	ep = ndo->ndo_snapend;
2993*05b00f60SXin Li 
2994*05b00f60SXin Li 	phase = (GET_BE_U_4(base->msgid) == 0) ? 1 : 2;
2995*05b00f60SXin Li 	if (phase == 1)
2996*05b00f60SXin Li 		ND_PRINT(" parent_sa");
2997*05b00f60SXin Li 	else
2998*05b00f60SXin Li 		ND_PRINT(" child_sa ");
2999*05b00f60SXin Li 
3000*05b00f60SXin Li 	ND_PRINT(" %s", ETYPESTR(GET_U_1(base->etype)));
3001*05b00f60SXin Li 	flags = GET_U_1(base->flags);
3002*05b00f60SXin Li 	if (flags) {
3003*05b00f60SXin Li 		ND_PRINT("[%s%s%s]",
3004*05b00f60SXin Li 			  flags & ISAKMP_FLAG_I ? "I" : "",
3005*05b00f60SXin Li 			  flags & ISAKMP_FLAG_V ? "V" : "",
3006*05b00f60SXin Li 			  flags & ISAKMP_FLAG_R ? "R" : "");
3007*05b00f60SXin Li 	}
3008*05b00f60SXin Li 
3009*05b00f60SXin Li 	if (ndo->ndo_vflag) {
3010*05b00f60SXin Li 		const struct isakmp_gen *ext;
3011*05b00f60SXin Li 
3012*05b00f60SXin Li 		ND_PRINT(":");
3013*05b00f60SXin Li 
3014*05b00f60SXin Li 		np = GET_U_1(base->np);
3015*05b00f60SXin Li 
3016*05b00f60SXin Li 		/* regardless of phase... */
3017*05b00f60SXin Li 		if (flags & ISAKMP_FLAG_E) {
3018*05b00f60SXin Li 			/*
3019*05b00f60SXin Li 			 * encrypted, nothing we can do right now.
3020*05b00f60SXin Li 			 * we hope to decrypt the packet in the future...
3021*05b00f60SXin Li 			 */
3022*05b00f60SXin Li 			ND_PRINT(" [encrypted %s]", NPSTR(np));
3023*05b00f60SXin Li 			goto done;
3024*05b00f60SXin Li 		}
3025*05b00f60SXin Li 
3026*05b00f60SXin Li 		CHECKLEN(p + 1, np)
3027*05b00f60SXin Li 		ext = (const struct isakmp_gen *)(p + 1);
3028*05b00f60SXin Li 		ikev2_sub_print(ndo, base, np, ext, ep, phase, 0, 0, 0);
3029*05b00f60SXin Li 	}
3030*05b00f60SXin Li 
3031*05b00f60SXin Li done:
3032*05b00f60SXin Li 	if (ndo->ndo_vflag) {
3033*05b00f60SXin Li 		if (GET_BE_U_4(base->len) != length) {
3034*05b00f60SXin Li 			ND_PRINT(" (len mismatch: isakmp %u/ip %u)",
3035*05b00f60SXin Li 				  GET_BE_U_4(base->len), length);
3036*05b00f60SXin Li 		}
3037*05b00f60SXin Li 	}
3038*05b00f60SXin Li }
3039*05b00f60SXin Li 
3040*05b00f60SXin Li void
isakmp_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2)3041*05b00f60SXin Li isakmp_print(netdissect_options *ndo,
3042*05b00f60SXin Li 	     const u_char *bp, u_int length,
3043*05b00f60SXin Li 	     const u_char *bp2)
3044*05b00f60SXin Li {
3045*05b00f60SXin Li 	const struct isakmp *p;
3046*05b00f60SXin Li 	const u_char *ep;
3047*05b00f60SXin Li 	u_int major, minor;
3048*05b00f60SXin Li 
3049*05b00f60SXin Li 	ndo->ndo_protocol = "isakmp";
3050*05b00f60SXin Li #ifdef HAVE_LIBCRYPTO
3051*05b00f60SXin Li 	/* initialize SAs */
3052*05b00f60SXin Li 	if (ndo->ndo_sa_list_head == NULL) {
3053*05b00f60SXin Li 		if (ndo->ndo_espsecret)
3054*05b00f60SXin Li 			esp_decodesecret_print(ndo);
3055*05b00f60SXin Li 	}
3056*05b00f60SXin Li #endif
3057*05b00f60SXin Li 
3058*05b00f60SXin Li 	p = (const struct isakmp *)bp;
3059*05b00f60SXin Li 	ep = ndo->ndo_snapend;
3060*05b00f60SXin Li 
3061*05b00f60SXin Li 	if ((const struct isakmp *)ep < p + 1) {
3062*05b00f60SXin Li 		nd_print_trunc(ndo);
3063*05b00f60SXin Li 		return;
3064*05b00f60SXin Li 	}
3065*05b00f60SXin Li 
3066*05b00f60SXin Li 	ND_PRINT("isakmp");
3067*05b00f60SXin Li 	major = (GET_U_1(p->vers) & ISAKMP_VERS_MAJOR)
3068*05b00f60SXin Li 		>> ISAKMP_VERS_MAJOR_SHIFT;
3069*05b00f60SXin Li 	minor = (GET_U_1(p->vers) & ISAKMP_VERS_MINOR)
3070*05b00f60SXin Li 		>> ISAKMP_VERS_MINOR_SHIFT;
3071*05b00f60SXin Li 
3072*05b00f60SXin Li 	if (ndo->ndo_vflag) {
3073*05b00f60SXin Li 		ND_PRINT(" %u.%u", major, minor);
3074*05b00f60SXin Li 	}
3075*05b00f60SXin Li 
3076*05b00f60SXin Li 	if (ndo->ndo_vflag) {
3077*05b00f60SXin Li 		ND_PRINT(" msgid ");
3078*05b00f60SXin Li 		hexprint(ndo, p->msgid, sizeof(p->msgid));
3079*05b00f60SXin Li 	}
3080*05b00f60SXin Li 
3081*05b00f60SXin Li 	if (1 < ndo->ndo_vflag) {
3082*05b00f60SXin Li 		ND_PRINT(" cookie ");
3083*05b00f60SXin Li 		hexprint(ndo, p->i_ck, sizeof(p->i_ck));
3084*05b00f60SXin Li 		ND_PRINT("->");
3085*05b00f60SXin Li 		hexprint(ndo, p->r_ck, sizeof(p->r_ck));
3086*05b00f60SXin Li 	}
3087*05b00f60SXin Li 	ND_PRINT(":");
3088*05b00f60SXin Li 
3089*05b00f60SXin Li 	switch(major) {
3090*05b00f60SXin Li 	case IKEv1_MAJOR_VERSION:
3091*05b00f60SXin Li 		ikev1_print(ndo, bp, length, bp2, p);
3092*05b00f60SXin Li 		break;
3093*05b00f60SXin Li 
3094*05b00f60SXin Li 	case IKEv2_MAJOR_VERSION:
3095*05b00f60SXin Li 		ikev2_print(ndo, bp, length, bp2, p);
3096*05b00f60SXin Li 		break;
3097*05b00f60SXin Li 	}
3098*05b00f60SXin Li }
3099*05b00f60SXin Li 
3100*05b00f60SXin Li void
isakmp_rfc3948_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2,int ver,int fragmented,u_int ttl_hl)3101*05b00f60SXin Li isakmp_rfc3948_print(netdissect_options *ndo,
3102*05b00f60SXin Li 		     const u_char *bp, u_int length,
3103*05b00f60SXin Li 		     const u_char *bp2, int ver, int fragmented, u_int ttl_hl)
3104*05b00f60SXin Li {
3105*05b00f60SXin Li 	ndo->ndo_protocol = "isakmp_rfc3948";
3106*05b00f60SXin Li 	if(length == 1 && GET_U_1(bp)==0xff) {
3107*05b00f60SXin Li 		ND_PRINT("isakmp-nat-keep-alive");
3108*05b00f60SXin Li 		return;
3109*05b00f60SXin Li 	}
3110*05b00f60SXin Li 
3111*05b00f60SXin Li 	if(length < 4) {
3112*05b00f60SXin Li 		goto trunc;
3113*05b00f60SXin Li 	}
3114*05b00f60SXin Li 
3115*05b00f60SXin Li 	/*
3116*05b00f60SXin Li 	 * see if this is an IKE packet
3117*05b00f60SXin Li 	 */
3118*05b00f60SXin Li 	if (GET_BE_U_4(bp) == 0) {
3119*05b00f60SXin Li 		ND_PRINT("NONESP-encap: ");
3120*05b00f60SXin Li 		isakmp_print(ndo, bp+4, length-4, bp2);
3121*05b00f60SXin Li 		return;
3122*05b00f60SXin Li 	}
3123*05b00f60SXin Li 
3124*05b00f60SXin Li 	/* must be an ESP packet */
3125*05b00f60SXin Li 	{
3126*05b00f60SXin Li 		ND_PRINT("UDP-encap: ");
3127*05b00f60SXin Li 
3128*05b00f60SXin Li 		esp_print(ndo, bp, length, bp2, ver, fragmented, ttl_hl);
3129*05b00f60SXin Li 
3130*05b00f60SXin Li 		/*
3131*05b00f60SXin Li 		 * Either this has decrypted the payload and
3132*05b00f60SXin Li 		 * printed it, in which case there's nothing more
3133*05b00f60SXin Li 		 * to do, or it hasn't, in which case there's
3134*05b00f60SXin Li 		 * nothing more to do.
3135*05b00f60SXin Li 		 */
3136*05b00f60SXin Li 		return;
3137*05b00f60SXin Li 	}
3138*05b00f60SXin Li 
3139*05b00f60SXin Li trunc:
3140*05b00f60SXin Li 	nd_print_trunc(ndo);
3141*05b00f60SXin Li }
3142