]>
Commit | Line | Data |
---|---|---|
17d92e97 MW |
1 | /** |
2 | * @file ike_mobike.c | |
3 | * | |
4 | * @brief Implementation of the ike_mobike task. | |
5 | * | |
6 | */ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2007 Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
22 | ||
23 | #include "ike_mobike.h" | |
24 | ||
25 | #include <string.h> | |
26 | ||
27 | #include <daemon.h> | |
28 | #include <encoding/payloads/notify_payload.h> | |
29 | ||
30 | ||
31 | typedef struct private_ike_mobike_t private_ike_mobike_t; | |
32 | ||
33 | /** | |
34 | * Private members of a ike_mobike_t task. | |
35 | */ | |
36 | struct private_ike_mobike_t { | |
37 | ||
38 | /** | |
39 | * Public methods and task_t interface. | |
40 | */ | |
41 | ike_mobike_t public; | |
42 | ||
43 | /** | |
44 | * Assigned IKE_SA. | |
45 | */ | |
46 | ike_sa_t *ike_sa; | |
47 | ||
48 | /** | |
49 | * Are we the initiator? | |
50 | */ | |
51 | bool initiator; | |
52 | ||
53 | /** | |
54 | * local host to roam to | |
55 | */ | |
56 | host_t *me; | |
57 | ||
58 | /** | |
59 | * remote host to roam to | |
60 | */ | |
61 | host_t *other; | |
62 | }; | |
63 | ||
64 | /** | |
65 | * flush the IKE_SAs list of additional addresses | |
66 | */ | |
67 | static void flush_additional_addresses(private_ike_mobike_t *this) | |
68 | { | |
69 | iterator_t *iterator; | |
70 | host_t *host; | |
71 | ||
72 | iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa); | |
73 | while (iterator->iterate(iterator, (void**)&host)) | |
74 | { | |
75 | iterator->remove(iterator); | |
76 | host->destroy(host); | |
77 | } | |
78 | iterator->destroy(iterator); | |
79 | } | |
80 | ||
81 | ||
82 | /** | |
83 | * read notifys from message and evaluate them | |
84 | */ | |
85 | static void process_payloads(private_ike_mobike_t *this, message_t *message) | |
86 | { | |
87 | iterator_t *iterator; | |
88 | payload_t *payload; | |
89 | bool first = TRUE; | |
90 | ||
91 | iterator = message->get_payload_iterator(message); | |
92 | while (iterator->iterate(iterator, (void**)&payload)) | |
93 | { | |
94 | int family = AF_INET; | |
95 | notify_payload_t *notify; | |
96 | chunk_t data; | |
97 | host_t *host; | |
98 | ||
99 | if (payload->get_type(payload) != NOTIFY) | |
100 | { | |
101 | continue; | |
102 | } | |
103 | notify = (notify_payload_t*)payload; | |
104 | switch (notify->get_notify_type(notify)) | |
105 | { | |
106 | case MOBIKE_SUPPORTED: | |
107 | { | |
108 | DBG2(DBG_IKE, "peer supports MOBIKE"); | |
109 | this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE); | |
110 | break; | |
111 | } | |
112 | case ADDITIONAL_IP6_ADDRESS: | |
113 | { | |
114 | family = AF_INET6; | |
115 | /* fall through */ | |
116 | } | |
117 | case ADDITIONAL_IP4_ADDRESS: | |
118 | { | |
119 | if (first) | |
120 | { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */ | |
121 | flush_additional_addresses(this); | |
122 | } | |
123 | data = notify->get_notification_data(notify); | |
124 | host = host_create_from_chunk(family, data, 0); | |
125 | DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host); | |
126 | this->ike_sa->add_additional_address(this->ike_sa, host); | |
127 | break; | |
128 | } | |
129 | case NO_ADDITIONAL_ADDRESSES: | |
130 | { | |
131 | flush_additional_addresses(this); | |
132 | break; | |
133 | } | |
134 | default: | |
135 | break; | |
136 | } | |
137 | } | |
138 | iterator->destroy(iterator); | |
139 | } | |
140 | ||
141 | /** | |
142 | * Add ADDITIONAL_*_ADDRESS notifys depending on our address list | |
143 | */ | |
144 | static void build_address_list(private_ike_mobike_t *this, message_t *message) | |
145 | { | |
146 | iterator_t *iterator; | |
147 | host_t *host, *me; | |
148 | notify_type_t type; | |
149 | bool additional = FALSE; | |
150 | ||
151 | me = this->ike_sa->get_my_host(this->ike_sa); | |
152 | iterator = charon->kernel_interface->create_address_iterator( | |
153 | charon->kernel_interface); | |
154 | while (iterator->iterate(iterator, (void**)&host)) | |
155 | { | |
156 | if (me->ip_equals(me, host)) | |
157 | { /* "ADDITIONAL" means do not include IKE_SAs host */ | |
158 | continue; | |
159 | } | |
160 | switch (host->get_family(host)) | |
161 | { | |
162 | case AF_INET: | |
163 | type = ADDITIONAL_IP4_ADDRESS; | |
164 | break; | |
165 | case AF_INET6: | |
166 | type = ADDITIONAL_IP6_ADDRESS; | |
167 | break; | |
168 | default: | |
169 | continue; | |
170 | } | |
171 | message->add_notify(message, FALSE, type, host->get_address(host)); | |
172 | additional = TRUE; | |
173 | } | |
174 | if (!additional) | |
175 | { | |
176 | message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty); | |
177 | } | |
178 | iterator->destroy(iterator); | |
179 | } | |
180 | ||
181 | /** | |
182 | * Implementation of task_t.process for initiator | |
183 | */ | |
184 | static status_t build_i(private_ike_mobike_t *this, message_t *message) | |
185 | { | |
186 | if (message->get_exchange_type(message) == IKE_AUTH && | |
187 | message->get_payload(message, SECURITY_ASSOCIATION)) | |
188 | { | |
189 | message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty); | |
190 | build_address_list(this, message); | |
191 | } | |
192 | ||
193 | return NEED_MORE; | |
194 | } | |
195 | ||
196 | /** | |
197 | * Implementation of task_t.process for responder | |
198 | */ | |
199 | static status_t process_r(private_ike_mobike_t *this, message_t *message) | |
200 | { | |
201 | process_payloads(this, message); | |
202 | ||
203 | return NEED_MORE; | |
204 | } | |
205 | ||
206 | /** | |
207 | * Implementation of task_t.build for responder | |
208 | */ | |
209 | static status_t build_r(private_ike_mobike_t *this, message_t *message) | |
210 | { | |
211 | if (message->get_exchange_type(message) == IKE_AUTH && | |
212 | message->get_payload(message, SECURITY_ASSOCIATION)) | |
213 | { | |
214 | if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE)) | |
215 | { | |
216 | message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty); | |
217 | build_address_list(this, message); | |
218 | } | |
219 | return SUCCESS; | |
220 | } | |
221 | return NEED_MORE; | |
222 | } | |
223 | ||
224 | /** | |
225 | * Implementation of task_t.process for initiator | |
226 | */ | |
227 | static status_t process_i(private_ike_mobike_t *this, message_t *message) | |
228 | { | |
229 | if (message->get_exchange_type(message) == IKE_AUTH && | |
230 | message->get_payload(message, SECURITY_ASSOCIATION)) | |
231 | { | |
232 | process_payloads(this, message); | |
233 | return SUCCESS; | |
234 | } | |
235 | return NEED_MORE; | |
236 | } | |
237 | ||
238 | /** | |
239 | * Implementation of ike_mobike_t.roam. | |
240 | */ | |
241 | static void roam(private_ike_mobike_t *this, host_t *me, host_t *other) | |
242 | { | |
243 | this->me = me; | |
244 | this->other = other; | |
245 | } | |
246 | ||
247 | /** | |
248 | * Implementation of task_t.get_type | |
249 | */ | |
250 | static task_type_t get_type(private_ike_mobike_t *this) | |
251 | { | |
252 | return IKE_MOBIKE; | |
253 | } | |
254 | ||
255 | /** | |
256 | * Implementation of task_t.migrate | |
257 | */ | |
258 | static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa) | |
259 | { | |
260 | DESTROY_IF(this->me); | |
261 | DESTROY_IF(this->other); | |
262 | this->ike_sa = ike_sa; | |
263 | this->me = NULL; | |
264 | this->other = NULL; | |
265 | } | |
266 | ||
267 | /** | |
268 | * Implementation of task_t.destroy | |
269 | */ | |
270 | static void destroy(private_ike_mobike_t *this) | |
271 | { | |
272 | DESTROY_IF(this->me); | |
273 | DESTROY_IF(this->other); | |
274 | free(this); | |
275 | } | |
276 | ||
277 | /* | |
278 | * Described in header. | |
279 | */ | |
280 | ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator) | |
281 | { | |
282 | private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t); | |
283 | ||
284 | this->public.roam = (void(*)(ike_mobike_t*, host_t *, host_t *))roam; | |
285 | this->public.task.get_type = (task_type_t(*)(task_t*))get_type; | |
286 | this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; | |
287 | this->public.task.destroy = (void(*)(task_t*))destroy; | |
288 | ||
289 | if (initiator) | |
290 | { | |
291 | this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; | |
292 | this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; | |
293 | } | |
294 | else | |
295 | { | |
296 | this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; | |
297 | this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; | |
298 | } | |
299 | ||
300 | this->ike_sa = ike_sa; | |
301 | this->initiator = initiator; | |
302 | this->me = NULL; | |
303 | this->other = NULL; | |
304 | ||
305 | return &this->public; | |
306 | } | |
307 |