Statistics
| Branch: | Tag: | Revision:

root / src / charon / encoding / generator.c @ 5bfe1b25299e557b4f514948840f7a6492f87828

History | View | Annotate | Download (23.4 KB)

1
/*
2
 * Copyright (C) 2005-2009 Martin Willi
3
 * Copyright (C) 2005 Jan Hutter
4
 * Hochschule fuer Technik Rapperswil
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License as published by the
8
 * Free Software Foundation; either version 2 of the License, or (at your
9
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
10
 *
11
 * This program is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
 * for more details.
15
 */
16
17
#include <stdlib.h>
18
#include <string.h>
19
#include <arpa/inet.h>
20
#include <stdio.h>
21
22
#include "generator.h"
23
24
#include <library.h>
25
#include <daemon.h>
26
#include <utils/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
45
46
typedef struct private_generator_t private_generator_t;
47
48
/**
49
 * Private part of a generator_t object.
50
 */
51
struct private_generator_t {
52
    /**
53
     * Public part of a generator_t object.
54
     */
55
     generator_t public;
56
57
    /**
58
     * Buffer used to generate the data into.
59
     */
60
    u_int8_t *buffer;
61
62
    /**
63
     * Current write position in buffer (one byte aligned).
64
     */
65
    u_int8_t *out_position;
66
67
    /**
68
     * Position of last byte in buffer.
69
     */
70
    u_int8_t *roof_position;
71
72
    /**
73
     * Current bit writing to in current byte (between 0 and 7).
74
     */
75
    u_int8_t current_bit;
76
77
    /**
78
     * Associated data struct to read informations from.
79
     */
80
    void *data_struct;
81
82
    /*
83
     * Last payload length position offset in the buffer.
84
     */
85
    u_int32_t last_payload_length_position_offset;
86
87
    /**
88
     * Offset of the header length field in the buffer.
89
     */
90
    u_int32_t header_length_position_offset;
91
92
    /**
93
     * Last SPI size.
94
     */
95
    u_int8_t last_spi_size;
96
97
    /**
98
     * Attribute format of the last generated transform attribute.
99
     *
100
     * Used to check if a variable value field is used or not for
101
     * the transform attribute value.
102
     */
103
    bool attribute_format;
104
105
    /**
106
     * Depending on the value of attribute_format this field is used
107
     * to hold the length of the transform attribute in bytes.
108
     */
109
    u_int16_t attribute_length;
110
};
111
112
/**
113
 * Get size of current buffer in bytes.
114
 */
115
static int get_size(private_generator_t *this)
116
{
117
    return this->roof_position - this->buffer;
118
}
119
120
/**
121
 * Get free space of current buffer in bytes.
122
 */
123
static int get_space(private_generator_t *this)
124
{
125
    return this->roof_position - this->out_position;
126
}
127
128
/**
129
 * Get length of data in buffer (in bytes).
130
 */
131
static int get_length(private_generator_t *this)
132
{
133
    return this->out_position - this->buffer;
134
}
135
136
/**
137
 * Get current offset in buffer (in bytes).
138
 */
139
static u_int32_t get_offset(private_generator_t *this)
140
{
141
    return this->out_position - this->buffer;
142
}
143
144
/**
145
 * Makes sure enough space is available in buffer to store amount of bits.
146
 */
147
static void make_space_available(private_generator_t *this, int bits)
148
{
149
    while ((get_space(this) * 8 - this->current_bit) < bits)
150
    {
151
        int old_buffer_size, new_buffer_size, out_position_offset;
152
153
        old_buffer_size = get_size(this);
154
        new_buffer_size = old_buffer_size + GENERATOR_DATA_BUFFER_INCREASE_VALUE;
155
        out_position_offset = this->out_position - this->buffer;
156
157
        DBG2(DBG_ENC, "increasing gen buffer from %d to %d byte",
158
             old_buffer_size, new_buffer_size);
159
160
        this->buffer = realloc(this->buffer,new_buffer_size);
161
        this->out_position = (this->buffer + out_position_offset);
162
        this->roof_position = (this->buffer + new_buffer_size);
163
    }
164
}
165
166
/**
167
 * Writes a specific amount of byte into the buffer.
168
 */
169
static void write_bytes_to_buffer(private_generator_t *this, void *bytes,
170
                                  int number_of_bytes)
