- nonce payload added
[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)) & ~0x8000;
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->byte_pos += length;
512
513 return SUCCESS;
514 }
515
516 /**
517 * implementation of parser_context_t.parse_payload
518 */
519 static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload)
520 {
521 payload_t *pld;
522 void *output;
523 size_t rule_count, payload_length, spi_size, attribute_length;
524 bool attribute_format;
525 int rule_number;
526 encoding_rule_t *rule;
527
528 this->logger->log(this->logger, CONTROL, "parsing %s payload", mapping_find(payload_type_t_mappings, payload_type));
529
530 /* ok, do the parsing */
531 pld = payload_create(payload_type);
532 if (pld == NULL)
533 {
534 this->logger->log(this->logger, ERROR, " payload %s not supported", mapping_find(payload_type_t_mappings, payload_type));
535 return NOT_SUPPORTED;
536 }
537 /* base pointer for output, avoids casting in every rule */
538 output = pld;
539
540 pld->get_encoding_rules(pld, &(this->rules), &rule_count);
541
542 for (rule_number = 0; rule_number < rule_count; rule_number++)
543 {
544 rule = &(this->rules[rule_number]);
545 this->logger->log(this->logger, CONTROL_MORE, " parsing rule %d %s",
546 rule_number, mapping_find(encoding_type_t_mappings, rule->type));
547 switch (rule->type)
548 {
549 case U_INT_4:
550 {
551 if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS)
552 {
553 pld->destroy(pld);
554 return PARSE_ERROR;
555 }
556 break;
557 }
558 case U_INT_8:
559 {
560 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
561 {
562 pld->destroy(pld);
563 return PARSE_ERROR;
564 }
565 break;
566 }
567 case U_INT_16:
568 {
569 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
570 {
571 pld->destroy(pld);
572 return PARSE_ERROR;
573 }
574 break;
575 }
576 case U_INT_32:
577 {
578 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
579 {
580 pld->destroy(pld);
581 return PARSE_ERROR;
582 }
583 break;
584 }
585 case U_INT_64:
586 {
587 if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS)
588 {
589 pld->destroy(pld);
590 return PARSE_ERROR;
591 }
592 break;
593 }
594 case RESERVED_BIT:
595 {
596 if (this->parse_bit(this, rule_number, NULL) != SUCCESS)
597 {
598 pld->destroy(pld);
599 return PARSE_ERROR;
600 }
601 break;
602 }
603 case RESERVED_BYTE:
604 {
605 if (this->parse_uint8(this, rule_number, NULL) != SUCCESS)
606 {
607 pld->destroy(pld);
608 return PARSE_ERROR;
609 }
610 break;
611 }
612 case FLAG:
613 {
614 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
615 {
616 pld->destroy(pld);
617 return PARSE_ERROR;
618 }
619 break;
620 }
621 case PAYLOAD_LENGTH:
622 {
623 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
624 {
625 pld->destroy(pld);
626 return PARSE_ERROR;
627 }
628 payload_length = *(u_int16_t*)(output + rule->offset);
629 break;
630 }
631 case HEADER_LENGTH:
632 {
633 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
634 {
635 pld->destroy(pld);
636 return PARSE_ERROR;
637 }
638 break;
639 }
640 case SPI_SIZE:
641 {
642 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
643 {
644 pld->destroy(pld);
645 return PARSE_ERROR;
646 }
647 spi_size = *(u_int8_t*)(output + rule->offset);
648 break;
649 }
650 case SPI:
651 {
652 if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS)
653 {
654 pld->destroy(pld);
655 return PARSE_ERROR;
656 }
657 break;
658 }
659 case PROPOSALS:
660 {
661 size_t proposals_length = payload_length - 4;
662 if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS)
663 {
664 pld->destroy(pld);
665 return PARSE_ERROR;
666 }
667 //TODO check if next_payloads are correct?
668 break;
669 }
670 case TRANSFORMS:
671 {
672 size_t transforms_length = payload_length - spi_size - 8;
673 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS)
674 {
675 pld->destroy(pld);
676 return PARSE_ERROR;
677 }
678 //TODO check if we have the desired transforms count
679 break;
680 }
681 case TRANSFORM_ATTRIBUTES:
682 {
683 size_t transform_a_length = payload_length - 8;
684 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS)
685 {
686 pld->destroy(pld);
687 return PARSE_ERROR;
688 }
689 break;
690 }
691 case ATTRIBUTE_FORMAT:
692 {
693 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
694 {
695 pld->destroy(pld);
696 return PARSE_ERROR;
697 }
698 attribute_format = *(bool*)(output + rule->offset);
699 break;
700 }
701 case ATTRIBUTE_TYPE:
702 {
703 if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS)
704 {
705 pld->destroy(pld);
706 return PARSE_ERROR;
707 }
708 attribute_format = *(bool*)(output + rule->offset);
709 break;
710 }
711 case ATTRIBUTE_LENGTH_OR_VALUE:
712 {
713 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
714 {
715 pld->destroy(pld);
716 return PARSE_ERROR;
717 }
718 attribute_length = *(u_int16_t*)(output + rule->offset);
719 break;
720 }
721 case ATTRIBUTE_VALUE:
722 {
723 if (attribute_format == FALSE)
724 {
725 if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS)
726 {
727 pld->destroy(pld);
728 return PARSE_ERROR;
729 }
730 }
731 break;
732 }
733 case NONCE_DATA:
734 {
735 size_t nonce_length = payload_length - 4;
736 if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS)
737 {
738 pld->destroy(pld);
739 return PARSE_ERROR;
740 }
741 break;
742 }
743 default:
744 {
745 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);
746 pld->destroy(pld);
747 return PARSE_ERROR;
748 }
749 }
750 /* process next rulue */
751 rule++;
752 }
753
754 *payload = pld;
755
756 this->logger->log(this->logger, CONTROL, "parsing %s successful", mapping_find(payload_type_t_mappings, payload_type));
757 return SUCCESS;
758 }
759
760 /**
761 * implementation of parser_t.destroy
762 */
763 static status_t destroy(private_parser_t *this)
764 {
765 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
766 allocator_free(this);
767
768 return SUCCESS;
769 }
770
771 /*
772 * see header file
773 */
774 parser_t *parser_create(chunk_t data)
775 {
776 private_parser_t *this = allocator_alloc_thing(private_parser_t);
777
778 if (this == NULL)
779 {
780 return NULL;
781 }
782
783 this->logger = global_logger_manager->create_logger(global_logger_manager, PARSER, NULL);
784 this->logger->enable_level(this->logger, CONTROL|CONTROL_MORE|ERROR|RAW);
785
786
787 if (this->logger == NULL)
788 {
789 allocator_free(this);
790 return NULL;
791 }
792
793 this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload;
794 this->public.destroy = (status_t(*)(parser_t*)) destroy;
795
796
797 this->parse_uint4 = parse_uint4;
798 this->parse_uint8 = parse_uint8;
799 this->parse_uint15 = parse_uint15;
800 this->parse_uint16 = parse_uint16;
801 this->parse_uint32 = parse_uint32;
802 this->parse_uint64 = parse_uint64;
803 this->parse_bit = parse_bit;
804 this->parse_list = parse_list;
805 this->parse_chunk = parse_chunk;
806
807
808 this->input = data.ptr;
809 this->byte_pos = data.ptr;
810 this->bit_pos = 0;
811 this->input_roof = data.ptr + data.len;
812
813 return (parser_t*)this;
814 }
815