Bug Summary

File:programs/pluto/packet.c
Warning:line 2620, column 12
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name packet.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -resource-dir /usr/lib64/clang/13.0.0 -D TimeZoneOffset=timezone -D PIE -D NSS_IPSEC_PROFILE -D XFRM_LIFETIME_DEFAULT=30 -D USE_IKEv1 -D XFRM_SUPPORT -D USE_XFRM_INTERFACE -D USE_DNSSEC -D DEFAULT_DNSSEC_ROOTKEY_FILE="/var/lib/unbound/root.key" -D HAVE_LABELED_IPSEC -D HAVE_SECCOMP -D LIBCURL -D USE_LINUX_AUDIT -D HAVE_NM -D USE_PAM_AUTH -D USE_3DES -D USE_AES -D USE_CAMELLIA -D USE_CHACHA -D USE_DH31 -D USE_MD5 -D USE_SHA1 -D USE_SHA2 -D USE_PRF_AES_XCBC -D USE_NSS_KDF -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/var/lib/ipsec/nss" -D IPSEC_CONFDIR="/etc" -D IPSEC_EXECDIR="/usr/local/libexec/ipsec" -D IPSEC_SBINDIR="/usr/local/sbin" -D IPSEC_VARDIR="/var" -D POLICYGROUPSDIR="/etc/ipsec.d/policies" -D IPSEC_SECRETS_FILE="/etc/ipsec.secrets" -D FORCE_PR_ASSERT -D USE_FORK=1 -D USE_VFORK=0 -D USE_DAEMON=0 -D USE_PTHREAD_SETSCHEDPRIO=1 -D GCC_LINT -D HAVE_LIBCAP_NG -I . -I ../../OBJ.linux.x86_64/programs/pluto -I ../../include -I /usr/include/nss3 -I /usr/include/nspr4 -I /home/build/quick-libreswan-2/programs/pluto/linux-copy -D HERE_FILENAME="programs/pluto/packet.c" -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -fdebug-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -ferror-limit 19 -stack-protector 3 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-01-205714-1273399-1 -x c /home/build/quick-libreswan-2/programs/pluto/packet.c
1/* parsing packets: formats and tools
2 *
3 * Copyright (C) 1997 Angelos D. Keromytis.
4 * Copyright (C) 1998-2001,2013 D. Hugh Redelmeier <hugh@mimosa.com>
5 * Copyright (C) 2012 Avesh Agarwal <avagarwa@redhat.com>
6 * Copyright (C) 2012-2013 Paul Wouters <pwouters@redhat.com>
7 * Copyright (C) 2015,2018 Andrew Cagney
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <stddef.h>
23#include <netinet/in.h>
24#include <string.h>
25#include <sys/socket.h> /* for AF_INET/AF_INET6 */
26
27#include "constants.h"
28#include "lswalloc.h"
29#include "impair.h"
30#include "ip_info.h" /* used by pbs_in_address() */
31#include "packet.h"
32#include "shunk.h"
33
34#include "defs.h"
35#include "log.h"
36
37const pb_stream empty_pbs;
38
39/*
40 * IKEv1/IKEv2 Header: for all messages
41 *
42 * Layout from IKEv1's RFC 2408 "ISAKMP" section 3.1 "ISAKMP Header
43 * Format", and IKEv2's RFC 7296 section 3.1. "The IKE Header".
44 *
45 * In IKEv1 the IKE SA Initiator/Responder SPIs were called cookies.
46 *
47 * The definition of the Message ID changed from (IKEv1):
48 *
49 * o Message ID (4 octets) - Unique Message Identifier used to
50 * identify protocol state during Phase 2 negotiations. This value
51 * is randomly generated by the initiator of the Phase 2
52 * negotiation.
53 *
54 * to (IKEv2):
55 *
56 * o Message ID (4 octets, unsigned integer) - Message identifier used
57 * to control retransmission of lost packets and matching of requests
58 * and responses. It is essential to the security of the protocol
59 * because it is used to prevent message replay attacks. See
60 * Sections 2.1 and 2.2.
61 *
62 * 1 2 3
63 * 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
64 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 * ! IKE SA Initiator's SPI !
66 * ! (icookie) !
67 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68 * ! IKE SA Responder's SPI !
69 * ! (rcookie) !
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 * ! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 * ! Message ID !
74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 * ! Length !
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 */
78
79static field_desc isa_fields[] = {
80 { ft_raw, IKE_SA_SPI_SIZE8, "initiator SPI", NULL((void*)0) },
81 { ft_raw, IKE_SA_SPI_SIZE8, "responder SPI", NULL((void*)0) },
82 { ft_mnpc, 8 / BITS_PER_BYTE8, "next payload type", &payload_names_ikev1orv2 },
83 { ft_loose_enum, 8 / BITS_PER_BYTE8, "ISAKMP version", &version_names },
84 { ft_enum, 8 / BITS_PER_BYTE8, "exchange type", &isakmp_xchg_type_names },
85 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &isakmp_flag_names },
86 { ft_nat, 32 / BITS_PER_BYTE8, "Message ID", NULL((void*)0) },
87 { ft_len, 32 / BITS_PER_BYTE8, "length", NULL((void*)0) },
88 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
89};
90
91struct_desc isakmp_hdr_desc = {
92 .name = "ISAKMP Message",
93 .fields = isa_fields,
94 .size = sizeof(struct isakmp_hdr),
95 .pt = ISAKMP_NEXT_NONE,
96};
97
98static field_desc raw_isa_fields[] = {
99 { ft_raw, IKE_SA_SPI_SIZE8, "initiator SPI", NULL((void*)0) },
100 { ft_raw, IKE_SA_SPI_SIZE8, "responder SPI", NULL((void*)0) },
101 { ft_nat, 8 / BITS_PER_BYTE8, "next payload type", NULL((void*)0), },
102 { ft_nat, 8 / BITS_PER_BYTE8, "ISAKMP version", NULL((void*)0), },
103 { ft_nat, 8 / BITS_PER_BYTE8, "exchange type", NULL((void*)0), },
104 { ft_nat, 8 / BITS_PER_BYTE8, "flags", NULL((void*)0), },
105 { ft_nat, 32 / BITS_PER_BYTE8, "Message ID", NULL((void*)0) },
106 { ft_nat, 32 / BITS_PER_BYTE8, "length", NULL((void*)0) },
107 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
108};
109
110struct_desc raw_isakmp_hdr_desc = {
111 .name = "ISAKMP Message (raw)",
112 .fields = raw_isa_fields,
113 .size = sizeof(struct isakmp_hdr),
114 .pt = ISAKMP_NEXT_NONE,
115};
116
117/* Generic portion of all ISAKMP payloads.
118 * layout from RFC 2408 "ISAKMP" section 3.2
119 * This describes the first 32-bit chunk of all payloads.
120 * The previous next payload depends on the actual payload type.
121 * 1 2 3
122 * 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
123 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 * ! Next Payload ! RESERVED ! Payload Length !
125 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126 */
127
128static field_desc isag_fields[] = {
129 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &payload_names_ikev1orv2 },
130 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
131 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
132 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
133};
134
135/* ISAKMP Data Attribute (generic representation within payloads)
136 * layout from RFC 2408 "ISAKMP" section 3.3
137 * This is not a payload type.
138 * In TLV format, this is followed by a value field.
139 * 1 2 3
140 * 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
141 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142 * !A! Attribute Type ! AF=0 Attribute Length !
143 * !F! ! AF=1 Attribute Value !
144 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145 * . AF=0 Attribute Value .
146 * . AF=1 Not Transmitted .
147 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148 */
149
150/* Oakley Attributes */
151static field_desc isaat_fields_oakley[] = {
152 { ft_af_enum, 16 / BITS_PER_BYTE8, "af+type", &oakley_attr_names },
153 { ft_lv, 16 / BITS_PER_BYTE8, "length/value", NULL((void*)0) },
154 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
155};
156
157struct_desc isakmp_oakley_attribute_desc = {
158 .name = "ISAKMP Oakley attribute",
159 .fields = isaat_fields_oakley,
160 .size = sizeof(struct isakmp_attribute),
161};
162
163/* IPsec DOI Attributes */
164static field_desc isaat_fields_ipsec[] = {
165 { ft_af_enum, 16 / BITS_PER_BYTE8, "af+type", &ipsec_attr_names },
166 { ft_lv, 16 / BITS_PER_BYTE8, "length/value", NULL((void*)0) },
167 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
168};
169
170struct_desc isakmp_ipsec_attribute_desc = {
171 .name = "ISAKMP IPsec DOI attribute",
172 .fields = isaat_fields_ipsec,
173 .size = sizeof(struct isakmp_attribute),
174};
175
176/* XAUTH Attributes */
177static field_desc isaat_fields_xauth[] = {
178 { ft_af_loose_enum, 16 / BITS_PER_BYTE8, "ModeCfg attr type", &modecfg_attr_names },
179 { ft_lv, 16 / BITS_PER_BYTE8, "length/value", NULL((void*)0) },
180 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
181};
182
183struct_desc isakmp_xauth_attribute_desc = {
184 .name = "ISAKMP ModeCfg attribute",
185 .fields = isaat_fields_xauth,
186 .size = sizeof(struct isakmp_attribute),
187};
188
189/* ISAKMP Security Association Payload
190 * layout from RFC 2408 "ISAKMP" section 3.4
191 *
192 * A variable length Situation followed by 0 or more Proposal payloads
193 * follow.
194 *
195 * The "Next Payload [...] field MUST NOT contain the values for the
196 * Proposal or Transform payloads as they are considered part of the
197 * security association negotiation". Hence .csst is set.
198 *
199 * Previous next payload: ISAKMP_NEXT_SA
200 *
201 * 1 2 3
202 * 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
203 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204 * ! Next Payload ! RESERVED ! Payload Length !
205 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206 * ! Domain of Interpretation (DOI) !
207 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208 * ! !
209 * ~ Situation ~
210 * ! !
211 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212 */
213static field_desc isasa_fields[] = {
214 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &payload_names_ikev1orv2 },
215 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
216 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
217 { ft_enum, 32 / BITS_PER_BYTE8, "DOI", &doi_names },
218 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
219};
220
221struct_desc isakmp_sa_desc = {
222 .name = "ISAKMP Security Association Payload",
223 .fields = isasa_fields,
224 .size = sizeof(struct isakmp_sa),
225 .pt = ISAKMP_NEXT_SA,
226 .nsst = ISAKMP_NEXT_P,
227};
228
229static field_desc ipsec_sit_field[] = {
230 { ft_lset, 32 / BITS_PER_BYTE8, "IPsec DOI SIT", &sit_bit_names },
231 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
232};
233
234struct_desc ipsec_sit_desc = {
235 .name = "IPsec DOI SIT",
236 .fields = ipsec_sit_field,
237 .size = sizeof(uint32_t),
238};
239
240/* ISAKMP Proposal Payload
241 * layout from RFC 2408 "ISAKMP" section 3.5
242 *
243 * A variable length SPI and then Transform Payloads follow.
244 *
245 * XXX:
246 *
247 * The Next Payload field below is something of a misnomer. It
248 * doesn't play any part in the Next Payload Chain. Instead it just
249 * acts as a flag where 0 indicate if it is the last payload within
250 * the SA.
251 *
252 * In IKEv2, this payload/field has been replaced by a sub-structure and
253 * "Last Substruct[ure]" field (and then makes the point that it is
254 * entirely redundant).
255 *
256 * 1 2 3
257 * 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
258 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
259 * ! Next Payload ! RESERVED ! Payload Length !
260 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
261 * ! Proposal # ! Protocol-Id ! SPI Size !# of Transforms!
262 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 * ! SPI (variable) !
264 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265 */
266static field_desc isap_fields[] = {
267 { ft_lss, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
268 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
269 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
270 { ft_nat, 8 / BITS_PER_BYTE8, "proposal number", NULL((void*)0) },
271 { ft_enum, 8 / BITS_PER_BYTE8, "protocol ID", &ikev1_protocol_names },
272 { ft_nat, 8 / BITS_PER_BYTE8, "SPI size", NULL((void*)0) },
273 { ft_nat, 8 / BITS_PER_BYTE8, "number of transforms", NULL((void*)0) },
274 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
275};
276
277struct_desc isakmp_proposal_desc = {
278 .name = "ISAKMP Proposal Payload",
279 .fields = isap_fields,
280 .size = sizeof(struct isakmp_proposal),
281 .nsst = ISAKMP_NEXT_T,
282};
283
284/* ISAKMP Transform Payload
285 * layout from RFC 2408 "ISAKMP" section 3.6
286 *
287 * Variable length SA Attributes follow.
288 *
289 * XXX:
290 *
291 * The Next Payload field below is something of a misnomer. It
292 * doesn't play any part in the Next Payload Chain. Instead it just
293 * acts as a flag where zero indicates that it is last payload within
294 * the proposal.
295 *
296 * In IKEv2, this payload/field has been replaced by a sub-structure and
297 * "Last Substruct[ure]" field (and then makes the point that it is
298 * entirely redundant).
299 *
300 * 1 2 3
301 * 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
302 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
303 * ! Next Payload ! RESERVED ! Payload Length !
304 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305 * ! Transform # ! Transform-Id ! RESERVED2 !
306 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307 * ! !
308 * ~ SA Attributes ~
309 * ! !
310 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311 */
312
313/* PROTO_ISAKMP */
314static field_desc isat_fields_isakmp[] = {
315 { ft_lss, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
316 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
317 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
318 { ft_nat, 8 / BITS_PER_BYTE8, "ISAKMP transform number", NULL((void*)0) },
319 { ft_enum, 8 / BITS_PER_BYTE8, "ISAKMP transform ID", &isakmp_transformid_names },
320 { ft_zig, 16 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
321 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
322};
323
324struct_desc isakmp_isakmp_transform_desc = {
325 .name = "ISAKMP Transform Payload (ISAKMP)",
326 .fields = isat_fields_isakmp,
327 .size = sizeof(struct isakmp_transform),
328};
329
330/* PROTO_IPSEC_AH */
331static field_desc isat_fields_ah[] = {
332 { ft_lss, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
333 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
334 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
335 { ft_nat, 8 / BITS_PER_BYTE8, "AH transform number", NULL((void*)0) },
336 { ft_enum, 8 / BITS_PER_BYTE8, "AH transform ID", &ah_transformid_names },
337 { ft_zig, 16 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
338 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
339};
340
341struct_desc isakmp_ah_transform_desc = {
342 .name = "ISAKMP Transform Payload (AH)",
343 .fields = isat_fields_ah,
344 .size = sizeof(struct isakmp_transform),
345};
346
347/* PROTO_IPSEC_ESP */
348static field_desc isat_fields_esp[] = {
349 { ft_lss, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
350 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
351 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
352 { ft_nat, 8 / BITS_PER_BYTE8, "ESP transform number", NULL((void*)0) },
353 { ft_enum, 8 / BITS_PER_BYTE8, "ESP transform ID", &esp_transformid_names },
354 { ft_zig, 16 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
355 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
356};
357
358struct_desc isakmp_esp_transform_desc = {
359 .name = "ISAKMP Transform Payload (ESP)",
360 .fields = isat_fields_esp,
361 .size = sizeof(struct isakmp_transform),
362};
363
364/* PROTO_IPCOMP */
365static field_desc isat_fields_ipcomp[] = {
366 { ft_lss, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
367 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
368 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
369 { ft_nat, 8 / BITS_PER_BYTE8, "IPCOMP transform number", NULL((void*)0) },
370 { ft_enum, 8 / BITS_PER_BYTE8, "IPCOMP transform ID", &ipsec_ipcomp_algo_names },
371 { ft_zig, 16 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
372 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
373};
374
375struct_desc isakmp_ipcomp_transform_desc = {
376 .name = "ISAKMP Transform Payload (COMP)",
377 .fields = isat_fields_ipcomp,
378 .size = sizeof(struct isakmp_transform),
379};
380
381/* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones.
382 * layout from RFC 2408 "ISAKMP" section 3.7
383 * Variable Key Exchange Data follow the generic fields.
384 * Previous next payload: ISAKMP_NEXT_KE
385 * 1 2 3
386 * 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
387 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
388 * ! Next Payload ! RESERVED ! Payload Length !
389 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
390 * ! !
391 * ~ Key Exchange Data ~
392 * ! !
393 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
394 */
395struct_desc isakmp_keyex_desc = {
396 .name = "ISAKMP Key Exchange Payload",
397 .fields = isag_fields,
398 .size = sizeof(struct isakmp_generic),
399 .pt = ISAKMP_NEXT_KE,
400};
401
402/* ISAKMP Identification Payload
403 * layout from RFC 2408 "ISAKMP" section 3.8
404 * See "struct identity" declared later.
405 * Variable length Identification Data follow.
406 * Previous next payload: ISAKMP_NEXT_ID
407 * 1 2 3
408 * 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
409 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
410 * ! Next Payload ! RESERVED ! Payload Length !
411 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
412 * ! ID Type ! DOI Specific ID Data !
413 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
414 * ! !
415 * ~ Identification Data ~
416 * ! !
417 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
418 */
419static field_desc isaid_fields[] = {
420 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &payload_names_ikev1orv2 },
421 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
422 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
423 { ft_enum, 8 / BITS_PER_BYTE8, "ID type", &ikev1_ike_id_type_names }, /* ??? depends on DOI? */
424 { ft_nat, 8 / BITS_PER_BYTE8, "DOI specific A", NULL((void*)0) }, /* ??? depends on DOI? */
425 { ft_nat, 16 / BITS_PER_BYTE8, "DOI specific B", NULL((void*)0) }, /* ??? depends on DOI? */
426 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
427};
428
429struct_desc isakmp_identification_desc = {
430 .name = "ISAKMP Identification Payload",
431 .fields = isaid_fields,
432 .size = sizeof(struct isakmp_id),
433 .pt = ISAKMP_NEXT_ID,
434};
435
436/* IPSEC Identification Payload Content
437 * layout from RFC 2407 "IPsec DOI" section 4.6.2
438 * See struct isakmp_id declared earlier.
439 * Note: Hashing skips the ISAKMP generic payload header
440 * Variable length Identification Data follow.
441 * 1 2 3
442 * 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
443 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
444 * ! Next Payload ! RESERVED ! Payload Length !
445 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
446 * ! ID Type ! Protocol ID ! Port !
447 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
448 * ~ Identification Data ~
449 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
450 */
451static field_desc isaiid_fields[] = {
452 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &payload_names_ikev1orv2 },
453 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
454 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
455 { ft_enum, 8 / BITS_PER_BYTE8, "ID type", &ikev1_ike_id_type_names },
456 { ft_loose_enum, 8 / BITS_PER_BYTE8, "Protocol ID", &ip_protocol_id_names, },
457 { ft_nat, 16 / BITS_PER_BYTE8, "port", NULL((void*)0) },
458 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
459};
460
461struct_desc isakmp_ipsec_identification_desc = {
462 .name = "ISAKMP Identification Payload (IPsec DOI)",
463 .fields = isaiid_fields,
464 .size = sizeof(struct isakmp_ipsec_id),
465 .pt = ISAKMP_NEXT_ID,
466};
467
468/* ISAKMP Certificate Payload: oddball fixed field beyond the generic ones.
469 * layout from RFC 2408 "ISAKMP" section 3.9
470 * Variable length Certificate Data follow the generic fields.
471 * Previous next payload: ISAKMP_NEXT_CERT.
472 * 1 2 3
473 * 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
474 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
475 * ! Next Payload ! RESERVED ! Payload Length !
476 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
477 * ! Cert Encoding ! !
478 * +-+-+-+-+-+-+-+-+ !
479 * ~ Certificate Data ~
480 * ! !
481 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
482 */
483static field_desc isacert_fields[] = {
484 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &payload_names_ikev1orv2 },
485 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
486 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
487 { ft_enum, 8 / BITS_PER_BYTE8, "cert encoding", &ike_cert_type_names },
488 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
489};
490
491/* Note: the size field of isakmp_ipsec_certificate_desc cannot be
492 * sizeof(struct isakmp_cert) because that will rounded up for padding.
493 */
494struct_desc isakmp_ipsec_certificate_desc = {
495 .name = "ISAKMP Certificate Payload",
496 .fields = isacert_fields,
497 .size = ISAKMP_CERT_SIZE5,
498 .pt = ISAKMP_NEXT_CERT,
499};
500
501/* ISAKMP Certificate Request Payload: oddball field beyond the generic ones.
502 * layout from RFC 2408 "ISAKMP" section 3.10
503 * Variable length Certificate Types and Certificate Authorities follow.
504 * Previous next payload: ISAKMP_NEXT_CR.
505 * 1 2 3
506 * 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
507 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
508 * ! Next Payload ! RESERVED ! Payload Length !
509 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
510 * ! Cert. Type ! !
511 * +-+-+-+-+-+-+-+-+ !
512 * ~ Certificate Authority ~
513 * ! !
514 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
515 */
516static field_desc isacr_fields[] = {
517 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &payload_names_ikev1orv2 },
518 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
519 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
520 { ft_enum, 8 / BITS_PER_BYTE8, "cert type", &ike_cert_type_names },
521 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
522};
523
524/* Note: the size field of isakmp_ipsec_cert_req_desc cannot be
525 * sizeof(struct isakmp_cr) because that will rounded up for padding.
526 */
527struct_desc isakmp_ipsec_cert_req_desc = {
528 .name = "ISAKMP Certificate RequestPayload",
529 .fields = isacr_fields,
530 .size = ISAKMP_CR_SIZE5,
531 .pt = ISAKMP_NEXT_CR,
532};
533
534/* ISAKMP Hash Payload: no fixed fields beyond the generic ones.
535 * layout from RFC 2408 "ISAKMP" section 3.11
536 * Variable length Hash Data follow.
537 * Previous next payload: ISAKMP_NEXT_HASH.
538 * 1 2 3
539 * 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
540 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541 * ! Next Payload ! RESERVED ! Payload Length !
542 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
543 * ! !
544 * ~ Hash Data ~
545 * ! !
546 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
547 */
548struct_desc isakmp_hash_desc = {
549 .name = "ISAKMP Hash Payload",
550 .fields = isag_fields,
551 .size = sizeof(struct isakmp_generic),
552 .pt = ISAKMP_NEXT_HASH,
553};
554
555/* ISAKMP Signature Payload: no fixed fields beyond the generic ones.
556 * layout from RFC 2408 "ISAKMP" section 3.12
557 * Variable length Signature Data follow.
558 * Previous next payload: ISAKMP_NEXT_SIG.
559 * 1 2 3
560 * 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
561 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
562 * ! Next Payload ! RESERVED ! Payload Length !
563 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
564 * ! !
565 * ~ Signature Data ~
566 * ! !
567 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
568 */
569struct_desc isakmp_signature_desc = {
570 .name = "ISAKMP Signature Payload",
571 .fields = isag_fields,
572 .size = sizeof(struct isakmp_generic),
573 .pt = ISAKMP_NEXT_SIG,
574};
575
576/* ISAKMP Nonce Payload: no fixed fields beyond the generic ones.
577 * layout from RFC 2408 "ISAKMP" section 3.13
578 * Variable length Nonce Data follow.
579 * Previous next payload: ISAKMP_NEXT_NONCE.
580 * 1 2 3
581 * 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
582 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
583 * ! Next Payload ! RESERVED ! Payload Length !
584 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
585 * ! !
586 * ~ Nonce Data ~
587 * ! !
588 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589 */
590struct_desc isakmp_nonce_desc = {
591 .name = "ISAKMP Nonce Payload",
592 .fields = isag_fields,
593 .size = sizeof(struct isakmp_generic),
594 .pt = ISAKMP_NEXT_NONCE,
595};
596
597/* ISAKMP Notification Payload
598 * layout from RFC 2408 "ISAKMP" section 3.14
599 * This is followed by a variable length SPI
600 * and then possibly by variable length Notification Data.
601 * Previous next payload: ISAKMP_NEXT_N
602 * 1 2 3
603 * 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
604 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
605 * ! Next Payload ! RESERVED ! Payload Length !
606 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
607 * ! Domain of Interpretation (DOI) !
608 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
609 * ! Protocol-ID ! SPI Size ! Notify Message Type !
610 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
611 * ! !
612 * ~ Security Parameter Index (SPI) ~
613 * ! !
614 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
615 * ! !
616 * ~ Notification Data ~
617 * ! !
618 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
619 */
620static field_desc isan_fields[] = {
621 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
622 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
623 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
624 { ft_enum, 32 / BITS_PER_BYTE8, "DOI", &doi_names },
625 { ft_nat, 8 / BITS_PER_BYTE8, "protocol ID", NULL((void*)0) }, /* ??? really enum: ISAKMP, IPSEC, ESP, ... */
626 { ft_nat, 8 / BITS_PER_BYTE8, "SPI size", NULL((void*)0) },
627 { ft_enum, 16 / BITS_PER_BYTE8, "Notify Message Type", &ikev1_notify_names },
628 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
629};
630
631struct_desc isakmp_notification_desc = {
632 .name = "ISAKMP Notification Payload",
633 .fields = isan_fields,
634 .size = sizeof(struct isakmp_notification),
635 .pt = ISAKMP_NEXT_N,
636};
637
638/* ISAKMP Delete Payload
639 * layout from RFC 2408 "ISAKMP" section 3.15
640 * This is followed by a variable length SPI.
641 * Previous next payload: ISAKMP_NEXT_D
642 * 1 2 3
643 * 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
644 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
645 * ! Next Payload ! RESERVED ! Payload Length !
646 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
647 * ! Domain of Interpretation (DOI) !
648 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
649 * ! Protocol-Id ! SPI Size ! # of SPIs !
650 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
651 * ! !
652 * ~ Security Parameter Index(es) (SPI) ~
653 * ! !
654 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
655 */
656static field_desc isad_fields[] = {
657 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
658 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
659 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
660 { ft_enum, 32 / BITS_PER_BYTE8, "DOI", &doi_names },
661 { ft_nat, 8 / BITS_PER_BYTE8, "protocol ID", NULL((void*)0) }, /* ??? really enum: ISAKMP, IPSEC */
662 { ft_nat, 8 / BITS_PER_BYTE8, "SPI size", NULL((void*)0) },
663 { ft_nat, 16 / BITS_PER_BYTE8, "number of SPIs", NULL((void*)0) },
664 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
665};
666
667struct_desc isakmp_delete_desc = {
668 .name = "ISAKMP Delete Payload",
669 .fields = isad_fields,
670 .size = sizeof(struct isakmp_delete),
671 .pt = ISAKMP_NEXT_D,
672};
673
674/* ISAKMP Vendor ID Payload
675 * layout from RFC 2408 "ISAKMP" section 3.15
676 * This is followed by a variable length VID.
677 * Previous next payload: ISAKMP_NEXT_VID
678 * 1 2 3
679 * 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
680 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
681 * ! Next Payload ! RESERVED ! Payload Length !
682 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
683 * ! !
684 * ~ Vendor ID (VID) ~
685 * ! !
686 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
687 */
688struct_desc isakmp_vendor_id_desc = {
689 .name = "ISAKMP Vendor ID Payload",
690 .fields = isag_fields,
691 .size = sizeof(struct isakmp_generic),
692 .pt = ISAKMP_NEXT_VID,
693};
694
695/* MODECFG */
696/*
697 * From draft-dukes-ike-mode-cfg
698 * 3.2. Attribute Payload
699 * 1 2 3
700 * 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
701 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
702 * ! Next Payload ! RESERVED ! Payload Length !
703 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
704 * ! Type ! RESERVED ! Identifier !
705 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
706 * ! !
707 * ~ Attributes ~
708 * ! !
709 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
710 */
711static field_desc isaattr_fields[] = {
712 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
713 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
714 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
715 { ft_enum, 8 / BITS_PER_BYTE8, "Attr Msg Type", &attr_msg_type_names },
716 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
717 { ft_nat, 16 / BITS_PER_BYTE8, "Identifier", NULL((void*)0) },
718 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
719};
720
721/*
722 * MODECFG
723 * From draft-dukes-ike-mode-cfg
724 * 3.2. Attribute Payload
725 * 1 2 3
726 * 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
727 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
728 * ! Next Payload ! RESERVED ! Payload Length !
729 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
730 * ! Type ! RESERVED ! Identifier !
731 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
732 * ! !
733 * ! !
734 * ~ Attributes ~
735 * ! !
736 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
737 */
738
739struct_desc isakmp_attr_desc = {
740 .name = "ISAKMP Mode Attribute",
741 .fields = isaattr_fields,
742 .size = sizeof(struct isakmp_mode_attr),
743 .pt = ISAKMP_NEXT_MCFG_ATTR,
744};
745
746/*
747 * ISAKMP NAT-Traversal NAT-D
748 * RFC 3947 https://tools.ietf.org/html/rfc3947
749 *
750 * 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
751 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
752 * ! Next Payload ! RESERVED ! Payload Length !
753 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
754 * ! HASH of the address and port !
755 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
756 */
757struct_desc isakmp_nat_d = {
758 .name = "ISAKMP NAT-D Payload",
759 .fields = isag_fields,
760 .size = sizeof(struct isakmp_generic),
761 .pt = ISAKMP_NEXT_NATD_RFC,
762};
763
764struct_desc isakmp_nat_d_drafts = {
765 .name = "ISAKMP NAT-D Payload (draft)",
766 .fields = isag_fields,
767 .size = sizeof(struct isakmp_generic),
768 .pt = ISAKMP_NEXT_NATD_DRAFTS,
769};
770
771/*
772 * ISAKMP NAT-Traversal NAT-OA
773 * RFC 3947 https://tools.ietf.org/html/rfc3947
774 *
775 * 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
776 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
777 * ! Next Payload ! RESERVED ! Payload Length !
778 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
779 * ! ID Type ! RESERVED !
780 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
781 * ! IPv4 (4 octets) or IPv6 address (16 octets) !
782 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
783 */
784static field_desc isanat_oa_fields[] = {
785 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev1_payload_names },
786 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
787 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
788 { ft_enum, 8 / BITS_PER_BYTE8, "ID type", &ikev1_ike_id_type_names },
789 { ft_zig, 24 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
790 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
791};
792
793struct_desc isakmp_nat_oa = {
794 .name = "ISAKMP NAT-OA Payload",
795 .fields = isanat_oa_fields,
796 .size = sizeof(struct isakmp_nat_oa),
797 .pt = ISAKMP_NEXT_NATOA_RFC,
798};
799
800struct_desc isakmp_nat_oa_drafts = {
801 .name = "ISAKMP NAT-OA Payload (draft)",
802 .fields = isanat_oa_fields,
803 .size = sizeof(struct isakmp_nat_oa),
804 .pt = ISAKMP_NEXT_NATOA_DRAFTS,
805};
806
807/* Generic payload: an unknown input payload */
808
809struct_desc isakmp_ignore_desc = {
810 .name = "ignored ISAKMP Generic Payload",
811 .fields = isag_fields,
812 .size = sizeof(struct isakmp_generic),
813 .pt = ISAKMP_NEXT_NONE,
814};
815
816/* ISAKMP IKE Fragmentation Payload
817 * Cisco proprietary, undocumented
818 *
819 * 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
820 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
821 * ! Next Payload ! RESERVED ! Payload Length !
822 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
823 * ! Fragment ID ! Frag Number ! Flags !
824 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
825 * ! !
826 * ~ Fragment Data ~
827 * ! !
828 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
829 */
830static field_desc isafrag_fields[] = {
831 { ft_zig, 8 / BITS_PER_BYTE8, "next payload type", NULL((void*)0) },
832 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
833 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
834 { ft_nat, 16 / BITS_PER_BYTE8, "fragment id", NULL((void*)0) },
835 { ft_nat, 8 / BITS_PER_BYTE8, "fragment number", NULL((void*)0) },
836 { ft_nat, 8 / BITS_PER_BYTE8, "flags", NULL((void*)0) }, /* 0x1 means last fragment */
837 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
838};
839
840struct_desc isakmp_ikefrag_desc = {
841 .name = "ISAKMP IKE Fragment Payload",
842 .fields = isafrag_fields,
843 .size = sizeof(struct isakmp_ikefrag),
844 .pt = ISAKMP_NEXT_IKE_FRAGMENTATION,
845};
846
847/*
848 * GENERIC IKEv2 header.
849 * Note differs from IKEv1, in that it has flags with one bit a critical bit
850 */
851static field_desc ikev2generic_fields[] = {
852 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
853 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
854 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
855 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
856};
857/* only for reading an unknown-to-us payload */
858struct_desc ikev2_generic_desc = {
859 .name = "IKEv2 Generic Payload",
860 .fields = ikev2generic_fields,
861 .size = sizeof(struct ikev2_generic),
862 .pt = ISAKMP_NEXT_v2NONE, /* could be any unknown */
863};
864/* for IMPAIR_ADD_UNKNOWN_PAYLOAD_TO_* */
865struct_desc ikev2_unknown_payload_desc = {
866 .name = "IKEv2 Unknown Payload",
867 .fields = ikev2generic_fields,
868 .size = sizeof(struct ikev2_generic),
869 .pt = ISAKMP_NEXT_v2UNKNOWN255,
870};
871
872/*
873 * IKEv2 - Security Association Payload
874 *
875 * layout from RFC 4306 - section 3.3.
876 * A variable number of Proposal Substructures follow.
877 *
878 * 1 2 3
879 * 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
880 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
881 * ! Next Payload !C! RESERVED ! Payload Length !
882 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
883 * ! !
884 * ~ <Proposals> ~
885 * ! !
886 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
887 *
888 */
889struct_desc ikev2_sa_desc = {
890 .name = "IKEv2 Security Association Payload",
891 .fields = ikev2generic_fields,
892 .size = sizeof(struct ikev2_sa),
893 .pt = ISAKMP_NEXT_v2SA,
894 .nsst = v2_PROPOSAL_NON_LAST,
895};
896
897/* IKEv2 - Proposal sub-structure
898 *
899 * 3.3.1. Proposal Substructure
900 *
901 *
902 * 1 2 3
903 * 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
904 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
905 * ! 0 (last) or 2 ! RESERVED ! Proposal Length !
906 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
907 * ! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
908 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 * ~ SPI (variable) ~
910 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911 * ! !
912 * ~ <Transforms> ~
913 * ! !
914 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
915 *
916 * Figure 7: Proposal Substructure
917 */
918static field_desc ikev2prop_fields[] = {
919 { ft_lss, 8 / BITS_PER_BYTE8, "last proposal", &ikev2_last_proposal_desc },
920 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
921 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
922 { ft_nat, 8 / BITS_PER_BYTE8, "prop #", NULL((void*)0) },
923 { ft_enum, 8 / BITS_PER_BYTE8, "proto ID", &ikev2_proposal_protocol_id_names },
924 { ft_nat, 8 / BITS_PER_BYTE8, "spi size", NULL((void*)0) },
925 { ft_nat, 8 / BITS_PER_BYTE8, "# transforms", NULL((void*)0) },
926 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
927};
928
929struct_desc ikev2_prop_desc = {
930 .name = "IKEv2 Proposal Substructure Payload",
931 .fields = ikev2prop_fields,
932 .size = sizeof(struct ikev2_prop),
933 .nsst = v2_TRANSFORM_NON_LAST,
934};
935
936/*
937 * 3.3.2. Transform Substructure
938 *
939 * 1 2 3
940 * 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
941 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942 * ! 0 (last) or 3 ! RESERVED ! Transform Length !
943 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944 * !Transform Type ! RESERVED ! Transform ID !
945 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946 * ! !
947 * ~ Transform Attributes ~
948 * ! !
949 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
950 *
951 */
952
953static field_desc ikev2trans_fields[] = {
954 { ft_lss, 8 / BITS_PER_BYTE8, "last transform", &ikev2_last_transform_desc },
955 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
956 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
957 { ft_loose_enum, 8 / BITS_PER_BYTE8, "IKEv2 transform type", &ikev2_trans_type_names },
958 { ft_zig, 8 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
959 { ft_loose_enum_enum, 16 / BITS_PER_BYTE8, "IKEv2 transform ID", &v2_transform_ID_enums }, /* select enum based on transform type */
960 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
961};
962
963struct_desc ikev2_trans_desc = {
964 .name = "IKEv2 Transform Substructure Payload",
965 .fields = ikev2trans_fields,
966 .size = sizeof(struct ikev2_trans),
967};
968
969/*
970 * 3.3.5. [Transform] Attribute substructure
971 *
972 * 1 2 3
973 * 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
974 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
975 * !A! Attribute Type ! AF=0 Attribute Length !
976 * !F! ! AF=1 Attribute Value !
977 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
978 * ! AF=0 Attribute Value !
979 * ! AF=1 Not Transmitted !
980 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
981 *
982 */
983static field_desc ikev2_trans_attr_fields[] = {
984 { ft_af_enum, 16 / BITS_PER_BYTE8, "af+type", &ikev2_trans_attr_descs },
985 { ft_lv, 16 / BITS_PER_BYTE8, "length/value", NULL((void*)0) },
986 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
987};
988
989struct_desc ikev2_trans_attr_desc = {
990 .name = "IKEv2 Attribute Substructure Payload",
991 .fields = ikev2_trans_attr_fields,
992 .size = sizeof(struct ikev2_trans_attr),
993};
994
995/* 3.4. Key Exchange Payload
996 *
997 * The Key Exchange Payload, denoted KE in this memo, is used to
998 * exchange Diffie-Hellman public numbers as part of a Diffie-Hellman
999 * key exchange. The Key Exchange Payload consists of the IKE generic
1000 * payload header followed by the Diffie-Hellman public value itself.
1001 *
1002 * 1 2 3
1003 * 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
1004 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1005 * ! Next Payload !C! RESERVED ! Payload Length !
1006 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1007 * ! DH Group # ! RESERVED !
1008 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1009 * ! !
1010 * ~ Key Exchange Data ~
1011 * ! !
1012 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1013 *
1014 * Figure 10: Key Exchange Payload Format
1015 *
1016 */
1017static field_desc ikev2ke_fields[] = {
1018 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1019 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1020 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1021 { ft_enum, 16 / BITS_PER_BYTE8, "DH group", &oakley_group_names },
1022 { ft_zig, 16 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
1023 { ft_end, 0, NULL((void*)0), NULL((void*)0) },
1024};
1025
1026struct_desc ikev2_ke_desc = {
1027 .name = "IKEv2 Key Exchange Payload",
1028 .fields = ikev2ke_fields,
1029 .size = sizeof(struct ikev2_ke),
1030 .pt = ISAKMP_NEXT_v2KE,
1031};
1032
1033/*
1034 * 3.5. Identification Payloads
1035 *
1036 * The Identification Payloads, denoted IDi and IDr in this memo, allow
1037 * peers to assert an identity to one another. This identity may be
1038 * used for policy lookup, but does not necessarily have to match
1039 * anything in the CERT payload; both fields may be used by an
1040 * implementation to perform access control decisions.
1041 *
1042 * NOTE: In IKEv1, two ID payloads were used in each direction to hold
1043 * Traffic Selector (TS) information for data passing over the SA. In
1044 * IKEv2, this information is carried in TS payloads (see section 3.13).
1045 *
1046 * The Identification Payload consists of the IKE generic payload header
1047 * followed by identification fields as follows:
1048 *
1049 * 1 2 3
1050 * 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
1051 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1052 * ! Next Payload !C! RESERVED ! Payload Length !
1053 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1054 * ! ID Type ! "RESERVED" |
1055 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1056 * ! !
1057 * ~ Identification Data ~
1058 * ! !
1059 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1060 *
1061 * Figure 11: Identification Payload Format
1062 *
1063 * Because the ID payload's RESERVED field is included in the AUTH
1064 * hash calculation it isn't really reserved (aka send zero, ignore on
1065 * input). Hence it is flagged as ft_raw and not ft_zig.
1066 */
1067
1068static field_desc ikev2id_fields[] = {
1069 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1070 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1071 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1072 { ft_enum, 8 / BITS_PER_BYTE8, "ID type", &ikev2_ike_id_type_names },
1073 { ft_raw, 24 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
1074 { ft_end, 0, NULL((void*)0), NULL((void*)0) },
1075};
1076
1077struct_desc ikev2_id_i_desc = {
1078 .name ="IKEv2 Identification - Initiator - Payload",
1079 .fields = ikev2id_fields,
1080 .size = sizeof(struct ikev2_id),
1081 .pt = ISAKMP_NEXT_v2IDi,
1082};
1083
1084struct_desc ikev2_id_r_desc = {
1085 .name ="IKEv2 Identification - Responder - Payload",
1086 .fields = ikev2id_fields,
1087 .size = sizeof(struct ikev2_id),
1088 .pt = ISAKMP_NEXT_v2IDr,
1089};
1090
1091/*
1092 * IKEv2 - draft-ietf-ipsecme-qr-ikev2-01 (no ascii art provided in RFC)
1093 * PPK_ID types
1094 * 1 2 3
1095 * 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
1096 * +---------------+-----------------------------------------------+
1097 * | PPK Type | |
1098 * +---------------+ PPK Data +
1099 * ~ ~
1100 * +---------------+-----------------------------------------------+
1101 *
1102 * PPK_ID Type Value
1103 * ----------- -----
1104 * Reserved 0
1105 * PPK_ID_OPAQUE 1
1106 * PPK_ID_FIXED 2
1107 * Unassigned 3-127
1108 * Reserved for private use 128-255
1109 */
1110static field_desc ikev2_ppk_id_fields[] = {
1111 { ft_enum, 8 / BITS_PER_BYTE8, "PPK ID type", &ikev2_ppk_id_type_names },
1112 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1113};
1114
1115struct_desc ikev2_ppk_id_desc = {
1116 .name = "IKEv2 PPK ID Payload",
1117 .fields = ikev2_ppk_id_fields,
1118 .size = sizeof(struct ikev2_ppk_id),
1119};
1120
1121
1122static field_desc ikev2cp_fields[] = {
1123 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1124 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1125 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1126 { ft_enum, 8 / BITS_PER_BYTE8, "ikev2_cfg_type", &ikev2_cp_type_names },
1127 { ft_zig, 24 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
1128 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1129};
1130
1131struct_desc ikev2_cp_desc = {
1132 .name = "IKEv2 Configuration Payload",
1133 .fields = ikev2cp_fields,
1134 .size = sizeof(struct ikev2_cp),
1135 .pt = ISAKMP_NEXT_v2CP,
1136};
1137
1138static field_desc ikev2_cp_attrbute_fields[] = {
1139 { ft_enum, 16 / BITS_PER_BYTE8, "Attribute Type", &ikev2_cp_attribute_type_names },
1140 { ft_lv, 16 / BITS_PER_BYTE8, "length/value", NULL((void*)0) },
1141 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1142};
1143
1144struct_desc ikev2_cp_attribute_desc = {
1145 .name = "IKEv2 Configuration Payload Attribute",
1146 .fields = ikev2_cp_attrbute_fields,
1147 .size = sizeof(struct ikev2_cp_attribute),
1148};
1149
1150/* section 3.6
1151 * The Certificate Payload is defined as follows:
1152 *
1153 * 1 2 3
1154 * 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
1155 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1156 * ! Next Payload !C! RESERVED ! Payload Length !
1157 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1158 * ! Cert Encoding ! !
1159 * +-+-+-+-+-+-+-+-+ !
1160 * ~ Certificate Data ~
1161 * ! !
1162 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1163 *
1164 */
1165static field_desc ikev2_cert_fields[] = {
1166 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1167 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1168 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1169 { ft_enum, 8 / BITS_PER_BYTE8, "ikev2 cert encoding",
1170 &ikev2_cert_type_names },
1171 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1172};
1173
1174struct_desc ikev2_certificate_desc = {
1175 .name = "IKEv2 Certificate Payload",
1176 .fields = ikev2_cert_fields,
1177 .size = IKEV2_CERT_SIZE5,
1178 .pt = ISAKMP_NEXT_v2CERT,
1179};
1180
1181/* section 3.7
1182 *
1183 * The Certificate Request Payload is defined as follows:
1184 *
1185 * 1 2 3
1186 * 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
1187 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1188 * ! Next Payload !C! RESERVED ! Payload Length !
1189 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1190 * ! Cert Encoding ! !
1191 * +-+-+-+-+-+-+-+-+ !
1192 * ~ Certification Authority ~
1193 * ! !
1194 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1195 *
1196 */
1197
1198static field_desc ikev2_cert_req_fields[] = {
1199 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1200 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1201 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1202 { ft_enum, 8 / BITS_PER_BYTE8, "ikev2 cert encoding",
1203 &ikev2_cert_type_names },
1204 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1205};
1206
1207struct_desc ikev2_certificate_req_desc = {
1208 .name = "IKEv2 Certificate Request Payload",
1209 .fields = ikev2_cert_req_fields,
1210 .size = IKEV2_CERT_SIZE5,
1211 .pt = ISAKMP_NEXT_v2CERTREQ,
1212};
1213
1214/*
1215 * 3.8. Authentication Payload
1216 *
1217 * 1 2 3
1218 * 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
1219 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1220 * ! Next Payload !C! RESERVED ! Payload Length !
1221 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1222 * ! Auth Method ! RESERVED !
1223 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1224 * ! !
1225 * ~ Authentication Data ~
1226 * ! !
1227 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1228 *
1229 * Figure 14: Authentication Payload Format
1230 *
1231 */
1232static field_desc ikev2_auth_fields[] = {
1233 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1234 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1235 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1236 { ft_enum, 8 / BITS_PER_BYTE8, "auth method", &ikev2_auth_names },
1237 { ft_zig, 24 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
1238 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1239};
1240
1241struct_desc ikev2_auth_desc = {
1242 .name = "IKEv2 Authentication Payload",
1243 .fields = ikev2_auth_fields,
1244 .size = sizeof(struct ikev2_auth),
1245 .pt = ISAKMP_NEXT_v2AUTH,
1246};
1247
1248/*
1249 * 3.9. Nonce Payload
1250 *
1251 * The Nonce Payload, denoted Ni and Nr in this memo for the initiator's
1252 * and responder's nonce respectively, contains random data used to
1253 * guarantee liveness during an exchange and protect against replay
1254 * attacks.
1255 *
1256 * The Nonce Payload is defined as follows:
1257 *
1258 * 1 2 3
1259 * 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
1260 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1261 * ! Next Payload !C! RESERVED ! Payload Length !
1262 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1263 * ! !
1264 * ~ Nonce Data ~
1265 * ! !
1266 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1267 *
1268 * Figure 15: Nonce Payload Format
1269 */
1270struct_desc ikev2_nonce_desc = {
1271 .name = "IKEv2 Nonce Payload",
1272 .fields = ikev2generic_fields,
1273 .size = sizeof(struct ikev2_generic),
1274 .pt = ISAKMP_NEXT_v2Ni, /*==ISAKMP_NEXT_v2Nr*/
1275};
1276
1277/* 3.10 Notify Payload
1278 *
1279 * 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
1280 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1281 * ! Next Payload !C! RESERVED ! Payload Length !
1282 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1283 * ! Protocol ID ! SPI Size ! Notify Message Type !
1284 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1285 * ! !
1286 * ~ Security Parameter Index (SPI) ~
1287 * ! !
1288 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1289 * ! !
1290 * ~ Notification Data ~
1291 * ! !
1292 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1293 *
1294 */
1295static field_desc ikev2_notify_fields[] = {
1296 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1297 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1298 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1299 { ft_enum, 8 / BITS_PER_BYTE8, "Protocol ID", &ikev2_notify_protocol_id_names },
1300 /* names used are v1 names may be we should use 4306 3.3.1 names */
1301 { ft_nat, 8 / BITS_PER_BYTE8, "SPI size", NULL((void*)0) },
1302 { ft_loose_enum, 16 / BITS_PER_BYTE8, "Notify Message Type",
1303 &ikev2_notify_names },
1304 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1305};
1306
1307struct_desc ikev2_notify_desc = {
1308 .name = "IKEv2 Notify Payload",
1309 .fields = ikev2_notify_fields,
1310 .size = sizeof(struct ikev2_notify),
1311 .pt = ISAKMP_NEXT_v2N,
1312};
1313
1314/* IKEv2 Delete Payload
1315 * layout from RFC 5996 Section 3.11
1316 * This is followed by a variable length SPI.
1317 *
1318 * 1 2 3
1319 * 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
1320 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1321 * ! Next Payload !C| RESERVED ! Payload Length !
1322 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1323 * ! Protocol ID ! SPI Size ! Num of SPIs !
1324 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1325 * ! !
1326 * ~ Security Parameter Index(es) (SPI) ~
1327 * ! !
1328 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1329 */
1330
1331static field_desc ikev2_delete_fields[] = {
1332 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1333 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1334 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1335 { ft_enum, 8 / BITS_PER_BYTE8, "protocol ID", &ikev2_delete_protocol_id_names },
1336 { ft_nat, 8 / BITS_PER_BYTE8, "SPI size", NULL((void*)0) },
1337 { ft_nat, 16 / BITS_PER_BYTE8, "number of SPIs", NULL((void*)0) },
1338 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1339};
1340
1341struct_desc ikev2_delete_desc = {
1342 .name = "IKEv2 Delete Payload",
1343 .fields = ikev2_delete_fields,
1344 .size = sizeof(struct ikev2_delete),
1345 .pt = ISAKMP_NEXT_v2D,
1346};
1347
1348/*
1349 * 3.12. Vendor ID Payload
1350 *
1351 * The Vendor ID Payload fields are defined as follows:
1352 *
1353 * 1 2 3
1354 * 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
1355 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1356 * ! Next Payload !C! RESERVED ! Payload Length !
1357 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1358 * ! !
1359 * ~ Vendor ID (VID) ~
1360 * ! !
1361 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1362 *
1363 */
1364struct_desc ikev2_vendor_id_desc = {
1365 .name = "IKEv2 Vendor ID Payload",
1366 .fields = ikev2generic_fields,
1367 .size = sizeof(struct ikev2_generic),
1368 .pt = ISAKMP_NEXT_v2V,
1369};
1370
1371/*
1372 * 3.13. Traffic Selector Payload
1373 *
1374 *
1375 * The Traffic Selector Payload, denoted TS in this memo, allows peers
1376 * to identify packet flows for processing by IPsec security services.
1377 * The Traffic Selector Payload consists of the IKE generic payload
1378 * header followed by individual traffic selectors as follows:
1379 *
1380 * 1 2 3
1381 * 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
1382 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1383 * ! Next Payload !C! RESERVED ! Payload Length !
1384 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1385 * ! Number of TSs ! RESERVED !
1386 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1387 * ! !
1388 * ~ <Traffic Selectors> ~
1389 * ! !
1390 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1391 */
1392static field_desc ikev2_ts_fields[] = {
1393 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1394 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1395 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1396 { ft_nat, 8 / BITS_PER_BYTE8, "number of TS", NULL((void*)0) },
1397 { ft_zig, 24 / BITS_PER_BYTE8, "reserved", NULL((void*)0) },
1398 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1399};
1400struct_desc ikev2_ts_i_desc = {
1401 .name = "IKEv2 Traffic Selector - Initiator - Payload",
1402 .fields = ikev2_ts_fields,
1403 .size = sizeof(struct ikev2_ts),
1404 .pt = ISAKMP_NEXT_v2TSi,
1405};
1406struct_desc ikev2_ts_r_desc = {
1407 .name = "IKEv2 Traffic Selector - Responder - Payload",
1408 .fields = ikev2_ts_fields,
1409 .size = sizeof(struct ikev2_ts),
1410 .pt = ISAKMP_NEXT_v2TSr,
1411};
1412
1413/*
1414 * Different types of traffic selector are handled together
1415 * See RFC 7296 and draft-ietf-ipsecme-labeled-ipsec-04
1416 *
1417 * 3.13.1. Traffic Selector
1418 *
1419 * 1 2 3
1420 * 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
1421 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1422 * ! TS Type !IP Protocol ID*| Selector Length |
1423 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1424 * | Start Port | End Port |
1425 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1426 * ! !
1427 * ~ Starting Address ~
1428 * ! !
1429 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1430 * ! !
1431 * ~ Ending Address ~
1432 * ! !
1433 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1434 *
1435 * Figure 20: Traffic Selector
1436 *
1437 * 2.1. TS_SECLABEL payload format
1438 *
1439 * 1 2 3
1440 * 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
1441 * +---------------+---------------+-------------------------------+
1442 * | TS Type | Reserved | Selector Length |
1443 * +---------------+---------------+-------------------------------+
1444 * | |
1445 * ~ Security Label* ~
1446 * | |
1447 * +---------------------------------------------------------------+
1448 *
1449 * Figure 1: Labeled IPsec Traffic Selector
1450 */
1451
1452/*
1453 * These are just read raw, so no struct or fields/desc are needed
1454 */
1455/*
1456 * Traffic Selector Header - read header, then sub out work to type handler
1457 */
1458static field_desc ikev2_ts_header_fields[] = {
1459 { ft_enum, 8 / BITS_PER_BYTE8, "TS type", &ikev2_ts_type_names },
1460 { ft_loose_enum, 8 / BITS_PER_BYTE8, "IP Protocol ID", &ip_protocol_id_names, },
1461 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1462 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1463};
1464struct_desc ikev2_ts_header_desc = {
1465 .name = "IKEv2 Traffic Selector Header",
1466 .fields = ikev2_ts_header_fields,
1467 .size = 4 /*sizeof(struct ikev2_ts_header) */ ,
1468};
1469
1470static field_desc ikev2_ts_portrange_fields[] = {
1471 { ft_nat, 16 / BITS_PER_BYTE8, "start port", NULL((void*)0) },
1472 { ft_nat, 16 / BITS_PER_BYTE8, "end port", NULL((void*)0) },
1473 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1474};
1475struct_desc ikev2_ts_portrange_desc = {
1476 .name = "IKEv2 IP Traffic Selector port range",
1477 .fields = ikev2_ts_portrange_fields,
1478 .size = sizeof(struct ikev2_ts_portrange),
1479};
1480
1481/*
1482 * 3.14. Encrypted Payload
1483 * 1 2 3
1484 * 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
1485 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1486 * ! Next Payload !C! RESERVED ! Payload Length !
1487 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1488 * ! Initialization Vector !
1489 * ! (length is block size for encryption algorithm) !
1490 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1491 * ~ Encrypted IKE Payloads ~
1492 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1493 * ! ! Padding (0-255 octets) !
1494 * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
1495 * ! ! Pad Length !
1496 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1497 * ~ Integrity Checksum Data ~
1498 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1499 *
1500 * Figure 21: Encrypted Payload Format
1501 */
1502struct_desc ikev2_sk_desc = {
1503 .name = "IKEv2 Encryption Payload",
1504 .fields = ikev2generic_fields,
1505 .size = sizeof(struct ikev2_generic),
1506 .pt = ISAKMP_NEXT_v2SK,
1507};
1508
1509/*
1510 * RFC 7383 2.5. Fragmenting Message
1511 *
1512 * 1 2 3
1513 * 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
1514 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1515 * | Next Payload |C| RESERVED | Payload Length |
1516 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1517 * | Fragment Number | Total Fragments |
1518 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1519 * | Initialization Vector |
1520 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1521 * ~ Encrypted content ~
1522 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1523 * | | Padding (0-255 octets) |
1524 * +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
1525 * | | Pad Length |
1526 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1527 * ~ Integrity Checksum Data ~
1528 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1529 *
1530 * Next Payload (1 octet) - in the very first fragment (with Fragment
1531 * Number equal to 1), this field MUST be set to the payload type of
1532 * the first inner payload (the same as for the Encrypted payload).
1533 * In the rest of the Fragment messages (with Fragment Number greater
1534 * than 1), this field MUST be set to zero.
1535 *
1536 * XXX: Even though the SKF's Next Payload field isn't really part of
1537 * the Next Payload chain (it is under the fragmentation code's
1538 * control so should be an ft_enum) it needs to be ft_pnpc so that the
1539 * code triggering an update of the message's next payload chain
1540 * executed.
1541 *
1542 * Encrypted Fragment Payload
1543 */
1544static field_desc ikev2skf_fields[] = {
1545 { ft_pnpc, 8 / BITS_PER_BYTE8, "next payload type", &ikev2_payload_names },
1546 { ft_lset, 8 / BITS_PER_BYTE8, "flags", &payload_flag_names },
1547 { ft_len, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) },
1548 { ft_nat, 16 / BITS_PER_BYTE8, "fragment number", NULL((void*)0) },
1549 { ft_nat, 16 / BITS_PER_BYTE8, "total fragments", NULL((void*)0) },
1550 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1551};
1552struct_desc ikev2_skf_desc = {
1553 .name = "IKEv2 Encrypted Fragment",
1554 .fields = ikev2skf_fields,
1555 .size = sizeof(struct ikev2_skf),
1556 .pt = ISAKMP_NEXT_v2SKF,
1557};
1558
1559/*
1560 * IKEv2 REDIRECT Payload - variable part
1561 *
1562 * 1 2 3
1563 * 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
1564 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1565 * | GW Ident Type | GW Ident Len | |
1566 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~
1567 * ~ New Responder GW Identity ~
1568 * | |
1569 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1570 * | |
1571 * ~ Nonce Data ~
1572 * | |
1573 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1574 *
1575 * This is actually Notify Data in IKEv2 Notify payload (see RFC 5685)
1576 *
1577 * This struct_desc will be used for checking GW Ident Type and GW Ident Len
1578 * fields, the rest when using in_struct will be stored in separate pb_stream
1579 */
1580static field_desc ikev2redirect_fields[] = {
1581 { ft_enum, 8 / BITS_PER_BYTE8, "GW Identity type", &ikev2_redirect_gw_names },
1582 { ft_nat, 8 / BITS_PER_BYTE8, "GW Identity length", NULL((void*)0) }, /* this cannot be ft_len,
1583 because of the Nonce Data */
1584 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1585};
1586
1587struct_desc ikev2_redirect_desc = {
1588 .name = "IKEv2 Redirect Notify Data",
1589 .fields = ikev2redirect_fields,
1590 .size = sizeof(struct ikev2_redirect_part),
1591};
1592
1593static field_desc suggested_group_fields[] = {
1594 { ft_enum, 16 / BITS_PER_BYTE8, "suggested DH Group", &oakley_group_names },
1595 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1596};
1597
1598struct_desc suggested_group_desc = {
1599 .name = "Suggested Group",
1600 .fields = suggested_group_fields,
1601 .size = sizeof(struct suggested_group),
1602 .pt = ISAKMP_NEXT_v2NONE,
1603};
1604
1605/*
1606 * IPcomp Notify as per RFC 7296:
1607 *
1608 * The data associated with this Notify message includes a two-octet
1609 * IPComp CPI followed by a one-octet Transform ID optionally followed
1610 * by attributes whose length and format are defined by that Transform
1611 * ID.
1612 *
1613 * Currently, we only support one Transform ID (2, IPCOMP_DEFLATE) which has
1614 * no further attributes.
1615 */
1616static field_desc ikev2notify_ipcomp_fields[] = {
1617 { ft_nat, 16 / BITS_PER_BYTE8, "IPcomp SPI (CPI)", NULL((void*)0) },
1618 { ft_enum, 8 / BITS_PER_BYTE8, "IKEv2 Notification IPCOMP Transform IDs", &ipsec_ipcomp_algo_names },
1619 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1620};
1621
1622struct_desc ikev2notify_ipcomp_data_desc = {
1623 .name = "IKEv2 IPcomp Notify Data",
1624 .fields = ikev2notify_ipcomp_fields,
1625 //.size = sizeof(struct ikev2_notify_ipcomp_data),
1626 .size = 3,
1627};
1628
1629/*
1630 * Undocumented Security Context for Labeled IPsec
1631 *
1632 * See struct sec_ctx in state.h
1633 */
1634#include "ikev1_labeled_ipsec.h" /* for struct sec_ctx */
1635
1636static field_desc sec_ctx_fields[] = {
1637 { ft_nat, 8 / BITS_PER_BYTE8, "DOI", NULL((void*)0) },
1638 { ft_nat, 8 / BITS_PER_BYTE8, "Alg", NULL((void*)0) },
1639 { ft_nat, 16 / BITS_PER_BYTE8, "length", NULL((void*)0) }, /* not ft_len */
1640 { ft_end, 0, NULL((void*)0), NULL((void*)0) }
1641};
1642
1643struct_desc sec_ctx_desc = {
1644 .name = "Security Label Context",
1645 .fields = sec_ctx_fields,
1646 .size = sizeof(struct sec_ctx),
1647};
1648
1649/*
1650 * descriptor for each V1 payload type
1651 *
1652 * There is a slight problem in that some payloads differ, depending
1653 * on the mode. Since this is table only used for top-level payloads,
1654 * Proposal and Transform payloads need not be handled. That leaves
1655 * only Identification payloads as a problem. We make all these
1656 * entries NULL
1657 */
1658struct_desc *v1_payload_desc(unsigned p)
1659{
1660 static struct_desc *const v1_payload_descs[] = {
1661 NULL((void*)0), /* 0 ISAKMP_NEXT_NONE (No other payload following) */
1662 &isakmp_sa_desc, /* 1 ISAKMP_NEXT_SA (Security Association) */
1663 NULL((void*)0), /* 2 ISAKMP_NEXT_P (Proposal) */
1664 NULL((void*)0), /* 3 ISAKMP_NEXT_T (Transform) */
1665 &isakmp_keyex_desc, /* 4 ISAKMP_NEXT_KE (Key Exchange) */
1666 NULL((void*)0), /* 5 ISAKMP_NEXT_ID (Identification) */
1667 &isakmp_ipsec_certificate_desc, /* 6 ISAKMP_NEXT_CERT (Certificate) */
1668 &isakmp_ipsec_cert_req_desc, /* 7 ISAKMP_NEXT_CR (Certificate Request) */
1669 &isakmp_hash_desc, /* 8 ISAKMP_NEXT_HASH (Hash) */
1670 &isakmp_signature_desc, /* 9 ISAKMP_NEXT_SIG (Signature) */
1671 &isakmp_nonce_desc, /* 10 ISAKMP_NEXT_NONCE (Nonce) */
1672 &isakmp_notification_desc, /* 11 ISAKMP_NEXT_N (Notification) */
1673 &isakmp_delete_desc, /* 12 ISAKMP_NEXT_D (Delete) */
1674 &isakmp_vendor_id_desc, /* 13 ISAKMP_NEXT_VID (Vendor ID) */
1675 &isakmp_attr_desc, /* 14 ISAKMP_NEXT_MCFG_ATTR (ModeCfg) */
1676 NULL((void*)0), /* 15 */
1677 NULL((void*)0), /* 16 */
1678 NULL((void*)0), /* 17 */
1679 NULL((void*)0), /* 18 */
1680 NULL((void*)0), /* 19 */
1681 &isakmp_nat_d, /* 20=130 ISAKMP_NEXT_NATD_RFC=ISAKMP_NEXT_NATD_DRAFTS (NAT-D) */
1682 &isakmp_nat_oa, /* 21=131 ISAKMP_NEXT_NATOA_RFC=ISAKMP_NEXT_NATOA_DRAFTS (NAT-OA) */
1683 };
1684 return p < elemsof(v1_payload_descs)(sizeof(v1_payload_descs) / sizeof(*(v1_payload_descs))) ? v1_payload_descs[p] : NULL((void*)0);
1685}
1686
1687struct_desc *v2_payload_desc(unsigned p)
1688{
1689 static struct_desc *const v2_payload_descs[] = {
1690 &ikev2_sa_desc, /* 33 ISAKMP_NEXT_v2SA */
1691 &ikev2_ke_desc, /* 34 ISAKMP_NEXT_v2KE */
1692 &ikev2_id_i_desc, /* 35 ISAKMP_NEXT_v2IDi */
1693 &ikev2_id_r_desc, /* 36 ISAKMP_NEXT_v2IDr */
1694 &ikev2_certificate_desc, /* 37 ISAKMP_NEXT_v2CERT */
1695 &ikev2_certificate_req_desc, /* 38 ISAKMP_NEXT_v2CERTREQ */
1696 &ikev2_auth_desc, /* 39 ISAKMP_NEXT_v2AUTH */
1697 &ikev2_nonce_desc, /* 40 ISAKMP_NEXT_v2Ni / ISAKMP_NEXT_v2Nr */
1698 &ikev2_notify_desc, /* 41 ISAKMP_NEXT_v2N */
1699 &ikev2_delete_desc, /* 42 ISAKMP_NEXT_v2D */
1700 &ikev2_vendor_id_desc, /* 43 ISAKMP_NEXT_v2V */
1701 &ikev2_ts_i_desc, /* 44 ISAKMP_NEXT_v2TSi */
1702 &ikev2_ts_r_desc, /* 45 ISAKMP_NEXT_v2TSr */
1703 &ikev2_sk_desc, /* 46 ISAKMP_NEXT_v2SK */
1704 &ikev2_cp_desc, /* 47 ISAKMP_NEXT_v2CP */
1705 NULL((void*)0), /* 48 */
1706 NULL((void*)0), /* 49 */
1707 NULL((void*)0), /* 50 */
1708 NULL((void*)0), /* 51 */
1709 NULL((void*)0), /* 52 */
1710 &ikev2_skf_desc, /* 53 ISAKMP_NEXT_v2SKF */
1711 };
1712 if (p < ISAKMP_v2PAYLOAD_TYPE_BASEISAKMP_NEXT_v2SA) {
1713 return NULL((void*)0);
1714 }
1715 unsigned q = p - ISAKMP_v2PAYLOAD_TYPE_BASEISAKMP_NEXT_v2SA;
1716 if (q >= elemsof(v2_payload_descs)(sizeof(v2_payload_descs) / sizeof(*(v2_payload_descs)))) {
1717 return NULL((void*)0);
1718 }
1719 return v2_payload_descs[q];
1720}
1721
1722void init_pbs(pb_stream *pbs, uint8_t *start, size_t len, const char *name)
1723{
1724 *pbs = (pb_stream) {
1725 /* .container = NULL, */
1726 /* .desc = NULL, */
1727 .name = name,
1728 .start = start,
1729 .cur = start,
1730 .roof = start + len,
1731 /* .lenfld = NULL, */
1732 /* .lenfld_desc = NULL, */
1733 /* .previous_np = NULL, */
1734 /* .previous_npc.fp = NULL, */
1735 /* .previous_np_struct = NULL, */
1736 };
1737}
1738
1739struct pbs_outpacket_byte_stream open_pbs_out(const char *name, uint8_t *buffer, size_t sizeof_buffer,
1740 struct logger *logger)
1741{
1742 struct pbs_outpacket_byte_stream outs;
1743 init_pbs(&outs, buffer, sizeof_buffer, name);
1744 memset(buffer, 0xFA, sizeof_buffer); /* value likely to be unpleasant */
1745 outs.outs_logger = logger;
1746 dbg("opening output PBS %s", name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("opening output PBS %s", name); } }
;
1747 return outs;
1748}
1749
1750pb_stream same_chunk_as_pbs_in(chunk_t chunk, const char *name)
1751{
1752 pb_stream pbs;
1753 init_pbs(&pbs, chunk.ptr, chunk.len, name);
1754 return pbs;
1755}
1756
1757shunk_t same_pbs_out_as_shunk(pb_stream *pbs)
1758{
1759 return shunk2(pbs->start, pbs_offset(pbs)((size_t)((pbs)->cur - (pbs)->start)));
1760}
1761
1762chunk_t clone_pbs_out_as_chunk(pb_stream *pbs, const char *name)
1763{
1764 return clone_hunk(same_pbs_out_as_shunk(pbs), name)({ typeof(same_pbs_out_as_shunk(pbs)) hunk_ = same_pbs_out_as_shunk
(pbs); clone_bytes_as_chunk(hunk_.ptr, hunk_.len, name); })
;
1765}
1766
1767shunk_t same_pbs_in_as_shunk(const struct pbs_inpacket_byte_stream *pbs)
1768{
1769 return shunk2(pbs->start, pbs_room(pbs)((size_t)((pbs)->roof - (pbs)->start)));
1770}
1771
1772chunk_t clone_pbs_in_as_chunk(const struct pbs_inpacket_byte_stream *pbs, const char *name)
1773{
1774 return clone_hunk(shunk2(pbs->start, pbs_room(pbs)), name)({ typeof(shunk2(pbs->start, ((size_t)((pbs)->roof - (pbs
)->start)))) hunk_ = shunk2(pbs->start, ((size_t)((pbs)
->roof - (pbs)->start))); clone_bytes_as_chunk(hunk_.ptr
, hunk_.len, name); })
;
1775}
1776
1777shunk_t pbs_in_left_as_shunk(const pb_stream *pbs)
1778{
1779 return shunk2(pbs->cur, pbs_left(pbs)((size_t)((pbs)->roof - (pbs)->cur)));
1780}
1781
1782/*
1783 * print a natural number using the specified FMT, with the value in
1784 * network-byte-order appended.
1785 */
1786
1787static void DBG_print_nat(const field_desc *fp, uintmax_t nat)
1788{
1789 LSWLOG_DEBUG(buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*)
0); jambuf_to_logger(buf, &failsafe_logger, DEBUG_STREAM)
, buf = ((void*)0))
{
1790 jam(buf, " %s: %ju", fp->name, nat);
1791 jam(buf, " (");
1792 /*
1793 * Note that a single byte value such as "(23)" is
1794 * ambiguous. Since it is prefixed by the equivalent
1795 * decimal it should be clear.
1796 *
1797 * XXX: the same conversion code appears in
1798 * out_struct() and probably elsewhere?
1799 */
1800 passert(fp->size > 0)({ _Bool assertion__ = fp->size > 0; if (!assertion__) {
where_t here = ({ static const struct where here = { .func =
__func__, .file = "programs/pluto/packet.c", .line = 1800, }
; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "fp->size > 0"); } (
void) 1; })
;
1801 passert(fp->size <= sizeof(nat))({ _Bool assertion__ = fp->size <= sizeof(nat); if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 1801,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "fp->size <= sizeof(nat)"
); } (void) 1; })
;
1802 uint8_t bytes[sizeof(nat)];
1803 uint8_t *cur = bytes + fp->size;
1804 uintmax_t n = nat;
1805 do {
1806 cur--;
1807 *cur = (uint8_t)n;
1808 n >>= BITS_PER_BYTE8;
1809 } while (cur > bytes);
1810 jam_dump_bytes(buf, bytes, fp->size);
1811 jam(buf, ")");
1812 }
1813}
1814
1815/*
1816 * print a host-byte-ordered struct
1817 *
1818 * This code assumes that the network and host structure members have
1819 * the same alignment and size! This requires that all padding be
1820 * explicit.
1821 */
1822
1823static void DBG_print_struct(const char *label, const void *struct_ptr,
1824 struct_desc *sd, bool_Bool len_meaningful)
1825{
1826 bool_Bool immediate = false0;
1827 const uint8_t *inp = struct_ptr;
1828 field_desc *fp;
1829 uintmax_t last_enum = 0;
1830
1831 DBG_log("%s%s:", label, sd->name);
1832
1833 for (fp = sd->fields; fp->field_type != ft_end; fp++) {
1834 int i = fp->size;
1835 uintmax_t n = 0;
1836
1837 switch (fp->field_type) {
1838 case ft_zig: /* zero (ignore violations) */
1839 inp += i;
1840 break;
1841 case ft_nat: /* natural number (may be 0) */
1842 case ft_len: /* length of this struct and any following crud */
1843 case ft_lv: /* length/value field of attribute */
1844 case ft_enum: /* value from an enumeration */
1845 case ft_loose_enum: /* value from an enumeration with only some names known */
1846 case ft_mnpc:
1847 case ft_pnpc:
1848 case ft_lss: /* last substructure field */
1849 case ft_loose_enum_enum: /* value from an enumeration with partial name table based on previous enum */
1850 case ft_af_enum: /* Attribute Format + value from an enumeration */
1851 case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
1852 case ft_lset: /* bits representing set */
1853 /* grab bytes in host-byte-order */
1854 switch (i) {
1855 case 8 / BITS_PER_BYTE8:
1856 n = *(const uint8_t *)inp;
1857 break;
1858 case 16 / BITS_PER_BYTE8:
1859 n = *(const uint16_t *)inp;
1860 break;
1861 case 32 / BITS_PER_BYTE8:
1862 n = *(const uint32_t *)inp;
1863 break;
1864 default:
1865 bad_case(i)libreswan_bad_case("i", (i), ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/packet.c", .line
= 1865, }; &here; }))
;
1866 }
1867
1868 /* display the result */
1869 switch (fp->field_type) {
1870 case ft_len: /* length of this struct and any following crud */
1871 case ft_lv: /* length/value field of attribute */
1872 if (!immediate && !len_meaningful)
1873 break;
1874 /* FALL THROUGH */
1875 case ft_nat: /* natural number (may be 0) */
1876 DBG_print_nat(fp, n);
1877 break;
1878
1879 case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
1880 case ft_af_enum: /* Attribute Format + value from an enumeration */
1881 {
1882 immediate = ((n & ISAKMP_ATTR_AF_MASK0x8000) ==
1883 ISAKMP_ATTR_AF_TV0x8000);
1884 last_enum = n & ~ISAKMP_ATTR_AF_MASK0x8000;
1885 /*
1886 * try to deal with fp->desc
1887 * containing a selection of
1888 * AF+<value> and <value> entries.
1889 *
1890 * NB and NAME must have same scope.
1891 */
1892 esb_buf nb;
1893 const char *name = enum_name(fp->desc, last_enum);
1894 if (name == NULL((void*)0)) {
1895 name = enum_show(fp->desc, n, &nb);
1896 }
1897 DBG_log(" %s: %s%s (0x%jx)",
1898 fp->name,
1899 immediate ? "AF+" : "",
1900 name, n);
1901 break;
1902 }
1903
1904 case ft_enum: /* value from an enumeration */
1905 case ft_loose_enum: /* value from an enumeration with only some names known */
1906 case ft_mnpc:
1907 case ft_pnpc:
1908 case ft_lss:
1909 {
1910 last_enum = n;
1911 esb_buf nb;
1912 DBG_log(" %s: %s (0x%jx)",
1913 fp->name,
1914 enum_show(fp->desc, n, &nb),
1915 n);
1916 break;
1917 }
1918
1919 case ft_loose_enum_enum:
1920 {
1921 esb_buf buf;
1922 const char *name = enum_enum_show(fp->desc, last_enum, n, &buf);
1923 DBG_log(" %s: %s (0x%jx)",
1924 fp->name, name, n);
1925 break;
1926 }
1927
1928 case ft_lset: /* bits representing set */
1929 LSWLOG_DEBUG(buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*)
0); jambuf_to_logger(buf, &failsafe_logger, DEBUG_STREAM)
, buf = ((void*)0))
{
1930 jam(buf, " %s: ", fp->name);
1931 jam_lset(buf, fp->desc, n);
1932 jam(buf, " (0x%jx)", n);
1933 }
1934 break;
1935
1936 default:
1937 bad_case(fp->field_type)libreswan_bad_case("fp->field_type", (fp->field_type), (
{ static const struct where here = { .func = __func__, .file =
"programs/pluto/packet.c", .line = 1937, }; &here; }))
;
1938 }
1939 inp += i;
1940 break;
1941
1942 case ft_raw: /* bytes to be left in network-order */
1943 LSWLOG_DEBUG(buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*)
0); jambuf_to_logger(buf, &failsafe_logger, DEBUG_STREAM)
, buf = ((void*)0))
{
1944 jam(buf, " %s: ", fp->name);
1945 jam_dump_bytes(buf, inp, i);
1946 }
1947 inp += i;
1948 break;
1949
1950 default:
1951 bad_case(fp->field_type)libreswan_bad_case("fp->field_type", (fp->field_type), (
{ static const struct where here = { .func = __func__, .file =
"programs/pluto/packet.c", .line = 1951, }; &here; }))
;
1952 }
1953 }
1954}
1955
1956static void DBG_prefix_print_struct(const pb_stream *pbs,
1957 const char *label, const void *struct_ptr,
1958 struct_desc *sd, bool_Bool len_meaningful)
1959{
1960 /* print out a title, with a prefix of asterisks to show
1961 * the nesting level.
1962 */
1963 char space[40]; /* arbitrary limit on label+flock-of-* */
1964 size_t len = strlen(label);
1965
1966 if (sizeof(space) <= len) {
1967 DBG_print_struct(label, struct_ptr, sd, len_meaningful);
1968 } else {
1969 const pb_stream *p = pbs;
1970 char *pre = &space[sizeof(space) - (len + 1)];
1971
1972 strcpy(pre, label);
1973
1974 /* put at least one * out */
1975 for (;; ) {
1976 if (pre <= space)
1977 break;
1978 *--pre = '*';
1979 if (p == NULL((void*)0))
1980 break;
1981 p = p->container;
1982 }
1983 DBG_print_struct(pre, struct_ptr, sd, len_meaningful);
1984 }
1985}
1986
1987/* "parse" a network struct into a host struct.
1988 *
1989 * This code assumes that the network and host structure
1990 * members have the same alignment and size! This requires
1991 * that all padding be explicit.
1992 *
1993 * If obj_pbs is supplied, a new pb_stream is created for the
1994 * variable part of the structure (this depends on their
1995 * being one length field in the structure). The cursor of this
1996 * new PBS is set to after the parsed part of the struct.
1997 *
1998 * This routine returns TRUE iff it succeeds.
1999 */
2000
2001diag_t pbs_in_struct(struct pbs_inpacket_byte_stream *ins, struct_desc *sd,
2002 void *dest_start, size_t dest_size,
2003 struct pbs_inpacket_byte_stream *obj_pbs)
2004{
2005 uint8_t *cur = ins->cur;
2006 if (cur + sd->size > ins->roof) {
2007 return diag("not enough room in input packet for %s (remain=%li, sd->size=%zu)",
2008 sd->name, (long int)(ins->roof - cur),
2009 sd->size);
2010 }
2011
2012 passert(dest_size >= sd->size)({ _Bool assertion__ = dest_size >= sd->size; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2012,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "dest_size >= sd->size"
); } (void) 1; })
;
2013 uint8_t *roof = cur + sd->size; /* may be changed by a length field */
2014 bool_Bool length_field_found = false0;
2015 uint8_t *dest = dest_start;
2016 uint8_t *dest_end = dest + dest_size;
2017 bool_Bool immediate = false0;
2018
2019 for (field_desc *fp = sd->fields; fp->field_type != ft_end; fp++) {
2020
2021 /* field ends within PBS? */
2022 passert(cur + fp->size <= ins->roof)({ _Bool assertion__ = cur + fp->size <= ins->roof; if
(!assertion__) { where_t here = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2022, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "cur + fp->size <= ins->roof"
); } (void) 1; })
;
2023 /* field ends within struct? */
2024 passert(cur + fp->size <= ins->cur + sd->size)({ _Bool assertion__ = cur + fp->size <= ins->cur + sd
->size; if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2024, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "cur + fp->size <= ins->cur + sd->size"
); } (void) 1; })
;
2025 /* field ends within dest */
2026 passert(dest + fp->size <= dest_end)({ _Bool assertion__ = dest + fp->size <= dest_end; if (
!assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/packet.c", .line
= 2026, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_passert(logger_, here, "%s", "dest + fp->size <= dest_end"
); } (void) 1; })
;
2027
2028#if 0
2029 dbg("%td (%td) '%s'.'%s' %d bytes ",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%td (%td) '%s'.'%s' %d bytes ", (cur - ins->
cur), (cur - ins->start), sd->name, fp->name, fp->
size); } }
2030 (cur - ins->cur), (cur - ins->start),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%td (%td) '%s'.'%s' %d bytes ", (cur - ins->
cur), (cur - ins->start), sd->name, fp->name, fp->
size); } }
2031 sd->name, fp->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%td (%td) '%s'.'%s' %d bytes ", (cur - ins->
cur), (cur - ins->start), sd->name, fp->name, fp->
size); } }
2032 fp->size){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%td (%td) '%s'.'%s' %d bytes ", (cur - ins->
cur), (cur - ins->start), sd->name, fp->name, fp->
size); } }
;
2033#endif
2034
2035 switch (fp->field_type) {
2036 case ft_zig: /* should be zero, ignore if not - liberal in what to receive, strict to send */
2037 for (size_t i = fp->size; i != 0; i--) {
2038 uint8_t byte = *cur;
2039 if (byte != 0) {
2040 /*
2041 * We cannot zeroize it, it
2042 * would break our hash
2043 * calculation.
2044 *
2045 * XXX: bytes used for hashing
2046 * can't be zero/ignore.
2047 */
2048 dbg("byte at offset %td (%td) of '%s'.'%s' is 0x%02"PRIx8" but should have been zero (ignored)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("byte at offset %td (%td) of '%s'.'%s' is 0x%02"
"x"" but should have been zero (ignored)", (cur - ins->cur
), (cur - ins->start), sd->name, fp->name, byte); } }
2049 (cur - ins->cur),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("byte at offset %td (%td) of '%s'.'%s' is 0x%02"
"x"" but should have been zero (ignored)", (cur - ins->cur
), (cur - ins->start), sd->name, fp->name, byte); } }
2050 (cur - ins->start),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("byte at offset %td (%td) of '%s'.'%s' is 0x%02"
"x"" but should have been zero (ignored)", (cur - ins->cur
), (cur - ins->start), sd->name, fp->name, byte); } }
2051 sd->name, fp->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("byte at offset %td (%td) of '%s'.'%s' is 0x%02"
"x"" but should have been zero (ignored)", (cur - ins->cur
), (cur - ins->start), sd->name, fp->name, byte); } }
2052 byte){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("byte at offset %td (%td) of '%s'.'%s' is 0x%02"
"x"" but should have been zero (ignored)", (cur - ins->cur
), (cur - ins->start), sd->name, fp->name, byte); } }
;
2053 }
2054 cur++;
2055 *dest++ = '\0';
2056 }
2057 break;
2058
2059 case ft_nat: /* natural number (may be 0) */
2060 case ft_len: /* length of this struct and any following crud */
2061 case ft_lv: /* length/value field of attribute */
2062 case ft_enum: /* value from an enumeration */
2063 case ft_loose_enum: /* value from an enumeration with only some names known */
2064 case ft_mnpc:
2065 case ft_pnpc:
2066 case ft_lss:
2067 case ft_loose_enum_enum: /* value from an enumeration with partial name table based on previous enum */
2068 case ft_af_enum: /* Attribute Format + value from an enumeration */
2069 case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
2070 case ft_lset: /* bits representing set */
2071 {
2072 uintmax_t n = 0;
2073
2074 /* Reportedly fails on arm, see bug #775 */
2075 for (size_t i = fp->size; i != 0; i--)
2076 n = (n << BITS_PER_BYTE8) | *cur++;
2077
2078 switch (fp->field_type) {
2079 case ft_len: /* length of this struct and any following crud */
2080 case ft_lv: /* length/value field of attribute */
2081 {
2082 passert(!length_field_found && obj_pbs != NULL)({ _Bool assertion__ = !length_field_found && obj_pbs
!= ((void*)0); if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2082, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "!length_field_found && obj_pbs != ((void*)0)"
); } (void) 1; })
;
2083 length_field_found = true1;
2084 size_t len = fp->field_type ==
2085 ft_len ? n :
2086 immediate ? sd->size :
2087 n + sd->size;
2088
2089 if (len < sd->size) {
2090 return diag("%zd-byte %s of %s is smaller than minimum",
2091 len, fp->name, sd->name);
2092 }
2093
2094 if (pbs_left(ins)((size_t)((ins)->roof - (ins)->cur)) < len) {
2095 return diag("%zd-byte %s of %s is larger than can fit",
2096 len, fp->name, sd->name);
2097 }
2098
2099 roof = ins->cur + len;
2100 break;
2101 }
2102
2103 case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
2104 case ft_af_enum: /* Attribute Format + value from an enumeration */
2105 immediate = ((n & ISAKMP_ATTR_AF_MASK0x8000) ==
2106 ISAKMP_ATTR_AF_TV0x8000);
2107 /*
2108 * Lookup fp->desc using N and
2109 * not LAST_ENUM. Only when N
2110 * (value or AF+value) is
2111 * found is it acceptable.
2112 */
2113 if (fp->field_type == ft_af_enum &&
2114 enum_name(fp->desc, n) == NULL((void*)0)) {
2115 return diag("%s of %s has an unknown value: %s%ju (0x%jx)",
2116 fp->name, sd->name,
2117 immediate ? "AF+" : "",
2118 n & ~ISAKMP_ATTR_AF_MASK0x8000, n);
2119 }
2120 break;
2121
2122 case ft_enum: /* value from an enumeration */
2123 if (enum_name(fp->desc, n) == NULL((void*)0)) {
2124 return diag("%s of %s has an unknown value: %ju (0x%jx)",
2125 fp->name, sd->name,
2126 n, n);
2127 }
2128 break;
2129
2130 case ft_loose_enum: /* value from an enumeration with only some names known */
2131 case ft_mnpc:
2132 case ft_pnpc:
2133 case ft_lss:
2134 break;
2135
2136 case ft_loose_enum_enum: /* value from an enumeration with partial name table based on previous enum */
2137 break;
2138
2139 case ft_lset: /* bits representing set */
2140 if (!test_lset(fp->desc, n)) {
2141 lset_buf lb;
2142 return diag("bitset %s of %s has unknown member(s): %s (0x%ju)",
2143 fp->name, sd->name,
2144 str_lset(fp->desc, n, &lb),
2145 n);
2146 }
2147 break;
2148
2149 default:
2150 break;
2151 }
2152
2153 /* deposit the value in the struct */
2154 switch (fp->size) {
2155 case 8 / BITS_PER_BYTE8:
2156 *(uint8_t *)dest = n;
2157 break;
2158 case 16 / BITS_PER_BYTE8:
2159 *(uint16_t *)dest = n;
2160 break;
2161 case 32 / BITS_PER_BYTE8:
2162 *(uint32_t *)dest = n;
2163 break;
2164 default:
2165 bad_case(fp->size)libreswan_bad_case("fp->size", (fp->size), ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2165, }; &here; }))
;
2166 }
2167 dest += fp->size;
2168 break;
2169 }
2170
2171 case ft_raw: /* bytes to be left in network-order */
2172 for (size_t i = fp->size; i != 0; i--)
2173 *dest++ = *cur++;
2174 break;
2175
2176 case ft_end: /* end of field list */
2177 lsw_passert_fail(HERE, "should not be here")llog_passert(&failsafe_logger, ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2177, }; &here; }), "should not be here")
;
2178
2179 default:
2180 bad_case(fp->field_type)libreswan_bad_case("fp->field_type", (fp->field_type), (
{ static const struct where here = { .func = __func__, .file =
"programs/pluto/packet.c", .line = 2180, }; &here; }))
;
2181 }
2182 }
2183
2184 passert(cur == ins->cur + sd->size)({ _Bool assertion__ = cur == ins->cur + sd->size; if (
!assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/packet.c", .line
= 2184, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_passert(logger_, here, "%s", "cur == ins->cur + sd->size"
); } (void) 1; })
;
2185 if (obj_pbs != NULL((void*)0)) {
2186 passert(length_field_found)({ _Bool assertion__ = length_field_found; if (!assertion__) {
where_t here = ({ static const struct where here = { .func =
__func__, .file = "programs/pluto/packet.c", .line = 2186, }
; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "length_field_found"); } (
void) 1; })
;
2187 init_pbs(obj_pbs, ins->cur,
2188 roof - ins->cur, sd->name);
2189 obj_pbs->container = ins;
2190 obj_pbs->desc = sd;
2191 obj_pbs->cur = cur;
2192 }
2193 ins->cur = roof;
2194 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
2195 DBG_prefix_print_struct(ins, "parse ",
2196 dest_start, sd,
2197 true1);
2198 }
2199 return NULL((void*)0);
2200}
2201
2202/* return first byte. If no byte return -1 */
2203int pbs_peek_byte(const struct pbs_inpacket_byte_stream *ins)
2204{
2205 return pbs_left(ins)((size_t)((ins)->roof - (ins)->cur)) == 0 ? -1 : ins->cur[0];
2206}
2207
2208diag_t pbs_in_raw(struct pbs_inpacket_byte_stream *ins, void *bytes, size_t len, const char *name)
2209{
2210 if (pbs_left(ins)((size_t)((ins)->roof - (ins)->cur)) < len) {
2211 /* XXX: needs current logger embedded in pbs_in? */
2212 return diag("not enough bytes left to get %s from %s",
2213 name, ins->name);
2214 } else {
2215 if (bytes == NULL((void*)0)) {
2216 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
2217 DBG_log("skipping %u raw bytes of %s (%s)",
2218 (unsigned) len, ins->name, name);
2219 DBG_dump(name, ins->cur, len);
2220 }
2221 } else {
2222 memcpy(bytes, ins->cur, len);
2223 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
2224 DBG_log("parsing %u raw bytes of %s into %s",
2225 (unsigned) len, ins->name, name);
2226 DBG_dump(name, bytes, len);
2227 }
2228 }
2229 ins->cur += len;
2230 return NULL((void*)0);
2231 }
2232}
2233
2234/*
2235 * Check IKEv2's Last Substructure field.
2236 */
2237
2238static void update_last_substructure(pb_stream *outs,
2239 struct_desc *sd, field_desc *fp,
2240 const uint8_t *inp, uint8_t *cur)
2241{
2242 /*
2243 * The containing structure should be expecting substructures.
2244 */
2245 passert(fp->size == 1)({ _Bool assertion__ = fp->size == 1; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/packet.c", .line = 2245, }; &here
; }); const struct logger *logger_ = &failsafe_logger; llog_passert
(logger_, here, "%s", "fp->size == 1"); } (void) 1; })
;
2246 pexpect(outs->desc->nsst != 0)({ _Bool assertion__ = outs->desc->nsst != 0; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2246,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "outs->desc->nsst != 0"
); } assertion__; })
;
2247 uint8_t n = *inp;
2248 pexpect(n == 0 || n == outs->desc->nsst)({ _Bool assertion__ = n == 0 || n == outs->desc->nsst;
if (!assertion__) { where_t here_ = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2248, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "n == 0 || n == outs->desc->nsst"
); } assertion__; })
;
2249 *cur = n;
2250 /*
2251 * Since there's a previous substructure, it can no longer be
2252 * last. Check/set its last substructure field to its type.
2253 */
2254 if (outs->last_substructure.loc != NULL((void*)0)) {
2255 esb_buf locb;
2256 esb_buf nsstb;
2257 dbg("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2258 /* '%s'.'%s'.'%s' */{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2259 outs->desc->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2260 outs->last_substructure.sd->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2261 outs->last_substructure.fp->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2262 /* containing ... */{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2263 enum_show(outs->last_substructure.fp->desc,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2264 outs->last_substructure.loc[0], &locb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2265 outs->last_substructure.loc[0],{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2266 /* is ... */{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2267 enum_show(outs->last_substructure.fp->desc,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2268 outs->desc->nsst, &nsstb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
2269 outs->desc->nsst){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' containing %s (0x%x) is %s (0x%x)"
, outs->desc->name, outs->last_substructure.sd->name
, outs->last_substructure.fp->name, enum_show(outs->
last_substructure.fp->desc, outs->last_substructure.loc
[0], &locb), outs->last_substructure.loc[0], enum_show
(outs->last_substructure.fp->desc, outs->desc->nsst
, &nsstb), outs->desc->nsst); } }
;
2270 pexpect(outs->last_substructure.loc[0] == outs->desc->nsst)({ _Bool assertion__ = outs->last_substructure.loc[0] == outs
->desc->nsst; if (!assertion__) { where_t here_ = ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2270, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "outs->last_substructure.loc[0] == outs->desc->nsst"
); } assertion__; })
;
2271 }
2272 /*
2273 * Now save the location of this Last Substructure.
2274 */
2275 dbg("last substructure: saving location '%s'.'%s'.'%s'",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: saving location '%s'.'%s'.'%s'"
, outs->desc->name, sd->name, fp->name); } }
2276 outs->desc->name, sd->name, fp->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: saving location '%s'.'%s'.'%s'"
, outs->desc->name, sd->name, fp->name); } }
;
2277 outs->last_substructure.loc = cur;
2278 outs->last_substructure.sd = sd;
2279 outs->last_substructure.fp = fp;
2280}
2281
2282static void close_last_substructure(pb_stream *pbs)
2283{
2284 if (pbs->last_substructure.loc != NULL((void*)0)) {
2285 dbg("last substructure: checking '%s'.'%s'.'%s' is 0",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' is 0"
, pbs->desc->name, pbs->last_substructure.sd->name
, pbs->last_substructure.fp->name); } }
2286 pbs->desc->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' is 0"
, pbs->desc->name, pbs->last_substructure.sd->name
, pbs->last_substructure.fp->name); } }
2287 pbs->last_substructure.sd->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' is 0"
, pbs->desc->name, pbs->last_substructure.sd->name
, pbs->last_substructure.fp->name); } }
2288 pbs->last_substructure.fp->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("last substructure: checking '%s'.'%s'.'%s' is 0"
, pbs->desc->name, pbs->last_substructure.sd->name
, pbs->last_substructure.fp->name); } }
;
2289 pexpect(pbs->desc->nsst != 0)({ _Bool assertion__ = pbs->desc->nsst != 0; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2289,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "pbs->desc->nsst != 0"
); } assertion__; })
;
2290 pexpect(pbs->last_substructure.loc[0] == 0)({ _Bool assertion__ = pbs->last_substructure.loc[0] == 0;
if (!assertion__) { where_t here_ = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2290, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "pbs->last_substructure.loc[0] == 0"
); } assertion__; })
;
2291#if 0
2292 } else {
2293 /* XXX: too strong, rejects empty? */
2294 pexpect(pbs->desc->nsst == 0)({ _Bool assertion__ = pbs->desc->nsst == 0; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2294,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "pbs->desc->nsst == 0"
); } assertion__; })
;
2295#endif
2296 }
2297}
2298
2299/*
2300 * Next Payload Chain
2301 */
2302
2303static void start_next_payload_chain(struct pbs_outpacket_byte_stream *outs,
2304 struct_desc *sd, field_desc *fp,
2305 const uint8_t *inp, uint8_t *cur)
2306{
2307 passert(fp->size == 1)({ _Bool assertion__ = fp->size == 1; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/packet.c", .line = 2307, }; &here
; }); const struct logger *logger_ = &failsafe_logger; llog_passert
(logger_, here, "%s", "fp->size == 1"); } (void) 1; })
;
2308 dbg("next payload chain: saving message location '%s'.'%s'",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: saving message location '%s'.'%s'"
, sd->name, fp->name); } }
2309 sd->name, fp->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: saving message location '%s'.'%s'"
, sd->name, fp->name); } }
;
2310 outs->next_payload_chain.loc = cur;
2311 outs->next_payload_chain.sd = sd;
2312 outs->next_payload_chain.fp = fp;
2313 uint8_t n = *inp;
2314 if (n != ISAKMP_NEXT_NONE) {
2315 esb_buf npb;
2316 pexpect_failllog_pexpect(outs->outs_logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/packet.c", .line = 2316, }; &here; })
,
2317 "next payload chain: ignoring supplied '%s'.'%s' value %d:%s",
2318 sd->name, fp->name, n,
2319 enum_show(fp->desc, n, &npb));
2320 n = ISAKMP_NEXT_NONE;
2321 }
2322 *cur = n;
2323}
2324
2325static void update_next_payload_chain(pb_stream *outs,
2326 struct_desc *sd, field_desc *fp,
2327 const uint8_t *inp, uint8_t *cur)
2328{
2329 passert(fp->size == 1)({ _Bool assertion__ = fp->size == 1; if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/packet.c", .line = 2329, }; &here
; }); const struct logger *logger_ = &failsafe_logger; llog_passert
(logger_, here, "%s", "fp->size == 1"); } (void) 1; })
;
2330 passert(sd->pt != ISAKMP_NEXT_NONE)({ _Bool assertion__ = sd->pt != ISAKMP_NEXT_NONE; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2330,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "sd->pt != ISAKMP_NEXT_NONE"
); } (void) 1; })
;
2331
2332 /*
2333 * Normally only comes after the header and ft_mnpc. However,
2334 * as part of authenticating, IKEv1 fakes up a PBS containing
2335 * just the "Identification Payload".
2336 */
2337 if (outs->container == NULL((void*)0)) {
2338 esb_buf npb;
2339 dbg("next payload chain: no previous for current %s (%d:%s); assumed to be fake",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: no previous for current %s (%d:%s); assumed to be fake"
, sd->name, sd->pt, enum_show(fp->desc, sd->pt, &
npb)); } }
2340 sd->name, sd->pt, enum_show(fp->desc, sd->pt, &npb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: no previous for current %s (%d:%s); assumed to be fake"
, sd->name, sd->pt, enum_show(fp->desc, sd->pt, &
npb)); } }
;
2341 return;
2342 }
2343
2344 /*
2345 * Find the message (packet) PBS containing the next payload
2346 * chain pointers initialized by start_next_payload_chain().
2347 * Since there is a single chain, running through the message,
2348 * this is stored in the outermost PBS.
2349 *
2350 * XXX: don't try to be all fancy and copy back values; could
2351 * use an outs->message pointer; but since nesting is minimal
2352 * this isn't really urgent
2353 */
2354 pb_stream *message = outs->container;
2355 passert(message != NULL)({ _Bool assertion__ = message != ((void*)0); if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2355,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "message != ((void*)0)");
} (void) 1; })
;
2356 while (message->container != NULL((void*)0)) {
2357 message = message->container;
2358 }
2359 passert(message->next_payload_chain.loc != NULL)({ _Bool assertion__ = message->next_payload_chain.loc != (
(void*)0); if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2359, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "message->next_payload_chain.loc != ((void*)0)"
); } (void) 1; })
;
2360 passert(message->next_payload_chain.sd != NULL)({ _Bool assertion__ = message->next_payload_chain.sd != (
(void*)0); if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2360, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "message->next_payload_chain.sd != ((void*)0)"
); } (void) 1; })
;
2361 passert(message->next_payload_chain.fp != NULL)({ _Bool assertion__ = message->next_payload_chain.fp != (
(void*)0); if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2361, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "message->next_payload_chain.fp != ((void*)0)"
); } (void) 1; })
;
2362 pexpect(*message->next_payload_chain.loc == ISAKMP_NEXT_NONE)({ _Bool assertion__ = *message->next_payload_chain.loc ==
ISAKMP_NEXT_NONE; if (!assertion__) { where_t here_ = ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2362, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "*message->next_payload_chain.loc == ISAKMP_NEXT_NONE"
); } assertion__; })
;
2363
2364 /*
2365 * Initialize this payload's next payload chain
2366 */
2367 uint8_t n = *inp;
2368 if (sd->pt == ISAKMP_NEXT_v2SKF) {
2369 /*
2370 * For v2SKF (IKEv2 secured fragments) assume the
2371 * header next payload type is correct. The
2372 * fragmenting code sets it to the payload type of the
2373 * unfragmented SK message's first payload. Something
2374 * this code isn't going to know.
2375 *
2376 * This works because v2SKF messages never have more
2377 * than one payload.
2378 */
2379 esb_buf npb;
2380 dbg("next payload chain: using supplied v2SKF '%s'.'%s' value %d:%s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: using supplied v2SKF '%s'.'%s' value %d:%s"
, sd->name, fp->name, n, enum_show(fp->desc, n, &
npb)); } }
2381 sd->name, fp->name, n,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: using supplied v2SKF '%s'.'%s' value %d:%s"
, sd->name, fp->name, n, enum_show(fp->desc, n, &
npb)); } }
2382 enum_show(fp->desc, n, &npb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: using supplied v2SKF '%s'.'%s' value %d:%s"
, sd->name, fp->name, n, enum_show(fp->desc, n, &
npb)); } }
;
2383 } else if (n != ISAKMP_NEXT_NONE) {
2384 esb_buf npb;
2385 pexpect_failllog_pexpect(outs->outs_logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/packet.c", .line = 2385, }; &here; })
,
2386 "next payload chain: ignoring supplied '%s'.'%s' value %d:%s",
2387 sd->name, fp->name, n,
2388 enum_show(fp->desc, n, &npb));
2389 n = ISAKMP_NEXT_NONE;
2390 }
2391 *cur = n;
2392
2393 /* update previous struct's next payload type field */
2394 esb_buf npb;
2395 dbg("next payload chain: setting previous '%s'.'%s' to current %s (%d:%s)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: setting previous '%s'.'%s' to current %s (%d:%s)"
, message->next_payload_chain.sd->name, message->next_payload_chain
.fp->name, sd->name, sd->pt, enum_show(fp->desc, sd
->pt, &npb)); } }
2396 message->next_payload_chain.sd->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: setting previous '%s'.'%s' to current %s (%d:%s)"
, message->next_payload_chain.sd->name, message->next_payload_chain
.fp->name, sd->name, sd->pt, enum_show(fp->desc, sd
->pt, &npb)); } }
2397 message->next_payload_chain.fp->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: setting previous '%s'.'%s' to current %s (%d:%s)"
, message->next_payload_chain.sd->name, message->next_payload_chain
.fp->name, sd->name, sd->pt, enum_show(fp->desc, sd
->pt, &npb)); } }
2398 sd->name, sd->pt, enum_show(fp->desc, sd->pt, &npb)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: setting previous '%s'.'%s' to current %s (%d:%s)"
, message->next_payload_chain.sd->name, message->next_payload_chain
.fp->name, sd->name, sd->pt, enum_show(fp->desc, sd
->pt, &npb)); } }
;
2399 *message->next_payload_chain.loc = sd->pt;
2400
2401 /* save new */
2402 dbg("next payload chain: saving location '%s'.'%s' in '%s'",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: saving location '%s'.'%s' in '%s'"
, sd->name, fp->name, message->name); } }
2403 sd->name, fp->name, message->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("next payload chain: saving location '%s'.'%s' in '%s'"
, sd->name, fp->name, message->name); } }
;
2404 message->next_payload_chain.loc = cur;
2405 message->next_payload_chain.sd = sd;
2406 message->next_payload_chain.fp = fp;
2407}
2408
2409/* "emit" a host struct into a network packet.
2410 *
2411 * This code assumes that the network and host structure
2412 * members have the same alignment and size! This requires
2413 * that all padding be explicit.
2414 *
2415 * If obj_pbs is non-NULL, its pbs describes a new output stream set up
2416 * to contain the object. The cursor will be left at the variable part.
2417 * This new stream must subsequently be finalized by close_output_pbs().
2418 *
2419 * The value of any field of type ft_len is computed, not taken
2420 * from the input struct. The length is actually filled in when
2421 * the object's output stream is finalized. If obj_pbs is NULL,
2422 * finalization is done by out_struct before it returns.
2423 *
2424 * This routine returns TRUE iff it succeeds.
2425 */
2426
2427diag_t pbs_out_struct(struct pbs_outpacket_byte_stream *outs, struct_desc *sd,
2428 const void *struct_ptr, size_t struct_size,
2429 struct pbs_outpacket_byte_stream *obj_pbs)
2430{
2431 const u_int8_t *inp = struct_ptr;
2432 u_int8_t *cur = outs->cur;
2433
2434 passert(struct_size == 0 || struct_size >= sd->size)({ _Bool assertion__ = struct_size == 0 || struct_size >= sd
->size; if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2434, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "struct_size == 0 || struct_size >= sd->size"
); } (void) 1; })
;
8
Taking false branch
2435
2436 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
9
Assuming the condition is false
10
Taking false branch
2437 DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs == NULL((void*)0));
2438 }
2439
2440 if (outs->roof - cur < (ptrdiff_t)sd->size) {
11
Assuming the condition is false
12
Taking false branch
2441 return diag("not enough room left in output packet to place %s", sd->name);
2442 }
2443
2444
2445 bool_Bool immediate = false0;
2446
2447 /* new child stream for portion of payload after this struct */
2448 struct pbs_outpacket_byte_stream obj = {
2449 .container = outs,
2450 .desc = sd,
2451 .name = sd->name,
2452 .outs_logger = outs->outs_logger,
2453
2454 /* until a length field is discovered */
2455 /* .lenfld = NULL, */
2456 /* .lenfld_desc = NULL, */
2457
2458 /* until an ft_mnpc field is discovered */
2459 /* message.previous_np = {0}, */
2460
2461 /* until an ft_lss is discovered */
2462 /* .last_substructure = {0}, */
2463 };
2464
2465 for (field_desc *fp = sd->fields; ; fp++) {
13
Loop condition is true. Entering loop body
2466 size_t i = fp->size;
2467
2468 /* make sure that there is space for the next structure element */
2469 passert(outs->roof - cur >= (ptrdiff_t)i)({ _Bool assertion__ = outs->roof - cur >= (ptrdiff_t)i
; if (!assertion__) { where_t here = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2469, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "outs->roof - cur >= (ptrdiff_t)i"
); } (void) 1; })
;
14
Assuming the condition is true
15
Taking false branch
2470
2471 /* verify that the spot is correct in the offset */
2472 passert(cur - outs->cur <= (ptrdiff_t)(sd->size - i))({ _Bool assertion__ = cur - outs->cur <= (ptrdiff_t)(sd
->size - i); if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2472, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "cur - outs->cur <= (ptrdiff_t)(sd->size - i)"
); } (void) 1; })
;
16
Taking false branch
2473
2474 /* verify that we are at the right place in the input structure */
2475 passert(inp - (cur - outs->cur) == struct_ptr)({ _Bool assertion__ = inp - (cur - outs->cur) == struct_ptr
; if (!assertion__) { where_t here = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2475, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "inp - (cur - outs->cur) == struct_ptr"
); } (void) 1; })
;
17
Taking false branch
2476
2477 DBGF(DBG_TMI, "out_struct: %d %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_TMI_IX))
))) { DBG_log("out_struct: %d %s", (int) (cur - outs->cur)
, fp->name == ((void*)0) ? "<end>" : fp->name); }
}
18
Assuming the condition is false
19
Taking false branch
2478 (int) (cur - outs->cur),{ if ((cur_debugging & (((lset_t)1 << (DBG_TMI_IX))
))) { DBG_log("out_struct: %d %s", (int) (cur - outs->cur)
, fp->name == ((void*)0) ? "<end>" : fp->name); }
}
2479 fp->name == NULL ? "<end>" : fp->name){ if ((cur_debugging & (((lset_t)1 << (DBG_TMI_IX))
))) { DBG_log("out_struct: %d %s", (int) (cur - outs->cur)
, fp->name == ((void*)0) ? "<end>" : fp->name); }
}
;
2480
2481 switch (fp->field_type) {
20
Control jumps to 'case ft_raw:' at line 2618
2482 case ft_zig: /* zero */
2483 {
2484 uint8_t byte;
2485 if (impair.send_nonzero_reserved) {
2486 byte = ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS(1<<ISAKMP_PAYLOAD_FLAG_LIBRESWAN_BOGUS_IX);
2487 llog(RC_LOG, outs->outs_logger,
2488 "IMPAIR: setting zero/ignore field to 0x%02x", byte);
2489 } else {
2490 byte = 0;
2491 }
2492 memset(cur, byte, i);
2493 inp += i;
2494 cur += i;
2495 break;
2496 }
2497
2498 case ft_mnpc:
2499 start_next_payload_chain(outs, sd, fp,
2500 inp, cur);
2501 inp += fp->size;
2502 cur += fp->size;
2503 break;
2504
2505 case ft_pnpc:
2506 update_next_payload_chain(outs, sd, fp,
2507 inp, cur);
2508 inp += fp->size;
2509 cur += fp->size;
2510 break;
2511
2512 case ft_lss:
2513 update_last_substructure(outs, sd, fp,
2514 inp, cur);
2515 inp += fp->size;
2516 cur += fp->size;
2517 break;
2518
2519 case ft_len: /* length of this struct and any following crud */
2520 case ft_lv: /* length/value field of attribute */
2521 if (!immediate) {
2522 /* We can't check the length because it must
2523 * be filled in after variable part is supplied.
2524 * We do record where this is so that it can be
2525 * filled in by a subsequent close_output_pbs().
2526 */
2527 passert(obj.lenfld == NULL)({ _Bool assertion__ = obj.lenfld == ((void*)0); if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2527,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "obj.lenfld == ((void*)0)"
); } (void) 1; })
; /* only one ft_len allowed */
2528 obj.lenfld = cur;
2529 obj.lenfld_desc = fp;
2530
2531 /* fill with crap so failure to overwrite will be noticed */
2532 memset(cur, 0xFA, i);
2533
2534 inp += i;
2535 cur += i;
2536 break;
2537 }
2538 /* immediate form is just like a number */
2539 /* FALL THROUGH */
2540 case ft_nat: /* natural number (may be 0) */
2541 case ft_enum: /* value from an enumeration */
2542 case ft_loose_enum: /* value from an enumeration with only some names known */
2543 case ft_loose_enum_enum: /* value from an enumeration with partial name table based on previous enum */
2544 case ft_af_enum: /* Attribute Format + value from an enumeration */
2545 case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
2546 case ft_lset: /* bits representing set */
2547 {
2548 uint32_t n;
2549
2550 switch (i) {
2551 case 8 / BITS_PER_BYTE8:
2552 n = *(const uint8_t *)inp;
2553 break;
2554 case 16 / BITS_PER_BYTE8:
2555 n = *(const uint16_t *)inp;
2556 break;
2557 case 32 / BITS_PER_BYTE8:
2558 n = *(const uint32_t *)inp;
2559 break;
2560 default:
2561 bad_case(i)libreswan_bad_case("i", (i), ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/packet.c", .line
= 2561, }; &here; }))
;
2562 }
2563
2564 switch (fp->field_type) {
2565
2566 case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
2567 case ft_af_enum: /* Attribute Format + value from an enumeration */
2568 immediate = ((n & ISAKMP_ATTR_AF_MASK0x8000) ==
2569 ISAKMP_ATTR_AF_TV0x8000);
2570 if (fp->field_type == ft_af_enum &&
2571 enum_name(fp->desc, n) == NULL((void*)0)) {
2572#define MSG"%s of %s has an unknown value: 0x%x+%" "u" " (0x%" "x" ")", fp
->name, sd->name, n & 0x8000, n & ~0x8000, n
"%s of %s has an unknown value: 0x%x+%" PRIu32"u" " (0x%" PRIx32"x" ")", fp->name, sd->name, n & ISAKMP_ATTR_AF_MASK0x8000, n & ~ISAKMP_ATTR_AF_MASK0x8000, n
2573 if (!impair.emitting) {
2574 return diag(MSG"%s of %s has an unknown value: 0x%x+%" "u" " (0x%" "x" ")", fp
->name, sd->name, n & 0x8000, n & ~0x8000, n
);
2575 }
2576 llog(RC_LOG, outs->outs_logger, "IMPAIR: emitting "MSG"%s of %s has an unknown value: 0x%x+%" "u" " (0x%" "x" ")", fp
->name, sd->name, n & 0x8000, n & ~0x8000, n
);
2577 }
2578 break;
2579
2580 case ft_enum: /* value from an enumeration */
2581 if (enum_name(fp->desc, n) == NULL((void*)0)) {
2582 return diag("%s of %s has an unknown value: %" PRIu32"u" " (0x%" PRIx32"x" ")",
2583 fp->name, sd->name,
2584 n, n);
2585 }
2586 break;
2587
2588 case ft_loose_enum: /* value from an enumeration with only some names known */
2589 break;
2590
2591 case ft_loose_enum_enum: /* value from an enumeration with partial name table based on previous enum */
2592 break;
2593
2594 case ft_lset: /* bits representing set */
2595 if (!test_lset(fp->desc, n)) {
2596 lset_buf lb;
2597 return diag("bitset %s of %s has unknown member(s): %s (0x%" PRIx32"x" ")",
2598 fp->name, sd->name,
2599 str_lset(fp->desc, n, &lb),
2600 n);
2601 }
2602 break;
2603
2604 default:
2605 break;
2606 }
2607
2608 /* emit i low-order bytes of n in network order */
2609 while (i-- != 0) {
2610 cur[i] = (uint8_t)n;
2611 n >>= BITS_PER_BYTE8;
2612 }
2613 inp += fp->size;
2614 cur += fp->size;
2615 break;
2616 }
2617
2618 case ft_raw: /* bytes to be left in network-order */
2619 for (; i != 0; i--)
21
Assuming 'i' is not equal to 0
22
Loop condition is true. Entering loop body
23
Assuming 'i' is not equal to 0
24
Loop condition is true. Entering loop body
25
Assuming 'i' is not equal to 0
26
Loop condition is true. Entering loop body
27
Assuming 'i' is not equal to 0
28
Loop condition is true. Entering loop body
2620 *cur++ = *inp++;
29
Assigned value is garbage or undefined
2621 break;
2622
2623 case ft_end: /* end of field list */
2624 passert(cur == outs->cur + sd->size)({ _Bool assertion__ = cur == outs->cur + sd->size; if (
!assertion__) { where_t here = ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/packet.c", .line
= 2624, }; &here; }); const struct logger *logger_ = &
failsafe_logger; llog_passert(logger_, here, "%s", "cur == outs->cur + sd->size"
); } (void) 1; })
;
2625
2626 obj.start = outs->cur;
2627 obj.cur = cur;
2628 obj.roof = outs->roof; /* limit of possible */
2629 /* obj.lenfld* and obj.previous_np* already set */
2630
2631 if (obj_pbs == NULL((void*)0)) {
2632 close_output_pbs(&obj); /* fill in length field, if any */
2633 } else {
2634 /* We set outs->cur to outs->roof so that
2635 * any attempt to output something into outs
2636 * before obj is closed will trigger an error.
2637 */
2638 outs->cur = outs->roof;
2639
2640 *obj_pbs = obj;
2641 }
2642 return NULL((void*)0);
2643
2644 default:
2645 bad_case(fp->field_type)libreswan_bad_case("fp->field_type", (fp->field_type), (
{ static const struct where here = { .func = __func__, .file =
"programs/pluto/packet.c", .line = 2645, }; &here; }))
;
2646 }
2647 }
2648
2649 /* never reached!?! */
2650}
2651
2652bool_Bool out_struct(const void *struct_ptr, struct_desc *sd,
2653 struct pbs_outpacket_byte_stream *outs, struct pbs_outpacket_byte_stream *obj_pbs)
2654{
2655 diag_t d = pbs_out_struct(outs, sd, struct_ptr, 0, obj_pbs);
7
Calling 'pbs_out_struct'
2656 if (d != NULL((void*)0)) {
2657 llog_diag(RC_LOG_SERIOUS, outs->outs_logger, &d, "%s", "");
2658 return false0;
2659 }
2660
2661 return true1;
2662}
2663
2664bool_Bool ikev1_out_generic(struct_desc *sd,
2665 pb_stream *outs, pb_stream *obj_pbs)
2666{
2667 passert(sd->fields == isag_fields)({ _Bool assertion__ = sd->fields == isag_fields; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2667,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "sd->fields == isag_fields"
); } (void) 1; })
;
2
Assuming 'assertion__' is true
3
Taking false branch
2668 passert(sd->pt != ISAKMP_NEXT_NONE)({ _Bool assertion__ = sd->pt != ISAKMP_NEXT_NONE; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/packet.c", .line = 2668,
}; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "sd->pt != ISAKMP_NEXT_NONE"
); } (void) 1; })
;
4
Assuming field 'pt' is not equal to ISAKMP_NEXT_NONE
5
Taking false branch
2669 struct isakmp_generic gen = {
2670 .isag_np = 0,
2671 };
2672 return out_struct(&gen, sd, outs, obj_pbs);
6
Calling 'out_struct'
2673}
2674
2675bool_Bool ikev1_out_generic_raw(struct_desc *sd,
2676 pb_stream *outs, const void *bytes, size_t len,
2677 const char *name)
2678{
2679 pb_stream pbs;
2680
2681 if (!ikev1_out_generic(sd, outs, &pbs)) {
1
Calling 'ikev1_out_generic'
2682 return false0;
2683 }
2684 diag_t d = pbs_out_raw(&pbs, bytes, len, name);
2685 if (d != NULL((void*)0)) {
2686 llog_diag(RC_LOG_SERIOUS, outs->outs_logger, &d, "%s", "");
2687 return false0;
2688 }
2689
2690 close_output_pbs(&pbs);
2691 return true1;
2692}
2693
2694static diag_t space_for(size_t len, pb_stream *outs, const char *fmt, ...) PRINTF_LIKE(3)__attribute__ ((format(printf, 3, 3 + 1))) MUST_USE_RESULT__attribute__ ((warn_unused_result));
2695static diag_t space_for(size_t len, pb_stream *outs, const char *fmt, ...)
2696{
2697 /* nothing to do, or at least one byte spare */
2698 if (len == 0 || pbs_left(outs)((size_t)((outs)->roof - (outs)->cur)) > len) {
2699 LSWDBGP(DBG_BASE, buf)for (_Bool lswlog_p = (cur_debugging & (((lset_t)1 <<
(DBG_BASE_IX)))); lswlog_p; lswlog_p = 0) for (char lswbuf[(
(size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ != ((void*)0); lswbuf_
= ((void*)0)) for (struct jambuf jambuf = array_as_jambuf((lswbuf
), sizeof(lswbuf)), *buf = &jambuf; buf != ((void*)0); buf
= ((void*)0)) for (; buf != ((void*)0); jambuf_to_logger(buf
, &failsafe_logger, DEBUG_STREAM), buf = ((void*)0))
{
2700 jam_string(buf, "emitting ");
2701 va_list ap;
2702 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2703 jam_va_list(buf, fmt, ap);
2704 va_end(ap)__builtin_va_end(ap);
2705 jam(buf, " into %s", outs->name);
2706 }
2707 return NULL((void*)0);
2708 }
2709
2710 if (pbs_left(outs)((size_t)((outs)->roof - (outs)->cur)) == 0) {
2711 /* should this be a DBGLOG? */
2712 diag_t d;
2713 JAMBUF(buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0))
{
2714 jam(buf, "%s is already full; discarding ", outs->name);
2715 va_list ap;
2716 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2717 jam_va_list(buf, fmt, ap);
2718 va_end(ap)__builtin_va_end(ap);
2719 d = diag(PRI_SHUNK"%.*s", pri_shunk(jambuf_as_shunk(buf))((int) (jambuf_as_shunk(buf)).len), (const char *) ((jambuf_as_shunk
(buf)).ptr)
);
2720 }
2721 return d;
2722 }
2723
2724 /* never exactly fill - reserve space for a trailing byte */
2725 pexpect(pbs_left(outs) <= len)({ _Bool assertion__ = ((size_t)((outs)->roof - (outs)->
cur)) <= len; if (!assertion__) { where_t here_ = ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2725, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "((size_t)((outs)->roof - (outs)->cur)) <= len"
); } assertion__; })
;
2726 diag_t d;
2727 JAMBUF(buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0))
{
2728 jam(buf, "%s is full; unable to emit ", outs->name);
2729 va_list ap;
2730 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2731 jam_va_list(buf, fmt, ap);
2732 va_end(ap)__builtin_va_end(ap);
2733 d = diag(PRI_SHUNK"%.*s", pri_shunk(jambuf_as_shunk(buf))((int) (jambuf_as_shunk(buf)).len), (const char *) ((jambuf_as_shunk
(buf)).ptr)
);
2734 }
2735 /* overflow the buffer */
2736 outs->cur += pbs_left(outs)((size_t)((outs)->roof - (outs)->cur));
2737 return d;
2738}
2739
2740diag_t pbs_out_raw(struct pbs_outpacket_byte_stream *outs, const void *bytes, size_t len, const char *name)
2741{
2742 diag_t d = space_for(len, outs, "%zu raw bytes of %s", len, name);
2743 if (d != NULL((void*)0)) {
2744 return d;
2745 }
2746
2747 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
2748 if (len > 16) { /* arbitrary */
2749 DBG_log("%s:", name);
2750 DBG_dump(NULL((void*)0), bytes, len);
2751 } else {
2752 LSWLOG_DEBUG(buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0)) for (; buf != ((void*)
0); jambuf_to_logger(buf, &failsafe_logger, DEBUG_STREAM)
, buf = ((void*)0))
{
2753 jam(buf, "%s: ", name);
2754 jam_dump_bytes(buf, bytes, len);
2755 }
2756 }
2757 }
2758 memcpy(outs->cur, bytes, len);
2759 outs->cur += len;
2760 return NULL((void*)0);
2761}
2762
2763diag_t pbs_out_repeated_byte(struct pbs_outpacket_byte_stream *outs, uint8_t byte, size_t len, const char *name)
2764{
2765 diag_t d = space_for(len, outs, "%zu 0x%02x repeated bytes of %s", len, byte, name);
2766 if (d != NULL((void*)0)) {
2767 return d;
2768 }
2769
2770 memset(outs->cur, byte, len);
2771 outs->cur += len;
2772 return NULL((void*)0);
2773}
2774
2775diag_t pbs_out_zero(struct pbs_outpacket_byte_stream *outs, size_t len, const char *name)
2776{
2777 diag_t d = space_for(len, outs, "%zu zero bytes of %s", len, name);
2778 if (d != NULL((void*)0)) {
2779 return d;
2780 }
2781
2782 memset(outs->cur, 0, len);
2783 outs->cur += len;
2784 return NULL((void*)0);
2785}
2786
2787/*
2788 * Reply messages are built in this nasty evil global buffer.
2789 *
2790 * Only one packet can be built at a time. That should be ok as
2791 * packets are only built on the main thread and code and a packet is
2792 * created using a single operation.
2793 *
2794 * In the good old days code would partially construct a packet,
2795 * wonder off to do crypto and process other packets, and then assume
2796 * things could be picked up where they were left off. Code to make
2797 * that work (saving restoring the buffer, re-initializing the buffer
2798 * in strange places, ....) has all been removed.
2799 *
2800 * Something else that should go is global access to REPLY_STREAM.
2801 * Instead all code should use open_reply_stream() and a reference
2802 * with only local scope. This should reduce the odds of code
2803 * meddling in reply_stream on the sly.
2804 *
2805 * Another possibility is to move the buffer onto the stack. However,
2806 * the PBS is 64K and that isn't so good for small machines. Then
2807 * again the send.[hc] and demux[hc] code both allocate 64K stack
2808 * buffers already. Oops.
2809 */
2810
2811uint8_t reply_buffer[MAX_OUTPUT_UDP_SIZE65536];
2812
2813/*
2814 * close_output_pbs: record current length and check previous_NP
2815 *
2816 * Note: currently, this may be repeated any number of times;
2817 * the last call's setting of the length wins.
2818 */
2819
2820void close_output_pbs(struct pbs_outpacket_byte_stream *pbs)
2821{
2822 if (pbs->lenfld != NULL((void*)0)) {
2823 uint32_t len = pbs_offset(pbs)((size_t)((pbs)->cur - (pbs)->start));
2824 int i = pbs->lenfld_desc->size;
2825
2826 passert(i > 0)({ _Bool assertion__ = i > 0; if (!assertion__) { where_t here
= ({ static const struct where here = { .func = __func__, .file
= "programs/pluto/packet.c", .line = 2826, }; &here; });
const struct logger *logger_ = &failsafe_logger; llog_passert
(logger_, here, "%s", "i > 0"); } (void) 1; })
;
2827
2828 if (pbs->lenfld_desc->field_type == ft_lv)
2829 len -= sizeof(struct isakmp_attribute);
2830
2831 dbg("emitting length of %s: %" PRIu32, pbs->name, len){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("emitting length of %s: %" "u", pbs->name, len
); } }
;
2832
2833 /* emit octets of length in network order */
2834 while (i-- != 0) {
2835 pbs->lenfld[i] = (uint8_t)len;
2836 len >>= BITS_PER_BYTE8;
2837 }
2838 }
2839
2840 /* if there is one */
2841 close_last_substructure(pbs);
2842
2843 if (pbs->container != NULL((void*)0))
2844 pbs->container->cur = pbs->cur; /* pass space utilization up */
2845 /* don't log against a closed pbs */
2846 pbs->outs_logger = NULL((void*)0);
2847}
2848
2849diag_t pbs_in_address(struct pbs_inpacket_byte_stream *input_pbs,
2850 ip_address *address, const struct ip_info *ipv,
2851 const char *what)
2852{
2853 switch (ipv->af) {
2854 case AF_INET2:
2855 {
2856 struct in_addr ip;
2857 diag_t d = pbs_in_raw(input_pbs, &ip, sizeof(ip), what);
2858 if (d != NULL((void*)0)) {
2859 *address = unset_address;
2860 return d;
2861 }
2862 *address = address_from_in_addr(&ip);
2863 return NULL((void*)0);
2864 }
2865 case AF_INET610:
2866 {
2867 struct in6_addr ip;
2868 diag_t d = pbs_in_raw(input_pbs, &ip, sizeof(ip), what);
2869 if (d != NULL((void*)0)) {
2870 *address = unset_address;
2871 return d;
2872 }
2873 *address = address_from_in6_addr(&ip);
2874 return NULL((void*)0);
2875 }
2876 default:
2877 bad_case(ipv->af)libreswan_bad_case("ipv->af", (ipv->af), ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/packet.c"
, .line = 2877, }; &here; }))
;
2878 }
2879}
2880
2881diag_t pbs_out_address(struct pbs_outpacket_byte_stream *out_pbs, const ip_address address, const char *what)
2882{
2883 shunk_t as = address_as_shunk(&address);
2884 return pbs_out_hunk(out_pbs, as, what)({ typeof(as) hunk_ = as; struct packet_byte_stream *outs_ = out_pbs
; pbs_out_raw(outs_, hunk_.ptr, hunk_.len, (what)); })
;
2885}