added support for xfrm remote kmaddress
[strongswan.git] / src / charon / processing / jobs / migrate_job.c
1 /*
2 * Copyright (C) 2008 Andreas Steffen
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "migrate_job.h"
19
20 #include <daemon.h>
21
22 #include <config/child_cfg.h>
23
24
25 typedef struct private_migrate_job_t private_migrate_job_t;
26
27 /**
28 * Private data of a migrate_job_t object.
29 */
30 struct private_migrate_job_t {
31 /**
32 * Public migrate_job_t interface.
33 */
34 migrate_job_t public;
35
36 /**
37 * reqid of the CHILD_SA if it already exists
38 */
39 u_int32_t reqid;
40
41 /**
42 * source traffic selector
43 */
44 traffic_selector_t *src_ts;
45
46 /**
47 * destination traffic selector
48 */
49 traffic_selector_t *dst_ts;
50
51 /**
52 * local host address to be used for IKE
53 */
54 host_t *local;
55
56 /**
57 * remote host address to be used for IKE
58 */
59 host_t *remote;
60 };
61
62 /**
63 * Implementation of job_t.destroy.
64 */
65 static void destroy(private_migrate_job_t *this)
66 {
67 DESTROY_IF(this->src_ts);
68 DESTROY_IF(this->dst_ts);
69 DESTROY_IF(this->local);
70 DESTROY_IF(this->remote);
71 free(this);
72 }
73
74 /**
75 * Implementation of job_t.execute.
76 */
77 static void execute(private_migrate_job_t *this)
78 {
79 ike_sa_t *ike_sa = NULL;
80
81 if (this->reqid)
82 {
83 ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
84 this->reqid, TRUE);
85 }
86 if (ike_sa == NULL)
87 {
88 enumerator_t *enumerator, *children;
89 peer_cfg_t *peer_cfg;
90 child_cfg_t *found_cfg = NULL;
91
92 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
93 while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
94 {
95 child_cfg_t *child_cfg;
96
97 if (peer_cfg->get_ike_version(peer_cfg) != 2)
98 {
99 continue;
100 }
101
102 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
103 while (children->enumerate(children, &child_cfg))
104 {
105 if (child_cfg->equal_traffic_selectors(child_cfg, TRUE, this->src_ts) &&
106 child_cfg->equal_traffic_selectors(child_cfg, FALSE, this->dst_ts))
107 {
108 found_cfg = child_cfg;
109 break;
110 }
111 }
112 children->destroy(children);
113 if (found_cfg)
114 {
115 break;
116 }
117 }
118 enumerator->destroy(enumerator);
119
120 if (found_cfg == NULL)
121 {
122 DBG1(DBG_JOB, "no matching child config found for policy %R === %R",
123 this->src_ts, this->dst_ts);
124 destroy(this);
125 return;
126 }
127 DBG1(DBG_JOB, "found matching child config '%s' for policy %R === %R",
128 found_cfg->get_name(found_cfg),
129 this->src_ts, this->dst_ts);
130
131 ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
132 peer_cfg);
133 if (ike_sa->get_peer_cfg(ike_sa) == NULL)
134 {
135 host_t *my_host, *other_host;
136 ike_cfg_t *ike_cfg;
137
138 ike_sa->set_peer_cfg(ike_sa, peer_cfg);
139 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
140 my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0);
141 other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0);
142 ike_sa->set_my_host(ike_sa, my_host);
143 ike_sa->set_other_host(ike_sa, other_host);
144 }
145 if (this->local)
146 {
147 ike_sa->set_my_host(ike_sa, this->local->clone(this->local));
148 }
149 if (this->remote)
150 {
151 ike_sa->set_other_host(ike_sa, this->remote->clone(this->remote));
152 }
153 /* add a CHILD_SA for 'found_cfg' with a policy that has already been
154 * installed in the kernel
155 */
156 }
157 else
158 {
159 DBG1(DBG_JOB, "found CHILD_SA with reqid {%d}", this->reqid);
160 if (this->local)
161 {
162 ike_sa->set_my_host(ike_sa, this->local);
163 }
164 if (this->remote)
165 {
166 ike_sa->set_other_host(ike_sa, this->remote->clone(this->remote));
167 }
168 }
169 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
170 destroy(this);
171 }
172
173 /*
174 * Described in header
175 */
176 migrate_job_t *migrate_job_create(u_int32_t reqid,
177 traffic_selector_t *src_ts,
178 traffic_selector_t *dst_ts,
179 policy_dir_t dir,
180 host_t *local, host_t *remote)
181 {
182 private_migrate_job_t *this = malloc_thing(private_migrate_job_t);
183
184 /* interface functions */
185 this->public.job_interface.execute = (void (*) (job_t *)) execute;
186 this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
187
188 /* private variables */
189 this->reqid = reqid;
190 this->src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts;
191 this->dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts;
192 this->local = local;
193 this->remote = remote;
194
195 return &this->public;
196 }