2  * Packet matching code.
 
   4  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
 
   5  * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
 
   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.
 
  11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
  12 #include <linux/capability.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>
 
  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>
 
  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"
 
  34 MODULE_LICENSE("GPL");
 
  35 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 
  36 MODULE_DESCRIPTION("IPv6 packet filter");
 
  38 /*#define DEBUG_IP_FIREWALL*/
 
  39 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
 
  40 /*#define DEBUG_IP_FIREWALL_USER*/
 
  42 #ifdef DEBUG_IP_FIREWALL
 
  43 #define dprintf(format, args...) pr_info(format , ## args)
 
  45 #define dprintf(format, args...)
 
  48 #ifdef DEBUG_IP_FIREWALL_USER
 
  49 #define duprintf(format, args...) pr_info(format , ## args)
 
  51 #define duprintf(format, args...)
 
  54 #ifdef CONFIG_NETFILTER_DEBUG
 
  55 #define IP_NF_ASSERT(x)                                         \
 
  58                 printk("IP_NF_ASSERT: %s:%s:%u\n",              \
 
  59                        __func__, __FILE__, __LINE__);   \
 
  62 #define IP_NF_ASSERT(x)
 
  66 /* All the better to debug you with... */
 
  71 void *ip6t_alloc_initial_table(const struct xt_table *info)
 
  73         return xt_alloc_initial_table(ip6t, IP6T);
 
  75 EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);
 
  78    We keep a set of rules for each CPU, so we can avoid write-locking
 
  79    them in the softirq when updating the counters and therefore
 
  80    only need to read-lock in the softirq; doing a write_lock_bh() in user
 
  81    context stops packets coming through and allows user context to read
 
  82    the counters or update the rules.
 
  84    Hence the start of any table is given by get_table() below.  */
 
  86 /* Check for an extension */
 
  88 ip6t_ext_hdr(u8 nexthdr)
 
  90         return ( (nexthdr == IPPROTO_HOPOPTS)   ||
 
  91                  (nexthdr == IPPROTO_ROUTING)   ||
 
  92                  (nexthdr == IPPROTO_FRAGMENT)  ||
 
  93                  (nexthdr == IPPROTO_ESP)       ||
 
  94                  (nexthdr == IPPROTO_AH)        ||
 
  95                  (nexthdr == IPPROTO_NONE)      ||
 
  96                  (nexthdr == IPPROTO_DSTOPTS) );
 
  99 /* Returns whether matches rule or not. */
 
 100 /* Performance critical - called for every packet */
 
 102 ip6_packet_match(const struct sk_buff *skb,
 
 105                  const struct ip6t_ip6 *ip6info,
 
 106                  unsigned int *protoff,
 
 107                  int *fragoff, bool *hotdrop)
 
 110         const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
 
 112 #define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg)))
 
 114         if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
 
 115                                        &ip6info->src), IP6T_INV_SRCIP) ||
 
 116             FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
 
 117                                        &ip6info->dst), IP6T_INV_DSTIP)) {
 
 118                 dprintf("Source or dest mismatch.\n");
 
 120                 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
 
 121                         ipinfo->smsk.s_addr, ipinfo->src.s_addr,
 
 122                         ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : "");
 
 123                 dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
 
 124                         ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
 
 125                         ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
 
 129         ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask);
 
 131         if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
 
 132                 dprintf("VIA in mismatch (%s vs %s).%s\n",
 
 133                         indev, ip6info->iniface,
 
 134                         ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
 
 138         ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask);
 
 140         if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
 
 141                 dprintf("VIA out mismatch (%s vs %s).%s\n",
 
 142                         outdev, ip6info->outiface,
 
 143                         ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
 
 147 /* ... might want to do something with class and flowlabel here ... */
 
 149         /* look for the desired protocol header */
 
 150         if((ip6info->flags & IP6T_F_PROTO)) {
 
 152                 unsigned short _frag_off;
 
 154                 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
 
 160                 *fragoff = _frag_off;
 
 162                 dprintf("Packet protocol %hi ?= %s%hi.\n",
 
 164                                 ip6info->invflags & IP6T_INV_PROTO ? "!":"",
 
 167                 if (ip6info->proto == protohdr) {
 
 168                         if(ip6info->invflags & IP6T_INV_PROTO) {
 
 174                 /* We need match for the '-p all', too! */
 
 175                 if ((ip6info->proto != 0) &&
 
 176                         !(ip6info->invflags & IP6T_INV_PROTO))
 
 182 /* should be ip6 safe */
 
 184 ip6_checkentry(const struct ip6t_ip6 *ipv6)
 
 186         if (ipv6->flags & ~IP6T_F_MASK) {
 
 187                 duprintf("Unknown flag bits set: %08X\n",
 
 188                          ipv6->flags & ~IP6T_F_MASK);
 
 191         if (ipv6->invflags & ~IP6T_INV_MASK) {
 
 192                 duprintf("Unknown invflag bits set: %08X\n",
 
 193                          ipv6->invflags & ~IP6T_INV_MASK);
 
 200 ip6t_error(struct sk_buff *skb, const struct xt_action_param *par)
 
 203                 pr_info("error: `%s'\n", (const char *)par->targinfo);
 
 208 static inline struct ip6t_entry *
 
 209 get_entry(const void *base, unsigned int offset)
 
 211         return (struct ip6t_entry *)(base + offset);
 
 214 /* All zeroes == unconditional rule. */
 
 215 /* Mildly perf critical (only if packet tracing is on) */
 
 216 static inline bool unconditional(const struct ip6t_ip6 *ipv6)
 
 218         static const struct ip6t_ip6 uncond;
 
 220         return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
 
 223 static inline const struct ip6t_entry_target *
 
 224 ip6t_get_target_c(const struct ip6t_entry *e)
 
 226         return ip6t_get_target((struct ip6t_entry *)e);
 
 229 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
 
 230     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
 
 231 /* This cries for unification! */
 
 232 static const char *const hooknames[] = {
 
 233         [NF_INET_PRE_ROUTING]           = "PREROUTING",
 
 234         [NF_INET_LOCAL_IN]              = "INPUT",
 
 235         [NF_INET_FORWARD]               = "FORWARD",
 
 236         [NF_INET_LOCAL_OUT]             = "OUTPUT",
 
 237         [NF_INET_POST_ROUTING]          = "POSTROUTING",
 
 240 enum nf_ip_trace_comments {
 
 241         NF_IP6_TRACE_COMMENT_RULE,
 
 242         NF_IP6_TRACE_COMMENT_RETURN,
 
 243         NF_IP6_TRACE_COMMENT_POLICY,
 
 246 static const char *const comments[] = {
 
 247         [NF_IP6_TRACE_COMMENT_RULE]     = "rule",
 
 248         [NF_IP6_TRACE_COMMENT_RETURN]   = "return",
 
 249         [NF_IP6_TRACE_COMMENT_POLICY]   = "policy",
 
 252 static struct nf_loginfo trace_loginfo = {
 
 253         .type = NF_LOG_TYPE_LOG,
 
 257                         .logflags = NF_LOG_MASK,
 
 262 /* Mildly perf critical (only if packet tracing is on) */
 
 264 get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
 
 265                       const char *hookname, const char **chainname,
 
 266                       const char **comment, unsigned int *rulenum)
 
 268         const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s);
 
 270         if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
 
 271                 /* Head of user chain: ERROR target with chainname */
 
 272                 *chainname = t->target.data;
 
 277                 if (s->target_offset == sizeof(struct ip6t_entry) &&
 
 278                     strcmp(t->target.u.kernel.target->name,
 
 279                            IP6T_STANDARD_TARGET) == 0 &&
 
 281                     unconditional(&s->ipv6)) {
 
 282                         /* Tail of chains: STANDARD target (return/policy) */
 
 283                         *comment = *chainname == hookname
 
 284                                 ? comments[NF_IP6_TRACE_COMMENT_POLICY]
 
 285                                 : comments[NF_IP6_TRACE_COMMENT_RETURN];
 
 294 static void trace_packet(const struct sk_buff *skb,
 
 296                          const struct net_device *in,
 
 297                          const struct net_device *out,
 
 298                          const char *tablename,
 
 299                          const struct xt_table_info *private,
 
 300                          const struct ip6t_entry *e)
 
 302         const void *table_base;
 
 303         const struct ip6t_entry *root;
 
 304         const char *hookname, *chainname, *comment;
 
 305         const struct ip6t_entry *iter;
 
 306         unsigned int rulenum = 0;
 
 308         table_base = private->entries[smp_processor_id()];
 
 309         root = get_entry(table_base, private->hook_entry[hook]);
 
 311         hookname = chainname = hooknames[hook];
 
 312         comment = comments[NF_IP6_TRACE_COMMENT_RULE];
 
 314         xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
 
 315                 if (get_chainname_rulenum(iter, e, hookname,
 
 316                     &chainname, &comment, &rulenum) != 0)
 
 319         nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
 
 320                       "TRACE: %s:%s:%s:%u ",
 
 321                       tablename, chainname, comment, rulenum);
 
 325 static inline __pure struct ip6t_entry *
 
 326 ip6t_next_entry(const struct ip6t_entry *entry)
 
 328         return (void *)entry + entry->next_offset;
 
 331 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 
 333 ip6t_do_table(struct sk_buff *skb,
 
 335               const struct net_device *in,
 
 336               const struct net_device *out,
 
 337               struct xt_table *table)
 
 339         static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
 
 340         /* Initializing verdict to NF_DROP keeps gcc happy. */
 
 341         unsigned int verdict = NF_DROP;
 
 342         const char *indev, *outdev;
 
 343         const void *table_base;
 
 344         struct ip6t_entry *e, **jumpstack;
 
 345         unsigned int *stackptr, origptr, cpu;
 
 346         const struct xt_table_info *private;
 
 347         struct xt_action_param acpar;
 
 350         indev = in ? in->name : nulldevname;
 
 351         outdev = out ? out->name : nulldevname;
 
 352         /* We handle fragments by dealing with the first fragment as
 
 353          * if it was a normal packet.  All other fragments are treated
 
 354          * normally, except that they will NEVER match rules that ask
 
 355          * things we don't know, ie. tcp syn flag or ports).  If the
 
 356          * rule is also a fragment-specific rule, non-fragments won't
 
 358         acpar.hotdrop = false;
 
 361         acpar.family  = NFPROTO_IPV6;
 
 362         acpar.hooknum = hook;
 
 364         IP_NF_ASSERT(table->valid_hooks & (1 << hook));
 
 367         private = table->private;
 
 368         cpu        = smp_processor_id();
 
 369         table_base = private->entries[cpu];
 
 370         jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];
 
 371         stackptr   = &private->stackptr[cpu];
 
 374         e = get_entry(table_base, private->hook_entry[hook]);
 
 377                 const struct ip6t_entry_target *t;
 
 378                 const struct xt_entry_match *ematch;
 
 381                 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
 
 382                     &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) {
 
 384                         e = ip6t_next_entry(e);
 
 388                 xt_ematch_foreach(ematch, e) {
 
 389                         acpar.match     = ematch->u.kernel.match;
 
 390                         acpar.matchinfo = ematch->data;
 
 391                         if (!acpar.match->match(skb, &acpar))
 
 395                 ADD_COUNTER(e->counters,
 
 396                             ntohs(ipv6_hdr(skb)->payload_len) +
 
 397                             sizeof(struct ipv6hdr), 1);
 
 399                 t = ip6t_get_target_c(e);
 
 400                 IP_NF_ASSERT(t->u.kernel.target);
 
 402 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
 
 403     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
 
 404                 /* The packet is traced: log it */
 
 405                 if (unlikely(skb->nf_trace))
 
 406                         trace_packet(skb, hook, in, out,
 
 407                                      table->name, private, e);
 
 409                 /* Standard target? */
 
 410                 if (!t->u.kernel.target->target) {
 
 413                         v = ((struct ip6t_standard_target *)t)->verdict;
 
 415                                 /* Pop from stack? */
 
 416                                 if (v != IP6T_RETURN) {
 
 417                                         verdict = (unsigned)(-v) - 1;
 
 421                                         e = get_entry(table_base,
 
 422                                             private->underflow[hook]);
 
 424                                         e = ip6t_next_entry(jumpstack[--*stackptr]);
 
 427                         if (table_base + v != ip6t_next_entry(e) &&
 
 428                             !(e->ipv6.flags & IP6T_F_GOTO)) {
 
 429                                 if (*stackptr >= private->stacksize) {
 
 433                                 jumpstack[(*stackptr)++] = e;
 
 436                         e = get_entry(table_base, v);
 
 440                 acpar.target   = t->u.kernel.target;
 
 441                 acpar.targinfo = t->data;
 
 443                 verdict = t->u.kernel.target->target(skb, &acpar);
 
 444                 if (verdict == IP6T_CONTINUE)
 
 445                         e = ip6t_next_entry(e);
 
 449         } while (!acpar.hotdrop);
 
 451         xt_info_rdunlock_bh();
 
 454 #ifdef DEBUG_ALLOW_ALL
 
 463 /* Figures out from what hook each rule can be called: returns 0 if
 
 464    there are loops.  Puts hook bitmask in comefrom. */
 
 466 mark_source_chains(const struct xt_table_info *newinfo,
 
 467                    unsigned int valid_hooks, void *entry0)
 
 471         /* No recursion; use packet counter to save back ptrs (reset
 
 472            to 0 as we leave), and comefrom to save source hook bitmask */
 
 473         for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
 
 474                 unsigned int pos = newinfo->hook_entry[hook];
 
 475                 struct ip6t_entry *e = (struct ip6t_entry *)(entry0 + pos);
 
 477                 if (!(valid_hooks & (1 << hook)))
 
 480                 /* Set initial back pointer. */
 
 481                 e->counters.pcnt = pos;
 
 484                         const struct ip6t_standard_target *t
 
 485                                 = (void *)ip6t_get_target_c(e);
 
 486                         int visited = e->comefrom & (1 << hook);
 
 488                         if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
 
 489                                 printk("iptables: loop hook %u pos %u %08X.\n",
 
 490                                        hook, pos, e->comefrom);
 
 493                         e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
 
 495                         /* Unconditional return/END. */
 
 496                         if ((e->target_offset == sizeof(struct ip6t_entry) &&
 
 497                              (strcmp(t->target.u.user.name,
 
 498                                      IP6T_STANDARD_TARGET) == 0) &&
 
 500                              unconditional(&e->ipv6)) || visited) {
 
 501                                 unsigned int oldpos, size;
 
 503                                 if ((strcmp(t->target.u.user.name,
 
 504                                             IP6T_STANDARD_TARGET) == 0) &&
 
 505                                     t->verdict < -NF_MAX_VERDICT - 1) {
 
 506                                         duprintf("mark_source_chains: bad "
 
 507                                                 "negative verdict (%i)\n",
 
 512                                 /* Return: backtrack through the last
 
 515                                         e->comefrom ^= (1<<NF_INET_NUMHOOKS);
 
 516 #ifdef DEBUG_IP_FIREWALL_USER
 
 518                                             & (1 << NF_INET_NUMHOOKS)) {
 
 519                                                 duprintf("Back unset "
 
 526                                         pos = e->counters.pcnt;
 
 527                                         e->counters.pcnt = 0;
 
 529                                         /* We're at the start. */
 
 533                                         e = (struct ip6t_entry *)
 
 535                                 } while (oldpos == pos + e->next_offset);
 
 538                                 size = e->next_offset;
 
 539                                 e = (struct ip6t_entry *)
 
 540                                         (entry0 + pos + size);
 
 541                                 e->counters.pcnt = pos;
 
 544                                 int newpos = t->verdict;
 
 546                                 if (strcmp(t->target.u.user.name,
 
 547                                            IP6T_STANDARD_TARGET) == 0 &&
 
 549                                         if (newpos > newinfo->size -
 
 550                                                 sizeof(struct ip6t_entry)) {
 
 551                                                 duprintf("mark_source_chains: "
 
 552                                                         "bad verdict (%i)\n",
 
 556                                         /* This a jump; chase it. */
 
 557                                         duprintf("Jump rule %u -> %u\n",
 
 560                                         /* ... this is a fallthru */
 
 561                                         newpos = pos + e->next_offset;
 
 563                                 e = (struct ip6t_entry *)
 
 565                                 e->counters.pcnt = pos;
 
 570                 duprintf("Finished chain %u\n", hook);
 
 575 static void cleanup_match(struct ip6t_entry_match *m, struct net *net)
 
 577         struct xt_mtdtor_param par;
 
 580         par.match     = m->u.kernel.match;
 
 581         par.matchinfo = m->data;
 
 582         par.family    = NFPROTO_IPV6;
 
 583         if (par.match->destroy != NULL)
 
 584                 par.match->destroy(&par);
 
 585         module_put(par.match->me);
 
 589 check_entry(const struct ip6t_entry *e, const char *name)
 
 591         const struct ip6t_entry_target *t;
 
 593         if (!ip6_checkentry(&e->ipv6)) {
 
 594                 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
 
 598         if (e->target_offset + sizeof(struct ip6t_entry_target) >
 
 602         t = ip6t_get_target_c(e);
 
 603         if (e->target_offset + t->u.target_size > e->next_offset)
 
 609 static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
 
 611         const struct ip6t_ip6 *ipv6 = par->entryinfo;
 
 614         par->match     = m->u.kernel.match;
 
 615         par->matchinfo = m->data;
 
 617         ret = xt_check_match(par, m->u.match_size - sizeof(*m),
 
 618                              ipv6->proto, ipv6->invflags & IP6T_INV_PROTO);
 
 620                 duprintf("ip_tables: check failed for `%s'.\n",
 
 628 find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
 
 630         struct xt_match *match;
 
 633         match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name,
 
 636                 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
 
 637                 return PTR_ERR(match);
 
 639         m->u.kernel.match = match;
 
 641         ret = check_match(m, par);
 
 647         module_put(m->u.kernel.match->me);
 
 651 static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
 
 653         struct ip6t_entry_target *t = ip6t_get_target(e);
 
 654         struct xt_tgchk_param par = {
 
 658                 .target    = t->u.kernel.target,
 
 660                 .hook_mask = e->comefrom,
 
 661                 .family    = NFPROTO_IPV6,
 
 665         t = ip6t_get_target(e);
 
 666         ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
 
 667               e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
 
 669                 duprintf("ip_tables: check failed for `%s'.\n",
 
 670                          t->u.kernel.target->name);
 
 677 find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
 
 680         struct ip6t_entry_target *t;
 
 681         struct xt_target *target;
 
 684         struct xt_mtchk_param mtpar;
 
 685         struct xt_entry_match *ematch;
 
 687         ret = check_entry(e, name);
 
 694         mtpar.entryinfo = &e->ipv6;
 
 695         mtpar.hook_mask = e->comefrom;
 
 696         mtpar.family    = NFPROTO_IPV6;
 
 697         xt_ematch_foreach(ematch, e) {
 
 698                 ret = find_check_match(ematch, &mtpar);
 
 700                         goto cleanup_matches;
 
 704         t = ip6t_get_target(e);
 
 705         target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name,
 
 707         if (IS_ERR(target)) {
 
 708                 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
 
 709                 ret = PTR_ERR(target);
 
 710                 goto cleanup_matches;
 
 712         t->u.kernel.target = target;
 
 714         ret = check_target(e, net, name);
 
 719         module_put(t->u.kernel.target->me);
 
 721         xt_ematch_foreach(ematch, e) {
 
 724                 cleanup_match(ematch, net);
 
 729 static bool check_underflow(const struct ip6t_entry *e)
 
 731         const struct ip6t_entry_target *t;
 
 732         unsigned int verdict;
 
 734         if (!unconditional(&e->ipv6))
 
 736         t = ip6t_get_target_c(e);
 
 737         if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
 
 739         verdict = ((struct ip6t_standard_target *)t)->verdict;
 
 740         verdict = -verdict - 1;
 
 741         return verdict == NF_DROP || verdict == NF_ACCEPT;
 
 745 check_entry_size_and_hooks(struct ip6t_entry *e,
 
 746                            struct xt_table_info *newinfo,
 
 747                            const unsigned char *base,
 
 748                            const unsigned char *limit,
 
 749                            const unsigned int *hook_entries,
 
 750                            const unsigned int *underflows,
 
 751                            unsigned int valid_hooks)
 
 755         if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 ||
 
 756             (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
 
 757                 duprintf("Bad offset %p\n", e);
 
 762             < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
 
 763                 duprintf("checking: element %p size %u\n",
 
 768         /* Check hooks & underflows */
 
 769         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 
 770                 if (!(valid_hooks & (1 << h)))
 
 772                 if ((unsigned char *)e - base == hook_entries[h])
 
 773                         newinfo->hook_entry[h] = hook_entries[h];
 
 774                 if ((unsigned char *)e - base == underflows[h]) {
 
 775                         if (!check_underflow(e)) {
 
 776                                 pr_err("Underflows must be unconditional and "
 
 777                                        "use the STANDARD target with "
 
 781                         newinfo->underflow[h] = underflows[h];
 
 785         /* Clear counters and comefrom */
 
 786         e->counters = ((struct xt_counters) { 0, 0 });
 
 791 static void cleanup_entry(struct ip6t_entry *e, struct net *net)
 
 793         struct xt_tgdtor_param par;
 
 794         struct ip6t_entry_target *t;
 
 795         struct xt_entry_match *ematch;
 
 797         /* Cleanup all matches */
 
 798         xt_ematch_foreach(ematch, e)
 
 799                 cleanup_match(ematch, net);
 
 800         t = ip6t_get_target(e);
 
 803         par.target   = t->u.kernel.target;
 
 804         par.targinfo = t->data;
 
 805         par.family   = NFPROTO_IPV6;
 
 806         if (par.target->destroy != NULL)
 
 807                 par.target->destroy(&par);
 
 808         module_put(par.target->me);
 
 811 /* Checks and translates the user-supplied table segment (held in
 
 814 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
 
 815                 const struct ip6t_replace *repl)
 
 817         struct ip6t_entry *iter;
 
 821         newinfo->size = repl->size;
 
 822         newinfo->number = repl->num_entries;
 
 824         /* Init all hooks to impossible value. */
 
 825         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 
 826                 newinfo->hook_entry[i] = 0xFFFFFFFF;
 
 827                 newinfo->underflow[i] = 0xFFFFFFFF;
 
 830         duprintf("translate_table: size %u\n", newinfo->size);
 
 832         /* Walk through entries, checking offsets. */
 
 833         xt_entry_foreach(iter, entry0, newinfo->size) {
 
 834                 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
 
 842                 if (strcmp(ip6t_get_target(iter)->u.user.name,
 
 843                     XT_ERROR_TARGET) == 0)
 
 844                         ++newinfo->stacksize;
 
 847         if (i != repl->num_entries) {
 
 848                 duprintf("translate_table: %u not %u entries\n",
 
 849                          i, repl->num_entries);
 
 853         /* Check hooks all assigned */
 
 854         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 
 855                 /* Only hooks which are valid */
 
 856                 if (!(repl->valid_hooks & (1 << i)))
 
 858                 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
 
 859                         duprintf("Invalid hook entry %u %u\n",
 
 860                                  i, repl->hook_entry[i]);
 
 863                 if (newinfo->underflow[i] == 0xFFFFFFFF) {
 
 864                         duprintf("Invalid underflow %u %u\n",
 
 865                                  i, repl->underflow[i]);
 
 870         if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
 
 873         /* Finally, each sanity check must pass */
 
 875         xt_entry_foreach(iter, entry0, newinfo->size) {
 
 876                 ret = find_check_entry(iter, net, repl->name, repl->size);
 
 883                 xt_entry_foreach(iter, entry0, newinfo->size) {
 
 886                         cleanup_entry(iter, net);
 
 891         /* And one copy for every other CPU */
 
 892         for_each_possible_cpu(i) {
 
 893                 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
 
 894                         memcpy(newinfo->entries[i], entry0, newinfo->size);
 
 901 get_counters(const struct xt_table_info *t,
 
 902              struct xt_counters counters[])
 
 904         struct ip6t_entry *iter;
 
 909         /* Instead of clearing (by a previous call to memset())
 
 910          * the counters and using adds, we set the counters
 
 911          * with data used by 'current' CPU
 
 913          * Bottom half has to be disabled to prevent deadlock
 
 914          * if new softirq were to run and call ipt_do_table
 
 917         curcpu = smp_processor_id();
 
 920         xt_entry_foreach(iter, t->entries[curcpu], t->size) {
 
 921                 SET_COUNTER(counters[i], iter->counters.bcnt,
 
 922                             iter->counters.pcnt);
 
 926         for_each_possible_cpu(cpu) {
 
 931                 xt_entry_foreach(iter, t->entries[cpu], t->size) {
 
 932                         ADD_COUNTER(counters[i], iter->counters.bcnt,
 
 933                                     iter->counters.pcnt);
 
 936                 xt_info_wrunlock(cpu);
 
 941 static struct xt_counters *alloc_counters(const struct xt_table *table)
 
 943         unsigned int countersize;
 
 944         struct xt_counters *counters;
 
 945         const struct xt_table_info *private = table->private;
 
 947         /* We need atomic snapshot of counters: rest doesn't change
 
 948            (other than comefrom, which userspace doesn't care
 
 950         countersize = sizeof(struct xt_counters) * private->number;
 
 951         counters = vmalloc_node(countersize, numa_node_id());
 
 953         if (counters == NULL)
 
 954                 return ERR_PTR(-ENOMEM);
 
 956         get_counters(private, counters);
 
 962 copy_entries_to_user(unsigned int total_size,
 
 963                      const struct xt_table *table,
 
 964                      void __user *userptr)
 
 966         unsigned int off, num;
 
 967         const struct ip6t_entry *e;
 
 968         struct xt_counters *counters;
 
 969         const struct xt_table_info *private = table->private;
 
 971         const void *loc_cpu_entry;
 
 973         counters = alloc_counters(table);
 
 974         if (IS_ERR(counters))
 
 975                 return PTR_ERR(counters);
 
 977         /* choose the copy that is on our node/cpu, ...
 
 978          * This choice is lazy (because current thread is
 
 979          * allowed to migrate to another cpu)
 
 981         loc_cpu_entry = private->entries[raw_smp_processor_id()];
 
 982         if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
 
 987         /* FIXME: use iterator macros --RR */
 
 988         /* ... then go back and fix counters and names */
 
 989         for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
 
 991                 const struct ip6t_entry_match *m;
 
 992                 const struct ip6t_entry_target *t;
 
 994                 e = (struct ip6t_entry *)(loc_cpu_entry + off);
 
 995                 if (copy_to_user(userptr + off
 
 996                                  + offsetof(struct ip6t_entry, counters),
 
 998                                  sizeof(counters[num])) != 0) {
 
1003                 for (i = sizeof(struct ip6t_entry);
 
1004                      i < e->target_offset;
 
1005                      i += m->u.match_size) {
 
1008                         if (copy_to_user(userptr + off + i
 
1009                                          + offsetof(struct ip6t_entry_match,
 
1011                                          m->u.kernel.match->name,
 
1012                                          strlen(m->u.kernel.match->name)+1)
 
1019                 t = ip6t_get_target_c(e);
 
1020                 if (copy_to_user(userptr + off + e->target_offset
 
1021                                  + offsetof(struct ip6t_entry_target,
 
1023                                  t->u.kernel.target->name,
 
1024                                  strlen(t->u.kernel.target->name)+1) != 0) {
 
1035 #ifdef CONFIG_COMPAT
 
1036 static void compat_standard_from_user(void *dst, const void *src)
 
1038         int v = *(compat_int_t *)src;
 
1041                 v += xt_compat_calc_jump(AF_INET6, v);
 
1042         memcpy(dst, &v, sizeof(v));
 
1045 static int compat_standard_to_user(void __user *dst, const void *src)
 
1047         compat_int_t cv = *(int *)src;
 
1050                 cv -= xt_compat_calc_jump(AF_INET6, cv);
 
1051         return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
 
1054 static int compat_calc_entry(const struct ip6t_entry *e,
 
1055                              const struct xt_table_info *info,
 
1056                              const void *base, struct xt_table_info *newinfo)
 
1058         const struct xt_entry_match *ematch;
 
1059         const struct ip6t_entry_target *t;
 
1060         unsigned int entry_offset;
 
1063         off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
 
1064         entry_offset = (void *)e - base;
 
1065         xt_ematch_foreach(ematch, e)
 
1066                 off += xt_compat_match_offset(ematch->u.kernel.match);
 
1067         t = ip6t_get_target_c(e);
 
1068         off += xt_compat_target_offset(t->u.kernel.target);
 
1069         newinfo->size -= off;
 
1070         ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
 
1074         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 
1075                 if (info->hook_entry[i] &&
 
1076                     (e < (struct ip6t_entry *)(base + info->hook_entry[i])))
 
1077                         newinfo->hook_entry[i] -= off;
 
1078                 if (info->underflow[i] &&
 
1079                     (e < (struct ip6t_entry *)(base + info->underflow[i])))
 
1080                         newinfo->underflow[i] -= off;
 
1085 static int compat_table_info(const struct xt_table_info *info,
 
1086                              struct xt_table_info *newinfo)
 
1088         struct ip6t_entry *iter;
 
1089         void *loc_cpu_entry;
 
1092         if (!newinfo || !info)
 
1095         /* we dont care about newinfo->entries[] */
 
1096         memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
 
1097         newinfo->initial_entries = 0;
 
1098         loc_cpu_entry = info->entries[raw_smp_processor_id()];
 
1099         xt_entry_foreach(iter, loc_cpu_entry, info->size) {
 
1100                 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
 
1108 static int get_info(struct net *net, void __user *user,
 
1109                     const int *len, int compat)
 
1111         char name[IP6T_TABLE_MAXNAMELEN];
 
1115         if (*len != sizeof(struct ip6t_getinfo)) {
 
1116                 duprintf("length %u != %zu\n", *len,
 
1117                          sizeof(struct ip6t_getinfo));
 
1121         if (copy_from_user(name, user, sizeof(name)) != 0)
 
1124         name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
 
1125 #ifdef CONFIG_COMPAT
 
1127                 xt_compat_lock(AF_INET6);
 
1129         t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
 
1130                                     "ip6table_%s", name);
 
1131         if (t && !IS_ERR(t)) {
 
1132                 struct ip6t_getinfo info;
 
1133                 const struct xt_table_info *private = t->private;
 
1134 #ifdef CONFIG_COMPAT
 
1135                 struct xt_table_info tmp;
 
1138                         ret = compat_table_info(private, &tmp);
 
1139                         xt_compat_flush_offsets(AF_INET6);
 
1143                 info.valid_hooks = t->valid_hooks;
 
1144                 memcpy(info.hook_entry, private->hook_entry,
 
1145                        sizeof(info.hook_entry));
 
1146                 memcpy(info.underflow, private->underflow,
 
1147                        sizeof(info.underflow));
 
1148                 info.num_entries = private->number;
 
1149                 info.size = private->size;
 
1150                 strcpy(info.name, name);
 
1152                 if (copy_to_user(user, &info, *len) != 0)
 
1160                 ret = t ? PTR_ERR(t) : -ENOENT;
 
1161 #ifdef CONFIG_COMPAT
 
1163                 xt_compat_unlock(AF_INET6);
 
1169 get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
 
1173         struct ip6t_get_entries get;
 
1176         if (*len < sizeof(get)) {
 
1177                 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
 
1180         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
 
1182         if (*len != sizeof(struct ip6t_get_entries) + get.size) {
 
1183                 duprintf("get_entries: %u != %zu\n",
 
1184                          *len, sizeof(get) + get.size);
 
1188         t = xt_find_table_lock(net, AF_INET6, get.name);
 
1189         if (t && !IS_ERR(t)) {
 
1190                 struct xt_table_info *private = t->private;
 
1191                 duprintf("t->private->number = %u\n", private->number);
 
1192                 if (get.size == private->size)
 
1193                         ret = copy_entries_to_user(private->size,
 
1194                                                    t, uptr->entrytable);
 
1196                         duprintf("get_entries: I've got %u not %u!\n",
 
1197                                  private->size, get.size);
 
1203                 ret = t ? PTR_ERR(t) : -ENOENT;
 
1209 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
 
1210              struct xt_table_info *newinfo, unsigned int num_counters,
 
1211              void __user *counters_ptr)
 
1215         struct xt_table_info *oldinfo;
 
1216         struct xt_counters *counters;
 
1217         const void *loc_cpu_old_entry;
 
1218         struct ip6t_entry *iter;
 
1221         counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
 
1228         t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
 
1229                                     "ip6table_%s", name);
 
1230         if (!t || IS_ERR(t)) {
 
1231                 ret = t ? PTR_ERR(t) : -ENOENT;
 
1232                 goto free_newinfo_counters_untrans;
 
1236         if (valid_hooks != t->valid_hooks) {
 
1237                 duprintf("Valid hook crap: %08X vs %08X\n",
 
1238                          valid_hooks, t->valid_hooks);
 
1243         oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
 
1247         /* Update module usage count based on number of rules */
 
1248         duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
 
1249                 oldinfo->number, oldinfo->initial_entries, newinfo->number);
 
1250         if ((oldinfo->number > oldinfo->initial_entries) ||
 
1251             (newinfo->number <= oldinfo->initial_entries))
 
1253         if ((oldinfo->number > oldinfo->initial_entries) &&
 
1254             (newinfo->number <= oldinfo->initial_entries))
 
1257         /* Get the old counters, and synchronize with replace */
 
1258         get_counters(oldinfo, counters);
 
1260         /* Decrease module usage counts and free resource */
 
1261         loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
 
1262         xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
 
1263                 cleanup_entry(iter, net);
 
1265         xt_free_table_info(oldinfo);
 
1266         if (copy_to_user(counters_ptr, counters,
 
1267                          sizeof(struct xt_counters) * num_counters) != 0)
 
1276  free_newinfo_counters_untrans:
 
1283 do_replace(struct net *net, const void __user *user, unsigned int len)
 
1286         struct ip6t_replace tmp;
 
1287         struct xt_table_info *newinfo;
 
1288         void *loc_cpu_entry;
 
1289         struct ip6t_entry *iter;
 
1291         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
 
1294         /* overflow check */
 
1295         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 
1298         newinfo = xt_alloc_table_info(tmp.size);
 
1302         /* choose the copy that is on our node/cpu */
 
1303         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
 
1304         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
 
1310         ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
 
1314         duprintf("ip_tables: Translated table\n");
 
1316         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
 
1317                            tmp.num_counters, tmp.counters);
 
1319                 goto free_newinfo_untrans;
 
1322  free_newinfo_untrans:
 
1323         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
 
1324                 cleanup_entry(iter, net);
 
1326         xt_free_table_info(newinfo);
 
1331 do_add_counters(struct net *net, const void __user *user, unsigned int len,
 
1334         unsigned int i, curcpu;
 
1335         struct xt_counters_info tmp;
 
1336         struct xt_counters *paddc;
 
1337         unsigned int num_counters;
 
1342         const struct xt_table_info *private;
 
1344         const void *loc_cpu_entry;
 
1345         struct ip6t_entry *iter;
 
1346 #ifdef CONFIG_COMPAT
 
1347         struct compat_xt_counters_info compat_tmp;
 
1351                 size = sizeof(struct compat_xt_counters_info);
 
1356                 size = sizeof(struct xt_counters_info);
 
1359         if (copy_from_user(ptmp, user, size) != 0)
 
1362 #ifdef CONFIG_COMPAT
 
1364                 num_counters = compat_tmp.num_counters;
 
1365                 name = compat_tmp.name;
 
1369                 num_counters = tmp.num_counters;
 
1373         if (len != size + num_counters * sizeof(struct xt_counters))
 
1376         paddc = vmalloc_node(len - size, numa_node_id());
 
1380         if (copy_from_user(paddc, user + size, len - size) != 0) {
 
1385         t = xt_find_table_lock(net, AF_INET6, name);
 
1386         if (!t || IS_ERR(t)) {
 
1387                 ret = t ? PTR_ERR(t) : -ENOENT;
 
1393         private = t->private;
 
1394         if (private->number != num_counters) {
 
1396                 goto unlock_up_free;
 
1400         /* Choose the copy that is on our node */
 
1401         curcpu = smp_processor_id();
 
1402         xt_info_wrlock(curcpu);
 
1403         loc_cpu_entry = private->entries[curcpu];
 
1404         xt_entry_foreach(iter, loc_cpu_entry, private->size) {
 
1405                 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
 
1408         xt_info_wrunlock(curcpu);
 
1420 #ifdef CONFIG_COMPAT
 
1421 struct compat_ip6t_replace {
 
1422         char                    name[IP6T_TABLE_MAXNAMELEN];
 
1426         u32                     hook_entry[NF_INET_NUMHOOKS];
 
1427         u32                     underflow[NF_INET_NUMHOOKS];
 
1429         compat_uptr_t           counters;       /* struct ip6t_counters * */
 
1430         struct compat_ip6t_entry entries[0];
 
1434 compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
 
1435                           unsigned int *size, struct xt_counters *counters,
 
1438         struct ip6t_entry_target *t;
 
1439         struct compat_ip6t_entry __user *ce;
 
1440         u_int16_t target_offset, next_offset;
 
1441         compat_uint_t origsize;
 
1442         const struct xt_entry_match *ematch;
 
1446         ce = (struct compat_ip6t_entry __user *)*dstptr;
 
1447         if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 ||
 
1448             copy_to_user(&ce->counters, &counters[i],
 
1449             sizeof(counters[i])) != 0)
 
1452         *dstptr += sizeof(struct compat_ip6t_entry);
 
1453         *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
 
1455         xt_ematch_foreach(ematch, e) {
 
1456                 ret = xt_compat_match_to_user(ematch, dstptr, size);
 
1460         target_offset = e->target_offset - (origsize - *size);
 
1461         t = ip6t_get_target(e);
 
1462         ret = xt_compat_target_to_user(t, dstptr, size);
 
1465         next_offset = e->next_offset - (origsize - *size);
 
1466         if (put_user(target_offset, &ce->target_offset) != 0 ||
 
1467             put_user(next_offset, &ce->next_offset) != 0)
 
1473 compat_find_calc_match(struct ip6t_entry_match *m,
 
1475                        const struct ip6t_ip6 *ipv6,
 
1476                        unsigned int hookmask,
 
1479         struct xt_match *match;
 
1481         match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name,
 
1482                                       m->u.user.revision);
 
1483         if (IS_ERR(match)) {
 
1484                 duprintf("compat_check_calc_match: `%s' not found\n",
 
1486                 return PTR_ERR(match);
 
1488         m->u.kernel.match = match;
 
1489         *size += xt_compat_match_offset(match);
 
1493 static void compat_release_entry(struct compat_ip6t_entry *e)
 
1495         struct ip6t_entry_target *t;
 
1496         struct xt_entry_match *ematch;
 
1498         /* Cleanup all matches */
 
1499         xt_ematch_foreach(ematch, e)
 
1500                 module_put(ematch->u.kernel.match->me);
 
1501         t = compat_ip6t_get_target(e);
 
1502         module_put(t->u.kernel.target->me);
 
1506 check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
 
1507                                   struct xt_table_info *newinfo,
 
1509                                   const unsigned char *base,
 
1510                                   const unsigned char *limit,
 
1511                                   const unsigned int *hook_entries,
 
1512                                   const unsigned int *underflows,
 
1515         struct xt_entry_match *ematch;
 
1516         struct ip6t_entry_target *t;
 
1517         struct xt_target *target;
 
1518         unsigned int entry_offset;
 
1522         duprintf("check_compat_entry_size_and_hooks %p\n", e);
 
1523         if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
 
1524             (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) {
 
1525                 duprintf("Bad offset %p, limit = %p\n", e, limit);
 
1529         if (e->next_offset < sizeof(struct compat_ip6t_entry) +
 
1530                              sizeof(struct compat_xt_entry_target)) {
 
1531                 duprintf("checking: element %p size %u\n",
 
1536         /* For purposes of check_entry casting the compat entry is fine */
 
1537         ret = check_entry((struct ip6t_entry *)e, name);
 
1541         off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
 
1542         entry_offset = (void *)e - (void *)base;
 
1544         xt_ematch_foreach(ematch, e) {
 
1545                 ret = compat_find_calc_match(ematch, name,
 
1546                                              &e->ipv6, e->comefrom, &off);
 
1548                         goto release_matches;
 
1552         t = compat_ip6t_get_target(e);
 
1553         target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name,
 
1554                                         t->u.user.revision);
 
1555         if (IS_ERR(target)) {
 
1556                 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
 
1558                 ret = PTR_ERR(target);
 
1559                 goto release_matches;
 
1561         t->u.kernel.target = target;
 
1563         off += xt_compat_target_offset(target);
 
1565         ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
 
1569         /* Check hooks & underflows */
 
1570         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 
1571                 if ((unsigned char *)e - base == hook_entries[h])
 
1572                         newinfo->hook_entry[h] = hook_entries[h];
 
1573                 if ((unsigned char *)e - base == underflows[h])
 
1574                         newinfo->underflow[h] = underflows[h];
 
1577         /* Clear counters and comefrom */
 
1578         memset(&e->counters, 0, sizeof(e->counters));
 
1583         module_put(t->u.kernel.target->me);
 
1585         xt_ematch_foreach(ematch, e) {
 
1588                 module_put(ematch->u.kernel.match->me);
 
1594 compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
 
1595                             unsigned int *size, const char *name,
 
1596                             struct xt_table_info *newinfo, unsigned char *base)
 
1598         struct ip6t_entry_target *t;
 
1599         struct xt_target *target;
 
1600         struct ip6t_entry *de;
 
1601         unsigned int origsize;
 
1603         struct xt_entry_match *ematch;
 
1607         de = (struct ip6t_entry *)*dstptr;
 
1608         memcpy(de, e, sizeof(struct ip6t_entry));
 
1609         memcpy(&de->counters, &e->counters, sizeof(e->counters));
 
1611         *dstptr += sizeof(struct ip6t_entry);
 
1612         *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
 
1614         xt_ematch_foreach(ematch, e) {
 
1615                 ret = xt_compat_match_from_user(ematch, dstptr, size);
 
1619         de->target_offset = e->target_offset - (origsize - *size);
 
1620         t = compat_ip6t_get_target(e);
 
1621         target = t->u.kernel.target;
 
1622         xt_compat_target_from_user(t, dstptr, size);
 
1624         de->next_offset = e->next_offset - (origsize - *size);
 
1625         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
 
1626                 if ((unsigned char *)de - base < newinfo->hook_entry[h])
 
1627                         newinfo->hook_entry[h] -= origsize - *size;
 
1628                 if ((unsigned char *)de - base < newinfo->underflow[h])
 
1629                         newinfo->underflow[h] -= origsize - *size;
 
1634 static int compat_check_entry(struct ip6t_entry *e, struct net *net,
 
1639         struct xt_mtchk_param mtpar;
 
1640         struct xt_entry_match *ematch;
 
1645         mtpar.entryinfo = &e->ipv6;
 
1646         mtpar.hook_mask = e->comefrom;
 
1647         mtpar.family    = NFPROTO_IPV6;
 
1648         xt_ematch_foreach(ematch, e) {
 
1649                 ret = check_match(ematch, &mtpar);
 
1651                         goto cleanup_matches;
 
1655         ret = check_target(e, net, name);
 
1657                 goto cleanup_matches;
 
1661         xt_ematch_foreach(ematch, e) {
 
1664                 cleanup_match(ematch, net);
 
1670 translate_compat_table(struct net *net,
 
1672                        unsigned int valid_hooks,
 
1673                        struct xt_table_info **pinfo,
 
1675                        unsigned int total_size,
 
1676                        unsigned int number,
 
1677                        unsigned int *hook_entries,
 
1678                        unsigned int *underflows)
 
1681         struct xt_table_info *newinfo, *info;
 
1682         void *pos, *entry0, *entry1;
 
1683         struct compat_ip6t_entry *iter0;
 
1684         struct ip6t_entry *iter1;
 
1691         info->number = number;
 
1693         /* Init all hooks to impossible value. */
 
1694         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 
1695                 info->hook_entry[i] = 0xFFFFFFFF;
 
1696                 info->underflow[i] = 0xFFFFFFFF;
 
1699         duprintf("translate_compat_table: size %u\n", info->size);
 
1701         xt_compat_lock(AF_INET6);
 
1702         /* Walk through entries, checking offsets. */
 
1703         xt_entry_foreach(iter0, entry0, total_size) {
 
1704                 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
 
1706                                                         entry0 + total_size,
 
1717                 duprintf("translate_compat_table: %u not %u entries\n",
 
1722         /* Check hooks all assigned */
 
1723         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 
1724                 /* Only hooks which are valid */
 
1725                 if (!(valid_hooks & (1 << i)))
 
1727                 if (info->hook_entry[i] == 0xFFFFFFFF) {
 
1728                         duprintf("Invalid hook entry %u %u\n",
 
1729                                  i, hook_entries[i]);
 
1732                 if (info->underflow[i] == 0xFFFFFFFF) {
 
1733                         duprintf("Invalid underflow %u %u\n",
 
1740         newinfo = xt_alloc_table_info(size);
 
1744         newinfo->number = number;
 
1745         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
 
1746                 newinfo->hook_entry[i] = info->hook_entry[i];
 
1747                 newinfo->underflow[i] = info->underflow[i];
 
1749         entry1 = newinfo->entries[raw_smp_processor_id()];
 
1752         xt_entry_foreach(iter0, entry0, total_size) {
 
1753                 ret = compat_copy_entry_from_user(iter0, &pos, &size,
 
1754                                                   name, newinfo, entry1);
 
1758         xt_compat_flush_offsets(AF_INET6);
 
1759         xt_compat_unlock(AF_INET6);
 
1764         if (!mark_source_chains(newinfo, valid_hooks, entry1))
 
1768         xt_entry_foreach(iter1, entry1, newinfo->size) {
 
1769                 ret = compat_check_entry(iter1, net, name);
 
1776                  * The first i matches need cleanup_entry (calls ->destroy)
 
1777                  * because they had called ->check already. The other j-i
 
1778                  * entries need only release.
 
1782                 xt_entry_foreach(iter0, entry0, newinfo->size) {
 
1787                         compat_release_entry(iter0);
 
1789                 xt_entry_foreach(iter1, entry1, newinfo->size) {
 
1792                         cleanup_entry(iter1, net);
 
1794                 xt_free_table_info(newinfo);
 
1798         /* And one copy for every other CPU */
 
1799         for_each_possible_cpu(i)
 
1800                 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
 
1801                         memcpy(newinfo->entries[i], entry1, newinfo->size);
 
1805         xt_free_table_info(info);
 
1809         xt_free_table_info(newinfo);
 
1811         xt_entry_foreach(iter0, entry0, total_size) {
 
1814                 compat_release_entry(iter0);
 
1818         xt_compat_flush_offsets(AF_INET6);
 
1819         xt_compat_unlock(AF_INET6);
 
1824 compat_do_replace(struct net *net, void __user *user, unsigned int len)
 
1827         struct compat_ip6t_replace tmp;
 
1828         struct xt_table_info *newinfo;
 
1829         void *loc_cpu_entry;
 
1830         struct ip6t_entry *iter;
 
1832         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
 
1835         /* overflow check */
 
1836         if (tmp.size >= INT_MAX / num_possible_cpus())
 
1838         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 
1841         newinfo = xt_alloc_table_info(tmp.size);
 
1845         /* choose the copy that is on our node/cpu */
 
1846         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
 
1847         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
 
1853         ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
 
1854                                      &newinfo, &loc_cpu_entry, tmp.size,
 
1855                                      tmp.num_entries, tmp.hook_entry,
 
1860         duprintf("compat_do_replace: Translated table\n");
 
1862         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
 
1863                            tmp.num_counters, compat_ptr(tmp.counters));
 
1865                 goto free_newinfo_untrans;
 
1868  free_newinfo_untrans:
 
1869         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
 
1870                 cleanup_entry(iter, net);
 
1872         xt_free_table_info(newinfo);
 
1877 compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
 
1882         if (!capable(CAP_NET_ADMIN))
 
1886         case IP6T_SO_SET_REPLACE:
 
1887                 ret = compat_do_replace(sock_net(sk), user, len);
 
1890         case IP6T_SO_SET_ADD_COUNTERS:
 
1891                 ret = do_add_counters(sock_net(sk), user, len, 1);
 
1895                 duprintf("do_ip6t_set_ctl:  unknown request %i\n", cmd);
 
1902 struct compat_ip6t_get_entries {
 
1903         char name[IP6T_TABLE_MAXNAMELEN];
 
1905         struct compat_ip6t_entry entrytable[0];
 
1909 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
 
1910                             void __user *userptr)
 
1912         struct xt_counters *counters;
 
1913         const struct xt_table_info *private = table->private;
 
1917         const void *loc_cpu_entry;
 
1919         struct ip6t_entry *iter;
 
1921         counters = alloc_counters(table);
 
1922         if (IS_ERR(counters))
 
1923                 return PTR_ERR(counters);
 
1925         /* choose the copy that is on our node/cpu, ...
 
1926          * This choice is lazy (because current thread is
 
1927          * allowed to migrate to another cpu)
 
1929         loc_cpu_entry = private->entries[raw_smp_processor_id()];
 
1932         xt_entry_foreach(iter, loc_cpu_entry, total_size) {
 
1933                 ret = compat_copy_entry_to_user(iter, &pos,
 
1934                                                 &size, counters, i++);
 
1944 compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
 
1948         struct compat_ip6t_get_entries get;
 
1951         if (*len < sizeof(get)) {
 
1952                 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
 
1956         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
 
1959         if (*len != sizeof(struct compat_ip6t_get_entries) + get.size) {
 
1960                 duprintf("compat_get_entries: %u != %zu\n",
 
1961                          *len, sizeof(get) + get.size);
 
1965         xt_compat_lock(AF_INET6);
 
1966         t = xt_find_table_lock(net, AF_INET6, get.name);
 
1967         if (t && !IS_ERR(t)) {
 
1968                 const struct xt_table_info *private = t->private;
 
1969                 struct xt_table_info info;
 
1970                 duprintf("t->private->number = %u\n", private->number);
 
1971                 ret = compat_table_info(private, &info);
 
1972                 if (!ret && get.size == info.size) {
 
1973                         ret = compat_copy_entries_to_user(private->size,
 
1974                                                           t, uptr->entrytable);
 
1976                         duprintf("compat_get_entries: I've got %u not %u!\n",
 
1977                                  private->size, get.size);
 
1980                 xt_compat_flush_offsets(AF_INET6);
 
1984                 ret = t ? PTR_ERR(t) : -ENOENT;
 
1986         xt_compat_unlock(AF_INET6);
 
1990 static int do_ip6t_get_ctl(struct sock *, int, void __user *, int *);
 
1993 compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 
1997         if (!capable(CAP_NET_ADMIN))
 
2001         case IP6T_SO_GET_INFO:
 
2002                 ret = get_info(sock_net(sk), user, len, 1);
 
2004         case IP6T_SO_GET_ENTRIES:
 
2005                 ret = compat_get_entries(sock_net(sk), user, len);
 
2008                 ret = do_ip6t_get_ctl(sk, cmd, user, len);
 
2015 do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
2019         if (!capable(CAP_NET_ADMIN))
 
2023         case IP6T_SO_SET_REPLACE:
 
2024                 ret = do_replace(sock_net(sk), user, len);
 
2027         case IP6T_SO_SET_ADD_COUNTERS:
 
2028                 ret = do_add_counters(sock_net(sk), user, len, 0);
 
2032                 duprintf("do_ip6t_set_ctl:  unknown request %i\n", cmd);
 
2040 do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 
2044         if (!capable(CAP_NET_ADMIN))
 
2048         case IP6T_SO_GET_INFO:
 
2049                 ret = get_info(sock_net(sk), user, len, 0);
 
2052         case IP6T_SO_GET_ENTRIES:
 
2053                 ret = get_entries(sock_net(sk), user, len);
 
2056         case IP6T_SO_GET_REVISION_MATCH:
 
2057         case IP6T_SO_GET_REVISION_TARGET: {
 
2058                 struct ip6t_get_revision rev;
 
2061                 if (*len != sizeof(rev)) {
 
2065                 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
 
2070                 if (cmd == IP6T_SO_GET_REVISION_TARGET)
 
2075                 try_then_request_module(xt_find_revision(AF_INET6, rev.name,
 
2078                                         "ip6t_%s", rev.name);
 
2083                 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
 
2090 struct xt_table *ip6t_register_table(struct net *net,
 
2091                                      const struct xt_table *table,
 
2092                                      const struct ip6t_replace *repl)
 
2095         struct xt_table_info *newinfo;
 
2096         struct xt_table_info bootstrap = {0};
 
2097         void *loc_cpu_entry;
 
2098         struct xt_table *new_table;
 
2100         newinfo = xt_alloc_table_info(repl->size);
 
2106         /* choose the copy on our node/cpu, but dont care about preemption */
 
2107         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
 
2108         memcpy(loc_cpu_entry, repl->entries, repl->size);
 
2110         ret = translate_table(net, newinfo, loc_cpu_entry, repl);
 
2114         new_table = xt_register_table(net, table, &bootstrap, newinfo);
 
2115         if (IS_ERR(new_table)) {
 
2116                 ret = PTR_ERR(new_table);
 
2122         xt_free_table_info(newinfo);
 
2124         return ERR_PTR(ret);
 
2127 void ip6t_unregister_table(struct net *net, struct xt_table *table)
 
2129         struct xt_table_info *private;
 
2130         void *loc_cpu_entry;
 
2131         struct module *table_owner = table->me;
 
2132         struct ip6t_entry *iter;
 
2134         private = xt_unregister_table(table);
 
2136         /* Decrease module usage counts and free resources */
 
2137         loc_cpu_entry = private->entries[raw_smp_processor_id()];
 
2138         xt_entry_foreach(iter, loc_cpu_entry, private->size)
 
2139                 cleanup_entry(iter, net);
 
2140         if (private->number > private->initial_entries)
 
2141                 module_put(table_owner);
 
2142         xt_free_table_info(private);
 
2145 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
 
2147 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
 
2148                      u_int8_t type, u_int8_t code,
 
2151         return (type == test_type && code >= min_code && code <= max_code)
 
2156 icmp6_match(const struct sk_buff *skb, struct xt_action_param *par)
 
2158         const struct icmp6hdr *ic;
 
2159         struct icmp6hdr _icmph;
 
2160         const struct ip6t_icmp *icmpinfo = par->matchinfo;
 
2162         /* Must not be a fragment. */
 
2163         if (par->fragoff != 0)
 
2166         ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
 
2168                 /* We've been asked to examine this packet, and we
 
2169                  * can't.  Hence, no choice but to drop.
 
2171                 duprintf("Dropping evil ICMP tinygram.\n");
 
2172                 par->hotdrop = true;
 
2176         return icmp6_type_code_match(icmpinfo->type,
 
2179                                      ic->icmp6_type, ic->icmp6_code,
 
2180                                      !!(icmpinfo->invflags&IP6T_ICMP_INV));
 
2183 /* Called when user tries to insert an entry of this type. */
 
2184 static int icmp6_checkentry(const struct xt_mtchk_param *par)
 
2186         const struct ip6t_icmp *icmpinfo = par->matchinfo;
 
2188         /* Must specify no unknown invflags */
 
2189         return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0;
 
2192 /* The built-in targets: standard (NULL) and error. */
 
2193 static struct xt_target ip6t_builtin_tg[] __read_mostly = {
 
2195                 .name             = IP6T_STANDARD_TARGET,
 
2196                 .targetsize       = sizeof(int),
 
2197                 .family           = NFPROTO_IPV6,
 
2198 #ifdef CONFIG_COMPAT
 
2199                 .compatsize       = sizeof(compat_int_t),
 
2200                 .compat_from_user = compat_standard_from_user,
 
2201                 .compat_to_user   = compat_standard_to_user,
 
2205                 .name             = IP6T_ERROR_TARGET,
 
2206                 .target           = ip6t_error,
 
2207                 .targetsize       = IP6T_FUNCTION_MAXNAMELEN,
 
2208                 .family           = NFPROTO_IPV6,
 
2212 static struct nf_sockopt_ops ip6t_sockopts = {
 
2214         .set_optmin     = IP6T_BASE_CTL,
 
2215         .set_optmax     = IP6T_SO_SET_MAX+1,
 
2216         .set            = do_ip6t_set_ctl,
 
2217 #ifdef CONFIG_COMPAT
 
2218         .compat_set     = compat_do_ip6t_set_ctl,
 
2220         .get_optmin     = IP6T_BASE_CTL,
 
2221         .get_optmax     = IP6T_SO_GET_MAX+1,
 
2222         .get            = do_ip6t_get_ctl,
 
2223 #ifdef CONFIG_COMPAT
 
2224         .compat_get     = compat_do_ip6t_get_ctl,
 
2226         .owner          = THIS_MODULE,
 
2229 static struct xt_match ip6t_builtin_mt[] __read_mostly = {
 
2232                 .match      = icmp6_match,
 
2233                 .matchsize  = sizeof(struct ip6t_icmp),
 
2234                 .checkentry = icmp6_checkentry,
 
2235                 .proto      = IPPROTO_ICMPV6,
 
2236                 .family     = NFPROTO_IPV6,
 
2240 static int __net_init ip6_tables_net_init(struct net *net)
 
2242         return xt_proto_init(net, NFPROTO_IPV6);
 
2245 static void __net_exit ip6_tables_net_exit(struct net *net)
 
2247         xt_proto_fini(net, NFPROTO_IPV6);
 
2250 static struct pernet_operations ip6_tables_net_ops = {
 
2251         .init = ip6_tables_net_init,
 
2252         .exit = ip6_tables_net_exit,
 
2255 static int __init ip6_tables_init(void)
 
2259         ret = register_pernet_subsys(&ip6_tables_net_ops);
 
2263         /* Noone else will be downing sem now, so we won't sleep */
 
2264         ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
 
2267         ret = xt_register_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
 
2271         /* Register setsockopt */
 
2272         ret = nf_register_sockopt(&ip6t_sockopts);
 
2276         pr_info("(C) 2000-2006 Netfilter Core Team\n");
 
2280         xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
 
2282         xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
 
2284         unregister_pernet_subsys(&ip6_tables_net_ops);
 
2289 static void __exit ip6_tables_fini(void)
 
2291         nf_unregister_sockopt(&ip6t_sockopts);
 
2293         xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
 
2294         xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
 
2295         unregister_pernet_subsys(&ip6_tables_net_ops);
 
2299  * find the offset to specified header or the protocol number of last header
 
2300  * if target < 0. "last header" is transport protocol header, ESP, or
 
2303  * If target header is found, its offset is set in *offset and return protocol
 
2304  * number. Otherwise, return -1.
 
2306  * If the first fragment doesn't contain the final protocol header or
 
2307  * NEXTHDR_NONE it is considered invalid.
 
2309  * Note that non-1st fragment is special case that "the protocol number
 
2310  * of last header" is "next header" field in Fragment header. In this case,
 
2311  * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
 
2315 int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 
2316                   int target, unsigned short *fragoff)
 
2318         unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
 
2319         u8 nexthdr = ipv6_hdr(skb)->nexthdr;
 
2320         unsigned int len = skb->len - start;
 
2325         while (nexthdr != target) {
 
2326                 struct ipv6_opt_hdr _hdr, *hp;
 
2327                 unsigned int hdrlen;
 
2329                 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
 
2335                 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
 
2338                 if (nexthdr == NEXTHDR_FRAGMENT) {
 
2339                         unsigned short _frag_off;
 
2341                         fp = skb_header_pointer(skb,
 
2342                                                 start+offsetof(struct frag_hdr,
 
2349                         _frag_off = ntohs(*fp) & ~0x7;
 
2352                                     ((!ipv6_ext_hdr(hp->nexthdr)) ||
 
2353                                      hp->nexthdr == NEXTHDR_NONE)) {
 
2355                                                 *fragoff = _frag_off;
 
2361                 } else if (nexthdr == NEXTHDR_AUTH)
 
2362                         hdrlen = (hp->hdrlen + 2) << 2;
 
2364                         hdrlen = ipv6_optlen(hp);
 
2366                 nexthdr = hp->nexthdr;
 
2375 EXPORT_SYMBOL(ip6t_register_table);
 
2376 EXPORT_SYMBOL(ip6t_unregister_table);
 
2377 EXPORT_SYMBOL(ip6t_do_table);
 
2378 EXPORT_SYMBOL(ip6t_ext_hdr);
 
2379 EXPORT_SYMBOL(ipv6_find_hdr);
 
2381 module_init(ip6_tables_init);
 
2382 module_exit(ip6_tables_fini);