]>
Commit | Line | Data |
---|---|---|
d1e348cf A |
1 | /* $NetBSD: handler.c,v 1.9.6.6 2007/06/06 09:20:12 vanhu Exp $ */ |
2 | ||
3 | /* Id: handler.c,v 1.28 2006/05/26 12:17:29 manubsd Exp */ | |
52b7d2ce A |
4 | |
5 | /* | |
6 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
7 | * All rights reserved. | |
8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. Neither the name of the project nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include "config.h" | |
35 | ||
36 | #include <sys/types.h> | |
37 | #include <sys/param.h> | |
38 | #include <sys/socket.h> | |
39 | ||
40 | #include <stdlib.h> | |
41 | #include <stdio.h> | |
42 | #include <string.h> | |
43 | #include <time.h> | |
44 | #include <errno.h> | |
45 | ||
46 | #include "var.h" | |
47 | #include "misc.h" | |
48 | #include "vmbuf.h" | |
49 | #include "plog.h" | |
50 | #include "sockmisc.h" | |
51 | #include "debug.h" | |
65c25746 | 52 | #include "fsm.h" |
52b7d2ce | 53 | |
d1e348cf A |
54 | #ifdef ENABLE_HYBRID |
55 | #include <resolv.h> | |
56 | #endif | |
57 | ||
52b7d2ce A |
58 | #include "schedule.h" |
59 | #include "grabmyaddr.h" | |
60 | #include "algorithm.h" | |
61 | #include "crypto_openssl.h" | |
62 | #include "policy.h" | |
63 | #include "proposal.h" | |
64 | #include "isakmp_var.h" | |
52b7d2ce A |
65 | #include "isakmp.h" |
66 | #ifdef ENABLE_HYBRID | |
67 | #include "isakmp_xauth.h" | |
68 | #include "isakmp_cfg.h" | |
69 | #endif | |
70 | #include "isakmp_inf.h" | |
71 | #include "oakley.h" | |
72 | #include "remoteconf.h" | |
73 | #include "localconf.h" | |
74 | #include "handler.h" | |
75 | #include "gcmalloc.h" | |
76 | #include "nattraversal.h" | |
d1e348cf | 77 | #include "ike_session.h" |
65c25746 | 78 | #include "isakmp_frag.h" |
d1e348cf A |
79 | |
80 | #include "sainfo.h" | |
52b7d2ce | 81 | |
e8d9021d | 82 | #include "power_mgmt.h" |
52b7d2ce | 83 | |
65c25746 | 84 | extern LIST_HEAD(_ike_session_tree_, ike_session) ike_session_tree; |
52b7d2ce A |
85 | static LIST_HEAD(_ctdtree_, contacted) ctdtree; |
86 | static LIST_HEAD(_rcptree_, recvdpkt) rcptree; | |
87 | ||
65c25746 A |
88 | static void ike_session_del_recvdpkt (struct recvdpkt *); |
89 | static void ike_session_rem_recvdpkt (struct recvdpkt *); | |
90 | static void sweep_recvdpkt (void *); | |
52b7d2ce A |
91 | |
92 | /* | |
93 | * functions about management of the isakmp status table | |
94 | */ | |
95 | /* %%% management phase 1 handler */ | |
96 | /* | |
97 | * search for isakmpsa handler with isakmp index. | |
98 | */ | |
99 | ||
65c25746 | 100 | extern caddr_t val2str (const char *, size_t); |
52b7d2ce | 101 | |
65c25746 A |
102 | static phase1_handle_t * |
103 | getph1byindex(ike_session_t *session, isakmp_index *index) | |
52b7d2ce | 104 | { |
65c25746 A |
105 | phase1_handle_t *p = NULL; |
106 | ||
107 | LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { | |
108 | if (FSM_STATE_IS_EXPIRED(p->status)) | |
52b7d2ce A |
109 | continue; |
110 | if (memcmp(&p->index, index, sizeof(*index)) == 0) | |
111 | return p; | |
112 | } | |
65c25746 | 113 | |
52b7d2ce A |
114 | return NULL; |
115 | } | |
116 | ||
65c25746 A |
117 | phase1_handle_t * |
118 | ike_session_getph1byindex(ike_session_t *session, isakmp_index *index) | |
119 | { | |
120 | phase1_handle_t *p; | |
121 | ike_session_t *cur_session = NULL; | |
122 | ||
123 | if (session) | |
124 | return getph1byindex(session, index); | |
125 | ||
126 | LIST_FOREACH(cur_session, &ike_session_tree, chain) { | |
127 | if ((p = getph1byindex(cur_session, index)) != NULL) | |
128 | return p; | |
129 | } | |
130 | return NULL; | |
131 | } | |
132 | ||
133 | ||
52b7d2ce A |
134 | /* |
135 | * search for isakmp handler by i_ck in index. | |
136 | */ | |
52b7d2ce | 137 | |
65c25746 A |
138 | static phase1_handle_t * |
139 | getph1byindex0 (ike_session_t *session, isakmp_index *index) | |
140 | { | |
141 | phase1_handle_t *p = NULL; | |
142 | ||
143 | LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { | |
144 | if (FSM_STATE_IS_EXPIRED(p->status)) | |
145 | continue; | |
146 | if (memcmp(&p->index.i_ck, &index->i_ck, sizeof(cookie_t)) == 0) | |
147 | return p; | |
148 | } | |
149 | return NULL; | |
150 | } | |
52b7d2ce | 151 | |
65c25746 A |
152 | phase1_handle_t * |
153 | ike_session_getph1byindex0(ike_session_t *session, isakmp_index *index) | |
154 | { | |
155 | phase1_handle_t *p = NULL; | |
156 | ike_session_t *cur_session = NULL; | |
157 | ||
158 | if (session) | |
159 | return getph1byindex0(session, index); | |
160 | ||
161 | LIST_FOREACH(cur_session, &ike_session_tree, chain) { | |
162 | if ((p = getph1byindex0(cur_session, index)) != NULL) | |
163 | return p; | |
164 | } | |
165 | ||
52b7d2ce A |
166 | return NULL; |
167 | } | |
168 | ||
169 | /* | |
170 | * search for isakmpsa handler by source and remote address. | |
171 | * don't use port number to search because this function search | |
172 | * with phase 2's destinaion. | |
173 | */ | |
65c25746 A |
174 | phase1_handle_t * |
175 | ike_session_getph1byaddr(ike_session_t *session, struct sockaddr_storage *local, struct sockaddr_storage *remote) | |
52b7d2ce | 176 | { |
65c25746 A |
177 | phase1_handle_t *p = NULL; |
178 | ||
179 | plog(ASL_LEVEL_DEBUG, "getph1byaddr: start\n"); | |
180 | plog(ASL_LEVEL_DEBUG, "local: %s\n", saddr2str((struct sockaddr *)local)); | |
181 | plog(ASL_LEVEL_DEBUG, "remote: %s\n", saddr2str((struct sockaddr *)remote)); | |
182 | ||
183 | LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { | |
184 | if (FSM_STATE_IS_EXPIRED(p->status)) | |
52b7d2ce | 185 | continue; |
65c25746 A |
186 | plog(ASL_LEVEL_DEBUG, "p->local: %s\n", saddr2str((struct sockaddr *)p->local)); |
187 | plog(ASL_LEVEL_DEBUG, "p->remote: %s\n", saddr2str((struct sockaddr *)p->remote)); | |
52b7d2ce | 188 | if (CMPSADDR(local, p->local) == 0 |
d1e348cf | 189 | && CMPSADDR(remote, p->remote) == 0){ |
65c25746 | 190 | plog(ASL_LEVEL_DEBUG, "matched\n"); |
52b7d2ce | 191 | return p; |
d1e348cf | 192 | } |
52b7d2ce | 193 | } |
65c25746 A |
194 | |
195 | plog(ASL_LEVEL_DEBUG, "no match\n"); | |
196 | ||
52b7d2ce A |
197 | return NULL; |
198 | } | |
199 | ||
65c25746 A |
200 | static phase1_handle_t * |
201 | sgetph1byaddrwop(ike_session_t *session, struct sockaddr_storage *local, struct sockaddr_storage *remote) | |
52b7d2ce | 202 | { |
65c25746 A |
203 | phase1_handle_t *p = NULL; |
204 | ||
205 | LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { | |
206 | if (FSM_STATE_IS_EXPIRED(p->status)) | |
52b7d2ce A |
207 | continue; |
208 | if (cmpsaddrwop(local, p->local) == 0 | |
65c25746 | 209 | && cmpsaddrwop(remote, p->remote) == 0) |
52b7d2ce A |
210 | return p; |
211 | } | |
65c25746 A |
212 | |
213 | return NULL; | |
214 | } | |
52b7d2ce | 215 | |
65c25746 A |
216 | phase1_handle_t * |
217 | ike_session_getph1byaddrwop(ike_session_t *session, struct sockaddr_storage *local, struct sockaddr_storage *remote) | |
218 | { | |
219 | phase1_handle_t *p; | |
220 | ike_session_t *cur_session = NULL; | |
221 | ||
222 | if (session) | |
223 | return sgetph1byaddrwop(session, local, remote); | |
224 | ||
225 | LIST_FOREACH(cur_session, &ike_session_tree, chain) { | |
226 | if ((p = sgetph1byaddrwop(cur_session, local, remote)) != NULL) | |
227 | return p; | |
228 | } | |
229 | ||
52b7d2ce A |
230 | return NULL; |
231 | } | |
232 | ||
233 | /* | |
234 | * search for isakmpsa handler by remote address. | |
235 | * don't use port number to search because this function search | |
236 | * with phase 2's destinaion. | |
237 | */ | |
65c25746 A |
238 | phase1_handle_t * |
239 | sike_session_getph1bydstaddrwop(ike_session_t *session, struct sockaddr_storage *remote) | |
52b7d2ce | 240 | { |
65c25746 A |
241 | phase1_handle_t *p = NULL; |
242 | ||
243 | LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { | |
244 | if (FSM_STATE_IS_EXPIRED(p->status)) | |
245 | continue; | |
246 | if (cmpsaddrwop(remote, p->remote) == 0) | |
247 | return p; | |
248 | } | |
249 | ||
250 | return NULL; | |
251 | } | |
52b7d2ce | 252 | |
65c25746 A |
253 | phase1_handle_t * |
254 | ike_session_getph1bydstaddrwop(ike_session_t *session, struct sockaddr_storage *remote) | |
255 | { | |
256 | phase1_handle_t *p; | |
257 | ike_session_t *cur_session = NULL; | |
258 | ||
259 | if (session) | |
260 | return sike_session_getph1bydstaddrwop(session, remote); | |
261 | else { | |
262 | LIST_FOREACH(cur_session, &ike_session_tree, chain) { | |
263 | if ((p = sike_session_getph1bydstaddrwop(cur_session, remote)) != NULL) | |
264 | return p; | |
265 | } | |
266 | } | |
267 | return NULL; | |
52b7d2ce A |
268 | } |
269 | ||
d1e348cf | 270 | int |
65c25746 | 271 | ike_session_islast_ph1(phase1_handle_t *ph1) |
d1e348cf | 272 | { |
65c25746 A |
273 | phase1_handle_t *p = NULL; |
274 | ||
275 | LIST_FOREACH(p, &ph1->parent_session->ph1tree, ph1ofsession_chain) { | |
276 | if (p->is_dying || FSM_STATE_IS_EXPIRED(p->status)) | |
d1e348cf A |
277 | continue; |
278 | if (CMPSADDR(ph1->remote, p->remote) == 0) { | |
279 | if (p == ph1) | |
280 | continue; | |
281 | return 0; | |
282 | } | |
283 | } | |
284 | return 1; | |
285 | } | |
286 | ||
52b7d2ce A |
287 | /* |
288 | * create new isakmp Phase 1 status record to handle isakmp in Phase1 | |
289 | */ | |
65c25746 A |
290 | phase1_handle_t * |
291 | ike_session_newph1(unsigned int version) | |
52b7d2ce | 292 | { |
65c25746 A |
293 | phase1_handle_t *iph1; |
294 | ||
52b7d2ce A |
295 | /* create new iph1 */ |
296 | iph1 = racoon_calloc(1, sizeof(*iph1)); | |
297 | if (iph1 == NULL) | |
298 | return NULL; | |
65c25746 | 299 | iph1->version = version; |
52b7d2ce A |
300 | |
301 | #ifdef ENABLE_DPD | |
302 | iph1->dpd_support = 0; | |
303 | iph1->dpd_lastack = 0; | |
304 | iph1->dpd_seq = 0; | |
305 | iph1->dpd_fails = 0; | |
d1e348cf | 306 | iph1->peer_sent_ike = 0; |
52b7d2ce A |
307 | iph1->dpd_r_u = NULL; |
308 | #endif | |
d1e348cf A |
309 | #ifdef ENABLE_VPNCONTROL_PORT |
310 | iph1->ping_sched = NULL; | |
311 | #endif | |
312 | iph1->is_dying = 0; | |
65c25746 | 313 | plog(ASL_LEVEL_DEBUG, "*** New Phase 1\n"); |
52b7d2ce A |
314 | return iph1; |
315 | } | |
316 | ||
317 | /* | |
318 | * delete new isakmp Phase 1 status record to handle isakmp in Phase1 | |
319 | */ | |
320 | void | |
65c25746 | 321 | ike_session_delph1(phase1_handle_t *iph1) |
52b7d2ce | 322 | { |
d1e348cf A |
323 | if (iph1 == NULL) |
324 | return; | |
65c25746 | 325 | |
52b7d2ce | 326 | #ifdef ENABLE_NATT |
52b7d2ce A |
327 | if (iph1->natt_options) { |
328 | racoon_free(iph1->natt_options); | |
329 | iph1->natt_options = NULL; | |
330 | } | |
331 | #endif | |
65c25746 | 332 | |
d1e348cf A |
333 | #ifdef ENABLE_HYBRID |
334 | if (iph1->mode_cfg) | |
335 | isakmp_cfg_rmstate(iph1); | |
336 | VPTRINIT(iph1->xauth_awaiting_userinput_msg); | |
337 | #endif | |
65c25746 | 338 | |
52b7d2ce | 339 | #ifdef ENABLE_DPD |
65c25746 | 340 | if (iph1->dpd_r_u) |
52b7d2ce A |
341 | SCHED_KILL(iph1->dpd_r_u); |
342 | #endif | |
d1e348cf | 343 | #ifdef ENABLE_VPNCONTROL_PORT |
65c25746 | 344 | if (iph1->ping_sched) |
d1e348cf A |
345 | SCHED_KILL(iph1->ping_sched); |
346 | #endif | |
65c25746 | 347 | |
52b7d2ce A |
348 | if (iph1->remote) { |
349 | racoon_free(iph1->remote); | |
350 | iph1->remote = NULL; | |
351 | } | |
352 | if (iph1->local) { | |
353 | racoon_free(iph1->local); | |
354 | iph1->local = NULL; | |
355 | } | |
65c25746 | 356 | |
52b7d2ce A |
357 | if (iph1->approval) { |
358 | delisakmpsa(iph1->approval); | |
359 | iph1->approval = NULL; | |
360 | } | |
65c25746 | 361 | |
52b7d2ce | 362 | sched_scrub_param(iph1); |
65c25746 A |
363 | if (iph1->sce) |
364 | SCHED_KILL(iph1->sce); | |
365 | if (iph1->sce_rekey) | |
366 | SCHED_KILL(iph1->sce_rekey); | |
367 | if (iph1->scr) | |
368 | SCHED_KILL(iph1->scr); | |
369 | ||
52b7d2ce | 370 | VPTRINIT(iph1->sendbuf); |
65c25746 | 371 | |
52b7d2ce A |
372 | VPTRINIT(iph1->dhpriv); |
373 | VPTRINIT(iph1->dhpub); | |
374 | VPTRINIT(iph1->dhpub_p); | |
375 | VPTRINIT(iph1->dhgxy); | |
376 | VPTRINIT(iph1->nonce); | |
377 | VPTRINIT(iph1->nonce_p); | |
378 | VPTRINIT(iph1->skeyid); | |
379 | VPTRINIT(iph1->skeyid_d); | |
380 | VPTRINIT(iph1->skeyid_a); | |
65c25746 | 381 | VPTRINIT(iph1->skeyid_a_p); |
52b7d2ce | 382 | VPTRINIT(iph1->skeyid_e); |
65c25746 | 383 | VPTRINIT(iph1->skeyid_e_p); |
52b7d2ce | 384 | VPTRINIT(iph1->key); |
65c25746 | 385 | VPTRINIT(iph1->key_p); |
52b7d2ce A |
386 | VPTRINIT(iph1->hash); |
387 | VPTRINIT(iph1->sig); | |
388 | VPTRINIT(iph1->sig_p); | |
389 | oakley_delcert(iph1->cert); | |
390 | iph1->cert = NULL; | |
391 | oakley_delcert(iph1->cert_p); | |
392 | iph1->cert_p = NULL; | |
393 | oakley_delcert(iph1->crl_p); | |
394 | iph1->crl_p = NULL; | |
395 | oakley_delcert(iph1->cr_p); | |
396 | iph1->cr_p = NULL; | |
397 | VPTRINIT(iph1->id); | |
398 | VPTRINIT(iph1->id_p); | |
65c25746 | 399 | |
d1e348cf A |
400 | if(iph1->approval != NULL) |
401 | delisakmpsa(iph1->approval); | |
65c25746 | 402 | |
52b7d2ce A |
403 | if (iph1->ivm) { |
404 | oakley_delivm(iph1->ivm); | |
405 | iph1->ivm = NULL; | |
406 | } | |
65c25746 | 407 | |
52b7d2ce A |
408 | VPTRINIT(iph1->sa); |
409 | VPTRINIT(iph1->sa_ret); | |
65c25746 | 410 | |
d1e348cf | 411 | if (iph1->rmconf) { |
65c25746 | 412 | release_rmconf(iph1->rmconf); |
d1e348cf A |
413 | iph1->rmconf = NULL; |
414 | } | |
65c25746 | 415 | |
52b7d2ce A |
416 | racoon_free(iph1); |
417 | } | |
418 | ||
52b7d2ce | 419 | void |
65c25746 | 420 | ike_session_flush_all_phase1_for_session(ike_session_t *session, int ignore_estab_or_assert_handles) |
52b7d2ce | 421 | { |
65c25746 A |
422 | phase1_handle_t *p, *next; |
423 | ||
424 | LIST_FOREACH_SAFE(p, &session->ph1tree, ph1ofsession_chain, next) { | |
425 | if (ignore_estab_or_assert_handles && p->parent_session && !p->parent_session->stopped_by_vpn_controller && p->parent_session->is_asserted) { | |
426 | plog(ASL_LEVEL_DEBUG, | |
427 | "Skipping Phase 1 %s that's asserted...\n", | |
428 | isakmp_pindex(&p->index, 0)); | |
429 | continue; | |
430 | } | |
431 | ||
432 | /* send delete information */ | |
433 | if (FSM_STATE_IS_ESTABLISHED(p->status)) { | |
434 | if (ignore_estab_or_assert_handles && | |
435 | (ike_session_has_negoing_ph2(p->parent_session) || ike_session_has_established_ph2(p->parent_session))) { | |
436 | plog(ASL_LEVEL_DEBUG, | |
437 | "Skipping Phase 1 %s that's established... because it's needed by children Phase 2s\n", | |
438 | isakmp_pindex(&p->index, 0)); | |
439 | continue; | |
440 | } | |
441 | /* send delete information */ | |
442 | plog(ASL_LEVEL_DEBUG, | |
443 | "Got a Phase 1 %s to flush...\n", | |
444 | isakmp_pindex(&p->index, 0)); | |
445 | isakmp_info_send_d1(p); | |
446 | } | |
447 | ||
448 | ike_session_stopped_by_controller(p->parent_session, | |
449 | ike_session_stopped_by_flush); | |
450 | ||
451 | ike_session_unlink_phase1(p); | |
452 | } | |
52b7d2ce A |
453 | } |
454 | ||
455 | /* | |
456 | * flush isakmp-sa | |
457 | */ | |
458 | void | |
65c25746 | 459 | ike_session_flush_all_phase1(int ignore_estab_or_assert_handles) |
52b7d2ce | 460 | { |
65c25746 A |
461 | ike_session_t *session = NULL; |
462 | ike_session_t *next_session = NULL; | |
d1e348cf | 463 | |
65c25746 A |
464 | plog(ASL_LEVEL_DEBUG, |
465 | "Flushing Phase 1 handles: ignore_estab_or_assert %d...\n", ignore_estab_or_assert_handles); | |
466 | ||
467 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
468 | ike_session_flush_all_phase1_for_session(session, ignore_estab_or_assert_handles); | |
469 | } | |
52b7d2ce A |
470 | } |
471 | ||
52b7d2ce | 472 | |
65c25746 | 473 | |
52b7d2ce A |
474 | /* |
475 | * search ph2handle with policy id. | |
476 | */ | |
65c25746 A |
477 | phase2_handle_t * |
478 | ike_session_getph2byspid(u_int32_t spid) | |
52b7d2ce | 479 | { |
65c25746 A |
480 | ike_session_t *session = NULL; |
481 | phase2_handle_t *p; | |
482 | ||
483 | LIST_FOREACH(session, &ike_session_tree, chain) { | |
484 | LIST_FOREACH(p, &session->ph2tree, ph2ofsession_chain) { | |
485 | /* | |
486 | * there are ph2handle independent on policy | |
487 | * such like informational exchange. | |
488 | */ | |
489 | if (p->spid == spid) | |
490 | return p; | |
491 | } | |
492 | } | |
493 | ||
52b7d2ce A |
494 | return NULL; |
495 | } | |
496 | ||
65c25746 | 497 | |
52b7d2ce A |
498 | /* |
499 | * search ph2handle with sequence number. | |
65c25746 | 500 | * Used by PF_KEY functions to locate the phase2 |
52b7d2ce | 501 | */ |
65c25746 A |
502 | phase2_handle_t * |
503 | ike_session_getph2byseq(u_int32_t seq) | |
52b7d2ce | 504 | { |
65c25746 A |
505 | ike_session_t *session; |
506 | phase2_handle_t *p; | |
507 | ||
508 | LIST_FOREACH(session, &ike_session_tree, chain) { | |
509 | LIST_FOREACH(p, &session->ph2tree, ph2ofsession_chain) { | |
510 | if (p->seq == seq) | |
511 | return p; | |
512 | } | |
513 | } | |
52b7d2ce A |
514 | return NULL; |
515 | } | |
516 | ||
517 | /* | |
518 | * search ph2handle with message id. | |
519 | */ | |
65c25746 A |
520 | phase2_handle_t * |
521 | ike_session_getph2bymsgid(phase1_handle_t *iph1, u_int32_t msgid) | |
52b7d2ce | 522 | { |
65c25746 A |
523 | phase2_handle_t *p; |
524 | ||
525 | LIST_FOREACH(p, &iph1->parent_session->ph2tree, ph2ofsession_chain) { | |
d9c572c0 | 526 | if (p->msgid == msgid && !p->is_defunct) |
52b7d2ce A |
527 | return p; |
528 | } | |
65c25746 | 529 | |
52b7d2ce A |
530 | return NULL; |
531 | } | |
532 | ||
65c25746 A |
533 | phase2_handle_t * |
534 | ike_session_getonlyph2(phase1_handle_t *iph1) | |
52b7d2ce | 535 | { |
65c25746 A |
536 | phase2_handle_t *only_ph2 = NULL; |
537 | phase2_handle_t *p = NULL; | |
538 | ||
539 | LIST_FOREACH(p, &iph1->bound_ph2tree, ph2ofsession_chain) { | |
540 | if (only_ph2) return NULL; | |
541 | only_ph2 = p; | |
542 | } | |
543 | ||
544 | return only_ph2; | |
545 | } | |
52b7d2ce | 546 | |
65c25746 A |
547 | phase2_handle_t * |
548 | ike_session_getph2byid(struct sockaddr_storage *src, struct sockaddr_storage *dst, u_int32_t spid) | |
549 | { | |
550 | ike_session_t *session = NULL; | |
551 | ike_session_t *next_session = NULL; | |
552 | phase2_handle_t *p; | |
553 | phase2_handle_t *next_iph2; | |
554 | ||
555 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
556 | LIST_FOREACH_SAFE(p, &session->ph2tree, ph2ofsession_chain, next_iph2) { | |
557 | if (spid == p->spid && | |
558 | CMPSADDR(src, p->src) == 0 && | |
559 | CMPSADDR(dst, p->dst) == 0){ | |
560 | /* Sanity check to detect zombie handlers | |
561 | * XXX Sould be done "somewhere" more interesting, | |
562 | * because we have lots of getph2byxxxx(), but this one | |
563 | * is called by pk_recvacquire(), so is the most important. | |
564 | */ | |
565 | if(!FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p->status) && | |
566 | p->retry_counter == 0 | |
567 | && p->sce == 0 && p->scr == 0 && | |
568 | p->retry_checkph1 == 0){ | |
569 | plog(ASL_LEVEL_DEBUG, | |
570 | "Zombie ph2 found, expiring it\n"); | |
571 | isakmp_ph2expire(p); | |
572 | }else | |
573 | return p; | |
574 | } | |
575 | } | |
576 | } | |
577 | ||
52b7d2ce A |
578 | return NULL; |
579 | } | |
580 | ||
65c25746 A |
581 | #ifdef NOT_USED |
582 | phase2_handle_t * | |
583 | ike_session_getph2bysaddr(struct sockaddr_storage *src, struct sockaddr_storage *dst) | |
52b7d2ce | 584 | { |
65c25746 A |
585 | ike_session_t *session; |
586 | phase2_handle_t *p; | |
587 | ||
588 | LIST_FOREACH(session, &ike_session_tree, chain) { | |
589 | LIST_FOREACH(p, &session->ph2tree, chain) { | |
590 | if (cmpsaddrstrict(src, p->src) == 0 && | |
591 | cmpsaddrstrict(dst, p->dst) == 0) | |
592 | return p; | |
593 | } | |
594 | } | |
595 | ||
52b7d2ce A |
596 | return NULL; |
597 | } | |
65c25746 | 598 | #endif /* NOT_USED */ |
52b7d2ce A |
599 | |
600 | /* | |
601 | * call by pk_recvexpire(). | |
602 | */ | |
65c25746 A |
603 | phase2_handle_t * |
604 | ike_session_getph2bysaidx(struct sockaddr_storage *src, struct sockaddr_storage *dst, u_int proto_id, u_int32_t spi) | |
52b7d2ce | 605 | { |
65c25746 A |
606 | ike_session_t *session; |
607 | phase2_handle_t *iph2; | |
52b7d2ce | 608 | struct saproto *pr; |
65c25746 A |
609 | |
610 | LIST_FOREACH(session, &ike_session_tree, chain) { | |
611 | LIST_FOREACH(iph2, &session->ph2tree, ph2ofsession_chain) { | |
612 | if (iph2->proposal == NULL && iph2->approval == NULL) | |
613 | continue; | |
614 | if (iph2->approval != NULL) { | |
615 | for (pr = iph2->approval->head; pr != NULL; | |
616 | pr = pr->next) { | |
617 | if (proto_id != pr->proto_id) | |
618 | break; | |
619 | if (spi == pr->spi || spi == pr->spi_p) | |
620 | return iph2; | |
621 | } | |
622 | } else if (iph2->proposal != NULL) { | |
623 | for (pr = iph2->proposal->head; pr != NULL; | |
624 | pr = pr->next) { | |
625 | if (proto_id != pr->proto_id) | |
626 | break; | |
627 | if (spi == pr->spi) | |
628 | return iph2; | |
629 | } | |
630 | } | |
631 | } | |
632 | } | |
633 | ||
634 | return NULL; | |
635 | } | |
52b7d2ce | 636 | |
65c25746 A |
637 | phase2_handle_t * |
638 | ike_session_getph2bysaidx2(struct sockaddr_storage *src, struct sockaddr_storage *dst, u_int proto_id, u_int32_t spi, u_int32_t *opposite_spi) | |
639 | { | |
640 | ike_session_t *session; | |
641 | phase2_handle_t *iph2; | |
642 | struct saproto *pr; | |
643 | ||
644 | LIST_FOREACH(session, &ike_session_tree, chain) { | |
645 | LIST_FOREACH(iph2, &session->ph2tree, ph2ofsession_chain) { | |
646 | if (iph2->proposal == NULL && iph2->approval == NULL) | |
647 | continue; | |
648 | if (iph2->approval != NULL) { | |
649 | for (pr = iph2->approval->head; pr != NULL; | |
650 | pr = pr->next) { | |
651 | if (proto_id != pr->proto_id) | |
652 | break; | |
653 | if (spi == pr->spi || spi == pr->spi_p) { | |
654 | if (opposite_spi) { | |
655 | *opposite_spi = (spi == pr->spi)? pr->spi_p : pr->spi; | |
656 | } | |
657 | return iph2; | |
658 | } | |
659 | } | |
660 | } else if (iph2->proposal != NULL) { | |
661 | for (pr = iph2->proposal->head; pr != NULL; | |
662 | pr = pr->next) { | |
663 | if (proto_id != pr->proto_id) | |
664 | break; | |
665 | if (spi == pr->spi || spi == pr->spi_p) { | |
666 | if (opposite_spi) { | |
667 | *opposite_spi = (spi == pr->spi)? pr->spi_p : pr->spi; | |
668 | } | |
669 | return iph2; | |
670 | } | |
671 | } | |
672 | } | |
673 | } | |
674 | } | |
675 | ||
52b7d2ce A |
676 | return NULL; |
677 | } | |
678 | ||
679 | /* | |
680 | * create new isakmp Phase 2 status record to handle isakmp in Phase2 | |
681 | */ | |
65c25746 A |
682 | phase2_handle_t * |
683 | ike_session_newph2(unsigned int version, int type) | |
52b7d2ce | 684 | { |
65c25746 A |
685 | phase2_handle_t *iph2 = NULL; |
686 | ||
52b7d2ce A |
687 | /* create new iph2 */ |
688 | iph2 = racoon_calloc(1, sizeof(*iph2)); | |
689 | if (iph2 == NULL) | |
690 | return NULL; | |
65c25746 A |
691 | iph2->version = version; |
692 | iph2->phase2_type = type; | |
d1e348cf | 693 | iph2->is_dying = 0; |
65c25746 A |
694 | |
695 | plog(ASL_LEVEL_DEBUG, "*** New Phase 2\n"); | |
52b7d2ce A |
696 | return iph2; |
697 | } | |
698 | ||
699 | /* | |
700 | * initialize ph2handle | |
701 | * NOTE: don't initialize src/dst. | |
702 | * SPI in the proposal is cleared. | |
703 | */ | |
704 | void | |
65c25746 | 705 | ike_session_initph2(phase2_handle_t *iph2) |
52b7d2ce A |
706 | { |
707 | sched_scrub_param(iph2); | |
708 | iph2->sce = NULL; | |
709 | iph2->scr = NULL; | |
65c25746 | 710 | |
52b7d2ce A |
711 | VPTRINIT(iph2->sendbuf); |
712 | VPTRINIT(iph2->msg1); | |
65c25746 | 713 | |
52b7d2ce A |
714 | /* clear spi, keep variables in the proposal */ |
715 | if (iph2->proposal) { | |
716 | struct saproto *pr; | |
717 | for (pr = iph2->proposal->head; pr != NULL; pr = pr->next) | |
718 | pr->spi = 0; | |
719 | } | |
65c25746 | 720 | |
52b7d2ce A |
721 | /* clear approval */ |
722 | if (iph2->approval) { | |
723 | flushsaprop(iph2->approval); | |
724 | iph2->approval = NULL; | |
725 | } | |
65c25746 | 726 | |
52b7d2ce A |
727 | /* clear the generated policy */ |
728 | if (iph2->spidx_gen) { | |
85f41bec | 729 | delsp_bothdir(iph2->spidx_gen); |
52b7d2ce A |
730 | racoon_free(iph2->spidx_gen); |
731 | iph2->spidx_gen = NULL; | |
732 | } | |
65c25746 | 733 | |
52b7d2ce A |
734 | if (iph2->pfsgrp) { |
735 | oakley_dhgrp_free(iph2->pfsgrp); | |
736 | iph2->pfsgrp = NULL; | |
737 | } | |
65c25746 | 738 | |
52b7d2ce A |
739 | VPTRINIT(iph2->dhpriv); |
740 | VPTRINIT(iph2->dhpub); | |
741 | VPTRINIT(iph2->dhpub_p); | |
742 | VPTRINIT(iph2->dhgxy); | |
743 | VPTRINIT(iph2->id); | |
744 | VPTRINIT(iph2->id_p); | |
745 | VPTRINIT(iph2->nonce); | |
746 | VPTRINIT(iph2->nonce_p); | |
747 | VPTRINIT(iph2->sa); | |
748 | VPTRINIT(iph2->sa_ret); | |
65c25746 | 749 | |
52b7d2ce A |
750 | if (iph2->ivm) { |
751 | oakley_delivm(iph2->ivm); | |
752 | iph2->ivm = NULL; | |
753 | } | |
754 | } | |
755 | ||
756 | /* | |
757 | * delete new isakmp Phase 2 status record to handle isakmp in Phase2 | |
758 | */ | |
759 | void | |
65c25746 | 760 | ike_session_delph2(phase2_handle_t *iph2) |
52b7d2ce | 761 | { |
65c25746 A |
762 | ike_session_initph2(iph2); |
763 | ||
52b7d2ce A |
764 | if (iph2->src) { |
765 | racoon_free(iph2->src); | |
766 | iph2->src = NULL; | |
767 | } | |
768 | if (iph2->dst) { | |
769 | racoon_free(iph2->dst); | |
770 | iph2->dst = NULL; | |
771 | } | |
772 | if (iph2->src_id) { | |
65c25746 A |
773 | racoon_free(iph2->src_id); |
774 | iph2->src_id = NULL; | |
52b7d2ce A |
775 | } |
776 | if (iph2->dst_id) { | |
65c25746 A |
777 | racoon_free(iph2->dst_id); |
778 | iph2->dst_id = NULL; | |
52b7d2ce | 779 | } |
65c25746 | 780 | |
52b7d2ce A |
781 | if (iph2->proposal) { |
782 | flushsaprop(iph2->proposal); | |
783 | iph2->proposal = NULL; | |
784 | } | |
65c25746 | 785 | |
d1e348cf | 786 | if (iph2->sainfo) { |
65c25746 | 787 | release_sainfo(iph2->sainfo); |
d1e348cf A |
788 | iph2->sainfo = NULL; |
789 | } | |
65c25746 A |
790 | VPTRINIT(iph2->id); |
791 | VPTRINIT(iph2->id_p); | |
792 | VPTRINIT(iph2->ext_nat_id); | |
793 | VPTRINIT(iph2->ext_nat_id_p); | |
794 | ||
795 | if (iph2->sce) | |
796 | SCHED_KILL(iph2->sce); | |
797 | if (iph2->scr) | |
798 | SCHED_KILL(iph2->scr); | |
799 | ||
52b7d2ce A |
800 | racoon_free(iph2); |
801 | } | |
802 | ||
52b7d2ce | 803 | void |
65c25746 | 804 | ike_session_flush_all_phase2_for_session(ike_session_t *session, int ignore_estab_or_assert_handles) |
52b7d2ce | 805 | { |
65c25746 A |
806 | phase2_handle_t *p = NULL; |
807 | phase2_handle_t *next = NULL; | |
808 | LIST_FOREACH_SAFE(p, &session->ph2tree, ph2ofsession_chain, next) { | |
809 | if (p->is_dying || FSM_STATE_IS_EXPIRED(p->status)) { | |
810 | continue; | |
811 | } | |
812 | if (ignore_estab_or_assert_handles && p->parent_session && !p->parent_session->stopped_by_vpn_controller && p->parent_session->is_asserted) { | |
813 | plog(ASL_LEVEL_DEBUG, | |
814 | "skipping phase2 handle that's asserted...\n"); | |
815 | continue; | |
816 | } | |
817 | if (FSM_STATE_IS_ESTABLISHED(p->status)){ | |
818 | if (ignore_estab_or_assert_handles) { | |
819 | plog(ASL_LEVEL_DEBUG, | |
820 | "skipping ph2 handler that's established...\n"); | |
821 | continue; | |
822 | } | |
823 | /* send delete information */ | |
824 | plog(ASL_LEVEL_DEBUG, | |
825 | "got an established ph2 handler to flush...\n"); | |
826 | isakmp_info_send_d2(p); | |
827 | }else{ | |
828 | plog(ASL_LEVEL_DEBUG, | |
829 | "got a ph2 handler to flush (state %d)\n", p->status); | |
830 | } | |
831 | ||
832 | ike_session_stopped_by_controller(p->parent_session, | |
833 | ike_session_stopped_by_flush); | |
834 | delete_spd(p); | |
835 | ike_session_unlink_phase2(p); | |
836 | } | |
52b7d2ce A |
837 | } |
838 | ||
839 | void | |
65c25746 | 840 | ike_session_flush_all_phase2(int ignore_estab_or_assert_handles) |
52b7d2ce | 841 | { |
65c25746 A |
842 | ike_session_t *session = NULL; |
843 | ike_session_t *next_session = NULL; | |
844 | ||
845 | plog(ASL_LEVEL_DEBUG, | |
e8d9021d | 846 | "flushing ph2 handles: ignore_estab_or_assert %d...\n", ignore_estab_or_assert_handles); |
65c25746 A |
847 | |
848 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
849 | ike_session_flush_all_phase2_for_session(session, ignore_estab_or_assert_handles); | |
850 | } | |
52b7d2ce A |
851 | } |
852 | ||
853 | /* | |
854 | * Delete all Phase 2 handlers for this src/dst/proto. This | |
855 | * is used during INITIAL-CONTACT processing (so no need to | |
856 | * send a message to the peer). | |
857 | */ | |
65c25746 | 858 | //%%%%%%%%%%%%%%%%%%% make this smarter - find session using addresses ???? |
52b7d2ce | 859 | void |
65c25746 | 860 | ike_session_deleteallph2(struct sockaddr_storage *src, struct sockaddr_storage *dst, u_int proto_id) |
52b7d2ce | 861 | { |
65c25746 A |
862 | ike_session_t *session = NULL; |
863 | ike_session_t *next_session = NULL; | |
864 | phase2_handle_t *iph2 = NULL; | |
865 | phase2_handle_t *next_iph2 = NULL; | |
52b7d2ce | 866 | struct saproto *pr; |
65c25746 A |
867 | |
868 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
869 | LIST_FOREACH_SAFE(iph2, &session->ph2tree, ph2ofsession_chain, next_iph2) { | |
870 | if (iph2->is_dying || FSM_STATE_IS_EXPIRED(iph2->status)) { | |
871 | continue; | |
872 | } | |
873 | if (iph2->proposal == NULL && iph2->approval == NULL) | |
874 | continue; | |
875 | if (cmpsaddrwop(src, iph2->src) != 0 || | |
876 | cmpsaddrwop(dst, iph2->dst) != 0) { | |
877 | continue; | |
878 | } | |
879 | if (iph2->approval != NULL) { | |
880 | for (pr = iph2->approval->head; pr != NULL; | |
881 | pr = pr->next) { | |
882 | if (proto_id == pr->proto_id) | |
883 | goto zap_it; | |
884 | } | |
885 | } else if (iph2->proposal != NULL) { | |
886 | for (pr = iph2->proposal->head; pr != NULL; | |
887 | pr = pr->next) { | |
888 | if (proto_id == pr->proto_id) | |
889 | goto zap_it; | |
890 | } | |
891 | } | |
d1e348cf | 892 | continue; |
65c25746 A |
893 | zap_it: |
894 | plog(ASL_LEVEL_DEBUG, | |
895 | "deleteallph2: got a ph2 handler...\n"); | |
896 | if (FSM_STATE_IS_ESTABLISHED(iph2->status)) | |
897 | isakmp_info_send_d2(iph2); | |
898 | ike_session_stopped_by_controller(iph2->parent_session, | |
899 | ike_session_stopped_by_flush); | |
900 | ike_session_unlink_phase2(iph2); | |
d1e348cf | 901 | } |
65c25746 | 902 | } |
52b7d2ce A |
903 | } |
904 | ||
d1e348cf A |
905 | /* |
906 | * Delete all Phase 1 handlers for this src/dst. | |
907 | */ | |
908 | void | |
65c25746 | 909 | ike_session_deleteallph1(struct sockaddr_storage *src, struct sockaddr_storage *dst) |
d1e348cf | 910 | { |
65c25746 A |
911 | ike_session_t *session = NULL; |
912 | ike_session_t *next_session = NULL; | |
913 | phase1_handle_t *iph1 = NULL; | |
914 | phase1_handle_t *next_iph1 = NULL; | |
915 | ||
916 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
917 | LIST_FOREACH_SAFE(iph1, &session->ph1tree, ph1ofsession_chain, next_iph1) { | |
918 | if (cmpsaddrwop(src, iph1->local) != 0 || | |
919 | cmpsaddrwop(dst, iph1->remote) != 0) { | |
920 | continue; | |
921 | } | |
922 | plog(ASL_LEVEL_DEBUG, | |
923 | "deleteallph1: got a ph1 handler...\n"); | |
924 | if (FSM_STATE_IS_ESTABLISHED(iph1->status)) | |
925 | isakmp_info_send_d1(iph1); | |
926 | ||
927 | ike_session_stopped_by_controller(iph1->parent_session, ike_session_stopped_by_flush); | |
928 | ike_session_unlink_phase1(iph1); | |
d1e348cf | 929 | } |
65c25746 | 930 | } |
52b7d2ce A |
931 | } |
932 | ||
d1e348cf | 933 | |
52b7d2ce A |
934 | /* %%% management contacted list */ |
935 | /* | |
936 | * search contacted list. | |
937 | */ | |
938 | struct contacted * | |
65c25746 A |
939 | ike_session_getcontacted(remote) |
940 | struct sockaddr_storage *remote; | |
52b7d2ce A |
941 | { |
942 | struct contacted *p; | |
65c25746 | 943 | |
52b7d2ce A |
944 | LIST_FOREACH(p, &ctdtree, chain) { |
945 | if (cmpsaddrstrict(remote, p->remote) == 0) | |
946 | return p; | |
947 | } | |
65c25746 | 948 | |
52b7d2ce A |
949 | return NULL; |
950 | } | |
951 | ||
952 | /* | |
953 | * create new isakmp Phase 2 status record to handle isakmp in Phase2 | |
954 | */ | |
955 | int | |
65c25746 A |
956 | ike_session_inscontacted(remote) |
957 | struct sockaddr_storage *remote; | |
52b7d2ce A |
958 | { |
959 | struct contacted *new; | |
65c25746 | 960 | |
52b7d2ce A |
961 | /* create new iph2 */ |
962 | new = racoon_calloc(1, sizeof(*new)); | |
963 | if (new == NULL) | |
964 | return -1; | |
65c25746 A |
965 | |
966 | new->remote = dupsaddr(remote); | |
d1e348cf | 967 | if (new->remote == NULL) { |
65c25746 A |
968 | plog(ASL_LEVEL_ERR, |
969 | "failed to allocate buffer.\n"); | |
d1e348cf A |
970 | racoon_free(new); |
971 | return -1; | |
972 | } | |
65c25746 | 973 | |
52b7d2ce | 974 | LIST_INSERT_HEAD(&ctdtree, new, chain); |
65c25746 | 975 | |
52b7d2ce A |
976 | return 0; |
977 | } | |
978 | ||
979 | ||
980 | void | |
65c25746 | 981 | ike_session_clear_contacted() |
52b7d2ce A |
982 | { |
983 | struct contacted *c, *next; | |
65c25746 | 984 | LIST_FOREACH_SAFE(c, &ctdtree, chain, next) { |
52b7d2ce A |
985 | LIST_REMOVE(c, chain); |
986 | racoon_free(c->remote); | |
987 | racoon_free(c); | |
988 | } | |
989 | } | |
990 | ||
991 | void | |
65c25746 | 992 | ike_session_initctdtree() |
52b7d2ce A |
993 | { |
994 | LIST_INIT(&ctdtree); | |
995 | } | |
996 | ||
e8d9021d | 997 | time_t |
65c25746 | 998 | ike_session_get_exp_retx_interval (int num_retries, int fixed_retry_interval) |
e8d9021d A |
999 | { |
1000 | // first 3 retries aren't exponential | |
1001 | if (num_retries <= 3) { | |
1002 | return (time_t)fixed_retry_interval; | |
1003 | } else { | |
1004 | return (time_t)(num_retries * fixed_retry_interval); | |
1005 | } | |
1006 | } | |
1007 | ||
52b7d2ce A |
1008 | /* |
1009 | * check the response has been sent to the peer. when not, simply reply | |
1010 | * the buffered packet to the peer. | |
1011 | * OUT: | |
1012 | * 0: the packet is received at the first time. | |
1013 | * 1: the packet was processed before. | |
1014 | * 2: the packet was processed before, but the address mismatches. | |
1015 | * -1: error happened. | |
1016 | */ | |
1017 | int | |
65c25746 A |
1018 | ike_session_check_recvdpkt(remote, local, rbuf) |
1019 | struct sockaddr_storage *remote, *local; | |
1020 | vchar_t *rbuf; | |
52b7d2ce A |
1021 | { |
1022 | vchar_t *hash; | |
1023 | struct recvdpkt *r; | |
e8d9021d | 1024 | time_t t, d; |
52b7d2ce | 1025 | int len, s; |
65c25746 | 1026 | |
52b7d2ce A |
1027 | /* set current time */ |
1028 | t = time(NULL); | |
65c25746 | 1029 | |
52b7d2ce A |
1030 | hash = eay_md5_one(rbuf); |
1031 | if (!hash) { | |
65c25746 A |
1032 | plog(ASL_LEVEL_ERR, |
1033 | "failed to allocate buffer.\n"); | |
52b7d2ce A |
1034 | return -1; |
1035 | } | |
65c25746 | 1036 | |
52b7d2ce A |
1037 | LIST_FOREACH(r, &rcptree, chain) { |
1038 | if (memcmp(hash->v, r->hash->v, r->hash->l) == 0) | |
1039 | break; | |
1040 | } | |
1041 | vfree(hash); | |
65c25746 | 1042 | |
52b7d2ce A |
1043 | /* this is the first time to receive the packet */ |
1044 | if (r == NULL) | |
1045 | return 0; | |
65c25746 | 1046 | |
52b7d2ce A |
1047 | /* |
1048 | * the packet was processed before, but the remote address mismatches. | |
65c25746 | 1049 | * ignore the port to accomodate port changes (e.g. floating). |
52b7d2ce | 1050 | */ |
d1e348cf | 1051 | if (cmpsaddrwop(remote, r->remote) != 0) { |
65c25746 A |
1052 | return 2; |
1053 | } | |
1054 | ||
52b7d2ce A |
1055 | /* |
1056 | * it should not check the local address because the packet | |
1057 | * may arrive at other interface. | |
1058 | */ | |
65c25746 | 1059 | |
52b7d2ce A |
1060 | /* check the previous time to send */ |
1061 | if (t - r->time_send < 1) { | |
65c25746 A |
1062 | plog(ASL_LEVEL_WARNING, |
1063 | "the packet retransmitted in a short time from %s\n", | |
1064 | saddr2str((struct sockaddr *)remote)); | |
52b7d2ce A |
1065 | /*XXX should it be error ? */ |
1066 | } | |
65c25746 | 1067 | |
52b7d2ce | 1068 | /* select the socket to be sent */ |
85f41bec | 1069 | s = getsockmyaddr((struct sockaddr *)r->local); |
52b7d2ce A |
1070 | if (s == -1) |
1071 | return -1; | |
65c25746 | 1072 | |
e8d9021d A |
1073 | // don't send if we recently sent a response. |
1074 | if (r->time_send && t > r->time_send) { | |
1075 | d = t - r->time_send; | |
1076 | if (d < r->retry_interval) { | |
65c25746 | 1077 | plog(ASL_LEVEL_ERR, "already responded within the past %ld secs\n", d); |
e8d9021d A |
1078 | return 1; |
1079 | } | |
1080 | } | |
65c25746 | 1081 | |
e8d9021d A |
1082 | #ifdef ENABLE_FRAG |
1083 | if (r->frag_flags && r->sendbuf->l > ISAKMP_FRAG_MAXLEN) { | |
1084 | /* resend the packet if needed */ | |
65c25746 | 1085 | plog(ASL_LEVEL_ERR, "!!! retransmitting frags\n"); |
e8d9021d A |
1086 | len = sendfragsfromto(s, r->sendbuf, |
1087 | r->local, r->remote, lcconf->count_persend, | |
1088 | r->frag_flags); | |
1089 | } else { | |
65c25746 | 1090 | plog(ASL_LEVEL_ERR, "!!! skipped retransmitting frags: frag_flags %x, r->sendbuf->l %zu, max %d\n", r->frag_flags, r->sendbuf->l, ISAKMP_FRAG_MAXLEN); |
e8d9021d A |
1091 | /* resend the packet if needed */ |
1092 | len = sendfromto(s, r->sendbuf->v, r->sendbuf->l, | |
1093 | r->local, r->remote, lcconf->count_persend); | |
1094 | } | |
1095 | #else | |
52b7d2ce A |
1096 | /* resend the packet if needed */ |
1097 | len = sendfromto(s, r->sendbuf->v, r->sendbuf->l, | |
65c25746 | 1098 | r->local, r->remote, lcconf->count_persend); |
e8d9021d | 1099 | #endif |
52b7d2ce | 1100 | if (len == -1) { |
65c25746 | 1101 | plog(ASL_LEVEL_ERR, "sendfromto failed\n"); |
52b7d2ce A |
1102 | return -1; |
1103 | } | |
65c25746 | 1104 | |
52b7d2ce A |
1105 | /* check the retry counter */ |
1106 | r->retry_counter--; | |
1107 | if (r->retry_counter <= 0) { | |
65c25746 A |
1108 | ike_session_rem_recvdpkt(r); |
1109 | ike_session_del_recvdpkt(r); | |
1110 | plog(ASL_LEVEL_DEBUG, | |
1111 | "deleted the retransmission packet to %s.\n", | |
1112 | saddr2str((struct sockaddr *)remote)); | |
e8d9021d | 1113 | } else { |
52b7d2ce | 1114 | r->time_send = t; |
65c25746 | 1115 | r->retry_interval = ike_session_get_exp_retx_interval((lcconf->retry_counter - r->retry_counter), |
e8d9021d A |
1116 | lcconf->retry_interval); |
1117 | } | |
65c25746 | 1118 | |
52b7d2ce A |
1119 | return 1; |
1120 | } | |
1121 | ||
1122 | /* | |
1123 | * adding a hash of received packet into the received list. | |
1124 | */ | |
1125 | int | |
65c25746 A |
1126 | ike_session_add_recvdpkt(remote, local, sbuf, rbuf, non_esp, frag_flags) |
1127 | struct sockaddr_storage *remote, *local; | |
1128 | vchar_t *sbuf, *rbuf; | |
1129 | size_t non_esp; | |
1130 | u_int32_t frag_flags; | |
52b7d2ce A |
1131 | { |
1132 | struct recvdpkt *new = NULL; | |
65c25746 | 1133 | |
52b7d2ce A |
1134 | if (lcconf->retry_counter == 0) { |
1135 | /* no need to add it */ | |
1136 | return 0; | |
1137 | } | |
65c25746 | 1138 | |
52b7d2ce A |
1139 | new = racoon_calloc(1, sizeof(*new)); |
1140 | if (!new) { | |
65c25746 A |
1141 | plog(ASL_LEVEL_ERR, |
1142 | "failed to allocate buffer.\n"); | |
52b7d2ce A |
1143 | return -1; |
1144 | } | |
65c25746 | 1145 | |
52b7d2ce A |
1146 | new->hash = eay_md5_one(rbuf); |
1147 | if (!new->hash) { | |
65c25746 A |
1148 | plog(ASL_LEVEL_ERR, |
1149 | "failed to allocate buffer.\n"); | |
1150 | ike_session_del_recvdpkt(new); | |
52b7d2ce A |
1151 | return -1; |
1152 | } | |
65c25746 | 1153 | new->remote = dupsaddr(remote); |
52b7d2ce | 1154 | if (new->remote == NULL) { |
65c25746 A |
1155 | plog(ASL_LEVEL_ERR, |
1156 | "failed to allocate buffer.\n"); | |
1157 | ike_session_del_recvdpkt(new); | |
52b7d2ce A |
1158 | return -1; |
1159 | } | |
65c25746 | 1160 | new->local = dupsaddr(local); |
52b7d2ce | 1161 | if (new->local == NULL) { |
65c25746 A |
1162 | plog(ASL_LEVEL_ERR, |
1163 | "failed to allocate buffer.\n"); | |
1164 | ike_session_del_recvdpkt(new); | |
52b7d2ce A |
1165 | return -1; |
1166 | } | |
65c25746 | 1167 | |
d1e348cf | 1168 | if (non_esp) { |
65c25746 A |
1169 | plog (ASL_LEVEL_DEBUG, "Adding NON-ESP marker\n"); |
1170 | ||
d1e348cf A |
1171 | /* If NAT-T port floating is in use, 4 zero bytes (non-ESP marker) |
1172 | must added just before the packet itself. For this we must | |
1173 | allocate a new buffer and release it at the end. */ | |
1174 | if ((new->sendbuf = vmalloc (sbuf->l + non_esp)) == NULL) { | |
65c25746 | 1175 | plog(ASL_LEVEL_ERR, |
d1e348cf | 1176 | "failed to allocate extra buf for non-esp\n"); |
65c25746 | 1177 | ike_session_del_recvdpkt(new); |
d1e348cf A |
1178 | return -1; |
1179 | } | |
85f41bec | 1180 | *ALIGNED_CAST(u_int32_t *)new->sendbuf->v = 0; |
d1e348cf A |
1181 | memcpy(new->sendbuf->v + non_esp, sbuf->v, sbuf->l); |
1182 | } else { | |
1183 | new->sendbuf = vdup(sbuf); | |
1184 | if (new->sendbuf == NULL) { | |
65c25746 | 1185 | plog(ASL_LEVEL_ERR, |
d1e348cf | 1186 | "failed to allocate buffer.\n"); |
65c25746 | 1187 | ike_session_del_recvdpkt(new); |
d1e348cf A |
1188 | return -1; |
1189 | } | |
1190 | } | |
65c25746 | 1191 | |
52b7d2ce A |
1192 | new->retry_counter = lcconf->retry_counter; |
1193 | new->time_send = 0; | |
1194 | new->created = time(NULL); | |
e8d9021d A |
1195 | #ifdef ENABLE_FRAG |
1196 | if (frag_flags) { | |
1197 | new->frag_flags = frag_flags; | |
1198 | } | |
1199 | #endif | |
65c25746 | 1200 | new->retry_interval = ike_session_get_exp_retx_interval((lcconf->retry_counter - new->retry_counter), |
e8d9021d | 1201 | lcconf->retry_interval); |
65c25746 | 1202 | |
52b7d2ce | 1203 | LIST_INSERT_HEAD(&rcptree, new, chain); |
65c25746 | 1204 | |
52b7d2ce A |
1205 | return 0; |
1206 | } | |
1207 | ||
1208 | void | |
65c25746 A |
1209 | ike_session_del_recvdpkt(r) |
1210 | struct recvdpkt *r; | |
52b7d2ce A |
1211 | { |
1212 | if (r->remote) | |
1213 | racoon_free(r->remote); | |
1214 | if (r->local) | |
1215 | racoon_free(r->local); | |
1216 | if (r->hash) | |
1217 | vfree(r->hash); | |
1218 | if (r->sendbuf) | |
1219 | vfree(r->sendbuf); | |
1220 | racoon_free(r); | |
1221 | } | |
1222 | ||
1223 | void | |
65c25746 A |
1224 | ike_session_rem_recvdpkt(r) |
1225 | struct recvdpkt *r; | |
52b7d2ce A |
1226 | { |
1227 | LIST_REMOVE(r, chain); | |
1228 | } | |
1229 | ||
1230 | void | |
1231 | sweep_recvdpkt(dummy) | |
65c25746 | 1232 | void *dummy; |
52b7d2ce A |
1233 | { |
1234 | struct recvdpkt *r, *next; | |
1235 | time_t t, lt; | |
65c25746 | 1236 | |
52b7d2ce A |
1237 | /* set current time */ |
1238 | t = time(NULL); | |
65c25746 | 1239 | |
52b7d2ce A |
1240 | /* set the lifetime of the retransmission */ |
1241 | lt = lcconf->retry_counter * lcconf->retry_interval; | |
65c25746 A |
1242 | |
1243 | LIST_FOREACH_SAFE(r, &rcptree, chain, next) { | |
52b7d2ce | 1244 | if (t - r->created > lt) { |
65c25746 A |
1245 | ike_session_rem_recvdpkt(r); |
1246 | ike_session_del_recvdpkt(r); | |
52b7d2ce A |
1247 | } |
1248 | } | |
65c25746 | 1249 | |
47612122 | 1250 | sched_new(lt, sweep_recvdpkt, &rcptree); |
52b7d2ce A |
1251 | } |
1252 | ||
1253 | void | |
65c25746 | 1254 | ike_session_clear_recvdpkt() |
52b7d2ce A |
1255 | { |
1256 | struct recvdpkt *r, *next; | |
1257 | ||
65c25746 A |
1258 | LIST_FOREACH_SAFE(r, &rcptree, chain, next) { |
1259 | ike_session_rem_recvdpkt(r); | |
1260 | ike_session_del_recvdpkt(r); | |
52b7d2ce | 1261 | } |
47612122 | 1262 | sched_scrub_param(&rcptree); |
52b7d2ce A |
1263 | } |
1264 | ||
1265 | void | |
65c25746 | 1266 | ike_session_init_recvdpkt() |
52b7d2ce A |
1267 | { |
1268 | time_t lt = lcconf->retry_counter * lcconf->retry_interval; | |
65c25746 | 1269 | |
52b7d2ce | 1270 | LIST_INIT(&rcptree); |
65c25746 | 1271 | |
47612122 | 1272 | sched_new(lt, sweep_recvdpkt, &rcptree); |
52b7d2ce A |
1273 | } |
1274 | ||
65c25746 | 1275 | #ifdef NOT_USED |
52b7d2ce A |
1276 | #ifdef ENABLE_HYBRID |
1277 | /* | |
1278 | * Returns 0 if the address was obtained by ISAKMP mode config, 1 otherwise | |
1279 | * This should be in isakmp_cfg.c but ph1tree being private, it must be there | |
1280 | */ | |
1281 | int | |
65c25746 | 1282 | exclude_cfg_addr(const struct sockaddr_storage *addr) |
52b7d2ce | 1283 | { |
65c25746 A |
1284 | ike_session_t *session; |
1285 | phase1_handle_t *p; | |
52b7d2ce | 1286 | struct sockaddr_in *sin; |
65c25746 A |
1287 | |
1288 | LIST_FOREACH(session, &ike_session_tree, chain) { | |
1289 | LIST_FOREACH(p, &session->ph1tree, chain) { | |
1290 | if ((p->mode_cfg != NULL) && | |
1291 | (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) && | |
1292 | (addr->ss_family == AF_INET)) { | |
1293 | sin = (struct sockaddr_in *)addr; | |
1294 | if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr) | |
1295 | return 0; | |
1296 | } | |
1297 | } | |
1298 | } | |
1299 | ||
52b7d2ce A |
1300 | return 1; |
1301 | } | |
1302 | #endif | |
65c25746 | 1303 | #endif /* NOT_USED */ |
d1e348cf A |
1304 | |
1305 | int | |
65c25746 A |
1306 | ike_session_expire_session(ike_session_t *session) |
1307 | { | |
1308 | int found = 0; | |
1309 | phase1_handle_t *p; | |
1310 | phase1_handle_t *next; | |
1311 | phase2_handle_t *p2; | |
1312 | ||
1313 | if (session == NULL) | |
1314 | return 0; | |
1315 | ||
1316 | LIST_FOREACH(p2, &session->ph2tree, ph2ofsession_chain) { | |
1317 | if (p2->is_dying || FSM_STATE_IS_EXPIRED(p2->status)) { | |
1318 | continue; | |
1319 | } | |
d1e348cf | 1320 | |
d9c572c0 | 1321 | // Don't send a delete, since the ph1 implies the removal of ph2s |
65c25746 A |
1322 | isakmp_ph2expire(p2); |
1323 | found++; | |
1324 | } | |
1325 | ||
1326 | LIST_FOREACH_SAFE(p, &session->ph1tree, ph1ofsession_chain, next) { | |
1327 | if (p->is_dying || FSM_STATE_IS_EXPIRED(p->status)) { | |
1328 | continue; | |
1329 | } | |
1330 | ||
1331 | ike_session_purge_ph2s_by_ph1(p); | |
1332 | if (FSM_STATE_IS_ESTABLISHED(p->status)) | |
1333 | isakmp_info_send_d1(p); | |
1334 | isakmp_ph1expire(p); | |
1335 | found++; | |
1336 | } | |
d1e348cf A |
1337 | |
1338 | return found; | |
1339 | } | |
1340 | ||
65c25746 | 1341 | #ifdef ENABLE_HYBRID |
d1e348cf | 1342 | int |
65c25746 | 1343 | ike_session_purgephXbydstaddrwop(struct sockaddr_storage *remote) |
d1e348cf A |
1344 | { |
1345 | int found = 0; | |
65c25746 A |
1346 | ike_session_t *session = NULL; |
1347 | ike_session_t *next_session = NULL; | |
1348 | phase1_handle_t *p; | |
1349 | phase2_handle_t *p2; | |
1350 | ||
1351 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
1352 | LIST_FOREACH(p2, &session->ph2tree, ph2ofsession_chain) { | |
1353 | if (p2->is_dying || FSM_STATE_IS_EXPIRED(p2->status)) { | |
85f41bec A |
1354 | continue; |
1355 | } | |
65c25746 A |
1356 | if (cmpsaddrwop(remote, p2->dst) == 0) { |
1357 | plog(ASL_LEVEL_DEBUG, | |
1358 | "in %s... purging Phase 2 structures\n", __FUNCTION__); | |
1359 | if (FSM_STATE_IS_ESTABLISHED(p2->status)) | |
1360 | isakmp_info_send_d2(p2); | |
1361 | isakmp_ph2expire(p2); | |
1362 | found++; | |
1363 | } | |
1364 | } | |
1365 | ||
1366 | LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { | |
1367 | if (p->is_dying || FSM_STATE_IS_EXPIRED(p->status)) { | |
85f41bec A |
1368 | continue; |
1369 | } | |
65c25746 A |
1370 | if (cmpsaddrwop(remote, p->remote) == 0) { |
1371 | plog(ASL_LEVEL_DEBUG, | |
1372 | "in %s... purging Phase 1 and related Phase 2 structures\n", __FUNCTION__); | |
1373 | ike_session_purge_ph2s_by_ph1(p); | |
1374 | if (FSM_STATE_IS_ESTABLISHED(p->status)) | |
1375 | isakmp_info_send_d1(p); | |
1376 | isakmp_ph1expire(p); | |
1377 | found++; | |
1378 | } | |
1379 | } | |
1380 | } | |
1381 | ||
d1e348cf A |
1382 | return found; |
1383 | } | |
1384 | ||
1385 | void | |
65c25746 | 1386 | ike_session_purgephXbyspid(u_int32_t spid, int del_boundph1) |
d1e348cf | 1387 | { |
65c25746 A |
1388 | ike_session_t *session = NULL; |
1389 | ike_session_t *next_session = NULL; | |
1390 | phase2_handle_t *iph2 = NULL; | |
1391 | phase2_handle_t *next_iph2 = NULL; | |
1392 | phase1_handle_t *iph1 = NULL; | |
1393 | phase1_handle_t *next_iph1 = NULL; | |
1394 | ||
1395 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
1396 | // do ph2's first... we need the ph1s for notifications | |
1397 | LIST_FOREACH_SAFE(iph2, &session->ph2tree, ph2ofsession_chain, next_iph2) { | |
1398 | if (spid == iph2->spid) { | |
1399 | if (iph2->is_dying || FSM_STATE_IS_EXPIRED(iph2->status)) { | |
1400 | continue; | |
1401 | } | |
1402 | if (FSM_STATE_IS_ESTABLISHED(iph2->status)) { | |
1403 | isakmp_info_send_d2(iph2); | |
1404 | } | |
1405 | ike_session_stopped_by_controller(iph2->parent_session, | |
1406 | ike_session_stopped_by_flush); | |
1407 | isakmp_ph2expire(iph2); // iph2 will go down 1 second later. | |
d1e348cf | 1408 | } |
d1e348cf | 1409 | } |
65c25746 A |
1410 | |
1411 | // do the ph1s last. %%%%%%%%%%%%%%%%%% re-organize this - check del_boundph1 first | |
1412 | LIST_FOREACH_SAFE(iph2, &session->ph2tree, ph2ofsession_chain, next_iph2) { | |
1413 | if (spid == iph2->spid) { | |
1414 | if (del_boundph1 && iph2->parent_session) { | |
1415 | LIST_FOREACH_SAFE(iph1, &iph2->parent_session->ph1tree, ph1ofsession_chain, next_iph1) { | |
1416 | if (iph1->is_dying || FSM_STATE_IS_EXPIRED(iph1->status)) { | |
1417 | continue; | |
1418 | } | |
1419 | if (FSM_STATE_IS_ESTABLISHED(iph1->status)) { | |
1420 | isakmp_info_send_d1(iph1); | |
1421 | } | |
1422 | isakmp_ph1expire(iph1); | |
d1e348cf | 1423 | } |
d1e348cf A |
1424 | } |
1425 | } | |
65c25746 A |
1426 | } |
1427 | } | |
d1e348cf A |
1428 | } |
1429 | ||
1430 | #endif | |
1431 | ||
1432 | #ifdef ENABLE_DPD | |
1433 | int | |
65c25746 | 1434 | ike_session_ph1_force_dpd (struct sockaddr_storage *remote) |
d1e348cf A |
1435 | { |
1436 | int status = -1; | |
65c25746 A |
1437 | ike_session_t *session = NULL; |
1438 | phase1_handle_t *p = NULL; | |
1439 | ||
1440 | LIST_FOREACH(session, &ike_session_tree, chain) { | |
1441 | LIST_FOREACH(p, &session->ph1tree, ph1ofsession_chain) { | |
1442 | if (cmpsaddrwop(remote, p->remote) == 0) { | |
1443 | if (FSM_STATE_IS_ESTABLISHED(p->status) && | |
1444 | !p->is_dying && | |
1445 | p->dpd_support && | |
1446 | p->rmconf->dpd_interval) { | |
1447 | if(!p->dpd_fails) { | |
1448 | isakmp_info_send_r_u(p); | |
1449 | status = 0; | |
1450 | } else { | |
1451 | plog(ASL_LEVEL_DEBUG, "Skipping forced-DPD for Phase 1 (dpd already in progress).\n"); | |
1452 | } | |
1453 | if (p->parent_session) { | |
1454 | p->parent_session->controller_awaiting_peer_resp = 1; | |
1455 | } | |
d1e348cf | 1456 | } else { |
65c25746 A |
1457 | plog(ASL_LEVEL_DEBUG, "Skipping forced-DPD for Phase 1 (status %d, dying %d, dpd-support %d, dpd-interval %d).\n", |
1458 | p->status, p->is_dying, p->dpd_support, p->rmconf->dpd_interval); | |
e8d9021d | 1459 | } |
d1e348cf A |
1460 | } |
1461 | } | |
1462 | } | |
65c25746 | 1463 | |
d1e348cf A |
1464 | return status; |
1465 | } | |
1466 | #endif | |
e8d9021d A |
1467 | |
1468 | void | |
1469 | sweep_sleepwake(void) | |
1470 | { | |
65c25746 A |
1471 | ike_session_t *session = NULL; |
1472 | ike_session_t *next_session = NULL; | |
1473 | phase2_handle_t *iph2 = NULL; | |
1474 | phase2_handle_t *next_iph2 = NULL; | |
1475 | phase1_handle_t *iph1 = NULL; | |
1476 | phase1_handle_t *next_iph1 = NULL; | |
1477 | ||
1478 | LIST_FOREACH_SAFE(session, &ike_session_tree, chain, next_session) { | |
1479 | // do the ph1s. | |
1480 | LIST_FOREACH_SAFE(iph1, &session->ph1tree, ph1ofsession_chain, next_iph1) { | |
1481 | if (iph1->parent_session && iph1->parent_session->is_asserted) { | |
1482 | plog(ASL_LEVEL_DEBUG, "Skipping sweep of Phase 1 %s because it's been asserted.\n", | |
1483 | isakmp_pindex(&iph1->index, 0)); | |
1484 | continue; | |
1485 | } | |
1486 | if (iph1->is_dying || FSM_STATE_IS_EXPIRED(iph1->status)) { | |
1487 | plog(ASL_LEVEL_DEBUG, "Skipping sweep of Phase 1 %s because it's already expired.\n", | |
1488 | isakmp_pindex(&iph1->index, 0)); | |
1489 | continue; | |
1490 | } | |
1491 | if (iph1->sce) { | |
1492 | time_t xtime; | |
1493 | if (sched_get_time(iph1->sce, &xtime)) { | |
1494 | if (xtime <= swept_at) { | |
1495 | SCHED_KILL(iph1->sce); | |
1496 | SCHED_KILL(iph1->sce_rekey); | |
1497 | iph1->is_dying = 1; | |
1498 | fsm_set_state(&iph1->status, IKEV1_STATE_PHASE1_EXPIRED); | |
1499 | ike_session_update_ph1_ph2tree(iph1); // move unbind/rebind ph2s to from current ph1 | |
1500 | iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1); | |
1501 | plog(ASL_LEVEL_DEBUG, "Phase 1 %s expired while sleeping: quick deletion.\n", | |
1502 | isakmp_pindex(&iph1->index, 0)); | |
1503 | } | |
1504 | } | |
1505 | } | |
1506 | if (iph1->sce_rekey) { | |
1507 | time_t xtime; | |
1508 | if (sched_get_time(iph1->sce_rekey, &xtime)) { | |
1509 | if (FSM_STATE_IS_EXPIRED(iph1->status) || xtime <= swept_at) { | |
1510 | SCHED_KILL(iph1->sce_rekey); | |
1511 | } | |
1512 | } | |
1513 | } | |
1514 | if (iph1->scr) { | |
1515 | time_t xtime; | |
1516 | if (sched_get_time(iph1->scr, &xtime)) { | |
1517 | if (FSM_STATE_IS_EXPIRED(iph1->status) || xtime <= swept_at) { | |
1518 | SCHED_KILL(iph1->scr); | |
1519 | } | |
1520 | } | |
1521 | } | |
1522 | #ifdef ENABLE_DPD | |
1523 | if (iph1->dpd_r_u) { | |
1524 | time_t xtime; | |
1525 | if (sched_get_time(iph1->dpd_r_u, &xtime)) { | |
1526 | if (FSM_STATE_IS_EXPIRED(iph1->status) || xtime <= swept_at) { | |
1527 | SCHED_KILL(iph1->dpd_r_u); | |
1528 | } | |
1529 | } | |
1530 | } | |
1531 | #endif | |
1532 | } | |
1533 | ||
1534 | // do ph2's next | |
1535 | LIST_FOREACH_SAFE(iph2, &session->ph2tree, ph2ofsession_chain, next_iph2) { | |
1536 | if (iph2->parent_session && iph2->parent_session->is_asserted) { | |
1537 | plog(ASL_LEVEL_DEBUG, "Skipping sweep of Phase 2 because it's been asserted.\n"); | |
1538 | continue; | |
1539 | } | |
1540 | if (iph2->is_dying || FSM_STATE_IS_EXPIRED(iph2->status)) { | |
1541 | plog(ASL_LEVEL_DEBUG, "Skipping sweep of Phase 2 because it's already expired.\n"); | |
1542 | continue; | |
1543 | } | |
1544 | if (iph2->sce) { | |
1545 | time_t xtime; | |
1546 | if (sched_get_time(iph2->sce, &xtime)) { | |
1547 | if (xtime <= swept_at) { | |
1548 | fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_EXPIRED); | |
1549 | iph2->is_dying = 1; | |
1550 | isakmp_ph2expire(iph2); // iph2 will go down 1 second later. | |
1551 | ike_session_stopped_by_controller(iph2->parent_session, | |
1552 | ike_session_stopped_by_sleepwake); | |
1553 | plog(ASL_LEVEL_DEBUG, "Phase 2 expired while sleeping: quick deletion.\n"); | |
1554 | } | |
1555 | } | |
1556 | } | |
1557 | if (iph2->scr) { | |
1558 | time_t xtime; | |
1559 | if (sched_get_time(iph2->scr, &xtime)) { | |
1560 | if (FSM_STATE_IS_EXPIRED(iph2->status) || xtime <= swept_at) { | |
1561 | SCHED_KILL(iph2->scr); | |
1562 | } | |
1563 | } | |
1564 | } | |
1565 | } | |
1566 | } | |
1567 | //%%%%%%%%%%%%%%% fix this | |
e8d9021d A |
1568 | // do the ike_session last |
1569 | ike_session_sweep_sleepwake(); | |
1570 | } |