Browse code

strongswan: Added HCX patches

Change-Id: Ic684e184577af0d22260d45cdac025c2b36e3a10
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/19962
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Harinadh Dommaraju <hdommaraju@vmware.com>

Srish Srinivasan authored on 2023/03/09 19:36:51
Showing 5 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,57 @@
0
+From d38847beb90d5ed549ded55386e916a0cb03df62 Mon Sep 17 00:00:00 2001
1
+From: Keerthana K <keerthanak@vmware.com>
2
+Date: Fri, 1 Jul 2022 07:47:39 +0000
3
+Subject: [PATCH 1/4] HCX: custom remote natt port
4
+
5
+Adds a new conf variable remote_port_nat_t.
6
+Remote natt port is set to its default value "IKEV2_NATT_PORT"
7
+if remote_port_nat_t is not configured
8
+
9
+Signed-off-by: Keerthana K <keerthanak@vmware.com>
10
+---
11
+ src/charon-cmd/cmd/cmd_connection.c |  8 +++++++-
12
+ src/libcharon/sa/ike_sa.c           | 10 +++++++++-
13
+ 2 files changed, 16 insertions(+), 2 deletions(-)
14
+
15
+diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
16
+index 37d9519..e22fcc4 100644
17
+--- a/src/charon-cmd/cmd/cmd_connection.c
18
+@@ -184,7 +184,13 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
19
+ 	ike.local_port = charon->socket->get_port(charon->socket, FALSE);
20
+ 	if (ike.local_port != IKEV2_UDP_PORT)
21
+ 	{
22
+-		ike.remote_port = IKEV2_NATT_PORT;
23
++		bool is_hcx_enabled = lib->settings->get_bool(lib->settings,
24
++						"%s.hcx_enabled", FALSE, lib->ns);
25
++		if (is_hcx_enabled)
26
++			ike.remote_port = lib->settings->get_int(lib->settings,
27
++						"%s.remote_port_nat_t", IKEV2_NATT_PORT, lib->ns);
28
++		else
29
++			ike.remote_port = IKEV2_NATT_PORT;
30
+ 	}
31
+ 	ike_cfg = ike_cfg_create(&ike);
32
+ 	if (this->ike_proposals->get_count(this->ike_proposals))
33
+diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
34
+index b7db069..251343a 100644
35
+--- a/src/libcharon/sa/ike_sa.c
36
+@@ -1127,7 +1127,15 @@ METHOD(ike_sa_t, float_ports, void,
37
+ 	if (this->other_host->get_port(this->other_host) == IKEV2_UDP_PORT ||
38
+ 		this->my_host->get_port(this->my_host) == IKEV2_UDP_PORT)
39
+ 	{
40
+-		this->other_host->set_port(this->other_host, IKEV2_NATT_PORT);
41
++		bool is_hcx_enabled = lib->settings->get_bool(lib->settings,
42
++						"%s.is_hcx_enabled", FALSE, lib->ns);
43
++		u_int16_t natt = IKEV2_NATT_PORT;
44
++		if (is_hcx_enabled)
45
++		{
46
++			natt = lib->settings->get_int(lib->settings,
47
++						"%s.remote_port_nat_t", IKEV2_NATT_PORT, lib->ns);
48
++		}
49
++		this->other_host->set_port(this->other_host, natt);
50
+ 	}
51
+ 	if (this->my_host->get_port(this->my_host) ==
52
+ 			charon->socket->get_port(charon->socket, FALSE))
53
+-- 
54
+2.28.0
0 55
new file mode 100644
... ...
@@ -0,0 +1,548 @@
0
+From 1d4ca409708e2ab30ebc9c1cb01c67173363ad1d Mon Sep 17 00:00:00 2001
1
+From: Keerthana K <keerthanak@vmware.com>
2
+Date: Tue, 5 Jul 2022 11:05:41 +0000
3
+Subject: [PATCH 2/4] ipsec: Add clear_df flag
4
+
5
+If clear_df flag set, DF bit in Outer IP is cleared
6
+Signed-off-by: Keerthana K <keerthanak@vmware.com>
7
+---
8
+ src/charon-cmd/cmd/cmd_connection.c           |  1 +
9
+ src/charon-nm/nm/nm_service.c                 |  1 +
10
+ src/conftest/config.c                         |  1 +
11
+ src/libcharon/config/child_cfg.c              | 14 ++++++++++++-
12
+ src/libcharon/config/child_cfg.h              | 10 +++++++++
13
+ src/libcharon/kernel/kernel_interface.c       |  4 ++--
14
+ src/libcharon/kernel/kernel_interface.h       |  2 +-
15
+ src/libcharon/kernel/kernel_ipsec.h           |  2 +-
16
+ .../plugins/bypass_lan/bypass_lan_listener.c  |  1 +
17
+ src/libcharon/plugins/ha/ha_tunnel.c          |  1 +
18
+ .../kernel_netlink/kernel_netlink_ipsec.c     | 10 +++++++--
19
+ .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c |  2 +-
20
+ .../plugins/load_tester/load_tester_config.c  |  1 +
21
+ src/libcharon/plugins/medcli/medcli_config.c  |  2 ++
22
+ src/libcharon/plugins/sql/sql_config.c        |  1 +
23
+ src/libcharon/plugins/stroke/stroke_config.c  |  4 ++++
24
+ src/libcharon/plugins/uci/uci_config.c        |  1 +
25
+ src/libcharon/plugins/unity/unity_handler.c   |  1 +
26
+ src/libcharon/plugins/vici/vici_config.c      |  2 ++
27
+ src/libcharon/sa/child_sa.c                   | 21 ++++++++++++++++++-
28
+ src/libcharon/sa/child_sa.h                   |  5 +++++
29
+ src/starter/args.c                            |  1 +
30
+ src/starter/confread.c                        | 12 +++++++++++
31
+ src/starter/confread.h                        |  1 +
32
+ src/starter/keywords.h.in                     |  1 +
33
+ src/starter/keywords.txt                      |  1 +
34
+ src/starter/starterstroke.c                   |  1 +
35
+ src/stroke/stroke_msg.h                       |  1 +
36
+ 28 files changed, 96 insertions(+), 9 deletions(-)
37
+
38
+diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
39
+index e1023cc..e712a06 100644
40
+--- a/src/charon-cmd/cmd/cmd_connection.c
41
+@@ -354,6 +354,7 @@ static child_cfg_t* create_child_cfg(private_cmd_connection_t *this,
42
+ 			}
43
+ 		},
44
+ 		.mode = MODE_TUNNEL,
45
++		.clear_df = false,
46
+ 	};
47
+ 
48
+ 	child_cfg = child_cfg_create("cmd", &child);
49
+diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
50
+index 5d6d329..cf57960 100644
51
+--- a/src/charon-nm/nm/nm_service.c
52
+@@ -634,6 +634,7 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
53
+ 			},
54
+ 		},
55
+ 		.mode = MODE_TUNNEL,
56
++		.clear_df = false,
57
+ 		.dpd_action = ACTION_START,
58
+ 		.close_action = ACTION_START,
59
+ 	};
60
+diff --git a/src/conftest/config.c b/src/conftest/config.c
61
+index a6dc61f..ab7e84a 100644
62
+--- a/src/conftest/config.c
63
+@@ -170,6 +170,7 @@ static child_cfg_t *load_child_config(private_config_t *this,
64
+ 	}
65
+ 	data.tfc = settings->get_int(settings, "configs.%s.%s.tfc_padding",
66
+ 								  0, config, child);
67
++	data.clear_df = false;
68
+ 	child_cfg = child_cfg_create(child, &data);
69
+ 
70
+ 	token = settings->get_str(settings, "configs.%s.%s.proposal",
71
+diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
72
+index bc9cff7..33e1439 100644
73
+--- a/src/libcharon/config/child_cfg.c
74
+@@ -183,6 +183,11 @@ struct private_child_cfg_t {
75
+ 	 * DS header field copy mode
76
+ 	 */
77
+ 	dscp_copy_t copy_dscp;
78
++
79
++	/**
80
++	 * clear DF flag in outer IP header
81
++	 */
82
++	bool clear_df;
83
+ };
84
+ 
85
+ METHOD(child_cfg_t, get_name, char*,
86
+@@ -727,6 +732,12 @@ METHOD(child_cfg_t, get_ref, child_cfg_t*,
87
+ 	return &this->public;
88
+ }
89
+ 
90
++METHOD(child_cfg_t, is_clear_df, bool,
91
++	private_child_cfg_t *this)
92
++{
93
++	return this->clear_df;
94
++}
95
++
96
+ METHOD(child_cfg_t, destroy, void,
97
+ 	private_child_cfg_t *this)
98
+ {
99
+@@ -781,6 +792,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
100
+ 			.has_option = _has_option,
101
+ 			.equals = _equals,
102
+ 			.get_ref = _get_ref,
103
++			.is_clear_df = _is_clear_df,
104
+ 			.destroy = _destroy,
105
+ 			.get_hw_offload = _get_hw_offload,
106
+ 			.get_copy_dscp = _get_copy_dscp,
107
+@@ -816,6 +828,6 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
108
+ 		.hw_offload = data->hw_offload,
109
+ 		.copy_dscp = data->copy_dscp,
110
+ 	);
111
+-
112
++	this->clear_df = data->clear_df;
113
+ 	return &this->public;
114
+ }
115
+diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
116
+index 9c44252..26fa897 100644
117
+--- a/src/libcharon/config/child_cfg.h
118
+@@ -346,6 +346,14 @@ struct child_cfg_t {
119
+ 	 */
120
+ 	child_cfg_t* (*get_ref) (child_cfg_t *this);
121
+ 
122
++	/**
123
++	 * Check whether DF bit has to be cleared in Outer IP
124
++	 *
125
++	 * @return				TRUE, if DF bit should be cleared
126
++	 *						FALSE, otherwise
127
++	 */
128
++	bool (*is_clear_df)(child_cfg_t *this);
129
++
130
+ 	/**
131
+ 	 * Destroys the child_cfg object.
132
+ 	 *
133
+@@ -436,6 +444,8 @@ struct child_cfg_create_t {
134
+ 	hw_offload_t hw_offload;
135
+ 	/** How to handle the DS header field in tunnel mode */
136
+ 	dscp_copy_t copy_dscp;
137
++	/** DF clear bit */
138
++	bool clear_df;
139
+ };
140
+ 
141
+ /**
142
+diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
143
+index 4f4a997..207cb8e 100644
144
+--- a/src/libcharon/kernel/kernel_interface.c
145
+@@ -472,13 +472,13 @@ METHOD(kernel_interface_t, release_reqid, status_t,
146
+ 
147
+ METHOD(kernel_interface_t, add_sa, status_t,
148
+ 	private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
149
+-	kernel_ipsec_add_sa_t *data)
150
++	kernel_ipsec_add_sa_t *data, bool clear_df)
151
+ {
152
+ 	if (!this->ipsec)
153
+ 	{
154
+ 		return NOT_SUPPORTED;
155
+ 	}
156
+-	return this->ipsec->add_sa(this->ipsec, id, data);
157
++	return this->ipsec->add_sa(this->ipsec, id, data, clear_df);
158
+ }
159
+ 
160
+ METHOD(kernel_interface_t, update_sa, status_t,
161
+diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
162
+index 21b777a..657afd8 100644
163
+--- a/src/libcharon/kernel/kernel_interface.h
164
+@@ -182,7 +182,7 @@ struct kernel_interface_t {
165
+ 	 * @return				SUCCESS if operation completed
166
+ 	 */
167
+ 	status_t (*add_sa)(kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
168
+-					   kernel_ipsec_add_sa_t *data);
169
++					   kernel_ipsec_add_sa_t *data, bool clear_df);
170
+ 
171
+ 	/**
172
+ 	 * Update the hosts on an installed SA.
173
+diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
174
+index ae8b82a..6c60850 100644
175
+--- a/src/libcharon/kernel/kernel_ipsec.h
176
+@@ -248,7 +248,7 @@ struct kernel_ipsec_t {
177
+ 	 * @return				SUCCESS if operation completed
178
+ 	 */
179
+ 	status_t (*add_sa)(kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
180
+-					   kernel_ipsec_add_sa_t *data);
181
++					   kernel_ipsec_add_sa_t *data, bool clear_df);
182
+ 
183
+ 	/**
184
+ 	 * Update the hosts on an installed SA.
185
+diff --git a/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c b/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
186
+index db7abd8..7375cb9 100644
187
+--- a/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
188
+@@ -163,6 +163,7 @@ static job_requeue_t update_bypass(private_bypass_lan_listener_t *this)
189
+ 		{
190
+ 			child_cfg_create_t child = {
191
+ 				.mode = MODE_PASS,
192
++				.clear_df = false,
193
+ 			};
194
+ 			child_cfg_t *cfg;
195
+ 			char name[128];
196
+diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
197
+index d7e83a0..05d7c77 100644
198
+--- a/src/libcharon/plugins/ha/ha_tunnel.c
199
+@@ -215,6 +215,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
200
+ 			},
201
+ 		},
202
+ 		.mode = MODE_TRANSPORT,
203
++		.clear_df = false,
204
+ 	};
205
+ 
206
+ 	/* setup credentials */
207
+diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
208
+index 6f7b50f..78df0da 100644
209
+--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
210
+@@ -1580,7 +1580,7 @@ out:
211
+ 
212
+ METHOD(kernel_ipsec_t, add_sa, status_t,
213
+ 	private_kernel_netlink_ipsec_t *this, kernel_ipsec_sa_id_t *id,
214
+-	kernel_ipsec_add_sa_t *data)
215
++	kernel_ipsec_add_sa_t *data, bool clear_df)
216
+ {
217
+ 	netlink_buf_t request;
218
+ 	const char *alg_name;
219
+@@ -1591,6 +1591,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
220
+ 	ipsec_mode_t mode = data->mode, original_mode = data->mode;
221
+ 	traffic_selector_t *first_src_ts, *first_dst_ts;
222
+ 	status_t status = FAILED;
223
++	bool is_hcx_enabled = false;
224
+ 
225
+ 	/* if IPComp is used, we install an additional IPComp SA. if the cpi is 0
226
+ 	 * we are in the recursive call below */
227
+@@ -1619,7 +1620,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
228
+ 			.inbound = data->inbound,
229
+ 			.update = data->update,
230
+ 		};
231
+-		add_sa(this, &ipcomp_id, &ipcomp_sa);
232
++		add_sa(this, &ipcomp_id, &ipcomp_sa, clear_df);
233
+ 		ipcomp = IPCOMP_NONE;
234
+ 		/* use transport mode ESP SA, IPComp uses tunnel mode */
235
+ 		mode = MODE_TRANSPORT;
236
+@@ -1642,6 +1643,11 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
237
+ 	sa->id.spi = id->spi;
238
+ 	sa->id.proto = id->proto;
239
+ 	sa->family = id->src->get_family(id->src);
240
++	is_hcx_enabled = lib->settings->get_bool(lib->settings,
241
++				"%s.is_hcx_enabled", FALSE, lib->ns);
242
++	if (is_hcx_enabled && clear_df) {
243
++		sa->flags |= XFRM_STATE_NOPMTUDISC;
244
++	}
245
+ 	sa->mode = mode2kernel(mode);
246
+ 
247
+ 	if (!data->copy_df)
248
+diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
249
+index e73767d..74265ec 100644
250
+--- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
251
+@@ -1704,7 +1704,7 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
252
+ 
253
+ METHOD(kernel_ipsec_t, add_sa, status_t,
254
+ 	private_kernel_pfkey_ipsec_t *this, kernel_ipsec_sa_id_t *id,
255
+-	kernel_ipsec_add_sa_t *data)
256
++	kernel_ipsec_add_sa_t *data, bool clear_df)
257
+ {
258
+ 	unsigned char request[PFKEY_BUFFER_SIZE];
259
+ 	struct sadb_msg *msg, *out = NULL;
260
+diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
261
+index 58e1cd9..cd037a9 100644
262
+--- a/src/libcharon/plugins/load_tester/load_tester_config.c
263
+@@ -713,6 +713,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, u_int num
264
+ 			},
265
+ 		},
266
+ 		.mode = MODE_TUNNEL,
267
++		.clear_df = false,
268
+ 	};
269
+ 
270
+ 	if (num)
271
+diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
272
+index f50f79d..edff21f 100644
273
+--- a/src/libcharon/plugins/medcli/medcli_config.c
274
+@@ -158,6 +158,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
275
+ 			},
276
+ 		},
277
+ 		.mode = MODE_TUNNEL,
278
++		.clear_df = false,
279
+ 	};
280
+ 
281
+ 	if (streq(name, "medcli-mediation"))
282
+@@ -253,6 +254,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
283
+ 			},
284
+ 		},
285
+ 		.mode = MODE_TUNNEL,
286
++		.clear_df = false,
287
+ 	};
288
+ 
289
+ 	VA_ARGS_VGET(args, cfg);
290
+diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
291
+index aef1e1c..583a70d 100644
292
+--- a/src/libcharon/plugins/sql/sql_config.c
293
+@@ -186,6 +186,7 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
294
+ 			.dpd_action = dpd,
295
+ 			.close_action = close,
296
+ 			.updown = updown,
297
++			.clear_df = false,
298
+ 		};
299
+ 		child_cfg = child_cfg_create(name, &child);
300
+ 		add_esp_proposals(this, child_cfg, id);
301
+diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
302
+index 55db379..e271b3a 100644
303
+--- a/src/libcharon/plugins/stroke/stroke_config.c
304
+@@ -1097,8 +1097,12 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
305
+ 		.dpd_action = map_action(msg->add_conn.dpd.action),
306
+ 		.close_action = map_action(msg->add_conn.close_action),
307
+ 		.updown = msg->add_conn.me.updown,
308
++		.clear_df = msg->add_conn.clear_df != 0,
309
+ 	};
310
+ 
311
++	DBG1(DBG_CFG, "build_child_cfg: conn %s, clear_df %d",
312
++					msg->add_conn.name, msg->add_conn.clear_df);
313
++
314
+ 	child_cfg = child_cfg_create(msg->add_conn.name, &child);
315
+ 	if (msg->add_conn.replay_window != -1)
316
+ 	{
317
+diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
318
+index 3a7fc7a..ecd0c51 100644
319
+--- a/src/libcharon/plugins/uci/uci_config.c
320
+@@ -152,6 +152,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
321
+ 			},
322
+ 		},
323
+ 		.mode = MODE_TUNNEL,
324
++		.clear_df = false,
325
+ 	};
326
+ 
327
+ 	VA_ARGS_VGET(args, cfg);
328
+diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c
329
+index 9a45275..a83bfed 100644
330
+--- a/src/libcharon/plugins/unity/unity_handler.c
331
+@@ -207,6 +207,7 @@ static job_requeue_t add_exclude_async(entry_t *entry)
332
+ 	child_cfg_t *child_cfg;
333
+ 	child_cfg_create_t child = {
334
+ 		.mode = MODE_PASS,
335
++		.clear_df = false,
336
+ 	};
337
+ 	ike_sa_t *ike_sa;
338
+ 	char name[128];
339
+diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
340
+index 0c061d4..87e93ed 100644
341
+--- a/src/libcharon/plugins/vici/vici_config.c
342
+@@ -2081,6 +2081,8 @@ CALLBACK(children_sn, bool,
343
+ 
344
+ 	log_child_data(&child, name);
345
+ 
346
++	child.cfg.clear_df = false;
347
++
348
+ 	cfg = child_cfg_create(name, &child.cfg);
349
+ 
350
+ 	if (child.replay_window != REPLAY_UNDEFINED)
351
+diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
352
+index 2c77ee2..ab5a3d0 100644
353
+--- a/src/libcharon/sa/child_sa.c
354
+@@ -279,6 +279,11 @@ struct private_child_sa_t {
355
+ 	 * last number of outbound bytes
356
+ 	 */
357
+ 	uint64_t other_usepackets;
358
++
359
++	/**
360
++	 * clear DF bit in outer IP
361
++	 */
362
++	bool clear_df;
363
+ };
364
+ 
365
+ /**
366
+@@ -499,6 +504,13 @@ METHOD(child_sa_t, create_ts_enumerator, enumerator_t*,
367
+ 	return array_create_enumerator(this->other_ts);
368
+ }
369
+ 
370
++METHOD(child_sa_t, is_clear_df, bool,
371
++	   private_child_sa_t *this)
372
++{
373
++	return this->clear_df;
374
++}
375
++
376
++
377
+ typedef struct policy_enumerator_t policy_enumerator_t;
378
+ 
379
+ /**
380
+@@ -1001,7 +1013,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
381
+ 		sa.mark.value = inbound ? this->mark_in.value : this->mark_out.value;
382
+ 	}
383
+ 
384
+-	status = charon->kernel->add_sa(charon->kernel, &id, &sa);
385
++	status = charon->kernel->add_sa(charon->kernel, &id, &sa, this->clear_df);
386
+ 
387
+ 	my_ts->destroy(my_ts);
388
+ 	other_ts->destroy(other_ts);
389
+@@ -2054,6 +2066,7 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
390
+ 			.create_ts_enumerator = _create_ts_enumerator,
391
+ 			.create_policy_enumerator = _create_policy_enumerator,
392
+ 			.destroy = _destroy,
393
++			.is_clear_df = _is_clear_df,
394
+ 		},
395
+ 		.encap = data->encap,
396
+ 		.ipcomp = IPCOMP_NONE,
397
+@@ -2078,6 +2091,12 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
398
+ 	this->config = config;
399
+ 	config->get_ref(config);
400
+ 
401
++	if (config != NULL && config->is_clear_df != NULL) {
402
++		this->clear_df = config->is_clear_df(config);
403
++	} else {
404
++		this->clear_df = false;
405
++	}
406
++
407
+ 	if (data->mark_in)
408
+ 	{
409
+ 		this->mark_in.value = data->mark_in;
410
+diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
411
+index 37f0027..742fa86 100644
412
+--- a/src/libcharon/sa/child_sa.h
413
+@@ -522,6 +522,11 @@ struct child_sa_t {
414
+ 	 * Destroys a child_sa.
415
+ 	 */
416
+ 	void (*destroy) (child_sa_t *this);
417
++
418
++	/**
419
++	 * Clear DF bit in outer IP
420
++	 */
421
++	bool (*is_clear_df) (child_sa_t *this);
422
+ };
423
+ 
424
+ /**
425
+diff --git a/src/starter/args.c b/src/starter/args.c
426
+index b71a216..cd72730 100644
427
+--- a/src/starter/args.c
428
+@@ -178,6 +178,7 @@ static const token_info_t token_info[] =
429
+ 	{ ARG_MISC, 0, NULL  /* KW_MARK_IN */                                          },
430
+ 	{ ARG_MISC, 0, NULL  /* KW_MARK_OUT */                                         },
431
+ 	{ ARG_MISC, 0, NULL  /* KW_TFC */                                              },
432
++	{ ARG_MISC, 0, NULL  /* KW_CLEAR_DF */                                         },
433
+ 	{ ARG_MISC, 0, NULL  /* KW_PFS_DEPRECATED */                                   },
434
+ 	{ ARG_MISC, 0, NULL  /* KW_CONN_DEPRECATED */                                  },
435
+ 
436
+diff --git a/src/starter/confread.c b/src/starter/confread.c
437
+index 5065bc3..1aa7ccc 100644
438
+--- a/src/starter/confread.c
439
+@@ -212,6 +212,7 @@ static void conn_defaults(starter_conn_t *conn)
440
+ 	conn->dpd_delay             =  30; /* seconds */
441
+ 	conn->dpd_timeout           = 150; /* seconds */
442
+ 	conn->replay_window         = SA_REPLAY_WINDOW_DEFAULT;
443
++	conn->clear_df              = false;
444
+ 	conn->fragmentation         = FRAGMENTATION_YES;
445
+ 
446
+ 	conn->left.sendcert = CERT_SEND_IF_ASKED;
447
+@@ -514,6 +515,17 @@ static void handle_keyword(kw_token_t token, starter_conn_t *conn, char *key,
448
+ 		case KW_XAUTH:
449
+ 			KW_SA_OPTION_FLAG("server", "client", SA_OPTION_XAUTH_SERVER)
450
+ 			break;
451
++		case KW_CLEAR_DF:
452
++			DBG1(DBG_APP, "handle_keyword: %s=%s", key, value);
453
++			if (streq(value, "yes"))
454
++			{
455
++				conn->clear_df = true;
456
++			}
457
++            else if (streq(value, "no"))
458
++			{
459
++				conn->clear_df = false;
460
++			}
461
++			break;
462
+ 		default:
463
+ 			break;
464
+ 	}
465
+diff --git a/src/starter/confread.h b/src/starter/confread.h
466
+index 0c22481..fbbe85e 100644
467
+--- a/src/starter/confread.h
468
+@@ -147,6 +147,7 @@ struct starter_conn {
469
+ 		uint32_t       tfc;
470
+ 		bool            install_policy;
471
+ 		bool            aggressive;
472
++		bool            clear_df;
473
+ 		starter_end_t   left, right;
474
+ 
475
+ 		unsigned long   id;
476
+diff --git a/src/starter/keywords.h.in b/src/starter/keywords.h.in
477
+index 258dc2b..071e344 100644
478
+--- a/src/starter/keywords.h.in
479
+@@ -77,6 +77,7 @@ enum kw_token_t {
480
+ 	KW_MARK_IN,
481
+ 	KW_MARK_OUT,
482
+ 	KW_TFC,
483
++	KW_CLEAR_DF,
484
+ 	KW_PFS_DEPRECATED,
485
+ 	KW_CONN_DEPRECATED,
486
+ 
487
+diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
488
+index 52845f3..c0005ba 100644
489
+--- a/src/starter/keywords.txt
490
+@@ -166,3 +166,4 @@ pfsgroup,          KW_PFS_DEPRECATED
491
+ eap,               KW_CONN_DEPRECATED
492
+ leftnexthop,       KW_LEFT_DEPRECATED
493
+ rightnexthop,      KW_RIGHT_DEPRECATED
494
++cleardf,           KW_CLEAR_DF
495
+diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
496
+index f4cfc15..147a32e 100644
497
+--- a/src/starter/starterstroke.c
498
+@@ -231,6 +231,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
499
+ 	msg->add_conn.mark_out.value = conn->mark_out.value;
500
+ 	msg->add_conn.mark_out.mask = conn->mark_out.mask;
501
+ 	msg->add_conn.tfc = conn->tfc;
502
++	msg->add_conn.clear_df = conn->clear_df ? 1 : 0;
503
+ 
504
+ 	add_end(&msg, offsetof(stroke_msg_t, add_conn.me), &conn->left);
505
+ 	add_end(&msg, offsetof(stroke_msg_t, add_conn.other), &conn->right);
506
+diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
507
+index 8ec08ad..f5aa63b 100644
508
+--- a/src/stroke/stroke_msg.h
509
+@@ -304,6 +304,7 @@ struct stroke_msg_t {
510
+ 			stroke_end_t me, other;
511
+ 			uint32_t replay_window;
512
+ 			bool sha256_96;
513
++			int clear_df;
514
+ 		} add_conn;
515
+ 
516
+ 		/* data for STR_ADD_CA */
517
+-- 
518
+2.35.6
519
+
0 520
new file mode 100644
... ...
@@ -0,0 +1,133 @@
0
+From 65a06e178e823a57c8772fcdfde955c68e8a89fd Mon Sep 17 00:00:00 2001
1
+From: Keerthana K <keerthanak@vmware.com>
2
+Date: Wed, 6 Jul 2022 15:39:51 +0530
3
+Subject: [PATCH 3/4] reiniate conn on failure
4
+
5
+Signed-off-by: Keerthana K <keerthanak@vmware.com>
6
+---
7
+ src/starter/starter.c       | 29 ++++++++++++++++++++++++++++-
8
+ src/starter/starterstroke.c | 24 ++++++++++++++++++++++--
9
+ src/starter/starterstroke.h |  1 +
10
+ 3 files changed, 51 insertions(+), 3 deletions(-)
11
+
12
+diff --git a/src/starter/starter.c b/src/starter/starter.c
13
+index ade88bb..28524ba 100644
14
+--- a/src/starter/starter.c
15
+@@ -358,6 +358,7 @@ int main (int argc, char **argv)
16
+ 	bool attach_gdb = FALSE;
17
+ 	bool load_warning = FALSE;
18
+ 	bool conftest = FALSE;
19
++	bool is_hcx_enabled = false;
20
+ 
21
+ 	library_init(NULL, "starter");
22
+ 	atexit(library_deinit);
23
+@@ -839,7 +840,33 @@ int main (int argc, char **argv)
24
+ 				}
25
+ 			}
26
+ 		}
27
+-
28
++		/*
29
++		 * Check connections if there is nothing better to do
30
++		 */
31
++		is_hcx_enabled = lib->settings->get_bool(lib->settings,
32
++					"charon.is_hcx_enabled", FALSE);
33
++		if (is_hcx_enabled && !_action_)
34
++		{
35
++			ts.tv_sec = 10;
36
++			ts.tv_nsec = 0;
37
++			if (pselect(0, NULL, NULL, NULL, &ts, &action.sa_mask) == 0)
38
++			{
39
++				for (conn = cfg->conn_first; conn; conn = conn->next)
40
++				{
41
++					if (conn->startup == STARTUP_START)
42
++					{
43
++						if (starter_charon_pid())
44
++						{
45
++							if (starter_stroke_check_conn(conn) == 1)
46
++							{
47
++								starter_stroke_initiate_conn(conn);
48
++							}
49
++						}
50
++					}
51
++				}
52
++				continue;
53
++			}
54
++		}
55
+ 		/*
56
+ 		 * If auto_update activated, when to stop select
57
+ 		 */
58
+diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
59
+index 147a32e..80e0620 100644
60
+--- a/src/starter/starterstroke.c
61
+@@ -78,6 +78,8 @@ static int send_stroke_msg(stroke_msg_t *msg)
62
+ 	stream_t *stream;
63
+ 	char *uri, buffer[64];
64
+ 	int count;
65
++	int result = 0;
66
++	bool is_hcx_enabled = false;
67
+ 
68
+ 	if (msg->length == UINT16_MAX)
69
+ 	{
70
+@@ -106,10 +108,19 @@ static int send_stroke_msg(stroke_msg_t *msg)
71
+ 		free(msg);
72
+ 		return -1;
73
+ 	}
74
++	is_hcx_enabled = lib->settings->get_bool(lib->settings,
75
++				"charon.is_hcx_enabled", FALSE);
76
+ 	while ((count = stream->read(stream, buffer, sizeof(buffer)-1, TRUE)) > 0)
77
+ 	{
78
+ 		buffer[count] = '\0';
79
+-		DBG1(DBG_APP, "%s", buffer);
80
++		if (is_hcx_enabled && msg->type == STR_STATUS)
81
++		{
82
++			result = strstr(buffer, "no match") ? 1 : 0;
83
++		}
84
++		else
85
++		{
86
++			DBG1(DBG_APP, "%s", buffer);
87
++		}
88
+ 	}
89
+ 	if (count < 0)
90
+ 	{
91
+@@ -117,7 +128,7 @@ static int send_stroke_msg(stroke_msg_t *msg)
92
+ 	}
93
+ 	stream->destroy(stream);
94
+ 	free(msg);
95
+-	return 0;
96
++	return result;
97
+ }
98
+ 
99
+ static char* connection_name(starter_conn_t *conn)
100
+@@ -317,6 +328,15 @@ int starter_stroke_initiate_conn(starter_conn_t *conn)
101
+ 	return send_stroke_msg(msg);
102
+ }
103
+ 
104
++int starter_stroke_check_conn(starter_conn_t *conn)
105
++{
106
++	stroke_msg_t *msg;
107
++
108
++	msg = create_stroke_msg(STR_STATUS);
109
++	push_string(&msg, initiate.name, connection_name(conn));
110
++	return send_stroke_msg(msg);
111
++}
112
++
113
+ int starter_stroke_add_ca(starter_ca_t *ca)
114
+ {
115
+ 	stroke_msg_t *msg;
116
+diff --git a/src/starter/starterstroke.h b/src/starter/starterstroke.h
117
+index 5450403..2d8fbd5 100644
118
+--- a/src/starter/starterstroke.h
119
+@@ -22,6 +22,7 @@ int starter_stroke_del_conn(starter_conn_t *conn);
120
+ int starter_stroke_route_conn(starter_conn_t *conn);
121
+ int starter_stroke_unroute_conn(starter_conn_t *conn);
122
+ int starter_stroke_initiate_conn(starter_conn_t *conn);
123
++int starter_stroke_check_conn(starter_conn_t *conn);
124
+ int starter_stroke_add_ca(starter_ca_t *ca);
125
+ int starter_stroke_del_ca(starter_ca_t *ca);
126
+ int starter_stroke_configure(starter_config_t *cfg);
127
+-- 
128
+2.35.6
129
+
0 130
new file mode 100644
... ...
@@ -0,0 +1,503 @@
0
+From 0b1de23a189cdf133a03379ccd1e34ff4fbb77c6 Mon Sep 17 00:00:00 2001
1
+From: Keerthana K <keerthanak@vmware.com>
2
+Date: Thu, 7 Jul 2022 07:16:15 +0000
3
+Subject: [PATCH 4/4] Add new configs min_spi and max_spi
4
+
5
+---
6
+ src/libcharon/config/child_cfg.c              | 26 ++++++++++++
7
+ src/libcharon/config/child_cfg.h              | 18 ++++++++
8
+ src/libcharon/kernel/kernel_interface.c       |  4 +-
9
+ src/libcharon/kernel/kernel_interface.h       |  2 +-
10
+ src/libcharon/kernel/kernel_ipsec.h           |  2 +-
11
+ .../kernel_netlink/kernel_netlink_ipsec.c     | 12 +++++-
12
+ src/libcharon/plugins/stroke/stroke_config.c  |  8 ++++
13
+ src/libcharon/plugins/vici/vici_config.c      |  2 +
14
+ src/libcharon/sa/child_sa.c                   | 37 +++++++++++++++-
15
+ src/libcharon/sa/child_sa.h                   | 10 +++++
16
+ src/libipsec/ipsec_sa_mgr.c                   |  2 +-
17
+ src/libipsec/ipsec_sa_mgr.h                   |  2 +-
18
+ src/starter/args.c                            |  2 +
19
+ src/starter/confread.c                        | 42 +++++++++++++++++++
20
+ src/starter/confread.h                        |  2 +
21
+ src/starter/keywords.h.in                     |  3 +-
22
+ src/starter/keywords.txt                      |  2 +
23
+ src/starter/starterstroke.c                   |  2 +
24
+ src/stroke/stroke_msg.h                       |  2 +
25
+ 19 files changed, 170 insertions(+), 10 deletions(-)
26
+
27
+diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
28
+index 33e1439..d1f255d 100644
29
+--- a/src/libcharon/config/child_cfg.c
30
+@@ -188,6 +188,16 @@ struct private_child_cfg_t {
31
+ 	 * clear DF flag in outer IP header
32
+ 	 */
33
+ 	bool clear_df;
34
++	
35
++	/**
36
++	 * min SPI value to use
37
++	 */
38
++	u_int32_t min_spi;
39
++
40
++	/**
41
++	 * max SPI value to use
42
++	 */
43
++	u_int32_t max_spi;
44
+ };
45
+ 
46
+ METHOD(child_cfg_t, get_name, char*,
47
+@@ -738,6 +748,18 @@ METHOD(child_cfg_t, is_clear_df, bool,
48
+ 	return this->clear_df;
49
+ }
50
+ 
51
++METHOD(child_cfg_t, min_spi, u_int32_t,
52
++	private_child_cfg_t *this)
53
++{
54
++	return this->min_spi;
55
++}
56
++
57
++METHOD(child_cfg_t, max_spi, u_int32_t,
58
++	private_child_cfg_t *this)
59
++{
60
++	return this->max_spi;
61
++}
62
++
63
+ METHOD(child_cfg_t, destroy, void,
64
+ 	private_child_cfg_t *this)
65
+ {
66
+@@ -793,6 +815,8 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
67
+ 			.equals = _equals,
68
+ 			.get_ref = _get_ref,
69
+ 			.is_clear_df = _is_clear_df,
70
++			.min_spi = _min_spi,
71
++			.max_spi = _max_spi,
72
+ 			.destroy = _destroy,
73
+ 			.get_hw_offload = _get_hw_offload,
74
+ 			.get_copy_dscp = _get_copy_dscp,
75
+@@ -829,5 +853,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
76
+ 		.copy_dscp = data->copy_dscp,
77
+ 	);
78
+ 	this->clear_df = data->clear_df;
79
++	this->min_spi = data->min_spi;
80
++	this->max_spi = data->max_spi;
81
+ 	return &this->public;
82
+ }
83
+diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
84
+index 26fa897..2cdfde0 100644
85
+--- a/src/libcharon/config/child_cfg.h
86
+@@ -354,6 +354,20 @@ struct child_cfg_t {
87
+ 	 */
88
+ 	bool (*is_clear_df)(child_cfg_t *this);
89
+ 
90
++	/**
91
++	 * Get the min SPI value to use
92
++	 *
93
++	 * @return				min SPI value
94
++	 */
95
++	u_int32_t (*min_spi)(child_cfg_t *this);
96
++
97
++	/**
98
++	 * Get the max SPI value to use
99
++	 *
100
++	 * @return				max SPI value
101
++	 */
102
++	u_int32_t (*max_spi)(child_cfg_t *this);
103
++
104
+ 	/**
105
+ 	 * Destroys the child_cfg object.
106
+ 	 *
107
+@@ -446,6 +460,10 @@ struct child_cfg_create_t {
108
+ 	dscp_copy_t copy_dscp;
109
+ 	/** DF clear bit */
110
+ 	bool clear_df;
111
++	/** min SPI value to use */
112
++	u_int32_t min_spi;
113
++	/** max SPI value to use */
114
++	u_int32_t max_spi;
115
+ };
116
+ 
117
+ /**
118
+diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
119
+index 207cb8e..818d72e 100644
120
+--- a/src/libcharon/kernel/kernel_interface.c
121
+@@ -171,13 +171,13 @@ METHOD(kernel_interface_t, get_features, kernel_feature_t,
122
+ 
123
+ METHOD(kernel_interface_t, get_spi, status_t,
124
+ 	private_kernel_interface_t *this, host_t *src, host_t *dst,
125
+-	uint8_t protocol, uint32_t *spi)
126
++	uint8_t protocol, u_int32_t min, u_int32_t max, uint32_t *spi)
127
+ {
128
+ 	if (!this->ipsec)
129
+ 	{
130
+ 		return NOT_SUPPORTED;
131
+ 	}
132
+-	return this->ipsec->get_spi(this->ipsec, src, dst, protocol, spi);
133
++	return this->ipsec->get_spi(this->ipsec, src, dst, protocol, min, max, spi);
134
+ }
135
+ 
136
+ METHOD(kernel_interface_t, get_cpi, status_t,
137
+diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
138
+index 657afd8..8eb68f6 100644
139
+--- a/src/libcharon/kernel/kernel_interface.h
140
+@@ -116,7 +116,7 @@ struct kernel_interface_t {
141
+ 	 * @return			SUCCESS if operation completed
142
+ 	 */
143
+ 	status_t (*get_spi)(kernel_interface_t *this, host_t *src, host_t *dst,
144
+-						uint8_t protocol, uint32_t *spi);
145
++						uint8_t protocol, u_int32_t min, u_int32_t max, uint32_t *spi);
146
+ 
147
+ 	/**
148
+ 	 * Get a Compression Parameter Index (CPI) from the kernel.
149
+diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
150
+index 6c60850..5a2fa8b 100644
151
+--- a/src/libcharon/kernel/kernel_ipsec.h
152
+@@ -224,7 +224,7 @@ struct kernel_ipsec_t {
153
+ 	 * @return			SUCCESS if operation completed
154
+ 	 */
155
+ 	status_t (*get_spi)(kernel_ipsec_t *this, host_t *src, host_t *dst,
156
+-						uint8_t protocol, uint32_t *spi);
157
++						uint8_t protocol, u_int32_t min, u_int32_t max, uint32_t *spi);
158
+ 
159
+ 	/**
160
+ 	 * Get a Compression Parameter Index (CPI) from the kernel.
161
+diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
162
+index 78df0da..0458993 100644
163
+--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
164
+@@ -1244,17 +1244,25 @@ static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
165
+ 
166
+ METHOD(kernel_ipsec_t, get_spi, status_t,
167
+ 	private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
168
+-	uint8_t protocol, uint32_t *spi)
169
++	uint8_t protocol, u_int32_t min, u_int32_t max, uint32_t *spi)
170
+ {
171
+ 	uint32_t spi_min, spi_max;
172
++	uint32_t max_t;
173
++	bool is_hcx_enabled = false;
174
+ 
175
+ 	spi_min = lib->settings->get_int(lib->settings, "%s.spi_min",
176
+ 									 KERNEL_SPI_MIN, lib->ns);
177
+ 	spi_max = lib->settings->get_int(lib->settings, "%s.spi_max",
178
+ 									 KERNEL_SPI_MAX, lib->ns);
179
++	is_hcx_enabled = lib->settings->get_bool(lib->settings,
180
++				"%s.is_hcx_enabled", FALSE, lib->ns);
181
++	if (is_hcx_enabled)
182
++		max_t = max(min, max);
183
++	else
184
++		max_t = max(spi_min, spi_max);
185
+ 
186
+ 	if (get_spi_internal(this, src, dst, protocol, min(spi_min, spi_max),
187
+-						 max(spi_min, spi_max), spi) != SUCCESS)
188
++						 max_t, spi) != SUCCESS)
189
+ 	{
190
+ 		DBG1(DBG_KNL, "unable to get SPI");
191
+ 		return FAILED;
192
+diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
193
+index e271b3a..7edac87 100644
194
+--- a/src/libcharon/plugins/stroke/stroke_config.c
195
+@@ -1098,10 +1098,18 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
196
+ 		.close_action = map_action(msg->add_conn.close_action),
197
+ 		.updown = msg->add_conn.me.updown,
198
+ 		.clear_df = msg->add_conn.clear_df != 0,
199
++		.min_spi = msg->add_conn.min_spi,
200
++		.max_spi = msg->add_conn.max_spi,
201
+ 	};
202
+ 
203
+ 	DBG1(DBG_CFG, "build_child_cfg: conn %s, clear_df %d",
204
+ 					msg->add_conn.name, msg->add_conn.clear_df);
205
++ 
206
++	DBG1(DBG_CFG, "build_child_cfg: conn %s, min_spi %u",
207
++					msg->add_conn.name, msg->add_conn.min_spi);
208
++
209
++	DBG1(DBG_CFG, "build_child_cfg: conn %s, max_spi %u",
210
++					msg->add_conn.name, msg->add_conn.max_spi);
211
+ 
212
+ 	child_cfg = child_cfg_create(msg->add_conn.name, &child);
213
+ 	if (msg->add_conn.replay_window != -1)
214
+diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
215
+index 87e93ed..afec9be 100644
216
+--- a/src/libcharon/plugins/vici/vici_config.c
217
+@@ -2082,6 +2082,8 @@ CALLBACK(children_sn, bool,
218
+ 	log_child_data(&child, name);
219
+ 
220
+ 	child.cfg.clear_df = false;
221
++	child.cfg.max_spi = 0;
222
++	child.cfg.min_spi = 0;
223
+ 
224
+ 	cfg = child_cfg_create(name, &child.cfg);
225
+ 
226
+diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
227
+index ab5a3d0..db119b4 100644
228
+--- a/src/libcharon/sa/child_sa.c
229
+@@ -284,6 +284,16 @@ struct private_child_sa_t {
230
+ 	 * clear DF bit in outer IP
231
+ 	 */
232
+ 	bool clear_df;
233
++
234
++	/**
235
++	 * min SPI value to use
236
++	 */
237
++	u_int32_t min_spi;
238
++
239
++	/**
240
++	 * max SPI value to use
241
++	 */
242
++	u_int32_t max_spi;
243
+ };
244
+ 
245
+ /**
246
+@@ -510,6 +520,17 @@ METHOD(child_sa_t, is_clear_df, bool,
247
+ 	return this->clear_df;
248
+ }
249
+ 
250
++METHOD(child_sa_t, min_spi, u_int32_t,
251
++	   private_child_sa_t *this)
252
++{
253
++	return this->min_spi;
254
++}
255
++
256
++METHOD(child_sa_t, max_spi, u_int32_t,
257
++	   private_child_sa_t *this)
258
++{
259
++	return this->max_spi;
260
++}
261
+ 
262
+ typedef struct policy_enumerator_t policy_enumerator_t;
263
+ 
264
+@@ -833,7 +854,7 @@ METHOD(child_sa_t, alloc_spi, uint32_t,
265
+ 	   private_child_sa_t *this, protocol_id_t protocol)
266
+ {
267
+ 	if (charon->kernel->get_spi(charon->kernel, this->other_addr, this->my_addr,
268
+-							proto_ike2ip(protocol), &this->my_spi) == SUCCESS)
269
++							proto_ike2ip(protocol), this->min_spi, this->max_spi, &this->my_spi) == SUCCESS)
270
+ 	{
271
+ 		/* if we allocate a SPI, but then are unable to establish the SA, we
272
+ 		 * need to know the protocol family to delete the partial SA */
273
+@@ -2067,6 +2088,8 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
274
+ 			.create_policy_enumerator = _create_policy_enumerator,
275
+ 			.destroy = _destroy,
276
+ 			.is_clear_df = _is_clear_df,
277
++			.min_spi = _min_spi,
278
++			.max_spi = _max_spi,
279
+ 		},
280
+ 		.encap = data->encap,
281
+ 		.ipcomp = IPCOMP_NONE,
282
+@@ -2097,6 +2120,18 @@ child_sa_t *child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
283
+ 		this->clear_df = false;
284
+ 	}
285
+ 
286
++	if (config != NULL && config->min_spi != NULL) {
287
++		this->min_spi = config->min_spi(config);
288
++	} else {
289
++		this->min_spi = 0;
290
++	}
291
++
292
++	if (config != NULL && config->max_spi != NULL) {
293
++		this->max_spi = config->max_spi(config);
294
++	} else {
295
++		this->max_spi = 0;
296
++	}
297
++
298
+ 	if (data->mark_in)
299
+ 	{
300
+ 		this->mark_in.value = data->mark_in;
301
+diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
302
+index 742fa86..c1aad3b 100644
303
+--- a/src/libcharon/sa/child_sa.h
304
+@@ -527,6 +527,16 @@ struct child_sa_t {
305
+ 	 * Clear DF bit in outer IP
306
+ 	 */
307
+ 	bool (*is_clear_df) (child_sa_t *this);
308
++
309
++	/**
310
++	 * Min SPI to use
311
++	 */
312
++	u_int32_t (*min_spi) (child_sa_t *this);
313
++
314
++	/**
315
++	 * Max SPI to use
316
++	 */
317
++	u_int32_t (*max_spi) (child_sa_t *this);
318
+ };
319
+ 
320
+ /**
321
+diff --git a/src/libipsec/ipsec_sa_mgr.c b/src/libipsec/ipsec_sa_mgr.c
322
+index ab6a2f0..f258f5c 100644
323
+--- a/src/libipsec/ipsec_sa_mgr.c
324
+@@ -421,7 +421,7 @@ static bool allocate_spi(private_ipsec_sa_mgr_t *this, uint32_t spi)
325
+ 
326
+ METHOD(ipsec_sa_mgr_t, get_spi, status_t,
327
+ 	private_ipsec_sa_mgr_t *this, host_t *src, host_t *dst, uint8_t protocol,
328
+-	uint32_t *spi)
329
++	u_int32_t min, u_int32_t max, uint32_t *spi)
330
+ {
331
+ 	uint32_t spi_min, spi_max, spi_new;
332
+ 
333
+diff --git a/src/libipsec/ipsec_sa_mgr.h b/src/libipsec/ipsec_sa_mgr.h
334
+index 549b9f2..2092d86 100644
335
+--- a/src/libipsec/ipsec_sa_mgr.h
336
+@@ -50,7 +50,7 @@ struct ipsec_sa_mgr_t {
337
+ 	 * @return				SUCCESS of operation successful
338
+ 	 */
339
+ 	status_t (*get_spi)(ipsec_sa_mgr_t *this, host_t *src, host_t *dst,
340
+-						uint8_t protocol, uint32_t *spi);
341
++						uint8_t protocol, u_int32_t min, u_int32_t max, uint32_t *spi);
342
+ 
343
+ 	/**
344
+ 	 * Add a new SA
345
+diff --git a/src/starter/args.c b/src/starter/args.c
346
+index cd72730..eeaebb7 100644
347
+--- a/src/starter/args.c
348
+@@ -179,6 +179,8 @@ static const token_info_t token_info[] =
349
+ 	{ ARG_MISC, 0, NULL  /* KW_MARK_OUT */                                         },
350
+ 	{ ARG_MISC, 0, NULL  /* KW_TFC */                                              },
351
+ 	{ ARG_MISC, 0, NULL  /* KW_CLEAR_DF */                                         },
352
++	{ ARG_MISC, 0, NULL  /* KW_MIN_SPI */                                          },
353
++	{ ARG_MISC, 0, NULL  /* KW_MAX_SPI */                                          },
354
+ 	{ ARG_MISC, 0, NULL  /* KW_PFS_DEPRECATED */                                   },
355
+ 	{ ARG_MISC, 0, NULL  /* KW_CONN_DEPRECATED */                                  },
356
+ 
357
+diff --git a/src/starter/confread.c b/src/starter/confread.c
358
+index 1aa7ccc..6719759 100644
359
+--- a/src/starter/confread.c
360
+@@ -213,6 +213,8 @@ static void conn_defaults(starter_conn_t *conn)
361
+ 	conn->dpd_timeout           = 150; /* seconds */
362
+ 	conn->replay_window         = SA_REPLAY_WINDOW_DEFAULT;
363
+ 	conn->clear_df              = false;
364
++	conn->min_spi               = 0;
365
++	conn->max_spi               = 0;
366
+ 	conn->fragmentation         = FRAGMENTATION_YES;
367
+ 
368
+ 	conn->left.sendcert = CERT_SEND_IF_ASKED;
369
+@@ -526,6 +528,46 @@ static void handle_keyword(kw_token_t token, starter_conn_t *conn, char *key,
370
+ 				conn->clear_df = false;
371
+ 			}
372
+ 			break;
373
++		case KW_MIN_SPI:
374
++			DBG1(DBG_APP, "handle_keyword: %s=%s", key, value);
375
++			{
376
++				char *endptr;
377
++
378
++				conn->min_spi = strtoul(value, &endptr, 0);
379
++				if (*endptr != '\0')
380
++				{
381
++					DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
382
++					cfg->err;
383
++				}
384
++				if ((conn->max_spi != 0) && (conn->min_spi >= conn->max_spi))
385
++				{
386
++					DBG1(DBG_APP, "# min spi %x >= max_spi %x", conn->min_spi,
387
++					     conn->max_spi);
388
++					cfg->err;
389
++				}
390
++			}
391
++			DBG1(DBG_APP, "confread min_spi: %x", conn->min_spi);
392
++			break;
393
++		case KW_MAX_SPI:
394
++			DBG1(DBG_APP, "handle_keyword: %s=%s", key, value);
395
++			{
396
++				char *endptr;
397
++
398
++				conn->max_spi = strtoul(value, &endptr, 0);
399
++				if (*endptr != '\0')
400
++				{
401
++					DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
402
++					cfg->err;
403
++				}
404
++				if ((conn->min_spi != 0) && (conn->max_spi <= conn->min_spi))
405
++				{
406
++					DBG1(DBG_APP, "# max spi %x <= min_spi %x", conn->max_spi,
407
++					     conn->min_spi);
408
++					cfg->err;
409
++				}
410
++			}
411
++			DBG1(DBG_APP, "confread max_spi: %x", conn->max_spi);
412
++			break;
413
+ 		default:
414
+ 			break;
415
+ 	}
416
+diff --git a/src/starter/confread.h b/src/starter/confread.h
417
+index fbbe85e..63ce7ad 100644
418
+--- a/src/starter/confread.h
419
+@@ -148,6 +148,8 @@ struct starter_conn {
420
+ 		bool            install_policy;
421
+ 		bool            aggressive;
422
+ 		bool            clear_df;
423
++		u_int32_t       min_spi;
424
++		u_int32_t       max_spi;
425
+ 		starter_end_t   left, right;
426
+ 
427
+ 		unsigned long   id;
428
+diff --git a/src/starter/keywords.h.in b/src/starter/keywords.h.in
429
+index 071e344..f3d2b41 100644
430
+--- a/src/starter/keywords.h.in
431
+@@ -78,6 +78,8 @@ enum kw_token_t {
432
+ 	KW_MARK_OUT,
433
+ 	KW_TFC,
434
+ 	KW_CLEAR_DF,
435
++	KW_MIN_SPI,
436
++	KW_MAX_SPI,
437
+ 	KW_PFS_DEPRECATED,
438
+ 	KW_CONN_DEPRECATED,
439
+ 
440
+@@ -188,7 +190,6 @@ enum kw_token_t {
441
+ 	/* general section keywords */
442
+ 	KW_ALSO,
443
+ 	KW_AUTO,
444
+-
445
+ };
446
+ 
447
+ struct kw_entry_t {
448
+diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
449
+index c0005ba..2eadae0 100644
450
+--- a/src/starter/keywords.txt
451
+@@ -167,3 +167,5 @@ eap,               KW_CONN_DEPRECATED
452
+ leftnexthop,       KW_LEFT_DEPRECATED
453
+ rightnexthop,      KW_RIGHT_DEPRECATED
454
+ cleardf,           KW_CLEAR_DF
455
++min_spi,           KW_MIN_SPI
456
++max_spi,           KW_MAX_SPI
457
+diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
458
+index 80e0620..c8ad0dc 100644
459
+--- a/src/starter/starterstroke.c
460
+@@ -243,6 +243,8 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
461
+ 	msg->add_conn.mark_out.mask = conn->mark_out.mask;
462
+ 	msg->add_conn.tfc = conn->tfc;
463
+ 	msg->add_conn.clear_df = conn->clear_df ? 1 : 0;
464
++	msg->add_conn.min_spi = conn->min_spi ? conn->min_spi : 0xc0000000;
465
++	msg->add_conn.max_spi = conn->max_spi ? conn->max_spi : 0xcfffffff;
466
+ 
467
+ 	add_end(&msg, offsetof(stroke_msg_t, add_conn.me), &conn->left);
468
+ 	add_end(&msg, offsetof(stroke_msg_t, add_conn.other), &conn->right);
469
+diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
470
+index f5aa63b..0d49132 100644
471
+--- a/src/stroke/stroke_msg.h
472
+@@ -305,6 +305,8 @@ struct stroke_msg_t {
473
+ 			uint32_t replay_window;
474
+ 			bool sha256_96;
475
+ 			int clear_df;
476
++			u_int32_t min_spi;
477
++			u_int32_t max_spi;
478
+ 		} add_conn;
479
+ 
480
+ 		/* data for STR_ADD_CA */
481
+-- 
482
+2.35.6
483
+
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:          The OpenSource IPsec-based VPN Solution
2 2
 Name:             strongswan
3 3
 Version:          5.9.8
4
-Release:          1%{?dist}
4
+Release:          2%{?dist}
5 5
 License:          GPLv2+
6 6
 URL:              https://www.strongswan.org
7 7
 Group:            System Environment/Security
... ...
@@ -15,9 +15,15 @@ Source0: https://download.strongswan.org/%{name}-%{version}.tar.bz2
15 15
 Patch0: strongswan-fix-make-check.patch
16 16
 %endif
17 17
 
18
+Patch1: 0001-HCX-custom-remote-natt-port.patch
19
+Patch2: 0002-ipsec-Add-clear_df-flag.patch
20
+Patch3: 0003-reiniate-conn-on-failure.patch
21
+Patch4: 0004-Add-new-configs-min_spi-and-max_spi.patch
22
+
18 23
 BuildRequires:    autoconf
19 24
 BuildRequires:    gmp-devel
20 25
 BuildRequires:    systemd-devel
26
+BuildRequires:    gperf
21 27
 %{?systemd_requires}
22 28
 
23 29
 Requires: systemd
... ...
@@ -31,7 +37,14 @@ strongSwan is a complete IPsec implementation for Linux 2.6, 3.x, and 4.x kernel
31 31
 
32 32
 %build
33 33
 %configure \
34
-    --enable-systemd
34
+    --enable-systemd \
35
+%ifarch x86_64
36
+    --enable-aesni \
37
+%endif
38
+    --enable-openssl \
39
+    --enable-socket-dynamic \
40
+    --enable-vici \
41
+    --enable-swanctl
35 42
 
36 43
 %make_build
37 44
 
... ...
@@ -76,6 +89,8 @@ rm -rf %{buildroot}/*
76 76
 %{_unitdir}/%{name}.service
77 77
 
78 78
 %changelog
79
+* Thu Mar 09 2023 Srish Srinivasan <ssrish@vmware.com> 5.9.8-2
80
+- Added HCX patches
79 81
 * Tue Nov 08 2022 Shreenidhi Shedi <sshedi@vmware.com> 5.9.8-1
80 82
 - Upgrade to v5.9.8
81 83
 * Thu Aug 18 2022 Gerrit Photon <photon-checkins@vmware.com> 5.9.7-1