configuration of NBNS server assignment via strongswan.conf
[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 * $Id$
17 */
18
19 #include "ike_config.h"
20
21 #include <daemon.h>
22 #include <encoding/payloads/cp_payload.h>
23
24 #define DNS_SERVER_MAX 2
25 #define NBNS_SERVER_MAX 2
26
27 typedef struct private_ike_config_t private_ike_config_t;
28
29 /**
30 * Private members of a ike_config_t task.
31 */
32 struct private_ike_config_t {
33
34 /**
35 * Public methods and task_t interface.
36 */
37 ike_config_t public;
38
39 /**
40 * Assigned IKE_SA.
41 */
42 ike_sa_t *ike_sa;
43
44 /**
45 * Are we the initiator?
46 */
47 bool initiator;
48
49 /**
50 * virtual ip
51 */
52 host_t *virtual_ip;
53
54 /**
55 * list of DNS servers
56 */
57 linked_list_t *dns;
58
59 /**
60 * list of WINS servers
61 */
62 linked_list_t *nbns;
63 };
64
65 /**
66 * build configuration payloads and attributes
67 */
68 static void build_payloads(private_ike_config_t *this, message_t *message,
69 config_type_t type)
70 {
71 cp_payload_t *cp;
72 configuration_attribute_t *ca;
73 chunk_t chunk, prefix;
74
75 if (!this->virtual_ip)
76 {
77 return;
78 }
79
80 cp = cp_payload_create();
81 cp->set_config_type(cp, type);
82
83 ca = configuration_attribute_create();
84
85 if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET)
86 {
87 ca->set_type(ca, INTERNAL_IP4_ADDRESS);
88 if (this->virtual_ip->is_anyaddr(this->virtual_ip))
89 {
90 chunk = chunk_empty;
91 }
92 else
93 {
94 chunk = this->virtual_ip->get_address(this->virtual_ip);
95 }
96 }
97 else
98 {
99 ca->set_type(ca, INTERNAL_IP6_ADDRESS);
100 if (this->virtual_ip->is_anyaddr(this->virtual_ip))
101 {
102 chunk = chunk_empty;
103 }
104 else
105 {
106 prefix = chunk_alloca(1);
107 *prefix.ptr = 64;
108 chunk = this->virtual_ip->get_address(this->virtual_ip);
109 chunk = chunk_cata("cc", chunk, prefix);
110 }
111 }
112 ca->set_value(ca, chunk);
113 cp->add_configuration_attribute(cp, ca);
114
115 /* we currently always add a DNS request if we request an IP */
116 if (this->initiator)
117 {
118 ca = configuration_attribute_create();
119 if (this->virtual_ip->get_family(this->virtual_ip) == AF_INET)
120 {
121 ca->set_type(ca, INTERNAL_IP4_DNS);
122 }
123 else
124 {
125 ca->set_type(ca, INTERNAL_IP6_DNS);
126 }
127 cp->add_configuration_attribute(cp, ca);
128 }
129 else
130 {
131 host_t *ip;
132 iterator_t *iterator;
133
134 /* Add internal DNS servers */
135 iterator = this->dns->create_iterator(this->dns, TRUE);
136 while (iterator->iterate(iterator, (void**)&ip))
137 {
138 ca = configuration_attribute_create();
139 if (ip->get_family(ip) == AF_INET)
140 {
141 ca->set_type(ca, INTERNAL_IP4_DNS);
142 }
143 else
144 {
145 ca->set_type(ca, INTERNAL_IP6_DNS);
146 }
147 chunk = ip->get_address(ip);
148 ca->set_value(ca, chunk);
149 cp->add_configuration_attribute(cp, ca);
150 }
151 iterator->destroy(iterator);
152
153 /* Add internal WINS servers */
154 iterator = this->nbns->create_iterator(this->nbns, TRUE);
155 while (iterator->iterate(iterator, (void**)&ip))
156 {
157 ca = configuration_attribute_create();
158 if (ip->get_family(ip) == AF_INET)
159 {
160 ca->set_type(ca, INTERNAL_IP4_NBNS);
161 }
162 else
163 {
164 ca->set_type(ca, INTERNAL_IP6_NBNS);
165 }
166 chunk = ip->get_address(ip);
167 ca->set_value(ca, chunk);
168 cp->add_configuration_attribute(cp, ca);
169 }
170 iterator->destroy(iterator);
171 }
172 message->add_payload(message, (payload_t*)cp);
173 }
174
175 /**
176 * process a single configuration attribute
177 */
178 static void process_attribute(private_ike_config_t *this,
179 configuration_attribute_t *ca)
180 {
181 host_t *ip;
182 chunk_t addr;
183 int family = AF_INET6;
184
185 switch (ca->get_type(ca))
186 {
187 case INTERNAL_IP4_ADDRESS:
188 family = AF_INET;
189 /* fall */
190 case INTERNAL_IP6_ADDRESS:
191 {
192 addr = ca->get_value(ca);
193 if (addr.len == 0)
194 {
195 ip = host_create_any(family);
196 }
197 else
198 {
199 /* skip prefix byte in IPv6 payload*/
200 if (family == AF_INET6)
201 {
202 addr.len--;
203 }
204 ip = host_create_from_chunk(family, addr, 0);
205 }
206 if (ip && !this->virtual_ip)
207 {
208 this->virtual_ip = ip;
209 }
210 break;
211 }
212 case INTERNAL_IP4_DNS:
213 family = AF_INET;
214 /* fall */
215 case INTERNAL_IP6_DNS:
216 {
217 addr = ca->get_value(ca);
218 if (addr.len == 0)
219 {
220 ip = host_create_any(family);
221 }
222 else
223 {
224 ip = host_create_from_chunk(family, addr, 0);
225 }
226 if (ip)
227 {
228 this->dns->insert_last(this->dns, ip);
229 }
230 break;
231 }
232 case INTERNAL_IP4_NBNS:
233 case INTERNAL_IP6_NBNS:
234 {
235 addr = ca->get_value(ca);
236 if (addr.len == 0)
237 {
238 ip = host_create_any(family);
239 }
240 else
241 {
242 ip = host_create_from_chunk(family, addr, 0);
243 }
244 if (ip)
245 {
246 this->nbns->insert_last(this->nbns, ip);
247 }
248 break;
249 }
250 default:
251 DBG1(DBG_IKE, "ignoring %N config attribute",
252 configuration_attribute_type_names,
253 ca->get_type(ca));
254 break;
255 }
256 }
257
258 /**
259 * Scan for configuration payloads and attributes
260 */
261 static void process_payloads(private_ike_config_t *this, message_t *message)
262 {
263 iterator_t *iterator, *attributes;
264 payload_t *payload;
265
266 iterator = message->get_payload_iterator(message);
267 while (iterator->iterate(iterator, (void**)&payload))
268 {
269 if (payload->get_type(payload) == CONFIGURATION)
270 {
271 cp_payload_t *cp = (cp_payload_t*)payload;
272 configuration_attribute_t *ca;
273 switch (cp->get_config_type(cp))
274 {
275 case CFG_REQUEST:
276 case CFG_REPLY:
277 {
278 attributes = cp->create_attribute_iterator(cp);
279 while (attributes->iterate(attributes, (void**)&ca))
280 {
281 process_attribute(this, ca);
282 }
283 attributes->destroy(attributes);
284 break;
285 }
286 default:
287 DBG1(DBG_IKE, "ignoring %N config payload",
288 config_type_names, cp->get_config_type(cp));
289 break;
290 }
291 }
292 }
293 iterator->destroy(iterator);
294 }
295
296 /**
297 * Implementation of task_t.process for initiator
298 */
299 static status_t build_i(private_ike_config_t *this, message_t *message)
300 {
301 if (message->get_exchange_type(message) == IKE_AUTH &&
302 message->get_payload(message, ID_INITIATOR))
303 {
304 peer_cfg_t *config;
305 host_t *vip;
306
307 /* reuse virtual IP if we already have one */
308 vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
309 if (!vip)
310 {
311 config = this->ike_sa->get_peer_cfg(this->ike_sa);
312 vip = config->get_virtual_ip(config);
313 }
314 if (vip)
315 {
316 this->virtual_ip = vip->clone(vip);
317 }
318
319 build_payloads(this, message, CFG_REQUEST);
320 }
321
322 return NEED_MORE;
323 }
324
325 /**
326 * Implementation of task_t.process for responder
327 */
328 static status_t process_r(private_ike_config_t *this, message_t *message)
329 {
330 if (message->get_exchange_type(message) == IKE_AUTH &&
331 message->get_payload(message, ID_INITIATOR))
332 {
333 process_payloads(this, message);
334 }
335 return NEED_MORE;
336 }
337
338 /**
339 * Implementation of task_t.build for responder
340 */
341 static status_t build_r(private_ike_config_t *this, message_t *message)
342 {
343 if (message->get_exchange_type(message) == IKE_AUTH &&
344 message->get_payload(message, EXTENSIBLE_AUTHENTICATION) == NULL)
345 {
346 peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
347
348 if (config && this->virtual_ip)
349 {
350 host_t *ip = NULL;
351
352 DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
353 if (config->get_pool(config))
354 {
355 ip = charon->attributes->acquire_address(charon->attributes,
356 config->get_pool(config),
357 this->ike_sa->get_other_id(this->ike_sa),
358 this->ike_sa->get_other_auth(this->ike_sa),
359 this->virtual_ip);
360 }
361 if (ip == NULL)
362 {
363 DBG1(DBG_IKE, "no virtual IP found, sending %N",
364 notify_type_names, INTERNAL_ADDRESS_FAILURE);
365 message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
366 chunk_empty);
367 return SUCCESS;
368 }
369 DBG1(DBG_IKE, "assigning virtual IP %H to peer", ip);
370 this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, ip);
371
372 this->virtual_ip->destroy(this->virtual_ip);
373 this->virtual_ip = ip;
374
375 build_payloads(this, message, CFG_REPLY);
376 }
377 return SUCCESS;
378 }
379 return NEED_MORE;
380 }
381
382 /**
383 * Implementation of task_t.process for initiator
384 */
385 static status_t process_i(private_ike_config_t *this, message_t *message)
386 {
387 if (message->get_exchange_type(message) == IKE_AUTH &&
388 !message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
389 {
390 host_t *ip;
391 peer_cfg_t *config;
392
393 DESTROY_IF(this->virtual_ip);
394 this->virtual_ip = NULL;
395
396 process_payloads(this, message);
397
398 if (this->virtual_ip == NULL)
399 { /* force a configured virtual IP, even if server didn't return one */
400 config = this->ike_sa->get_peer_cfg(this->ike_sa);
401 this->virtual_ip = config->get_virtual_ip(config);
402 if (this->virtual_ip)
403 {
404 this->virtual_ip = this->virtual_ip->clone(this->virtual_ip);
405 }
406 }
407
408 if (this->virtual_ip && !this->virtual_ip->is_anyaddr(this->virtual_ip))
409 {
410 this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
411
412 while (this->dns->remove_last(this->dns, (void**)&ip) == SUCCESS)
413 {
414 if (!ip->is_anyaddr(ip))
415 {
416 this->ike_sa->add_dns_server(this->ike_sa, ip);
417 }
418 ip->destroy(ip);
419 }
420 }
421 return SUCCESS;
422 }
423 return NEED_MORE;
424 }
425
426 /**
427 * Implementation of task_t.get_type
428 */
429 static task_type_t get_type(private_ike_config_t *this)
430 {
431 return IKE_CONFIG;
432 }
433
434 /**
435 * Implementation of task_t.migrate
436 */
437 static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
438 {
439 DESTROY_IF(this->virtual_ip);
440 this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
441
442 this->ike_sa = ike_sa;
443 this->virtual_ip = NULL;
444 this->dns = linked_list_create();
445 }
446
447 /**
448 * Implementation of task_t.destroy
449 */
450 static void destroy(private_ike_config_t *this)
451 {
452 DESTROY_IF(this->virtual_ip);
453 this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
454 this->nbns->destroy_offset(this->nbns, offsetof(host_t, destroy));
455 free(this);
456 }
457
458 /*
459 * Described in header.
460 */
461 ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
462 {
463 private_ike_config_t *this = malloc_thing(private_ike_config_t);
464
465 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
466 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
467 this->public.task.destroy = (void(*)(task_t*))destroy;
468
469 this->initiator = initiator;
470 this->ike_sa = ike_sa;
471 this->virtual_ip = NULL;
472 this->dns = linked_list_create();
473 this->nbns = linked_list_create();
474
475 if (initiator)
476 {
477 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
478 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
479 }
480 else
481 {
482 int i;
483
484 /* assign DNS servers */
485 for (i = 1; i <= DNS_SERVER_MAX; i++)
486 {
487 char dns_key[16], *dns_str;
488
489 snprintf(dns_key, sizeof(dns_key), "charon.dns%d", i);
490 dns_str = lib->settings->get_str(lib->settings, dns_key, NULL);
491 if (dns_str)
492 {
493 host_t *dns = host_create_from_string(dns_str, 0);
494
495 if (dns)
496 {
497 DBG2(DBG_CFG, "assigning DNS server %H to peer", dns);
498 this->dns->insert_last(this->dns, dns);
499 }
500 }
501 }
502
503 /* assign WINS servers */
504 for (i = 1; i <= NBNS_SERVER_MAX; i++)
505 {
506 char nbns_key[16], *nbns_str;
507
508 snprintf(nbns_key, sizeof(nbns_key), "charon.nbns%d", i);
509 nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL);
510 if (nbns_str)
511 {
512 host_t *nbns = host_create_from_string(nbns_str, 0);
513
514 if (nbns)
515 {
516 DBG2(DBG_CFG, "assigning NBNS server %H to peer", nbns);
517 this->nbns->insert_last(this->nbns, nbns);
518 }
519 }
520 }
521
522 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
523 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
524 }
525
526 return &this->public;
527 }