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