Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 236639
b: refs/heads/master
c: a8fc0d9
h: refs/heads/master
i:
  236637: 8a1defe
  236635: 48b9ee0
  236631: 18a700a
  236623: 8cfc8b9
  236607: 42ddb46
v: v3
  • Loading branch information
Patrick McHardy committed Jan 18, 2011
1 parent 35f1cad commit 6fcf044
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0b8ad876275c74e4bfb6ec3150793f3c0ecfcee2
refs/heads/master: a8fc0d9b3401cb5e42a437293db383998290157d
21 changes: 16 additions & 5 deletions trunk/include/linux/netfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,30 @@
#define NF_MAX_VERDICT NF_STOP

/* we overload the higher bits for encoding auxiliary data such as the queue
* number. Not nice, but better than additional function arguments. */
#define NF_VERDICT_MASK 0x0000ffff
#define NF_VERDICT_BITS 16
* number or errno values. Not nice, but better than additional function
* arguments. */
#define NF_VERDICT_MASK 0x000000ff

/* extra verdict flags have mask 0x0000ff00 */
#define NF_VERDICT_FLAG_QUEUE_BYPASS 0x00008000

/* queue number (NF_QUEUE) or errno (NF_DROP) */
#define NF_VERDICT_QMASK 0xffff0000
#define NF_VERDICT_QBITS 16

#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE)
#define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE)

#define NF_DROP_ERR(x) (((-x) << NF_VERDICT_BITS) | NF_DROP)
#define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP)

/* only for userspace compatibility */
#ifndef __KERNEL__
/* Generic cache responses from hook functions.
<= 0x2000 is used for protocol-flags. */
#define NFC_UNKNOWN 0x4000
#define NFC_ALTERED 0x8000

/* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */
#define NF_VERDICT_BITS 16
#endif

