Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ab43f84 authored by Harald Welte's avatar Harald Welte Committed by David S. Miller
Browse files

[NETFILTER]: Core changes required by upcoming nfnetlink_queue code



- split netfiler verdict in 16bit verdict and 16bit queue number
- add 'queuenum' argument to nf_queue_outfn_t and its users ip[6]_queue
- move NFNL_SUBSYS_ definitions from enum to #define
- introduce autoloading for nfnetlink subsystem modules
- add MODULE_ALIAS_NFNL_SUBSYS macro
- add nf_unregister_queue_handlers() to register all handlers for a given
  nf_queue_outfn_t
- add more verbose DEBUGP macro definition to nfnetlink.c
- make nfnetlink_subsys_register fail if subsys already exists
- add some more comments and debug statements to nfnetlink.c

Signed-off-by: default avatarHarald Welte <laforge@netfilter.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2cc7d573
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -21,6 +21,16 @@
#define NF_STOP 5
#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

#define NF_VERDICT_QMASK 0xffff0000
#define NF_VERDICT_QBITS 16

#define NF_QUEUE_NR(x) ((x << NF_VERDICT_QBITS) & NF_VERDICT_QMASK || NF_QUEUE)

/* only for userspace compatibility */
#ifndef __KERNEL__
/* Generic cache responses from hook functions.
@@ -179,10 +189,12 @@ int nf_getsockopt(struct sock *sk, int pf, int optval, char __user *opt,

/* Packet queuing */
typedef int (*nf_queue_outfn_t)(struct sk_buff *skb, 
                                struct nf_info *info, void *data);
                                struct nf_info *info,
				unsigned int queuenum, void *data);
extern int nf_register_queue_handler(int pf, 
                                     nf_queue_outfn_t outfn, void *data);
extern int nf_unregister_queue_handler(int pf);
extern void nf_unregister_queue_handlers(nf_queue_outfn_t outfn);
extern void nf_reinject(struct sk_buff *skb,
			struct nf_info *info,
			unsigned int verdict);
+11 −9
Original line number Diff line number Diff line
@@ -69,15 +69,14 @@ struct nfgenmsg {
#define NFNL_SUBSYS_ID(x)	((x & 0xff00) >> 8)
#define NFNL_MSG_TYPE(x)	(x & 0x00ff)

enum nfnl_subsys_id {
	NFNL_SUBSYS_NONE = 0,
	NFNL_SUBSYS_CTNETLINK,
	NFNL_SUBSYS_CTNETLINK_EXP,
	NFNL_SUBSYS_IPTNETLINK,
	NFNL_SUBSYS_QUEUE,
	NFNL_SUBSYS_ULOG,
	NFNL_SUBSYS_COUNT,
};
/* No enum here, otherwise __stringify() trick of MODULE_ALIAS_NFNL_SUBSYS()
 * won't work anymore */
#define NFNL_SUBSYS_NONE 		0
#define NFNL_SUBSYS_CTNETLINK		1
#define NFNL_SUBSYS_CTNETLINK_EXP	2
#define NFNL_SUBSYS_QUEUE		3
#define NFNL_SUBSYS_ULOG		4
#define NFNL_SUBSYS_COUNT		5

#ifdef __KERNEL__

@@ -142,5 +141,8 @@ extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,
			  int echo);
extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags);

#define MODULE_ALIAS_NFNL_SUBSYS(subsys) \
	MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys))

