]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/ike_session.c
ipsec-146.3.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / ike_session.c
1 /*
2 * Copyright (c) 2008 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <string.h>
27
28 #include "var.h"
29 #include "misc.h"
30 #include "vmbuf.h"
31 #include "plog.h"
32 #include "sockmisc.h"
33 #include "debug.h"
34
35 #include "isakmp_var.h"
36 #include "isakmp.h"
37 #include "ike_session.h"
38 #include "handler.h"
39 #include "gcmalloc.h"
40 #include "nattraversal.h"
41 #include "schedule.h"
42 #include "pfkey.h"
43 #include "ipsec_doi.h"
44 #include "ipsecSessionTracer.h"
45 #include "ipsecMessageTracer.h"
46 #include "isakmp_inf.h"
47 #include "localconf.h"
48 #include "remoteconf.h"
49 #include "vpn_control.h"
50 #include "proposal.h"
51 #include "sainfo.h"
52 #include "power_mgmt.h"
53
54 #define GET_SAMPLE_PERIOD(s,m) do { \
55 s = m / 20; \
56 if (s < 3) { \
57 s = 3; \
58 if (m < (s * 2)) { \
59 s = 1; /* bad */\
60 } \
61 } \
62 } while(0);
63
64 const char *ike_session_stopped_by_vpn_disconnect = "Stopped by VPN disconnect";
65 const char *ike_session_stopped_by_flush = "Stopped by Flush";
66 const char *ike_session_stopped_by_idle = "Stopped by Idle";
67 const char *ike_session_stopped_by_xauth_timeout = "Stopped by XAUTH timeout";
68 const char *ike_session_stopped_by_sleepwake = "Stopped by Sleep-Wake";
69 const char *ike_session_stopped_by_assert = "Stopped by Assert";
70
71 static LIST_HEAD(_ike_session_tree_, ike_session) ike_session_tree = { NULL };
72
73 static ike_session_t *
74 new_ike_session (ike_session_id_t *id)
75 {
76 ike_session_t *session;
77
78 if (!id) {
79 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
80 return NULL;
81 }
82
83 plog(LLV_DEBUG, LOCATION, NULL, "new parent session.\n");
84 session = racoon_calloc(1, sizeof(*session));
85 if (session) {
86 bzero(session, sizeof(*session));
87 memcpy(&session->session_id, id, sizeof(*id));
88 LIST_INIT(&session->ikev1_state.ph1tree);
89 LIST_INIT(&session->ikev1_state.ph2tree);
90 LIST_INSERT_HEAD(&ike_session_tree, session, chain);
91 session->version = IKE_VERSION_1; // hard-coded for now
92 IPSECSESSIONTRACERSTART(session);
93 }
94 return session;
95 }
96
97 static void
98 free_ike_session (ike_session_t *session)
99 {
100 int is_failure = TRUE;
101 if (session) {
102 SCHED_KILL(session->traffic_monitor.sc_mon);
103 SCHED_KILL(session->traffic_monitor.sc_idle);
104 SCHED_KILL(session->sc_xauth);
105 if (session->start_timestamp.tv_sec || session->start_timestamp.tv_usec) {
106 if (!(session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec)) {
107 gettimeofday(&session->stop_timestamp, NULL);
108 }
109 if (session->term_reason != ike_session_stopped_by_vpn_disconnect ||
110 session->term_reason != ike_session_stopped_by_flush ||
111 session->term_reason != ike_session_stopped_by_idle) {
112 is_failure = FALSE;
113 }
114 IPSECSESSIONTRACERSTOP(session,
115 is_failure,
116 session->term_reason);
117 }
118 // do MessageTracer cleanup here
119 plog(LLV_DEBUG, LOCATION, NULL,
120 "Freeing IKE-Session to %s.\n",
121 saddr2str((struct sockaddr *)&session->session_id.remote));
122 LIST_REMOVE(session, chain);
123 racoon_free(session);
124 }
125 }
126
127 struct ph1handle *
128 ike_session_get_established_or_negoing_ph1 (ike_session_t *session)
129 {
130 struct ph1handle *p, *iph1 = NULL;
131
132 if (!session) {
133 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
134 return NULL;
135 }
136
137 // look for the most mature ph1 under the session
138 for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = LIST_NEXT(p, ph1ofsession_chain)) {
139 if (!p->is_dying && p->status >= PHASE1ST_START && p->status <= PHASE1ST_ESTABLISHED) {
140 if (!iph1 || p->status > iph1->status) {
141 iph1 = p;
142 } else if (iph1 && p->status == iph1->status) {
143 // TODO: pick better one based on farthest rekey/expiry remaining
144 }
145 }
146 }
147
148 return iph1;
149 }
150
151 struct ph1handle *
152 ike_session_get_established_ph1 (ike_session_t *session)
153 {
154 struct ph1handle *p;
155
156 if (!session) {
157 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
158 return NULL;
159 }
160
161 for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = LIST_NEXT(p, ph1ofsession_chain)) {
162 if (!p->is_dying && p->status == PHASE1ST_ESTABLISHED) {
163 return p;
164 }
165 }
166
167 return NULL;
168 }
169
170 void
171 ike_session_init (void)
172 {
173 LIST_INIT(&ike_session_tree);
174 }
175
176 u_int
177 ike_session_get_rekey_lifetime (int local_spi_is_higher, u_int expiry_lifetime)
178 {
179 u_int rekey_lifetime = expiry_lifetime / 10;
180
181 if (rekey_lifetime) {
182 if (local_spi_is_higher) {
183 return (rekey_lifetime * 9);
184 } else {
185 return (rekey_lifetime * 8);
186 }
187 } else {
188 if (local_spi_is_higher) {
189 rekey_lifetime = expiry_lifetime - 1;
190 } else {
191 rekey_lifetime = expiry_lifetime - 2;
192 }
193 }
194 if (rekey_lifetime < expiry_lifetime) {
195 return (rekey_lifetime);
196 }
197 return(0);
198 }
199
200 // TODO: optimize this mess later
201 ike_session_t *
202 ike_session_get_session (struct sockaddr *local,
203 struct sockaddr *remote,
204 int alloc_if_absent)
205 {
206 ike_session_t *p;
207 ike_session_id_t id;
208 ike_session_id_t id_default;
209 ike_session_id_t id_floated_default;
210 ike_session_id_t id_wop;
211 ike_session_t *best_match = NULL;
212 u_int16_t remote_port;
213 int is_isakmp_remote_port;
214
215 if (!local || !remote) {
216 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
217 return NULL;
218 }
219
220 remote_port = extract_port(remote);
221 if (remote_port && remote_port != PORT_ISAKMP && remote_port != PORT_ISAKMP_NATT) {
222 is_isakmp_remote_port = 0;
223 } else {
224 is_isakmp_remote_port = 1;
225 }
226
227 /* 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 */
228 bzero(&id, sizeof(id));
229 bzero(&id_default, sizeof(id_default));
230 bzero(&id_floated_default, sizeof(id_floated_default));
231 bzero(&id_wop, sizeof(id_wop));
232 if (local->sa_family == AF_INET) {
233 memcpy(&id.local, local, sizeof(struct sockaddr_in));
234 memcpy(&id_default.local, local, sizeof(struct sockaddr_in));
235 memcpy(&id_floated_default.local, local, sizeof(struct sockaddr_in));
236 memcpy(&id_wop.local, local, sizeof(struct sockaddr_in));
237 } else if (local->sa_family == AF_INET6) {
238 memcpy(&id.local, local, sizeof(struct sockaddr_in6));
239 memcpy(&id_default.local, local, sizeof(struct sockaddr_in6));
240 memcpy(&id_floated_default.local, local, sizeof(struct sockaddr_in6));
241 memcpy(&id_wop.local, local, sizeof(struct sockaddr_in6));
242 }
243 set_port((struct sockaddr *)&id_default.local, PORT_ISAKMP);
244 set_port((struct sockaddr *)&id_floated_default.local, PORT_ISAKMP_NATT);
245 set_port((struct sockaddr *)&id_wop.local, 0);
246 if (remote->sa_family == AF_INET) {
247 memcpy(&id.remote, remote, sizeof(struct sockaddr_in));
248 memcpy(&id_default.remote, remote, sizeof(struct sockaddr_in));
249 memcpy(&id_floated_default.remote, remote, sizeof(struct sockaddr_in));
250 memcpy(&id_wop.remote, remote, sizeof(struct sockaddr_in));
251 } else if (remote->sa_family == AF_INET6) {
252 memcpy(&id.remote, remote, sizeof(struct sockaddr_in6));
253 memcpy(&id_default.remote, remote, sizeof(struct sockaddr_in6));
254 memcpy(&id_floated_default.remote, remote, sizeof(struct sockaddr_in6));
255 memcpy(&id_wop.remote, remote, sizeof(struct sockaddr_in6));
256 }
257 set_port((struct sockaddr *)&id_default.remote, PORT_ISAKMP);
258 set_port((struct sockaddr *)&id_floated_default.remote, PORT_ISAKMP_NATT);
259 set_port((struct sockaddr *)&id_wop.remote, 0);
260
261 plog(LLV_DEBUG, LOCATION, local,
262 "start search for IKE-Session. target %s.\n",
263 saddr2str(remote));
264
265 for (p = LIST_FIRST(&ike_session_tree); p; p = LIST_NEXT(p, chain)) {
266 plog(LLV_DEBUG, LOCATION, local,
267 "still search for IKE-Session. this %s.\n",
268 saddr2str((struct sockaddr *)&p->session_id.remote));
269
270 // for now: ignore any stopped sessions as they will go down
271 if (p->is_dying || p->stopped_by_vpn_controller || p->stop_timestamp.tv_sec || p->stop_timestamp.tv_usec) {
272 plog(LLV_DEBUG, LOCATION, local,
273 "still searching. skipping... session to %s is already stopped, active ph1 %d ph2 %d.\n",
274 saddr2str((struct sockaddr *)&p->session_id.remote),
275 p->ikev1_state.active_ph1cnt, p->ikev1_state.active_ph2cnt);
276 continue;
277 }
278
279 if (memcmp(&p->session_id, &id, sizeof(id)) == 0) {
280 plog(LLV_DEBUG, LOCATION, local,
281 "Pre-existing IKE-Session to %s. case 1.\n",
282 saddr2str(remote));
283 return p;
284 } else if (is_isakmp_remote_port && memcmp(&p->session_id, &id_default, sizeof(id_default)) == 0) {
285 plog(LLV_DEBUG, LOCATION, local,
286 "Pre-existing IKE-Session to %s. case 2.\n",
287 saddr2str(remote));
288 return p;
289 } else if (is_isakmp_remote_port && p->ports_floated && memcmp(&p->session_id, &id_floated_default, sizeof(id_floated_default)) == 0) {
290 plog(LLV_DEBUG, LOCATION, local,
291 "Pre-existing IKE-Session to %s. case 3.\n",
292 saddr2str(remote));
293 return p;
294 } else if (is_isakmp_remote_port && memcmp(&p->session_id, &id_wop, sizeof(id_wop)) == 0) {
295 best_match = p;
296 }
297 }
298 if (best_match) {
299 plog(LLV_DEBUG, LOCATION, local,
300 "Best-match IKE-Session to %s.\n",
301 saddr2str((struct sockaddr *)&best_match->session_id.remote));
302 return best_match;
303 }
304 if (alloc_if_absent) {
305 plog(LLV_DEBUG, LOCATION, local,
306 "New IKE-Session to %s.\n",
307 saddr2str((struct sockaddr *)&id.remote));
308 return new_ike_session(&id);
309 } else {
310 return NULL;
311 }
312 }
313
314 void
315 ike_session_init_traffic_cop_params (struct ph1handle *iph1)
316 {
317 if (!iph1 ||
318 !iph1->rmconf ||
319 (!iph1->rmconf->idle_timeout && !iph1->rmconf->dpd_interval)) {
320 return;
321 }
322
323 if (!iph1->parent_session->traffic_monitor.interv_idle) {
324 iph1->parent_session->traffic_monitor.interv_idle = iph1->rmconf->idle_timeout;
325 }
326 if (!iph1->parent_session->traffic_monitor.dir_idle) {
327 iph1->parent_session->traffic_monitor.dir_idle = iph1->rmconf->idle_timeout_dir;
328 }
329
330 if (!iph1->parent_session->traffic_monitor.interv_mon) {
331 int min_period, max_period, sample_period = 0;
332
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;
342 } else {
343 // DPD_ALGO_DEFAULT is configured and there's no idle timeout... we don't need to monitor traffic
344 return;
345 }
346 if (min_period) {
347 GET_SAMPLE_PERIOD(sample_period, min_period);
348 } else {
349 GET_SAMPLE_PERIOD(sample_period, max_period);
350 }
351 iph1->parent_session->traffic_monitor.interv_mon = sample_period;
352 }
353 }
354
355 int
356 ike_session_link_ph1_to_session (struct ph1handle *iph1)
357 {
358 ike_session_t *session;
359
360 if (!iph1) {
361 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
362 return -1;
363 }
364
365 session = ike_session_get_session(iph1->local, iph1->remote, TRUE);
366 if (!session) {
367 plog(LLV_DEBUG2, LOCATION, NULL, "failed to get session in %s.\n", __FUNCTION__);
368 return -1;
369 }
370
371 // already linked
372 if (iph1->parent_session) {
373 if (session == iph1->parent_session) {
374 return 0;
375 }
376 // undo previous session
377 if (ike_session_unlink_ph1_from_session(iph1) == 0) {
378 plog(LLV_DEBUG2, LOCATION, NULL, "failed to unlink ph1 in %s.\n", __FUNCTION__);
379 free_ike_session(session);
380 return -1;
381 }
382 } else {
383 gettimeofday(&session->start_timestamp, NULL);
384 }
385
386
387 if (iph1->started_by_api) {
388 session->is_cisco_ipsec = 1;
389 session->is_l2tpvpn_ipsec = 0;
390 session->is_btmm_ipsec = 0;
391 }
392 iph1->parent_session = session;
393 LIST_INSERT_HEAD(&session->ikev1_state.ph1tree, iph1, ph1ofsession_chain);
394 session->ikev1_state.active_ph1cnt++;
395 if ((!session->ikev1_state.ph1cnt &&
396 iph1->side == INITIATOR) ||
397 iph1->started_by_api) {
398 // client initiates the first phase1 or, is started by controller api
399 session->is_client = 1;
400 }
401 if (session->established &&
402 session->ikev1_state.ph1cnt) {
403 iph1->is_rekey = 1;
404 }
405 session->ikev1_state.ph1cnt++;
406 ike_session_init_traffic_cop_params(iph1);
407
408 return 0;
409 }
410
411 void
412 ike_session_update_mode (struct ph2handle *iph2)
413 {
414 if (!iph2 || !iph2->parent_session) {
415 return;
416 }
417
418 // exit early if we already detected cisco-ipsec
419 if (iph2->parent_session->is_cisco_ipsec) {
420 return;
421 }
422
423 if (iph2->approval) {
424 if (!ipsecdoi_any_transportmode(iph2->approval)) {
425 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
426 iph2->parent_session->is_cisco_ipsec = 0;
427 iph2->parent_session->is_l2tpvpn_ipsec = 0;
428 iph2->parent_session->is_btmm_ipsec = 1;
429 return;
430 } else if (ipsecdoi_transportmode(iph2->approval)) {
431 iph2->parent_session->is_cisco_ipsec = 0;
432 iph2->parent_session->is_l2tpvpn_ipsec = 1;
433 iph2->parent_session->is_btmm_ipsec = 0;
434 return;
435 }
436 } else if (iph2->proposal) {
437 if (!ipsecdoi_any_transportmode(iph2->proposal)) {
438 // cisco & btmm ipsec are pure tunnel-mode (but cisco ipsec is detected by ph1)
439 iph2->parent_session->is_cisco_ipsec = 0;
440 iph2->parent_session->is_l2tpvpn_ipsec = 0;
441 iph2->parent_session->is_btmm_ipsec = 1;
442 return;
443 } else if (ipsecdoi_transportmode(iph2->proposal)) {
444 iph2->parent_session->is_cisco_ipsec = 0;
445 iph2->parent_session->is_l2tpvpn_ipsec = 1;
446 iph2->parent_session->is_btmm_ipsec = 0;
447 return;
448 }
449 }
450 }
451
452 static void
453 ike_session_cleanup_xauth_timeout (void *arg)
454 {
455 ike_session_t *session = (ike_session_t *)arg;
456
457 SCHED_KILL(session->sc_xauth);
458 // if there are no more established ph2s, start a timer to teardown the session
459 if (!ike_session_has_established_ph2(session)) {
460 ike_session_cleanup(session, ike_session_stopped_by_xauth_timeout);
461 } else {
462 session->sc_xauth = sched_new(300 /* 5 mins */,
463 ike_session_cleanup_xauth_timeout,
464 session);
465 }
466 }
467
468 int
469 ike_session_link_ph2_to_session (struct ph2handle *iph2)
470 {
471 struct sockaddr *local;
472 struct sockaddr *remote;
473 ike_session_t *session;
474
475 if (!iph2) {
476 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
477 return -1;
478 }
479
480 local = iph2->src;
481 remote = iph2->dst;
482
483 session = ike_session_get_session(local, remote, TRUE);
484 if (!session) {
485 plog(LLV_DEBUG2, LOCATION, NULL, "failed to get session in %s.\n", __FUNCTION__);
486 return -1;
487 }
488
489 // already linked
490 if (iph2->parent_session) {
491 if (session == iph2->parent_session) {
492 return 0;
493 }
494 // undo previous session
495 if (ike_session_unlink_ph2_from_session(iph2) == 0) {
496 plog(LLV_DEBUG2, LOCATION, NULL, "failed to unlink ph2 in %s.\n", __FUNCTION__);
497 free_ike_session(session);
498 return -1;
499 }
500 }
501
502 iph2->parent_session = session;
503 LIST_INSERT_HEAD(&session->ikev1_state.ph2tree, iph2, ph2ofsession_chain);
504 session->ikev1_state.active_ph2cnt++;
505 if (!session->ikev1_state.ph2cnt &&
506 iph2->side == INITIATOR) {
507 // client initiates the first phase2
508 session->is_client = 1;
509 }
510 if (session->established &&
511 session->ikev1_state.ph2cnt) {
512 iph2->is_rekey = 1;
513 }
514 session->ikev1_state.ph2cnt++;
515
516 ike_session_update_mode(iph2);
517
518 return 0;
519 }
520
521 int
522 ike_session_unlink_ph1_from_session (struct ph1handle *iph1)
523 {
524 ike_session_t *session;
525
526 if (!iph1 || !iph1->parent_session) {
527 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
528 return -1;
529 }
530
531 if (LIST_FIRST(&iph1->ph2tree)) {
532 // reparent any phase2 that may be hanging on to this phase1
533 ike_session_update_ph1_ph2tree(iph1);
534 }
535
536 session = iph1->parent_session;
537 LIST_REMOVE(iph1, ph1ofsession_chain);
538 iph1->parent_session = NULL;
539 session->ikev1_state.active_ph1cnt--;
540 if (session->ikev1_state.active_ph1cnt == 0 && session->ikev1_state.active_ph2cnt == 0) {
541 session->is_dying = 1;
542 free_ike_session(session);
543 }
544
545 return 0;
546 }
547
548 int
549 ike_session_unlink_ph2_from_session (struct ph2handle *iph2)
550 {
551 ike_session_t *session;
552
553 if (!iph2 || !iph2->parent_session) {
554 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
555 return -1;
556 }
557
558 LIST_REMOVE(iph2, ph2ofsession_chain);
559 session = iph2->parent_session;
560 iph2->parent_session = NULL;
561 session->ikev1_state.active_ph2cnt--;
562 if (session->ikev1_state.active_ph1cnt == 0 && session->ikev1_state.active_ph2cnt == 0) {
563 session->is_dying = 1;
564 free_ike_session(session);
565 }
566
567 return 0;
568 }
569
570 int
571 ike_session_has_other_established_ph1 (ike_session_t *session, struct ph1handle *iph1)
572 {
573 struct ph1handle *p;
574
575 if (!session) {
576 return 0;
577 }
578
579 for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = LIST_NEXT(p, ph1ofsession_chain)) {
580 if (iph1 != p && !p->is_dying) {
581 if (p->status == PHASE1ST_ESTABLISHED && p->sce_rekey) {
582 return 1;
583 }
584 }
585 }
586
587 return 0;
588 }
589
590 int
591 ike_session_has_other_negoing_ph1 (ike_session_t *session, struct ph1handle *iph1)
592 {
593 struct ph1handle *p;
594
595 if (!session) {
596 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
597 return 0;
598 }
599
600 for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = LIST_NEXT(p, ph1ofsession_chain)) {
601 if (iph1 != p && !p->is_dying) {
602 if (p->status >= PHASE1ST_START && p->status <= PHASE1ST_ESTABLISHED) {
603 return 1;
604 }
605 }
606 }
607
608 return 0;
609 }
610
611 int
612 ike_session_has_other_established_ph2 (ike_session_t *session, struct ph2handle *iph2)
613 {
614 struct ph2handle *p;
615
616 if (!session) {
617 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
618 return 0;
619 }
620
621 for (p = LIST_FIRST(&session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
622 if (iph2 != p && !p->is_dying && iph2->spid == p->spid) {
623 if (p->status == PHASE2ST_ESTABLISHED) {
624 return 1;
625 }
626 }
627 }
628
629 return 0;
630 }
631
632 int
633 ike_session_has_other_negoing_ph2 (ike_session_t *session, struct ph2handle *iph2)
634 {
635 struct ph2handle *p;
636
637 if (!session) {
638 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
639 return 0;
640 }
641
642 for (p = LIST_FIRST(&session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
643 plog(LLV_DEBUG2, LOCATION, NULL, "%s: ph2 sub spid %d, db spid %d\n", __FUNCTION__, iph2->spid, p->spid);
644 if (iph2 != p && !p->is_dying && iph2->spid == p->spid) {
645 if (p->status >= PHASE2ST_START && p->status <= PHASE2ST_ESTABLISHED) {
646 return 1;
647 }
648 }
649 }
650
651 return 0;
652 }
653
654 static void
655 ike_session_unbindph12_from_ph1 (struct ph1handle *iph1)
656 {
657 struct ph2handle *p, *next;
658
659 for (p = LIST_FIRST(&iph1->ph2tree); p; p = next) {
660 // take next pointer now, since unbind and rebind may change the underlying ph2tree list
661 next = LIST_NEXT(p, ph1bind);
662 unbindph12(p);
663 }
664 }
665
666 static void
667 ike_session_rebindph12_from_old_ph1_to_new_ph1 (struct ph1handle *old_iph1,
668 struct ph1handle *new_iph1)
669 {
670 struct ph2handle *p, *next;
671
672 if (old_iph1 == new_iph1 || !old_iph1 || !new_iph1) {
673 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
674 return;
675 }
676
677 if (old_iph1->parent_session != new_iph1->parent_session) {
678 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parent sessions in %s.\n", __FUNCTION__);
679 return;
680 }
681
682 for (p = LIST_FIRST(&old_iph1->ph2tree); p; p = next) {
683 // take next pointer now, since rebind may change the underlying ph2tree list
684 next = LIST_NEXT(p, ph1bind);
685 if (p->parent_session != new_iph1->parent_session) {
686 plog(LLV_ERROR, LOCATION, NULL, "mismatched parent session in ph1bind replacement.\n");
687 }
688 if (p->ph1 == new_iph1) {
689 plog(LLV_ERROR, LOCATION, NULL, "same phase1 in ph1bind replacement in %s.\n",__FUNCTION__);
690 }
691 rebindph12(new_iph1, p);
692 }
693 }
694
695 int
696 ike_session_verify_ph2_parent_session (struct ph2handle *iph2)
697 {
698 if (!iph2) {
699 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
700 return -1;
701 }
702
703 if (!iph2->parent_session) {
704 plog(LLV_DEBUG, LOCATION, NULL, "NULL parent session.\n");
705 if (ike_session_link_ph2_to_session(iph2)) {
706 plog(LLV_DEBUG, LOCATION, NULL, "NULL parent session... still failed to link to session.\n");
707 // failed to bind ph2 to session
708 return 1;
709 }
710 }
711 return 0;
712 }
713
714 struct ph1handle *
715 ike_session_update_ph1_ph2tree (struct ph1handle *iph1)
716 {
717 struct ph1handle *new_iph1 = NULL;
718
719 if (!iph1) {
720 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
721 return NULL;
722 }
723
724 if (iph1->parent_session) {
725 new_iph1 = ike_session_get_established_ph1(iph1->parent_session);
726
727 if (!new_iph1) {
728 plog(LLV_DEBUG2, LOCATION, NULL, "no ph1bind replacement found. NULL ph1.\n");
729 ike_session_unbindph12_from_ph1(iph1);
730 } else if (iph1 == new_iph1) {
731 plog(LLV_DEBUG2, LOCATION, NULL, "no ph1bind replacement found. same ph1.\n");
732 ike_session_unbindph12_from_ph1(iph1);
733 } else {
734 ike_session_rebindph12_from_old_ph1_to_new_ph1(iph1, new_iph1);
735 }
736 } else {
737 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parent session in %s.\n", __FUNCTION__);
738 }
739 return new_iph1;
740 }
741
742 struct ph1handle *
743 ike_session_update_ph2_ph1bind (struct ph2handle *iph2)
744 {
745 struct ph1handle *iph1;
746
747 if (!iph2) {
748 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
749 return NULL;
750 }
751
752 iph1 = ike_session_get_established_ph1(iph2->parent_session);
753 if (iph1 && iph2->ph1 && iph1 != iph2->ph1) {
754 rebindph12(iph1, iph2);
755 } else if (iph1 && !iph2->ph1) {
756 bindph12(iph1, iph2);
757 }
758
759 return iph1;
760 }
761
762 void
763 ike_session_ikev1_float_ports (struct ph1handle *iph1)
764 {
765 struct sockaddr *local, *remote;
766 struct ph2handle *p;
767
768 if (iph1->parent_session) {
769 local = (struct sockaddr *)&iph1->parent_session->session_id.local;
770 remote = (struct sockaddr *)&iph1->parent_session->session_id.remote;
771
772 set_port(local, extract_port(iph1->local));
773 set_port(remote, extract_port(iph1->remote));
774 iph1->parent_session->ports_floated = 1;
775
776 for (p = LIST_FIRST(&iph1->parent_session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
777
778 local = p->src;
779 remote = p->dst;
780
781 set_port(local, extract_port(iph1->local));
782 set_port(remote, extract_port(iph1->remote));
783 }
784 } else {
785 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parent session in %s.\n", __FUNCTION__);
786 }
787 }
788
789 static void
790 ike_session_traffic_cop (void *arg)
791 {
792 ike_session_t *session = (__typeof__(session))arg;
793
794 if (session &&
795 (session->established && !session->stopped_by_vpn_controller && !session->stop_timestamp.tv_sec && !session->stop_timestamp.tv_usec)) {
796 SCHED_KILL(session->traffic_monitor.sc_mon);
797 /* get traffic query from kernel */
798 if (pk_sendget_inbound_sastats(session) < 0) {
799 // log message
800 plog(LLV_DEBUG2, LOCATION, NULL, "pk_sendget_inbound_sastats failed in %s.\n", __FUNCTION__);
801 }
802 if (pk_sendget_outbound_sastats(session) < 0) {
803 // log message
804 plog(LLV_DEBUG2, LOCATION, NULL, "pk_sendget_outbound_sastats failed in %s.\n", __FUNCTION__);
805 }
806 session->traffic_monitor.sc_mon = sched_new(session->traffic_monitor.interv_mon,
807 ike_session_traffic_cop,
808 session);
809 } else {
810 // log message
811 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
812 }
813 }
814
815 static void
816 ike_session_cleanup_idle (void *arg)
817 {
818 ike_session_cleanup((ike_session_t *)arg, ike_session_stopped_by_idle);
819 }
820
821 static void
822 ike_session_monitor_idle (ike_session_t *session)
823 {
824 if (!session)
825 return;
826
827 if (session->traffic_monitor.dir_idle == IPSEC_DIR_INBOUND ||
828 session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) {
829 if (session->peer_sent_data_sc_idle) {
830 plog(LLV_DEBUG2, LOCATION, NULL, "%s: restart idle-timeout because peer sent data. monitoring dir %d.\n",
831 __FUNCTION__, session->traffic_monitor.dir_idle);
832 SCHED_KILL(session->traffic_monitor.sc_idle);
833 if (session->traffic_monitor.interv_idle) {
834 session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
835 ike_session_cleanup_idle,
836 session);
837 }
838 session->peer_sent_data_sc_idle = 0;
839 session->i_sent_data_sc_idle = 0;
840 return;
841 }
842 }
843 if (session->traffic_monitor.dir_idle == IPSEC_DIR_OUTBOUND ||
844 session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) {
845 if (session->i_sent_data_sc_idle) {
846 plog(LLV_DEBUG2, LOCATION, NULL, "%s: restart idle-timeout because i sent data. monitoring dir %d.\n",
847 __FUNCTION__, session->traffic_monitor.dir_idle);
848 SCHED_KILL(session->traffic_monitor.sc_idle);
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,
852 session);
853 }
854 session->peer_sent_data_sc_idle = 0;
855 session->i_sent_data_sc_idle = 0;
856 return;
857 }
858 }
859 }
860
861 static void
862 ike_session_start_traffic_mon (ike_session_t *session)
863 {
864 if (session->traffic_monitor.interv_mon) {
865 session->traffic_monitor.sc_mon = sched_new(session->traffic_monitor.interv_mon,
866 ike_session_traffic_cop,
867 session);
868 }
869 if (session->traffic_monitor.interv_idle) {
870 session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
871 ike_session_cleanup_idle,
872 session);
873 }
874 }
875
876 void
877 ike_session_ph2_established (struct ph2handle *iph2)
878 {
879 if (!iph2->parent_session) {
880 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
881 return;
882 }
883 SCHED_KILL(iph2->parent_session->sc_xauth);
884 if (!iph2->parent_session->established) {
885 gettimeofday(&iph2->parent_session->estab_timestamp, NULL);
886 iph2->parent_session->established = 1;
887 IPSECSESSIONTRACERESTABLISHED(iph2->parent_session);
888 ike_session_start_traffic_mon(iph2->parent_session);
889 } else if (iph2->parent_session->is_asserted) {
890 ike_session_start_traffic_mon(iph2->parent_session);
891 }
892 iph2->parent_session->is_asserted = 0;
893 // nothing happening to this session
894 iph2->parent_session->term_reason = NULL;
895
896 ike_session_update_mode(iph2);
897
898 #ifdef ENABLE_VPNCONTROL_PORT
899 vpncontrol_notify_peer_resp_ph2(1, iph2);
900 #endif /* ENABLE_VPNCONTROL_PORT */
901 plog(LLV_DEBUG2, LOCATION, NULL, "%s: ph2 established, spid %d\n", __FUNCTION__, iph2->spid);
902 }
903
904 void
905 ike_session_cleanup_ph1 (struct ph1handle *iph1)
906 {
907 if (iph1->status == PHASE1ST_EXPIRED) {
908 // since this got here via ike_session_cleanup_other_established_ph1s, assumes LIST_FIRST(&iph1->ph2tree) == NULL
909 iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
910 return;
911 }
912
913 /* send delete information */
914 if (iph1->status == PHASE1ST_ESTABLISHED) {
915 isakmp_info_send_d1(iph1);
916 }
917
918 isakmp_ph1expire(iph1);
919 }
920
921 void
922 ike_session_cleanup_ph1_stub (void *p)
923 {
924
925 ike_session_cleanup_ph1((struct ph1handle *)p);
926 }
927
928 void
929 ike_session_cleanup_other_established_ph1s (ike_session_t *session,
930 struct ph1handle *new_iph1)
931 {
932 struct ph1handle *p, *next;
933 char *local, *remote;
934
935 if (!session || !new_iph1 || session != new_iph1->parent_session) {
936 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
937 return;
938 }
939
940 /*
941 * if we are responder, then we should wait until the server sends a delete notification.
942 */
943 if (session->is_client && new_iph1->side == RESPONDER) {
944 return;
945 }
946
947 for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = next) {
948 // take next pointer now, since delete change the underlying ph1tree list
949 next = LIST_NEXT(p, ph1ofsession_chain);
950 /*
951 * TODO: currently, most recently established SA wins. Need to revisit to see if
952 * alternative selections is better (e.g. largest p->index stays).
953 */
954 if (p != new_iph1 && !p->is_dying) {
955 SCHED_KILL(p->sce);
956 SCHED_KILL(p->sce_rekey);
957 p->is_dying = 1;
958
959 //log deletion
960 local = racoon_strdup(saddr2str(p->local));
961 remote = racoon_strdup(saddr2str(p->remote));
962 STRDUP_FATAL(local);
963 STRDUP_FATAL(remote);
964 plog(LLV_DEBUG, LOCATION, NULL,
965 "ISAKMP-SA needs to be deleted %s-%s spi:%s\n",
966 local, remote, isakmp_pindex(&p->index, 0));
967 racoon_free(local);
968 racoon_free(remote);
969
970 // first rebind the children ph2s of this dying ph1 to the new ph1.
971 ike_session_rebindph12_from_old_ph1_to_new_ph1 (p, new_iph1);
972
973 if (p->side == INITIATOR) {
974 /* everyone deletes old outbound SA */
975 p->sce = sched_new(5, ike_session_cleanup_ph1_stub, p);
976 } else {
977 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
978 p->sce = sched_new(7, ike_session_cleanup_ph1_stub, p);
979 }
980 }
981 }
982 }
983
984 void
985 ike_session_cleanup_ph2 (struct ph2handle *iph2)
986 {
987 if (iph2->status == PHASE2ST_EXPIRED) {
988 return;
989 }
990
991 SCHED_KILL(iph2->sce);
992
993 plog(LLV_ERROR, LOCATION, NULL,
994 "about to cleanup ph2: status %d, seq %d dying %d\n",
995 iph2->status, iph2->seq, iph2->is_dying);
996
997 /* send delete information */
998 if (iph2->status == PHASE2ST_ESTABLISHED) {
999 isakmp_info_send_d2(iph2);
1000
1001 // delete outgoing SAs
1002 if (iph2->approval) {
1003 struct saproto *pr;
1004
1005 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1006 if (pr->ok) {
1007 pfkey_send_delete(lcconf->sock_pfkey,
1008 ipsecdoi2pfkey_proto(pr->proto_id),
1009 IPSEC_MODE_ANY,
1010 iph2->src, iph2->dst, pr->spi_p /* pr->reqid_out */);
1011 }
1012 }
1013 }
1014 }
1015
1016 delete_spd(iph2);
1017 unbindph12(iph2);
1018 remph2(iph2);
1019 delph2(iph2);
1020 }
1021
1022 void
1023 ike_session_cleanup_ph2_stub (void *p)
1024 {
1025
1026 ike_session_cleanup_ph2((struct ph2handle *)p);
1027 }
1028
1029 void
1030 ike_session_cleanup_other_established_ph2s (ike_session_t *session,
1031 struct ph2handle *new_iph2)
1032 {
1033 struct ph2handle *p, *next;
1034
1035 if (!session || !new_iph2 || session != new_iph2->parent_session) {
1036 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1037 return;
1038 }
1039
1040 /*
1041 * if we are responder, then we should wait until the server sends a delete notification.
1042 */
1043 if (session->is_client && new_iph2->side == RESPONDER) {
1044 return;
1045 }
1046
1047 for (p = LIST_FIRST(&session->ikev1_state.ph2tree); p; p = next) {
1048 // take next pointer now, since delete change the underlying ph2tree list
1049 next = LIST_NEXT(p, ph2ofsession_chain);
1050 /*
1051 * TODO: currently, most recently established SA wins. Need to revisit to see if
1052 * alternative selections is better.
1053 */
1054 if (p != new_iph2 && p->spid == new_iph2->spid && !p->is_dying) {
1055 SCHED_KILL(p->sce);
1056 p->is_dying = 1;
1057
1058 //log deletion
1059 plog(LLV_DEBUG, LOCATION, NULL,
1060 "IPsec-SA needs to be deleted: %s\n",
1061 sadbsecas2str(p->src, p->dst,
1062 p->satype, p->spid, 0));
1063
1064 if (p->side == INITIATOR) {
1065 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1066 p->sce = sched_new(3, ike_session_cleanup_ph2_stub, p);
1067 } else {
1068 /* responder sets up timer to delete old inbound SAs... say 5 secs later and flags them as rekeyed */
1069 p->sce = sched_new(5, ike_session_cleanup_ph2_stub, p);
1070 }
1071 }
1072 }
1073 }
1074
1075 void
1076 ike_session_stopped_by_controller (ike_session_t *session,
1077 const char *reason)
1078 {
1079 if (!session) {
1080 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1081 return;
1082 }
1083 if (session->stop_timestamp.tv_sec ||
1084 session->stop_timestamp.tv_usec) {
1085 plog(LLV_DEBUG2, LOCATION, NULL, "already stopped %s.\n", __FUNCTION__);
1086 return;
1087 }
1088 session->stopped_by_vpn_controller = 1;
1089 gettimeofday(&session->stop_timestamp, NULL);
1090 if (!session->term_reason) {
1091 session->term_reason = reason;
1092 }
1093 }
1094
1095 void
1096 ike_sessions_stopped_by_controller (struct sockaddr *remote,
1097 int withport,
1098 const char *reason)
1099 {
1100 ike_session_t *p = NULL;
1101
1102 if (!remote) {
1103 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1104 return;
1105 }
1106
1107 for (p = LIST_FIRST(&ike_session_tree); p; p = LIST_NEXT(p, chain)) {
1108 if (withport && cmpsaddrstrict(&p->session_id.remote, remote) == 0 ||
1109 !withport && cmpsaddrwop(&p->session_id.remote, remote) == 0) {
1110 ike_session_stopped_by_controller(p, reason);
1111 }
1112 }
1113 }
1114
1115 void
1116 ike_session_purge_ph2s_by_ph1 (struct ph1handle *iph1)
1117 {
1118 struct ph2handle *p, *next;
1119
1120 if (!iph1 || !iph1->parent_session) {
1121 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1122 return;
1123 }
1124
1125 for (p = LIST_FIRST(&iph1->parent_session->ikev1_state.ph2tree); p; p = next) {
1126 // take next pointer now, since delete change the underlying ph2tree list
1127 next = LIST_NEXT(p, ph2ofsession_chain);
1128 if (p->is_dying) {
1129 continue;
1130 }
1131 SCHED_KILL(p->sce);
1132 p->is_dying = 1;
1133
1134 //log deletion
1135 plog(LLV_DEBUG, LOCATION, NULL,
1136 "IPsec-SA needs to be purged: %s\n",
1137 sadbsecas2str(p->src, p->dst,
1138 p->satype, p->spid, 0));
1139
1140 ike_session_cleanup_ph2(p);
1141 }
1142 }
1143
1144 void
1145 ike_session_update_ph2_ports (struct ph2handle *iph2)
1146 {
1147 struct sockaddr *local;
1148 struct sockaddr *remote;
1149
1150 if (iph2->parent_session) {
1151 local = (struct sockaddr *)&iph2->parent_session->session_id.local;
1152 remote = (struct sockaddr *)&iph2->parent_session->session_id.remote;
1153
1154 set_port(iph2->src, extract_port(local));
1155 set_port(iph2->dst, extract_port(remote));
1156 } else {
1157 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parent session in %s.\n", __FUNCTION__);
1158 }
1159 }
1160
1161 u_int32_t
1162 ike_session_get_sas_for_stats (ike_session_t *session,
1163 u_int8_t dir,
1164 u_int32_t *seq,
1165 struct sastat *stats,
1166 u_int32_t max_stats)
1167 {
1168 int found = 0;
1169 struct ph2handle *iph2;
1170
1171 if (!session || !seq || !stats || !max_stats || (dir != IPSEC_DIR_INBOUND && dir != IPSEC_DIR_OUTBOUND)) {
1172 plog(LLV_DEBUG2, LOCATION, NULL, "invalid args in %s.\n", __FUNCTION__);
1173 return found;
1174 }
1175
1176 *seq = 0;
1177 for (iph2 = LIST_FIRST(&session->ikev1_state.ph2tree); iph2; iph2 = LIST_NEXT(iph2, ph2ofsession_chain)) {
1178
1179 if (iph2->approval) {
1180 struct saproto *pr;
1181
1182 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1183 if (pr->ok && pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP) {
1184 if (!*seq) {
1185 *seq = iph2->seq;
1186 }
1187 if (dir == IPSEC_DIR_INBOUND) {
1188 stats[found].spi = pr->spi;
1189 } else {
1190 stats[found].spi = pr->spi_p;
1191 }
1192 if (++found == max_stats) {
1193 return found;
1194 }
1195 }
1196 }
1197 }
1198 }
1199 return found;
1200 }
1201
1202 void
1203 ike_session_update_traffic_idle_status (ike_session_t *session,
1204 u_int32_t dir,
1205 struct sastat *new_stats,
1206 u_int32_t max_stats)
1207 {
1208 int i, j, found = 0, idle = 1;
1209
1210 if (!session || !new_stats || (dir != IPSEC_DIR_INBOUND && dir != IPSEC_DIR_OUTBOUND)) {
1211 plog(LLV_DEBUG2, LOCATION, NULL, "invalid args in %s.\n", __FUNCTION__);
1212 return;
1213 }
1214
1215 if (!session->established || session->stopped_by_vpn_controller || session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec) {
1216 plog(LLV_DEBUG2, LOCATION, NULL, "dropping update on invalid session in %s.\n", __FUNCTION__);
1217 return;
1218 }
1219
1220 for (i = 0; i < max_stats; i++) {
1221 if (dir == IPSEC_DIR_INBOUND) {
1222 for (j = 0; j < session->traffic_monitor.num_in_last_poll; j++) {
1223 if (new_stats[i].spi != session->traffic_monitor.in_last_poll[j].spi) {
1224 continue;
1225 }
1226 found = 1;
1227 if (new_stats[i].lft_c.sadb_lifetime_bytes != session->traffic_monitor.in_last_poll[j].lft_c.sadb_lifetime_bytes) {
1228 idle = 0;
1229 }
1230 }
1231 } else {
1232 for (j = 0; j < session->traffic_monitor.num_out_last_poll; j++) {
1233 if (new_stats[i].spi != session->traffic_monitor.out_last_poll[j].spi) {
1234 continue;
1235 }
1236 found = 1;
1237 if (new_stats[i].lft_c.sadb_lifetime_bytes != session->traffic_monitor.out_last_poll[j].lft_c.sadb_lifetime_bytes) {
1238 idle = 0;
1239 }
1240 }
1241 }
1242 // new SA.... check for any activity
1243 if (!found) {
1244 if (new_stats[i].lft_c.sadb_lifetime_bytes) {
1245 plog(LLV_DEBUG, LOCATION, NULL, "new SA: dir %d....\n", dir);
1246 idle = 0;
1247 }
1248 }
1249 }
1250 if (dir == IPSEC_DIR_INBOUND) {
1251 // overwrite old stats
1252 bzero(session->traffic_monitor.in_last_poll, sizeof(session->traffic_monitor.in_last_poll));
1253 bcopy(new_stats, session->traffic_monitor.in_last_poll, (max_stats * sizeof(*new_stats)));
1254 session->traffic_monitor.num_in_last_poll = max_stats;
1255 if (!idle) {
1256 plog(LLV_DEBUG, LOCATION, NULL, "peer sent data....\n");
1257 session->peer_sent_data_sc_dpd = 1;
1258 session->peer_sent_data_sc_idle = 1;
1259 }
1260 } else {
1261 // overwrite old stats
1262 bzero(session->traffic_monitor.out_last_poll, sizeof(session->traffic_monitor.out_last_poll));
1263 bcopy(new_stats, session->traffic_monitor.out_last_poll, (max_stats * sizeof(*new_stats)));
1264 session->traffic_monitor.num_out_last_poll = max_stats;
1265 if (!idle) {
1266 plog(LLV_DEBUG, LOCATION, NULL, "i sent data....\n");
1267 session->i_sent_data_sc_dpd = 1;
1268 session->i_sent_data_sc_idle = 1;
1269 }
1270 }
1271 if (!idle)
1272 session->last_time_data_sc_detected = time(NULL);
1273
1274 ike_session_monitor_idle(session);
1275 }
1276
1277 void
1278 ike_session_cleanup (ike_session_t *session,
1279 const char *reason)
1280 {
1281 struct ph2handle *iph2;
1282 struct ph1handle *iph1;
1283
1284 if (!session)
1285 return;
1286
1287 session->is_dying = 1;
1288
1289 SCHED_KILL(session->traffic_monitor.sc_idle);
1290 // do ph2's first... we need the ph1s for notifications
1291 for (iph2 = LIST_FIRST(&session->ikev1_state.ph2tree); iph2; iph2 = LIST_NEXT(iph2, ph2ofsession_chain)) {
1292 if (iph2->status == PHASE2ST_ESTABLISHED) {
1293 isakmp_info_send_d2(iph2);
1294 }
1295 isakmp_ph2expire(iph2); // iph2 will go down 1 second later.
1296 ike_session_stopped_by_controller(session, reason);
1297 }
1298
1299 // do the ph1s last.
1300 for (iph1 = LIST_FIRST(&session->ikev1_state.ph1tree); iph1; iph1 = LIST_NEXT(iph1, ph1ofsession_chain)) {
1301 if (iph1->status == PHASE1ST_ESTABLISHED) {
1302 isakmp_info_send_d1(iph1);
1303 }
1304 isakmp_ph1expire(iph1);
1305 }
1306
1307 // send ipsecManager a notification
1308 if (session->is_cisco_ipsec && reason && reason != ike_session_stopped_by_vpn_disconnect) {
1309 u_int32_t address;
1310 if (((struct sockaddr *)&session->session_id.remote)->sa_family == AF_INET) {
1311 address = ((struct sockaddr_in *)&session->session_id.remote)->sin_addr.s_addr;
1312 } else {
1313 address = 0;
1314 }
1315 // TODO: log
1316 if (reason == ike_session_stopped_by_idle) {
1317 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_IDLE_TIMEOUT, FROM_LOCAL, address, 0, NULL);
1318 } else {
1319 (void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_INTERNAL_ERROR, FROM_LOCAL, address, 0, NULL);
1320 }
1321 }
1322 }
1323
1324 int
1325 ike_session_has_negoing_ph1 (ike_session_t *session)
1326 {
1327 struct ph1handle *p;
1328
1329 if (!session) {
1330 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1331 return 0;
1332 }
1333
1334 for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = LIST_NEXT(p, ph1ofsession_chain)) {
1335 if (!p->is_dying && p->status >= PHASE1ST_START && p->status <= PHASE1ST_ESTABLISHED) {
1336 return 1;
1337 }
1338 }
1339
1340 return 0;
1341 }
1342
1343 int
1344 ike_session_has_established_ph1 (ike_session_t *session)
1345 {
1346 struct ph1handle *p;
1347
1348 if (!session) {
1349 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1350 return 0;
1351 }
1352
1353 for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = LIST_NEXT(p, ph1ofsession_chain)) {
1354 if (!p->is_dying && p->status == PHASE1ST_ESTABLISHED) {
1355 return 1;
1356 }
1357 }
1358
1359 return 0;
1360 }
1361
1362 int
1363 ike_session_has_negoing_ph2 (ike_session_t *session)
1364 {
1365 struct ph2handle *p;
1366
1367 if (!session) {
1368 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1369 return 0;
1370 }
1371
1372 for (p = LIST_FIRST(&session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
1373 if (!p->is_dying && p->status >= PHASE2ST_START && p->status <= PHASE2ST_ESTABLISHED) {
1374 return 1;
1375 }
1376 }
1377
1378 return 0;
1379 }
1380
1381 int
1382 ike_session_has_established_ph2 (ike_session_t *session)
1383 {
1384 struct ph2handle *p;
1385
1386 if (!session) {
1387 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1388 return 0;
1389 }
1390
1391 for (p = LIST_FIRST(&session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
1392 if (!p->is_dying && p->status == PHASE2ST_ESTABLISHED) {
1393 return 1;
1394 }
1395 }
1396
1397 return 0;
1398 }
1399
1400 void
1401 ike_session_cleanup_ph1s_by_ph2 (struct ph2handle *iph2)
1402 {
1403 struct ph1handle *iph1;
1404
1405 if (!iph2 || !iph2->parent_session) {
1406 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1407 return;
1408 }
1409
1410 // phase1 is no longer useful
1411 for (iph1 = LIST_FIRST(&iph2->parent_session->ikev1_state.ph1tree); iph1; iph1 = LIST_NEXT(iph1, ph1ofsession_chain)) {
1412 if (iph1->status == PHASE1ST_ESTABLISHED) {
1413 isakmp_info_send_d1(iph1);
1414 }
1415 isakmp_ph1expire(iph1);
1416 }
1417 }
1418
1419 int
1420 ike_session_is_client_ph2_rekey (struct ph2handle *iph2)
1421 {
1422 if (iph2->parent_session &&
1423 iph2->parent_session->is_client &&
1424 iph2->is_rekey &&
1425 iph2->parent_session->is_cisco_ipsec) {
1426 return 1;
1427 }
1428 return 0;
1429 }
1430
1431 int
1432 ike_session_is_client_ph1_rekey (struct ph1handle *iph1)
1433 {
1434 if (iph1->parent_session &&
1435 iph1->parent_session->is_client &&
1436 iph1->is_rekey &&
1437 iph1->parent_session->is_cisco_ipsec) {
1438 return 1;
1439 }
1440 return 0;
1441 }
1442
1443 void
1444 ike_session_start_xauth_timer (struct ph1handle *iph1)
1445 {
1446 // if there are no more established ph2s, start a timer to teardown the session
1447 if (iph1->parent_session &&
1448 iph1->parent_session->is_client &&
1449 iph1->parent_session->is_cisco_ipsec &&
1450 !iph1->parent_session->sc_xauth) {
1451 iph1->parent_session->sc_xauth = sched_new(300 /* 5 mins */,
1452 ike_session_cleanup_xauth_timeout,
1453 iph1->parent_session);
1454 }
1455 }
1456
1457 void
1458 ike_session_stop_xauth_timer (struct ph1handle *iph1)
1459 {
1460 if (iph1->parent_session) {
1461 SCHED_KILL(iph1->parent_session->sc_xauth);
1462 }
1463 }
1464
1465 static int
1466 ike_session_is_id_ipany (vchar_t *ext_id)
1467 {
1468 struct id {
1469 u_int8_t type; /* ID Type */
1470 u_int8_t proto_id; /* Protocol ID */
1471 u_int16_t port; /* Port */
1472 u_int32_t addr; /* IPv4 address */
1473 u_int32_t mask;
1474 } *id_ptr;
1475
1476 /* ignore protocol and port */
1477 id_ptr = (struct id *)ext_id->v;
1478 if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR &&
1479 id_ptr->addr == 0) {
1480 return 1;
1481 } else if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR_SUBNET &&
1482 id_ptr->mask == 0 &&
1483 id_ptr->addr == 0) {
1484 return 1;
1485 }
1486 plog(LLV_DEBUG2, LOCATION, NULL, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
1487 __FUNCTION__, id_ptr->type, id_ptr->addr, id_ptr->mask);
1488 return 0;
1489 }
1490
1491 static int
1492 ike_session_is_id_portany (vchar_t *ext_id)
1493 {
1494 struct id {
1495 u_int8_t type; /* ID Type */
1496 u_int8_t proto_id; /* Protocol ID */
1497 u_int16_t port; /* Port */
1498 u_int32_t addr; /* IPv4 address */
1499 u_int32_t mask;
1500 } *id_ptr;
1501
1502 /* ignore addr */
1503 id_ptr = (struct id *)ext_id->v;
1504 if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR &&
1505 id_ptr->port == 0) {
1506 return 1;
1507 }
1508 plog(LLV_DEBUG2, LOCATION, NULL, "not portany_ids in %s: type %d, port %x.\n",
1509 __FUNCTION__, id_ptr->type, id_ptr->port);
1510 return 0;
1511 }
1512
1513 static void
1514 ike_session_set_id_portany (vchar_t *ext_id)
1515 {
1516 struct id {
1517 u_int8_t type; /* ID Type */
1518 u_int8_t proto_id; /* Protocol ID */
1519 u_int16_t port; /* Port */
1520 u_int32_t addr; /* IPv4 address */
1521 u_int32_t mask;
1522 } *id_ptr;
1523
1524 /* ignore addr */
1525 id_ptr = (struct id *)ext_id->v;
1526 if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR) {
1527 id_ptr->port = 0;
1528 return;
1529 }
1530 }
1531
1532 static int
1533 ike_session_cmp_ph2_ids_ipany (vchar_t *ext_id,
1534 vchar_t *ext_id_p)
1535 {
1536 if (ike_session_is_id_ipany(ext_id) &&
1537 ike_session_is_id_ipany(ext_id_p)) {
1538 return 1;
1539 }
1540 return 0;
1541 }
1542
1543 /*
1544 * ipsec rekeys for l2tp-over-ipsec fail particularly when client is behind nat because the client's configs and policies don't
1545 * match the server's view of the client's address and port.
1546 * servers behave differently when using this address-port info to generate ids during phase2 rekeys, so try to match the incoming id to
1547 * a variety of info saved in the older phase2.
1548 */
1549 int
1550 ike_session_cmp_ph2_ids (struct ph2handle *iph2,
1551 struct ph2handle *older_ph2)
1552 {
1553 vchar_t *portany_id = NULL;
1554 vchar_t *portany_id_p = NULL;
1555
1556 if (iph2->id && older_ph2->id &&
1557 iph2->id->l == older_ph2->id->l &&
1558 memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
1559 iph2->id_p && older_ph2->id_p &&
1560 iph2->id_p->l == older_ph2->id_p->l &&
1561 memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) {
1562 return 0;
1563 }
1564 if (iph2->ext_nat_id && older_ph2->ext_nat_id &&
1565 iph2->ext_nat_id->l == older_ph2->ext_nat_id->l &&
1566 memcmp(iph2->ext_nat_id->v, older_ph2->ext_nat_id->v, iph2->ext_nat_id->l) == 0 &&
1567 iph2->ext_nat_id_p && older_ph2->ext_nat_id_p &&
1568 iph2->ext_nat_id_p->l == older_ph2->ext_nat_id_p->l &&
1569 memcmp(iph2->ext_nat_id_p->v, older_ph2->ext_nat_id_p->v, iph2->ext_nat_id_p->l) == 0) {
1570 return 0;
1571 }
1572 if (iph2->id && older_ph2->ext_nat_id &&
1573 iph2->id->l == older_ph2->ext_nat_id->l &&
1574 memcmp(iph2->id->v, older_ph2->ext_nat_id->v, iph2->id->l) == 0 &&
1575 iph2->id_p && older_ph2->ext_nat_id_p &&
1576 iph2->id_p->l == older_ph2->ext_nat_id_p->l &&
1577 memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) {
1578 return 0;
1579 }
1580 if (iph2->id && older_ph2->ext_nat_id &&
1581 iph2->id->l == older_ph2->ext_nat_id->l &&
1582 memcmp(iph2->id->v, older_ph2->ext_nat_id->v, iph2->id->l) == 0 &&
1583 iph2->id_p && older_ph2->id_p &&
1584 iph2->id_p->l == older_ph2->id_p->l &&
1585 memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) {
1586 return 0;
1587 }
1588 if (iph2->id && older_ph2->id &&
1589 iph2->id->l == older_ph2->id->l &&
1590 memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
1591 iph2->id_p && older_ph2->ext_nat_id_p &&
1592 iph2->id_p->l == older_ph2->ext_nat_id_p->l &&
1593 memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) {
1594 return 0;
1595 }
1596
1597 /* check if the external id has a wildcard port and compare ids accordingly */
1598 if ((older_ph2->ext_nat_id && ike_session_is_id_portany(older_ph2->ext_nat_id)) ||
1599 (older_ph2->ext_nat_id_p && ike_session_is_id_portany(older_ph2->ext_nat_id_p))) {
1600 // try ignoring ports in iph2->id and iph2->id
1601 if (iph2->id && (portany_id = vdup(iph2->id))) {
1602 ike_session_set_id_portany(portany_id);
1603 }
1604 if (iph2->id_p && (portany_id_p = vdup(iph2->id_p))) {
1605 ike_session_set_id_portany(portany_id_p);
1606 }
1607 if (portany_id && older_ph2->ext_nat_id &&
1608 portany_id->l == older_ph2->ext_nat_id->l &&
1609 memcmp(portany_id->v, older_ph2->ext_nat_id->v, portany_id->l) == 0 &&
1610 portany_id_p && older_ph2->ext_nat_id_p &&
1611 portany_id_p->l == older_ph2->ext_nat_id_p->l &&
1612 memcmp(portany_id_p->v, older_ph2->ext_nat_id_p->v, portany_id_p->l) == 0) {
1613 if (portany_id) {
1614 vfree(portany_id);
1615 }
1616 if (portany_id_p) {
1617 vfree(portany_id_p);
1618 }
1619 return 0;
1620 }
1621 if (portany_id && iph2->id && older_ph2->ext_nat_id &&
1622 iph2->id->l == older_ph2->ext_nat_id->l &&
1623 memcmp(portany_id->v, older_ph2->ext_nat_id->v, portany_id->l) == 0 &&
1624 iph2->id_p && older_ph2->id_p &&
1625 iph2->id_p->l == older_ph2->id_p->l &&
1626 memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) {
1627 if (portany_id) {
1628 vfree(portany_id);
1629 }
1630 if (portany_id_p) {
1631 vfree(portany_id_p);
1632 }
1633 return 0;
1634 }
1635 if (portany_id_p && iph2->id && older_ph2->id &&
1636 iph2->id->l == older_ph2->id->l &&
1637 memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
1638 iph2->id_p && older_ph2->ext_nat_id_p &&
1639 iph2->id_p->l == older_ph2->ext_nat_id_p->l &&
1640 memcmp(portany_id_p->v, older_ph2->ext_nat_id_p->v, portany_id_p->l) == 0) {
1641 if (portany_id) {
1642 vfree(portany_id);
1643 }
1644 if (portany_id_p) {
1645 vfree(portany_id_p);
1646 }
1647 return 0;
1648 }
1649 if (portany_id) {
1650 vfree(portany_id);
1651 }
1652 if (portany_id_p) {
1653 vfree(portany_id_p);
1654 }
1655 }
1656 return -1;
1657 }
1658
1659 int
1660 ike_session_get_sainfo_r (struct ph2handle *iph2)
1661 {
1662 if (iph2->parent_session &&
1663 iph2->parent_session->is_client &&
1664 iph2->id && iph2->id_p) {
1665 struct ph2handle *p;
1666 int ipany_ids = ike_session_cmp_ph2_ids_ipany(iph2->id, iph2->id_p);
1667 plog(LLV_DEBUG2, LOCATION, NULL, "ipany_ids %d in %s.\n", ipany_ids, __FUNCTION__);
1668
1669 for (p = LIST_FIRST(&iph2->parent_session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
1670 if (iph2 != p && !p->is_dying && p->status >= PHASE2ST_ESTABLISHED &&
1671 p->sainfo && !p->sainfo->to_delete && !p->sainfo->to_remove) {
1672 plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 found in %s.\n", __FUNCTION__);
1673 if (ipany_ids ||
1674 ike_session_cmp_ph2_ids(iph2, p) == 0) {
1675 plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 matched in %s.\n", __FUNCTION__);
1676 iph2->sainfo = p->sainfo;
1677 if (!iph2->spid) {
1678 iph2->spid = p->spid;
1679 } else {
1680 plog(LLV_DEBUG2, LOCATION, NULL, "%s: pre-assigned spid %d.\n", __FUNCTION__, iph2->spid);
1681 }
1682 if (p->ext_nat_id) {
1683 if (iph2->ext_nat_id) {
1684 vfree(iph2->ext_nat_id);
1685 }
1686 iph2->ext_nat_id = vdup(p->ext_nat_id);
1687 }
1688 if (p->ext_nat_id_p) {
1689 if (iph2->ext_nat_id_p) {
1690 vfree(iph2->ext_nat_id_p);
1691 }
1692 iph2->ext_nat_id_p = vdup(p->ext_nat_id_p);
1693 }
1694 return 0;
1695 }
1696 }
1697 }
1698 }
1699 return -1;
1700 }
1701
1702 int
1703 ike_session_get_proposal_r (struct ph2handle *iph2)
1704 {
1705 if (iph2->parent_session &&
1706 iph2->parent_session->is_client &&
1707 iph2->id && iph2->id_p) {
1708 struct ph2handle *p;
1709 int ipany_ids = ike_session_cmp_ph2_ids_ipany(iph2->id, iph2->id_p);
1710 plog(LLV_DEBUG2, LOCATION, NULL, "ipany_ids %d in %s.\n", ipany_ids, __FUNCTION__);
1711
1712 for (p = LIST_FIRST(&iph2->parent_session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
1713 if (iph2 != p && !p->is_dying && p->status >= PHASE2ST_ESTABLISHED &&
1714 p->approval) {
1715 plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 found in %s.\n", __FUNCTION__);
1716 if (ipany_ids ||
1717 ike_session_cmp_ph2_ids(iph2, p) == 0) {
1718 plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 matched in %s.\n", __FUNCTION__);
1719 iph2->proposal = dupsaprop(p->approval, 1);
1720 if (!iph2->spid) {
1721 iph2->spid = p->spid;
1722 } else {
1723 plog(LLV_DEBUG2, LOCATION, NULL, "%s: pre-assigned spid %d.\n", __FUNCTION__, iph2->spid);
1724 }
1725 return 0;
1726 }
1727 }
1728 }
1729 }
1730 return -1;
1731 }
1732
1733 void
1734 ike_session_update_natt_version (struct ph1handle *iph1)
1735 {
1736 if (iph1->parent_session) {
1737 if (iph1->natt_options) {
1738 iph1->parent_session->natt_version = iph1->natt_options->version;
1739 } else {
1740 iph1->parent_session->natt_version = 0;
1741 }
1742 }
1743 }
1744
1745 int
1746 ike_session_get_natt_version (struct ph1handle *iph1)
1747 {
1748 if (iph1->parent_session) {
1749 return(iph1->parent_session->natt_version);
1750 }
1751 return 0;
1752 }
1753
1754 int
1755 ike_session_drop_rekey (ike_session_t *session, ike_session_rekey_type_t rekey_type)
1756 {
1757 if (session) {
1758 if (session->is_btmm_ipsec &&
1759 session->last_time_data_sc_detected &&
1760 session->traffic_monitor.interv_mon &&
1761 session->traffic_monitor.interv_idle) {
1762 // for btmm: drop ph1/ph2 rekey if session is idle
1763 time_t now = time(NULL);
1764
1765 if ((now - session->last_time_data_sc_detected) > (session->traffic_monitor.interv_mon << 1)) {
1766 plog(LLV_DEBUG2, LOCATION, NULL, "btmm session is idle: drop ph%drekey.\n",
1767 rekey_type);
1768 return 1;
1769 }
1770 } else if (!session->is_btmm_ipsec) {
1771 if (rekey_type == IKE_SESSION_REKEY_TYPE_PH1 &&
1772 !ike_session_has_negoing_ph2(session)) {
1773 // for vpn: only drop ph1 if there are no more ph2s.
1774 plog(LLV_DEBUG2, LOCATION, NULL, "vpn session is idle: drop ph1 rekey.\n");
1775 return 1;
1776 }
1777 }
1778 }
1779 return 0;
1780 }
1781
1782 /*
1783 * this is called after racooon receives a 'kIOMessageSystemHasPoweredOn'
1784 * a lot is done to make sure that we don't sweep a session that's already been asserted.
1785 * however, it'll be too bad if the assertion comes after the session has already been swept.
1786 */
1787 void
1788 ike_session_sweep_sleepwake (void)
1789 {
1790 ike_session_t *p;
1791
1792 // flag session as dying if all ph1/ph2 are dead/dying
1793 for (p = LIST_FIRST(&ike_session_tree); p; p = LIST_NEXT(p, chain)) {
1794 if (p->is_dying) {
1795 plog(LLV_DEBUG2, LOCATION, NULL, "skipping sweep of dying session.\n");
1796 continue;
1797 }
1798 SCHED_KILL(p->sc_xauth);
1799 if (p->is_asserted) {
1800 // for asserted session, traffic monitors will be restared after phase2 becomes established.
1801 SCHED_KILL(p->traffic_monitor.sc_mon);
1802 SCHED_KILL(p->traffic_monitor.sc_idle);
1803 plog(LLV_DEBUG2, LOCATION, NULL, "skipping sweep of asserted session.\n");
1804 continue;
1805 }
1806
1807 // cleanup any stopped sessions as they will go down
1808 if (p->stopped_by_vpn_controller || p->stop_timestamp.tv_sec || p->stop_timestamp.tv_usec) {
1809 plog(LLV_DEBUG2, LOCATION, NULL, "sweeping stopped session.\n");
1810 ike_session_cleanup(p, ike_session_stopped_by_sleepwake);
1811 continue;
1812 }
1813
1814 if (!ike_session_has_established_ph1(p) && !ike_session_has_established_ph2(p)) {
1815 plog(LLV_DEBUG2, LOCATION, NULL, "session died while sleeping.\n");
1816 ike_session_cleanup(p, ike_session_stopped_by_sleepwake);
1817 }
1818 if (p->traffic_monitor.sc_mon) {
1819 if (p->traffic_monitor.sc_mon->xtime <= swept_at) {
1820 SCHED_KILL(p->traffic_monitor.sc_mon);
1821 if (!p->is_dying && p->traffic_monitor.interv_mon) {
1822 p->traffic_monitor.sc_mon = sched_new(p->traffic_monitor.interv_mon,
1823 ike_session_traffic_cop,
1824 p);
1825 }
1826 }
1827 }
1828 if (p->traffic_monitor.sc_idle) {
1829 if (p->traffic_monitor.sc_idle->xtime <= swept_at) {
1830 SCHED_KILL(p->traffic_monitor.sc_idle);
1831 if (!p->is_dying && p->traffic_monitor.interv_idle) {
1832 p->traffic_monitor.sc_idle = sched_new(p->traffic_monitor.interv_idle,
1833 ike_session_cleanup_idle,
1834 p);
1835 }
1836 }
1837 }
1838 }
1839 }
1840
1841 /*
1842 * this is called after racooon receives an assert command from the controller/pppd.
1843 * this is intended to make racoon prepare to rekey both SAs because a network event occurred.
1844 * in the event of a sleepwake, the assert could happen before or after 'ike_session_sweep_sleepwake'.
1845 */
1846 int
1847 ike_session_assert_session (ike_session_t *session)
1848 {
1849 struct ph2handle *iph2, *iph2_next;
1850 struct ph1handle *iph1, *iph1_next;
1851
1852 if (!session || session->is_dying) {
1853 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1854 return -1;
1855 }
1856
1857 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase2s
1858 for (iph2 = LIST_FIRST(&session->ikev1_state.ph2tree); iph2; iph2 = iph2_next) {
1859 // take next pointer now, since delete change the underlying ph2tree list
1860 iph2_next = LIST_NEXT(iph2, ph2ofsession_chain);
1861 if (!iph2->is_dying && iph2->status < PHASE2ST_EXPIRED) {
1862 SCHED_KILL(iph2->sce);
1863 iph2->is_dying = 1;
1864
1865 // delete SAs (in the kernel)
1866 if (iph2->status == PHASE2ST_ESTABLISHED && iph2->approval) {
1867 struct saproto *pr;
1868
1869 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1870 if (pr->ok) {
1871 //log deletion
1872 plog(LLV_DEBUG, LOCATION, NULL,
1873 "assert: phase2 %s deleted\n",
1874 sadbsecas2str(iph2->src, iph2->dst, iph2->satype, iph2->spid, ipsecdoi2pfkey_mode(pr->encmode)));
1875
1876 pfkey_send_delete(lcconf->sock_pfkey,
1877 ipsecdoi2pfkey_proto(pr->proto_id),
1878 ipsecdoi2pfkey_mode(pr->encmode),
1879 iph2->src, iph2->dst, pr->spi_p);
1880 }
1881 }
1882 }
1883
1884 iph2->status = PHASE2ST_EXPIRED; // we want to delete SAs without telling the PEER
1885 iph2->sce = sched_new(3, ike_session_cleanup_ph2_stub, iph2);
1886 }
1887 }
1888
1889 // the goal is to prepare the session for fresh rekeys by silently deleting the currently active phase1s
1890 for (iph1 = LIST_FIRST(&session->ikev1_state.ph1tree); iph1; iph1 = iph1_next) {
1891 // take next pointer now, since delete change the underlying ph1tree list
1892 iph1_next = LIST_NEXT(iph1, ph1ofsession_chain);
1893 if (!iph1->is_dying && iph1->status < PHASE1ST_EXPIRED) {
1894 SCHED_KILL(iph1->sce);
1895 SCHED_KILL(iph1->sce_rekey);
1896 iph1->is_dying = 1;
1897
1898 //log deletion
1899 plog(LLV_DEBUG, LOCATION, NULL,
1900 "assert: phase1 %s deleted\n",
1901 isakmp_pindex(&iph1->index, 0));
1902
1903 ike_session_unbindph12_from_ph1(iph1);
1904
1905 iph1->status = PHASE1ST_EXPIRED; // we want to delete SAs without telling the PEER
1906 /* responder sets up timer to delete old inbound SAs... say 7 secs later and flags them as rekeyed */
1907 iph1->sce = sched_new(5, ike_session_cleanup_ph1_stub, iph1);
1908 }
1909 }
1910 session->is_asserted = 1;
1911
1912 return 0;
1913 }
1914
1915 int
1916 ike_session_assert (struct sockaddr *local,
1917 struct sockaddr *remote)
1918 {
1919 ike_session_t *sess;
1920
1921 if (!local || !remote) {
1922 plog(LLV_DEBUG2, LOCATION, NULL, "invalid parameters in %s.\n", __FUNCTION__);
1923 return -1;
1924 }
1925
1926 if ((sess = ike_session_get_session(local, remote, FALSE))) {
1927 return(ike_session_assert_session(sess));
1928 }
1929 return -1;
1930 }
1931
1932 void
1933 ike_session_ph2_retransmits (struct ph2handle *iph2)
1934 {
1935 int num_retransmits;
1936
1937 if (!iph2->is_dying &&
1938 iph2->is_rekey &&
1939 iph2->ph1 &&
1940 iph2->ph1->sce_rekey && !iph2->ph1->sce_rekey->dead &&
1941 iph2->side == INITIATOR &&
1942 iph2->parent_session &&
1943 !iph2->parent_session->is_cisco_ipsec && /* not for Cisco */
1944 iph2->parent_session->is_client) {
1945 num_retransmits = iph2->ph1->rmconf->retry_counter - iph2->retry_counter;
1946 if (num_retransmits == 3) {
1947 /*
1948 * phase2 negotiation is stalling on retransmits, inspite of a valid ph1.
1949 * one of the following is possible:
1950 * - (0) severe packet loss.
1951 * - (1) the peer is dead.
1952 * - (2) the peer is out of sync hence dropping this phase2 rekey (and perhaps responding with insecure
1953 * invalid-cookie notifications... but those are untrusted and so we can't rekey phase1 off that)
1954 * (2.1) the peer rebooted (or process restarted) and is now alive.
1955 * (2.2) the peer has deleted phase1 without notifying us (or the notification got dropped somehow).
1956 * (2.3) the peer has a policy/bug stopping this phase2 rekey
1957 *
1958 * in all these cases, one sure way to know is to trigger a phase1 rekey early.
1959 */
1960 plog(LLV_DEBUG2, LOCATION, NULL, "many phase2 retransmits: try phase1 rekey and this phase2 to quit earlier.\n");
1961 isakmp_ph1rekeyexpire(iph2->ph1, TRUE);
1962 iph2->retry_counter = 0;
1963 }
1964 }
1965 }
1966
1967 void
1968 ike_session_ph1_retransmits (struct ph1handle *iph1)
1969 {
1970 int num_retransmits;
1971
1972 if (!iph1->is_dying &&
1973 iph1->is_rekey &&
1974 !iph1->sce_rekey &&
1975 iph1->status >= PHASE1ST_START && iph1->status < PHASE1ST_ESTABLISHED &&
1976 iph1->side == INITIATOR &&
1977 iph1->parent_session &&
1978 iph1->parent_session->is_client &&
1979 !ike_session_has_other_negoing_ph1(iph1->parent_session, iph1)) {
1980 num_retransmits = iph1->rmconf->retry_counter - iph1->retry_counter;
1981 if (num_retransmits == 3) {
1982 plog(LLV_DEBUG2, LOCATION, NULL, "many phase1 retransmits: try quit earlier.\n");
1983 iph1->retry_counter = 0;
1984 }
1985 }
1986 }