payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / libcharon / encoding / generator.c
1 /*
2 * Copyright (C) 2011 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <arpa/inet.h>
21 #include <stdio.h>
22
23 #include "generator.h"
24
25 #include <library.h>
26 #include <daemon.h>
27 #include <collections/linked_list.h>
28 #include <encoding/payloads/payload.h>
29 #include <encoding/payloads/proposal_substructure.h>
30 #include <encoding/payloads/transform_substructure.h>
31 #include <encoding/payloads/sa_payload.h>
32 #include <encoding/payloads/ke_payload.h>
33 #include <encoding/payloads/notify_payload.h>
34 #include <encoding/payloads/nonce_payload.h>
35 #include <encoding/payloads/id_payload.h>
36 #include <encoding/payloads/auth_payload.h>
37 #include <encoding/payloads/cert_payload.h>
38 #include <encoding/payloads/certreq_payload.h>
39 #include <encoding/payloads/ts_payload.h>
40 #include <encoding/payloads/delete_payload.h>
41 #include <encoding/payloads/vendor_id_payload.h>
42 #include <encoding/payloads/cp_payload.h>
43 #include <encoding/payloads/configuration_attribute.h>
44 #include <encoding/payloads/eap_payload.h>
45 #include <encoding/payloads/unknown_payload.h>
46
47 /**
48 * Generating is done in a data buffer.
49 * This is the start size of this buffer in bytes.
50 */
51 #define GENERATOR_DATA_BUFFER_SIZE 500
52
53 /**
54 * Number of bytes to increase the buffer, if it is too small.
55 */
56 #define GENERATOR_DATA_BUFFER_INCREASE_VALUE 500
57
58 typedef struct private_generator_t private_generator_t;
59
60 /**
61 * Private part of a generator_t object.
62 */
63 struct private_generator_t {
64 /**
65 * Public part of a generator_t object.
66 */
67 generator_t public;
68
69 /**
70 * Buffer used to generate the data into.
71 */
72 u_int8_t *buffer;
73
74 /**
75 * Current write position in buffer (one byte aligned).
76 */
77 u_int8_t *out_position;
78
79 /**
80 * Position of last byte in buffer.
81 */
82 u_int8_t *roof_position;
83
84 /**
85 * Current bit writing to in current byte (between 0 and 7).
86 */
87 u_int8_t current_bit;
88
89 /**
90 * Associated data struct to read informations from.
91 */
92 void *data_struct;
93
94 /**
95 * Offset of the header length field in the buffer.
96 */
97 u_int32_t header_length_offset;
98
99 /**
100 * Attribute format of the last generated transform attribute.
101 *
102 * Used to check if a variable value field is used or not for
103 * the transform attribute value.
104 */
105 bool attribute_format;
106
107 /**
108 * Depending on the value of attribute_format this field is used
109 * to hold the length of the transform attribute in bytes.
110 */
111 u_int16_t attribute_length;
112
113 /**
114 * TRUE, if debug messages should be logged during generation.
115 */
116 bool debug;
117 };
118
119 /**
120 * Get size of current buffer in bytes.
121 */
122 static int get_size(private_generator_t *this)
123 {
124 return this->roof_position - this->buffer;
125 }
126
127 /**
128 * Get free space of current buffer in bytes.
129 */
130 static int get_space(private_generator_t *this)
131 {
132 return this->roof_position - this->out_position;
133 }
134
135 /**
136 * Get length of data in buffer (in bytes).
137 */
138 static int get_length(private_generator_t *this)
139 {
140 return this->out_position - this->buffer;
141 }
142
143 /**
144 * Get current offset in buffer (in bytes).
145 */
146 static u_int32_t get_offset(private_generator_t *this)
147 {
148 return this->out_position - this->buffer;
149 }
150
151 /**
152 * Makes sure enough space is available in buffer to store amount of bits.
153 */
154 static void make_space_available(private_generator_t *this, int bits)
155 {
156 while ((get_space(this) * 8 - this->current_bit) < bits)
157 {
158 int old_buffer_size, new_buffer_size, out_position_offset;
159
160 old_buffer_size = get_size(this);
161 new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
162 out_position_offset = this->out_position - this->buffer;
163
164 if (this->debug)
165 {
166 DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
167 old_buffer_size, new_buffer_size);
168 }
169
170 this->buffer = realloc(this->buffer,new_buffer_size);
171 this->out_position = (this->buffer + out_position_offset);
172 this->roof_position = (this->buffer + new_buffer_size);
173 }
174 }
175
176 /**
177 * Writes a specific amount of byte into the buffer.
178 */
179 static void write_bytes_to_buffer(private_generator_t *this, void *bytes,
180 int number_of_bytes)
181 {
182 int i;
183 u_int8_t *read_position = (u_int8_t *)bytes;
184
185 make_space_available(this, number_of_bytes * 8);
186
187 for (i = 0; i < number_of_bytes; i++)
188 {
189 *(this->out_position) = *(read_position);
190 read_position++;
191 this->out_position++;
192 }
193 }
194
195 /**
196 * Generates a U_INT-Field type and writes it to buffer.
197 */
198 static void generate_u_int_type(private_generator_t *this,
199 encoding_type_t int_type,u_int32_t offset)
200 {
201 int number_of_bits = 0;
202
203 /* find out number of bits of each U_INT type to check for enough space */
204 switch (int_type)
205 {
206 case U_INT_4:
207 number_of_bits = 4;
208 break;
209 case TS_TYPE:
210 case RESERVED_BYTE:
211 case SPI_SIZE:
212 case U_INT_8:
213 number_of_bits = 8;
214 break;
215 case U_INT_16:
216 case PAYLOAD_LENGTH:
217 case ATTRIBUTE_LENGTH:
218 number_of_bits = 16;
219 break;
220 case U_INT_32:
221 number_of_bits = 32;
222 break;
223 case ATTRIBUTE_TYPE:
224 number_of_bits = 15;
225 break;
226 case IKE_SPI:
227 number_of_bits = 64;
228 break;
229 default:
230 DBG1(DBG_ENC, "U_INT Type %N is not supported",
231 encoding_type_names, int_type);
232 return;
233 }
234 if ((number_of_bits % 8) == 0 && this->current_bit != 0)
235 {
236 DBG1(DBG_ENC, "U_INT Type %N is not 8 Bit aligned",
237 encoding_type_names, int_type);
238 return;
239 }
240
241 make_space_available(this, number_of_bits);
242 switch (int_type)
243 {
244 case U_INT_4:
245 {
246 u_int8_t high, low;
247
248 if (this->current_bit == 0)
249 {
250 /* high of current byte in buffer has to be set to the new value*/
251 high = *((u_int8_t *)(this->data_struct + offset)) << 4;
252 /* low in buffer is not changed */
253 low = *(this->out_position) & 0x0F;
254 /* high is set, low_val is not changed */
255 *(this->out_position) = high | low;
256 if (this->debug)
257 {
258 DBG3(DBG_ENC, " => %d", *(this->out_position));
259 }
260 /* write position is not changed, just bit position is moved */
261 this->current_bit = 4;
262 }
263 else if (this->current_bit == 4)
264 {
265 /* high in buffer is not changed */
266 high = *(this->out_position) & 0xF0;
267 /* low of current byte in buffer has to be set to the new value*/
268 low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
269 *(this->out_position) = high | low;
270 if (this->debug)
271 {
272 DBG3(DBG_ENC, " => %d", *(this->out_position));
273 }
274 this->out_position++;
275 this->current_bit = 0;
276 }
277 else
278 {
279 DBG1(DBG_ENC, "U_INT_4 Type is not 4 Bit aligned");
280 /* 4 Bit integers must have a 4 bit alignment */
281 return;
282 }
283 break;
284 }
285 case TS_TYPE:
286 case RESERVED_BYTE:
287 case SPI_SIZE:
288 case U_INT_8:
289 {
290 /* 8 bit values are written as they are */
291 *this->out_position = *((u_int8_t *)(this->data_struct + offset));
292 if (this->debug)
293 {
294 DBG3(DBG_ENC, " => %d", *(this->out_position));
295 }
296 this->out_position++;
297 break;
298 }
299 case ATTRIBUTE_TYPE:
300 {
301 u_int8_t attribute_format_flag;
302 u_int16_t val;
303
304 /* attribute type must not change first bit of current byte */
305 if (this->current_bit != 1)
306 {
307 DBG1(DBG_ENC, "ATTRIBUTE FORMAT flag is not set");
308 return;
309 }
310 attribute_format_flag = *(this->out_position) & 0x80;
311 /* get attribute type value as 16 bit integer*/
312 val = *((u_int16_t*)(this->data_struct + offset));
313 /* unset most significant bit */
314 val &= 0x7FFF;
315 if (attribute_format_flag)
316 {
317 val |= 0x8000;
318 }
319 val = htons(val);
320 if (this->debug)
321 {
322 DBG3(DBG_ENC, " => %d", val);
323 }
324 /* write bytes to buffer (set bit is overwritten) */
325 write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
326 this->current_bit = 0;
327 break;
328
329 }
330 case U_INT_16:
331 case PAYLOAD_LENGTH:
332 case ATTRIBUTE_LENGTH:
333 {
334 u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
335 if (this->debug)
336 {
337 DBG3(DBG_ENC, " %b", &val, sizeof(u_int16_t));
338 }
339 write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
340 break;
341 }
342 case U_INT_32:
343 {
344 u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
345 if (this->debug)
346 {
347 DBG3(DBG_ENC, " %b", &val, sizeof(u_int32_t));
348 }
349 write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
350 break;
351 }
352 case IKE_SPI:
353 {
354 /* 64 bit are written as-is, no host order conversion */
355 write_bytes_to_buffer(this, this->data_struct + offset,
356 sizeof(u_int64_t));
357 if (this->debug)
358 {
359 DBG3(DBG_ENC, " %b", this->data_struct + offset,
360 sizeof(u_int64_t));
361 }
362 break;
363 }
364 default:
365 {
366 DBG1(DBG_ENC, "U_INT Type %N is not supported",
367 encoding_type_names, int_type);
368 return;
369 }
370 }
371 }
372
373 /**
374 * Generate a FLAG filed
375 */
376 static void generate_flag(private_generator_t *this, u_int32_t offset)
377 {
378 u_int8_t flag_value;
379 u_int8_t flag;
380
381 flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
382 /* get flag position */
383 flag = (flag_value << (7 - this->current_bit));
384
385 /* make sure one bit is available in buffer */
386 make_space_available(this, 1);
387 if (this->current_bit == 0)
388 {
389 /* memory must be zero */
390 *(this->out_position) = 0x00;
391 }
392
393 *(this->out_position) = *(this->out_position) | flag;
394 if (this->debug)
395 {
396 DBG3(DBG_ENC, " => %d", *this->out_position);
397 }
398
399 this->current_bit++;
400 if (this->current_bit >= 8)
401 {
402 this->current_bit = this->current_bit % 8;
403 this->out_position++;
404 }
405 }
406
407 /**
408 * Generates a bytestream from a chunk_t.
409 */
410 static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
411 {
412 chunk_t *value;
413
414 if (this->current_bit != 0)
415 {
416 DBG1(DBG_ENC, "can not generate a chunk at bitpos %d",
417 this->current_bit);
418 return ;
419 }
420
421 value = (chunk_t *)(this->data_struct + offset);
422 if (this->debug)
423 {
424 DBG3(DBG_ENC, " %B", value);
425 }
426
427 write_bytes_to_buffer(this, value->ptr, value->len);
428 }
429
430 METHOD(generator_t, get_chunk, chunk_t,
431 private_generator_t *this, u_int32_t **lenpos)
432 {
433 chunk_t data;
434
435 *lenpos = (u_int32_t*)(this->buffer + this->header_length_offset);
436 data = chunk_create(this->buffer, get_length(this));
437 if (this->debug)
438 {
439 DBG3(DBG_ENC, "generated data of this generator %B", &data);
440 }
441 return data;
442 }
443
444 METHOD(generator_t, generate_payload, void,
445 private_generator_t *this, payload_t *payload)
446 {
447 int i, offset_start, rule_count;
448 encoding_rule_t *rules;
449 payload_type_t payload_type;
450
451 this->data_struct = payload;
452 payload_type = payload->get_type(payload);
453
454 offset_start = this->out_position - this->buffer;
455
456 if (this->debug)
457 {
458 DBG2(DBG_ENC, "generating payload of type %N",
459 payload_type_names, payload_type);
460 }
461
462 /* each payload has its own encoding rules */
463 rule_count = payload->get_encoding_rules(payload, &rules);
464
465 for (i = 0; i < rule_count;i++)
466 {
467 if (this->debug)
468 {
469 DBG2(DBG_ENC, " generating rule %d %N",
470 i, encoding_type_names, rules[i].type);
471 }
472 switch ((int)rules[i].type)
473 {
474 case U_INT_4:
475 case U_INT_8:
476 case U_INT_16:
477 case U_INT_32:
478 case PAYLOAD_LENGTH:
479 case IKE_SPI:
480 case RESERVED_BYTE:
481 case SPI_SIZE:
482 case TS_TYPE:
483 case ATTRIBUTE_TYPE:
484 case ATTRIBUTE_LENGTH:
485 generate_u_int_type(this, rules[i].type, rules[i].offset);
486 break;
487 case RESERVED_BIT:
488 case FLAG:
489 generate_flag(this, rules[i].offset);
490 break;
491 case HEADER_LENGTH:
492 this->header_length_offset = get_offset(this);
493 generate_u_int_type(this, U_INT_32, rules[i].offset);
494 break;
495 case ADDRESS:
496 case SPI:
497 case CHUNK_DATA:
498 case ENCRYPTED_DATA:
499 generate_from_chunk(this, rules[i].offset);
500 break;
501 case PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE:
502 case PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE:
503 case PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE:
504 case PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE:
505 case PAYLOAD_LIST + PLV2_TRANSFORM_ATTRIBUTE:
506 case PAYLOAD_LIST + PLV1_TRANSFORM_ATTRIBUTE:
507 case PAYLOAD_LIST + PLV2_CONFIGURATION_ATTRIBUTE:
508 case PAYLOAD_LIST + PLV1_CONFIGURATION_ATTRIBUTE:
509 case PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE:
510 {
511 linked_list_t *proposals;
512 enumerator_t *enumerator;
513 payload_t *proposal;
514
515 proposals = *((linked_list_t **)
516 (this->data_struct + rules[i].offset));
517 enumerator = proposals->create_enumerator(proposals);
518 while (enumerator->enumerate(enumerator, &proposal))
519 {
520 generate_payload(this, proposal);
521 }
522 enumerator->destroy(enumerator);
523 break;
524 }
525 case ATTRIBUTE_FORMAT:
526 generate_flag(this, rules[i].offset);
527 /* Attribute format is a flag which is stored in context*/
528 this->attribute_format =
529 *((bool *)(this->data_struct + rules[i].offset));
530 break;
531 case ATTRIBUTE_LENGTH_OR_VALUE:
532 if (this->attribute_format)
533 {
534 generate_u_int_type(this, U_INT_16, rules[i].offset);
535 }
536 else
537 {
538 generate_u_int_type(this, U_INT_16, rules[i].offset);
539 /* this field hold the length of the attribute */
540 this->attribute_length =
541 *((u_int16_t *)(this->data_struct + rules[i].offset));
542 }
543 break;
544 case ATTRIBUTE_VALUE:
545 {
546 if (!this->attribute_format)
547 {
548 if (this->debug)
549 {
550 DBG2(DBG_ENC, "attribute value has not fixed size");
551 }
552 /* the attribute value is generated */
553 generate_from_chunk(this, rules[i].offset);
554 }
555 break;
556 }
557 default:
558 DBG1(DBG_ENC, "field type %N is not supported",
559 encoding_type_names, rules[i].type);
560 return;
561 }
562 }
563 if (this->debug)
564 {
565 DBG2(DBG_ENC, "generating %N payload finished",
566 payload_type_names, payload_type);
567 DBG3(DBG_ENC, "generated data for this payload %b",
568 this->buffer + offset_start,
569 (u_int)(this->out_position - this->buffer - offset_start));
570 }
571 }
572
573 METHOD(generator_t, destroy, void,
574 private_generator_t *this)
575 {
576 free(this->buffer);
577 free(this);
578 }
579
580 /*
581 * Described in header
582 */
583 generator_t *generator_create()
584 {
585 private_generator_t *this;
586
587 INIT(this,
588 .public = {
589 .get_chunk = _get_chunk,
590 .generate_payload = _generate_payload,
591 .destroy = _destroy,
592 },
593 .buffer = malloc(GENERATOR_DATA_BUFFER_SIZE),
594 .debug = TRUE,
595 );
596
597 this->out_position = this->buffer;
598 this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
599
600 return &this->public;
601 }
602
603 /*
604 * Described in header
605 */
606 generator_t *generator_create_no_dbg()
607 {
608 private_generator_t *this = (private_generator_t*)generator_create();
609
610 this->debug = FALSE;
611
612 return &this->public;
613 }