7d21258b14f5facef1baa7a796e9603fd918cdef
[strongswan.git] / src / libcharon / encoding / payloads / transform_attribute.c
1 /*
2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 <string.h>
19 #include <stddef.h>
20
21 #include "transform_attribute.h"
22
23 #include <encoding/payloads/encodings.h>
24 #include <library.h>
25
26 typedef struct private_transform_attribute_t private_transform_attribute_t;
27
28 /**
29 * Private data of an transform_attribute_t object.
30 */
31 struct private_transform_attribute_t {
32
33 /**
34 * Public transform_attribute_t interface.
35 */
36 transform_attribute_t public;
37
38 /**
39 * Attribute Format Flag.
40 *
41 * - TRUE means value is stored in attribute_length_or_value
42 * - FALSE means value is stored in attribute_value
43 */
44 bool attribute_format;
45
46 /**
47 * Type of the attribute.
48 */
49 u_int16_t attribute_type;
50
51 /**
52 * Attribute Length if attribute_format is 0, attribute Value otherwise.
53 */
54 u_int16_t attribute_length_or_value;
55
56 /**
57 * Attribute value as chunk if attribute_format is 0 (FALSE).
58 */
59 chunk_t attribute_value;
60 };
61
62
63 ENUM_BEGIN(transform_attribute_type_name, ATTRIBUTE_UNDEFINED, ATTRIBUTE_UNDEFINED,
64 "ATTRIBUTE_UNDEFINED");
65 ENUM_NEXT(transform_attribute_type_name, KEY_LENGTH, KEY_LENGTH, ATTRIBUTE_UNDEFINED,
66 "KEY_LENGTH");
67 ENUM_END(transform_attribute_type_name, KEY_LENGTH);
68
69 /**
70 * Encoding rules to parse or generate a Transform attribute.
71 *
72 * The defined offsets are the positions in a object of type
73 * private_transform_attribute_t.
74 */
75 encoding_rule_t transform_attribute_encodings[] = {
76 /* Flag defining the format of this payload */
77 { ATTRIBUTE_FORMAT, offsetof(private_transform_attribute_t, attribute_format) },
78 /* type of the attribute as 15 bit unsigned integer */
79 { ATTRIBUTE_TYPE, offsetof(private_transform_attribute_t, attribute_type) },
80 /* Length or value, depending on the attribute format flag */
81 { ATTRIBUTE_LENGTH_OR_VALUE,offsetof(private_transform_attribute_t, attribute_length_or_value) },
82 /* Value of attribute if attribute format flag is zero */
83 { ATTRIBUTE_VALUE, offsetof(private_transform_attribute_t, attribute_value) }
84 };
85
86 /*
87 1 2 3
88 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
89 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 !A! Attribute Type ! AF=0 Attribute Length !
91 !F! ! AF=1 Attribute Value !
92 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 ! AF=0 Attribute Value !
94 ! AF=1 Not Transmitted !
95 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96 */
97
98 METHOD(payload_t, verify, status_t,
99 private_transform_attribute_t *this)
100 {
101 return SUCCESS;
102 }
103
104 METHOD(payload_t, get_encoding_rules, void,
105 private_transform_attribute_t *this, encoding_rule_t **rules,
106 size_t *rule_count)
107 {
108 *rules = transform_attribute_encodings;
109 *rule_count = countof(transform_attribute_encodings);
110 }
111
112 METHOD(payload_t, get_type, payload_type_t,
113 private_transform_attribute_t *this)
114 {
115 return TRANSFORM_ATTRIBUTE;
116 }
117
118 METHOD(payload_t, get_next_type, payload_type_t,
119 private_transform_attribute_t *this)
120 {
121 return NO_PAYLOAD;
122 }
123
124 METHOD(payload_t, set_next_type, void,
125 private_transform_attribute_t *this, payload_type_t type)
126 {
127 }
128
129 METHOD(payload_t, get_length, size_t,
130 private_transform_attribute_t *this)
131 {
132 if (this->attribute_format)
133 {
134 return 4;
135 }
136 return this->attribute_length_or_value + 4;
137 }
138
139 METHOD(transform_attribute_t, set_value_chunk, void,
140 private_transform_attribute_t *this, chunk_t value)
141 {
142 chunk_free(&this->attribute_value);
143
144 if (value.len != 2)
145 {
146 this->attribute_value = chunk_clone(value);
147 this->attribute_length_or_value = value.len;
148 this->attribute_format = FALSE;
149 }
150 else
151 {
152 memcpy(&this->attribute_length_or_value, value.ptr, value.len);
153 }
154 }
155
156 METHOD(transform_attribute_t, set_value, void,
157 private_transform_attribute_t *this, u_int16_t value)
158 {
159 chunk_free(&this->attribute_value);
160 this->attribute_length_or_value = value;
161 this->attribute_format = TRUE;
162 }
163
164 METHOD(transform_attribute_t, get_value_chunk, chunk_t,
165 private_transform_attribute_t *this)
166 {
167 if (this->attribute_format)
168 {
169 return chunk_from_thing(this->attribute_length_or_value);
170 }
171 return this->attribute_value;
172 }
173
174 METHOD(transform_attribute_t, get_value, u_int16_t,
175 private_transform_attribute_t *this)
176 {
177 return this->attribute_length_or_value;
178 }
179
180 METHOD(transform_attribute_t, set_attribute_type, void,
181 private_transform_attribute_t *this, u_int16_t type)
182 {
183 this->attribute_type = type & 0x7FFF;
184 }
185
186 METHOD(transform_attribute_t, get_attribute_type, u_int16_t,
187 private_transform_attribute_t *this)
188 {
189 return this->attribute_type;
190 }
191
192 METHOD(transform_attribute_t, clone_, transform_attribute_t*,
193 private_transform_attribute_t *this)
194 {
195 private_transform_attribute_t *new_clone;
196
197 new_clone = (private_transform_attribute_t *)transform_attribute_create();
198
199 new_clone->attribute_format = this->attribute_format;
200 new_clone->attribute_type = this->attribute_type;
201 new_clone->attribute_length_or_value = this->attribute_length_or_value;
202
203 if (!new_clone->attribute_format)
204 {
205 new_clone->attribute_value = chunk_clone(this->attribute_value);
206 }
207 return &new_clone->public;
208 }
209
210 METHOD2(payload_t, transform_attribute_t, destroy, void,
211 private_transform_attribute_t *this)
212 {
213 free(this->attribute_value.ptr);
214 free(this);
215 }
216
217 /*
218 * Described in header.
219 */
220 transform_attribute_t *transform_attribute_create()
221 {
222 private_transform_attribute_t *this;
223
224 INIT(this,
225 .public = {
226 .payload_interface = {
227 .verify = _verify,
228 .get_encoding_rules = _get_encoding_rules,
229 .get_length = _get_length,
230 .get_next_type = _get_next_type,
231 .set_next_type = _set_next_type,
232 .get_type = _get_type,
233 .destroy = _destroy,
234 },
235 .set_value_chunk = _set_value_chunk,
236 .set_value = _set_value,
237 .get_value_chunk = _get_value_chunk,
238 .get_value = _get_value,
239 .set_attribute_type = _set_attribute_type,
240 .get_attribute_type = _get_attribute_type,
241 .clone = _clone_,
242 .destroy = _destroy,
243 },
244 .attribute_format = TRUE,
245 );
246 return &this->public;
247 }
248
249 /*
250 * Described in header.
251 */
252 transform_attribute_t *transform_attribute_create_key_length(u_int16_t key_length)
253 {
254 transform_attribute_t *attribute = transform_attribute_create();
255 attribute->set_attribute_type(attribute, KEY_LENGTH);
256 attribute->set_value(attribute, key_length);
257 return attribute;
258 }