diff options
author | Florian Westphal <fw@strlen.de> | 2011-01-18 09:52:14 -0500 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2011-01-18 09:52:14 -0500 |
commit | f615df76ed862b7d3927ec5f55b805ca19be29d9 (patch) | |
tree | 11d8dca165f2b44cfe31e39eacf52d2d899ffbcf | |
parent | 06cdb6349c1f3fd439398dbc04ce4c696f0a41ab (diff) |
netfilter: reduce NF_VERDICT_MASK to 0xff
NF_VERDICT_MASK is currently 0xffff. This is because the upper
16 bits are used to store errno (for NF_DROP) or the queue number
(NF_QUEUE verdict).
As there are up to 0xffff different queues available, there is no more
room to store additional flags.
At the moment there are only 6 different verdicts, i.e. we can reduce
NF_VERDICT_MASK to 0xff to allow storing additional flags in the 0xff00 space.
NF_VERDICT_BITS would then be reduced to 8, but because the value is
exported to userspace, this might cause breakage; e.g.:
e.g. 'queuenr = (1 << NF_VERDICT_BITS) | NF_QUEUE' would now break.
Thus, remove NF_VERDICT_BITS usage in the kernel and move the old value
to the 'userspace compat' section.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/linux/netfilter.h | 20 | ||||
-rw-r--r-- | net/netfilter/core.c | 4 | ||||
-rw-r--r-- | net/netfilter/nf_queue.c | 2 |
3 files changed, 18 insertions, 8 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 0ab7ca787b22..78b73cc10216 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -24,16 +24,19 @@ | |||
24 | #define NF_MAX_VERDICT NF_STOP | 24 | #define NF_MAX_VERDICT NF_STOP |
25 | 25 | ||
26 | /* we overload the higher bits for encoding auxiliary data such as the queue | 26 | /* we overload the higher bits for encoding auxiliary data such as the queue |
27 | * number. Not nice, but better than additional function arguments. */ | 27 | * number or errno values. Not nice, but better than additional function |
28 | #define NF_VERDICT_MASK 0x0000ffff | 28 | * arguments. */ |
29 | #define NF_VERDICT_BITS 16 | 29 | #define NF_VERDICT_MASK 0x000000ff |
30 | |||
31 | /* extra verdict flags have mask 0x0000ff00 */ | ||
30 | 32 | ||
33 | /* queue number (NF_QUEUE) or errno (NF_DROP) */ | ||
31 | #define NF_VERDICT_QMASK 0xffff0000 | 34 | #define NF_VERDICT_QMASK 0xffff0000 |
32 | #define NF_VERDICT_QBITS 16 | 35 | #define NF_VERDICT_QBITS 16 |
33 | 36 | ||
34 | #define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE) | 37 | #define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE) |
35 | 38 | ||
36 | #define NF_DROP_ERR(x) (((-x) << NF_VERDICT_BITS) | NF_DROP) | 39 | #define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP) |
37 | 40 | ||
38 | /* only for userspace compatibility */ | 41 | /* only for userspace compatibility */ |
39 | #ifndef __KERNEL__ | 42 | #ifndef __KERNEL__ |
@@ -41,6 +44,9 @@ | |||
41 | <= 0x2000 is used for protocol-flags. */ | 44 | <= 0x2000 is used for protocol-flags. */ |
42 | #define NFC_UNKNOWN 0x4000 | 45 | #define NFC_UNKNOWN 0x4000 |
43 | #define NFC_ALTERED 0x8000 | 46 | #define NFC_ALTERED 0x8000 |
47 | |||
48 | /* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */ | ||
49 | #define NF_VERDICT_BITS 16 | ||
44 | #endif | 50 | #endif |
45 | 51 | ||
46 | enum nf_inet_hooks { | 52 | enum nf_inet_hooks { |
@@ -72,6 +78,10 @@ union nf_inet_addr { | |||
72 | 78 | ||
73 | #ifdef __KERNEL__ | 79 | #ifdef __KERNEL__ |
74 | #ifdef CONFIG_NETFILTER | 80 | #ifdef CONFIG_NETFILTER |
81 | static inline int NF_DROP_GETERR(int verdict) | ||
82 | { | ||
83 | return -(verdict >> NF_VERDICT_QBITS); | ||
84 | } | ||
75 | 85 | ||
76 | static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1, | 86 | static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1, |
77 | const union nf_inet_addr *a2) | 87 | const union nf_inet_addr *a2) |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 0c5b796ef527..4d88e45b978e 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -175,12 +175,12 @@ next_hook: | |||
175 | ret = 1; | 175 | ret = 1; |
176 | } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) { | 176 | } else if ((verdict & NF_VERDICT_MASK) == NF_DROP) { |
177 | kfree_skb(skb); | 177 | kfree_skb(skb); |
178 | ret = -(verdict >> NF_VERDICT_BITS); | 178 | ret = NF_DROP_GETERR(verdict); |
179 | if (ret == 0) | 179 | if (ret == 0) |
180 | ret = -EPERM; | 180 | ret = -EPERM; |
181 | } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { | 181 | } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { |
182 | ret = nf_queue(skb, elem, pf, hook, indev, outdev, okfn, | 182 | ret = nf_queue(skb, elem, pf, hook, indev, outdev, okfn, |
183 | verdict >> NF_VERDICT_BITS); | 183 | verdict >> NF_VERDICT_QBITS); |
184 | if (ret < 0) { | 184 | if (ret < 0) { |
185 | if (ret == -ECANCELED) | 185 | if (ret == -ECANCELED) |
186 | goto next_hook; | 186 | goto next_hook; |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 5c4b730a2e68..ce1150d4a3f2 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -299,7 +299,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) | |||
299 | case NF_QUEUE: | 299 | case NF_QUEUE: |
300 | err = __nf_queue(skb, elem, entry->pf, entry->hook, | 300 | err = __nf_queue(skb, elem, entry->pf, entry->hook, |
301 | entry->indev, entry->outdev, entry->okfn, | 301 | entry->indev, entry->outdev, entry->okfn, |
302 | verdict >> NF_VERDICT_BITS); | 302 | verdict >> NF_VERDICT_QBITS); |
303 | if (err < 0) { | 303 | if (err < 0) { |
304 | if (err == -ECANCELED) | 304 | if (err == -ECANCELED) |
305 | goto next_hook; | 305 | goto next_hook; |