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