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
)
363 // exit early if we already detected cisco-ipsec
364 if (iph2
->parent_session
->is_cisco_ipsec
) {
368 if (iph2
->approval
) {
369 if (!ipsecdoi_any_transportmode(iph2
->approval
)) {
370 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
371 iph2
->parent_session
->is_cisco_ipsec
= 0;
372 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
373 iph2
->parent_session
->is_btmm_ipsec
= 1;
375 } else if (ipsecdoi_transportmode(iph2
->approval
)) {
376 iph2
->parent_session
->is_cisco_ipsec
= 0;
377 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
378 iph2
->parent_session
->is_btmm_ipsec
= 0;
381 } else if (iph2
->proposal
) {
382 if (!ipsecdoi_any_transportmode(iph2
->proposal
)) {
383 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
384 iph2
->parent_session
->is_cisco_ipsec
= 0;
385 iph2
->parent_session
->is_l2tpvpn_ipsec
= 0;
386 iph2
->parent_session
->is_btmm_ipsec
= 1;
388 } else if (ipsecdoi_transportmode(iph2
->proposal
)) {
389 iph2
->parent_session
->is_cisco_ipsec
= 0;
390 iph2
->parent_session
->is_l2tpvpn_ipsec
= 1;
391 iph2
->parent_session
->is_btmm_ipsec
= 0;
398 ike_session_cleanup_xauth_timeout (void *arg
)
400 ike_session_t
*session
= (ike_session_t
*)arg
;
402 SCHED_KILL(session
->sc_xauth
);
403 // if there are no more established ph2s, start a timer to teardown the session
404 if (!ike_session_has_established_ph2(session
)) {
405 ike_session_cleanup(session
, ike_session_stopped_by_xauth_timeout
);
407 session
->sc_xauth
= sched_new(300 /* 5 mins */,
408 ike_session_cleanup_xauth_timeout
,
414 ike_session_link_phase1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
417 if (!session
|| !iph1
) {
418 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
422 gettimeofday(&session
->start_timestamp
, NULL
);
424 if (iph1
->started_by_api
) {
425 session
->is_cisco_ipsec
= 1;
426 session
->is_l2tpvpn_ipsec
= 0;
427 session
->is_btmm_ipsec
= 0;
429 iph1
->parent_session
= session
;
430 LIST_INSERT_HEAD(&session
->ph1tree
, iph1
, ph1ofsession_chain
);
431 session
->ikev1_state
.active_ph1cnt
++;
432 if ((!session
->ikev1_state
.ph1cnt
&&
433 iph1
->side
== INITIATOR
) ||
434 iph1
->started_by_api
) {
435 // client initiates the first phase1 or, is started by controller api
436 session
->is_client
= 1;
438 if (session
->established
&&
439 session
->ikev1_state
.ph1cnt
&&
440 iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
443 session
->ikev1_state
.ph1cnt
++;
444 ike_session_init_traffic_cop_params(iph1
);
450 ike_session_link_phase2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
453 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
456 if (iph2
->parent_session
) {
457 plog(ASL_LEVEL_ERR
, "Phase 2 already linked to session %s.\n", __FUNCTION__
);
460 iph2
->parent_session
= session
;
461 LIST_INSERT_HEAD(&session
->ph2tree
, iph2
, ph2ofsession_chain
);
462 session
->ikev1_state
.active_ph2cnt
++;
463 if (!session
->ikev1_state
.ph2cnt
&&
464 iph2
->side
== INITIATOR
) {
465 // client initiates the first phase2
466 session
->is_client
= 1;
468 if (iph2
->phase2_type
== PHASE2_TYPE_SA
&&
469 session
->established
&&
470 session
->ikev1_state
.ph2cnt
&&
471 iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
474 session
->ikev1_state
.ph2cnt
++;
475 ike_session_update_mode(iph2
);
481 ike_session_link_ph2_to_ph1 (phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
483 struct sockaddr_storage
*local
;
484 struct sockaddr_storage
*remote
;
488 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
492 plog(ASL_LEVEL_ERR
, "Phase 2 already linked %s.\n", __FUNCTION__
);
493 if (iph2
->ph1
== iph1
)
496 return -1; // This shouldn't happen
502 if (iph2
->parent_session
== NULL
)
503 if ((error
= ike_session_link_phase2(iph1
->parent_session
, iph2
)))
506 ike_session_bindph12(iph1
, iph2
);
511 ike_session_unlink_phase1 (phase1_handle_t
*iph1
)
513 ike_session_t
*session
;
515 if (!iph1
|| !iph1
->parent_session
) {
516 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
520 if (iph1
->version
== ISAKMP_VERSION_NUMBER_IKEV1
) {
521 if (LIST_FIRST(&iph1
->bound_ph2tree
)) {
522 // reparent any phase2 that may be hanging on to this phase1
523 ike_session_update_ph1_ph2tree(iph1
);
527 sched_scrub_param(iph1
);
528 session
= iph1
->parent_session
;
529 LIST_REMOVE(iph1
, ph1ofsession_chain
);
530 iph1
->parent_session
= NULL
;
531 session
->ikev1_state
.active_ph1cnt
--;
532 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
533 session
->is_dying
= 1;
534 free_ike_session(session
);
536 ike_session_delph1(iph1
);
541 ike_session_unlink_phase2 (phase2_handle_t
*iph2
)
543 ike_session_t
*session
;
545 if (!iph2
|| !iph2
->parent_session
) {
546 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
549 sched_scrub_param(iph2
);
550 ike_session_unbindph12(iph2
);
552 LIST_REMOVE(iph2
, ph2ofsession_chain
);
553 session
= iph2
->parent_session
;
554 iph2
->parent_session
= NULL
;
555 session
->ikev1_state
.active_ph2cnt
--;
556 if (session
->ikev1_state
.active_ph1cnt
== 0 && session
->ikev1_state
.active_ph2cnt
== 0) {
557 session
->is_dying
= 1;
558 free_ike_session(session
);
560 ike_session_delph2(iph2
);
566 ike_session_update_ph1_ph2tree (phase1_handle_t
*iph1
)
568 phase1_handle_t
*new_iph1
= NULL
;
571 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
575 if (iph1
->parent_session
) {
576 new_iph1
= ike_session_get_established_ph1(iph1
->parent_session
);
579 plog(ASL_LEVEL_DEBUG
, "no ph1bind replacement found. NULL ph1.\n");
580 ike_session_unbind_all_ph2_from_ph1(iph1
);
581 } else if (iph1
== new_iph1
) {
582 plog(ASL_LEVEL_DEBUG
, "no ph1bind replacement found. same ph1.\n");
583 ike_session_unbind_all_ph2_from_ph1(iph1
);
585 ike_session_rebind_all_ph12_to_new_ph1(iph1
, new_iph1
);
588 plog(ASL_LEVEL_DEBUG
, "invalid parent session in %s.\n", __FUNCTION__
);
594 ike_session_update_ph2_ph1bind (phase2_handle_t
*iph2
)
596 phase1_handle_t
*iph1
;
598 if (!iph2
|| iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
599 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
603 iph1
= ike_session_get_established_ph1(iph2
->parent_session
);
604 if (iph1
&& iph2
->ph1
&& iph1
!= iph2
->ph1
) {
605 ike_session_rebindph12(iph1
, iph2
);
606 } else if (iph1
&& !iph2
->ph1
) {
607 ike_session_bindph12(iph1
, iph2
);
614 ike_session_get_established_or_negoing_ph1 (ike_session_t
*session
)
616 phase1_handle_t
*p
, *iph1
= NULL
;
619 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
623 // look for the most mature ph1 under the session
624 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
625 if (!p
->is_dying
&& (FSM_STATE_IS_ESTABLISHED(p
->status
) || FSM_STATE_IS_NEGOTIATING(p
->status
))) {
626 if (!iph1
|| p
->status
> iph1
->status
) {
628 } else if (iph1
&& p
->status
== iph1
->status
) {
629 // TODO: pick better one based on farthest rekey/expiry remaining
638 ike_session_get_established_ph1 (ike_session_t
*session
)
643 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
647 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
648 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
658 ike_session_has_other_established_ph1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
666 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
667 if (iph1
!= p
&& !p
->is_dying
) {
668 if (FSM_STATE_IS_ESTABLISHED(p
->status
) && p
->sce_rekey
) {
678 ike_session_has_other_negoing_ph1 (ike_session_t
*session
, phase1_handle_t
*iph1
)
683 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
687 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
688 if (iph1
!= p
&& !p
->is_dying
) {
689 if (FSM_STATE_IS_NEGOTIATING(p
->status
)) {
699 ike_session_has_other_established_ph2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
704 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
708 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
709 if (p
->phase2_type
== PHASE2_TYPE_SA
&& iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
710 if (FSM_STATE_IS_ESTABLISHED(p
->status
)) {
720 ike_session_has_other_negoing_ph2 (ike_session_t
*session
, phase2_handle_t
*iph2
)
725 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
729 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
730 plog(ASL_LEVEL_DEBUG
, "%s: ph2 sub spid %d, db spid %d\n", __FUNCTION__
, iph2
->spid
, p
->spid
);
731 if (p
->phase2_type
== PHASE2_TYPE_SA
&& iph2
!= p
&& !p
->is_dying
&& iph2
->spid
== p
->spid
) {
732 if (FSM_STATE_IS_NEGOTIATING(p
->status
)) {
743 ike_session_ikev1_float_ports (phase1_handle_t
*iph1
)
745 struct sockaddr_storage
*local
, *remote
;
748 if (iph1
->parent_session
) {
749 local
= &iph1
->parent_session
->session_id
.local
;
750 remote
= &iph1
->parent_session
->session_id
.remote
;
752 set_port(local
, extract_port(iph1
->local
));
753 set_port(remote
, extract_port(iph1
->remote
));
754 iph1
->parent_session
->ports_floated
= 1;
756 LIST_FOREACH(p
, &iph1
->parent_session
->ph2tree
, ph2ofsession_chain
) {
761 set_port(local
, extract_port(iph1
->local
));
762 set_port(remote
, extract_port(iph1
->remote
));
765 plog(ASL_LEVEL_DEBUG
, "invalid parent session in %s.\n", __FUNCTION__
);
770 ike_session_traffic_cop (void *arg
)
772 ike_session_t
*session
= (__typeof__(session
))arg
;
775 (session
->established
&& !session
->stopped_by_vpn_controller
&& !session
->stop_timestamp
.tv_sec
&& !session
->stop_timestamp
.tv_usec
)) {
776 SCHED_KILL(session
->traffic_monitor
.sc_mon
);
777 /* get traffic query from kernel */
778 if (pk_sendget_inbound_sastats(session
) < 0) {
780 plog(ASL_LEVEL_DEBUG
, "pk_sendget_inbound_sastats failed in %s.\n", __FUNCTION__
);
782 if (pk_sendget_outbound_sastats(session
) < 0) {
784 plog(ASL_LEVEL_DEBUG
, "pk_sendget_outbound_sastats failed in %s.\n", __FUNCTION__
);
786 session
->traffic_monitor
.sc_mon
= sched_new(session
->traffic_monitor
.interv_mon
,
787 ike_session_traffic_cop
,
791 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
796 ike_session_cleanup_idle (void *arg
)
798 ike_session_cleanup((ike_session_t
*)arg
, ike_session_stopped_by_idle
);
802 ike_session_monitor_idle (ike_session_t
*session
)
807 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_INBOUND
||
808 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
809 if (session
->peer_sent_data_sc_idle
) {
810 plog(ASL_LEVEL_DEBUG
, "%s: restart idle-timeout because peer sent data. monitoring dir %d.\n",
811 __FUNCTION__
, session
->traffic_monitor
.dir_idle
);
812 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
813 if (session
->traffic_monitor
.interv_idle
) {
814 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
815 ike_session_cleanup_idle
,
818 session
->peer_sent_data_sc_idle
= 0;
819 session
->i_sent_data_sc_idle
= 0;
823 if (session
->traffic_monitor
.dir_idle
== IPSEC_DIR_OUTBOUND
||
824 session
->traffic_monitor
.dir_idle
== IPSEC_DIR_ANY
) {
825 if (session
->i_sent_data_sc_idle
) {
826 plog(ASL_LEVEL_DEBUG
, "%s: restart idle-timeout because i sent data. monitoring dir %d.\n",
827 __FUNCTION__
, session
->traffic_monitor
.dir_idle
);
828 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
829 if (session
->traffic_monitor
.interv_idle
) {
830 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
831 ike_session_cleanup_idle
,
834 session
->peer_sent_data_sc_idle
= 0;
835 session
->i_sent_data_sc_idle
= 0;
842 ike_session_start_traffic_mon (ike_session_t
*session
)
844 if (session
->traffic_monitor
.interv_mon
) {
845 session
->traffic_monitor
.sc_mon
= sched_new(session
->traffic_monitor
.interv_mon
,
846 ike_session_traffic_cop
,
849 if (session
->traffic_monitor
.interv_idle
) {
850 session
->traffic_monitor
.sc_idle
= sched_new(session
->traffic_monitor
.interv_idle
,
851 ike_session_cleanup_idle
,
857 ike_session_ph2_established (phase2_handle_t
*iph2
)
859 if (!iph2
->parent_session
|| iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
860 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
863 SCHED_KILL(iph2
->parent_session
->sc_xauth
);
864 if (!iph2
->parent_session
->established
) {
865 gettimeofday(&iph2
->parent_session
->estab_timestamp
, NULL
);
866 iph2
->parent_session
->established
= 1;
867 IPSECSESSIONTRACERESTABLISHED(iph2
->parent_session
);
868 ike_session_start_traffic_mon(iph2
->parent_session
);
869 } else if (iph2
->parent_session
->is_asserted
) {
870 ike_session_start_traffic_mon(iph2
->parent_session
);
872 iph2
->parent_session
->is_asserted
= 0;
873 // nothing happening to this session
874 iph2
->parent_session
->term_reason
= NULL
;
876 ike_session_update_mode(iph2
);
877 if (iph2
->version
== ISAKMP_VERSION_NUMBER_IKEV1
)
878 ike_session_unbindph12(iph2
);
880 #ifdef ENABLE_VPNCONTROL_PORT
881 vpncontrol_notify_peer_resp_ph2(1, iph2
);
882 #endif /* ENABLE_VPNCONTROL_PORT */
883 plog(ASL_LEVEL_DEBUG
, "%s: ph2 established, spid %d\n", __FUNCTION__
, iph2
->spid
);
887 ike_session_cleanup_ph1 (phase1_handle_t
*iph1
)
889 if (FSM_STATE_IS_EXPIRED(iph1
->status
)) {
890 // since this got here via ike_session_cleanup_other_established_ph1s, assumes LIST_FIRST(&iph1->ph2tree) == NULL
891 iph1
->sce
= sched_new(1, isakmp_ph1delete_stub
, iph1
);
895 /* send delete information */
896 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
897 isakmp_info_send_d1(iph1
);
900 isakmp_ph1expire(iph1
);
904 ike_session_cleanup_ph1_stub (void *p
)
907 ike_session_cleanup_ph1((phase1_handle_t
*)p
);
911 ike_session_replace_other_ph1 (phase1_handle_t
*new_iph1
,
912 phase1_handle_t
*old_iph1
)
914 char *local
, *remote
, *index
;
915 ike_session_t
*session
= NULL
;
918 session
= new_iph1
->parent_session
;
920 if (!session
|| !new_iph1
|| !old_iph1
|| session
!= old_iph1
->parent_session
|| new_iph1
== old_iph1
) {
921 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
926 * if we are responder, then we should wait until the server sends a delete notification.
928 if (session
->is_client
&&
929 new_iph1
->side
== RESPONDER
) {
933 SCHED_KILL(old_iph1
->sce
);
934 SCHED_KILL(old_iph1
->sce_rekey
);
935 old_iph1
->is_dying
= 1;
938 local
= racoon_strdup(saddr2str((struct sockaddr
*)old_iph1
->local
));
939 remote
= racoon_strdup(saddr2str((struct sockaddr
*)old_iph1
->remote
));
940 index
= racoon_strdup(isakmp_pindex(&old_iph1
->index
, 0));
942 STRDUP_FATAL(remote
);
944 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));
949 // first rebind the children ph2s of this dying ph1 to the new ph1.
950 ike_session_rebind_all_ph12_to_new_ph1 (old_iph1
, new_iph1
);
952 if (old_iph1
->side
== INITIATOR
) {
953 /* everyone deletes old outbound SA */
954 old_iph1
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, old_iph1
);
956 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
957 old_iph1
->sce
= sched_new(7, ike_session_cleanup_ph1_stub
, old_iph1
);
962 ike_session_cleanup_other_established_ph1s (ike_session_t
*session
,
963 phase1_handle_t
*new_iph1
)
965 phase1_handle_t
*p
, *next
;
966 char *local
, *remote
;
968 if (!session
|| !new_iph1
|| session
!= new_iph1
->parent_session
) {
969 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
974 * if we are responder, then we should wait until the server sends a delete notification.
976 if (session
->is_client
&&
977 new_iph1
->side
== RESPONDER
) {
981 LIST_FOREACH_SAFE(p
, &session
->ph1tree
, ph1ofsession_chain
, next
) {
983 * TODO: currently, most recently established SA wins. Need to revisit to see if
984 * alternative selections is better (e.g. largest p->index stays).
986 if (p
!= new_iph1
&& !p
->is_dying
) {
988 SCHED_KILL(p
->sce_rekey
);
992 local
= racoon_strdup(saddr2str((struct sockaddr
*)p
->local
));
993 remote
= racoon_strdup(saddr2str((struct sockaddr
*)p
->remote
));
995 STRDUP_FATAL(remote
);
996 plog(ASL_LEVEL_DEBUG
,
997 "ISAKMP-SA needs to be deleted %s-%s spi:%s\n",
998 local
, remote
, isakmp_pindex(&p
->index
, 0));
1000 racoon_free(remote
);
1002 // first rebind the children ph2s of this dying ph1 to the new ph1.
1003 ike_session_rebind_all_ph12_to_new_ph1 (p
, new_iph1
);
1005 if (p
->side
== INITIATOR
) {
1006 /* everyone deletes old outbound SA */
1007 p
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, p
);
1009 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
1010 p
->sce
= sched_new(7, ike_session_cleanup_ph1_stub
, p
);
1017 ike_session_cleanup_ph2 (phase2_handle_t
*iph2
)
1019 if (iph2
->phase2_type
!= PHASE2_TYPE_SA
)
1021 if (FSM_STATE_IS_EXPIRED(iph2
->status
)) {
1025 SCHED_KILL(iph2
->sce
);
1028 "about to cleanup ph2: status %d, seq %d dying %d\n",
1029 iph2
->status
, iph2
->seq
, iph2
->is_dying
);
1031 /* send delete information */
1032 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
)) {
1033 isakmp_info_send_d2(iph2
);
1035 // delete outgoing SAs
1036 if (iph2
->approval
) {
1039 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1041 pfkey_send_delete(lcconf
->sock_pfkey
,
1042 ipsecdoi2pfkey_proto(pr
->proto_id
),
1044 iph2
->src
, iph2
->dst
, pr
->spi_p
/* pr->reqid_out */);
1051 ike_session_unlink_phase2(iph2
);
1055 ike_session_cleanup_ph2_stub (void *p
)
1058 ike_session_cleanup_ph2((phase2_handle_t
*)p
);
1062 ike_session_cleanup_other_established_ph2s (ike_session_t
*session
,
1063 phase2_handle_t
*new_iph2
)
1065 phase2_handle_t
*p
, *next
;
1067 if (!session
|| !new_iph2
|| session
!= new_iph2
->parent_session
|| new_iph2
->phase2_type
!= PHASE2_TYPE_SA
) {
1068 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1073 * if we are responder, then we should wait until the server sends a delete notification.
1075 if (session
->is_client
&& new_iph2
->side
== RESPONDER
) {
1079 LIST_FOREACH_SAFE(p
, &session
->ph2tree
, ph2ofsession_chain
, next
) {
1081 * TODO: currently, most recently established SA wins. Need to revisit to see if
1082 * alternative selections is better.
1084 if (p
!= new_iph2
&& p
->spid
== new_iph2
->spid
&& !p
->is_dying
) {
1089 plog(ASL_LEVEL_DEBUG
,
1090 "IPsec-SA needs to be deleted: %s\n",
1091 sadbsecas2str(p
->src
, p
->dst
,
1092 p
->satype
, p
->spid
, 0));
1094 if (p
->side
== INITIATOR
) {
1095 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1096 p
->sce
= sched_new(3, ike_session_cleanup_ph2_stub
, p
);
1098 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1099 p
->sce
= sched_new(5, ike_session_cleanup_ph2_stub
, p
);
1106 ike_session_stopped_by_controller (ike_session_t
*session
,
1110 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1113 if (session
->stop_timestamp
.tv_sec
||
1114 session
->stop_timestamp
.tv_usec
) {
1115 plog(ASL_LEVEL_DEBUG
, "already stopped %s.\n", __FUNCTION__
);
1118 session
->stopped_by_vpn_controller
= 1;
1119 gettimeofday(&session
->stop_timestamp
, NULL
);
1120 if (!session
->term_reason
) {
1121 session
->term_reason
= (__typeof__(session
->term_reason
))reason
;
1126 ike_sessions_stopped_by_controller (struct sockaddr_storage
*remote
,
1130 ike_session_t
*p
= NULL
;
1131 ike_session_t
*next_session
= NULL
;
1134 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1138 LIST_FOREACH_SAFE(p
, &ike_session_tree
, chain
, next_session
) {
1139 if ((withport
&& cmpsaddrstrict(&p
->session_id
.remote
, remote
) == 0) ||
1140 (!withport
&& cmpsaddrwop(&p
->session_id
.remote
, remote
) == 0)) {
1141 ike_session_stopped_by_controller(p
, reason
);
1147 ike_session_purge_ph2s_by_ph1 (phase1_handle_t
*iph1
)
1149 phase2_handle_t
*p
, *next
;
1151 if (!iph1
|| !iph1
->parent_session
) {
1152 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1156 LIST_FOREACH_SAFE(p
, &iph1
->parent_session
->ph2tree
, ph2ofsession_chain
, next
) {
1164 plog(ASL_LEVEL_DEBUG
,
1165 "IPsec-SA needs to be purged: %s\n",
1166 sadbsecas2str(p
->src
, p
->dst
,
1167 p
->satype
, p
->spid
, 0));
1169 ike_session_cleanup_ph2(p
);
1174 ike_session_update_ph2_ports (phase2_handle_t
*iph2
)
1176 struct sockaddr_storage
*local
;
1177 struct sockaddr_storage
*remote
;
1179 if (iph2
->parent_session
) {
1180 local
= &iph2
->parent_session
->session_id
.local
;
1181 remote
= &iph2
->parent_session
->session_id
.remote
;
1183 set_port(iph2
->src
, extract_port(local
));
1184 set_port(iph2
->dst
, extract_port(remote
));
1186 plog(ASL_LEVEL_DEBUG
, "invalid parent session in %s.\n", __FUNCTION__
);
1191 ike_session_get_sas_for_stats (ike_session_t
*session
,
1194 struct sastat
*stats
,
1195 u_int32_t max_stats
)
1198 phase2_handle_t
*iph2
;
1200 if (!session
|| !seq
|| !stats
|| !max_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1201 plog(ASL_LEVEL_DEBUG
, "invalid args in %s.\n", __FUNCTION__
);
1206 LIST_FOREACH(iph2
, &session
->ph2tree
, ph2ofsession_chain
) {
1207 if (iph2
->approval
) {
1210 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1211 if (pr
->ok
&& pr
->proto_id
== IPSECDOI_PROTO_IPSEC_ESP
) {
1215 if (dir
== IPSEC_DIR_INBOUND
) {
1216 stats
[found
].spi
= pr
->spi
;
1218 stats
[found
].spi
= pr
->spi_p
;
1220 if (++found
== max_stats
) {
1231 ike_session_update_traffic_idle_status (ike_session_t
*session
,
1233 struct sastat
*new_stats
,
1234 u_int32_t max_stats
)
1236 int i
, j
, found
= 0, idle
= 1;
1238 if (!session
|| !new_stats
|| (dir
!= IPSEC_DIR_INBOUND
&& dir
!= IPSEC_DIR_OUTBOUND
)) {
1239 plog(ASL_LEVEL_DEBUG
, "invalid args in %s.\n", __FUNCTION__
);
1243 if (!session
->established
|| session
->stopped_by_vpn_controller
|| session
->stop_timestamp
.tv_sec
|| session
->stop_timestamp
.tv_usec
) {
1244 plog(ASL_LEVEL_DEBUG
, "dropping update on invalid session in %s.\n", __FUNCTION__
);
1248 for (i
= 0; i
< max_stats
; i
++) {
1249 if (dir
== IPSEC_DIR_INBOUND
) {
1250 for (j
= 0; j
< session
->traffic_monitor
.num_in_last_poll
; j
++) {
1251 if (new_stats
[i
].spi
!= session
->traffic_monitor
.in_last_poll
[j
].spi
) {
1255 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.in_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1260 for (j
= 0; j
< session
->traffic_monitor
.num_out_last_poll
; j
++) {
1261 if (new_stats
[i
].spi
!= session
->traffic_monitor
.out_last_poll
[j
].spi
) {
1265 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
!= session
->traffic_monitor
.out_last_poll
[j
].lft_c
.sadb_lifetime_bytes
) {
1270 // new SA.... check for any activity
1272 if (new_stats
[i
].lft_c
.sadb_lifetime_bytes
) {
1273 plog(ASL_LEVEL_DEBUG
, "new SA: dir %d....\n", dir
);
1278 if (dir
== IPSEC_DIR_INBOUND
) {
1279 // overwrite old stats
1280 bzero(session
->traffic_monitor
.in_last_poll
, sizeof(session
->traffic_monitor
.in_last_poll
));
1281 bcopy(new_stats
, session
->traffic_monitor
.in_last_poll
, (max_stats
* sizeof(*new_stats
)));
1282 session
->traffic_monitor
.num_in_last_poll
= max_stats
;
1284 //plog(ASL_LEVEL_DEBUG, "peer sent data....\n");
1285 session
->peer_sent_data_sc_dpd
= 1;
1286 session
->peer_sent_data_sc_idle
= 1;
1289 // overwrite old stats
1290 bzero(session
->traffic_monitor
.out_last_poll
, sizeof(session
->traffic_monitor
.out_last_poll
));
1291 bcopy(new_stats
, session
->traffic_monitor
.out_last_poll
, (max_stats
* sizeof(*new_stats
)));
1292 session
->traffic_monitor
.num_out_last_poll
= max_stats
;
1294 //plog(ASL_LEVEL_DEBUG, "i sent data....\n");
1295 session
->i_sent_data_sc_dpd
= 1;
1296 session
->i_sent_data_sc_idle
= 1;
1300 session
->last_time_data_sc_detected
= time(NULL
);
1302 ike_session_monitor_idle(session
);
1306 ike_session_cleanup (ike_session_t
*session
,
1309 phase2_handle_t
*iph2
= NULL
;
1310 phase2_handle_t
*next_iph2
= NULL
;
1311 phase1_handle_t
*iph1
= NULL
;
1312 phase1_handle_t
*next_iph1
= NULL
;
1317 session
->is_dying
= 1;
1318 ike_session_stopped_by_controller(session
, reason
);
1320 SCHED_KILL(session
->traffic_monitor
.sc_idle
);
1321 // do ph2's first... we need the ph1s for notifications
1322 LIST_FOREACH_SAFE(iph2
, &session
->ph2tree
, ph2ofsession_chain
, next_iph2
) {
1323 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
)) {
1324 isakmp_info_send_d2(iph2
);
1326 isakmp_ph2expire(iph2
); // iph2 will go down 1 second later.
1329 // do the ph1s last.
1330 LIST_FOREACH_SAFE(iph1
, &session
->ph1tree
, ph1ofsession_chain
, next_iph1
) {
1331 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
1332 isakmp_info_send_d1(iph1
);
1334 isakmp_ph1expire(iph1
);
1337 // send ipsecManager a notification
1338 if (session
->is_cisco_ipsec
&& reason
&& reason
!= ike_session_stopped_by_vpn_disconnect
1339 && reason
!= ike_session_stopped_by_controller_comm_lost
) {
1341 if ((&session
->session_id
.remote
)->ss_family
== AF_INET
) {
1342 address
= ((struct sockaddr_in
*)&session
->session_id
.remote
)->sin_addr
.s_addr
;
1347 if (reason
== ike_session_stopped_by_idle
) {
1348 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_IDLE_TIMEOUT
, FROM_LOCAL
, address
, 0, NULL
);
1350 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_INTERNAL_ERROR
, FROM_LOCAL
, address
, 0, NULL
);
1356 ike_session_has_negoing_ph1 (ike_session_t
*session
)
1361 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1365 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
1366 if (!p
->is_dying
&& FSM_STATE_IS_NEGOTIATING(p
->status
)) {
1375 ike_session_has_established_ph1 (ike_session_t
*session
)
1380 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1384 LIST_FOREACH(p
, &session
->ph1tree
, ph1ofsession_chain
) {
1385 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
1394 ike_session_has_negoing_ph2 (ike_session_t
*session
)
1399 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1403 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
1404 if (!p
->is_dying
&& FSM_STATE_IS_NEGOTIATING(p
->status
)) {
1413 ike_session_has_established_ph2 (ike_session_t
*session
)
1418 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1422 LIST_FOREACH(p
, &session
->ph2tree
, ph2ofsession_chain
) {
1423 if (!p
->is_dying
&& FSM_STATE_IS_ESTABLISHED(p
->status
)) {
1432 ike_session_cleanup_ph1s_by_ph2 (phase2_handle_t
*iph2
)
1434 phase1_handle_t
*iph1
= NULL
;
1435 phase1_handle_t
*next_iph1
= NULL
;
1437 if (!iph2
|| !iph2
->parent_session
) {
1438 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1442 // phase1 is no longer useful
1443 LIST_FOREACH_SAFE(iph1
, &iph2
->parent_session
->ph1tree
, ph1ofsession_chain
, next_iph1
) {
1444 if (FSM_STATE_IS_ESTABLISHED(iph1
->status
)) {
1445 isakmp_info_send_d1(iph1
);
1447 isakmp_ph1expire(iph1
);
1452 ike_session_is_client_ph2_rekey (phase2_handle_t
*iph2
)
1454 if (iph2
->parent_session
&&
1455 iph2
->parent_session
->is_client
&&
1457 iph2
->parent_session
->is_cisco_ipsec
) {
1464 ike_session_is_client_ph1_rekey (phase1_handle_t
*iph1
)
1466 if (iph1
->parent_session
&&
1467 iph1
->parent_session
->is_client
&&
1469 iph1
->parent_session
->is_cisco_ipsec
) {
1476 ike_session_is_client_ph1 (phase1_handle_t
*iph1
)
1478 if (iph1
->parent_session
&&
1479 iph1
->parent_session
->is_client
) {
1486 ike_session_is_client_ph2 (phase2_handle_t
*iph2
)
1488 if (iph2
->parent_session
&&
1489 iph2
->parent_session
->is_client
) {
1496 ike_session_start_xauth_timer (phase1_handle_t
*iph1
)
1498 // if there are no more established ph2s, start a timer to teardown the session
1499 if (iph1
->parent_session
&&
1500 iph1
->parent_session
->is_client
&&
1501 iph1
->parent_session
->is_cisco_ipsec
&&
1502 !iph1
->parent_session
->sc_xauth
) {
1503 iph1
->parent_session
->sc_xauth
= sched_new(300 /* 5 mins */,
1504 ike_session_cleanup_xauth_timeout
,
1505 iph1
->parent_session
);
1510 ike_session_stop_xauth_timer (phase1_handle_t
*iph1
)
1512 if (iph1
->parent_session
) {
1513 SCHED_KILL(iph1
->parent_session
->sc_xauth
);
1518 ike_session_is_id_ipany (vchar_t
*ext_id
)
1521 u_int8_t type
; /* ID Type */
1522 u_int8_t proto_id
; /* Protocol ID */
1523 u_int16_t port
; /* Port */
1524 u_int32_t addr
; /* IPv4 address */
1528 /* ignore protocol and port */
1529 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1530 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1531 id_ptr
->addr
== 0) {
1533 } else if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR_SUBNET
&&
1534 id_ptr
->mask
== 0 &&
1535 id_ptr
->addr
== 0) {
1538 plog(ASL_LEVEL_DEBUG
, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
1539 __FUNCTION__
, id_ptr
->type
, id_ptr
->addr
, id_ptr
->mask
);
1544 ike_session_is_id_portany (vchar_t
*ext_id
)
1547 u_int8_t type
; /* ID Type */
1548 u_int8_t proto_id
; /* Protocol ID */
1549 u_int16_t port
; /* Port */
1550 u_int32_t addr
; /* IPv4 address */
1555 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1556 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
&&
1557 id_ptr
->port
== 0) {
1560 plog(ASL_LEVEL_DEBUG
, "not portany_ids in %s: type %d, port %x.\n",
1561 __FUNCTION__
, id_ptr
->type
, id_ptr
->port
);
1566 ike_session_set_id_portany (vchar_t
*ext_id
)
1569 u_int8_t type
; /* ID Type */
1570 u_int8_t proto_id
; /* Protocol ID */
1571 u_int16_t port
; /* Port */
1572 u_int32_t addr
; /* IPv4 address */
1577 id_ptr
= ALIGNED_CAST(struct id
*)ext_id
->v
;
1578 if (id_ptr
->type
== IPSECDOI_ID_IPV4_ADDR
) {
1585 ike_session_cmp_ph2_ids_ipany (vchar_t
*ext_id
,
1588 if (ike_session_is_id_ipany(ext_id
) &&
1589 ike_session_is_id_ipany(ext_id_p
)) {
1596 * ipsec rekeys for l2tp-over-ipsec fail particularly when client is behind nat because the client's configs and policies don't
1597 * match the server's view of the client's address and port.
1598 * servers behave differently when using this address-port info to generate ids during phase2 rekeys, so try to match the incoming id to
1599 * a variety of info saved in the older phase2.
1602 ike_session_cmp_ph2_ids (phase2_handle_t
*iph2
,
1603 phase2_handle_t
*older_ph2
)
1605 vchar_t
*portany_id
= NULL
;
1606 vchar_t
*portany_id_p
= NULL
;
1608 if (iph2
->id
&& older_ph2
->id
&&
1609 iph2
->id
->l
== older_ph2
->id
->l
&&
1610 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1611 iph2
->id_p
&& older_ph2
->id_p
&&
1612 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1613 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1616 if (iph2
->ext_nat_id
&& older_ph2
->ext_nat_id
&&
1617 iph2
->ext_nat_id
->l
== older_ph2
->ext_nat_id
->l
&&
1618 memcmp(iph2
->ext_nat_id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->ext_nat_id
->l
) == 0 &&
1619 iph2
->ext_nat_id_p
&& older_ph2
->ext_nat_id_p
&&
1620 iph2
->ext_nat_id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1621 memcmp(iph2
->ext_nat_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->ext_nat_id_p
->l
) == 0) {
1624 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1625 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1626 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1627 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1628 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1629 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1632 if (iph2
->id
&& older_ph2
->ext_nat_id
&&
1633 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1634 memcmp(iph2
->id
->v
, older_ph2
->ext_nat_id
->v
, iph2
->id
->l
) == 0 &&
1635 iph2
->id_p
&& older_ph2
->id_p
&&
1636 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1637 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1640 if (iph2
->id
&& older_ph2
->id
&&
1641 iph2
->id
->l
== older_ph2
->id
->l
&&
1642 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1643 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1644 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1645 memcmp(iph2
->id_p
->v
, older_ph2
->ext_nat_id_p
->v
, iph2
->id_p
->l
) == 0) {
1649 /* check if the external id has a wildcard port and compare ids accordingly */
1650 if ((older_ph2
->ext_nat_id
&& ike_session_is_id_portany(older_ph2
->ext_nat_id
)) ||
1651 (older_ph2
->ext_nat_id_p
&& ike_session_is_id_portany(older_ph2
->ext_nat_id_p
))) {
1652 // try ignoring ports in iph2->id and iph2->id
1653 if (iph2
->id
&& (portany_id
= vdup(iph2
->id
))) {
1654 ike_session_set_id_portany(portany_id
);
1656 if (iph2
->id_p
&& (portany_id_p
= vdup(iph2
->id_p
))) {
1657 ike_session_set_id_portany(portany_id_p
);
1659 if (portany_id
&& older_ph2
->ext_nat_id
&&
1660 portany_id
->l
== older_ph2
->ext_nat_id
->l
&&
1661 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1662 portany_id_p
&& older_ph2
->ext_nat_id_p
&&
1663 portany_id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1664 memcmp(portany_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, portany_id_p
->l
) == 0) {
1669 vfree(portany_id_p
);
1673 if (portany_id
&& iph2
->id
&& older_ph2
->ext_nat_id
&&
1674 iph2
->id
->l
== older_ph2
->ext_nat_id
->l
&&
1675 memcmp(portany_id
->v
, older_ph2
->ext_nat_id
->v
, portany_id
->l
) == 0 &&
1676 iph2
->id_p
&& older_ph2
->id_p
&&
1677 iph2
->id_p
->l
== older_ph2
->id_p
->l
&&
1678 memcmp(iph2
->id_p
->v
, older_ph2
->id_p
->v
, iph2
->id_p
->l
) == 0) {
1683 vfree(portany_id_p
);
1687 if (portany_id_p
&& iph2
->id
&& older_ph2
->id
&&
1688 iph2
->id
->l
== older_ph2
->id
->l
&&
1689 memcmp(iph2
->id
->v
, older_ph2
->id
->v
, iph2
->id
->l
) == 0 &&
1690 iph2
->id_p
&& older_ph2
->ext_nat_id_p
&&
1691 iph2
->id_p
->l
== older_ph2
->ext_nat_id_p
->l
&&
1692 memcmp(portany_id_p
->v
, older_ph2
->ext_nat_id_p
->v
, portany_id_p
->l
) == 0) {
1697 vfree(portany_id_p
);
1705 vfree(portany_id_p
);
1712 ike_session_get_sainfo_r (phase2_handle_t
*iph2
)
1714 if (iph2
->parent_session
&&
1715 iph2
->parent_session
->is_client
&&
1716 iph2
->id
&& iph2
->id_p
) {
1718 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1719 plog(ASL_LEVEL_DEBUG
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1721 LIST_FOREACH(p
, &iph2
->parent_session
->ph2tree
, ph2ofsession_chain
) {
1722 if (iph2
!= p
&& !p
->is_dying
&& FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p
->status
) && p
->sainfo
) {
1723 plog(ASL_LEVEL_DEBUG
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1725 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1726 plog(ASL_LEVEL_DEBUG
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1727 iph2
->sainfo
= p
->sainfo
;
1729 retain_sainfo(iph2
->sainfo
);
1731 iph2
->spid
= p
->spid
;
1733 plog(ASL_LEVEL_DEBUG
, "%s: pre-assigned spid %d.\n", __FUNCTION__
, iph2
->spid
);
1735 if (p
->ext_nat_id
) {
1736 if (iph2
->ext_nat_id
) {
1737 vfree(iph2
->ext_nat_id
);
1739 iph2
->ext_nat_id
= vdup(p
->ext_nat_id
);
1741 if (p
->ext_nat_id_p
) {
1742 if (iph2
->ext_nat_id_p
) {
1743 vfree(iph2
->ext_nat_id_p
);
1745 iph2
->ext_nat_id_p
= vdup(p
->ext_nat_id_p
);
1756 ike_session_get_proposal_r (phase2_handle_t
*iph2
)
1758 if (iph2
->parent_session
&&
1759 iph2
->parent_session
->is_client
&&
1760 iph2
->id
&& iph2
->id_p
) {
1762 int ipany_ids
= ike_session_cmp_ph2_ids_ipany(iph2
->id
, iph2
->id_p
);
1763 plog(ASL_LEVEL_DEBUG
, "ipany_ids %d in %s.\n", ipany_ids
, __FUNCTION__
);
1765 LIST_FOREACH(p
, &iph2
->parent_session
->ph2tree
, ph2ofsession_chain
) {
1766 if (iph2
!= p
&& !p
->is_dying
&& FSM_STATE_IS_ESTABLISHED_OR_EXPIRED(p
->status
) &&
1768 plog(ASL_LEVEL_DEBUG
, "candidate ph2 found in %s.\n", __FUNCTION__
);
1770 ike_session_cmp_ph2_ids(iph2
, p
) == 0) {
1771 plog(ASL_LEVEL_DEBUG
, "candidate ph2 matched in %s.\n", __FUNCTION__
);
1772 iph2
->proposal
= dupsaprop(p
->approval
, 1);
1774 iph2
->spid
= p
->spid
;
1776 plog(ASL_LEVEL_DEBUG
, "%s: pre-assigned spid %d.\n", __FUNCTION__
, iph2
->spid
);
1787 ike_session_update_natt_version (phase1_handle_t
*iph1
)
1789 if (iph1
->parent_session
) {
1790 if (iph1
->natt_options
) {
1791 iph1
->parent_session
->natt_version
= iph1
->natt_options
->version
;
1793 iph1
->parent_session
->natt_version
= 0;
1799 ike_session_get_natt_version (phase1_handle_t
*iph1
)
1801 if (iph1
->parent_session
) {
1802 return(iph1
->parent_session
->natt_version
);
1808 ike_session_drop_rekey (ike_session_t
*session
, ike_session_rekey_type_t rekey_type
)
1811 if (session
->is_btmm_ipsec
&&
1812 session
->last_time_data_sc_detected
&&
1813 session
->traffic_monitor
.interv_mon
&&
1814 session
->traffic_monitor
.interv_idle
) {
1815 // for btmm: drop ph1/ph2 rekey if session is idle
1816 time_t now
= time(NULL
);
1818 if ((now
- session
->last_time_data_sc_detected
) > (session
->traffic_monitor
.interv_mon
<< 1)) {
1819 plog(ASL_LEVEL_DEBUG
, "btmm session is idle: drop ph%drekey.\n",
1823 } else if (!session
->is_btmm_ipsec
) {
1824 if (rekey_type
== IKE_SESSION_REKEY_TYPE_PH1
&&
1825 !ike_session_has_negoing_ph2(session
) && !ike_session_has_established_ph2(session
)) {
1826 // for vpn: only drop ph1 if there are no more ph2s.
1827 plog(ASL_LEVEL_DEBUG
, "vpn session is idle: drop ph1 rekey.\n");
1836 * this is called after racooon receives a 'kIOMessageSystemHasPoweredOn'
1837 * a lot is done to make sure that we don't sweep a session that's already been asserted.
1838 * however, it'll be too bad if the assertion comes after the session has already been swept.
1841 ike_session_sweep_sleepwake (void)
1843 ike_session_t
*p
= NULL
;
1844 ike_session_t
*next_session
= NULL
;
1846 // flag session as dying if all ph1/ph2 are dead/dying
1847 LIST_FOREACH_SAFE(p
, &ike_session_tree
, chain
, next_session
) {
1849 plog(ASL_LEVEL_DEBUG
, "skipping sweep of dying session.\n");
1852 SCHED_KILL(p
->sc_xauth
);
1853 if (p
->is_asserted
) {
1854 // for asserted session, traffic monitors will be restared after phase2 becomes established.
1855 SCHED_KILL(p
->traffic_monitor
.sc_mon
);
1856 SCHED_KILL(p
->traffic_monitor
.sc_idle
);
1857 plog(ASL_LEVEL_DEBUG
, "skipping sweep of asserted session.\n");
1861 // cleanup any stopped sessions as they will go down
1862 if (p
->stopped_by_vpn_controller
|| p
->stop_timestamp
.tv_sec
|| p
->stop_timestamp
.tv_usec
) {
1863 plog(ASL_LEVEL_DEBUG
, "sweeping stopped session.\n");
1864 ike_session_cleanup(p
, ike_session_stopped_by_sleepwake
);
1868 if (!ike_session_has_established_ph1(p
) && !ike_session_has_established_ph2(p
)) {
1869 plog(ASL_LEVEL_DEBUG
, "session died while sleeping.\n");
1870 ike_session_cleanup(p
, ike_session_stopped_by_sleepwake
);
1873 if (p
->traffic_monitor
.sc_mon
) {
1875 if (sched_get_time(p
->traffic_monitor
.sc_mon
, &xtime
)) {
1876 if (xtime
<= swept_at
) {
1877 SCHED_KILL(p
->traffic_monitor
.sc_mon
);
1878 if (!p
->is_dying
&& p
->traffic_monitor
.interv_mon
) {
1879 p
->traffic_monitor
.sc_mon
= sched_new(p
->traffic_monitor
.interv_mon
,
1880 ike_session_traffic_cop
,
1886 if (p
->traffic_monitor
.sc_idle
) {
1888 if (sched_get_time(p
->traffic_monitor
.sc_idle
, &xtime
)) {
1889 if (xtime
<= swept_at
) {
1890 SCHED_KILL(p
->traffic_monitor
.sc_idle
);
1891 if (!p
->is_dying
&& p
->traffic_monitor
.interv_idle
) {
1892 p
->traffic_monitor
.sc_idle
= sched_new(p
->traffic_monitor
.interv_idle
,
1893 ike_session_cleanup_idle
,
1903 * this is called after racooon receives an assert command from the controller/pppd.
1904 * this is intended to make racoon prepare to rekey both SAs because a network event occurred.
1905 * in the event of a sleepwake, the assert could happen before or after 'ike_session_sweep_sleepwake'.
1908 ike_session_assert_session (ike_session_t
*session
)
1910 phase2_handle_t
*iph2
= NULL
;
1911 phase2_handle_t
*iph2_next
= NULL
;
1912 phase1_handle_t
*iph1
= NULL
;
1913 phase1_handle_t
*iph1_next
= NULL
;
1915 if (!session
|| session
->is_dying
) {
1916 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
1920 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase2s
1921 LIST_FOREACH_SAFE(iph2
, &session
->ph2tree
, ph2ofsession_chain
, iph2_next
) {
1922 if (!iph2
->is_dying
&& !FSM_STATE_IS_EXPIRED(iph2
->status
)) {
1923 SCHED_KILL(iph2
->sce
);
1926 // delete SAs (in the kernel)
1927 if (FSM_STATE_IS_ESTABLISHED(iph2
->status
) && iph2
->approval
) {
1930 for (pr
= iph2
->approval
->head
; pr
!= NULL
; pr
= pr
->next
) {
1933 plog(ASL_LEVEL_DEBUG
,
1934 "Assert: Phase 2 %s deleted\n",
1935 sadbsecas2str(iph2
->src
, iph2
->dst
, iph2
->satype
, iph2
->spid
, ipsecdoi2pfkey_mode(pr
->encmode
)));
1937 pfkey_send_delete(lcconf
->sock_pfkey
,
1938 ipsecdoi2pfkey_proto(pr
->proto_id
),
1939 ipsecdoi2pfkey_mode(pr
->encmode
),
1940 iph2
->src
, iph2
->dst
, pr
->spi_p
);
1945 fsm_set_state(&iph2
->status
, IKEV1_STATE_PHASE2_EXPIRED
); // we want to delete SAs without telling the PEER
1946 iph2
->sce
= sched_new(3, ike_session_cleanup_ph2_stub
, iph2
);
1950 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase1s
1951 LIST_FOREACH_SAFE(iph1
, &session
->ph1tree
, ph1ofsession_chain
, iph1_next
) {
1952 if (!iph1
->is_dying
&& !FSM_STATE_IS_EXPIRED(iph1
->status
)) {
1953 SCHED_KILL(iph1
->sce
);
1954 SCHED_KILL(iph1
->sce_rekey
);
1958 plog(ASL_LEVEL_DEBUG
,
1959 "Assert: Phase 1 %s deleted\n",
1960 isakmp_pindex(&iph1
->index
, 0));
1962 ike_session_unbind_all_ph2_from_ph1(iph1
);
1964 fsm_set_state(&iph1
->status
, IKEV1_STATE_PHASE1_EXPIRED
); // we want to delete SAs without telling the PEER
1965 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
1966 iph1
->sce
= sched_new(5, ike_session_cleanup_ph1_stub
, iph1
);
1969 session
->is_asserted
= 1;
1975 ike_session_assert (struct sockaddr_storage
*local
,
1976 struct sockaddr_storage
*remote
)
1978 ike_session_t
*sess
;
1980 if (!local
|| !remote
) {
1981 plog(ASL_LEVEL_DEBUG
, "invalid parameters in %s.\n", __FUNCTION__
);
1985 if ((sess
= ike_session_get_session(local
, remote
, FALSE
, NULL
))) {
1986 return(ike_session_assert_session(sess
));
1992 ike_session_ph2_retransmits (phase2_handle_t
*iph2
)
1994 int num_retransmits
;
1996 if (!iph2
->is_dying
&&
1999 iph2
->ph1
->sce_rekey
&& !sched_is_dead(iph2
->ph1
->sce_rekey
) &&
2000 iph2
->side
== INITIATOR
&&
2001 iph2
->parent_session
&&
2002 !iph2
->parent_session
->is_cisco_ipsec
&& /* not for Cisco */
2003 iph2
->parent_session
->is_client
) {
2004 num_retransmits
= iph2
->ph1
->rmconf
->retry_counter
- iph2
->retry_counter
;
2005 if (num_retransmits
== 3) {
2007 * phase2 negotiation is stalling on retransmits, inspite of a valid ph1.
2008 * one of the following is possible:
2009 * - (0) severe packet loss.
2010 * - (1) the peer is dead.
2011 * - (2) the peer is out of sync hence dropping this phase2 rekey (and perhaps responding with insecure
2012 * invalid-cookie notifications... but those are untrusted and so we can't rekey phase1 off that)
2013 * (2.1) the peer rebooted (or process restarted) and is now alive.
2014 * (2.2) the peer has deleted phase1 without notifying us (or the notification got dropped somehow).
2015 * (2.3) the peer has a policy/bug stopping this phase2 rekey
2017 * in all these cases, one sure way to know is to trigger a phase1 rekey early.
2019 plog(ASL_LEVEL_DEBUG
, "Many Phase 2 retransmits: try Phase 1 rekey and this Phase 2 to quit earlier.\n");
2020 isakmp_ph1rekeyexpire(iph2
->ph1
, TRUE
);
2021 iph2
->retry_counter
= 0;
2027 ike_session_ph1_retransmits (phase1_handle_t
*iph1
)
2029 int num_retransmits
;
2031 if (!iph1
->is_dying
&&
2034 FSM_STATE_IS_NEGOTIATING(iph1
->status
) &&
2035 iph1
->side
== INITIATOR
&&
2036 iph1
->parent_session
&&
2037 iph1
->parent_session
->is_client
&&
2038 !ike_session_has_other_negoing_ph1(iph1
->parent_session
, iph1
)) {
2039 num_retransmits
= iph1
->rmconf
->retry_counter
- iph1
->retry_counter
;
2040 if (num_retransmits
== 3) {
2041 plog(ASL_LEVEL_DEBUG
, "Many Phase 1 retransmits: try quit earlier.\n");
2042 iph1
->retry_counter
= 0;
2048 ike_session_bindph12(phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
2051 plog(ASL_LEVEL_ERR
, "Phase 2 already bound %s.\n", __FUNCTION__
);
2054 LIST_INSERT_HEAD(&iph1
->bound_ph2tree
, iph2
, ph1bind_chain
);
2058 ike_session_unbindph12(phase2_handle_t
*iph2
)
2060 if (iph2
->ph1
!= NULL
) {
2062 LIST_REMOVE(iph2
, ph1bind_chain
);
2067 ike_session_rebindph12(phase1_handle_t
*new_ph1
, phase2_handle_t
*iph2
)
2073 // reconcile the ph1-to-ph2 binding
2074 ike_session_unbindph12(iph2
);
2075 ike_session_bindph12(new_ph1
, iph2
);
2076 // recalculate ivm since ph1 binding has changed
2077 if (iph2
->ivm
!= NULL
) {
2078 oakley_delivm(iph2
->ivm
);
2079 if (FSM_STATE_IS_ESTABLISHED(new_ph1
->status
)) {
2080 iph2
->ivm
= oakley_newiv2(new_ph1
, iph2
->msgid
);
2081 plog(ASL_LEVEL_DEBUG
, "Phase 1-2 binding changed... recalculated ivm.\n");
2089 ike_session_unbind_all_ph2_from_ph1 (phase1_handle_t
*iph1
)
2091 phase2_handle_t
*p
= NULL
;
2092 phase2_handle_t
*next
= NULL
;
2094 LIST_FOREACH_SAFE(p
, &iph1
->bound_ph2tree
, ph1bind_chain
, next
) {
2095 ike_session_unbindph12(p
);
2100 ike_session_rebind_all_ph12_to_new_ph1 (phase1_handle_t
*old_iph1
,
2101 phase1_handle_t
*new_iph1
)
2103 phase2_handle_t
*p
= NULL
;
2104 phase2_handle_t
*next
= NULL
;
2106 if (old_iph1
== new_iph1
|| !old_iph1
|| !new_iph1
) {
2107 plog(ASL_LEVEL_DEBUG
, "Invalid parameters in %s.\n", __FUNCTION__
);
2111 if (old_iph1
->parent_session
!= new_iph1
->parent_session
) {
2112 plog(ASL_LEVEL_DEBUG
, "Invalid parent sessions in %s.\n", __FUNCTION__
);
2116 LIST_FOREACH_SAFE(p
, &old_iph1
->bound_ph2tree
, ph1bind_chain
, next
) {
2117 if (p
->parent_session
!= new_iph1
->parent_session
) {
2118 plog(ASL_LEVEL_ERR
, "Mismatched parent session in ph1bind replacement.\n");
2120 if (p
->ph1
== new_iph1
) {
2121 plog(ASL_LEVEL_ERR
, "Same Phase 2 in ph1bind replacement in %s.\n",__FUNCTION__
);
2123 ike_session_rebindph12(new_iph1
, p
);