Commit b11dabfd authored by David S. Miller's avatar David S. Miller

Merge branch 'net-more-extack'

David Ahern says:

====================
net: another round of extack handling for routing

This set focuses on passing extack through lwtunnel and MPLS with
additional catches for IPv4 route add and minor cleanups in MPLS
encountered passing the extack arg around.

v2
- mindful of bloat adding duplicate messages
  + refactored prefix and prefix length checks in ipv4's fib_table_insert
    and fib_table_del
  + refactored label check in mpls

- split mpls cleanups into 2 patches
  + move nla_get_via up in af_mpls to avoid forward declaration
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f1bd4dae e1af005b
...@@ -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);
......
...@@ -266,7 +266,8 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, ...@@ -266,7 +266,8 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
struct fib_result *res, int fib_flags); struct fib_result *res, int fib_flags);
int fib_table_insert(struct net *, struct fib_table *, struct fib_config *, int fib_table_insert(struct net *, struct fib_table *, struct fib_config *,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int fib_table_delete(struct net *, struct fib_table *, struct fib_config *); int fib_table_delete(struct net *, struct fib_table *, struct fib_config *,
struct netlink_ext_ack *extack);
int fib_table_dump(struct fib_table *table, struct sk_buff *skb, int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
struct netlink_callback *cb); struct netlink_callback *cb);
int fib_table_flush(struct net *net, struct fib_table *table); int fib_table_flush(struct net *net, struct fib_table *table);
......
...@@ -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);
...@@ -107,12 +108,15 @@ int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op, ...@@ -107,12 +108,15 @@ int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op,
unsigned int num); unsigned int num);
int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op, int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
unsigned int num); unsigned int num);
int lwtunnel_valid_encap_type(u16 encap_type); int lwtunnel_valid_encap_type(u16 encap_type,
int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len); struct netlink_ext_ack *extack);
int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
struct netlink_ext_ack *extack);
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);
...@@ -172,11 +176,14 @@ static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op, ...@@ -172,11 +176,14 @@ static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int lwtunnel_valid_encap_type(u16 encap_type) static inline int lwtunnel_valid_encap_type(u16 encap_type,
struct netlink_ext_ack *extack)
{ {
NL_SET_ERR_MSG(extack, "CONFIG_LWTUNNEL is not enabled in this kernel");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len) static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
struct netlink_ext_ack *extack)
{ {
/* return 0 since we are not walking attr looking for /* return 0 since we are not walking attr looking for
* RTA_ENCAP_TYPE attribute on nexthops. * RTA_ENCAP_TYPE attribute on nexthops.
...@@ -187,7 +194,8 @@ static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len) ...@@ -187,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,37 +103,53 @@ EXPORT_SYMBOL(lwtunnel_encap_del_ops); ...@@ -103,37 +103,53 @@ 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);
int lwtunnel_valid_encap_type(u16 encap_type) int lwtunnel_valid_encap_type(u16 encap_type, struct netlink_ext_ack *extack)
{ {
const struct lwtunnel_encap_ops *ops; const struct lwtunnel_encap_ops *ops;
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(extack, "Unknown lwt encapsulation type");
return ret; return ret;
}
rcu_read_lock(); rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[encap_type]); ops = rcu_dereference(lwtun_encaps[encap_type]);
...@@ -153,11 +169,16 @@ int lwtunnel_valid_encap_type(u16 encap_type) ...@@ -153,11 +169,16 @@ int lwtunnel_valid_encap_type(u16 encap_type)
} }
} }
#endif #endif
return ops ? 0 : -EOPNOTSUPP; ret = ops ? 0 : -EOPNOTSUPP;
if (ret < 0)
NL_SET_ERR_MSG(extack, "lwt encapsulation type not supported");
return ret;
} }
EXPORT_SYMBOL(lwtunnel_valid_encap_type); EXPORT_SYMBOL(lwtunnel_valid_encap_type);
int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining) int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining,
struct netlink_ext_ack *extack)
{ {
struct rtnexthop *rtnh = (struct rtnexthop *)attr; struct rtnexthop *rtnh = (struct rtnexthop *)attr;
struct nlattr *nla_entype; struct nlattr *nla_entype;
...@@ -174,7 +195,8 @@ int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining) ...@@ -174,7 +195,8 @@ int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining)
if (nla_entype) { if (nla_entype) {
encap_type = nla_get_u16(nla_entype); encap_type = nla_get_u16(nla_entype);
if (lwtunnel_valid_encap_type(encap_type) != 0) if (lwtunnel_valid_encap_type(encap_type,
extack) != 0)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }
......
...@@ -588,7 +588,8 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -588,7 +588,8 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
if (cmd == SIOCDELRT) { if (cmd == SIOCDELRT) {
tb = fib_get_table(net, cfg.fc_table); tb = fib_get_table(net, cfg.fc_table);
if (tb) if (tb)
err = fib_table_delete(net, tb, &cfg); err = fib_table_delete(net, tb, &cfg,
NULL);
else else
err = -ESRCH; err = -ESRCH;
} else { } else {
...@@ -684,7 +685,8 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, ...@@ -684,7 +685,8 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
break; break;
case RTA_MULTIPATH: case RTA_MULTIPATH:
err = lwtunnel_valid_encap_type_attr(nla_data(attr), err = lwtunnel_valid_encap_type_attr(nla_data(attr),
nla_len(attr)); nla_len(attr),
extack);
if (err < 0) if (err < 0)
goto errout; goto errout;
cfg->fc_mp = nla_data(attr); cfg->fc_mp = nla_data(attr);
...@@ -701,7 +703,8 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, ...@@ -701,7 +703,8 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
break; break;
case RTA_ENCAP_TYPE: case RTA_ENCAP_TYPE:
cfg->fc_encap_type = nla_get_u16(attr); cfg->fc_encap_type = nla_get_u16(attr);
err = lwtunnel_valid_encap_type(cfg->fc_encap_type); err = lwtunnel_valid_encap_type(cfg->fc_encap_type,
extack);
if (err < 0) if (err < 0)
goto errout; goto errout;
break; break;
...@@ -732,7 +735,7 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -732,7 +735,7 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh,
goto errout; goto errout;
} }
err = fib_table_delete(net, tb, &cfg); err = fib_table_delete(net, tb, &cfg, extack);
errout: errout:
return err; return err;
} }
...@@ -851,7 +854,7 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad ...@@ -851,7 +854,7 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad
if (cmd == RTM_NEWROUTE) if (cmd == RTM_NEWROUTE)
fib_table_insert(net, tb, &cfg, NULL); fib_table_insert(net, tb, &cfg, NULL);
else else
fib_table_delete(net, tb, &cfg); fib_table_delete(net, tb, &cfg, NULL);
} }
void fib_add_ifaddr(struct in_ifaddr *ifa) void fib_add_ifaddr(struct in_ifaddr *ifa)
......
...@@ -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,8 +646,8 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) ...@@ -644,8 +646,8 @@ 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) &&
...@@ -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;
......
...@@ -1099,6 +1099,22 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp, ...@@ -1099,6 +1099,22 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp,
return 0; return 0;
} }
static bool fib_valid_key_len(u32 key, u8 plen, struct netlink_ext_ack *extack)
{
if (plen > KEYLENGTH) {
NL_SET_ERR_MSG(extack, "Invalid prefix length");
return false;
}
if ((plen < KEYLENGTH) && (key << plen)) {
NL_SET_ERR_MSG(extack,
"Invalid prefix for given prefix length");
return false;
}
return true;
}
/* Caller must hold RTNL. */ /* Caller must hold RTNL. */
int fib_table_insert(struct net *net, struct fib_table *tb, int fib_table_insert(struct net *net, struct fib_table *tb,
struct fib_config *cfg, struct netlink_ext_ack *extack) struct fib_config *cfg, struct netlink_ext_ack *extack)
...@@ -1115,16 +1131,13 @@ int fib_table_insert(struct net *net, struct fib_table *tb, ...@@ -1115,16 +1131,13 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
u32 key; u32 key;
int err; int err;
if (plen > KEYLENGTH)
return -EINVAL;
key = ntohl(cfg->fc_dst); key = ntohl(cfg->fc_dst);
pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen); if (!fib_valid_key_len(key, plen, extack))
if ((plen < KEYLENGTH) && (key << plen))
return -EINVAL; return -EINVAL;
pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
fi = fib_create_info(cfg, extack); fi = fib_create_info(cfg, extack);
if (IS_ERR(fi)) { if (IS_ERR(fi)) {
err = PTR_ERR(fi); err = PTR_ERR(fi);
...@@ -1508,7 +1521,7 @@ static void fib_remove_alias(struct trie *t, struct key_vector *tp, ...@@ -1508,7 +1521,7 @@ static void fib_remove_alias(struct trie *t, struct key_vector *tp,
/* Caller must hold RTNL. */ /* Caller must hold RTNL. */
int fib_table_delete(struct net *net, struct fib_table *tb, int fib_table_delete(struct net *net, struct fib_table *tb,
struct fib_config *cfg) struct fib_config *cfg, struct netlink_ext_ack *extack)
{ {
struct trie *t = (struct trie *) tb->tb_data; struct trie *t = (struct trie *) tb->tb_data;
struct fib_alias *fa, *fa_to_delete; struct fib_alias *fa, *fa_to_delete;
...@@ -1518,12 +1531,9 @@ int fib_table_delete(struct net *net, struct fib_table *tb, ...@@ -1518,12 +1531,9 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
u8 tos = cfg->fc_tos; u8 tos = cfg->fc_tos;
u32 key; u32 key;
if (plen > KEYLENGTH)
return -EINVAL;
key = ntohl(cfg->fc_dst); key = ntohl(cfg->fc_dst);
if ((plen < KEYLENGTH) && (key << plen)) if (!fib_valid_key_len(key, plen, extack))
return -EINVAL; return -EINVAL;
l = fib_find_node(t, &tp, key); l = fib_find_node(t, &tp, key);
...@@ -1552,7 +1562,7 @@ int fib_table_delete(struct net *net, struct fib_table *tb, ...@@ -1552,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);
...@@ -3016,7 +3016,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -3016,7 +3016,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]); cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
err = lwtunnel_valid_encap_type_attr(cfg->fc_mp, err = lwtunnel_valid_encap_type_attr(cfg->fc_mp,
cfg->fc_mp_len); cfg->fc_mp_len, extack);
if (err < 0) if (err < 0)
goto errout; goto errout;
} }
...@@ -3035,7 +3035,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -3035,7 +3035,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
if (tb[RTA_ENCAP_TYPE]) { if (tb[RTA_ENCAP_TYPE]) {
cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]); cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]);
err = lwtunnel_valid_encap_type(cfg->fc_encap_type); err = lwtunnel_valid_encap_type(cfg->fc_encap_type, extack);
if (err < 0) if (err < 0)
goto errout; goto errout;
} }
......
...@@ -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;
......
This diff is collapsed.
...@@ -203,9 +203,7 @@ static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev) ...@@ -203,9 +203,7 @@ static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
int nla_put_labels(struct sk_buff *skb, int attrtype, u8 labels, int nla_put_labels(struct sk_buff *skb, int attrtype, u8 labels,
const u32 label[]); const u32 label[]);
int nla_get_labels(const struct nlattr *nla, u8 max_labels, u8 *labels, int nla_get_labels(const struct nlattr *nla, u8 max_labels, u8 *labels,
u32 label[]); u32 label[], struct netlink_ext_ack *extack);
int nla_get_via(const struct nlattr *nla, u8 *via_alen, u8 *via_table,
u8 via[]);
bool mpls_output_possible(const struct net_device *dev); bool mpls_output_possible(const struct net_device *dev);
unsigned int mpls_dev_mtu(const struct net_device *dev); unsigned int mpls_dev_mtu(const struct net_device *dev);
bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu); bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu);
......
...@@ -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,17 +169,18 @@ static int mpls_build_state(struct nlattr *nla, ...@@ -168,17 +169,18 @@ 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;
if (!tb[MPLS_IPTUNNEL_DST]) if (!tb[MPLS_IPTUNNEL_DST]) {
NL_SET_ERR_MSG(extack, "MPLS_IPTUNNEL_DST attribute is missing");
return -EINVAL; return -EINVAL;
}
/* determine number of labels */ /* determine number of labels */
if (nla_get_labels(tb[MPLS_IPTUNNEL_DST], if (nla_get_labels(tb[MPLS_IPTUNNEL_DST], MAX_NEW_LABELS,
MAX_NEW_LABELS, &n_labels, NULL)) &n_labels, NULL, extack))
return -EINVAL; return -EINVAL;
newts = lwtunnel_state_alloc(sizeof(*tun_encap_info) + newts = lwtunnel_state_alloc(sizeof(*tun_encap_info) +
...@@ -188,7 +190,8 @@ static int mpls_build_state(struct nlattr *nla, ...@@ -188,7 +190,8 @@ static int mpls_build_state(struct nlattr *nla,
tun_encap_info = mpls_lwtunnel_encap(newts); tun_encap_info = mpls_lwtunnel_encap(newts);
ret = nla_get_labels(tb[MPLS_IPTUNNEL_DST], n_labels, ret = nla_get_labels(tb[MPLS_IPTUNNEL_DST], n_labels,
&tun_encap_info->labels, tun_encap_info->label); &tun_encap_info->labels, tun_encap_info->label,
extack);
if (ret) if (ret)
goto errout; goto errout;
......
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