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