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