a846d633b3b6f04a3ed72be1d884e484d3efa030
[linux-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 xt_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 xt_standard_target *t = (void *)ipt_get_target_c(s);
234
235         if (strcmp(t->target.u.kernel.target->name, XT_ERROR_TARGET) == 0) {
236                 /* Head of user chain: ERROR target with chainname */
237                 *chainname = t->target.data;
238                 (*rulenum) = 0;
239         } else if (s == e) {
240                 (*rulenum)++;
241
242                 if (s->target_offset == sizeof(struct ipt_entry) &&
243                     strcmp(t->target.u.kernel.target->name,
244                            XT_STANDARD_TARGET) == 0 &&
245                    t->verdict < 0 &&
246                    unconditional(&s->ip)) {
247                         /* Tail of chains: STANDARD target (return/policy) */
248                         *comment = *chainname == hookname
249                                 ? comments[NF_IP_TRACE_COMMENT_POLICY]
250                                 : comments[NF_IP_TRACE_COMMENT_RETURN];
251                 }
252                 return 1;
253         } else
254                 (*rulenum)++;
255
256         return 0;
257 }
258
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 xt_entry_target *t;
350                 const struct xt_entry_match *ematch;
351
352                 IP_NF_ASSERT(e);
353                 if (!ip_packet_match(ip, indev, outdev,
354                     &e->ip, acpar.fragoff)) {
355  no_match:
356                         e = ipt_next_entry(e);
357                         continue;
358                 }
359
360                 xt_ematch_foreach(ematch, e) {
361                         acpar.match     = ematch->u.kernel.match;
362                         acpar.matchinfo = ematch->data;
363                         if (!acpar.match->match(skb, &acpar))
364                                 goto no_match;
365                 }
366
367                 ADD_COUNTER(e->counters, skb->len, 1);
368
369                 t = ipt_get_target(e);
370                 IP_NF_ASSERT(t->u.kernel.target);
371
372 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
373     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
374                 /* The packet is traced: log it */
375                 if (unlikely(skb->nf_trace))
376                         trace_packet(skb, hook, in, out,
377                                      table->name, private, e);
378 #endif
379                 /* Standard target? */
380                 if (!t->u.kernel.target->target) {
381                         int v;
382
383                         v = ((struct xt_standard_target *)t)->verdict;
384                         if (v < 0) {
385                                 /* Pop from stack? */
386                                 if (v != XT_RETURN) {
387                                         verdict = (unsigned)(-v) - 1;
388                                         break;
389                                 }
390                                 if (*stackptr == 0) {
391                                         e = get_entry(table_base,
392                                             private->underflow[hook]);
393                                         pr_debug("Underflow (this is normal) "
394                                                  "to %p\n", e);
395                                 } else {
396                                         e = jumpstack[--*stackptr];
397                                         pr_debug("Pulled %p out from pos %u\n",
398                                                  e, *stackptr);
399                                         e = ipt_next_entry(e);
400                                 }
401                                 continue;
402                         }
403                         if (table_base + v != ipt_next_entry(e) &&
404                             !(e->ip.flags & IPT_F_GOTO)) {
405                                 if (*stackptr >= private->stacksize) {
406                                         verdict = NF_DROP;
407                                         break;
408                                 }
409                                 jumpstack[(*stackptr)++] = e;
410                                 pr_debug("Pushed %p into pos %u\n",
411                                          e, *stackptr - 1);
412                         }
413
414                         e = get_entry(table_base, v);
415                         continue;
416                 }
417
418                 acpar.target   = t->u.kernel.target;
419                 acpar.targinfo = t->data;
420
421                 verdict = t->u.kernel.target->target(skb, &acpar);
422                 /* Target might have changed stuff. */
423                 ip = ip_hdr(skb);
424                 if (verdict == XT_CONTINUE)
425                         e = ipt_next_entry(e);
426                 else
427                         /* Verdict */
428                         break;
429         } while (!acpar.hotdrop);
430         xt_info_rdunlock_bh();
431         pr_debug("Exiting %s; resetting sp from %u to %u\n",
432                  __func__, *stackptr, origptr);
433         *stackptr = origptr;
434 #ifdef DEBUG_ALLOW_ALL
435         return NF_ACCEPT;
436 #else
437         if (acpar.hotdrop)
438                 return NF_DROP;
439         else return verdict;
440 #endif
441 }
442
443 /* Figures out from what hook each rule can be called: returns 0 if
444    there are loops.  Puts hook bitmask in comefrom. */
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 xt_standard_target *t
465                                 = (void *)ipt_get_target_c(e);
466                         int visited = e->comefrom & (1 << hook);
467
468                         if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
469                                 pr_err("iptables: loop hook %u pos %u %08X.\n",
470                                        hook, pos, e->comefrom);
471                                 return 0;
472                         }
473                         e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
474
475                         /* Unconditional return/END. */
476                         if ((e->target_offset == sizeof(struct ipt_entry) &&
477                              (strcmp(t->target.u.user.name,
478                                      XT_STANDARD_TARGET) == 0) &&
479                              t->verdict < 0 && unconditional(&e->ip)) ||
480                             visited) {
481                                 unsigned int oldpos, size;
482
483                                 if ((strcmp(t->target.u.user.name,
484                                             XT_STANDARD_TARGET) == 0) &&
485                                     t->verdict < -NF_MAX_VERDICT - 1) {
486                                         duprintf("mark_source_chains: bad "
487                                                 "negative verdict (%i)\n",
488                                                                 t->verdict);
489                                         return 0;
490                                 }
491
492                                 /* Return: backtrack through the last
493                                    big jump. */
494                                 do {
495                                         e->comefrom ^= (1<<NF_INET_NUMHOOKS);
496 #ifdef DEBUG_IP_FIREWALL_USER
497                                         if (e->comefrom
498                                             & (1 << NF_INET_NUMHOOKS)) {
499                                                 duprintf("Back unset "
500                                                          "on hook %u "
501                                                          "rule %u\n",
502                                                          hook, pos);
503                                         }
504 #endif
505                                         oldpos = pos;
506                                         pos = e->counters.pcnt;
507                                         e->counters.pcnt = 0;
508
509                                         /* We're at the start. */
510                                         if (pos == oldpos)
511                                                 goto next;
512
513                                         e = (struct ipt_entry *)
514                                                 (entry0 + pos);
515                                 } while (oldpos == pos + e->next_offset);
516
517                                 /* Move along one */
518                                 size = e->next_offset;
519                                 e = (struct ipt_entry *)
520                                         (entry0 + pos + size);
521                                 e->counters.pcnt = pos;
522                                 pos += size;
523                         } else {
524                                 int newpos = t->verdict;
525
526                                 if (strcmp(t->target.u.user.name,
527                                            XT_STANDARD_TARGET) == 0 &&
528                                     newpos >= 0) {
529                                         if (newpos > newinfo->size -
530                                                 sizeof(struct ipt_entry)) {
531                                                 duprintf("mark_source_chains: "
532                                                         "bad verdict (%i)\n",
533                                                                 newpos);
534                                                 return 0;
535                                         }
536                                         /* This a jump; chase it. */
537                                         duprintf("Jump rule %u -> %u\n",
538                                                  pos, newpos);
539                                 } else {
540                                         /* ... this is a fallthru */
541                                         newpos = pos + e->next_offset;
542                                 }
543                                 e = (struct ipt_entry *)
544                                         (entry0 + newpos);
545                                 e->counters.pcnt = pos;
546                                 pos = newpos;
547                         }
548                 }
549                 next:
550                 duprintf("Finished chain %u\n", hook);
551         }
552         return 1;
553 }
554
555 static void cleanup_match(struct xt_entry_match *m, struct net *net)
556 {
557         struct xt_mtdtor_param par;
558
559         par.net       = net;
560         par.match     = m->u.kernel.match;
561         par.matchinfo = m->data;
562         par.family    = NFPROTO_IPV4;
563         if (par.match->destroy != NULL)
564                 par.match->destroy(&par);
565         module_put(par.match->me);
566 }
567
568 static int
569 check_entry(const struct ipt_entry *e, const char *name)
570 {
571         const struct xt_entry_target *t;
572
573         if (!ip_checkentry(&e->ip)) {
574                 duprintf("ip check failed %p %s.\n", e, par->match->name);
575                 return -EINVAL;
576         }
577
578         if (e->target_offset + sizeof(struct xt_entry_target) >
579             e->next_offset)
580                 return -EINVAL;
581
582         t = ipt_get_target_c(e);
583         if (e->target_offset + t->u.target_size > e->next_offset)
584                 return -EINVAL;
585
586         return 0;
587 }
588
589 static int
590 check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
591 {
592         const struct ipt_ip *ip = par->entryinfo;
593         int ret;
594
595         par->match     = m->u.kernel.match;
596         par->matchinfo = m->data;
597
598         ret = xt_check_match(par, m->u.match_size - sizeof(*m),
599               ip->proto, ip->invflags & IPT_INV_PROTO);
600         if (ret < 0) {
601                 duprintf("check failed for `%s'.\n", par->match->name);
602                 return ret;
603         }
604         return 0;
605 }
606
607 static int
608 find_check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
609 {
610         struct xt_match *match;
611         int ret;
612
613         match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
614                                       m->u.user.revision);
615         if (IS_ERR(match)) {
616                 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
617                 return PTR_ERR(match);
618         }
619         m->u.kernel.match = match;
620
621         ret = check_match(m, par);
622         if (ret)
623                 goto err;
624
625         return 0;
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 xt_entry_target *t = ipt_get_target(e);
634         struct xt_tgchk_param par = {
635                 .net       = net,
636                 .table     = name,
637                 .entryinfo = e,
638                 .target    = t->u.kernel.target,
639                 .targinfo  = t->data,
640                 .hook_mask = e->comefrom,
641                 .family    = NFPROTO_IPV4,
642         };
643         int ret;
644
645         ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
646               e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
647         if (ret < 0) {
648                 duprintf("check failed for `%s'.\n",
649                          t->u.kernel.target->name);
650                 return ret;
651         }
652         return 0;
653 }
654
655 static int
656 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
657                  unsigned int size)
658 {
659         struct xt_entry_target *t;
660         struct xt_target *target;
661         int ret;
662         unsigned int j;
663         struct xt_mtchk_param mtpar;
664         struct xt_entry_match *ematch;
665
666         ret = check_entry(e, name);
667         if (ret)
668                 return ret;
669
670         j = 0;
671         mtpar.net       = net;
672         mtpar.table     = name;
673         mtpar.entryinfo = &e->ip;
674         mtpar.hook_mask = e->comefrom;
675         mtpar.family    = NFPROTO_IPV4;
676         xt_ematch_foreach(ematch, e) {
677                 ret = find_check_match(ematch, &mtpar);
678                 if (ret != 0)
679                         goto cleanup_matches;
680                 ++j;
681         }
682
683         t = ipt_get_target(e);
684         target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
685                                         t->u.user.revision);
686         if (IS_ERR(target)) {
687                 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
688                 ret = PTR_ERR(target);
689                 goto cleanup_matches;
690         }
691         t->u.kernel.target = target;
692
693         ret = check_target(e, net, name);
694         if (ret)
695                 goto err;
696         return 0;
697  err:
698         module_put(t->u.kernel.target->me);
699  cleanup_matches:
700         xt_ematch_foreach(ematch, e) {
701                 if (j-- == 0)
702                         break;
703                 cleanup_match(ematch, net);
704         }
705         return ret;
706 }
707
708 static bool check_underflow(const struct ipt_entry *e)
709 {
710         const struct xt_entry_target *t;
711         unsigned int verdict;
712
713         if (!unconditional(&e->ip))
714                 return false;
715         t = ipt_get_target_c(e);
716         if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
717                 return false;
718         verdict = ((struct xt_standard_target *)t)->verdict;
719         verdict = -verdict - 1;
720         return verdict == NF_DROP || verdict == NF_ACCEPT;
721 }
722
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 xt_entry_target)) {
742                 duprintf("checking: element %p size %u\n",
743                          e, e->next_offset);
744                 return -EINVAL;
745         }
746
747         /* Check hooks & underflows */
748         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
749                 if (!(valid_hooks & (1 << h)))
750                         continue;
751                 if ((unsigned char *)e - base == hook_entries[h])
752                         newinfo->hook_entry[h] = hook_entries[h];
753                 if ((unsigned char *)e - base == underflows[h]) {
754                         if (!check_underflow(e)) {
755                                 pr_err("Underflows must be unconditional and "
756                                        "use the STANDARD target with "
757                                        "ACCEPT/DROP\n");
758                                 return -EINVAL;
759                         }
760                         newinfo->underflow[h] = underflows[h];
761                 }
762         }
763
764         /* Clear counters and comefrom */
765         e->counters = ((struct xt_counters) { 0, 0 });
766         e->comefrom = 0;
767         return 0;
768 }
769
770 static void
771 cleanup_entry(struct ipt_entry *e, struct net *net)
772 {
773         struct xt_tgdtor_param par;
774         struct xt_entry_target *t;
775         struct xt_entry_match *ematch;
776
777         /* Cleanup all matches */
778         xt_ematch_foreach(ematch, e)
779                 cleanup_match(ematch, net);
780         t = ipt_get_target(e);
781
782         par.net      = net;
783         par.target   = t->u.kernel.target;
784         par.targinfo = t->data;
785         par.family   = NFPROTO_IPV4;
786         if (par.target->destroy != NULL)
787                 par.target->destroy(&par);
788         module_put(par.target->me);
789 }
790
791 /* Checks and translates the user-supplied table segment (held in
792    newinfo) */
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                 local_bh_disable();
913                 xt_info_wrlock(cpu);
914                 xt_entry_foreach(iter, t->entries[cpu], t->size) {
915                         ADD_COUNTER(counters[i], iter->counters.bcnt,
916                                     iter->counters.pcnt);
917                         ++i; /* macro does multi eval of i */
918                 }
919                 xt_info_wrunlock(cpu);
920                 local_bh_enable();
921         }
922         put_cpu();
923 }
924
925 static struct xt_counters *alloc_counters(const struct xt_table *table)
926 {
927         unsigned int countersize;
928         struct xt_counters *counters;
929         const struct xt_table_info *private = table->private;
930
931         /* We need atomic snapshot of counters: rest doesn't change
932            (other than comefrom, which userspace doesn't care
933            about). */
934         countersize = sizeof(struct xt_counters) * private->number;
935         counters = vmalloc(countersize);
936
937         if (counters == NULL)
938                 return ERR_PTR(-ENOMEM);
939
940         get_counters(private, counters);
941
942         return counters;
943 }
944
945 static int
946 copy_entries_to_user(unsigned int total_size,
947                      const struct xt_table *table,
948                      void __user *userptr)
949 {
950         unsigned int off, num;
951         const struct ipt_entry *e;
952         struct xt_counters *counters;
953         const struct xt_table_info *private = table->private;
954         int ret = 0;
955         const void *loc_cpu_entry;
956
957         counters = alloc_counters(table);
958         if (IS_ERR(counters))
959                 return PTR_ERR(counters);
960
961         /* choose the copy that is on our node/cpu, ...
962          * This choice is lazy (because current thread is
963          * allowed to migrate to another cpu)
964          */
965         loc_cpu_entry = private->entries[raw_smp_processor_id()];
966         if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
967                 ret = -EFAULT;
968                 goto free_counters;
969         }
970
971         /* FIXME: use iterator macros --RR */
972         /* ... then go back and fix counters and names */
973         for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
974                 unsigned int i;
975                 const struct xt_entry_match *m;
976                 const struct xt_entry_target *t;
977
978                 e = (struct ipt_entry *)(loc_cpu_entry + off);
979                 if (copy_to_user(userptr + off
980                                  + offsetof(struct ipt_entry, counters),
981                                  &counters[num],
982                                  sizeof(counters[num])) != 0) {
983                         ret = -EFAULT;
984                         goto free_counters;
985                 }
986
987                 for (i = sizeof(struct ipt_entry);
988                      i < e->target_offset;
989                      i += m->u.match_size) {
990                         m = (void *)e + i;
991
992                         if (copy_to_user(userptr + off + i
993                                          + offsetof(struct xt_entry_match,
994                                                     u.user.name),
995                                          m->u.kernel.match->name,
996                                          strlen(m->u.kernel.match->name)+1)
997                             != 0) {
998                                 ret = -EFAULT;
999                                 goto free_counters;
1000                         }
1001                 }
1002
1003                 t = ipt_get_target_c(e);
1004                 if (copy_to_user(userptr + off + e->target_offset
1005                                  + offsetof(struct xt_entry_target,
1006                                             u.user.name),
1007                                  t->u.kernel.target->name,
1008                                  strlen(t->u.kernel.target->name)+1) != 0) {
1009                         ret = -EFAULT;
1010                         goto free_counters;
1011                 }
1012         }
1013
1014  free_counters:
1015         vfree(counters);
1016         return ret;
1017 }
1018
1019 #ifdef CONFIG_COMPAT
1020 static void compat_standard_from_user(void *dst, const void *src)
1021 {
1022         int v = *(compat_int_t *)src;
1023
1024         if (v > 0)
1025                 v += xt_compat_calc_jump(AF_INET, v);
1026         memcpy(dst, &v, sizeof(v));
1027 }
1028
1029 static int compat_standard_to_user(void __user *dst, const void *src)
1030 {
1031         compat_int_t cv = *(int *)src;
1032
1033         if (cv > 0)
1034                 cv -= xt_compat_calc_jump(AF_INET, cv);
1035         return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1036 }
1037
1038 static int compat_calc_entry(const struct ipt_entry *e,
1039                              const struct xt_table_info *info,
1040                              const void *base, struct xt_table_info *newinfo)
1041 {
1042         const struct xt_entry_match *ematch;
1043         const struct xt_entry_target *t;
1044         unsigned int entry_offset;
1045         int off, i, ret;
1046
1047         off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1048         entry_offset = (void *)e - base;
1049         xt_ematch_foreach(ematch, e)
1050                 off += xt_compat_match_offset(ematch->u.kernel.match);
1051         t = ipt_get_target_c(e);
1052         off += xt_compat_target_offset(t->u.kernel.target);
1053         newinfo->size -= off;
1054         ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1055         if (ret)
1056                 return ret;
1057
1058         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1059                 if (info->hook_entry[i] &&
1060                     (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1061                         newinfo->hook_entry[i] -= off;
1062                 if (info->underflow[i] &&
1063                     (e < (struct ipt_entry *)(base + info->underflow[i])))
1064                         newinfo->underflow[i] -= off;
1065         }
1066         return 0;
1067 }
1068
1069 static int compat_table_info(const struct xt_table_info *info,
1070                              struct xt_table_info *newinfo)
1071 {
1072         struct ipt_entry *iter;
1073         void *loc_cpu_entry;
1074         int ret;
1075
1076         if (!newinfo || !info)
1077                 return -EINVAL;
1078
1079         /* we dont care about newinfo->entries[] */
1080         memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1081         newinfo->initial_entries = 0;
1082         loc_cpu_entry = info->entries[raw_smp_processor_id()];
1083         xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1084                 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1085                 if (ret != 0)
1086                         return ret;
1087         }
1088         return 0;
1089 }
1090 #endif
1091
1092 static int get_info(struct net *net, void __user *user,
1093                     const int *len, int compat)
1094 {
1095         char name[XT_TABLE_MAXNAMELEN];
1096         struct xt_table *t;
1097         int ret;
1098
1099         if (*len != sizeof(struct ipt_getinfo)) {
1100                 duprintf("length %u != %zu\n", *len,
1101                          sizeof(struct ipt_getinfo));
1102                 return -EINVAL;
1103         }
1104
1105         if (copy_from_user(name, user, sizeof(name)) != 0)
1106                 return -EFAULT;
1107
1108         name[XT_TABLE_MAXNAMELEN-1] = '\0';
1109 #ifdef CONFIG_COMPAT
1110         if (compat)
1111                 xt_compat_lock(AF_INET);
1112 #endif
1113         t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1114                                     "iptable_%s", name);
1115         if (t && !IS_ERR(t)) {
1116                 struct ipt_getinfo info;
1117                 const struct xt_table_info *private = t->private;
1118 #ifdef CONFIG_COMPAT
1119                 struct xt_table_info tmp;
1120
1121                 if (compat) {
1122                         ret = compat_table_info(private, &tmp);
1123                         xt_compat_flush_offsets(AF_INET);
1124                         private = &tmp;
1125                 }
1126 #endif
1127                 memset(&info, 0, sizeof(info));
1128                 info.valid_hooks = t->valid_hooks;
1129                 memcpy(info.hook_entry, private->hook_entry,
1130                        sizeof(info.hook_entry));
1131                 memcpy(info.underflow, private->underflow,
1132                        sizeof(info.underflow));
1133                 info.num_entries = private->number;
1134                 info.size = private->size;
1135                 strcpy(info.name, name);
1136
1137                 if (copy_to_user(user, &info, *len) != 0)
1138                         ret = -EFAULT;
1139                 else
1140                         ret = 0;
1141
1142                 xt_table_unlock(t);
1143                 module_put(t->me);
1144         } else
1145                 ret = t ? PTR_ERR(t) : -ENOENT;
1146 #ifdef CONFIG_COMPAT
1147         if (compat)
1148                 xt_compat_unlock(AF_INET);
1149 #endif
1150         return ret;
1151 }
1152
1153 static int
1154 get_entries(struct net *net, struct ipt_get_entries __user *uptr,
1155             const int *len)
1156 {
1157         int ret;
1158         struct ipt_get_entries get;
1159         struct xt_table *t;
1160
1161         if (*len < sizeof(get)) {
1162                 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1163                 return -EINVAL;
1164         }
1165         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1166                 return -EFAULT;
1167         if (*len != sizeof(struct ipt_get_entries) + get.size) {
1168                 duprintf("get_entries: %u != %zu\n",
1169                          *len, sizeof(get) + get.size);
1170                 return -EINVAL;
1171         }
1172
1173         t = xt_find_table_lock(net, AF_INET, get.name);
1174         if (t && !IS_ERR(t)) {
1175                 const struct xt_table_info *private = t->private;
1176                 duprintf("t->private->number = %u\n", private->number);
1177                 if (get.size == private->size)
1178                         ret = copy_entries_to_user(private->size,
1179                                                    t, uptr->entrytable);
1180                 else {
1181                         duprintf("get_entries: I've got %u not %u!\n",
1182                                  private->size, get.size);
1183                         ret = -EAGAIN;
1184                 }
1185                 module_put(t->me);
1186                 xt_table_unlock(t);
1187         } else
1188                 ret = t ? PTR_ERR(t) : -ENOENT;
1189
1190         return ret;
1191 }
1192
1193 static int
1194 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1195              struct xt_table_info *newinfo, unsigned int num_counters,
1196              void __user *counters_ptr)
1197 {
1198         int ret;
1199         struct xt_table *t;
1200         struct xt_table_info *oldinfo;
1201         struct xt_counters *counters;
1202         void *loc_cpu_old_entry;
1203         struct ipt_entry *iter;
1204
1205         ret = 0;
1206         counters = vmalloc(num_counters * sizeof(struct xt_counters));
1207         if (!counters) {
1208                 ret = -ENOMEM;
1209                 goto out;
1210         }
1211
1212         t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1213                                     "iptable_%s", name);
1214         if (!t || IS_ERR(t)) {
1215                 ret = t ? PTR_ERR(t) : -ENOENT;
1216                 goto free_newinfo_counters_untrans;
1217         }
1218
1219         /* You lied! */
1220         if (valid_hooks != t->valid_hooks) {
1221                 duprintf("Valid hook crap: %08X vs %08X\n",
1222                          valid_hooks, t->valid_hooks);
1223                 ret = -EINVAL;
1224                 goto put_module;
1225         }
1226
1227         oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1228         if (!oldinfo)
1229                 goto put_module;
1230
1231         /* Update module usage count based on number of rules */
1232         duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1233                 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1234         if ((oldinfo->number > oldinfo->initial_entries) ||
1235             (newinfo->number <= oldinfo->initial_entries))
1236                 module_put(t->me);
1237         if ((oldinfo->number > oldinfo->initial_entries) &&
1238             (newinfo->number <= oldinfo->initial_entries))
1239                 module_put(t->me);
1240
1241         /* Get the old counters, and synchronize with replace */
1242         get_counters(oldinfo, counters);
1243
1244         /* Decrease module usage counts and free resource */
1245         loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1246         xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1247                 cleanup_entry(iter, net);
1248
1249         xt_free_table_info(oldinfo);
1250         if (copy_to_user(counters_ptr, counters,
1251                          sizeof(struct xt_counters) * num_counters) != 0)
1252                 ret = -EFAULT;
1253         vfree(counters);
1254         xt_table_unlock(t);
1255         return ret;
1256
1257  put_module:
1258         module_put(t->me);
1259         xt_table_unlock(t);
1260  free_newinfo_counters_untrans:
1261         vfree(counters);
1262  out:
1263         return ret;
1264 }
1265
1266 static int
1267 do_replace(struct net *net, const void __user *user, unsigned int len)
1268 {
1269         int ret;
1270         struct ipt_replace tmp;
1271         struct xt_table_info *newinfo;
1272         void *loc_cpu_entry;
1273         struct ipt_entry *iter;
1274
1275         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1276                 return -EFAULT;
1277
1278         /* overflow check */
1279         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1280                 return -ENOMEM;
1281
1282         newinfo = xt_alloc_table_info(tmp.size);
1283         if (!newinfo)
1284                 return -ENOMEM;
1285
1286         /* choose the copy that is on our node/cpu */
1287         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1288         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1289                            tmp.size) != 0) {
1290                 ret = -EFAULT;
1291                 goto free_newinfo;
1292         }
1293
1294         ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1295         if (ret != 0)
1296                 goto free_newinfo;
1297
1298         duprintf("Translated table\n");
1299
1300         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1301                            tmp.num_counters, tmp.counters);
1302         if (ret)
1303                 goto free_newinfo_untrans;
1304         return 0;
1305
1306  free_newinfo_untrans:
1307         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1308                 cleanup_entry(iter, net);
1309  free_newinfo:
1310         xt_free_table_info(newinfo);
1311         return ret;
1312 }
1313
1314 static int
1315 do_add_counters(struct net *net, const void __user *user,
1316                 unsigned int len, int compat)
1317 {
1318         unsigned int i, curcpu;
1319         struct xt_counters_info tmp;
1320         struct xt_counters *paddc;
1321         unsigned int num_counters;
1322         const char *name;
1323         int size;
1324         void *ptmp;
1325         struct xt_table *t;
1326         const struct xt_table_info *private;
1327         int ret = 0;
1328         void *loc_cpu_entry;
1329         struct ipt_entry *iter;
1330 #ifdef CONFIG_COMPAT
1331         struct compat_xt_counters_info compat_tmp;
1332
1333         if (compat) {
1334                 ptmp = &compat_tmp;
1335                 size = sizeof(struct compat_xt_counters_info);
1336         } else
1337 #endif
1338         {
1339                 ptmp = &tmp;
1340                 size = sizeof(struct xt_counters_info);
1341         }
1342
1343         if (copy_from_user(ptmp, user, size) != 0)
1344                 return -EFAULT;
1345
1346 #ifdef CONFIG_COMPAT
1347         if (compat) {
1348                 num_counters = compat_tmp.num_counters;
1349                 name = compat_tmp.name;
1350         } else
1351 #endif
1352         {
1353                 num_counters = tmp.num_counters;
1354                 name = tmp.name;
1355         }
1356
1357         if (len != size + num_counters * sizeof(struct xt_counters))
1358                 return -EINVAL;
1359
1360         paddc = vmalloc(len - size);
1361         if (!paddc)
1362                 return -ENOMEM;
1363
1364         if (copy_from_user(paddc, user + size, len - size) != 0) {
1365                 ret = -EFAULT;
1366                 goto free;
1367         }
1368
1369         t = xt_find_table_lock(net, AF_INET, name);
1370         if (!t || IS_ERR(t)) {
1371                 ret = t ? PTR_ERR(t) : -ENOENT;
1372                 goto free;
1373         }
1374
1375         local_bh_disable();
1376         private = t->private;
1377         if (private->number != num_counters) {
1378                 ret = -EINVAL;
1379                 goto unlock_up_free;
1380         }
1381
1382         i = 0;
1383         /* Choose the copy that is on our node */
1384         curcpu = smp_processor_id();
1385         loc_cpu_entry = private->entries[curcpu];
1386         xt_info_wrlock(curcpu);
1387         xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1388                 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1389                 ++i;
1390         }
1391         xt_info_wrunlock(curcpu);
1392  unlock_up_free:
1393         local_bh_enable();
1394         xt_table_unlock(t);
1395         module_put(t->me);
1396  free:
1397         vfree(paddc);
1398
1399         return ret;
1400 }
1401
1402 #ifdef CONFIG_COMPAT
1403 struct compat_ipt_replace {
1404         char                    name[XT_TABLE_MAXNAMELEN];
1405         u32                     valid_hooks;
1406         u32                     num_entries;
1407         u32                     size;
1408         u32                     hook_entry[NF_INET_NUMHOOKS];
1409         u32                     underflow[NF_INET_NUMHOOKS];
1410         u32                     num_counters;
1411         compat_uptr_t           counters;       /* struct xt_counters * */
1412         struct compat_ipt_entry entries[0];
1413 };
1414
1415 static int
1416 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1417                           unsigned int *size, struct xt_counters *counters,
1418                           unsigned int i)
1419 {
1420         struct xt_entry_target *t;
1421         struct compat_ipt_entry __user *ce;
1422         u_int16_t target_offset, next_offset;
1423         compat_uint_t origsize;
1424         const struct xt_entry_match *ematch;
1425         int ret = 0;
1426
1427         origsize = *size;
1428         ce = (struct compat_ipt_entry __user *)*dstptr;
1429         if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
1430             copy_to_user(&ce->counters, &counters[i],
1431             sizeof(counters[i])) != 0)
1432                 return -EFAULT;
1433
1434         *dstptr += sizeof(struct compat_ipt_entry);
1435         *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1436
1437         xt_ematch_foreach(ematch, e) {
1438                 ret = xt_compat_match_to_user(ematch, dstptr, size);
1439                 if (ret != 0)
1440                         return ret;
1441         }
1442         target_offset = e->target_offset - (origsize - *size);
1443         t = ipt_get_target(e);
1444         ret = xt_compat_target_to_user(t, dstptr, size);
1445         if (ret)
1446                 return ret;
1447         next_offset = e->next_offset - (origsize - *size);
1448         if (put_user(target_offset, &ce->target_offset) != 0 ||
1449             put_user(next_offset, &ce->next_offset) != 0)
1450                 return -EFAULT;
1451         return 0;
1452 }
1453
1454 static int
1455 compat_find_calc_match(struct xt_entry_match *m,
1456                        const char *name,
1457                        const struct ipt_ip *ip,
1458                        unsigned int hookmask,
1459                        int *size)
1460 {
1461         struct xt_match *match;
1462
1463         match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
1464                                       m->u.user.revision);
1465         if (IS_ERR(match)) {
1466                 duprintf("compat_check_calc_match: `%s' not found\n",
1467                          m->u.user.name);
1468                 return PTR_ERR(match);
1469         }
1470         m->u.kernel.match = match;
1471         *size += xt_compat_match_offset(match);
1472         return 0;
1473 }
1474
1475 static void compat_release_entry(struct compat_ipt_entry *e)
1476 {
1477         struct xt_entry_target *t;
1478         struct xt_entry_match *ematch;
1479
1480         /* Cleanup all matches */
1481         xt_ematch_foreach(ematch, e)
1482                 module_put(ematch->u.kernel.match->me);
1483         t = compat_ipt_get_target(e);
1484         module_put(t->u.kernel.target->me);
1485 }
1486
1487 static int
1488 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1489                                   struct xt_table_info *newinfo,
1490                                   unsigned int *size,
1491                                   const unsigned char *base,
1492                                   const unsigned char *limit,
1493                                   const unsigned int *hook_entries,
1494                                   const unsigned int *underflows,
1495                                   const char *name)
1496 {
1497         struct xt_entry_match *ematch;
1498         struct xt_entry_target *t;
1499         struct xt_target *target;
1500         unsigned int entry_offset;
1501         unsigned int j;
1502         int ret, off, h;
1503
1504         duprintf("check_compat_entry_size_and_hooks %p\n", e);
1505         if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1506             (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1507                 duprintf("Bad offset %p, limit = %p\n", e, limit);
1508                 return -EINVAL;
1509         }
1510
1511         if (e->next_offset < sizeof(struct compat_ipt_entry) +
1512                              sizeof(struct compat_xt_entry_target)) {
1513                 duprintf("checking: element %p size %u\n",
1514                          e, e->next_offset);
1515                 return -EINVAL;
1516         }
1517
1518         /* For purposes of check_entry casting the compat entry is fine */
1519         ret = check_entry((struct ipt_entry *)e, name);
1520         if (ret)
1521                 return ret;
1522
1523         off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1524         entry_offset = (void *)e - (void *)base;
1525         j = 0;
1526         xt_ematch_foreach(ematch, e) {
1527                 ret = compat_find_calc_match(ematch, name,
1528                                              &e->ip, e->comefrom, &off);
1529                 if (ret != 0)
1530                         goto release_matches;
1531                 ++j;
1532         }
1533
1534         t = compat_ipt_get_target(e);
1535         target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
1536                                         t->u.user.revision);
1537         if (IS_ERR(target)) {
1538                 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1539                          t->u.user.name);
1540                 ret = PTR_ERR(target);
1541                 goto release_matches;
1542         }
1543         t->u.kernel.target = target;
1544
1545         off += xt_compat_target_offset(target);
1546         *size += off;
1547         ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1548         if (ret)
1549                 goto out;
1550
1551         /* Check hooks & underflows */
1552         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1553                 if ((unsigned char *)e - base == hook_entries[h])
1554                         newinfo->hook_entry[h] = hook_entries[h];
1555                 if ((unsigned char *)e - base == underflows[h])
1556                         newinfo->underflow[h] = underflows[h];
1557         }
1558
1559         /* Clear counters and comefrom */
1560         memset(&e->counters, 0, sizeof(e->counters));
1561         e->comefrom = 0;
1562         return 0;
1563
1564 out:
1565         module_put(t->u.kernel.target->me);
1566 release_matches:
1567         xt_ematch_foreach(ematch, e) {
1568                 if (j-- == 0)
1569                         break;
1570                 module_put(ematch->u.kernel.match->me);
1571         }
1572         return ret;
1573 }
1574
1575 static int
1576 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1577                             unsigned int *size, const char *name,
1578                             struct xt_table_info *newinfo, unsigned char *base)
1579 {
1580         struct xt_entry_target *t;
1581         struct xt_target *target;
1582         struct ipt_entry *de;
1583         unsigned int origsize;
1584         int ret, h;
1585         struct xt_entry_match *ematch;
1586
1587         ret = 0;
1588         origsize = *size;
1589         de = (struct ipt_entry *)*dstptr;
1590         memcpy(de, e, sizeof(struct ipt_entry));
1591         memcpy(&de->counters, &e->counters, sizeof(e->counters));
1592
1593         *dstptr += sizeof(struct ipt_entry);
1594         *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1595
1596         xt_ematch_foreach(ematch, e) {
1597                 ret = xt_compat_match_from_user(ematch, dstptr, size);
1598                 if (ret != 0)
1599                         return ret;
1600         }
1601         de->target_offset = e->target_offset - (origsize - *size);
1602         t = compat_ipt_get_target(e);
1603         target = t->u.kernel.target;
1604         xt_compat_target_from_user(t, dstptr, size);
1605
1606         de->next_offset = e->next_offset - (origsize - *size);
1607         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1608                 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1609                         newinfo->hook_entry[h] -= origsize - *size;
1610                 if ((unsigned char *)de - base < newinfo->underflow[h])
1611                         newinfo->underflow[h] -= origsize - *size;
1612         }
1613         return ret;
1614 }
1615
1616 static int
1617 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1618 {
1619         struct xt_entry_match *ematch;
1620         struct xt_mtchk_param mtpar;
1621         unsigned int j;
1622         int ret = 0;
1623
1624         j = 0;
1625         mtpar.net       = net;
1626         mtpar.table     = name;
1627         mtpar.entryinfo = &e->ip;
1628         mtpar.hook_mask = e->comefrom;
1629         mtpar.family    = NFPROTO_IPV4;
1630         xt_ematch_foreach(ematch, e) {
1631                 ret = check_match(ematch, &mtpar);
1632                 if (ret != 0)
1633                         goto cleanup_matches;
1634                 ++j;
1635         }
1636
1637         ret = check_target(e, net, name);
1638         if (ret)
1639                 goto cleanup_matches;
1640         return 0;
1641
1642  cleanup_matches:
1643         xt_ematch_foreach(ematch, e) {
1644                 if (j-- == 0)
1645                         break;
1646                 cleanup_match(ematch, net);
1647         }
1648         return ret;
1649 }
1650
1651 static int
1652 translate_compat_table(struct net *net,
1653                        const char *name,
1654                        unsigned int valid_hooks,
1655                        struct xt_table_info **pinfo,
1656                        void **pentry0,
1657                        unsigned int total_size,
1658                        unsigned int number,
1659                        unsigned int *hook_entries,
1660                        unsigned int *underflows)
1661 {
1662         unsigned int i, j;
1663         struct xt_table_info *newinfo, *info;
1664         void *pos, *entry0, *entry1;
1665         struct compat_ipt_entry *iter0;
1666         struct ipt_entry *iter1;
1667         unsigned int size;
1668         int ret;
1669
1670         info = *pinfo;
1671         entry0 = *pentry0;
1672         size = total_size;
1673         info->number = number;
1674
1675         /* Init all hooks to impossible value. */
1676         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1677                 info->hook_entry[i] = 0xFFFFFFFF;
1678                 info->underflow[i] = 0xFFFFFFFF;
1679         }
1680
1681         duprintf("translate_compat_table: size %u\n", info->size);
1682         j = 0;
1683         xt_compat_lock(AF_INET);
1684         /* Walk through entries, checking offsets. */
1685         xt_entry_foreach(iter0, entry0, total_size) {
1686                 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1687                                                         entry0,
1688                                                         entry0 + total_size,
1689                                                         hook_entries,
1690                                                         underflows,
1691                                                         name);
1692                 if (ret != 0)
1693                         goto out_unlock;
1694                 ++j;
1695         }
1696
1697         ret = -EINVAL;
1698         if (j != number) {
1699                 duprintf("translate_compat_table: %u not %u entries\n",
1700                          j, number);
1701                 goto out_unlock;
1702         }
1703
1704         /* Check hooks all assigned */
1705         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1706                 /* Only hooks which are valid */
1707                 if (!(valid_hooks & (1 << i)))
1708                         continue;
1709                 if (info->hook_entry[i] == 0xFFFFFFFF) {
1710                         duprintf("Invalid hook entry %u %u\n",
1711                                  i, hook_entries[i]);
1712                         goto out_unlock;
1713                 }
1714                 if (info->underflow[i] == 0xFFFFFFFF) {
1715                         duprintf("Invalid underflow %u %u\n",
1716                                  i, underflows[i]);
1717                         goto out_unlock;
1718                 }
1719         }
1720
1721         ret = -ENOMEM;
1722         newinfo = xt_alloc_table_info(size);
1723         if (!newinfo)
1724                 goto out_unlock;
1725
1726         newinfo->number = number;
1727         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1728                 newinfo->hook_entry[i] = info->hook_entry[i];
1729                 newinfo->underflow[i] = info->underflow[i];
1730         }
1731         entry1 = newinfo->entries[raw_smp_processor_id()];
1732         pos = entry1;
1733         size = total_size;
1734         xt_entry_foreach(iter0, entry0, total_size) {
1735                 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1736                                                   name, newinfo, entry1);
1737                 if (ret != 0)
1738                         break;
1739         }
1740         xt_compat_flush_offsets(AF_INET);
1741         xt_compat_unlock(AF_INET);
1742         if (ret)
1743                 goto free_newinfo;
1744
1745         ret = -ELOOP;
1746         if (!mark_source_chains(newinfo, valid_hooks, entry1))
1747                 goto free_newinfo;
1748
1749         i = 0;
1750         xt_entry_foreach(iter1, entry1, newinfo->size) {
1751                 ret = compat_check_entry(iter1, net, name);
1752                 if (ret != 0)
1753                         break;
1754                 ++i;
1755                 if (strcmp(ipt_get_target(iter1)->u.user.name,
1756                     XT_ERROR_TARGET) == 0)
1757                         ++newinfo->stacksize;
1758         }
1759         if (ret) {
1760                 /*
1761                  * The first i matches need cleanup_entry (calls ->destroy)
1762                  * because they had called ->check already. The other j-i
1763                  * entries need only release.
1764                  */
1765                 int skip = i;
1766                 j -= i;
1767                 xt_entry_foreach(iter0, entry0, newinfo->size) {
1768                         if (skip-- > 0)
1769                                 continue;
1770                         if (j-- == 0)
1771                                 break;
1772                         compat_release_entry(iter0);
1773                 }
1774                 xt_entry_foreach(iter1, entry1, newinfo->size) {
1775                         if (i-- == 0)
1776                                 break;
1777                         cleanup_entry(iter1, net);
1778                 }
1779                 xt_free_table_info(newinfo);
1780                 return ret;
1781         }
1782
1783         /* And one copy for every other CPU */
1784         for_each_possible_cpu(i)
1785                 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1786                         memcpy(newinfo->entries[i], entry1, newinfo->size);
1787
1788         *pinfo = newinfo;
1789         *pentry0 = entry1;
1790         xt_free_table_info(info);
1791         return 0;
1792
1793 free_newinfo:
1794         xt_free_table_info(newinfo);
1795 out:
1796         xt_entry_foreach(iter0, entry0, total_size) {
1797                 if (j-- == 0)
1798                         break;
1799                 compat_release_entry(iter0);
1800         }
1801         return ret;
1802 out_unlock:
1803         xt_compat_flush_offsets(AF_INET);
1804         xt_compat_unlock(AF_INET);
1805         goto out;
1806 }
1807
1808 static int
1809 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1810 {
1811         int ret;
1812         struct compat_ipt_replace tmp;
1813         struct xt_table_info *newinfo;
1814         void *loc_cpu_entry;
1815         struct ipt_entry *iter;
1816
1817         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1818                 return -EFAULT;
1819
1820         /* overflow check */
1821         if (tmp.size >= INT_MAX / num_possible_cpus())
1822                 return -ENOMEM;
1823         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1824                 return -ENOMEM;
1825
1826         newinfo = xt_alloc_table_info(tmp.size);
1827         if (!newinfo)
1828                 return -ENOMEM;
1829
1830         /* choose the copy that is on our node/cpu */
1831         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1832         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1833                            tmp.size) != 0) {
1834                 ret = -EFAULT;
1835                 goto free_newinfo;
1836         }
1837
1838         ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1839                                      &newinfo, &loc_cpu_entry, tmp.size,
1840                                      tmp.num_entries, tmp.hook_entry,
1841                                      tmp.underflow);
1842         if (ret != 0)
1843                 goto free_newinfo;
1844
1845         duprintf("compat_do_replace: Translated table\n");
1846
1847         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1848                            tmp.num_counters, compat_ptr(tmp.counters));
1849         if (ret)
1850                 goto free_newinfo_untrans;
1851         return 0;
1852
1853  free_newinfo_untrans:
1854         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1855                 cleanup_entry(iter, net);
1856  free_newinfo:
1857         xt_free_table_info(newinfo);
1858         return ret;
1859 }
1860
1861 static int
1862 compat_do_ipt_set_ctl(struct sock *sk,  int cmd, void __user *user,
1863                       unsigned int len)
1864 {
1865         int ret;
1866
1867         if (!capable(CAP_NET_ADMIN))
1868                 return -EPERM;
1869
1870         switch (cmd) {
1871         case IPT_SO_SET_REPLACE:
1872                 ret = compat_do_replace(sock_net(sk), user, len);
1873                 break;
1874
1875         case IPT_SO_SET_ADD_COUNTERS:
1876                 ret = do_add_counters(sock_net(sk), user, len, 1);
1877                 break;
1878
1879         default:
1880                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
1881                 ret = -EINVAL;
1882         }
1883
1884         return ret;
1885 }
1886
1887 struct compat_ipt_get_entries {
1888         char name[XT_TABLE_MAXNAMELEN];
1889         compat_uint_t size;
1890         struct compat_ipt_entry entrytable[0];
1891 };
1892
1893 static int
1894 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1895                             void __user *userptr)
1896 {
1897         struct xt_counters *counters;
1898         const struct xt_table_info *private = table->private;
1899         void __user *pos;
1900         unsigned int size;
1901         int ret = 0;
1902         const void *loc_cpu_entry;
1903         unsigned int i = 0;
1904         struct ipt_entry *iter;
1905
1906         counters = alloc_counters(table);
1907         if (IS_ERR(counters))
1908                 return PTR_ERR(counters);
1909
1910         /* choose the copy that is on our node/cpu, ...
1911          * This choice is lazy (because current thread is
1912          * allowed to migrate to another cpu)
1913          */
1914         loc_cpu_entry = private->entries[raw_smp_processor_id()];
1915         pos = userptr;
1916         size = total_size;
1917         xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1918                 ret = compat_copy_entry_to_user(iter, &pos,
1919                                                 &size, counters, i++);
1920                 if (ret != 0)
1921                         break;
1922         }
1923
1924         vfree(counters);
1925         return ret;
1926 }
1927
1928 static int
1929 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1930                    int *len)
1931 {
1932         int ret;
1933         struct compat_ipt_get_entries get;
1934         struct xt_table *t;
1935
1936         if (*len < sizeof(get)) {
1937                 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1938                 return -EINVAL;
1939         }
1940
1941         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1942                 return -EFAULT;
1943
1944         if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1945                 duprintf("compat_get_entries: %u != %zu\n",
1946                          *len, sizeof(get) + get.size);
1947                 return -EINVAL;
1948         }
1949
1950         xt_compat_lock(AF_INET);
1951         t = xt_find_table_lock(net, AF_INET, get.name);
1952         if (t && !IS_ERR(t)) {
1953                 const struct xt_table_info *private = t->private;
1954                 struct xt_table_info info;
1955                 duprintf("t->private->number = %u\n", private->number);
1956                 ret = compat_table_info(private, &info);
1957                 if (!ret && get.size == info.size) {
1958                         ret = compat_copy_entries_to_user(private->size,
1959                                                           t, uptr->entrytable);
1960                 } else if (!ret) {
1961                         duprintf("compat_get_entries: I've got %u not %u!\n",
1962                                  private->size, get.size);
1963                         ret = -EAGAIN;
1964                 }
1965                 xt_compat_flush_offsets(AF_INET);
1966                 module_put(t->me);
1967                 xt_table_unlock(t);
1968         } else
1969                 ret = t ? PTR_ERR(t) : -ENOENT;
1970
1971         xt_compat_unlock(AF_INET);
1972         return ret;
1973 }
1974
1975 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1976
1977 static int
1978 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1979 {
1980         int ret;
1981
1982         if (!capable(CAP_NET_ADMIN))
1983                 return -EPERM;
1984
1985         switch (cmd) {
1986         case IPT_SO_GET_INFO:
1987                 ret = get_info(sock_net(sk), user, len, 1);
1988                 break;
1989         case IPT_SO_GET_ENTRIES:
1990                 ret = compat_get_entries(sock_net(sk), user, len);
1991                 break;
1992         default:
1993                 ret = do_ipt_get_ctl(sk, cmd, user, len);
1994         }
1995         return ret;
1996 }
1997 #endif
1998
1999 static int
2000 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2001 {
2002         int ret;
2003
2004         if (!capable(CAP_NET_ADMIN))
2005                 return -EPERM;
2006
2007         switch (cmd) {
2008         case IPT_SO_SET_REPLACE:
2009                 ret = do_replace(sock_net(sk), user, len);
2010                 break;
2011
2012         case IPT_SO_SET_ADD_COUNTERS:
2013                 ret = do_add_counters(sock_net(sk), user, len, 0);
2014                 break;
2015
2016         default:
2017                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
2018                 ret = -EINVAL;
2019         }
2020
2021         return ret;
2022 }
2023
2024 static int
2025 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2026 {
2027         int ret;
2028
2029         if (!capable(CAP_NET_ADMIN))
2030                 return -EPERM;
2031
2032         switch (cmd) {
2033         case IPT_SO_GET_INFO:
2034                 ret = get_info(sock_net(sk), user, len, 0);
2035                 break;
2036
2037         case IPT_SO_GET_ENTRIES:
2038                 ret = get_entries(sock_net(sk), user, len);
2039                 break;
2040
2041         case IPT_SO_GET_REVISION_MATCH:
2042         case IPT_SO_GET_REVISION_TARGET: {
2043                 struct xt_get_revision rev;
2044                 int target;
2045
2046                 if (*len != sizeof(rev)) {
2047                         ret = -EINVAL;
2048                         break;
2049                 }
2050                 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2051                         ret = -EFAULT;
2052                         break;
2053                 }
2054
2055                 if (cmd == IPT_SO_GET_REVISION_TARGET)
2056                         target = 1;
2057                 else
2058                         target = 0;
2059
2060                 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2061                                                          rev.revision,
2062                                                          target, &ret),
2063                                         "ipt_%s", rev.name);
2064                 break;
2065         }
2066
2067         default:
2068                 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2069                 ret = -EINVAL;
2070         }
2071
2072         return ret;
2073 }
2074
2075 struct xt_table *ipt_register_table(struct net *net,
2076                                     const struct xt_table *table,
2077                                     const struct ipt_replace *repl)
2078 {
2079         int ret;
2080         struct xt_table_info *newinfo;
2081         struct xt_table_info bootstrap = {0};
2082         void *loc_cpu_entry;
2083         struct xt_table *new_table;
2084
2085         newinfo = xt_alloc_table_info(repl->size);
2086         if (!newinfo) {
2087                 ret = -ENOMEM;
2088                 goto out;
2089         }
2090
2091         /* choose the copy on our node/cpu, but dont care about preemption */
2092         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2093         memcpy(loc_cpu_entry, repl->entries, repl->size);
2094
2095         ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2096         if (ret != 0)
2097                 goto out_free;
2098
2099         new_table = xt_register_table(net, table, &bootstrap, newinfo);
2100         if (IS_ERR(new_table)) {
2101                 ret = PTR_ERR(new_table);
2102                 goto out_free;
2103         }
2104
2105         return new_table;
2106
2107 out_free:
2108         xt_free_table_info(newinfo);
2109 out:
2110         return ERR_PTR(ret);
2111 }
2112
2113 void ipt_unregister_table(struct net *net, struct xt_table *table)
2114 {
2115         struct xt_table_info *private;
2116         void *loc_cpu_entry;
2117         struct module *table_owner = table->me;
2118         struct ipt_entry *iter;
2119
2120         private = xt_unregister_table(table);
2121
2122         /* Decrease module usage counts and free resources */
2123         loc_cpu_entry = private->entries[raw_smp_processor_id()];
2124         xt_entry_foreach(iter, loc_cpu_entry, private->size)
2125                 cleanup_entry(iter, net);
2126         if (private->number > private->initial_entries)
2127                 module_put(table_owner);
2128         xt_free_table_info(private);
2129 }
2130
2131 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2132 static inline bool
2133 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2134                      u_int8_t type, u_int8_t code,
2135                      bool invert)
2136 {
2137         return ((test_type == 0xFF) ||
2138                 (type == test_type && code >= min_code && code <= max_code))
2139                 ^ invert;
2140 }
2141
2142 static bool
2143 icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
2144 {
2145         const struct icmphdr *ic;
2146         struct icmphdr _icmph;
2147         const struct ipt_icmp *icmpinfo = par->matchinfo;
2148
2149         /* Must not be a fragment. */
2150         if (par->fragoff != 0)
2151                 return false;
2152
2153         ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2154         if (ic == NULL) {
2155                 /* We've been asked to examine this packet, and we
2156                  * can't.  Hence, no choice but to drop.
2157                  */
2158                 duprintf("Dropping evil ICMP tinygram.\n");
2159                 par->hotdrop = true;
2160                 return false;
2161         }
2162
2163         return icmp_type_code_match(icmpinfo->type,
2164                                     icmpinfo->code[0],
2165                                     icmpinfo->code[1],
2166                                     ic->type, ic->code,
2167                                     !!(icmpinfo->invflags&IPT_ICMP_INV));
2168 }
2169
2170 static int icmp_checkentry(const struct xt_mtchk_param *par)
2171 {
2172         const struct ipt_icmp *icmpinfo = par->matchinfo;
2173
2174         /* Must specify no unknown invflags */
2175         return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
2176 }
2177
2178 static struct xt_target ipt_builtin_tg[] __read_mostly = {
2179         {
2180                 .name             = XT_STANDARD_TARGET,
2181                 .targetsize       = sizeof(int),
2182                 .family           = NFPROTO_IPV4,
2183 #ifdef CONFIG_COMPAT
2184                 .compatsize       = sizeof(compat_int_t),
2185                 .compat_from_user = compat_standard_from_user,
2186                 .compat_to_user   = compat_standard_to_user,
2187 #endif
2188         },
2189         {
2190                 .name             = XT_ERROR_TARGET,
2191                 .target           = ipt_error,
2192                 .targetsize       = XT_FUNCTION_MAXNAMELEN,
2193                 .family           = NFPROTO_IPV4,
2194         },
2195 };
2196
2197 static struct nf_sockopt_ops ipt_sockopts = {
2198         .pf             = PF_INET,
2199         .set_optmin     = IPT_BASE_CTL,
2200         .set_optmax     = IPT_SO_SET_MAX+1,
2201         .set            = do_ipt_set_ctl,
2202 #ifdef CONFIG_COMPAT
2203         .compat_set     = compat_do_ipt_set_ctl,
2204 #endif
2205         .get_optmin     = IPT_BASE_CTL,
2206         .get_optmax     = IPT_SO_GET_MAX+1,
2207         .get            = do_ipt_get_ctl,
2208 #ifdef CONFIG_COMPAT
2209         .compat_get     = compat_do_ipt_get_ctl,
2210 #endif
2211         .owner          = THIS_MODULE,
2212 };
2213
2214 static struct xt_match ipt_builtin_mt[] __read_mostly = {
2215         {
2216                 .name       = "icmp",
2217                 .match      = icmp_match,
2218                 .matchsize  = sizeof(struct ipt_icmp),
2219                 .checkentry = icmp_checkentry,
2220                 .proto      = IPPROTO_ICMP,
2221                 .family     = NFPROTO_IPV4,
2222         },
2223 };
2224
2225 static int __net_init ip_tables_net_init(struct net *net)
2226 {
2227         return xt_proto_init(net, NFPROTO_IPV4);
2228 }
2229
2230 static void __net_exit ip_tables_net_exit(struct net *net)
2231 {
2232         xt_proto_fini(net, NFPROTO_IPV4);
2233 }
2234
2235 static struct pernet_operations ip_tables_net_ops = {
2236         .init = ip_tables_net_init,
2237         .exit = ip_tables_net_exit,
2238 };
2239
2240 static int __init ip_tables_init(void)
2241 {
2242         int ret;
2243
2244         ret = register_pernet_subsys(&ip_tables_net_ops);
2245         if (ret < 0)
2246                 goto err1;
2247
2248         /* Noone else will be downing sem now, so we won't sleep */
2249         ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2250         if (ret < 0)
2251                 goto err2;
2252         ret = xt_register_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2253         if (ret < 0)
2254                 goto err4;
2255
2256         /* Register setsockopt */
2257         ret = nf_register_sockopt(&ipt_sockopts);
2258         if (ret < 0)
2259                 goto err5;
2260
2261         pr_info("(C) 2000-2006 Netfilter Core Team\n");
2262         return 0;
2263
2264 err5:
2265         xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2266 err4:
2267         xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2268 err2:
2269         unregister_pernet_subsys(&ip_tables_net_ops);
2270 err1:
2271         return ret;
2272 }
2273
2274 static void __exit ip_tables_fini(void)
2275 {
2276         nf_unregister_sockopt(&ipt_sockopts);
2277
2278         xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
2279         xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
2280         unregister_pernet_subsys(&ip_tables_net_ops);
2281 }
2282
2283 EXPORT_SYMBOL(ipt_register_table);
2284 EXPORT_SYMBOL(ipt_unregister_table);
2285 EXPORT_SYMBOL(ipt_do_table);
2286 module_init(ip_tables_init);
2287 module_exit(ip_tables_fini);