diff options
Diffstat (limited to 'net/netfilter/xt_NFQUEUE.c')
| -rw-r--r-- | net/netfilter/xt_NFQUEUE.c | 87 | 
1 files changed, 18 insertions, 69 deletions
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 1e2fae32f81..8f1779ff7e3 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c @@ -11,15 +11,13 @@  #include <linux/module.h>  #include <linux/skbuff.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <linux/jhash.h> -  #include <linux/netfilter.h>  #include <linux/netfilter_arp.h>  #include <linux/netfilter/x_tables.h>  #include <linux/netfilter/xt_NFQUEUE.h> +#include <net/netfilter/nf_queue.h> +  MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");  MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");  MODULE_LICENSE("GPL"); @@ -28,7 +26,6 @@ MODULE_ALIAS("ip6t_NFQUEUE");  MODULE_ALIAS("arpt_NFQUEUE");  static u32 jhash_initval __read_mostly; -static bool rnd_inited __read_mostly;  static unsigned int  nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par) @@ -38,69 +35,16 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)  	return NF_QUEUE_NR(tinfo->queuenum);  } -static u32 hash_v4(const struct sk_buff *skb) -{ -	const struct iphdr *iph = ip_hdr(skb); - -	/* packets in either direction go into same queue */ -	if ((__force u32)iph->saddr < (__force u32)iph->daddr) -		return jhash_3words((__force u32)iph->saddr, -			(__force u32)iph->daddr, iph->protocol, jhash_initval); - -	return jhash_3words((__force u32)iph->daddr, -			(__force u32)iph->saddr, iph->protocol, jhash_initval); -} - -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) -static u32 hash_v6(const struct sk_buff *skb) -{ -	const struct ipv6hdr *ip6h = ipv6_hdr(skb); -	u32 a, b, c; - -	if ((__force u32)ip6h->saddr.s6_addr32[3] < -	    (__force u32)ip6h->daddr.s6_addr32[3]) { -		a = (__force u32) ip6h->saddr.s6_addr32[3]; -		b = (__force u32) ip6h->daddr.s6_addr32[3]; -	} else { -		b = (__force u32) ip6h->saddr.s6_addr32[3]; -		a = (__force u32) ip6h->daddr.s6_addr32[3]; -	} - -	if ((__force u32)ip6h->saddr.s6_addr32[1] < -	    (__force u32)ip6h->daddr.s6_addr32[1]) -		c = (__force u32) ip6h->saddr.s6_addr32[1]; -	else -		c = (__force u32) ip6h->daddr.s6_addr32[1]; - -	return jhash_3words(a, b, c, jhash_initval); -} -#endif - -static u32 -nfqueue_hash(const struct sk_buff *skb, const struct xt_action_param *par) -{ -	const struct xt_NFQ_info_v1 *info = par->targinfo; -	u32 queue = info->queuenum; - -	if (par->family == NFPROTO_IPV4) -		queue += ((u64) hash_v4(skb) * info->queues_total) >> 32; -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) -	else if (par->family == NFPROTO_IPV6) -		queue += ((u64) hash_v6(skb) * info->queues_total) >> 32; -#endif - -	return queue; -} -  static unsigned int  nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)  {  	const struct xt_NFQ_info_v1 *info = par->targinfo;  	u32 queue = info->queuenum; -	if (info->queues_total > 1) -		queue = nfqueue_hash(skb, par); - +	if (info->queues_total > 1) { +		queue = nfqueue_hash(skb, queue, info->queues_total, +				     par->family, jhash_initval); +	}  	return NF_QUEUE_NR(queue);  } @@ -120,10 +64,8 @@ static int nfqueue_tg_check(const struct xt_tgchk_param *par)  	const struct xt_NFQ_info_v3 *info = par->targinfo;  	u32 maxid; -	if (unlikely(!rnd_inited)) { -		get_random_bytes(&jhash_initval, sizeof(jhash_initval)); -		rnd_inited = true; -	} +	init_hashrandom(&jhash_initval); +  	if (info->queues_total == 0) {  		pr_err("NFQUEUE: number of total queues is 0\n");  		return -EINVAL; @@ -147,17 +89,24 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)  {  	const struct xt_NFQ_info_v3 *info = par->targinfo;  	u32 queue = info->queuenum; +	int ret;  	if (info->queues_total > 1) {  		if (info->flags & NFQ_FLAG_CPU_FANOUT) {  			int cpu = smp_processor_id();  			queue = info->queuenum + cpu % info->queues_total; -		} else -			queue = nfqueue_hash(skb, par); +		} else { +			queue = nfqueue_hash(skb, queue, info->queues_total, +					     par->family, jhash_initval); +		}  	} -	return NF_QUEUE_NR(queue); +	ret = NF_QUEUE_NR(queue); +	if (info->flags & NFQ_FLAG_BYPASS) +		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS; + +	return ret;  }  static struct xt_target nfqueue_tg_reg[] __read_mostly = {  | 
