aboutsummaryrefslogtreecommitdiffstats
path: root/main/strongswan/0202-controller-Optionally-adhere-to-init-limits-also-whe.patch
blob: fbc54c11c4206159b28594fffe0a333e46f959b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
From 0d6412ab81fbf0376cc99e9419de417e58dc0e72 Mon Sep 17 00:00:00 2001
From: Tobias Brunner <tobias@strongswan.org>
Date: Thu, 16 Jul 2015 17:21:54 +0200
Subject: [PATCH] controller: Optionally adhere to init limits also when
 initiating IKE_SAs

---
 src/charon-cmd/cmd/cmd_connection.c                |  2 +-
 src/conftest/actions.c                             |  2 +-
 src/libcharon/control/controller.c                 | 54 ++++++++++++++++++++--
 src/libcharon/control/controller.h                 |  5 +-
 .../plugins/load_tester/load_tester_control.c      |  2 +-
 .../plugins/load_tester/load_tester_plugin.c       |  2 +-
 src/libcharon/plugins/medcli/medcli_config.c       |  2 +-
 src/libcharon/plugins/smp/smp.c                    |  2 +-
 src/libcharon/plugins/stroke/stroke_control.c      |  4 +-
 src/libcharon/plugins/uci/uci_control.c            |  2 +-
 src/libcharon/plugins/vici/vici_config.c           |  2 +-
 src/libcharon/plugins/vici/vici_control.c          |  4 +-
 .../processing/jobs/initiate_mediation_job.c       |  4 +-
 src/libcharon/processing/jobs/start_action_job.c   |  2 +-
 15 files changed, 71 insertions(+), 20 deletions(-)

diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
index 2c0b7b9..0c6a504 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -434,7 +434,7 @@ static job_requeue_t initiate(private_cmd_connection_t *this)
 	child_cfg = create_child_cfg(this, peer_cfg);
 
 	if (charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
-									 controller_cb_empty, NULL, 0) != SUCCESS)
+								controller_cb_empty, NULL, 0, FALSE) != SUCCESS)
 	{
 		terminate(pid);
 	}
