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