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