Files
strongswan-ext/src/libcharon/encoding/payloads/transform_attribute.c
T

259 lines
6.9 KiB
C

/*
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <string.h>
#include <stddef.h>
#include "transform_attribute.h"
#include <encoding/payloads/encodings.h>
#include <library.h>
typedef struct private_transform_attribute_t private_transform_attribute_t;
/**
* Private data of an transform_attribute_t object.
*/
struct private_transform_attribute_t {
/**
* Public transform_attribute_t interface.
*/
transform_attribute_t public;
/**
* Attribute Format Flag.
*
* - TRUE means value is stored in attribute_length_or_value
* - FALSE means value is stored in attribute_value
*/
bool attribute_format;
/**
* Type of the attribute.
*/
u_int16_t attribute_type;
/**
* Attribute Length if attribute_format is 0, attribute Value otherwise.
*/
u_int16_t attribute_length_or_value;
/**
* Attribute value as chunk if attribute_format is 0 (FALSE).
*/
chunk_t attribute_value;
};
ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
"ATTRIBUTE_UNDEFINED");
ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
"KEY_LENGTH");
ENUM_END(transform_attribute_type_name, KEY_LENGTH);
/**
* Encoding rules to parse or generate a Transform attribute.
*
* The defined offsets are the positions in a object of type
* private_transform_attribute_t.
*/
encoding_rule_t transform_attribute_encodings[] = {
/* Flag defining the format of this payload */
{ ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
/* type of the attribute as 15 bit unsigned integer */
{ ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
/* Length or value, depending on the attribute format flag */
{ ATTRIBUTE_LENGTH_OR_VALUE,offsetof(private_transform_attribute_t, attribute_length_or_value) },
/* Value of attribute if attribute format flag is zero */
{ ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
};
/*
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!A! Attribute Type ! AF=0 Attribute Length !
!F! ! AF=1 Attribute Value !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! AF=0 Attribute Value !
! AF=1 Not Transmitted !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
METHOD(payload_t, verify, status_t,
private_transform_attribute_t *this)
{
return SUCCESS;
}
METHOD(payload_t, get_encoding_rules, void,
private_transform_attribute_t *this, encoding_rule_t **rules,
size_t *rule_count)
{
*rules = transform_attribute_encodings;
*rule_count = countof(transform_attribute_encodings);
}
METHOD(payload_t, get_type, payload_type_t,
private_transform_attribute_t *this)
{
return TRANSFORM_ATTRIBUTE;
}
METHOD(payload_t, get_next_type, payload_type_t,
private_transform_attribute_t *this)
{
return NO_PAYLOAD;
}
METHOD(payload_t, set_next_type, void,
private_transform_attribute_t *this, payload_type_t type)
{
}
METHOD(payload_t, get_length, size_t,
private_transform_attribute_t *this)
{
if (this->attribute_format)
{
return 4;
}
return this->attribute_length_or_value + 4;
}
METHOD(transform_attribute_t, set_value_chunk, void,
private_transform_attribute_t *this, chunk_t value)
{
chunk_free(&this->attribute_value);
if (value.len != 2)
{
this->attribute_value = chunk_clone(value);
this->attribute_length_or_value = value.len;
this->attribute_format = FALSE;
}
else
{
memcpy(&this->attribute_length_or_value, value.ptr, value.len);
}
}
METHOD(transform_attribute_t, set_value, void,
private_transform_attribute_t *this, u_int16_t value)
{
chunk_free(&this->attribute_value);
this->attribute_length_or_value = value;
this->attribute_format = TRUE;
}
METHOD(transform_attribute_t, get_value_chunk, chunk_t,
private_transform_attribute_t *this)
{
if (this->attribute_format)
{
return chunk_from_thing(this->attribute_length_or_value);
}
return this->attribute_value;
}
METHOD(transform_attribute_t, get_value, u_int16_t,
private_transform_attribute_t *this)
{
return this->attribute_length_or_value;
}
METHOD(transform_attribute_t, set_attribute_type, void,
private_transform_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
}
METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
private_transform_attribute_t *this)
{
return this->attribute_type;
}
METHOD(transform_attribute_t, clone_, transform_attribute_t*,
private_transform_attribute_t *this)
{
private_transform_attribute_t *new_clone;
new_clone = (private_transform_attribute_t *)transform_attribute_create();
new_clone->attribute_format = this->attribute_format;
new_clone->attribute_type = this->attribute_type;
new_clone->attribute_length_or_value = this->attribute_length_or_value;
if (!new_clone->attribute_format)
{
new_clone->attribute_value = chunk_clone(this->attribute_value);
}
return &new_clone->public;
}
METHOD2(payload_t, transform_attribute_t, destroy, void,
private_transform_attribute_t *this)
{
free(this->attribute_value.ptr);
free(this);
}
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create()
{
private_transform_attribute_t *this;
INIT(this,
.public = {
.payload_interface = {
.verify = _verify,
.get_encoding_rules = _get_encoding_rules,
.get_length = _get_length,
.get_next_type = _get_next_type,
.set_next_type = _set_next_type,
.get_type = _get_type,
.destroy = _destroy,
},
.set_value_chunk = _set_value_chunk,
.set_value = _set_value,
.get_value_chunk = _get_value_chunk,
.get_value = _get_value,
.set_attribute_type = _set_attribute_type,
.get_attribute_type = _get_attribute_type,
.clone = _clone_,
.destroy = _destroy,
},
.attribute_format = TRUE,
);
return &this->public;
}
/*
* Described in header.
*/
transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
{
transform_attribute_t *attribute = transform_attribute_create();
attribute->set_attribute_type(attribute, KEY_LENGTH);
attribute->set_value(attribute, key_length);
return attribute;
}