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