enum nf_inet_hooks {
Expand Down Expand Up @@ -72,6 +79,10 @@ union nf_inet_addr {

#ifdef __KERNEL__
#ifdef CONFIG_NETFILTER
static inline int NF_DROP_GETERR(int verdict)
{
return -(verdict >> NF_VERDICT_QBITS);
}

static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1,
const union nf_inet_addr *a2)
Expand Down
6 changes: 6 additions & 0 deletions trunk/include/linux/netfilter/xt_NFQUEUE.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ struct xt_NFQ_info_v1 {
__u16 queues_total;
};

struct xt_NFQ_info_v2 {
__u16 queuenum;
__u16 queues_total;
__u16 bypass;
};

#endif /* _XT_NFQ_TARGET_H */
4 changes: 2 additions & 2 deletions trunk/include/net/netfilter/nf_nat_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ static inline int nf_nat_initialized(struct nf_conn *ct,
enum nf_nat_manip_type manip)
{
if (manip == IP_NAT_MANIP_SRC)
return ct->status & IPS_SRC_NAT_DONE_BIT;
return ct->status & IPS_SRC_NAT_DONE;
else
return ct->status & IPS_DST_NAT_DONE_BIT;
return ct->status & IPS_DST_NAT_DONE;
}

struct nlattr;
Expand Down
4 changes: 2 additions & 2 deletions trunk/net/ipv4/netfilter/nf_nat_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,9 @@ nf_nat_setup_info(struct nf_conn *ct,

/* It's done. */
if (maniptype == IP_NAT_MANIP_DST)
ct->status |= IPS_DST_NAT_DONE_BIT;
ct->status |= IPS_DST_NAT_DONE;
else
ct->status |= IPS_SRC_NAT_DONE_BIT;
ct->status |= IPS_SRC_NAT_DONE;

return NF_ACCEPT;
}
Expand Down
1 change: 1 addition & 0 deletions trunk/net/netfilter/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ config NETFILTER_XT_TARGET_NFLOG
config NETFILTER_XT_TARGET_NFQUEUE
tristate '"NFQUEUE" target Support'
depends on NETFILTER_ADVANCED
select NETFILTER_NETLINK_QUEUE
help
This target replaced the old obsolete QUEUE target.

Expand Down
16 changes: 12 additions & 4 deletions trunk/net/netfilter/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,21 @@ int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
ret = 1;
} else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
kfree_skb(skb);
ret = -(verdict >> NF_VERDICT_BITS);
ret = NF_DROP_GETERR(verdict);
if (ret == 0)
ret = -EPERM;
} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
verdict >> NF_VERDICT_BITS))
goto next_hook;
ret = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
verdict >> NF_VERDICT_QBITS);
if (ret < 0) {
if (ret == -ECANCELED)
goto next_hook;
if (ret == -ESRCH &&
(verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
goto next_hook;
kfree_skb(skb);
}
ret = 0;
}
rcu_read_unlock();
return ret;
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/netfilter/nf_conntrack_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
ct->timeout.expires += jiffies;
add_timer(&ct->timeout);
atomic_inc(&ct->ct_general.use);
set_bit(IPS_CONFIRMED_BIT, &ct->status);
ct->status |= IPS_CONFIRMED;

/* Since the lookup is lockless, hash insertion must be done after
* starting the timer and setting the CONFIRMED bit. The RCU barriers
Expand Down
64 changes: 45 additions & 19 deletions trunk/net/netfilter/nf_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static int __nf_queue(struct sk_buff *skb,
int (*okfn)(struct sk_buff *),
unsigned int queuenum)
{
int status;
int status = -ENOENT;
struct nf_queue_entry *entry = NULL;
#ifdef CONFIG_BRIDGE_NETFILTER
struct net_device *physindev;
Expand All @@ -138,16 +138,20 @@ static int __nf_queue(struct sk_buff *skb,
rcu_read_lock();

qh = rcu_dereference(queue_handler[pf]);
if (!qh)
if (!qh) {
status = -ESRCH;
goto err_unlock;
}

afinfo = nf_get_afinfo(pf);
if (!afinfo)
goto err_unlock;

entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC);
if (!entry)
if (!entry) {
status = -ENOMEM;
goto err_unlock;
}

*entry = (struct nf_queue_entry) {
.skb = skb,
Expand All @@ -161,11 +165,9 @@ static int __nf_queue(struct sk_buff *skb,

/* If it's going away, ignore hook. */
if (!try_module_get(entry->elem->owner)) {
rcu_read_unlock();
kfree(entry);
return 0;
status = -ECANCELED;
goto err_unlock;
}

/* Bump dev refs so they don't vanish while packet is out */
if (indev)
dev_hold(indev);
Expand All @@ -192,14 +194,13 @@ static int __nf_queue(struct sk_buff *skb,
goto err;
}

return 1;
return 0;

err_unlock:
rcu_read_unlock();
err:
kfree_skb(skb);
kfree(entry);
return 1;
return status;
}

