linux/net/ipv4/netfilter/arp_tables.c
<<
>>
Prefs
   1/*
   2 * Packet matching code for ARP packets.
   3 *
   4 * Based heavily, if not almost entirely, upon ip_tables.c framework.
   5 *
   6 * Some ARP specific bits are:
   7 *
   8 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
   9 * Copyright (C) 2006-2009 Patrick McHardy <kaber@trash.net>
  10 *
  11 */
  12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13#include <linux/kernel.h>
  14#include <linux/skbuff.h>
  15#include <linux/netdevice.h>
  16#include <linux/capability.h>
  17#include <linux/if_arp.h>
  18#include <linux/kmod.h>
  19#include <linux/vmalloc.h>
  20#include <linux/proc_fs.h>
  21#include <linux/module.h>
  22#include <linux/init.h>
  23#include <linux/mutex.h>
  24#include <linux/err.h>
  25#include <net/compat.h>
  26#include <net/sock.h>
  27#include <asm/uaccess.h>
  28
  29#include <linux/netfilter/x_tables.h>
  30#include <linux/netfilter_arp/arp_tables.h>
  31#include "../../netfilter/xt_repldata.h"
  32
  33MODULE_LICENSE("GPL");
  34MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
  35MODULE_DESCRIPTION("arptables core");
  36
  37void *arpt_alloc_initial_table(const struct xt_table *info)
  38{
  39        return xt_alloc_initial_table(arpt, ARPT);
  40}
  41EXPORT_SYMBOL_GPL(arpt_alloc_initial_table);
  42
  43static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
  44                                      const char *hdr_addr, int len)
  45{
  46        int i, ret;
  47
  48        if (len > ARPT_DEV_ADDR_LEN_MAX)
  49                len = ARPT_DEV_ADDR_LEN_MAX;
  50
  51        ret = 0;
  52        for (i = 0; i < len; i++)
  53                ret |= (hdr_addr[i] ^ ap->addr[i]) & ap->mask[i];
  54
  55        return ret != 0;
  56}
  57
  58/*
  59 * Unfortunately, _b and _mask are not aligned to an int (or long int)
  60 * Some arches dont care, unrolling the loop is a win on them.
  61 * For other arches, we only have a 16bit alignement.
  62 */
  63static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask)
  64{
  65#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
  66        unsigned long ret = ifname_compare_aligned(_a, _b, _mask);
  67#else
  68        unsigned long ret = 0;
  69        const u16 *a = (const u16 *)_a;
  70        const u16 *b = (const u16 *)_b;
  71        const u16 *mask = (const u16 *)_mask;
  72        int i;
  73
  74        for (i = 0; i < IFNAMSIZ/sizeof(u16); i++)
  75                ret |= (a[i] ^ b[i]) & mask[i];
  76#endif
  77        return ret;
  78}
  79
  80/* Returns whether packet matches rule or not. */
  81static inline int arp_packet_match(const struct arphdr *arphdr,
  82                                   struct net_device *dev,
  83                                   const char *indev,
  84                                   const char *outdev,
  85                                   const struct arpt_arp *arpinfo)
  86{
  87        const char *arpptr = (char *)(arphdr + 1);
  88        const char *src_devaddr, *tgt_devaddr;
  89        __be32 src_ipaddr, tgt_ipaddr;
  90        long ret;
  91
  92        if (NF_INVF(arpinfo, ARPT_INV_ARPOP,
  93                    (arphdr->ar_op & arpinfo->arpop_mask) != arpinfo->arpop))
  94                return 0;
  95
  96        if (NF_INVF(arpinfo, ARPT_INV_ARPHRD,
  97                    (arphdr->ar_hrd & arpinfo->arhrd_mask) != arpinfo->arhrd))
  98                return 0;
  99
 100        if (NF_INVF(arpinfo, ARPT_INV_ARPPRO,
 101                    (arphdr->ar_pro & arpinfo->arpro_mask) != arpinfo->arpro))
 102                return 0;
 103
 104        if (NF_INVF(arpinfo, ARPT_INV_ARPHLN,
 105                    (arphdr->ar_hln & arpinfo->arhln_mask) != arpinfo->arhln))
 106                return 0;
 107
 108        src_devaddr = arpptr;
 109        arpptr += dev->addr_len;
 110        memcpy(&src_ipaddr, arpptr, sizeof(u32));
 111        arpptr += sizeof(u32);
 112        tgt_devaddr = arpptr;
 113        arpptr += dev->addr_len;
 114        memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
 115
 116        if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
 117                    arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
 118                                        dev->addr_len)) ||
 119            NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
 120                    arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
 121                                        dev->addr_len)))
 122                return 0;
 123
 124        if (NF_INVF(arpinfo, ARPT_INV_SRCIP,
 125                    (src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr) ||
 126            NF_INVF(arpinfo, ARPT_INV_TGTIP,
 127                    (tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr))
 128                return 0;
 129
 130        /* Look for ifname matches.  */
 131        ret = ifname_compare(indev, arpinfo->iniface, arpinfo->iniface_mask);
 132
 133        if (NF_INVF(arpinfo, ARPT_INV_VIA_IN, ret != 0))
 134                return 0;
 135
 136        ret = ifname_compare(outdev, arpinfo->outiface, arpinfo->outiface_mask);
 137
 138        if (NF_INVF(arpinfo, ARPT_INV_VIA_OUT, ret != 0))
 139                return 0;
 140
 141        return 1;
 142}
 143
 144static inline int arp_checkentry(const struct arpt_arp *arp)
 145{
 146        if (arp->flags & ~ARPT_F_MASK)
 147                return 0;
 148        if (arp->invflags & ~ARPT_INV_MASK)
 149                return 0;
 150
 151        return 1;
 152}
 153
 154static unsigned int
 155arpt_error(struct sk_buff *skb, const struct xt_action_param *par)
 156{
 157        net_err_ratelimited("arp_tables: error: '%s'\n",
 158                            (const char *)par->targinfo);
 159
 160        return NF_DROP;
 161}
 162
 163static inline const struct xt_entry_target *
 164arpt_get_target_c(const struct arpt_entry *e)
 165{
 166        return arpt_get_target((struct arpt_entry *)e);
 167}
 168
 169static inline struct arpt_entry *
 170get_entry(const void *base, unsigned int offset)
 171{
 172        return (struct arpt_entry *)(base + offset);
 173}
 174
 175static inline
 176struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry)
 177{
 178        return (void *)entry + entry->next_offset;
 179}
 180
 181unsigned int arpt_do_table(struct sk_buff *skb,
 182                           const struct nf_hook_state *state,
 183                           struct xt_table *table)
 184{
 185        unsigned int hook = state->hook;
 186        static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
 187        unsigned int verdict = NF_DROP;
 188        const struct arphdr *arp;
 189        struct arpt_entry *e, **jumpstack;
 190        const char *indev, *outdev;
 191        const void *table_base;
 192        unsigned int cpu, stackidx = 0;
 193        const struct xt_table_info *private;
 194        struct xt_action_param acpar;
 195        unsigned int addend;
 196
 197        if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
 198                return NF_DROP;
 199
 200        indev = state->in ? state->in->name : nulldevname;
 201        outdev = state->out ? state->out->name : nulldevname;
 202
 203        local_bh_disable();
 204        addend = xt_write_recseq_begin();
 205        private = table->private;
 206        cpu     = smp_processor_id();
 207        /*
 208         * Ensure we load private-> members after we've fetched the base
 209         * pointer.
 210         */
 211        smp_read_barrier_depends();
 212        table_base = private->entries;
 213        jumpstack  = (struct arpt_entry **)private->jumpstack[cpu];
 214
 215        /* No TEE support for arptables, so no need to switch to alternate
 216         * stack.  All targets that reenter must return absolute verdicts.
 217         */
 218        e = get_entry(table_base, private->hook_entry[hook]);
 219
 220        acpar.net     = state->net;
 221        acpar.in      = state->in;
 222        acpar.out     = state->out;
 223        acpar.hooknum = hook;
 224        acpar.family  = NFPROTO_ARP;
 225        acpar.hotdrop = false;
 226
 227        arp = arp_hdr(skb);
 228        do {
 229                const struct xt_entry_target *t;
 230                struct xt_counters *counter;
 231
 232                if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
 233                        e = arpt_next_entry(e);
 234                        continue;
 235                }
 236
 237                counter = xt_get_this_cpu_counter(&e->counters);
 238                ADD_COUNTER(*counter, arp_hdr_len(skb->dev), 1);
 239
 240                t = arpt_get_target_c(e);
 241
 242                /* Standard target? */
 243                if (!t->u.kernel.target->target) {
 244                        int v;
 245
 246                        v = ((struct xt_standard_target *)t)->verdict;
 247                        if (v < 0) {
 248                                /* Pop from stack? */
 249                                if (v != XT_RETURN) {
 250                                        verdict = (unsigned int)(-v) - 1;
 251                                        break;
 252                                }
 253                                if (stackidx == 0) {
 254                                        e = get_entry(table_base,
 255                                                      private->underflow[hook]);
 256                                } else {
 257                                        e = jumpstack[--stackidx];
 258                                        e = arpt_next_entry(e);
 259                                }
 260                                continue;
 261                        }
 262                        if (table_base + v
 263                            != arpt_next_entry(e)) {
 264                                jumpstack[stackidx++] = e;
 265                        }
 266
 267                        e = get_entry(table_base, v);
 268                        continue;
 269                }
 270
 271                acpar.target   = t->u.kernel.target;
 272                acpar.targinfo = t->data;
 273                verdict = t->u.kernel.target->target(skb, &acpar);
 274
 275                /* Target might have changed stuff. */
 276                arp = arp_hdr(skb);
 277
 278                if (verdict == XT_CONTINUE)
 279                        e = arpt_next_entry(e);
 280                else
 281                        /* Verdict */
 282                        break;
 283        } while (!acpar.hotdrop);
 284        xt_write_recseq_end(addend);
 285        local_bh_enable();
 286
 287        if (acpar.hotdrop)
 288                return NF_DROP;
 289        else
 290                return verdict;
 291}
 292
 293/* All zeroes == unconditional rule. */
 294static inline bool unconditional(const struct arpt_entry *e)
 295{
 296        static const struct arpt_arp uncond;
 297
 298        return e->target_offset == sizeof(struct arpt_entry) &&
 299               memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
 300}
 301
 302/* Figures out from what hook each rule can be called: returns 0 if
 303 * there are loops.  Puts hook bitmask in comefrom.
 304 */
 305static int mark_source_chains(const struct xt_table_info *newinfo,
 306                              unsigned int valid_hooks, void *entry0,
 307                              unsigned int *offsets)
 308{
 309        unsigned int hook;
 310
 311        /* No recursion; use packet counter to save back ptrs (reset
 312         * to 0 as we leave), and comefrom to save source hook bitmask.
 313         */
 314        for (hook = 0; hook < NF_ARP_NUMHOOKS; hook++) {
 315                unsigned int pos = newinfo->hook_entry[hook];
 316                struct arpt_entry *e
 317                        = (struct arpt_entry *)(entry0 + pos);
 318
 319                if (!(valid_hooks & (1 << hook)))
 320                        continue;
 321
 322                /* Set initial back pointer. */
 323                e->counters.pcnt = pos;
 324
 325                for (;;) {
 326                        const struct xt_standard_target *t
 327                                = (void *)arpt_get_target_c(e);
 328                        int visited = e->comefrom & (1 << hook);
 329
 330                        if (e->comefrom & (1 << NF_ARP_NUMHOOKS))
 331                                return 0;
 332
 333                        e->comefrom
 334                                |= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
 335
 336                        /* Unconditional return/END. */
 337                        if ((unconditional(e) &&
 338                             (strcmp(t->target.u.user.name,
 339                                     XT_STANDARD_TARGET) == 0) &&
 340                             t->verdict < 0) || visited) {
 341                                unsigned int oldpos, size;
 342
 343                                if ((strcmp(t->target.u.user.name,
 344                                            XT_STANDARD_TARGET) == 0) &&
 345                                    t->verdict < -NF_MAX_VERDICT - 1)
 346                                        return 0;
 347
 348                                /* Return: backtrack through the last
 349                                 * big jump.
 350                                 */
 351                                do {
 352                                        e->comefrom ^= (1<<NF_ARP_NUMHOOKS);
 353                                        oldpos = pos;
 354                                        pos = e->counters.pcnt;
 355                                        e->counters.pcnt = 0;
 356
 357                                        /* We're at the start. */
 358                                        if (pos == oldpos)
 359                                                goto next;
 360
 361                                        e = (struct arpt_entry *)
 362                                                (entry0 + pos);
 363                                } while (oldpos == pos + e->next_offset);
 364
 365                                /* Move along one */
 366                                size = e->next_offset;
 367                                e = (struct arpt_entry *)
 368                                        (entry0 + pos + size);
 369                                if (pos + size >= newinfo->size)
 370                                        return 0;
 371                                e->counters.pcnt = pos;
 372                                pos += size;
 373                        } else {
 374                                int newpos = t->verdict;
 375
 376                                if (strcmp(t->target.u.user.name,
 377                                           XT_STANDARD_TARGET) == 0 &&
 378                                    newpos >= 0) {
 379                                        /* This a jump; chase it. */
 380                                        if (!xt_find_jump_offset(offsets, newpos,
 381                                                                 newinfo->number))
 382                                                return 0;
 383                                        e = (struct arpt_entry *)
 384                                                (entry0 + newpos);
 385                                } else {
 386                                        /* ... this is a fallthru */
 387                                        newpos = pos + e->next_offset;
 388                                        if (newpos >= newinfo->size)
 389                                                return 0;
 390                                }
 391                                e = (struct arpt_entry *)
 392                                        (entry0 + newpos);
 393                                e->counters.pcnt = pos;
 394                                pos = newpos;
 395                        }
 396                }
 397next:           ;
 398        }
 399        return 1;
 400}
 401
 402static inline int check_target(struct arpt_entry *e, const char *name)
 403{
 404        struct xt_entry_target *t = arpt_get_target(e);
 405        struct xt_tgchk_param par = {
 406                .table     = name,
 407                .entryinfo = e,
 408                .target    = t->u.kernel.target,
 409                .targinfo  = t->data,
 410                .hook_mask = e->comefrom,
 411                .family    = NFPROTO_ARP,
 412        };
 413
 414        return xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
 415}
 416
 417static inline int
 418find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)
 419{
 420        struct xt_entry_target *t;
 421        struct xt_target *target;
 422        unsigned long pcnt;
 423        int ret;
 424
 425        pcnt = xt_percpu_counter_alloc();
 426        if (IS_ERR_VALUE(pcnt))
 427                return -ENOMEM;
 428        e->counters.pcnt = pcnt;
 429
 430        t = arpt_get_target(e);
 431        target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
 432                                        t->u.user.revision);
 433        if (IS_ERR(target)) {
 434                ret = PTR_ERR(target);
 435                goto out;
 436        }
 437        t->u.kernel.target = target;
 438
 439        ret = check_target(e, name);
 440        if (ret)
 441                goto err;
 442        return 0;
 443err:
 444        module_put(t->u.kernel.target->me);
 445out:
 446        xt_percpu_counter_free(e->counters.pcnt);
 447
 448        return ret;
 449}
 450
 451static bool check_underflow(const struct arpt_entry *e)
 452{
 453        const struct xt_entry_target *t;
 454        unsigned int verdict;
 455
 456        if (!unconditional(e))
 457                return false;
 458        t = arpt_get_target_c(e);
 459        if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
 460                return false;
 461        verdict = ((struct xt_standard_target *)t)->verdict;
 462        verdict = -verdict - 1;
 463        return verdict == NF_DROP || verdict == NF_ACCEPT;
 464}
 465
 466static inline int check_entry_size_and_hooks(struct arpt_entry *e,
 467                                             struct xt_table_info *newinfo,
 468                                             const unsigned char *base,
 469                                             const unsigned char *limit,
 470                                             const unsigned int *hook_entries,
 471                                             const unsigned int *underflows,
 472                                             unsigned int valid_hooks)
 473{
 474        unsigned int h;
 475        int err;
 476
 477        if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 ||
 478            (unsigned char *)e + sizeof(struct arpt_entry) >= limit ||
 479            (unsigned char *)e + e->next_offset > limit)
 480                return -EINVAL;
 481
 482        if (e->next_offset
 483            < sizeof(struct arpt_entry) + sizeof(struct xt_entry_target))
 484                return -EINVAL;
 485
 486        if (!arp_checkentry(&e->arp))
 487                return -EINVAL;
 488
 489        err = xt_check_entry_offsets(e, e->elems, e->target_offset,
 490                                     e->next_offset);
 491        if (err)
 492                return err;
 493
 494        /* Check hooks & underflows */
 495        for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
 496                if (!(valid_hooks & (1 << h)))
 497                        continue;
 498                if ((unsigned char *)e - base == hook_entries[h])
 499                        newinfo->hook_entry[h] = hook_entries[h];
 500                if ((unsigned char *)e - base == underflows[h]) {
 501                        if (!check_underflow(e))
 502                                return -EINVAL;
 503
 504                        newinfo->underflow[h] = underflows[h];
 505                }
 506        }
 507
 508        /* Clear counters and comefrom */
 509        e->counters = ((struct xt_counters) { 0, 0 });
 510        e->comefrom = 0;
 511        return 0;
 512}
 513
 514static inline void cleanup_entry(struct arpt_entry *e)
 515{
 516        struct xt_tgdtor_param par;
 517        struct xt_entry_target *t;
 518
 519        t = arpt_get_target(e);
 520        par.target   = t->u.kernel.target;
 521        par.targinfo = t->data;
 522        par.family   = NFPROTO_ARP;
 523        if (par.target->destroy != NULL)
 524                par.target->destroy(&par);
 525        module_put(par.target->me);
 526        xt_percpu_counter_free(e->counters.pcnt);
 527}
 528
 529/* Checks and translates the user-supplied table segment (held in
 530 * newinfo).
 531 */
 532static int translate_table(struct xt_table_info *newinfo, void *entry0,
 533                           const struct arpt_replace *repl)
 534{
 535        struct arpt_entry *iter;
 536        unsigned int *offsets;
 537        unsigned int i;
 538        int ret = 0;
 539
 540        newinfo->size = repl->size;
 541        newinfo->number = repl->num_entries;
 542
 543        /* Init all hooks to impossible value. */
 544        for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
 545                newinfo->hook_entry[i] = 0xFFFFFFFF;
 546                newinfo->underflow[i] = 0xFFFFFFFF;
 547        }
 548
 549        offsets = xt_alloc_entry_offsets(newinfo->number);
 550        if (!offsets)
 551                return -ENOMEM;
 552        i = 0;
 553
 554        /* Walk through entries, checking offsets. */
 555        xt_entry_foreach(iter, entry0, newinfo->size) {
 556                ret = check_entry_size_and_hooks(iter, newinfo, entry0,
 557                                                 entry0 + repl->size,
 558                                                 repl->hook_entry,
 559                                                 repl->underflow,
 560                                                 repl->valid_hooks);
 561                if (ret != 0)
 562                        goto out_free;
 563                if (i < repl->num_entries)
 564                        offsets[i] = (void *)iter - entry0;
 565                ++i;
 566                if (strcmp(arpt_get_target(iter)->u.user.name,
 567                    XT_ERROR_TARGET) == 0)
 568                        ++newinfo->stacksize;
 569        }
 570        if (ret != 0)
 571                goto out_free;
 572
 573        ret = -EINVAL;
 574        if (i != repl->num_entries)
 575                goto out_free;
 576
 577        /* Check hooks all assigned */
 578        for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
 579                /* Only hooks which are valid */
 580                if (!(repl->valid_hooks & (1 << i)))
 581                        continue;
 582                if (newinfo->hook_entry[i] == 0xFFFFFFFF)
 583                        goto out_free;
 584                if (newinfo->underflow[i] == 0xFFFFFFFF)
 585                        goto out_free;
 586        }
 587
 588        if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) {
 589                ret = -ELOOP;
 590                goto out_free;
 591        }
 592        kvfree(offsets);
 593
 594        /* Finally, each sanity check must pass */
 595        i = 0;
 596        xt_entry_foreach(iter, entry0, newinfo->size) {
 597                ret = find_check_entry(iter, repl->name, repl->size);
 598                if (ret != 0)
 599                        break;
 600                ++i;
 601        }
 602
 603        if (ret != 0) {
 604                xt_entry_foreach(iter, entry0, newinfo->size) {
 605                        if (i-- == 0)
 606                                break;
 607                        cleanup_entry(iter);
 608                }
 609                return ret;
 610        }
 611
 612        return ret;
 613 out_free:
 614        kvfree(offsets);
 615        return ret;
 616}
 617
 618static void get_counters(const struct xt_table_info *t,
 619                         struct xt_counters counters[])
 620{
 621        struct arpt_entry *iter;
 622        unsigned int cpu;
 623        unsigned int i;
 624
 625        for_each_possible_cpu(cpu) {
 626                seqcount_t *s = &per_cpu(xt_recseq, cpu);
 627
 628                i = 0;
 629                xt_entry_foreach(iter, t->entries, t->size) {
 630                        struct xt_counters *tmp;
 631                        u64 bcnt, pcnt;
 632                        unsigned int start;
 633
 634                        tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
 635                        do {
 636                                start = read_seqcount_begin(s);
 637                                bcnt = tmp->bcnt;
 638                                pcnt = tmp->pcnt;
 639                        } while (read_seqcount_retry(s, start));
 640
 641                        ADD_COUNTER(counters[i], bcnt, pcnt);
 642                        ++i;
 643                }
 644        }
 645}
 646
 647static struct xt_counters *alloc_counters(const struct xt_table *table)
 648{
 649        unsigned int countersize;
 650        struct xt_counters *counters;
 651        const struct xt_table_info *private = table->private;
 652
 653        /* We need atomic snapshot of counters: rest doesn't change
 654         * (other than comefrom, which userspace doesn't care
 655         * about).
 656         */
 657        countersize = sizeof(struct xt_counters) * private->number;
 658        counters = vzalloc(countersize);
 659
 660        if (counters == NULL)
 661                return ERR_PTR(-ENOMEM);
 662
 663        get_counters(private, counters);
 664
 665        return counters;
 666}
 667
 668static int copy_entries_to_user(unsigned int total_size,
 669                                const struct xt_table *table,
 670                                void __user *userptr)
 671{
 672        unsigned int off, num;
 673        const struct arpt_entry *e;
 674        struct xt_counters *counters;
 675        struct xt_table_info *private = table->private;
 676        int ret = 0;
 677        void *loc_cpu_entry;
 678
 679        counters = alloc_counters(table);
 680        if (IS_ERR(counters))
 681                return PTR_ERR(counters);
 682
 683        loc_cpu_entry = private->entries;
 684        /* ... then copy entire thing ... */
 685        if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
 686                ret = -EFAULT;
 687                goto free_counters;
 688        }
 689
 690        /* FIXME: use iterator macros --RR */
 691        /* ... then go back and fix counters and names */
 692        for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
 693                const struct xt_entry_target *t;
 694
 695                e = (struct arpt_entry *)(loc_cpu_entry + off);
 696                if (copy_to_user(userptr + off
 697                                 + offsetof(struct arpt_entry, counters),
 698                                 &counters[num],
 699                                 sizeof(counters[num])) != 0) {
 700                        ret = -EFAULT;
 701                        goto free_counters;
 702                }
 703
 704                t = arpt_get_target_c(e);
 705                if (copy_to_user(userptr + off + e->target_offset
 706                                 + offsetof(struct xt_entry_target,
 707                                            u.user.name),
 708                                 t->u.kernel.target->name,
 709                                 strlen(t->u.kernel.target->name)+1) != 0) {
 710                        ret = -EFAULT;
 711                        goto free_counters;
 712                }
 713        }
 714
 715 free_counters:
 716        vfree(counters);
 717        return ret;
 718}
 719
 720#ifdef CONFIG_COMPAT
 721static void compat_standard_from_user(void *dst, const void *src)
 722{
 723        int v = *(compat_int_t *)src;
 724
 725        if (v > 0)
 726                v += xt_compat_calc_jump(NFPROTO_ARP, v);
 727        memcpy(dst, &v, sizeof(v));
 728}
 729
 730static int compat_standard_to_user(void __user *dst, const void *src)
 731{
 732        compat_int_t cv = *(int *)src;
 733
 734        if (cv > 0)
 735                cv -= xt_compat_calc_jump(NFPROTO_ARP, cv);
 736        return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
 737}
 738
 739static int compat_calc_entry(const struct arpt_entry *e,
 740                             const struct xt_table_info *info,
 741                             const void *base, struct xt_table_info *newinfo)
 742{
 743        const struct xt_entry_target *t;
 744        unsigned int entry_offset;
 745        int off, i, ret;
 746
 747        off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);
 748        entry_offset = (void *)e - base;
 749
 750        t = arpt_get_target_c(e);
 751        off += xt_compat_target_offset(t->u.kernel.target);
 752        newinfo->size -= off;
 753        ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off);
 754        if (ret)
 755                return ret;
 756
 757        for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
 758                if (info->hook_entry[i] &&
 759                    (e < (struct arpt_entry *)(base + info->hook_entry[i])))
 760                        newinfo->hook_entry[i] -= off;
 761                if (info->underflow[i] &&
 762                    (e < (struct arpt_entry *)(base + info->underflow[i])))
 763                        newinfo->underflow[i] -= off;
 764        }
 765        return 0;
 766}
 767
 768static int compat_table_info(const struct xt_table_info *info,
 769                             struct xt_table_info *newinfo)
 770{
 771        struct arpt_entry *iter;
 772        const void *loc_cpu_entry;
 773        int ret;
 774
 775        if (!newinfo || !info)
 776                return -EINVAL;
 777
 778        /* we dont care about newinfo->entries */
 779        memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
 780        newinfo->initial_entries = 0;
 781        loc_cpu_entry = info->entries;
 782        xt_compat_init_offsets(NFPROTO_ARP, info->number);
 783        xt_entry_foreach(iter, loc_cpu_entry, info->size) {
 784                ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
 785                if (ret != 0)
 786                        return ret;
 787        }
 788        return 0;
 789}
 790#endif
 791
 792static int get_info(struct net *net, void __user *user,
 793                    const int *len, int compat)
 794{
 795        char name[XT_TABLE_MAXNAMELEN];
 796        struct xt_table *t;
 797        int ret;
 798
 799        if (*len != sizeof(struct arpt_getinfo))
 800                return -EINVAL;
 801
 802        if (copy_from_user(name, user, sizeof(name)) != 0)
 803                return -EFAULT;
 804
 805        name[XT_TABLE_MAXNAMELEN-1] = '\0';
 806#ifdef CONFIG_COMPAT
 807        if (compat)
 808                xt_compat_lock(NFPROTO_ARP);
 809#endif
 810        t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name),
 811                                    "arptable_%s", name);
 812        if (!IS_ERR_OR_NULL(t)) {
 813                struct arpt_getinfo info;
 814                const struct xt_table_info *private = t->private;
 815#ifdef CONFIG_COMPAT
 816                struct xt_table_info tmp;
 817
 818                if (compat) {
 819                        ret = compat_table_info(private, &tmp);
 820                        xt_compat_flush_offsets(NFPROTO_ARP);
 821                        private = &tmp;
 822                }
 823#endif
 824                memset(&info, 0, sizeof(info));
 825                info.valid_hooks = t->valid_hooks;
 826                memcpy(info.hook_entry, private->hook_entry,
 827                       sizeof(info.hook_entry));
 828                memcpy(info.underflow, private->underflow,
 829                       sizeof(info.underflow));
 830                info.num_entries = private->number;
 831                info.size = private->size;
 832                strcpy(info.name, name);
 833
 834                if (copy_to_user(user, &info, *len) != 0)
 835                        ret = -EFAULT;
 836                else
 837                        ret = 0;
 838                xt_table_unlock(t);
 839                module_put(t->me);
 840        } else
 841                ret = t ? PTR_ERR(t) : -ENOENT;
 842#ifdef CONFIG_COMPAT
 843        if (compat)
 844                xt_compat_unlock(NFPROTO_ARP);
 845#endif
 846        return ret;
 847}
 848
 849static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
 850                       const int *len)
 851{
 852        int ret;
 853        struct arpt_get_entries get;
 854        struct xt_table *t;
 855
 856        if (*len < sizeof(get))
 857                return -EINVAL;
 858        if (copy_from_user(&get, uptr, sizeof(get)) != 0)
 859                return -EFAULT;
 860        if (*len != sizeof(struct arpt_get_entries) + get.size)
 861                return -EINVAL;
 862
 863        get.name[sizeof(get.name) - 1] = '\0';
 864
 865        t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
 866        if (!IS_ERR_OR_NULL(t)) {
 867                const struct xt_table_info *private = t->private;
 868
 869                if (get.size == private->size)
 870                        ret = copy_entries_to_user(private->size,
 871                                                   t, uptr->entrytable);
 872                else
 873                        ret = -EAGAIN;
 874
 875                module_put(t->me);
 876                xt_table_unlock(t);
 877        } else
 878                ret = t ? PTR_ERR(t) : -ENOENT;
 879
 880        return ret;
 881}
 882
 883static int __do_replace(struct net *net, const char *name,
 884                        unsigned int valid_hooks,
 885                        struct xt_table_info *newinfo,
 886                        unsigned int num_counters,
 887                        void __user *counters_ptr)
 888{
 889        int ret;
 890        struct xt_table *t;
 891        struct xt_table_info *oldinfo;
 892        struct xt_counters *counters;
 893        void *loc_cpu_old_entry;
 894        struct arpt_entry *iter;
 895
 896        ret = 0;
 897        counters = vzalloc(num_counters * sizeof(struct xt_counters));
 898        if (!counters) {
 899                ret = -ENOMEM;
 900                goto out;
 901        }
 902
 903        t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name),
 904                                    "arptable_%s", name);
 905        if (IS_ERR_OR_NULL(t)) {
 906                ret = t ? PTR_ERR(t) : -ENOENT;
 907                goto free_newinfo_counters_untrans;
 908        }
 909
 910        /* You lied! */
 911        if (valid_hooks != t->valid_hooks) {
 912                ret = -EINVAL;
 913                goto put_module;
 914        }
 915
 916        oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
 917        if (!oldinfo)
 918                goto put_module;
 919
 920        /* Update module usage count based on number of rules */
 921        if ((oldinfo->number > oldinfo->initial_entries) ||
 922            (newinfo->number <= oldinfo->initial_entries))
 923                module_put(t->me);
 924        if ((oldinfo->number > oldinfo->initial_entries) &&
 925            (newinfo->number <= oldinfo->initial_entries))
 926                module_put(t->me);
 927
 928        /* Get the old counters, and synchronize with replace */
 929        get_counters(oldinfo, counters);
 930
 931        /* Decrease module usage counts and free resource */
 932        loc_cpu_old_entry = oldinfo->entries;
 933        xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
 934                cleanup_entry(iter);
 935
 936        xt_free_table_info(oldinfo);
 937        if (copy_to_user(counters_ptr, counters,
 938                         sizeof(struct xt_counters) * num_counters) != 0) {
 939                /* Silent error, can't fail, new table is already in place */
 940                net_warn_ratelimited("arptables: counters copy to user failed while replacing table\n");
 941        }
 942        vfree(counters);
 943        xt_table_unlock(t);
 944        return ret;
 945
 946 put_module:
 947        module_put(t->me);
 948        xt_table_unlock(t);
 949 free_newinfo_counters_untrans:
 950        vfree(counters);
 951 out:
 952        return ret;
 953}
 954
 955static int do_replace(struct net *net, const void __user *user,
 956                      unsigned int len)
 957{
 958        int ret;
 959        struct arpt_replace tmp;
 960        struct xt_table_info *newinfo;
 961        void *loc_cpu_entry;
 962        struct arpt_entry *iter;
 963
 964        if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
 965                return -EFAULT;
 966
 967        /* overflow check */
 968        if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 969                return -ENOMEM;
 970        if (tmp.num_counters == 0)
 971                return -EINVAL;
 972
 973        tmp.name[sizeof(tmp.name)-1] = 0;
 974
 975        newinfo = xt_alloc_table_info(tmp.size);
 976        if (!newinfo)
 977                return -ENOMEM;
 978
 979        loc_cpu_entry = newinfo->entries;
 980        if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
 981                           tmp.size) != 0) {
 982                ret = -EFAULT;
 983                goto free_newinfo;
 984        }
 985
 986        ret = translate_table(newinfo, loc_cpu_entry, &tmp);
 987        if (ret != 0)
 988                goto free_newinfo;
 989
 990        ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
 991                           tmp.num_counters, tmp.counters);
 992        if (ret)
 993                goto free_newinfo_untrans;
 994        return 0;
 995
 996 free_newinfo_untrans:
 997        xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
 998                cleanup_entry(iter);
 999 free_newinfo:
