Commit 44e2b838 authored by Benedict Wong's avatar Benedict Wong Committed by Steffen Klassert

xfrm: Return detailed errors from xfrmi_newlink

Currently all failure modes of xfrm interface creation return EEXIST.
This change improves the granularity of errnos provided by also
returning ENODEV or EINVAL if failures happen in looking up the
underlying interface, or a required parameter is not provided.

This change has been tested against the Android Kernel Networking Tests,
with additional xfrmi_newlink tests here:

https://android-review.googlesource.com/c/kernel/tests/+/715755Signed-off-by: default avatarBenedict Wong <benedictwong@google.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 934ffce1
...@@ -149,14 +149,18 @@ static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p) ...@@ -149,14 +149,18 @@ static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p)
char name[IFNAMSIZ]; char name[IFNAMSIZ];
int err; int err;
if (p->name[0]) if (p->name[0]) {
strlcpy(name, p->name, IFNAMSIZ); strlcpy(name, p->name, IFNAMSIZ);
else } else {
err = -EINVAL;
goto failed; goto failed;
}
dev = alloc_netdev(sizeof(*xi), name, NET_NAME_UNKNOWN, xfrmi_dev_setup); dev = alloc_netdev(sizeof(*xi), name, NET_NAME_UNKNOWN, xfrmi_dev_setup);
if (!dev) if (!dev) {
err = -EAGAIN;
goto failed; goto failed;
}
dev_net_set(dev, net); dev_net_set(dev, net);
...@@ -165,8 +169,10 @@ static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p) ...@@ -165,8 +169,10 @@ static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p)
xi->net = net; xi->net = net;
xi->dev = dev; xi->dev = dev;
xi->phydev = dev_get_by_index(net, p->link); xi->phydev = dev_get_by_index(net, p->link);
if (!xi->phydev) if (!xi->phydev) {
err = -ENODEV;
goto failed_free; goto failed_free;
}
err = xfrmi_create2(dev); err = xfrmi_create2(dev);
if (err < 0) if (err < 0)
...@@ -179,7 +185,7 @@ static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p) ...@@ -179,7 +185,7 @@ static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p)
failed_free: failed_free:
free_netdev(dev); free_netdev(dev);
failed: failed:
return NULL; return ERR_PTR(err);
} }
static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p, static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p,
...@@ -194,13 +200,13 @@ static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p, ...@@ -194,13 +200,13 @@ static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p,
xip = &xi->next) { xip = &xi->next) {
if (xi->p.if_id == p->if_id) { if (xi->p.if_id == p->if_id) {
if (create) if (create)
return NULL; return ERR_PTR(-EEXIST);
return xi; return xi;
} }
} }
if (!create) if (!create)
return NULL; return ERR_PTR(-ENODEV);
return xfrmi_create(net, p); return xfrmi_create(net, p);
} }
...@@ -682,8 +688,9 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev, ...@@ -682,8 +688,9 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
nla_strlcpy(p->name, tb[IFLA_IFNAME], IFNAMSIZ); nla_strlcpy(p->name, tb[IFLA_IFNAME], IFNAMSIZ);
if (!xfrmi_locate(net, p, 1)) xi = xfrmi_locate(net, p, 1);
return -EEXIST; if (IS_ERR(xi))
return PTR_ERR(xi);
return 0; return 0;
} }
...@@ -704,11 +711,12 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -704,11 +711,12 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],
xi = xfrmi_locate(net, &xi->p, 0); xi = xfrmi_locate(net, &xi->p, 0);
if (xi) { if (IS_ERR_OR_NULL(xi)) {
xi = netdev_priv(dev);
} else {
if (xi->dev != dev) if (xi->dev != dev)
return -EEXIST; return -EEXIST;
} else }
xi = netdev_priv(dev);
return xfrmi_update(xi, &xi->p); return xfrmi_update(xi, &xi->p);
} }
......
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