b972905835eeaf4e1bdd184262ad0cf83533598f
[strongswan.git] / src / charon / sa / tasks / ike_config.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
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 "ike_config.h"
18
19 #include <daemon.h>
20 #include <encoding/payloads/cp_payload.h>
21
22 #define DNS_SERVER_MAX 2
23 #define NBNS_SERVER_MAX 2
24
25 typedef struct private_ike_config_t private_ike_config_t;
26
27 /**
28 * Private members of a ike_config_t task.
29 */
30 struct private_ike_config_t {
31
32 /**
33 * Public methods and task_t interface.
34 */
35 ike_config_t public;
36
37 /**
38 * Assigned IKE_SA.
39 */
40 ike_sa_t *ike_sa;
41
42 /**
43 * Are we the initiator?
44 */
45 bool initiator;
46
47 /**
48 * virtual ip
49 */
50 host_t *virtual_ip;
51 };
52
53 /**
54 * build INTERNAL_IPV4/6_ADDRESS from virtual ip
55 */
56 static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
57 {
58 configuration_attribute_t *ca;
59 chunk_t chunk, prefix;
60
61 ca = configuration_attribute_create();
62
63 if (vip->get_family(vip) == AF_INET)
64 {
65 ca->set_type(ca, INTERNAL_IP4_ADDRESS);
66 if (vip->is_anyaddr(vip))
67 {
68 chunk = chunk_empty;
69 }
70 else
71 {
72 chunk = vip->get_address(vip);
73 }
74 }
75 else
76 {
77 ca->set_type(ca, INTERNAL_IP6_ADDRESS);
78 if (vip->is_anyaddr(vip))
79 {
80 chunk = chunk_empty;
81 }
82 else
83 {
84 prefix = chunk_alloca(1);
85 *prefix.ptr = 64;
86 chunk = vip->get_address(vip);
87 chunk = chunk_cata("cc", chunk, prefix);
88 }
89 }
90 ca->set_value(ca, chunk);
91 cp->add_configuration_attribute(cp, ca);
92 }
93
94 /**
95 * process a single configuration attribute
96 */
97 static void process_attribute(private_ike_config_t *this,
98 configuration_attribute_t *ca)
99 {
100 host_t *ip;
101 chunk_t addr;
102 int family = AF_INET6;
103
104 switch (ca->get_type(ca))
105 {
106 case INTERNAL_IP4_ADDRESS:
107 family = AF_INET;
108 /* fall */
109 case INTERNAL_IP6_ADDRESS:
110 {
111 addr = ca->get_value(ca);
112 if (addr.len == 0)
113 {
114 ip = host_create_any(family);
115 }
116 else
117 {
118 /* skip prefix byte in IPv6 payload*/
119 if (family == AF_INET6)
120 {
121 addr.len--;
122 }
123 ip = host_create_from_chunk(family, addr, 0);
124 }
125 if (ip)
126 {
127 DESTROY_IF(this->virtual_ip);
128 this->virtual_ip = ip;
129 }
130 break;
131 }
132 default:
133 if (this->initiator)
134 {
135 this->ike_sa->add_configuration_attribute(this->ike_sa,
136 ca->get_type(ca), ca->get_value(ca));
137 }
138 else
139 {
140 /* we do not handle attribute requests other than for VIPs */
141 }
142 }
143 }
144
145 /**
146 * Scan for configuration payloads and attributes
147 */
148 static void process_payloads(private_ike_config_t *this, message_t *message)
149 {
150 enumerator_t *enumerator;
151 iterator_t *attributes;
152 payload_t *payload;
153
154 enumerator = message->create_payload_enumerator(message);
155 while (enumerator->enumerate(enumerator, &payload))
156 {
157 if (payload->get_type(payload) == CONFIGURATION)
158 {
159 cp_payload_t *cp = (cp_payload_t*)payload;
160 configuration_attribute_t *ca;
161 switch (cp->get_config_type(cp))
162 {
163 case CFG_REQUEST:
164 case CFG_REPLY:
165 {
166 attributes = cp->create_attribute_iterator(cp);
167 while (attributes->iterate(attributes, (void**)&ca))
168 {
169 process_attribute(this, ca);
170 }
171 attributes->destroy(attributes);
172 break;
173 }
174 default:
175 DBG1(DBG_IKE, "ignoring %N config payload",
176 config_type_names, cp->get_config_type(cp));
177 break;
178 }
179 }
180 }
181 enumerator->destroy(enumerator);
182 }
183
184 /**
185 * Implementation of task_t.process for initiator
186 */
187 static status_t build_i(private_ike_config_t *this, message_t *message)
188 {
189 if (message->get_message_id(message) == 1)
190 { /* in first IKE_AUTH only */
191 peer_cfg_t *config;
192 host_t *vip;
193
194 /* reuse virtual IP if we already have one */
195 vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
196 if (!vip)
197 {
198 config = this->ike_sa->get_peer_cfg(this->ike_sa);
199 vip = config->get_virtual_ip(config);
200 }
201 if (vip)
202 {
203 configuration_attribute_t *ca;
204 cp_payload_t *cp;
205
206 cp = cp_payload_create();
207 cp->set_config_type(cp, CFG_REQUEST);
208
209 build_vip(this, vip, cp);
210
211 /* we currently always add a DNS request if we request an IP */
212 ca = configuration_attribute_create();
213 if (vip->get_family(vip) == AF_INET)
214 {
215 ca->set_type(ca, INTERNAL_IP4_DNS);
216 }
217 else
218 {
219 ca->set_type(ca, INTERNAL_IP6_DNS);
220 }
221 cp->add_configuration_attribute(cp, ca);
222 message->add_payload(message, (payload_t*)cp);
223 }
224 }
225 return NEED_MORE;
226 }
227
228 /**
229 * Implementation of task_t.process for responder
230 */
231 static status_t process_r(private_ike_config_t *this, message_t *message)
232 {
233 if (message->get_message_id(message) == 1)
234 { /* in first IKE_AUTH only */
235 process_payloads(this, message);
236 }
237 return NEED_MORE;
238 }
239
240 /**
241 * Implementation of task_t.build for responder
242 */
243 static status_t build_r(private_ike_config_t *this, message_t *message)
244 {
245 if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
246 { /* in last IKE_AUTH exchange */
247 peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
248
249 if (config && this->virtual_ip)
250 {
251 enumerator_t *enumerator;
252 configuration_attribute_type_t type;
253 configuration_attribute_t *ca;
254 chunk_t value;
255 cp_payload_t *cp;
256 host_t *vip = NULL;
257
258 DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
259 if (config->get_pool(config))
260 {
261 vip = charon->attributes->acquire_address(charon->attributes,
262 config->get_pool(config),
263 this->ike_sa->get_other_id(this->ike_sa),
264 this->virtual_ip);
265 }
266 if (vip == NULL)
267 {
268 DBG1(DBG_IKE, "no virtual IP found, sending %N",
269 notify_type_names, INTERNAL_ADDRESS_FAILURE);
270 message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
271 chunk_empty);
272 return SUCCESS;
273 }
274 DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
275 this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
276
277 cp = cp_payload_create();
278 cp->set_config_type(cp, CFG_REQUEST);
279
280 build_vip(this, vip, cp);
281
282 /* if we add an IP, we also look for other attributes */
283 enumerator = charon->attributes->create_attribute_enumerator(
284 charon->attributes, this->ike_sa->get_other_id(this->ike_sa));
285 while (enumerator->enumerate(enumerator, &type, &value))
286 {
287 ca = configuration_attribute_create();
288 ca->set_type(ca, type);
289 ca->set_value(ca, value);
290 cp->add_configuration_attribute(cp, ca);
291 }
292 enumerator->destroy(enumerator);
293
294 message->add_payload(message, (payload_t*)cp);
295 }
296 return SUCCESS;
297 }
298 return NEED_MORE;
299 }
300
301 /**
302 * Implementation of task_t.process for initiator
303 */
304 static status_t process_i(private_ike_config_t *this, message_t *message)
305 {
306 if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
307 { /* in last IKE_AUTH exchange */
308
309 process_payloads(this, message);
310
311 if (this->virtual_ip)
312 {
313 this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
314 }
315 return SUCCESS;
316 }
317 return NEED_MORE;
318 }
319
320 /**
321 * Implementation of task_t.get_type
322 */
323 static task_type_t get_type(private_ike_config_t *this)
324 {
325 return IKE_CONFIG;
326 }
327
328 /**
329 * Implementation of task_t.migrate
330 */
331 static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
332 {
333 DESTROY_IF(this->virtual_ip);
334
335 this->ike_sa = ike_sa;
336 this->virtual_ip = NULL;
337 }
338
339 /**
340 * Implementation of task_t.destroy
341 */
342 static void destroy(private_ike_config_t *this)
343 {
344 DESTROY_IF(this->virtual_ip);
345 free(this);
346 }
347
348 /*
349 * Described in header.
350 */
351 ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
352 {
353 private_ike_config_t *this = malloc_thing(private_ike_config_t);
354
355 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
356 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
357 this->public.task.destroy = (void(*)(task_t*))destroy;
358
359 this->initiator = initiator;
360 this->ike_sa = ike_sa;
361 this->virtual_ip = NULL;
362
363 if (initiator)
364 {
365 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
366 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
367 }
368 else
369 {
370 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
371 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
372 }
373
374 return &this->public;
375 }
376