Skip to content

Commit

Permalink
Merge branch 'netlink_ext_ACK'
Browse files Browse the repository at this point in the history
Johannes Berg says:

====================
netlink extended ACK reporting

Changes since v4:
 * use __NLMSGERR_ATTR_MAX instead of NUM_NLMSGERR_ATTRS

Changes since v3:
 * Add NLM_F_CAPPED and NLM_F_ACK_TLVS flags, to allow entirely
   stateless parsing of the ACK messages by looking at the new
   flags. Need to check NLM_F_ACK_TLVS first, since capping can
   be done in kernels before this patchset without setting the
   flag.
 * Remove "missing_attr" functionality - this can obviously be
   added back rather easily, but I'd rather have more discussion
   about the nesting problem there.
 * Improve documentation of NLMSGERR_ATTR_OFFS
 * Improve message structure documentation, documenting that the
   request message is always capped for success cases
 * fix nlmsg_len of the outer message by calling nlmsg_end()
 * fix memcpy() of the request in success cases, going back to
   the original code that I'd changed before due to the payload
   adjustments that I reverted when introducing tlvlen

Changes since v2:
 * add NUM_NLMSGERR_ATTRS, NLMSGERR_ATTR_MAX
 * fix cookie length to 20 (sha-1 length)
 * move struct members for cookie to patch 3 where they should be
 * another cleanup suggested by David Ahern

Changes since v1:
 * credit Pablo and Jamal
 * incorporate suggestion from David Ahern
 * fix compilation in decnet
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 13, 2017
2 parents fb9eb89 + fe52145 commit ce07183
Show file tree
Hide file tree
Showing 139 changed files with 672 additions and 427 deletions.
5 changes: 3 additions & 2 deletions crypto/crypto_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,8 @@ static const struct crypto_link {
[CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
};

static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{
struct nlattr *attrs[CRYPTOCFGA_MAX+1];
const struct crypto_link *link;
Expand Down Expand Up @@ -522,7 +523,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}

err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
crypto_policy);
crypto_policy, extack);
if (err < 0)
return err;

Expand Down
2 changes: 1 addition & 1 deletion drivers/block/drbd/drbd_nla.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla,

err = drbd_nla_check_mandatory(maxtype, nla);
if (!err)
err = nla_parse_nested(tb, maxtype, nla, policy);
err = nla_parse_nested(tb, maxtype, nla, policy, NULL);

return err;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/core/addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
return false;

ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_addr_policy);
nlmsg_len(nlh), ib_nl_addr_policy, NULL);
if (ret)
return false;

Expand Down
6 changes: 4 additions & 2 deletions drivers/infiniband/core/iwpm_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,12 +472,14 @@ int iwpm_parse_nlmsg(struct netlink_callback *cb, int policy_max,
int ret;
const char *err_str = "";

ret = nlmsg_validate(cb->nlh, nlh_len, policy_max-1, nlmsg_policy);
ret = nlmsg_validate(cb->nlh, nlh_len, policy_max - 1, nlmsg_policy,
NULL);
if (ret) {
err_str = "Invalid attribute";
goto parse_nlmsg_error;
}
ret = nlmsg_parse(cb->nlh, nlh_len, nltb, policy_max-1, nlmsg_policy);
ret = nlmsg_parse(cb->nlh, nlh_len, nltb, policy_max - 1,
nlmsg_policy, NULL);
if (ret) {
err_str = "Unable to parse the nlmsg";
goto parse_nlmsg_error;
Expand Down
5 changes: 3 additions & 2 deletions drivers/infiniband/core/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
}
EXPORT_SYMBOL(ibnl_put_attr);

static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{
struct ibnl_client *client;
int type = nlh->nlmsg_type;
Expand Down Expand Up @@ -209,7 +210,7 @@ static void ibnl_rcv_reply_skb(struct sk_buff *skb)
if (nlh->nlmsg_flags & NLM_F_REQUEST)
return;

ibnl_rcv_msg(skb, nlh);
ibnl_rcv_msg(skb, nlh, NULL);

msglen = NLMSG_ALIGN(nlh->nlmsg_len);
if (msglen > skb->len)
Expand Down
4 changes: 2 additions & 2 deletions drivers/infiniband/core/sa_query.c
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ int ib_nl_handle_set_timeout(struct sk_buff *skb,
return -EPERM;

ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_policy);
nlmsg_len(nlh), ib_nl_policy, NULL);
attr = (const struct nlattr *)tb[LS_NLA_TYPE_TIMEOUT];
if (ret || !attr)
goto settimeout_out;
Expand Down Expand Up @@ -860,7 +860,7 @@ static inline int ib_nl_is_good_resolve_resp(const struct nlmsghdr *nlh)
return 0;

ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_policy);
nlmsg_len(nlh), ib_nl_policy, NULL);
if (ret)
return 0;