1000        xt_free_table_info(newinfo);
1001        return ret;
1002}
1003
1004static int do_add_counters(struct net *net, const void __user *user,
1005                           unsigned int len, int compat)
1006{
1007        unsigned int i;
1008        struct xt_counters_info tmp;
1009        struct xt_counters *paddc;
1010        struct xt_table *t;
1011        const struct xt_table_info *private;
1012        int ret = 0;
1013        struct arpt_entry *iter;
1014        unsigned int addend;
1015
1016        paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
1017        if (IS_ERR(paddc))
1018                return PTR_ERR(paddc);
1019
1020        t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name);
1021        if (IS_ERR_OR_NULL(t)) {
1022                ret = t ? PTR_ERR(t) : -ENOENT;
1023                goto free;
1024        }
1025
1026        local_bh_disable();
1027        private = t->private;
1028        if (private->number != tmp.num_counters) {
1029                ret = -EINVAL;
1030                goto unlock_up_free;
1031        }
1032
1033        i = 0;
1034
1035        addend = xt_write_recseq_begin();
1036        xt_entry_foreach(iter,  private->entries, private->size) {
1037                struct xt_counters *tmp;
1038
1039                tmp = xt_get_this_cpu_counter(&iter->counters);
1040                ADD_COUNTER(*tmp, paddc[i].bcnt, paddc[i].pcnt);
1041                ++i;
1042        }
1043        xt_write_recseq_end(addend);
1044 unlock_up_free:
1045        local_bh_enable();
1046        xt_table_unlock(t);
1047        module_put(t->me);
1048 free:
1049        vfree(paddc);
1050
1051        return ret;
1052}
1053
1054#ifdef CONFIG_COMPAT
1055struct compat_arpt_replace {
1056        char                            name[XT_TABLE_MAXNAMELEN];
1057        u32                             valid_hooks;
1058        u32                             num_entries;
1059        u32                             size;
1060        u32                             hook_entry[NF_ARP_NUMHOOKS];
1061        u32                             underflow[NF_ARP_NUMHOOKS];
1062        u32                             num_counters;
1063        compat_uptr_t                   counters;
1064        struct compat_arpt_entry        entries[0];
1065};
1066
1067static inline void compat_release_entry(struct compat_arpt_entry *e)
1068{
1069        struct xt_entry_target *t;
1070
1071        t = compat_arpt_get_target(e);
1072        module_put(t->u.kernel.target->me);
1073}
1074
1075static int
1076check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
1077                                  struct xt_table_info *newinfo,
1078                                  unsigned int *size,
1079                                  const unsigned char *base,
1080                                  const unsigned char *limit)
1081{
1082        struct xt_entry_target *t;
1083        struct xt_target *target;
1084        unsigned int entry_offset;
1085        int ret, off;
1086
1087        if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 ||
1088            (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit ||
1089            (unsigned char *)e + e->next_offset > limit)
1090                return -EINVAL;
1091
1092        if (e->next_offset < sizeof(struct compat_arpt_entry) +
1093                             sizeof(struct compat_xt_entry_target))
1094                return -EINVAL;
1095
1096        if (!arp_checkentry(&e->arp))
1097                return -EINVAL;
1098
1099        ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset,
1100                                            e->next_offset);
1101        if (ret)
1102                return ret;
1103
1104        off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);
1105        entry_offset = (void *)e - (void *)base;
1106
1107        t = compat_arpt_get_target(e);
1108        target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
1109                                        t->u.user.revision);
1110        if (IS_ERR(target)) {
1111                ret = PTR_ERR(target);
1112                goto out;
1113        }
1114        t->u.kernel.target = target;
1115
1116        off += xt_compat_target_offset(target);
1117        *size += off;
1118        ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off);
1119        if (ret)
1120                goto release_target;
1121
1122        return 0;
1123
1124release_target:
1125        module_put(t->u.kernel.target->me);
1126out:
1127        return ret;
1128}
1129
1130static void
1131compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
1132                            unsigned int *size,
1133                            struct xt_table_info *newinfo, unsigned char *base)
1134{
1135        struct xt_entry_target *t;
1136        struct xt_target *target;
1137        struct arpt_entry *de;
1138        unsigned int origsize;
1139        int h;
1140
1141        origsize = *size;
1142        de = (struct arpt_entry *)*dstptr;
1143        memcpy(de, e, sizeof(struct arpt_entry));
1144        memcpy(&de->counters, &e->counters, sizeof(e->counters));
1145
1146        *dstptr += sizeof(struct arpt_entry);
1147        *size += sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);
1148
1149        de->target_offset = e->target_offset - (origsize - *size);
1150        t = compat_arpt_get_target(e);
1151        target = t->u.kernel.target;
1152        xt_compat_target_from_user(t, dstptr, size);
1153
1154        de->next_offset = e->next_offset - (origsize - *size);
1155        for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
1156                if ((unsigned char *)de - base < newinfo->hook_entry[h])
1157                        newinfo->hook_entry[h] -= origsize - *size;
1158                if ((unsigned char *)de - base < newinfo->underflow[h])
1159                        newinfo->underflow[h] -= origsize - *size;
1160        }
1161}
1162
1163static int translate_compat_table(struct xt_table_info **pinfo,
1164                                  void **pentry0,
1165                                  const struct compat_arpt_replace *compatr)
1166{
1167        unsigned int i, j;
1168        struct xt_table_info *newinfo, *info;
1169        void *pos, *entry0, *entry1;
1170        struct compat_arpt_entry *iter0;
1171        struct arpt_replace repl;
1172        unsigned int size;
1173        int ret = 0;
1174
1175        info = *pinfo;
1176        entry0 = *pentry0;
1177        size = compatr->size;
1178        info->number = compatr->num_entries;
1179
1180        j = 0;
1181        xt_compat_lock(NFPROTO_ARP);
1182        xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries);
1183        /* Walk through entries, checking offsets. */
1184        xt_entry_foreach(iter0, entry0, compatr->size) {
1185                ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1186                                                        entry0,
1187                                                        entry0 + compatr->size);
1188                if (ret != 0)
1189                        goto out_unlock;
1190                ++j;
1191        }
1192
1193        ret = -EINVAL;
1194        if (j != compatr->num_entries)
1195                goto out_unlock;
1196
1197        ret = -ENOMEM;
1198        newinfo = xt_alloc_table_info(size);
1199        if (!newinfo)
1200                goto out_unlock;
1201
1202        newinfo->number = compatr->num_entries;
1203        for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
1204                newinfo->hook_entry[i] = compatr->hook_entry[i];
1205                newinfo->underflow[i] = compatr->underflow[i];
1206        }
1207        entry1 = newinfo->entries;
1208        pos = entry1;
1209        size = compatr->size;
1210        xt_entry_foreach(iter0, entry0, compatr->size)
1211                compat_copy_entry_from_user(iter0, &pos, &size,
1212                                            newinfo, entry1);
1213
1214        /* all module references in entry0 are now gone */
1215
1216        xt_compat_flush_offsets(NFPROTO_ARP);
1217        xt_compat_unlock(NFPROTO_ARP);
1218
1219        memcpy(&repl, compatr, sizeof(*compatr));
1220
1221        for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
1222                repl.hook_entry[i] = newinfo->hook_entry[i];
1223                repl.underflow[i] = newinfo->underflow[i];
1224        }
1225
1226        repl.num_counters = 0;
1227        repl.counters = NULL;
1228        repl.size = newinfo->size;
1229        ret = translate_table(newinfo, entry1, &repl);
1230        if (ret)
1231                goto free_newinfo;
1232
1233        *pinfo = newinfo;
1234        *pentry0 = entry1;
1235        xt_free_table_info(info);
1236        return 0;
1237
1238free_newinfo:
1239        xt_free_table_info(newinfo);
1240        return ret;
1241out_unlock:
1242        xt_compat_flush_offsets(NFPROTO_ARP);
1243        xt_compat_unlock(NFPROTO_ARP);
1244        xt_entry_foreach(iter0, entry0, compatr->size) {
1245                if (j-- == 0)
1246                        break;
1247                compat_release_entry(iter0);
1248        }
1249        return ret;
1250}
1251
1252static int compat_do_replace(struct net *net, void __user *user,
1253                             unsigned int len)
1254{
1255        int ret;
1256        struct compat_arpt_replace tmp;
1257        struct xt_table_info *newinfo;
1258        void *loc_cpu_entry;
1259        struct arpt_entry *iter;
1260
1261        if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1262                return -EFAULT;
1263
1264        /* overflow check */
1265        if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1266                return -ENOMEM;
1267        if (tmp.num_counters == 0)
1268                return -EINVAL;
1269
1270        tmp.name[sizeof(tmp.name)-1] = 0;
1271
1272        newinfo = xt_alloc_table_info(tmp.size);
1273        if (!newinfo)
1274                return -ENOMEM;
1275
1276        loc_cpu_entry = newinfo->entries;
1277        if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), tmp.size) != 0) {
1278                ret = -EFAULT;
1279                goto free_newinfo;
1280        }
1281
1282        ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
1283        if (ret != 0)
1284                goto free_newinfo;
1285
1286        ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1287                           tmp.num_counters, compat_ptr(tmp.counters));
1288        if (ret)
1289                goto free_newinfo_untrans;
1290        return 0;
1291
1292 free_newinfo_untrans:
1293        xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1294                cleanup_entry(iter);
1295 free_newinfo:
1296        xt_free_table_info(newinfo);
1297        return ret;
1298}
1299
1300static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user,
1301                                  unsigned int len)
1302{
1303        int ret;
1304
1305        if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1306                return -EPERM;
1307
1308        switch (cmd) {
1309        case ARPT_SO_SET_REPLACE:
1310                ret = compat_do_replace(sock_net(sk), user, len);
1311                break;
1312
1313        case ARPT_SO_SET_ADD_COUNTERS:
1314                ret = do_add_counters(sock_net(sk), user, len, 1);
1315                break;
1316
1317        default:
1318                ret = -EINVAL;
1319        }
1320
1321        return ret;
1322}
1323
1324static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr,
1325                                     compat_uint_t *size,
1326                                     struct xt_counters *counters,
1327                                     unsigned int i)
1328{
1329        struct xt_entry_target *t;
1330        struct compat_arpt_entry __user *ce;
1331        u_int16_t target_offset, next_offset;
1332        compat_uint_t origsize;
1333        int ret;
1334
1335        origsize = *size;
1336        ce = (struct compat_arpt_entry __user *)*dstptr;
1337        if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 ||
1338            copy_to_user(&ce->counters, &counters[i],
1339            sizeof(counters[i])) != 0)
1340                return -EFAULT;
1341
1342        *dstptr += sizeof(struct compat_arpt_entry);
1343        *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);
1344
1345        target_offset = e->target_offset - (origsize - *size);
1346
1347        t = arpt_get_target(e);
1348        ret = xt_compat_target_to_user(t, dstptr, size);
1349        if (ret)
1350                return ret;
1351        next_offset = e->next_offset - (origsize - *size);
1352        if (put_user(target_offset, &ce->target_offset) != 0 ||
1353            put_user(next_offset, &ce->next_offset) != 0)
1354                return -EFAULT;
1355        return 0;
1356}
1357
1358static int compat_copy_entries_to_user(unsigned int total_size,
1359                                       struct xt_table *table,
1360                                       void __user *userptr)
1361{
1362        struct xt_counters *counters;
1363        const struct xt_table_info *private = table->private;
1364        void __user *pos;
1365        unsigned int size;
1366        int ret = 0;
1367        unsigned int i = 0;
1368        struct arpt_entry *iter;
1369
1370        counters = alloc_counters(table);
1371        if (IS_ERR(counters))
1372                return PTR_ERR(counters);
1373
1374        pos = userptr;
1375        size = total_size;
1376        xt_entry_foreach(iter, private->entries, total_size) {
1377                ret = compat_copy_entry_to_user(iter, &pos,
1378                                                &size, counters, i++);
1379                if (ret != 0)
1380                        break;
1381        }
1382        vfree(counters);
1383        return ret;
1384}
1385
1386struct compat_arpt_get_entries {
1387        char name[XT_TABLE_MAXNAMELEN];
1388        compat_uint_t size;
1389        struct compat_arpt_entry entrytable[0];
1390};
1391
1392static int compat_get_entries(struct net *net,
1393                              struct compat_arpt_get_entries __user *uptr,
1394                              int *len)
1395{
1396        int ret;
1397        struct compat_arpt_get_entries get;
1398        struct xt_table *t;
1399
1400        if (*len < sizeof(get))
1401                return -EINVAL;
1402        if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1403                return -EFAULT;
1404        if (*len != sizeof(struct compat_arpt_get_entries) + get.size)
1405                return -EINVAL;
1406
1407        get.name[sizeof(get.name) - 1] = '\0';
1408
1409        xt_compat_lock(NFPROTO_ARP);
1410        t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
1411        if (!IS_ERR_OR_NULL(t)) {
1412                const struct xt_table_info *private = t->private;
1413                struct xt_table_info info;
1414
1415                ret = compat_table_info(private, &info);
1416                if (!ret && get.size == info.size) {
1417                        ret = compat_copy_entries_to_user(private->size,
1418                                                          t, uptr->entrytable);
1419                } else if (!ret)
1420                        ret = -EAGAIN;
1421
1422                xt_compat_flush_offsets(NFPROTO_ARP);
1423                module_put(t->me);
1424                xt_table_unlock(t);
1425        } else
1426                ret = t ? PTR_ERR(t) : -ENOENT;
1427
1428        xt_compat_unlock(NFPROTO_ARP);
1429        return ret;
1430}
1431
1432static int do_arpt_get_ctl(struct sock *, int, void __user *, int *);
1433
1434static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user,
1435                                  int *len)
1436{
1437        int ret;
1438
1439        if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1440                return -EPERM;
1441
1442        switch (cmd) {
1443        case ARPT_SO_GET_INFO:
1444                ret = get_info(sock_net(sk), user, len, 1);
1445                break;
1446        case ARPT_SO_GET_ENTRIES:
1447                ret = compat_get_entries(sock_net(sk), user, len);
1448                break;
1449        default:
1450                ret = do_arpt_get_ctl(sk, cmd, user, len);
1451        }
1452        return ret;
1453}
1454#endif
1455
1456static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1457{
1458        int ret;
1459
1460        if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1461                return -EPERM;
1462
1463        switch (cmd) {
1464        case ARPT_SO_SET_REPLACE:
1465                ret = do_replace(sock_net(sk), user, len);
1466                break;
1467
1468        case ARPT_SO_SET_ADD_COUNTERS:
1469                ret = do_add_counters(sock_net(sk), user, len, 0);
1470                break;
1471
1472        default:
1473                ret = -EINVAL;
1474        }
1475
1476        return ret;
1477}
1478
1479static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1480{
1481        int ret;
1482
1483        if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1484                return -EPERM;
1485
1486        switch (cmd) {
1487        case ARPT_SO_GET_INFO:
1488                ret = get_info(sock_net(sk), user, len, 0);
1489                break;
1490
1491        case ARPT_SO_GET_ENTRIES:
1492                ret = get_entries(sock_net(sk), user, len);
1493                break;
1494
1495        case ARPT_SO_GET_REVISION_TARGET: {
1496                struct xt_get_revision rev;
1497
1498                if (*len != sizeof(rev)) {
1499                        ret = -EINVAL;
1500                        break;
1501                }
1502                if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1503                        ret = -EFAULT;
1504                        break;
1505                }
1506                rev.name[sizeof(rev.name)-1] = 0;
1507
1508                try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name,
1509                                                         rev.revision, 1, &ret),
1510                                        "arpt_%s", rev.name);
1511                break;
1512        }
1513
1514        default:
1515                ret = -EINVAL;
1516        }
1517
1518        return ret;
1519}
1520
1521static void __arpt_unregister_table(struct xt_table *table)
1522{
1523        struct xt_table_info *private;
1524        void *loc_cpu_entry;
1525        struct module *table_owner = table->me;
1526        struct arpt_entry *iter;
1527
1528        private = xt_unregister_table(table);
1529
1530        /* Decrease module usage counts and free resources */
1531        loc_cpu_entry = private->entries;
1532        xt_entry_foreach(iter, loc_cpu_entry, private->size)
1533                cleanup_entry(iter);
1534        if (private->number > private->initial_entries)
1535                module_put(table_owner);
1536        xt_free_table_info(private);
1537}
1538
1539int arpt_register_table(struct net *net,
1540                        const struct xt_table *table,
1541                        const struct arpt_replace *repl,
1542                        const struct nf_hook_ops *ops,
1543                        struct xt_table **res)
1544{
1545        int ret;
1546        struct xt_table_info *newinfo;
1547        struct xt_table_info bootstrap = {0};
1548        void *loc_cpu_entry;
1549        struct xt_table *new_table;
1550
1551        newinfo = xt_alloc_table_info(repl->size);
1552        if (!newinfo)
1553                return -ENOMEM;
1554
1555        loc_cpu_entry = newinfo->entries;
1556        memcpy(loc_cpu_entry, repl->entries, repl->size);
1557
1558        ret = translate_table(newinfo, loc_cpu_entry, repl);
1559        if (ret != 0)
1560                goto out_free;
1561
1562        new_table = xt_register_table(net, table, &bootstrap, newinfo);
1563        if (IS_ERR(new_table)) {
1564                ret = PTR_ERR(new_table);
1565                goto out_free;
1566        }
1567
1568        /* set res now, will see skbs right after nf_register_net_hooks */
1569        WRITE_ONCE(*res, new_table);
1570
1571        ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
1572        if (ret != 0) {
1573                __arpt_unregister_table(new_table);
1574                *res = NULL;
1575        }
1576
1577        return ret;
1578
1579out_free:
1580        xt_free_table_info(newinfo);
1581        return ret;
1582}
1583
1584void arpt_unregister_table(struct net *net, struct xt_table *table,
1585                           const struct nf_hook_ops *ops)
1586{
1587        nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
1588        __arpt_unregister_table(table);
1589}
1590
1591/* The built-in targets: standard (NULL) and error. */
1592static struct xt_target arpt_builtin_tg[] __read_mostly = {
1593        {
1594                .name             = XT_STANDARD_TARGET,
1595                .targetsize       = sizeof(int),
1596                .family           = NFPROTO_ARP,
1597#ifdef CONFIG_COMPAT
1598                .compatsize       = sizeof(compat_int_t),
1599                .compat_from_user = compat_standard_from_user,
1600                .compat_to_user   = compat_standard_to_user,
1601#endif
1602        },
1603        {
1604                .name             = XT_ERROR_TARGET,
1605                .target           = arpt_error,
1606                .targetsize       = XT_FUNCTION_MAXNAMELEN,
1607                .family           = NFPROTO_ARP,
1608        },
1609};
1610
1611static struct nf_sockopt_ops arpt_sockopts = {
1612        .pf             = PF_INET,
1613        .set_optmin     = ARPT_BASE_CTL,
1614        .set_optmax     = ARPT_SO_SET_MAX+1,
1615        .set            = do_arpt_set_ctl,
1616#ifdef CONFIG_COMPAT
1617        .compat_set     = compat_do_arpt_set_ctl,
1618#endif
1619        .get_optmin     = ARPT_BASE_CTL,
1620        .get_optmax     = ARPT_SO_GET_MAX+1,
1621        .get            = do_arpt_get_ctl,
1622#ifdef CONFIG_COMPAT
1623        .compat_get     = compat_do_arpt_get_ctl,
1624#endif
1625        .owner          = THIS_MODULE,
1626};
1627
1628static int __net_init arp_tables_net_init(struct net *net)
1629{
1630        return xt_proto_init(net, NFPROTO_ARP);
1631}
1632
1633static void __net_exit arp_tables_net_exit(struct net *net)
1634{
1635        xt_proto_fini(net, NFPROTO_ARP);
1636}
1637
1638static struct pernet_operations arp_tables_net_ops = {
1639        .init = arp_tables_net_init,
1640        .exit = arp_tables_net_exit,
1641};
1642
1643static int __init arp_tables_init(void)
1644{
1645        int ret;
1646
1647        ret = register_pernet_subsys(&arp_tables_net_ops);
1648        if (ret < 0)
1649                goto err1;
1650
1651        /* No one else will be downing sem now, so we won't sleep */
1652        ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg));
1653        if (ret < 0)
1654                goto err2;
1655
1656        /* Register setsockopt */
1657        ret = nf_register_sockopt(&arpt_sockopts);
1658        if (ret < 0)
1659                goto err4;
1660
1661        pr_info("arp_tables: (C) 2002 David S. Miller\n");
1662        return 0;
1663
1664err4:
1665        xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg));
1666err2:
1667        unregister_pernet_subsys(&arp_tables_net_ops);
1668err1:
1669        return ret;
1670}
1671
1672static void __exit arp_tables_fini(void)
1673{
1674        nf_unregister_sockopt(&arpt_sockopts);
1675        xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg));
1676        unregister_pernet_subsys(&arp_tables_net_ops);
1677}
1678
1679EXPORT_SYMBOL(arpt_register_table);
1680EXPORT_SYMBOL(arpt_unregister_table);
1681EXPORT_SYMBOL(arpt_do_table);
1682
1683module_init(arp_tables_init);
1684module_exit(arp_tables_fini);
1685