int nf_queue(struct sk_buff *skb,
Expand All @@ -211,6 +212,8 @@ int nf_queue(struct sk_buff *skb,
unsigned int queuenum)
{
struct sk_buff *segs;
int err;
unsigned int queued;

if (!skb_is_gso(skb))
return __nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
Expand All @@ -226,27 +229,43 @@ int nf_queue(struct sk_buff *skb,
}

segs = skb_gso_segment(skb, 0);
kfree_skb(skb);
/* Does not use PTR_ERR to limit the number of error codes that can be
* returned by nf_queue. For instance, callers rely on -ECANCELED to mean
* 'ignore this hook'.
*/
if (IS_ERR(segs))
return 1;
return -EINVAL;

queued = 0;
err = 0;
do {
struct sk_buff *nskb = segs->next;

segs->next = NULL;
if (!__nf_queue(segs, elem, pf, hook, indev, outdev, okfn,
queuenum))
if (err == 0)
err = __nf_queue(segs, elem, pf, hook, indev,
outdev, okfn, queuenum);
if (err == 0)
queued++;
else
kfree_skb(segs);
segs = nskb;
} while (segs);
return 1;

/* also free orig skb if only some segments were queued */
if (unlikely(err && queued))
err = 0;
if (err == 0)
kfree_skb(skb);
return err;
}

void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
{
struct sk_buff *skb = entry->skb;
struct list_head *elem = &entry->elem->list;
const struct nf_afinfo *afinfo;
int err;

rcu_read_lock();

Expand Down Expand Up @@ -280,10 +299,17 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
local_bh_enable();
break;
case NF_QUEUE:
if (!__nf_queue(skb, elem, entry->pf, entry->hook,
entry->indev, entry->outdev, entry->okfn,
verdict >> NF_VERDICT_BITS))
goto next_hook;
err = __nf_queue(skb, elem, entry->pf, entry->hook,
entry->indev, entry->outdev, entry->okfn,
verdict >> NF_VERDICT_QBITS);
if (err < 0) {
if (err == -ECANCELED)
goto next_hook;
if (err == -ESRCH &&
(verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
goto next_hook;
kfree_skb(skb);
}
break;
case NF_STOLEN:
default:
Expand Down
22 changes: 14 additions & 8 deletions trunk/net/netfilter/nfnetlink_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,25 +387,31 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
{
struct sk_buff *nskb;
struct nfqnl_instance *queue;
int err;
int err = -ENOBUFS;

/* rcu_read_lock()ed by nf_hook_slow() */
queue = instance_lookup(queuenum);
if (!queue)
if (!queue) {
err = -ESRCH;
goto err_out;
}

if (queue->copy_mode == NFQNL_COPY_NONE)
if (queue->copy_mode == NFQNL_COPY_NONE) {
err = -EINVAL;
goto err_out;
}

nskb = nfqnl_build_packet_message(queue, entry);
if (nskb == NULL)
if (nskb == NULL) {
err = -ENOMEM;
goto err_out;

}
spin_lock_bh(&queue->lock);

if (!queue->peer_pid)
if (!queue->peer_pid) {
err = -EINVAL;
goto err_out_free_nskb;

}
if (queue->queue_total >= queue->queue_maxlen) {
queue->queue_dropped++;
if (net_ratelimit())
Expand All @@ -432,7 +438,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
err_out_unlock:
spin_unlock_bh(&queue->lock);
err_out:
return -1;
return err;
}

static int
Expand Down
28 changes: 25 additions & 3 deletions trunk/net/netfilter/xt_NFQUEUE.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,20 @@ nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
return NF_QUEUE_NR(queue);
}

static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
static unsigned int
nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_NFQ_info_v1 *info = par->targinfo;
const struct xt_NFQ_info_v2 *info = par->targinfo;
unsigned int ret = nfqueue_tg_v1(skb, par);

if (info->bypass)
ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
return ret;
}

static int nfqueue_tg_check(const struct xt_tgchk_param *par)
{
const struct xt_NFQ_info_v2 *info = par->targinfo;
u32 maxid;

if (unlikely(!rnd_inited)) {
Expand All @@ -102,6 +113,8 @@ static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
info->queues_total, maxid);
return -ERANGE;
}
if (par->target->revision == 2 && info->bypass > 1)
return -EINVAL;
return 0;
}

Expand All @@ -117,11 +130,20 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = {
.name = "NFQUEUE",
.revision = 1,
.family = NFPROTO_UNSPEC,
.checkentry = nfqueue_tg_v1_check,
.checkentry = nfqueue_tg_check,
.target = nfqueue_tg_v1,
.targetsize = sizeof(struct xt_NFQ_info_v1),
.me = THIS_MODULE,
},
{
.name = "NFQUEUE",
.revision = 2,
.family = NFPROTO_UNSPEC,
.checkentry = nfqueue_tg_check,
.target = nfqueue_tg_v2,
.targetsize = sizeof(struct xt_NFQ_info_v2),
.me = THIS_MODULE,
},
};

static int __init nfqueue_tg_init(void)
Expand Down

0 comments on commit 6fcf044

Please sign in to comment.