2 * Copyright (c) 2008 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
36 #include "isakmp_var.h"
38 #include "ike_session.h"
41 #include "nattraversal.h"
44 #include "ipsec_doi.h"
45 #include "ipsecSessionTracer.h"
46 #include "ipsecMessageTracer.h"
47 #include "isakmp_inf.h"
48 #include "localconf.h"
49 #include "remoteconf.h"
50 #include "vpn_control.h"
51 #include "vpn_control_var.h"
54 #include "power_mgmt.h"
56 #define GET_SAMPLE_PERIOD(s,m) do { \
66 const char *ike_session_stopped_by_vpn_disconnect
= "Stopped by VPN disconnect";
67 const char *ike_session_stopped_by_controller_comm_lost
= "Stopped by loss of controller communication";
68 const char *ike_session_stopped_by_flush
= "Stopped by Flush";
69 const char *ike_session_stopped_by_idle
= "Stopped by Idle";
70 const char *ike_session_stopped_by_xauth_timeout
= "Stopped by XAUTH timeout";
71 const char *ike_session_stopped_by_sleepwake
= "Stopped by Sleep-Wake";
72 const char *ike_session_stopped_by_assert
= "Stopped by Assert";
73 const char *ike_session_stopped_by_peer
= "Stopped by Peer";
75 LIST_HEAD(_ike_session_tree_
, ike_session
) ike_session_tree
= { NULL
};
77 static void ike_session_bindph12(phase1_handle_t
*, phase2_handle_t
*);
78 static void ike_session_rebindph12(phase1_handle_t
*, phase2_handle_t
*);
79 static void ike_session_unbind_all_ph2_from_ph1 (phase1_handle_t
*);
80 static void ike_session_rebind_all_ph12_to_new_ph1 (phase1_handle_t
*, phase1_handle_t
*);
82 static ike_session_t
*
83 new_ike_session (ike_session_id_t
*id
)
85 ike_session_t
*session
;
88 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
92 session
= racoon_calloc(1, sizeof(*session
));
94 bzero(session
, sizeof(*session
));
95 memcpy(&session
->session_id
, id
, sizeof(*id
));
96 LIST_INIT(&session
->ph1tree
);
97 LIST_INIT(&session
->ph2tree
);
98 LIST_INSERT_HEAD(&ike_session_tree
, session
, chain
);
99 IPSECSESSIONTRACERSTART(session
);
105 free_ike_session (ike_session_t
*session
)
107 int is_failure
= TRUE
;
109 SCHED_KILL(session
->traffic_monitor
.sc_mon
);
110 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
111 SCHED_KILL(session
->sc_xauth
);
112 if (session
->start_timestamp
.tv_sec
|| session
->start_timestamp
.tv_usec
) {
113 if (!(session
->stop_timestamp
.tv_sec
|| session
->stop_timestamp
.tv_usec
)) {
114 gettimeofday(&session
->stop_timestamp
, NULL
);
116 if (session
->term_reason
!= ike_session_stopped_by_vpn_disconnect
||
117 session
->term_reason
!= ike_session_stopped_by_controller_comm_lost
||
118 session
->term_reason
!= ike_session_stopped_by_flush
||
119 session
->term_reason
!= ike_session_stopped_by_idle
) {
122 IPSECSESSIONTRACERSTOP(session
,
124 session
->term_reason
);
126 // do MessageTracer cleanup here
127 plog(ASL_LEVEL_DEBUG
,
128 "Freeing IKE-Session to %s.\n",
129 saddr2str((struct sockaddr
*)&session
->session_id
.remote
));
130 LIST_REMOVE(session
, chain
);
131 racoon_free(session
);
137 ike_session_init (void)
139 LIST_INIT(&ike_session_tree
);
143 ike_session_get_rekey_lifetime (int local_spi_is_higher
, u_int expiry_lifetime
)
145 u_int rekey_lifetime
= expiry_lifetime
/ 10;
147 if (rekey_lifetime
) {
148 if (local_spi_is_higher
) {
149 return (rekey_lifetime
* 9);
151 return (rekey_lifetime
* 8);
154 if (local_spi_is_higher
) {
155 rekey_lifetime
= expiry_lifetime
- 1;
157 rekey_lifetime
= expiry_lifetime
- 2;
160 if (rekey_lifetime
< expiry_lifetime
) {
161 return rekey_lifetime
;
167 ike_session_create_session (ike_session_id_t
*session_id
)
172 plog(ASL_LEVEL_DEBUG
, "New IKE Session to %s.\n", saddr2str((struct sockaddr
*)&session_id
->remote
));
174 return new_ike_session(session_id
);
178 ike_session_release_session (ike_session_t
*session
)
180 while (!LIST_EMPTY(&session
->ph2tree
)) {
181 phase2_handle_t
*phase2
= LIST_FIRST(&session
->ph2tree
);
182 ike_session_unlink_phase2(phase2
);
185 while (!LIST_EMPTY(&session
->ph1tree
)) {
186 phase1_handle_t
*phase1
= LIST_FIRST(&session
->ph1tree
);
187 ike_session_unlink_phase1(phase1
);
191 // %%%%%%%%% re-examine this - keep both floated and unfloated port when behind nat
193 ike_session_get_session (struct sockaddr_storage
*local
,
194 struct sockaddr_storage
*remote
,
196 isakmp_index
*optionalIndex
)
198 ike_session_t
*p
= NULL
;
200 ike_session_id_t id_default
;
201 ike_session_id_t id_floated_default
;
202 ike_session_id_t id_wop
;
203 ike_session_t
*best_match
= NULL
;
204 u_int16_t remote_port
;
205 int is_isakmp_remote_port
;
207 if (!local
|| !remote
) {
208 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
212 remote_port
= extract_port(remote
);
213 if (remote_port
&& remote_port
!= PORT_ISAKMP
&& remote_port
!= PORT_ISAKMP_NATT
) {
214 is_isakmp_remote_port
= 0;
216 is_isakmp_remote_port
= 1;
219 /* we will try a couple of matches first: if the exact id isn't found, then we'll try for an id that has zero'd ports */
220 bzero(&id
, sizeof(id
));
221 bzero(&id_default
, sizeof(id_default
));
222 bzero(&id_floated_default
, sizeof(id_floated_default
));
223 bzero(&id_wop
, sizeof(id_wop
));
224 if (local
->ss_family
== AF_INET
) {
225 memcpy(&id
.local
, local
, sizeof(struct sockaddr_in
));
226 memcpy(&id_default
.local
, local
, sizeof(struct sockaddr_in
));
227 memcpy(&id_floated_default
.local
, local
, sizeof(struct sockaddr_in
));
228 memcpy(&id_wop
.local
, local
, sizeof(struct sockaddr_in
));
229 } else if (local
->ss_family
== AF_INET6
) {
230 memcpy(&id
.local
, local
, sizeof(struct sockaddr_in6
));
231 memcpy(&id_default
.local
, local
, sizeof(struct sockaddr_in6
));
232 memcpy(&id_floated_default
.local
, local
, sizeof(struct sockaddr_in6
));
233 memcpy(&id_wop
.local
, local
, sizeof(struct sockaddr_in6
));
235 set_port(&id_default
.local
, PORT_ISAKMP
);
236 set_port(&id_floated_default
.local
, PORT_ISAKMP_NATT
);
237 set_port(&id_wop
.local
, 0);
238 if (remote
->ss_family
== AF_INET
) {
239 memcpy(&id
.remote
, remote
, sizeof(struct sockaddr_in
));
240 memcpy(&id_default
.remote
, remote
, sizeof(struct sockaddr_in
));
241 memcpy(&id_floated_default
.remote
, remote
, sizeof(struct sockaddr_in
));
242 memcpy(&id_wop
.remote
, remote
, sizeof(struct sockaddr_in
));
243 } else if (remote
->ss_family
== AF_INET6
) {
244 memcpy(&id
.remote
, remote
, sizeof(struct sockaddr_in6
));
245 memcpy(&id_default
.remote
, remote
, sizeof(struct sockaddr_in6
));
246 memcpy(&id_floated_default
.remote
, remote
, sizeof(struct sockaddr_in6
));
247 memcpy(&id_wop
.remote
, remote
, sizeof(struct sockaddr_in6
));
249 set_port(&id_default
.remote
, PORT_ISAKMP
);
250 set_port(&id_floated_default
.remote
, PORT_ISAKMP_NATT
);
251 set_port(&id_wop
.remote
, 0);
253 plog(ASL_LEVEL_DEBUG
,
254 "start search for IKE-Session. target %s.\n",
255 saddr2str((struct sockaddr
*)remote
));
257 LIST_FOREACH(p
, &ike_session_tree
, chain
) {
258 plog(ASL_LEVEL_DEBUG
,
259 "still search for IKE-Session. this %s.\n",
260 saddr2str((struct sockaddr
*)&p
->session_id
.remote
));
262 // for now: ignore any stopped sessions as they will go down
263 if (p
->is_dying
|| p
->stopped_by_vpn_controller
|| p
->stop_timestamp
.tv_sec
|| p
->stop_timestamp
.tv_usec
) {
264 plog(ASL_LEVEL_DEBUG
, "still searching. skipping... session to %s is already stopped, active ph1 %d ph2 %d.\n",
265 saddr2str((struct sockaddr
*)&p
->session_id
.remote
),
266 p
->ikev1_state
.active_ph1cnt
, p
->ikev1_state
.active_ph2cnt
);
270 // Skip if the spi doesn't match
271 if (optionalIndex
!= NULL
&& ike_session_getph1byindex(p
, optionalIndex
) == NULL
) {
275 if (memcmp(&p
->session_id
, &id
, sizeof(id
)) == 0) {
276 plog(ASL_LEVEL_DEBUG
,
277 "Pre-existing IKE-Session to %s. case 1.\n",
278 saddr2str((struct sockaddr
*)remote
));
280 } else if (is_isakmp_remote_port
&& memcmp(&p
->session_id
, &id_default
, sizeof(id_default
)) == 0) {
281 plog(ASL_LEVEL_DEBUG
,
282 "Pre-existing IKE-Session to %s. case 2.\n",
283 saddr2str((struct sockaddr
*)remote
));
285 } else if (is_isakmp_remote_port
&& p
->ports_floated
&& memcmp(&p
->session_id
, &id_floated_default
, sizeof(id_floated_default
)) == 0) {
286 plog(ASL_LEVEL_DEBUG
,
287 "Pre-existing IKE-Session to %s. case 3.\n",
288 saddr2str((struct sockaddr
*)remote
));
290 } else if (is_isakmp_remote_port
&& memcmp(&p
->session_id
, &id_wop
, sizeof(id_wop
)) == 0) {
292 } else if (optionalIndex
!= NULL
) {
293 // If the SPI did match, this one counts as a best match
298 plog(ASL_LEVEL_DEBUG
,
299 "Best-match IKE-Session to %s.\n",
300 saddr2str((struct sockaddr
*)&best_match
->session_id
.remote
));
303 if (alloc_if_absent
) {
304 plog(ASL_LEVEL_DEBUG
,
305 "New IKE-Session to %s.\n",
306 saddr2str((struct sockaddr
*)&id
.remote
));
307 return new_ike_session(&id
);
314 ike_session_init_traffic_cop_params (phase1_handle_t
*iph1
)
318 (!iph1
->rmconf
->idle_timeout
&& !iph1
->rmconf
->dpd_interval
)) {
322 if (!iph1
->parent_session
->traffic_monitor
.interv_idle
) {
323 iph1
->parent_session
->traffic_monitor
.interv_idle
= iph1
->rmconf
->idle_timeout
;
325 if (!iph1
->parent_session
->traffic_monitor
.dir_idle
) {
326 iph1
->parent_session
->traffic_monitor
.dir_idle
= iph1
->rmconf
->idle_timeout_dir
;
329 if (!iph1
->parent_session
->traffic_monitor
.interv_mon
) {
330 int min_period
, max_period
, sample_period
= 0;
332 /* calculate the sampling interval... half the smaller interval */
333 if (iph1
->rmconf
->dpd_interval
&&
334 (iph1
->rmconf
->dpd_algo
== DPD_ALGO_INBOUND_DETECT
||
335 iph1
->rmconf
->dpd_algo
== DPD_ALGO_BLACKHOLE_DETECT
)) {
336 // when certain types of dpd are enabled
337 min_period
= MIN(iph1
->rmconf
->dpd_interval
, iph1
->rmconf
->idle_timeout
);
338 max_period
= MAX(iph1
->rmconf
->dpd_interval
, iph1
->rmconf
->idle_timeout
);
339 } else if (iph1
->rmconf
->idle_timeout
) {
340 min_period
= max_period
= iph1
->rmconf
->idle_timeout
;
342 // DPD_ALGO_DEFAULT is configured and there's no idle timeout... we don't need to monitor traffic
346 GET_SAMPLE_PERIOD(sample_period
, min_period
);
348 GET_SAMPLE_PERIOD(sample_period
, max_period
);
350 iph1
->parent_session
->traffic_monitor
.interv_mon
= sample_period
;
355 ike_session_update_mode (phase2_handle_t
*iph2
)
357 if (!iph2
|| !iph2
->parent_session
) {
360 if (iph2
->phase2_type
!= PHASE2_TYPE_SA
)
362 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV2
) {
365 // exit early if we already detected cisco-ipsec
366 if (iph2
->parent_session
->is_cisco_ipsec
) {
370 if (iph2
->approval
) {
371 if (!ipsecdoi_any_transportmode(iph2
->approval
)) {
372 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
373 iph2
->parent_session
->is_cisco_ipsec
= 0;
374 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
375 iph2
->parent_session
->is_btmm_ipsec
= 1;
377 } else if (ipsecdoi_transportmode(iph2
->approval
)) {
378 iph2
->parent_session
->is_cisco_ipsec
= 0;
379 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
380 iph2
->parent_session
->is_btmm_ipsec
= 0;
383 } else if (iph2
->proposal
) {
384 if (!ipsecdoi_any_transportmode(iph2
->proposal
)) {
385 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
386 iph2
->parent_session
->is_cisco_ipsec
= 0;
387 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
388 iph2
->parent_session
->is_btmm_ipsec
= 1;
390 } else if (ipsecdoi_transportmode(iph2
->proposal
)) {
391 iph2
->parent_session
->is_cisco_ipsec
= 0;
392 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
393 iph2
->parent_session
->is_btmm_ipsec
= 0;
400 ike_session_cleanup_xauth_timeout (void *arg
)
402 ike_session_t
*session
= (ike_session_t
*)arg
;
404 SCHED_KILL(session
->sc_xauth
);
405 // if there are no more established ph2s, start a timer to teardown the session
406 if (!ike_session_has_established_ph2(session
)) {
407 ike_session_cleanup(session
, ike_session_stopped_by_xauth_timeout
);
409 session
->sc_xauth
= sched_new(300 /* 5 mins */,
410 ike_session_cleanup_xauth_timeout
,
416 ike_session_link_phase1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
419 if (!session
|| !iph1
) {
420 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
424 gettimeofday(&session
->start_timestamp
, NULL
);
426 if (iph1
->started_by_api
) {
427 session
->is_cisco_ipsec
= 1;
428 session
->is_l2tpvpn_ipsec
= 0;
429 session
->is_btmm_ipsec
= 0;
431 iph1
->parent_session
= session
;
432 LIST_INSERT_HEAD(&session
->ph1tree
, iph1
, ph1ofsession_chain
);
433 session
->ikev1_state
.active_ph1cnt
++;
434 if ((!session
->ikev1_state
.ph1cnt
&&
435 iph1
->side
== INITIATOR
) ||
436 iph1
->started_by_api
) {
437 // client initiates the first phase1 or, is started by controller api
438 session
->is_client
= 1;
440 if (session
->established
&&
441 session
->ikev1_state
.ph1cnt
&&
442 iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
445 session
->ikev1_state
.ph1cnt
++;
446 ike_session_init_traffic_cop_params(iph1
);
452 ike_session_link_phase2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
455 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
458 if (iph2
->parent_session
) {
459 plog(ASL_LEVEL_ERR
, "Phase 2 already linked to session %s.\n", __FUNCTION__
);
462 iph2
->parent_session
= session
;
463 LIST_INSERT_HEAD(&session
->ph2tree
, iph2
, ph2ofsession_chain
);
464 session
->ikev1_state
.active_ph2cnt
++;
465 if (!session
->ikev1_state
.ph2cnt
&&
466 iph2
->side
== INITIATOR
) {
467 // client initiates the first phase2
468 session
->is_client
= 1;
470 if (iph2
->phase2_type
== PHASE2_TYPE_SA
&&
471 session
->established
&&
472 session
->ikev1_state
.ph2cnt
&&
473 iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
476 session
->ikev1_state
.ph2cnt
++;
477 ike_session_update_mode(iph2
);
483 ike_session_link_ph2_to_ph1 (phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
485 struct sockaddr_storage
*local
;
486 struct sockaddr_storage
*remote
;
490 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
494 plog(ASL_LEVEL_ERR
, "Phase 2 already linked %s.\n", __FUNCTION__
);
495 if (iph2
->ph1
== iph1
)
498 return -1; // This shouldn't happen
504 if (iph2
->parent_session
== NULL
)
505 if ((error
= ike_session_link_phase2(iph1
->parent_session
, iph2
)))
508 ike_session_bindph12(iph1
, iph2
);
513 ike_session_unlink_phase1 (phase1_handle_t
*iph1
)
515 ike_session_t
*session
;
517 if (!iph1
|| !iph1
->parent_session
) {
518 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
522 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
523 if (LIST_FIRST(&iph1
->bound_ph2tree
)) {
524 // reparent any phase2 that may be hanging on to this phase1
525 ike_session_update_ph1_ph2tree(iph1
);
529 sched_scrub_param(iph1
);
530 session
= iph1
->parent_session
;
531 LIST_REMOVE(iph1
, ph1ofsession_chain
);
532 iph1
->parent_session
= NULL
;
533 session
->ikev1_state
.active_ph1cnt
--;
534 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
535 session
->is_dying
= 1;
536 free_ike_session(session
);
538 ike_session_delph1(iph1
);
543 ike_session_unlink_phase2 (phase2_handle_t
*iph2
)
545 ike_session_t
*session
;
547 if (!iph2
|| !iph2
->parent_session
) {
548 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
551 sched_scrub_param(iph2
);
552 ike_session_unbindph12(iph2
);
554 LIST_REMOVE(iph2
, ph2ofsession_chain
);
555 session
= iph2
->parent_session
;
556 iph2
->parent_session
= NULL
;
557 session
->ikev1_state
.active_ph2cnt
--;
558 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
559 session
->is_dying
= 1;
560 free_ike_session(session
);
562 ike_session_delph2(iph2
);
568 ike_session_update_ph1_ph2tree (phase1_handle_t
*iph1
)
570 phase1_handle_t
*new_iph1
= NULL
;
573 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
577 if (iph1
->parent_session
) {
578 new_iph1
= ike_session_get_established_ph1(iph1
->parent_session
);
581 plog(ASL_LEVEL_DEBUG
, "no ph1bind replacement found. NULL ph1.\n");
582 ike_session_unbind_all_ph2_from_ph1(iph1
);
583 } else if (iph1
== new_iph1
) {
584 plog(ASL_LEVEL_DEBUG
, "no ph1bind replacement found. same ph1.\n");
585 ike_session_unbind_all_ph2_from_ph1(iph1
);
587 ike_session_rebind_all_ph12_to_new_ph1(iph1
, new_iph1
);
590 plog(ASL_LEVEL_DEBUG
, "invalid parent session in %s.\n", __FUNCTION__
);
596 ike_session_update_ph2_ph1bind (phase2_handle_t
*iph2
)
598 phase1_handle_t
*iph1
;
600 if (!iph2
|| iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
601 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
605 iph1
= ike_session_get_established_ph1(iph2
->parent_session
);
606 if (iph1
&& iph2
->ph1
&& iph1
!= iph2
->ph1
) {
607 ike_session_rebindph12(iph1
, iph2
);
608 } else if (iph1
&& !iph2
->ph1
) {
609 ike_session_bindph12(iph1
, iph2
);
616 ike_session_get_established_or_negoing_ph1 (ike_session_t
*session
)
618 phase1_handle_t
*p
, *iph1
= NULL
;
621 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
625 // look for the most mature ph1 under the session
626 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
627 if (!p
->is_dying
&& (FSM_STATE_IS_ESTABLISHED(p
->status
) || FSM_STATE_IS_NEGOTIATING(p
->status
))) {
628 if (!iph1
|| p
->status
> iph1
->status
) {
630 } else if (iph1
&& p
->status
== iph1
->status
) {
631 // TODO: pick better one based on farthest rekey/expiry remaining
640 ike_session_get_established_ph1 (ike_session_t
*session
)
645 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
649 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
650 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
660 ike_session_has_other_established_ph1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
668 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
669 if (iph1
!= p
&& !p
->is_dying
) {
670 if (FSM_STATE_IS_ESTABLISHED(p
->status
) && p
->sce_rekey
) {
680 ike_session_has_other_negoing_ph1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
685 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
689 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
690 if (iph1
!= p
&& !p
->is_dying
) {
691 if (FSM_STATE_IS_NEGOTIATING(p
->status
)) {
701 ike_session_has_other_established_ph2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
706 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
710 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
711 if (p
->phase2_type
== PHASE2_TYPE_SA
&& iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
712 if (FSM_STATE_IS_ESTABLISHED(p
->status
)) {
722 ike_session_has_other_negoing_ph2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
727 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
731 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
732 plog(ASL_LEVEL_DEBUG
, "%s: ph2 sub spid %d, db spid %d\n", __FUNCTION__
, iph2
->spid
, p
->spid
);
733 if (p
->phase2_type
== PHASE2_TYPE_SA
&& iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
734 if (FSM_STATE_IS_NEGOTIATING(p
->status
)) {
745 ike_session_ikev1_float_ports (phase1_handle_t
*iph1
)
747 struct sockaddr_storage
*local
, *remote
;
750 if (iph1
->parent_session
) {
751 local
= &iph1
->parent_session
->session_id
.local
;
752 remote
= &iph1
->parent_session
->session_id
.remote
;
754 set_port(local
, extract_port(iph1
->local
));
755 set_port(remote
, extract_port(iph1
->remote
));
756 iph1
->parent_session
->ports_floated
= 1;
758 LIST_FOREACH(p
, &iph1
->parent_session
->ph2tree
, ph2ofsession_chain
) {
763 set_port(local
, extract_port(iph1
->local
));
764 set_port(remote
, extract_port(iph1
->remote
));
767 plog(ASL_LEVEL_DEBUG
, "invalid parent session in %s.\n", __FUNCTION__
);
772 ike_session_traffic_cop (void *arg
)
774 ike_session_t
*session
= (__typeof__(session
))arg
;
777 (session
->established
&& !session
->stopped_by_vpn_controller
&& !session
->stop_timestamp
.tv_sec
&& !session
->stop_timestamp
.tv_usec
)) {
778 SCHED_KILL(session
->traffic_monitor
.sc_mon
);
779 /* get traffic query from kernel */
780 if (pk_sendget_inbound_sastats(session
) < 0) {
782 plog(ASL_LEVEL_DEBUG
, "pk_sendget_inbound_sastats failed in %s.\n", __FUNCTION__
);
784 if (pk_sendget_outbound_sastats(session
) < 0) {
786 plog(ASL_LEVEL_DEBUG
, "pk_sendget_outbound_sastats failed in %s.\n", __FUNCTION__
);
788 session
->traffic_monitor
.sc_mon
= sched_new(session
->traffic_monitor
.interv_mon
,
789 ike_session_traffic_cop
,
793 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
798 ike_session_cleanup_idle (void *arg
)
800 ike_session_cleanup((ike_session_t
*)arg
, ike_session_stopped_by_idle
);
804 ike_session_monitor_idle (ike_session_t
*session
)
809 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_INBOUND
||
810 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
811 if (session
->peer_sent_data_sc_idle
) {
812 plog(ASL_LEVEL_DEBUG
, "%s: restart idle-timeout because peer sent data. monitoring dir %d.\n",
813 __FUNCTION__
, session
->traffic_monitor
.dir_idle
);
814 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
815 if (session
->traffic_monitor
.interv_idle
) {
816 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
817 ike_session_cleanup_idle
,
820 session
->peer_sent_data_sc_idle
= 0;
821 session
->i_sent_data_sc_idle
= 0;
825 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_OUTBOUND
||
826 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
827 if (session
->i_sent_data_sc_idle
) {
828 plog(ASL_LEVEL_DEBUG
, "%s: restart idle-timeout because i sent data. monitoring dir %d.\n",
829 __FUNCTION__
, session
->traffic_monitor
.dir_idle
);
830 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
831 if (session
->traffic_monitor
.interv_idle
) {
832 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
833 ike_session_cleanup_idle
,
836 session
->peer_sent_data_sc_idle
= 0;
837 session
->i_sent_data_sc_idle
= 0;
844 ike_session_start_traffic_mon (ike_session_t
*session
)
846 if (session
->traffic_monitor
.interv_mon
) {
847 session
->traffic_monitor
.sc_mon
= sched_new(session
->traffic_monitor
.interv_mon
,
848 ike_session_traffic_cop
,
851 if (session
->traffic_monitor
.interv_idle
) {
852 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
853 ike_session_cleanup_idle
,
859 ike_session_ph2_established (phase2_handle_t
*iph2
)
861 if (!iph2
->parent_session
|| iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
862 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
865 SCHED_KILL(iph2
->parent_session
->sc_xauth
);
866 if (!iph2
->parent_session
->established
) {
867 gettimeofday(&iph2
->parent_session
->estab_timestamp
, NULL
);
868 iph2
->parent_session
->established
= 1;
869 IPSECSESSIONTRACERESTABLISHED(iph2
->parent_session
);
870 ike_session_start_traffic_mon(iph2
->parent_session
);
871 } else if (iph2
->parent_session
->is_asserted
) {
872 ike_session_start_traffic_mon(iph2
->parent_session
);
874 iph2
->parent_session
->is_asserted
= 0;
875 // nothing happening to this session
876 iph2
->parent_session
->term_reason
= NULL
;
878 ike_session_update_mode(iph2
);
879 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
)
880 ike_session_unbindph12(iph2
);
882 #ifdef ENABLE_VPNCONTROL_PORT
883 vpncontrol_notify_peer_resp_ph2(1, iph2
);
884 #endif /* ENABLE_VPNCONTROL_PORT */
885 plog(ASL_LEVEL_DEBUG
, "%s: ph2 established, spid %d\n", __FUNCTION__
, iph2
->spid
);
889 ike_session_cleanup_ph1 (phase1_handle_t
*iph1
)
891 if (FSM_STATE_IS_EXPIRED(iph1
->status
)) {
892 // since this got here via ike_session_cleanup_other_established_ph1s, assumes LIST_FIRST(&iph1->ph2tree) == NULL
893 iph1
->sce
= sched_new(1, isakmp_ph1delete_stub
, iph1
);
897 /* send delete information */
898 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
899 isakmp_info_send_d1(iph1
);
902 isakmp_ph1expire(iph1
);
906 ike_session_cleanup_ph1_stub (void *p
)
909 ike_session_cleanup_ph1((phase1_handle_t
*)p
);
913 ike_session_replace_other_ph1 (phase1_handle_t
*new_iph1
,
914 phase1_handle_t
*old_iph1
)
916 char *local
, *remote
, *index
;
917 ike_session_t
*session
= NULL
;
920 session
= new_iph1
->parent_session
;
922 if (!session
|| !new_iph1
|| !old_iph1
|| session
!= old_iph1
->parent_session
|| new_iph1
== old_iph1
) {
923 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
928 * if we are responder, then we should wait until the server sends a delete notification.
930 if ((new_iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV2
|| session
->is_client
) &&
931 new_iph1
->side
== RESPONDER
) {
935 SCHED_KILL(old_iph1
->sce
);
936 SCHED_KILL(old_iph1
->sce_rekey
);
937 old_iph1
->is_dying
= 1;
940 local
= racoon_strdup(saddr2str((struct sockaddr
*)old_iph1
->local
));
941 remote
= racoon_strdup(saddr2str((struct sockaddr
*)old_iph1
->remote
));
942 index
= racoon_strdup(isakmp_pindex(&old_iph1
->index
, 0));
944 STRDUP_FATAL(remote
);
946 plog(ASL_LEVEL_DEBUG
, "ISAKMP-SA %s-%s (spi:%s) needs to be deleted, replaced by (spi:%s)\n", local
, remote
, index
, isakmp_pindex(&new_iph1
->index
, 0));
951 // first rebind the children ph2s of this dying ph1 to the new ph1.
952 ike_session_rebind_all_ph12_to_new_ph1 (old_iph1
, new_iph1
);
954 if (old_iph1
->side
== INITIATOR
) {
955 /* everyone deletes old outbound SA */
956 old_iph1
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, old_iph1
);
958 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
959 old_iph1
->sce
= sched_new(7, ike_session_cleanup_ph1_stub
, old_iph1
);
964 ike_session_cleanup_other_established_ph1s (ike_session_t
*session
,
965 phase1_handle_t
*new_iph1
)
967 phase1_handle_t
*p
, *next
;
968 char *local
, *remote
;
970 if (!session
|| !new_iph1
|| session
!= new_iph1
->parent_session
) {
971 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
976 * if we are responder, then we should wait until the server sends a delete notification.
978 if ((new_iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV2
|| session
->is_client
) &&
979 new_iph1
->side
== RESPONDER
) {
983 LIST_FOREACH_SAFE(p
, &session
->ph1tree
, ph1ofsession_chain
, next
) {
985 * TODO: currently, most recently established SA wins. Need to revisit to see if
986 * alternative selections is better (e.g. largest p->index stays).
988 if (p
!= new_iph1
&& !p
->is_dying
) {
990 SCHED_KILL(p
->sce_rekey
);
994 local
= racoon_strdup(saddr2str((struct sockaddr
*)p
->local
));
995 remote
= racoon_strdup(saddr2str((struct sockaddr
*)p
->remote
));
997 STRDUP_FATAL(remote
);
998 plog(ASL_LEVEL_DEBUG
,
999 "ISAKMP-SA needs to be deleted %s-%s spi:%s\n",
1000 local
, remote
, isakmp_pindex(&p
->index
, 0));
1002 racoon_free(remote
);
1004 // first rebind the children ph2s of this dying ph1 to the new ph1.
1005 ike_session_rebind_all_ph12_to_new_ph1 (p
, new_iph1
);
1007 if (p
->side
== INITIATOR
) {
1008 /* everyone deletes old outbound SA */
1009 p
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, p
);
1011 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
1012 p
->sce
= sched_new(7, ike_session_cleanup_ph1_stub
, p
);
1019 ike_session_cleanup_ph2 (phase2_handle_t
*iph2
)
1021 if (iph2
->phase2_type
!= PHASE2_TYPE_SA
)
1023 if (FSM_STATE_IS_EXPIRED(iph2
->status
)) {
1027 SCHED_KILL(iph2
->sce
);
1030 "about to cleanup ph2: status %d, seq %d dying %d\n",
1031 iph2
->status
, iph2
->seq
, iph2
->is_dying
);
1033 /* send delete information */
1034 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
)) {
1035 isakmp_info_send_d2(iph2
);
1037 // delete outgoing SAs
1038 if (iph2
->approval
) {
1041 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1043 pfkey_send_delete(lcconf
->sock_pfkey
,
1044 ipsecdoi2pfkey_proto(pr
->proto_id
),
1046 iph2
->src
, iph2
->dst
, pr
->spi_p
/* pr->reqid_out */);
1053 ike_session_unlink_phase2(iph2
);
1057 ike_session_cleanup_ph2_stub (void *p
)
1060 ike_session_cleanup_ph2((phase2_handle_t
*)p
);
1064 ike_session_cleanup_other_established_ph2s (ike_session_t
*session
,
1065 phase2_handle_t
*new_iph2
)
1067 phase2_handle_t
*p
, *next
;
1069 if (!session
|| !new_iph2
|| session
!= new_iph2
->parent_session
|| new_iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
1070 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1075 * if we are responder, then we should wait until the server sends a delete notification.
1077 if (session
->is_client
&& new_iph2
->side
== RESPONDER
) {
1081 LIST_FOREACH_SAFE(p
, &session
->ph2tree
, ph2ofsession_chain
, next
) {
1083 * TODO: currently, most recently established SA wins. Need to revisit to see if
1084 * alternative selections is better.
1086 if (p
!= new_iph2
&& p
->spid
== new_iph2
->spid
&& !p
->is_dying
) {
1091 plog(ASL_LEVEL_DEBUG
,
1092 "IPsec-SA needs to be deleted: %s\n",
1093 sadbsecas2str(p
->src
, p
->dst
,
1094 p
->satype
, p
->spid
, 0));
1096 if (p
->side
== INITIATOR
) {
1097 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1098 p
->sce
= sched_new(3, ike_session_cleanup_ph2_stub
, p
);
1100 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1101 p
->sce
= sched_new(5, ike_session_cleanup_ph2_stub
, p
);
1108 ike_session_stopped_by_controller (ike_session_t
*session
,
1112 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1115 if (session
->stop_timestamp
.tv_sec
||
1116 session
->stop_timestamp
.tv_usec
) {
1117 plog(ASL_LEVEL_DEBUG
, "already stopped %s.\n", __FUNCTION__
);
1120 session
->stopped_by_vpn_controller
= 1;
1121 gettimeofday(&session
->stop_timestamp
, NULL
);
1122 if (!session
->term_reason
) {
1123 session
->term_reason
= (__typeof__(session
->term_reason
))reason
;
1128 ike_sessions_stopped_by_controller (struct sockaddr_storage
*remote
,
1132 ike_session_t
*p
= NULL
;
1133 ike_session_t
*next_session
= NULL
;
1136 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1140 LIST_FOREACH_SAFE(p
, &ike_session_tree
, chain
, next_session
) {
1141 if ((withport
&& cmpsaddrstrict(&p
->session_id
.remote
, remote
) == 0) ||
1142 (!withport
&& cmpsaddrwop(&p
->session_id
.remote
, remote
) == 0)) {
1143 ike_session_stopped_by_controller(p
, reason
);
1149 ike_session_purge_ph2s_by_ph1 (phase1_handle_t
*iph1
)
1151 phase2_handle_t
*p
, *next
;
1153 if (!iph1
|| !iph1
->parent_session
) {
1154 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1158 LIST_FOREACH_SAFE(p
, &iph1
->parent_session
->ph2tree
, ph2ofsession_chain
, next
) {
1166 plog(ASL_LEVEL_DEBUG
,
1167 "IPsec-SA needs to be purged: %s\n",
1168 sadbsecas2str(p
->src
, p
->dst
,
1169 p
->satype
, p
->spid
, 0));
1171 ike_session_cleanup_ph2(p
);
1176 ike_session_update_ph2_ports (phase2_handle_t
*iph2
)
1178 struct sockaddr_storage
*local
;
1179 struct sockaddr_storage
*remote
;
1181 if (iph2
->parent_session
) {
1182 local
= &iph2
->parent_session
->session_id
.local
;
1183 remote
= &iph2
->parent_session
->session_id
.remote
;
1185 set_port(iph2
->src
, extract_port(local
));
1186 set_port(iph2
->dst
, extract_port(remote
));
1188 plog(ASL_LEVEL_DEBUG
, "invalid parent session in %s.\n", __FUNCTION__
);
1193 ike_session_get_sas_for_stats (ike_session_t
*session
,
1196 struct sastat
*stats
,
1197 u_int32_t max_stats
)
1200 phase2_handle_t
*iph2
;
1202 if (!session
|| !seq
|| !stats
|| !max_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1203 plog(ASL_LEVEL_DEBUG
, "invalid args in %s.\n", __FUNCTION__
);
1208 LIST_FOREACH(iph2
, &session
->ph2tree
, ph2ofsession_chain
) {
1209 if (iph2
->approval
) {
1212 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1213 if (pr
->ok
&& pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
) {
1217 if (dir
== IPSEC_DIR_INBOUND
) {
1218 stats
[found
].spi
= pr
->spi
;
1220 stats
[found
].spi
= pr
->spi_p
;
1222 if (++found
== max_stats
) {
1233 ike_session_update_traffic_idle_status (ike_session_t
*session
,
1235 struct sastat
*new_stats
,
1236 u_int32_t max_stats
)
1238 int i
, j
, found
= 0, idle
= 1;
1240 if (!session
|| !new_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1241 plog(ASL_LEVEL_DEBUG
, "invalid args in %s.\n", __FUNCTION__
);
1245 if (!session
->established
|| session
->stopped_by_vpn_controller
|| session
->stop_timestamp
.tv_sec
|| session
->stop_timestamp
.tv_usec
) {
1246 plog(ASL_LEVEL_DEBUG
, "dropping update on invalid session in %s.\n", __FUNCTION__
);
1250 for (i
= 0; i
< max_stats
; i
++) {
1251 if (dir
== IPSEC_DIR_INBOUND
) {
1252 for (j
= 0; j
< session
->traffic_monitor
.num_in_last_poll
; j
++) {
1253 if (new_stats
[i
].spi
!= session
->traffic_monitor
.in_last_poll
[j
].spi
) {
1257 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.in_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1262 for (j
= 0; j
< session
->traffic_monitor
.num_out_last_poll
; j
++) {
1263 if (new_stats
[i
].spi
!= session
->traffic_monitor
.out_last_poll
[j
].spi
) {
1267 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.out_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1272 // new SA.... check for any activity
1274 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
) {
1275 plog(ASL_LEVEL_DEBUG
, "new SA: dir %d....\n", dir
);
1280 if (dir
== IPSEC_DIR_INBOUND
) {
1281 // overwrite old stats
1282 bzero(session
->traffic_monitor
.in_last_poll
, sizeof(session
->traffic_monitor
.in_last_poll
));
1283 bcopy(new_stats
, session
->traffic_monitor
.in_last_poll
, (max_stats
* sizeof(*new_stats
)));
1284 session
->traffic_monitor
.num_in_last_poll
= max_stats
;
1286 //plog(ASL_LEVEL_DEBUG, "peer sent data....\n");
1287 session
->peer_sent_data_sc_dpd
= 1;
1288 session
->peer_sent_data_sc_idle
= 1;
1291 // overwrite old stats
1292 bzero(session
->traffic_monitor
.out_last_poll
, sizeof(session
->traffic_monitor
.out_last_poll
));
1293 bcopy(new_stats
, session
->traffic_monitor
.out_last_poll
, (max_stats
* sizeof(*new_stats
)));
1294 session
->traffic_monitor
.num_out_last_poll
= max_stats
;
1296 //plog(ASL_LEVEL_DEBUG, "i sent data....\n");
1297 session
->i_sent_data_sc_dpd
= 1;
1298 session
->i_sent_data_sc_idle
= 1;
1302 session
->last_time_data_sc_detected
= time(NULL
);
1304 ike_session_monitor_idle(session
);
1308 ike_session_cleanup (ike_session_t
*session
,
1311 phase2_handle_t
*iph2
= NULL
;
1312 phase2_handle_t
*next_iph2
= NULL
;
1313 phase1_handle_t
*iph1
= NULL
;
1314 phase1_handle_t
*next_iph1
= NULL
;
1319 session
->is_dying
= 1;
1320 ike_session_stopped_by_controller(session
, reason
);
1322 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
1323 // do ph2's first... we need the ph1s for notifications
1324 LIST_FOREACH_SAFE(iph2
, &session
->ph2tree
, ph2ofsession_chain
, next_iph2
) {
1325 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
)) {
1326 isakmp_info_send_d2(iph2
);
1328 isakmp_ph2expire(iph2
); // iph2 will go down 1 second later.
1331 // do the ph1s last.
1332 LIST_FOREACH_SAFE(iph1
, &session
->ph1tree
, ph1ofsession_chain
, next_iph1
) {
1333 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
1334 isakmp_info_send_d1(iph1
);
1336 isakmp_ph1expire(iph1
);
1339 // send ipsecManager a notification
1340 if (session
->is_cisco_ipsec
&& reason
&& reason
!= ike_session_stopped_by_vpn_disconnect
1341 && reason
!= ike_session_stopped_by_controller_comm_lost
) {
1343 if ((&session
->session_id
.remote
)->ss_family
== AF_INET
) {
1344 address
= ((struct sockaddr_in
*)&session
->session_id
.remote
)->sin_addr
.s_addr
;
1349 if (reason
== ike_session_stopped_by_idle
) {
1350 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_IDLE_TIMEOUT
, FROM_LOCAL
, address
, 0, NULL
);
1352 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_INTERNAL_ERROR
, FROM_LOCAL
, address
, 0, NULL
);
1358 ike_session_has_negoing_ph1 (ike_session_t
*session
)
1363 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1367 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
1368 if (!p
->is_dying
&& FSM_STATE_IS_NEGOTIATING(p
->status
)) {
1377 ike_session_has_established_ph1 (ike_session_t
*session
)
1382 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1386 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
1387 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
1396 ike_session_has_negoing_ph2 (ike_session_t
*session
)
1401 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1405 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
1406 if (!p
->is_dying
&& FSM_STATE_IS_NEGOTIATING(p
->status
)) {
1415 ike_session_has_established_ph2 (ike_session_t
*session
)
1420 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1424 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
1425 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
1434 ike_session_cleanup_ph1s_by_ph2 (phase2_handle_t
*iph2
)
1436 phase1_handle_t
*iph1
= NULL
;
1437 phase1_handle_t
*next_iph1
= NULL
;
1439 if (!iph2
|| !iph2
->parent_session
) {
1440 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1444 // phase1 is no longer useful
1445 LIST_FOREACH_SAFE(iph1
, &iph2
->parent_session
->ph1tree
, ph1ofsession_chain
, next_iph1
) {
1446 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
1447 isakmp_info_send_d1(iph1
);
1449 isakmp_ph1expire(iph1
);
1454 ike_session_is_client_ph2_rekey (phase2_handle_t
*iph2
)
1456 if (iph2
->parent_session
&&
1457 iph2
->parent_session
->is_client
&&
1459 iph2
->parent_session
->is_cisco_ipsec
) {
1466 ike_session_is_client_ph1_rekey (phase1_handle_t
*iph1
)
1468 if (iph1
->parent_session
&&
1469 iph1
->parent_session
->is_client
&&
1471 iph1
->parent_session
->is_cisco_ipsec
) {
1478 ike_session_is_client_ph1 (phase1_handle_t
*iph1
)
1480 if (iph1
->parent_session
&&
1481 iph1
->parent_session
->is_client
) {
1488 ike_session_is_client_ph2 (phase2_handle_t
*iph2
)
1490 if (iph2
->parent_session
&&
1491 iph2
->parent_session
->is_client
) {
1498 ike_session_start_xauth_timer (phase1_handle_t
*iph1
)
1500 // if there are no more established ph2s, start a timer to teardown the session
1501 if (iph1
->parent_session
&&
1502 iph1
->parent_session
->is_client
&&
1503 iph1
->parent_session
->is_cisco_ipsec
&&
1504 !iph1
->parent_session
->sc_xauth
) {
1505 iph1
->parent_session
->sc_xauth
= sched_new(300 /* 5 mins */,
1506 ike_session_cleanup_xauth_timeout
,
1507 iph1
->parent_session
);
1512 ike_session_stop_xauth_timer (phase1_handle_t
*iph1
)
1514 if (iph1
->parent_session
) {
1515 SCHED_KILL(iph1
->parent_session
->sc_xauth
);
1520 ike_session_is_id_ipany (vchar_t
*ext_id
)
1523 u_int8_t type
; /* ID Type */
1524 u_int8_t proto_id
; /* Protocol ID */
1525 u_int16_t port
; /* Port */
1526 u_int32_t addr
; /* IPv4 address */
1530 /* ignore protocol and port */
1531 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1532 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1533 id_ptr
->addr
== 0) {
1535 } else if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
&&
1536 id_ptr
->mask
== 0 &&
1537 id_ptr
->addr
== 0) {
1540 plog(ASL_LEVEL_DEBUG
, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
1541 __FUNCTION__
, id_ptr
->type
, id_ptr
->addr
, id_ptr
->mask
);
1546 ike_session_is_id_portany (vchar_t
*ext_id
)
1549 u_int8_t type
; /* ID Type */
1550 u_int8_t proto_id
; /* Protocol ID */
1551 u_int16_t port
; /* Port */
1552 u_int32_t addr
; /* IPv4 address */
1557 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1558 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1559 id_ptr
->port
== 0) {
1562 plog(ASL_LEVEL_DEBUG
, "not portany_ids in %s: type %d, port %x.\n",
1563 __FUNCTION__
, id_ptr
->type
, id_ptr
->port
);
1568 ike_session_set_id_portany (vchar_t
*ext_id
)
1571 u_int8_t type
; /* ID Type */
1572 u_int8_t proto_id
; /* Protocol ID */
1573 u_int16_t port
; /* Port */
1574 u_int32_t addr
; /* IPv4 address */
1579 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1580 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
) {
1587 ike_session_cmp_ph2_ids_ipany (vchar_t
*ext_id
,
1590 if (ike_session_is_id_ipany(ext_id
) &&
1591 ike_session_is_id_ipany(ext_id_p
)) {
1598 * ipsec rekeys for l2tp-over-ipsec fail particularly when client is behind nat because the client's configs and policies don't
1599 * match the server's view of the client's address and port.
1600 * servers behave differently when using this address-port info to generate ids during phase2 rekeys, so try to match the incoming id to
1601 * a variety of info saved in the older phase2.
1604 ike_session_cmp_ph2_ids (phase2_handle_t
*iph2
,
1605 phase2_handle_t
*older_ph2
)
1607 vchar_t
*portany_id
= NULL
;
1608 vchar_t
*portany_id_p
= NULL
;
1610 if (iph2
->id
&& older_ph2
->id
&&
1611 iph2
->id
->l
== older_ph2
->id
->l
&&
1612 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1613 iph2
->id_p
&& older_ph2
->id_p
&&
1614 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1615 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1618 if (iph2
->ext_nat_id
&& older_ph2
->ext_nat_id
&&
1619 iph2
->ext_nat_id
->l
== older_ph2
->ext_nat_id
->l
&&
1620 memcmp(iph2
->ext_nat_id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->ext_nat_id
->l
) == 0 &&
1621 iph2
->ext_nat_id_p
&& older_ph2
->ext_nat_id_p
&&
1622 iph2
->ext_nat_id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1623 memcmp(iph2
->ext_nat_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->ext_nat_id_p
->l
) == 0) {
1626 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1627 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1628 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1629 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1630 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1631 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1634 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1635 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1636 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1637 iph2
->id_p
&& older_ph2
->id_p
&&
1638 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1639 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1642 if (iph2
->id
&& older_ph2
->id
&&
1643 iph2
->id
->l
== older_ph2
->id
->l
&&
1644 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1645 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1646 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1647 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1651 /* check if the external id has a wildcard port and compare ids accordingly */
1652 if ((older_ph2
->ext_nat_id
&& ike_session_is_id_portany(older_ph2
->ext_nat_id
)) ||
1653 (older_ph2
->ext_nat_id_p
&& ike_session_is_id_portany(older_ph2
->ext_nat_id_p
))) {
1654 // try ignoring ports in iph2->id and iph2->id
1655 if (iph2
->id
&& (portany_id
= vdup(iph2
->id
))) {
1656 ike_session_set_id_portany(portany_id
);
1658 if (iph2
->id_p
&& (portany_id_p
= vdup(iph2
->id_p
))) {
1659 ike_session_set_id_portany(portany_id_p
);
1661 if (portany_id
&& older_ph2
->ext_nat_id
&&
1662 portany_id
->l
== older_ph2
->ext_nat_id
->l
&&
1663 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1664 portany_id_p
&& older_ph2
->ext_nat_id_p
&&
1665 portany_id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1666 memcmp(portany_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, portany_id_p
->l
) == 0) {
1671 vfree(portany_id_p
);
1675 if (portany_id
&& iph2
->id
&& older_ph2
->ext_nat_id
&&
1676 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1677 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1678 iph2
->id_p
&& older_ph2
->id_p
&&
1679 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1680 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1685 vfree(portany_id_p
);
1689 if (portany_id_p
&& iph2
->id
&& older_ph2
->id
&&
1690 iph2
->id
->l
== older_ph2
->id
->l
&&
1691 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1692 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1693 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1694 memcmp(portany_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, portany_id_p
->l
) == 0) {
1699 vfree(portany_id_p
);
1707 vfree(portany_id_p
);
1714 ike_session_get_sainfo_r (phase2_handle_t
*iph2
)
1716 if (iph2
->parent_session
&&
1717 iph2
->parent_session
->is_client
&&
1718 iph2
->id
&& iph2
->id_p
) {
1720 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1721 plog(ASL_LEVEL_DEBUG
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1723 LIST_FOREACH(p
, &iph2
->parent_session
->ph2tree
, ph2ofsession_chain
) {
1724 if (iph2
!= p
&& !p
->is_dying
&& FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p
->status
) && p
->sainfo
) {
1725 plog(ASL_LEVEL_DEBUG
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1727 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1728 plog(ASL_LEVEL_DEBUG
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1729 iph2
->sainfo
= p
->sainfo
;
1731 retain_sainfo(iph2
->sainfo
);
1733 iph2
->spid
= p
->spid
;
1735 plog(ASL_LEVEL_DEBUG
, "%s: pre-assigned spid %d.\n", __FUNCTION__
, iph2
->spid
);
1737 if (p
->ext_nat_id
) {
1738 if (iph2
->ext_nat_id
) {
1739 vfree(iph2
->ext_nat_id
);
1741 iph2
->ext_nat_id
= vdup(p
->ext_nat_id
);
1743 if (p
->ext_nat_id_p
) {
1744 if (iph2
->ext_nat_id_p
) {
1745 vfree(iph2
->ext_nat_id_p
);
1747 iph2
->ext_nat_id_p
= vdup(p
->ext_nat_id_p
);
1758 ike_session_get_proposal_r (phase2_handle_t
*iph2
)
1760 if (iph2
->parent_session
&&
1761 iph2
->parent_session
->is_client
&&
1762 iph2
->id
&& iph2
->id_p
) {
1764 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1765 plog(ASL_LEVEL_DEBUG
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1767 LIST_FOREACH(p
, &iph2
->parent_session
->ph2tree
, ph2ofsession_chain
) {
1768 if (iph2
!= p
&& !p
->is_dying
&& FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p
->status
) &&
1770 plog(ASL_LEVEL_DEBUG
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1772 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1773 plog(ASL_LEVEL_DEBUG
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1774 iph2
->proposal
= dupsaprop(p
->approval
, 1);
1776 iph2
->spid
= p
->spid
;
1778 plog(ASL_LEVEL_DEBUG
, "%s: pre-assigned spid %d.\n", __FUNCTION__
, iph2
->spid
);
1789 ike_session_update_natt_version (phase1_handle_t
*iph1
)
1791 if (iph1
->parent_session
) {
1792 if (iph1
->natt_options
) {
1793 iph1
->parent_session
->natt_version
= iph1
->natt_options
->version
;
1795 iph1
->parent_session
->natt_version
= 0;
1801 ike_session_get_natt_version (phase1_handle_t
*iph1
)
1803 if (iph1
->parent_session
) {
1804 return(iph1
->parent_session
->natt_version
);
1810 ike_session_drop_rekey (ike_session_t
*session
, ike_session_rekey_type_t rekey_type
)
1813 if (session
->is_btmm_ipsec
&&
1814 session
->last_time_data_sc_detected
&&
1815 session
->traffic_monitor
.interv_mon
&&
1816 session
->traffic_monitor
.interv_idle
) {
1817 // for btmm: drop ph1/ph2 rekey if session is idle
1818 time_t now
= time(NULL
);
1820 if ((now
- session
->last_time_data_sc_detected
) > (session
->traffic_monitor
.interv_mon
<< 1)) {
1821 plog(ASL_LEVEL_DEBUG
, "btmm session is idle: drop ph%drekey.\n",
1825 } else if (!session
->is_btmm_ipsec
) {
1826 if (rekey_type
== IKE_SESSION_REKEY_TYPE_PH1
&&
1827 !ike_session_has_negoing_ph2(session
) && !ike_session_has_established_ph2(session
)) {
1828 // for vpn: only drop ph1 if there are no more ph2s.
1829 plog(ASL_LEVEL_DEBUG
, "vpn session is idle: drop ph1 rekey.\n");
1838 * this is called after racooon receives a 'kIOMessageSystemHasPoweredOn'
1839 * a lot is done to make sure that we don't sweep a session that's already been asserted.
1840 * however, it'll be too bad if the assertion comes after the session has already been swept.
1843 ike_session_sweep_sleepwake (void)
1845 ike_session_t
*p
= NULL
;
1846 ike_session_t
*next_session
= NULL
;
1848 // flag session as dying if all ph1/ph2 are dead/dying
1849 LIST_FOREACH_SAFE(p
, &ike_session_tree
, chain
, next_session
) {
1851 plog(ASL_LEVEL_DEBUG
, "skipping sweep of dying session.\n");
1854 SCHED_KILL(p
->sc_xauth
);
1855 if (p
->is_asserted
) {
1856 // for asserted session, traffic monitors will be restared after phase2 becomes established.
1857 SCHED_KILL(p
->traffic_monitor
.sc_mon
);
1858 SCHED_KILL(p
->traffic_monitor
.sc_idle
);
1859 plog(ASL_LEVEL_DEBUG
, "skipping sweep of asserted session.\n");
1863 // cleanup any stopped sessions as they will go down
1864 if (p
->stopped_by_vpn_controller
|| p
->stop_timestamp
.tv_sec
|| p
->stop_timestamp
.tv_usec
) {
1865 plog(ASL_LEVEL_DEBUG
, "sweeping stopped session.\n");
1866 ike_session_cleanup(p
, ike_session_stopped_by_sleepwake
);
1870 if (!ike_session_has_established_ph1(p
) && !ike_session_has_established_ph2(p
)) {
1871 plog(ASL_LEVEL_DEBUG
, "session died while sleeping.\n");
1872 ike_session_cleanup(p
, ike_session_stopped_by_sleepwake
);
1875 if (p
->traffic_monitor
.sc_mon
) {
1877 if (sched_get_time(p
->traffic_monitor
.sc_mon
, &xtime
)) {
1878 if (xtime
<= swept_at
) {
1879 SCHED_KILL(p
->traffic_monitor
.sc_mon
);
1880 if (!p
->is_dying
&& p
->traffic_monitor
.interv_mon
) {
1881 p
->traffic_monitor
.sc_mon
= sched_new(p
->traffic_monitor
.interv_mon
,
1882 ike_session_traffic_cop
,
1888 if (p
->traffic_monitor
.sc_idle
) {
1890 if (sched_get_time(p
->traffic_monitor
.sc_idle
, &xtime
)) {
1891 if (xtime
<= swept_at
) {
1892 SCHED_KILL(p
->traffic_monitor
.sc_idle
);
1893 if (!p
->is_dying
&& p
->traffic_monitor
.interv_idle
) {
1894 p
->traffic_monitor
.sc_idle
= sched_new(p
->traffic_monitor
.interv_idle
,
1895 ike_session_cleanup_idle
,
1905 * this is called after racooon receives an assert command from the controller/pppd.
1906 * this is intended to make racoon prepare to rekey both SAs because a network event occurred.
1907 * in the event of a sleepwake, the assert could happen before or after 'ike_session_sweep_sleepwake'.
1910 ike_session_assert_session (ike_session_t
*session
)
1912 phase2_handle_t
*iph2
= NULL
;
1913 phase2_handle_t
*iph2_next
= NULL
;
1914 phase1_handle_t
*iph1
= NULL
;
1915 phase1_handle_t
*iph1_next
= NULL
;
1917 if (!session
|| session
->is_dying
) {
1918 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
1922 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase2s
1923 LIST_FOREACH_SAFE(iph2
, &session
->ph2tree
, ph2ofsession_chain
, iph2_next
) {
1924 if (!iph2
->is_dying
&& !FSM_STATE_IS_EXPIRED(iph2
->status
)) {
1925 SCHED_KILL(iph2
->sce
);
1928 // delete SAs (in the kernel)
1929 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
) && iph2
->approval
) {
1932 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1935 plog(ASL_LEVEL_DEBUG
,
1936 "Assert: Phase 2 %s deleted\n",
1937 sadbsecas2str(iph2
->src
, iph2
->dst
, iph2
->satype
, iph2
->spid
, ipsecdoi2pfkey_mode(pr
->encmode
)));
1939 pfkey_send_delete(lcconf
->sock_pfkey
,
1940 ipsecdoi2pfkey_proto(pr
->proto_id
),
1941 ipsecdoi2pfkey_mode(pr
->encmode
),
1942 iph2
->src
, iph2
->dst
, pr
->spi_p
);
1947 fsm_set_state(&iph2
->status
, IKEV1_STATE_PHASE2_EXPIRED
); // we want to delete SAs without telling the PEER
1948 iph2
->sce
= sched_new(3, ike_session_cleanup_ph2_stub
, iph2
);
1952 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase1s
1953 LIST_FOREACH_SAFE(iph1
, &session
->ph1tree
, ph1ofsession_chain
, iph1_next
) {
1954 if (!iph1
->is_dying
&& !FSM_STATE_IS_EXPIRED(iph1
->status
)) {
1955 SCHED_KILL(iph1
->sce
);
1956 SCHED_KILL(iph1
->sce_rekey
);
1960 plog(ASL_LEVEL_DEBUG
,
1961 "Assert: Phase 1 %s deleted\n",
1962 isakmp_pindex(&iph1
->index
, 0));
1964 ike_session_unbind_all_ph2_from_ph1(iph1
);
1966 fsm_set_state(&iph1
->status
, IKEV1_STATE_PHASE1_EXPIRED
); // we want to delete SAs without telling the PEER
1967 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
1968 iph1
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, iph1
);
1971 session
->is_asserted
= 1;
1977 ike_session_assert (struct sockaddr_storage
*local
,
1978 struct sockaddr_storage
*remote
)
1980 ike_session_t
*sess
;
1982 if (!local
|| !remote
) {
1983 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1987 if ((sess
= ike_session_get_session(local
, remote
, FALSE
, NULL
))) {
1988 return(ike_session_assert_session(sess
));
1994 ike_session_ph2_retransmits (phase2_handle_t
*iph2
)
1996 int num_retransmits
;
1998 if (!iph2
->is_dying
&&
2001 iph2
->ph1
->sce_rekey
&& !sched_is_dead(iph2
->ph1
->sce_rekey
) &&
2002 iph2
->side
== INITIATOR
&&
2003 iph2
->parent_session
&&
2004 !iph2
->parent_session
->is_cisco_ipsec
&& /* not for Cisco */
2005 iph2
->parent_session
->is_client
) {
2006 num_retransmits
= iph2
->ph1
->rmconf
->retry_counter
- iph2
->retry_counter
;
2007 if (num_retransmits
== 3) {
2009 * phase2 negotiation is stalling on retransmits, inspite of a valid ph1.
2010 * one of the following is possible:
2011 * - (0) severe packet loss.
2012 * - (1) the peer is dead.
2013 * - (2) the peer is out of sync hence dropping this phase2 rekey (and perhaps responding with insecure
2014 * invalid-cookie notifications... but those are untrusted and so we can't rekey phase1 off that)
2015 * (2.1) the peer rebooted (or process restarted) and is now alive.
2016 * (2.2) the peer has deleted phase1 without notifying us (or the notification got dropped somehow).
2017 * (2.3) the peer has a policy/bug stopping this phase2 rekey
2019 * in all these cases, one sure way to know is to trigger a phase1 rekey early.
2021 plog(ASL_LEVEL_DEBUG
, "Many Phase 2 retransmits: try Phase 1 rekey and this Phase 2 to quit earlier.\n");
2022 isakmp_ph1rekeyexpire(iph2
->ph1
, TRUE
);
2023 iph2
->retry_counter
= 0;
2029 ike_session_ph1_retransmits (phase1_handle_t
*iph1
)
2031 int num_retransmits
;
2033 if (!iph1
->is_dying
&&
2036 FSM_STATE_IS_NEGOTIATING(iph1
->status
) &&
2037 iph1
->side
== INITIATOR
&&
2038 iph1
->parent_session
&&
2039 iph1
->parent_session
->is_client
&&
2040 !ike_session_has_other_negoing_ph1(iph1
->parent_session
, iph1
)) {
2041 num_retransmits
= iph1
->rmconf
->retry_counter
- iph1
->retry_counter
;
2042 if (num_retransmits
== 3) {
2043 plog(ASL_LEVEL_DEBUG
, "Many Phase 1 retransmits: try quit earlier.\n");
2044 iph1
->retry_counter
= 0;
2050 ike_session_bindph12(phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
2053 plog(ASL_LEVEL_ERR
, "Phase 2 already bound %s.\n", __FUNCTION__
);
2056 LIST_INSERT_HEAD(&iph1
->bound_ph2tree
, iph2
, ph1bind_chain
);
2060 ike_session_unbindph12(phase2_handle_t
*iph2
)
2062 if (iph2
->ph1
!= NULL
) {
2064 LIST_REMOVE(iph2
, ph1bind_chain
);
2069 ike_session_rebindph12(phase1_handle_t
*new_ph1
, phase2_handle_t
*iph2
)
2075 // reconcile the ph1-to-ph2 binding
2076 ike_session_unbindph12(iph2
);
2077 ike_session_bindph12(new_ph1
, iph2
);
2078 // recalculate ivm since ph1 binding has changed
2079 if (iph2
->ivm
!= NULL
) {
2080 oakley_delivm(iph2
->ivm
);
2081 if (FSM_STATE_IS_ESTABLISHED(new_ph1
->status
)) {
2082 iph2
->ivm
= oakley_newiv2(new_ph1
, iph2
->msgid
);
2083 plog(ASL_LEVEL_DEBUG
, "Phase 1-2 binding changed... recalculated ivm.\n");
2091 ike_session_unbind_all_ph2_from_ph1 (phase1_handle_t
*iph1
)
2093 phase2_handle_t
*p
= NULL
;
2094 phase2_handle_t
*next
= NULL
;
2096 LIST_FOREACH_SAFE(p
, &iph1
->bound_ph2tree
, ph1bind_chain
, next
) {
2097 ike_session_unbindph12(p
);
2102 ike_session_rebind_all_ph12_to_new_ph1 (phase1_handle_t
*old_iph1
,
2103 phase1_handle_t
*new_iph1
)
2105 phase2_handle_t
*p
= NULL
;
2106 phase2_handle_t
*next
= NULL
;
2108 if (old_iph1
== new_iph1
|| !old_iph1
|| !new_iph1
) {
2109 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
2113 if (old_iph1
->parent_session
!= new_iph1
->parent_session
) {
2114 plog(ASL_LEVEL_DEBUG
, "Invalid parent sessions in %s.\n", __FUNCTION__
);
2118 LIST_FOREACH_SAFE(p
, &old_iph1
->bound_ph2tree
, ph1bind_chain
, next
) {
2119 if (p
->parent_session
!= new_iph1
->parent_session
) {
2120 plog(ASL_LEVEL_ERR
, "Mismatched parent session in ph1bind replacement.\n");
2122 if (p
->ph1
== new_iph1
) {
2123 plog(ASL_LEVEL_ERR
, "Same Phase 2 in ph1bind replacement in %s.\n",__FUNCTION__
);
2125 ike_session_rebindph12(new_iph1
, p
);