Commit c39596f6 authored by Steffen Klassert's avatar Steffen Klassert

Merge branch 'xfrm: add netlink extack to all the ->init_stat'

Sabrina Dubroca says:

============
This series completes extack support for state creation.
============
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parents 48ff45da 28b5dbd5
...@@ -22,7 +22,7 @@ struct xfrm_state; ...@@ -22,7 +22,7 @@ struct xfrm_state;
int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb); int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb);
int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb); int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb);
void ipcomp_destroy(struct xfrm_state *x); void ipcomp_destroy(struct xfrm_state *x);
int ipcomp_init_state(struct xfrm_state *x); int ipcomp_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack);
static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb) static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
{ {
......
...@@ -405,7 +405,8 @@ struct xfrm_type { ...@@ -405,7 +405,8 @@ struct xfrm_type {
#define XFRM_TYPE_LOCAL_COADDR 4 #define XFRM_TYPE_LOCAL_COADDR 4
#define XFRM_TYPE_REMOTE_COADDR 8 #define XFRM_TYPE_REMOTE_COADDR 8
int (*init_state)(struct xfrm_state *x); int (*init_state)(struct xfrm_state *x,
struct netlink_ext_ack *extack);
void (*destructor)(struct xfrm_state *); void (*destructor)(struct xfrm_state *);
int (*input)(struct xfrm_state *, struct sk_buff *skb); int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb); int (*output)(struct xfrm_state *, struct sk_buff *pskb);
......
...@@ -471,30 +471,38 @@ static int ah4_err(struct sk_buff *skb, u32 info) ...@@ -471,30 +471,38 @@ static int ah4_err(struct sk_buff *skb, u32 info)
return 0; return 0;
} }
static int ah_init_state(struct xfrm_state *x) static int ah_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
struct ah_data *ahp = NULL; struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc; struct xfrm_algo_desc *aalg_desc;
struct crypto_ahash *ahash; struct crypto_ahash *ahash;
if (!x->aalg) if (!x->aalg) {
NL_SET_ERR_MSG(extack, "AH requires a state with an AUTH algorithm");
goto error; goto error;
}
if (x->encap) if (x->encap) {
NL_SET_ERR_MSG(extack, "AH is not compatible with encapsulation");
goto error; goto error;
}
ahp = kzalloc(sizeof(*ahp), GFP_KERNEL); ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
if (!ahp) if (!ahp)
return -ENOMEM; return -ENOMEM;
ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0); ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
if (IS_ERR(ahash)) if (IS_ERR(ahash)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error; goto error;
}
ahp->ahash = ahash; ahp->ahash = ahash;
if (crypto_ahash_setkey(ahash, x->aalg->alg_key, if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
(x->aalg->alg_key_len + 7) / 8)) (x->aalg->alg_key_len + 7) / 8)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error; goto error;
}
/* /*
* Lookup the algorithm description maintained by xfrm_algo, * Lookup the algorithm description maintained by xfrm_algo,
...@@ -507,10 +515,7 @@ static int ah_init_state(struct xfrm_state *x) ...@@ -507,10 +515,7 @@ static int ah_init_state(struct xfrm_state *x)
if (aalg_desc->uinfo.auth.icv_fullbits/8 != if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
crypto_ahash_digestsize(ahash)) { crypto_ahash_digestsize(ahash)) {
pr_info("%s: %s digestsize %u != %u\n", NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
__func__, x->aalg->alg_name,
crypto_ahash_digestsize(ahash),
aalg_desc->uinfo.auth.icv_fullbits / 8);
goto error; goto error;
} }
......
...@@ -1007,16 +1007,17 @@ static void esp_destroy(struct xfrm_state *x) ...@@ -1007,16 +1007,17 @@ static void esp_destroy(struct xfrm_state *x)
crypto_free_aead(aead); crypto_free_aead(aead);
} }
static int esp_init_aead(struct xfrm_state *x) static int esp_init_aead(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
char aead_name[CRYPTO_MAX_ALG_NAME]; char aead_name[CRYPTO_MAX_ALG_NAME];
struct crypto_aead *aead; struct crypto_aead *aead;
int err; int err;
err = -ENAMETOOLONG;
if (snprintf(aead_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", if (snprintf(aead_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME) x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME) {
goto error; NL_SET_ERR_MSG(extack, "Algorithm name is too long");
return -ENAMETOOLONG;
}
aead = crypto_alloc_aead(aead_name, 0, 0); aead = crypto_alloc_aead(aead_name, 0, 0);
err = PTR_ERR(aead); err = PTR_ERR(aead);
...@@ -1034,11 +1035,15 @@ static int esp_init_aead(struct xfrm_state *x) ...@@ -1034,11 +1035,15 @@ static int esp_init_aead(struct xfrm_state *x)
if (err) if (err)
goto error; goto error;
return 0;
error: error:
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
return err; return err;
} }
static int esp_init_authenc(struct xfrm_state *x) static int esp_init_authenc(struct xfrm_state *x,
struct netlink_ext_ack *extack)
{ {
struct crypto_aead *aead; struct crypto_aead *aead;
struct crypto_authenc_key_param *param; struct crypto_authenc_key_param *param;
...@@ -1049,10 +1054,6 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1049,10 +1054,6 @@ static int esp_init_authenc(struct xfrm_state *x)
unsigned int keylen; unsigned int keylen;
int err; int err;
err = -EINVAL;
if (!x->ealg)
goto error;
err = -ENAMETOOLONG; err = -ENAMETOOLONG;
if ((x->props.flags & XFRM_STATE_ESN)) { if ((x->props.flags & XFRM_STATE_ESN)) {
...@@ -1061,22 +1062,28 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1061,22 +1062,28 @@ static int esp_init_authenc(struct xfrm_state *x)
x->geniv ?: "", x->geniv ? "(" : "", x->geniv ?: "", x->geniv ? "(" : "",
x->aalg ? x->aalg->alg_name : "digest_null", x->aalg ? x->aalg->alg_name : "digest_null",
x->ealg->alg_name, x->ealg->alg_name,
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) {
NL_SET_ERR_MSG(extack, "Algorithm name is too long");
goto error; goto error;
}
} else { } else {
if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
"%s%sauthenc(%s,%s)%s", "%s%sauthenc(%s,%s)%s",
x->geniv ?: "", x->geniv ? "(" : "", x->geniv ?: "", x->geniv ? "(" : "",
x->aalg ? x->aalg->alg_name : "digest_null", x->aalg ? x->aalg->alg_name : "digest_null",
x->ealg->alg_name, x->ealg->alg_name,
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) {
NL_SET_ERR_MSG(extack, "Algorithm name is too long");
goto error; goto error;
}
} }
aead = crypto_alloc_aead(authenc_name, 0, 0); aead = crypto_alloc_aead(authenc_name, 0, 0);
err = PTR_ERR(aead); err = PTR_ERR(aead);
if (IS_ERR(aead)) if (IS_ERR(aead)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error; goto error;
}
x->data = aead; x->data = aead;
...@@ -1106,17 +1113,16 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1106,17 +1113,16 @@ static int esp_init_authenc(struct xfrm_state *x)
err = -EINVAL; err = -EINVAL;
if (aalg_desc->uinfo.auth.icv_fullbits / 8 != if (aalg_desc->uinfo.auth.icv_fullbits / 8 !=
crypto_aead_authsize(aead)) { crypto_aead_authsize(aead)) {
pr_info("ESP: %s digestsize %u != %u\n", NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
x->aalg->alg_name,
crypto_aead_authsize(aead),
aalg_desc->uinfo.auth.icv_fullbits / 8);
goto free_key; goto free_key;
} }
err = crypto_aead_setauthsize( err = crypto_aead_setauthsize(
aead, x->aalg->alg_trunc_len / 8); aead, x->aalg->alg_trunc_len / 8);
if (err) if (err) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto free_key; goto free_key;
}
} }
param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
...@@ -1131,7 +1137,7 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1131,7 +1137,7 @@ static int esp_init_authenc(struct xfrm_state *x)
return err; return err;
} }
static int esp_init_state(struct xfrm_state *x) static int esp_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
struct crypto_aead *aead; struct crypto_aead *aead;
u32 align; u32 align;
...@@ -1139,10 +1145,14 @@ static int esp_init_state(struct xfrm_state *x) ...@@ -1139,10 +1145,14 @@ static int esp_init_state(struct xfrm_state *x)
x->data = NULL; x->data = NULL;
if (x->aead) if (x->aead) {
err = esp_init_aead(x); err = esp_init_aead(x, extack);
else } else if (x->ealg) {
err = esp_init_authenc(x); err = esp_init_authenc(x, extack);
} else {
NL_SET_ERR_MSG(extack, "ESP: AEAD or CRYPT must be provided");
err = -EINVAL;
}
if (err) if (err)
goto error; goto error;
...@@ -1160,6 +1170,7 @@ static int esp_init_state(struct xfrm_state *x) ...@@ -1160,6 +1170,7 @@ static int esp_init_state(struct xfrm_state *x)
switch (encap->encap_type) { switch (encap->encap_type) {
default: default:
NL_SET_ERR_MSG(extack, "Unsupported encapsulation type for ESP");
err = -EINVAL; err = -EINVAL;
goto error; goto error;
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
......
...@@ -117,7 +117,8 @@ static int ipcomp_tunnel_attach(struct xfrm_state *x) ...@@ -117,7 +117,8 @@ static int ipcomp_tunnel_attach(struct xfrm_state *x)
return err; return err;
} }
static int ipcomp4_init_state(struct xfrm_state *x) static int ipcomp4_init_state(struct xfrm_state *x,
struct netlink_ext_ack *extack)
{ {
int err = -EINVAL; int err = -EINVAL;
...@@ -129,17 +130,20 @@ static int ipcomp4_init_state(struct xfrm_state *x) ...@@ -129,17 +130,20 @@ static int ipcomp4_init_state(struct xfrm_state *x)
x->props.header_len += sizeof(struct iphdr); x->props.header_len += sizeof(struct iphdr);
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Unsupported XFRM mode for IPcomp");
goto out; goto out;
} }
err = ipcomp_init_state(x); err = ipcomp_init_state(x, extack);
if (err) if (err)
goto out; goto out;
if (x->props.mode == XFRM_MODE_TUNNEL) { if (x->props.mode == XFRM_MODE_TUNNEL) {
err = ipcomp_tunnel_attach(x); err = ipcomp_tunnel_attach(x);
if (err) if (err) {
NL_SET_ERR_MSG(extack, "Kernel error: failed to initialize the associated state");
goto out; goto out;
}
} }
err = 0; err = 0;
......
...@@ -22,13 +22,17 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) ...@@ -22,13 +22,17 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
return ip_hdr(skb)->protocol; return ip_hdr(skb)->protocol;
} }
static int ipip_init_state(struct xfrm_state *x) static int ipip_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
if (x->props.mode != XFRM_MODE_TUNNEL) if (x->props.mode != XFRM_MODE_TUNNEL) {
NL_SET_ERR_MSG(extack, "IPv4 tunnel can only be used with tunnel mode");
return -EINVAL; return -EINVAL;
}
if (x->encap) if (x->encap) {
NL_SET_ERR_MSG(extack, "IPv4 tunnel is not compatible with encapsulation");
return -EINVAL; return -EINVAL;
}
x->props.header_len = sizeof(struct iphdr); x->props.header_len = sizeof(struct iphdr);
......
...@@ -666,30 +666,38 @@ static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -666,30 +666,38 @@ static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0; return 0;
} }
static int ah6_init_state(struct xfrm_state *x) static int ah6_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
struct ah_data *ahp = NULL; struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc; struct xfrm_algo_desc *aalg_desc;
struct crypto_ahash *ahash; struct crypto_ahash *ahash;
if (!x->aalg) if (!x->aalg) {
NL_SET_ERR_MSG(extack, "AH requires a state with an AUTH algorithm");
goto error; goto error;
}
if (x->encap) if (x->encap) {
NL_SET_ERR_MSG(extack, "AH is not compatible with encapsulation");
goto error; goto error;
}
ahp = kzalloc(sizeof(*ahp), GFP_KERNEL); ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
if (!ahp) if (!ahp)
return -ENOMEM; return -ENOMEM;
ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0); ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
if (IS_ERR(ahash)) if (IS_ERR(ahash)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error; goto error;
}
ahp->ahash = ahash; ahp->ahash = ahash;
if (crypto_ahash_setkey(ahash, x->aalg->alg_key, if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
(x->aalg->alg_key_len + 7) / 8)) (x->aalg->alg_key_len + 7) / 8)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error; goto error;
}
/* /*
* Lookup the algorithm description maintained by xfrm_algo, * Lookup the algorithm description maintained by xfrm_algo,
...@@ -702,9 +710,7 @@ static int ah6_init_state(struct xfrm_state *x) ...@@ -702,9 +710,7 @@ static int ah6_init_state(struct xfrm_state *x)
if (aalg_desc->uinfo.auth.icv_fullbits/8 != if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
crypto_ahash_digestsize(ahash)) { crypto_ahash_digestsize(ahash)) {
pr_info("AH: %s digestsize %u != %u\n", NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
x->aalg->alg_name, crypto_ahash_digestsize(ahash),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error; goto error;
} }
...@@ -721,6 +727,7 @@ static int ah6_init_state(struct xfrm_state *x) ...@@ -721,6 +727,7 @@ static int ah6_init_state(struct xfrm_state *x)
x->props.header_len += sizeof(struct ipv6hdr); x->props.header_len += sizeof(struct ipv6hdr);
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Invalid mode requested for AH, must be one of TRANSPORT, TUNNEL, BEET");
goto error; goto error;
} }
x->data = ahp; x->data = ahp;
......
...@@ -1050,16 +1050,17 @@ static void esp6_destroy(struct xfrm_state *x) ...@@ -1050,16 +1050,17 @@ static void esp6_destroy(struct xfrm_state *x)
crypto_free_aead(aead); crypto_free_aead(aead);
} }
static int esp_init_aead(struct xfrm_state *x) static int esp_init_aead(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
char aead_name[CRYPTO_MAX_ALG_NAME]; char aead_name[CRYPTO_MAX_ALG_NAME];
struct crypto_aead *aead; struct crypto_aead *aead;
int err; int err;
err = -ENAMETOOLONG;
if (snprintf(aead_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", if (snprintf(aead_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME) x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME) {
goto error; NL_SET_ERR_MSG(extack, "Algorithm name is too long");
return -ENAMETOOLONG;
}
aead = crypto_alloc_aead(aead_name, 0, 0); aead = crypto_alloc_aead(aead_name, 0, 0);
err = PTR_ERR(aead); err = PTR_ERR(aead);
...@@ -1077,11 +1078,15 @@ static int esp_init_aead(struct xfrm_state *x) ...@@ -1077,11 +1078,15 @@ static int esp_init_aead(struct xfrm_state *x)
if (err) if (err)
goto error; goto error;
return 0;
error: error:
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
return err; return err;
} }
static int esp_init_authenc(struct xfrm_state *x) static int esp_init_authenc(struct xfrm_state *x,
struct netlink_ext_ack *extack)
{ {
struct crypto_aead *aead; struct crypto_aead *aead;
struct crypto_authenc_key_param *param; struct crypto_authenc_key_param *param;
...@@ -1092,10 +1097,6 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1092,10 +1097,6 @@ static int esp_init_authenc(struct xfrm_state *x)
unsigned int keylen; unsigned int keylen;
int err; int err;
err = -EINVAL;
if (!x->ealg)
goto error;
err = -ENAMETOOLONG; err = -ENAMETOOLONG;
if ((x->props.flags & XFRM_STATE_ESN)) { if ((x->props.flags & XFRM_STATE_ESN)) {
...@@ -1104,22 +1105,28 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1104,22 +1105,28 @@ static int esp_init_authenc(struct xfrm_state *x)
x->geniv ?: "", x->geniv ? "(" : "", x->geniv ?: "", x->geniv ? "(" : "",
x->aalg ? x->aalg->alg_name : "digest_null", x->aalg ? x->aalg->alg_name : "digest_null",
x->ealg->alg_name, x->ealg->alg_name,
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) {
NL_SET_ERR_MSG(extack, "Algorithm name is too long");
goto error; goto error;
}
} else { } else {
if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
"%s%sauthenc(%s,%s)%s", "%s%sauthenc(%s,%s)%s",
x->geniv ?: "", x->geniv ? "(" : "", x->geniv ?: "", x->geniv ? "(" : "",
x->aalg ? x->aalg->alg_name : "digest_null", x->aalg ? x->aalg->alg_name : "digest_null",
x->ealg->alg_name, x->ealg->alg_name,
x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME) {
NL_SET_ERR_MSG(extack, "Algorithm name is too long");
goto error; goto error;
}
} }
aead = crypto_alloc_aead(authenc_name, 0, 0); aead = crypto_alloc_aead(authenc_name, 0, 0);
err = PTR_ERR(aead); err = PTR_ERR(aead);
if (IS_ERR(aead)) if (IS_ERR(aead)) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto error; goto error;
}
x->data = aead; x->data = aead;
...@@ -1149,17 +1156,16 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1149,17 +1156,16 @@ static int esp_init_authenc(struct xfrm_state *x)
err = -EINVAL; err = -EINVAL;
if (aalg_desc->uinfo.auth.icv_fullbits / 8 != if (aalg_desc->uinfo.auth.icv_fullbits / 8 !=
crypto_aead_authsize(aead)) { crypto_aead_authsize(aead)) {
pr_info("ESP: %s digestsize %u != %u\n", NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
x->aalg->alg_name,
crypto_aead_authsize(aead),
aalg_desc->uinfo.auth.icv_fullbits / 8);
goto free_key; goto free_key;
} }
err = crypto_aead_setauthsize( err = crypto_aead_setauthsize(
aead, x->aalg->alg_trunc_len / 8); aead, x->aalg->alg_trunc_len / 8);
if (err) if (err) {
NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
goto free_key; goto free_key;
}
} }
param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
...@@ -1174,7 +1180,7 @@ static int esp_init_authenc(struct xfrm_state *x) ...@@ -1174,7 +1180,7 @@ static int esp_init_authenc(struct xfrm_state *x)
return err; return err;
} }
static int esp6_init_state(struct xfrm_state *x) static int esp6_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
struct crypto_aead *aead; struct crypto_aead *aead;
u32 align; u32 align;
...@@ -1182,10 +1188,14 @@ static int esp6_init_state(struct xfrm_state *x) ...@@ -1182,10 +1188,14 @@ static int esp6_init_state(struct xfrm_state *x)
x->data = NULL; x->data = NULL;
if (x->aead) if (x->aead) {
err = esp_init_aead(x); err = esp_init_aead(x, extack);
else } else if (x->ealg) {
err = esp_init_authenc(x); err = esp_init_authenc(x, extack);
} else {
NL_SET_ERR_MSG(extack, "ESP: AEAD or CRYPT must be provided");
err = -EINVAL;
}
if (err) if (err)
goto error; goto error;
...@@ -1213,6 +1223,7 @@ static int esp6_init_state(struct xfrm_state *x) ...@@ -1213,6 +1223,7 @@ static int esp6_init_state(struct xfrm_state *x)
switch (encap->encap_type) { switch (encap->encap_type) {
default: default:
NL_SET_ERR_MSG(extack, "Unsupported encapsulation type for ESP");
err = -EINVAL; err = -EINVAL;
goto error; goto error;
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
......
...@@ -136,7 +136,8 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x) ...@@ -136,7 +136,8 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x)
return err; return err;
} }
static int ipcomp6_init_state(struct xfrm_state *x) static int ipcomp6_init_state(struct xfrm_state *x,
struct netlink_ext_ack *extack)
{ {
int err = -EINVAL; int err = -EINVAL;
...@@ -148,17 +149,20 @@ static int ipcomp6_init_state(struct xfrm_state *x) ...@@ -148,17 +149,20 @@ static int ipcomp6_init_state(struct xfrm_state *x)
x->props.header_len += sizeof(struct ipv6hdr); x->props.header_len += sizeof(struct ipv6hdr);
break; break;
default: default:
NL_SET_ERR_MSG(extack, "Unsupported XFRM mode for IPcomp");
goto out; goto out;
} }
err = ipcomp_init_state(x); err = ipcomp_init_state(x, extack);
if (err) if (err)
goto out; goto out;
if (x->props.mode == XFRM_MODE_TUNNEL) { if (x->props.mode == XFRM_MODE_TUNNEL) {
err = ipcomp6_tunnel_attach(x); err = ipcomp6_tunnel_attach(x);
if (err) if (err) {
NL_SET_ERR_MSG(extack, "Kernel error: failed to initialize the associated state");
goto out; goto out;
}
} }
err = 0; err = 0;
......
...@@ -247,15 +247,14 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, ...@@ -247,15 +247,14 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb,
return err; return err;
} }
static int mip6_destopt_init_state(struct xfrm_state *x) static int mip6_destopt_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
if (x->id.spi) { if (x->id.spi) {
pr_info("%s: spi is not 0: %u\n", __func__, x->id.spi); NL_SET_ERR_MSG(extack, "SPI must be 0");
return -EINVAL; return -EINVAL;
} }
if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
pr_info("%s: state's mode is not %u: %u\n", NL_SET_ERR_MSG(extack, "XFRM mode must be XFRM_MODE_ROUTEOPTIMIZATION");
__func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
return -EINVAL; return -EINVAL;
} }
...@@ -333,15 +332,14 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -333,15 +332,14 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
return 0; return 0;
} }
static int mip6_rthdr_init_state(struct xfrm_state *x) static int mip6_rthdr_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
if (x->id.spi) { if (x->id.spi) {
pr_info("%s: spi is not 0: %u\n", __func__, x->id.spi); NL_SET_ERR_MSG(extack, "SPI must be 0");
return -EINVAL; return -EINVAL;
} }
if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) {
pr_info("%s: state's mode is not %u: %u\n", NL_SET_ERR_MSG(extack, "XFRM mode must be XFRM_MODE_ROUTEOPTIMIZATION");
__func__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode);
return -EINVAL; return -EINVAL;
} }
......
...@@ -270,13 +270,17 @@ static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -270,13 +270,17 @@ static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0; return 0;
} }
static int xfrm6_tunnel_init_state(struct xfrm_state *x) static int xfrm6_tunnel_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
if (x->props.mode != XFRM_MODE_TUNNEL) if (x->props.mode != XFRM_MODE_TUNNEL) {
NL_SET_ERR_MSG(extack, "IPv6 tunnel can only be used with tunnel mode");
return -EINVAL; return -EINVAL;
}
if (x->encap) if (x->encap) {
NL_SET_ERR_MSG(extack, "IPv6 tunnel is not compatible with encapsulation");
return -EINVAL; return -EINVAL;
}
x->props.header_len = sizeof(struct ipv6hdr); x->props.header_len = sizeof(struct ipv6hdr);
......
...@@ -325,18 +325,22 @@ void ipcomp_destroy(struct xfrm_state *x) ...@@ -325,18 +325,22 @@ void ipcomp_destroy(struct xfrm_state *x)
} }
EXPORT_SYMBOL_GPL(ipcomp_destroy); EXPORT_SYMBOL_GPL(ipcomp_destroy);
int ipcomp_init_state(struct xfrm_state *x) int ipcomp_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
{ {
int err; int err;
struct ipcomp_data *ipcd; struct ipcomp_data *ipcd;
struct xfrm_algo_desc *calg_desc; struct xfrm_algo_desc *calg_desc;
err = -EINVAL; err = -EINVAL;
if (!x->calg) if (!x->calg) {
NL_SET_ERR_MSG(extack, "Missing required compression algorithm");
goto out; goto out;
}
if (x->encap) if (x->encap) {
NL_SET_ERR_MSG(extack, "IPComp is not compatible with encapsulation");
goto out; goto out;
}
err = -ENOMEM; err = -ENOMEM;
ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL); ipcd = kzalloc(sizeof(*ipcd), GFP_KERNEL);
......
...@@ -2673,7 +2673,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload, ...@@ -2673,7 +2673,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
x->type_offload = xfrm_get_type_offload(x->id.proto, family, offload); x->type_offload = xfrm_get_type_offload(x->id.proto, family, offload);
err = x->type->init_state(x); err = x->type->init_state(x, extack);
if (err) if (err)
goto error; goto error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment