Moving charon to libcharon.
[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 <daemon.h>
19
20 typedef struct private_inactivity_job_t private_inactivity_job_t;
21
22 /**
23 * Private data of an inactivity_job_t object.
24 */
25 struct private_inactivity_job_t {
26
27 /**
28 * Public inactivity_job_t interface.
29 */
30 inactivity_job_t public;
31
32 /**
33 * Reqid of CHILD_SA to check
34 */
35 u_int32_t reqid;
36
37 /**
38 * Inactivity timeout
39 */
40 u_int32_t timeout;
41
42 /**
43 * Close IKE_SA if last remaining CHILD inactive?
44 */
45 bool close_ike;
46 };
47
48 METHOD(job_t, destroy, void,
49 private_inactivity_job_t *this)
50 {
51 free(this);
52 }
53
54 METHOD(job_t, execute, void,
55 private_inactivity_job_t *this)
56 {
57 ike_sa_t *ike_sa;
58 bool rescheduled = FALSE;
59
60 ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
61 this->reqid, TRUE);
62 if (ike_sa)
63 {
64 iterator_t *iterator;
65 child_sa_t *child_sa;
66 u_int32_t delete = 0;
67 protocol_id_t proto = 0;
68 int children = 0;
69 status_t status = SUCCESS;
70
71 iterator = ike_sa->create_child_sa_iterator(ike_sa);
72 while (iterator->iterate(iterator, (void**)&child_sa))
73 {
74 if (child_sa->get_reqid(child_sa) == this->reqid)
75 {
76 time_t in, out, diff;
77
78 child_sa->get_usestats(child_sa, TRUE, &in, NULL);
79 child_sa->get_usestats(child_sa, FALSE, &out, NULL);
80
81 diff = time_monotonic(NULL) - max(in, out);
82
83 if (diff >= this->timeout)
84 {
85 delete = child_sa->get_spi(child_sa, TRUE);
86 proto = child_sa->get_protocol(child_sa);
87 }
88 else
89 {
90 charon->scheduler->schedule_job(charon->scheduler,
91 &this->public.job_interface, this->timeout - diff);
92 rescheduled = TRUE;
93 }
94 }
95 children++;
96 }
97 iterator->destroy(iterator);
98
99 if (delete)
100 {
101 if (children == 1 && this->close_ike)
102 {
103 DBG1(DBG_JOB, "deleting IKE_SA after %d seconds "
104 "of CHILD_SA inactivity", this->timeout);
105 status = ike_sa->delete(ike_sa);
106 }
107 else
108 {
109 DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds "
110 "of inactivity", this->timeout);
111 status = ike_sa->delete_child_sa(ike_sa, proto, delete);
112 }
113 }
114 if (status == DESTROY_ME)
115 {
116 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
117 ike_sa);
118 }
119 else
120 {
121 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
122 }
123 }
124 if (!rescheduled)
125 {
126 destroy(this);
127 }
128 }
129
130 /**
131 * See header
132 */
133 inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout,
134 bool close_ike)
135 {
136 private_inactivity_job_t *this;
137
138 INIT(this,
139 .public.job_interface = {
140 .execute = _execute,
141 .destroy = _destroy,
142 },
143 .reqid = reqid,
144 .timeout = timeout,
145 .close_ike = close_ike,
146 );
147
148 return &this->public;
149 }
150