moved force_encap to ike_config, enables responder to enforce udp encapsulation
[strongswan.git] / src / charon / config / ike_cfg.c
1 /**
2 * @file ike_cfg.c
3 *
4 * @brief Implementation of ike_cfg_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include "ike_cfg.h"
25
26 #include <string.h>
27
28
29 typedef struct private_ike_cfg_t private_ike_cfg_t;
30
31 /**
32 * Private data of an ike_cfg_t object
33 */
34 struct private_ike_cfg_t {
35
36 /**
37 * Public part
38 */
39 ike_cfg_t public;
40
41 /**
42 * Number of references hold by others to this ike_cfg
43 */
44 refcount_t refcount;
45
46 /**
47 * Address of local host
48 */
49 host_t *my_host;
50
51 /**
52 * Address of remote host
53 */
54 host_t *other_host;
55
56 /**
57 * should we send a certificate request?
58 */
59 bool certreq;
60
61 /**
62 * enforce UDP encapsulation
63 */
64 bool force_encap;
65
66 /**
67 * List of proposals to use
68 */
69 linked_list_t *proposals;
70 };
71
72 /**
73 * Implementation of ike_cfg_t.certreq.
74 */
75 static bool send_certreq(private_ike_cfg_t *this)
76 {
77 return this->certreq;
78 }
79
80 /**
81 * Implementation of ike_cfg_t.force_encap.
82 */
83 static bool force_encap_meth(private_ike_cfg_t *this)
84 {
85 return this->force_encap;
86 }
87
88 /**
89 * Implementation of ike_cfg_t.get_my_host.
90 */
91 static host_t *get_my_host (private_ike_cfg_t *this)
92 {
93 return this->my_host;
94 }
95
96 /**
97 * Implementation of ike_cfg_t.get_other_host.
98 */
99 static host_t *get_other_host (private_ike_cfg_t *this)
100 {
101 return this->other_host;
102 }
103
104 /**
105 * Implementation of ike_cfg_t.add_proposal.
106 */
107 static void add_proposal(private_ike_cfg_t *this, proposal_t *proposal)
108 {
109 this->proposals->insert_last(this->proposals, proposal);
110 }
111
112 /**
113 * Implementation of ike_cfg_t.get_proposals.
114 */
115 static linked_list_t* get_proposals(private_ike_cfg_t *this)
116 {
117 iterator_t *iterator;
118 proposal_t *current;
119 linked_list_t *proposals = linked_list_create();
120
121 iterator = this->proposals->create_iterator(this->proposals, TRUE);
122 while (iterator->iterate(iterator, (void**)&current))
123 {
124 current = current->clone(current);
125 proposals->insert_last(proposals, (void*)current);
126 }
127 iterator->destroy(iterator);
128
129 return proposals;
130 }
131
132 /**
133 * Implementation of ike_cfg_t.select_proposal.
134 */
135 static proposal_t *select_proposal(private_ike_cfg_t *this,
136 linked_list_t *proposals)
137 {
138 iterator_t *stored_iter, *supplied_iter;
139 proposal_t *stored, *supplied, *selected;
140
141 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
142 supplied_iter = proposals->create_iterator(proposals, TRUE);
143
144 /* compare all stored proposals with all supplied. Stored ones are preferred.*/
145 while (stored_iter->iterate(stored_iter, (void**)&stored))
146 {
147 supplied_iter->reset(supplied_iter);
148
149 while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
150 {
151 selected = stored->select(stored, supplied);
152 if (selected)
153 {
154 /* they match, return */
155 stored_iter->destroy(stored_iter);
156 supplied_iter->destroy(supplied_iter);
157 return selected;
158 }
159 }
160 }
161 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
162 stored_iter->destroy(stored_iter);
163 supplied_iter->destroy(supplied_iter);
164
165 return NULL;
166 }
167
168 /**
169 * Implementation of ike_cfg_t.get_dh_group.
170 */
171 static diffie_hellman_group_t get_dh_group(private_ike_cfg_t *this)
172 {
173 iterator_t *iterator;
174 proposal_t *proposal;
175 algorithm_t *algo;
176 diffie_hellman_group_t dh_group = MODP_NONE;
177
178 iterator = this->proposals->create_iterator(this->proposals, TRUE);
179 while (iterator->iterate(iterator, (void**)&proposal))
180 {
181 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo))
182 {
183 dh_group = algo->algorithm;
184 break;
185 }
186 }
187 iterator->destroy(iterator);
188 return dh_group;
189 }
190
191 /**
192 * Implementation of ike_cfg_t.get_ref.
193 */
194 static void get_ref(private_ike_cfg_t *this)
195 {
196 ref_get(&this->refcount);
197 }
198
199 /**
200 * Implementation of ike_cfg_t.destroy.
201 */
202 static void destroy(private_ike_cfg_t *this)
203 {
204 if (ref_put(&this->refcount))
205 {
206 this->proposals->destroy_offset(this->proposals,
207 offsetof(proposal_t, destroy));
208 this->my_host->destroy(this->my_host);
209 this->other_host->destroy(this->other_host);
210 free(this);
211 }
212 }
213
214 /**
215 * Described in header.
216 */
217 ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
218 host_t *my_host, host_t *other_host)
219 {
220 private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t);
221
222 /* public functions */
223 this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq;
224 this->public.force_encap = (bool (*) (ike_cfg_t *))force_encap_meth;
225 this->public.get_my_host = (host_t*(*)(ike_cfg_t*))get_my_host;
226 this->public.get_other_host = (host_t*(*)(ike_cfg_t*))get_other_host;
227 this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal;
228 this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals;
229 this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal;
230 this->public.get_dh_group = (diffie_hellman_group_t(*)(ike_cfg_t*)) get_dh_group;
231 this->public.get_ref = (void(*)(ike_cfg_t*))get_ref;
232 this->public.destroy = (void(*)(ike_cfg_t*))destroy;
233
234 /* private variables */
235 this->refcount = 1;
236 this->certreq = certreq;
237 this->force_encap = force_encap;
238 this->my_host = my_host;
239 this->other_host = other_host;
240
241 this->proposals = linked_list_create();
242
243 return &this->public;
244 }