[NETFILTER] nfnetlink: use highest bit of nfa_type to indicate nested TLV
As Henrik Nordstrom pointed out, all our efforts with "split endian" (i.e. host byte order tags, net byte order values) are useless, unless a parser can determine whether an attribute is nested or not. This patch steals the highest bit of nfattr.nfa_type to indicate whether the data payload contains a nested nfattr (1) or not (0). This will break userspace compatibility, but luckily no kernel with nfnetlink was released so far. Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f40863cec8
commit
ebe0bbf06c
|
@ -41,11 +41,15 @@ enum nfnetlink_groups {
|
||||||
struct nfattr
|
struct nfattr
|
||||||
{
|
{
|
||||||
u_int16_t nfa_len;
|
u_int16_t nfa_len;
|
||||||
u_int16_t nfa_type;
|
u_int16_t nfa_type; /* we use 15 bits for the type, and the highest
|
||||||
|
* bit to indicate whether the payload is nested */
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* FIXME: Shamelessly copy and pasted from rtnetlink.h, it's time
|
/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from
|
||||||
* to put this in a generic file */
|
* rtnetlink.h, it's time to put this in a generic file */
|
||||||
|
|
||||||
|
#define NFNL_NFA_NEST 0x8000
|
||||||
|
#define NFA_TYPE(attr) ((attr)->nfa_type & 0x7fff)
|
||||||
|
|
||||||
#define NFA_ALIGNTO 4
|
#define NFA_ALIGNTO 4
|
||||||
#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
|
#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
|
||||||
|
@ -59,7 +63,7 @@ struct nfattr
|
||||||
#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
|
#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
|
||||||
#define NFA_NEST(skb, type) \
|
#define NFA_NEST(skb, type) \
|
||||||
({ struct nfattr *__start = (struct nfattr *) (skb)->tail; \
|
({ struct nfattr *__start = (struct nfattr *) (skb)->tail; \
|
||||||
NFA_PUT(skb, type, 0, NULL); \
|
NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \
|
||||||
__start; })
|
__start; })
|
||||||
#define NFA_NEST_END(skb, start) \
|
#define NFA_NEST_END(skb, start) \
|
||||||
({ (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \
|
({ (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \
|
||||||
|
|
|
@ -133,7 +133,7 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
|
||||||
memset(tb, 0, sizeof(struct nfattr *) * maxattr);
|
memset(tb, 0, sizeof(struct nfattr *) * maxattr);
|
||||||
|
|
||||||
while (NFA_OK(nfa, len)) {
|
while (NFA_OK(nfa, len)) {
|
||||||
unsigned flavor = nfa->nfa_type;
|
unsigned flavor = NFA_TYPE(nfa);
|
||||||
if (flavor && flavor <= maxattr)
|
if (flavor && flavor <= maxattr)
|
||||||
tb[flavor-1] = nfa;
|
tb[flavor-1] = nfa;
|
||||||
nfa = NFA_NEXT(nfa, len);
|
nfa = NFA_NEXT(nfa, len);
|
||||||
|
@ -177,7 +177,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
|
||||||
int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
|
int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
|
||||||
|
|
||||||
while (NFA_OK(attr, attrlen)) {
|
while (NFA_OK(attr, attrlen)) {
|
||||||
unsigned flavor = attr->nfa_type;
|
unsigned flavor = NFA_TYPE(attr);
|
||||||
if (flavor) {
|
if (flavor) {
|
||||||
if (flavor > attr_count)
|
if (flavor > attr_count)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Reference in New Issue