171
{
172
    int i;
173
    u_int8_t *read_position = (u_int8_t *)bytes;
174
175
    make_space_available(this, number_of_bytes * 8);
176
177
    for (i = 0; i < number_of_bytes; i++)
178
    {
179
        *(this->out_position) = *(read_position);
180
        read_position++;
181
        this->out_position++;
182
    }
183
}
184
185
/**
186
 * Writes a specific amount of byte into the buffer at a specific offset.
187
 */
188
static void write_bytes_to_buffer_at_offset(private_generator_t *this,
189
                        void *bytes, int number_of_bytes, u_int32_t offset)
190
{
191
    int i;
192
    u_int8_t *read_position = (u_int8_t *)bytes;
193
    u_int8_t *write_position;
194
    u_int32_t free_space_after_offset = get_size(this) - offset;
195
196
    /* check first if enough space for new data is available */
197
    if (number_of_bytes > free_space_after_offset)
198
    {
199
        make_space_available(this,
200
                             (number_of_bytes - free_space_after_offset) * 8);
201
    }
202
203
    write_position = this->buffer + offset;
204
    for (i = 0; i < number_of_bytes; i++)
205
    {
206
        *write_position = *read_position;
207
        read_position++;
208
        write_position++;
209
    }
210
}
211
212
/**
213
 * Generates a U_INT-Field type and writes it to buffer.
214
 */
215
static void generate_u_int_type(private_generator_t *this,
216
                                encoding_type_t int_type,u_int32_t offset)
