ike: Maintain per-IKE_SA CHILD_SAs in the global CHILD_SA manager
[strongswan.git] / src / libcharon / processing / jobs / mediation_job.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
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
16 #include "mediation_job.h"
17
18 #include <encoding/payloads/endpoint_notify.h>
19 #include <daemon.h>
20
21
22 typedef struct private_mediation_job_t private_mediation_job_t;
23
24 /**
25 * Private data of an mediation_job_t Object
26 */
27 struct private_mediation_job_t {
28 /**
29 * public mediation_job_t interface
30 */
31 mediation_job_t public;
32
33 /**
34 * ID of target peer.
35 */
36 identification_t *target;
37
38 /**
39 * ID of the source peer.
40 */
41 identification_t *source;
42
43 /**
44 * ME_CONNECTID
45 */
46 chunk_t connect_id;
47
48 /**
49 * ME_CONNECTKEY
50 */
51 chunk_t connect_key;
52
53 /**
54 * Submitted endpoints
55 */
56 linked_list_t *endpoints;
57
58 /**
59 * Is this a callback job?
60 */
61 bool callback;
62
63 /**
64 * Is this a response?
65 */
66 bool response;
67 };
68
69 METHOD(job_t, destroy, void,
70 private_mediation_job_t *this)
71 {
72 DESTROY_IF(this->target);
73 DESTROY_IF(this->source);
74 chunk_free(&this->connect_id);
75 chunk_free(&this->connect_key);
76 DESTROY_OFFSET_IF(this->endpoints, offsetof(endpoint_notify_t, destroy));
77 free(this);
78 }
79
80 METHOD(job_t, execute, job_requeue_t,
81 private_mediation_job_t *this)
82 {
83 ike_sa_id_t *target_sa_id;
84
85 target_sa_id = charon->mediation_manager->check(charon->mediation_manager, this->target);
86
87 if (target_sa_id)
88 {
89 ike_sa_t *target_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
90 target_sa_id);
91 if (target_sa)
92 {
93 if (this->callback)
94 {
95 /* send callback to a peer */
96 if (target_sa->callback(target_sa, this->source) != SUCCESS)
97 {
98 DBG1(DBG_JOB, "callback for '%Y' to '%Y' failed",
99 this->source, this->target);
100 charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
101 return JOB_REQUEUE_NONE;
102 }
103 }
104 else
105 {
106 /* normal mediation between two peers */
107 if (target_sa->relay(target_sa, this->source, this->connect_id,
108 this->connect_key, this->endpoints, this->response) != SUCCESS)
109 {
110 DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed",
111 this->source, this->target);
112 charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
113 /* FIXME: notify the initiator */
114 return JOB_REQUEUE_NONE;
115 }
116 }
117
118 charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
119 }
120 else
121 {
122 DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: "
123 "SA not found", this->source, this->target);
124 }
125 }
126 else
127 {
128 DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: "
129 "peer is not online anymore", this->source, this->target);
130 }
131 return JOB_REQUEUE_NONE;
132 }
133
134 METHOD(job_t, get_priority, job_priority_t,
135 private_mediation_job_t *this)
136 {
137 return JOB_PRIO_MEDIUM;
138 }
139
140 /**
141 * Creates an empty mediation job
142 */
143 static private_mediation_job_t *mediation_job_create_empty()
144 {
145 private_mediation_job_t *this;
146 INIT(this,
147 .public = {
148 .job_interface = {
149 .execute = _execute,
150 .get_priority = _get_priority,
151 .destroy = _destroy,
152 },
153 },
154 );
155 return this;
156 }
157
158 /*
159 * Described in header
160 */
161 mediation_job_t *mediation_job_create(identification_t *peer_id,
162 identification_t *requester, chunk_t connect_id, chunk_t connect_key,
163 linked_list_t *endpoints, bool response)
164 {
165 private_mediation_job_t *this = mediation_job_create_empty();
166
167 this->target = peer_id->clone(peer_id);
168 this->source = requester->clone(requester);
169 this->connect_id = chunk_clone(connect_id);
170 this->connect_key = chunk_clone(connect_key);
171 this->endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone));
172 this->response = response;
173
174 return &this->public;
175 }
176
177 /*
178 * Described in header
179 */
180 mediation_job_t *mediation_callback_job_create(identification_t *requester,
181 identification_t *peer_id)
182 {
183 private_mediation_job_t *this = mediation_job_create_empty();
184
185 this->target = requester->clone(requester);
186 this->source = peer_id->clone(peer_id);
187 this->callback = TRUE;
188
189 return &this->public;
190 }