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