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