Bug Summary

File:programs/pluto/packet.c
Warning:line 2479, column 4
Value stored to 'last_enum' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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