Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ip6_tables.c
Go to the documentation of this file.
1 /*
2  * Packet matching code.
3  *
4  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5  * Copyright (C) 2000-2005 Netfilter Core Team <[email protected]>
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 <[email protected]>");
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 
67 {
68  return xt_alloc_initial_table(ip6t, IP6T);
69 }
71 
72 /*
73  We keep a set of rules for each CPU, so we can avoid write-locking
74  them in the softirq when updating the counters and therefore
75  only need to read-lock in the softirq; doing a write_lock_bh() in user
76  context stops packets coming through and allows user context to read
77  the counters or update the rules.
78 
79  Hence the start of any table is given by get_table() below. */
80 
81 /* Returns whether matches rule or not. */
82 /* Performance critical - called for every packet */
83 static inline bool
84 ip6_packet_match(const struct sk_buff *skb,
85  const char *indev,
86  const char *outdev,
87  const struct ip6t_ip6 *ip6info,
88  unsigned int *protoff,
89  int *fragoff, bool *hotdrop)
90 {
91  unsigned long ret;
92  const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
93 
94 #define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg)))
95 
96  if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
97  &ip6info->src), IP6T_INV_SRCIP) ||
98  FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
99  &ip6info->dst), IP6T_INV_DSTIP)) {
100  dprintf("Source or dest mismatch.\n");
101 /*
102  dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
103  ipinfo->smsk.s_addr, ipinfo->src.s_addr,
104  ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : "");
105  dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
106  ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
107  ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
108  return false;
109  }
110 
111  ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask);
112 
113  if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
114  dprintf("VIA in mismatch (%s vs %s).%s\n",
115  indev, ip6info->iniface,
116  ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
117  return false;
118  }
119 
120  ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask);
121 
122  if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
123  dprintf("VIA out mismatch (%s vs %s).%s\n",
124  outdev, ip6info->outiface,
125  ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
126  return false;
127  }
128 
129 /* ... might want to do something with class and flowlabel here ... */
130 
131  /* look for the desired protocol header */
132  if((ip6info->flags & IP6T_F_PROTO)) {
133  int protohdr;
134  unsigned short _frag_off;
135 
136  protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off, NULL);
137  if (protohdr < 0) {
138  if (_frag_off == 0)
139  *hotdrop = true;
140  return false;
141  }
142  *fragoff = _frag_off;
143 
144  dprintf("Packet protocol %hi ?= %s%hi.\n",
145  protohdr,
146  ip6info->invflags & IP6T_INV_PROTO ? "!":"",
147  ip6info->proto);
148 
149  if (ip6info->proto == protohdr) {
150  if(ip6info->invflags & IP6T_INV_PROTO) {
151  return false;
152  }
153  return true;
154  }
155 
156  /* We need match for the '-p all', too! */
157  if ((ip6info->proto != 0) &&
158  !(ip6info->invflags & IP6T_INV_PROTO))
159  return false;
160  }
161  return true;
162 }
163 
164 /* should be ip6 safe */
165 static bool
166 ip6_checkentry(const struct ip6t_ip6 *ipv6)
167 {
168  if (ipv6->flags & ~IP6T_F_MASK) {
169  duprintf("Unknown flag bits set: %08X\n",
170  ipv6->flags & ~IP6T_F_MASK);
171  return false;
172  }
173  if (ipv6->invflags & ~IP6T_INV_MASK) {
174  duprintf("Unknown invflag bits set: %08X\n",
175  ipv6->invflags & ~IP6T_INV_MASK);
176  return false;
177  }
178  return true;
179 }
180 
181 static unsigned int
182 ip6t_error(struct sk_buff *skb, const struct xt_action_param *par)
183 {
184  net_info_ratelimited("error: `%s'\n", (const char *)par->targinfo);
185 
186  return NF_DROP;
187 }
188 
189 static inline struct ip6t_entry *
190 get_entry(const void *base, unsigned int offset)
191 {
192  return (struct ip6t_entry *)(base + offset);
193 }
194 
195 /* All zeroes == unconditional rule. */
196 /* Mildly perf critical (only if packet tracing is on) */
197 static inline bool unconditional(const struct ip6t_ip6 *ipv6)
198 {
199  static const struct ip6t_ip6 uncond;
200 
201  return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
202 }
203 
204 static inline const struct xt_entry_target *
205 ip6t_get_target_c(const struct ip6t_entry *e)
206 {
207  return ip6t_get_target((struct ip6t_entry *)e);
208 }
209 
210 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
211  defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
212 /* This cries for unification! */
213 static const char *const hooknames[] = {
214  [NF_INET_PRE_ROUTING] = "PREROUTING",
215  [NF_INET_LOCAL_IN] = "INPUT",
216  [NF_INET_FORWARD] = "FORWARD",
217  [NF_INET_LOCAL_OUT] = "OUTPUT",
218  [NF_INET_POST_ROUTING] = "POSTROUTING",
219 };
220 
221 enum nf_ip_trace_comments {
222  NF_IP6_TRACE_COMMENT_RULE,
223  NF_IP6_TRACE_COMMENT_RETURN,
224  NF_IP6_TRACE_COMMENT_POLICY,
225 };
226 
227 static const char *const comments[] = {
228  [NF_IP6_TRACE_COMMENT_RULE] = "rule",
229  [NF_IP6_TRACE_COMMENT_RETURN] = "return",
230  [NF_IP6_TRACE_COMMENT_POLICY] = "policy",
231 };
232 
233 static struct nf_loginfo trace_loginfo = {
235  .u = {
236  .log = {
237  .level = 4,
238  .logflags = NF_LOG_MASK,
239  },
240  },
241 };
242 
243 /* Mildly perf critical (only if packet tracing is on) */
244 static inline int
245 get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
246  const char *hookname, const char **chainname,
247  const char **comment, unsigned int *rulenum)
248 {
249  const struct xt_standard_target *t = (void *)ip6t_get_target_c(s);
250 
251  if (strcmp(t->target.u.kernel.target->name, XT_ERROR_TARGET) == 0) {
252  /* Head of user chain: ERROR target with chainname */
253  *chainname = t->target.data;
254  (*rulenum) = 0;
255  } else if (s == e) {
256  (*rulenum)++;
257 
258  if (s->target_offset == sizeof(struct ip6t_entry) &&
259  strcmp(t->target.u.kernel.target->name,
260  XT_STANDARD_TARGET) == 0 &&
261  t->verdict < 0 &&
262  unconditional(&s->ipv6)) {
263  /* Tail of chains: STANDARD target (return/policy) */
264  *comment = *chainname == hookname
265  ? comments[NF_IP6_TRACE_COMMENT_POLICY]
266  : comments[NF_IP6_TRACE_COMMENT_RETURN];
267  }
268  return 1;
269  } else
270  (*rulenum)++;
271 
272  return 0;
273 }
274 
275 static void trace_packet(const struct sk_buff *skb,
276  unsigned int hook,
277  const struct net_device *in,
278  const struct net_device *out,
279  const char *tablename,
280  const struct xt_table_info *private,
281  const struct ip6t_entry *e)
282 {
283  const void *table_base;
284  const struct ip6t_entry *root;
285  const char *hookname, *chainname, *comment;
286  const struct ip6t_entry *iter;
287  unsigned int rulenum = 0;
288 
289  table_base = private->entries[smp_processor_id()];
290  root = get_entry(table_base, private->hook_entry[hook]);
291 
292  hookname = chainname = hooknames[hook];
293  comment = comments[NF_IP6_TRACE_COMMENT_RULE];
294 
295  xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
296  if (get_chainname_rulenum(iter, e, hookname,
297  &chainname, &comment, &rulenum) != 0)
298  break;
299 
300  nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
301  "TRACE: %s:%s:%s:%u ",
302  tablename, chainname, comment, rulenum);
303 }
304 #endif
305 
306 static inline __pure struct ip6t_entry *
307 ip6t_next_entry(const struct ip6t_entry *entry)
308 {
309  return (void *)entry + entry->next_offset;
310 }
311 
312 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
313 unsigned int
314 ip6t_do_table(struct sk_buff *skb,
315  unsigned int hook,
316  const struct net_device *in,
317  const struct net_device *out,
318  struct xt_table *table)
319 {
320  static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
321  /* Initializing verdict to NF_DROP keeps gcc happy. */
322  unsigned int verdict = NF_DROP;
323  const char *indev, *outdev;
324  const void *table_base;
325  struct ip6t_entry *e, **jumpstack;
326  unsigned int *stackptr, origptr, cpu;
327  const struct xt_table_info *private;
328  struct xt_action_param acpar;
329  unsigned int addend;
330 
331  /* Initialization */
332  indev = in ? in->name : nulldevname;
333  outdev = out ? out->name : nulldevname;
334  /* We handle fragments by dealing with the first fragment as
335  * if it was a normal packet. All other fragments are treated
336  * normally, except that they will NEVER match rules that ask
337  * things we don't know, ie. tcp syn flag or ports). If the
338  * rule is also a fragment-specific rule, non-fragments won't
339  * match it. */
340  acpar.hotdrop = false;
341  acpar.in = in;
342  acpar.out = out;
343  acpar.family = NFPROTO_IPV6;
344  acpar.hooknum = hook;
345 
346  IP_NF_ASSERT(table->valid_hooks & (1 << hook));
347 
349  addend = xt_write_recseq_begin();
350  private = table->private;
351  cpu = smp_processor_id();
352  table_base = private->entries[cpu];
353  jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];
354  stackptr = per_cpu_ptr(private->stackptr, cpu);
355  origptr = *stackptr;
356 
357  e = get_entry(table_base, private->hook_entry[hook]);
358 
359  do {
360  const struct xt_entry_target *t;
361  const struct xt_entry_match *ematch;
362 
363  IP_NF_ASSERT(e);
364  acpar.thoff = 0;
365  if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
366  &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) {
367  no_match:
368  e = ip6t_next_entry(e);
369  continue;
370  }
371 
372  xt_ematch_foreach(ematch, e) {
373  acpar.match = ematch->u.kernel.match;
374  acpar.matchinfo = ematch->data;
375  if (!acpar.match->match(skb, &acpar))
376  goto no_match;
377  }
378 
379  ADD_COUNTER(e->counters, skb->len, 1);
380 
381  t = ip6t_get_target_c(e);
382  IP_NF_ASSERT(t->u.kernel.target);
383 
384 #if 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 int)(-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 */
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 */
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 
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];
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 
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 
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 
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,
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  * Note that *offset is used as input/output parameter. an if it is not zero,
2282  * then it must be a valid offset to an inner IPv6 header. This can be used
2283  * to explore inner IPv6 header, eg. ICMPv6 error messages.
2284  *
2285  * If target header is found, its offset is set in *offset and return protocol
2286  * number. Otherwise, return -1.
2287  *
2288  * If the first fragment doesn't contain the final protocol header or
2289  * NEXTHDR_NONE it is considered invalid.
2290  *
2291  * Note that non-1st fragment is special case that "the protocol number
2292  * of last header" is "next header" field in Fragment header. In this case,
2293  * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
2294  * isn't NULL.
2295  *
2296  * if flags is not NULL and it's a fragment, then the frag flag IP6T_FH_F_FRAG
2297  * will be set. If it's an AH header, the IP6T_FH_F_AUTH flag is set and
2298  * target < 0, then this function will stop at the AH header.
2299  */
2300 int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2301  int target, unsigned short *fragoff, int *flags)
2302 {
2303  unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
2304  u8 nexthdr = ipv6_hdr(skb)->nexthdr;
2305  unsigned int len;
2306 
2307  if (fragoff)
2308  *fragoff = 0;
2309 
2310  if (*offset) {
2311  struct ipv6hdr _ip6, *ip6;
2312 
2313  ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
2314  if (!ip6 || (ip6->version != 6)) {
2315  printk(KERN_ERR "IPv6 header not found\n");
2316  return -EBADMSG;
2317  }
2318  start = *offset + sizeof(struct ipv6hdr);
2319  nexthdr = ip6->nexthdr;
2320  }
2321  len = skb->len - start;
2322 
2323  while (nexthdr != target) {
2324  struct ipv6_opt_hdr _hdr, *hp;
2325  unsigned int hdrlen;
2326 
2327  if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
2328  if (target < 0)
2329  break;
2330  return -ENOENT;
2331  }
2332 
2333  hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
2334  if (hp == NULL)
2335  return -EBADMSG;
2336  if (nexthdr == NEXTHDR_FRAGMENT) {
2337  unsigned short _frag_off;
2338  __be16 *fp;
2339 
2340  if (flags) /* Indicate that this is a fragment */
2341  *flags |= IP6T_FH_F_FRAG;
2342  fp = skb_header_pointer(skb,
2343  start+offsetof(struct frag_hdr,
2344  frag_off),
2345  sizeof(_frag_off),
2346  &_frag_off);
2347  if (fp == NULL)
2348  return -EBADMSG;
2349 
2350  _frag_off = ntohs(*fp) & ~0x7;
2351  if (_frag_off) {
2352  if (target < 0 &&
2353  ((!ipv6_ext_hdr(hp->nexthdr)) ||
2354  hp->nexthdr == NEXTHDR_NONE)) {
2355  if (fragoff)
2356  *fragoff = _frag_off;
2357  return hp->nexthdr;
2358  }
2359  return -ENOENT;
2360  }
2361  hdrlen = 8;
2362  } else if (nexthdr == NEXTHDR_AUTH) {
2363  if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
2364  break;
2365  hdrlen = (hp->hdrlen + 2) << 2;
2366  } else
2367  hdrlen = ipv6_optlen(hp);
2368 
2369  nexthdr = hp->nexthdr;
2370  len -= hdrlen;
2371  start += hdrlen;
2372  }
2373 
2374  *offset = start;
2375  return nexthdr;
2376 }
2377 
2382 
2383 module_init(ip6_tables_init);
2384 module_exit(ip6_tables_fini);