Moving charon to libcharon.
[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 /**
70 * Implements job_t.destroy.
71 */
72 static void destroy(private_mediation_job_t *this)
73 {
74 DESTROY_IF(this->target);
75 DESTROY_IF(this->source);
76 chunk_free(&this->connect_id);
77 chunk_free(&this->connect_key);
78 DESTROY_OFFSET_IF(this->endpoints, offsetof(endpoint_notify_t, destroy));
79 free(this);
80 }
81
82 /**
83 * Implementation of job_t.execute.
84 */
85 static void execute(private_mediation_job_t *this)
86 {
87 ike_sa_id_t *target_sa_id;
88
89 target_sa_id = charon->mediation_manager->check(charon->mediation_manager, this->target);
90
91 if (target_sa_id)
92 {
93 ike_sa_t *target_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
94 target_sa_id);
95 if (target_sa)
96 {
97 if (this->callback)
98 {
99 /* send callback to a peer */
100 if (target_sa->callback(target_sa, this->source) != SUCCESS)
101 {
102 DBG1(DBG_JOB, "callback for '%Y' to '%Y' failed",
103 this->source, this->target);
104 charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
105 destroy(this);
106 return;
107 }
108 }
109 else
110 {
111 /* normal mediation between two peers */
112 if (target_sa->relay(target_sa, this->source, this->connect_id,
113 this->connect_key, this->endpoints, this->response) != SUCCESS)
114 {
115 DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed",
116 this->source, this->target);
117 charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
118 /* FIXME: notify the initiator */
119 destroy(this);
120 return;
121 }
122 }
123
124 charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa);
125 }
126 else
127 {
128 DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: "
129 "SA not found", this->source, this->target);
130 }
131 }
132 else
133 {
134 DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: "
135 "peer is not online anymore", this->source, this->target);
136 }
137 destroy(this);
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 = malloc_thing(private_mediation_job_t);
146
147 /* interface functions */
148 this->public.job_interface.execute = (void (*) (job_t *)) execute;
149 this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
150
151 /* private variables */
152 this->target = NULL;
153 this->source = NULL;
154 this->callback = FALSE;
155 this->connect_id = chunk_empty;
156 this->connect_key = chunk_empty;
157 this->endpoints = NULL;
158 this->response = FALSE;
159
160 return this;
161 }
162
163 /*
164 * Described in header
165 */
166 mediation_job_t *mediation_job_create(identification_t *peer_id,
167 identification_t *requester, chunk_t connect_id, chunk_t connect_key,
168 linked_list_t *endpoints, bool response)
169 {
170 private_mediation_job_t *this = mediation_job_create_empty();
171
172 this->target = peer_id->clone(peer_id);
173 this->source = requester->clone(requester);
174 this->connect_id = chunk_clone(connect_id);
175 this->connect_key = chunk_clone(connect_key);
176 this->endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone));
177 this->response = response;
178
179 return &this->public;
180 }
181
182 /*
183 * Described in header
184 */
185 mediation_job_t *mediation_callback_job_create(identification_t *requester,
186 identification_t *peer_id)
187 {
188 private_mediation_job_t *this = mediation_job_create_empty();
189
190 this->target = requester->clone(requester);
191 this->source = peer_id->clone(peer_id);
192 this->callback = TRUE;
193
194 return &this->public;
195 }