diff --git a/src/conftest/actions.c b/src/conftest/actions.c
index 474672c..256b63d 100644
--- a/src/conftest/actions.c
+++ b/src/conftest/actions.c
@@ -65,7 +65,7 @@ static job_requeue_t initiate(char *config)
 	{
 		DBG1(DBG_CFG, "initiating IKE_SA for CHILD_SA config '%s'", config);
 		charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
-									 NULL, NULL, 0);
+									 NULL, NULL, 0, FALSE);
 	}
 	else
 	{
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
index fd8349e..097f5ac 100644
--- a/src/libcharon/control/controller.c
+++ b/src/libcharon/control/controller.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Tobias Brunner
+ * Copyright (C) 2011-2015 Tobias Brunner
  * Copyright (C) 2007-2011 Martin Willi
  * Copyright (C) 2011 revosec AG
  * Hochschule fuer Technik Rapperswil
@@ -116,6 +116,11 @@ struct interface_listener_t {
 	 * spinlock to update the IKE_SA handle properly
 	 */
 	spinlock_t *lock;
+
+	/**
+	 * whether to check limits
+	 */
+	bool limits;
 };
 
 
@@ -358,7 +363,6 @@ METHOD(job_t, initiate_execute, job_requeue_t,
 		listener->child_cfg->destroy(listener->child_cfg);
 		peer_cfg->destroy(peer_cfg);
 		listener->status = FAILED;
-		/* release listener */
 		listener_done(listener);
 		return JOB_REQUEUE_NONE;
 	}
@@ -372,6 +376,49 @@ METHOD(job_t, initiate_execute, job_requeue_t,
 	}
 	peer_cfg->destroy(peer_cfg);
 
+	if (listener->limits && ike_sa->get_state(ike_sa) == IKE_CREATED)
+	{	/* only check if we are not reusing an IKE_SA */
+		u_int half_open, limit_half_open, limit_job_load;
+
+		half_open = charon->ike_sa_manager->get_half_open_count(
+										charon->ike_sa_manager, NULL);
+		limit_half_open = lib->settings->get_int(lib->settings,
+										"%s.init_limit_half_open", 0, lib->ns);
+		limit_job_load = lib->settings->get_int(lib->settings,
+										"%s.init_limit_job_load", 0, lib->ns);
+		if (limit_half_open && half_open >= limit_half_open)
+		{
+			DBG1(DBG_IKE, "abort IKE_SA initiation, half open IKE_SA count of "
+				 "%d exceeds limit of %d", half_open, limit_half_open);
+			charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+														ike_sa);
+			listener->child_cfg->destroy(listener->child_cfg);
+			listener->status = INVALID_STATE;
+			listener_done(listener);
+			return JOB_REQUEUE_NONE;
+		}
+		if (limit_job_load)
+		{
+			u_int jobs = 0, i;
+
+			for (i = 0; i < JOB_PRIO_MAX; i++)
+			{
+				jobs += lib->processor->get_job_load(lib->processor, i);
+			}
+			if (jobs > limit_job_load)
+			{
+				DBG1(DBG_IKE, "abort IKE_SA initiation, job load of %d exceeds "
+					 "limit of %d", jobs, limit_job_load);
+				charon->ike_sa_manager->checkin_and_destroy(
+												charon->ike_sa_manager, ike_sa);
+				listener->child_cfg->destroy(listener->child_cfg);
+				listener->status = INVALID_STATE;
+				listener_done(listener);
+				return JOB_REQUEUE_NONE;
+			}
+		}
+	}
+
 	if (ike_sa->initiate(ike_sa, listener->child_cfg, 0, NULL, NULL) == SUCCESS)
 	{
 		if (!listener->logger.callback)
@@ -391,7 +438,7 @@ METHOD(job_t, initiate_execute, job_requeue_t,
 
 METHOD(controller_t, initiate, status_t,
 	private_controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
-	controller_cb_t callback, void *param, u_int timeout)
+	controller_cb_t callback, void *param, u_int timeout, bool limits)
 {
 	interface_job_t *job;
 	status_t status;
@@ -414,6 +461,7 @@ METHOD(controller_t, initiate, status_t,
 			.child_cfg = child_cfg,
 			.peer_cfg = peer_cfg,
 			.lock = spinlock_create(),
+			.limits = limits,
 		},
 		.public = {
 			.execute = _initiate_execute,
diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h
index 02f4ebb..5ffeac5 100644
--- a/src/libcharon/control/controller.h
+++ b/src/libcharon/control/controller.h
@@ -82,15 +82,18 @@ struct controller_t {
 	 * @param cb			logging callback
 	 * @param param			parameter to include in each call of cb
 	 * @param timeout		timeout in ms to wait for callbacks, 0 to disable
+	 * @param limits		whether to check limits regarding IKE_SA initiation
 	 * @return
 	 *						- SUCCESS, if CHILD_SA established
 	 *						- FAILED, if setup failed
 	 *						- NEED_MORE, if callback returned FALSE
 	 *						- OUT_OF_RES if timed out
+	 *						- INVALID_STATE if limits prevented initiation
 	 */
 	status_t (*initiate)(controller_t *this,
 						 peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
-						 controller_cb_t callback, void *param, u_int timeout);
+						 controller_cb_t callback, void *param, u_int timeout,
+						 bool limits);
 
 	/**
 	 * Terminate an IKE_SA and all of its CHILD_SAs.
diff --git a/src/libcharon/plugins/load_tester/load_tester_control.c b/src/libcharon/plugins/load_tester/load_tester_control.c
index 5f089f5..24076d4 100644
--- a/src/libcharon/plugins/load_tester/load_tester_control.c
+++ b/src/libcharon/plugins/load_tester/load_tester_control.c
@@ -239,7 +239,7 @@ static bool on_accept(private_load_tester_control_t *this, stream_t *io)
 
 		switch (charon->controller->initiate(charon->controller,
 										peer_cfg, child_cfg->get_ref(child_cfg),
-										(void*)initiate_cb, listener, 0))
+										(void*)initiate_cb, listener, 0, FALSE))
 		{
 			case NEED_MORE:
 				/* Callback returns FALSE once it got track of this IKE_SA.
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
index e684f22..c7380b9 100644
--- a/src/libcharon/plugins/load_tester/load_tester_plugin.c
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -152,7 +152,7 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this)
 
 		charon->controller->initiate(charon->controller,
 					peer_cfg, child_cfg->get_ref(child_cfg),
-					NULL, NULL, 0);
+					NULL, NULL, 0, FALSE);
 		if (s)
 		{
 			sleep(s);
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 1fb57b9..25b1383 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -314,7 +314,7 @@ static job_requeue_t initiate_config(peer_cfg_t *peer_cfg)
 		peer_cfg->get_ref(peer_cfg);
 		enumerator->destroy(enumerator);
 		charon->controller->initiate(charon->controller,
-									 peer_cfg, child_cfg, NULL, NULL, 0);
+									 peer_cfg, child_cfg, NULL, NULL, 0, FALSE);
 	}
 	else
 	{
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
index 04bf382..2aa061f 100644
--- a/src/libcharon/plugins/smp/smp.c
+++ b/src/libcharon/plugins/smp/smp.c
@@ -488,7 +488,7 @@ static void request_control_initiate(xmlTextReaderPtr reader,
 			{
 				status = charon->controller->initiate(charon->controller,
 							peer, child, (controller_cb_t)xml_callback,
-							writer, 0);
+							writer, 0, FALSE);
 			}
 			else
 			{
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 0084fbf..0125d17 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -109,7 +109,7 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
 	if (msg->output_verbosity < 0)
 	{
 		charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
-									 NULL, NULL, 0);
+									 NULL, NULL, 0, FALSE);
 	}
 	else
 	{
@@ -118,7 +118,7 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
 
 		status = charon->controller->initiate(charon->controller,
 							peer_cfg, child_cfg, (controller_cb_t)stroke_log,
-							&info, this->timeout);
+							&info, this->timeout, FALSE);
 		switch (status)
 		{
 			case SUCCESS:
diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c
index cebc389..a7d26e6 100644
--- a/src/libcharon/plugins/uci/uci_control.c
+++ b/src/libcharon/plugins/uci/uci_control.c
@@ -147,7 +147,7 @@ static void initiate(private_uci_control_t *this, char *name)
 		if (enumerator->enumerate(enumerator, &child_cfg) &&
 			charon->controller->initiate(charon->controller, peer_cfg,
 								child_cfg->get_ref(child_cfg),
-								controller_cb_empty, NULL, 0) == SUCCESS)
+								controller_cb_empty, NULL, 0, FALSE) == SUCCESS)
 		{
 			write_fifo(this, "connection '%s' established\n", name);
 		}
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index d232599..dfea2ab 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -1558,7 +1558,7 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
 			DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
 			charon->controller->initiate(charon->controller,
 					peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
-					NULL, NULL, 0);
+					NULL, NULL, 0, FALSE);
 			break;
 		case ACTION_ROUTE:
 			DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 01d5036..e568239 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -184,8 +184,8 @@ CALLBACK(initiate, vici_message_t*,
 	{
 		return send_reply(this, "CHILD_SA config '%s' not found", child);
 	}
-	switch (charon->controller->initiate(charon->controller,
-				peer_cfg, child_cfg, (controller_cb_t)log_vici, &log, timeout))
+	switch (charon->controller->initiate(charon->controller, peer_cfg,
+					child_cfg, (controller_cb_t)log_vici, &log, timeout, FALSE))
 	{
 		case SUCCESS:
 			return send_reply(this, NULL);
diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c
index 17ab830..5b5fb9d 100644
--- a/src/libcharon/processing/jobs/initiate_mediation_job.c
+++ b/src/libcharon/processing/jobs/initiate_mediation_job.c
@@ -119,8 +119,8 @@ METHOD(job_t, initiate, job_requeue_t,
 		/* we need an additional reference because initiate consumes one */
 		mediation_cfg->get_ref(mediation_cfg);
 
-		if (charon->controller->initiate(charon->controller, mediation_cfg,
-				NULL, (controller_cb_t)initiate_callback, this, 0) != SUCCESS)
+		if (charon->controller->initiate(charon->controller, mediation_cfg, NULL,
+				(controller_cb_t)initiate_callback, this, 0, FALSE) != SUCCESS)
 		{
 			mediation_cfg->destroy(mediation_cfg);
 			mediated_cfg->destroy(mediated_cfg);
diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c
index 981473b..5e88ac2 100644
--- a/src/libcharon/processing/jobs/start_action_job.c
+++ b/src/libcharon/processing/jobs/start_action_job.c
@@ -61,7 +61,7 @@ METHOD(job_t, execute, job_requeue_t,
 					charon->controller->initiate(charon->controller,
 												 peer_cfg->get_ref(peer_cfg),
 												 child_cfg->get_ref(child_cfg),
-												 NULL, NULL, 0);
+												 NULL, NULL, 0, FALSE);
 					break;
 				case ACTION_ROUTE:
 					DBG1(DBG_JOB, "start action: route '%s'", name);
-- 
2.4.6