Expand Down
10 changes: 6 additions & 4 deletions drivers/net/macsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1590,8 +1590,9 @@ static int parse_sa_config(struct nlattr **attrs, struct nlattr **tb_sa)
if (!attrs[MACSEC_ATTR_SA_CONFIG])
return -EINVAL;

if (nla_parse_nested(tb_sa, MACSEC_SA_ATTR_MAX, attrs[MACSEC_ATTR_SA_CONFIG],
macsec_genl_sa_policy))
if (nla_parse_nested(tb_sa, MACSEC_SA_ATTR_MAX,
attrs[MACSEC_ATTR_SA_CONFIG],
macsec_genl_sa_policy, NULL))
return -EINVAL;

return 0;
Expand All @@ -1602,8 +1603,9 @@ static int parse_rxsc_config(struct nlattr **attrs, struct nlattr **tb_rxsc)
if (!attrs[MACSEC_ATTR_RXSC_CONFIG])
return -EINVAL;

if (nla_parse_nested(tb_rxsc, MACSEC_RXSC_ATTR_MAX, attrs[MACSEC_ATTR_RXSC_CONFIG],
macsec_genl_rxsc_policy))
if (nla_parse_nested(tb_rxsc, MACSEC_RXSC_ATTR_MAX,
attrs[MACSEC_ATTR_RXSC_CONFIG],
macsec_genl_rxsc_policy, NULL))
return -EINVAL;

return 0;
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/team/team.c
Original file line number Diff line number Diff line change
Expand Up @@ -2471,7 +2471,8 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
goto team_put;
}
err = nla_parse_nested(opt_attrs, TEAM_ATTR_OPTION_MAX,
nl_option, team_nl_option_policy);
nl_option, team_nl_option_policy,
info->extack);
if (err)
goto team_put;
if (!opt_attrs[TEAM_ATTR_OPTION_NAME] ||
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/veth.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,8 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
ifmp = nla_data(nla_peer);
err = rtnl_nla_parse_ifla(peer_tb,
nla_data(nla_peer) + sizeof(struct ifinfomsg),
nla_len(nla_peer) - sizeof(struct ifinfomsg));
nla_len(nla_peer) - sizeof(struct ifinfomsg),
NULL);
if (err < 0)
return err;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath10k/testmode.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,8 @@ int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
int ret;

ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len,
ath10k_tm_policy);
ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len, ath10k_tm_policy,
NULL);
if (ret)
return ret;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath/ath6kl/testmode.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ int ath6kl_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
int err, buf_len;
void *buf;

err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len,
ath6kl_tm_policy);
err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, ath6kl_tm_policy,
NULL);
if (err)
return err;

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -3711,7 +3711,8 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
int err;
u32 noa_duration;

err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy);
err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy,
NULL);
if (err)
return err;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/mac80211_hwsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy,
u32 val;

err = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
hwsim_vendor_test_policy);
hwsim_vendor_test_policy, NULL);
if (err)
return err;
if (!tb[QCA_WLAN_VENDOR_ATTR_TEST])
Expand Down Expand Up @@ -1852,7 +1852,7 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
int err, ps;

err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len,
hwsim_testmode_policy);
hwsim_testmode_policy, NULL);
if (err)
return err;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/marvell/mwifiex/cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -4016,8 +4016,8 @@ static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,
if (!priv)
return -EINVAL;

