e608497bd2c2f25eb401cace15ef10aac64f4560
[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 * Reserved bit
40 */
41 bool reserved;
42
43 /**
44 * Type of the attribute.
45 */
46 u_int16_t type;
47
48 /**
49 * Length of the attribute.
50 */
51 u_int16_t length;
52
53 /**
54 * Attribute value as chunk.
55 */
56 chunk_t value;
57 };
58
59 /**
60 * Encoding rules to parse or generate a configuration attribute.
61 *
62 * The defined offsets are the positions in a object of type
63 * private_configuration_attribute_t.
64 */
65 encoding_rule_t configuration_attribute_encodings[] = {
66 /* 1 reserved bit */
67 { RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved)},
68 /* type of the attribute as 15 bit unsigned integer */
69 { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) },
70 /* Length of attribute value */
71 { CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length) },
72 /* Value of attribute if attribute format flag is zero */
73 { CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) }
74 };
75
76 /*
77 1 2 3
78 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
79 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80 !R| Attribute Type ! Length |
81 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 | |
83 ~ Value ~
84 | |
85 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 */
87
88 METHOD(payload_t, verify, status_t,
89 private_configuration_attribute_t *this)
90 {
91 bool failed = FALSE;
92
93 if (this->length != this->value.len)
94 {
95 DBG1(DBG_ENC, "invalid attribute length");
96 return FAILED;
97 }
98
99 switch (this->type)
100 {
101 case INTERNAL_IP4_ADDRESS:
102 case INTERNAL_IP4_NETMASK:
103 case INTERNAL_IP4_DNS:
104 case INTERNAL_IP4_NBNS:
105 case INTERNAL_ADDRESS_EXPIRY:
106 case INTERNAL_IP4_DHCP:
107 if (this->length != 0 && this->length != 4)
108 {
109 failed = TRUE;
110 }
111 break;
112 case INTERNAL_IP4_SUBNET:
113 if (this->length != 0 && this->length != 8)
114 {
115 failed = TRUE;
116 }
117 break;
118 case INTERNAL_IP6_ADDRESS:
119 case INTERNAL_IP6_SUBNET:
120 if (this->length != 0 && this->length != 17)
121 {
122 failed = TRUE;
123 }
124 break;
125 case INTERNAL_IP6_DNS:
126 case INTERNAL_IP6_NBNS:
127 case INTERNAL_IP6_DHCP:
128 if (this->length != 0 && this->length != 16)
129 {
130 failed = TRUE;
131 }
132 break;
133 case SUPPORTED_ATTRIBUTES:
134 if (this->length % 2)
135 {
136 failed = TRUE;
137 }
138 break;
139 case APPLICATION_VERSION:
140 /* any length acceptable */
141 break;
142 default:
143 DBG1(DBG_ENC, "unknown attribute type %N",
144 configuration_attribute_type_names, this->type);
145 break;
146 }
147
148 if (failed)
149 {
150 DBG1(DBG_ENC, "invalid attribute length %d for %N",
151 this->length, configuration_attribute_type_names, this->type);
152 return FAILED;
153 }
154 return SUCCESS;
155 }
156
157 METHOD(payload_t, get_encoding_rules, void,
158 private_configuration_attribute_t *this, encoding_rule_t **rules,
159 size_t *rule_count)
160 {
161 *rules = configuration_attribute_encodings;
162 *rule_count = countof(configuration_attribute_encodings);
163 }
164
165 METHOD(payload_t, get_type, payload_type_t,
166 private_configuration_attribute_t *this)
167 {
168 return CONFIGURATION_ATTRIBUTE;
169 }
170
171 METHOD(payload_t, get_next_type, payload_type_t,
172 private_configuration_attribute_t *this)
173 {
174 return NO_PAYLOAD;
175 }
176
177 METHOD(payload_t, set_next_type, void,
178 private_configuration_attribute_t *this, payload_type_t type)
179 {
180 }
181
182 METHOD(payload_t, get_length, size_t,
183 private_configuration_attribute_t *this)
184 {
185 return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
186 }
187
188 METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t,
189 private_configuration_attribute_t *this)
190 {
191 return this->type;
192 }
193
194 METHOD(configuration_attribute_t, get_value, chunk_t,
195 private_configuration_attribute_t *this)
196 {
197 return this->value;
198 }
199
200 METHOD2(payload_t, configuration_attribute_t, destroy, void,
201 private_configuration_attribute_t *this)
202 {
203 free(this->value.ptr);
204 free(this);
205 }
206
207 /*
208 * Described in header.
209 */
210 configuration_attribute_t *configuration_attribute_create()
211 {
212 private_configuration_attribute_t *this;
213
214 INIT(this,
215 .public = {
216 .payload_interface = {
217 .verify = _verify,
218 .get_encoding_rules = _get_encoding_rules,
219 .get_length = _get_length,
220 .get_next_type = _get_next_type,
221 .set_next_type = _set_next_type,
222 .get_type = _get_type,
223 .destroy = _destroy,
224 },
225 .get_value = _get_value,
226 .get_type = _get_cattr_type,
227 .destroy = _destroy,
228 },
229 );
230 return &this->public;
231 }
232
233 /*
234 * Described in header.
235 */
236 configuration_attribute_t *configuration_attribute_create_value(
237 configuration_attribute_type_t type, chunk_t value)
238 {
239 private_configuration_attribute_t *this;
240
241 this = (private_configuration_attribute_t*)configuration_attribute_create();
242 this->type = ((u_int16_t)type) & 0x7FFF;
243 this->value = chunk_clone(value);
244 this->length = value.len;
245
246 return &this->public;
247 }
248