- added and tested id_payload_t
[strongswan.git] / Source / charon / encoding / parser.c
1 /**
2 * @file parser.c
3 *
4 * @brief Implementation of parser_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <stdlib.h>
24 #include <arpa/inet.h>
25
26 #include "parser.h"
27
28 #include <types.h>
29 #include <definitions.h>
30 #include <globals.h>
31 #include <utils/allocator.h>
32 #include <utils/logger.h>
33 #include <utils/linked_list.h>
34 #include <encoding/payloads/encodings.h>
35 #include <encoding/payloads/payload.h>
36 #include <encoding/payloads/sa_payload.h>
37 #include <encoding/payloads/proposal_substructure.h>
38 #include <encoding/payloads/transform_substructure.h>
39 #include <encoding/payloads/transform_attribute.h>
40 #include <encoding/payloads/ke_payload.h>
41 #include <encoding/payloads/nonce_payload.h>
42 #include <encoding/payloads/id_payload.h>
43 #include <encoding/payloads/notify_payload.h>
44 #include <encoding/payloads/encryption_payload.h>
45
46
47
48 typedef struct private_parser_t private_parser_t;
49
50 /**
51 * Private data stored in a context.
52 *
53 * Contains pointers and counters to store current state.
54 */
55 struct private_parser_t {
56 /**
57 * Public members, see parser_t.
58 */
59 parser_t public;
60
61 /**
62 * @brief Parse a 4-Bit unsigned integer from the current parsing position.
63 *
64 * @param this parser_t object
65 * @param rule_number number of current rule
66 * @param[out] output_pos pointer where to write the parsed result
67 * @return
68 * - SUCCESS or
69 * - PARSE_ERROR when not successful
70 */
71 status_t (*parse_uint4) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
72
73 /**
74 * @brief Parse a 8-Bit unsigned integer from the current parsing position.
75 *
76 * @param this parser_t object
77 * @param rule_number number of current rule
78 * @param[out] output_pos pointer where to write the parsed result
79 * @return
80 * - SUCCESS or
81 * - PARSE_ERROR when not successful
82 */
83 status_t (*parse_uint8) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
84
85 /**
86 * @brief Parse a 15-Bit unsigned integer from the current parsing position.
87 *
88 * This is a special case used for ATTRIBUTE_TYPE.
89 * Big-/Little-endian conversion is done here.
90 *
91 * @param this parser_t object
92 * @param rule_number number of current rule
93 * @param[out] output_pos pointer where to write the parsed result
94 * @return
95 * - SUCCESS or
96 * - PARSE_ERROR when not successful
97 */
98 status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
99
100 /**
101 * @brief Parse a 16-Bit unsigned integer from the current parsing position.
102 *
103 * Big-/Little-endian conversion is done here.
104 *
105 * @param this parser_t object
106 * @param rule_number number of current rule
107 * @param[out] output_pos pointer where to write the parsed result
108 * @return
109 * - SUCCESS or
110 * - PARSE_ERROR when not successful
111 */
112 status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
113
114 /**
115 * @brief Parse a 32-Bit unsigned integer from the current parsing position.
116 *
117 * Big-/Little-endian conversion is done here.
118 *
119 * @param this parser_t object
120 * @param rule_number number of current rule
121 * @param[out] output_pos pointer where to write the parsed result
122 * @return
123 * - SUCCESS or
124 * - PARSE_ERROR when not successful
125 */
126 status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos);
127
128 /**
129 * @brief Parse a 64-Bit unsigned integer from the current parsing position.
130 *
131 * @todo add support for big-endian machines.
132 *
133 * @param this parser_t object
134 * @param rule_number number of current rule
135 * @param[out] output_pos pointer where to write the parsed result
136 * @return
137 * - SUCCESS or
138 * - PARSE_ERROR when not successful
139 */
140 status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos);
141
142 /**
143 * @brief Parse a given amount of bytes and writes them to a specific location
144 *
145 * @param this parser_t object
146 * @param rule_number number of current rule
147 * @param[out] output_pos pointer where to write the parsed result
148 * @param bytes number of bytes to parse
149 * @return
150 * - SUCCESS or
151 * - PARSE_ERROR when not successful
152 */
153 status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes);
154
155 /**
156 * @brief Parse a single Bit from the current parsing position
157 *
158 * @param this parser_t object
159 * @param rule_number number of current rule
160 * @param[out] output_pos pointer where to write the parsed result
161 * @return
162 * - SUCCESS or
163 * - PARSE_ERROR when not successful
164 */
165 status_t (*parse_bit) (private_parser_t *this, int rule_number, bool *output_pos);
166
167 /**
168 * @brief Parse substructures in a list
169 *
170 * This function calls the parser recursivly to parse contained substructures
171 * in a linked_list_t. The list must already be created. Payload defines
172 * the type of the substructures. parsing is continued until the specified length
173 * is completely parsed.
174 *
175 * @param this parser_t object
176 * @param rule_number number of current rule
177 * @param[out] output_pos pointer of a linked_list where substructures are added
178 * @param payload_type type of the contained substructures to parse
179 * @param length number of bytes to parse in this list
180 * @return
181 * - SUCCESS or
182 * - PARSE_ERROR when not successful
183 */
184 status_t (*parse_list) (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length);
185
186 /**
187 * @brief Parse data from current parsing position in a chunk.
188 *
189 * This function clones length number of bytes to output_pos, without
190 * modifiyng them. Space will be allocated and must be freed by caller.
191 *
192 * @param this parser_t object
193 * @param rule_number number of current rule
194 * @param[out] output_pos pointer of a chunk which will point to the allocated data
195 * @param length number of bytes to clone
196 * @return
197 * - SUCCESS or
198 * - PARSE_ERROR when not successful
199 */
200 status_t (*parse_chunk) (private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length);
201
202 /**
203 * Current bit for reading in input data.
204 */
205 u_int8_t bit_pos;
206
207 /**
208 * Current byte for reading in input data.
209 */
210 u_int8_t *byte_pos;
211
212 /**
213 * Input data to parse.
214 */
215 u_int8_t *input;
216
217 /**
218 * Roof of input, used for length-checking.
219 */
220 u_int8_t *input_roof;
221
222 /**
223 * Set of encoding rules for this parsing session.
224 */
225 encoding_rule_t *rules;
226
227 /**
228 * Assigned logger_t object.
229 */
230 logger_t *logger;
231 };
232
233 /**
234 * Implementation of private_parser_t.parse_uint4.
235 */
236 static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *output_pos)
237 {
238 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
239 {
240 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
241 rule_number, mapping_find(encoding_type_m,
242 this->rules[rule_number].type));
243 return PARSE_ERROR;
244 }
245 switch (this->bit_pos)
246 {
247 case 0:
248 /* caller interested in result ? */
249 if (output_pos != NULL)
250 {
251 *output_pos = *(this->byte_pos) >> 4;
252 }
253 this->bit_pos = 4;
254 break;
255 case 4:
256 /* caller interested in result ? */
257 if (output_pos != NULL)
258 {
259 *output_pos = *(this->byte_pos) & 0x0F;
260 }
261 this->bit_pos = 0;
262 this->byte_pos++;
263 break;
264 default:
265 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
266 rule_number, mapping_find(encoding_type_m,
267 this->rules[rule_number].type), this->bit_pos);
268 return PARSE_ERROR;
269 }
270
271 if (output_pos != NULL)
272 {
273 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
274 }
275
276 return SUCCESS;
277 }
278
279 /**
280 * Implementation of private_parser_t.parse_uint8.
281 */
282 static status_t parse_uint8(private_parser_t *this, int rule_number, u_int8_t *output_pos)
283 {
284 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
285 {
286 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
287 rule_number, mapping_find(encoding_type_m,
288 this->rules[rule_number].type));
289 return PARSE_ERROR;
290 }
291 if (this->bit_pos)
292 {
293 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
294 rule_number, mapping_find(encoding_type_m,
295 this->rules[rule_number].type), this->bit_pos);
296 return PARSE_ERROR;
297 }
298
299 /* caller interested in result ? */
300 if (output_pos != NULL)
301 {
302 *output_pos = *(this->byte_pos);
303 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
304 }
305 this->byte_pos++;
306
307 return SUCCESS;
308 }
309
310 /**
311 * Implementation of private_parser_t.parse_uint15.
312 */
313 static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos)
314 {
315 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
316 {
317 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
318 rule_number, mapping_find(encoding_type_m,
319 this->rules[rule_number].type));
320 return PARSE_ERROR;
321 }
322 if (this->bit_pos != 1)
323 {
324 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
325 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
326 this->bit_pos);
327 return PARSE_ERROR;
328 }
329 /* caller interested in result ? */
330 if (output_pos != NULL)
331 {
332 *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000;
333 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
334 }
335 this->byte_pos += 2;
336 this->bit_pos = 0;
337
338 return SUCCESS;
339 }
340
341 /**
342 * Implementation of private_parser_t.parse_uint16.
343 */
344 static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos)
345 {
346 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
347 {
348 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
349 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
350 return PARSE_ERROR;
351 }
352 if (this->bit_pos)
353 {
354 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
355 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
356 this->bit_pos);
357 return PARSE_ERROR;
358 }
359 /* caller interested in result ? */
360 if (output_pos != NULL)
361 {
362 *output_pos = ntohs(*((u_int16_t*)this->byte_pos));
363
364 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
365 }
366 this->byte_pos += 2;
367
368 return SUCCESS;
369 }
370 /**
371 * Implementation of private_parser_t.parse_uint32.
372 */
373 static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos)
374 {
375 if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
376 {
377 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
378 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
379 return PARSE_ERROR;
380 }
381 if (this->bit_pos)
382 {
383 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
384 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
385 this->bit_pos);
386 return PARSE_ERROR;
387 }
388 /* caller interested in result ? */
389 if (output_pos != NULL)
390 {
391 *output_pos = ntohl(*((u_int32_t*)this->byte_pos));
392
393 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
394 }
395 this->byte_pos += 4;
396
397 return SUCCESS;
398 }
399
400 /**
401 * Implementation of private_parser_t.parse_uint64.
402 */
403 static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos)
404 {
405 if (this->byte_pos + sizeof(u_int64_t) > this->input_roof)
406 {
407 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
408 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
409 return PARSE_ERROR;
410 }
411 if (this->bit_pos)
412 {
413 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
414 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
415 this->bit_pos);
416 return PARSE_ERROR;
417 }
418 /* caller interested in result ? */
419 if (output_pos != NULL)
420 {
421 /* assuming little endian host order */
422 *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos));
423 *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1));
424
425 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos, 8);
426 }
427 this->byte_pos += 8;
428
429 return SUCCESS;
430 }
431
432 /**
433 * Implementation of private_parser_t.parse_bytes.
434 */
435 static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes)
436 {
437 if (this->byte_pos + bytes > this->input_roof)
438 {
439 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
440 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
441 return PARSE_ERROR;
442 }
443 if (this->bit_pos)
444 {
445 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
446 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
447 this->bit_pos);
448 return PARSE_ERROR;
449 }
450
451 /* caller interested in result ? */
452 if (output_pos != NULL)
453 {
454 memcpy(output_pos,this->byte_pos,bytes);
455
456 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos, bytes);
457 }
458 this->byte_pos += bytes;
459
460 return SUCCESS;
461 }
462
463 /**
464 * Implementation of private_parser_t.parse_bit.
465 */
466 static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos)
467 {
468 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
469 {
470 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
471 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
472 return PARSE_ERROR;
473 }
474 /* caller interested in result ? */
475 if (output_pos != NULL)
476 {
477 u_int8_t mask;
478 mask = 0x01 << (7 - this->bit_pos);
479 *output_pos = *this->byte_pos & mask;
480
481 if (*output_pos)
482 {
483 /* set to a "clean", comparable true */
484 *output_pos = TRUE;
485 }
486
487 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
488 }
489 this->bit_pos = (this->bit_pos + 1) % 8;
490 if (this->bit_pos == 0)
491 {
492 this->byte_pos++;
493 }
494
495 return SUCCESS;
496 }
497
498 /**
499 * Implementation of private_parser_t.parse_list.
500 */
501 static status_t parse_list(private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_type, size_t length)
502 {
503 linked_list_t * list = *output_pos;
504
505 if (length < 0)
506 {
507 this->logger->log(this->logger, ERROR, " invalid length for rule %d %s",
508 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
509 return PARSE_ERROR;
510 }
511
512 if (this->bit_pos)
513 {
514 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
515 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
516 return PARSE_ERROR;
517 }
518
519 while (length > 0)
520 {
521 u_int8_t *pos_before = this->byte_pos;
522 payload_t *payload;
523 status_t status;
524 this->logger->log(this->logger, CONTROL|MORE, " %d bytes left, parsing recursivly %s",
525 length, mapping_find(payload_type_m, payload_type));
526 status = this->public.parse_payload((parser_t*)this, payload_type, &payload);
527 if (status != SUCCESS)
528 {
529 this->logger->log(this->logger, ERROR, " parsing of a %s substructure failed",
530 mapping_find(payload_type_m, payload_type));
531 return status;
532 }
533 list->insert_last(list, payload);
534 length -= this->byte_pos - pos_before;
535 }
536 *output_pos = list;
537 return SUCCESS;
538 }
539
540 /**
541 * Implementation of private_parser_t.parse_chunk.
542 */
543 static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length)
544 {
545 if (this->byte_pos + length > this->input_roof)
546 {
547 this->logger->log(this->logger, ERROR, " not enough input (%d bytes) to parse rule %d %s",
548 length, rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
549 return PARSE_ERROR;
550 }
551 if (this->bit_pos)
552 {
553 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
554 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
555 return PARSE_ERROR;
556 }
557 if (output_pos != NULL)
558 {
559 output_pos->len = length;
560 output_pos->ptr = allocator_alloc(length);
561 memcpy(output_pos->ptr, this->byte_pos, length);
562 }
563 this->byte_pos += length;
564 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos->ptr, length);
565
566 return SUCCESS;
567 }
568
569 /**
570 * Implementation of parser_t.parse_payload.
571 */
572 static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload)
573 {
574 payload_t *pld;
575 void *output;
576 size_t rule_count, payload_length, spi_size, attribute_length;
577 bool attribute_format;
578 int rule_number;
579 encoding_rule_t *rule;
580
581 this->logger->log(this->logger, CONTROL, "parsing %s payload, %d bytes left",
582 mapping_find(payload_type_m, payload_type),
583 this->input_roof-this->byte_pos);
584
585 this->logger->log_bytes(this->logger, RAW, "parsing payload from", this->byte_pos,
586 this->input_roof-this->byte_pos);
587
588 /* ok, do the parsing */
589 pld = payload_create(payload_type);
590 if (pld == NULL)
591 {
592 this->logger->log(this->logger, ERROR, " payload %s not supported", mapping_find(payload_type_m, payload_type));
593 return NOT_SUPPORTED;
594 }
595 /* base pointer for output, avoids casting in every rule */
596 output = pld;
597
598 pld->get_encoding_rules(pld, &(this->rules), &rule_count);
599
600 for (rule_number = 0; rule_number < rule_count; rule_number++)
601 {
602 rule = &(this->rules[rule_number]);
603 this->logger->log(this->logger, CONTROL|MORE, " parsing rule %d %s",
604 rule_number, mapping_find(encoding_type_m, rule->type));
605 switch (rule->type)
606 {
607 case U_INT_4:
608 {
609 if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS)
610 {
611 pld->destroy(pld);
612 return PARSE_ERROR;
613 }
614 break;
615 }
616 case U_INT_8:
617 {
618 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
619 {
620 pld->destroy(pld);
621 return PARSE_ERROR;
622 }
623 break;
624 }
625 case U_INT_16:
626 {
627 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
628 {
629 pld->destroy(pld);
630 return PARSE_ERROR;
631 }
632 break;
633 }
634 case U_INT_32:
635 {
636 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
637 {
638 pld->destroy(pld);
639 return PARSE_ERROR;
640 }
641 break;
642 }
643 case U_INT_64:
644 {
645 if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS)
646 {
647 pld->destroy(pld);
648 return PARSE_ERROR;
649 }
650 break;
651 }
652 case IKE_SPI:
653 {
654 if (this->parse_bytes(this, rule_number, output + rule->offset,8) != SUCCESS)
655 {
656 pld->destroy(pld);
657 return PARSE_ERROR;
658 }
659 break;
660 }
661 case RESERVED_BIT:
662 {
663 if (this->parse_bit(this, rule_number, NULL) != SUCCESS)
664 {
665 pld->destroy(pld);
666 return PARSE_ERROR;
667 }
668 break;
669 }
670 case RESERVED_BYTE:
671 {
672 if (this->parse_uint8(this, rule_number, NULL) != SUCCESS)
673 {
674 pld->destroy(pld);
675 return PARSE_ERROR;
676 }
677 break;
678 }
679 case FLAG:
680 {
681 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
682 {
683 pld->destroy(pld);
684 return PARSE_ERROR;
685 }
686 break;
687 }
688 case PAYLOAD_LENGTH:
689 {
690 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
691 {
692 pld->destroy(pld);
693 return PARSE_ERROR;
694 }
695 payload_length = *(u_int16_t*)(output + rule->offset);
696 break;
697 }
698 case HEADER_LENGTH:
699 {
700 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
701 {
702 pld->destroy(pld);
703 return PARSE_ERROR;
704 }
705 break;
706 }
707 case SPI_SIZE:
708 {
709 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
710 {
711 pld->destroy(pld);
712 return PARSE_ERROR;
713 }
714 spi_size = *(u_int8_t*)(output + rule->offset);
715 break;
716 }
717 case SPI:
718 {
719 if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS)
720 {
721 pld->destroy(pld);
722 return PARSE_ERROR;
723 }
724 break;
725 }
726 case PROPOSALS:
727 {
728 size_t proposals_length = payload_length - SA_PAYLOAD_HEADER_LENGTH;
729 if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS)
730 {
731 pld->destroy(pld);
732 return PARSE_ERROR;
733 }
734 break;
735 }
736 case TRANSFORMS:
737 {
738 size_t transforms_length = payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
739 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS)
740 {
741 pld->destroy(pld);
742 return PARSE_ERROR;
743 }
744 break;
745 }
746 case TRANSFORM_ATTRIBUTES:
747 {
748 size_t transform_a_length = payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
749 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS)
750 {
751 pld->destroy(pld);
752 return PARSE_ERROR;
753 }
754 break;
755 }
756 case ATTRIBUTE_FORMAT:
757 {
758 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
759 {
760 pld->destroy(pld);
761 return PARSE_ERROR;
762 }
763 attribute_format = *(bool*)(output + rule->offset);
764 break;
765 }
766 case ATTRIBUTE_TYPE:
767 {
768 if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS)
769 {
770 pld->destroy(pld);
771 return PARSE_ERROR;
772 }
773 attribute_format = *(bool*)(output + rule->offset);
774 break;
775 }
776 case ATTRIBUTE_LENGTH_OR_VALUE:
777 {
778 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
779 {
780 pld->destroy(pld);
781 return PARSE_ERROR;
782 }
783 attribute_length = *(u_int16_t*)(output + rule->offset);
784 break;
785 }
786 case ATTRIBUTE_VALUE:
787 {
788 if (attribute_format == FALSE)
789 {
790 if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS)
791 {
792 pld->destroy(pld);
793 return PARSE_ERROR;
794 }
795 }
796 break;
797 }
798 case NONCE_DATA:
799 {
800 size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH;
801 if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS)
802 {
803 pld->destroy(pld);
804 return PARSE_ERROR;
805 }
806 break;
807 }
808 case ID_DATA:
809 {
810 size_t data_length = payload_length - ID_PAYLOAD_HEADER_LENGTH;
811 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
812 {
813 pld->destroy(pld);
814 return PARSE_ERROR;
815 }
816 break;
817 }
818 case KEY_EXCHANGE_DATA:
819 {
820 size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH;
821 if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS)
822 {
823 pld->destroy(pld);
824 return PARSE_ERROR;
825 }
826 break;
827 }
828 case NOTIFICATION_DATA:
829 {
830 size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size;
831 if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS)
832 {
833 pld->destroy(pld);
834 return PARSE_ERROR;
835 }
836 break;
837 }
838 case ENCRYPTED_DATA:
839 {
840 size_t data_length = payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH ;
841 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
842 {
843 pld->destroy(pld);
844 return PARSE_ERROR;
845 }
846 break;
847 }
848 default:
849 {
850 this->logger->log(this->logger, ERROR, " no rule to parse rule %d %s (%d)", rule_number, mapping_find(encoding_type_m, rule->type), rule->type);
851 pld->destroy(pld);
852 return PARSE_ERROR;
853 }
854 }
855 /* process next rulue */
856 rule++;
857 }
858
859 *payload = pld;
860
861 return SUCCESS;
862 }
863
864 /**
865 * Implementation of parser_t.reset_context.
866 */
867 static void reset_context (private_parser_t *this)
868 {
869 this->byte_pos = this->input;
870 this->bit_pos = 0;
871 }
872
873 /**
874 * Implementation of parser_t.destroy.
875 */
876 static void destroy(private_parser_t *this)
877 {
878 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
879 allocator_free(this);
880 }
881
882 /*
883 * Described in header.
884 */
885 parser_t *parser_create(chunk_t data)
886 {
887 private_parser_t *this = allocator_alloc_thing(private_parser_t);
888
889 this->logger = global_logger_manager->create_logger(global_logger_manager, PARSER, NULL);
890
891 this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload;
892 this->public.reset_context = (void(*)(parser_t*)) reset_context;
893 this->public.destroy = (void(*)(parser_t*)) destroy;
894
895
896 this->parse_uint4 = parse_uint4;
897 this->parse_uint8 = parse_uint8;
898 this->parse_uint15 = parse_uint15;
899 this->parse_uint16 = parse_uint16;
900 this->parse_uint32 = parse_uint32;
901 this->parse_uint64 = parse_uint64;
902 this->parse_bytes = parse_bytes;
903 this->parse_bit = parse_bit;
904 this->parse_list = parse_list;
905 this->parse_chunk = parse_chunk;
906
907 this->input = data.ptr;
908 this->byte_pos = data.ptr;
909 this->bit_pos = 0;
910 this->input_roof = data.ptr + data.len;
911
912 return (parser_t*)this;
913 }
914