- moved hasher_*_t to *_hasher_t
[strongswan.git] / Source / charon / encoding / 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 <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
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 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 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 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 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 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 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 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 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 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 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 * logger 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
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
308
309 return SUCCESS;
310 }
311
312 /**
313 * implementation of private_parser_t.parse_uint15
314 */
315 static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos)
316 {
317 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
318 {
319 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
320 rule_number, mapping_find(encoding_type_m,
321 this->rules[rule_number].type));
322 return PARSE_ERROR;
323 }
324 if (this->bit_pos != 1)
325 {
326 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
327 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
328 this->bit_pos);
329 return PARSE_ERROR;
330 }
331 /* caller interested in result ? */
332 if (output_pos != NULL)
333 {
334 *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000;
335 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
336 }
337 this->byte_pos += 2;
338 this->bit_pos = 0;
339
340
341
342 return SUCCESS;
343 }
344
345 /**
346 * implementation of private_parser_t.parse_uint16
347 */
348 static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos)
349 {
350 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
351 {
352 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
353 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
354 return PARSE_ERROR;
355 }
356 if (this->bit_pos)
357 {
358 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
359 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
360 this->bit_pos);
361 return PARSE_ERROR;
362 }
363 /* caller interested in result ? */
364 if (output_pos != NULL)
365 {
366 *output_pos = ntohs(*((u_int16_t*)this->byte_pos));
367
368 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
369 }
370 this->byte_pos += 2;
371
372
373 return SUCCESS;
374 }
375 /**
376 * implementation of private_parser_t.parse_uint32
377 */
378 static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos)
379 {
380 if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
381 {
382 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
383 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
384 return PARSE_ERROR;
385 }
386 if (this->bit_pos)
387 {
388 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
389 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
390 this->bit_pos);
391 return PARSE_ERROR;
392 }
393 /* caller interested in result ? */
394 if (output_pos != NULL)
395 {
396 *output_pos = ntohl(*((u_int32_t*)this->byte_pos));
397
398 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
399 }
400 this->byte_pos += 4;
401
402
403 return SUCCESS;
404 }
405
406 /**
407 * implementation of private_parser_t.parse_uint64
408 */
409 static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos)
410 {
411 if (this->byte_pos + sizeof(u_int64_t) > this->input_roof)
412 {
413 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
414 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
415 return PARSE_ERROR;
416 }
417 if (this->bit_pos)
418 {
419 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
420 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
421 this->bit_pos);
422 return PARSE_ERROR;
423 }
424 /* caller interested in result ? */
425 if (output_pos != NULL)
426 {
427 /* assuming little endian host order */
428 *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos));
429 *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1));
430
431 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos, 8);
432 }
433 this->byte_pos += 8;
434
435
436
437 return SUCCESS;
438 }
439
440 static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes)
441 {
442 if (this->byte_pos + bytes > this->input_roof)
443 {
444 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
445 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
446 return PARSE_ERROR;
447 }
448 if (this->bit_pos)
449 {
450 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
451 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
452 this->bit_pos);
453 return PARSE_ERROR;
454 }
455
456 /* caller interested in result ? */
457 if (output_pos != NULL)
458 {
459 memcpy(output_pos,this->byte_pos,bytes);
460
461 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos, bytes);
462 }
463 this->byte_pos += bytes;
464
465 return SUCCESS;
466 }
467
468 /**
469 * implementation of private_parser_t.parse_bit
470 */
471 static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos)
472 {
473 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
474 {
475 this->logger->log(this->logger, ERROR, " not enough input to parse rule %d %s",
476 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
477 return PARSE_ERROR;
478 }
479 /* caller interested in result ? */
480 if (output_pos != NULL)
481 {
482 u_int8_t mask;
483 mask = 0x01 << (7 - this->bit_pos);
484 *output_pos = *this->byte_pos & mask;
485
486 if (*output_pos)
487 {
488 /* set to a "clean", comparable true */
489 *output_pos = TRUE;
490 }
491
492 this->logger->log(this->logger, RAW|MOST, " => %d", *output_pos);
493 }
494 this->bit_pos = (this->bit_pos + 1) % 8;
495 if (this->bit_pos == 0)
496 {
497 this->byte_pos++;
498 }
499
500
501 return SUCCESS;
502 }
503
504 /**
505 * implementation of private_parser_t.parse_list
506 */
507 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)
508 {
509 linked_list_t * list = *output_pos;
510
511 if (length < 0)
512 {
513 this->logger->log(this->logger, ERROR, " invalid length for rule %d %s",
514 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
515 return PARSE_ERROR;
516 }
517
518 if (this->bit_pos)
519 {
520 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
521 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
522 return PARSE_ERROR;
523 }
524
525 while (length > 0)
526 {
527 u_int8_t *pos_before = this->byte_pos;
528 payload_t *payload;
529 status_t status;
530 this->logger->log(this->logger, CONTROL|MORE, " %d bytes left, parsing recursivly %s",
531 length, mapping_find(payload_type_m, payload_type));
532 status = this->public.parse_payload((parser_t*)this, payload_type, &payload);
533 if (status != SUCCESS)
534 {
535 this->logger->log(this->logger, ERROR, " parsing of a %s substructure failed",
536 mapping_find(payload_type_m, payload_type));
537 return status;
538 }
539 list->insert_last(list, payload);
540 length -= this->byte_pos - pos_before;
541 }
542 *output_pos = list;
543 return SUCCESS;
544 }
545
546 /**
547 * implementation of private_parser_t.parse_chunk
548 */
549 static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length)
550 {
551 if (this->byte_pos + length > this->input_roof)
552 {
553 this->logger->log(this->logger, ERROR, " not enough input (%d bytes) to parse rule %d %s",
554 length, rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
555 return PARSE_ERROR;
556 }
557 if (this->bit_pos)
558 {
559 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
560 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
561 return PARSE_ERROR;
562 }
563 if (output_pos != NULL)
564 {
565 output_pos->len = length;
566 output_pos->ptr = allocator_alloc(length);
567 if (output_pos->ptr == NULL)
568 {
569 this->logger->log(this->logger, ERROR, " allocation of chunk (%d bytes) failed", length);
570 return OUT_OF_RES;
571 }
572 memcpy(output_pos->ptr, this->byte_pos, length);
573 }
574 this->byte_pos += length;
575 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)output_pos->ptr, length);
576
577 return SUCCESS;
578 }
579
580 /**
581 * implementation of parser_context_t.parse_payload
582 */
583 static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload)
584 {
585 payload_t *pld;
586 void *output;
587 size_t rule_count, payload_length, spi_size, attribute_length;
588 bool attribute_format;
589 int rule_number;
590 encoding_rule_t *rule;
591
592 this->logger->log(this->logger, CONTROL, "parsing %s payload, %d bytes left",
593 mapping_find(payload_type_m, payload_type),
594 this->input_roof-this->byte_pos);
595
596 this->logger->log_bytes(this->logger, RAW, "parsing payload from", this->byte_pos,
597 this->input_roof-this->byte_pos);
598
599 /* ok, do the parsing */
600 pld = payload_create(payload_type);
601 if (pld == NULL)
602 {
603 this->logger->log(this->logger, ERROR, " payload %s not supported", mapping_find(payload_type_m, payload_type));
604 return NOT_SUPPORTED;
605 }
606 /* base pointer for output, avoids casting in every rule */
607 output = pld;
608
609 pld->get_encoding_rules(pld, &(this->rules), &rule_count);
610
611 for (rule_number = 0; rule_number < rule_count; rule_number++)
612 {
613 rule = &(this->rules[rule_number]);
614 this->logger->log(this->logger, CONTROL|MORE, " parsing rule %d %s",
615 rule_number, mapping_find(encoding_type_m, rule->type));
616 switch (rule->type)
617 {
618 case U_INT_4:
619 {
620 if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS)
621 {
622 pld->destroy(pld);
623 return PARSE_ERROR;
624 }
625 break;
626 }
627 case U_INT_8:
628 {
629 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
630 {
631 pld->destroy(pld);
632 return PARSE_ERROR;
633 }
634 break;
635 }
636 case U_INT_16:
637 {
638 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
639 {
640 pld->destroy(pld);
641 return PARSE_ERROR;
642 }
643 break;
644 }
645 case U_INT_32:
646 {
647 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
648 {
649 pld->destroy(pld);
650 return PARSE_ERROR;
651 }
652 break;
653 }
654 case U_INT_64:
655 {
656 if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS)
657 {
658 pld->destroy(pld);
659 return PARSE_ERROR;
660 }
661 break;
662 }
663 case IKE_SPI:
664 {
665 if (this->parse_bytes(this, rule_number, output + rule->offset,8) != SUCCESS)
666 {
667 pld->destroy(pld);
668 return PARSE_ERROR;
669 }
670 break;
671 }
672 case RESERVED_BIT:
673 {
674 if (this->parse_bit(this, rule_number, NULL) != SUCCESS)
675 {
676 pld->destroy(pld);
677 return PARSE_ERROR;
678 }
679 break;
680 }
681 case RESERVED_BYTE:
682 {
683 if (this->parse_uint8(this, rule_number, NULL) != SUCCESS)
684 {
685 pld->destroy(pld);
686 return PARSE_ERROR;
687 }
688 break;
689 }
690 case FLAG:
691 {
692 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
693 {
694 pld->destroy(pld);
695 return PARSE_ERROR;
696 }
697 break;
698 }
699 case PAYLOAD_LENGTH:
700 {
701 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
702 {
703 pld->destroy(pld);
704 return PARSE_ERROR;
705 }
706 payload_length = *(u_int16_t*)(output + rule->offset);
707 break;
708 }
709 case HEADER_LENGTH:
710 {
711 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
712 {
713 pld->destroy(pld);
714 return PARSE_ERROR;
715 }
716 break;
717 }
718 case SPI_SIZE:
719 {
720 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
721 {
722 pld->destroy(pld);
723 return PARSE_ERROR;
724 }
725 spi_size = *(u_int8_t*)(output + rule->offset);
726 break;
727 }
728 case SPI:
729 {
730 if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS)
731 {
732 pld->destroy(pld);
733 return PARSE_ERROR;
734 }
735 break;
736 }
737 case PROPOSALS:
738 {
739 size_t proposals_length = payload_length - SA_PAYLOAD_HEADER_LENGTH;
740 if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS)
741 {
742 pld->destroy(pld);
743 return PARSE_ERROR;
744 }
745 break;
746 }
747 case TRANSFORMS:
748 {
749 size_t transforms_length = payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
750 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS)
751 {
752 pld->destroy(pld);
753 return PARSE_ERROR;
754 }
755 break;
756 }
757 case TRANSFORM_ATTRIBUTES:
758 {
759 size_t transform_a_length = payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
760 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS)
761 {
762 pld->destroy(pld);
763 return PARSE_ERROR;
764 }
765 break;
766 }
767 case ATTRIBUTE_FORMAT:
768 {
769 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
770 {
771 pld->destroy(pld);
772 return PARSE_ERROR;
773 }
774 attribute_format = *(bool*)(output + rule->offset);
775 break;
776 }
777 case ATTRIBUTE_TYPE:
778 {
779 if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS)
780 {
781 pld->destroy(pld);
782 return PARSE_ERROR;
783 }
784 attribute_format = *(bool*)(output + rule->offset);
785 break;
786 }
787 case ATTRIBUTE_LENGTH_OR_VALUE:
788 {
789 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
790 {
791 pld->destroy(pld);
792 return PARSE_ERROR;
793 }
794 attribute_length = *(u_int16_t*)(output + rule->offset);
795 break;
796 }
797 case ATTRIBUTE_VALUE:
798 {
799 if (attribute_format == FALSE)
800 {
801 if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS)
802 {
803 pld->destroy(pld);
804 return PARSE_ERROR;
805 }
806 }
807 break;
808 }
809 case NONCE_DATA:
810 {
811 size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH;
812 if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS)
813 {
814 pld->destroy(pld);
815 return PARSE_ERROR;
816 }
817 break;
818 }
819 case KEY_EXCHANGE_DATA:
820 {
821 size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH;
822 if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS)
823 {
824 pld->destroy(pld);
825 return PARSE_ERROR;
826 }
827 break;
828 }
829 case NOTIFICATION_DATA:
830 {
831 size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size;
832 if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS)
833 {
834 pld->destroy(pld);
835 return PARSE_ERROR;
836 }
837 break;
838 }
839 default:
840 {
841 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);
842 pld->destroy(pld);
843 return PARSE_ERROR;
844 }
845 }
846 /* process next rulue */
847 rule++;
848 }
849
850 *payload = pld;
851
852 return SUCCESS;
853 }
854
855 /**
856 * implementation of parser_t.reset_context
857 */
858 static status_t reset_context (private_parser_t *this)
859 {
860 this->byte_pos = this->input;
861 this->bit_pos = 0;
862 return SUCCESS;
863 }
864
865 /**
866 * implementation of parser_t.destroy
867 */
868 static status_t destroy(private_parser_t *this)
869 {
870 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
871 allocator_free(this);
872
873 return SUCCESS;
874 }
875
876 /*
877 * see header file
878 */
879 parser_t *parser_create(chunk_t data)
880 {
881 private_parser_t *this = allocator_alloc_thing(private_parser_t);
882
883 if (this == NULL)
884 {
885 return NULL;
886 }
887
888 this->logger = global_logger_manager->create_logger(global_logger_manager, PARSER, NULL);
889
890
891 if (this->logger == NULL)
892 {
893 global_logger_manager->destroy_logger(global_logger_manager, this->logger);
894 allocator_free(this);
895 return NULL;
896 }
897
898 this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload;
899 this->public.reset_context = (status_t(*)(parser_t*)) reset_context;
900 this->public.destroy = (status_t(*)(parser_t*)) destroy;
901
902
903 this->parse_uint4 = parse_uint4;
904 this->parse_uint8 = parse_uint8;
905 this->parse_uint15 = parse_uint15;
906 this->parse_uint16 = parse_uint16;
907 this->parse_uint32 = parse_uint32;
908 this->parse_uint64 = parse_uint64;
909 this->parse_bytes = parse_bytes;
910 this->parse_bit = parse_bit;
911 this->parse_list = parse_list;
912 this->parse_chunk = parse_chunk;
913
914 this->input = data.ptr;
915 this->byte_pos = data.ptr;
916 this->bit_pos = 0;
917 this->input_roof = data.ptr + data.len;
918
919 return (parser_t*)this;
920 }
921