Simplify signature of get_encoding_rules(), make all rules static
[strongswan.git] / src / libcharon / 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 * Log invalid length error
90 */
91 static bool short_input(private_parser_t *this, int number)
92 {
93 DBG1(DBG_ENC, " not enough input to parse rule %d %N",
94 number, encoding_type_names, this->rules[number].type);
95 return FALSE;
96 }
97
98 /**
99 * Log unaligned rules
100 */
101 static bool bad_bitpos(private_parser_t *this, int number)
102 {
103 DBG1(DBG_ENC, " found rule %d %N on bitpos %d",
104 number, encoding_type_names, this->rules[number].type, this->bit_pos);
105 return FALSE;
106 }
107
108 /**
109 * Parse a 4-Bit unsigned integer from the current parsing position.
110 */
111 static bool parse_uint4(private_parser_t *this, int rule_number,
112 u_int8_t *output_pos)
113 {
114 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
115 {
116 return short_input(this, rule_number);
117 }
118 switch (this->bit_pos)
119 {
120 case 0:
121 if (output_pos)
122 {
123 *output_pos = *(this->byte_pos) >> 4;
124 }
125 this->bit_pos = 4;
126 break;
127 case 4:
128 if (output_pos)
129 {
130 *output_pos = *(this->byte_pos) & 0x0F;
131 }
132 this->bit_pos = 0;
133 this->byte_pos++;
134 break;
135 default:
136 return bad_bitpos(this, rule_number);
137 }
138 if (output_pos)
139 {
140 DBG3(DBG_ENC, " => %d", *output_pos);
141 }
142 return TRUE;
143 }
144
145 /**
146 * Parse a 8-Bit unsigned integer from the current parsing position.
147 */
148 static bool parse_uint8(private_parser_t *this, int rule_number,
149 u_int8_t *output_pos)
150 {
151 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
152 {
153 return short_input(this, rule_number);
154 }
155 if (this->bit_pos)
156 {
157 return bad_bitpos(this, rule_number);
158 }
159 if (output_pos)
160 {
161 *output_pos = *(this->byte_pos);
162 DBG3(DBG_ENC, " => %d", *output_pos);
163 }
164 this->byte_pos++;
165 return TRUE;
166 }
167
168 /**
169 * Parse a 15-Bit unsigned integer from the current parsing position.
170 */
171 static bool parse_uint15(private_parser_t *this, int rule_number,
172 u_int16_t *output_pos)
173 {
174 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
175 {
176 return short_input(this, rule_number);
177 }
178 if (this->bit_pos != 1)
179 {
180 return bad_bitpos(this, rule_number);
181 }
182 if (output_pos)
183 {
184 memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
185 *output_pos = ntohs(*output_pos) & ~0x8000;
186 DBG3(DBG_ENC, " => %d", *output_pos);
187 }
188 this->byte_pos += sizeof(u_int16_t);
189 this->bit_pos = 0;
190 return TRUE;
191 }
192
193 /**
194 * Parse a 16-Bit unsigned integer from the current parsing position.
195 */
196 static bool parse_uint16(private_parser_t *this, int rule_number,
197 u_int16_t *output_pos)
198 {
199 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
200 {
201 return short_input(this, rule_number);
202 }
203 if (this->bit_pos)
204 {
205 return bad_bitpos(this, rule_number);
206 }
207 if (output_pos)
208 {
209 memcpy(output_pos, this->byte_pos, sizeof(u_int16_t));
210 *output_pos = ntohs(*output_pos);
211 DBG3(DBG_ENC, " => %d", *output_pos);
212 }
213 this->byte_pos += sizeof(u_int16_t);
214 return TRUE;
215 }
216 /**
217 * Parse a 32-Bit unsigned integer from the current parsing position.
218 */
219 static bool parse_uint32(private_parser_t *this, int rule_number,
220 u_int32_t *output_pos)
221 {
222 if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
223 {
224 return short_input(this, rule_number);
225 }
226 if (this->bit_pos)
227 {
228 return bad_bitpos(this, rule_number);
229 }
230 if (output_pos)
231 {
232 memcpy(output_pos, this->byte_pos, sizeof(u_int32_t));
233 *output_pos = ntohl(*output_pos);
234 DBG3(DBG_ENC, " => %d", *output_pos);
235 }
236 this->byte_pos += sizeof(u_int32_t);
237 return TRUE;
238 }
239
240 /**
241 * Parse a given amount of bytes and writes them to a specific location
242 */
243 static bool parse_bytes(private_parser_t *this, int rule_number,
244 u_int8_t *output_pos, int bytes)
245 {
246 if (this->byte_pos + bytes > this->input_roof)
247 {
248 return short_input(this, rule_number);
249 }
250 if (this->bit_pos)
251 {
252 return bad_bitpos(this, rule_number);
253 }
254 if (output_pos)
255 {
256 memcpy(output_pos, this->byte_pos, bytes);
257 DBG3(DBG_ENC, " => %b", output_pos, bytes);
258 }
259 this->byte_pos += bytes;
260 return TRUE;
261 }
262
263 /**
264 * Parse a single Bit from the current parsing position
265 */
266 static bool parse_bit(private_parser_t *this, int rule_number,
267 bool *output_pos)
268 {
269 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
270 {
271 return short_input(this, rule_number);
272 }
273 if (output_pos)
274 {
275 u_int8_t mask;
276 mask = 0x01 << (7 - this->bit_pos);
277 *output_pos = *this->byte_pos & mask;
278
279 if (*output_pos)
280 { /* set to a "clean", comparable true */
281 *output_pos = TRUE;
282 }
283 DBG3(DBG_ENC, " => %d", *output_pos);
284 }
285 this->bit_pos = (this->bit_pos + 1) % 8;
286 if (this->bit_pos == 0)
287 {
288 this->byte_pos++;
289 }
290 return TRUE;
291 }
292
293 /**
294 * Parse substructures in a list.
295 */
296 static bool parse_list(private_parser_t *this, int rule_number,
297 linked_list_t **output_pos, payload_type_t payload_type, int length)
298 {
299 linked_list_t *list = *output_pos;
300
301 if (length < 0)
302 {
303 return short_input(this, rule_number);
304 }
305 if (this->bit_pos)
306 {
307 return bad_bitpos(this, rule_number);
308 }
309 while (length > 0)
310 {
311 u_int8_t *pos_before = this->byte_pos;
312 payload_t *payload;
313
314 DBG2(DBG_ENC, " %d bytes left, parsing recursively %N",
315 length, payload_type_names, payload_type);
316
317 if (this->public.parse_payload(&this->public, payload_type,
318 &payload) != SUCCESS)
319 {
320 DBG1(DBG_ENC, " parsing of a %N substructure failed",
321 payload_type_names, payload_type);
322 return FALSE;
323 }
324 list->insert_last(list, payload);
325 length -= this->byte_pos - pos_before;
326 }
327 if (length != 0)
328 { /* must yield exactly to zero */
329 DBG1(DBG_ENC, " length of %N substructure list invalid",
330 payload_type_names, payload_type);
331 return FALSE;
332 }
333 *output_pos = list;
334 return TRUE;
335 }
336
337 /**
338 * Parse data from current parsing position in a chunk.
339 */
340 static bool parse_chunk(private_parser_t *this, int rule_number,
341 chunk_t *output_pos, int length)
342 {
343 if (this->byte_pos + length > this->input_roof)
344 {
345 return short_input(this, rule_number);
346 }
347 if (this->bit_pos)
348 {
349 return bad_bitpos(this, rule_number);
350 }
351 if (output_pos)
352 {
353 *output_pos = chunk_alloc(length);
354 memcpy(output_pos->ptr, this->byte_pos, length);
355 DBG3(DBG_ENC, " => %b", output_pos->ptr, length);
356 }
357 this->byte_pos += length;
358 return TRUE;
359 }
360
361 METHOD(parser_t, parse_payload, status_t,
362 private_parser_t *this, payload_type_t payload_type, payload_t **payload)
363 {
364 payload_t *pld;
365 void *output;
366 int payload_length = 0, spi_size = 0, attribute_length = 0;
367 u_int16_t ts_type = 0;
368 bool attribute_format = FALSE;
369 int rule_number, rule_count;
370 encoding_rule_t *rule;
371
372 /* create instance of the payload to parse */
373 pld = payload_create(payload_type);
374
375 DBG2(DBG_ENC, "parsing %N payload, %d bytes left",
376 payload_type_names, payload_type, this->input_roof - this->byte_pos);
377
378 DBG3(DBG_ENC, "parsing payload from %b",
379 this->byte_pos, this->input_roof - this->byte_pos);
380
381 /* base pointer for output, avoids casting in every rule */
382 output = pld;
383
384 /* parse the payload with its own rulse */
385 rule_count = pld->get_encoding_rules(pld, &this->rules);
386 for (rule_number = 0; rule_number < rule_count; rule_number++)
387 {
388 rule = &(this->rules[rule_number]);
389 DBG2(DBG_ENC, " parsing rule %d %N",
390 rule_number, encoding_type_names, rule->type);
391 switch (rule->type)
392 {
393 case U_INT_4:
394 {
395 if (!parse_uint4(this, rule_number, output + rule->offset))
396 {
397 pld->destroy(pld);
398 return PARSE_ERROR;
399 }
400 break;
401 }
402 case U_INT_8:
403 case RESERVED_BYTE:
404 {
405 if (!parse_uint8(this, rule_number, output + rule->offset))
406 {
407 pld->destroy(pld);
408 return PARSE_ERROR;
409 }
410 break;
411 }
412 case U_INT_16:
413 {
414 if (!parse_uint16(this, rule_number, output + rule->offset))
415 {
416 pld->destroy(pld);
417 return PARSE_ERROR;
418 }
419 break;
420 }
421 case U_INT_32:
422 case HEADER_LENGTH:
423 {
424 if (!parse_uint32(this, rule_number, output + rule->offset))
425 {
426 pld->destroy(pld);
427 return PARSE_ERROR;
428 }
429 break;
430 }
431 case IKE_SPI:
432 {
433 if (!parse_bytes(this, rule_number, output + rule->offset, 8))
434 {
435 pld->destroy(pld);
436 return PARSE_ERROR;
437 }
438 break;
439 }
440 case RESERVED_BIT:
441 case FLAG:
442 {
443 if (!parse_bit(this, rule_number, output + rule->offset))
444 {
445 pld->destroy(pld);
446 return PARSE_ERROR;
447 }
448 break;
449 }
450 case PAYLOAD_LENGTH:
451 {
452 if (!parse_uint16(this, rule_number, output + rule->offset))
453 {
454 pld->destroy(pld);
455 return PARSE_ERROR;
456 }
457 /* parsed u_int16 should be aligned */
458 payload_length = *(u_int16_t*)(output + rule->offset);
459 if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH)
460 {
461 pld->destroy(pld);
462 return PARSE_ERROR;
463 }
464 break;
465 }
466 case SPI_SIZE:
467 {
468 if (!parse_uint8(this, rule_number, output + rule->offset))
469 {
470 pld->destroy(pld);
471 return PARSE_ERROR;
472 }
473 spi_size = *(u_int8_t*)(output + rule->offset);
474 break;
475 }
476 case SPI:
477 {
478 if (!parse_chunk(this, rule_number, output + rule->offset,
479 spi_size))
480 {
481 pld->destroy(pld);
482 return PARSE_ERROR;
483 }
484 break;
485 }
486 case PROPOSALS:
487 {
488 if (payload_length < SA_PAYLOAD_HEADER_LENGTH ||
489 !parse_list(this, rule_number, output + rule->offset,
490 PROPOSAL_SUBSTRUCTURE,
491 payload_length - SA_PAYLOAD_HEADER_LENGTH))
492 {
493 pld->destroy(pld);
494 return PARSE_ERROR;
495 }
496 break;
497 }
498 case PROPOSALS_V1:
499 {
500 if (payload_length < SA_PAYLOAD_V1_HEADER_LENGTH ||
501 !parse_list(this, rule_number, output + rule->offset,
502 PROPOSAL_SUBSTRUCTURE_V1,
503 payload_length - SA_PAYLOAD_V1_HEADER_LENGTH))
504 {
505 pld->destroy(pld);
506 return PARSE_ERROR;
507 }
508 break;
509 }
510 case TRANSFORMS:
511 {
512 if (payload_length <
513 spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
514 !parse_list(this, rule_number, output + rule->offset,
515 TRANSFORM_SUBSTRUCTURE, payload_length - spi_size -
516 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
517 {
518 pld->destroy(pld);
519 return PARSE_ERROR;
520 }
521 break;
522 }
523 case TRANSFORMS_V1:
524 {
525 if (payload_length <
526 spi_size + PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH ||
527 !parse_list(this, rule_number, output + rule->offset,
528 TRANSFORM_SUBSTRUCTURE_V1, payload_length - spi_size -
529 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH))
530 {
531 pld->destroy(pld);
532 return PARSE_ERROR;
533 }
534 break;
535 }
536 case TRANSFORM_ATTRIBUTES:
537 {
538 if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
539 !parse_list(this, rule_number, output + rule->offset,
540 TRANSFORM_ATTRIBUTE,
541 payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
542 {
543 pld->destroy(pld);
544 return PARSE_ERROR;
545 }
546 break;
547 }
548 case TRANSFORM_ATTRIBUTES_V1:
549 {
550 if (payload_length < TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH ||
551 !parse_list(this, rule_number, output + rule->offset,
552 TRANSFORM_ATTRIBUTE_V1,
553 payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH))
554 {
555 pld->destroy(pld);
556 return PARSE_ERROR;
557 }
558 break;
559 }
560 case CONFIGURATION_ATTRIBUTES:
561 {
562 if (payload_length < CP_PAYLOAD_HEADER_LENGTH ||
563 !parse_list(this, rule_number, output + rule->offset,
564 CONFIGURATION_ATTRIBUTE,
565 payload_length - CP_PAYLOAD_HEADER_LENGTH))
566 {
567 pld->destroy(pld);
568 return PARSE_ERROR;
569 }
570 break;
571 }
572 case ATTRIBUTE_FORMAT:
573 {
574 if (!parse_bit(this, rule_number, output + rule->offset))
575 {
576 pld->destroy(pld);
577 return PARSE_ERROR;
578 }
579 attribute_format = *(bool*)(output + rule->offset);
580 break;
581 }
582 case ATTRIBUTE_TYPE:
583 {
584 if (!parse_uint15(this, rule_number, output + rule->offset))
585 {
586 pld->destroy(pld);
587 return PARSE_ERROR;
588 }
589 break;
590 }
591 case CONFIGURATION_ATTRIBUTE_LENGTH:
592 {
593 if (!parse_uint16(this, rule_number, output + rule->offset))
594 {
595 pld->destroy(pld);
596 return PARSE_ERROR;
597 }
598 attribute_length = *(u_int16_t*)(output + rule->offset);
599 break;
600 }
601 case ATTRIBUTE_LENGTH_OR_VALUE:
602 {
603 if (!parse_uint16(this, rule_number, output + rule->offset))
604 {
605 pld->destroy(pld);
606 return PARSE_ERROR;
607 }
608 attribute_length = *(u_int16_t*)(output + rule->offset);
609 break;
610 }
611 case ATTRIBUTE_VALUE:
612 {
613 if (attribute_format == FALSE &&
614 !parse_chunk(this, rule_number, output + rule->offset,
615 attribute_length))
616 {
617 pld->destroy(pld);
618 return PARSE_ERROR;
619 }
620 break;
621 }
622 case NONCE_DATA:
623 {
624 if (payload_length < NONCE_PAYLOAD_HEADER_LENGTH ||
625 !parse_chunk(this, rule_number, output + rule->offset,
626 payload_length - NONCE_PAYLOAD_HEADER_LENGTH))
627 {
628 pld->destroy(pld);
629 return PARSE_ERROR;
630 }
631 break;
632 }
633 case ID_DATA:
634 {
635 if (payload_length < ID_PAYLOAD_HEADER_LENGTH ||
636 !parse_chunk(this, rule_number, output + rule->offset,
637 payload_length - ID_PAYLOAD_HEADER_LENGTH))
638 {
639 pld->destroy(pld);
640 return PARSE_ERROR;
641 }
642 break;
643 }
644 case AUTH_DATA:
645 {
646 if (payload_length < AUTH_PAYLOAD_HEADER_LENGTH ||
647 !parse_chunk(this, rule_number, output + rule->offset,
648 payload_length - AUTH_PAYLOAD_HEADER_LENGTH))
649 {
650 pld->destroy(pld);
651 return PARSE_ERROR;
652 }
653 break;
654 }
655 case CERT_DATA:
656 {
657 if (payload_length < CERT_PAYLOAD_HEADER_LENGTH ||
658 !parse_chunk(this, rule_number, output + rule->offset,
659 payload_length - CERT_PAYLOAD_HEADER_LENGTH))
660 {
661 pld->destroy(pld);
662 return PARSE_ERROR;
663 }
664 break;
665 }
666 case CERTREQ_DATA:
667 {
668 if (payload_length < CERTREQ_PAYLOAD_HEADER_LENGTH ||
669 !parse_chunk(this, rule_number, output + rule->offset,
670 payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH))
671 {
672 pld->destroy(pld);
673 return PARSE_ERROR;
674 }
675 break;
676 }
677 case EAP_DATA:
678 {
679 if (payload_length < EAP_PAYLOAD_HEADER_LENGTH ||
680 !parse_chunk(this, rule_number, output + rule->offset,
681 payload_length - EAP_PAYLOAD_HEADER_LENGTH))
682 {
683 pld->destroy(pld);
684 return PARSE_ERROR;
685 }
686 break;
687 }
688 case SPIS:
689 {
690 if (payload_length < DELETE_PAYLOAD_HEADER_LENGTH ||
691 !parse_chunk(this, rule_number, output + rule->offset,
692 payload_length - DELETE_PAYLOAD_HEADER_LENGTH))
693 {
694 pld->destroy(pld);
695 return PARSE_ERROR;
696 }
697 break;
698 }
699 case VID_DATA:
700 {
701 if (payload_length < VENDOR_ID_PAYLOAD_HEADER_LENGTH ||
702 !parse_chunk(this, rule_number, output + rule->offset,
703 payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH))
704 {
705 pld->destroy(pld);
706 return PARSE_ERROR;
707 }
708 break;
709 }
710 case CONFIGURATION_ATTRIBUTE_VALUE:
711 {
712 if (!parse_chunk(this, rule_number, output + rule->offset,
713 attribute_length))
714 {
715 pld->destroy(pld);
716 return PARSE_ERROR;
717 }
718 break;
719 }
720 case KEY_EXCHANGE_DATA:
721 {
722 if (payload_length < KE_PAYLOAD_HEADER_LENGTH ||
723 !parse_chunk(this, rule_number, output + rule->offset,
724 payload_length - KE_PAYLOAD_HEADER_LENGTH))
725 {
726 pld->destroy(pld);
727 return PARSE_ERROR;
728 }
729 break;
730 }
731 case KEY_EXCHANGE_DATA_V1:
732 {
733 if (payload_length < KE_PAYLOAD_V1_HEADER_LENGTH ||
734 !parse_chunk(this, rule_number, output + rule->offset,
735 payload_length - KE_PAYLOAD_V1_HEADER_LENGTH))
736 {
737 pld->destroy(pld);
738 return PARSE_ERROR;
739 }
740 break;
741 }
742 case NOTIFICATION_DATA:
743 {
744 if (payload_length < NOTIFY_PAYLOAD_HEADER_LENGTH + spi_size ||
745 !parse_chunk(this, rule_number, output + rule->offset,
746 payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size))
747 {
748 pld->destroy(pld);
749 return PARSE_ERROR;
750 }
751 break;
752 }
753 case ENCRYPTED_DATA:
754 {
755 if (payload_length < ENCRYPTION_PAYLOAD_HEADER_LENGTH ||
756 !parse_chunk(this, rule_number, output + rule->offset,
757 payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH))
758 {
759 pld->destroy(pld);
760 return PARSE_ERROR;
761 }
762 break;
763 }
764 case TS_TYPE:
765 {
766 if (!parse_uint8(this, rule_number, output + rule->offset))
767 {
768 pld->destroy(pld);
769 return PARSE_ERROR;
770 }
771 ts_type = *(u_int8_t*)(output + rule->offset);
772 break;
773 }
774 case ADDRESS:
775 {
776 int address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
777
778 if (!parse_chunk(this, rule_number, output + rule->offset,
779 address_length))
780 {
781 pld->destroy(pld);
782 return PARSE_ERROR;
783 }
784 break;
785 }
786 case TRAFFIC_SELECTORS:
787 {
788 if (payload_length < TS_PAYLOAD_HEADER_LENGTH ||
789 !parse_list(this, rule_number, output + rule->offset,
790 TRAFFIC_SELECTOR_SUBSTRUCTURE,
791 payload_length - TS_PAYLOAD_HEADER_LENGTH))
792 {
793 pld->destroy(pld);
794 return PARSE_ERROR;
795 }
796 break;
797 }
798 case UNKNOWN_DATA:
799 {
800 if (payload_length < UNKNOWN_PAYLOAD_HEADER_LENGTH ||
801 !parse_chunk(this, rule_number, output + rule->offset,
802 payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH))
803 {
804 pld->destroy(pld);
805 return PARSE_ERROR;
806 }
807 break;
808 }
809 default:
810 {
811 DBG1(DBG_ENC, " no rule to parse rule %d %N",
812 rule_number, encoding_type_names, rule->type);
813 pld->destroy(pld);
814 return PARSE_ERROR;
815 }
816 }
817 /* process next rulue */
818 rule++;
819 }
820
821 *payload = pld;
822 DBG2(DBG_ENC, "parsing %N payload finished",
823 payload_type_names, payload_type);
824 return SUCCESS;
825 }
826
827 METHOD(parser_t, get_remaining_byte_count, int,
828 private_parser_t *this)
829 {
830 return this->input_roof - this->byte_pos;
831 }
832
833 METHOD(parser_t, reset_context, void,
834 private_parser_t *this)
835 {
836 this->byte_pos = this->input;
837 this->bit_pos = 0;
838 }
839
840 METHOD(parser_t, destroy, void,
841 private_parser_t *this)
842 {
843 free(this);
844 }
845
846 /*
847 * Described in header.
848 */
849 parser_t *parser_create(chunk_t data)
850 {
851 private_parser_t *this;
852
853 INIT(this,
854 .public = {
855 .parse_payload = _parse_payload,
856 .reset_context = _reset_context,
857 .get_remaining_byte_count = _get_remaining_byte_count,
858 .destroy = _destroy,
859 },
860 .input = data.ptr,
861 .byte_pos = data.ptr,
862 .input_roof = data.ptr + data.len,
863 );
864
865 return &this->public;
866 }
867