Refer to scheduler via hydra and not charon.
[strongswan.git] / src / libcharon / processing / jobs / inactivity_job.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "inactivity_job.h"
17
18 #include <hydra.h>
19 #include <daemon.h>
20
21 typedef struct private_inactivity_job_t private_inactivity_job_t;
22
23 /**
24 * Private data of an inactivity_job_t object.
25 */
26 struct private_inactivity_job_t {
27
28 /**
29 * Public inactivity_job_t interface.
30 */
31 inactivity_job_t public;
32
33 /**
34 * Reqid of CHILD_SA to check
35 */
36 u_int32_t reqid;
37
38 /**
39 * Inactivity timeout
40 */
41 u_int32_t timeout;
42
43 /**
44 * Close IKE_SA if last remaining CHILD inactive?
45 */
46 bool close_ike;
47 };
48
49 METHOD(job_t, destroy, void,
50 private_inactivity_job_t *this)
51 {
52 free(this);
53 }
54
55 METHOD(job_t, execute, void,
56 private_inactivity_job_t *this)
57 {
58 ike_sa_t *ike_sa;
59 bool rescheduled = FALSE;
60
61 ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
62 this->reqid, TRUE);
63 if (ike_sa)
64 {
65 iterator_t *iterator;
66 child_sa_t *child_sa;
67 u_int32_t delete = 0;
68 protocol_id_t proto = 0;
69 int children = 0;
70 status_t status = SUCCESS;
71
72 iterator = ike_sa->create_child_sa_iterator(ike_sa);
73 while (iterator->iterate(iterator, (void**)&child_sa))
74 {
75 if (child_sa->get_reqid(child_sa) == this->reqid)
76 {
77 time_t in, out, diff;
78
79 child_sa->get_usestats(child_sa, TRUE, &in, NULL);
80 child_sa->get_usestats(child_sa, FALSE, &out, NULL);
81
82 diff = time_monotonic(NULL) - max(in, out);
83
84 if (diff >= this->timeout)
85 {
86 delete = child_sa->get_spi(child_sa, TRUE);
87 proto = child_sa->get_protocol(child_sa);
88 }
89 else
90 {
91 hydra->scheduler->schedule_job(hydra->scheduler,
92 &this->public.job_interface, this->timeout - diff);
93 rescheduled = TRUE;
94 }
95 }
96 children++;
97 }
98 iterator->destroy(iterator);
99
100 if (delete)
101 {
102 if (children == 1 && this->close_ike)
103 {
104 DBG1(DBG_JOB, "deleting IKE_SA after %d seconds "
105 "of CHILD_SA inactivity", this->timeout);
106 status = ike_sa->delete(ike_sa);
107 }
108 else
109 {
110 DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds "
111 "of inactivity", this->timeout);
112 status = ike_sa->delete_child_sa(ike_sa, proto, delete);
113 }
114 }
115 if (status == DESTROY_ME)
116 {
117 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
118 ike_sa);
119 }
120 else
121 {
122 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
123 }
124 }
125 if (!rescheduled)
126 {
127 destroy(this);
128 }
129 }
130
131 /**
132 * See header
133 */
134 inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout,
135 bool close_ike)
136 {
137 private_inactivity_job_t *this;
138
139 INIT(this,
140 .public = {
141 .job_interface = {
142 .execute = _execute,
143 .destroy = _destroy,
144 },
145 },
146 .reqid = reqid,
147 .timeout = timeout,
148 .close_ike = close_ike,
149 );
150
151 return &this->public;
152 }
153