Commit 08724ef6 authored by Florian Westphal's avatar Florian Westphal Committed by David S. Miller

netlink: introduce NLA_POLICY_MAX_BE

netlink allows to specify allowed ranges for integer types.
Unfortunately, nfnetlink passes integers in big endian, so the existing
NLA_POLICY_MAX() cannot be used.

At the moment, nfnetlink users, such as nf_tables, need to resort to
programmatic checking via helpers such as nft_parse_u32_check().

This is both cumbersome and error prone.  This adds NLA_POLICY_MAX_BE
which adds range check support for BE16, BE32 and BE64 integers.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 98ba8108
...@@ -325,6 +325,7 @@ struct nla_policy { ...@@ -325,6 +325,7 @@ struct nla_policy {
struct netlink_range_validation_signed *range_signed; struct netlink_range_validation_signed *range_signed;
struct { struct {
s16 min, max; s16 min, max;
u8 network_byte_order:1;
}; };
int (*validate)(const struct nlattr *attr, int (*validate)(const struct nlattr *attr,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
...@@ -418,6 +419,14 @@ struct nla_policy { ...@@ -418,6 +419,14 @@ struct nla_policy {
.type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \ .type = NLA_ENSURE_INT_OR_BINARY_TYPE(tp), \
.validation_type = NLA_VALIDATE_MAX, \ .validation_type = NLA_VALIDATE_MAX, \
.max = _max, \ .max = _max, \
.network_byte_order = 0, \
}
#define NLA_POLICY_MAX_BE(tp, _max) { \
.type = NLA_ENSURE_UINT_TYPE(tp), \
.validation_type = NLA_VALIDATE_MAX, \
.max = _max, \
.network_byte_order = 1, \
} }
#define NLA_POLICY_MASK(tp, _mask) { \ #define NLA_POLICY_MASK(tp, _mask) { \
......
...@@ -159,6 +159,31 @@ void nla_get_range_unsigned(const struct nla_policy *pt, ...@@ -159,6 +159,31 @@ void nla_get_range_unsigned(const struct nla_policy *pt,
} }
} }
static u64 nla_get_attr_bo(const struct nla_policy *pt,
const struct nlattr *nla)
{
switch (pt->type) {
case NLA_U16:
if (pt->network_byte_order)
return ntohs(nla_get_be16(nla));
return nla_get_u16(nla);
case NLA_U32:
if (pt->network_byte_order)
return ntohl(nla_get_be32(nla));
return nla_get_u32(nla);
case NLA_U64:
if (pt->network_byte_order)
return be64_to_cpu(nla_get_be64(nla));
return nla_get_u64(nla);
}
WARN_ON_ONCE(1);
return 0;
}
static int nla_validate_range_unsigned(const struct nla_policy *pt, static int nla_validate_range_unsigned(const struct nla_policy *pt,
const struct nlattr *nla, const struct nlattr *nla,
struct netlink_ext_ack *extack, struct netlink_ext_ack *extack,
...@@ -172,12 +197,10 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt, ...@@ -172,12 +197,10 @@ static int nla_validate_range_unsigned(const struct nla_policy *pt,
value = nla_get_u8(nla); value = nla_get_u8(nla);
break; break;
case NLA_U16: case NLA_U16:
value = nla_get_u16(nla);
break;
case NLA_U32: case NLA_U32:
value = nla_get_u32(nla);
break;
case NLA_U64: case NLA_U64:
value = nla_get_attr_bo(pt, nla);
break;
case NLA_MSECS: case NLA_MSECS:
value = nla_get_u64(nla); value = nla_get_u64(nla);
break; break;
......
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