payload: Use common prefixes for all payload type identifiers
[strongswan.git] / src / libcharon / encoding / payloads / configuration_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 <stddef.h>
19
20 #include "configuration_attribute.h"
21
22 #include <encoding/payloads/encodings.h>
23 #include <library.h>
24 #include <daemon.h>
25
26 typedef struct private_configuration_attribute_t private_configuration_attribute_t;
27
28 /**
29 * Private data of an configuration_attribute_t object.
30 */
31 struct private_configuration_attribute_t {
32
33 /**
34 * Public configuration_attribute_t interface.
35 */
36 configuration_attribute_t public;
37
38 /**
39 * Value encoded in length field?
40 */
41 bool af_flag;
42
43 /**
44 * Reserved bit (af_flag in IKEv2)
45 */
46 bool reserved;
47
48 /**
49 * Type of the attribute.
50 */
51 u_int16_t attr_type;
52
53 /**
54 * Length of the attribute, value if af_flag set.
55 */
56 u_int16_t length_or_value;
57
58 /**
59 * Attribute value as chunk.
60 */
61 chunk_t value;
62
63 /**
64 * Payload type, PLV2_CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
65 */
66 payload_type_t type;
67 };
68
69 /**
70 * Encoding rules for a IKEv2 configuration attribute / IKEv1 data attribute
71 */
72 static encoding_rule_t encodings_v2[] = {
73 /* 1 reserved bit */
74 { RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved) },
75 /* type of the attribute as 15 bit unsigned integer */
76 { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
77 /* Length of attribute value */
78 { ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length_or_value)},
79 /* Value of attribute if attribute format flag is zero */
80 { ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
81 };
82
83 /*
84 1 2 3
85 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
86 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 !R| Attribute Type ! Length |
88 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 | |
90 ~ Value ~
91 | |
92 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 */
94
95 /**
96 * Encoding rules for a IKEv1 data attribute
97 */
98 static encoding_rule_t encodings_v1[] = {
99 /* AF Flag */
100 { ATTRIBUTE_FORMAT, offsetof(private_configuration_attribute_t, af_flag) },
101 /* type of the attribute as 15 bit unsigned integer */
102 { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
103 /* Length of attribute value */
104 { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_configuration_attribute_t, length_or_value)},
105 /* Value of attribute if attribute format flag is zero */
106 { ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
107 };
108
109 /*
110 1 2 3
111 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
112 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
113 !F| Attribute Type ! Length |
114 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 | |
116 ~ Value ~
117 | |
118 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 */
120
121
122 METHOD(payload_t, verify, status_t,
123 private_configuration_attribute_t *this)
124 {
125 bool failed = FALSE;
126
127 switch (this->attr_type)
128 {
129 case INTERNAL_IP4_ADDRESS:
130 case INTERNAL_IP4_NETMASK:
131 case INTERNAL_IP4_DNS:
132 case INTERNAL_IP4_NBNS:
133 case INTERNAL_ADDRESS_EXPIRY:
134 case INTERNAL_IP4_DHCP:
135 if (this->length_or_value != 0 && this->length_or_value != 4)
136 {
137 failed = TRUE;
138 }
139 break;
140 case INTERNAL_IP4_SUBNET:
141 if (this->length_or_value != 0 && this->length_or_value != 8)
142 {
143 failed = TRUE;
144 }
145 break;
146 case INTERNAL_IP6_ADDRESS:
147 case INTERNAL_IP6_SUBNET:
148 if (this->length_or_value != 0 && this->length_or_value != 17)
149 {
150 failed = TRUE;
151 }
152 break;
153 case INTERNAL_IP6_DNS:
154 case INTERNAL_IP6_NBNS:
155 case INTERNAL_IP6_DHCP:
156 if (this->length_or_value != 0 && this->length_or_value != 16)
157 {
158 failed = TRUE;
159 }
160 break;
161 case SUPPORTED_ATTRIBUTES:
162 if (this->length_or_value % 2)
163 {
164 failed = TRUE;
165 }
166 break;
167 case APPLICATION_VERSION:
168 case INTERNAL_IP4_SERVER:
169 case INTERNAL_IP6_SERVER:
170 case XAUTH_TYPE:
171 case XAUTH_USER_NAME:
172 case XAUTH_USER_PASSWORD:
173 case XAUTH_PASSCODE:
174 case XAUTH_MESSAGE:
175 case XAUTH_CHALLENGE:
176 case XAUTH_DOMAIN:
177 case XAUTH_STATUS:
178 case XAUTH_NEXT_PIN:
179 case XAUTH_ANSWER:
180 case UNITY_BANNER:
181 case UNITY_SAVE_PASSWD:
182 case UNITY_DEF_DOMAIN:
183 case UNITY_SPLITDNS_NAME:
184 case UNITY_SPLIT_INCLUDE:
185 case UNITY_NATT_PORT:
186 case UNITY_LOCAL_LAN:
187 case UNITY_PFS:
188 case UNITY_FW_TYPE:
189 case UNITY_BACKUP_SERVERS:
190 case UNITY_DDNS_HOSTNAME:
191 /* any length acceptable */
192 break;
193 default:
194 DBG1(DBG_ENC, "unknown attribute type %N",
195 configuration_attribute_type_names, this->attr_type);
196 break;
197 }
198
199 if (failed)
200 {
201 DBG1(DBG_ENC, "invalid attribute length %d for %N",
202 this->length_or_value, configuration_attribute_type_names,
203 this->attr_type);
204 return FAILED;
205 }
206 return SUCCESS;
207 }
208
209 METHOD(payload_t, get_encoding_rules, int,
210 private_configuration_attribute_t *this, encoding_rule_t **rules)
211 {
212 if (this->type == PLV2_CONFIGURATION_ATTRIBUTE)
213 {
214 *rules = encodings_v2;
215 return countof(encodings_v2);
216 }
217 *rules = encodings_v1;
218 return countof(encodings_v1);
219 }
220
221 METHOD(payload_t, get_header_length, int,
222 private_configuration_attribute_t *this)
223 {
224 return 4;
225 }
226
227 METHOD(payload_t, get_type, payload_type_t,
228 private_configuration_attribute_t *this)
229 {
230 return this->type;
231 }
232
233 METHOD(payload_t, get_next_type, payload_type_t,
234 private_configuration_attribute_t *this)
235 {
236 return PL_NONE;
237 }
238
239 METHOD(payload_t, set_next_type, void,
240 private_configuration_attribute_t *this, payload_type_t type)
241 {
242 }
243
244 METHOD(payload_t, get_length, size_t,
245 private_configuration_attribute_t *this)
246 {
247 return get_header_length(this) + this->value.len;
248 }
249
250 METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t,
251 private_configuration_attribute_t *this)
252 {
253 return this->attr_type;
254 }
255
256 METHOD(configuration_attribute_t, get_chunk, chunk_t,
257 private_configuration_attribute_t *this)
258 {
259 if (this->af_flag)
260 {
261 return chunk_from_thing(this->length_or_value);
262 }
263 return this->value;
264 }
265
266 METHOD(configuration_attribute_t, get_value, u_int16_t,
267 private_configuration_attribute_t *this)
268 {
269 if (this->af_flag)
270 {
271 return this->length_or_value;
272 }
273 return 0;
274 }
275
276 METHOD2(payload_t, configuration_attribute_t, destroy, void,
277 private_configuration_attribute_t *this)
278 {
279 free(this->value.ptr);
280 free(this);
281 }
282
283 /*
284 * Described in header.
285 */
286 configuration_attribute_t *configuration_attribute_create(payload_type_t type)
287 {
288 private_configuration_attribute_t *this;
289
290 INIT(this,
291 .public = {
292 .payload_interface = {
293 .verify = _verify,
294 .get_encoding_rules = _get_encoding_rules,
295 .get_header_length = _get_header_length,
296 .get_length = _get_length,
297 .get_next_type = _get_next_type,
298 .set_next_type = _set_next_type,
299 .get_type = _get_type,
300 .destroy = _destroy,
301 },
302 .get_chunk = _get_chunk,
303 .get_value = _get_value,
304 .get_type = _get_cattr_type,
305 .destroy = _destroy,
306 },
307 .type = type
308 );
309 return &this->public;
310 }
311
312 /*
313 * Described in header.
314 */
315 configuration_attribute_t *configuration_attribute_create_chunk(
316 payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk)
317 {
318 private_configuration_attribute_t *this;
319
320 this = (private_configuration_attribute_t*)
321 configuration_attribute_create(type);
322 this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
323 this->value = chunk_clone(chunk);
324 this->length_or_value = chunk.len;
325
326 return &this->public;
327 }
328
329 /*
330 * Described in header.
331 */
332 configuration_attribute_t *configuration_attribute_create_value(
333 configuration_attribute_type_t attr_type, u_int16_t value)
334 {
335 private_configuration_attribute_t *this;
336
337 this = (private_configuration_attribute_t*)
338 configuration_attribute_create(PLV1_CONFIGURATION_ATTRIBUTE);
339 this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
340 this->length_or_value = value;
341 this->af_flag = TRUE;
342
343 return &this->public;
344 }
345