]>
Commit | Line | Data |
---|---|---|
b82c0cab JH |
1 | /** |
2 | * @file generator.c | |
79538669 | 3 | * |
c7748338 | 4 | * @brief Generic generator class used to generate IKEv2-header and payloads. |
79538669 | 5 | * |
b82c0cab JH |
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> | |
762ce218 | 24 | #include <string.h> |
c7748338 | 25 | #include <arpa/inet.h> |
7330c172 | 26 | #include <stdio.h> |
b82c0cab | 27 | |
88878242 | 28 | |
b82c0cab JH |
29 | #include "generator.h" |
30 | ||
021c2322 MW |
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> | |
4a962238 MW |
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> | |
762ce218 | 43 | |
1e8bb886 JH |
44 | /** |
45 | * Private part of a generator_t object | |
46 | */ | |
47 | typedef struct private_generator_s private_generator_t; | |
762ce218 | 48 | |
1e8bb886 | 49 | struct private_generator_s { |
762ce218 | 50 | /** |
1e8bb886 | 51 | * Public part of a generator_t object |
762ce218 | 52 | */ |
1e8bb886 JH |
53 | generator_t public; |
54 | ||
55 | /* private functions and fields */ | |
c3dc6f1a | 56 | |
c3dc6f1a | 57 | |
762ce218 | 58 | /** |
7031a50b | 59 | * Generates a U_INT-Field type and writes it to buffer. |
1e8bb886 JH |
60 | * |
61 | * @param this private_generator_t object | |
62 | * @param int_type type of U_INT field (U_INT_4, U_INT_8, etc.) | |
7031a50b | 63 | * ATTRIBUTE_TYPE is also generated in this function |
1e8bb886 JH |
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 | |
762ce218 | 68 | */ |
1e8bb886 | 69 | status_t (*generate_u_int_type) (private_generator_t *this,encoding_type_t int_type,u_int32_t offset); |
c3dc6f1a | 70 | |
762ce218 | 71 | /** |
7031a50b JH |
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. | |
1e8bb886 JH |
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 | |
762ce218 | 113 | */ |
1e8bb886 JH |
114 | status_t (*generate_reserved_field) (private_generator_t *this,int bits); |
115 | ||
762ce218 | 116 | /** |
1e8bb886 JH |
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 | |
762ce218 | 124 | */ |
1e8bb886 JH |
125 | status_t (*generate_flag) (private_generator_t *this,u_int32_t offset); |
126 | ||
762ce218 | 127 | /** |
110dc83a JH |
128 | * Writes the current buffer content into a chunk_t |
129 | * | |
130 | * Memory of specific chunk_t gets allocated. | |
c3dc6f1a | 131 | * |
1e8bb886 | 132 | * @param this calling private_generator_t object |
110dc83a JH |
133 | * @param data pointer of chunk_t to write to |
134 | * @return | |
135 | * - SUCCESSFUL if succeeded | |
136 | * - OUT_OF_RES otherwise | |
762ce218 | 137 | */ |
1e8bb886 | 138 | status_t (*write_chunk) (private_generator_t *this,chunk_t *data); |
110dc83a | 139 | |
f561c205 JH |
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); | |
c3dc6f1a | 149 | |
762ce218 | 150 | /** |
c08ffafe JH |
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. | |
c3dc6f1a | 155 | * |
1e8bb886 | 156 | * @param this calling private_generator_t object |
c08ffafe JH |
157 | * @param bits number of bits to make available in buffer |
158 | * @return | |
159 | * - SUCCESSFUL if succeeded | |
160 | * - OUT_OF_RES otherwise | |
762ce218 | 161 | */ |
1e8bb886 | 162 | status_t (*make_space_available) (private_generator_t *this,size_t bits); |
c3dc6f1a | 163 | |
c08ffafe JH |
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 | * | |
1e8bb886 | 170 | * @param this calling private_generator_t object |
c08ffafe JH |
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 | */ | |
1e8bb886 JH |
177 | status_t (*write_bytes_to_buffer) (private_generator_t *this,void * bytes,size_t number_of_bytes); |
178 | ||
110dc83a | 179 | |
f3c01a28 JH |
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 | ||
b82c0cab | 195 | /** |
1e8bb886 | 196 | * Buffer used to generate the data into. |
b82c0cab | 197 | */ |
1e8bb886 | 198 | u_int8_t *buffer; |
79538669 | 199 | |
5f08382c | 200 | /** |
1e8bb886 | 201 | * Current write position in buffer (one byte aligned). |
5f08382c | 202 | */ |
1e8bb886 | 203 | u_int8_t *out_position; |
79538669 | 204 | |
5f08382c | 205 | /** |
1e8bb886 | 206 | * Position of last byte in buffer. |
5f08382c | 207 | */ |
1e8bb886 | 208 | u_int8_t *roof_position; |
79538669 | 209 | |
7330c172 | 210 | /** |
1e8bb886 | 211 | * Current bit writing to in current byte (between 0 and 7). |
7330c172 | 212 | */ |
1e8bb886 JH |
213 | size_t current_bit; |
214 | ||
7330c172 | 215 | /** |
1e8bb886 | 216 | * Associated data struct to read informations from. |
7330c172 | 217 | */ |
1e8bb886 JH |
218 | void * data_struct; |
219 | ||
f3c01a28 JH |
220 | /* |
221 | * Last payload length position offset in the buffer | |
222 | */ | |
223 | u_int32_t last_payload_length_position_offset; | |
224 | ||
2b9dd467 JH |
225 | /** |
226 | * Offset of the header length field in the buffer | |
227 | */ | |
228 | u_int32_t header_length_position_offset; | |
229 | ||
bcf0c3af JH |
230 | /** |
231 | * Last SPI size | |
232 | */ | |
233 | u_int8_t last_spi_size; | |
234 | ||
f561c205 JH |
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 | */ | |
f561c205 JH |
247 | u_int16_t attribute_length; |
248 | ||
5f08382c | 249 | /** |
1e8bb886 | 250 | * Associated Logger |
5f08382c | 251 | */ |
1e8bb886 | 252 | logger_t *logger; |
b82c0cab JH |
253 | }; |
254 | ||
7031a50b JH |
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); | |
7031a50b JH |
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 | ||
5f08382c | 294 | /** |
c08ffafe JH |
295 | * Implements private_generator_t's generate_u_int_type function. |
296 | * See #private_generator_s.generate_u_int_type. | |
5f08382c | 297 | */ |
1e8bb886 | 298 | static status_t generate_u_int_type (private_generator_t *this,encoding_type_t int_type,u_int32_t offset) |
5f08382c | 299 | { |
79538669 | 300 | size_t number_of_bits = 0; |
762ce218 | 301 | status_t status; |
c3dc6f1a | 302 | |
7031a50b JH |
303 | /* find out number of bits of each U_INT type to check for enough space |
304 | in buffer */ | |
5f08382c JH |
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; | |
f561c205 JH |
322 | case ATTRIBUTE_TYPE: |
323 | number_of_bits = 15; | |
324 | break; | |
fb71af18 JH |
325 | case IKE_SPI: |
326 | number_of_bits = 64; | |
327 | break; | |
328 | ||
5f08382c JH |
329 | default: |
330 | return FAILED; | |
331 | } | |
7031a50b | 332 | /* U_INT Types of multiple then 8 bits must be aligned */ |
1e8bb886 | 333 | if (((number_of_bits % 8) == 0) && (this->current_bit != 0)) |
74683cbd | 334 | { |
75ab0668 MW |
335 | this->logger->log(this->logger, ERROR, "U_INT Type %s is not 8 Bit aligned", |
336 | mapping_find(encoding_type_m,int_type)); | |
f561c205 | 337 | /* current bit has to be zero for values multiple of 8 bits */ |
74683cbd JH |
338 | return FAILED; |
339 | } | |
7031a50b JH |
340 | |
341 | /* make sure enough space is available in buffer */ | |
1e8bb886 | 342 | status = this->make_space_available(this,number_of_bits); |
762ce218 JH |
343 | if (status != SUCCESS) |
344 | { | |
345 | return status; | |
346 | } | |
7031a50b | 347 | /* now handle each u int type differently */ |
74683cbd | 348 | switch (int_type) |
762ce218 | 349 | { |
74683cbd JH |
350 | case U_INT_4: |
351 | { | |
1e8bb886 | 352 | if (this->current_bit == 0) |
c3dc6f1a | 353 | { |
7031a50b | 354 | /* highval of current byte in buffer has to be set to the new value*/ |
1e8bb886 | 355 | u_int8_t high_val = *((u_int8_t *)(this->data_struct + offset)) << 4; |
7031a50b | 356 | /* lowval in buffer is not changed */ |
1e8bb886 | 357 | u_int8_t low_val = *(this->out_position) & 0x0F; |
7031a50b | 358 | /* highval is set, low_val is not changed */ |
1e8bb886 | 359 | *(this->out_position) = high_val | low_val; |
75ab0668 | 360 | this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position)); |
74683cbd | 361 | /* write position is not changed, just bit position is moved */ |
1e8bb886 | 362 | this->current_bit = 4; |
74683cbd | 363 | } |
1e8bb886 | 364 | else if (this->current_bit == 4) |
74683cbd | 365 | { |
7031a50b | 366 | /* highval in buffer is not changed */ |
1e8bb886 | 367 | u_int high_val = *(this->out_position) & 0xF0; |
7031a50b | 368 | /* lowval of current byte in buffer has to be set to the new value*/ |
1e8bb886 JH |
369 | u_int low_val = *((u_int8_t *)(this->data_struct + offset)) & 0x0F; |
370 | *(this->out_position) = high_val | low_val; | |
75ab0668 | 371 | this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position)); |
1e8bb886 JH |
372 | this->out_position++; |
373 | this->current_bit = 0; | |
c3dc6f1a | 374 | |
74683cbd JH |
375 | } |
376 | else | |
377 | { | |
75ab0668 | 378 | this->logger->log(this->logger, ERROR, "U_INT_4 Type is not 4 Bit aligned"); |
74683cbd JH |
379 | /* 4 Bit integers must have a 4 bit alignment */ |
380 | return FAILED; | |
381 | }; | |
382 | break; | |
383 | } | |
74683cbd JH |
384 | case U_INT_8: |
385 | { | |
7031a50b | 386 | /* 8 bit values are written as they are */ |
1e8bb886 | 387 | *this->out_position = *((u_int8_t *)(this->data_struct + offset)); |
75ab0668 | 388 | this->logger->log(this->logger, RAW|MOST, " => 0x%x", *(this->out_position)); |
1e8bb886 | 389 | this->out_position++; |
74683cbd | 390 | break; |
c3dc6f1a | 391 | |
74683cbd | 392 | } |
f561c205 JH |
393 | case ATTRIBUTE_TYPE: |
394 | { | |
7031a50b | 395 | /* attribute type must not change first bit uf current byte ! */ |
f561c205 JH |
396 | if (this->current_bit != 1) |
397 | { | |
75ab0668 | 398 | this->logger->log(this->logger, ERROR, "ATTRIBUTE FORMAT flag is not set"); |
7031a50b | 399 | /* first bit has to be set! */ |
f561c205 JH |
400 | return FAILED; |
401 | } | |
7031a50b | 402 | /* get value of attribute format flag */ |
f561c205 | 403 | u_int8_t attribute_format_flag = *(this->out_position) & 0x80; |
7031a50b | 404 | /* get attribute type value as 16 bit integer*/ |
f561c205 | 405 | u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); |
7031a50b | 406 | /* last bit must be unset */ |
f561c205 JH |
407 | int16_val = int16_val & 0xFF7F; |
408 | ||
409 | int16_val = int16_val | attribute_format_flag; | |
75ab0668 | 410 | this->logger->log(this->logger, RAW|MOST, " => 0x%x", int16_val); |
7031a50b | 411 | /* write bytes to buffer (set bit is overwritten)*/ |
f561c205 JH |
412 | this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t)); |
413 | this->current_bit = 0; | |
414 | break; | |
415 | ||
416 | } | |
74683cbd JH |
417 | case U_INT_16: |
418 | { | |
1e8bb886 | 419 | u_int16_t int16_val = htons(*((u_int16_t*)(this->data_struct + offset))); |
75ab0668 | 420 | this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)&int16_val, sizeof(int16_val)); |
1e8bb886 | 421 | this->write_bytes_to_buffer(this,&int16_val,sizeof(u_int16_t)); |
74683cbd JH |
422 | break; |
423 | } | |
424 | case U_INT_32: | |
425 | { | |
1e8bb886 | 426 | u_int32_t int32_val = htonl(*((u_int32_t*)(this->data_struct + offset))); |
75ab0668 | 427 | this->logger->log_bytes(this->logger, RAW|MOST, " =>", (void*)&int32_val, sizeof(int32_val)); |
1e8bb886 | 428 | this->write_bytes_to_buffer(this,&int32_val,sizeof(u_int32_t)); |
74683cbd JH |
429 | break; |
430 | } | |
431 | case U_INT_64: | |
432 | { | |
7031a50b | 433 | /* 64 bit integers are written as two 32 bit integers */ |
1e8bb886 JH |
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)); | |
75ab0668 MW |
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)); | |
7031a50b | 438 | /* TODO add support for big endian machines */ |
1e8bb886 JH |
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)); | |
74683cbd JH |
441 | break; |
442 | } | |
fb71af18 JH |
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 | } | |
c3dc6f1a | 451 | |
74683cbd | 452 | default: |
75ab0668 | 453 | this->logger->log(this->logger, ERROR, "U_INT Type %s is not supported", mapping_find(encoding_type_m,int_type)); |
762ce218 | 454 | return FAILED; |
762ce218 | 455 | } |
5f08382c JH |
456 | return SUCCESS; |
457 | } | |
458 | ||
1e8bb886 JH |
459 | /** |
460 | * Implements private_generator_t's generate_reserved_field function. | |
461 | * See #private_generator_s.generate_reserved_field. | |
462 | */ | |
75ab0668 | 463 | static status_t generate_reserved_field(private_generator_t *this,int bits) |
7330c172 JH |
464 | { |
465 | status_t status; | |
466 | ||
7031a50b | 467 | /* only one bit or 8 bit fields are supported */ |
7330c172 JH |
468 | if ((bits != 1) && (bits != 8)) |
469 | { | |
75ab0668 | 470 | this->logger->log(this->logger, ERROR, "Reserved field of %d bits cannot be generated", bits); |
7330c172 JH |
471 | return FAILED; |
472 | } | |
7031a50b | 473 | /* make sure enough space is available in buffer */ |
1e8bb886 | 474 | status = this->make_space_available(this,bits); |
7330c172 JH |
475 | if (status != SUCCESS) |
476 | { | |
477 | return status; | |
478 | } | |
479 | ||
480 | if (bits == 1) | |
481 | { | |
7031a50b | 482 | /* one bit processing */ |
1e8bb886 | 483 | u_int8_t reserved_bit = ~(1 << (7 - this->current_bit)); |
1e8bb886 | 484 | *(this->out_position) = *(this->out_position) & reserved_bit; |
de257bc0 JH |
485 | if (this->current_bit == 0) |
486 | { | |
487 | /* memory must be zero */ | |
488 | *(this->out_position) = 0x00; | |
489 | } | |
490 | ||
491 | ||
1e8bb886 JH |
492 | this->current_bit++; |
493 | if (this->current_bit >= 8) | |
7330c172 | 494 | { |
1e8bb886 JH |
495 | this->current_bit = this->current_bit % 8; |
496 | this->out_position++; | |
7330c172 JH |
497 | } |
498 | } | |
499 | else | |
500 | { | |
7031a50b | 501 | /* one byte processing*/ |
1e8bb886 | 502 | if (this->current_bit > 0) |
7330c172 | 503 | { |
75ab0668 MW |
504 | this->logger->log(this->logger, ERROR, |
505 | "Reserved field cannot be written cause allignement of current bit is %d", | |
506 | this->current_bit); | |
7330c172 JH |
507 | return FAILED; |
508 | } | |
1e8bb886 JH |
509 | *(this->out_position) = 0x00; |
510 | this->out_position++; | |
7330c172 JH |
511 | } |
512 | ||
513 | return SUCCESS; | |
514 | ||
515 | ||
516 | } | |
517 | ||
1e8bb886 JH |
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) | |
7330c172 JH |
523 | { |
524 | status_t status; | |
7031a50b JH |
525 | /* value of current flag */ |
526 | u_int8_t flag_value; | |
527 | /* position of flag in current byte */ | |
528 | u_int8_t flag; | |
7330c172 | 529 | |
7031a50b JH |
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 */ | |
1e8bb886 | 536 | status = this->make_space_available(this,1); |
7330c172 JH |
537 | if (status != SUCCESS) |
538 | { | |
539 | return status; | |
540 | } | |
de257bc0 JH |
541 | if (this->current_bit == 0) |
542 | { | |
543 | /* memory must be zero */ | |
544 | *(this->out_position) = 0x00; | |
545 | } | |
7330c172 | 546 | |
1e8bb886 | 547 | *(this->out_position) = *(this->out_position) | flag; |
75ab0668 MW |
548 | |
549 | ||
550 | this->logger->log(this->logger, RAW|MOST, " => 0x0%x", *(this->out_position)); | |
7330c172 | 551 | |
1e8bb886 JH |
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 | ||
f561c205 JH |
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 | { | |
75ab0668 | 569 | this->logger->log(this->logger, ERROR, "can not generate a chunk at Bitpos %d", this->current_bit); |
f561c205 JH |
570 | return FAILED; |
571 | } | |
75ab0668 | 572 | |
7031a50b | 573 | /* position in buffer */ |
f561c205 JH |
574 | chunk_t *attribute_value = (chunk_t *)(this->data_struct + offset); |
575 | ||
75ab0668 MW |
576 | this->logger->log_chunk(this->logger, RAW|MOST, " =>", attribute_value); |
577 | ||
7031a50b JH |
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); | |
f561c205 JH |
580 | |
581 | } | |
582 | ||
1e8bb886 JH |
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 | { | |
7031a50b | 589 | while (((this->get_current_buffer_space(this) * 8) - this->current_bit) < bits) |
7330c172 | 590 | { |
7031a50b JH |
591 | /* must increase buffer */ |
592 | u_int8_t *new_buffer; | |
593 | size_t old_buffer_size = this->get_current_buffer_size(this); | |
1e8bb886 JH |
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)); | |
1e8bb886 | 596 | |
75ab0668 MW |
597 | this->logger->log(this->logger, CONTROL|MOST, "increased gen buffer from %d to %d byte", |
598 | old_buffer_size, new_buffer_size); | |
7031a50b JH |
599 | |
600 | /* Reallocate space for new buffer */ | |
1e8bb886 JH |
601 | new_buffer = allocator_realloc(this->buffer,new_buffer_size); |
602 | if (new_buffer == NULL) | |
603 | { | |
75ab0668 | 604 | this->logger->log(this->logger, ERROR, "reallocation of gen buffer failed!!!"); |
1e8bb886 JH |
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); | |
7330c172 JH |
612 | } |
613 | return SUCCESS; | |
614 | } | |
615 | ||
5f08382c | 616 | /** |
1e8bb886 JH |
617 | * Implements private_generator_t's write_bytes_to_buffer function. |
618 | * See #private_generator_s.write_bytes_to_buffer. | |
5f08382c | 619 | */ |
75ab0668 | 620 | static status_t write_bytes_to_buffer (private_generator_t *this,void * bytes, size_t number_of_bytes) |
5f08382c | 621 | { |
5f08382c | 622 | int i; |
762ce218 | 623 | status_t status; |
7031a50b JH |
624 | u_int8_t *read_position = (u_int8_t *) bytes; |
625 | ||
1e8bb886 | 626 | status = this->make_space_available(this,number_of_bytes * 8); |
1e8bb886 JH |
627 | if (status != SUCCESS) |
628 | { | |
629 | return status; | |
630 | } | |
631 | ||
632 | for (i = 0; i < number_of_bytes; i++) | |
5f08382c | 633 | { |
1e8bb886 JH |
634 | *(this->out_position) = *(read_position); |
635 | read_position++; | |
636 | this->out_position++; | |
637 | } | |
638 | return status; | |
639 | } | |
640 | ||
f3c01a28 JH |
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. | |
f3c01a28 JH |
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 | { | |
f3c01a28 | 647 | int i; |
7031a50b JH |
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 | } | |
f3c01a28 | 658 | |
7031a50b | 659 | write_position = this->buffer + offset; |
f3c01a28 JH |
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 | ||
1e8bb886 JH |
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 | { | |
7031a50b | 675 | size_t data_length = this->get_current_data_length(this); |
2b9dd467 JH |
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 | } | |
1e8bb886 JH |
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; | |
75ab0668 | 691 | this->logger->log(this->logger, ERROR, "not enougth ressources to allocate chunk"); |
5f08382c JH |
692 | return OUT_OF_RES; |
693 | } | |
1e8bb886 JH |
694 | memcpy(data->ptr,this->buffer,data_length); |
695 | data->len = data_length; | |
75ab0668 MW |
696 | |
697 | this->logger->log_chunk(this->logger, RAW, "generated data of this parser", data); | |
698 | ||
1e8bb886 JH |
699 | return SUCCESS; |
700 | } | |
701 | ||
1e8bb886 JH |
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; | |
7031a50b | 713 | payload_type_t payload_type; |
75ab0668 | 714 | u_int8_t *payload_start; |
1e8bb886 | 715 | |
7031a50b JH |
716 | /* get payload type */ |
717 | payload_type = payload->get_type(payload); | |
8166bcec JH |
718 | /* spi size has to get reseted */ |
719 | this->last_spi_size = 0; | |
1e8bb886 | 720 | |
75ab0668 MW |
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)); | |
1e8bb886 | 725 | |
7031a50b | 726 | /* each payload has its own encoding rules */ |
1e8bb886 JH |
727 | payload->get_encoding_rules(payload,&rules,&rule_count); |
728 | ||
729 | for (i = 0; i < rule_count;i++) | |
5f08382c | 730 | { |
762ce218 | 731 | status = SUCCESS; |
75ab0668 MW |
732 | this->logger->log(this->logger, CONTROL|MORE, " generating rule %d %s", |
733 | i, mapping_find(encoding_type_m,rules[i].type)); | |
1e8bb886 | 734 | switch (rules[i].type) |
5f08382c | 735 | { |
fb71af18 | 736 | /* all u int values, IKE_SPI and ATTRIBUTE_TYPE are generated in generate_u_int_type */ |
5f08382c JH |
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: | |
fb71af18 | 742 | case IKE_SPI: |
7031a50b JH |
743 | case ATTRIBUTE_TYPE: |
744 | { | |
1e8bb886 | 745 | status = this->generate_u_int_type(this,rules[i].type,rules[i].offset); |
5f08382c | 746 | break; |
7031a50b | 747 | } |
5f08382c | 748 | case RESERVED_BIT: |
e6fbf1d2 | 749 | { |
1e8bb886 | 750 | status = this->generate_reserved_field(this,1); |
e6fbf1d2 JH |
751 | break; |
752 | } | |
5f08382c | 753 | case RESERVED_BYTE: |
e6fbf1d2 | 754 | { |
1e8bb886 | 755 | status = this->generate_reserved_field(this,8); |
e6fbf1d2 | 756 | break; |
7330c172 | 757 | } |
5f08382c | 758 | case FLAG: |
e6fbf1d2 | 759 | { |
1e8bb886 | 760 | status = this->generate_flag(this,rules[i].offset); |
e6fbf1d2 JH |
761 | break; |
762 | } | |
1b89ef11 | 763 | case PAYLOAD_LENGTH: |
7031a50b JH |
764 | { |
765 | /* position of payload lenght field is temporary stored */ | |
766 | this->last_payload_length_position_offset = this->get_current_buffer_offset(this); | |
1b89ef11 JH |
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; | |
7031a50b | 770 | } |
1b89ef11 | 771 | case HEADER_LENGTH: |
7031a50b JH |
772 | { |
773 | /* position of header length field is temporary stored */ | |
774 | this->header_length_position_offset = this->get_current_buffer_offset(this); | |
1b89ef11 | 775 | /* header length is generated like an U_INT_32 */ |
1e8bb886 | 776 | status = this->generate_u_int_type(this,U_INT_32,rules[i].offset); |
7330c172 | 777 | break; |
7031a50b | 778 | } |
5f08382c | 779 | case SPI_SIZE: |
bcf0c3af JH |
780 | /* spi size is handled as 8 bit unsigned integer */ |
781 | status = this->generate_u_int_type(this,U_INT_8,rules[i].offset); | |
7031a50b | 782 | /* last spi size is temporary stored */ |
bcf0c3af | 783 | this->last_spi_size = *((u_int8_t *)(this->data_struct + rules[i].offset)); |
f3c01a28 | 784 | break; |
bcf0c3af JH |
785 | case SPI: |
786 | { | |
7031a50b | 787 | /* the SPI value is generated from chunk */ |
bcf0c3af JH |
788 | status = this->generate_from_chunk(this,rules[i].offset); |
789 | break; | |
790 | } | |
113f461e JH |
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 | { | |
75ab0668 | 797 | this->logger->log(this->logger, ERROR, "could no write key exchange data from chunk"); |
113f461e JH |
798 | return status; |
799 | } | |
800 | ||
113f461e JH |
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 | { | |
75ab0668 | 809 | this->logger->log(this->logger, ERROR, "could not write payload length into buffer"); |
113f461e JH |
810 | return status; |
811 | } | |
812 | break; | |
8166bcec JH |
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 | { | |
75ab0668 | 820 | this->logger->log(this->logger, ERROR, "Could not generate notification data from chunk"); |
8166bcec JH |
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 | { | |
75ab0668 | 833 | this->logger->log(this->logger, ERROR, "could not write payload length into buffer"); |
8166bcec JH |
834 | return status; |
835 | } | |
836 | break; | |
837 | } | |
2a489f33 JH |
838 | case NONCE_DATA: |
839 | { | |
840 | /* the Nonce Data value is generated from chunk */ | |
75ab0668 MW |
841 | status = this->generate_from_chunk(this, rules[i].offset); |
842 | ||
2a489f33 JH |
843 | if (status != SUCCESS) |
844 | { | |
75ab0668 | 845 | this->logger->log(this->logger, ERROR, "could not write nonce data from chunk"); |
2a489f33 JH |
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 | { | |
75ab0668 | 857 | this->logger->log(this->logger, ERROR, "could not write payload length into buffer"); |
2a489f33 JH |
858 | return status; |
859 | } | |
860 | break; | |
861 | } | |
7f613a4b JH |
862 | case PROPOSALS: |
863 | { | |
8bf27ddf | 864 | /* before iterative generate the transforms, store the current payload length position */ |
7f613a4b | 865 | u_int32_t payload_length_position_offset = this->last_payload_length_position_offset; |
8bf27ddf | 866 | /* Length of SA_PAYLOAD is calculated */ |
7f613a4b JH |
867 | u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH; |
868 | u_int16_t int16_val; | |
8bf27ddf | 869 | /* proposals are stored in a linked list and so accessed */ |
7f613a4b JH |
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 | { | |
75ab0668 | 877 | this->logger->log(this->logger, ERROR, "could not create iterator for proposals"); |
7f613a4b JH |
878 | return status; |
879 | } | |
8bf27ddf | 880 | /* every proposal is processed (iterative call )*/ |
7f613a4b JH |
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 **)¤t_proposal); | |
888 | if (status != SUCCESS) | |
889 | { | |
890 | iterator->destroy(iterator); | |
891 | return status; | |
892 | } | |
8bf27ddf | 893 | before_generate_position_offset = this->get_current_buffer_offset(this); |
7f613a4b | 894 | status = this->public.generate_payload(&(this->public),current_proposal); |
8bf27ddf | 895 | after_generate_position_offset = this->get_current_buffer_offset(this); |
7f613a4b JH |
896 | if (status != SUCCESS) |
897 | { | |
8bf27ddf | 898 | iterator->destroy(iterator); |
7f613a4b JH |
899 | return status; |
900 | } | |
901 | ||
902 | /* increase size of transform */ | |
903 | length_of_sa_payload += (after_generate_position_offset - before_generate_position_offset); | |
904 | } | |
7f613a4b | 905 | iterator->destroy(iterator); |
7f613a4b JH |
906 | |
907 | int16_val = htons(length_of_sa_payload); | |
8bf27ddf JH |
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 | { | |
75ab0668 | 911 | this->logger->log(this->logger, ERROR, "could not write payload length into buffer"); |
8bf27ddf JH |
912 | return status; |
913 | } | |
7f613a4b JH |
914 | break; |
915 | } | |
916 | ||
bcf0c3af | 917 | case TRANSFORMS: |
8bf27ddf | 918 | { |
bcf0c3af JH |
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; | |
bcf0c3af JH |
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)); | |
bcf0c3af | 924 | linked_list_iterator_t *iterator; |
75ab0668 | 925 | |
bcf0c3af JH |
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 **)¤t_transform); | |
939 | if (status != SUCCESS) | |
940 | { | |
941 | iterator->destroy(iterator); | |
942 | return status; | |
943 | } | |
944 | ||
8bf27ddf | 945 | before_generate_position_offset = this->get_current_buffer_offset(this); |
7f613a4b | 946 | status = this->public.generate_payload(&(this->public),current_transform); |
8bf27ddf | 947 | after_generate_position_offset = this->get_current_buffer_offset(this); |
7f613a4b JH |
948 | if (status != SUCCESS) |
949 | { | |
8bf27ddf | 950 | iterator->destroy(iterator); |
7f613a4b JH |
951 | return status; |
952 | } | |
bcf0c3af JH |
953 | |
954 | /* increase size of transform */ | |
955 | length_of_proposal += (after_generate_position_offset - before_generate_position_offset); | |
956 | } | |
957 | ||
958 | iterator->destroy(iterator); | |
75ab0668 | 959 | |
bcf0c3af JH |
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 | } | |
f3c01a28 JH |
965 | case TRANSFORM_ATTRIBUTES: |
966 | { | |
bcf0c3af | 967 | /* before iterative generate the transform attributes, store the current length position */ |
f3c01a28 JH |
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; | |
bcf0c3af | 986 | |
f3c01a28 JH |
987 | status = iterator->current(iterator,(void **)¤t_attribute); |
988 | if (status != SUCCESS) | |
989 | { | |
990 | iterator->destroy(iterator); | |
991 | return status; | |
992 | } | |
993 | ||
8bf27ddf | 994 | before_generate_position_offset = this->get_current_buffer_offset(this); |
f3c01a28 | 995 | this->public.generate_payload(&(this->public),current_attribute); |
8bf27ddf | 996 | after_generate_position_offset = this->get_current_buffer_offset(this); |
f3c01a28 JH |
997 | |
998 | /* increase size of transform */ | |
999 | length_of_transform += (after_generate_position_offset - before_generate_position_offset); | |
1000 | } | |
1001 | ||
1002 | iterator->destroy(iterator); | |
f561c205 | 1003 | |
f3c01a28 JH |
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 | } | |
f561c205 JH |
1009 | case ATTRIBUTE_FORMAT: |
1010 | { | |
f561c205 | 1011 | status = this->generate_flag(this,rules[i].offset); |
8bf27ddf | 1012 | /* Attribute format is a flag which is stored in context*/ |
f561c205 JH |
1013 | this->attribute_format = *((bool *) (this->data_struct + rules[i].offset)); |
1014 | break; | |
1015 | } | |
7031a50b | 1016 | |
f561c205 JH |
1017 | case ATTRIBUTE_LENGTH_OR_VALUE: |
1018 | { | |
f561c205 JH |
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 | { | |
daa1c00e MW |
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); | |
f561c205 | 1029 | } |
5f08382c | 1030 | break; |
f561c205 JH |
1031 | } |
1032 | case ATTRIBUTE_VALUE: | |
1033 | { | |
1034 | if (this->attribute_format == FALSE) | |
1035 | { | |
75ab0668 | 1036 | this->logger->log(this->logger, CONTROL|MOST, "attribute value has not fixed size"); |
f561c205 JH |
1037 | /* the attribute value is generated */ |
1038 | status = this->generate_from_chunk(this,rules[i].offset); | |
1039 | } | |
1040 | break; | |
1041 | } | |
1042 | default: | |
75ab0668 MW |
1043 | this->logger->log(this->logger, ERROR, "field type %s is not supported", |
1044 | mapping_find(encoding_type_m,rules[i].type)); | |
f561c205 | 1045 | return NOT_SUPPORTED; |
5f08382c | 1046 | } |
5f08382c | 1047 | } |
75ab0668 MW |
1048 | this->logger->log_bytes(this->logger, RAW|MORE, "generated data for this payload", |
1049 | payload_start, this->out_position-payload_start); | |
79538669 | 1050 | |
762ce218 | 1051 | return status; |
b82c0cab JH |
1052 | } |
1053 | ||
1054 | /** | |
c08ffafe JH |
1055 | * Implements generator_t's destroy function. |
1056 | * See #generator_s.destroy. | |
b82c0cab JH |
1057 | */ |
1058 | static status_t destroy(private_generator_t *this) | |
1059 | { | |
1e8bb886 JH |
1060 | allocator_free(this->buffer); |
1061 | global_logger_manager->destroy_logger(global_logger_manager,this->logger); | |
79538669 | 1062 | allocator_free(this); |
b82c0cab JH |
1063 | return SUCCESS; |
1064 | } | |
1065 | ||
5f08382c JH |
1066 | /* |
1067 | * Described in header | |
1068 | */ | |
1e8bb886 | 1069 | generator_t * generator_create() |
b82c0cab | 1070 | { |
5f08382c | 1071 | private_generator_t *this; |
79538669 | 1072 | |
6c4b815f | 1073 | this = allocator_alloc_thing(private_generator_t); |
5f08382c JH |
1074 | if (this == NULL) |
1075 | { | |
1076 | return NULL; | |
1077 | } | |
79538669 | 1078 | |
762ce218 | 1079 | /* initiate public functions */ |
1e8bb886 | 1080 | this->public.generate_payload = (status_t(*)(generator_t*, payload_t *)) generate_payload; |
b82c0cab | 1081 | this->public.destroy = (status_t(*)(generator_t*)) destroy; |
1e8bb886 JH |
1082 | this->public.write_to_chunk = (status_t (*) (generator_t *,chunk_t *)) write_to_chunk; |
1083 | ||
1084 | ||
762ce218 | 1085 | /* initiate private functions */ |
7031a50b JH |
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; | |
5f08382c | 1090 | this->generate_u_int_type = generate_u_int_type; |
7330c172 JH |
1091 | this->generate_reserved_field = generate_reserved_field; |
1092 | this->generate_flag = generate_flag; | |
f561c205 | 1093 | this->generate_from_chunk = generate_from_chunk; |
1e8bb886 JH |
1094 | this->make_space_available = make_space_available; |
1095 | this->write_bytes_to_buffer = write_bytes_to_buffer; | |
f3c01a28 | 1096 | this->write_bytes_to_buffer_at_offset = write_bytes_to_buffer_at_offset; |
79538669 | 1097 | |
79538669 | 1098 | |
1e8bb886 JH |
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; | |
f3c01a28 | 1112 | this->last_payload_length_position_offset = 0; |
2b9dd467 | 1113 | this->header_length_position_offset = 0; |
1e8bb886 | 1114 | this->logger = global_logger_manager->create_logger(global_logger_manager,GENERATOR,NULL); |
75ab0668 MW |
1115 | this->logger->disable_level(this->logger, FULL); |
1116 | this->logger->enable_level(this->logger, CONTROL); | |
8bf27ddf JH |
1117 | |
1118 | if (this->logger == NULL) | |
1119 | { | |
1120 | allocator_free(this->buffer); | |
1121 | allocator_free(this); | |
1122 | return NULL; | |
1123 | } | |
b82c0cab JH |
1124 | return &(this->public); |
1125 | } |