err = nla_parse(tb, MWIFIEX_TM_ATTR_MAX, data, len,
mwifiex_tm_policy);
err = nla_parse(tb, MWIFIEX_TM_ATTR_MAX, data, len, mwifiex_tm_policy,
NULL);
if (err)
return err;

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/ti/wlcore/testmode.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 nla_cmd;
int err;

err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy);
err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy,
NULL);
if (err)
return err;

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/ti/wlcore/vendor_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
return -EINVAL;

ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
wlcore_vendor_attr_policy);
wlcore_vendor_attr_policy, NULL);
if (ret)
return ret;

Expand Down Expand Up @@ -116,7 +116,7 @@ wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
return -EINVAL;

ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
wlcore_vendor_attr_policy);
wlcore_vendor_attr_policy, NULL);
if (ret)
return ret;

Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/scsi_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)

next_msg:
if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
netlink_ack(skb, nlh, err);
netlink_ack(skb, nlh, err, NULL);

skb_pull(skb, rlen);
}
Expand Down
33 changes: 32 additions & 1 deletion include/linux/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,42 @@ netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
return __netlink_kernel_create(net, unit, THIS_MODULE, cfg);
}

/* this can be increased when necessary - don't expose to userland */
#define NETLINK_MAX_COOKIE_LEN 20

/**
* struct netlink_ext_ack - netlink extended ACK report struct
* @_msg: message string to report - don't access directly, use
* %NL_SET_ERR_MSG
* @bad_attr: attribute with error
* @cookie: cookie data to return to userspace (for success)
* @cookie_len: actual cookie data length
*/
struct netlink_ext_ack {
const char *_msg;
const struct nlattr *bad_attr;
u8 cookie[NETLINK_MAX_COOKIE_LEN];
u8 cookie_len;
};

/* Always use this macro, this allows later putting the
* message into a separate section or such for things
* like translation or listing all possible messages.
* Currently string formatting is not supported (due
* to the lack of an output buffer.)
*/
#define NL_SET_ERR_MSG(extack, msg) do { \
static const char _msg[] = (msg); \
\
(extack)->_msg = _msg; \
} while (0)

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 void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
const struct netlink_ext_ack *extack);
extern int netlink_has_listeners(struct sock *sk, unsigned int group);

extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock);
Expand Down
20 changes: 17 additions & 3 deletions include/net/genetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct nlattr **genl_family_attrbuf(const struct genl_family *family);
* @attrs: netlink attributes
* @_net: network namespace
* @user_ptr: user pointers
* @extack: extended ACK report struct
*/
struct genl_info {
u32 snd_seq;
Expand All @@ -94,6 +95,7 @@ struct genl_info {
struct nlattr ** attrs;
possible_net_t _net;
void * user_ptr[2];
struct netlink_ext_ack *extack;
};

static inline struct net *genl_info_net(struct genl_info *info)
Expand All @@ -106,6 +108,16 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
write_pnet(&info->_net, net);
}

#define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG((info)->extack, msg)

static inline int genl_err_attr(struct genl_info *info, int err,
struct nlattr *attr)
{
info->extack->bad_attr = attr;

return err;
}

/**
* struct genl_ops - generic netlink operations
* @cmd: command identifier
Expand Down Expand Up @@ -162,14 +174,16 @@ genlmsg_nlhdr(void *user_hdr, const struct genl_family *family)
* @tb: destination array with maxtype+1 elements
* @maxtype: maximum attribute type to be expected
* @policy: validation policy
* */
* @extack: extended ACK report struct
*/
static inline int genlmsg_parse(const struct nlmsghdr *nlh,
const struct genl_family *family,
struct nlattr *tb[], int maxtype,
const struct nla_policy *policy)
const struct nla_policy *policy,
struct netlink_ext_ack *extack)
{
return nlmsg_parse(nlh, family->hdrsize + GENL_HDRLEN, tb, maxtype,
policy);
policy, extack);
}

/**
Expand Down
Loading

0 comments on commit ce07183

Please sign in to comment.