diff mbox series

[API-NEXT,v14,13/16] linux-gen: ipsec: support ODP_IPSEC_FRAG_CHECK

Message ID 1513119632-28755-14-git-send-email-odpbot@yandex.ru
State New
Headers show
Series [API-NEXT,v14,1/16] validation: ipsec: add ipv4 name parts | expand

Commit Message

Github ODP bot Dec. 12, 2017, 11 p.m. UTC
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>


Support checking MTU after IPsec transformation.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

---
/** Email created from pull request 304 (lumag:ipsec-ipv6-2)
 ** https://github.com/Linaro/odp/pull/304
 ** Patch: https://github.com/Linaro/odp/pull/304.patch
 ** Base sha: d96a8207591fbcaac25b79286d7d72a537354c1f
 ** Merge commit sha: 832a79461bc8bd90e572c396fa081e162e1dacb6
 **/
 platform/linux-generic/odp_ipsec.c | 39 ++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index 43fbafd5d..6568924a3 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -990,7 +990,8 @@  static int ipsec_out_esp(odp_packet_t *pkt,
 			 ipsec_state_t *state,
 			 ipsec_sa_t *ipsec_sa,
 			 odp_crypto_packet_op_param_t *param,
-			 odp_ipsec_op_status_t *status)
+			 odp_ipsec_op_status_t *status,
+			 uint32_t mtu)
 {
 	_odp_esphdr_t esp;
 	_odp_esptrl_t esptrl;
@@ -1026,6 +1027,11 @@  static int ipsec_out_esp(odp_packet_t *pkt,
 		udphdr.chksum = 0; /* should be 0 by RFC */
 	}
 
+	if (state->ip_tot_len + hdr_len + trl_len > mtu) {
+		status->error.mtu = 1;
+		return -1;
+	}
+
 	if (ipsec_out_iv(state, ipsec_sa) < 0) {
 		status->error.alg = 1;
 		return -1;
@@ -1124,7 +1130,8 @@  static int ipsec_out_ah(odp_packet_t *pkt,
 			ipsec_state_t *state,
 			ipsec_sa_t *ipsec_sa,
 			odp_crypto_packet_op_param_t *param,
-			odp_ipsec_op_status_t *status)
+			odp_ipsec_op_status_t *status,
+			uint32_t mtu)
 {
 	_odp_ahhdr_t ah;
 	unsigned hdr_len = _ODP_AHHDR_LEN + ipsec_sa->esp_iv_len +
@@ -1132,6 +1139,11 @@  static int ipsec_out_ah(odp_packet_t *pkt,
 	uint16_t ipsec_offset = state->ip_offset + state->ip_hdr_len;
 	uint8_t proto = _ODP_IPPROTO_AH;
 
+	if (state->ip_tot_len + hdr_len > mtu) {
+		status->error.mtu = 1;
+		return -1;
+	}
+
 	memset(&ah, 0, sizeof(ah));
 	ah.spi = odp_cpu_to_be_32(ipsec_sa->spi);
 	ah.seq_no = odp_cpu_to_be_32(ipsec_seq_no(ipsec_sa));
@@ -1228,7 +1240,7 @@  static void ipsec_out_ah_post(ipsec_state_t *state, odp_packet_t pkt)
 static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 				    odp_ipsec_sa_t sa,
 				    odp_packet_t *pkt_out,
-				    const odp_ipsec_out_opt_t *opt ODP_UNUSED,
+				    const odp_ipsec_out_opt_t *opt,
 				    odp_ipsec_op_status_t *status)
 {
 	ipsec_state_t state;
@@ -1237,6 +1249,7 @@  static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 	int rc;
 	odp_crypto_packet_result_t crypto; /**< Crypto operation result */
 	odp_packet_hdr_t *pkt_hdr;
+	uint32_t mtu;
 
 	state.ip_offset = odp_packet_l3_offset(pkt);
 	ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != state.ip_offset);
@@ -1247,6 +1260,12 @@  static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 	ipsec_sa = _odp_ipsec_sa_use(sa);
 	ODP_ASSERT(NULL != ipsec_sa);
 
+	if ((opt && opt->mode == ODP_IPSEC_FRAG_CHECK) ||
+	    (!opt && ipsec_sa->out.frag_mode == ODP_IPSEC_FRAG_CHECK))
+		mtu = ipsec_sa->out.mtu;
+	else
+		mtu = UINT32_MAX;
+
 	/* Initialize parameters block */
 	memset(&param, 0, sizeof(param));
 
@@ -1281,9 +1300,9 @@  static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 	}
 
 	if (ODP_IPSEC_ESP == ipsec_sa->proto) {
-		rc = ipsec_out_esp(&pkt, &state, ipsec_sa, &param, status);
+		rc = ipsec_out_esp(&pkt, &state, ipsec_sa, &param, status, mtu);
 	} else if (ODP_IPSEC_AH == ipsec_sa->proto) {
-		rc = ipsec_out_ah(&pkt, &state, ipsec_sa, &param, status);
+		rc = ipsec_out_ah(&pkt, &state, ipsec_sa, &param, status, mtu);
 	} else {
 		status->error.alg = 1;
 		goto err;
@@ -1401,10 +1420,6 @@  int odp_ipsec_in(const odp_packet_t pkt_in[], int num_in,
 	return in_pkt;
 }
 
-static const odp_ipsec_out_opt_t default_opt = {
-	.mode = ODP_IPSEC_FRAG_DISABLED,
-};
-
 int odp_ipsec_out(const odp_packet_t pkt_in[], int num_in,
 		  odp_packet_t pkt_out[], int *num_out,
 		  const odp_ipsec_out_param_t *param)
@@ -1433,7 +1448,7 @@  int odp_ipsec_out(const odp_packet_t pkt_in[], int num_in,
 		ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa);
 
 		if (0 == param->num_opt)
-			opt = &default_opt;
+			opt = NULL;
 		else
 			opt = &param->opt[opt_idx];
 
@@ -1540,7 +1555,7 @@  int odp_ipsec_out_enq(const odp_packet_t pkt_in[], int num_in,
 		ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa);
 
 		if (0 == param->num_opt)
-			opt = &default_opt;
+			opt = NULL;
 		else
 			opt = &param->opt[opt_idx];
 
@@ -1635,7 +1650,7 @@  int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int num_in,
 		}
 
 		if (0 == param->num_opt)
-			opt = &default_opt;
+			opt = NULL;
 		else
 			opt = &param->opt[opt_idx];