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 case P_CSCF_IP4_ADDRESS
:
136 if (this->length_or_value
!= 0 && this->length_or_value
!= 4)
141 case INTERNAL_IP4_SUBNET
:
142 if (this->length_or_value
!= 0 && this->length_or_value
!= 8)
147 case INTERNAL_IP6_ADDRESS
:
148 if (this->type
== PLV1_CONFIGURATION_ATTRIBUTE
&&
149 this->length_or_value
== 16)
150 { /* 16 bytes are correct for IKEv1, but older releases sent a
151 * prefix byte so we still accept 0 or 17 as in IKEv2 */
155 case INTERNAL_IP6_SUBNET
:
156 if (this->length_or_value
!= 0 && this->length_or_value
!= 17)
161 case INTERNAL_IP6_DNS
:
162 case INTERNAL_IP6_NBNS
:
163 case INTERNAL_IP6_DHCP
:
164 case P_CSCF_IP6_ADDRESS
:
165 if (this->length_or_value
!= 0 && this->length_or_value
!= 16)
170 case SUPPORTED_ATTRIBUTES
:
171 if (this->length_or_value
% 2)
176 case APPLICATION_VERSION
:
177 case INTERNAL_IP4_SERVER
:
178 case INTERNAL_IP6_SERVER
:
180 case XAUTH_USER_NAME
:
181 case XAUTH_USER_PASSWORD
:
184 case XAUTH_CHALLENGE
:
190 case UNITY_SAVE_PASSWD
:
191 case UNITY_DEF_DOMAIN
:
192 case UNITY_SPLITDNS_NAME
:
193 case UNITY_SPLIT_INCLUDE
:
194 case UNITY_NATT_PORT
:
195 case UNITY_LOCAL_LAN
:
198 case UNITY_BACKUP_SERVERS
:
199 case UNITY_DDNS_HOSTNAME
:
200 /* any length acceptable */
203 DBG1(DBG_ENC
, "unknown attribute type %N",
204 configuration_attribute_type_names
, this->attr_type
);
210 DBG1(DBG_ENC
, "invalid attribute length %d for %N",
211 this->length_or_value
, configuration_attribute_type_names
,
218 METHOD(payload_t
, get_encoding_rules
, int,
219 private_configuration_attribute_t
*this, encoding_rule_t
**rules
)
221 if (this->type
== PLV2_CONFIGURATION_ATTRIBUTE
)
223 *rules
= encodings_v2
;
224 return countof(encodings_v2
);
226 *rules
= encodings_v1
;
227 return countof(encodings_v1
);
230 METHOD(payload_t
, get_header_length
, int,
231 private_configuration_attribute_t
*this)
236 METHOD(payload_t
, get_type
, payload_type_t
,
237 private_configuration_attribute_t
*this)
242 METHOD(payload_t
, get_next_type
, payload_type_t
,
243 private_configuration_attribute_t
*this)
248 METHOD(payload_t
, set_next_type
, void,
249 private_configuration_attribute_t
*this, payload_type_t type
)
253 METHOD(payload_t
, get_length
, size_t,
254 private_configuration_attribute_t
*this)
256 return get_header_length(this) + this->value
.len
;
259 METHOD(configuration_attribute_t
, get_cattr_type
, configuration_attribute_type_t
,
260 private_configuration_attribute_t
*this)
262 return this->attr_type
;
265 METHOD(configuration_attribute_t
, get_chunk
, chunk_t
,
266 private_configuration_attribute_t
*this)
270 return chunk_from_thing(this->length_or_value
);
275 METHOD(configuration_attribute_t
, get_value
, u_int16_t
,
276 private_configuration_attribute_t
*this)
280 return this->length_or_value
;
285 METHOD2(payload_t
, configuration_attribute_t
, destroy
, void,
286 private_configuration_attribute_t
*this)
288 free(this->value
.ptr
);
293 * Described in header.
295 configuration_attribute_t
*configuration_attribute_create(payload_type_t type
)
297 private_configuration_attribute_t
*this;
301 .payload_interface
= {
303 .get_encoding_rules
= _get_encoding_rules
,
304 .get_header_length
= _get_header_length
,
305 .get_length
= _get_length
,
306 .get_next_type
= _get_next_type
,
307 .set_next_type
= _set_next_type
,
308 .get_type
= _get_type
,
311 .get_chunk
= _get_chunk
,
312 .get_value
= _get_value
,
313 .get_type
= _get_cattr_type
,
318 return &this->public;
322 * Described in header.
324 configuration_attribute_t
*configuration_attribute_create_chunk(
325 payload_type_t type
, configuration_attribute_type_t attr_type
, chunk_t chunk
)
327 private_configuration_attribute_t
*this;
329 this = (private_configuration_attribute_t
*)
330 configuration_attribute_create(type
);
331 this->attr_type
= ((u_int16_t
)attr_type
) & 0x7FFF;
332 this->value
= chunk_clone(chunk
);
333 this->length_or_value
= chunk
.len
;
335 return &this->public;
339 * Described in header.
341 configuration_attribute_t
*configuration_attribute_create_value(
342 configuration_attribute_type_t attr_type
, u_int16_t value
)
344 private_configuration_attribute_t
*this;
346 this = (private_configuration_attribute_t
*)
347 configuration_attribute_create(PLV1_CONFIGURATION_ATTRIBUTE
);
348 this->attr_type
= ((u_int16_t
)attr_type
) & 0x7FFF;
349 this->length_or_value
= value
;
350 this->af_flag
= TRUE
;
352 return &this->public;