Migrated ike_cfg_t to METHOD/INIT macros
[strongswan.git] / src / charon / config / ike_cfg.c
1 /*
2 * Copyright (C) 2005-2007 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
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
17 #include "ike_cfg.h"
18
19 #include <string.h>
20
21 #include <daemon.h>
22
23
24 typedef struct private_ike_cfg_t private_ike_cfg_t;
25
26 /**
27 * Private data of an ike_cfg_t object
28 */
29 struct private_ike_cfg_t {
30
31 /**
32 * Public part
33 */
34 ike_cfg_t public;
35
36 /**
37 * Number of references hold by others to this ike_cfg
38 */
39 refcount_t refcount;
40
41 /**
42 * Address of local host
43 */
44 char *me;
45
46 /**
47 * Address of remote host
48 */
49 char *other;
50
51 /**
52 * should we send a certificate request?
53 */
54 bool certreq;
55
56 /**
57 * enforce UDP encapsulation
58 */
59 bool force_encap;
60
61 /**
62 * List of proposals to use
63 */
64 linked_list_t *proposals;
65 };
66
67 METHOD(ike_cfg_t, send_certreq, bool,
68 private_ike_cfg_t *this)
69 {
70 return this->certreq;
71 }
72
73 METHOD(ike_cfg_t, force_encap_, bool,
74 private_ike_cfg_t *this)
75 {
76 return this->force_encap;
77 }
78
79 METHOD(ike_cfg_t, get_my_addr, char*,
80 private_ike_cfg_t *this)
81 {
82 return this->me;
83 }
84
85 METHOD(ike_cfg_t, get_other_addr, char*,
86 private_ike_cfg_t *this)
87 {
88 return this->other;
89 }
90
91 METHOD(ike_cfg_t, add_proposal, void,
92 private_ike_cfg_t *this, proposal_t *proposal)
93 {
94 this->proposals->insert_last(this->proposals, proposal);
95 }
96
97 METHOD(ike_cfg_t, get_proposals, linked_list_t*,
98 private_ike_cfg_t *this)
99 {
100 enumerator_t *enumerator;
101 proposal_t *current;
102 linked_list_t *proposals;
103
104 proposals = linked_list_create();
105 enumerator = this->proposals->create_enumerator(this->proposals);
106 while (enumerator->enumerate(enumerator, &current))
107 {
108 current = current->clone(current);
109 proposals->insert_last(proposals, current);
110 }
111 enumerator->destroy(enumerator);
112
113 return proposals;
114 }
115
116 METHOD(ike_cfg_t, select_proposal, proposal_t*,
117 private_ike_cfg_t *this, linked_list_t *proposals, bool private)
118 {
119 iterator_t *stored_iter, *supplied_iter;
120 proposal_t *stored, *supplied, *selected;
121
122 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
123 supplied_iter = proposals->create_iterator(proposals, TRUE);
124
125
126 /* compare all stored proposals with all supplied. Stored ones are preferred.*/
127 while (stored_iter->iterate(stored_iter, (void**)&stored))
128 {
129 supplied_iter->reset(supplied_iter);
130
131 while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
132 {
133 selected = stored->select(stored, supplied, private);
134 if (selected)
135 {
136 /* they match, return */
137 stored_iter->destroy(stored_iter);
138 supplied_iter->destroy(supplied_iter);
139 DBG2(DBG_CFG, "received proposals: %#P", proposals);
140 DBG2(DBG_CFG, "configured proposals: %#P", this->proposals);
141 DBG2(DBG_CFG, "selected proposal: %P", selected);
142 return selected;
143 }
144 }
145 }
146 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
147 stored_iter->destroy(stored_iter);
148 supplied_iter->destroy(supplied_iter);
149 DBG1(DBG_CFG, "received proposals: %#P", proposals);
150 DBG1(DBG_CFG, "configured proposals: %#P", this->proposals);
151
152 return NULL;
153 }
154
155 METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
156 private_ike_cfg_t *this)
157 {
158 enumerator_t *enumerator;
159 proposal_t *proposal;
160 u_int16_t dh_group = MODP_NONE;
161
162 enumerator = this->proposals->create_enumerator(this->proposals);
163 while (enumerator->enumerate(enumerator, &proposal))
164 {
165 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
166 {
167 break;
168 }
169 }
170 enumerator->destroy(enumerator);
171 return dh_group;
172 }
173
174 METHOD(ike_cfg_t, equals, bool,
175 private_ike_cfg_t *this, ike_cfg_t *other_public)
176 {
177 private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
178 enumerator_t *e1, *e2;
179 proposal_t *p1, *p2;
180 bool eq = TRUE;
181
182 if (this == other)
183 {
184 return TRUE;
185 }
186 if (this->public.equals != other->public.equals)
187 {
188 return FALSE;
189 }
190 if (this->proposals->get_count(this->proposals) !=
191 other->proposals->get_count(other->proposals))
192 {
193 return FALSE;
194 }
195 e1 = this->proposals->create_enumerator(this->proposals);
196 e2 = this->proposals->create_enumerator(this->proposals);
197 while (e1->enumerate(e1, &p1) && e2->enumerate(e2, &p2))
198 {
199 if (!p1->equals(p1, p2))
200 {
201 eq = FALSE;
202 break;
203 }
204 }
205 e1->destroy(e1);
206 e2->destroy(e2);
207
208 return (eq &&
209 this->certreq == other->certreq &&
210 this->force_encap == other->force_encap &&
211 streq(this->me, other->me) &&
212 streq(this->other, other->other));
213 }
214
215 METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
216 private_ike_cfg_t *this)
217 {
218 ref_get(&this->refcount);
219 return &this->public;
220 }
221
222 METHOD(ike_cfg_t, destroy, void,
223 private_ike_cfg_t *this)
224 {
225 if (ref_put(&this->refcount))
226 {
227 this->proposals->destroy_offset(this->proposals,
228 offsetof(proposal_t, destroy));
229 free(this->me);
230 free(this->other);
231 free(this);
232 }
233 }
234
235 /**
236 * Described in header.
237 */
238 ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
239 char *me, char *other)
240 {
241 private_ike_cfg_t *this;
242
243 INIT(this,
244 .public = {
245 .send_certreq = _send_certreq,
246 .force_encap = _force_encap_,
247 .get_my_addr = _get_my_addr,
248 .get_other_addr = _get_other_addr,
249 .add_proposal = _add_proposal,
250 .get_proposals = _get_proposals,
251 .select_proposal = _select_proposal,
252 .get_dh_group = _get_dh_group,
253 .equals = _equals,
254 .get_ref = _get_ref,
255 .destroy = _destroy,
256 },
257 .refcount = 1,
258 .certreq = certreq,
259 .force_encap = force_encap,
260 .me = strdup(me),
261 .other = strdup(other),
262 .proposals = linked_list_create(),
263 );
264
265 return &this->public;
266 }