Moving charon to libcharon.
[strongswan.git] / src / libcharon / encoding / payloads / configuration_attribute.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stddef.h>
18
19 #include "configuration_attribute.h"
20
21 #include <encoding/payloads/encodings.h>
22 #include <library.h>
23 #include <daemon.h>
24
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 */
32 struct private_configuration_attribute_t {
33 /**
34 * Public configuration_attribute_t interface.
35 */
36 configuration_attribute_t public;
37
38 /**
39 * Type of the attribute.
40 */
41 u_int16_t type;
42
43 /**
44 * Length of the attribute.
45 */
46 u_int16_t length;
47
48 /**
49 * Attribute value as chunk.
50 */
51 chunk_t value;
52 };
53
54 /**
55 * Encoding rules to parse or generate a configuration attribute.
56 *
57 * The defined offsets are the positions in a object of type
58 * private_configuration_attribute_t.
59 */
60 encoding_rule_t configuration_attribute_encodings[] = {
61
62 { RESERVED_BIT, 0 },
63 /* type of the attribute as 15 bit unsigned integer */
64 { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, type) },
65 /* Length of attribute value */
66 { CONFIGURATION_ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length) },
67 /* Value of attribute if attribute format flag is zero */
68 { CONFIGURATION_ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) }
69 };
70
71 /*
72 1 2 3
73 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
74 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 !R| Attribute Type ! Length |
76 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 | |
78 ~ Value ~
79 | |
80 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 */
82
83 /**
84 * Implementation of payload_t.verify.
85 */
86 static status_t verify(private_configuration_attribute_t *this)
87 {
88 bool failed = FALSE;
89
90 if (this->length != this->value.len)
91 {
92 DBG1(DBG_ENC, "invalid attribute length");
93 return FAILED;
94 }
95
96 switch (this->type)
97 {
98 case INTERNAL_IP4_ADDRESS:
99 case INTERNAL_IP4_NETMASK:
100 case INTERNAL_IP4_DNS:
101 case INTERNAL_IP4_NBNS:
102 case INTERNAL_ADDRESS_EXPIRY:
103 case INTERNAL_IP4_DHCP:
104 if (this->length != 0 && this->length != 4)
105 {
106 failed = TRUE;
107 }
108 break;
109 case INTERNAL_IP4_SUBNET:
110 if (this->length != 0 && this->length != 8)
111 {
112 failed = TRUE;
113 }
114 break;
115 case INTERNAL_IP6_ADDRESS:
116 case INTERNAL_IP6_SUBNET:
117 if (this->length != 0 && this->length != 17)
118 {
119 failed = TRUE;
120 }
121 break;
122 case INTERNAL_IP6_DNS:
123 case INTERNAL_IP6_NBNS:
124 case INTERNAL_IP6_DHCP:
125 if (this->length != 0 && this->length != 16)
126 {
127 failed = TRUE;
128 }
129 break;
130 case SUPPORTED_ATTRIBUTES:
131 if (this->length % 2)
132 {
133 failed = TRUE;
134 }
135 break;
136 case APPLICATION_VERSION:
137 /* any length acceptable */
138 break;
139 default:
140 DBG1(DBG_ENC, "unknown attribute type %N",
141 configuration_attribute_type_names, this->type);
142 break;
143 }
144
145 if (failed)
146 {
147 DBG1(DBG_ENC, "invalid attribute length %d for %N",
148 this->length, configuration_attribute_type_names, this->type);
149 return FAILED;
150 }
151 return SUCCESS;
152 }
153
154 /**
155 * Implementation of payload_t.get_encoding_rules.
156 */
157 static void get_encoding_rules(private_configuration_attribute_t *this,
158 encoding_rule_t **rules, size_t *rule_count)
159 {
160 *rules = configuration_attribute_encodings;
161 *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t);
162 }
163
164 /**
165 * Implementation of payload_t.get_type.
166 */
167 static payload_type_t get_type(private_configuration_attribute_t *this)
168 {
169 return CONFIGURATION_ATTRIBUTE;
170 }
171
172 /**
173 * Implementation of payload_t.get_next_type.
174 */
175 static payload_type_t get_next_type(private_configuration_attribute_t *this)
176 {
177 return NO_PAYLOAD;
178 }
179
180 /**
181 * Implementation of payload_t.set_next_type.
182 */
183 static void set_next_type(private_configuration_attribute_t *this,
184 payload_type_t type)
185 {
186 }
187
188 /**
189 * Implementation of configuration_attribute_t.get_length.
190 */
191 static size_t get_length(private_configuration_attribute_t *this)
192 {
193 return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
194 }
195
196 /**
197 * Implementation of configuration_attribute_t.get_type.
198 */
199 static configuration_attribute_type_t get_configuration_attribute_type(
200 private_configuration_attribute_t *this)
201 {
202 return this->type;
203 }
204
205 /**
206 * Implementation of configuration_attribute_t.get_value.
207 */
208 static chunk_t get_value(private_configuration_attribute_t *this)
209 {
210 return this->value;
211 }
212
213 /**
214 * Implementation of configuration_attribute_t.destroy and payload_t.destroy.
215 */
216 static void destroy(private_configuration_attribute_t *this)
217 {
218 free(this->value.ptr);
219 free(this);
220 }
221
222 /*
223 * Described in header.
224 */
225 configuration_attribute_t *configuration_attribute_create()
226 {
227 private_configuration_attribute_t *this;
228
229 this = malloc_thing(private_configuration_attribute_t);
230 this->public.payload_interface.verify = (status_t(*)(payload_t *))verify;
231 this->public.payload_interface.get_encoding_rules = (void(*)(payload_t *, encoding_rule_t **, size_t *) )get_encoding_rules;
232 this->public.payload_interface.get_length = (size_t(*)(payload_t *))get_length;
233 this->public.payload_interface.get_next_type = (payload_type_t(*)(payload_t *))get_next_type;
234 this->public.payload_interface.set_next_type = (void(*)(payload_t *,payload_type_t))set_next_type;
235 this->public.payload_interface.get_type = (payload_type_t(*)(payload_t *))get_type;
236 this->public.payload_interface.destroy = (void(*)(payload_t*))destroy;
237
238 this->public.get_value = (chunk_t(*)(configuration_attribute_t *))get_value;
239 this->public.get_type = (configuration_attribute_type_t(*)(configuration_attribute_t *))get_configuration_attribute_type;
240 this->public.destroy = (void (*)(configuration_attribute_t*))destroy;
241
242 this->type = 0;
243 this->value = chunk_empty;
244 this->length = 0;
245
246 return &this->public;
247 }
248
249 /*
250 * Described in header.
251 */
252 configuration_attribute_t *configuration_attribute_create_value(
253 configuration_attribute_type_t type, chunk_t value)
254 {
255 private_configuration_attribute_t *this;
256
257 this = (private_configuration_attribute_t*)configuration_attribute_create();
258 this->type = ((u_int16_t)type) & 0x7FFF;
259 this->value = chunk_clone(value);
260 this->length = value.len;
261
262 return &this->public;
263 }
264