do not access unaligned words/half-words directly
[strongswan.git] / src / charon / encoding / parser.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdlib.h>
18 #include <arpa/inet.h>
19 #include <string.h>
20
21 #include "parser.h"
22
23 #include <library.h>
24 #include <daemon.h>
25 #include <utils/linked_list.h>
26 #include <encoding/payloads/encodings.h>
27 #include <encoding/payloads/payload.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/proposal_substructure.h>
30 #include <encoding/payloads/transform_substructure.h>
31 #include <encoding/payloads/transform_attribute.h>
32 #include <encoding/payloads/ke_payload.h>
33 #include <encoding/payloads/nonce_payload.h>
34 #include <encoding/payloads/id_payload.h>
35 #include <encoding/payloads/notify_payload.h>
36 #include <encoding/payloads/encryption_payload.h>
37 #include <encoding/payloads/auth_payload.h>
38 #include <encoding/payloads/cert_payload.h>
39 #include <encoding/payloads/certreq_payload.h>
40 #include <encoding/payloads/ts_payload.h>
41 #include <encoding/payloads/delete_payload.h>
42 #include <encoding/payloads/vendor_id_payload.h>
43 #include <encoding/payloads/cp_payload.h>
44 #include <encoding/payloads/configuration_attribute.h>
45 #include <encoding/payloads/eap_payload.h>
46 #include <encoding/payloads/unknown_payload.h>
47
48
49 typedef struct private_parser_t private_parser_t;
50
51 /**
52 * Private data stored in a context.
53 *
54 * Contains pointers and counters to store current state.
55 */
56 struct private_parser_t {
57 /**
58 * Public members, see parser_t.
59 */
60 parser_t public;
61
62 /**
63 * Current bit for reading in input data.
64 */
65 u_int8_t bit_pos;
66
67 /**
68 * Current byte for reading in input data.
69 */
70 u_int8_t *byte_pos;
71
72 /**
73 * Input data to parse.
74 */
75 u_int8_t *input;
76
77 /**
78 * Roof of input, used for length-checking.
79 */
80 u_int8_t *input_roof;
81
82 /**
83 * Set of encoding rules for this parsing session.
84 */
85 encoding_rule_t *rules;
86 };
87
88 /**
89 * Forward declaration
90 */
91 static status_t parse_payload(private_parser_t *this,
92 payload_type_t payload_type, payload_t **payload);
93
94 /**
95 * Log invalid length error
96 */
97 static bool short_input(private_parser_t *this, int number)
98 {
99 DBG1(DBG_ENC, " not enough input to parse rule %d %N",
100 number, encoding_type_names, this->rules[number].type);
101 return FALSE;
102 }
103
104 /**
105 * Log unaligned rules
106 */
107 static bool bad_bitpos(private_parser_t *this, int number)
108 {
109 DBG1(DBG_ENC, " found rule %d %N on bitpos %d",
110 number, encoding_type_names, this->rules[number].type, this->bit_pos);
111 return FALSE;
112 }
113
114 /**
115 * Parse a 4-Bit unsigned integer from the current parsing position.
116 */
117 static bool parse_uint4(private_parser_t *this, int rule_number,
118 u_int8_t *output_pos)
119 {
120 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
121 {
122 return short_input(this, rule_number);
123 }
124 switch (this->bit_pos)
125 {
126 case 0:
127 if (output_pos)
128 {
129 *output_pos = *(this->byte_pos) >> 4;
130 }
131 this->bit_pos = 4;
132 break;
133 case 4:
134 if (output_pos)
135 {
136 *output_pos = *(this->byte_pos) & 0x0F;
137 }
138 this->bit_pos = 0;
139 this->byte_pos++;
140 break;
141 default:
142 return bad_bitpos(this, rule_number);
143 }
144 if (output_pos)
145 {
146 DBG3(DBG_ENC, " => %d", *output_pos);
147 }
148 return TRUE;
149 }
150
151 /**
152 * Parse a 8-Bit unsigned integer from the current parsing position.
153 */
154 static bool parse_uint8(private_parser_t *this, int rule_number,
155 u_int8_t *output_pos)
156 {
157 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
158 {
159 return short_input(this, rule_number);
160 }
161 if (this->bit_pos)
162 {
163 return bad_bitpos(this, rule_number);
164 }
165 if (output_pos)
166 {
167 *output_pos = *(this->byte_pos);
168 DBG3(DBG_ENC, " => %d", *output_pos);
169 }
170 this->byte_pos++;
171 return TRUE;
172 }
173
174 /**
175 * Parse a 15-Bit unsigned integer from the current parsing position.
176 */
177 static bool parse_uint15(private_parser_t *this, int rule_number,
178 u_int16_t *output_pos)
179 {
180 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
181 {
182 return short_input(this, rule_number);
183 }
184 if (this->bit_pos != 1)
185 {
186 return bad_bitpos(this, rule_number);
187 }
188 if (output_pos)
189 {
190 memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
191 *output_pos = ntohs(*output_pos) & ~0x8000;
192 DBG3(DBG_ENC, " => %d", *output_pos);
193 }
194 this->byte_pos += sizeof(u_int16_t);
195 this->bit_pos = 0;
196 return TRUE;
197 }
198
199 /**
200 * Parse a 16-Bit unsigned integer from the current parsing position.
201 */
202 static bool parse_uint16(private_parser_t *this, int rule_number,
203 u_int16_t *output_pos)
204 {
205 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
206 {
207 return short_input(this, rule_number);
208 }
209 if (this->bit_pos)
210 {
211 return bad_bitpos(this, rule_number);
212 }
213 if (output_pos)
214 {
215 memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
216 *output_pos = ntohs(*output_pos);
217 DBG3(DBG_ENC, " => %d", *output_pos);
218 }
219 this->byte_pos += sizeof(u_int16_t);
220 return TRUE;
221 }
222 /**
223 * Parse a 32-Bit unsigned integer from the current parsing position.
224 */
225 static bool parse_uint32(private_parser_t *this, int rule_number,
226 u_int32_t *output_pos)
227 {
228 if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
229 {
230 return short_input(this, rule_number);
231 }
232 if (this->bit_pos)
233 {
234 return bad_bitpos(this, rule_number);
235 }
236 if (output_pos)
237 {
238 memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
239 *output_pos = ntohl(*output_pos);
240 DBG3(DBG_ENC, " => %d", *output_pos);
241 }
242 this->byte_pos += sizeof(u_int32_t);
243 return TRUE;
244 }
245
246 /**
247 * Parse a 64-Bit unsigned integer from the current parsing position.
248 */
249 static bool parse_uint64(private_parser_t *this, int rule_number,
250 u_int64_t *output_pos)
251 {
252 if (this->byte_pos + sizeof(u_int64_t) > this->input_roof)
253 {
254 return short_input(this, rule_number);
255 }
256 if (this->bit_pos)
257 {
258 return bad_bitpos(this, rule_number);
259 }
260 if (output_pos)
261 {
262 /* assuming little endian host order */
263 *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos));
264 *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1));
265 DBG3(DBG_ENC, " => %b", output_pos, sizeof(u_int64_t));
266 }
267 this->byte_pos += sizeof(u_int64_t);
268 return TRUE;
269 }
270
271 /**
272 * Parse a given amount of bytes and writes them to a specific location
273 */
274 static bool parse_bytes(private_parser_t *this, int rule_number,
275 u_int8_t *output_pos, size_t bytes)
276 {
277 if (this->byte_pos + bytes > this->input_roof)
278 {
279 return short_input(this, rule_number);
280 }
281 if (this->bit_pos)
282 {
283 return bad_bitpos(this, rule_number);
284 }
285 if (output_pos)
286 {
287 memcpy(output_pos, this->byte_pos, bytes);
288 DBG3(DBG_ENC, " => %b", output_pos, bytes);
289 }
290 this->byte_pos += bytes;
291 return TRUE;
292 }
293
294 /**
295 * Parse a single Bit from the current parsing position
296 */
297 static bool parse_bit(private_parser_t *this, int rule_number,
298 bool *output_pos)
299 {
300 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
301 {
302 return short_input(this, rule_number);
303 }
304 if (output_pos)
305 {
306 u_int8_t mask;
307 mask = 0x01 << (7 - this->bit_pos);
308 *output_pos = *this->byte_pos & mask;
309
310 if (*output_pos)
311 { /* set to a "clean", comparable true */
312 *output_pos = TRUE;
313 }
314 DBG3(DBG_ENC, " => %d", *output_pos);
315 }
316 this->bit_pos = (this->bit_pos + 1) % 8;
317 if (this->bit_pos == 0)
318 {
319 this->byte_pos++;
320 }
321 return TRUE;
322 }
323
324 /**
325 * Parse substructures in a list.
326 */
327 static bool parse_list(private_parser_t *this, int rule_number,
328 linked_list_t **output_pos, payload_type_t payload_type, size_t length)
329 {
330 linked_list_t *list = *output_pos;
331
332 if (length < 0)
333 {
334 return short_input(this, rule_number);
335 }
336 if (this->bit_pos)
337 {
338 return bad_bitpos(this, rule_number);
339 }
340 while (length > 0)
341 {
342 u_int8_t *pos_before = this->byte_pos;
343 payload_t *payload;
344
345 DBG2(DBG_ENC, " %d bytes left, parsing recursively %N",
346 length, payload_type_names, payload_type);
347
348 if (parse_payload(this, payload_type, &payload) != SUCCESS)
349 {
350 DBG1(DBG_ENC, " parsing of a %N substructure failed",
351 payload_type_names, payload_type);
352 return FALSE;
353 }
354 list->insert_last(list, payload);
355 length -= this->byte_pos - pos_before;
356 }
357 *output_pos = list;
358 return TRUE;
359 }
360
361 /**
362 * Parse data from current parsing position in a chunk.
363 */
364 static bool parse_chunk(private_parser_t *this, int rule_number,
365 chunk_t *output_pos, size_t length)
366 {
367 if (this->byte_pos + length > this->input_roof)
368 {
369 return short_input(this, rule_number);
370 }
371 if (this->bit_pos)
372 {
373 return bad_bitpos(this, rule_number);
374 }
375 if (output_pos)
376 {
377 *output_pos = chunk_alloc(length);
378 memcpy(output_pos->ptr, this->byte_pos, length);
379 DBG3(DBG_ENC, " => %b", output_pos->ptr, length);
380 }
381 this->byte_pos += length;
382 return TRUE;
383 }
384
385 /**
386 * Implementation of parser_t.parse_payload.
387 */
388 static status_t parse_payload(private_parser_t *this,
389 payload_type_t payload_type, payload_t **payload)
390 {
391 payload_t *pld;
392 void *output;
393 size_t rule_count, payload_length = 0, spi_size = 0, attribute_length = 0;
394 u_int16_t ts_type = 0;
395 bool attribute_format = FALSE;
396 int rule_number;
397 encoding_rule_t *rule;
398
399 /* create instance of the payload to parse */
400 pld = payload_create(payload_type);
401
402 DBG2(DBG_ENC, "parsing %N payload, %d bytes left",
403 payload_type_names, payload_type, this->input_roof - this->byte_pos);
404
405 DBG3(DBG_ENC, "parsing payload from %b",
406 this->byte_pos, this->input_roof - this->byte_pos);
407
408 if (pld->get_type(pld) == UNKNOWN_PAYLOAD)
409 {
410 DBG1(DBG_ENC, " payload type %d is unknown, handling as %N",
411 payload_type, payload_type_names, UNKNOWN_PAYLOAD);
412 }
413
414 /* base pointer for output, avoids casting in every rule */
415 output = pld;
416
417 /* parse the payload with its own rulse */
418 pld->get_encoding_rules(pld, &(this->rules), &rule_count);
419 for (rule_number = 0; rule_number < rule_count; rule_number++)
420 {
421 rule = &(this->rules[rule_number]);
422 DBG2(DBG_ENC, " parsing rule %d %N",
423 rule_number, encoding_type_names, rule->type);
424 switch (rule->type)
425 {
426 case U_INT_4:
427 {
428 if (!parse_uint4(this, rule_number, output + rule->offset))
429 {
430 pld->destroy(pld);
431 return PARSE_ERROR;
432 }
433 break;
434 }
435 case U_INT_8:
436 {
437 if (!parse_uint8(this, rule_number, output + rule->offset))
438 {
439 pld->destroy(pld);
440 return PARSE_ERROR;
441 }
442 break;
443 }
444 case U_INT_16:
445 {
446 if (!parse_uint16(this, rule_number, output + rule->offset))
447 {
448 pld->destroy(pld);
449 return PARSE_ERROR;
450 }
451 break;
452 }
453 case U_INT_32:
454 {
455 if (!parse_uint32(this, rule_number, output + rule->offset))
456 {
457 pld->destroy(pld);
458 return PARSE_ERROR;
459 }
460 break;
461 }
462 case U_INT_64:
463 {
464 if (!parse_uint64(this, rule_number, output + rule->offset))
465 {
466 pld->destroy(pld);
467 return PARSE_ERROR;
468 }
469 break;
470 }
471 case IKE_SPI:
472 {
473 if (!parse_bytes(this, rule_number, output + rule->offset, 8))
474 {
475 pld->destroy(pld);
476 return PARSE_ERROR;
477 }
478 break;
479 }
480 case RESERVED_BIT:
481 {
482 if (!parse_bit(this, rule_number, NULL))
483 {
484 pld->destroy(pld);
485 return PARSE_ERROR;
486 }
487 break;
488 }
489 case RESERVED_BYTE:
490 {
491 if (!parse_uint8(this, rule_number, NULL))
492 {
493 pld->destroy(pld);
494 return PARSE_ERROR;
495 }
496 break;
497 }
498 case FLAG:
499 {
500 if (!parse_bit(this, rule_number, output + rule->offset))
501 {
502 pld->destroy(pld);
503 return PARSE_ERROR;
504 }
505 break;
506 }
507 case PAYLOAD_LENGTH:
508 {
509 if (!parse_uint16(this, rule_number, output + rule->offset))
510 {
511 pld->destroy(pld);
512 return PARSE_ERROR;
513 }
514 /* parsed u_int16 should be aligned */
515 payload_length = *(u_int16_t*)(output + rule->offset);
516 if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
517 {
518 pld->destroy(pld);
519 return PARSE_ERROR;
520 }
521 break;
522 }
523 case HEADER_LENGTH:
524 {
525 if (!parse_uint32(this, rule_number, output + rule->offset))
526 {
527 pld->destroy(pld);
528 return PARSE_ERROR;
529 }
530 break;
531 }
532 case SPI_SIZE:
533 {
534 if (!parse_uint8(this, rule_number, output + rule->offset))
535 {
536 pld->destroy(pld);
537 return PARSE_ERROR;
538 }
539 spi_size = *(u_int8_t*)(output + rule->offset);
540 break;
541 }
542 case SPI:
543 {
544 if (!parse_chunk(this, rule_number, output + rule->offset,
545 spi_size))
546 {
547 pld->destroy(pld);
548 return PARSE_ERROR;
549 }
550 break;
551 }
552 case PROPOSALS:
553 {
554 if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
555 !parse_list(this, rule_number, output + rule->offset,
556 PROPOSAL_SUBSTRUCTURE,
557 payload_length - SA_PAYLOAD_HEADER_LENGTH))
558 {
559 pld->destroy(pld);
560 return PARSE_ERROR;
561 }
562 break;
563 }
564 case TRANSFORMS:
565 {
566 if (payload_length <
567 spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
568 !parse_list(this, rule_number, output + rule->offset,
569 TRANSFORM_SUBSTRUCTURE, payload_length - spi_size -
570 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
571 {
572 pld->destroy(pld);
573 return PARSE_ERROR;
574 }
575 break;
576 }
577 case TRANSFORM_ATTRIBUTES:
578 {
579 if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
580 !parse_list(this, rule_number, output + rule->offset,
581 TRANSFORM_ATTRIBUTE,
582 payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
583 {
584 pld->destroy(pld);
585 return PARSE_ERROR;
586 }
587 break;
588 }
589 case CONFIGURATION_ATTRIBUTES:
590 {
591 if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
592 !parse_list(this, rule_number, output + rule->offset,
593 CONFIGURATION_ATTRIBUTE,
594 payload_length - CP_PAYLOAD_HEADER_LENGTH))
595 {
596 pld->destroy(pld);
597 return PARSE_ERROR;
598 }
599 break;
600 }
601 case ATTRIBUTE_FORMAT:
602 {
603 if (!parse_bit(this, rule_number, output + rule->offset))
604 {
605 pld->destroy(pld);
606 return PARSE_ERROR;
607 }
608 attribute_format = *(bool*)(output + rule->offset);
609 break;
610 }
611 case ATTRIBUTE_TYPE:
612 {
613 if (!parse_uint15(this, rule_number, output + rule->offset))
614 {
615 pld->destroy(pld);
616 return PARSE_ERROR;
617 }
618 attribute_format = *(bool*)(output + rule->offset);
619 break;
620 }
621 case CONFIGURATION_ATTRIBUTE_LENGTH:
622 {
623 if (!parse_uint16(this, rule_number, output + rule->offset))
624 {
625 pld->destroy(pld);
626 return PARSE_ERROR;
627 }
628 attribute_length = *(u_int16_t*)(output + rule->offset);
629 break;
630 }
631 case ATTRIBUTE_LENGTH_OR_VALUE:
632 {
633 if (!parse_uint16(this, rule_number, output + rule->offset))
634 {
635 pld->destroy(pld);
636 return PARSE_ERROR;
637 }
638 attribute_length = *(u_int16_t*)(output + rule->offset);
639 break;
640 }
641 case ATTRIBUTE_VALUE:
642 {
643 if (attribute_format == FALSE &&
644 !parse_chunk(this, rule_number, output + rule->offset,
645 attribute_length))
646 {
647 pld->destroy(pld);
648 return PARSE_ERROR;
649 }
650 break;
651 }
652 case NONCE_DATA:
653 {
654 if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
655 !parse_chunk(this, rule_number, output + rule->offset,
656 payload_length - NONCE_PAYLOAD_HEADER_LENGTH))
657 {
658 pld->destroy(pld);
659 return PARSE_ERROR;
660 }
661 break;
662 }
663 case ID_DATA:
664 {
665 if (payload_length < ID_PAYLOAD_HEADER_LENGTH ||
666 !parse_chunk(this, rule_number, output + rule->offset,
667 payload_length - ID_PAYLOAD_HEADER_LENGTH))
668 {
669 pld->destroy(pld);
670 return PARSE_ERROR;
671 }
672 break;
673 }
674 case AUTH_DATA:
675 {
676 if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH ||
677 !parse_chunk(this, rule_number, output + rule->offset,
678 payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
679 {
680 pld->destroy(pld);
681 return PARSE_ERROR;
682 }
683 break;
684 }
685 case CERT_DATA:
686 {
687 if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
688 !parse_chunk(this, rule_number, output + rule->offset,
689 payload_length - CERT_PAYLOAD_HEADER_LENGTH))
690 {
691 pld->destroy(pld);
692 return PARSE_ERROR;
693 }
694 break;
695 }
696 case CERTREQ_DATA:
697 {
698 if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
699 !parse_chunk(this, rule_number, output + rule->offset,
700 payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
701 {
702 pld->destroy(pld);
703 return PARSE_ERROR;
704 }
705 break;
706 }
707 case EAP_DATA:
708 {
709 if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
710 !parse_chunk(this, rule_number, output + rule->offset,
711 payload_length - EAP_PAYLOAD_HEADER_LENGTH))
712 {
713 pld->destroy(pld);
714 return PARSE_ERROR;
715 }
716 break;
717 }
718 case SPIS:
719 {
720 if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
721 !parse_chunk(this, rule_number, output + rule->offset,
722 payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
723 {
724 pld->destroy(pld);
725 return PARSE_ERROR;
726 }
727 break;
728 }
729 case VID_DATA:
730 {
731 if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
732 !parse_chunk(this, rule_number, output + rule->offset,
733 payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
734 {
735 pld->destroy(pld);
736 return PARSE_ERROR;
737 }
738 break;
739 }
740 case CONFIGURATION_ATTRIBUTE_VALUE:
741 {
742 if (!parse_chunk(this, rule_number, output + rule->offset,
743 attribute_length))
744 {
745 pld->destroy(pld);
746 return PARSE_ERROR;
747 }
748 break;
749 }
750 case KEY_EXCHANGE_DATA:
751 {
752 if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
753 !parse_chunk(this, rule_number, output + rule->offset,
754 payload_length - KE_PAYLOAD_HEADER_LENGTH))
755 {
756 pld->destroy(pld);
757 return PARSE_ERROR;
758 }
759 break;
760 }
761 case NOTIFICATION_DATA:
762 {
763 if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
764 !parse_chunk(this, rule_number, output + rule->offset,
765 payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
766 {
767 pld->destroy(pld);
768 return PARSE_ERROR;
769 }
770 break;
771 }
772 case ENCRYPTED_DATA:
773 {
774 if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
775 !parse_chunk(this, rule_number, output + rule->offset,
776 payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
777 {
778 pld->destroy(pld);
779 return PARSE_ERROR;
780 }
781 break;
782 }
783 case TS_TYPE:
784 {
785 if (!parse_uint8(this, rule_number, output + rule->offset))
786 {
787 pld->destroy(pld);
788 return PARSE_ERROR;
789 }
790 ts_type = *(u_int8_t*)(output + rule->offset);
791 break;
792 }
793 case ADDRESS:
794 {
795 size_t address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
796
797 if (!parse_chunk(this, rule_number, output + rule->offset,
798 address_length))
799 {
800 pld->destroy(pld);
801 return PARSE_ERROR;
802 }
803 break;
804 }
805 case TRAFFIC_SELECTORS:
806 {
807 if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
808 !parse_list(this, rule_number, output + rule->offset,
809 TRAFFIC_SELECTOR_SUBSTRUCTURE,
810 payload_length - TS_PAYLOAD_HEADER_LENGTH))
811 {
812 pld->destroy(pld);
813 return PARSE_ERROR;
814 }
815 break;
816 }
817 case UNKNOWN_DATA:
818 {
819 if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
820 !parse_chunk(this, rule_number, output + rule->offset,
821 payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
822 {
823 pld->destroy(pld);
824 return PARSE_ERROR;
825 }
826 break;
827 }
828 default:
829 {
830 DBG1(DBG_ENC, " no rule to parse rule %d %N",
831 rule_number, encoding_type_names, rule->type);
832 pld->destroy(pld);
833 return PARSE_ERROR;
834 }
835 }
836 /* process next rulue */
837 rule++;
838 }
839
840 *payload = pld;
841 DBG2(DBG_ENC, "parsing %N payload finished",
842 payload_type_names, payload_type);
843 return SUCCESS;
844 }
845
846 /**
847 * Implementation of parser_t.get_remaining_byte_count.
848 */
849 static int get_remaining_byte_count (private_parser_t *this)
850 {
851 return this->input_roof - this->byte_pos;
852 }
853
854 /**
855 * Implementation of parser_t.reset_context.
856 */
857 static void reset_context (private_parser_t *this)
858 {
859 this->byte_pos = this->input;
860 this->bit_pos = 0;
861 }
862
863 /**
864 * Implementation of parser_t.destroy.
865 */
866 static void destroy(private_parser_t *this)
867 {
868 free(this);
869 }
870
871 /*
872 * Described in header.
873 */
874 parser_t *parser_create(chunk_t data)
875 {
876 private_parser_t *this = malloc_thing(private_parser_t);
877
878 this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**))parse_payload;
879 this->public.reset_context = (void(*)(parser_t*)) reset_context;
880 this->public.get_remaining_byte_count = (int (*) (parser_t *))get_remaining_byte_count;
881 this->public.destroy = (void(*)(parser_t*)) destroy;
882
883 this->input = data.ptr;
884 this->byte_pos = data.ptr;
885 this->bit_pos = 0;
886 this->input_roof = data.ptr + data.len;
887
888 return &this->public;
889 }
890