2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
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>.
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
20 #include "configuration_attribute.h"
22 #include <encoding/payloads/encodings.h>
26 typedef struct private_configuration_attribute_t private_configuration_attribute_t
;
29 * Private data of an configuration_attribute_t object.
31 struct private_configuration_attribute_t
{
34 * Public configuration_attribute_t interface.
36 configuration_attribute_t
public;
39 * Value encoded in length field?
44 * Reserved bit (af_flag in IKEv2)
49 * Type of the attribute.
54 * Length of the attribute, value if af_flag set.
56 u_int16_t length_or_value
;
59 * Attribute value as chunk.
64 * Payload type, PLV2_CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
70 * Encoding rules for a IKEv2 configuration attribute / IKEv1 data attribute
72 static encoding_rule_t encodings_v2
[] = {
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
) },
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96 * Encoding rules for a IKEv1 data attribute
98 static encoding_rule_t encodings_v1
[] = {
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
) },
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 METHOD(payload_t
, verify
, status_t
,
123 private_configuration_attribute_t
*this)
127 switch (this->attr_type
)
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)
140 case INTERNAL_IP4_SUBNET
:
141 if (this->length_or_value
!= 0 && this->length_or_value
!= 8)
146 case INTERNAL_IP6_ADDRESS
:
147 if (this->type
== PLV1_CONFIGURATION_ATTRIBUTE
&&
148 this->length_or_value
== 16)
149 { /* 16 bytes are correct for IKEv1, but older releases sent a
150 * prefix byte so we still accept 0 or 17 as in IKEv2 */
154 case INTERNAL_IP6_SUBNET
:
155 if (this->length_or_value
!= 0 && this->length_or_value
!= 17)
160 case INTERNAL_IP6_DNS
:
161 case INTERNAL_IP6_NBNS
:
162 case INTERNAL_IP6_DHCP
:
163 if (this->length_or_value
!= 0 && this->length_or_value
!= 16)
168 case SUPPORTED_ATTRIBUTES
:
169 if (this->length_or_value
% 2)
174 case APPLICATION_VERSION
:
175 case INTERNAL_IP4_SERVER
:
176 case INTERNAL_IP6_SERVER
:
178 case XAUTH_USER_NAME
:
179 case XAUTH_USER_PASSWORD
:
182 case XAUTH_CHALLENGE
:
188 case UNITY_SAVE_PASSWD
:
189 case UNITY_DEF_DOMAIN
:
190 case UNITY_SPLITDNS_NAME
:
191 case UNITY_SPLIT_INCLUDE
:
192 case UNITY_NATT_PORT
:
193 case UNITY_LOCAL_LAN
:
196 case UNITY_BACKUP_SERVERS
:
197 case UNITY_DDNS_HOSTNAME
:
198 /* any length acceptable */
201 DBG1(DBG_ENC
, "unknown attribute type %N",
202 configuration_attribute_type_names
, this->attr_type
);
208 DBG1(DBG_ENC
, "invalid attribute length %d for %N",
209 this->length_or_value
, configuration_attribute_type_names
,
216 METHOD(payload_t
, get_encoding_rules
, int,
217 private_configuration_attribute_t
*this, encoding_rule_t
**rules
)
219 if (this->type
== PLV2_CONFIGURATION_ATTRIBUTE
)
221 *rules
= encodings_v2
;
222 return countof(encodings_v2
);
224 *rules
= encodings_v1
;
225 return countof(encodings_v1
);
228 METHOD(payload_t
, get_header_length
, int,
229 private_configuration_attribute_t
*this)
234 METHOD(payload_t
, get_type
, payload_type_t
,
235 private_configuration_attribute_t
*this)
240 METHOD(payload_t
, get_next_type
, payload_type_t
,
241 private_configuration_attribute_t
*this)
246 METHOD(payload_t
, set_next_type
, void,
247 private_configuration_attribute_t
*this, payload_type_t type
)
251 METHOD(payload_t
, get_length
, size_t,
252 private_configuration_attribute_t
*this)
254 return get_header_length(this) + this->value
.len
;
257 METHOD(configuration_attribute_t
, get_cattr_type
, configuration_attribute_type_t
,
258 private_configuration_attribute_t
*this)
260 return this->attr_type
;
263 METHOD(configuration_attribute_t
, get_chunk
, chunk_t
,
264 private_configuration_attribute_t
*this)
268 return chunk_from_thing(this->length_or_value
);
273 METHOD(configuration_attribute_t
, get_value
, u_int16_t
,
274 private_configuration_attribute_t
*this)
278 return this->length_or_value
;
283 METHOD2(payload_t
, configuration_attribute_t
, destroy
, void,
284 private_configuration_attribute_t
*this)
286 free(this->value
.ptr
);
291 * Described in header.
293 configuration_attribute_t
*configuration_attribute_create(payload_type_t type
)
295 private_configuration_attribute_t
*this;
299 .payload_interface
= {
301 .get_encoding_rules
= _get_encoding_rules
,
302 .get_header_length
= _get_header_length
,
303 .get_length
= _get_length
,
304 .get_next_type
= _get_next_type
,
305 .set_next_type
= _set_next_type
,
306 .get_type
= _get_type
,
309 .get_chunk
= _get_chunk
,
310 .get_value
= _get_value
,
311 .get_type
= _get_cattr_type
,
316 return &this->public;
320 * Described in header.
322 configuration_attribute_t
*configuration_attribute_create_chunk(
323 payload_type_t type
, configuration_attribute_type_t attr_type
, chunk_t chunk
)
325 private_configuration_attribute_t
*this;
327 this = (private_configuration_attribute_t
*)
328 configuration_attribute_create(type
);
329 this->attr_type
= ((u_int16_t
)attr_type
) & 0x7FFF;
330 this->value
= chunk_clone(chunk
);
331 this->length_or_value
= chunk
.len
;
333 return &this->public;
337 * Described in header.
339 configuration_attribute_t
*configuration_attribute_create_value(
340 configuration_attribute_type_t attr_type
, u_int16_t value
)
342 private_configuration_attribute_t
*this;
344 this = (private_configuration_attribute_t
*)
345 configuration_attribute_create(PLV1_CONFIGURATION_ATTRIBUTE
);
346 this->attr_type
= ((u_int16_t
)attr_type
) & 0x7FFF;
347 this->length_or_value
= value
;
348 this->af_flag
= TRUE
;
350 return &this->public;