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