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