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