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