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_ERR
, "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_NOTICE
,
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_NOTICE
, "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_ERR
, "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
;
326 if (!iph1
->parent_session
->traffic_monitor
.dir_idle
) {
327 iph1
->parent_session
->traffic_monitor
.dir_idle
= iph1
->rmconf
->idle_timeout_dir
;
330 if (!iph1
->parent_session
->traffic_monitor
.interv_mon
) {
331 int min_period
, max_period
, sample_period
= 0;
333 /* calculate the sampling interval... half the smaller interval */
334 if (iph1
->rmconf
->dpd_interval
&&
335 (iph1
->rmconf
->dpd_algo
== DPD_ALGO_INBOUND_DETECT
||
336 iph1
->rmconf
->dpd_algo
== DPD_ALGO_BLACKHOLE_DETECT
)) {
337 // when certain types of dpd are enabled
338 min_period
= MIN(iph1
->rmconf
->dpd_interval
, iph1
->rmconf
->idle_timeout
);
339 max_period
= MAX(iph1
->rmconf
->dpd_interval
, iph1
->rmconf
->idle_timeout
);
340 } else if (iph1
->rmconf
->idle_timeout
) {
341 min_period
= max_period
= iph1
->rmconf
->idle_timeout
;
343 // DPD_ALGO_DEFAULT is configured and there's no idle timeout... we don't need to monitor traffic
347 GET_SAMPLE_PERIOD(sample_period
, min_period
);
349 GET_SAMPLE_PERIOD(sample_period
, max_period
);
351 iph1
->parent_session
->traffic_monitor
.interv_mon
= sample_period
;
356 ike_session_update_mode (phase2_handle_t
*iph2
)
358 if (!iph2
|| !iph2
->parent_session
) {
361 if (iph2
->phase2_type
!= PHASE2_TYPE_SA
)
364 // exit early if we already detected cisco-ipsec
365 if (iph2
->parent_session
->is_cisco_ipsec
) {
369 if (iph2
->approval
) {
370 if (!ipsecdoi_any_transportmode(iph2
->approval
)) {
371 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
372 iph2
->parent_session
->is_cisco_ipsec
= 0;
373 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
374 iph2
->parent_session
->is_btmm_ipsec
= 1;
376 } else if (ipsecdoi_transportmode(iph2
->approval
)) {
377 iph2
->parent_session
->is_cisco_ipsec
= 0;
378 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
379 iph2
->parent_session
->is_btmm_ipsec
= 0;
382 } else if (iph2
->proposal
) {
383 if (!ipsecdoi_any_transportmode(iph2
->proposal
)) {
384 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
385 iph2
->parent_session
->is_cisco_ipsec
= 0;
386 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
387 iph2
->parent_session
->is_btmm_ipsec
= 1;
389 } else if (ipsecdoi_transportmode(iph2
->proposal
)) {
390 iph2
->parent_session
->is_cisco_ipsec
= 0;
391 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
392 iph2
->parent_session
->is_btmm_ipsec
= 0;
399 ike_session_cleanup_xauth_timeout (void *arg
)
401 ike_session_t
*session
= (ike_session_t
*)arg
;
403 SCHED_KILL(session
->sc_xauth
);
404 // if there are no more established ph2s, start a timer to teardown the session
405 if (!ike_session_has_established_ph2(session
)) {
406 ike_session_cleanup(session
, ike_session_stopped_by_xauth_timeout
);
408 session
->sc_xauth
= sched_new(300 /* 5 mins */,
409 ike_session_cleanup_xauth_timeout
,
415 ike_session_link_phase1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
418 if (!session
|| !iph1
) {
419 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
423 gettimeofday(&session
->start_timestamp
, NULL
);
425 if (iph1
->started_by_api
) {
426 session
->is_cisco_ipsec
= 1;
427 session
->is_l2tpvpn_ipsec
= 0;
428 session
->is_btmm_ipsec
= 0;
430 iph1
->parent_session
= session
;
431 LIST_INSERT_HEAD(&session
->ph1tree
, iph1
, ph1ofsession_chain
);
432 session
->ikev1_state
.active_ph1cnt
++;
433 if ((!session
->ikev1_state
.ph1cnt
&&
434 iph1
->side
== INITIATOR
) ||
435 iph1
->started_by_api
) {
436 // client initiates the first phase1 or, is started by controller api
437 session
->is_client
= 1;
439 if (session
->established
&&
440 session
->ikev1_state
.ph1cnt
&&
441 iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
444 session
->ikev1_state
.ph1cnt
++;
445 ike_session_init_traffic_cop_params(iph1
);
451 ike_session_link_phase2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
454 plog(ASL_LEVEL_ERR
, "Invalid parameters in %s.\n", __FUNCTION__
);
457 if (iph2
->parent_session
) {
458 plog(ASL_LEVEL_ERR
, "Phase 2 already linked to session %s.\n", __FUNCTION__
);
461 iph2
->parent_session
= session
;
462 LIST_INSERT_HEAD(&session
->ph2tree
, iph2
, ph2ofsession_chain
);
463 session
->ikev1_state
.active_ph2cnt
++;
464 if (!session
->ikev1_state
.ph2cnt
&&
465 iph2
->side
== INITIATOR
) {
466 // client initiates the first phase2
467 session
->is_client
= 1;
469 if (iph2
->phase2_type
== PHASE2_TYPE_SA
&&
470 session
->established
&&
471 session
->ikev1_state
.ph2cnt
&&
472 iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
475 session
->ikev1_state
.ph2cnt
++;
476 ike_session_update_mode(iph2
);
482 ike_session_link_ph2_to_ph1 (phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
484 struct sockaddr_storage
*local
;
485 struct sockaddr_storage
*remote
;
489 plog(ASL_LEVEL_ERR
, "Invalid parameters in %s.\n", __FUNCTION__
);
493 plog(ASL_LEVEL_ERR
, "Phase 2 already linked %s.\n", __FUNCTION__
);
494 if (iph2
->ph1
== iph1
)
497 return -1; // This shouldn't happen
503 if (iph2
->parent_session
== NULL
)
504 if ((error
= ike_session_link_phase2(iph1
->parent_session
, iph2
)))
507 ike_session_bindph12(iph1
, iph2
);
512 ike_session_unlink_phase1 (phase1_handle_t
*iph1
)
514 ike_session_t
*session
;
516 if (!iph1
|| !iph1
->parent_session
) {
517 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
521 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
522 if (LIST_FIRST(&iph1
->bound_ph2tree
)) {
523 // reparent any phase2 that may be hanging on to this phase1
524 ike_session_update_ph1_ph2tree(iph1
);
528 sched_scrub_param(iph1
);
529 session
= iph1
->parent_session
;
530 LIST_REMOVE(iph1
, ph1ofsession_chain
);
531 iph1
->parent_session
= NULL
;
532 session
->ikev1_state
.active_ph1cnt
--;
533 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
534 session
->is_dying
= 1;
535 free_ike_session(session
);
537 ike_session_delph1(iph1
);
542 ike_session_unlink_phase2 (phase2_handle_t
*iph2
)
544 ike_session_t
*session
;
546 if (!iph2
|| !iph2
->parent_session
) {
547 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
550 sched_scrub_param(iph2
);
551 ike_session_unbindph12(iph2
);
553 LIST_REMOVE(iph2
, ph2ofsession_chain
);
554 session
= iph2
->parent_session
;
555 iph2
->parent_session
= NULL
;
556 session
->ikev1_state
.active_ph2cnt
--;
557 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
558 session
->is_dying
= 1;
559 free_ike_session(session
);
561 ike_session_delph2(iph2
);
567 ike_session_update_ph1_ph2tree (phase1_handle_t
*iph1
)
569 phase1_handle_t
*new_iph1
= NULL
;
572 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
576 if (iph1
->parent_session
) {
577 new_iph1
= ike_session_get_established_ph1(iph1
->parent_session
);
580 plog(ASL_LEVEL_NOTICE
, "no ph1bind replacement found. NULL ph1.\n");
581 ike_session_unbind_all_ph2_from_ph1(iph1
);
582 } else if (iph1
== new_iph1
) {
583 plog(ASL_LEVEL_NOTICE
, "no ph1bind replacement found. same ph1.\n");
584 ike_session_unbind_all_ph2_from_ph1(iph1
);
586 ike_session_rebind_all_ph12_to_new_ph1(iph1
, new_iph1
);
589 plog(ASL_LEVEL_NOTICE
, "invalid parent session in %s.\n", __FUNCTION__
);
595 ike_session_update_ph2_ph1bind (phase2_handle_t
*iph2
)
597 phase1_handle_t
*iph1
;
599 if (!iph2
|| iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
600 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
604 iph1
= ike_session_get_established_ph1(iph2
->parent_session
);
605 if (iph1
&& iph2
->ph1
&& iph1
!= iph2
->ph1
) {
606 ike_session_rebindph12(iph1
, iph2
);
607 } else if (iph1
&& !iph2
->ph1
) {
608 ike_session_bindph12(iph1
, iph2
);
615 ike_session_get_established_or_negoing_ph1 (ike_session_t
*session
)
617 phase1_handle_t
*p
, *iph1
= NULL
;
620 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
624 // look for the most mature ph1 under the session
625 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
626 if (!p
->is_dying
&& (FSM_STATE_IS_ESTABLISHED(p
->status
) || FSM_STATE_IS_NEGOTIATING(p
->status
))) {
627 if (!iph1
|| p
->status
> iph1
->status
) {
629 } else if (iph1
&& p
->status
== iph1
->status
) {
630 // TODO: pick better one based on farthest rekey/expiry remaining
639 ike_session_get_established_ph1 (ike_session_t
*session
)
644 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
648 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
649 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
659 ike_session_has_other_established_ph1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
667 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
668 if (iph1
!= p
&& !p
->is_dying
) {
669 if (FSM_STATE_IS_ESTABLISHED(p
->status
) && p
->sce_rekey
) {
679 ike_session_has_other_negoing_ph1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
684 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
688 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
689 if (iph1
!= p
&& !p
->is_dying
) {
690 if (FSM_STATE_IS_NEGOTIATING(p
->status
)) {
700 ike_session_has_other_established_ph2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
705 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
709 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
710 if (p
->phase2_type
== PHASE2_TYPE_SA
&& iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
711 if (FSM_STATE_IS_ESTABLISHED(p
->status
)) {
721 ike_session_has_other_negoing_ph2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
726 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
730 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
731 plog(ASL_LEVEL_DEBUG
, "%s: ph2 sub spid %d, db spid %d\n", __FUNCTION__
, iph2
->spid
, p
->spid
);
732 if (p
->phase2_type
== PHASE2_TYPE_SA
&& iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
733 if (FSM_STATE_IS_NEGOTIATING(p
->status
)) {
744 ike_session_ikev1_float_ports (phase1_handle_t
*iph1
)
746 struct sockaddr_storage
*local
, *remote
;
749 if (iph1
->parent_session
) {
750 local
= &iph1
->parent_session
->session_id
.local
;
751 remote
= &iph1
->parent_session
->session_id
.remote
;
753 set_port(local
, extract_port(iph1
->local
));
754 set_port(remote
, extract_port(iph1
->remote
));
755 iph1
->parent_session
->ports_floated
= 1;
757 LIST_FOREACH(p
, &iph1
->parent_session
->ph2tree
, ph2ofsession_chain
) {
762 set_port(local
, extract_port(iph1
->local
));
763 set_port(remote
, extract_port(iph1
->remote
));
766 plog(ASL_LEVEL_NOTICE
, "invalid parent session in %s.\n", __FUNCTION__
);
771 ike_session_traffic_cop (void *arg
)
773 ike_session_t
*session
= (__typeof__(session
))arg
;
776 (session
->established
&& !session
->stopped_by_vpn_controller
&& !session
->stop_timestamp
.tv_sec
&& !session
->stop_timestamp
.tv_usec
)) {
777 SCHED_KILL(session
->traffic_monitor
.sc_mon
);
778 /* get traffic query from kernel */
779 if (pk_sendget_inbound_sastats(session
) < 0) {
781 plog(ASL_LEVEL_NOTICE
, "pk_sendget_inbound_sastats failed in %s.\n", __FUNCTION__
);
783 if (pk_sendget_outbound_sastats(session
) < 0) {
785 plog(ASL_LEVEL_NOTICE
, "pk_sendget_outbound_sastats failed in %s.\n", __FUNCTION__
);
787 session
->traffic_monitor
.sc_mon
= sched_new(session
->traffic_monitor
.interv_mon
,
788 ike_session_traffic_cop
,
792 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
797 ike_session_cleanup_idle (void *arg
)
799 ike_session_cleanup((ike_session_t
*)arg
, ike_session_stopped_by_idle
);
803 ike_session_monitor_idle (ike_session_t
*session
)
808 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_INBOUND
||
809 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
810 if (session
->peer_sent_data_sc_idle
) {
811 plog(ASL_LEVEL_NOTICE
, "%s: restart idle-timeout because peer sent data. monitoring dir %d. idle timer %d s\n",
812 __FUNCTION__
, session
->traffic_monitor
.dir_idle
, session
->traffic_monitor
.interv_idle
);
813 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
814 if (session
->traffic_monitor
.interv_idle
) {
815 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
816 ike_session_cleanup_idle
,
819 session
->peer_sent_data_sc_idle
= 0;
820 session
->i_sent_data_sc_idle
= 0;
824 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_OUTBOUND
||
825 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
826 if (session
->i_sent_data_sc_idle
) {
827 plog(ASL_LEVEL_NOTICE
, "%s: restart idle-timeout because i sent data. monitoring dir %d. idle times %d s\n",
828 __FUNCTION__
, session
->traffic_monitor
.dir_idle
, session
->traffic_monitor
.interv_idle
);
829 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
830 if (session
->traffic_monitor
.interv_idle
) {
831 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
832 ike_session_cleanup_idle
,
835 session
->peer_sent_data_sc_idle
= 0;
836 session
->i_sent_data_sc_idle
= 0;
843 ike_session_start_traffic_mon (ike_session_t
*session
)
845 if (session
->traffic_monitor
.interv_mon
) {
846 session
->traffic_monitor
.sc_mon
= sched_new(session
->traffic_monitor
.interv_mon
,
847 ike_session_traffic_cop
,
850 if (session
->traffic_monitor
.interv_idle
) {
851 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
852 ike_session_cleanup_idle
,
858 ike_session_ph2_established (phase2_handle_t
*iph2
)
860 if (!iph2
->parent_session
|| iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
861 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
864 SCHED_KILL(iph2
->parent_session
->sc_xauth
);
865 if (!iph2
->parent_session
->established
) {
866 gettimeofday(&iph2
->parent_session
->estab_timestamp
, NULL
);
867 iph2
->parent_session
->established
= 1;
868 IPSECSESSIONTRACERESTABLISHED(iph2
->parent_session
);
869 ike_session_start_traffic_mon(iph2
->parent_session
);
870 } else if (iph2
->parent_session
->is_asserted
) {
871 ike_session_start_traffic_mon(iph2
->parent_session
);
873 iph2
->parent_session
->is_asserted
= 0;
874 // nothing happening to this session
875 iph2
->parent_session
->term_reason
= NULL
;
877 ike_session_update_mode(iph2
);
878 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
)
879 ike_session_unbindph12(iph2
);
881 #ifdef ENABLE_VPNCONTROL_PORT
882 vpncontrol_notify_peer_resp_ph2(1, iph2
);
883 #endif /* ENABLE_VPNCONTROL_PORT */
884 plog(ASL_LEVEL_NOTICE
, "%s: ph2 established, spid %d\n", __FUNCTION__
, iph2
->spid
);
888 ike_session_cleanup_ph1 (phase1_handle_t
*iph1
)
890 if (FSM_STATE_IS_EXPIRED(iph1
->status
)) {
891 // since this got here via ike_session_cleanup_other_established_ph1s, assumes LIST_FIRST(&iph1->ph2tree) == NULL
892 iph1
->sce
= sched_new(1, isakmp_ph1delete_stub
, iph1
);
896 /* send delete information */
897 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
898 isakmp_info_send_d1(iph1
);
901 isakmp_ph1expire(iph1
);
905 ike_session_cleanup_ph1_stub (void *p
)
908 ike_session_cleanup_ph1((phase1_handle_t
*)p
);
912 ike_session_replace_other_ph1 (phase1_handle_t
*new_iph1
,
913 phase1_handle_t
*old_iph1
)
915 char *local
, *remote
, *index
;
916 ike_session_t
*session
= NULL
;
919 session
= new_iph1
->parent_session
;
921 if (!session
|| !new_iph1
|| !old_iph1
|| session
!= old_iph1
->parent_session
|| new_iph1
== old_iph1
) {
922 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
927 * if we are responder, then we should wait until the server sends a delete notification.
929 if (session
->is_client
&&
930 new_iph1
->side
== RESPONDER
) {
934 SCHED_KILL(old_iph1
->sce
);
935 SCHED_KILL(old_iph1
->sce_rekey
);
936 old_iph1
->is_dying
= 1;
939 local
= racoon_strdup(saddr2str((struct sockaddr
*)old_iph1
->local
));
940 remote
= racoon_strdup(saddr2str((struct sockaddr
*)old_iph1
->remote
));
941 index
= racoon_strdup(isakmp_pindex(&old_iph1
->index
, 0));
943 STRDUP_FATAL(remote
);
945 plog(ASL_LEVEL_NOTICE
, "ISAKMP-SA %s-%s (spi:%s) needs to be deleted, replaced by (spi:%s)\n", local
, remote
, index
, isakmp_pindex(&new_iph1
->index
, 0));
950 // first rebind the children ph2s of this dying ph1 to the new ph1.
951 ike_session_rebind_all_ph12_to_new_ph1 (old_iph1
, new_iph1
);
953 if (old_iph1
->side
== INITIATOR
) {
954 /* everyone deletes old outbound SA */
955 old_iph1
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, old_iph1
);
957 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
958 old_iph1
->sce
= sched_new(7, ike_session_cleanup_ph1_stub
, old_iph1
);
963 ike_session_cleanup_other_established_ph1s (ike_session_t
*session
,
964 phase1_handle_t
*new_iph1
)
966 phase1_handle_t
*p
, *next
;
967 char *local
, *remote
;
969 if (!session
|| !new_iph1
|| session
!= new_iph1
->parent_session
) {
970 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
975 * if we are responder, then we should wait until the server sends a delete notification.
977 if (session
->is_client
&&
978 new_iph1
->side
== RESPONDER
) {
982 LIST_FOREACH_SAFE(p
, &session
->ph1tree
, ph1ofsession_chain
, next
) {
984 * TODO: currently, most recently established SA wins. Need to revisit to see if
985 * alternative selections is better (e.g. largest p->index stays).
987 if (p
!= new_iph1
&& !p
->is_dying
) {
989 SCHED_KILL(p
->sce_rekey
);
993 local
= racoon_strdup(saddr2str((struct sockaddr
*)p
->local
));
994 remote
= racoon_strdup(saddr2str((struct sockaddr
*)p
->remote
));
996 STRDUP_FATAL(remote
);
997 plog(ASL_LEVEL_NOTICE
,
998 "ISAKMP-SA needs to be deleted %s-%s spi:%s\n",
999 local
, remote
, isakmp_pindex(&p
->index
, 0));
1001 racoon_free(remote
);
1003 // first rebind the children ph2s of this dying ph1 to the new ph1.
1004 ike_session_rebind_all_ph12_to_new_ph1 (p
, new_iph1
);
1006 if (p
->side
== INITIATOR
) {
1007 /* everyone deletes old outbound SA */
1008 p
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, p
);
1010 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
1011 p
->sce
= sched_new(7, ike_session_cleanup_ph1_stub
, p
);
1018 ike_session_cleanup_ph2 (phase2_handle_t
*iph2
)
1020 if (iph2
->phase2_type
!= PHASE2_TYPE_SA
)
1022 if (FSM_STATE_IS_EXPIRED(iph2
->status
)) {
1026 SCHED_KILL(iph2
->sce
);
1029 "about to cleanup ph2: status %d, seq %d dying %d\n",
1030 iph2
->status
, iph2
->seq
, iph2
->is_dying
);
1032 /* send delete information */
1033 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
)) {
1034 isakmp_info_send_d2(iph2
);
1036 // delete outgoing SAs
1037 if (iph2
->approval
) {
1040 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1042 pfkey_send_delete(lcconf
->sock_pfkey
,
1043 ipsecdoi2pfkey_proto(pr
->proto_id
),
1045 iph2
->src
, iph2
->dst
, pr
->spi_p
/* pr->reqid_out */);
1052 ike_session_unlink_phase2(iph2
);
1056 ike_session_cleanup_ph2_stub (void *p
)
1059 ike_session_cleanup_ph2((phase2_handle_t
*)p
);
1063 ike_session_cleanup_other_established_ph2s (ike_session_t
*session
,
1064 phase2_handle_t
*new_iph2
)
1066 phase2_handle_t
*p
, *next
;
1068 if (!session
|| !new_iph2
|| session
!= new_iph2
->parent_session
|| new_iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
1069 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1074 * if we are responder, then we should wait until the server sends a delete notification.
1076 if (session
->is_client
&& new_iph2
->side
== RESPONDER
) {
1080 LIST_FOREACH_SAFE(p
, &session
->ph2tree
, ph2ofsession_chain
, next
) {
1082 * TODO: currently, most recently established SA wins. Need to revisit to see if
1083 * alternative selections is better.
1085 if (p
!= new_iph2
&& p
->spid
== new_iph2
->spid
&& !p
->is_dying
) {
1090 plog(ASL_LEVEL_NOTICE
,
1091 "IPsec-SA needs to be deleted: %s\n",
1092 sadbsecas2str(p
->src
, p
->dst
,
1093 p
->satype
, p
->spid
, 0));
1095 if (p
->side
== INITIATOR
) {
1096 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1097 p
->sce
= sched_new(3, ike_session_cleanup_ph2_stub
, p
);
1099 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1100 p
->sce
= sched_new(5, ike_session_cleanup_ph2_stub
, p
);
1107 ike_session_stopped_by_controller (ike_session_t
*session
,
1111 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1114 if (session
->stop_timestamp
.tv_sec
||
1115 session
->stop_timestamp
.tv_usec
) {
1116 plog(ASL_LEVEL_NOTICE
, "already stopped %s.\n", __FUNCTION__
);
1119 session
->stopped_by_vpn_controller
= 1;
1120 gettimeofday(&session
->stop_timestamp
, NULL
);
1121 if (!session
->term_reason
) {
1122 session
->term_reason
= (__typeof__(session
->term_reason
))reason
;
1127 ike_sessions_stopped_by_controller (struct sockaddr_storage
*remote
,
1131 ike_session_t
*p
= NULL
;
1132 ike_session_t
*next_session
= NULL
;
1135 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1139 LIST_FOREACH_SAFE(p
, &ike_session_tree
, chain
, next_session
) {
1140 if ((withport
&& cmpsaddrstrict(&p
->session_id
.remote
, remote
) == 0) ||
1141 (!withport
&& cmpsaddrwop(&p
->session_id
.remote
, remote
) == 0)) {
1142 ike_session_stopped_by_controller(p
, reason
);
1148 ike_session_purge_ph1s_by_session (ike_session_t
*session
)
1150 phase1_handle_t
*iph1
;
1151 phase1_handle_t
*next_iph1
= NULL
;
1153 LIST_FOREACH_SAFE(iph1
, &session
->ph1tree
, ph1ofsession_chain
, next_iph1
) {
1154 plog(ASL_LEVEL_NOTICE
, "deleteallph1 of given session: got a ph1 handler...\n");
1156 vpncontrol_notify_ike_failed(VPNCTL_NTYPE_NO_PROPOSAL_CHOSEN
, FROM_REMOTE
,
1157 iph1_get_remote_v4_address(iph1
), 0, NULL
);
1159 ike_session_unlink_phase1(iph1
);
1164 ike_session_purge_ph2s_by_ph1 (phase1_handle_t
*iph1
)
1166 phase2_handle_t
*p
, *next
;
1168 if (!iph1
|| !iph1
->parent_session
) {
1169 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1173 LIST_FOREACH_SAFE(p
, &iph1
->parent_session
->ph2tree
, ph2ofsession_chain
, next
) {
1181 plog(ASL_LEVEL_NOTICE
,
1182 "IPsec-SA needs to be purged: %s\n",
1183 sadbsecas2str(p
->src
, p
->dst
,
1184 p
->satype
, p
->spid
, 0));
1186 ike_session_cleanup_ph2(p
);
1191 ike_session_update_ph2_ports (phase2_handle_t
*iph2
)
1193 struct sockaddr_storage
*local
;
1194 struct sockaddr_storage
*remote
;
1196 if (iph2
->parent_session
) {
1197 local
= &iph2
->parent_session
->session_id
.local
;
1198 remote
= &iph2
->parent_session
->session_id
.remote
;
1200 set_port(iph2
->src
, extract_port(local
));
1201 set_port(iph2
->dst
, extract_port(remote
));
1203 plog(ASL_LEVEL_NOTICE
, "invalid parent session in %s.\n", __FUNCTION__
);
1208 ike_session_get_sas_for_stats (ike_session_t
*session
,
1211 struct sastat
*stats
,
1212 u_int32_t max_stats
)
1215 phase2_handle_t
*iph2
;
1217 if (!session
|| !seq
|| !stats
|| !max_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1218 plog(ASL_LEVEL_ERR
, "invalid args in %s.\n", __FUNCTION__
);
1223 LIST_FOREACH(iph2
, &session
->ph2tree
, ph2ofsession_chain
) {
1224 if (iph2
->approval
) {
1227 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1228 if (pr
->ok
&& pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
) {
1232 if (dir
== IPSEC_DIR_INBOUND
) {
1233 stats
[found
].spi
= pr
->spi
;
1235 stats
[found
].spi
= pr
->spi_p
;
1237 if (++found
== max_stats
) {
1248 ike_session_update_traffic_idle_status (ike_session_t
*session
,
1250 struct sastat
*new_stats
,
1251 u_int32_t max_stats
)
1253 int i
, j
, found
= 0, idle
= 1;
1255 if (!session
|| !new_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1256 plog(ASL_LEVEL_ERR
, "invalid args in %s.\n", __FUNCTION__
);
1260 if (!session
->established
|| session
->stopped_by_vpn_controller
|| session
->stop_timestamp
.tv_sec
|| session
->stop_timestamp
.tv_usec
) {
1261 plog(ASL_LEVEL_NOTICE
, "dropping update on invalid session in %s.\n", __FUNCTION__
);
1265 for (i
= 0; i
< max_stats
; i
++) {
1266 if (dir
== IPSEC_DIR_INBOUND
) {
1267 for (j
= 0; j
< session
->traffic_monitor
.num_in_last_poll
; j
++) {
1268 if (new_stats
[i
].spi
!= session
->traffic_monitor
.in_last_poll
[j
].spi
) {
1272 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.in_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1277 for (j
= 0; j
< session
->traffic_monitor
.num_out_last_poll
; j
++) {
1278 if (new_stats
[i
].spi
!= session
->traffic_monitor
.out_last_poll
[j
].spi
) {
1282 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.out_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1287 // new SA.... check for any activity
1289 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
) {
1290 plog(ASL_LEVEL_NOTICE
, "new SA: dir %d....\n", dir
);
1295 if (dir
== IPSEC_DIR_INBOUND
) {
1296 // overwrite old stats
1297 bzero(session
->traffic_monitor
.in_last_poll
, sizeof(session
->traffic_monitor
.in_last_poll
));
1298 bcopy(new_stats
, session
->traffic_monitor
.in_last_poll
, (max_stats
* sizeof(*new_stats
)));
1299 session
->traffic_monitor
.num_in_last_poll
= max_stats
;
1301 //plog(ASL_LEVEL_DEBUG, "peer sent data....\n");
1302 session
->peer_sent_data_sc_dpd
= 1;
1303 session
->peer_sent_data_sc_idle
= 1;
1306 // overwrite old stats
1307 bzero(session
->traffic_monitor
.out_last_poll
, sizeof(session
->traffic_monitor
.out_last_poll
));
1308 bcopy(new_stats
, session
->traffic_monitor
.out_last_poll
, (max_stats
* sizeof(*new_stats
)));
1309 session
->traffic_monitor
.num_out_last_poll
= max_stats
;
1311 //plog(ASL_LEVEL_DEBUG, "i sent data....\n");
1312 session
->i_sent_data_sc_dpd
= 1;
1313 session
->i_sent_data_sc_idle
= 1;
1317 session
->last_time_data_sc_detected
= time(NULL
);
1319 ike_session_monitor_idle(session
);
1323 ike_session_cleanup (ike_session_t
*session
,
1326 phase2_handle_t
*iph2
= NULL
;
1327 phase2_handle_t
*next_iph2
= NULL
;
1328 phase1_handle_t
*iph1
= NULL
;
1329 phase1_handle_t
*next_iph1
= NULL
;
1330 nw_nat64_prefix_t nat64_prefix
;
1335 memset(&nat64_prefix
, 0, sizeof(nat64_prefix
));
1336 session
->is_dying
= 1;
1337 ike_session_stopped_by_controller(session
, reason
);
1339 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
1340 // do ph2's first... we need the ph1s for notifications
1341 LIST_FOREACH_SAFE(iph2
, &session
->ph2tree
, ph2ofsession_chain
, next_iph2
) {
1342 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
)) {
1343 isakmp_info_send_d2(iph2
);
1345 isakmp_ph2expire(iph2
); // iph2 will go down 1 second later.
1348 // do the ph1s last.
1349 LIST_FOREACH_SAFE(iph1
, &session
->ph1tree
, ph1ofsession_chain
, next_iph1
) {
1351 if (iph1
->nat64_prefix
.length
> 0) {
1352 memcpy(&nat64_prefix
, &iph1
->nat64_prefix
, sizeof(nat64_prefix
));
1355 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
1356 isakmp_info_send_d1(iph1
);
1358 isakmp_ph1expire(iph1
);
1361 // send ipsecManager a notification
1362 if (session
->is_cisco_ipsec
&& reason
&& reason
!= ike_session_stopped_by_vpn_disconnect
1363 && reason
!= ike_session_stopped_by_controller_comm_lost
) {
1364 u_int32_t address
= 0;
1365 if ((&session
->session_id
.remote
)->ss_family
== AF_INET
) {
1366 address
= ((struct sockaddr_in
*)&session
->session_id
.remote
)->sin_addr
.s_addr
;
1368 if (nat64_prefix
.length
> 0) {
1369 struct in_addr inaddr
;
1370 nw_nat64_extract_v4(&nat64_prefix
,
1371 &((struct sockaddr_in6
*)&session
->session_id
.remote
)->sin6_addr
,
1373 address
= inaddr
.s_addr
;
1377 if (reason
== ike_session_stopped_by_idle
) {
1378 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_IDLE_TIMEOUT
, FROM_LOCAL
, address
, 0, NULL
);
1380 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_INTERNAL_ERROR
, FROM_LOCAL
, address
, 0, NULL
);
1386 ike_session_has_negoing_ph1 (ike_session_t
*session
)
1391 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1395 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
1396 if (!p
->is_dying
&& FSM_STATE_IS_NEGOTIATING(p
->status
)) {
1405 ike_session_has_established_ph1 (ike_session_t
*session
)
1410 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1414 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
1415 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
1424 ike_session_has_negoing_ph2 (ike_session_t
*session
)
1429 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1433 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
1434 if (!p
->is_dying
&& FSM_STATE_IS_NEGOTIATING(p
->status
)) {
1443 ike_session_has_established_ph2 (ike_session_t
*session
)
1448 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1452 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
1453 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
1462 ike_session_cleanup_ph1s_by_ph2 (phase2_handle_t
*iph2
)
1464 phase1_handle_t
*iph1
= NULL
;
1465 phase1_handle_t
*next_iph1
= NULL
;
1467 if (!iph2
|| !iph2
->parent_session
) {
1468 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1472 // phase1 is no longer useful
1473 LIST_FOREACH_SAFE(iph1
, &iph2
->parent_session
->ph1tree
, ph1ofsession_chain
, next_iph1
) {
1474 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
1475 isakmp_info_send_d1(iph1
);
1477 isakmp_ph1expire(iph1
);
1482 ike_session_is_client_ph2_rekey (phase2_handle_t
*iph2
)
1484 if (iph2
->parent_session
&&
1485 iph2
->parent_session
->is_client
&&
1487 iph2
->parent_session
->is_cisco_ipsec
) {
1494 ike_session_is_client_ph1_rekey (phase1_handle_t
*iph1
)
1496 if (iph1
->parent_session
&&
1497 iph1
->parent_session
->is_client
&&
1499 iph1
->parent_session
->is_cisco_ipsec
) {
1506 ike_session_is_client_ph1 (phase1_handle_t
*iph1
)
1508 if (iph1
->parent_session
&&
1509 iph1
->parent_session
->is_client
) {
1516 ike_session_is_client_ph2 (phase2_handle_t
*iph2
)
1518 if (iph2
->parent_session
&&
1519 iph2
->parent_session
->is_client
) {
1526 ike_session_start_xauth_timer (phase1_handle_t
*iph1
)
1528 // if there are no more established ph2s, start a timer to teardown the session
1529 if (iph1
->parent_session
&&
1530 iph1
->parent_session
->is_client
&&
1531 iph1
->parent_session
->is_cisco_ipsec
&&
1532 !iph1
->parent_session
->sc_xauth
) {
1533 iph1
->parent_session
->sc_xauth
= sched_new(300 /* 5 mins */,
1534 ike_session_cleanup_xauth_timeout
,
1535 iph1
->parent_session
);
1540 ike_session_stop_xauth_timer (phase1_handle_t
*iph1
)
1542 if (iph1
->parent_session
) {
1543 SCHED_KILL(iph1
->parent_session
->sc_xauth
);
1548 ike_session_is_id_ipany (vchar_t
*ext_id
)
1551 u_int8_t type
; /* ID Type */
1552 u_int8_t proto_id
; /* Protocol ID */
1553 u_int16_t port
; /* Port */
1554 u_int32_t addr
; /* IPv4 address */
1558 /* ignore protocol and port */
1559 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1560 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1561 id_ptr
->addr
== 0) {
1563 } else if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
&&
1564 id_ptr
->mask
== 0 &&
1565 id_ptr
->addr
== 0) {
1568 plog(ASL_LEVEL_DEBUG
, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
1569 __FUNCTION__
, id_ptr
->type
, id_ptr
->addr
, id_ptr
->mask
);
1574 ike_session_is_id_portany (vchar_t
*ext_id
)
1577 u_int8_t type
; /* ID Type */
1578 u_int8_t proto_id
; /* Protocol ID */
1579 u_int16_t port
; /* Port */
1580 u_int32_t addr
; /* IPv4 address */
1585 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1586 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1587 id_ptr
->port
== 0) {
1590 plog(ASL_LEVEL_DEBUG
, "not portany_ids in %s: type %d, port %x.\n",
1591 __FUNCTION__
, id_ptr
->type
, id_ptr
->port
);
1596 ike_session_set_id_portany (vchar_t
*ext_id
)
1599 u_int8_t type
; /* ID Type */
1600 u_int8_t proto_id
; /* Protocol ID */
1601 u_int16_t port
; /* Port */
1602 u_int32_t addr
; /* IPv4 address */
1607 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1608 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
) {
1615 ike_session_cmp_ph2_ids_ipany (vchar_t
*ext_id
,
1618 if (ike_session_is_id_ipany(ext_id
) &&
1619 ike_session_is_id_ipany(ext_id_p
)) {
1626 * ipsec rekeys for l2tp-over-ipsec fail particularly when client is behind nat because the client's configs and policies don't
1627 * match the server's view of the client's address and port.
1628 * servers behave differently when using this address-port info to generate ids during phase2 rekeys, so try to match the incoming id to
1629 * a variety of info saved in the older phase2.
1632 ike_session_cmp_ph2_ids (phase2_handle_t
*iph2
,
1633 phase2_handle_t
*older_ph2
)
1635 vchar_t
*portany_id
= NULL
;
1636 vchar_t
*portany_id_p
= NULL
;
1638 if (iph2
->id
&& older_ph2
->id
&&
1639 iph2
->id
->l
== older_ph2
->id
->l
&&
1640 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1641 iph2
->id_p
&& older_ph2
->id_p
&&
1642 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1643 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1646 if (iph2
->ext_nat_id
&& older_ph2
->ext_nat_id
&&
1647 iph2
->ext_nat_id
->l
== older_ph2
->ext_nat_id
->l
&&
1648 memcmp(iph2
->ext_nat_id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->ext_nat_id
->l
) == 0 &&
1649 iph2
->ext_nat_id_p
&& older_ph2
->ext_nat_id_p
&&
1650 iph2
->ext_nat_id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1651 memcmp(iph2
->ext_nat_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->ext_nat_id_p
->l
) == 0) {
1654 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1655 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1656 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1657 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1658 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1659 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1662 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1663 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1664 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1665 iph2
->id_p
&& older_ph2
->id_p
&&
1666 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1667 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1670 if (iph2
->id
&& older_ph2
->id
&&
1671 iph2
->id
->l
== older_ph2
->id
->l
&&
1672 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1673 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1674 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1675 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1679 /* check if the external id has a wildcard port and compare ids accordingly */
1680 if ((older_ph2
->ext_nat_id
&& ike_session_is_id_portany(older_ph2
->ext_nat_id
)) ||
1681 (older_ph2
->ext_nat_id_p
&& ike_session_is_id_portany(older_ph2
->ext_nat_id_p
))) {
1682 // try ignoring ports in iph2->id and iph2->id
1683 if (iph2
->id
&& (portany_id
= vdup(iph2
->id
))) {
1684 ike_session_set_id_portany(portany_id
);
1686 if (iph2
->id_p
&& (portany_id_p
= vdup(iph2
->id_p
))) {
1687 ike_session_set_id_portany(portany_id_p
);
1689 if (portany_id
&& older_ph2
->ext_nat_id
&&
1690 portany_id
->l
== older_ph2
->ext_nat_id
->l
&&
1691 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1692 portany_id_p
&& older_ph2
->ext_nat_id_p
&&
1693 portany_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
);
1703 if (portany_id
&& iph2
->id
&& older_ph2
->ext_nat_id
&&
1704 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1705 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1706 iph2
->id_p
&& older_ph2
->id_p
&&
1707 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1708 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1713 vfree(portany_id_p
);
1717 if (portany_id_p
&& iph2
->id
&& older_ph2
->id
&&
1718 iph2
->id
->l
== older_ph2
->id
->l
&&
1719 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1720 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1721 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1722 memcmp(portany_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, portany_id_p
->l
) == 0) {
1727 vfree(portany_id_p
);
1735 vfree(portany_id_p
);
1742 ike_session_get_sainfo_r (phase2_handle_t
*iph2
)
1744 if (iph2
->parent_session
&&
1745 iph2
->parent_session
->is_client
&&
1746 iph2
->id
&& iph2
->id_p
) {
1748 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1749 plog(ASL_LEVEL_DEBUG
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1751 LIST_FOREACH(p
, &iph2
->parent_session
->ph2tree
, ph2ofsession_chain
) {
1752 if (iph2
!= p
&& !p
->is_dying
&& FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p
->status
) && p
->sainfo
) {
1753 plog(ASL_LEVEL_DEBUG
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1755 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1756 plog(ASL_LEVEL_DEBUG
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1757 iph2
->sainfo
= p
->sainfo
;
1759 retain_sainfo(iph2
->sainfo
);
1761 iph2
->spid
= p
->spid
;
1763 plog(ASL_LEVEL_DEBUG
, "%s: pre-assigned spid %d.\n", __FUNCTION__
, iph2
->spid
);
1765 if (p
->ext_nat_id
) {
1766 if (iph2
->ext_nat_id
) {
1767 vfree(iph2
->ext_nat_id
);
1769 iph2
->ext_nat_id
= vdup(p
->ext_nat_id
);
1771 if (p
->ext_nat_id_p
) {
1772 if (iph2
->ext_nat_id_p
) {
1773 vfree(iph2
->ext_nat_id_p
);
1775 iph2
->ext_nat_id_p
= vdup(p
->ext_nat_id_p
);
1786 ike_session_get_proposal_r (phase2_handle_t
*iph2
)
1788 if (iph2
->parent_session
&&
1789 iph2
->parent_session
->is_client
&&
1790 iph2
->id
&& iph2
->id_p
) {
1792 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1793 plog(ASL_LEVEL_DEBUG
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1795 LIST_FOREACH(p
, &iph2
->parent_session
->ph2tree
, ph2ofsession_chain
) {
1796 if (iph2
!= p
&& !p
->is_dying
&& FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p
->status
) &&
1798 plog(ASL_LEVEL_DEBUG
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1800 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1801 plog(ASL_LEVEL_DEBUG
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1802 iph2
->proposal
= dupsaprop(p
->approval
, 1);
1804 iph2
->spid
= p
->spid
;
1806 plog(ASL_LEVEL_DEBUG
, "%s: pre-assigned spid %d.\n", __FUNCTION__
, iph2
->spid
);
1817 ike_session_update_natt_version (phase1_handle_t
*iph1
)
1819 if (iph1
->parent_session
) {
1820 if (iph1
->natt_options
) {
1821 iph1
->parent_session
->natt_version
= iph1
->natt_options
->version
;
1823 iph1
->parent_session
->natt_version
= 0;
1829 ike_session_get_natt_version (phase1_handle_t
*iph1
)
1831 if (iph1
->parent_session
) {
1832 return(iph1
->parent_session
->natt_version
);
1838 ike_session_drop_rekey (ike_session_t
*session
, ike_session_rekey_type_t rekey_type
)
1841 if (session
->is_btmm_ipsec
&&
1842 session
->last_time_data_sc_detected
&&
1843 session
->traffic_monitor
.interv_mon
&&
1844 session
->traffic_monitor
.interv_idle
) {
1845 // for btmm: drop ph1/ph2 rekey if session is idle
1846 time_t now
= time(NULL
);
1848 if ((now
- session
->last_time_data_sc_detected
) > (session
->traffic_monitor
.interv_mon
<< 1)) {
1849 plog(ASL_LEVEL_NOTICE
, "btmm session is idle: drop ph%drekey.\n",
1853 } else if (!session
->is_btmm_ipsec
) {
1854 if (rekey_type
== IKE_SESSION_REKEY_TYPE_PH1
&&
1855 !ike_session_has_negoing_ph2(session
) && !ike_session_has_established_ph2(session
)) {
1856 // for vpn: only drop ph1 if there are no more ph2s.
1857 plog(ASL_LEVEL_NOTICE
, "vpn session is idle: drop ph1 rekey.\n");
1866 * this is called after racooon receives a 'kIOMessageSystemHasPoweredOn'
1867 * a lot is done to make sure that we don't sweep a session that's already been asserted.
1868 * however, it'll be too bad if the assertion comes after the session has already been swept.
1871 ike_session_sweep_sleepwake (void)
1873 ike_session_t
*p
= NULL
;
1874 ike_session_t
*next_session
= NULL
;
1876 // flag session as dying if all ph1/ph2 are dead/dying
1877 LIST_FOREACH_SAFE(p
, &ike_session_tree
, chain
, next_session
) {
1879 plog(ASL_LEVEL_NOTICE
, "skipping sweep of dying session.\n");
1882 SCHED_KILL(p
->sc_xauth
);
1883 if (p
->is_asserted
) {
1884 // for asserted session, traffic monitors will be restared after phase2 becomes established.
1885 SCHED_KILL(p
->traffic_monitor
.sc_mon
);
1886 SCHED_KILL(p
->traffic_monitor
.sc_idle
);
1887 plog(ASL_LEVEL_NOTICE
, "skipping sweep of asserted session.\n");
1891 // cleanup any stopped sessions as they will go down
1892 if (p
->stopped_by_vpn_controller
|| p
->stop_timestamp
.tv_sec
|| p
->stop_timestamp
.tv_usec
) {
1893 plog(ASL_LEVEL_NOTICE
, "sweeping stopped session.\n");
1894 ike_session_cleanup(p
, ike_session_stopped_by_sleepwake
);
1898 if (!ike_session_has_established_ph1(p
) && !ike_session_has_established_ph2(p
)) {
1899 plog(ASL_LEVEL_NOTICE
, "session died while sleeping.\n");
1900 ike_session_cleanup(p
, ike_session_stopped_by_sleepwake
);
1903 if (p
->traffic_monitor
.sc_mon
) {
1905 if (sched_get_time(p
->traffic_monitor
.sc_mon
, &xtime
)) {
1906 if (xtime
<= swept_at
) {
1907 SCHED_KILL(p
->traffic_monitor
.sc_mon
);
1908 if (!p
->is_dying
&& p
->traffic_monitor
.interv_mon
) {
1909 p
->traffic_monitor
.sc_mon
= sched_new(p
->traffic_monitor
.interv_mon
,
1910 ike_session_traffic_cop
,
1916 if (p
->traffic_monitor
.sc_idle
) {
1918 if (sched_get_time(p
->traffic_monitor
.sc_idle
, &xtime
)) {
1919 if (xtime
<= swept_at
) {
1920 SCHED_KILL(p
->traffic_monitor
.sc_idle
);
1921 if (!p
->is_dying
&& p
->traffic_monitor
.interv_idle
) {
1922 p
->traffic_monitor
.sc_idle
= sched_new(p
->traffic_monitor
.interv_idle
,
1923 ike_session_cleanup_idle
,
1933 * this is called after racooon receives an assert command from the controller/pppd.
1934 * this is intended to make racoon prepare to rekey both SAs because a network event occurred.
1935 * in the event of a sleepwake, the assert could happen before or after 'ike_session_sweep_sleepwake'.
1938 ike_session_assert_session (ike_session_t
*session
)
1940 phase2_handle_t
*iph2
= NULL
;
1941 phase2_handle_t
*iph2_next
= NULL
;
1942 phase1_handle_t
*iph1
= NULL
;
1943 phase1_handle_t
*iph1_next
= NULL
;
1945 if (!session
|| session
->is_dying
) {
1946 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
1950 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase2s
1951 LIST_FOREACH_SAFE(iph2
, &session
->ph2tree
, ph2ofsession_chain
, iph2_next
) {
1952 if (!iph2
->is_dying
&& !FSM_STATE_IS_EXPIRED(iph2
->status
)) {
1953 SCHED_KILL(iph2
->sce
);
1956 // delete SAs (in the kernel)
1957 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
) && iph2
->approval
) {
1960 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1963 plog(ASL_LEVEL_NOTICE
,
1964 "Assert: Phase 2 %s deleted\n",
1965 sadbsecas2str(iph2
->src
, iph2
->dst
, iph2
->satype
, iph2
->spid
, ipsecdoi2pfkey_mode(pr
->encmode
)));
1967 pfkey_send_delete(lcconf
->sock_pfkey
,
1968 ipsecdoi2pfkey_proto(pr
->proto_id
),
1969 ipsecdoi2pfkey_mode(pr
->encmode
),
1970 iph2
->src
, iph2
->dst
, pr
->spi_p
);
1975 fsm_set_state(&iph2
->status
, IKEV1_STATE_PHASE2_EXPIRED
); // we want to delete SAs without telling the PEER
1976 iph2
->sce
= sched_new(3, ike_session_cleanup_ph2_stub
, iph2
);
1980 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase1s
1981 LIST_FOREACH_SAFE(iph1
, &session
->ph1tree
, ph1ofsession_chain
, iph1_next
) {
1982 if (!iph1
->is_dying
&& !FSM_STATE_IS_EXPIRED(iph1
->status
)) {
1983 SCHED_KILL(iph1
->sce
);
1984 SCHED_KILL(iph1
->sce_rekey
);
1988 plog(ASL_LEVEL_NOTICE
,
1989 "Assert: Phase 1 %s deleted\n",
1990 isakmp_pindex(&iph1
->index
, 0));
1992 ike_session_unbind_all_ph2_from_ph1(iph1
);
1994 fsm_set_state(&iph1
->status
, IKEV1_STATE_PHASE1_EXPIRED
); // we want to delete SAs without telling the PEER
1995 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
1996 iph1
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, iph1
);
1999 session
->is_asserted
= 1;
2005 ike_session_assert (struct sockaddr_storage
*local
,
2006 struct sockaddr_storage
*remote
)
2008 ike_session_t
*sess
;
2010 if (!local
|| !remote
) {
2011 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
2015 if ((sess
= ike_session_get_session(local
, remote
, FALSE
, NULL
))) {
2016 return(ike_session_assert_session(sess
));
2022 ike_session_ph2_retransmits (phase2_handle_t
*iph2
)
2024 int num_retransmits
;
2026 if (!iph2
->is_dying
&&
2029 iph2
->ph1
->sce_rekey
&& !sched_is_dead(iph2
->ph1
->sce_rekey
) &&
2030 iph2
->side
== INITIATOR
&&
2031 iph2
->parent_session
&&
2032 !iph2
->parent_session
->is_cisco_ipsec
&& /* not for Cisco */
2033 iph2
->parent_session
->is_client
) {
2034 num_retransmits
= iph2
->ph1
->rmconf
->retry_counter
- iph2
->retry_counter
;
2035 if (num_retransmits
== 3) {
2037 * phase2 negotiation is stalling on retransmits, inspite of a valid ph1.
2038 * one of the following is possible:
2039 * - (0) severe packet loss.
2040 * - (1) the peer is dead.
2041 * - (2) the peer is out of sync hence dropping this phase2 rekey (and perhaps responding with insecure
2042 * invalid-cookie notifications... but those are untrusted and so we can't rekey phase1 off that)
2043 * (2.1) the peer rebooted (or process restarted) and is now alive.
2044 * (2.2) the peer has deleted phase1 without notifying us (or the notification got dropped somehow).
2045 * (2.3) the peer has a policy/bug stopping this phase2 rekey
2047 * in all these cases, one sure way to know is to trigger a phase1 rekey early.
2049 plog(ASL_LEVEL_NOTICE
, "Many Phase 2 retransmits: try Phase 1 rekey and this Phase 2 to quit earlier.\n");
2050 isakmp_ph1rekeyexpire(iph2
->ph1
, TRUE
);
2051 iph2
->retry_counter
= 0;
2057 ike_session_ph1_retransmits (phase1_handle_t
*iph1
)
2059 int num_retransmits
;
2061 if (!iph1
->is_dying
&&
2064 FSM_STATE_IS_NEGOTIATING(iph1
->status
) &&
2065 iph1
->side
== INITIATOR
&&
2066 iph1
->parent_session
&&
2067 iph1
->parent_session
->is_client
&&
2068 !ike_session_has_other_negoing_ph1(iph1
->parent_session
, iph1
)) {
2069 num_retransmits
= iph1
->rmconf
->retry_counter
- iph1
->retry_counter
;
2070 if (num_retransmits
== 3) {
2071 plog(ASL_LEVEL_NOTICE
, "Many Phase 1 retransmits: try quit earlier.\n");
2072 iph1
->retry_counter
= 0;
2078 ike_session_bindph12(phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
2081 plog(ASL_LEVEL_ERR
, "Phase 2 already bound %s.\n", __FUNCTION__
);
2084 LIST_INSERT_HEAD(&iph1
->bound_ph2tree
, iph2
, ph1bind_chain
);
2088 ike_session_unbindph12(phase2_handle_t
*iph2
)
2090 if (iph2
->ph1
!= NULL
) {
2092 LIST_REMOVE(iph2
, ph1bind_chain
);
2097 ike_session_rebindph12(phase1_handle_t
*new_ph1
, phase2_handle_t
*iph2
)
2103 // reconcile the ph1-to-ph2 binding
2104 ike_session_unbindph12(iph2
);
2105 ike_session_bindph12(new_ph1
, iph2
);
2106 // recalculate ivm since ph1 binding has changed
2107 if (iph2
->ivm
!= NULL
) {
2108 oakley_delivm(iph2
->ivm
);
2109 if (FSM_STATE_IS_ESTABLISHED(new_ph1
->status
)) {
2110 iph2
->ivm
= oakley_newiv2(new_ph1
, iph2
->msgid
);
2111 plog(ASL_LEVEL_NOTICE
, "Phase 1-2 binding changed... recalculated ivm.\n");
2119 ike_session_unbind_all_ph2_from_ph1 (phase1_handle_t
*iph1
)
2121 phase2_handle_t
*p
= NULL
;
2122 phase2_handle_t
*next
= NULL
;
2124 LIST_FOREACH_SAFE(p
, &iph1
->bound_ph2tree
, ph1bind_chain
, next
) {
2125 ike_session_unbindph12(p
);
2130 ike_session_rebind_all_ph12_to_new_ph1 (phase1_handle_t
*old_iph1
,
2131 phase1_handle_t
*new_iph1
)
2133 phase2_handle_t
*p
= NULL
;
2134 phase2_handle_t
*next
= NULL
;
2136 if (old_iph1
== new_iph1
|| !old_iph1
|| !new_iph1
) {
2137 plog(ASL_LEVEL_ERR
, "invalid parameters in %s.\n", __FUNCTION__
);
2141 if (old_iph1
->parent_session
!= new_iph1
->parent_session
) {
2142 plog(ASL_LEVEL_ERR
, "Invalid parent sessions in %s.\n", __FUNCTION__
);
2146 LIST_FOREACH_SAFE(p
, &old_iph1
->bound_ph2tree
, ph1bind_chain
, next
) {
2147 if (p
->parent_session
!= new_iph1
->parent_session
) {
2148 plog(ASL_LEVEL_ERR
, "Mismatched parent session in ph1bind replacement.\n");
2150 if (p
->ph1
== new_iph1
) {
2151 plog(ASL_LEVEL_ERR
, "Same Phase 2 in ph1bind replacement in %s.\n",__FUNCTION__
);
2153 ike_session_rebindph12(new_iph1
, p
);