~ubuntu-branches/ubuntu/hardy/openswan/hardy-updates

« back to all changes in this revision

Viewing changes to programs/pluto/packet.c

  • Committer: Bazaar Package Importer
  • Author(s): Rene Mayrhofer
  • Date: 2005-01-27 16:10:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050127161011-idgybmyz3vwhpfiq
Tags: 2.3.0-2
Urgency HIGH due to security issue and problems with build-deps in sarge.
* Fix the security issue. Please see
  http://www.idefense.com/application/poi/display?id=190&
      type=vulnerabilities&flashstatus=false
  for more details. Thanks to Martin Schulze for informing me about
  this issue.
  Closes: #292458: Openswan XAUTH/PAM Buffer Overflow Vulnerability
* Added a Build-Dependency to lynx.
  Closes: #291143: openswan: FTBFS: Missing build dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* parsing packets: formats and tools
2
 
 * Copyright (C) 1997 Angelos D. Keromytis.
3
 
 * Copyright (C) 1998-2001  D. Hugh Redelmeier.
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify it
6
 
 * under the terms of the GNU General Public License as published by the
7
 
 * Free Software Foundation; either version 2 of the License, or (at your
8
 
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful, but
11
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12
 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13
 
 * for more details.
14
 
 *
15
 
 * RCSID $Id: packet.c,v 1.43.2.1 2004/03/21 05:23:34 mcr Exp $
16
 
 */
17
 
 
18
 
#include <stdio.h>
19
 
#include <stdlib.h>
20
 
#include <stddef.h>
21
 
#include <netinet/in.h>
22
 
#include <string.h>
23
 
 
24
 
#include <openswan.h>
25
 
 
26
 
#include "constants.h"
27
 
#include "defs.h"
28
 
#include "log.h"
29
 
#include "packet.h"
30
 
#include "whack.h"      /* for RC_LOG_SERIOUS */
31
 
 
32
 
/* ISAKMP Header: for all messages
33
 
 * layout from RFC 2408 "ISAKMP" section 3.1
34
 
 *                      1                   2                   3
35
 
 *  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
36
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37
 
 * !                          Initiator                            !
38
 
 * !                            Cookie                             !
39
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40
 
 * !                          Responder                            !
41
 
 * !                            Cookie                             !
42
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43
 
 * !  Next Payload ! MjVer ! MnVer ! Exchange Type !     Flags     !
44
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45
 
 * !                          Message ID                           !
46
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47
 
 * !                            Length                             !
48
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49
 
 */
50
 
 
51
 
static field_desc isa_fields[] = {
52
 
    { ft_raw, COOKIE_SIZE, "initiator cookie", NULL },
53
 
    { ft_raw, COOKIE_SIZE, "responder cookie", NULL },
54
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
55
 
    { ft_enum, 8/BITS_PER_BYTE, "ISAKMP version", &version_names },
56
 
    { ft_enum, 8/BITS_PER_BYTE, "exchange type", &exchange_names },
57
 
    { ft_set, 8/BITS_PER_BYTE, "flags", flag_bit_names },
58
 
    { ft_raw, 32/BITS_PER_BYTE, "message ID", NULL },
59
 
    { ft_len, 32/BITS_PER_BYTE, "length", NULL },
60
 
    { ft_end, 0, NULL, NULL }
61
 
};
62
 
 
63
 
struct_desc isakmp_hdr_desc = { "ISAKMP Message", isa_fields, sizeof(struct isakmp_hdr) };
64
 
 
65
 
/* Generic portion of all ISAKMP payloads.
66
 
 * layout from RFC 2408 "ISAKMP" section 3.2
67
 
 * This describes the first 32-bit chunk of all payloads.
68
 
 * The previous next payload depends on the actual payload type.
69
 
 *                      1                   2                   3
70
 
 *  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
71
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
73
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74
 
 */
75
 
 
76
 
static field_desc isag_fields[] = {
77
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
78
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
79
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
80
 
    { ft_end, 0, NULL, NULL }
81
 
};
82
 
 
83
 
struct_desc isakmp_generic_desc = { "ISAKMP Generic Payload", isag_fields, sizeof(struct isakmp_generic) };
84
 
 
85
 
 
86
 
/* ISAKMP Data Attribute (generic representation within payloads)
87
 
 * layout from RFC 2408 "ISAKMP" section 3.3
88
 
 * This is not a payload type.
89
 
 * In TLV format, this is followed by a value field.
90
 
 *                      1                   2                   3
91
 
 *  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
92
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93
 
 * !A!       Attribute Type        !    AF=0  Attribute Length     !
94
 
 * !F!                             !    AF=1  Attribute Value      !
95
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96
 
 * .                   AF=0  Attribute Value                       .
97
 
 * .                   AF=1  Not Transmitted                       .
98
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99
 
 */
100
 
 
101
 
/* Oakley Attributes */
102
 
static field_desc isaat_fields_oakley[] = {
103
 
    { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &oakley_attr_names },
104
 
    { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
105
 
    { ft_end, 0, NULL, NULL }
106
 
};
107
 
 
108
 
struct_desc isakmp_oakley_attribute_desc = {
109
 
    "ISAKMP Oakley attribute",
110
 
    isaat_fields_oakley, sizeof(struct isakmp_attribute) };
111
 
 
112
 
/* IPsec DOI Attributes */
113
 
static field_desc isaat_fields_ipsec[] = {
114
 
    { ft_af_enum, 16/BITS_PER_BYTE, "af+type", &ipsec_attr_names },
115
 
    { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
116
 
    { ft_end, 0, NULL, NULL }
117
 
};
118
 
 
119
 
struct_desc isakmp_ipsec_attribute_desc = {
120
 
    "ISAKMP IPsec DOI attribute",
121
 
    isaat_fields_ipsec, sizeof(struct isakmp_attribute) };
122
 
 
123
 
/* XAUTH Attributes */
124
 
static field_desc isaat_fields_xauth[] = {
125
 
    { ft_af_loose_enum, 16/BITS_PER_BYTE, "ModeCfg attr type", &modecfg_attr_names },
126
 
    { ft_lv, 16/BITS_PER_BYTE, "length/value", NULL },
127
 
    { ft_end, 0, NULL, NULL }
128
 
};
129
 
 
130
 
struct_desc isakmp_xauth_attribute_desc = {
131
 
    "ISAKMP ModeCfg attribute",
132
 
    isaat_fields_xauth, sizeof(struct isakmp_attribute) };
133
 
 
134
 
/* ISAKMP Security Association Payload
135
 
 * layout from RFC 2408 "ISAKMP" section 3.4
136
 
 * A variable length Situation follows.
137
 
 * Previous next payload: ISAKMP_NEXT_SA
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
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
142
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143
 
 * !              Domain of Interpretation  (DOI)                  !
144
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145
 
 * !                                                               !
146
 
 * ~                           Situation                           ~
147
 
 * !                                                               !
148
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149
 
 */
150
 
static field_desc isasa_fields[] = {
151
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
152
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
153
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
154
 
    { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
155
 
    { ft_end, 0, NULL, NULL }
156
 
};
157
 
 
158
 
struct_desc isakmp_sa_desc = { "ISAKMP Security Association Payload", isasa_fields, sizeof(struct isakmp_sa) };
159
 
 
160
 
static field_desc ipsec_sit_field[] = {
161
 
    { ft_set, 32/BITS_PER_BYTE, "IPsec DOI SIT", &sit_bit_names },
162
 
    { ft_end, 0, NULL, NULL }
163
 
};
164
 
 
165
 
struct_desc ipsec_sit_desc = { "IPsec DOI SIT", ipsec_sit_field, sizeof(u_int32_t) };
166
 
 
167
 
/* ISAKMP Proposal Payload
168
 
 * layout from RFC 2408 "ISAKMP" section 3.5
169
 
 * A variable length SPI follows.
170
 
 * Previous next payload: ISAKMP_NEXT_P
171
 
 *                      1                   2                   3
172
 
 *  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
173
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
175
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176
 
 * !  Proposal #   !  Protocol-Id  !    SPI Size   !# of Transforms!
177
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178
 
 * !                        SPI (variable)                         !
179
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180
 
 */
181
 
static field_desc isap_fields[] = {
182
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
183
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
184
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
185
 
    { ft_nat, 8/BITS_PER_BYTE, "proposal number", NULL },
186
 
    { ft_enum, 8/BITS_PER_BYTE, "protocol ID", &protocol_names },
187
 
    { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
188
 
    { ft_nat, 8/BITS_PER_BYTE, "number of transforms", NULL },
189
 
    { ft_end, 0, NULL, NULL }
190
 
};
191
 
 
192
 
struct_desc isakmp_proposal_desc = { "ISAKMP Proposal Payload", isap_fields, sizeof(struct isakmp_proposal) };
193
 
 
194
 
/* ISAKMP Transform Payload
195
 
 * layout from RFC 2408 "ISAKMP" section 3.6
196
 
 * Variable length SA Attributes follow.
197
 
 * Previous next payload: ISAKMP_NEXT_T
198
 
 *                      1                   2                   3
199
 
 *  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
200
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
201
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
202
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
203
 
 * !  Transform #  !  Transform-Id !           RESERVED2           !
204
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205
 
 * !                                                               !
206
 
 * ~                        SA Attributes                          ~
207
 
 * !                                                               !
208
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
209
 
 */
210
 
 
211
 
/* PROTO_ISAKMP */
212
 
static field_desc isat_fields_isakmp[] = {
213
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
214
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
215
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
216
 
    { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
217
 
    { ft_enum, 8/BITS_PER_BYTE, "transform ID", &isakmp_transformid_names },
218
 
    { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
219
 
    { ft_end, 0, NULL, NULL }
220
 
};
221
 
 
222
 
struct_desc isakmp_isakmp_transform_desc = {
223
 
    "ISAKMP Transform Payload (ISAKMP)",
224
 
    isat_fields_isakmp, sizeof(struct isakmp_transform) };
225
 
 
226
 
/* PROTO_IPSEC_AH */
227
 
static field_desc isat_fields_ah[] = {
228
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
229
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
230
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
231
 
    { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
232
 
    { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ah_transformid_names },
233
 
    { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
234
 
    { ft_end, 0, NULL, NULL }
235
 
};
236
 
 
237
 
struct_desc isakmp_ah_transform_desc = {
238
 
    "ISAKMP Transform Payload (AH)",
239
 
    isat_fields_ah, sizeof(struct isakmp_transform) };
240
 
 
241
 
/* PROTO_IPSEC_ESP */
242
 
static field_desc isat_fields_esp[] = {
243
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
244
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
245
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
246
 
    { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
247
 
    { ft_enum, 8/BITS_PER_BYTE, "transform ID", &esp_transformid_names },
248
 
    { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
249
 
    { ft_end, 0, NULL, NULL }
250
 
};
251
 
 
252
 
struct_desc isakmp_esp_transform_desc = {
253
 
    "ISAKMP Transform Payload (ESP)",
254
 
    isat_fields_esp, sizeof(struct isakmp_transform) };
255
 
 
256
 
/* PROTO_IPCOMP */
257
 
static field_desc isat_fields_ipcomp[] = {
258
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
259
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
260
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
261
 
    { ft_nat, 8/BITS_PER_BYTE, "transform number", NULL },
262
 
    { ft_enum, 8/BITS_PER_BYTE, "transform ID", &ipcomp_transformid_names },
263
 
    { ft_mbz, 16/BITS_PER_BYTE, NULL, NULL },
264
 
    { ft_end, 0, NULL, NULL }
265
 
};
266
 
 
267
 
struct_desc isakmp_ipcomp_transform_desc = {
268
 
    "ISAKMP Transform Payload (COMP)",
269
 
    isat_fields_ipcomp, sizeof(struct isakmp_transform) };
270
 
 
271
 
 
272
 
/* ISAKMP Key Exchange Payload: no fixed fields beyond the generic ones.
273
 
 * layout from RFC 2408 "ISAKMP" section 3.7
274
 
 * Variable Key Exchange Data follow the generic fields.
275
 
 * Previous next payload: ISAKMP_NEXT_KE
276
 
 *                      1                   2                   3
277
 
 *  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
278
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
280
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281
 
 * !                                                               !
282
 
 * ~                       Key Exchange Data                       ~
283
 
 * !                                                               !
284
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
285
 
 */
286
 
struct_desc isakmp_keyex_desc = { "ISAKMP Key Exchange Payload", isag_fields, sizeof(struct isakmp_generic) };
287
 
 
288
 
/* ISAKMP Identification Payload
289
 
 * layout from RFC 2408 "ISAKMP" section 3.8
290
 
 * See "struct identity" declared later.
291
 
 * Variable length Identification Data follow.
292
 
 * Previous next payload: ISAKMP_NEXT_ID
293
 
 *                      1                   2                   3
294
 
 *  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
295
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
296
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
297
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
298
 
 * !   ID Type     !             DOI Specific ID Data              !
299
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
300
 
 * !                                                               !
301
 
 * ~                   Identification Data                         ~
302
 
 * !                                                               !
303
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
304
 
 */
305
 
static field_desc isaid_fields[] = {
306
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
307
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
308
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
309
 
    { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },      /* ??? depends on DOI? */
310
 
    { ft_nat, 8/BITS_PER_BYTE, "DOI specific A", NULL },        /* ??? depends on DOI? */
311
 
    { ft_nat, 16/BITS_PER_BYTE, "DOI specific B", NULL },       /* ??? depends on DOI? */
312
 
    { ft_end, 0, NULL, NULL }
313
 
};
314
 
 
315
 
struct_desc isakmp_identification_desc = { "ISAKMP Identification Payload", isaid_fields, sizeof(struct isakmp_id) };
316
 
 
317
 
/* IPSEC Identification Payload Content
318
 
 * layout from RFC 2407 "IPsec DOI" section 4.6.2
319
 
 * See struct isakmp_id declared earlier.
320
 
 * Note: Hashing skips the ISAKMP generic payload header
321
 
 * Variable length Identification Data follow.
322
 
 *                      1                   2                   3
323
 
 *  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
324
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
325
 
 * !  Next Payload !   RESERVED    !        Payload Length         !
326
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
327
 
 * !   ID Type     !  Protocol ID  !             Port              !
328
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329
 
 * ~                     Identification Data                       ~
330
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
331
 
 */
332
 
static field_desc isaiid_fields[] = {
333
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
334
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
335
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
336
 
    { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
337
 
    { ft_nat, 8/BITS_PER_BYTE, "Protocol ID", NULL },   /* ??? UDP/TCP or 0? */
338
 
    { ft_nat, 16/BITS_PER_BYTE, "port", NULL },
339
 
    { ft_end, 0, NULL, NULL }
340
 
};
341
 
 
342
 
struct_desc isakmp_ipsec_identification_desc = { "ISAKMP Identification Payload (IPsec DOI)", isaiid_fields, sizeof(struct isakmp_ipsec_id) };
343
 
 
344
 
/* ISAKMP Certificate Payload: oddball fixed field beyond the generic ones.
345
 
 * layout from RFC 2408 "ISAKMP" section 3.9
346
 
 * Variable length Certificate Data follow the generic fields.
347
 
 * Previous next payload: ISAKMP_NEXT_CERT.
348
 
 *                      1                   2                   3
349
 
 *  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
350
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
351
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
352
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
353
 
 * ! Cert Encoding !                                               !
354
 
 * +-+-+-+-+-+-+-+-+                                               !
355
 
 * ~                       Certificate Data                        ~
356
 
 * !                                                               !
357
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
358
 
 */
359
 
static field_desc isacert_fields[] = {
360
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
361
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
362
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
363
 
    { ft_enum, 8/BITS_PER_BYTE, "cert encoding", &cert_type_names },
364
 
    { ft_end, 0, NULL, NULL }
365
 
};
366
 
 
367
 
/* Note: the size field of isakmp_ipsec_certificate_desc cannot be
368
 
 * sizeof(struct isakmp_cert) because that will rounded up for padding.
369
 
 */
370
 
 struct_desc isakmp_ipsec_certificate_desc = { "ISAKMP Certificate Payload", isacert_fields, ISAKMP_CERT_SIZE };
371
 
 
372
 
/* ISAKMP Certificate Request Payload: oddball field beyond the generic ones.
373
 
 * layout from RFC 2408 "ISAKMP" section 3.10
374
 
 * Variable length Certificate Types and Certificate Authorities follow.
375
 
 * Previous next payload: ISAKMP_NEXT_CR.
376
 
 *                      1                   2                   3
377
 
 *  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
378
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
379
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
380
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
381
 
 * !  Cert. Type   !                                               !
382
 
 * +-+-+-+-+-+-+-+-+                                               !
383
 
 * ~                    Certificate Authority                      ~
384
 
 * !                                                               !
385
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
386
 
 */
387
 
static field_desc isacr_fields[] = {
388
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
389
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
390
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
391
 
    { ft_enum, 8/BITS_PER_BYTE, "cert type", &cert_type_names },
392
 
    { ft_end, 0, NULL, NULL }
393
 
};
394
 
 
395
 
/* Note: the size field of isakmp_ipsec_cert_req_desc cannot be
396
 
 * sizeof(struct isakmp_cr) because that will rounded up for padding.
397
 
 */
398
 
struct_desc isakmp_ipsec_cert_req_desc = { "ISAKMP Certificate RequestPayload", isacr_fields, ISAKMP_CR_SIZE };
399
 
 
400
 
/* ISAKMP Hash Payload: no fixed fields beyond the generic ones.
401
 
 * layout from RFC 2408 "ISAKMP" section 3.11
402
 
 * Variable length Hash Data follow.
403
 
 * Previous next payload: ISAKMP_NEXT_HASH.
404
 
 *                      1                   2                   3
405
 
 *  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
406
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
407
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
408
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
409
 
 * !                                                               !
410
 
 * ~                           Hash Data                           ~
411
 
 * !                                                               !
412
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
413
 
 */
414
 
struct_desc isakmp_hash_desc = { "ISAKMP Hash Payload", isag_fields, sizeof(struct isakmp_generic) };
415
 
 
416
 
/* ISAKMP Signature Payload: no fixed fields beyond the generic ones.
417
 
 * layout from RFC 2408 "ISAKMP" section 3.12
418
 
 * Variable length Signature Data follow.
419
 
 * Previous next payload: ISAKMP_NEXT_SIG.
420
 
 *                      1                   2                   3
421
 
 *  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
422
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
423
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
424
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
425
 
 * !                                                               !
426
 
 * ~                         Signature Data                        ~
427
 
 * !                                                               !
428
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
429
 
 */
430
 
struct_desc isakmp_signature_desc = { "ISAKMP Signature Payload", isag_fields, sizeof(struct isakmp_generic) };
431
 
 
432
 
/* ISAKMP Nonce Payload: no fixed fields beyond the generic ones.
433
 
 * layout from RFC 2408 "ISAKMP" section 3.13
434
 
 * Variable length Nonce Data follow.
435
 
 * Previous next payload: ISAKMP_NEXT_NONCE.
436
 
 *                      1                   2                   3
437
 
 *  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
438
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
439
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
440
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
441
 
 * !                                                               !
442
 
 * ~                            Nonce Data                         ~
443
 
 * !                                                               !
444
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
445
 
 */
446
 
struct_desc isakmp_nonce_desc = { "ISAKMP Nonce Payload", isag_fields, sizeof(struct isakmp_generic) };
447
 
 
448
 
/* ISAKMP Notification Payload
449
 
 * layout from RFC 2408 "ISAKMP" section 3.14
450
 
 * This is followed by a variable length SPI
451
 
 * and then possibly by variable length Notification Data.
452
 
 * Previous next payload: ISAKMP_NEXT_N
453
 
 *                      1                   2                   3
454
 
 *  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
455
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
456
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
457
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
458
 
 * !              Domain of Interpretation  (DOI)                  !
459
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460
 
 * !  Protocol-ID  !   SPI Size    !      Notify Message Type      !
461
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
462
 
 * !                                                               !
463
 
 * ~                Security Parameter Index (SPI)                 ~
464
 
 * !                                                               !
465
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
466
 
 * !                                                               !
467
 
 * ~                       Notification Data                       ~
468
 
 * !                                                               !
469
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
470
 
 */
471
 
static field_desc isan_fields[] = {
472
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
473
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
474
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
475
 
    { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
476
 
    { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL },   /* ??? really enum: ISAKMP, IPSEC, ESP, ... */
477
 
    { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
478
 
    { ft_enum, 16/BITS_PER_BYTE, "Notify Message Type", &ipsec_notification_names },
479
 
    { ft_end, 0, NULL, NULL }
480
 
};
481
 
 
482
 
struct_desc isakmp_notification_desc = { "ISAKMP Notification Payload", isan_fields, sizeof(struct isakmp_notification) };
483
 
 
484
 
/* ISAKMP Delete Payload
485
 
 * layout from RFC 2408 "ISAKMP" section 3.15
486
 
 * This is followed by a variable length SPI.
487
 
 * Previous next payload: ISAKMP_NEXT_D
488
 
 *                      1                   2                   3
489
 
 *  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
490
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
491
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
492
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
493
 
 * !              Domain of Interpretation  (DOI)                  !
494
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
495
 
 * !  Protocol-Id  !   SPI Size    !           # of SPIs           !
496
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
497
 
 * !                                                               !
498
 
 * ~               Security Parameter Index(es) (SPI)              ~
499
 
 * !                                                               !
500
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
501
 
 */
502
 
static field_desc isad_fields[] = {
503
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
504
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
505
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
506
 
    { ft_enum, 32/BITS_PER_BYTE, "DOI", &doi_names },
507
 
    { ft_nat, 8/BITS_PER_BYTE, "protocol ID", NULL },   /* ??? really enum: ISAKMP, IPSEC */
508
 
    { ft_nat, 8/BITS_PER_BYTE, "SPI size", NULL },
509
 
    { ft_nat, 16/BITS_PER_BYTE, "number of SPIs", NULL },
510
 
    { ft_end, 0, NULL, NULL }
511
 
};
512
 
 
513
 
struct_desc isakmp_delete_desc = { "ISAKMP Delete Payload", isad_fields, sizeof(struct isakmp_delete) };
514
 
 
515
 
/* ISAKMP Vendor ID Payload
516
 
 * layout from RFC 2408 "ISAKMP" section 3.15
517
 
 * This is followed by a variable length VID.
518
 
 * Previous next payload: ISAKMP_NEXT_VID
519
 
 *                      1                   2                   3
520
 
 *  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
521
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
522
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
523
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
524
 
 * !                                                               !
525
 
 * ~                        Vendor ID (VID)                        ~
526
 
 * !                                                               !
527
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
528
 
 */
529
 
struct_desc isakmp_vendor_id_desc = { "ISAKMP Vendor ID Payload", isag_fields, sizeof(struct isakmp_generic) };
530
 
 
531
 
/* MODECFG */
532
 
/*
533
 
 * From draft-dukes-ike-mode-cfg
534
 
3.2. Attribute Payload 
535
 
                           1                   2                   3 
536
 
       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 
537
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
538
 
     ! Next Payload  !   RESERVED    !         Payload Length        ! 
539
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
540
 
     !     Type      !   RESERVED    !           Identifier          ! 
541
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
542
 
     !                                                               ! 
543
 
     ~                           Attributes                          ~ 
544
 
     !                                                               ! 
545
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
546
 
*/    
547
 
static field_desc isaattr_fields[] = {
548
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
549
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
550
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
551
 
    { ft_enum, 8/BITS_PER_BYTE, "Attr Msg Type", &attr_msg_type_names },
552
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
553
 
    { ft_nat, 16/BITS_PER_BYTE, "Identifier", NULL },
554
 
    { ft_end, 0, NULL, NULL }
555
 
};
556
 
 
557
 
/* MODECFG */
558
 
/* From draft-dukes-ike-mode-cfg
559
 
3.2. Attribute Payload
560
 
                           1                   2                   3  
561
 
       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
562
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
563
 
     ! Next Payload  !   RESERVED    !         Payload Length        !
564
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
565
 
     !     Type      !   RESERVED    !           Identifier          !
566
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
567
 
     !                                                               !
568
 
     !                                                               !
569
 
     ~                           Attributes                          ~
570
 
     !                                                               !
571
 
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572
 
*/
573
 
 
574
 
struct_desc isakmp_attr_desc = { "ISAKMP Mode Attribute", isaattr_fields, sizeof(struct isakmp_mode_attr) };
575
 
 
576
 
/* ISAKMP NAT-Traversal NAT-D
577
 
 * layout from draft-ietf-ipsec-nat-t-ike-01.txt section 3.2
578
 
 *
579
 
 *  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
580
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
581
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
582
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
583
 
 * !                 HASH of the address and port                  !
584
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
585
 
 */
586
 
struct_desc isakmp_nat_d = { "ISAKMP NAT-D Payload", isag_fields, sizeof(struct isakmp_generic) };
587
 
 
588
 
/* ISAKMP NAT-Traversal NAT-OA
589
 
 * layout from draft-ietf-ipsec-nat-t-ike-01.txt section 4.2
590
 
 *
591
 
 *  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
592
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
593
 
 * ! Next Payload  !   RESERVED    !         Payload Length        !
594
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
595
 
 * !   ID Type     !   RESERVED    !            RESERVED           !
596
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
597
 
 * !         IPv4 (4 octets) or IPv6 address (16 octets)           !
598
 
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
599
 
 */
600
 
static field_desc isanat_oa_fields[] = {
601
 
    { ft_enum, 8/BITS_PER_BYTE, "next payload type", &payload_names },
602
 
    { ft_mbz, 8/BITS_PER_BYTE, NULL, NULL },
603
 
    { ft_len, 16/BITS_PER_BYTE, "length", NULL },
604
 
    { ft_enum, 8/BITS_PER_BYTE, "ID type", &ident_names },
605
 
    { ft_mbz, 24/BITS_PER_BYTE, NULL, NULL },
606
 
    { ft_end, 0, NULL, NULL }
607
 
};
608
 
 
609
 
struct_desc isakmp_nat_oa = { "ISAKMP NAT-OA Payload", isanat_oa_fields, sizeof(struct isakmp_nat_oa) };
610
 
 
611
 
/* descriptor for each payload type
612
 
 *
613
 
 * There is a slight problem in that some payloads differ, depending
614
 
 * on the mode.  Since this is table only used for top-level payloads,
615
 
 * Proposal and Transform payloads need not be handled.
616
 
 * That leaves only Identification payloads as a problem.
617
 
 * We make all these entries NULL
618
 
 */
619
 
struct_desc *const payload_descs[ISAKMP_NEXT_ROOF] = {
620
 
    NULL,                               /* 0 ISAKMP_NEXT_NONE (No other payload following) */
621
 
    &isakmp_sa_desc,                    /* 1 ISAKMP_NEXT_SA (Security Association) */
622
 
    NULL,                               /* 2 ISAKMP_NEXT_P (Proposal) */
623
 
    NULL,                               /* 3 ISAKMP_NEXT_T (Transform) */
624
 
    &isakmp_keyex_desc,                 /* 4 ISAKMP_NEXT_KE (Key Exchange) */
625
 
    NULL,                               /* 5 ISAKMP_NEXT_ID (Identification) */
626
 
    &isakmp_ipsec_certificate_desc,     /* 6 ISAKMP_NEXT_CERT (Certificate) */
627
 
    &isakmp_ipsec_cert_req_desc,        /* 7 ISAKMP_NEXT_CR (Certificate Request) */
628
 
    &isakmp_hash_desc,                  /* 8 ISAKMP_NEXT_HASH (Hash) */
629
 
    &isakmp_signature_desc,             /* 9 ISAKMP_NEXT_SIG (Signature) */
630
 
    &isakmp_nonce_desc,                 /* 10 ISAKMP_NEXT_NONCE (Nonce) */
631
 
    &isakmp_notification_desc,          /* 11 ISAKMP_NEXT_N (Notification) */
632
 
    &isakmp_delete_desc,                /* 12 ISAKMP_NEXT_D (Delete) */
633
 
    &isakmp_vendor_id_desc,             /* 13 ISAKMP_NEXT_VID (Vendor ID) */
634
 
    &isakmp_attr_desc,                  /* 14 ISAKMP_NEXT_ATTR (ModeCfg)  */    
635
 
    &isakmp_nat_d,                      /* 15=130 ISAKMP_NEXT_NATD (NAT-D) */
636
 
    &isakmp_nat_oa,                     /* 16=131 ISAKMP_NEXT_NATOA (NAT-OA) */
637
 
};
638
 
 
639
 
void
640
 
init_pbs(pb_stream *pbs, u_int8_t *start, size_t len, const char *name)
641
 
{
642
 
    pbs->container = NULL;
643
 
    pbs->desc = NULL;
644
 
    pbs->name = name;
645
 
    pbs->start = pbs->cur = start;
646
 
    pbs->roof = start + len;
647
 
    pbs->lenfld = NULL;
648
 
    pbs->lenfld_desc = NULL;
649
 
}
650
 
 
651
 
#ifdef DEBUG
652
 
 
653
 
/* print a host struct
654
 
 *
655
 
 * This code assumes that the network and host structure
656
 
 * members have the same alignment and size!  This requires
657
 
 * that all padding be explicit.
658
 
 */
659
 
void
660
 
DBG_print_struct(const char *label, const void *struct_ptr
661
 
, struct_desc *sd, bool len_meaningful)
662
 
{
663
 
    bool immediate = FALSE;
664
 
    const u_int8_t *inp = struct_ptr;
665
 
    field_desc *fp;
666
 
 
667
 
    DBG_log("%s%s:", label, sd->name);
668
 
 
669
 
    for (fp = sd->fields; fp->field_type != ft_end; fp++)
670
 
    {
671
 
        int i = fp->size;
672
 
        u_int32_t n = 0;
673
 
 
674
 
        switch (fp->field_type)
675
 
        {
676
 
        case ft_mbz:    /* must be zero */
677
 
            inp += i;
678
 
            break;
679
 
        case ft_nat:    /* natural number (may be 0) */
680
 
        case ft_len:    /* length of this struct and any following crud */
681
 
        case ft_lv:     /* length/value field of attribute */
682
 
        case ft_enum:   /* value from an enumeration */
683
 
        case ft_loose_enum:     /* value from an enumeration with only some names known */
684
 
        case ft_af_enum:        /* Attribute Format + value from an enumeration */
685
 
        case ft_af_loose_enum:  /* Attribute Format + value from an enumeration */
686
 
        case ft_set:    /* bits representing set */
687
 
            switch (i)
688
 
            {
689
 
            case 8/BITS_PER_BYTE:
690
 
                n = *(const u_int8_t *)inp;
691
 
                break;
692
 
            case 16/BITS_PER_BYTE:
693
 
                n = *(const u_int16_t *)inp;
694
 
                break;
695
 
            case 32/BITS_PER_BYTE:
696
 
                n = *(const u_int32_t *)inp;
697
 
                break;
698
 
            default:
699
 
                bad_case(i);
700
 
            }
701
 
            switch (fp->field_type)
702
 
            {
703
 
            case ft_len:        /* length of this struct and any following crud */
704
 
            case ft_lv:         /* length/value field of attribute */
705
 
                if (!immediate && !len_meaningful)
706
 
                    break;
707
 
                /* FALL THROUGH */
708
 
            case ft_nat:        /* natural number (may be 0) */
709
 
                DBG_log("   %s: %lu", fp->name, (unsigned long)n);
710
 
                break;
711
 
 
712
 
            case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
713
 
            case ft_af_enum:    /* Attribute Format + value from an enumeration */
714
 
                if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
715
 
                    immediate = TRUE;
716
 
                /* FALL THROUGH */
717
 
            case ft_enum:       /* value from an enumeration */
718
 
            case ft_loose_enum: /* value from an enumeration with only some names known */
719
 
                DBG_log("   %s: %s", fp->name, enum_show(fp->desc, n));
720
 
                break;
721
 
            case ft_set:        /* bits representing set */
722
 
                DBG_log("   %s: %s", fp->name, bitnamesof(fp->desc, n));
723
 
                break;
724
 
            default:
725
 
                bad_case(fp->field_type);
726
 
            }
727
 
            inp += i;
728
 
            break;
729
 
 
730
 
        case ft_raw:    /* bytes to be left in network-order */
731
 
            {
732
 
                char m[50];     /* arbitrary limit on name width in log */
733
 
 
734
 
                snprintf(m, sizeof(m), "   %s:", fp->name);
735
 
                DBG_dump(m, inp, i);
736
 
                inp += i;
737
 
            }
738
 
            break;
739
 
        default:
740
 
            bad_case(fp->field_type);
741
 
        }
742
 
    }
743
 
}
744
 
 
745
 
static void
746
 
DBG_prefix_print_struct(const pb_stream *pbs
747
 
, const char *label, const void *struct_ptr
748
 
, struct_desc *sd, bool len_meaningful)
749
 
{
750
 
    /* print out a title, with a prefix of asterisks to show
751
 
     * the nesting level.
752
 
     */
753
 
    char space[40];     /* arbitrary limit on label+flock-of-* */
754
 
    size_t len = strlen(label);
755
 
 
756
 
    if (sizeof(space) <= len)
757
 
    {
758
 
        DBG_print_struct(label, struct_ptr, sd, len_meaningful);
759
 
    }
760
 
    else
761
 
    {
762
 
        const pb_stream *p = pbs;
763
 
        char *pre = &space[sizeof(space) - (len + 1)];
764
 
 
765
 
        strcpy(pre, label);
766
 
 
767
 
        /* put at least one * out */
768
 
        for (;;)
769
 
        {
770
 
            if (pre <= space)
771
 
                break;
772
 
            *--pre = '*';
773
 
            if (p == NULL)
774
 
                break;
775
 
            p = p->container;
776
 
        }
777
 
        DBG_print_struct(pre, struct_ptr, sd, len_meaningful);
778
 
    }
779
 
}
780
 
 
781
 
#endif
782
 
 
783
 
/* "parse" a network struct into a host struct.
784
 
 *
785
 
 * This code assumes that the network and host structure
786
 
 * members have the same alignment and size!  This requires
787
 
 * that all padding be explicit.
788
 
 *
789
 
 * If obj_pbs is supplied, a new pb_stream is created for the
790
 
 * variable part of the structure (this depends on their
791
 
 * being one length field in the structure).  The cursor of this
792
 
 * new PBS is set to after the parsed part of the struct.
793
 
 *
794
 
 * This routine returns TRUE iff it succeeds.
795
 
 */
796
 
 
797
 
bool
798
 
in_struct(void *struct_ptr, struct_desc *sd
799
 
, pb_stream *ins, pb_stream *obj_pbs)
800
 
{
801
 
    err_t ugh = NULL;
802
 
    u_int8_t *cur = ins->cur;
803
 
 
804
 
    if (ins->roof - cur < (ptrdiff_t)sd->size)
805
 
    {
806
 
        ugh = builddiag("not enough room in input packet for %s", sd->name);
807
 
    }
808
 
    else
809
 
    {
810
 
        u_int8_t *roof = cur + sd->size;    /* may be changed by a length field */
811
 
        u_int8_t *outp = struct_ptr;
812
 
        bool immediate = FALSE;
813
 
        field_desc *fp;
814
 
 
815
 
        for (fp = sd->fields; ugh == NULL; fp++)
816
 
        {
817
 
            size_t i = fp->size;
818
 
 
819
 
            passert(ins->roof - cur >= (ptrdiff_t)i);
820
 
            passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i));
821
 
            passert(outp - (cur - ins->cur) == struct_ptr);
822
 
 
823
 
#if 0
824
 
            DBG(DBG_PARSING, DBG_log("%d %s"
825
 
                , (int) (cur - ins->cur), fp->name == NULL? "" : fp->name));
826
 
#endif
827
 
            switch (fp->field_type)
828
 
            {
829
 
            case ft_mbz:        /* must be zero */
830
 
                for (; i != 0; i--)
831
 
                {
832
 
                    if (*cur++ != 0)
833
 
                    {
834
 
                        ugh = builddiag("byte %d of %s must be zero, but is not"
835
 
                            , (int) (cur - ins->cur), sd->name);
836
 
                        break;
837
 
                    }
838
 
                    *outp++ = '\0';     /* probably redundant */
839
 
                }
840
 
                break;
841
 
 
842
 
            case ft_nat:        /* natural number (may be 0) */
843
 
            case ft_len:        /* length of this struct and any following crud */
844
 
            case ft_lv:         /* length/value field of attribute */
845
 
            case ft_enum:       /* value from an enumeration */
846
 
            case ft_loose_enum: /* value from an enumeration with only some names known */
847
 
            case ft_af_enum:    /* Attribute Format + value from an enumeration */
848
 
            case ft_af_loose_enum:      /* Attribute Format + value from an enumeration */
849
 
            case ft_set:        /* bits representing set */
850
 
            {
851
 
                u_int32_t n = 0;
852
 
 
853
 
                for (; i != 0; i--)
854
 
                    n = (n << BITS_PER_BYTE) | *cur++;
855
 
 
856
 
                switch (fp->field_type)
857
 
                {
858
 
                case ft_len:    /* length of this struct and any following crud */
859
 
                case ft_lv:     /* length/value field of attribute */
860
 
                {
861
 
                    u_int32_t len = fp->field_type == ft_len? n
862
 
                        : immediate? sd->size : n + sd->size;
863
 
 
864
 
                    if (len < sd->size)
865
 
                    {
866
 
                        ugh = builddiag("%s of %s is smaller than minimum"
867
 
                            , fp->name, sd->name);
868
 
                    }
869
 
                    else if (pbs_left(ins) < len)
870
 
                    {
871
 
                        ugh = builddiag("%s of %s is larger than can fit"
872
 
                            , fp->name, sd->name);
873
 
                    }
874
 
                    else
875
 
                    {
876
 
                        roof = ins->cur + len;
877
 
                    }
878
 
                    break;
879
 
                }
880
 
                case ft_af_loose_enum:  /* Attribute Format + value from an enumeration */
881
 
                    if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
882
 
                        immediate = TRUE;
883
 
                    break;
884
 
 
885
 
                case ft_af_enum:        /* Attribute Format + value from an enumeration */
886
 
                    if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
887
 
                        immediate = TRUE;
888
 
                    /* FALL THROUGH */
889
 
                case ft_enum:   /* value from an enumeration */
890
 
                    if (enum_name(fp->desc, n) == NULL)
891
 
                    {
892
 
                        ugh = builddiag("%s of %s has an unknown value: %lu"
893
 
                            , fp->name, sd->name, (unsigned long)n);
894
 
                    }
895
 
                    /* FALL THROUGH */
896
 
                case ft_loose_enum:     /* value from an enumeration with only some names known */
897
 
                    break;
898
 
                case ft_set:    /* bits representing set */
899
 
                    if (!testset(fp->desc, n))
900
 
                    {
901
 
                        ugh = builddiag("bitset %s of %s has unknown member(s): %s"
902
 
                            , fp->name, sd->name, bitnamesof(fp->desc, n));
903
 
                    }
904
 
                    break;
905
 
                default:
906
 
                        break;
907
 
                }
908
 
                i = fp->size;
909
 
                switch (i)
910
 
                {
911
 
                case 8/BITS_PER_BYTE:
912
 
                    *(u_int8_t *)outp = n;
913
 
                    break;
914
 
                case 16/BITS_PER_BYTE:
915
 
                    *(u_int16_t *)outp = n;
916
 
                    break;
917
 
                case 32/BITS_PER_BYTE:
918
 
                    *(u_int32_t *)outp = n;
919
 
                    break;
920
 
                default:
921
 
                    bad_case(i);
922
 
                }
923
 
                outp += i;
924
 
                break;
925
 
            }
926
 
 
927
 
            case ft_raw:        /* bytes to be left in network-order */
928
 
                for (; i != 0; i--)
929
 
                {
930
 
                    *outp++ = *cur++;
931
 
                }
932
 
                break;
933
 
 
934
 
            case ft_end:        /* end of field list */
935
 
                passert(cur == ins->cur + sd->size);
936
 
                if (obj_pbs != NULL)
937
 
                {
938
 
                    init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name);
939
 
                    obj_pbs->container = ins;
940
 
                    obj_pbs->desc = sd;
941
 
                    obj_pbs->cur = cur;
942
 
                }
943
 
                ins->cur = roof;
944
 
                DBG(DBG_PARSING
945
 
                    , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE));
946
 
                return TRUE;
947
 
 
948
 
            default:
949
 
                bad_case(fp->field_type);
950
 
            }
951
 
        }
952
 
    }
953
 
 
954
 
    /* some failure got us here: report it */
955
 
    loglog(RC_LOG_SERIOUS, ugh);
956
 
    return FALSE;
957
 
}
958
 
 
959
 
bool
960
 
in_raw(void *bytes, size_t len, pb_stream *ins, const char *name)
961
 
{
962
 
    if (pbs_left(ins) < len)
963
 
    {
964
 
        loglog(RC_LOG_SERIOUS, "not enough bytes left to get %s from %s", name, ins->name);
965
 
        return FALSE;
966
 
    }
967
 
    else
968
 
    {
969
 
        if (bytes == NULL)
970
 
        {
971
 
            DBG(DBG_PARSING
972
 
                , DBG_log("skipping %u raw bytes of %s (%s)"
973
 
                    , (unsigned) len, ins->name, name);
974
 
                  DBG_dump(name, ins->cur, len));
975
 
        }
976
 
        else
977
 
        {
978
 
            memcpy(bytes, ins->cur, len);
979
 
            DBG(DBG_PARSING
980
 
                , DBG_log("parsing %u raw bytes of %s into %s"
981
 
                    , (unsigned) len, ins->name, name);
982
 
                  DBG_dump(name, bytes, len));
983
 
        }
984
 
        ins->cur += len;
985
 
        return TRUE;
986
 
    }
987
 
}
988
 
 
989
 
/* "emit" a host struct into a network packet.
990
 
 *
991
 
 * This code assumes that the network and host structure
992
 
 * members have the same alignment and size!  This requires
993
 
 * that all padding be explicit.
994
 
 *
995
 
 * If obj_pbs is non-NULL, its pbs describes a new output stream set up
996
 
 * to contain the object.  The cursor will be left at the variable part.
997
 
 * This new stream must subsequently be finalized by close_output_pbs().
998
 
 *
999
 
 * The value of any field of type ft_len is computed, not taken
1000
 
 * from the input struct.  The length is actually filled in when
1001
 
 * the object's output stream is finalized.  If obj_pbs is NULL,
1002
 
 * finalization is done by out_struct before it returns.
1003
 
 *
1004
 
 * This routine returns TRUE iff it succeeds.
1005
 
 */
1006
 
 
1007
 
bool
1008
 
out_struct(const void *struct_ptr, struct_desc *sd
1009
 
           , pb_stream *outs, pb_stream *obj_pbs)
1010
 
{
1011
 
    err_t ugh = NULL;
1012
 
    const u_int8_t *inp = struct_ptr;
1013
 
    u_int8_t *cur = outs->cur;
1014
 
 
1015
 
    DBG(DBG_EMITTING
1016
 
        , DBG_prefix_print_struct(outs, "emit ", struct_ptr, sd, obj_pbs==NULL));
1017
 
 
1018
 
    if (outs->roof - cur < (ptrdiff_t)sd->size)
1019
 
    {
1020
 
        ugh = builddiag("not enough room left in output packet to place %s"
1021
 
            , sd->name);
1022
 
    }
1023
 
    else
1024
 
    {
1025
 
        bool immediate = FALSE;
1026
 
        pb_stream obj;
1027
 
        field_desc *fp;
1028
 
 
1029
 
        obj.lenfld = NULL;  /* until a length field is discovered */
1030
 
        obj.lenfld_desc = NULL;
1031
 
 
1032
 
        for (fp = sd->fields; ugh == NULL; fp++)
1033
 
        {
1034
 
            size_t i = fp->size;
1035
 
 
1036
 
            passert(outs->roof - cur >= (ptrdiff_t)i);
1037
 
            passert(cur - outs->cur <= (ptrdiff_t)(sd->size - i));
1038
 
            passert(inp - (cur - outs->cur) == struct_ptr);
1039
 
 
1040
 
#if 0
1041
 
            DBG(DBG_EMITTING, DBG_log("%d %s"
1042
 
                , (int) (cur - outs->cur), fp->name == NULL? "" : fp->name);
1043
 
#endif
1044
 
            switch (fp->field_type)
1045
 
            {
1046
 
            case ft_mbz:        /* must be zero */
1047
 
                inp += i;
1048
 
                for (; i != 0; i--)
1049
 
                    *cur++ = '\0';
1050
 
                break;
1051
 
            case ft_nat:        /* natural number (may be 0) */
1052
 
            case ft_len:        /* length of this struct and any following crud */
1053
 
            case ft_lv:         /* length/value field of attribute */
1054
 
            case ft_enum:       /* value from an enumeration */
1055
 
            case ft_loose_enum: /* value from an enumeration with only some names known */
1056
 
            case ft_af_enum:    /* Attribute Format + value from an enumeration */
1057
 
            case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
1058
 
            case ft_set:        /* bits representing set */
1059
 
            {
1060
 
                u_int32_t n = 0;
1061
 
 
1062
 
                switch (i)
1063
 
                {
1064
 
                case 8/BITS_PER_BYTE:
1065
 
                    n = *(const u_int8_t *)inp;
1066
 
                    break;
1067
 
                case 16/BITS_PER_BYTE:
1068
 
                    n = *(const u_int16_t *)inp;
1069
 
                    break;
1070
 
                case 32/BITS_PER_BYTE:
1071
 
                    n = *(const u_int32_t *)inp;
1072
 
                    break;
1073
 
                default:
1074
 
                    bad_case(i);
1075
 
                }
1076
 
 
1077
 
                switch (fp->field_type)
1078
 
                {
1079
 
                case ft_len:    /* length of this struct and any following crud */
1080
 
                case ft_lv:     /* length/value field of attribute */
1081
 
                    if (immediate)
1082
 
                        break;  /* not a length */
1083
 
                    /* We can't check the length because it will likely
1084
 
                     * be filled in after variable part is supplied.
1085
 
                     * We do record where this is so that it can be
1086
 
                     * filled in by a subsequent close_output_pbs().
1087
 
                     */
1088
 
                    passert(obj.lenfld == NULL);        /* only one ft_len allowed */
1089
 
                    obj.lenfld = cur;
1090
 
                    obj.lenfld_desc = fp;
1091
 
                    break;
1092
 
                case ft_af_loose_enum: /* Attribute Format + value from an enumeration */
1093
 
                    if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
1094
 
                        immediate = TRUE;
1095
 
                    break;
1096
 
 
1097
 
                case ft_af_enum:        /* Attribute Format + value from an enumeration */
1098
 
                    if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV)
1099
 
                        immediate = TRUE;
1100
 
                    /* FALL THROUGH */
1101
 
                case ft_enum:   /* value from an enumeration */
1102
 
                    if (enum_name(fp->desc, n) == NULL)
1103
 
                    {
1104
 
                        ugh = builddiag("%s of %s has an unknown value: %lu"
1105
 
                            , fp->name, sd->name, (unsigned long)n);
1106
 
                    }
1107
 
                    /* FALL THROUGH */
1108
 
                case ft_loose_enum:     /* value from an enumeration with only some names known */
1109
 
                    break;
1110
 
                case ft_set:    /* bits representing set */
1111
 
                    if (!testset(fp->desc, n))
1112
 
                    {
1113
 
                        ugh = builddiag("bitset %s of %s has unknown member(s): %s"
1114
 
                            , fp->name, sd->name, bitnamesof(fp->desc, n));
1115
 
                    }
1116
 
                    break;
1117
 
                default:
1118
 
                    break;
1119
 
                }
1120
 
 
1121
 
                while (i-- != 0)
1122
 
                {
1123
 
                    cur[i] = (u_int8_t)n;
1124
 
                    n >>= BITS_PER_BYTE;
1125
 
                }
1126
 
                inp += fp->size;
1127
 
                cur += fp->size;
1128
 
                break;
1129
 
            }
1130
 
            case ft_raw:        /* bytes to be left in network-order */
1131
 
                for (; i != 0; i--)
1132
 
                    *cur++ = *inp++;
1133
 
                break;
1134
 
            case ft_end:        /* end of field list */
1135
 
                passert(cur == outs->cur + sd->size);
1136
 
 
1137
 
                obj.container = outs;
1138
 
                obj.desc = sd;
1139
 
                obj.name = sd->name;
1140
 
                obj.start = outs->cur;
1141
 
                obj.cur = cur;
1142
 
                obj.roof = outs->roof;  /* limit of possible */
1143
 
                /* obj.lenfld and obj.lenfld_desc already set */
1144
 
 
1145
 
                if (obj_pbs == NULL)
1146
 
                {
1147
 
                    close_output_pbs(&obj); /* fill in length field, if any */
1148
 
                }
1149
 
                else
1150
 
                {
1151
 
                    /* We set outs->cur to outs->roof so that
1152
 
                     * any attempt to output something into outs
1153
 
                     * before obj is closed will trigger an error.
1154
 
                     */
1155
 
                    outs->cur = outs->roof;
1156
 
 
1157
 
                    *obj_pbs = obj;
1158
 
                }
1159
 
                return TRUE;
1160
 
 
1161
 
            default:
1162
 
                bad_case(fp->field_type);
1163
 
            }
1164
 
        }
1165
 
    }
1166
 
 
1167
 
    /* some failure got us here: report it */
1168
 
    loglog(RC_LOG_SERIOUS, ugh);        /* ??? serious, but errno not relevant */
1169
 
    return FALSE;
1170
 
}
1171
 
 
1172
 
bool
1173
 
out_modify_previous_np(u_int8_t np, pb_stream *outs)
1174
 
{
1175
 
        size_t len = (outs->cur - outs->start), offset;
1176
 
        if (len < sizeof(struct isakmp_hdr)) {
1177
 
                return FALSE;
1178
 
        }
1179
 
        else if (len == sizeof(struct isakmp_hdr)) {
1180
 
                struct isakmp_hdr *hdr = (struct isakmp_hdr *)outs->start;
1181
 
                hdr->isa_np = np;
1182
 
                return TRUE;
1183
 
        }
1184
 
        else {
1185
 
                struct isakmp_generic *hdr;
1186
 
                for (offset = sizeof(struct isakmp_hdr); offset < len ;
1187
 
                        offset += ntohs(hdr->isag_length)) {
1188
 
                        if ((len - offset) < sizeof(struct isakmp_generic))
1189
 
                                return FALSE;
1190
 
                        hdr = (struct isakmp_generic *)(outs->start+offset);
1191
 
                        if ((len - offset) < ntohs(hdr->isag_length))
1192
 
                                return FALSE;
1193
 
                        if ((len - offset) == ntohs(hdr->isag_length)) {
1194
 
                                hdr->isag_np = np;
1195
 
                                return TRUE;
1196
 
                        }
1197
 
                }
1198
 
        }
1199
 
        return FALSE;
1200
 
}
1201
 
 
1202
 
bool
1203
 
out_generic(u_int8_t np, struct_desc *sd
1204
 
, pb_stream *outs, pb_stream *obj_pbs)
1205
 
{
1206
 
    struct isakmp_generic gen;
1207
 
 
1208
 
    passert(sd->fields == isakmp_generic_desc.fields);
1209
 
    gen.isag_np = np;
1210
 
    return out_struct(&gen, sd, outs, obj_pbs);
1211
 
}
1212
 
 
1213
 
bool
1214
 
out_generic_raw(u_int8_t np, struct_desc *sd
1215
 
, pb_stream *outs, const void *bytes, size_t len, const char *name)
1216
 
{
1217
 
    pb_stream pbs;
1218
 
 
1219
 
    if (!out_generic(np, sd, outs, &pbs)
1220
 
    || !out_raw(bytes, len, &pbs, name))
1221
 
        return FALSE;
1222
 
    close_output_pbs(&pbs);
1223
 
    return TRUE;
1224
 
}
1225
 
 
1226
 
bool
1227
 
out_raw(const void *bytes, size_t len, pb_stream *outs, const char *name)
1228
 
{
1229
 
    if (pbs_left(outs) < len)
1230
 
    {
1231
 
        loglog(RC_LOG_SERIOUS, "not enough room left to place %lu bytes of %s in %s"
1232
 
            , (unsigned long) len, name, outs->name);
1233
 
        return FALSE;
1234
 
    }
1235
 
    else
1236
 
    {
1237
 
        DBG(DBG_EMITTING
1238
 
            , DBG_log("emitting %u raw bytes of %s into %s"
1239
 
                , (unsigned) len, name, outs->name);
1240
 
              DBG_dump(name, bytes, len));
1241
 
        memcpy(outs->cur, bytes, len);
1242
 
        outs->cur += len;
1243
 
        return TRUE;
1244
 
    }
1245
 
}
1246
 
 
1247
 
bool
1248
 
out_zero(size_t len, pb_stream *outs, const char *name)
1249
 
{
1250
 
    if (pbs_left(outs) < len)
1251
 
    {
1252
 
        loglog(RC_LOG_SERIOUS, "not enough room left to place %s in %s", name, outs->name);
1253
 
        return FALSE;
1254
 
    }
1255
 
    else
1256
 
    {
1257
 
        DBG(DBG_EMITTING, DBG_log("emitting %u zero bytes of %s into %s"
1258
 
            , (unsigned) len, name, outs->name));
1259
 
        memset(outs->cur, 0x00, len);
1260
 
        outs->cur += len;
1261
 
        return TRUE;
1262
 
    }
1263
 
}
1264
 
 
1265
 
/* Record current length.
1266
 
 * Note: currently, this may be repeated any number of times;
1267
 
 * the last one wins.
1268
 
 */
1269
 
void
1270
 
close_output_pbs(pb_stream *pbs)
1271
 
{
1272
 
    if (pbs->lenfld != NULL)
1273
 
    {
1274
 
        u_int32_t len = pbs_offset(pbs);
1275
 
        int i = pbs->lenfld_desc->size;
1276
 
 
1277
 
        if (pbs->lenfld_desc->field_type == ft_lv)
1278
 
            len -= sizeof(struct isakmp_attribute);
1279
 
        DBG(DBG_EMITTING, DBG_log("emitting length of %s: %lu"
1280
 
            , pbs->name, (unsigned long) len));
1281
 
        while (i-- != 0)
1282
 
        {
1283
 
            pbs->lenfld[i] = (u_int8_t)len;
1284
 
            len >>= BITS_PER_BYTE;
1285
 
        }
1286
 
    }
1287
 
    if (pbs->container != NULL)
1288
 
        pbs->container->cur = pbs->cur; /* pass space utilization up */
1289
 
}