217
{
218
    int number_of_bits = 0;
219
220
    /* find out number of bits of each U_INT type to check for enough space */
221
    switch (int_type)
222
    {
223
        case U_INT_4:
224
            number_of_bits = 4;
225
            break;
226
        case TS_TYPE:
227
        case U_INT_8:
228
            number_of_bits = 8;
229
            break;
230
        case U_INT_16:
231
        case CONFIGURATION_ATTRIBUTE_LENGTH:
232
            number_of_bits = 16;
233
            break;
234
        case U_INT_32:
235
            number_of_bits = 32;
236
            break;
237
        case ATTRIBUTE_TYPE:
238
            number_of_bits = 15;
239
            break;
240
        case IKE_SPI:
241
            number_of_bits = 64;
242
            break;
243
        default:
244
            DBG1(DBG_ENC, "U_INT Type %N is not supported",
245
                 encoding_type_names, int_type);
246
            return;
247
    }
248
    if ((number_of_bits % 8) == 0 && this->current_bit != 0)
249
    {
250
        DBG1(DBG_ENC, "U_INT Type %N is not 8 Bit aligned",
251
             encoding_type_names, int_type);
252
        return;
253
    }
254
255
    make_space_available(this, number_of_bits);
256
    switch (int_type)
257
    {
258
        case U_INT_4:
259
        {
260
            u_int8_t high, low;
261
262
            if (this->current_bit == 0)
263
            {
264
                /* high of current byte in buffer has to be set to the new value*/
265
                high = *((u_int8_t *)(this->data_struct + offset)) << 4;
266
                /* low in buffer is not changed */
267
                low = *(this->out_position) & 0x0F;
268
                /* high is set, low_val is not changed */
269
                *(this->out_position) = high | low;
270
                DBG3(DBG_ENC, "   => %d", *(this->out_position));
271
                /* write position is not changed, just bit position is moved */
272
                this->current_bit = 4;
273
            }
274
            else if (this->current_bit == 4)
275
            {
276
                /* high in buffer is not changed */
277
                high = *(this->out_position) & 0xF0;
278
                /* low of current byte in buffer has to be set to the new value*/
279
                low = *((u_int8_t *)(this->data_struct + offset)) & 0x0F;
280
                *(this->out_position) = high | low;
281
                DBG3(DBG_ENC, "   => %d", *(this->out_position));
282
                this->out_position++;
283
                this->current_bit = 0;
284
            }
285
            else
286
            {
287
                DBG1(DBG_ENC, "U_INT_4 Type is not 4 Bit aligned");
288
                /* 4 Bit integers must have a 4 bit alignment */
289
                return;
290
            }
291
            break;
292
        }
293
        case TS_TYPE:
294
        case U_INT_8:
295
        {
296
            /* 8 bit values are written as they are */
297
            *this->out_position = *((u_int8_t *)(this->data_struct + offset));
298
            DBG3(DBG_ENC, "   => %d", *(this->out_position));
299
            this->out_position++;
300
            break;
301
        }
302
        case ATTRIBUTE_TYPE:
303
        {
304
            u_int8_t attribute_format_flag;
305
            u_int16_t val;
306
307
            /* attribute type must not change first bit of current byte */
308
            if (this->current_bit != 1)
309
            {
310
                DBG1(DBG_ENC, "ATTRIBUTE FORMAT flag is not set");
311
                return;
312
            }
313
            attribute_format_flag = *(this->out_position) & 0x80;
314
            /* get attribute type value as 16 bit integer*/
315
            val = *((u_int16_t*)(this->data_struct + offset));
316
            /* unset most significant bit */
317
            val &= 0x7FFF;
318
            if (attribute_format_flag)
319
            {
320
                val |= 0x8000;
321
            }
322
            val = htons(val);
323
            DBG3(DBG_ENC, "   => %d", val);
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 CONFIGURATION_ATTRIBUTE_LENGTH:
332
        {
333
            u_int16_t val = htons(*((u_int16_t*)(this->data_struct + offset)));
334
            DBG3(DBG_ENC, "   => %b", &val, sizeof(u_int16_t));
335
            write_bytes_to_buffer(this, &val, sizeof(u_int16_t));
336
            break;
337
        }
338
        case U_INT_32:
339
        {
340
            u_int32_t val = htonl(*((u_int32_t*)(this->data_struct + offset)));
341
            DBG3(DBG_ENC, "   => %b", &val, sizeof(u_int32_t));
342
            write_bytes_to_buffer(this, &val, sizeof(u_int32_t));
343
            break;
344
        }
345
        case IKE_SPI:
346
        {
347
            /* 64 bit are written as-is, no host order conversion */
348
            write_bytes_to_buffer(this, this->data_struct + offset,
349
                                  sizeof(u_int64_t));
350
            DBG3(DBG_ENC, "   => %b", this->data_struct + offset,
351
                 sizeof(u_int64_t));
352
            break;
353
        }
354
        default:
355
        {
356
            DBG1(DBG_ENC, "U_INT Type %N is not supported",
357
                 encoding_type_names, int_type);
358
            return;
359
        }
360
    }
361
}
362
363
/**
364
 * Generate a reserved bit or byte
365
 */
366
static void generate_reserved_field(private_generator_t *this, int bits)
367
{
368
    /* only one bit or 8 bit fields are supported */
369
    if (bits != 1 && bits != 8)
370
    {
371
        DBG1(DBG_ENC, "reserved field of %d bits cannot be generated", bits);
372
        return ;
373
    }
374
    make_space_available(this, bits);
375
376
    if (bits == 1)
377
    {
378
        u_int8_t reserved_bit = ~(1 << (7 - this->current_bit));
379
380
        *(this->out_position) = *(this->out_position) & reserved_bit;
381
        if (this->current_bit == 0)
382
        {
383
            /* memory must be zero */
384
            *(this->out_position) = 0x00;
385
        }
386
        this->current_bit++;
387
        if (this->current_bit >= 8)
388
        {
389
            this->current_bit = this->current_bit % 8;
390
            this->out_position++;
391
        }
392
    }
393
    else
394
    {
395
        if (this->current_bit > 0)
396
        {
397
            DBG1(DBG_ENC, "reserved field cannot be written cause "
398
                 "alignement of current bit is %d", this->current_bit);
399
            return;
400
        }
401
        *(this->out_position) = 0x00;
402
        this->out_position++;
403
    }
404
}
405
406
/**
407
 * Generate a FLAG filed
408
 */
409
static void generate_flag(private_generator_t *this, u_int32_t offset)
410
{
411
    u_int8_t flag_value;
412
    u_int8_t flag;
413
414
    flag_value = (*((bool *) (this->data_struct + offset))) ? 1 : 0;
415
    /* get flag position */
416
    flag = (flag_value << (7 - this->current_bit));
417
418
    /* make sure one bit is available in buffer */
419
    make_space_available(this, 1);
420
    if (this->current_bit == 0)
421
    {
422
        /* memory must be zero */
423
        *(this->out_position) = 0x00;
424
    }
425
426
    *(this->out_position) = *(this->out_position) | flag;
427
    DBG3(DBG_ENC, "   => %d", *this->out_position);
428
429
    this->current_bit++;
430
    if (this->current_bit >= 8)
431
    {
432
        this->current_bit = this->current_bit % 8;
433
        this->out_position++;
434
    }
435
}
436
437
/**
438
 * Generates a bytestream from a chunk_t.
439
 */
440
static void generate_from_chunk(private_generator_t *this, u_int32_t offset)
441
{
442
    chunk_t *value;
443
444
    if (this->current_bit != 0)
445
    {
446
        DBG1(DBG_ENC, "can not generate a chunk at Bitpos %d", this->current_bit);
447
        return ;
448
    }
449
450
    value = (chunk_t *)(this->data_struct + offset);
451
    DBG3(DBG_ENC, "   => %B", value);
452
453
    write_bytes_to_buffer(this, value->ptr, value->len);
454
}
455
456
/**
457
 * Implementation of private_generator_t.write_to_chunk.
458
 */
459
static void write_to_chunk(private_generator_t *this,chunk_t *data)
460
{
461
    int data_length = get_length(this);
462
    u_int32_t header_length_field = data_length;
463
464
    /* write length into header length field */
465
    if (this->header_length_position_offset > 0)
466
    {
467
        u_int32_t val = htonl(header_length_field);
468
        write_bytes_to_buffer_at_offset(this, &val, sizeof(u_int32_t),
469
                                        this->header_length_position_offset);
470
    }
471
472
    if (this->current_bit > 0)
473
    {
474
        data_length++;
475
    }
476
    *data = chunk_alloc(data_length);
477
    memcpy(data->ptr, this->buffer, data_length);
478
479
    DBG3(DBG_ENC, "generated data of this generator %B", data);
480
}
481
482
/**
483
 * Implementation of private_generator_t.generate_payload.
484
 */
485
static void generate_payload (private_generator_t *this,payload_t *payload)
486
{
487
    int i, offset_start;
488
    size_t rule_count;
489
    encoding_rule_t *rules;
490
    payload_type_t payload_type;
491
492
    this->data_struct = payload;
493
    payload_type = payload->get_type(payload);
494
    /* spi size has to get reseted */
495
    this->last_spi_size = 0;
496
497
    offset_start = this->out_position - this->buffer;
498
499
    DBG2(DBG_ENC, "generating payload of type %N",
500
         payload_type_names, payload_type);
501
502
    /* each payload has its own encoding rules */
503
    payload->get_encoding_rules(payload, &rules, &rule_count);
504
505
    for (i = 0; i < rule_count;i++)
506
    {
507
        DBG2(DBG_ENC, "  generating rule %d %N",
508
             i, encoding_type_names, rules[i].type);
509
        switch (rules[i].type)
510
        {
511
            case U_INT_4:
512
            case U_INT_8:
513
            case U_INT_16:
514
            case U_INT_32:
515
            case IKE_SPI:
516
            case TS_TYPE:
517
            case ATTRIBUTE_TYPE:
518
            case CONFIGURATION_ATTRIBUTE_LENGTH:
519
            {
520
                generate_u_int_type(this, rules[i].type, rules[i].offset);
521
                break;
522
            }
523
            case RESERVED_BIT:
524
            {
525
                generate_reserved_field(this, 1);
526
                break;
527
            }
528
            case RESERVED_BYTE:
529
            {
530
                generate_reserved_field(this, 8);
531
                break;
532
            }
533
            case FLAG:
534
            {
535
                generate_flag(this, rules[i].offset);
536
                break;
537
            }
538
            case PAYLOAD_LENGTH:
539
            {
540
                this->last_payload_length_position_offset = get_offset(this);
541
                generate_u_int_type(this, U_INT_16,rules[i].offset);
542
                break;
543
            }
544
            case HEADER_LENGTH:
545
            {
546
                this->header_length_position_offset = get_offset(this);
547
                generate_u_int_type(this ,U_INT_32, rules[i].offset);
548
                break;
549
            }
550
            case SPI_SIZE:
551
                generate_u_int_type(this, U_INT_8, rules[i].offset);
552
                this->last_spi_size = *((u_int8_t *)(this->data_struct +
553
                                                     rules[i].offset));
554
                break;
555
            case ADDRESS:
556
            {
557
                generate_from_chunk(this, rules[i].offset);
558
                break;
559
            }
560
            case SPI:
561
            {
562
                generate_from_chunk(this, rules[i].offset);
563
                break;
564
            }
565
            case KEY_EXCHANGE_DATA:
566
            case NOTIFICATION_DATA:
567
            case NONCE_DATA:
568
            case ID_DATA:
569
            case AUTH_DATA:
570
            case CERT_DATA:
571
            case CERTREQ_DATA:
572
            case SPIS:
573
            case CONFIGURATION_ATTRIBUTE_VALUE:
574
            case VID_DATA:
575
            case EAP_DATA:
576
            {
577
                u_int32_t payload_length_position_offset;
578
                u_int16_t length_of_payload;
579
                u_int16_t header_length = 0;
580
                u_int16_t length_in_network_order;
581
582
                switch(rules[i].type)
583
                {
584
                    case KEY_EXCHANGE_DATA:
585
                        header_length = KE_PAYLOAD_HEADER_LENGTH;
586
                        break;
587
                    case NOTIFICATION_DATA:
588
                        header_length = NOTIFY_PAYLOAD_HEADER_LENGTH +
589
                                                        this->last_spi_size;
590
                        break;
591
                    case NONCE_DATA:
592
                        header_length = NONCE_PAYLOAD_HEADER_LENGTH;
593
                        break;
594
                    case ID_DATA:
595
                        header_length = ID_PAYLOAD_HEADER_LENGTH;
596
                        break;
597
                    case AUTH_DATA:
598
                        header_length = AUTH_PAYLOAD_HEADER_LENGTH;
599
                        break;
600
                    case CERT_DATA:
601
                        header_length = CERT_PAYLOAD_HEADER_LENGTH;
602
                        break;
603
                    case CERTREQ_DATA:
604
                        header_length = CERTREQ_PAYLOAD_HEADER_LENGTH;
605
                        break;
606
                    case SPIS:
607
                        header_length = DELETE_PAYLOAD_HEADER_LENGTH;
608
                        break;
609
                    case VID_DATA:
610
                        header_length = VENDOR_ID_PAYLOAD_HEADER_LENGTH;
611
                        break;
612
                    case CONFIGURATION_ATTRIBUTE_VALUE:
613
                        header_length = CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
614
                        break;
615
                    case EAP_DATA:
616
                        header_length = EAP_PAYLOAD_HEADER_LENGTH;
617
                        break;
618
                    default:
619
                        break;
620
                }
621
                generate_from_chunk(this, rules[i].offset);
622
623
                payload_length_position_offset =
624
                                    this->last_payload_length_position_offset;
625
626
                length_of_payload = header_length +
627
                        ((chunk_t *)(this->data_struct + rules[i].offset))->len;
628
629
                length_in_network_order = htons(length_of_payload);
630
                write_bytes_to_buffer_at_offset(this, &length_in_network_order,
631
                            sizeof(u_int16_t), payload_length_position_offset);
632
                break;
633
            }
634
            case PROPOSALS:
635
            {
636
                u_int32_t payload_length_position_offset =
637
                                    this->last_payload_length_position_offset;
638
                /* Length of SA_PAYLOAD is calculated */
639
                u_int16_t length_of_sa_payload = SA_PAYLOAD_HEADER_LENGTH;
640
                u_int16_t int16_val;
641
                linked_list_t *proposals = *((linked_list_t **)
642
                                        (this->data_struct + rules[i].offset));
643
                iterator_t *iterator;
644
                payload_t *current_proposal;
645
646
                iterator = proposals->create_iterator(proposals,TRUE);
647
                while (iterator->iterate(iterator, (void**)&current_proposal))
648
                {
649
                    u_int32_t before_generate_position_offset;
650
                    u_int32_t after_generate_position_offset;
651
652
                    before_generate_position_offset = get_offset(this);
653
                    generate_payload(this, current_proposal);
654
                    after_generate_position_offset = get_offset(this);
655
                    length_of_sa_payload += (after_generate_position_offset -
656
                                             before_generate_position_offset);
657
                }
658
                iterator->destroy(iterator);
659
660
                int16_val = htons(length_of_sa_payload);
661
                write_bytes_to_buffer_at_offset(this, &int16_val,
662
                            sizeof(u_int16_t),payload_length_position_offset);
663
                break;
664
            }
665
            case TRANSFORMS:
666
            {
667
                u_int32_t payload_length_position_offset =
668
                                    this->last_payload_length_position_offset;
669
                u_int16_t length_of_proposal =
670
                    PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH + this->last_spi_size;
671
                u_int16_t int16_val;
672
                linked_list_t *transforms = *((linked_list_t **)
673
                                        (this->data_struct + rules[i].offset));
674
                iterator_t *iterator;
675
                payload_t *current_transform;
676
677
                iterator = transforms->create_iterator(transforms,TRUE);
678
                while (iterator->iterate(iterator, (void**)&current_transform))
679
                {
680
                    u_int32_t before_generate_position_offset;
681
                    u_int32_t after_generate_position_offset;
682
683
                    before_generate_position_offset = get_offset(this);
684
                    generate_payload(this, current_transform);
685
                    after_generate_position_offset = get_offset(this);
686
687
                    length_of_proposal += (after_generate_position_offset -
688
                                           before_generate_position_offset);
689
                }
690
                iterator->destroy(iterator);
691
692
                int16_val = htons(length_of_proposal);
693
                write_bytes_to_buffer_at_offset(this, &int16_val,
694
                            sizeof(u_int16_t), payload_length_position_offset);
695
                break;
696
            }
697
            case TRANSFORM_ATTRIBUTES:
698
            {
699
                u_int32_t transform_length_position_offset =
700
                                    this->last_payload_length_position_offset;
701
                u_int16_t length_of_transform =
702
                                    TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
703
                u_int16_t int16_val;
704
                linked_list_t *transform_attributes =*((linked_list_t **)
705
                                    (this->data_struct + rules[i].offset));
706
                iterator_t *iterator;
707
                payload_t *current_attribute;
708
709
                iterator = transform_attributes->create_iterator(
710
                                                    transform_attributes, TRUE);
711
                while (iterator->iterate(iterator, (void**)&current_attribute))
712
                {
713
                    u_int32_t before_generate_position_offset;
714
                    u_int32_t after_generate_position_offset;
715
716
                    before_generate_position_offset = get_offset(this);
717
                    generate_payload(this, current_attribute);
718
                    after_generate_position_offset = get_offset(this);
719
720
                    length_of_transform += (after_generate_position_offset -
721
                                            before_generate_position_offset);
722
                }
723
724
                iterator->destroy(iterator);
725
726
                int16_val = htons(length_of_transform);
727
                write_bytes_to_buffer_at_offset(this, &int16_val,
728
                            sizeof(u_int16_t),transform_length_position_offset);
729
                break;
730
            }
731
            case CONFIGURATION_ATTRIBUTES:
732
            {
733
                u_int32_t configurations_length_position_offset =
734
                                    this->last_payload_length_position_offset;
735
                u_int16_t length_of_configurations = CP_PAYLOAD_HEADER_LENGTH;
736
                u_int16_t int16_val;
737
                linked_list_t *configuration_attributes = *((linked_list_t **)
738
                                        (this->data_struct + rules[i].offset));
739
                iterator_t *iterator;
740
                payload_t *current_attribute;
741
742
                iterator = configuration_attributes->create_iterator(
743
                                                configuration_attributes,TRUE);
744
                while (iterator->iterate(iterator, (void**)&current_attribute))
745
                {
746
                    u_int32_t before_generate_position_offset;
747
                    u_int32_t after_generate_position_offset;
748
749
                    before_generate_position_offset = get_offset(this);
750
                    generate_payload(this, current_attribute);
751
                    after_generate_position_offset = get_offset(this);
752
753
                    length_of_configurations += after_generate_position_offset -
754
                                            before_generate_position_offset;
755
                }
756
757
                iterator->destroy(iterator);
758
759
                int16_val = htons(length_of_configurations);
760
                write_bytes_to_buffer_at_offset(this, &int16_val,
761
                     sizeof(u_int16_t),configurations_length_position_offset);
762
                break;
763
            }
764
            case ATTRIBUTE_FORMAT:
765
            {
766
                generate_flag(this, rules[i].offset);
767
                /* Attribute format is a flag which is stored in context*/
768
                this->attribute_format =
769
                            *((bool *)(this->data_struct + rules[i].offset));
770
                break;
771
            }
772
773
            case ATTRIBUTE_LENGTH_OR_VALUE:
774
            {
775
                if (this->attribute_format == FALSE)
776
                {
777
                    generate_u_int_type(this, U_INT_16, rules[i].offset);
778
                    /* this field hold the length of the attribute */
779
                    this->attribute_length =
780
                        *((u_int16_t *)(this->data_struct + rules[i].offset));
781
                }
782
                else
783
                {
784
                    generate_u_int_type(this, U_INT_16, rules[i].offset);
785
                }
786
                break;
787
            }
788
            case ATTRIBUTE_VALUE:
789
            {
790
                if (this->attribute_format == FALSE)
791
                {
792
                    DBG2(DBG_ENC, "attribute value has not fixed size");
793
                    /* the attribute value is generated */
794
                    generate_from_chunk(this, rules[i].offset);
795
                }
796
                break;
797
            }
798
            case TRAFFIC_SELECTORS:
799
            {
800
                u_int32_t payload_length_position_offset =
801
                                    this->last_payload_length_position_offset;
802
                u_int16_t length_of_ts_payload = TS_PAYLOAD_HEADER_LENGTH;
803
                u_int16_t int16_val;
804
                linked_list_t *traffic_selectors = *((linked_list_t **)
805
                                        (this->data_struct + rules[i].offset));
806
                iterator_t *iterator;
807
                payload_t *current_tss;
808
809
                iterator = traffic_selectors->create_iterator(
810
                                                    traffic_selectors,TRUE);
811
                while (iterator->iterate(iterator, (void **)&current_tss))
812
                {
813
                    u_int32_t before_generate_position_offset;
814
                    u_int32_t after_generate_position_offset;
815
816
                    before_generate_position_offset = get_offset(this);
817
                    generate_payload(this, current_tss);
818
                    after_generate_position_offset = get_offset(this);
819
820
                    length_of_ts_payload += (after_generate_position_offset -
821
                                             before_generate_position_offset);
822
                }
823
                iterator->destroy(iterator);
824
825
                int16_val = htons(length_of_ts_payload);
826
                write_bytes_to_buffer_at_offset(this, &int16_val,
827
                            sizeof(u_int16_t),payload_length_position_offset);
828
                break;
829
            }
830
831
            case ENCRYPTED_DATA:
832
            {
833
                generate_from_chunk(this, rules[i].offset);
834
                break;
835
            }
836
            default:
837
                DBG1(DBG_ENC, "field type %N is not supported",
838
                     encoding_type_names, rules[i].type);
839
                return;
840
        }
841
    }
842
    DBG2(DBG_ENC, "generating %N payload finished",
843
         payload_type_names, payload_type);
844
    DBG3(DBG_ENC, "generated data for this payload %b",
845
         this->buffer + offset_start,
846
         this->out_position - this->buffer - offset_start);
847
}
848
849
/**
850
 * Implementation of generator_t.destroy.
851
 */
852
static status_t destroy(private_generator_t *this)
853
{
854
    free(this->buffer);
855
    free(this);
856
    return SUCCESS;
857
}
858
859
/*
860
 * Described in header
861
 */
862
generator_t *generator_create()
863
{
864
    private_generator_t *this;
865
866
    this = malloc_thing(private_generator_t);
867
868
    /* initiate public functions */
869
    this->public.generate_payload = (void(*)(generator_t*, payload_t *))generate_payload;
870
    this->public.destroy = (void(*)(generator_t*)) destroy;
871
    this->public.write_to_chunk = (void (*) (generator_t *,chunk_t *))write_to_chunk;
872
873
    /* allocate memory for buffer */
874
    this->buffer = malloc(GENERATOR_DATA_BUFFER_SIZE);
875
876
    /* initiate private variables */
877
    this->out_position = this->buffer;
878
    this->roof_position = this->buffer + GENERATOR_DATA_BUFFER_SIZE;
879
    this->data_struct = NULL;
880
    this->current_bit = 0;
881
    this->last_payload_length_position_offset = 0;
882
    this->header_length_position_offset = 0;
883
    this->attribute_format = FALSE;
884
    this->attribute_length = 0;
885
886
    return &(this->public);
887
}
888