Commit 768075eb authored by Johannes Berg's avatar Johannes Berg

nl80211: add a few extended error strings to key parsing

This mostly serves as an example for how to add error strings
and erroneous attribute pointers.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 6c2fb1e6
...@@ -734,11 +734,12 @@ struct key_parse { ...@@ -734,11 +734,12 @@ struct key_parse {
bool def_uni, def_multi; bool def_uni, def_multi;
}; };
static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
struct key_parse *k)
{ {
struct nlattr *tb[NL80211_KEY_MAX + 1]; struct nlattr *tb[NL80211_KEY_MAX + 1];
int err = nla_parse_nested(tb, NL80211_KEY_MAX, key, int err = nla_parse_nested(tb, NL80211_KEY_MAX, key,
nl80211_key_policy, NULL); nl80211_key_policy, info->extack);
if (err) if (err)
return err; return err;
...@@ -771,7 +772,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) ...@@ -771,7 +772,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
if (tb[NL80211_KEY_TYPE]) { if (tb[NL80211_KEY_TYPE]) {
k->type = nla_get_u32(tb[NL80211_KEY_TYPE]); k->type = nla_get_u32(tb[NL80211_KEY_TYPE]);
if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
return -EINVAL; return genl_err_attr(info, -EINVAL,
tb[NL80211_KEY_TYPE]);
} }
if (tb[NL80211_KEY_DEFAULT_TYPES]) { if (tb[NL80211_KEY_DEFAULT_TYPES]) {
...@@ -779,7 +781,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) ...@@ -779,7 +781,8 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1, err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
tb[NL80211_KEY_DEFAULT_TYPES], tb[NL80211_KEY_DEFAULT_TYPES],
nl80211_key_default_policy, NULL); nl80211_key_default_policy,
info->extack);
if (err) if (err)
return err; return err;
...@@ -820,9 +823,11 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) ...@@ -820,9 +823,11 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
if (info->attrs[NL80211_ATTR_KEY_TYPE]) { if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]); k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES) {
GENL_SET_ERR_MSG(info, "key type out of range");
return -EINVAL; return -EINVAL;
} }
}
if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) { if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES]; struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
...@@ -850,41 +855,53 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) ...@@ -850,41 +855,53 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
k->type = -1; k->type = -1;
if (info->attrs[NL80211_ATTR_KEY]) if (info->attrs[NL80211_ATTR_KEY])
err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); err = nl80211_parse_key_new(info, info->attrs[NL80211_ATTR_KEY], k);
else else
err = nl80211_parse_key_old(info, k); err = nl80211_parse_key_old(info, k);
if (err) if (err)
return err; return err;
if (k->def && k->defmgmt) if (k->def && k->defmgmt) {
GENL_SET_ERR_MSG(info, "key with def && defmgmt is invalid");
return -EINVAL; return -EINVAL;
}
if (k->defmgmt) { if (k->defmgmt) {
if (k->def_uni || !k->def_multi) if (k->def_uni || !k->def_multi) {
GENL_SET_ERR_MSG(info, "defmgmt key must be mcast");
return -EINVAL; return -EINVAL;
} }
}
if (k->idx != -1) { if (k->idx != -1) {
if (k->defmgmt) { if (k->defmgmt) {
if (k->idx < 4 || k->idx > 5) if (k->idx < 4 || k->idx > 5) {
GENL_SET_ERR_MSG(info,
"defmgmt key idx not 4 or 5");
return -EINVAL; return -EINVAL;
}
} else if (k->def) { } else if (k->def) {
if (k->idx < 0 || k->idx > 3) if (k->idx < 0 || k->idx > 3) {
GENL_SET_ERR_MSG(info, "def key idx not 0-3");
return -EINVAL; return -EINVAL;
}
} else { } else {
if (k->idx < 0 || k->idx > 5) if (k->idx < 0 || k->idx > 5) {
GENL_SET_ERR_MSG(info, "key idx not 0-5");
return -EINVAL; return -EINVAL;
} }
} }
}
return 0; return 0;
} }
static struct cfg80211_cached_keys * static struct cfg80211_cached_keys *
nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
struct nlattr *keys, bool *no_ht) struct genl_info *info, bool *no_ht)
{ {
struct nlattr *keys = info->attrs[NL80211_ATTR_KEYS];
struct key_parse parse; struct key_parse parse;
struct nlattr *key; struct nlattr *key;
struct cfg80211_cached_keys *result; struct cfg80211_cached_keys *result;
...@@ -909,17 +926,22 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, ...@@ -909,17 +926,22 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
memset(&parse, 0, sizeof(parse)); memset(&parse, 0, sizeof(parse));
parse.idx = -1; parse.idx = -1;
err = nl80211_parse_key_new(key, &parse); err = nl80211_parse_key_new(info, key, &parse);
if (err) if (err)
goto error; goto error;
err = -EINVAL; err = -EINVAL;
if (!parse.p.key) if (!parse.p.key)
goto error; goto error;
if (parse.idx < 0 || parse.idx > 3) if (parse.idx < 0 || parse.idx > 3) {
GENL_SET_ERR_MSG(info, "key index out of range [0-3]");
goto error; goto error;
}
if (parse.def) { if (parse.def) {
if (def) if (def) {
GENL_SET_ERR_MSG(info,
"only one key can be default");
goto error; goto error;
}
def = 1; def = 1;
result->def = parse.idx; result->def = parse.idx;
if (!parse.def_uni || !parse.def_multi) if (!parse.def_uni || !parse.def_multi)
...@@ -932,6 +954,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, ...@@ -932,6 +954,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
goto error; goto error;
if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 && if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) { parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
GENL_SET_ERR_MSG(info, "connect key must be WEP");
err = -EINVAL; err = -EINVAL;
goto error; goto error;
} }
...@@ -947,6 +970,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, ...@@ -947,6 +970,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
if (result->def < 0) { if (result->def < 0) {
err = -EINVAL; err = -EINVAL;
GENL_SET_ERR_MSG(info, "need a default/TX key");
goto error; goto error;
} }
...@@ -8611,9 +8635,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) ...@@ -8611,9 +8635,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
bool no_ht = false; bool no_ht = false;
connkeys = nl80211_parse_connkeys(rdev, connkeys = nl80211_parse_connkeys(rdev, info, &no_ht);
info->attrs[NL80211_ATTR_KEYS],
&no_ht);
if (IS_ERR(connkeys)) if (IS_ERR(connkeys))
return PTR_ERR(connkeys); return PTR_ERR(connkeys);
...@@ -9017,8 +9039,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) ...@@ -9017,8 +9039,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
} }
if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
connkeys = nl80211_parse_connkeys(rdev, connkeys = nl80211_parse_connkeys(rdev, info, NULL);
info->attrs[NL80211_ATTR_KEYS], NULL);
if (IS_ERR(connkeys)) if (IS_ERR(connkeys))
return PTR_ERR(connkeys); return PTR_ERR(connkeys);
} }
......
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