2 * Copyright (C) 2007 Martin Willi
3 * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
4 * Hochschule fuer Technik Rapperswil
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>.
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
17 #include "ike_config.h"
20 #include <encoding/payloads/cp_payload.h>
22 #define DNS_SERVER_MAX 2
23 #define NBNS_SERVER_MAX 2
25 typedef struct private_ike_config_t private_ike_config_t
;
28 * Private members of a ike_config_t task.
30 struct private_ike_config_t
{
33 * Public methods and task_t interface.
43 * Are we the initiator?
54 * build INTERNAL_IPV4/6_ADDRESS from virtual ip
56 static void build_vip(private_ike_config_t
*this, host_t
*vip
, cp_payload_t
*cp
)
58 configuration_attribute_t
*ca
;
59 chunk_t chunk
, prefix
;
61 ca
= configuration_attribute_create();
63 if (vip
->get_family(vip
) == AF_INET
)
65 ca
->set_type(ca
, INTERNAL_IP4_ADDRESS
);
66 if (vip
->is_anyaddr(vip
))
72 chunk
= vip
->get_address(vip
);
77 ca
->set_type(ca
, INTERNAL_IP6_ADDRESS
);
78 if (vip
->is_anyaddr(vip
))
84 prefix
= chunk_alloca(1);
86 chunk
= vip
->get_address(vip
);
87 chunk
= chunk_cata("cc", chunk
, prefix
);
90 ca
->set_value(ca
, chunk
);
91 cp
->add_configuration_attribute(cp
, ca
);
95 * process a single configuration attribute
97 static void process_attribute(private_ike_config_t
*this,
98 configuration_attribute_t
*ca
)
102 int family
= AF_INET6
;
104 switch (ca
->get_type(ca
))
106 case INTERNAL_IP4_ADDRESS
:
109 case INTERNAL_IP6_ADDRESS
:
111 addr
= ca
->get_value(ca
);
114 ip
= host_create_any(family
);
118 /* skip prefix byte in IPv6 payload*/
119 if (family
== AF_INET6
)
123 ip
= host_create_from_chunk(family
, addr
, 0);
127 DESTROY_IF(this->virtual_ip
);
128 this->virtual_ip
= ip
;
135 this->ike_sa
->add_configuration_attribute(this->ike_sa
,
136 ca
->get_type(ca
), ca
->get_value(ca
));
140 /* we do not handle attribute requests other than for VIPs */
146 * Scan for configuration payloads and attributes
148 static void process_payloads(private_ike_config_t
*this, message_t
*message
)
150 enumerator_t
*enumerator
;
151 iterator_t
*attributes
;
154 enumerator
= message
->create_payload_enumerator(message
);
155 while (enumerator
->enumerate(enumerator
, &payload
))
157 if (payload
->get_type(payload
) == CONFIGURATION
)
159 cp_payload_t
*cp
= (cp_payload_t
*)payload
;
160 configuration_attribute_t
*ca
;
161 switch (cp
->get_config_type(cp
))
166 attributes
= cp
->create_attribute_iterator(cp
);
167 while (attributes
->iterate(attributes
, (void**)&ca
))
169 process_attribute(this, ca
);
171 attributes
->destroy(attributes
);
175 DBG1(DBG_IKE
, "ignoring %N config payload",
176 config_type_names
, cp
->get_config_type(cp
));
181 enumerator
->destroy(enumerator
);
185 * Implementation of task_t.process for initiator
187 static status_t
build_i(private_ike_config_t
*this, message_t
*message
)
189 if (message
->get_message_id(message
) == 1)
190 { /* in first IKE_AUTH only */
194 /* reuse virtual IP if we already have one */
195 vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
198 config
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
199 vip
= config
->get_virtual_ip(config
);
203 configuration_attribute_t
*ca
;
206 cp
= cp_payload_create();
207 cp
->set_config_type(cp
, CFG_REQUEST
);
209 build_vip(this, vip
, cp
);
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
)
215 ca
->set_type(ca
, INTERNAL_IP4_DNS
);
219 ca
->set_type(ca
, INTERNAL_IP6_DNS
);
221 cp
->add_configuration_attribute(cp
, ca
);
222 message
->add_payload(message
, (payload_t
*)cp
);
229 * Implementation of task_t.process for responder
231 static status_t
process_r(private_ike_config_t
*this, message_t
*message
)
233 if (message
->get_message_id(message
) == 1)
234 { /* in first IKE_AUTH only */
235 process_payloads(this, message
);
241 * Implementation of task_t.build for responder
243 static status_t
build_r(private_ike_config_t
*this, message_t
*message
)
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
);
249 if (config
&& this->virtual_ip
)
251 enumerator_t
*enumerator
;
252 configuration_attribute_type_t type
;
253 configuration_attribute_t
*ca
;
258 DBG1(DBG_IKE
, "peer requested virtual IP %H", this->virtual_ip
);
259 if (config
->get_pool(config
))
261 vip
= charon
->attributes
->acquire_address(charon
->attributes
,
262 config
->get_pool(config
),
263 this->ike_sa
->get_other_id(this->ike_sa
),
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
,
274 DBG1(DBG_IKE
, "assigning virtual IP %H to peer", vip
);
275 this->ike_sa
->set_virtual_ip(this->ike_sa
, FALSE
, vip
);
277 cp
= cp_payload_create();
278 cp
->set_config_type(cp
, CFG_REPLY
);
280 build_vip(this, vip
, cp
);
283 /* if we add an IP, we also look for other attributes */
284 enumerator
= charon
->attributes
->create_attribute_enumerator(
285 charon
->attributes
, this->ike_sa
->get_other_id(this->ike_sa
));
286 while (enumerator
->enumerate(enumerator
, &type
, &value
))
288 ca
= configuration_attribute_create();
289 ca
->set_type(ca
, type
);
290 ca
->set_value(ca
, value
);
291 cp
->add_configuration_attribute(cp
, ca
);
293 enumerator
->destroy(enumerator
);
295 message
->add_payload(message
, (payload_t
*)cp
);
303 * Implementation of task_t.process for initiator
305 static status_t
process_i(private_ike_config_t
*this, message_t
*message
)
307 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_ESTABLISHED
)
308 { /* in last IKE_AUTH exchange */
310 process_payloads(this, message
);
312 if (this->virtual_ip
)
314 this->ike_sa
->set_virtual_ip(this->ike_sa
, TRUE
, this->virtual_ip
);
322 * Implementation of task_t.get_type
324 static task_type_t
get_type(private_ike_config_t
*this)
330 * Implementation of task_t.migrate
332 static void migrate(private_ike_config_t
*this, ike_sa_t
*ike_sa
)
334 DESTROY_IF(this->virtual_ip
);
336 this->ike_sa
= ike_sa
;
337 this->virtual_ip
= NULL
;
341 * Implementation of task_t.destroy
343 static void destroy(private_ike_config_t
*this)
345 DESTROY_IF(this->virtual_ip
);
350 * Described in header.
352 ike_config_t
*ike_config_create(ike_sa_t
*ike_sa
, bool initiator
)
354 private_ike_config_t
*this = malloc_thing(private_ike_config_t
);
356 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
357 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
358 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
360 this->initiator
= initiator
;
361 this->ike_sa
= ike_sa
;
362 this->virtual_ip
= NULL
;
366 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
367 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
371 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
372 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
375 return &this->public;