• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/net/ipv4/netfilter/
1/*
2 * Packet matching code.
3 *
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12#include <linux/cache.h>
13#include <linux/capability.h>
14#include <linux/skbuff.h>
15#include <linux/kmod.h>
16#include <linux/vmalloc.h>
17#include <linux/netdevice.h>
18#include <linux/module.h>
19#include <linux/icmp.h>
20#include <net/ip.h>
21#include <net/compat.h>
22#include <asm/uaccess.h>
23#include <linux/mutex.h>
24#include <linux/proc_fs.h>
25#include <linux/err.h>
26#include <linux/cpumask.h>
27
28#include <linux/netfilter/x_tables.h>
29#include <linux/netfilter_ipv4/ip_tables.h>
30#ifdef CONFIG_IP_NF_TARGET_CONE
31#include <linux/netfilter_ipv4/ipt_cone.h>
32#endif /* CONFIG_IP_NF_TARGET_CONE */
33#include <net/netfilter/nf_log.h>
34#include "../../netfilter/xt_repldata.h"
35
36#include <typedefs.h>
37#include <bcmdefs.h>
38
39MODULE_LICENSE("GPL");
40MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
41MODULE_DESCRIPTION("IPv4 packet filter");
42
43/*#define DEBUG_IP_FIREWALL*/
44/*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
45/*#define DEBUG_IP_FIREWALL_USER*/
46
47#ifdef DEBUG_IP_FIREWALL
48#define dprintf(format, args...) pr_info(format , ## args)
49#else
50#define dprintf(format, args...)
51#endif
52
53#ifdef DEBUG_IP_FIREWALL_USER
54#define duprintf(format, args...) pr_info(format , ## args)
55#else
56#define duprintf(format, args...)
57#endif
58
59#ifdef CONFIG_NETFILTER_DEBUG
60#define IP_NF_ASSERT(x)		WARN_ON(!(x))
61#else
62#define IP_NF_ASSERT(x)
63#endif
64
65
66void *ipt_alloc_initial_table(const struct xt_table *info)
67{
68	return xt_alloc_initial_table(ipt, IPT);
69}
70EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);
71
72/*
73   We keep a set of rules for each CPU, so we can avoid write-locking
74   them in the softirq when updating the counters and therefore
75   only need to read-lock in the softirq; doing a write_lock_bh() in user
76   context stops packets coming through and allows user context to read
77   the counters or update the rules.
78
79   Hence the start of any table is given by get_table() below.  */
80
81/* Returns whether matches rule or not. */
82/* Performance critical - called for every packet */
83static inline bool
84ip_packet_match(const struct iphdr *ip,
85		const char *indev,
86		const char *outdev,
87		const struct ipt_ip *ipinfo,
88		int isfrag)
89{
90	unsigned long ret;
91
92#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
93
94	if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
95		  IPT_INV_SRCIP) ||
96	    FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
97		  IPT_INV_DSTIP)) {
98		dprintf("Source or dest mismatch.\n");
99
100		dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
101			&ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
102			ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
103		dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
104			&ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
105			ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
106		return false;
107	}
108
109	ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
110
111	if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
112		dprintf("VIA in mismatch (%s vs %s).%s\n",
113			indev, ipinfo->iniface,
114			ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
115		return false;
116	}
117
118	ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
119
120	if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
121		dprintf("VIA out mismatch (%s vs %s).%s\n",
122			outdev, ipinfo->outiface,
123			ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
124		return false;
125	}
126
127	/* Check specific protocol */
128	if (ipinfo->proto &&
129	    FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
130		dprintf("Packet protocol %hi does not match %hi.%s\n",
131			ip->protocol, ipinfo->proto,
132			ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
133		return false;
134	}
135
136	/* If we have a fragment rule but the packet is not a fragment
137	 * then we return zero */
138	if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
139		dprintf("Fragment rule but not fragment.%s\n",
140			ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
141		return false;
142	}
143
144	return true;
145}
146
147static bool
148ip_checkentry(const struct ipt_ip *ip)
149{
150	if (ip->flags & ~IPT_F_MASK) {
151		duprintf("Unknown flag bits set: %08X\n",
152			 ip->flags & ~IPT_F_MASK);
153		return false;
154	}
155	if (ip->invflags & ~IPT_INV_MASK) {
156		duprintf("Unknown invflag bits set: %08X\n",
157			 ip->invflags & ~IPT_INV_MASK);
158		return false;
159	}
160	return true;
161}
162
163static unsigned int
164ipt_error(struct sk_buff *skb, const struct xt_action_param *par)
165{
166	if (net_ratelimit())
167		pr_info("error: `%s'\n", (const char *)par->targinfo);
168
169	return NF_DROP;
170}
171
172/* Performance critical */
173static inline struct ipt_entry *
174get_entry(const void *base, unsigned int offset)
175{
176	return (struct ipt_entry *)(base + offset);
177}
178
179/* All zeroes == unconditional rule. */
180/* Mildly perf critical (only if packet tracing is on) */
181static inline bool unconditional(const struct ipt_ip *ip)
182{
183	static const struct ipt_ip uncond;
184
185	return memcmp(ip, &uncond, sizeof(uncond)) == 0;
186#undef FWINV
187}
188
189/* for const-correctness */
190static inline const struct ipt_entry_target *
191ipt_get_target_c(const struct ipt_entry *e)
192{
193	return ipt_get_target((struct ipt_entry *)e);
194}
195
196#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
197	defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
198static const char *const hooknames[] = {
199	[NF_INET_PRE_ROUTING]		= "PREROUTING",
200	[NF_INET_LOCAL_IN]		= "INPUT",
201	[NF_INET_FORWARD]		= "FORWARD",
202	[NF_INET_LOCAL_OUT]		= "OUTPUT",
203	[NF_INET_POST_ROUTING]		= "POSTROUTING",
204};
205
206enum nf_ip_trace_comments {
207	NF_IP_TRACE_COMMENT_RULE,
208	NF_IP_TRACE_COMMENT_RETURN,
209	NF_IP_TRACE_COMMENT_POLICY,
210};
211
212static const char *const comments[] = {
213	[NF_IP_TRACE_COMMENT_RULE]	= "rule",
214	[NF_IP_TRACE_COMMENT_RETURN]	= "return",
215	[NF_IP_TRACE_COMMENT_POLICY]	= "policy",
216};
217
218static struct nf_loginfo trace_loginfo = {
219	.type = NF_LOG_TYPE_LOG,
220	.u = {
221		.log = {
222			.level = 4,
223			.logflags = NF_LOG_MASK,
224		},
225	},
226};
227
228/* Mildly perf critical (only if packet tracing is on) */
229static inline int
230get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e,
231		      const char *hookname, const char **chainname,
232		      const char **comment, unsigned int *rulenum)
233{
234	const struct ipt_standard_target *t = (void *)ipt_get_target_c(s);
235
236	if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
237		/* Head of user chain: ERROR target with chainname */
238		*chainname = t->target.data;
239		(*rulenum) = 0;
240	} else if (s == e) {
241		(*rulenum)++;
242
243		if (s->target_offset == sizeof(struct ipt_entry) &&
244		    strcmp(t->target.u.kernel.target->name,
245			   IPT_STANDARD_TARGET) == 0 &&
246		   t->verdict < 0 &&
247		   unconditional(&s->ip)) {
248			/* Tail of chains: STANDARD target (return/policy) */
249			*comment = *chainname == hookname
250				? comments[NF_IP_TRACE_COMMENT_POLICY]
251				: comments[NF_IP_TRACE_COMMENT_RETURN];
252		}
253		return 1;
254	} else
255		(*rulenum)++;
256
257	return 0;
258}
259
260static void trace_packet(const struct sk_buff *skb,
261			 unsigned int hook,
262			 const struct net_device *in,
263			 const struct net_device *out,
264			 const char *tablename,
265			 const struct xt_table_info *private,
266			 const struct ipt_entry *e)
267{
268	const void *table_base;
269	const struct ipt_entry *root;
270	const char *hookname, *chainname, *comment;
271	const struct ipt_entry *iter;
272	unsigned int rulenum = 0;
273
274	table_base = private->entries[smp_processor_id()];
275	root = get_entry(table_base, private->hook_entry[hook]);
276
277	hookname = chainname = hooknames[hook];
278	comment = comments[NF_IP_TRACE_COMMENT_RULE];
279
280	xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
281		if (get_chainname_rulenum(iter, e, hookname,
282		    &chainname, &comment, &rulenum) != 0)
283			break;
284
285	nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
286		      "TRACE: %s:%s:%s:%u ",
287		      tablename, chainname, comment, rulenum);
288}
289#endif
290
291static inline __pure
292struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
293{
294	return (void *)entry + entry->next_offset;
295}
296
297/* Returns one of the generic firewall policies, like NF_ACCEPT. */
298unsigned int BCMFASTPATH_HOST
299ipt_do_table(struct sk_buff *skb,
300	     unsigned int hook,
301	     const struct net_device *in,
302	     const struct net_device *out,
303	     struct xt_table *table)
304{
305	static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
306	const struct iphdr *ip;
307	/* Initializing verdict to NF_DROP keeps gcc happy. */
308	unsigned int verdict = NF_DROP;
309	const char *indev, *outdev;
310	const void *table_base;
311	struct ipt_entry *e, **jumpstack;
312	unsigned int *stackptr, origptr, cpu;
313	const struct xt_table_info *private;
314	struct xt_action_param acpar;
315
316	/* Initialization */
317	ip = ip_hdr(skb);
318	indev = in ? in->name : nulldevname;
319	outdev = out ? out->name : nulldevname;
320	/* We handle fragments by dealing with the first fragment as
321	 * if it was a normal packet.  All other fragments are treated
322	 * normally, except that they will NEVER match rules that ask
323	 * things we don't know, ie. tcp syn flag or ports).  If the
324	 * rule is also a fragment-specific rule, non-fragments won't
325	 * match it. */
326	acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
327	acpar.thoff   = ip_hdrlen(skb);
328	acpar.hotdrop = false;
329	acpar.in      = in;
330	acpar.out     = out;
331	acpar.family  = NFPROTO_IPV4;
332	acpar.hooknum = hook;
333
334	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
335	xt_info_rdlock_bh();
336	private = table->private;
337	cpu        = smp_processor_id();
338	table_base = private->entries[cpu];
339	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
340	stackptr   = per_cpu_ptr(private->stackptr, cpu);
341	origptr    = *stackptr;
342
343	e = get_entry(table_base, private->hook_entry[hook]);
344
345	pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n",
346		 table->name, hook, origptr,
347		 get_entry(table_base, private->underflow[hook]));
348
349	do {
350		const struct ipt_entry_target *t;
351		const struct xt_entry_match *ematch;
352
353		IP_NF_ASSERT(e);
354#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
355		skb->nfcache |= e->nfcache;
356#endif
357		if (!ip_packet_match(ip, indev, outdev,
358		    &e->ip, acpar.fragoff)) {
359 no_match:
360			e = ipt_next_entry(e);
361			continue;
362		}
363
364		xt_ematch_foreach(ematch, e) {
365			acpar.match     = ematch->u.kernel.match;
366			acpar.matchinfo = ematch->data;
367			if (!acpar.match->match(skb, &acpar))
368				goto no_match;
369		}
370
371		ADD_COUNTER(e->counters, skb->len, 1);
372
373		t = ipt_get_target(e);
374		IP_NF_ASSERT(t->u.kernel.target);
375
376#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
377	defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
378		/* The packet is traced: log it */
379		if (unlikely(skb->nf_trace))
380			trace_packet(skb, hook, in, out,
381				     table->name, private, e);
382#endif
383		/* Standard target? */
384		if (!t->u.kernel.target->target) {
385			int v;
386
387			v = ((struct ipt_standard_target *)t)->verdict;
388			if (v < 0) {
389				/* Pop from stack? */
390				if (v != IPT_RETURN) {
391					verdict = (unsigned)(-v) - 1;
392#ifdef CONFIG_IP_NF_TARGET_CONE
393					acpar.target   = t->u.kernel.target;
394					acpar.targinfo = t->data;
395					if (ipt_cone_target(skb, &acpar) == NF_ACCEPT) {
396						/* Accept cone target as default */
397						verdict = NF_ACCEPT;
398					}
399#endif /* CONFIG_IP_NF_TARGET_CONE */
400					break;
401				}
402				if (*stackptr == 0) {
403					e = get_entry(table_base,
404					    private->underflow[hook]);
405					pr_debug("Underflow (this is normal) "
406						 "to %p\n", e);
407				} else {
408					e = jumpstack[--*stackptr];
409					pr_debug("Pulled %p out from pos %u\n",
410						 e, *stackptr);
411					e = ipt_next_entry(e);
412				}
413				continue;
414			}
415			if (table_base + v != ipt_next_entry(e) &&
416			    !(e->ip.flags & IPT_F_GOTO)) {
417				if (*stackptr >= private->stacksize) {
418					verdict = NF_DROP;
419					break;
420				}
421				jumpstack[(*stackptr)++] = e;
422				pr_debug("Pushed %p into pos %u\n",
423					 e, *stackptr - 1);
424			}
425
426			e = get_entry(table_base, v);
427			continue;
428		}
429
430		acpar.target   = t->u.kernel.target;
431		acpar.targinfo = t->data;
432
433		verdict = t->u.kernel.target->target(skb, &acpar);
434		/* Target might have changed stuff. */
435		ip = ip_hdr(skb);
436		if (verdict == IPT_CONTINUE)
437			e = ipt_next_entry(e);
438		else
439			/* Verdict */
440			break;
441	} while (!acpar.hotdrop);
442	xt_info_rdunlock_bh();
443	pr_debug("Exiting %s; resetting sp from %u to %u\n",
444		 __func__, *stackptr, origptr);
445	*stackptr = origptr;
446#ifdef DEBUG_ALLOW_ALL
447	return NF_ACCEPT;
448#else
449	if (acpar.hotdrop)
450		return NF_DROP;
451	else return verdict;
452#endif
453}
454
455/* Figures out from what hook each rule can be called: returns 0 if
456   there are loops.  Puts hook bitmask in comefrom. */
457static int
458mark_source_chains(const struct xt_table_info *newinfo,
459		   unsigned int valid_hooks, void *entry0)
460{
461	unsigned int hook;
462
463	/* No recursion; use packet counter to save back ptrs (reset
464	   to 0 as we leave), and comefrom to save source hook bitmask */
465	for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
466		unsigned int pos = newinfo->hook_entry[hook];
467		struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
468
469		if (!(valid_hooks & (1 << hook)))
470			continue;
471
472		/* Set initial back pointer. */
473		e->counters.pcnt = pos;
474
475		for (;;) {
476			const struct ipt_standard_target *t
477				= (void *)ipt_get_target_c(e);
478			int visited = e->comefrom & (1 << hook);
479
480			if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
481				pr_err("iptables: loop hook %u pos %u %08X.\n",
482				       hook, pos, e->comefrom);
483				return 0;
484			}
485			e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
486
487			/* Unconditional return/END. */
488			if ((e->target_offset == sizeof(struct ipt_entry) &&
489			     (strcmp(t->target.u.user.name,
490				     IPT_STANDARD_TARGET) == 0) &&
491			     t->verdict < 0 && unconditional(&e->ip)) ||
492			    visited) {
493				unsigned int oldpos, size;
494
495				if ((strcmp(t->target.u.user.name,
496			    		    IPT_STANDARD_TARGET) == 0) &&
497				    t->verdict < -NF_MAX_VERDICT - 1) {
498					duprintf("mark_source_chains: bad "
499						"negative verdict (%i)\n",
500								t->verdict);
501					return 0;
502				}
503
504				/* Return: backtrack through the last
505				   big jump. */
506				do {
507					e->comefrom ^= (1<<NF_INET_NUMHOOKS);
508#ifdef DEBUG_IP_FIREWALL_USER
509					if (e->comefrom
510					    & (1 << NF_INET_NUMHOOKS)) {
511						duprintf("Back unset "
512							 "on hook %u "
513							 "rule %u\n",
514							 hook, pos);
515					}
516#endif
517					oldpos = pos;
518					pos = e->counters.pcnt;
519					e->counters.pcnt = 0;
520
521					/* We're at the start. */
522					if (pos == oldpos)
523						goto next;
524
525					e = (struct ipt_entry *)
526						(entry0 + pos);
527				} while (oldpos == pos + e->next_offset);
528
529				/* Move along one */
530				size = e->next_offset;
531				e = (struct ipt_entry *)
532					(entry0 + pos + size);
533				e->counters.pcnt = pos;
534				pos += size;
535			} else {
536				int newpos = t->verdict;
537
538				if (strcmp(t->target.u.user.name,
539					   IPT_STANDARD_TARGET) == 0 &&
540				    newpos >= 0) {
541					if (newpos > newinfo->size -
542						sizeof(struct ipt_entry)) {
543						duprintf("mark_source_chains: "
544							"bad verdict (%i)\n",
545								newpos);
546						return 0;
547					}
548					/* This a jump; chase it. */
549					duprintf("Jump rule %u -> %u\n",
550						 pos, newpos);
551				} else {
552					/* ... this is a fallthru */
553					newpos = pos + e->next_offset;
554				}
555				e = (struct ipt_entry *)
556					(entry0 + newpos);
557				e->counters.pcnt = pos;
558				pos = newpos;
559			}
560		}
561		next:
562		duprintf("Finished chain %u\n", hook);
563	}
564	return 1;
565}
566
567static void cleanup_match(struct ipt_entry_match *m, struct net *net)
568{
569	struct xt_mtdtor_param par;
570
571	par.net       = net;
572	par.match     = m->u.kernel.match;
573	par.matchinfo = m->data;
574	par.family    = NFPROTO_IPV4;
575	if (par.match->destroy != NULL)
576		par.match->destroy(&par);
577	module_put(par.match->me);
578}
579
580static int
581check_entry(const struct ipt_entry *e, const char *name)
582{
583	const struct ipt_entry_target *t;
584
585	if (!ip_checkentry(&e->ip)) {
586		duprintf("ip check failed %p %s.\n", e, par->match->name);
587		return -EINVAL;
588	}
589
590	if (e->target_offset + sizeof(struct ipt_entry_target) >
591	    e->next_offset)
592		return -EINVAL;
593
594	t = ipt_get_target_c(e);
595	if (e->target_offset + t->u.target_size > e->next_offset)
596		return -EINVAL;
597
598	return 0;
599}
600
601static int
602check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
603{
604	const struct ipt_ip *ip = par->entryinfo;
605	int ret;
606
607	par->match     = m->u.kernel.match;
608	par->matchinfo = m->data;
609
610	ret = xt_check_match(par, m->u.match_size - sizeof(*m),
611	      ip->proto, ip->invflags & IPT_INV_PROTO);
612	if (ret < 0) {
613		duprintf("check failed for `%s'.\n", par->match->name);
614		return ret;
615	}
616	return 0;
617}
618
619static int
620find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
621{
622	struct xt_match *match;
623	int ret;
624
625	match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
626				      m->u.user.revision);
627	if (IS_ERR(match)) {
628		duprintf("find_check_match: `%s' not found\n", m->u.user.name);
629		return PTR_ERR(match);
630	}
631	m->u.kernel.match = match;
632
633	ret = check_match(m, par);
634	if (ret)
635		goto err;
636
637	return 0;
638err:
639	module_put(m->u.kernel.match->me);
640	return ret;
641}
642
643static int check_target(struct ipt_entry *e, struct net *net, const char *name)
644{
645	struct ipt_entry_target *t = ipt_get_target(e);
646	struct xt_tgchk_param par = {
647		.net       = net,
648		.table     = name,
649		.entryinfo = e,
650		.target    = t->u.kernel.target,
651		.targinfo  = t->data,
652		.hook_mask = e->comefrom,
653		.family    = NFPROTO_IPV4,
654	};
655	int ret;
656
657	ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
658	      e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
659	if (ret < 0) {
660		duprintf("check failed for `%s'.\n",
661			 t->u.kernel.target->name);
662		return ret;
663	}
664	return 0;
665}
666
667static int
668find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
669		 unsigned int size)
670{
671	struct ipt_entry_target *t;
672	struct xt_target *target;
673	int ret;
674	unsigned int j;
675	struct xt_mtchk_param mtpar;
676	struct xt_entry_match *ematch;
677
678	ret = check_entry(e, name);
679	if (ret)
680		return ret;
681
682	j = 0;
683	mtpar.net	= net;
684	mtpar.table     = name;
685	mtpar.entryinfo = &e->ip;
686	mtpar.hook_mask = e->comefrom;
687	mtpar.family    = NFPROTO_IPV4;
688	xt_ematch_foreach(ematch, e) {
689		ret = find_check_match(ematch, &mtpar);
690		if (ret != 0)
691			goto cleanup_matches;
692		++j;
693	}
694
695	t = ipt_get_target(e);
696	target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
697					t->u.user.revision);
698	if (IS_ERR(target)) {
699		duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
700		ret = PTR_ERR(target);
701		goto cleanup_matches;
702	}
703	t->u.kernel.target = target;
704
705	ret = check_target(e, net, name);
706	if (ret)
707		goto err;
708	return 0;
709 err:
710	module_put(t->u.kernel.target->me);
711 cleanup_matches:
712	xt_ematch_foreach(ematch, e) {
713		if (j-- == 0)
714			break;
715		cleanup_match(ematch, net);
716	}
717	return ret;
718}
719
720static bool check_underflow(const struct ipt_entry *e)
721{
722	const struct ipt_entry_target *t;
723	unsigned int verdict;
724
725	if (!unconditional(&e->ip))
726		return false;
727	t = ipt_get_target_c(e);
728	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
729		return false;
730	verdict = ((struct ipt_standard_target *)t)->verdict;
731	verdict = -verdict - 1;
732	return verdict == NF_DROP || verdict == NF_ACCEPT;
733}
734
735static int
736check_entry_size_and_hooks(struct ipt_entry *e,
737			   struct xt_table_info *newinfo,
738			   const unsigned char *base,
739			   const unsigned char *limit,
740			   const unsigned int *hook_entries,
741			   const unsigned int *underflows,
742			   unsigned int valid_hooks)
743{
744	unsigned int h;
745
746	if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
747	    (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
748		duprintf("Bad offset %p\n", e);
749		return -EINVAL;
750	}
751
752	if (e->next_offset
753	    < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
754		duprintf("checking: element %p size %u\n",
755			 e, e->next_offset);
756		return -EINVAL;
757	}
758
759	/* Check hooks & underflows */
760	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
761		if (!(valid_hooks & (1 << h)))
762			continue;
763		if ((unsigned char *)e - base == hook_entries[h])
764			newinfo->hook_entry[h] = hook_entries[h];
765		if ((unsigned char *)e - base == underflows[h]) {
766			if (!check_underflow(e)) {
767				pr_err("Underflows must be unconditional and "
768				       "use the STANDARD target with "
769				       "ACCEPT/DROP\n");
770				return -EINVAL;
771			}
772			newinfo->underflow[h] = underflows[h];
773		}
774	}
775
776	/* Clear counters and comefrom */
777	e->counters = ((struct xt_counters) { 0, 0 });
778	e->comefrom = 0;
779	return 0;
780}
781
782static void
783cleanup_entry(struct ipt_entry *e, struct net *net)
784{
785	struct xt_tgdtor_param par;
786	struct ipt_entry_target *t;
787	struct xt_entry_match *ematch;
788
789	/* Cleanup all matches */
790	xt_ematch_foreach(ematch, e)
791		cleanup_match(ematch, net);
792	t = ipt_get_target(e);
793
794	par.net      = net;
795	par.target   = t->u.kernel.target;
796	par.targinfo = t->data;
797	par.family   = NFPROTO_IPV4;
798	if (par.target->destroy != NULL)
799		par.target->destroy(&par);
800	module_put(par.target->me);
801}
802
803/* Checks and translates the user-supplied table segment (held in
804   newinfo) */
805static int
806translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
807                const struct ipt_replace *repl)
808{
809	struct ipt_entry *iter;
810	unsigned int i;
811	int ret = 0;
812
813	newinfo->size = repl->size;
814	newinfo->number = repl->num_entries;
815
816	/* Init all hooks to impossible value. */
817	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
818		newinfo->hook_entry[i] = 0xFFFFFFFF;
819		newinfo->underflow[i] = 0xFFFFFFFF;
820	}
821
822	duprintf("translate_table: size %u\n", newinfo->size);
823	i = 0;
824	/* Walk through entries, checking offsets. */
825	xt_entry_foreach(iter, entry0, newinfo->size) {
826		ret = check_entry_size_and_hooks(iter, newinfo, entry0,
827						 entry0 + repl->size,
828						 repl->hook_entry,
829						 repl->underflow,
830						 repl->valid_hooks);
831		if (ret != 0)
832			return ret;
833		++i;
834		if (strcmp(ipt_get_target(iter)->u.user.name,
835		    XT_ERROR_TARGET) == 0)
836			++newinfo->stacksize;
837	}
838
839	if (i != repl->num_entries) {
840		duprintf("translate_table: %u not %u entries\n",
841			 i, repl->num_entries);
842		return -EINVAL;
843	}
844
845	/* Check hooks all assigned */
846	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
847		/* Only hooks which are valid */
848		if (!(repl->valid_hooks & (1 << i)))
849			continue;
850		if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
851			duprintf("Invalid hook entry %u %u\n",
852				 i, repl->hook_entry[i]);
853			return -EINVAL;
854		}
855		if (newinfo->underflow[i] == 0xFFFFFFFF) {
856			duprintf("Invalid underflow %u %u\n",
857				 i, repl->underflow[i]);
858			return -EINVAL;
859		}
860	}
861
862	if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
863		return -ELOOP;
864
865	/* Finally, each sanity check must pass */
866	i = 0;
867	xt_entry_foreach(iter, entry0, newinfo->size) {
868		ret = find_check_entry(iter, net, repl->name, repl->size);
869		if (ret != 0)
870			break;
871		++i;
872	}
873
874	if (ret != 0) {
875		xt_entry_foreach(iter, entry0, newinfo->size) {
876			if (i-- == 0)
877				break;
878			cleanup_entry(iter, net);
879		}
880		return ret;
881	}
882
883	/* And one copy for every other CPU */
884	for_each_possible_cpu(i) {
885		if (newinfo->entries[i] && newinfo->entries[i] != entry0)
886			memcpy(newinfo->entries[i], entry0, newinfo->size);
887	}
888
889	return ret;
890}
891
892static void
893get_counters(const struct xt_table_info *t,
894	     struct xt_counters counters[])
895{
896	struct ipt_entry *iter;
897	unsigned int cpu;
898	unsigned int i;
899	unsigned int curcpu = get_cpu();
900
901	/* Instead of clearing (by a previous call to memset())
902	 * the counters and using adds, we set the counters
903	 * with data used by 'current' CPU.
904	 *
905	 * Bottom half has to be disabled to prevent deadlock
906	 * if new softirq were to run and call ipt_do_table
907	 */
908	local_bh_disable();
909	i = 0;
910	xt_entry_foreach(iter, t->entries[curcpu], t->size) {
911		SET_COUNTER(counters[i], iter->counters.bcnt,
912			    iter->counters.pcnt);
913		++i;
914	}
915	local_bh_enable();
916	/* Processing counters from other cpus, we can let bottom half enabled,
917	 * (preemption is disabled)
918	 */
919
920	for_each_possible_cpu(cpu) {
921		if (cpu == curcpu)
922			continue;
923		i = 0;
924		local_bh_disable();
925		xt_info_wrlock(cpu);
926		xt_entry_foreach(iter, t->entries[cpu], t->size) {
927			ADD_COUNTER(counters[i], iter->counters.bcnt,
928				    iter->counters.pcnt);
929			++i; /* macro does multi eval of i */
930		}
931		xt_info_wrunlock(cpu);
932		local_bh_enable();
933	}
934	put_cpu();
935}
936
937static struct xt_counters *alloc_counters(const struct xt_table *table)
938{
939	unsigned int countersize;
940	struct xt_counters *counters;
941	const struct xt_table_info *private = table->private;
942
943	/* We need atomic snapshot of counters: rest doesn't change
944	   (other than comefrom, which userspace doesn't care
945	   about). */
946	countersize = sizeof(struct xt_counters) * private->number;
947	counters = vmalloc(countersize);
948
949	if (counters == NULL)
950		return ERR_PTR(-ENOMEM);
951
952	get_counters(private, counters);
953
954	return counters;
955}
956
957static int
958copy_entries_to_user(unsigned int total_size,
959		     const struct xt_table *table,
960		     void __user *userptr)
961{
962	unsigned int off, num;
963	const struct ipt_entry *e;
964	struct xt_counters *counters;
965	const struct xt_table_info *private = table->private;
966	int ret = 0;
967	const void *loc_cpu_entry;
968
969	counters = alloc_counters(table);
970	if (IS_ERR(counters))
971		return PTR_ERR(counters);
972
973	/* choose the copy that is on our node/cpu, ...
974	 * This choice is lazy (because current thread is
975	 * allowed to migrate to another cpu)
976	 */
977	loc_cpu_entry = private->entries[raw_smp_processor_id()];
978	if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
979		ret = -EFAULT;
980		goto free_counters;
981	}
982
983	/* ... then go back and fix counters and names */
984	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
985		unsigned int i;
986		const struct ipt_entry_match *m;
987		const struct ipt_entry_target *t;
988
989		e = (struct ipt_entry *)(loc_cpu_entry + off);
990		if (copy_to_user(userptr + off
991				 + offsetof(struct ipt_entry, counters),
992				 &counters[num],
993				 sizeof(counters[num])) != 0) {
994			ret = -EFAULT;
995			goto free_counters;
996		}
997
998		for (i = sizeof(struct ipt_entry);
999		     i < e->target_offset;
1000		     i += m->u.match_size) {
1001			m = (void *)e + i;
1002
1003			if (copy_to_user(userptr + off + i
1004					 + offsetof(struct ipt_entry_match,
1005						    u.user.name),
1006					 m->u.kernel.match->name,
1007					 strlen(m->u.kernel.match->name)+1)
1008			    != 0) {
1009				ret = -EFAULT;
1010				goto free_counters;
1011			}
1012		}
1013
1014		t = ipt_get_target_c(e);
1015		if (copy_to_user(userptr + off + e->target_offset
1016				 + offsetof(struct ipt_entry_target,
1017					    u.user.name),
1018				 t->u.kernel.target->name,
1019				 strlen(t->u.kernel.target->name)+1) != 0) {
1020			ret = -EFAULT;
1021			goto free_counters;
1022		}
1023	}
1024
1025 free_counters:
1026	vfree(counters);
1027	return ret;
1028}
1029
1030#ifdef CONFIG_COMPAT
1031static void compat_standard_from_user(void *dst, const void *src)
1032{
1033	int v = *(compat_int_t *)src;
1034
1035	if (v > 0)
1036		v += xt_compat_calc_jump(AF_INET, v);
1037	memcpy(dst, &v, sizeof(v));
1038}
1039
1040static int compat_standard_to_user(void __user *dst, const void *src)
1041{
1042	compat_int_t cv = *(int *)src;
1043
1044	if (cv > 0)
1045		cv -= xt_compat_calc_jump(AF_INET, cv);
1046	return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1047}
1048
1049static int compat_calc_entry(const struct ipt_entry *e,
1050			     const struct xt_table_info *info,
1051			     const void *base, struct xt_table_info *newinfo)
1052{
1053	const struct xt_entry_match *ematch;
1054	const struct ipt_entry_target *t;
1055	unsigned int entry_offset;
1056	int off, i, ret;
1057
1058	off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1059	entry_offset = (void *)e - base;
1060	xt_ematch_foreach(ematch, e)
1061		off += xt_compat_match_offset(ematch->u.kernel.match);
1062	t = ipt_get_target_c(e);
1063	off += xt_compat_target_offset(t->u.kernel.target);
1064	newinfo->size -= off;
1065	ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1066	if (ret)
1067		return ret;
1068
1069	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1070		if (info->hook_entry[i] &&
1071		    (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1072			newinfo->hook_entry[i] -= off;
1073		if (info->underflow[i] &&
1074		    (e < (struct ipt_entry *)(base + info->underflow[i])))
1075			newinfo->underflow[i] -= off;
1076	}
1077	return 0;
1078}
1079
1080static int compat_table_info(const struct xt_table_info *info,
1081			     struct xt_table_info *newinfo)
1082{
1083	struct ipt_entry *iter;
1084	void *loc_cpu_entry;
1085	int ret;
1086
1087	if (!newinfo || !info)
1088		return -EINVAL;
1089
1090	/* we dont care about newinfo->entries[] */
1091	memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1092	newinfo->initial_entries = 0;
1093	loc_cpu_entry = info->entries[raw_smp_processor_id()];
1094	xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1095		ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1096		if (ret != 0)
1097			return ret;
1098	}
1099	return 0;
1100}
1101#endif
1102
1103static int get_info(struct net *net, void __user *user,
1104                    const int *len, int compat)
1105{
1106	char name[IPT_TABLE_MAXNAMELEN];
1107	struct xt_table *t;
1108	int ret;
1109
1110	if (*len != sizeof(struct ipt_getinfo)) {
1111		duprintf("length %u != %zu\n", *len,
1112			 sizeof(struct ipt_getinfo));
1113		return -EINVAL;
1114	}
1115
1116	if (copy_from_user(name, user, sizeof(name)) != 0)
1117		return -EFAULT;
1118
1119	name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1120#ifdef CONFIG_COMPAT
1121	if (compat)
1122		xt_compat_lock(AF_INET);
1123#endif
1124	t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1125				    "iptable_%s", name);
1126	if (t && !IS_ERR(t)) {
1127		struct ipt_getinfo info;
1128		const struct xt_table_info *private = t->private;
1129#ifdef CONFIG_COMPAT
1130		struct xt_table_info tmp;
1131
1132		if (compat) {
1133			ret = compat_table_info(private, &tmp);
1134			xt_compat_flush_offsets(AF_INET);
1135			private = &tmp;
1136		}
1137#endif
1138		info.valid_hooks = t->valid_hooks;
1139		memcpy(info.hook_entry, private->hook_entry,
1140		       sizeof(info.hook_entry));
1141		memcpy(info.underflow, private->underflow,
1142		       sizeof(info.underflow));
1143		info.num_entries = private->number;
1144		info.size = private->size;
1145		strcpy(info.name, name);
1146
1147		if (copy_to_user(user, &info, *len) != 0)
1148			ret = -EFAULT;
1149		else
1150			ret = 0;
1151
1152		xt_table_unlock(t);
1153		module_put(t->me);
1154	} else
1155		ret = t ? PTR_ERR(t) : -ENOENT;
1156#ifdef CONFIG_COMPAT
1157	if (compat)
1158		xt_compat_unlock(AF_INET);
1159#endif
1160	return ret;
1161}
1162
1163static int
1164get_entries(struct net *net, struct ipt_get_entries __user *uptr,
1165	    const int *len)
1166{
1167	int ret;
1168	struct ipt_get_entries get;
1169	struct xt_table *t;
1170
1171	if (*len < sizeof(get)) {
1172		duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1173		return -EINVAL;
1174	}
1175	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1176		return -EFAULT;
1177	if (*len != sizeof(struct ipt_get_entries) + get.size) {
1178		duprintf("get_entries: %u != %zu\n",
1179			 *len, sizeof(get) + get.size);
1180		return -EINVAL;
1181	}
1182
1183	t = xt_find_table_lock(net, AF_INET, get.name);
1184	if (t && !IS_ERR(t)) {
1185		const struct xt_table_info *private = t->private;
1186		duprintf("t->private->number = %u\n", private->number);
1187		if (get.size == private->size)
1188			ret = copy_entries_to_user(private->size,
1189						   t, uptr->entrytable);
1190		else {
1191			duprintf("get_entries: I've got %u not %u!\n",
1192				 private->size, get.size);
1193			ret = -EAGAIN;
1194		}
1195		module_put(t->me);
1196		xt_table_unlock(t);
1197	} else
1198		ret = t ? PTR_ERR(t) : -ENOENT;
1199
1200	return ret;
1201}
1202
1203static int
1204__do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1205	     struct xt_table_info *newinfo, unsigned int num_counters,
1206	     void __user *counters_ptr)
1207{
1208	int ret;
1209	struct xt_table *t;
1210	struct xt_table_info *oldinfo;
1211	struct xt_counters *counters;
1212	void *loc_cpu_old_entry;
1213	struct ipt_entry *iter;
1214
1215	ret = 0;
1216	counters = vmalloc(num_counters * sizeof(struct xt_counters));
1217	if (!counters) {
1218		ret = -ENOMEM;
1219		goto out;
1220	}
1221
1222	t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1223				    "iptable_%s", name);
1224	if (!t || IS_ERR(t)) {
1225		ret = t ? PTR_ERR(t) : -ENOENT;
1226		goto free_newinfo_counters_untrans;
1227	}
1228
1229	/* You lied! */
1230	if (valid_hooks != t->valid_hooks) {
1231		duprintf("Valid hook crap: %08X vs %08X\n",
1232			 valid_hooks, t->valid_hooks);
1233		ret = -EINVAL;
1234		goto put_module;
1235	}
1236
1237	oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1238	if (!oldinfo)
1239		goto put_module;
1240
1241	/* Update module usage count based on number of rules */
1242	duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1243		oldinfo->number, oldinfo->initial_entries, newinfo->number);
1244	if ((oldinfo->number > oldinfo->initial_entries) ||
1245	    (newinfo->number <= oldinfo->initial_entries))
1246		module_put(t->me);
1247	if ((oldinfo->number > oldinfo->initial_entries) &&
1248	    (newinfo->number <= oldinfo->initial_entries))
1249		module_put(t->me);
1250
1251	/* Get the old counters, and synchronize with replace */
1252	get_counters(oldinfo, counters);
1253
1254	/* Decrease module usage counts and free resource */
1255	loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1256	xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1257		cleanup_entry(iter, net);
1258
1259	xt_free_table_info(oldinfo);
1260	if (copy_to_user(counters_ptr, counters,
1261			 sizeof(struct xt_counters) * num_counters) != 0)
1262		ret = -EFAULT;
1263	vfree(counters);
1264	xt_table_unlock(t);
1265	return ret;
1266
1267 put_module:
1268	module_put(t->me);
1269	xt_table_unlock(t);
1270 free_newinfo_counters_untrans:
1271	vfree(counters);
1272 out:
1273	return ret;
1274}
1275
1276static int
1277do_replace(struct net *net, const void __user *user, unsigned int len)
1278{
1279	int ret;
1280	struct ipt_replace tmp;
1281	struct xt_table_info *newinfo;
1282	void *loc_cpu_entry;
1283	struct ipt_entry *iter;
1284
1285	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1286		return -EFAULT;
1287
1288	/* overflow check */
1289	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1290		return -ENOMEM;
1291
1292	newinfo = xt_alloc_table_info(tmp.size);
1293	if (!newinfo)
1294		return -ENOMEM;
1295
1296	/* choose the copy that is on our node/cpu */
1297	loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1298	if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1299			   tmp.size) != 0) {
1300		ret = -EFAULT;
1301		goto free_newinfo;
1302	}
1303
1304	ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1305	if (ret != 0)
1306		goto free_newinfo;
1307
1308	duprintf("Translated table\n");
1309
1310	ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1311			   tmp.num_counters, tmp.counters);
1312	if (ret)
1313		goto free_newinfo_untrans;
1314	return 0;
1315
1316 free_newinfo_untrans:
1317	xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1318		cleanup_entry(iter, net);
1319 free_newinfo:
1320	xt_free_table_info(newinfo);
1321	return ret;
1322}
1323
1324static int
1325do_add_counters(struct net *net, const void __user *user,
1326                unsigned int len, int compat)
1327{
1328	unsigned int i, curcpu;
1329	struct xt_counters_info tmp;
1330	struct xt_counters *paddc;
1331	unsigned int num_counters;
1332	const char *name;
1333	int size;
1334	void *ptmp;
1335	struct xt_table *t;
1336	const struct xt_table_info *private;
1337	int ret = 0;
1338	void *loc_cpu_entry;
1339	struct ipt_entry *iter;
1340#ifdef CONFIG_COMPAT
1341	struct compat_xt_counters_info compat_tmp;
1342
1343	if (compat) {
1344		ptmp = &compat_tmp;
1345		size = sizeof(struct compat_xt_counters_info);
1346	} else
1347#endif
1348	{
1349		ptmp = &tmp;
1350		size = sizeof(struct xt_counters_info);
1351	}
1352
1353	if (copy_from_user(ptmp, user, size) != 0)
1354		return -EFAULT;
1355
1356#ifdef CONFIG_COMPAT
1357	if (compat) {
1358		num_counters = compat_tmp.num_counters;
1359		name = compat_tmp.name;
1360	} else
1361#endif
1362	{
1363		num_counters = tmp.num_counters;
1364		name = tmp.name;
1365	}
1366
1367	if (len != size + num_counters * sizeof(struct xt_counters))
1368		return -EINVAL;
1369
1370	paddc = vmalloc(len - size);
1371	if (!paddc)
1372		return -ENOMEM;
1373
1374	if (copy_from_user(paddc, user + size, len - size) != 0) {
1375		ret = -EFAULT;
1376		goto free;
1377	}
1378
1379	t = xt_find_table_lock(net, AF_INET, name);
1380	if (!t || IS_ERR(t)) {
1381		ret = t ? PTR_ERR(t) : -ENOENT;
1382		goto free;
1383	}
1384
1385	local_bh_disable();
1386	private = t->private;
1387	if (private->number != num_counters) {
1388		ret = -EINVAL;
1389		goto unlock_up_free;
1390	}
1391
1392	i = 0;
1393	/* Choose the copy that is on our node */
1394	curcpu = smp_processor_id();
1395	loc_cpu_entry = private->entries[curcpu];
1396	xt_info_wrlock(curcpu);
1397	xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1398		ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1399		++i;
1400	}
1401	xt_info_wrunlock(curcpu);
1402 unlock_up_free:
1403	local_bh_enable();
1404	xt_table_unlock(t);
1405	module_put(t->me);
1406 free:
1407	vfree(paddc);
1408
1409	return ret;
1410}
1411
1412#ifdef CONFIG_COMPAT
1413struct compat_ipt_replace {
1414	char			name[IPT_TABLE_MAXNAMELEN];
1415	u32			valid_hooks;
1416	u32			num_entries;
1417	u32			size;
1418	u32			hook_entry[NF_INET_NUMHOOKS];
1419	u32			underflow[NF_INET_NUMHOOKS];
1420	u32			num_counters;
1421	compat_uptr_t		counters;	/* struct ipt_counters * */
1422	struct compat_ipt_entry	entries[0];
1423};
1424
1425static int
1426compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1427			  unsigned int *size, struct xt_counters *counters,
1428			  unsigned int i)
1429{
1430	struct ipt_entry_target *t;
1431	struct compat_ipt_entry __user *ce;
1432	u_int16_t target_offset, next_offset;
1433	compat_uint_t origsize;
1434	const struct xt_entry_match *ematch;
1435	int ret = 0;
1436
1437	origsize = *size;
1438	ce = (struct compat_ipt_entry __user *)*dstptr;
1439	if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
1440	    copy_to_user(&ce->counters, &counters[i],
1441	    sizeof(counters[i])) != 0)
1442		return -EFAULT;
1443
1444	*dstptr += sizeof(struct compat_ipt_entry);
1445	*size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1446
1447	xt_ematch_foreach(ematch, e) {
1448		ret = xt_compat_match_to_user(ematch, dstptr, size);
1449		if (ret != 0)
1450			return ret;
1451	}
1452	target_offset = e->target_offset - (origsize - *size);
1453	t = ipt_get_target(e);
1454	ret = xt_compat_target_to_user(t, dstptr, size);
1455	if (ret)
1456		return ret;
1457	next_offset = e->next_offset - (origsize - *size);
1458	if (put_user(target_offset, &ce->target_offset) != 0 ||
1459	    put_user(next_offset, &ce->next_offset) != 0)
1460		return -EFAULT;
1461	return 0;
1462}
1463
1464static int
1465compat_find_calc_match(struct ipt_entry_match *m,
1466		       const char *name,
1467		       const struct ipt_ip *ip,
1468		       unsigned int hookmask,
1469		       int *size)
1470{
1471	struct xt_match *match;
1472
1473	match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
1474				      m->u.user.revision);
1475	if (IS_ERR(match)) {
1476		duprintf("compat_check_calc_match: `%s' not found\n",
1477			 m->u.user.name);
1478		return PTR_ERR(match);
1479	}
1480	m->u.kernel.match = match;
1481	*size += xt_compat_match_offset(match);
1482	return 0;
1483}
1484
1485static void compat_release_entry(struct compat_ipt_entry *e)
1486{
1487	struct ipt_entry_target *t;
1488	struct xt_entry_match *ematch;
1489
1490	/* Cleanup all matches */
1491	xt_ematch_foreach(ematch, e)
1492		module_put(ematch->u.kernel.match->me);
1493	t = compat_ipt_get_target(e);
1494	module_put(t->u.kernel.target->me);
1495}
1496
1497static int
1498check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1499				  struct xt_table_info *newinfo,
1500				  unsigned int *size,
1501				  const unsigned char *base,
1502				  const unsigned char *limit,
1503				  const unsigned int *hook_entries,
1504				  const unsigned int *underflows,
1505				  const char *name)
1506{
1507	struct xt_entry_match *ematch;
1508	struct ipt_entry_target *t;
1509	struct xt_target *target;
1510	unsigned int entry_offset;
1511	unsigned int j;
1512	int ret, off, h;
1513
1514	duprintf("check_compat_entry_size_and_hooks %p\n", e);
1515	if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1516	    (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1517		duprintf("Bad offset %p, limit = %p\n", e, limit);
1518		return -EINVAL;
1519	}
1520
1521	if (e->next_offset < sizeof(struct compat_ipt_entry) +
1522			     sizeof(struct compat_xt_entry_target)) {
1523		duprintf("checking: element %p size %u\n",
1524			 e, e->next_offset);
1525		return -EINVAL;
1526	}
1527
1528	/* For purposes of check_entry casting the compat entry is fine */
1529	ret = check_entry((struct ipt_entry *)e, name);
1530	if (ret)
1531		return ret;
1532
1533	off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1534	entry_offset = (void *)e - (void *)base;
1535	j = 0;
1536	xt_ematch_foreach(ematch, e) {
1537		ret = compat_find_calc_match(ematch, name,
1538					     &e->ip, e->comefrom, &off);
1539		if (ret != 0)
1540			goto release_matches;
1541		++j;
1542	}
1543
1544	t = compat_ipt_get_target(e);
1545	target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
1546					t->u.user.revision);
1547	if (IS_ERR(target)) {
1548		duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1549			 t->u.user.name);
1550		ret = PTR_ERR(target);
1551		goto release_matches;
1552	}
1553	t->u.kernel.target = target;
1554
1555	off += xt_compat_target_offset(target);
1556	*size += off;
1557	ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1558	if (ret)
1559		goto out;
1560
1561	/* Check hooks & underflows */
1562	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1563		if ((unsigned char *)e - base == hook_entries[h])
1564			newinfo->hook_entry[h] = hook_entries[h];
1565		if ((unsigned char *)e - base == underflows[h])
1566			newinfo->underflow[h] = underflows[h];
1567	}
1568
1569	/* Clear counters and comefrom */
1570	memset(&e->counters, 0, sizeof(e->counters));
1571	e->comefrom = 0;
1572	return 0;
1573
1574out:
1575	module_put(t->u.kernel.target->me);
1576release_matches:
1577	xt_ematch_foreach(ematch, e) {
1578		if (j-- == 0)
1579			break;
1580		module_put(ematch->u.kernel.match->me);
1581	}
1582	return ret;
1583}
1584
1585static int
1586compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1587			    unsigned int *size, const char *name,
1588			    struct xt_table_info *newinfo, unsigned char *base)
1589{
1590	struct ipt_entry_target *t;
1591	struct xt_target *target;
1592	struct ipt_entry *de;
1593	unsigned int origsize;
1594	int ret, h;
1595	struct xt_entry_match *ematch;
1596
1597	ret = 0;
1598	origsize = *size;
1599	de = (struct ipt_entry *)*dstptr;
1600	memcpy(de, e, sizeof(struct ipt_entry));
1601	memcpy(&de->counters, &e->counters, sizeof(e->counters));
1602
1603	*dstptr += sizeof(struct ipt_entry);
1604	*size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1605
1606	xt_ematch_foreach(ematch, e) {
1607		ret = xt_compat_match_from_user(ematch, dstptr, size);
1608		if (ret != 0)
1609			return ret;
1610	}
1611	de->target_offset = e->target_offset - (origsize - *size);
1612	t = compat_ipt_get_target(e);
1613	target = t->u.kernel.target;
1614	xt_compat_target_from_user(t, dstptr, size);
1615
1616	de->next_offset = e->next_offset - (origsize - *size);
1617	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1618		if ((unsigned char *)de - base < newinfo->hook_entry[h])
1619			newinfo->hook_entry[h] -= origsize - *size;
1620		if ((unsigned char *)de - base < newinfo->underflow[h])
1621			newinfo->underflow[h] -= origsize - *size;
1622	}
1623	return ret;
1624}
1625
1626static int
1627compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1628{
1629	struct xt_entry_match *ematch;
1630	struct xt_mtchk_param mtpar;
1631	unsigned int j;
1632	int ret = 0;
1633
1634	j = 0;
1635	mtpar.net	= net;
1636	mtpar.table     = name;
1637	mtpar.entryinfo = &e->ip;
1638	mtpar.hook_mask = e->comefrom;
1639	mtpar.family    = NFPROTO_IPV4;
1640	xt_ematch_foreach(ematch, e) {
1641		ret = check_match(ematch, &mtpar);
1642		if (ret != 0)
1643			goto cleanup_matches;
1644		++j;
1645	}
1646
1647	ret = check_target(e, net, name);
1648	if (ret)
1649		goto cleanup_matches;
1650	return 0;
1651
1652 cleanup_matches:
1653	xt_ematch_foreach(ematch, e) {
1654		if (j-- == 0)
1655			break;
1656		cleanup_match(ematch, net);
1657	}
1658	return ret;
1659}
1660
1661static int
1662translate_compat_table(struct net *net,
1663		       const char *name,
1664		       unsigned int valid_hooks,
1665		       struct xt_table_info **pinfo,
1666		       void **pentry0,
1667		       unsigned int total_size,
1668		       unsigned int number,
1669		       unsigned int *hook_entries,
1670		       unsigned int *underflows)
1671{
1672	unsigned int i, j;
1673	struct xt_table_info *newinfo, *info;
1674	void *pos, *entry0, *entry1;
1675	struct compat_ipt_entry *iter0;
1676	struct ipt_entry *iter1;
1677	unsigned int size;
1678	int ret;
1679
1680	info = *pinfo;
1681	entry0 = *pentry0;
1682	size = total_size;
1683	info->number = number;
1684
1685	/* Init all hooks to impossible value. */
1686	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1687		info->hook_entry[i] = 0xFFFFFFFF;
1688		info->underflow[i] = 0xFFFFFFFF;
1689	}
1690
1691	duprintf("translate_compat_table: size %u\n", info->size);
1692	j = 0;
1693	xt_compat_lock(AF_INET);
1694	/* Walk through entries, checking offsets. */
1695	xt_entry_foreach(iter0, entry0, total_size) {
1696		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1697							entry0,
1698							entry0 + total_size,
1699							hook_entries,
1700							underflows,
1701							name);
1702		if (ret != 0)
1703			goto out_unlock;
1704		++j;
1705	}
1706
1707	ret = -EINVAL;
1708	if (j != number) {
1709		duprintf("translate_compat_table: %u not %u entries\n",
1710			 j, number);
1711		goto out_unlock;
1712	}
1713
1714	/* Check hooks all assigned */
1715	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1716		/* Only hooks which are valid */
1717		if (!(valid_hooks & (1 << i)))
1718			continue;
1719		if (info->hook_entry[i] == 0xFFFFFFFF) {
1720			duprintf("Invalid hook entry %u %u\n",
1721				 i, hook_entries[i]);
1722			goto out_unlock;
1723		}
1724		if (info->underflow[i] == 0xFFFFFFFF) {
1725			duprintf("Invalid underflow %u %u\n",
1726				 i, underflows[i]);
1727			goto out_unlock;
1728		}
1729	}
1730
1731	ret = -ENOMEM;
1732	newinfo = xt_alloc_table_info(size);
1733	if (!newinfo)
1734		goto out_unlock;
1735
1736	newinfo->number = number;
1737	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1738		newinfo->hook_entry[i] = info->hook_entry[i];
1739		newinfo->underflow[i] = info->underflow[i];
1740	}
1741	entry1 = newinfo->entries[raw_smp_processor_id()];
1742	pos = entry1;
1743	size = total_size;
1744	xt_entry_foreach(iter0, entry0, total_size) {
1745		ret = compat_copy_entry_from_user(iter0, &pos, &size,
1746						  name, newinfo, entry1);
1747		if (ret != 0)
1748			break;
1749	}
1750	xt_compat_flush_offsets(AF_INET);
1751	xt_compat_unlock(AF_INET);
1752	if (ret)
1753		goto free_newinfo;
1754
1755	ret = -ELOOP;
1756	if (!mark_source_chains(newinfo, valid_hooks, entry1))
1757		goto free_newinfo;
1758
1759	i = 0;
1760	xt_entry_foreach(iter1, entry1, newinfo->size) {
1761		ret = compat_check_entry(iter1, net, name);
1762		if (ret != 0)
1763			break;
1764		++i;
1765		if (strcmp(ipt_get_target(iter1)->u.user.name,
1766		    XT_ERROR_TARGET) == 0)
1767			++newinfo->stacksize;
1768	}
1769	if (ret) {
1770		/*
1771		 * The first i matches need cleanup_entry (calls ->destroy)
1772		 * because they had called ->check already. The other j-i
1773		 * entries need only release.
1774		 */
1775		int skip = i;
1776		j -= i;
1777		xt_entry_foreach(iter0, entry0, newinfo->size) {
1778			if (skip-- > 0)
1779				continue;
1780			if (j-- == 0)
1781				break;
1782			compat_release_entry(iter0);
1783		}
1784		xt_entry_foreach(iter1, entry1, newinfo->size) {
1785			if (i-- == 0)
1786				break;
1787			cleanup_entry(iter1, net);
1788		}
1789		xt_free_table_info(newinfo);
1790		return ret;
1791	}
1792
1793	/* And one copy for every other CPU */
1794	for_each_possible_cpu(i)
1795		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1796			memcpy(newinfo->entries[i], entry1, newinfo->size);
1797
1798	*pinfo = newinfo;
1799	*pentry0 = entry1;
1800	xt_free_table_info(info);
1801	return 0;
1802
1803free_newinfo:
1804	xt_free_table_info(newinfo);
1805out:
1806	xt_entry_foreach(iter0, entry0, total_size) {
1807		if (j-- == 0)
1808			break;
1809		compat_release_entry(iter0);
1810	}
1811	return ret;
1812out_unlock:
1813	xt_compat_flush_offsets(AF_INET);
1814	xt_compat_unlock(AF_INET);
1815	goto out;
1816}
1817
1818static int
1819compat_do_replace(struct net *net, void __user *user, unsigned int len)
1820{
1821	int ret;
1822	struct compat_ipt_replace tmp;
1823	struct xt_table_info *newinfo;
1824	void *loc_cpu_entry;
1825	struct ipt_entry *iter;
1826
1827	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1828		return -EFAULT;
1829
1830	/* overflow check */
1831	if (tmp.size >= INT_MAX / num_possible_cpus())
1832		return -ENOMEM;
1833	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1834		return -ENOMEM;
1835
1836	newinfo = xt_alloc_table_info(tmp.size);
1837	if (!newinfo)
1838		return -ENOMEM;
1839
1840	/* choose the copy that is on our node/cpu */
1841	loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1842	if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1843			   tmp.size) != 0) {
1844		ret = -EFAULT;
1845		goto free_newinfo;
1846	}
1847
1848	ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1849				     &newinfo, &loc_cpu_entry, tmp.size,
1850				     tmp.num_entries, tmp.hook_entry,
1851				     tmp.underflow);
1852	if (ret != 0)
1853		goto free_newinfo;
1854
1855	duprintf("compat_do_replace: Translated table\n");
1856
1857	ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1858			   tmp.num_counters, compat_ptr(tmp.counters));
1859	if (ret)
1860		goto free_newinfo_untrans;
1861	return 0;
1862
1863 free_newinfo_untrans:
1864	xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1865		cleanup_entry(iter, net);
1866 free_newinfo:
1867	xt_free_table_info(newinfo);
1868	return ret;
1869}
1870
1871static int
1872compat_do_ipt_set_ctl(struct sock *sk,	int cmd, void __user *user,
1873		      unsigned int len)
1874{
1875	int ret;
1876
1877	if (!capable(CAP_NET_ADMIN))
1878		return -EPERM;
1879
1880	switch (cmd) {
1881	case IPT_SO_SET_REPLACE:
1882		ret = compat_do_replace(sock_net(sk), user, len);
1883		break;
1884
1885	case IPT_SO_SET_ADD_COUNTERS:
1886		ret = do_add_counters(sock_net(sk), user, len, 1);
1887		break;
1888
1889	default:
1890		duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
1891		ret = -EINVAL;
1892	}
1893
1894	return ret;
1895}
1896
1897struct compat_ipt_get_entries {
1898	char name[IPT_TABLE_MAXNAMELEN];
1899	compat_uint_t size;
1900	struct compat_ipt_entry entrytable[0];
1901};
1902
1903static int
1904compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1905			    void __user *userptr)
1906{
1907	struct xt_counters *counters;
1908	const struct xt_table_info *private = table->private;
1909	void __user *pos;
1910	unsigned int size;
1911	int ret = 0;
1912	const void *loc_cpu_entry;
1913	unsigned int i = 0;
1914	struct ipt_entry *iter;
1915
1916	counters = alloc_counters(table);
1917	if (IS_ERR(counters))
1918		return PTR_ERR(counters);
1919
1920	/* choose the copy that is on our node/cpu, ...
1921	 * This choice is lazy (because current thread is
1922	 * allowed to migrate to another cpu)
1923	 */
1924	loc_cpu_entry = private->entries[raw_smp_processor_id()];
1925	pos = userptr;
1926	size = total_size;
1927	xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1928		ret = compat_copy_entry_to_user(iter, &pos,
1929						&size, counters, i++);
1930		if (ret != 0)
1931			break;
1932	}
1933
1934	vfree(counters);
1935	return ret;
1936}
1937
1938static int
1939compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1940		   int *len)
1941{
1942	int ret;
1943	struct compat_ipt_get_entries get;
1944	struct xt_table *t;
1945
1946	if (*len < sizeof(get)) {
1947		duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1948		return -EINVAL;
1949	}
1950
1951	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1952		return -EFAULT;
1953
1954	if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1955		duprintf("compat_get_entries: %u != %zu\n",
1956			 *len, sizeof(get) + get.size);
1957		return -EINVAL;
1958	}
1959
1960	xt_compat_lock(AF_INET);
1961	t = xt_find_table_lock(net, AF_INET, get.name);
1962	if (t && !IS_ERR(t)) {
1963		const struct xt_table_info *private = t->private;
1964		struct xt_table_info info;
1965		duprintf("t->private->number = %u\n", private->number);
1966		ret = compat_table_info(private, &info);
1967		if (!ret && get.size == info.size) {
1968			ret = compat_copy_entries_to_user(private->size,
1969							  t, uptr->entrytable);
1970		} else if (!ret) {
1971			duprintf("compat_get_entries: I've got %u not %u!\n",
1972				 private->size, get.size);
1973			ret = -EAGAIN;
1974		}
1975		xt_compat_flush_offsets(AF_INET);
1976		module_put(t->me);
1977		xt_table_unlock(t);
1978	} else
1979		ret = t ? PTR_ERR(t) : -ENOENT;
1980
1981	xt_compat_unlock(AF_INET);
1982	return ret;
1983}
1984
1985static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1986
1987static int
1988compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1989{
1990	int ret;
1991
1992	if (!capable(CAP_NET_ADMIN))
1993		return -EPERM;
1994
1995	switch (cmd) {
1996	case IPT_SO_GET_INFO:
1997		ret = get_info(sock_net(sk), user, len, 1);
1998		break;
1999	case IPT_SO_GET_ENTRIES:
2000		ret = compat_get_entries(sock_net(sk), user, len);
2001		break;
2002	default:
2003		ret = do_ipt_get_ctl(sk, cmd, user, len);
2004	}
2005	return ret;
2006}
2007#endif
2008
2009static int
2010do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2011{
2012	int ret;
2013
2014	if (!capable(CAP_NET_ADMIN))
2015		return -EPERM;
2016
2017	switch (cmd) {
2018	case IPT_SO_SET_REPLACE:
2019		ret = do_replace(sock_net(sk), user, len);
2020		break;
2021
2022	case IPT_SO_SET_ADD_COUNTERS:
2023		ret = do_add_counters(sock_net(sk), user, len, 0);
2024		break;
2025
2026	default:
2027		duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
2028		ret = -EINVAL;
2029	}
2030
2031	return ret;
2032}
2033
2034static int
2035do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2036{
2037	int ret;
2038
2039	if (!capable(CAP_NET_ADMIN))
2040		return -EPERM;
2041
2042	switch (cmd) {
2043	case IPT_SO_GET_INFO:
2044		ret = get_info(sock_net(sk), user, len, 0);
2045		break;
2046
2047	case IPT_SO_GET_ENTRIES:
2048		ret = get_entries(sock_net(sk), user, len);
2049		break;
2050
2051	case IPT_SO_GET_REVISION_MATCH:
2052	case IPT_SO_GET_REVISION_TARGET: {
2053		struct ipt_get_revision rev;
2054		int target;
2055
2056		if (*len != sizeof(rev)) {
2057			ret = -EINVAL;
2058			break;
2059		}
2060		if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2061			ret = -EFAULT;
2062			break;
2063		}
2064
2065		if (cmd == IPT_SO_GET_REVISION_TARGET)
2066			target = 1;
2067		else
2068			target = 0;
2069
2070		try_then_request_module(xt_find_revision(AF_INET, rev.name,
2071							 rev.revision,
2072							 target, &ret),
2073					"ipt_%s", rev.name);
2074		break;
2075	}
2076
2077	default:
2078		duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2079		ret = -EINVAL;
2080	}
2081
2082	return ret;
2083}
2084
2085struct xt_table *ipt_register_table(struct net *net,
2086				    const struct xt_table *table,
2087				    const struct ipt_replace *repl)
2088{
2089	int ret;
2090	struct xt_table_info *newinfo;
2091	struct xt_table_info bootstrap = {0};
2092	void *loc_cpu_entry;
2093	struct xt_table *new_table;
2094
2095	newinfo = xt_alloc_table_info(repl->size);
2096	if (!newinfo) {
2097		ret = -ENOMEM;
2098		goto out;
2099	}
2100
2101	/* choose the copy on our node/cpu, but dont care about preemption */
2102	loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2103	memcpy(loc_cpu_entry, repl->entries, repl->size);
2104
2105	ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2106	if (ret != 0)
2107		goto out_free;
2108
2109	new_table = xt_register_table(net, table, &bootstrap, newinfo);
2110	if (IS_ERR(new_table)) {
2111		ret = PTR_ERR(new_table);
2112		goto out_free;
2113	}
2114
2115	return new_table;
2116
2117out_free:
2118	xt_free_table_info(newinfo);
2119out:
2120	return ERR_PTR(ret);
2121}
2122
2123void ipt_unregister_table(struct net *net, struct xt_table *table)
2124{
2125	struct xt_table_info *private;
2126	void *loc_cpu_entry;
2127	struct module *table_owner = table->me;
2128	struct ipt_entry *iter;
2129
2130	private = xt_unregister_table(table);
2131
2132	/* Decrease module usage counts and free resources */
2133	loc_cpu_entry = private->entries[raw_smp_processor_id()];
2134	xt_entry_foreach(iter, loc_cpu_entry, private->size)
2135		cleanup_entry(iter, net);
2136	if (private->number > private->initial_entries)
2137		module_put(table_owner);
2138	xt_free_table_info(private);
2139}
2140
2141/* Returns 1 if the type and code is matched by the range, 0 otherwise */
2142static inline bool
2143icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2144		     u_int8_t type, u_int8_t code,
2145		     bool invert)
2146{
2147	return ((test_type == 0xFF) ||
2148		(type == test_type && code >= min_code && code <= max_code))
2149		^ invert;
2150}
2151
2152static bool
2153icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
2154{
2155	const struct icmphdr *ic;
2156	struct icmphdr _icmph;
2157	const struct ipt_icmp *icmpinfo = par->matchinfo;
2158
2159	/* Must not be a fragment. */
2160	if (par->fragoff != 0)
2161		return false;
2162
2163	ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2164	if (ic == NULL) {
2165		/* We've been asked to examine this packet, and we
2166		 * can't.  Hence, no choice but to drop.
2167		 */
2168		duprintf("Dropping evil ICMP tinygram.\n");
2169		par->hotdrop = true;
2170		return false;
2171	}
2172
2173	return icmp_type_code_match(icmpinfo->type,
2174				    icmpinfo->code[0],
2175				    icmpinfo->code[1],
2176				    ic->type, ic->code,
2177				    !!(icmpinfo->invflags&IPT_ICMP_INV));
2178}
2179
2180static int icmp_checkentry(const struct xt_mtchk_param *par)
2181{
2182	const struct ipt_icmp *icmpinfo = par->matchinfo;
2183
2184	/* Must specify no unknown invflags */
2185	return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
2186}
2187
2188static struct xt_target ipt_builtin_tg[] __read_mostly = {
2189	{
2190		.name             = IPT_STANDARD_TARGET,
2191		.targetsize       = sizeof(int),
2192		.family           = NFPROTO_IPV4,
2193#ifdef CONFIG_COMPAT
2194		.compatsize       = sizeof(compat_int_t),
2195		.compat_from_user = compat_standard_from_user,
2196		.compat_to_user   = compat_standard_to_user,
2197#endif
2198	},
2199	{
2200		.name             = IPT_ERROR_TARGET,
2201		.target           = ipt_error,
2202		.targetsize       = IPT_FUNCTION_MAXNAMELEN,
2203		.family           = NFPROTO_IPV4,
2204	},
2205};
2206
2207static struct nf_sockopt_ops ipt_sockopts = {
2208	.pf		= PF_INET,
2209	.set_optmin	= IPT_BASE_CTL,
2210	.set_optmax	= IPT_SO_SET_MAX+1,
2211	.set		= do_ipt_set_ctl,
2212#ifdef CONFIG_COMPAT
2213	.compat_set	= compat_do_ipt_set_ctl,
2214#endif
2215	.get_optmin	= IPT_BASE_CTL,
2216	.get_optmax	= IPT_SO_GET_MAX+1,
2217	.get		= do_ipt_get_ctl,
2218#ifdef CONFIG_COMPAT
2219	.compat_get	= compat_do_ipt_get_ctl,
2220#endif
2221	.owner		= THIS_MODULE,
2222};
2223
2224static struct xt_match ipt_builtin_mt[] __read_mostly = {
2225	{
2226		.name       = "icmp",
2227		.match      = icmp_match,
2228		.matchsize  = sizeof(struct ipt_icmp),
2229		.checkentry = icmp_checkentry,
2230		.proto      = IPPROTO_ICMP,
2231		.family     = NFPROTO_IPV4,
2232	},
2233};
2234
2235static int __net_init ip_tables_net_init(struct net *net)
2236{
2237	return xt_proto_init(net, NFPROTO_IPV4);
2238}
2239
2240static void __net_exit ip_tables_net_exit(struct net *net)
2241{
2242	xt_proto_fini(net, NFPROTO_IPV4);
2243}
2244
2245static struct pernet_operations ip_tables_net_ops = {
2246	.init = ip_tables_net_init,
2247	.exit = ip_tables_net_exit,
2248};
2249
2250static int __init ip_tables_init(void)
2251{
2252	int ret;
2253
2254	ret = register_pernet_subsys(&ip_tables_net_ops);
2255	if (ret < 0)
2256		goto err1;
2257
2258	/* Noone else will be downing sem now, so we won't sleep */
2259	ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2260	if (ret < 0)
2261		goto err2;
2262	ret = xt_register_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2263	if (ret < 0)
2264		goto err4;
2265
2266	/* Register setsockopt */
2267	ret = nf_register_sockopt(&ipt_sockopts);
2268	if (ret < 0)
2269		goto err5;
2270
2271	pr_info("(C) 2000-2006 Netfilter Core Team\n");
2272	return 0;
2273
2274err5:
2275	xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2276err4:
2277	xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2278err2:
2279	unregister_pernet_subsys(&ip_tables_net_ops);
2280err1:
2281	return ret;
2282}
2283
2284static void __exit ip_tables_fini(void)
2285{
2286	nf_unregister_sockopt(&ipt_sockopts);
2287
2288	xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2289	xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2290	unregister_pernet_subsys(&ip_tables_net_ops);
2291}
2292
2293EXPORT_SYMBOL(ipt_register_table);
2294EXPORT_SYMBOL(ipt_unregister_table);
2295EXPORT_SYMBOL(ipt_do_table);
2296module_init(ip_tables_init);
2297module_exit(ip_tables_fini);
2298