2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
21 #include "medcli_config.h"
24 #include <processing/jobs/callback_job.h>
26 typedef struct private_medcli_config_t private_medcli_config_t
;
29 * Private data of an medcli_config_t object
31 struct private_medcli_config_t
{
36 medcli_config_t
public;
60 * create a traffic selector from a CIDR notation string
62 static traffic_selector_t
*ts_from_string(char *str
)
71 pos
= strchr(str
, '/');
84 net
= host_create_from_string(str
, 0);
87 return traffic_selector_create_from_subnet(net
, netbits
, 0, 0);
90 return traffic_selector_create_dynamic(0, 0, 65535);
94 * implements backend_t.get_peer_cfg_by_name.
96 static peer_cfg_t
*get_peer_cfg_by_name(private_medcli_config_t
*this, char *name
)
99 peer_cfg_t
*peer_cfg
, *med_cfg
;
101 child_cfg_t
*child_cfg
;
103 char *address
, *local_net
, *remote_net
;
105 /* query mediation server config:
106 * - build ike_cfg/peer_cfg for mediation connection on-the-fly
108 e
= this->db
->query(this->db
,
109 "SELECT Address, ClientConfig.KeyId, MediationServerConfig.KeyId "
110 "FROM MediationServerConfig JOIN ClientConfig",
111 DB_TEXT
, DB_BLOB
, DB_BLOB
);
112 if (!e
|| !e
->enumerate(e
, &address
, &me
, &other
))
117 ike_cfg
= ike_cfg_create(FALSE
, FALSE
, "0.0.0.0", address
);
118 ike_cfg
->add_proposal(ike_cfg
, proposal_create_default(PROTO_IKE
));
119 med_cfg
= peer_cfg_create(
120 "mediation", 2, ike_cfg
,
121 identification_create_from_encoding(ID_KEY_ID
, me
),
122 identification_create_from_encoding(ID_KEY_ID
, other
),
123 CERT_NEVER_SEND
, UNIQUE_REPLACE
,
124 1, this->rekey
*60, 0, /* keytries, rekey, reauth */
125 this->rekey
*5, this->rekey
*3, /* jitter, overtime */
126 TRUE
, this->dpd
, /* mobike, dpddelay */
127 NULL
, NULL
, /* vip, pool */
128 TRUE
, NULL
, NULL
); /* mediation, med by, peer id */
131 /* query mediated config:
132 * - use any-any ike_cfg
133 * - build peer_cfg on-the-fly using med_cfg
136 e
= this->db
->query(this->db
,
137 "SELECT ClientConfig.KeyId, Connection.KeyId, "
138 "Connection.LocalSubnet, Connection.RemoteSubnet "
139 "FROM ClientConfig JOIN Connection "
140 "WHERE Active AND Alias = ?", DB_TEXT
, name
,
141 DB_BLOB
, DB_BLOB
, DB_TEXT
, DB_TEXT
);
142 if (!e
|| !e
->enumerate(e
, &me
, &other
, &local_net
, &remote_net
))
147 peer_cfg
= peer_cfg_create(
148 name
, 2, this->ike
->get_ref(this->ike
),
149 identification_create_from_encoding(ID_KEY_ID
, me
),
150 identification_create_from_encoding(ID_KEY_ID
, other
),
151 CERT_NEVER_SEND
, UNIQUE_REPLACE
,
152 1, this->rekey
*60, 0, /* keytries, rekey, reauth */
153 this->rekey
*5, this->rekey
*3, /* jitter, overtime */
154 TRUE
, this->dpd
, /* mobike, dpddelay */
155 NULL
, NULL
, /* vip, pool */
156 FALSE
, med_cfg
, /* mediation, med by */
157 identification_create_from_encoding(ID_KEY_ID
, other
));
159 child_cfg
= child_cfg_create(name
, this->rekey
*60 + this->rekey
,
160 this->rekey
*60, this->rekey
, NULL
, TRUE
,
161 MODE_TUNNEL
, ACTION_NONE
, ACTION_NONE
, FALSE
);
162 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
163 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts_from_string(local_net
));
164 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts_from_string(remote_net
));
165 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
171 * Implementation of backend_t.create_ike_cfg_enumerator.
173 static enumerator_t
* create_ike_cfg_enumerator(private_medcli_config_t
*this,
174 host_t
*me
, host_t
*other
)
176 return enumerator_create_single(this->ike
, NULL
);
180 /** implements enumerator */
182 /** inner SQL enumerator */
184 /** currently enumerated peer config */
186 /** ike cfg to use in peer cfg */
195 * Implementation of peer_enumerator_t.public.enumerate
197 static bool peer_enumerator_enumerate(peer_enumerator_t
*this, peer_cfg_t
**cfg
)
199 char *name
, *local_net
, *remote_net
;
201 child_cfg_t
*child_cfg
;
203 DESTROY_IF(this->current
);
204 if (!this->inner
->enumerate(this->inner
, &name
, &me
, &other
,
205 &local_net
, &remote_net
))
207 this->current
= NULL
;
210 this->current
= peer_cfg_create(
211 name
, 2, this->ike
->get_ref(this->ike
),
212 identification_create_from_encoding(ID_KEY_ID
, me
),
213 identification_create_from_encoding(ID_KEY_ID
, other
),
214 CERT_NEVER_SEND
, UNIQUE_REPLACE
,
215 1, this->rekey
*60, 0, /* keytries, rekey, reauth */
216 this->rekey
*5, this->rekey
*3, /* jitter, overtime */
217 TRUE
, this->dpd
, /* mobike, dpddelay */
218 NULL
, NULL
, /* vip, pool */
219 FALSE
, NULL
, NULL
); /* mediation, med by, peer id */
220 child_cfg
= child_cfg_create(
221 name
, this->rekey
*60 + this->rekey
,
222 this->rekey
*60, this->rekey
, NULL
, TRUE
,
223 MODE_TUNNEL
, ACTION_NONE
, ACTION_NONE
, FALSE
);
224 child_cfg
->add_proposal(child_cfg
, proposal_create_default(PROTO_ESP
));
225 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, ts_from_string(local_net
));
226 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, ts_from_string(remote_net
));
227 this->current
->add_child_cfg(this->current
, child_cfg
);
228 *cfg
= this->current
;
233 * Implementation of peer_enumerator_t.public.destroy
235 static void peer_enumerator_destroy(peer_enumerator_t
*this)
237 DESTROY_IF(this->current
);
238 this->inner
->destroy(this->inner
);
243 * Implementation of backend_t.create_peer_cfg_enumerator.
245 static enumerator_t
* create_peer_cfg_enumerator(private_medcli_config_t
*this,
246 identification_t
*me
,
247 identification_t
*other
)
249 peer_enumerator_t
*e
= malloc_thing(peer_enumerator_t
);
253 e
->rekey
= this->rekey
;
255 e
->public.enumerate
= (void*)peer_enumerator_enumerate
;
256 e
->public.destroy
= (void*)peer_enumerator_destroy
;
258 /* filter on IDs: NULL or ANY or matching KEY_ID */
259 e
->inner
= this->db
->query(this->db
,
260 "SELECT Alias, ClientConfig.KeyId, Connection.KeyId, "
261 "Connection.LocalSubnet, Connection.RemoteSubnet "
262 "FROM ClientConfig JOIN Connection "
264 "(? OR ClientConfig.KeyId = ?) AND (? OR Connection.KeyId = ?)",
265 DB_INT
, me
== NULL
|| me
->get_type(me
) == ID_ANY
,
266 DB_BLOB
, me
&& me
->get_type(me
) == ID_KEY_ID ?
267 me
->get_encoding(me
) : chunk_empty
,
268 DB_INT
, other
== NULL
|| other
->get_type(other
) == ID_ANY
,
269 DB_BLOB
, other
&& other
->get_type(other
) == ID_KEY_ID ?
270 other
->get_encoding(other
) : chunk_empty
,
271 DB_TEXT
, DB_BLOB
, DB_BLOB
, DB_TEXT
, DB_TEXT
);
281 * initiate a peer config
283 static job_requeue_t
initiate_config(peer_cfg_t
*peer_cfg
)
285 enumerator_t
*enumerator
;
286 child_cfg_t
*child_cfg
= NULL
;;
288 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
289 enumerator
->enumerate(enumerator
, &child_cfg
);
292 child_cfg
->get_ref(child_cfg
);
293 peer_cfg
->get_ref(peer_cfg
);
294 enumerator
->destroy(enumerator
);
295 charon
->controller
->initiate(charon
->controller
,
296 peer_cfg
, child_cfg
, NULL
, NULL
);
300 enumerator
->destroy(enumerator
);
302 return JOB_REQUEUE_NONE
;
306 * schedule initation of all "active" connections
308 static void schedule_autoinit(private_medcli_config_t
*this)
313 e
= this->db
->query(this->db
, "SELECT Alias FROM Connection WHERE Active",
317 while (e
->enumerate(e
, &name
))
319 peer_cfg_t
*peer_cfg
;
321 peer_cfg
= get_peer_cfg_by_name(this, name
);
324 /* schedule asynchronous initiation job */
325 charon
->processor
->queue_job(charon
->processor
,
326 (job_t
*)callback_job_create(
327 (callback_job_cb_t
)initiate_config
,
328 peer_cfg
, (void*)peer_cfg
->destroy
, NULL
));
336 * Implementation of medcli_config_t.destroy.
338 static void destroy(private_medcli_config_t
*this)
340 this->ike
->destroy(this->ike
);
345 * Described in header.
347 medcli_config_t
*medcli_config_create(database_t
*db
)
349 private_medcli_config_t
*this = malloc_thing(private_medcli_config_t
);
351 this->public.backend
.create_peer_cfg_enumerator
= (enumerator_t
*(*)(backend_t
*, identification_t
*me
, identification_t
*other
))create_peer_cfg_enumerator
;
352 this->public.backend
.create_ike_cfg_enumerator
= (enumerator_t
*(*)(backend_t
*, host_t
*me
, host_t
*other
))create_ike_cfg_enumerator
;
353 this->public.backend
.get_peer_cfg_by_name
= (peer_cfg_t
* (*)(backend_t
*,char*))get_peer_cfg_by_name
;
354 this->public.destroy
= (void(*)(medcli_config_t
*))destroy
;
357 this->rekey
= lib
->settings
->get_int(lib
->settings
,
358 "medcli.rekey", 20) * 60;
359 this->dpd
= lib
->settings
->get_int(lib
->settings
, "medcli.dpd", 300);
360 this->ike
= ike_cfg_create(FALSE
, FALSE
, "0.0.0.0", "0.0.0.0");
361 this->ike
->add_proposal(this->ike
, proposal_create_default(PROTO_IKE
));
363 schedule_autoinit(this);
365 return &this->public;