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