4 * @brief Implementation of the ike_config task.
9 * Copyright (C) 2007 Martin Willi
10 * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include "ike_config.h"
27 #include <encoding/payloads/cp_payload.h>
29 typedef struct private_ike_config_t private_ike_config_t
;
32 * Private members of a ike_config_t task.
34 struct private_ike_config_t
{
37 * Public methods and task_t interface.
47 * Are we the initiator?
63 * build configuration payloads and attributes
65 static void build_payloads(private_ike_config_t
*this, message_t
*message
,
69 configuration_attribute_t
*ca
;
70 chunk_t chunk
, prefix
;
72 if (!this->virtual_ip
)
77 cp
= cp_payload_create();
78 cp
->set_config_type(cp
, type
);
80 ca
= configuration_attribute_create();
82 if (this->virtual_ip
->get_family(this->virtual_ip
) == AF_INET
)
84 ca
->set_type(ca
, INTERNAL_IP4_ADDRESS
);
85 if (this->virtual_ip
->is_anyaddr(this->virtual_ip
))
91 chunk
= this->virtual_ip
->get_address(this->virtual_ip
);
96 ca
->set_type(ca
, INTERNAL_IP6_ADDRESS
);
97 if (this->virtual_ip
->is_anyaddr(this->virtual_ip
))
103 prefix
= chunk_alloca(1);
105 chunk
= this->virtual_ip
->get_address(this->virtual_ip
);
106 chunk
= chunk_cata("cc", chunk
, prefix
);
109 ca
->set_value(ca
, chunk
);
110 cp
->add_configuration_attribute(cp
, ca
);
112 /* we currently always add a DNS request if we request an IP */
115 ca
= configuration_attribute_create();
116 if (this->virtual_ip
->get_family(this->virtual_ip
) == AF_INET
)
118 ca
->set_type(ca
, INTERNAL_IP4_DNS
);
122 ca
->set_type(ca
, INTERNAL_IP6_DNS
);
124 cp
->add_configuration_attribute(cp
, ca
);
129 iterator_t
*iterator
= this->dns
->create_iterator(this->dns
, TRUE
);
130 while (iterator
->iterate(iterator
, (void**)&ip
))
132 ca
= configuration_attribute_create();
133 if (ip
->get_family(ip
) == AF_INET
)
135 ca
->set_type(ca
, INTERNAL_IP4_DNS
);
139 ca
->set_type(ca
, INTERNAL_IP6_DNS
);
141 chunk
= ip
->get_address(ip
);
142 ca
->set_value(ca
, chunk
);
143 cp
->add_configuration_attribute(cp
, ca
);
145 iterator
->destroy(iterator
);
147 message
->add_payload(message
, (payload_t
*)cp
);
151 * process a single configuration attribute
153 static void process_attribute(private_ike_config_t
*this,
154 configuration_attribute_t
*ca
)
158 int family
= AF_INET6
;
160 switch (ca
->get_type(ca
))
162 case INTERNAL_IP4_ADDRESS
:
165 case INTERNAL_IP6_ADDRESS
:
167 addr
= ca
->get_value(ca
);
170 ip
= host_create_any(family
);
174 /* skip prefix byte in IPv6 payload*/
175 if (family
== AF_INET6
)
179 ip
= host_create_from_chunk(family
, addr
, 0);
181 if (ip
&& !this->virtual_ip
)
183 this->virtual_ip
= ip
;
187 case INTERNAL_IP4_DNS
:
190 case INTERNAL_IP6_DNS
:
192 addr
= ca
->get_value(ca
);
195 ip
= host_create_any(family
);
199 ip
= host_create_from_chunk(family
, addr
, 0);
203 this->dns
->insert_last(this->dns
, ip
);
207 case INTERNAL_IP4_NBNS
:
208 case INTERNAL_IP6_NBNS
:
211 DBG1(DBG_IKE
, "ignoring %N config attribute",
212 configuration_attribute_type_names
,
219 * Scan for configuration payloads and attributes
221 static void process_payloads(private_ike_config_t
*this, message_t
*message
)
223 iterator_t
*iterator
, *attributes
;
226 iterator
= message
->get_payload_iterator(message
);
227 while (iterator
->iterate(iterator
, (void**)&payload
))
229 if (payload
->get_type(payload
) == CONFIGURATION
)
231 cp_payload_t
*cp
= (cp_payload_t
*)payload
;
232 configuration_attribute_t
*ca
;
233 switch (cp
->get_config_type(cp
))
238 attributes
= cp
->create_attribute_iterator(cp
);
239 while (attributes
->iterate(attributes
, (void**)&ca
))
241 process_attribute(this, ca
);
243 attributes
->destroy(attributes
);
247 DBG1(DBG_IKE
, "ignoring %N config payload",
248 config_type_names
, cp
->get_config_type(cp
));
253 iterator
->destroy(iterator
);
257 * Implementation of task_t.process for initiator
259 static status_t
build_i(private_ike_config_t
*this, message_t
*message
)
261 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
262 message
->get_payload(message
, ID_INITIATOR
))
267 /* reuse virtual IP if we already have one */
268 vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
271 this->virtual_ip
= vip
->clone(vip
);
275 config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
276 this->virtual_ip
= config
->get_my_virtual_ip(config
);
279 build_payloads(this, message
, CFG_REQUEST
);
286 * Implementation of task_t.process for responder
288 static status_t
process_r(private_ike_config_t
*this, message_t
*message
)
290 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
291 message
->get_payload(message
, ID_INITIATOR
))
293 process_payloads(this, message
);
299 * Implementation of task_t.build for responder
301 static status_t
build_r(private_ike_config_t
*this, message_t
*message
)
303 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
304 message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
) == NULL
)
306 peer_cfg_t
*config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
308 if (config
&& this->virtual_ip
)
312 DBG1(DBG_IKE
, "peer requested virtual IP %H", this->virtual_ip
);
313 ip
= config
->get_other_virtual_ip(config
, this->virtual_ip
);
314 if (ip
== NULL
|| ip
->is_anyaddr(ip
))
316 DBG1(DBG_IKE
, "not assigning a virtual IP to peer");
320 DBG1(DBG_IKE
, "assigning virtual IP %H to peer", ip
);
321 this->ike_sa
->set_virtual_ip(this->ike_sa
, FALSE
, ip
);
323 this->virtual_ip
->destroy(this->virtual_ip
);
324 this->virtual_ip
= ip
;
326 /* DNS testing values
327 if (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS)
330 ip = host_create_from_string("10.3.0.1", 0);
331 this->dns->insert_last(this->dns, ip);
332 ip = host_create_from_string("10.3.0.2", 0);
333 this->dns->insert_last(this->dns, ip);
336 build_payloads(this, message
, CFG_REPLY
);
344 * Implementation of task_t.process for initiator
346 static status_t
process_i(private_ike_config_t
*this, message_t
*message
)
348 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
349 !message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
354 DESTROY_IF(this->virtual_ip
);
355 this->virtual_ip
= NULL
;
357 process_payloads(this, message
);
359 if (this->virtual_ip
== NULL
)
360 { /* force a configured virtual IP, even server didn't return one */
361 config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
362 this->virtual_ip
= config
->get_my_virtual_ip(config
);
365 if (this->virtual_ip
&& !this->virtual_ip
->is_anyaddr(this->virtual_ip
))
367 this->ike_sa
->set_virtual_ip(this->ike_sa
, TRUE
, this->virtual_ip
);
369 while (this->dns
->remove_last(this->dns
, (void**)&ip
) == SUCCESS
)
371 if (!ip
->is_anyaddr(ip
))
373 this->ike_sa
->add_dns_server(this->ike_sa
, ip
);
384 * Implementation of task_t.get_type
386 static task_type_t
get_type(private_ike_config_t
*this)
392 * Implementation of task_t.migrate
394 static void migrate(private_ike_config_t
*this, ike_sa_t
*ike_sa
)
396 DESTROY_IF(this->virtual_ip
);
397 this->dns
->destroy_offset(this->dns
, offsetof(host_t
, destroy
));
399 this->ike_sa
= ike_sa
;
400 this->virtual_ip
= NULL
;
401 this->dns
= linked_list_create();
405 * Implementation of task_t.destroy
407 static void destroy(private_ike_config_t
*this)
409 DESTROY_IF(this->virtual_ip
);
410 this->dns
->destroy_offset(this->dns
, offsetof(host_t
, destroy
));
415 * Described in header.
417 ike_config_t
*ike_config_create(ike_sa_t
*ike_sa
, bool initiator
)
419 private_ike_config_t
*this = malloc_thing(private_ike_config_t
);
421 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
422 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
423 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
427 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
428 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
432 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
433 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
435 this->initiator
= initiator
;
436 this->ike_sa
= ike_sa
;
437 this->virtual_ip
= NULL
;
438 this->dns
= linked_list_create();
440 return &this->public;