aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2006-01-12 16:30:04 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-12 17:06:43 -0500
commit2e4e6a17af35be359cc8f1c924f8f198fbd478cc (patch)
treecb4b5438dcf9ff9d57518a26124308bcbfffd214 /net/ipv6
parent880b005f294454d989783d0984dc554dfe3c8214 (diff)
[NETFILTER] x_tables: Abstraction layer for {ip,ip6,arp}_tables
This monster-patch tries to do the best job for unifying the data structures and backend interfaces for the three evil clones ip_tables, ip6_tables and arp_tables. In an ideal world we would never have allowed this kind of copy+paste programming... but well, our world isn't (yet?) ideal. o introduce a new x_tables module o {ip,arp,ip6}_tables depend on this x_tables module o registration functions for tables, matches and targets are only wrappers around x_tables provided functions o all matches/targets that are used from ip_tables and ip6_tables are now implemented as xt_FOOBAR.c files and provide module aliases to ipt_FOOBAR and ip6t_FOOBAR o header files for xt_matches are in include/linux/netfilter/, include/linux/netfilter_{ipv4,ipv6} contains compatibility wrappers around the xt_FOOBAR.h headers Based on this patchset we're going to further unify the code, gradually getting rid of all the layer 3 specific assumptions. Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/Kconfig72
-rw-r--r--net/ipv6/netfilter/Makefile6
-rw-r--r--net/ipv6/netfilter/ip6_tables.c828
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c2
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c2
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c81
-rw-r--r--net/ipv6/netfilter/ip6t_NFQUEUE.c70
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c2
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c2
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c2
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c2
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c2
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c2
-rw-r--r--net/ipv6/netfilter/ip6t_length.c66
-rw-r--r--net/ipv6/netfilter/ip6t_limit.c147
-rw-r--r--net/ipv6/netfilter/ip6t_mac.c81
-rw-r--r--net/ipv6/netfilter/ip6t_mark.c66
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c3
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c2
-rw-r--r--net/ipv6/netfilter/ip6t_physdev.c135
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c2
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c1
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c1
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c8
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c45
29 files changed, 140 insertions, 1502 deletions
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 105dd69ee9fb..2d6f8ecbc27b 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -41,6 +41,7 @@ config IP6_NF_QUEUE
41 41
42config IP6_NF_IPTABLES 42config IP6_NF_IPTABLES
43 tristate "IP6 tables support (required for filtering/masq/NAT)" 43 tristate "IP6 tables support (required for filtering/masq/NAT)"
44 depends on NETFILTER_XTABLES
44 help 45 help
45 ip6tables is a general, extensible packet identification framework. 46 ip6tables is a general, extensible packet identification framework.
46 Currently only the packet filtering and packet mangling subsystem 47 Currently only the packet filtering and packet mangling subsystem
@@ -50,25 +51,6 @@ config IP6_NF_IPTABLES
50 To compile it as a module, choose M here. If unsure, say N. 51 To compile it as a module, choose M here. If unsure, say N.
51 52
52# The simple matches. 53# The simple matches.
53config IP6_NF_MATCH_LIMIT
54 tristate "limit match support"
55 depends on IP6_NF_IPTABLES
56 help
57 limit matching allows you to control the rate at which a rule can be
58 matched: mainly useful in combination with the LOG target ("LOG
59 target support", below) and to avoid some Denial of Service attacks.
60
61 To compile it as a module, choose M here. If unsure, say N.
62
63config IP6_NF_MATCH_MAC
64 tristate "MAC address match support"
65 depends on IP6_NF_IPTABLES
66 help
67 mac matching allows you to match packets based on the source
68 Ethernet address of the packet.
69
70 To compile it as a module, choose M here. If unsure, say N.
71
72config IP6_NF_MATCH_RT 54config IP6_NF_MATCH_RT
73 tristate "Routing header match support" 55 tristate "Routing header match support"
74 depends on IP6_NF_IPTABLES 56 depends on IP6_NF_IPTABLES
@@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER
124 106
125 To compile it as a module, choose M here. If unsure, say N. 107 To compile it as a module, choose M here. If unsure, say N.
126 108
127config IP6_NF_MATCH_MARK
128 tristate "netfilter MARK match support"
129 depends on IP6_NF_IPTABLES
130 help
131 Netfilter mark matching allows you to match packets based on the
132 `nfmark' value in the packet. This can be set by the MARK target
133 (see below).
134
135 To compile it as a module, choose M here. If unsure, say N.
136
137config IP6_NF_MATCH_IPV6HEADER 109config IP6_NF_MATCH_IPV6HEADER
138 tristate "IPv6 Extension Headers Match" 110 tristate "IPv6 Extension Headers Match"
139 depends on IP6_NF_IPTABLES 111 depends on IP6_NF_IPTABLES
@@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP
151 123
152 To compile it as a module, choose M here. If unsure, say N. 124 To compile it as a module, choose M here. If unsure, say N.
153 125
154config IP6_NF_MATCH_LENGTH
155 tristate "Packet Length match support"
156 depends on IP6_NF_IPTABLES
157 help
158 This option allows you to match the length of a packet against a
159 specific value or range of values.
160
161 To compile it as a module, choose M here. If unsure, say N.
162
163config IP6_NF_MATCH_EUI64 126config IP6_NF_MATCH_EUI64
164 tristate "EUI64 address check" 127 tristate "EUI64 address check"
165 depends on IP6_NF_IPTABLES 128 depends on IP6_NF_IPTABLES
@@ -170,15 +133,6 @@ config IP6_NF_MATCH_EUI64
170 133
171 To compile it as a module, choose M here. If unsure, say N. 134 To compile it as a module, choose M here. If unsure, say N.
172 135
173config IP6_NF_MATCH_PHYSDEV
174 tristate "Physdev match support"
175 depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
176 help
177 Physdev packet matching matches against the physical bridge ports
178 the IP packet arrived on or will leave by.
179
180 To compile it as a module, choose M here. If unsure, say N.
181
182config IP6_NF_MATCH_POLICY 136config IP6_NF_MATCH_POLICY
183 tristate "IPsec policy match support" 137 tristate "IPsec policy match support"
184 depends on IP6_NF_IPTABLES && XFRM 138 depends on IP6_NF_IPTABLES && XFRM
@@ -219,17 +173,6 @@ config IP6_NF_TARGET_REJECT
219 173
220 To compile it as a module, choose M here. If unsure, say N. 174 To compile it as a module, choose M here. If unsure, say N.
221 175
222config IP6_NF_TARGET_NFQUEUE
223 tristate "NFQUEUE Target Support"
224 depends on IP6_NF_IPTABLES
225 help
226 This Target replaced the old obsolete QUEUE target.
227
228 As opposed to QUEUE, it supports 65535 different queues,
229 not just one.
230
231 To compile it as a module, choose M here. If unsure, say N.
232
233config IP6_NF_MANGLE 176config IP6_NF_MANGLE
234 tristate "Packet mangling" 177 tristate "Packet mangling"
235 depends on IP6_NF_IPTABLES 178 depends on IP6_NF_IPTABLES
@@ -240,19 +183,6 @@ config IP6_NF_MANGLE
240 183
241 To compile it as a module, choose M here. If unsure, say N. 184 To compile it as a module, choose M here. If unsure, say N.
242 185
243config IP6_NF_TARGET_MARK
244 tristate "MARK target support"
245 depends on IP6_NF_MANGLE
246 help
247 This option adds a `MARK' target, which allows you to create rules
248 in the `mangle' table which alter the netfilter mark (nfmark) field
249 associated with the packet packet prior to routing. This can change
250 the routing method (see `Use netfilter MARK value as routing
251 key') and can also be used by other subsystems to change their
252 behavior.
253
254 To compile it as a module, choose M here. If unsure, say N.
255
256config IP6_NF_TARGET_HL 186config IP6_NF_TARGET_HL
257 tristate 'HL (hoplimit) target support' 187 tristate 'HL (hoplimit) target support'
258 depends on IP6_NF_MANGLE 188 depends on IP6_NF_MANGLE
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index c0c809b426e8..663b4749820d 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -4,10 +4,7 @@
4 4
5# Link order matters here. 5# Link order matters here.
6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
7obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
8obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
9obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o 7obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
10obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
11obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 8obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
12obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o 9obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
13obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 10obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
@@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
17obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 14obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
18obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o 15obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
19obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o 16obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
20obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
21obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 17obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
22obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 18obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
23obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
24obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o 19obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
25obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o
26obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 20obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
27obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o 21obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
28obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 22obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1390370186d9..847068fd3367 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -13,6 +13,9 @@
13 * a table 13 * a table
14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> 14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu>
15 * - new extension header parser code 15 * - new extension header parser code
16 * 15 Oct 2005 Harald Welte <laforge@netfilter.org>
17 * - Unification of {ip,ip6}_tables into x_tables
18 * - Removed tcp and udp code, since it's not ipv6 specific
16 */ 19 */
17 20
18#include <linux/capability.h> 21#include <linux/capability.h>
@@ -23,8 +26,6 @@
23#include <linux/vmalloc.h> 26#include <linux/vmalloc.h>
24#include <linux/netdevice.h> 27#include <linux/netdevice.h>
25#include <linux/module.h> 28#include <linux/module.h>
26#include <linux/tcp.h>
27#include <linux/udp.h>
28#include <linux/icmpv6.h> 29#include <linux/icmpv6.h>
29#include <net/ipv6.h> 30#include <net/ipv6.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -33,6 +34,7 @@
33#include <linux/cpumask.h> 34#include <linux/cpumask.h>
34 35
35#include <linux/netfilter_ipv6/ip6_tables.h> 36#include <linux/netfilter_ipv6/ip6_tables.h>
37#include <linux/netfilter/x_tables.h>
36 38
37MODULE_LICENSE("GPL"); 39MODULE_LICENSE("GPL");
38MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 40MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -67,13 +69,8 @@ do { \
67#else 69#else
68#define IP_NF_ASSERT(x) 70#define IP_NF_ASSERT(x)
69#endif 71#endif
70#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
71 72
72static DECLARE_MUTEX(ip6t_mutex);
73 73
74/* Must have mutex */
75#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
76#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
77#include <linux/netfilter_ipv4/listhelp.h> 74#include <linux/netfilter_ipv4/listhelp.h>
78 75
79#if 0 76#if 0
@@ -91,30 +88,6 @@ static DECLARE_MUTEX(ip6t_mutex);
91 88
92 Hence the start of any table is given by get_table() below. */ 89 Hence the start of any table is given by get_table() below. */
93 90
94/* The table itself */
95struct ip6t_table_info
96{
97 /* Size per table */
98 unsigned int size;
99 /* Number of entries: FIXME. --RR */
100 unsigned int number;
101 /* Initial number of entries. Needed for module usage count */
102 unsigned int initial_entries;
103
104 /* Entry points and underflows */
105 unsigned int hook_entry[NF_IP6_NUMHOOKS];
106 unsigned int underflow[NF_IP6_NUMHOOKS];
107
108 /* ip6t_entry tables: one per CPU */
109 void *entries[NR_CPUS];
110};
111
112static LIST_HEAD(ip6t_target);
113static LIST_HEAD(ip6t_match);
114static LIST_HEAD(ip6t_tables);
115#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
116#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
117
118#if 0 91#if 0
119#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) 92#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
120#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) 93#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
@@ -297,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb,
297 unsigned int hook, 270 unsigned int hook,
298 const struct net_device *in, 271 const struct net_device *in,
299 const struct net_device *out, 272 const struct net_device *out,
300 struct ip6t_table *table, 273 struct xt_table *table,
301 void *userdata) 274 void *userdata)
302{ 275{
303 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 276 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
@@ -309,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb,
309 const char *indev, *outdev; 282 const char *indev, *outdev;
310 void *table_base; 283 void *table_base;
311 struct ip6t_entry *e, *back; 284 struct ip6t_entry *e, *back;
285 struct xt_table_info *private;
312 286
313 /* Initialization */ 287 /* Initialization */
314 indev = in ? in->name : nulldevname; 288 indev = in ? in->name : nulldevname;
@@ -321,9 +295,10 @@ ip6t_do_table(struct sk_buff **pskb,
321 * match it. */ 295 * match it. */
322 296
323 read_lock_bh(&table->lock); 297 read_lock_bh(&table->lock);
298 private = table->private;
324 IP_NF_ASSERT(table->valid_hooks & (1 << hook)); 299 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
325 table_base = (void *)table->private->entries[smp_processor_id()]; 300 table_base = (void *)private->entries[smp_processor_id()];
326 e = get_entry(table_base, table->private->hook_entry[hook]); 301 e = get_entry(table_base, private->hook_entry[hook]);
327 302
328#ifdef CONFIG_NETFILTER_DEBUG 303#ifdef CONFIG_NETFILTER_DEBUG
329 /* Check noone else using our table */ 304 /* Check noone else using our table */
@@ -339,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb,
339#endif 314#endif
340 315
341 /* For return from builtin chain */ 316 /* For return from builtin chain */
342 back = get_entry(table_base, table->private->underflow[hook]); 317 back = get_entry(table_base, private->underflow[hook]);
343 318
344 do { 319 do {
345 IP_NF_ASSERT(e); 320 IP_NF_ASSERT(e);
@@ -439,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb,
439#endif 414#endif
440} 415}
441 416
442/*
443 * These are weird, but module loading must not be done with mutex
444 * held (since they will register), and we have to have a single
445 * function to use try_then_request_module().
446 */
447
448/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
449static inline struct ip6t_table *find_table_lock(const char *name)
450{
451 struct ip6t_table *t;
452
453 if (down_interruptible(&ip6t_mutex) != 0)
454 return ERR_PTR(-EINTR);
455
456 list_for_each_entry(t, &ip6t_tables, list)
457 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
458 return t;
459 up(&ip6t_mutex);
460 return NULL;
461}
462
463/* Find match, grabs ref. Returns ERR_PTR() on error. */
464static inline struct ip6t_match *find_match(const char *name, u8 revision)
465{
466 struct ip6t_match *m;
467 int err = 0;
468
469 if (down_interruptible(&ip6t_mutex) != 0)
470 return ERR_PTR(-EINTR);
471
472 list_for_each_entry(m, &ip6t_match, list) {
473 if (strcmp(m->name, name) == 0) {
474 if (m->revision == revision) {
475 if (try_module_get(m->me)) {
476 up(&ip6t_mutex);
477 return m;
478 }
479 } else
480 err = -EPROTOTYPE; /* Found something. */
481 }
482 }
483 up(&ip6t_mutex);
484 return ERR_PTR(err);
485}
486
487/* Find target, grabs ref. Returns ERR_PTR() on error. */
488static inline struct ip6t_target *find_target(const char *name, u8 revision)
489{
490 struct ip6t_target *t;
491 int err = 0;
492
493 if (down_interruptible(&ip6t_mutex) != 0)
494 return ERR_PTR(-EINTR);
495
496 list_for_each_entry(t, &ip6t_target, list) {
497 if (strcmp(t->name, name) == 0) {
498 if (t->revision == revision) {
499 if (try_module_get(t->me)) {
500 up(&ip6t_mutex);
501 return t;
502 }
503 } else
504 err = -EPROTOTYPE; /* Found something. */
505 }
506 }
507 up(&ip6t_mutex);
508 return ERR_PTR(err);
509}
510
511struct ip6t_target *ip6t_find_target(const char *name, u8 revision)
512{
513 struct ip6t_target *target;
514
515 target = try_then_request_module(find_target(name, revision),
516 "ip6t_%s", name);
517 if (IS_ERR(target) || !target)
518 return NULL;
519 return target;
520}
521
522static int match_revfn(const char *name, u8 revision, int *bestp)
523{
524 struct ip6t_match *m;
525 int have_rev = 0;
526
527 list_for_each_entry(m, &ip6t_match, list) {
528 if (strcmp(m->name, name) == 0) {
529 if (m->revision > *bestp)
530 *bestp = m->revision;
531 if (m->revision == revision)
532 have_rev = 1;
533 }
534 }
535 return have_rev;
536}
537
538static int target_revfn(const char *name, u8 revision, int *bestp)
539{
540 struct ip6t_target *t;
541 int have_rev = 0;
542
543 list_for_each_entry(t, &ip6t_target, list) {
544 if (strcmp(t->name, name) == 0) {
545 if (t->revision > *bestp)
546 *bestp = t->revision;
547 if (t->revision == revision)
548 have_rev = 1;
549 }
550 }
551 return have_rev;
552}
553
554/* Returns true or fals (if no such extension at all) */
555static inline int find_revision(const char *name, u8 revision,
556 int (*revfn)(const char *, u8, int *),
557 int *err)
558{
559 int have_rev, best = -1;
560
561 if (down_interruptible(&ip6t_mutex) != 0) {
562 *err = -EINTR;
563 return 1;
564 }
565 have_rev = revfn(name, revision, &best);
566 up(&ip6t_mutex);
567
568 /* Nothing at all? Return 0 to try loading module. */
569 if (best == -1) {
570 *err = -ENOENT;
571 return 0;
572 }
573
574 *err = best;
575 if (!have_rev)
576 *err = -EPROTONOSUPPORT;
577 return 1;
578}
579
580
581/* All zeroes == unconditional rule. */ 417/* All zeroes == unconditional rule. */
582static inline int 418static inline int
583unconditional(const struct ip6t_ip6 *ipv6) 419unconditional(const struct ip6t_ip6 *ipv6)
@@ -594,7 +430,7 @@ unconditional(const struct ip6t_ip6 *ipv6)
594/* Figures out from what hook each rule can be called: returns 0 if 430/* Figures out from what hook each rule can be called: returns 0 if
595 there are loops. Puts hook bitmask in comefrom. */ 431 there are loops. Puts hook bitmask in comefrom. */
596static int 432static int
597mark_source_chains(struct ip6t_table_info *newinfo, 433mark_source_chains(struct xt_table_info *newinfo,
598 unsigned int valid_hooks, void *entry0) 434 unsigned int valid_hooks, void *entry0)
599{ 435{
600 unsigned int hook; 436 unsigned int hook;
@@ -740,11 +576,11 @@ check_match(struct ip6t_entry_match *m,
740{ 576{
741 struct ip6t_match *match; 577 struct ip6t_match *match;
742 578
743 match = try_then_request_module(find_match(m->u.user.name, 579 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
744 m->u.user.revision), 580 m->u.user.revision),
745 "ip6t_%s", m->u.user.name); 581 "ip6t_%s", m->u.user.name);
746 if (IS_ERR(match) || !match) { 582 if (IS_ERR(match) || !match) {
747 duprintf("check_match: `%s' not found\n", m->u.user.name); 583 duprintf("check_match: `%s' not found\n", m->u.user.name);
748 return match ? PTR_ERR(match) : -ENOENT; 584 return match ? PTR_ERR(match) : -ENOENT;
749 } 585 }
750 m->u.kernel.match = match; 586 m->u.kernel.match = match;
@@ -785,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
785 goto cleanup_matches; 621 goto cleanup_matches;
786 622
787 t = ip6t_get_target(e); 623 t = ip6t_get_target(e);
788 target = try_then_request_module(find_target(t->u.user.name, 624 target = try_then_request_module(xt_find_target(AF_INET6,
789 t->u.user.revision), 625 t->u.user.name,
626 t->u.user.revision),
790 "ip6t_%s", t->u.user.name); 627 "ip6t_%s", t->u.user.name);
791 if (IS_ERR(target) || !target) { 628 if (IS_ERR(target) || !target) {
792 duprintf("check_entry: `%s' not found\n", t->u.user.name); 629 duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -822,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
822 659
823static inline int 660static inline int
824check_entry_size_and_hooks(struct ip6t_entry *e, 661check_entry_size_and_hooks(struct ip6t_entry *e,
825 struct ip6t_table_info *newinfo, 662 struct xt_table_info *newinfo,
826 unsigned char *base, 663 unsigned char *base,
827 unsigned char *limit, 664 unsigned char *limit,
828 const unsigned int *hook_entries, 665 const unsigned int *hook_entries,
@@ -856,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
856 < 0 (not IP6T_RETURN). --RR */ 693 < 0 (not IP6T_RETURN). --RR */
857 694
858 /* Clear counters and comefrom */ 695 /* Clear counters and comefrom */
859 e->counters = ((struct ip6t_counters) { 0, 0 }); 696 e->counters = ((struct xt_counters) { 0, 0 });
860 e->comefrom = 0; 697 e->comefrom = 0;
861 698
862 (*i)++; 699 (*i)++;
@@ -886,7 +723,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
886static int 723static int
887translate_table(const char *name, 724translate_table(const char *name,
888 unsigned int valid_hooks, 725 unsigned int valid_hooks,
889 struct ip6t_table_info *newinfo, 726 struct xt_table_info *newinfo,
890 void *entry0, 727 void *entry0,
891 unsigned int size, 728 unsigned int size,
892 unsigned int number, 729 unsigned int number,
@@ -963,48 +800,10 @@ translate_table(const char *name,
963 return ret; 800 return ret;
964} 801}
965 802
966static struct ip6t_table_info *
967replace_table(struct ip6t_table *table,
968 unsigned int num_counters,
969 struct ip6t_table_info *newinfo,
970 int *error)
971{
972 struct ip6t_table_info *oldinfo;
973
974#ifdef CONFIG_NETFILTER_DEBUG
975 {
976 int cpu;
977
978 for_each_cpu(cpu) {
979 struct ip6t_entry *table_base = newinfo->entries[cpu];
980 if (table_base)
981 table_base->comefrom = 0xdead57ac;
982 }
983 }
984#endif
985
986 /* Do the substitution. */
987 write_lock_bh(&table->lock);
988 /* Check inside lock: is the old number correct? */
989 if (num_counters != table->private->number) {
990 duprintf("num_counters != table->private->number (%u/%u)\n",
991 num_counters, table->private->number);
992 write_unlock_bh(&table->lock);
993 *error = -EAGAIN;
994 return NULL;
995 }
996 oldinfo = table->private;
997 table->private = newinfo;
998 newinfo->initial_entries = oldinfo->initial_entries;
999 write_unlock_bh(&table->lock);
1000
1001 return oldinfo;
1002}
1003
1004/* Gets counters. */ 803/* Gets counters. */
1005static inline int 804static inline int
1006add_entry_to_counter(const struct ip6t_entry *e, 805add_entry_to_counter(const struct ip6t_entry *e,
1007 struct ip6t_counters total[], 806 struct xt_counters total[],
1008 unsigned int *i) 807 unsigned int *i)
1009{ 808{
1010 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); 809 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
@@ -1025,8 +824,8 @@ set_entry_to_counter(const struct ip6t_entry *e,
1025} 824}
1026 825
1027static void 826static void
1028get_counters(const struct ip6t_table_info *t, 827get_counters(const struct xt_table_info *t,
1029 struct ip6t_counters counters[]) 828 struct xt_counters counters[])
1030{ 829{
1031 unsigned int cpu; 830 unsigned int cpu;
1032 unsigned int i; 831 unsigned int i;
@@ -1060,19 +859,20 @@ get_counters(const struct ip6t_table_info *t,
1060 859
1061static int 860static int
1062copy_entries_to_user(unsigned int total_size, 861copy_entries_to_user(unsigned int total_size,
1063 struct ip6t_table *table, 862 struct xt_table *table,
1064 void __user *userptr) 863 void __user *userptr)
1065{ 864{
1066 unsigned int off, num, countersize; 865 unsigned int off, num, countersize;
1067 struct ip6t_entry *e; 866 struct ip6t_entry *e;
1068 struct ip6t_counters *counters; 867 struct xt_counters *counters;
868 struct xt_table_info *private = table->private;
1069 int ret = 0; 869 int ret = 0;
1070 void *loc_cpu_entry; 870 void *loc_cpu_entry;
1071 871
1072 /* We need atomic snapshot of counters: rest doesn't change 872 /* We need atomic snapshot of counters: rest doesn't change
1073 (other than comefrom, which userspace doesn't care 873 (other than comefrom, which userspace doesn't care
1074 about). */ 874 about). */
1075 countersize = sizeof(struct ip6t_counters) * table->private->number; 875 countersize = sizeof(struct xt_counters) * private->number;
1076 counters = vmalloc(countersize); 876 counters = vmalloc(countersize);
1077 877
1078 if (counters == NULL) 878 if (counters == NULL)
@@ -1080,11 +880,11 @@ copy_entries_to_user(unsigned int total_size,
1080 880
1081 /* First, sum counters... */ 881 /* First, sum counters... */
1082 write_lock_bh(&table->lock); 882 write_lock_bh(&table->lock);
1083 get_counters(table->private, counters); 883 get_counters(private, counters);
1084 write_unlock_bh(&table->lock); 884 write_unlock_bh(&table->lock);
1085 885
1086 /* choose the copy that is on ourc node/cpu */ 886 /* choose the copy that is on ourc node/cpu */
1087 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 887 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1088 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 888 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1089 ret = -EFAULT; 889 ret = -EFAULT;
1090 goto free_counters; 890 goto free_counters;
@@ -1143,87 +943,42 @@ get_entries(const struct ip6t_get_entries *entries,
1143 struct ip6t_get_entries __user *uptr) 943 struct ip6t_get_entries __user *uptr)
1144{ 944{
1145 int ret; 945 int ret;
1146 struct ip6t_table *t; 946 struct xt_table *t;
1147 947
1148 t = find_table_lock(entries->name); 948 t = xt_find_table_lock(AF_INET6, entries->name);
1149 if (t && !IS_ERR(t)) { 949 if (t && !IS_ERR(t)) {
1150 duprintf("t->private->number = %u\n", 950 struct xt_table_info *private = t->private;
1151 t->private->number); 951 duprintf("t->private->number = %u\n", private->number);
1152 if (entries->size == t->private->size) 952 if (entries->size == private->size)
1153 ret = copy_entries_to_user(t->private->size, 953 ret = copy_entries_to_user(private->size,
1154 t, uptr->entrytable); 954 t, uptr->entrytable);
1155 else { 955 else {
1156 duprintf("get_entries: I've got %u not %u!\n", 956 duprintf("get_entries: I've got %u not %u!\n",
1157 t->private->size, 957 private->size, entries->size);
1158 entries->size);
1159 ret = -EINVAL; 958 ret = -EINVAL;
1160 } 959 }
1161 module_put(t->me); 960 module_put(t->me);
1162 up(&ip6t_mutex); 961 xt_table_unlock(t);
1163 } else 962 } else
1164 ret = t ? PTR_ERR(t) : -ENOENT; 963 ret = t ? PTR_ERR(t) : -ENOENT;
1165 964
1166 return ret; 965 return ret;
1167} 966}
1168 967
1169static void free_table_info(struct ip6t_table_info *info)
1170{
1171 int cpu;
1172 for_each_cpu(cpu) {
1173 if (info->size <= PAGE_SIZE)
1174 kfree(info->entries[cpu]);
1175 else
1176 vfree(info->entries[cpu]);
1177 }
1178 kfree(info);
1179}
1180
1181static struct ip6t_table_info *alloc_table_info(unsigned int size)
1182{
1183 struct ip6t_table_info *newinfo;
1184 int cpu;
1185
1186 newinfo = kzalloc(sizeof(struct ip6t_table_info), GFP_KERNEL);
1187 if (!newinfo)
1188 return NULL;
1189
1190 newinfo->size = size;
1191
1192 for_each_cpu(cpu) {
1193 if (size <= PAGE_SIZE)
1194 newinfo->entries[cpu] = kmalloc_node(size,
1195 GFP_KERNEL,
1196 cpu_to_node(cpu));
1197 else
1198 newinfo->entries[cpu] = vmalloc_node(size,
1199 cpu_to_node(cpu));
1200 if (newinfo->entries[cpu] == NULL) {
1201 free_table_info(newinfo);
1202 return NULL;
1203 }
1204 }
1205
1206 return newinfo;
1207}
1208
1209static int 968static int
1210do_replace(void __user *user, unsigned int len) 969do_replace(void __user *user, unsigned int len)
1211{ 970{
1212 int ret; 971 int ret;
1213 struct ip6t_replace tmp; 972 struct ip6t_replace tmp;
1214 struct ip6t_table *t; 973 struct xt_table *t;
1215 struct ip6t_table_info *newinfo, *oldinfo; 974 struct xt_table_info *newinfo, *oldinfo;
1216 struct ip6t_counters *counters; 975 struct xt_counters *counters;
1217 void *loc_cpu_entry, *loc_cpu_old_entry; 976 void *loc_cpu_entry, *loc_cpu_old_entry;
1218 977
1219 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 978 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1220 return -EFAULT; 979 return -EFAULT;
1221 980
1222 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ 981 newinfo = xt_alloc_table_info(tmp.size);
1223 if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
1224 return -ENOMEM;
1225
1226 newinfo = alloc_table_info(tmp.size);
1227 if (!newinfo) 982 if (!newinfo)
1228 return -ENOMEM; 983 return -ENOMEM;
1229 984
@@ -1235,7 +990,7 @@ do_replace(void __user *user, unsigned int len)
1235 goto free_newinfo; 990 goto free_newinfo;
1236 } 991 }
1237 992
1238 counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); 993 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1239 if (!counters) { 994 if (!counters) {
1240 ret = -ENOMEM; 995 ret = -ENOMEM;
1241 goto free_newinfo; 996 goto free_newinfo;
@@ -1249,7 +1004,7 @@ do_replace(void __user *user, unsigned int len)
1249 1004
1250 duprintf("ip_tables: Translated table\n"); 1005 duprintf("ip_tables: Translated table\n");
1251 1006
1252 t = try_then_request_module(find_table_lock(tmp.name), 1007 t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
1253 "ip6table_%s", tmp.name); 1008 "ip6table_%s", tmp.name);
1254 if (!t || IS_ERR(t)) { 1009 if (!t || IS_ERR(t)) {
1255 ret = t ? PTR_ERR(t) : -ENOENT; 1010 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1264,7 +1019,7 @@ do_replace(void __user *user, unsigned int len)
1264 goto put_module; 1019 goto put_module;
1265 } 1020 }
1266 1021
1267 oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); 1022 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1268 if (!oldinfo) 1023 if (!oldinfo)
1269 goto put_module; 1024 goto put_module;
1270 1025
@@ -1283,23 +1038,23 @@ do_replace(void __user *user, unsigned int len)
1283 /* Decrease module usage counts and free resource */ 1038 /* Decrease module usage counts and free resource */
1284 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1039 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1285 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); 1040 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1286 free_table_info(oldinfo); 1041 xt_free_table_info(oldinfo);
1287 if (copy_to_user(tmp.counters, counters, 1042 if (copy_to_user(tmp.counters, counters,
1288 sizeof(struct ip6t_counters) * tmp.num_counters) != 0) 1043 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1289 ret = -EFAULT; 1044 ret = -EFAULT;
1290 vfree(counters); 1045 vfree(counters);
1291 up(&ip6t_mutex); 1046 xt_table_unlock(t);
1292 return ret; 1047 return ret;
1293 1048
1294 put_module: 1049 put_module:
1295 module_put(t->me); 1050 module_put(t->me);
1296 up(&ip6t_mutex); 1051 xt_table_unlock(t);
1297 free_newinfo_counters_untrans: 1052 free_newinfo_counters_untrans:
1298 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); 1053 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1299 free_newinfo_counters: 1054 free_newinfo_counters:
1300 vfree(counters); 1055 vfree(counters);
1301 free_newinfo: 1056 free_newinfo:
1302 free_table_info(newinfo); 1057 xt_free_table_info(newinfo);
1303 return ret; 1058 return ret;
1304} 1059}
1305 1060
@@ -1307,7 +1062,7 @@ do_replace(void __user *user, unsigned int len)
1307 * and everything is OK. */ 1062 * and everything is OK. */
1308static inline int 1063static inline int
1309add_counter_to_entry(struct ip6t_entry *e, 1064add_counter_to_entry(struct ip6t_entry *e,
1310 const struct ip6t_counters addme[], 1065 const struct xt_counters addme[],
1311 unsigned int *i) 1066 unsigned int *i)
1312{ 1067{
1313#if 0 1068#if 0
@@ -1329,15 +1084,16 @@ static int
1329do_add_counters(void __user *user, unsigned int len) 1084do_add_counters(void __user *user, unsigned int len)
1330{ 1085{
1331 unsigned int i; 1086 unsigned int i;
1332 struct ip6t_counters_info tmp, *paddc; 1087 struct xt_counters_info tmp, *paddc;
1333 struct ip6t_table *t; 1088 struct xt_table_info *private;
1089 struct xt_table *t;
1334 int ret = 0; 1090 int ret = 0;
1335 void *loc_cpu_entry; 1091 void *loc_cpu_entry;
1336 1092
1337 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1093 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1338 return -EFAULT; 1094 return -EFAULT;
1339 1095
1340 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) 1096 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1341 return -EINVAL; 1097 return -EINVAL;
1342 1098
1343 paddc = vmalloc(len); 1099 paddc = vmalloc(len);
@@ -1349,29 +1105,30 @@ do_add_counters(void __user *user, unsigned int len)
1349 goto free; 1105 goto free;
1350 } 1106 }
1351 1107
1352 t = find_table_lock(tmp.name); 1108 t = xt_find_table_lock(AF_INET6, tmp.name);
1353 if (!t || IS_ERR(t)) { 1109 if (!t || IS_ERR(t)) {
1354 ret = t ? PTR_ERR(t) : -ENOENT; 1110 ret = t ? PTR_ERR(t) : -ENOENT;
1355 goto free; 1111 goto free;
1356 } 1112 }
1357 1113
1358 write_lock_bh(&t->lock); 1114 write_lock_bh(&t->lock);
1359 if (t->private->number != paddc->num_counters) { 1115 private = t->private;
1116 if (private->number != paddc->num_counters) {
1360 ret = -EINVAL; 1117 ret = -EINVAL;
1361 goto unlock_up_free; 1118 goto unlock_up_free;
1362 } 1119 }
1363 1120
1364 i = 0; 1121 i = 0;
1365 /* Choose the copy that is on our node */ 1122 /* Choose the copy that is on our node */
1366 loc_cpu_entry = t->private->entries[smp_processor_id()]; 1123 loc_cpu_entry = private->entries[smp_processor_id()];
1367 IP6T_ENTRY_ITERATE(loc_cpu_entry, 1124 IP6T_ENTRY_ITERATE(loc_cpu_entry,
1368 t->private->size, 1125 private->size,
1369 add_counter_to_entry, 1126 add_counter_to_entry,
1370 paddc->counters, 1127 paddc->counters,
1371 &i); 1128 &i);
1372 unlock_up_free: 1129 unlock_up_free:
1373 write_unlock_bh(&t->lock); 1130 write_unlock_bh(&t->lock);
1374 up(&ip6t_mutex); 1131 xt_table_unlock(t);
1375 module_put(t->me); 1132 module_put(t->me);
1376 free: 1133 free:
1377 vfree(paddc); 1134 vfree(paddc);
@@ -1415,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1415 switch (cmd) { 1172 switch (cmd) {
1416 case IP6T_SO_GET_INFO: { 1173 case IP6T_SO_GET_INFO: {
1417 char name[IP6T_TABLE_MAXNAMELEN]; 1174 char name[IP6T_TABLE_MAXNAMELEN];
1418 struct ip6t_table *t; 1175 struct xt_table *t;
1419 1176
1420 if (*len != sizeof(struct ip6t_getinfo)) { 1177 if (*len != sizeof(struct ip6t_getinfo)) {
1421 duprintf("length %u != %u\n", *len, 1178 duprintf("length %u != %u\n", *len,
@@ -1430,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1430 } 1187 }
1431 name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; 1188 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1432 1189
1433 t = try_then_request_module(find_table_lock(name), 1190 t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
1434 "ip6table_%s", name); 1191 "ip6table_%s", name);
1435 if (t && !IS_ERR(t)) { 1192 if (t && !IS_ERR(t)) {
1436 struct ip6t_getinfo info; 1193 struct ip6t_getinfo info;
1194 struct xt_table_info *private = t->private;
1437 1195
1438 info.valid_hooks = t->valid_hooks; 1196 info.valid_hooks = t->valid_hooks;
1439 memcpy(info.hook_entry, t->private->hook_entry, 1197 memcpy(info.hook_entry, private->hook_entry,
1440 sizeof(info.hook_entry)); 1198 sizeof(info.hook_entry));
1441 memcpy(info.underflow, t->private->underflow, 1199 memcpy(info.underflow, private->underflow,
1442 sizeof(info.underflow)); 1200 sizeof(info.underflow));
1443 info.num_entries = t->private->number; 1201 info.num_entries = private->number;
1444 info.size = t->private->size; 1202 info.size = private->size;
1445 memcpy(info.name, name, sizeof(info.name)); 1203 memcpy(info.name, name, sizeof(info.name));
1446 1204
1447 if (copy_to_user(user, &info, *len) != 0) 1205 if (copy_to_user(user, &info, *len) != 0)
1448 ret = -EFAULT; 1206 ret = -EFAULT;
1449 else 1207 else
1450 ret = 0; 1208 ret = 0;
1451 up(&ip6t_mutex); 1209 xt_table_unlock(t);
1452 module_put(t->me); 1210 module_put(t->me);
1453 } else 1211 } else
1454 ret = t ? PTR_ERR(t) : -ENOENT; 1212 ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1475,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1475 case IP6T_SO_GET_REVISION_MATCH: 1233 case IP6T_SO_GET_REVISION_MATCH:
1476 case IP6T_SO_GET_REVISION_TARGET: { 1234 case IP6T_SO_GET_REVISION_TARGET: {
1477 struct ip6t_get_revision rev; 1235 struct ip6t_get_revision rev;
1478 int (*revfn)(const char *, u8, int *); 1236 int target;
1479 1237
1480 if (*len != sizeof(rev)) { 1238 if (*len != sizeof(rev)) {
1481 ret = -EINVAL; 1239 ret = -EINVAL;
@@ -1487,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1487 } 1245 }
1488 1246
1489 if (cmd == IP6T_SO_GET_REVISION_TARGET) 1247 if (cmd == IP6T_SO_GET_REVISION_TARGET)
1490 revfn = target_revfn; 1248 target = 1;
1491 else 1249 else
1492 revfn = match_revfn; 1250 target = 0;
1493 1251
1494 try_then_request_module(find_revision(rev.name, rev.revision, 1252 try_then_request_module(xt_find_revision(AF_INET6, rev.name,
1495 revfn, &ret), 1253 rev.revision,
1254 target, &ret),
1496 "ip6t_%s", rev.name); 1255 "ip6t_%s", rev.name);
1497 break; 1256 break;
1498 } 1257 }
@@ -1505,61 +1264,16 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1505 return ret; 1264 return ret;
1506} 1265}
1507 1266
1508/* Registration hooks for targets. */ 1267int ip6t_register_table(struct xt_table *table,
1509int
1510ip6t_register_target(struct ip6t_target *target)
1511{
1512 int ret;
1513
1514 ret = down_interruptible(&ip6t_mutex);
1515 if (ret != 0)
1516 return ret;
1517 list_add(&target->list, &ip6t_target);
1518 up(&ip6t_mutex);
1519 return ret;
1520}
1521
1522void
1523ip6t_unregister_target(struct ip6t_target *target)
1524{
1525 down(&ip6t_mutex);
1526 LIST_DELETE(&ip6t_target, target);
1527 up(&ip6t_mutex);
1528}
1529
1530int
1531ip6t_register_match(struct ip6t_match *match)
1532{
1533 int ret;
1534
1535 ret = down_interruptible(&ip6t_mutex);
1536 if (ret != 0)
1537 return ret;
1538
1539 list_add(&match->list, &ip6t_match);
1540 up(&ip6t_mutex);
1541
1542 return ret;
1543}
1544
1545void
1546ip6t_unregister_match(struct ip6t_match *match)
1547{
1548 down(&ip6t_mutex);
1549 LIST_DELETE(&ip6t_match, match);
1550 up(&ip6t_mutex);
1551}
1552
1553int ip6t_register_table(struct ip6t_table *table,
1554 const struct ip6t_replace *repl) 1268 const struct ip6t_replace *repl)
1555{ 1269{
1556 int ret; 1270 int ret;
1557 struct ip6t_table_info *newinfo; 1271 struct xt_table_info *newinfo;
1558 static struct ip6t_table_info bootstrap 1272 static struct xt_table_info bootstrap
1559 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1273 = { 0, 0, 0, { 0 }, { 0 }, { } };
1560 void *loc_cpu_entry; 1274 void *loc_cpu_entry;
1561 1275
1562 newinfo = alloc_table_info(repl->size); 1276 newinfo = xt_alloc_table_info(repl->size);
1563 if (!newinfo) 1277 if (!newinfo)
1564 return -ENOMEM; 1278 return -ENOMEM;
1565 1279
@@ -1573,244 +1287,29 @@ int ip6t_register_table(struct ip6t_table *table,
1573 repl->hook_entry, 1287 repl->hook_entry,
1574 repl->underflow); 1288 repl->underflow);
1575 if (ret != 0) { 1289 if (ret != 0) {
1576 free_table_info(newinfo); 1290 xt_free_table_info(newinfo);
1577 return ret; 1291 return ret;
1578 } 1292 }
1579 1293
1580 ret = down_interruptible(&ip6t_mutex); 1294 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1581 if (ret != 0) { 1295 xt_free_table_info(newinfo);
1582 free_table_info(newinfo);
1583 return ret; 1296 return ret;
1584 } 1297 }
1585 1298
1586 /* Don't autoload: we'd eat our tail... */ 1299 return 0;
1587 if (list_named_find(&ip6t_tables, table->name)) {
1588 ret = -EEXIST;
1589 goto free_unlock;
1590 }
1591
1592 /* Simplifies replace_table code. */
1593 table->private = &bootstrap;
1594 if (!replace_table(table, 0, newinfo, &ret))
1595 goto free_unlock;
1596
1597 duprintf("table->private->number = %u\n",
1598 table->private->number);
1599
1600 /* save number of initial entries */
1601 table->private->initial_entries = table->private->number;
1602
1603 rwlock_init(&table->lock);
1604 list_prepend(&ip6t_tables, table);
1605
1606 unlock:
1607 up(&ip6t_mutex);
1608 return ret;
1609
1610 free_unlock:
1611 free_table_info(newinfo);
1612 goto unlock;
1613} 1300}
1614 1301
1615void ip6t_unregister_table(struct ip6t_table *table) 1302void ip6t_unregister_table(struct xt_table *table)
1616{ 1303{
1304 struct xt_table_info *private;
1617 void *loc_cpu_entry; 1305 void *loc_cpu_entry;
1618 1306
1619 down(&ip6t_mutex); 1307 private = xt_unregister_table(table);
1620 LIST_DELETE(&ip6t_tables, table);
1621 up(&ip6t_mutex);
1622 1308
1623 /* Decrease module usage counts and free resources */ 1309 /* Decrease module usage counts and free resources */
1624 loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; 1310 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1625 IP6T_ENTRY_ITERATE(loc_cpu_entry, table->private->size, 1311 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1626 cleanup_entry, NULL); 1312 xt_free_table_info(private);
1627 free_table_info(table->private);
1628}
1629
1630/* Returns 1 if the port is matched by the range, 0 otherwise */
1631static inline int
1632port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
1633{
1634 int ret;
1635
1636 ret = (port >= min && port <= max) ^ invert;
1637 return ret;
1638}
1639
1640static int
1641tcp_find_option(u_int8_t option,
1642 const struct sk_buff *skb,
1643 unsigned int tcpoff,
1644 unsigned int optlen,
1645 int invert,
1646 int *hotdrop)
1647{
1648 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
1649 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
1650 unsigned int i;
1651
1652 duprintf("tcp_match: finding option\n");
1653 if (!optlen)
1654 return invert;
1655 /* If we don't have the whole header, drop packet. */
1656 op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
1657 _opt);
1658 if (op == NULL) {
1659 *hotdrop = 1;
1660 return 0;
1661 }
1662
1663 for (i = 0; i < optlen; ) {
1664 if (op[i] == option) return !invert;
1665 if (op[i] < 2) i++;
1666 else i += op[i+1]?:1;
1667 }
1668
1669 return invert;
1670}
1671
1672static int
1673tcp_match(const struct sk_buff *skb,
1674 const struct net_device *in,
1675 const struct net_device *out,
1676 const void *matchinfo,
1677 int offset,
1678 unsigned int protoff,
1679 int *hotdrop)
1680{
1681 struct tcphdr _tcph, *th;
1682 const struct ip6t_tcp *tcpinfo = matchinfo;
1683
1684 if (offset) {
1685 /* To quote Alan:
1686
1687 Don't allow a fragment of TCP 8 bytes in. Nobody normal
1688 causes this. Its a cracker trying to break in by doing a
1689 flag overwrite to pass the direction checks.
1690 */
1691 if (offset == 1) {
1692 duprintf("Dropping evil TCP offset=1 frag.\n");
1693 *hotdrop = 1;
1694 }
1695 /* Must not be a fragment. */
1696 return 0;
1697 }
1698
1699#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
1700
1701 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
1702 if (th == NULL) {
1703 /* We've been asked to examine this packet, and we
1704 can't. Hence, no choice but to drop. */
1705 duprintf("Dropping evil TCP offset=0 tinygram.\n");
1706 *hotdrop = 1;
1707 return 0;
1708 }
1709
1710 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
1711 ntohs(th->source),
1712 !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
1713 return 0;
1714 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
1715 ntohs(th->dest),
1716 !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
1717 return 0;
1718 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
1719 == tcpinfo->flg_cmp,
1720 IP6T_TCP_INV_FLAGS))
1721 return 0;
1722 if (tcpinfo->option) {
1723 if (th->doff * 4 < sizeof(_tcph)) {
1724 *hotdrop = 1;
1725 return 0;
1726 }
1727 if (!tcp_find_option(tcpinfo->option, skb, protoff,
1728 th->doff*4 - sizeof(*th),
1729 tcpinfo->invflags & IP6T_TCP_INV_OPTION,
1730 hotdrop))
1731 return 0;
1732 }
1733 return 1;
1734}
1735
1736/* Called when user tries to insert an entry of this type. */
1737static int
1738tcp_checkentry(const char *tablename,
1739 const struct ip6t_ip6 *ipv6,
1740 void *matchinfo,
1741 unsigned int matchsize,
1742 unsigned int hook_mask)
1743{
1744 const struct ip6t_tcp *tcpinfo = matchinfo;
1745
1746 /* Must specify proto == TCP, and no unknown invflags */
1747 return ipv6->proto == IPPROTO_TCP
1748 && !(ipv6->invflags & IP6T_INV_PROTO)
1749 && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp))
1750 && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK);
1751}
1752
1753static int
1754udp_match(const struct sk_buff *skb,
1755 const struct net_device *in,
1756 const struct net_device *out,
1757 const void *matchinfo,
1758 int offset,
1759 unsigned int protoff,
1760 int *hotdrop)
1761{
1762 struct udphdr _udph, *uh;
1763 const struct ip6t_udp *udpinfo = matchinfo;
1764
1765 /* Must not be a fragment. */
1766 if (offset)
1767 return 0;
1768
1769 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
1770 if (uh == NULL) {
1771 /* We've been asked to examine this packet, and we
1772 can't. Hence, no choice but to drop. */
1773 duprintf("Dropping evil UDP tinygram.\n");
1774 *hotdrop = 1;
1775 return 0;
1776 }
1777
1778 return port_match(udpinfo->spts[0], udpinfo->spts[1],
1779 ntohs(uh->source),
1780 !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
1781 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
1782 ntohs(uh->dest),
1783 !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
1784}
1785
1786/* Called when user tries to insert an entry of this type. */
1787static int
1788udp_checkentry(const char *tablename,
1789 const struct ip6t_ip6 *ipv6,
1790 void *matchinfo,
1791 unsigned int matchinfosize,
1792 unsigned int hook_mask)
1793{
1794 const struct ip6t_udp *udpinfo = matchinfo;
1795
1796 /* Must specify proto == UDP, and no unknown invflags */
1797 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) {
1798 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
1799 IPPROTO_UDP);
1800 return 0;
1801 }
1802 if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) {
1803 duprintf("ip6t_udp: matchsize %u != %u\n",
1804 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp)));
1805 return 0;
1806 }
1807 if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) {
1808 duprintf("ip6t_udp: unknown flags %X\n",
1809 udpinfo->invflags);
1810 return 0;
1811 }
1812
1813 return 1;
1814} 1313}
1815 1314
1816/* Returns 1 if the type and code is matched by the range, 0 otherwise */ 1315/* Returns 1 if the type and code is matched by the range, 0 otherwise */
@@ -1858,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb,
1858/* Called when user tries to insert an entry of this type. */ 1357/* Called when user tries to insert an entry of this type. */
1859static int 1358static int
1860icmp6_checkentry(const char *tablename, 1359icmp6_checkentry(const char *tablename,
1861 const struct ip6t_ip6 *ipv6, 1360 const void *entry,
1862 void *matchinfo, 1361 void *matchinfo,
1863 unsigned int matchsize, 1362 unsigned int matchsize,
1864 unsigned int hook_mask) 1363 unsigned int hook_mask)
1865{ 1364{
1365 const struct ip6t_ip6 *ipv6 = entry;
1866 const struct ip6t_icmp *icmpinfo = matchinfo; 1366 const struct ip6t_icmp *icmpinfo = matchinfo;
1867 1367
1868 /* Must specify proto == ICMP, and no unknown invflags */ 1368 /* Must specify proto == ICMP, and no unknown invflags */
@@ -1892,164 +1392,42 @@ static struct nf_sockopt_ops ip6t_sockopts = {
1892 .get = do_ip6t_get_ctl, 1392 .get = do_ip6t_get_ctl,
1893}; 1393};
1894 1394
1895static struct ip6t_match tcp_matchstruct = {
1896 .name = "tcp",
1897 .match = &tcp_match,
1898 .checkentry = &tcp_checkentry,
1899};
1900
1901static struct ip6t_match udp_matchstruct = {
1902 .name = "udp",
1903 .match = &udp_match,
1904 .checkentry = &udp_checkentry,
1905};
1906
1907static struct ip6t_match icmp6_matchstruct = { 1395static struct ip6t_match icmp6_matchstruct = {
1908 .name = "icmp6", 1396 .name = "icmp6",
1909 .match = &icmp6_match, 1397 .match = &icmp6_match,
1910 .checkentry = &icmp6_checkentry, 1398 .checkentry = &icmp6_checkentry,
1911}; 1399};
1912 1400
1913#ifdef CONFIG_PROC_FS
1914static inline int print_name(const char *i,
1915 off_t start_offset, char *buffer, int length,
1916 off_t *pos, unsigned int *count)
1917{
1918 if ((*count)++ >= start_offset) {
1919 unsigned int namelen;
1920
1921 namelen = sprintf(buffer + *pos, "%s\n",
1922 i + sizeof(struct list_head));
1923 if (*pos + namelen > length) {
1924 /* Stop iterating */
1925 return 1;
1926 }
1927 *pos += namelen;
1928 }
1929 return 0;
1930}
1931
1932static inline int print_target(const struct ip6t_target *t,
1933 off_t start_offset, char *buffer, int length,
1934 off_t *pos, unsigned int *count)
1935{
1936 if (t == &ip6t_standard_target || t == &ip6t_error_target)
1937 return 0;
1938 return print_name((char *)t, start_offset, buffer, length, pos, count);
1939}
1940
1941static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length)
1942{
1943 off_t pos = 0;
1944 unsigned int count = 0;
1945
1946 if (down_interruptible(&ip6t_mutex) != 0)
1947 return 0;
1948
1949 LIST_FIND(&ip6t_tables, print_name, char *,
1950 offset, buffer, length, &pos, &count);
1951
1952 up(&ip6t_mutex);
1953
1954 /* `start' hack - see fs/proc/generic.c line ~105 */
1955 *start=(char *)((unsigned long)count-offset);
1956 return pos;
1957}
1958
1959static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length)
1960{
1961 off_t pos = 0;
1962 unsigned int count = 0;
1963
1964 if (down_interruptible(&ip6t_mutex) != 0)
1965 return 0;
1966
1967 LIST_FIND(&ip6t_target, print_target, struct ip6t_target *,
1968 offset, buffer, length, &pos, &count);
1969
1970 up(&ip6t_mutex);
1971
1972 *start = (char *)((unsigned long)count - offset);
1973 return pos;
1974}
1975
1976static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length)
1977{
1978 off_t pos = 0;
1979 unsigned int count = 0;
1980
1981 if (down_interruptible(&ip6t_mutex) != 0)
1982 return 0;
1983
1984 LIST_FIND(&ip6t_match, print_name, char *,
1985 offset, buffer, length, &pos, &count);
1986
1987 up(&ip6t_mutex);
1988
1989 *start = (char *)((unsigned long)count - offset);
1990 return pos;
1991}
1992
1993static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
1994{ { "ip6_tables_names", ip6t_get_tables },
1995 { "ip6_tables_targets", ip6t_get_targets },
1996 { "ip6_tables_matches", ip6t_get_matches },
1997 { NULL, NULL} };
1998#endif /*CONFIG_PROC_FS*/
1999
2000static int __init init(void) 1401static int __init init(void)
2001{ 1402{
2002 int ret; 1403 int ret;
2003 1404
1405 xt_proto_init(AF_INET6);
1406
2004 /* Noone else will be downing sem now, so we won't sleep */ 1407 /* Noone else will be downing sem now, so we won't sleep */
2005 down(&ip6t_mutex); 1408 xt_register_target(AF_INET6, &ip6t_standard_target);
2006 list_append(&ip6t_target, &ip6t_standard_target); 1409 xt_register_target(AF_INET6, &ip6t_error_target);
2007 list_append(&ip6t_target, &ip6t_error_target); 1410 xt_register_match(AF_INET6, &icmp6_matchstruct);
2008 list_append(&ip6t_match, &tcp_matchstruct);
2009 list_append(&ip6t_match, &udp_matchstruct);
2010 list_append(&ip6t_match, &icmp6_matchstruct);
2011 up(&ip6t_mutex);
2012 1411
2013 /* Register setsockopt */ 1412 /* Register setsockopt */
2014 ret = nf_register_sockopt(&ip6t_sockopts); 1413 ret = nf_register_sockopt(&ip6t_sockopts);
2015 if (ret < 0) { 1414 if (ret < 0) {
2016 duprintf("Unable to register sockopts.\n"); 1415 duprintf("Unable to register sockopts.\n");
1416 xt_proto_fini(AF_INET6);
2017 return ret; 1417 return ret;
2018 } 1418 }
2019 1419
2020#ifdef CONFIG_PROC_FS 1420 printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
2021 {
2022 struct proc_dir_entry *proc;
2023 int i;
2024
2025 for (i = 0; ip6t_proc_entry[i].name; i++) {
2026 proc = proc_net_create(ip6t_proc_entry[i].name, 0,
2027 ip6t_proc_entry[i].get_info);
2028 if (!proc) {
2029 while (--i >= 0)
2030 proc_net_remove(ip6t_proc_entry[i].name);
2031 nf_unregister_sockopt(&ip6t_sockopts);
2032 return -ENOMEM;
2033 }
2034 proc->owner = THIS_MODULE;
2035 }
2036 }
2037#endif
2038
2039 printk("ip6_tables: (C) 2000-2002 Netfilter core team\n");
2040 return 0; 1421 return 0;
2041} 1422}
2042 1423
2043static void __exit fini(void) 1424static void __exit fini(void)
2044{ 1425{
2045 nf_unregister_sockopt(&ip6t_sockopts); 1426 nf_unregister_sockopt(&ip6t_sockopts);
2046#ifdef CONFIG_PROC_FS 1427 xt_unregister_match(AF_INET6, &icmp6_matchstruct);
2047 { 1428 xt_unregister_target(AF_INET6, &ip6t_error_target);
2048 int i; 1429 xt_unregister_target(AF_INET6, &ip6t_standard_target);
2049 for (i = 0; ip6t_proc_entry[i].name; i++) 1430 xt_proto_fini(AF_INET6);
2050 proc_net_remove(ip6t_proc_entry[i].name);
2051 }
2052#endif
2053} 1431}
2054 1432
2055/* 1433/*
@@ -2128,10 +1506,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2128EXPORT_SYMBOL(ip6t_register_table); 1506EXPORT_SYMBOL(ip6t_register_table);
2129EXPORT_SYMBOL(ip6t_unregister_table); 1507EXPORT_SYMBOL(ip6t_unregister_table);
2130EXPORT_SYMBOL(ip6t_do_table); 1508EXPORT_SYMBOL(ip6t_do_table);
2131EXPORT_SYMBOL(ip6t_register_match);
2132EXPORT_SYMBOL(ip6t_unregister_match);
2133EXPORT_SYMBOL(ip6t_register_target);
2134EXPORT_SYMBOL(ip6t_unregister_target);
2135EXPORT_SYMBOL(ip6t_ext_hdr); 1509EXPORT_SYMBOL(ip6t_ext_hdr);
2136EXPORT_SYMBOL(ipv6_find_hdr); 1510EXPORT_SYMBOL(ipv6_find_hdr);
2137EXPORT_SYMBOL(ip6_masked_addrcmp); 1511EXPORT_SYMBOL(ip6_masked_addrcmp);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 8f5549b72720..306200c35057 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
62} 62}
63 63
64static int ip6t_hl_checkentry(const char *tablename, 64static int ip6t_hl_checkentry(const char *tablename,
65 const struct ip6t_entry *e, 65 const void *entry,
66 void *targinfo, 66 void *targinfo,
67 unsigned int targinfosize, 67 unsigned int targinfosize,
68 unsigned int hook_mask) 68 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index ae4653bfd654..fc19d8a4ca68 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -444,7 +444,7 @@ ip6t_log_target(struct sk_buff **pskb,
444 444
445 445
446static int ip6t_log_checkentry(const char *tablename, 446static int ip6t_log_checkentry(const char *tablename,
447 const struct ip6t_entry *e, 447 const void *entry,
448 void *targinfo, 448 void *targinfo,
449 unsigned int targinfosize, 449 unsigned int targinfosize,
450 unsigned int hook_mask) 450 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
deleted file mode 100644
index eab8fb864ee0..000000000000
--- a/net/ipv6/netfilter/ip6t_MARK.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* This is a module which is used for setting the NFMARK field of an skb. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/ip.h>
13#include <net/checksum.h>
14
15#include <linux/netfilter_ipv6/ip6_tables.h>
16#include <linux/netfilter_ipv6/ip6t_MARK.h>
17
18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
20
21static unsigned int
22target(struct sk_buff **pskb,
23 const struct net_device *in,
24 const struct net_device *out,
25 unsigned int hooknum,
26 const void *targinfo,
27 void *userinfo)
28{
29 const struct ip6t_mark_target_info *markinfo = targinfo;
30
31 if((*pskb)->nfmark != markinfo->mark)
32 (*pskb)->nfmark = markinfo->mark;
33
34 return IP6T_CONTINUE;
35}
36
37static int
38checkentry(const char *tablename,
39 const struct ip6t_entry *e,
40 void *targinfo,
41 unsigned int targinfosize,
42 unsigned int hook_mask)
43{
44 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) {
45 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
46 targinfosize,
47 IP6T_ALIGN(sizeof(struct ip6t_mark_target_info)));
48 return 0;
49 }
50
51 if (strcmp(tablename, "mangle") != 0) {
52 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
53 return 0;
54 }
55
56 return 1;
57}
58
59static struct ip6t_target ip6t_mark_reg = {
60 .name = "MARK",
61 .target = target,
62 .checkentry = checkentry,
63 .me = THIS_MODULE
64};
65
66static int __init init(void)
67{
68 printk(KERN_DEBUG "registering ipv6 mark target\n");
69 if (ip6t_register_target(&ip6t_mark_reg))
70 return -EINVAL;
71
72 return 0;
73}
74
75static void __exit fini(void)
76{
77 ip6t_unregister_target(&ip6t_mark_reg);
78}
79
80module_init(init);
81module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c
deleted file mode 100644
index c6e3730e7409..000000000000
--- a/net/ipv6/netfilter/ip6t_NFQUEUE.c
+++ /dev/null
@@ -1,70 +0,0 @@
1/* ip6tables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_ipv6/ip6_tables.h>
16#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
17
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables NFQUEUE target");
20MODULE_LICENSE("GPL");
21
22static unsigned int
23target(struct sk_buff **pskb,
24 const struct net_device *in,
25 const struct net_device *out,
26 unsigned int hooknum,
27 const void *targinfo,
28 void *userinfo)
29{
30 const struct ipt_NFQ_info *tinfo = targinfo;
31
32 return NF_QUEUE_NR(tinfo->queuenum);
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_entry *e,
38 void *targinfo,
39 unsigned int targinfosize,
40 unsigned int hook_mask)
41{
42 if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) {
43 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
44 targinfosize,
45 IP6T_ALIGN(sizeof(struct ipt_NFQ_info)));
46 return 0;
47 }
48
49 return 1;
50}
51
52static struct ip6t_target ipt_NFQ_reg = {
53 .name = "NFQUEUE",
54 .target = target,
55 .checkentry = checkentry,
56 .me = THIS_MODULE,
57};
58
59static int __init init(void)
60{
61 return ip6t_register_target(&ipt_NFQ_reg);
62}
63
64static void __exit fini(void)
65{
66 ip6t_unregister_target(&ipt_NFQ_reg);
67}
68
69module_init(init);
70module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index b03e87adca93..c745717b4ce2 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb,
218} 218}
219 219
220static int check(const char *tablename, 220static int check(const char *tablename,
221 const struct ip6t_entry *e, 221 const void *entry,
222 void *targinfo, 222 void *targinfo,
223 unsigned int targinfosize, 223 unsigned int targinfosize,
224 unsigned int hook_mask) 224 unsigned int hook_mask)
225{ 225{
226 const struct ip6t_reject_info *rejinfo = targinfo; 226 const struct ip6t_reject_info *rejinfo = targinfo;
227 const struct ip6t_entry *e = entry;
227 228
228 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { 229 if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
229 DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); 230 DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index f5c1a7ff4a1f..219a30365dff 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -98,7 +98,7 @@ match(const struct sk_buff *skb,
98/* Called when user tries to insert an entry of this type. */ 98/* Called when user tries to insert an entry of this type. */
99static int 99static int
100checkentry(const char *tablename, 100checkentry(const char *tablename,
101 const struct ip6t_ip6 *ip, 101 const void *entry,
102 void *matchinfo, 102 void *matchinfo,
103 unsigned int matchinfosize, 103 unsigned int matchinfosize,
104 unsigned int hook_mask) 104 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index 48cf5f9efc95..80fe82669ce2 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb,
178/* Called when user tries to insert an entry of this type. */ 178/* Called when user tries to insert an entry of this type. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(const char *tablename,
181 const struct ip6t_ip6 *ip, 181 const void *info,
182 void *matchinfo, 182 void *matchinfo,
183 unsigned int matchinfosize, 183 unsigned int matchinfosize,
184 unsigned int hook_mask) 184 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index e1828f6d0a40..724285df8711 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -76,7 +76,7 @@ match(const struct sk_buff *skb,
76/* Called when user tries to insert an entry of this type. */ 76/* Called when user tries to insert an entry of this type. */
77static int 77static int
78checkentry(const char *tablename, 78checkentry(const char *tablename,
79 const struct ip6t_ip6 *ip, 79 const void *ip,
80 void *matchinfo, 80 void *matchinfo,
81 unsigned int matchinfosize, 81 unsigned int matchinfosize,
82 unsigned int hook_mask) 82 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 616c2cbcd54d..ddf5f571909c 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -62,7 +62,7 @@ match(const struct sk_buff *skb,
62 62
63static int 63static int
64ip6t_eui64_checkentry(const char *tablename, 64ip6t_eui64_checkentry(const char *tablename,
65 const struct ip6t_ip6 *ip, 65 const void *ip,
66 void *matchinfo, 66 void *matchinfo,
67 unsigned int matchsize, 67 unsigned int matchsize,
68 unsigned int hook_mask) 68 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index d1549b268669..a9964b946ed5 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -115,7 +115,7 @@ match(const struct sk_buff *skb,
115/* Called when user tries to insert an entry of this type. */ 115/* Called when user tries to insert an entry of this type. */
116static int 116static int
117checkentry(const char *tablename, 117checkentry(const char *tablename,
118 const struct ip6t_ip6 *ip, 118 const void *ip,
119 void *matchinfo, 119 void *matchinfo,
120 unsigned int matchinfosize, 120 unsigned int matchinfosize,
121 unsigned int hook_mask) 121 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index e3bc8e2700e7..ed8ded18bbd4 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb,
178/* Called when user tries to insert an entry of this type. */ 178/* Called when user tries to insert an entry of this type. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(const char *tablename,
181 const struct ip6t_ip6 *ip, 181 const void *entry,
182 void *matchinfo, 182 void *matchinfo,
183 unsigned int matchinfosize, 183 unsigned int matchinfosize,
184 unsigned int hook_mask) 184 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 0beaff5471dd..c5d9079f2d9d 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
48 return 0; 48 return 0;
49} 49}
50 50
51static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, 51static int checkentry(const char *tablename, const void *entry,
52 void *matchinfo, unsigned int matchsize, 52 void *matchinfo, unsigned int matchsize,
53 unsigned int hook_mask) 53 unsigned int hook_mask)
54{ 54{
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 32e67f05845b..fda1ceaf5a29 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb,
124 124
125static int 125static int
126ipv6header_checkentry(const char *tablename, 126ipv6header_checkentry(const char *tablename,
127 const struct ip6t_ip6 *ip, 127 const void *ip,
128 void *matchinfo, 128 void *matchinfo,
129 unsigned int matchsize, 129 unsigned int matchsize,
130 unsigned int hook_mask) 130 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c
deleted file mode 100644
index e0537d3811d5..000000000000
--- a/net/ipv6/netfilter/ip6t_length.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/* Length Match - IPv6 Port */
2
3/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/netfilter_ipv6/ip6t_length.h>
14#include <linux/netfilter_ipv6/ip6_tables.h>
15
16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
18MODULE_DESCRIPTION("IPv6 packet length match");
19
20static int
21match(const struct sk_buff *skb,
22 const struct net_device *in,
23 const struct net_device *out,
24 const void *matchinfo,
25 int offset,
26 unsigned int protoff,
27 int *hotdrop)
28{
29 const struct ip6t_length_info *info = matchinfo;
30 u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
31
32 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_ip6 *ip,
38 void *matchinfo,
39 unsigned int matchsize,
40 unsigned int hook_mask)
41{
42 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info)))
43 return 0;
44
45 return 1;
46}
47
48static struct ip6t_match length_match = {
49 .name = "length",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&length_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&length_match);
63}
64
65module_init(init);
66module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c
deleted file mode 100644
index fb782f610be2..000000000000
--- a/net/ipv6/netfilter/ip6t_limit.c
+++ /dev/null
@@ -1,147 +0,0 @@
1/* Kernel module to control the rate
2 *
3 * 2 September 1999: Changed from the target RATE to the match
4 * `limit', removed logging. Did I mention that
5 * Alexey is a fucking genius?
6 * Rusty Russell (rusty@rustcorp.com.au). */
7
8/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
9 * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/module.h>
17#include <linux/skbuff.h>
18#include <linux/spinlock.h>
19#include <linux/interrupt.h>
20
21#include <linux/netfilter_ipv6/ip6_tables.h>
22#include <linux/netfilter_ipv6/ip6t_limit.h>
23
24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_DESCRIPTION("rate limiting within ip6tables");
27
28/* The algorithm used is the Simple Token Bucket Filter (TBF)
29 * see net/sched/sch_tbf.c in the linux source tree
30 */
31
32static DEFINE_SPINLOCK(limit_lock);
33
34/* Rusty: This is my (non-mathematically-inclined) understanding of
35 this algorithm. The `average rate' in jiffies becomes your initial
36 amount of credit `credit' and the most credit you can ever have
37 `credit_cap'. The `peak rate' becomes the cost of passing the
38 test, `cost'.
39
40 `prev' tracks the last packet hit: you gain one credit per jiffy.
41 If you get credit balance more than this, the extra credit is
42 discarded. Every time the match passes, you lose `cost' credits;
43 if you don't have that many, the test fails.
44
45 See Alexey's formal explanation in net/sched/sch_tbf.c.
46
47 To avoid underflow, we multiply by 128 (ie. you get 128 credits per
48 jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds
49 at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes
50 per second at 100HZ. */
51
52#define CREDITS_PER_JIFFY 128
53
54static int
55ip6t_limit_match(const struct sk_buff *skb,
56 const struct net_device *in,
57 const struct net_device *out,
58 const void *matchinfo,
59 int offset,
60 unsigned int protoff,
61 int *hotdrop)
62{
63 struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master;
64 unsigned long now = jiffies;
65
66 spin_lock_bh(&limit_lock);
67 r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY;
68 if (r->credit > r->credit_cap)
69 r->credit = r->credit_cap;
70
71 if (r->credit >= r->cost) {
72 /* We're not limited. */
73 r->credit -= r->cost;
74 spin_unlock_bh(&limit_lock);
75 return 1;
76 }
77
78 spin_unlock_bh(&limit_lock);
79 return 0;
80}
81
82/* Precision saver. */
83static u_int32_t
84user2credits(u_int32_t user)
85{
86 /* If multiplying would overflow... */
87 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
88 /* Divide first. */
89 return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
90
91 return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE;
92}
93
94static int
95ip6t_limit_checkentry(const char *tablename,
96 const struct ip6t_ip6 *ip,
97 void *matchinfo,
98 unsigned int matchsize,
99 unsigned int hook_mask)
100{
101 struct ip6t_rateinfo *r = matchinfo;
102
103 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo)))
104 return 0;
105
106 /* Check for overflow. */
107 if (r->burst == 0
108 || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
109 printk("Call rusty: overflow in ip6t_limit: %u/%u\n",
110 r->avg, r->burst);
111 return 0;
112 }
113
114 /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies *
115 128. */
116 r->prev = jiffies;
117 r->credit = user2credits(r->avg * r->burst); /* Credits full. */
118 r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
119 r->cost = user2credits(r->avg);
120
121 /* For SMP, we only want to use one set of counters. */
122 r->master = r;
123
124 return 1;
125}
126
127static struct ip6t_match ip6t_limit_reg = {
128 .name = "limit",
129 .match = ip6t_limit_match,
130 .checkentry = ip6t_limit_checkentry,
131 .me = THIS_MODULE,
132};
133
134static int __init init(void)
135{
136 if (ip6t_register_match(&ip6t_limit_reg))
137 return -EINVAL;
138 return 0;
139}
140
141static void __exit fini(void)
142{
143 ip6t_unregister_match(&ip6t_limit_reg);
144}
145
146module_init(init);
147module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
deleted file mode 100644
index c848152315bc..000000000000
--- a/net/ipv6/netfilter/ip6t_mac.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* Kernel module to match MAC address parameters. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/if_ether.h>
14#include <linux/etherdevice.h>
15
16#include <linux/netfilter_ipv6/ip6t_mac.h>
17#include <linux/netfilter_ipv6/ip6_tables.h>
18
19MODULE_LICENSE("GPL");
20MODULE_DESCRIPTION("MAC address matching module for IPv6");
21MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>");
22
23static int
24match(const struct sk_buff *skb,
25 const struct net_device *in,
26 const struct net_device *out,
27 const void *matchinfo,
28 int offset,
29 unsigned int protoff,
30 int *hotdrop)
31{
32 const struct ip6t_mac_info *info = matchinfo;
33
34 /* Is mac pointer valid? */
35 return (skb->mac.raw >= skb->head
36 && (skb->mac.raw + ETH_HLEN) <= skb->data
37 /* If so, compare... */
38 && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
39 ^ info->invert));
40}
41
42static int
43ip6t_mac_checkentry(const char *tablename,
44 const struct ip6t_ip6 *ip,
45 void *matchinfo,
46 unsigned int matchsize,
47 unsigned int hook_mask)
48{
49 if (hook_mask
50 & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN)
51 | (1 << NF_IP6_FORWARD))) {
52 printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or"
53 " FORWARD\n");
54 return 0;
55 }
56
57 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info)))
58 return 0;
59
60 return 1;
61}
62
63static struct ip6t_match mac_match = {
64 .name = "mac",
65 .match = &match,
66 .checkentry = &ip6t_mac_checkentry,
67 .me = THIS_MODULE,
68};
69
70static int __init init(void)
71{
72 return ip6t_register_match(&mac_match);
73}
74
75static void __exit fini(void)
76{
77 ip6t_unregister_match(&mac_match);
78}
79
80module_init(init);
81module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c
deleted file mode 100644
index affc3de364fc..000000000000
--- a/net/ipv6/netfilter/ip6t_mark.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/* Kernel module to match NFMARK values. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter_ipv6/ip6t_mark.h>
15#include <linux/netfilter_ipv6/ip6_tables.h>
16
17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables mark match");
20
21static int
22match(const struct sk_buff *skb,
23 const struct net_device *in,
24 const struct net_device *out,
25 const void *matchinfo,
26 int offset,
27 unsigned int protoff,
28 int *hotdrop)
29{
30 const struct ip6t_mark_info *info = matchinfo;
31
32 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
33}
34
35static int
36checkentry(const char *tablename,
37 const struct ip6t_ip6 *ip,
38 void *matchinfo,
39 unsigned int matchsize,
40 unsigned int hook_mask)
41{
42 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info)))
43 return 0;
44
45 return 1;
46}
47
48static struct ip6t_match mark_match = {
49 .name = "mark",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&mark_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&mark_match);
63}
64
65module_init(init);
66module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 6e3246153fa3..49f7829dfbc2 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -84,11 +84,12 @@ match(const struct sk_buff *skb,
84/* Called when user tries to insert an entry of this type. */ 84/* Called when user tries to insert an entry of this type. */
85static int 85static int
86checkentry(const char *tablename, 86checkentry(const char *tablename,
87 const struct ip6t_ip6 *ip, 87 const void *info,
88 void *matchinfo, 88 void *matchinfo,
89 unsigned int matchsize, 89 unsigned int matchsize,
90 unsigned int hook_mask) 90 unsigned int hook_mask)
91{ 91{
92 const struct ip6t_ip6 *ip = info;
92 const struct ip6t_multiport *multiinfo = matchinfo; 93 const struct ip6t_multiport *multiinfo = matchinfo;
93 94
94 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) 95 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport)))
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 4de4cdad4b7d..5409b375b512 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -53,7 +53,7 @@ match(const struct sk_buff *skb,
53 53
54static int 54static int
55checkentry(const char *tablename, 55checkentry(const char *tablename,
56 const struct ip6t_ip6 *ip, 56 const void *ip,
57 void *matchinfo, 57 void *matchinfo,
58 unsigned int matchsize, 58 unsigned int matchsize,
59 unsigned int hook_mask) 59 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/ipv6/netfilter/ip6t_physdev.c
deleted file mode 100644
index 71515c86ece1..000000000000
--- a/net/ipv6/netfilter/ip6t_physdev.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/* Kernel module to match the bridge port in and
2 * out device for IP packets coming into contact with a bridge. */
3
4/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/netfilter_ipv6/ip6t_physdev.h>
14#include <linux/netfilter_ipv6/ip6_tables.h>
15#include <linux/netfilter_bridge.h>
16#define MATCH 1
17#define NOMATCH 0
18
19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
21MODULE_DESCRIPTION("iptables bridge physical device match module");
22
23static int
24match(const struct sk_buff *skb,
25 const struct net_device *in,
26 const struct net_device *out,
27 const void *matchinfo,
28 int offset,
29 unsigned int protoff,
30 int *hotdrop)
31{
32 int i;
33 static const char nulldevname[IFNAMSIZ];
34 const struct ip6t_physdev_info *info = matchinfo;
35 unsigned int ret;
36 const char *indev, *outdev;
37 struct nf_bridge_info *nf_bridge;
38
39 /* Not a bridged IP packet or no info available yet:
40 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
41 * the destination device will be a bridge. */
42 if (!(nf_bridge = skb->nf_bridge)) {
43 /* Return MATCH if the invert flags of the used options are on */
44 if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
45 !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))
46 return NOMATCH;
47 if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) &&
48 !(info->invert & IP6T_PHYSDEV_OP_ISIN))
49 return NOMATCH;
50 if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) &&
51 !(info->invert & IP6T_PHYSDEV_OP_ISOUT))
52 return NOMATCH;
53 if ((info->bitmask & IP6T_PHYSDEV_OP_IN) &&
54 !(info->invert & IP6T_PHYSDEV_OP_IN))
55 return NOMATCH;
56 if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) &&
57 !(info->invert & IP6T_PHYSDEV_OP_OUT))
58 return NOMATCH;
59 return MATCH;
60 }
61
62 /* This only makes sense in the FORWARD and POSTROUTING chains */
63 if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
64 (!!(nf_bridge->mask & BRNF_BRIDGED) ^
65 !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)))
66 return NOMATCH;
67
68 if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN &&
69 (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) ||
70 (info->bitmask & IP6T_PHYSDEV_OP_ISOUT &&
71 (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT))))
72 return NOMATCH;
73
74 if (!(info->bitmask & IP6T_PHYSDEV_OP_IN))
75 goto match_outdev;
76 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
77 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
78 ret |= (((const unsigned int *)indev)[i]
79 ^ ((const unsigned int *)info->physindev)[i])
80 & ((const unsigned int *)info->in_mask)[i];
81 }
82
83 if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN))
84 return NOMATCH;
85
86match_outdev:
87 if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT))
88 return MATCH;
89 outdev = nf_bridge->physoutdev ?
90 nf_bridge->physoutdev->name : nulldevname;
91 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
92 ret |= (((const unsigned int *)outdev)[i]
93 ^ ((const unsigned int *)info->physoutdev)[i])
94 & ((const unsigned int *)info->out_mask)[i];
95 }
96
97 return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT);
98}
99
100static int
101checkentry(const char *tablename,
102 const struct ip6t_ip6 *ip,
103 void *matchinfo,
104 unsigned int matchsize,
105 unsigned int hook_mask)
106{
107 const struct ip6t_physdev_info *info = matchinfo;
108
109 if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info)))
110 return 0;
111 if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) ||
112 info->bitmask & ~IP6T_PHYSDEV_OP_MASK)
113 return 0;
114 return 1;
115}
116
117static struct ip6t_match physdev_match = {
118 .name = "physdev",
119 .match = &match,
120 .checkentry = &checkentry,
121 .me = THIS_MODULE,
122};
123
124static int __init init(void)
125{
126 return ip6t_register_match(&physdev_match);
127}
128
129static void __exit fini(void)
130{
131 ip6t_unregister_match(&physdev_match);
132}
133
134module_init(init);
135module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index c1e770e45543..8465b4375855 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -183,7 +183,7 @@ match(const struct sk_buff *skb,
183/* Called when user tries to insert an entry of this type. */ 183/* Called when user tries to insert an entry of this type. */
184static int 184static int
185checkentry(const char *tablename, 185checkentry(const char *tablename,
186 const struct ip6t_ip6 *ip, 186 const void *entry,
187 void *matchinfo, 187 void *matchinfo,
188 unsigned int matchinfosize, 188 unsigned int matchinfosize,
189 unsigned int hook_mask) 189 unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 4c0028671c20..ce4a968e1f70 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = {
97 .valid_hooks = FILTER_VALID_HOOKS, 97 .valid_hooks = FILTER_VALID_HOOKS,
98 .lock = RW_LOCK_UNLOCKED, 98 .lock = RW_LOCK_UNLOCKED,
99 .me = THIS_MODULE, 99 .me = THIS_MODULE,
100 .af = AF_INET6,
100}; 101};
101 102
102/* The work comes in here from netfilter.c. */ 103/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 85c1e6eada19..30a4627e000d 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = {
127 .valid_hooks = MANGLE_VALID_HOOKS, 127 .valid_hooks = MANGLE_VALID_HOOKS,
128 .lock = RW_LOCK_UNLOCKED, 128 .lock = RW_LOCK_UNLOCKED,
129 .me = THIS_MODULE, 129 .me = THIS_MODULE,
130 .af = AF_INET6,
130}; 131};
131 132
132/* The work comes in here from netfilter.c. */ 133/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index c2982efd14af..db28ba3855e2 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -106,11 +106,12 @@ static struct
106 } 106 }
107}; 107};
108 108
109static struct ip6t_table packet_raw = { 109static struct xt_table packet_raw = {
110 .name = "raw", 110 .name = "raw",
111 .valid_hooks = RAW_VALID_HOOKS, 111 .valid_hooks = RAW_VALID_HOOKS,
112 .lock = RW_LOCK_UNLOCKED, 112 .lock = RW_LOCK_UNLOCKED,
113 .me = THIS_MODULE 113 .me = THIS_MODULE,
114 .af = AF_INET6,
114}; 115};
115 116
116/* The work comes in here from netfilter.c. */ 117/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index e57d6fc9957a..92ad53d8f8c3 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -584,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
584 584
585static int __init init(void) 585static int __init init(void)
586{ 586{
587 need_nf_conntrack(); 587 need_conntrack();
588 return init_or_cleanup(1); 588 return init_or_cleanup(1);
589} 589}
590 590
@@ -595,9 +595,3 @@ static void __exit fini(void)
595 595
596module_init(init); 596module_init(init);
597module_exit(fini); 597module_exit(fini);
598
599void need_ip6_conntrack(void)
600{
601}
602
603EXPORT_SYMBOL(need_ip6_conntrack);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index f3e5ffbd592f..84ef9a13108d 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb
70 70
71struct nf_ct_frag6_queue 71struct nf_ct_frag6_queue
72{ 72{
73 struct nf_ct_frag6_queue *next; 73 struct hlist_node list;
74 struct list_head lru_list; /* lru list member */ 74 struct list_head lru_list; /* lru list member */
75 75
76 __u32 id; /* fragment id */ 76 __u32 id; /* fragment id */
77 struct in6_addr saddr; 77 struct in6_addr saddr;
@@ -90,14 +90,13 @@ struct nf_ct_frag6_queue
90#define FIRST_IN 2 90#define FIRST_IN 2
91#define LAST_IN 1 91#define LAST_IN 1
92 __u16 nhoffset; 92 __u16 nhoffset;
93 struct nf_ct_frag6_queue **pprev;
94}; 93};
95 94
96/* Hash table. */ 95/* Hash table. */
97 96
98#define FRAG6Q_HASHSZ 64 97#define FRAG6Q_HASHSZ 64
99 98
100static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; 99static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ];
101static DEFINE_RWLOCK(nf_ct_frag6_lock); 100static DEFINE_RWLOCK(nf_ct_frag6_lock);
102static u32 nf_ct_frag6_hash_rnd; 101static u32 nf_ct_frag6_hash_rnd;
103static LIST_HEAD(nf_ct_frag6_lru_list); 102static LIST_HEAD(nf_ct_frag6_lru_list);
@@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0;
105 104
106static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) 105static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq)
107{ 106{
108 if (fq->next) 107 hlist_del(&fq->list);
109 fq->next->pprev = fq->pprev;
110 *fq->pprev = fq->next;
111 list_del(&fq->lru_list); 108 list_del(&fq->lru_list);
112 nf_ct_frag6_nqueues--; 109 nf_ct_frag6_nqueues--;
113} 110}
@@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy)
158 get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); 155 get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32));
159 for (i = 0; i < FRAG6Q_HASHSZ; i++) { 156 for (i = 0; i < FRAG6Q_HASHSZ; i++) {
160 struct nf_ct_frag6_queue *q; 157 struct nf_ct_frag6_queue *q;
158 struct hlist_node *p, *n;
161 159
162 q = nf_ct_frag6_hash[i]; 160 hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) {
163 while (q) {
164 struct nf_ct_frag6_queue *next = q->next;
165 unsigned int hval = ip6qhashfn(q->id, 161 unsigned int hval = ip6qhashfn(q->id,
166 &q->saddr, 162 &q->saddr,
167 &q->daddr); 163 &q->daddr);
168
169 if (hval != i) { 164 if (hval != i) {
170 /* Unlink. */ 165 hlist_del(&q->list);
171 if (q->next)
172 q->next->pprev = q->pprev;
173 *q->pprev = q->next;
174
175 /* Relink to new hash chain. */ 166 /* Relink to new hash chain. */
176 if ((q->next = nf_ct_frag6_hash[hval]) != NULL) 167 hlist_add_head(&q->list,
177 q->next->pprev = &q->next; 168 &nf_ct_frag6_hash[hval]);
178 nf_ct_frag6_hash[hval] = q;
179 q->pprev = &nf_ct_frag6_hash[hval];
180 } 169 }
181
182 q = next;
183 } 170 }
184 } 171 }
185 write_unlock(&nf_ct_frag6_lock); 172 write_unlock(&nf_ct_frag6_lock);
@@ -314,15 +301,17 @@ out:
314 301
315/* Creation primitives. */ 302/* Creation primitives. */
316 303
317
318static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, 304static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
319 struct nf_ct_frag6_queue *fq_in) 305 struct nf_ct_frag6_queue *fq_in)
320{ 306{
321 struct nf_ct_frag6_queue *fq; 307 struct nf_ct_frag6_queue *fq;
308#ifdef CONFIG_SMP
309 struct hlist_node *n;
310#endif
322 311
323 write_lock(&nf_ct_frag6_lock); 312 write_lock(&nf_ct_frag6_lock);
324#ifdef CONFIG_SMP 313#ifdef CONFIG_SMP
325 for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { 314 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
326 if (fq->id == fq_in->id && 315 if (fq->id == fq_in->id &&
327 !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && 316 !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) &&
328 !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { 317 !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) {
@@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
340 atomic_inc(&fq->refcnt); 329 atomic_inc(&fq->refcnt);
341 330
342 atomic_inc(&fq->refcnt); 331 atomic_inc(&fq->refcnt);
343 if ((fq->next = nf_ct_frag6_hash[hash]) != NULL) 332 hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]);
344 fq->next->pprev = &fq->next;
345 nf_ct_frag6_hash[hash] = fq;
346 fq->pprev = &nf_ct_frag6_hash[hash];
347 INIT_LIST_HEAD(&fq->lru_list); 333 INIT_LIST_HEAD(&fq->lru_list);
348 list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); 334 list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list);
349 nf_ct_frag6_nqueues++; 335 nf_ct_frag6_nqueues++;
@@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue *
384fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) 370fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
385{ 371{
386 struct nf_ct_frag6_queue *fq; 372 struct nf_ct_frag6_queue *fq;
373 struct hlist_node *n;
387 unsigned int hash = ip6qhashfn(id, src, dst); 374 unsigned int hash = ip6qhashfn(id, src, dst);
388 375
389 read_lock(&nf_ct_frag6_lock); 376 read_lock(&nf_ct_frag6_lock);
390 for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { 377 hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
391 if (fq->id == id && 378 if (fq->id == id &&
392 !ipv6_addr_cmp(src, &fq->saddr) && 379 !ipv6_addr_cmp(src, &fq->saddr) &&
393 !ipv6_addr_cmp(dst, &fq->daddr)) { 380 !ipv6_addr_cmp(dst, &fq->daddr)) {