#endif	/* __KERNEL__ */
#endif	/* _NFNETLINK_H */
+33 −7
Original line number Diff line number Diff line
@@ -221,7 +221,8 @@ static unsigned int nf_iterate(struct list_head *head,
		verdict = elem->hook(hook, skb, indev, outdev, okfn);
		if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
			if (unlikely(verdict > NF_MAX_VERDICT)) {
			if (unlikely((verdict & NF_VERDICT_MASK)
							> NF_MAX_VERDICT)) {
				NFDEBUG("Evil return from %p(%u).\n",
				        elem->hook, hook);
				continue;
@@ -239,6 +240,9 @@ int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
{      
	int ret;

	if (pf >= NPROTO)
		return -EINVAL;

	write_lock_bh(&queue_handler_lock);
	if (queue_handler[pf].outfn)
		ret = -EBUSY;
@@ -255,6 +259,9 @@ int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
/* The caller must flush their queue before this */
int nf_unregister_queue_handler(int pf)
{
	if (pf >= NPROTO)
		return -EINVAL;

	write_lock_bh(&queue_handler_lock);
	queue_handler[pf].outfn = NULL;
	queue_handler[pf].data = NULL;
@@ -286,6 +293,20 @@ int nf_unregister_queue_rerouter(int pf)
	return 0;
}

void nf_unregister_queue_handlers(nf_queue_outfn_t outfn)
{
	int pf;

	write_lock_bh(&queue_handler_lock);
	for (pf = 0; pf < NPROTO; pf++)  {
		if (queue_handler[pf].outfn == outfn) {
			queue_handler[pf].outfn = NULL;
			queue_handler[pf].data = NULL;
		}
	}
	write_unlock_bh(&queue_handler_lock);
}

/* 
 * Any packet that leaves via this function must come back 
 * through nf_reinject().
@@ -295,7 +316,8 @@ static int nf_queue(struct sk_buff **skb,
		    int pf, unsigned int hook,
		    struct net_device *indev,
		    struct net_device *outdev,
		    int (*okfn)(struct sk_buff *))
		    int (*okfn)(struct sk_buff *),
		    unsigned int queuenum)
{
	int status;
	struct nf_info *info;
@@ -347,7 +369,8 @@ static int nf_queue(struct sk_buff **skb,
	if (queue_rerouter[pf].save)
		queue_rerouter[pf].save(*skb, info);

	status = queue_handler[pf].outfn(*skb, info, queue_handler[pf].data);
	status = queue_handler[pf].outfn(*skb, info, queuenum,
					 queue_handler[pf].data);

	if (status >= 0 && queue_rerouter[pf].reroute)
		status = queue_rerouter[pf].reroute(skb, info);
@@ -397,9 +420,10 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
	} else if (verdict == NF_DROP) {
		kfree_skb(*pskb);
		ret = -EPERM;
	} else if (verdict == NF_QUEUE) {
	} else if ((verdict & NF_VERDICT_MASK)  == NF_QUEUE) {
		NFDEBUG("nf_hook: Verdict = QUEUE.\n");
		if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn))
		if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn,
			      verdict >> NF_VERDICT_BITS))
			goto next_hook;
	}
unlock:
@@ -456,14 +480,15 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
				     info->okfn, INT_MIN);
	}

	switch (verdict) {
	switch (verdict & NF_VERDICT_MASK) {
	case NF_ACCEPT:
		info->okfn(skb);
		break;

	case NF_QUEUE:
		if (!nf_queue(&skb, elem, info->pf, info->hook, 
			      info->indev, info->outdev, info->okfn))
			      info->indev, info->outdev, info->okfn,
			      verdict >> NF_VERDICT_BITS))
			goto next_hook;
		break;
	}
@@ -613,6 +638,7 @@ EXPORT_SYMBOL(nf_reinject);
EXPORT_SYMBOL(nf_setsockopt);
EXPORT_SYMBOL(nf_unregister_hook);
EXPORT_SYMBOL(nf_unregister_queue_handler);
EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
EXPORT_SYMBOL(nf_unregister_sockopt);
+2 −1
Original line number Diff line number Diff line
@@ -280,7 +280,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
}

static int
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
		   unsigned int queuenum, void *data)
{
	int status = -EINVAL;
	struct sk_buff *nskb;
+2 −1
Original line number Diff line number Diff line
@@ -278,7 +278,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
}

static int
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, 
		   unsigned int queuenum, void *data)
{
	int status = -EINVAL;
	struct sk_buff *nskb;
Loading