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