- created encoding package
[strongswan.git] / Source / charon / encoding / generator.c
1 /**
2 * @file generator.c
3 *
4 * @brief Generic generator class used to generate IKEv2-header and payloads.
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 <string.h>
25 #include <arpa/inet.h>
26 #include <stdio.h>
27
28
29 #include "generator.h"
30
31 #include <types.h>
32 #include <globals.h>
33 #include <utils/allocator.h>
34 #include <utils/linked_list.h>
35 #include <utils/logger_manager.h>
36 #include <encoding/payloads/payload.h>
37 #include <encoding/payloads/proposal_substructure.h>
38 #include <encoding/payloads/transform_substructure.h>
39 #include <encoding/payloads/sa_payload.h>
40 #include <encoding/payloads/ke_payload.h>
41 #include <encoding/payloads/notify_payload.h>
42 #include <encoding/payloads/nonce_payload.h>
43
44 /**
45 * Private part of a generator_t object
46 */
47 typedef struct private_generator_s private_generator_t;
48
49 struct private_generator_s {
50 /**
51 * Public part of a generator_t object
52 */
53 generator_t public;
54
55 /* private functions and fields */
56
57
58 /**
59 * Generates a U_INT-Field type and writes it to buffer.
60 *
61 * @param this private_generator_t object
62 * @param int_type type of U_INT field (U_INT_4, U_INT_8, etc.)
63 * ATTRIBUTE_TYPE is also generated in this function
64 * @param offset offset of value in data struct
65 * @param generator_contexts generator_contexts_t object where the context is written or read from
66 * @return - SUCCESS if succeeded
67 * - OUT_OF_RES if out of ressources
68 */
69 status_t (*generate_u_int_type) (private_generator_t *this,encoding_type_t int_type,u_int32_t offset);
70
71 /**
72 * Get size of current buffer in bytes.
73 *
74 * @param this private_generator_t object
75 * @return Size of buffer in bytes
76 */
77 size_t (*get_current_buffer_size) (private_generator_t *this);
78
79 /**
80 * Get free space of current buffer in bytes.
81 *
82 * @param this private_generator_t object
83 * @return space in buffer in bytes
84 */
85 size_t (*get_current_buffer_space) (private_generator_t *this);
86
87 /**
88 * Get length of data in buffer (in bytes).
89 *
90 * @param this private_generator_t object
91 * @return length of data in bytes
92 */
93 size_t (*get_current_data_length) (private_generator_t *this);
94
95 /**
96 * Get current offset in buffer (in bytes).
97 *
98 * @param this private_generator_t object
99 * @return offset in bytes
100 */
101 u_int32_t (*get_current_buffer_offset) (private_generator_t *this);
102
103 /**
104 * Generates a RESERVED BIT field or a RESERVED BYTE field and writes
105 * it to the buffer.
106 *
107 * @param this private_generator_t object
108 * @param generator_contexts generator_contexts_t object where the context is written or read from
109 * @param bits number of bits to generate
110 * @return - SUCCESS if succeeded
111 * - OUT_OF_RES if out of ressources
112 * - FAILED if bit count not supported
113 */
114 status_t (*generate_reserved_field) (private_generator_t *this,int bits);
115
116 /**
117 * Generates a FLAG field
118 *
119 * @param this private_generator_t object
120 * @param generator_contexts generator_contexts_t object where the context is written or read from
121 * @param offset offset of flag value in data struct
122 * @return - SUCCESS if succeeded
123 * - OUT_OF_RES if out of ressources
124 */
125 status_t (*generate_flag) (private_generator_t *this,u_int32_t offset);
126
127 /**
128 * Writes the current buffer content into a chunk_t
129 *
130 * Memory of specific chunk_t gets allocated.
131 *
132 * @param this calling private_generator_t object
133 * @param data pointer of chunk_t to write to
134 * @return
135 * - SUCCESSFUL if succeeded
136 * - OUT_OF_RES otherwise
137 */
138 status_t (*write_chunk) (private_generator_t *this,chunk_t *data);
139
140 /**
141 * Generates a bytestream from a chunk_t
142 *
143 * @param this private_generator_t object
144 * @param offset offset of chunk_t value in data struct
145 * @return - SUCCESS if succeeded
146 * - OUT_OF_RES if out of ressources
147 */
148 status_t (*generate_from_chunk) (private_generator_t *this,u_int32_t offset);
149
150 /**
151 * Makes sure enough space is available in buffer to store amount of bits.
152 *
153 * If buffer is to small to hold the specific amount of bits it
154 * is increased using reallocation function of allocator.
155 *
156 * @param this calling private_generator_t object
157 * @param bits number of bits to make available in buffer
158 * @return
159 * - SUCCESSFUL if succeeded
160 * - OUT_OF_RES otherwise
161 */
162 status_t (*make_space_available) (private_generator_t *this,size_t bits);
163
164 /**
165 * Writes a specific amount of byte into the buffer.
166 *
167 * If buffer is to small to hold the specific amount of bytes it
168 * is increased.
169 *
170 * @param this calling private_generator_t object
171 * @param bytes pointer to bytes to write
172 * @param number_of_bytes number of bytes to write into buffer
173 * @return
174 * - SUCCESSFUL if succeeded
175 * - OUT_OF_RES otherwise
176 */
177 status_t (*write_bytes_to_buffer) (private_generator_t *this,void * bytes,size_t number_of_bytes);
178
179
180 /**
181 * Writes a specific amount of byte into the buffer at a specific offset.
182 *
183 * @warning buffer size is not check to hold the data if offset is to large.
184 *
185 * @param this calling private_generator_t object
186 * @param bytes pointer to bytes to write
187 * @param number_of_bytes number of bytes to write into buffer
188 * @param offset offset to write the data into
189 * @return
190 * - SUCCESSFUL if succeeded
191 * - OUT_OF_RES otherwise
192 */
193 status_t (*write_bytes_to_buffer_at_offset) (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset);
194
195 /**
196 * Buffer used to generate the data into.
197 */
198 u_int8_t *buffer;
199
200 /**
201 * Current write position in buffer (one byte aligned).
202 */
203 u_int8_t *out_position;
204
205 /**
206 * Position of last byte in buffer.
207 */
208 u_int8_t *roof_position;
209
210 /**
211 * Current bit writing to in current byte (between 0 and 7).
212 */
213 size_t current_bit;
214
215 /**
216 * Associated data struct to read informations from.
217 */
218 void * data_struct;
219
220 /*
221 * Last payload length position offset in the buffer
222 */
223 u_int32_t last_payload_length_position_offset;
224
225 /**
226 * Offset of the header length field in the buffer
227 */
228 u_int32_t header_length_position_offset;
229
230 /**
231 * Last SPI size
232 */
233 u_int8_t last_spi_size;
234
235 /*
236 * Attribute format of the last generated transform attribute
237 *
238 * Used to check if a variable value field is used or not for
239 * the transform attribute value.
240 */
241 bool attribute_format;
242
243 /*
244 * Depending on the value of attribute_format this field is used
245 * to hold the length of the transform attribute in bytes
246 */
247 u_int16_t attribute_length;
248
249 /**
250 * Associated Logger
251 */
252 logger_t *logger;
253 };
254
255 /**
256 * Implements private_generator_t's get_current_buffer_size function.
257 * See #private_generator_s.get_current_buffer_size.
258 */
259 static size_t get_current_buffer_size (private_generator_t *this)
260 {
261 return ((this->roof_position) - (this->buffer));
262 }
263
264 /**
265 * Implements private_generator_t's get_current_buffer_space function.
266 * See #private_generator_s.get_current_buffer_space.
267 */
268 static size_t get_current_buffer_space (private_generator_t *this)
269 {
270 /* we know, one byte more */
271 size_t space = (this->roof_position) - (this->out_position);
272 return (space);
273 }
274
275 /**
276 * Implements private_generator_t's get_current_buffer_space function.
277 * See #private_generator_s.get_current_buffer_space.
278 */
279 static size_t get_current_data_length (private_generator_t *this)
280 {
281 return (this->out_position - this->buffer);
282 }
283
284 /**
285 * Implements private_generator_t's get_current_buffer_offset function.
286 * See #private_generator_s.get_current_buffer_offset.
287 */
288 static u_int32_t get_current_buffer_offset (private_generator_t *this)
289 {
290 return (this->out_position - this->buffer);
291 }
292
293
294 /**
295 * Implements private_generator_t's generate_u_int_type function.
296 * See #private_generator_s.generate_u_int_type.
297 */
298 static status_t generate_u_int_type (private_generator_t *this,encoding_type_t int_type,u_int32_t offset)
299 {
300 size_t number_of_bits = 0;
301 status_t status;
302
303 /* find out number of bits of each U_INT type to check for enough space
304 in buffer */
305 switch (int_type)
306 {
307 case U_INT_4:
308 number_of_bits = 4;
309 break;
310 case U_INT_8:
311 number_of_bits = 8;
312 break;
313 case U_INT_16:
314 number_of_bits = 16;
315 break;
316 case U_INT_32:
317 number_of_bits = 32;
318 break;
319 case U_INT_64:
320 number_of_bits = 64;
321 break;
322 case ATTRIBUTE_TYPE:
323 number_of_bits = 15;
324 break;
325 case IKE_SPI:
326 number_of_bits = 64;
327 break;
328
329 default:
330 return FAILED;
331 }
332 /* U_INT Types of multiple then 8 bits must be aligned */
333 if (((number_of_bits % 8) == 0) && (this->current_bit != 0))
334 {
335 this->logger->log(this->logger, ERROR, "U_INT Type %s is not 8 Bit aligned",
336 mapping_find(encoding_type_m,int_type));
337 /* current bit has to be zero for values multiple of 8 bits */
338 return FAILED;
339 }
340
341 /* make sure enough space is available in buffer */
342 status = this->make_space_available(this,number_of_bits);
343 if (status != SUCCESS)
344 {
345 return status;
346 }
347 /* now handle each u int type differently */
348 switch (int_type)
349 {
350 case U_INT_4:
351 {
352 if (this->current_bit == 0)
353 {
354 /* highval of current byte in buffer has to be set to the new value*/
355 u_int8_t high_val = *((u_int8_t *)(this->data_struct + offset)) << 4;
356 /* lowval in buffer is not changed */
357 u_int8_t low_val = *(this->out_position) & 0x0F;
358 /* highval is set, low_val is not changed */
359 *(this->out_position) = high_val | low_val;
360 this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position));
361 /* write position is not changed, just bit position is moved */
362 this->current_bit = 4;
363 }
364 else if (this->current_bit == 4)
365 {
366 /* highval in buffer is not changed */
367 u_int high_val = *(this->out_position) & 0xF0;
368 /* lowval of current byte in buffer has to be set to the new value*/
369 u_int low_val = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
370 *(this->out_position) = high_val | low_val;
371 this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position));
372 this->out_position++;
373 this->current_bit = 0;
374
375 }
376 else
377 {
378 this->logger->log(this->logger, ERROR, "U_INT_4 Type is not 4 Bit aligned");
379 /* 4 Bit integers must have a 4 bit alignment */
380 return FAILED;
381 };
382 break;
383 }
384 case U_INT_8:
385 {
386 /* 8 bit values are written as they are */
387 *this->out_position = *((u_int8_t *)(this->data_struct + offset));
388 this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position));
389 this->out_position++;
390 break;
391
392 }
393 case ATTRIBUTE_TYPE:
394 {
395 /* attribute type must not change first bit uf current byte ! */
396 if (this->current_bit != 1)
397 {
398 this->logger->log(this->logger, ERROR, "ATTRIBUTE FORMAT flag is not set");
399 /* first bit has to be set! */
400 return FAILED;
401 }
402 /* get value of attribute format flag */
403 u_int8_t attribute_format_flag = *(this->out_position) & 0x80;
404 /* get attribute type value as 16 bit integer*/
405 u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset)));
406 /* last bit must be unset */
407 int16_val = int16_val & 0xFF7F;
408
409 int16_val = int16_val | attribute_format_flag;
410 this->logger->log(this->logger, RAW|MOST, " => 0x%x", int16_val);
411 /* write bytes to buffer (set bit is overwritten)*/
412 this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t));
413 this->current_bit = 0;
414 break;
415
416 }
417 case U_INT_16:
418 {
419 u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset)));
420 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)&int16_val, sizeof(int16_val));
421 this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t));
422 break;
423 }
424 case U_INT_32:
425 {
426 u_int32_t int32_val = htonl(*((u_int32_t*)(this->data_struct + offset)));
427 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)&int32_val, sizeof(int32_val));
428 this->write_bytes_to_buffer(this,&int32_val,sizeof(u_int32_t));
429 break;
430 }
431 case U_INT_64:
432 {
433 /* 64 bit integers are written as two 32 bit integers */
434 u_int32_t int32_val_low = htonl(*((u_int32_t*)(this->data_struct + offset)));
435 u_int32_t int32_val_high = htonl(*((u_int32_t*)(this->data_struct + offset) + 1));
436 this->logger->log_bytes(this->logger, RAW|MOST, " => (low)", (void*)&int32_val_low, sizeof(int32_val_low));
437 this->logger->log_bytes(this->logger, RAW|MOST, " => (high)", (void*)&int32_val_high, sizeof(int32_val_high));
438 /* TODO add support for big endian machines */
439 this->write_bytes_to_buffer(this,&int32_val_high,sizeof(u_int32_t));
440 this->write_bytes_to_buffer(this,&int32_val_low,sizeof(u_int32_t));
441 break;
442 }
443
444 case IKE_SPI:
445 {
446 /* 64 bit are written as they come :-) */
447 this->write_bytes_to_buffer(this,(this->data_struct + offset),sizeof(u_int64_t));
448 this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)(this->data_struct + offset), sizeof(u_int64_t));
449 break;
450 }
451
452 default:
453 this->logger->log(this->logger, ERROR, "U_INT Type %s is not supported", mapping_find(encoding_type_m,int_type));
454 return FAILED;
455 }
456 return SUCCESS;
457 }
458
459 /**
460 * Implements private_generator_t's generate_reserved_field function.
461 * See #private_generator_s.generate_reserved_field.
462 */
463 static status_t generate_reserved_field(private_generator_t *this,int bits)
464 {
465 status_t status;
466
467 /* only one bit or 8 bit fields are supported */
468 if ((bits != 1) && (bits != 8))
469 {
470 this->logger->log(this->logger, ERROR, "Reserved field of %d bits cannot be generated", bits);
471 return FAILED;
472 }
473 /* make sure enough space is available in buffer */
474 status = this->make_space_available(this,bits);
475 if (status != SUCCESS)
476 {
477 return status;
478 }
479
480 if (bits == 1)
481 {
482 /* one bit processing */
483 u_int8_t reserved_bit = ~(1 << (7 - this->current_bit));
484 *(this->out_position) = *(this->out_position) & reserved_bit;
485 if (this->current_bit == 0)
486 {
487 /* memory must be zero */
488 *(this->out_position) = 0x00;
489 }
490
491
492 this->current_bit++;
493 if (this->current_bit >= 8)
494 {
495 this->current_bit = this->current_bit % 8;
496 this->out_position++;
497 }
498 }
499 else
500 {
501 /* one byte processing*/
502 if (this->current_bit > 0)
503 {
504 this->logger->log(this->logger, ERROR,
505 "Reserved field cannot be written cause allignement of current bit is %d",
506 this->current_bit);
507 return FAILED;
508 }
509 *(this->out_position) = 0x00;
510 this->out_position++;
511 }
512
513 return SUCCESS;
514
515
516 }
517
518 /**
519 * Implements private_generator_t's generate_flag function.
520 * See #private_generator_s.generate_flag.
521 */
522 static status_t generate_flag (private_generator_t *this,u_int32_t offset)
523 {
524 status_t status;
525 /* value of current flag */
526 u_int8_t flag_value;
527 /* position of flag in current byte */
528 u_int8_t flag;
529
530 /* if the value in the data_struct is TRUE, flag_value is set to 1, 0 otherwise */
531 flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
532 /* get flag position */
533 flag = (flag_value << (7 - this->current_bit));
534
535 /* make sure one bit is available in buffer */
536 status = this->make_space_available(this,1);
537 if (status != SUCCESS)
538 {
539 return status;
540 }
541 if (this->current_bit == 0)
542 {
543 /* memory must be zero */
544 *(this->out_position) = 0x00;
545 }
546
547 *(this->out_position) = *(this->out_position) | flag;
548
549
550 this->logger->log(this->logger, RAW|MOST, " => 0x0%x", *(this->out_position));
551
552 this->current_bit++;
553 if (this->current_bit >= 8)
554 {
555 this->current_bit = this->current_bit % 8;
556 this->out_position++;
557 }
558 return SUCCESS;
559 }
560
561 /**
562 * Implements private_generator_t's generate_from_chunk function.
563 * See #private_generator_s.generate_from_chunk.
564 */
565 static status_t generate_from_chunk (private_generator_t *this,u_int32_t offset)
566 {
567 if (this->current_bit != 0)
568 {
569 this->logger->log(this->logger, ERROR, "can not generate a chunk at Bitpos %d", this->current_bit);
570 return FAILED;
571 }
572
573 /* position in buffer */
574 chunk_t *attribute_value = (chunk_t *)(this->data_struct + offset);
575
576 this->logger->log_chunk(this->logger, RAW|MOST, " =>", attribute_value);
577
578 /* use write_bytes_to_buffer function to do the job */
579 return this->write_bytes_to_buffer(this,attribute_value->ptr,attribute_value->len);
580
581 }
582
583 /**
584 * Implements private_generator_t's generator_context_make_space_available function.
585 * See #private_generator_s.generator_context_make_space_available.
586 */
587 static status_t make_space_available (private_generator_t *this, size_t bits)
588 {
589 while (((this->get_current_buffer_space(this) * 8) - this->current_bit) < bits)
590 {
591 /* must increase buffer */
592 u_int8_t *new_buffer;
593 size_t old_buffer_size = this->get_current_buffer_size(this);
594 size_t new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
595 size_t out_position_offset = ((this->out_position) - (this->buffer));
596
597 this->logger->log(this->logger, CONTROL|MOST, "increased gen buffer from %d to %d byte",
598 old_buffer_size, new_buffer_size);
599
600 /* Reallocate space for new buffer */
601 new_buffer = allocator_realloc(this->buffer,new_buffer_size);
602 if (new_buffer == NULL)
603 {
604 this->logger->log(this->logger, ERROR, "reallocation of gen buffer failed!!!");
605 return OUT_OF_RES;
606 }
607
608 this->buffer = new_buffer;
609
610 this->out_position = (this->buffer + out_position_offset);
611 this->roof_position = (this->buffer + new_buffer_size);
612 }
613 return SUCCESS;
614 }
615
616 /**
617 * Implements private_generator_t's write_bytes_to_buffer function.
618 * See #private_generator_s.write_bytes_to_buffer.
619 */
620 static status_t write_bytes_to_buffer (private_generator_t *this,void * bytes, size_t number_of_bytes)
621 {
622 int i;
623 status_t status;
624 u_int8_t *read_position = (u_int8_t *) bytes;
625
626 status = this->make_space_available(this,number_of_bytes * 8);
627 if (status != SUCCESS)
628 {
629 return status;
630 }
631
632 for (i = 0; i < number_of_bytes; i++)
633 {
634 *(this->out_position) = *(read_position);
635 read_position++;
636 this->out_position++;
637 }
638 return status;
639 }
640
641 /**
642 * Implements private_generator_t's write_bytes_to_buffer_at_offset function.
643 * See #private_generator_s.write_bytes_to_buffer_at_offset.
644 */
645 static status_t write_bytes_to_buffer_at_offset (private_generator_t *this,void * bytes,size_t number_of_bytes,u_int32_t offset)
646 {
647 int i;
648 status_t status;
649 u_int8_t *read_position = (u_int8_t *) bytes;
650 u_int8_t *write_position;
651 u_int32_t free_space_after_offset = (this->get_current_buffer_size(this) - offset);
652
653 /* check first if enough space for new data is available */
654 if (number_of_bytes > free_space_after_offset)
655 {
656 status = this->make_space_available(this,(number_of_bytes - free_space_after_offset) * 8);
657 }
658
659 write_position = this->buffer + offset;
660 for (i = 0; i < number_of_bytes; i++)
661 {
662 *(write_position) = *(read_position);
663 read_position++;
664 write_position++;
665 }
666 return SUCCESS;
667 }
668
669 /**
670 * Implements generator_t's write_chunk function.
671 * See #generator_s.write_chunk.
672 */
673 static status_t write_to_chunk (private_generator_t *this,chunk_t *data)
674 {
675 size_t data_length = this->get_current_data_length(this);
676 u_int32_t header_length_field = data_length;
677
678 /* write length into header length field */
679 if (this->header_length_position_offset > 0)
680 {
681 u_int32_t int32_val = htonl(header_length_field);
682 this->write_bytes_to_buffer_at_offset(this,&int32_val,sizeof(u_int32_t),this->header_length_position_offset);
683 }
684
685 if (this->current_bit > 0)
686 data_length++;
687 data->ptr = allocator_alloc(data_length);
688 if (data->ptr == NULL)
689 {
690 data->len = 0;
691 this->logger->log(this->logger, ERROR, "not enougth ressources to allocate chunk");
692 return OUT_OF_RES;
693 }
694 memcpy(data->ptr,this->buffer,data_length);
695 data->len = data_length;
696
697 this->logger->log_chunk(this->logger, RAW, "generated data of this parser", data);
698
699 return SUCCESS;
700 }
701
702 /**
703 * Implements generator_t's generate_payload function.
704 * See #generator_s.generate_payload.
705 */
706 static status_t generate_payload (private_generator_t *this,payload_t *payload)
707 {
708 int i;
709 status_t status;
710 this->data_struct = payload;
711 size_t rule_count;
712 encoding_rule_t *rules;
713 payload_type_t payload_type;
714 u_int8_t *payload_start;
715
716 /* get payload type */
717 payload_type = payload->get_type(payload);
718 /* spi size has to get reseted */
719 this->last_spi_size = 0;
720
721 payload_start = this->out_position;
722
723 this->logger->log(this->logger, CONTROL, "generating payload of type %s",
724 mapping_find(payload_type_m,payload_type));
725
726 /* each payload has its own encoding rules */
727 payload->get_encoding_rules(payload,&rules,&rule_count);
728
729 for (i = 0; i < rule_count;i++)
730 {
731 status = SUCCESS;
732 this->logger->log(this->logger, CONTROL|MORE, " generating rule %d %s",
733 i, mapping_find(encoding_type_m,rules[i].type));
734 switch (rules[i].type)
735 {
736 /* all u int values, IKE_SPI and ATTRIBUTE_TYPE are generated in generate_u_int_type */
737 case U_INT_4:
738 case U_INT_8:
739 case U_INT_16:
740 case U_INT_32:
741 case U_INT_64:
742 case IKE_SPI:
743 case ATTRIBUTE_TYPE:
744 {
745 status = this->generate_u_int_type(this,rules[i].type,rules[i].offset);
746 break;
747 }
748 case RESERVED_BIT:
749 {
750 status = this->generate_reserved_field(this,1);
751 break;
752 }
753 case RESERVED_BYTE:
754 {
755 status = this->generate_reserved_field(this,8);
756 break;
757 }
758 case FLAG:
759 {
760 status = this->generate_flag(this,rules[i].offset);
761 break;
762 }
763 case PAYLOAD_LENGTH:
764 {
765 /* position of payload lenght field is temporary stored */
766 this->last_payload_length_position_offset = this->get_current_buffer_offset(this);
767 /* payload length is generated like an U_INT_16 */
768 status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
769 break;
770 }
771 case HEADER_LENGTH:
772 {
773 /* position of header length field is temporary stored */
774 this->header_length_position_offset = this->get_current_buffer_offset(this);
775 /* header length is generated like an U_INT_32 */
776 status = this->generate_u_int_type(this,U_INT_32,rules[i].offset);
777 break;
778 }
779 case SPI_SIZE:
780 /* spi size is handled as 8 bit unsigned integer */
781 status = this->generate_u_int_type(this,U_INT_8,rules[i].offset);
782 /* last spi size is temporary stored */
783 this->last_spi_size = *((u_int8_t *)(this->data_struct + rules[i].offset));
784 break;
785 case SPI:
786 {
787 /* the SPI value is generated from chunk */
788 status = this->generate_from_chunk(this,rules[i].offset);
789 break;
790 }
791 case KEY_EXCHANGE_DATA:
792 {
793 /* the Key Exchange Data value is generated from chunk */
794 status = this->generate_from_chunk(this,rules[i].offset);
795 if (status != SUCCESS)
796 {
797 this->logger->log(this->logger, ERROR, "could no write key exchange data from chunk");
798 return status;
799 }
800
801 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
802 /* Length of KE_PAYLOAD is calculated */
803 u_int16_t length_of_ke_payload = KE_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
804
805 u_int16_t int16_val = htons(length_of_ke_payload);
806 status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
807 if (status != SUCCESS)
808 {
809 this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
810 return status;
811 }
812 break;
813 }
814 case NOTIFICATION_DATA:
815 {
816 /* the Notification Data value is generated from chunk */
817 status = this->generate_from_chunk(this,rules[i].offset);
818 if (status != SUCCESS)
819 {
820 this->logger->log(this->logger, ERROR, "Could not generate notification data from chunk");
821 return status;
822 }
823
824 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
825 /* Length of Notification PAYLOAD is calculated */
826 u_int16_t length_of_notify_payload = NOTIFY_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
827 length_of_notify_payload += this->last_spi_size;
828 u_int16_t int16_val = htons(length_of_notify_payload);
829
830 status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
831 if (status != SUCCESS)
832 {
833 this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
834 return status;
835 }
836 break;
837 }
838 case NONCE_DATA:
839 {
840 /* the Nonce Data value is generated from chunk */
841 status = this->generate_from_chunk(this, rules[i].offset);
842
843 if (status != SUCCESS)
844 {
845 this->logger->log(this->logger, ERROR, "could not write nonce data from chunk");
846 return status;
847 }
848
849 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
850 /* Length of nonce PAYLOAD is calculated */
851 u_int16_t length_of_nonce_payload = NONCE_PAYLOAD_HEADER_LENGTH + ((chunk_t *)(this->data_struct + rules[i].offset))->len;
852 u_int16_t int16_val = htons(length_of_nonce_payload);
853
854 status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
855 if (status != SUCCESS)
856 {
857 this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
858 return status;
859 }
860 break;
861 }
862 case PROPOSALS:
863 {
864 /* before iterative generate the transforms, store the current payload length position */
865 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
866 /* Length of SA_PAYLOAD is calculated */
867 u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
868 u_int16_t int16_val;
869 /* proposals are stored in a linked list and so accessed */
870 linked_list_t *proposals = *((linked_list_t **)(this->data_struct + rules[i].offset));
871
872 linked_list_iterator_t *iterator;
873 /* create forward iterator */
874 status = proposals->create_iterator(proposals,&iterator,TRUE);
875 if (status != SUCCESS)
876 {
877 this->logger->log(this->logger, ERROR, "could not create iterator for proposals");
878 return status;
879 }
880 /* every proposal is processed (iterative call )*/
881 while (iterator->has_next(iterator))
882 {
883 payload_t *current_proposal;
884 u_int32_t before_generate_position_offset;
885 u_int32_t after_generate_position_offset;
886
887 status = iterator->current(iterator,(void **)&current_proposal);
888 if (status != SUCCESS)
889 {
890 iterator->destroy(iterator);
891 return status;
892 }
893 before_generate_position_offset = this->get_current_buffer_offset(this);
894 status = this->public.generate_payload(&(this->public),current_proposal);
895 after_generate_position_offset = this->get_current_buffer_offset(this);
896 if (status != SUCCESS)
897 {
898 iterator->destroy(iterator);
899 return status;
900 }
901
902 /* increase size of transform */
903 length_of_sa_payload += (after_generate_position_offset - before_generate_position_offset);
904 }
905 iterator->destroy(iterator);
906
907 int16_val = htons(length_of_sa_payload);
908 status = this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
909 if (status != SUCCESS)
910 {
911 this->logger->log(this->logger, ERROR, "could not write payload length into buffer");
912 return status;
913 }
914 break;
915 }
916
917 case TRANSFORMS:
918 {
919 /* before iterative generate the transforms, store the current length position */
920 u_int32_t payload_length_position_offset = this->last_payload_length_position_offset;
921 u_int16_t length_of_proposal = PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
922 u_int16_t int16_val;
923 linked_list_t *transforms = *((linked_list_t **)(this->data_struct + rules[i].offset));
924 linked_list_iterator_t *iterator;
925
926 /* create forward iterator */
927 status = transforms->create_iterator(transforms,&iterator,TRUE);
928 if (status != SUCCESS)
929 {
930 return status;
931 }
932 while (iterator->has_next(iterator))
933 {
934 payload_t *current_transform;
935 u_int32_t before_generate_position_offset;
936 u_int32_t after_generate_position_offset;
937
938 status = iterator->current(iterator,(void **)&current_transform);
939 if (status != SUCCESS)
940 {
941 iterator->destroy(iterator);
942 return status;
943 }
944
945 before_generate_position_offset = this->get_current_buffer_offset(this);
946 status = this->public.generate_payload(&(this->public),current_transform);
947 after_generate_position_offset = this->get_current_buffer_offset(this);
948 if (status != SUCCESS)
949 {
950 iterator->destroy(iterator);
951 return status;
952 }
953
954 /* increase size of transform */
955 length_of_proposal += (after_generate_position_offset - before_generate_position_offset);
956 }
957
958 iterator->destroy(iterator);
959
960 int16_val = htons(length_of_proposal);
961 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),payload_length_position_offset);
962
963 break;
964 }
965 case TRANSFORM_ATTRIBUTES:
966 {
967 /* before iterative generate the transform attributes, store the current length position */
968 u_int32_t transform_length_position_offset = this->last_payload_length_position_offset;
969
970 u_int16_t length_of_transform = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
971 u_int16_t int16_val;
972 linked_list_t *transform_attributes =*((linked_list_t **)(this->data_struct + rules[i].offset));
973
974 linked_list_iterator_t *iterator;
975 /* create forward iterator */
976 status = transform_attributes->create_iterator(transform_attributes,&iterator,TRUE);
977 if (status != SUCCESS)
978 {
979 return status;
980 }
981 while (iterator->has_next(iterator))
982 {
983 payload_t *current_attribute;
984 u_int32_t before_generate_position_offset;
985 u_int32_t after_generate_position_offset;
986
987 status = iterator->current(iterator,(void **)&current_attribute);
988 if (status != SUCCESS)
989 {
990 iterator->destroy(iterator);
991 return status;
992 }
993
994 before_generate_position_offset = this->get_current_buffer_offset(this);
995 this->public.generate_payload(&(this->public),current_attribute);
996 after_generate_position_offset = this->get_current_buffer_offset(this);
997
998 /* increase size of transform */
999 length_of_transform += (after_generate_position_offset - before_generate_position_offset);
1000 }
1001
1002 iterator->destroy(iterator);
1003
1004 int16_val = htons(length_of_transform);
1005 this->write_bytes_to_buffer_at_offset(this,&int16_val,sizeof(u_int16_t),transform_length_position_offset);
1006
1007 break;
1008 }
1009 case ATTRIBUTE_FORMAT:
1010 {
1011 status = this->generate_flag(this,rules[i].offset);
1012 /* Attribute format is a flag which is stored in context*/
1013 this->attribute_format = *((bool *) (this->data_struct + rules[i].offset));
1014 break;
1015 }
1016
1017 case ATTRIBUTE_LENGTH_OR_VALUE:
1018 {
1019 if (this->attribute_format == FALSE)
1020 {
1021 status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
1022 /* this field hold the length of the attribute */
1023 this->attribute_length = *((u_int16_t *)(this->data_struct + rules[i].offset));
1024 }
1025 else
1026 {
1027 status = this->generate_u_int_type(this,U_INT_16,rules[i].offset);
1028 // status = this->write_bytes_to_buffer(this,(this->data_struct + rules[i].offset),2);
1029 }
1030 break;
1031 }
1032 case ATTRIBUTE_VALUE:
1033 {
1034 if (this->attribute_format == FALSE)
1035 {
1036 this->logger->log(this->logger, CONTROL|MOST, "attribute value has not fixed size");
1037 /* the attribute value is generated */
1038 status = this->generate_from_chunk(this,rules[i].offset);
1039 }
1040 break;
1041 }
1042 default:
1043 this->logger->log(this->logger, ERROR, "field type %s is not supported",
1044 mapping_find(encoding_type_m,rules[i].type));
1045 return NOT_SUPPORTED;
1046 }
1047 }
1048 this->logger->log_bytes(this->logger, RAW|MORE, "generated data for this payload",
1049 payload_start, this->out_position-payload_start);
1050
1051 return status;
1052 }
1053
1054 /**
1055 * Implements generator_t's destroy function.
1056 * See #generator_s.destroy.
1057 */
1058 static status_t destroy(private_generator_t *this)
1059 {
1060 allocator_free(this->buffer);
1061 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
1062 allocator_free(this);
1063 return SUCCESS;
1064 }
1065
1066 /*
1067 * Described in header
1068 */
1069 generator_t * generator_create()
1070 {
1071 private_generator_t *this;
1072
1073 this = allocator_alloc_thing(private_generator_t);
1074 if (this == NULL)
1075 {
1076 return NULL;
1077 }
1078
1079 /* initiate public functions */
1080 this->public.generate_payload = (status_t(*)(generator_t*, payload_t *)) generate_payload;
1081 this->public.destroy = (status_t(*)(generator_t*)) destroy;
1082 this->public.write_to_chunk = (status_t (*) (generator_t *,chunk_t *)) write_to_chunk;
1083
1084
1085 /* initiate private functions */
1086 this->get_current_buffer_size = get_current_buffer_size;
1087 this->get_current_buffer_space = get_current_buffer_space;
1088 this->get_current_data_length = get_current_data_length;
1089 this->get_current_buffer_offset = get_current_buffer_offset;
1090 this->generate_u_int_type = generate_u_int_type;
1091 this->generate_reserved_field = generate_reserved_field;
1092 this->generate_flag = generate_flag;
1093 this->generate_from_chunk = generate_from_chunk;
1094 this->make_space_available = make_space_available;
1095 this->write_bytes_to_buffer = write_bytes_to_buffer;
1096 this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset;
1097
1098
1099 /* allocate memory for buffer */
1100 this->buffer = allocator_alloc(GENERATOR_DATA_BUFFER_SIZE);
1101 if (this->buffer == NULL)
1102 {
1103 allocator_free(this);
1104 return NULL;
1105 }
1106
1107 /* initiate private variables */
1108 this->out_position = this->buffer;
1109 this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
1110 this->data_struct = NULL;
1111 this->current_bit = 0;
1112 this->last_payload_length_position_offset = 0;
1113 this->header_length_position_offset = 0;
1114 this->logger = global_logger_manager->create_logger(global_logger_manager,GENERATOR,NULL);
1115 this->logger->disable_level(this->logger, FULL);
1116 this->logger->enable_level(this->logger, CONTROL);
1117
1118 if (this->logger == NULL)
1119 {
1120 allocator_free(this->buffer);
1121 allocator_free(this);
1122 return NULL;
1123 }
1124 return &(this->public);
1125 }