Commit 9ae28727 authored by David Ahern's avatar David Ahern Committed by David S. Miller

net: add extack arg to lwtunnel build state

Pass extack arg down to lwtunnel_build_state and the build_state callbacks.
Add messages for failures in lwtunnel_build_state, and add the extarg to
nla_parse where possible in the build_state callbacks.
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c255bd68
...@@ -102,6 +102,16 @@ struct netlink_ext_ack { ...@@ -102,6 +102,16 @@ struct netlink_ext_ack {
(extack)->bad_attr = (attr); \ (extack)->bad_attr = (attr); \
} while (0) } while (0)
#define NL_SET_ERR_MSG_ATTR(extack, attr, msg) do { \
static const char __msg[] = (msg); \
struct netlink_ext_ack *__extack = (extack); \
\
if (__extack) { \
__extack->_msg = __msg; \
__extack->bad_attr = (attr); \
} \
} while (0)
extern void netlink_kernel_release(struct sock *sk); extern void netlink_kernel_release(struct sock *sk);
extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups); extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
extern int netlink_change_ngroups(struct sock *sk, unsigned int groups); extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
......
...@@ -35,7 +35,8 @@ struct lwtunnel_state { ...@@ -35,7 +35,8 @@ struct lwtunnel_state {
struct lwtunnel_encap_ops { struct lwtunnel_encap_ops {
int (*build_state)(struct nlattr *encap, int (*build_state)(struct nlattr *encap,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **ts); struct lwtunnel_state **ts,
struct netlink_ext_ack *extack);
void (*destroy_state)(struct lwtunnel_state *lws); void (*destroy_state)(struct lwtunnel_state *lws);
int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
int (*input)(struct sk_buff *skb); int (*input)(struct sk_buff *skb);
...@@ -114,7 +115,8 @@ int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, ...@@ -114,7 +115,8 @@ int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
int lwtunnel_build_state(u16 encap_type, int lwtunnel_build_state(u16 encap_type,
struct nlattr *encap, struct nlattr *encap,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **lws); struct lwtunnel_state **lws,
struct netlink_ext_ack *extack);
int lwtunnel_fill_encap(struct sk_buff *skb, int lwtunnel_fill_encap(struct sk_buff *skb,
struct lwtunnel_state *lwtstate); struct lwtunnel_state *lwtstate);
int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate); int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);
...@@ -192,7 +194,8 @@ static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, ...@@ -192,7 +194,8 @@ static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
static inline int lwtunnel_build_state(u16 encap_type, static inline int lwtunnel_build_state(u16 encap_type,
struct nlattr *encap, struct nlattr *encap,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **lws) struct lwtunnel_state **lws,
struct netlink_ext_ack *extack)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -240,7 +240,8 @@ static const struct nla_policy bpf_nl_policy[LWT_BPF_MAX + 1] = { ...@@ -240,7 +240,8 @@ static const struct nla_policy bpf_nl_policy[LWT_BPF_MAX + 1] = {
static int bpf_build_state(struct nlattr *nla, static int bpf_build_state(struct nlattr *nla,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{ {
struct nlattr *tb[LWT_BPF_MAX + 1]; struct nlattr *tb[LWT_BPF_MAX + 1];
struct lwtunnel_state *newts; struct lwtunnel_state *newts;
...@@ -250,7 +251,7 @@ static int bpf_build_state(struct nlattr *nla, ...@@ -250,7 +251,7 @@ static int bpf_build_state(struct nlattr *nla,
if (family != AF_INET && family != AF_INET6) if (family != AF_INET && family != AF_INET6)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
ret = nla_parse_nested(tb, LWT_BPF_MAX, nla, bpf_nl_policy, NULL); ret = nla_parse_nested(tb, LWT_BPF_MAX, nla, bpf_nl_policy, extack);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -103,25 +103,39 @@ EXPORT_SYMBOL(lwtunnel_encap_del_ops); ...@@ -103,25 +103,39 @@ EXPORT_SYMBOL(lwtunnel_encap_del_ops);
int lwtunnel_build_state(u16 encap_type, int lwtunnel_build_state(u16 encap_type,
struct nlattr *encap, unsigned int family, struct nlattr *encap, unsigned int family,
const void *cfg, struct lwtunnel_state **lws) const void *cfg, struct lwtunnel_state **lws,
struct netlink_ext_ack *extack)
{ {
const struct lwtunnel_encap_ops *ops; const struct lwtunnel_encap_ops *ops;
bool found = false;
int ret = -EINVAL; int ret = -EINVAL;
if (encap_type == LWTUNNEL_ENCAP_NONE || if (encap_type == LWTUNNEL_ENCAP_NONE ||
encap_type > LWTUNNEL_ENCAP_MAX) encap_type > LWTUNNEL_ENCAP_MAX) {
NL_SET_ERR_MSG_ATTR(extack, encap,
"Unknown LWT encapsulation type");
return ret; return ret;
}
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
rcu_read_lock(); rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[encap_type]); ops = rcu_dereference(lwtun_encaps[encap_type]);
if (likely(ops && ops->build_state && try_module_get(ops->owner))) { if (likely(ops && ops->build_state && try_module_get(ops->owner))) {
ret = ops->build_state(encap, family, cfg, lws); found = true;
ret = ops->build_state(encap, family, cfg, lws, extack);
if (ret) if (ret)
module_put(ops->owner); module_put(ops->owner);
} }
rcu_read_unlock(); rcu_read_unlock();
/* don't rely on -EOPNOTSUPP to detect match as build_state
* handlers could return it
*/
if (!found) {
NL_SET_ERR_MSG_ATTR(extack, encap,
"LWT encapsulation type not supported");
}
return ret; return ret;
} }
EXPORT_SYMBOL(lwtunnel_build_state); EXPORT_SYMBOL(lwtunnel_build_state);
......
...@@ -30,7 +30,8 @@ static inline void fib_alias_accessed(struct fib_alias *fa) ...@@ -30,7 +30,8 @@ static inline void fib_alias_accessed(struct fib_alias *fa)
void fib_release_info(struct fib_info *); void fib_release_info(struct fib_info *);
struct fib_info *fib_create_info(struct fib_config *cfg, struct fib_info *fib_create_info(struct fib_config *cfg,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
struct netlink_ext_ack *extack);
int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, u32 tb_id, int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, u32 tb_id,
u8 type, __be32 dst, int dst_len, u8 tos, struct fib_info *fi, u8 type, __be32 dst, int dst_len, u8 tos, struct fib_info *fi,
unsigned int); unsigned int);
......
...@@ -532,7 +532,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, ...@@ -532,7 +532,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
ret = lwtunnel_build_state(nla_get_u16( ret = lwtunnel_build_state(nla_get_u16(
nla_entype), nla_entype),
nla, AF_INET, cfg, nla, AF_INET, cfg,
&lwtstate); &lwtstate, extack);
if (ret) if (ret)
goto errout; goto errout;
nexthop_nh->nh_lwtstate = nexthop_nh->nh_lwtstate =
...@@ -614,7 +614,8 @@ static inline void fib_add_weight(struct fib_info *fi, ...@@ -614,7 +614,8 @@ static inline void fib_add_weight(struct fib_info *fi,
static int fib_encap_match(u16 encap_type, static int fib_encap_match(u16 encap_type,
struct nlattr *encap, struct nlattr *encap,
const struct fib_nh *nh, const struct fib_nh *nh,
const struct fib_config *cfg) const struct fib_config *cfg,
struct netlink_ext_ack *extack)
{ {
struct lwtunnel_state *lwtstate; struct lwtunnel_state *lwtstate;
int ret, result = 0; int ret, result = 0;
...@@ -622,8 +623,8 @@ static int fib_encap_match(u16 encap_type, ...@@ -622,8 +623,8 @@ static int fib_encap_match(u16 encap_type,
if (encap_type == LWTUNNEL_ENCAP_NONE) if (encap_type == LWTUNNEL_ENCAP_NONE)
return 0; return 0;
ret = lwtunnel_build_state(encap_type, encap, ret = lwtunnel_build_state(encap_type, encap, AF_INET,
AF_INET, cfg, &lwtstate); cfg, &lwtstate, extack);
if (!ret) { if (!ret) {
result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate); result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate);
lwtstate_free(lwtstate); lwtstate_free(lwtstate);
...@@ -632,7 +633,8 @@ static int fib_encap_match(u16 encap_type, ...@@ -632,7 +633,8 @@ static int fib_encap_match(u16 encap_type,
return result; return result;
} }
int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
struct netlink_ext_ack *extack)
{ {
#ifdef CONFIG_IP_ROUTE_MULTIPATH #ifdef CONFIG_IP_ROUTE_MULTIPATH
struct rtnexthop *rtnh; struct rtnexthop *rtnh;
...@@ -644,9 +646,9 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) ...@@ -644,9 +646,9 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
if (cfg->fc_oif || cfg->fc_gw) { if (cfg->fc_oif || cfg->fc_gw) {
if (cfg->fc_encap) { if (cfg->fc_encap) {
if (fib_encap_match(cfg->fc_encap_type, if (fib_encap_match(cfg->fc_encap_type, cfg->fc_encap,
cfg->fc_encap, fi->fib_nh, cfg)) fi->fib_nh, cfg, extack))
return 1; return 1;
} }
if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) && if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) &&
(!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw)) (!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw))
...@@ -1148,7 +1150,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg, ...@@ -1148,7 +1150,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
} }
err = lwtunnel_build_state(cfg->fc_encap_type, err = lwtunnel_build_state(cfg->fc_encap_type,
cfg->fc_encap, AF_INET, cfg, cfg->fc_encap, AF_INET, cfg,
&lwtstate); &lwtstate, extack);
if (err) if (err)
goto failure; goto failure;
......
...@@ -1562,7 +1562,7 @@ int fib_table_delete(struct net *net, struct fib_table *tb, ...@@ -1562,7 +1562,7 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
fi->fib_prefsrc == cfg->fc_prefsrc) && fi->fib_prefsrc == cfg->fc_prefsrc) &&
(!cfg->fc_protocol || (!cfg->fc_protocol ||
fi->fib_protocol == cfg->fc_protocol) && fi->fib_protocol == cfg->fc_protocol) &&
fib_nh_match(cfg, fi) == 0) { fib_nh_match(cfg, fi, extack) == 0) {
fa_to_delete = fa; fa_to_delete = fa;
break; break;
} }
......
...@@ -228,14 +228,16 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = { ...@@ -228,14 +228,16 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = {
static int ip_tun_build_state(struct nlattr *attr, static int ip_tun_build_state(struct nlattr *attr,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{ {
struct ip_tunnel_info *tun_info; struct ip_tunnel_info *tun_info;
struct lwtunnel_state *new_state; struct lwtunnel_state *new_state;
struct nlattr *tb[LWTUNNEL_IP_MAX + 1]; struct nlattr *tb[LWTUNNEL_IP_MAX + 1];
int err; int err;
err = nla_parse_nested(tb, LWTUNNEL_IP_MAX, attr, ip_tun_policy, NULL); err = nla_parse_nested(tb, LWTUNNEL_IP_MAX, attr, ip_tun_policy,
extack);
if (err < 0) if (err < 0)
return err; return err;
...@@ -325,7 +327,8 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = { ...@@ -325,7 +327,8 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
static int ip6_tun_build_state(struct nlattr *attr, static int ip6_tun_build_state(struct nlattr *attr,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{ {
struct ip_tunnel_info *tun_info; struct ip_tunnel_info *tun_info;
struct lwtunnel_state *new_state; struct lwtunnel_state *new_state;
...@@ -333,7 +336,7 @@ static int ip6_tun_build_state(struct nlattr *attr, ...@@ -333,7 +336,7 @@ static int ip6_tun_build_state(struct nlattr *attr,
int err; int err;
err = nla_parse_nested(tb, LWTUNNEL_IP6_MAX, attr, ip6_tun_policy, err = nla_parse_nested(tb, LWTUNNEL_IP6_MAX, attr, ip6_tun_policy,
NULL); extack);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -117,7 +117,8 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { ...@@ -117,7 +117,8 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
static int ila_build_state(struct nlattr *nla, static int ila_build_state(struct nlattr *nla,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{ {
struct ila_lwt *ilwt; struct ila_lwt *ilwt;
struct ila_params *p; struct ila_params *p;
...@@ -146,7 +147,7 @@ static int ila_build_state(struct nlattr *nla, ...@@ -146,7 +147,7 @@ static int ila_build_state(struct nlattr *nla,
return -EINVAL; return -EINVAL;
} }
ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, NULL); ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -1939,7 +1939,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg, ...@@ -1939,7 +1939,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
err = lwtunnel_build_state(cfg->fc_encap_type, err = lwtunnel_build_state(cfg->fc_encap_type,
cfg->fc_encap, AF_INET6, cfg, cfg->fc_encap, AF_INET6, cfg,
&lwtstate); &lwtstate, extack);
if (err) if (err)
goto out; goto out;
rt->dst.lwtstate = lwtstate_get(lwtstate); rt->dst.lwtstate = lwtstate_get(lwtstate);
......
...@@ -326,7 +326,8 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb) ...@@ -326,7 +326,8 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
static int seg6_build_state(struct nlattr *nla, static int seg6_build_state(struct nlattr *nla,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{ {
struct nlattr *tb[SEG6_IPTUNNEL_MAX + 1]; struct nlattr *tb[SEG6_IPTUNNEL_MAX + 1];
struct seg6_iptunnel_encap *tuninfo; struct seg6_iptunnel_encap *tuninfo;
...@@ -336,7 +337,7 @@ static int seg6_build_state(struct nlattr *nla, ...@@ -336,7 +337,7 @@ static int seg6_build_state(struct nlattr *nla,
int err; int err;
err = nla_parse_nested(tb, SEG6_IPTUNNEL_MAX, nla, err = nla_parse_nested(tb, SEG6_IPTUNNEL_MAX, nla,
seg6_iptunnel_policy, NULL); seg6_iptunnel_policy, extack);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -159,7 +159,8 @@ static int mpls_xmit(struct sk_buff *skb) ...@@ -159,7 +159,8 @@ static int mpls_xmit(struct sk_buff *skb)
static int mpls_build_state(struct nlattr *nla, static int mpls_build_state(struct nlattr *nla,
unsigned int family, const void *cfg, unsigned int family, const void *cfg,
struct lwtunnel_state **ts) struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{ {
struct mpls_iptunnel_encap *tun_encap_info; struct mpls_iptunnel_encap *tun_encap_info;
struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1]; struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
...@@ -168,7 +169,7 @@ static int mpls_build_state(struct nlattr *nla, ...@@ -168,7 +169,7 @@ static int mpls_build_state(struct nlattr *nla,
int ret; int ret;
ret = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla, ret = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla,
mpls_iptunnel_policy, NULL); mpls_iptunnel_policy, extack);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
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