Blame view

net/netfilter/xt_NFQUEUE.c 3.82 KB
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
1
2
3
4
5
  /* iptables module for using new netfilter netlink queue
   *
   * (C) 2005 by Harald Welte <laforge@netfilter.org>
   *
   * This program is free software; you can redistribute it and/or modify
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
6
   * it under the terms of the GNU General Public License version 2 as
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
7
   * published by the Free Software Foundation.
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
8
   *
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
9
10
11
12
   */
  
  #include <linux/module.h>
  #include <linux/skbuff.h>
10662aa30   Florian Westphal   netfilter: xt_NFQ...
13
14
15
  #include <linux/ip.h>
  #include <linux/ipv6.h>
  #include <linux/jhash.h>
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
16
17
18
19
20
21
  #include <linux/netfilter.h>
  #include <linux/netfilter_arp.h>
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_NFQUEUE.h>
  
  MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2ae15b64e   Jan Engelhardt   [NETFILTER]: Upda...
22
  MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
23
24
25
26
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("ipt_NFQUEUE");
  MODULE_ALIAS("ip6t_NFQUEUE");
  MODULE_ALIAS("arpt_NFQUEUE");
10662aa30   Florian Westphal   netfilter: xt_NFQ...
27
  static u32 jhash_initval __read_mostly;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
28
  static unsigned int
7eb355865   Jan Engelhardt   netfilter: xtable...
29
  nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par)
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
30
  {
7eb355865   Jan Engelhardt   netfilter: xtable...
31
  	const struct xt_NFQ_info *tinfo = par->targinfo;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
32
33
34
  
  	return NF_QUEUE_NR(tinfo->queuenum);
  }
10662aa30   Florian Westphal   netfilter: xt_NFQ...
35
36
37
  static u32 hash_v4(const struct sk_buff *skb)
  {
  	const struct iphdr *iph = ip_hdr(skb);
f9ffc3125   Patrick McHardy   netfilter: fix so...
38
  	__be32 ipaddr;
10662aa30   Florian Westphal   netfilter: xt_NFQ...
39
40
41
  
  	/* packets in either direction go into same queue */
  	ipaddr = iph->saddr ^ iph->daddr;
f9ffc3125   Patrick McHardy   netfilter: fix so...
42
  	return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval);
10662aa30   Florian Westphal   netfilter: xt_NFQ...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  }
  
  static unsigned int
  nfqueue_tg4_v1(struct sk_buff *skb, const struct xt_target_param *par)
  {
  	const struct xt_NFQ_info_v1 *info = par->targinfo;
  	u32 queue = info->queuenum;
  
  	if (info->queues_total > 1)
  		queue = hash_v4(skb) % info->queues_total + queue;
  	return NF_QUEUE_NR(queue);
  }
  
  #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
  static u32 hash_v6(const struct sk_buff *skb)
  {
  	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
f9ffc3125   Patrick McHardy   netfilter: fix so...
60
  	__be32 addr[4];
10662aa30   Florian Westphal   netfilter: xt_NFQ...
61
62
63
64
65
  
  	addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0];
  	addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1];
  	addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2];
  	addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3];
f9ffc3125   Patrick McHardy   netfilter: fix so...
66
  	return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval);
10662aa30   Florian Westphal   netfilter: xt_NFQ...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  }
  
  static unsigned int
  nfqueue_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par)
  {
  	const struct xt_NFQ_info_v1 *info = par->targinfo;
  	u32 queue = info->queuenum;
  
  	if (info->queues_total > 1)
  		queue = hash_v6(skb) % info->queues_total + queue;
  	return NF_QUEUE_NR(queue);
  }
  #endif
  
  static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
  {
  	const struct xt_NFQ_info_v1 *info = par->targinfo;
  	u32 maxid;
  
  	if (info->queues_total == 0) {
  		pr_err("NFQUEUE: number of total queues is 0
  ");
  		return false;
  	}
  	maxid = info->queues_total - 1 + info->queuenum;
  	if (maxid > 0xffff) {
  		pr_err("NFQUEUE: number of queues (%u) out of range (got %u)
  ",
  		       info->queues_total, maxid);
  		return false;
  	}
  	return true;
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
100
  static struct xt_target nfqueue_tg_reg[] __read_mostly = {
4470bbc74   Patrick McHardy   [NETFILTER]: x_ta...
101
102
  	{
  		.name		= "NFQUEUE",
61f5abcab   Florian Westphal   netfilter: xt_NFQ...
103
  		.family		= NFPROTO_UNSPEC,
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
104
  		.target		= nfqueue_tg,
4470bbc74   Patrick McHardy   [NETFILTER]: x_ta...
105
106
107
  		.targetsize	= sizeof(struct xt_NFQ_info),
  		.me		= THIS_MODULE,
  	},
10662aa30   Florian Westphal   netfilter: xt_NFQ...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  	{
  		.name		= "NFQUEUE",
  		.revision	= 1,
  		.family		= NFPROTO_IPV4,
  		.checkentry	= nfqueue_tg_v1_check,
  		.target		= nfqueue_tg4_v1,
  		.targetsize	= sizeof(struct xt_NFQ_info_v1),
  		.me		= THIS_MODULE,
  	},
  #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
  	{
  		.name		= "NFQUEUE",
  		.revision	= 1,
  		.family		= NFPROTO_IPV6,
  		.checkentry	= nfqueue_tg_v1_check,
  		.target		= nfqueue_tg6_v1,
  		.targetsize	= sizeof(struct xt_NFQ_info_v1),
  		.me		= THIS_MODULE,
  	},
  #endif
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
128
  };
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
129
  static int __init nfqueue_tg_init(void)
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
130
  {
10662aa30   Florian Westphal   netfilter: xt_NFQ...
131
  	get_random_bytes(&jhash_initval, sizeof(jhash_initval));
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
132
  	return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
133
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
134
  static void __exit nfqueue_tg_exit(void)
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
135
  {
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
136
  	xt_unregister_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
137
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
138
139
  module_init(nfqueue_tg_init);
  module_exit(nfqueue_tg_exit);