Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[sfrench/cifs-2.6.git] / net / ipv4 / netfilter / ip_tables.c
1 /*
2  * Packet matching code.
3  *
4  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5  * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/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
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
35 MODULE_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
65 void *ipt_alloc_initial_table(const struct xt_table *info)
66 {
67         return xt_alloc_initial_table(ipt, IPT);
68 }
69 EXPORT_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 */
82 static inline bool
83 ip_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
146 static bool
147 ip_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
162 static unsigned int
163 ipt_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 */
172 static inline struct ipt_entry *
173 get_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) */
180 static 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 */
189 static inline const struct ipt_entry_target *
190 ipt_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)
197 static 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
205 enum nf_ip_trace_comments {
206         NF_IP_TRACE_COMMENT_RULE,
207         NF_IP_TRACE_COMMENT_RETURN,
208         NF_IP_TRACE_COMMENT_POLICY,
209 };
210
211 static 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
217 static 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) */
228 static inline int
229 get_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 ipt_standard_target *t = (void *)ipt_get_target_c(s);
234
235         if (strcmp(t->target.u.kernel.target->name, IPT_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                            IPT_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
259 static 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
290 static inline __pure
291 struct 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. */
297 unsigned int
298 ipt_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 ipt_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 ipt_standard_target *)t)->verdict;
384                         if (v < 0) {
385                                 /* Pop from stack? */
386                                 if (v != IPT_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 == IPT_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. */
445 static int
446 mark_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 ipt_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                                      IPT_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                                             IPT_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                                            IPT_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
555 static void cleanup_match(struct ipt_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
568 static int
569 check_entry(const struct ipt_entry *e, const char *name)
570 {
571         const struct ipt_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 ipt_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
589 static int
590 check_match(struct ipt_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
607 static int
608 find_check_match(struct ipt_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;
626 err:
627         module_put(m->u.kernel.match->me);
628         return ret;
629 }
630
631 static int check_target(struct ipt_entry *e, struct net *net, const char *name)
632 {
633         struct ipt_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
655 static int
656 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
657                  unsigned int size)
658 {
659         struct ipt_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
708 static bool check_underflow(const struct ipt_entry *e)
709 {
710         const struct ipt_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 ipt_standard_target *)t)->verdict;
719         verdict = -verdict - 1;
720         return verdict == NF_DROP || verdict == NF_ACCEPT;
721 }
722
723 static int
724 check_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 ipt_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
770 static void
771 cleanup_entry(struct ipt_entry *e, struct net *net)
772 {
773         struct xt_tgdtor_param par;
774         struct ipt_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) */
793 static int
794 translate_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
880 static void
881 get_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         unsigned int curcpu = get_cpu();
888
889         /* Instead of clearing (by a previous call to memset())
890          * the counters and using adds, we set the counters
891          * with data used by 'current' CPU.
892          *
893          * Bottom half has to be disabled to prevent deadlock
894          * if new softirq were to run and call ipt_do_table
895          */
896         local_bh_disable();
897         i = 0;
898         xt_entry_foreach(iter, t->entries[curcpu], t->size) {
899                 SET_COUNTER(counters[i], iter->counters.bcnt,
900                             iter->counters.pcnt);
901                 ++i;
902         }
903         local_bh_enable();
904         /* Processing counters from other cpus, we can let bottom half enabled,
905          * (preemption is disabled)
906          */
907
908         for_each_possible_cpu(cpu) {
909                 if (cpu == curcpu)
910                         continue;
911                 i = 0;
912                 xt_info_wrlock(cpu);
913                 xt_entry_foreach(iter, t->entries[cpu], t->size) {
914                         ADD_COUNTER(counters[i], iter->counters.bcnt,
915                                     iter->counters.pcnt);
916                         ++i; /* macro does multi eval of i */
917                 }
918                 xt_info_wrunlock(cpu);
919         }
920         put_cpu();
921 }
922
923 static struct xt_counters *alloc_counters(const struct xt_table *table)
924 {
925         unsigned int countersize;
926         struct xt_counters *counters;
927         const struct xt_table_info *private = table->private;
928
929         /* We need atomic snapshot of counters: rest doesn't change
930            (other than comefrom, which userspace doesn't care
931            about). */
932         countersize = sizeof(struct xt_counters) * private->number;
933         counters = vmalloc(countersize);
934
935         if (counters == NULL)
936                 return ERR_PTR(-ENOMEM);
937
938         get_counters(private, counters);
939
940         return counters;
941 }
942
943 static int
944 copy_entries_to_user(unsigned int total_size,
945                      const struct xt_table *table,
946                      void __user *userptr)
947 {
948         unsigned int off, num;
949         const struct ipt_entry *e;
950         struct xt_counters *counters;
951         const struct xt_table_info *private = table->private;
952         int ret = 0;
953         const void *loc_cpu_entry;
954
955         counters = alloc_counters(table);
956         if (IS_ERR(counters))
957                 return PTR_ERR(counters);
958
959         /* choose the copy that is on our node/cpu, ...
960          * This choice is lazy (because current thread is
961          * allowed to migrate to another cpu)
962          */
963         loc_cpu_entry = private->entries[raw_smp_processor_id()];
964         if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
965                 ret = -EFAULT;
966                 goto free_counters;
967         }
968
969         /* FIXME: use iterator macros --RR */
970         /* ... then go back and fix counters and names */
971         for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
972                 unsigned int i;
973                 const struct ipt_entry_match *m;
974                 const struct ipt_entry_target *t;
975
976                 e = (struct ipt_entry *)(loc_cpu_entry + off);
977                 if (copy_to_user(userptr + off
978                                  + offsetof(struct ipt_entry, counters),
979                                  &counters[num],
980                                  sizeof(counters[num])) != 0) {
981                         ret = -EFAULT;
982                         goto free_counters;
983                 }
984
985                 for (i = sizeof(struct ipt_entry);
986                      i < e->target_offset;
987                      i += m->u.match_size) {
988                         m = (void *)e + i;
989
990                         if (copy_to_user(userptr + off + i
991                                          + offsetof(struct ipt_entry_match,
992                                                     u.user.name),
993                                          m->u.kernel.match->name,
994                                          strlen(m->u.kernel.match->name)+1)
995                             != 0) {
996                                 ret = -EFAULT;
997                                 goto free_counters;
998                         }
999                 }
1000
1001                 t = ipt_get_target_c(e);
1002                 if (copy_to_user(userptr + off + e->target_offset
1003                                  + offsetof(struct ipt_entry_target,
1004                                             u.user.name),
1005                                  t->u.kernel.target->name,
1006                                  strlen(t->u.kernel.target->name)+1) != 0) {
1007                         ret = -EFAULT;
1008                         goto free_counters;
1009                 }
1010         }
1011
1012  free_counters:
1013         vfree(counters);
1014         return ret;
1015 }
1016
1017 #ifdef CONFIG_COMPAT
1018 static void compat_standard_from_user(void *dst, const void *src)
1019 {
1020         int v = *(compat_int_t *)src;
1021
1022         if (v > 0)
1023                 v += xt_compat_calc_jump(AF_INET, v);
1024         memcpy(dst, &v, sizeof(v));
1025 }
1026
1027 static int compat_standard_to_user(void __user *dst, const void *src)
1028 {
1029         compat_int_t cv = *(int *)src;
1030
1031         if (cv > 0)
1032                 cv -= xt_compat_calc_jump(AF_INET, cv);
1033         return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1034 }
1035
1036 static int compat_calc_entry(const struct ipt_entry *e,
1037                              const struct xt_table_info *info,
1038                              const void *base, struct xt_table_info *newinfo)
1039 {
1040         const struct xt_entry_match *ematch;
1041         const struct ipt_entry_target *t;
1042         unsigned int entry_offset;
1043         int off, i, ret;
1044
1045         off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1046         entry_offset = (void *)e - base;
1047         xt_ematch_foreach(ematch, e)
1048                 off += xt_compat_match_offset(ematch->u.kernel.match);
1049         t = ipt_get_target_c(e);
1050         off += xt_compat_target_offset(t->u.kernel.target);
1051         newinfo->size -= off;
1052         ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1053         if (ret)
1054                 return ret;
1055
1056         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1057                 if (info->hook_entry[i] &&
1058                     (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1059                         newinfo->hook_entry[i] -= off;
1060                 if (info->underflow[i] &&
1061                     (e < (struct ipt_entry *)(base + info->underflow[i])))
1062                         newinfo->underflow[i] -= off;
1063         }
1064         return 0;
1065 }
1066
1067 static int compat_table_info(const struct xt_table_info *info,
1068                              struct xt_table_info *newinfo)
1069 {
1070         struct ipt_entry *iter;
1071         void *loc_cpu_entry;
1072         int ret;
1073
1074         if (!newinfo || !info)
1075                 return -EINVAL;
1076
1077         /* we dont care about newinfo->entries[] */
1078         memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1079         newinfo->initial_entries = 0;
1080         loc_cpu_entry = info->entries[raw_smp_processor_id()];
1081         xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1082                 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1083                 if (ret != 0)
1084                         return ret;
1085         }
1086         return 0;
1087 }
1088 #endif
1089
1090 static int get_info(struct net *net, void __user *user,
1091                     const int *len, int compat)
1092 {
1093         char name[IPT_TABLE_MAXNAMELEN];
1094         struct xt_table *t;
1095         int ret;
1096
1097         if (*len != sizeof(struct ipt_getinfo)) {
1098                 duprintf("length %u != %zu\n", *len,
1099                          sizeof(struct ipt_getinfo));
1100                 return -EINVAL;
1101         }
1102
1103         if (copy_from_user(name, user, sizeof(name)) != 0)
1104                 return -EFAULT;
1105
1106         name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1107 #ifdef CONFIG_COMPAT
1108         if (compat)
1109                 xt_compat_lock(AF_INET);
1110 #endif
1111         t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1112                                     "iptable_%s", name);
1113         if (t && !IS_ERR(t)) {
1114                 struct ipt_getinfo info;
1115                 const struct xt_table_info *private = t->private;
1116 #ifdef CONFIG_COMPAT
1117                 struct xt_table_info tmp;
1118
1119                 if (compat) {
1120                         ret = compat_table_info(private, &tmp);
1121                         xt_compat_flush_offsets(AF_INET);
1122                         private = &tmp;
1123                 }
1124 #endif
1125                 info.valid_hooks = t->valid_hooks;
1126                 memcpy(info.hook_entry, private->hook_entry,
1127                        sizeof(info.hook_entry));
1128                 memcpy(info.underflow, private->underflow,
1129                        sizeof(info.underflow));
1130                 info.num_entries = private->number;
1131                 info.size = private->size;
1132                 strcpy(info.name, name);
1133
1134                 if (copy_to_user(user, &info, *len) != 0)
1135                         ret = -EFAULT;
1136                 else
1137                         ret = 0;
1138
1139                 xt_table_unlock(t);
1140                 module_put(t->me);
1141         } else
1142                 ret = t ? PTR_ERR(t) : -ENOENT;
1143 #ifdef CONFIG_COMPAT
1144         if (compat)
1145                 xt_compat_unlock(AF_INET);
1146 #endif
1147         return ret;
1148 }
1149
1150 static int
1151 get_entries(struct net *net, struct ipt_get_entries __user *uptr,
1152             const int *len)
1153 {
1154         int ret;
1155         struct ipt_get_entries get;
1156         struct xt_table *t;
1157
1158         if (*len < sizeof(get)) {
1159                 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1160                 return -EINVAL;
1161         }
1162         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1163                 return -EFAULT;
1164         if (*len != sizeof(struct ipt_get_entries) + get.size) {
1165                 duprintf("get_entries: %u != %zu\n",
1166                          *len, sizeof(get) + get.size);
1167                 return -EINVAL;
1168         }
1169
1170         t = xt_find_table_lock(net, AF_INET, get.name);
1171         if (t && !IS_ERR(t)) {
1172                 const struct xt_table_info *private = t->private;
1173                 duprintf("t->private->number = %u\n", private->number);
1174                 if (get.size == private->size)
1175                         ret = copy_entries_to_user(private->size,
1176                                                    t, uptr->entrytable);
1177                 else {
1178                         duprintf("get_entries: I've got %u not %u!\n",
1179                                  private->size, get.size);
1180                         ret = -EAGAIN;
1181                 }
1182                 module_put(t->me);
1183                 xt_table_unlock(t);
1184         } else
1185                 ret = t ? PTR_ERR(t) : -ENOENT;
1186
1187         return ret;
1188 }
1189
1190 static int
1191 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1192              struct xt_table_info *newinfo, unsigned int num_counters,
1193              void __user *counters_ptr)
1194 {
1195         int ret;
1196         struct xt_table *t;
1197         struct xt_table_info *oldinfo;
1198         struct xt_counters *counters;
1199         void *loc_cpu_old_entry;
1200         struct ipt_entry *iter;
1201
1202         ret = 0;
1203         counters = vmalloc(num_counters * sizeof(struct xt_counters));
1204         if (!counters) {
1205                 ret = -ENOMEM;
1206                 goto out;
1207         }
1208
1209         t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1210                                     "iptable_%s", name);
1211         if (!t || IS_ERR(t)) {
1212                 ret = t ? PTR_ERR(t) : -ENOENT;
1213                 goto free_newinfo_counters_untrans;
1214         }
1215
1216         /* You lied! */
1217         if (valid_hooks != t->valid_hooks) {
1218                 duprintf("Valid hook crap: %08X vs %08X\n",
1219                          valid_hooks, t->valid_hooks);
1220                 ret = -EINVAL;
1221                 goto put_module;
1222         }
1223
1224         oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1225         if (!oldinfo)
1226                 goto put_module;
1227
1228         /* Update module usage count based on number of rules */
1229         duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1230                 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1231         if ((oldinfo->number > oldinfo->initial_entries) ||
1232             (newinfo->number <= oldinfo->initial_entries))
1233                 module_put(t->me);
1234         if ((oldinfo->number > oldinfo->initial_entries) &&
1235             (newinfo->number <= oldinfo->initial_entries))
1236                 module_put(t->me);
1237
1238         /* Get the old counters, and synchronize with replace */
1239         get_counters(oldinfo, counters);
1240
1241         /* Decrease module usage counts and free resource */
1242         loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1243         xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1244                 cleanup_entry(iter, net);
1245
1246         xt_free_table_info(oldinfo);
1247         if (copy_to_user(counters_ptr, counters,
1248                          sizeof(struct xt_counters) * num_counters) != 0)
1249                 ret = -EFAULT;
1250         vfree(counters);
1251         xt_table_unlock(t);
1252         return ret;
1253
1254  put_module:
1255         module_put(t->me);
1256         xt_table_unlock(t);
1257  free_newinfo_counters_untrans:
1258         vfree(counters);
1259  out:
1260         return ret;
1261 }
1262
1263 static int
1264 do_replace(struct net *net, const void __user *user, unsigned int len)
1265 {
1266         int ret;
1267         struct ipt_replace tmp;
1268         struct xt_table_info *newinfo;
1269         void *loc_cpu_entry;
1270         struct ipt_entry *iter;
1271
1272         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1273                 return -EFAULT;
1274
1275         /* overflow check */
1276         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1277                 return -ENOMEM;
1278
1279         newinfo = xt_alloc_table_info(tmp.size);
1280         if (!newinfo)
1281                 return -ENOMEM;
1282
1283         /* choose the copy that is on our node/cpu */
1284         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1285         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1286                            tmp.size) != 0) {
1287                 ret = -EFAULT;
1288                 goto free_newinfo;
1289         }
1290
1291         ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1292         if (ret != 0)
1293                 goto free_newinfo;
1294
1295         duprintf("Translated table\n");
1296
1297         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1298                            tmp.num_counters, tmp.counters);
1299         if (ret)
1300                 goto free_newinfo_untrans;
1301         return 0;
1302
1303  free_newinfo_untrans:
1304         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1305                 cleanup_entry(iter, net);
1306  free_newinfo:
1307         xt_free_table_info(newinfo);
1308         return ret;
1309 }
1310
1311 static int
1312 do_add_counters(struct net *net, const void __user *user,
1313                 unsigned int len, int compat)
1314 {
1315         unsigned int i, curcpu;
1316         struct xt_counters_info tmp;
1317         struct xt_counters *paddc;
1318         unsigned int num_counters;
1319         const char *name;
1320         int size;
1321         void *ptmp;
1322         struct xt_table *t;
1323         const struct xt_table_info *private;
1324         int ret = 0;
1325         void *loc_cpu_entry;
1326         struct ipt_entry *iter;
1327 #ifdef CONFIG_COMPAT
1328         struct compat_xt_counters_info compat_tmp;
1329
1330         if (compat) {
1331                 ptmp = &compat_tmp;
1332                 size = sizeof(struct compat_xt_counters_info);
1333         } else
1334 #endif
1335         {
1336                 ptmp = &tmp;
1337                 size = sizeof(struct xt_counters_info);
1338         }
1339
1340         if (copy_from_user(ptmp, user, size) != 0)
1341                 return -EFAULT;
1342
1343 #ifdef CONFIG_COMPAT
1344         if (compat) {
1345                 num_counters = compat_tmp.num_counters;
1346                 name = compat_tmp.name;
1347         } else
1348 #endif
1349         {
1350                 num_counters = tmp.num_counters;
1351                 name = tmp.name;
1352         }
1353
1354         if (len != size + num_counters * sizeof(struct xt_counters))
1355                 return -EINVAL;
1356
1357         paddc = vmalloc(len - size);
1358         if (!paddc)
1359                 return -ENOMEM;
1360
1361         if (copy_from_user(paddc, user + size, len - size) != 0) {
1362                 ret = -EFAULT;
1363                 goto free;
1364         }
1365
1366         t = xt_find_table_lock(net, AF_INET, name);
1367         if (!t || IS_ERR(t)) {
1368                 ret = t ? PTR_ERR(t) : -ENOENT;
1369                 goto free;
1370         }
1371
1372         local_bh_disable();
1373         private = t->private;
1374         if (private->number != num_counters) {
1375                 ret = -EINVAL;
1376                 goto unlock_up_free;
1377         }
1378
1379         i = 0;
1380         /* Choose the copy that is on our node */
1381         curcpu = smp_processor_id();
1382         loc_cpu_entry = private->entries[curcpu];
1383         xt_info_wrlock(curcpu);
1384         xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1385                 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1386                 ++i;
1387         }
1388         xt_info_wrunlock(curcpu);
1389  unlock_up_free:
1390         local_bh_enable();
1391         xt_table_unlock(t);
1392         module_put(t->me);
1393  free:
1394         vfree(paddc);
1395
1396         return ret;
1397 }
1398
1399 #ifdef CONFIG_COMPAT
1400 struct compat_ipt_replace {
1401         char                    name[IPT_TABLE_MAXNAMELEN];
1402         u32                     valid_hooks;
1403         u32                     num_entries;
1404         u32                     size;
1405         u32                     hook_entry[NF_INET_NUMHOOKS];
1406         u32                     underflow[NF_INET_NUMHOOKS];
1407         u32                     num_counters;
1408         compat_uptr_t           counters;       /* struct ipt_counters * */
1409         struct compat_ipt_entry entries[0];
1410 };
1411
1412 static int
1413 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1414                           unsigned int *size, struct xt_counters *counters,
1415                           unsigned int i)
1416 {
1417         struct ipt_entry_target *t;
1418         struct compat_ipt_entry __user *ce;
1419         u_int16_t target_offset, next_offset;
1420         compat_uint_t origsize;
1421         const struct xt_entry_match *ematch;
1422         int ret = 0;
1423
1424         origsize = *size;
1425         ce = (struct compat_ipt_entry __user *)*dstptr;
1426         if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
1427             copy_to_user(&ce->counters, &counters[i],
1428             sizeof(counters[i])) != 0)
1429                 return -EFAULT;
1430
1431         *dstptr += sizeof(struct compat_ipt_entry);
1432         *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1433
1434         xt_ematch_foreach(ematch, e) {
1435                 ret = xt_compat_match_to_user(ematch, dstptr, size);
1436                 if (ret != 0)
1437                         return ret;
1438         }
1439         target_offset = e->target_offset - (origsize - *size);
1440         t = ipt_get_target(e);
1441         ret = xt_compat_target_to_user(t, dstptr, size);
1442         if (ret)
1443                 return ret;
1444         next_offset = e->next_offset - (origsize - *size);
1445         if (put_user(target_offset, &ce->target_offset) != 0 ||
1446             put_user(next_offset, &ce->next_offset) != 0)
1447                 return -EFAULT;
1448         return 0;
1449 }
1450
1451 static int
1452 compat_find_calc_match(struct ipt_entry_match *m,
1453                        const char *name,
1454                        const struct ipt_ip *ip,
1455                        unsigned int hookmask,
1456                        int *size)
1457 {
1458         struct xt_match *match;
1459
1460         match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
1461                                       m->u.user.revision);
1462         if (IS_ERR(match)) {
1463                 duprintf("compat_check_calc_match: `%s' not found\n",
1464                          m->u.user.name);
1465                 return PTR_ERR(match);
1466         }
1467         m->u.kernel.match = match;
1468         *size += xt_compat_match_offset(match);
1469         return 0;
1470 }
1471
1472 static void compat_release_entry(struct compat_ipt_entry *e)
1473 {
1474         struct ipt_entry_target *t;
1475         struct xt_entry_match *ematch;
1476
1477         /* Cleanup all matches */
1478         xt_ematch_foreach(ematch, e)
1479                 module_put(ematch->u.kernel.match->me);
1480         t = compat_ipt_get_target(e);
1481         module_put(t->u.kernel.target->me);
1482 }
1483
1484 static int
1485 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1486                                   struct xt_table_info *newinfo,
1487                                   unsigned int *size,
1488                                   const unsigned char *base,
1489                                   const unsigned char *limit,
1490                                   const unsigned int *hook_entries,
1491                                   const unsigned int *underflows,
1492                                   const char *name)
1493 {
1494         struct xt_entry_match *ematch;
1495         struct ipt_entry_target *t;
1496         struct xt_target *target;
1497         unsigned int entry_offset;
1498         unsigned int j;
1499         int ret, off, h;
1500
1501         duprintf("check_compat_entry_size_and_hooks %p\n", e);
1502         if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1503             (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1504                 duprintf("Bad offset %p, limit = %p\n", e, limit);
1505                 return -EINVAL;
1506         }
1507
1508         if (e->next_offset < sizeof(struct compat_ipt_entry) +
1509                              sizeof(struct compat_xt_entry_target)) {
1510                 duprintf("checking: element %p size %u\n",
1511                          e, e->next_offset);
1512                 return -EINVAL;
1513         }
1514
1515         /* For purposes of check_entry casting the compat entry is fine */
1516         ret = check_entry((struct ipt_entry *)e, name);
1517         if (ret)
1518                 return ret;
1519
1520         off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1521         entry_offset = (void *)e - (void *)base;
1522         j = 0;
1523         xt_ematch_foreach(ematch, e) {
1524                 ret = compat_find_calc_match(ematch, name,
1525                                              &e->ip, e->comefrom, &off);
1526                 if (ret != 0)
1527                         goto release_matches;
1528                 ++j;
1529         }
1530
1531         t = compat_ipt_get_target(e);
1532         target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
1533                                         t->u.user.revision);
1534         if (IS_ERR(target)) {
1535                 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1536                          t->u.user.name);
1537                 ret = PTR_ERR(target);
1538                 goto release_matches;
1539         }
1540         t->u.kernel.target = target;
1541
1542         off += xt_compat_target_offset(target);
1543         *size += off;
1544         ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1545         if (ret)
1546                 goto out;
1547
1548         /* Check hooks & underflows */
1549         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1550                 if ((unsigned char *)e - base == hook_entries[h])
1551                         newinfo->hook_entry[h] = hook_entries[h];
1552                 if ((unsigned char *)e - base == underflows[h])
1553                         newinfo->underflow[h] = underflows[h];
1554         }
1555
1556         /* Clear counters and comefrom */
1557         memset(&e->counters, 0, sizeof(e->counters));
1558         e->comefrom = 0;
1559         return 0;
1560
1561 out:
1562         module_put(t->u.kernel.target->me);
1563 release_matches:
1564         xt_ematch_foreach(ematch, e) {
1565                 if (j-- == 0)
1566                         break;
1567                 module_put(ematch->u.kernel.match->me);
1568         }
1569         return ret;
1570 }
1571
1572 static int
1573 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1574                             unsigned int *size, const char *name,
1575                             struct xt_table_info *newinfo, unsigned char *base)
1576 {
1577         struct ipt_entry_target *t;
1578         struct xt_target *target;
1579         struct ipt_entry *de;
1580         unsigned int origsize;
1581         int ret, h;
1582         struct xt_entry_match *ematch;
1583
1584         ret = 0;
1585         origsize = *size;
1586         de = (struct ipt_entry *)*dstptr;
1587         memcpy(de, e, sizeof(struct ipt_entry));
1588         memcpy(&de->counters, &e->counters, sizeof(e->counters));
1589
1590         *dstptr += sizeof(struct ipt_entry);
1591         *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1592
1593         xt_ematch_foreach(ematch, e) {
1594                 ret = xt_compat_match_from_user(ematch, dstptr, size);
1595                 if (ret != 0)
1596                         return ret;
1597         }
1598         de->target_offset = e->target_offset - (origsize - *size);
1599         t = compat_ipt_get_target(e);
1600         target = t->u.kernel.target;
1601         xt_compat_target_from_user(t, dstptr, size);
1602
1603         de->next_offset = e->next_offset - (origsize - *size);
1604         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1605                 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1606                         newinfo->hook_entry[h] -= origsize - *size;
1607                 if ((unsigned char *)de - base < newinfo->underflow[h])
1608                         newinfo->underflow[h] -= origsize - *size;
1609         }
1610         return ret;
1611 }
1612
1613 static int
1614 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1615 {
1616         struct xt_entry_match *ematch;
1617         struct xt_mtchk_param mtpar;
1618         unsigned int j;
1619         int ret = 0;
1620
1621         j = 0;
1622         mtpar.net       = net;
1623         mtpar.table     = name;
1624         mtpar.entryinfo = &e->ip;
1625         mtpar.hook_mask = e->comefrom;
1626         mtpar.family    = NFPROTO_IPV4;
1627         xt_ematch_foreach(ematch, e) {
1628                 ret = check_match(ematch, &mtpar);
1629                 if (ret != 0)
1630                         goto cleanup_matches;
1631                 ++j;
1632         }
1633
1634         ret = check_target(e, net, name);
1635         if (ret)
1636                 goto cleanup_matches;
1637         return 0;
1638
1639  cleanup_matches:
1640         xt_ematch_foreach(ematch, e) {
1641                 if (j-- == 0)
1642                         break;
1643                 cleanup_match(ematch, net);
1644         }
1645         return ret;
1646 }
1647
1648 static int
1649 translate_compat_table(struct net *net,
1650                        const char *name,
1651                        unsigned int valid_hooks,
1652                        struct xt_table_info **pinfo,
1653                        void **pentry0,
1654                        unsigned int total_size,
1655                        unsigned int number,
1656                        unsigned int *hook_entries,
1657                        unsigned int *underflows)
1658 {
1659         unsigned int i, j;
1660         struct xt_table_info *newinfo, *info;
1661         void *pos, *entry0, *entry1;
1662         struct compat_ipt_entry *iter0;
1663         struct ipt_entry *iter1;
1664         unsigned int size;
1665         int ret;
1666
1667         info = *pinfo;
1668         entry0 = *pentry0;
1669         size = total_size;
1670         info->number = number;
1671
1672         /* Init all hooks to impossible value. */
1673         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1674                 info->hook_entry[i] = 0xFFFFFFFF;
1675                 info->underflow[i] = 0xFFFFFFFF;
1676         }
1677
1678         duprintf("translate_compat_table: size %u\n", info->size);
1679         j = 0;
1680         xt_compat_lock(AF_INET);
1681         /* Walk through entries, checking offsets. */
1682         xt_entry_foreach(iter0, entry0, total_size) {
1683                 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1684                                                         entry0,
1685                                                         entry0 + total_size,
1686                                                         hook_entries,
1687                                                         underflows,
1688                                                         name);
1689                 if (ret != 0)
1690                         goto out_unlock;
1691                 ++j;
1692         }
1693
1694         ret = -EINVAL;
1695         if (j != number) {
1696                 duprintf("translate_compat_table: %u not %u entries\n",
1697                          j, number);
1698                 goto out_unlock;
1699         }
1700
1701         /* Check hooks all assigned */
1702         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1703                 /* Only hooks which are valid */
1704                 if (!(valid_hooks & (1 << i)))
1705                         continue;
1706                 if (info->hook_entry[i] == 0xFFFFFFFF) {
1707                         duprintf("Invalid hook entry %u %u\n",
1708                                  i, hook_entries[i]);
1709                         goto out_unlock;
1710                 }
1711                 if (info->underflow[i] == 0xFFFFFFFF) {
1712                         duprintf("Invalid underflow %u %u\n",
1713                                  i, underflows[i]);
1714                         goto out_unlock;
1715                 }
1716         }
1717
1718         ret = -ENOMEM;
1719         newinfo = xt_alloc_table_info(size);
1720         if (!newinfo)
1721                 goto out_unlock;
1722
1723         newinfo->number = number;
1724         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1725                 newinfo->hook_entry[i] = info->hook_entry[i];
1726                 newinfo->underflow[i] = info->underflow[i];
1727         }
1728         entry1 = newinfo->entries[raw_smp_processor_id()];
1729         pos = entry1;
1730         size = total_size;
1731         xt_entry_foreach(iter0, entry0, total_size) {
1732                 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1733                                                   name, newinfo, entry1);
1734                 if (ret != 0)
1735                         break;
1736         }
1737         xt_compat_flush_offsets(AF_INET);
1738         xt_compat_unlock(AF_INET);
1739         if (ret)
1740                 goto free_newinfo;
1741
1742         ret = -ELOOP;
1743         if (!mark_source_chains(newinfo, valid_hooks, entry1))
1744                 goto free_newinfo;
1745
1746         i = 0;
1747         xt_entry_foreach(iter1, entry1, newinfo->size) {
1748                 ret = compat_check_entry(iter1, net, name);
1749                 if (ret != 0)
1750                         break;
1751                 ++i;
1752         }
1753         if (ret) {
1754                 /*
1755                  * The first i matches need cleanup_entry (calls ->destroy)
1756                  * because they had called ->check already. The other j-i
1757                  * entries need only release.
1758                  */
1759                 int skip = i;
1760                 j -= i;
1761                 xt_entry_foreach(iter0, entry0, newinfo->size) {
1762                         if (skip-- > 0)
1763                                 continue;
1764                         if (j-- == 0)
1765                                 break;
1766                         compat_release_entry(iter0);
1767                 }
1768                 xt_entry_foreach(iter1, entry1, newinfo->size) {
1769                         if (i-- == 0)
1770                                 break;
1771                         cleanup_entry(iter1, net);
1772                 }
1773                 xt_free_table_info(newinfo);
1774                 return ret;
1775         }
1776
1777         /* And one copy for every other CPU */
1778         for_each_possible_cpu(i)
1779                 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1780                         memcpy(newinfo->entries[i], entry1, newinfo->size);
1781
1782         *pinfo = newinfo;
1783         *pentry0 = entry1;
1784         xt_free_table_info(info);
1785         return 0;
1786
1787 free_newinfo:
1788         xt_free_table_info(newinfo);
1789 out:
1790         xt_entry_foreach(iter0, entry0, total_size) {
1791                 if (j-- == 0)
1792                         break;
1793                 compat_release_entry(iter0);
1794         }
1795         return ret;
1796 out_unlock:
1797         xt_compat_flush_offsets(AF_INET);
1798         xt_compat_unlock(AF_INET);
1799         goto out;
1800 }
1801
1802 static int
1803 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1804 {
1805         int ret;
1806         struct compat_ipt_replace tmp;
1807         struct xt_table_info *newinfo;
1808         void *loc_cpu_entry;
1809         struct ipt_entry *iter;
1810
1811         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1812                 return -EFAULT;
1813
1814         /* overflow check */
1815         if (tmp.size >= INT_MAX / num_possible_cpus())
1816                 return -ENOMEM;
1817         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1818                 return -ENOMEM;
1819
1820         newinfo = xt_alloc_table_info(tmp.size);
1821         if (!newinfo)
1822                 return -ENOMEM;
1823
1824         /* choose the copy that is on our node/cpu */
1825         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1826         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1827                            tmp.size) != 0) {
1828                 ret = -EFAULT;
1829                 goto free_newinfo;
1830         }
1831
1832         ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1833                                      &newinfo, &loc_cpu_entry, tmp.size,
1834                                      tmp.num_entries, tmp.hook_entry,
1835                                      tmp.underflow);
1836         if (ret != 0)
1837                 goto free_newinfo;
1838
1839         duprintf("compat_do_replace: Translated table\n");
1840
1841         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1842                            tmp.num_counters, compat_ptr(tmp.counters));
1843         if (ret)
1844                 goto free_newinfo_untrans;
1845         return 0;
1846
1847  free_newinfo_untrans:
1848         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1849                 cleanup_entry(iter, net);
1850  free_newinfo:
1851         xt_free_table_info(newinfo);
1852         return ret;
1853 }
1854
1855 static int
1856 compat_do_ipt_set_ctl(struct sock *sk,  int cmd, void __user *user,
1857                       unsigned int len)
1858 {
1859         int ret;
1860
1861         if (!capable(CAP_NET_ADMIN))
1862                 return -EPERM;
1863
1864         switch (cmd) {
1865         case IPT_SO_SET_REPLACE:
1866                 ret = compat_do_replace(sock_net(sk), user, len);
1867                 break;
1868
1869         case IPT_SO_SET_ADD_COUNTERS:
1870                 ret = do_add_counters(sock_net(sk), user, len, 1);
1871                 break;
1872
1873         default:
1874                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
1875                 ret = -EINVAL;
1876         }
1877
1878         return ret;
1879 }
1880
1881 struct compat_ipt_get_entries {
1882         char name[IPT_TABLE_MAXNAMELEN];
1883         compat_uint_t size;
1884         struct compat_ipt_entry entrytable[0];
1885 };
1886
1887 static int
1888 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1889                             void __user *userptr)
1890 {
1891         struct xt_counters *counters;
1892         const struct xt_table_info *private = table->private;
1893         void __user *pos;
1894         unsigned int size;
1895         int ret = 0;
1896         const void *loc_cpu_entry;
1897         unsigned int i = 0;
1898         struct ipt_entry *iter;
1899
1900         counters = alloc_counters(table);
1901         if (IS_ERR(counters))
1902                 return PTR_ERR(counters);
1903
1904         /* choose the copy that is on our node/cpu, ...
1905          * This choice is lazy (because current thread is
1906          * allowed to migrate to another cpu)
1907          */
1908         loc_cpu_entry = private->entries[raw_smp_processor_id()];
1909         pos = userptr;
1910         size = total_size;
1911         xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1912                 ret = compat_copy_entry_to_user(iter, &pos,
1913                                                 &size, counters, i++);
1914                 if (ret != 0)
1915                         break;
1916         }
1917
1918         vfree(counters);
1919         return ret;
1920 }
1921
1922 static int
1923 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1924                    int *len)
1925 {
1926         int ret;
1927         struct compat_ipt_get_entries get;
1928         struct xt_table *t;
1929
1930         if (*len < sizeof(get)) {
1931                 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1932                 return -EINVAL;
1933         }
1934
1935         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1936                 return -EFAULT;
1937
1938         if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1939                 duprintf("compat_get_entries: %u != %zu\n",
1940                          *len, sizeof(get) + get.size);
1941                 return -EINVAL;
1942         }
1943
1944         xt_compat_lock(AF_INET);
1945         t = xt_find_table_lock(net, AF_INET, get.name);
1946         if (t && !IS_ERR(t)) {
1947                 const struct xt_table_info *private = t->private;
1948                 struct xt_table_info info;
1949                 duprintf("t->private->number = %u\n", private->number);
1950                 ret = compat_table_info(private, &info);
1951                 if (!ret && get.size == info.size) {
1952                         ret = compat_copy_entries_to_user(private->size,
1953                                                           t, uptr->entrytable);
1954                 } else if (!ret) {
1955                         duprintf("compat_get_entries: I've got %u not %u!\n",
1956                                  private->size, get.size);
1957                         ret = -EAGAIN;
1958                 }
1959                 xt_compat_flush_offsets(AF_INET);
1960                 module_put(t->me);
1961                 xt_table_unlock(t);
1962         } else
1963                 ret = t ? PTR_ERR(t) : -ENOENT;
1964
1965         xt_compat_unlock(AF_INET);
1966         return ret;
1967 }
1968
1969 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1970
1971 static int
1972 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1973 {
1974         int ret;
1975
1976         if (!capable(CAP_NET_ADMIN))
1977                 return -EPERM;
1978
1979         switch (cmd) {
1980         case IPT_SO_GET_INFO:
1981                 ret = get_info(sock_net(sk), user, len, 1);
1982                 break;
1983         case IPT_SO_GET_ENTRIES:
1984                 ret = compat_get_entries(sock_net(sk), user, len);
1985                 break;
1986         default:
1987                 ret = do_ipt_get_ctl(sk, cmd, user, len);
1988         }
1989         return ret;
1990 }
1991 #endif
1992
1993 static int
1994 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1995 {
1996         int ret;
1997
1998         if (!capable(CAP_NET_ADMIN))
1999                 return -EPERM;
2000
2001         switch (cmd) {
2002         case IPT_SO_SET_REPLACE:
2003                 ret = do_replace(sock_net(sk), user, len);
2004                 break;
2005
2006         case IPT_SO_SET_ADD_COUNTERS:
2007                 ret = do_add_counters(sock_net(sk), user, len, 0);
2008                 break;
2009
2010         default:
2011                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
2012                 ret = -EINVAL;
2013         }
2014
2015         return ret;
2016 }
2017
2018 static int
2019 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2020 {
2021         int ret;
2022
2023         if (!capable(CAP_NET_ADMIN))
2024                 return -EPERM;
2025
2026         switch (cmd) {
2027         case IPT_SO_GET_INFO:
2028                 ret = get_info(sock_net(sk), user, len, 0);
2029                 break;
2030
2031         case IPT_SO_GET_ENTRIES:
2032                 ret = get_entries(sock_net(sk), user, len);
2033                 break;
2034
2035         case IPT_SO_GET_REVISION_MATCH:
2036         case IPT_SO_GET_REVISION_TARGET: {
2037                 struct ipt_get_revision rev;
2038                 int target;
2039
2040                 if (*len != sizeof(rev)) {
2041                         ret = -EINVAL;
2042                         break;
2043                 }
2044                 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2045                         ret = -EFAULT;
2046                         break;
2047                 }
2048
2049                 if (cmd == IPT_SO_GET_REVISION_TARGET)
2050                         target = 1;
2051                 else
2052                         target = 0;
2053
2054                 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2055                                                          rev.revision,
2056                                                          target, &ret),
2057                                         "ipt_%s", rev.name);
2058                 break;
2059         }
2060
2061         default:
2062                 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2063                 ret = -EINVAL;
2064         }
2065
2066         return ret;
2067 }
2068
2069 struct xt_table *ipt_register_table(struct net *net,
2070                                     const struct xt_table *table,
2071                                     const struct ipt_replace *repl)
2072 {
2073         int ret;
2074         struct xt_table_info *newinfo;
2075         struct xt_table_info bootstrap = {0};
2076         void *loc_cpu_entry;
2077         struct xt_table *new_table;
2078
2079         newinfo = xt_alloc_table_info(repl->size);
2080         if (!newinfo) {
2081                 ret = -ENOMEM;
2082                 goto out;
2083         }
2084
2085         /* choose the copy on our node/cpu, but dont care about preemption */
2086         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2087         memcpy(loc_cpu_entry, repl->entries, repl->size);
2088
2089         ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2090         if (ret != 0)
2091                 goto out_free;
2092
2093         new_table = xt_register_table(net, table, &bootstrap, newinfo);
2094         if (IS_ERR(new_table)) {
2095                 ret = PTR_ERR(new_table);
2096                 goto out_free;
2097         }
2098
2099         return new_table;
2100
2101 out_free:
2102         xt_free_table_info(newinfo);
2103 out:
2104         return ERR_PTR(ret);
2105 }
2106
2107 void ipt_unregister_table(struct net *net, struct xt_table *table)
2108 {
2109         struct xt_table_info *private;
2110         void *loc_cpu_entry;
2111         struct module *table_owner = table->me;
2112         struct ipt_entry *iter;
2113
2114         private = xt_unregister_table(table);
2115
2116         /* Decrease module usage counts and free resources */
2117         loc_cpu_entry = private->entries[raw_smp_processor_id()];
2118         xt_entry_foreach(iter, loc_cpu_entry, private->size)
2119                 cleanup_entry(iter, net);
2120         if (private->number > private->initial_entries)
2121                 module_put(table_owner);
2122         xt_free_table_info(private);
2123 }
2124
2125 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2126 static inline bool
2127 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2128                      u_int8_t type, u_int8_t code,
2129                      bool invert)
2130 {
2131         return ((test_type == 0xFF) ||
2132                 (type == test_type && code >= min_code && code <= max_code))
2133                 ^ invert;
2134 }
2135
2136 static bool
2137 icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
2138 {
2139         const struct icmphdr *ic;
2140         struct icmphdr _icmph;
2141         const struct ipt_icmp *icmpinfo = par->matchinfo;
2142
2143         /* Must not be a fragment. */
2144         if (par->fragoff != 0)
2145                 return false;
2146
2147         ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2148         if (ic == NULL) {
2149                 /* We've been asked to examine this packet, and we
2150                  * can't.  Hence, no choice but to drop.
2151                  */
2152                 duprintf("Dropping evil ICMP tinygram.\n");
2153                 par->hotdrop = true;
2154                 return false;
2155         }
2156
2157         return icmp_type_code_match(icmpinfo->type,
2158                                     icmpinfo->code[0],
2159                                     icmpinfo->code[1],
2160                                     ic->type, ic->code,
2161                                     !!(icmpinfo->invflags&IPT_ICMP_INV));
2162 }
2163
2164 static int icmp_checkentry(const struct xt_mtchk_param *par)
2165 {
2166         const struct ipt_icmp *icmpinfo = par->matchinfo;
2167
2168         /* Must specify no unknown invflags */
2169         return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
2170 }
2171
2172 static struct xt_target ipt_builtin_tg[] __read_mostly = {
2173         {
2174                 .name             = IPT_STANDARD_TARGET,
2175                 .targetsize       = sizeof(int),
2176                 .family           = NFPROTO_IPV4,
2177 #ifdef CONFIG_COMPAT
2178                 .compatsize       = sizeof(compat_int_t),
2179                 .compat_from_user = compat_standard_from_user,
2180                 .compat_to_user   = compat_standard_to_user,
2181 #endif
2182         },
2183         {
2184                 .name             = IPT_ERROR_TARGET,
2185                 .target           = ipt_error,
2186                 .targetsize       = IPT_FUNCTION_MAXNAMELEN,
2187                 .family           = NFPROTO_IPV4,
2188         },
2189 };
2190
2191 static struct nf_sockopt_ops ipt_sockopts = {
2192         .pf             = PF_INET,
2193         .set_optmin     = IPT_BASE_CTL,
2194         .set_optmax     = IPT_SO_SET_MAX+1,
2195         .set            = do_ipt_set_ctl,
2196 #ifdef CONFIG_COMPAT
2197         .compat_set     = compat_do_ipt_set_ctl,
2198 #endif
2199         .get_optmin     = IPT_BASE_CTL,
2200         .get_optmax     = IPT_SO_GET_MAX+1,
2201         .get            = do_ipt_get_ctl,
2202 #ifdef CONFIG_COMPAT
2203         .compat_get     = compat_do_ipt_get_ctl,
2204 #endif
2205         .owner          = THIS_MODULE,
2206 };
2207
2208 static struct xt_match ipt_builtin_mt[] __read_mostly = {
2209         {
2210                 .name       = "icmp",
2211                 .match      = icmp_match,
2212                 .matchsize  = sizeof(struct ipt_icmp),
2213                 .checkentry = icmp_checkentry,
2214                 .proto      = IPPROTO_ICMP,
2215                 .family     = NFPROTO_IPV4,
2216         },
2217 };
2218
2219 static int __net_init ip_tables_net_init(struct net *net)
2220 {
2221         return xt_proto_init(net, NFPROTO_IPV4);
2222 }
2223
2224 static void __net_exit ip_tables_net_exit(struct net *net)
2225 {
2226         xt_proto_fini(net, NFPROTO_IPV4);
2227 }
2228
2229 static struct pernet_operations ip_tables_net_ops = {
2230         .init = ip_tables_net_init,
2231         .exit = ip_tables_net_exit,
2232 };
2233
2234 static int __init ip_tables_init(void)
2235 {
2236         int ret;
2237
2238         ret = register_pernet_subsys(&ip_tables_net_ops);
2239         if (ret < 0)
2240                 goto err1;
2241
2242         /* Noone else will be downing sem now, so we won't sleep */
2243         ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2244         if (ret < 0)
2245                 goto err2;
2246         ret = xt_register_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2247         if (ret < 0)
2248                 goto err4;
2249
2250         /* Register setsockopt */
2251         ret = nf_register_sockopt(&ipt_sockopts);
2252         if (ret < 0)
2253                 goto err5;
2254
2255         pr_info("(C) 2000-2006 Netfilter Core Team\n");
2256         return 0;
2257
2258 err5:
2259         xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2260 err4:
2261         xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2262 err2:
2263         unregister_pernet_subsys(&ip_tables_net_ops);
2264 err1:
2265         return ret;
2266 }
2267
2268 static void __exit ip_tables_fini(void)
2269 {
2270         nf_unregister_sockopt(&ipt_sockopts);
2271
2272         xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2273         xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2274         unregister_pernet_subsys(&ip_tables_net_ops);
2275 }
2276
2277 EXPORT_SYMBOL(ipt_register_table);
2278 EXPORT_SYMBOL(ipt_unregister_table);
2279 EXPORT_SYMBOL(ipt_do_table);
2280 module_init(ip_tables_init);
2281 module_exit(ip_tables_fini);