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