607f89f16b76214e7ca851ffd3b8b6b817fd0384
[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)                                         \
55 do {                                                            \
56         if (!(x))                                               \
57                 printk("IP_NF_ASSERT: %s:%s:%u\n",              \
58                        __func__, __FILE__, __LINE__);   \
59 } while(0)
60 #else
61 #define IP_NF_ASSERT(x)
62 #endif
63
64 #if 0
65 /* All the better to debug you with... */
66 #define static
67 #define inline
68 #endif
69
70 void *ipt_alloc_initial_table(const struct xt_table *info)
71 {
72         return xt_alloc_initial_table(ipt, IPT);
73 }
74 EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);
75
76 /*
77    We keep a set of rules for each CPU, so we can avoid write-locking
78    them in the softirq when updating the counters and therefore
79    only need to read-lock in the softirq; doing a write_lock_bh() in user
80    context stops packets coming through and allows user context to read
81    the counters or update the rules.
82
83    Hence the start of any table is given by get_table() below.  */
84
85 /* Returns whether matches rule or not. */
86 /* Performance critical - called for every packet */
87 static inline bool
88 ip_packet_match(const struct iphdr *ip,
89                 const char *indev,
90                 const char *outdev,
91                 const struct ipt_ip *ipinfo,
92                 int isfrag)
93 {
94         unsigned long ret;
95
96 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
97
98         if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
99                   IPT_INV_SRCIP) ||
100             FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
101                   IPT_INV_DSTIP)) {
102                 dprintf("Source or dest mismatch.\n");
103
104                 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
105                         &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
106                         ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
107                 dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
108                         &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
109                         ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
110                 return false;
111         }
112
113         ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
114
115         if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
116                 dprintf("VIA in mismatch (%s vs %s).%s\n",
117                         indev, ipinfo->iniface,
118                         ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
119                 return false;
120         }
121
122         ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
123
124         if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
125                 dprintf("VIA out mismatch (%s vs %s).%s\n",
126                         outdev, ipinfo->outiface,
127                         ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
128                 return false;
129         }
130
131         /* Check specific protocol */
132         if (ipinfo->proto &&
133             FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
134                 dprintf("Packet protocol %hi does not match %hi.%s\n",
135                         ip->protocol, ipinfo->proto,
136                         ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
137                 return false;
138         }
139
140         /* If we have a fragment rule but the packet is not a fragment
141          * then we return zero */
142         if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
143                 dprintf("Fragment rule but not fragment.%s\n",
144                         ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
145                 return false;
146         }
147
148         return true;
149 }
150
151 static bool
152 ip_checkentry(const struct ipt_ip *ip)
153 {
154         if (ip->flags & ~IPT_F_MASK) {
155                 duprintf("Unknown flag bits set: %08X\n",
156                          ip->flags & ~IPT_F_MASK);
157                 return false;
158         }
159         if (ip->invflags & ~IPT_INV_MASK) {
160                 duprintf("Unknown invflag bits set: %08X\n",
161                          ip->invflags & ~IPT_INV_MASK);
162                 return false;
163         }
164         return true;
165 }
166
167 static unsigned int
168 ipt_error(struct sk_buff *skb, const struct xt_action_param *par)
169 {
170         if (net_ratelimit())
171                 pr_info("error: `%s'\n", (const char *)par->targinfo);
172
173         return NF_DROP;
174 }
175
176 /* Performance critical */
177 static inline struct ipt_entry *
178 get_entry(const void *base, unsigned int offset)
179 {
180         return (struct ipt_entry *)(base + offset);
181 }
182
183 /* All zeroes == unconditional rule. */
184 /* Mildly perf critical (only if packet tracing is on) */
185 static inline bool unconditional(const struct ipt_ip *ip)
186 {
187         static const struct ipt_ip uncond;
188
189         return memcmp(ip, &uncond, sizeof(uncond)) == 0;
190 #undef FWINV
191 }
192
193 /* for const-correctness */
194 static inline const struct ipt_entry_target *
195 ipt_get_target_c(const struct ipt_entry *e)
196 {
197         return ipt_get_target((struct ipt_entry *)e);
198 }
199
200 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
201     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
202 static const char *const hooknames[] = {
203         [NF_INET_PRE_ROUTING]           = "PREROUTING",
204         [NF_INET_LOCAL_IN]              = "INPUT",
205         [NF_INET_FORWARD]               = "FORWARD",
206         [NF_INET_LOCAL_OUT]             = "OUTPUT",
207         [NF_INET_POST_ROUTING]          = "POSTROUTING",
208 };
209
210 enum nf_ip_trace_comments {
211         NF_IP_TRACE_COMMENT_RULE,
212         NF_IP_TRACE_COMMENT_RETURN,
213         NF_IP_TRACE_COMMENT_POLICY,
214 };
215
216 static const char *const comments[] = {
217         [NF_IP_TRACE_COMMENT_RULE]      = "rule",
218         [NF_IP_TRACE_COMMENT_RETURN]    = "return",
219         [NF_IP_TRACE_COMMENT_POLICY]    = "policy",
220 };
221
222 static struct nf_loginfo trace_loginfo = {
223         .type = NF_LOG_TYPE_LOG,
224         .u = {
225                 .log = {
226                         .level = 4,
227                         .logflags = NF_LOG_MASK,
228                 },
229         },
230 };
231
232 /* Mildly perf critical (only if packet tracing is on) */
233 static inline int
234 get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e,
235                       const char *hookname, const char **chainname,
236                       const char **comment, unsigned int *rulenum)
237 {
238         const struct ipt_standard_target *t = (void *)ipt_get_target_c(s);
239
240         if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
241                 /* Head of user chain: ERROR target with chainname */
242                 *chainname = t->target.data;
243                 (*rulenum) = 0;
244         } else if (s == e) {
245                 (*rulenum)++;
246
247                 if (s->target_offset == sizeof(struct ipt_entry) &&
248                     strcmp(t->target.u.kernel.target->name,
249                            IPT_STANDARD_TARGET) == 0 &&
250                    t->verdict < 0 &&
251                    unconditional(&s->ip)) {
252                         /* Tail of chains: STANDARD target (return/policy) */
253                         *comment = *chainname == hookname
254                                 ? comments[NF_IP_TRACE_COMMENT_POLICY]
255                                 : comments[NF_IP_TRACE_COMMENT_RETURN];
256                 }
257                 return 1;
258         } else
259                 (*rulenum)++;
260
261         return 0;
262 }
263
264 static void trace_packet(const struct sk_buff *skb,
265                          unsigned int hook,
266                          const struct net_device *in,
267                          const struct net_device *out,
268                          const char *tablename,
269                          const struct xt_table_info *private,
270                          const struct ipt_entry *e)
271 {
272         const void *table_base;
273         const struct ipt_entry *root;
274         const char *hookname, *chainname, *comment;
275         const struct ipt_entry *iter;
276         unsigned int rulenum = 0;
277
278         table_base = private->entries[smp_processor_id()];
279         root = get_entry(table_base, private->hook_entry[hook]);
280
281         hookname = chainname = hooknames[hook];
282         comment = comments[NF_IP_TRACE_COMMENT_RULE];
283
284         xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
285                 if (get_chainname_rulenum(iter, e, hookname,
286                     &chainname, &comment, &rulenum) != 0)
287                         break;
288
289         nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
290                       "TRACE: %s:%s:%s:%u ",
291                       tablename, chainname, comment, rulenum);
292 }
293 #endif
294
295 static inline __pure
296 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
297 {
298         return (void *)entry + entry->next_offset;
299 }
300
301 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
302 unsigned int
303 ipt_do_table(struct sk_buff *skb,
304              unsigned int hook,
305              const struct net_device *in,
306              const struct net_device *out,
307              struct xt_table *table)
308 {
309         static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
310         const struct iphdr *ip;
311         /* Initializing verdict to NF_DROP keeps gcc happy. */
312         unsigned int verdict = NF_DROP;
313         const char *indev, *outdev;
314         const void *table_base;
315         struct ipt_entry *e, **jumpstack;
316         unsigned int *stackptr, origptr, cpu;
317         const struct xt_table_info *private;
318         struct xt_action_param acpar;
319
320         /* Initialization */
321         ip = ip_hdr(skb);
322         indev = in ? in->name : nulldevname;
323         outdev = out ? out->name : nulldevname;
324         /* We handle fragments by dealing with the first fragment as
325          * if it was a normal packet.  All other fragments are treated
326          * normally, except that they will NEVER match rules that ask
327          * things we don't know, ie. tcp syn flag or ports).  If the
328          * rule is also a fragment-specific rule, non-fragments won't
329          * match it. */
330         acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
331         acpar.thoff   = ip_hdrlen(skb);
332         acpar.hotdrop = false;
333         acpar.in      = in;
334         acpar.out     = out;
335         acpar.family  = NFPROTO_IPV4;
336         acpar.hooknum = hook;
337
338         IP_NF_ASSERT(table->valid_hooks & (1 << hook));
339         xt_info_rdlock_bh();
340         private = table->private;
341         cpu        = smp_processor_id();
342         table_base = private->entries[cpu];
343         jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
344         stackptr   = &private->stackptr[cpu];
345         origptr    = *stackptr;
346
347         e = get_entry(table_base, private->hook_entry[hook]);
348
349         pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n",
350                  table->name, hook, origptr,
351                  get_entry(table_base, private->underflow[hook]));
352
353         do {
354                 const struct ipt_entry_target *t;
355                 const struct xt_entry_match *ematch;
356
357                 IP_NF_ASSERT(e);
358                 if (!ip_packet_match(ip, indev, outdev,
359                     &e->ip, acpar.fragoff)) {
360  no_match:
361                         e = ipt_next_entry(e);
362                         continue;
363                 }
364
365                 xt_ematch_foreach(ematch, e) {
366                         acpar.match     = ematch->u.kernel.match;
367                         acpar.matchinfo = ematch->data;
368                         if (!acpar.match->match(skb, &acpar))
369                                 goto no_match;
370                 }
371
372                 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
373
374                 t = ipt_get_target(e);
375                 IP_NF_ASSERT(t->u.kernel.target);
376
377 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
378     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
379                 /* The packet is traced: log it */
380                 if (unlikely(skb->nf_trace))
381                         trace_packet(skb, hook, in, out,
382                                      table->name, private, e);
383 #endif
384                 /* Standard target? */
385                 if (!t->u.kernel.target->target) {
386                         int v;
387
388                         v = ((struct ipt_standard_target *)t)->verdict;
389                         if (v < 0) {
390                                 /* Pop from stack? */
391                                 if (v != IPT_RETURN) {
392                                         verdict = (unsigned)(-v) - 1;
393                                         break;
394                                 }
395                                 if (*stackptr == 0) {
396                                         e = get_entry(table_base,
397                                             private->underflow[hook]);
398                                         pr_debug("Underflow (this is normal) "
399                                                  "to %p\n", e);
400                                 } else {
401                                         e = jumpstack[--*stackptr];
402                                         pr_debug("Pulled %p out from pos %u\n",
403                                                  e, *stackptr);
404                                         e = ipt_next_entry(e);
405                                 }
406                                 continue;
407                         }
408                         if (table_base + v != ipt_next_entry(e) &&
409                             !(e->ip.flags & IPT_F_GOTO)) {
410                                 if (*stackptr >= private->stacksize) {
411                                         verdict = NF_DROP;
412                                         break;
413                                 }
414                                 jumpstack[(*stackptr)++] = e;
415                                 pr_debug("Pushed %p into pos %u\n",
416                                          e, *stackptr - 1);
417                         }
418
419                         e = get_entry(table_base, v);
420                         continue;
421                 }
422
423                 acpar.target   = t->u.kernel.target;
424                 acpar.targinfo = t->data;
425
426                 verdict = t->u.kernel.target->target(skb, &acpar);
427                 /* Target might have changed stuff. */
428                 ip = ip_hdr(skb);
429                 if (verdict == IPT_CONTINUE)
430                         e = ipt_next_entry(e);
431                 else
432                         /* Verdict */
433                         break;
434         } while (!acpar.hotdrop);
435         xt_info_rdunlock_bh();
436         pr_debug("Exiting %s; resetting sp from %u to %u\n",
437                  __func__, *stackptr, origptr);
438         *stackptr = origptr;
439 #ifdef DEBUG_ALLOW_ALL
440         return NF_ACCEPT;
441 #else
442         if (acpar.hotdrop)
443                 return NF_DROP;
444         else return verdict;
445 #endif
446 }
447
448 /* Figures out from what hook each rule can be called: returns 0 if
449    there are loops.  Puts hook bitmask in comefrom. */
450 static int
451 mark_source_chains(const struct xt_table_info *newinfo,
452                    unsigned int valid_hooks, void *entry0)
453 {
454         unsigned int hook;
455
456         /* No recursion; use packet counter to save back ptrs (reset
457            to 0 as we leave), and comefrom to save source hook bitmask */
458         for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
459                 unsigned int pos = newinfo->hook_entry[hook];
460                 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
461
462                 if (!(valid_hooks & (1 << hook)))
463                         continue;
464
465                 /* Set initial back pointer. */
466                 e->counters.pcnt = pos;
467
468                 for (;;) {
469                         const struct ipt_standard_target *t
470                                 = (void *)ipt_get_target_c(e);
471                         int visited = e->comefrom & (1 << hook);
472
473                         if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
474                                 printk("iptables: loop hook %u pos %u %08X.\n",
475                                        hook, pos, e->comefrom);
476                                 return 0;
477                         }
478                         e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
479
480                         /* Unconditional return/END. */
481                         if ((e->target_offset == sizeof(struct ipt_entry) &&
482                              (strcmp(t->target.u.user.name,
483                                      IPT_STANDARD_TARGET) == 0) &&
484                              t->verdict < 0 && unconditional(&e->ip)) ||
485                             visited) {
486                                 unsigned int oldpos, size;
487
488                                 if ((strcmp(t->target.u.user.name,
489                                             IPT_STANDARD_TARGET) == 0) &&
490                                     t->verdict < -NF_MAX_VERDICT - 1) {
491                                         duprintf("mark_source_chains: bad "
492                                                 "negative verdict (%i)\n",
493                                                                 t->verdict);
494                                         return 0;
495                                 }
496
497                                 /* Return: backtrack through the last
498                                    big jump. */
499                                 do {
500                                         e->comefrom ^= (1<<NF_INET_NUMHOOKS);
501 #ifdef DEBUG_IP_FIREWALL_USER
502                                         if (e->comefrom
503                                             & (1 << NF_INET_NUMHOOKS)) {
504                                                 duprintf("Back unset "
505                                                          "on hook %u "
506                                                          "rule %u\n",
507                                                          hook, pos);
508                                         }
509 #endif
510                                         oldpos = pos;
511                                         pos = e->counters.pcnt;
512                                         e->counters.pcnt = 0;
513
514                                         /* We're at the start. */
515                                         if (pos == oldpos)
516                                                 goto next;
517
518                                         e = (struct ipt_entry *)
519                                                 (entry0 + pos);
520                                 } while (oldpos == pos + e->next_offset);
521
522                                 /* Move along one */
523                                 size = e->next_offset;
524                                 e = (struct ipt_entry *)
525                                         (entry0 + pos + size);
526                                 e->counters.pcnt = pos;
527                                 pos += size;
528                         } else {
529                                 int newpos = t->verdict;
530
531                                 if (strcmp(t->target.u.user.name,
532                                            IPT_STANDARD_TARGET) == 0 &&
533                                     newpos >= 0) {
534                                         if (newpos > newinfo->size -
535                                                 sizeof(struct ipt_entry)) {
536                                                 duprintf("mark_source_chains: "
537                                                         "bad verdict (%i)\n",
538                                                                 newpos);
539                                                 return 0;
540                                         }
541                                         /* This a jump; chase it. */
542                                         duprintf("Jump rule %u -> %u\n",
543                                                  pos, newpos);
544                                 } else {
545                                         /* ... this is a fallthru */
546                                         newpos = pos + e->next_offset;
547                                 }
548                                 e = (struct ipt_entry *)
549                                         (entry0 + newpos);
550                                 e->counters.pcnt = pos;
551                                 pos = newpos;
552                         }
553                 }
554                 next:
555                 duprintf("Finished chain %u\n", hook);
556         }
557         return 1;
558 }
559
560 static void cleanup_match(struct ipt_entry_match *m, struct net *net)
561 {
562         struct xt_mtdtor_param par;
563
564         par.net       = net;
565         par.match     = m->u.kernel.match;
566         par.matchinfo = m->data;
567         par.family    = NFPROTO_IPV4;
568         if (par.match->destroy != NULL)
569                 par.match->destroy(&par);
570         module_put(par.match->me);
571 }
572
573 static int
574 check_entry(const struct ipt_entry *e, const char *name)
575 {
576         const struct ipt_entry_target *t;
577
578         if (!ip_checkentry(&e->ip)) {
579                 duprintf("ip check failed %p %s.\n", e, par->match->name);
580                 return -EINVAL;
581         }
582
583         if (e->target_offset + sizeof(struct ipt_entry_target) >
584             e->next_offset)
585                 return -EINVAL;
586
587         t = ipt_get_target_c(e);
588         if (e->target_offset + t->u.target_size > e->next_offset)
589                 return -EINVAL;
590
591         return 0;
592 }
593
594 static int
595 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
596 {
597         const struct ipt_ip *ip = par->entryinfo;
598         int ret;
599
600         par->match     = m->u.kernel.match;
601         par->matchinfo = m->data;
602
603         ret = xt_check_match(par, m->u.match_size - sizeof(*m),
604               ip->proto, ip->invflags & IPT_INV_PROTO);
605         if (ret < 0) {
606                 duprintf("check failed for `%s'.\n", par->match->name);
607                 return ret;
608         }
609         return 0;
610 }
611
612 static int
613 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
614 {
615         struct xt_match *match;
616         int ret;
617
618         match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
619                                       m->u.user.revision);
620         if (IS_ERR(match)) {
621                 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
622                 return PTR_ERR(match);
623         }
624         m->u.kernel.match = match;
625
626         ret = check_match(m, par);
627         if (ret)
628                 goto err;
629
630         return 0;
631 err:
632         module_put(m->u.kernel.match->me);
633         return ret;
634 }
635
636 static int check_target(struct ipt_entry *e, struct net *net, const char *name)
637 {
638         struct ipt_entry_target *t = ipt_get_target(e);
639         struct xt_tgchk_param par = {
640                 .net       = net,
641                 .table     = name,
642                 .entryinfo = e,
643                 .target    = t->u.kernel.target,
644                 .targinfo  = t->data,
645                 .hook_mask = e->comefrom,
646                 .family    = NFPROTO_IPV4,
647         };
648         int ret;
649
650         ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
651               e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
652         if (ret < 0) {
653                 duprintf("check failed for `%s'.\n",
654                          t->u.kernel.target->name);
655                 return ret;
656         }
657         return 0;
658 }
659
660 static int
661 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
662                  unsigned int size)
663 {
664         struct ipt_entry_target *t;
665         struct xt_target *target;
666         int ret;
667         unsigned int j;
668         struct xt_mtchk_param mtpar;
669         struct xt_entry_match *ematch;
670
671         ret = check_entry(e, name);
672         if (ret)
673                 return ret;
674
675         j = 0;
676         mtpar.net       = net;
677         mtpar.table     = name;
678         mtpar.entryinfo = &e->ip;
679         mtpar.hook_mask = e->comefrom;
680         mtpar.family    = NFPROTO_IPV4;
681         xt_ematch_foreach(ematch, e) {
682                 ret = find_check_match(ematch, &mtpar);
683                 if (ret != 0)
684                         goto cleanup_matches;
685                 ++j;
686         }
687
688         t = ipt_get_target(e);
689         target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
690                                         t->u.user.revision);
691         if (IS_ERR(target)) {
692                 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
693                 ret = PTR_ERR(target);
694                 goto cleanup_matches;
695         }
696         t->u.kernel.target = target;
697
698         ret = check_target(e, net, name);
699         if (ret)
700                 goto err;
701         return 0;
702  err:
703         module_put(t->u.kernel.target->me);
704  cleanup_matches:
705         xt_ematch_foreach(ematch, e) {
706                 if (j-- == 0)
707                         break;
708                 cleanup_match(ematch, net);
709         }
710         return ret;
711 }
712
713 static bool check_underflow(const struct ipt_entry *e)
714 {
715         const struct ipt_entry_target *t;
716         unsigned int verdict;
717
718         if (!unconditional(&e->ip))
719                 return false;
720         t = ipt_get_target_c(e);
721         if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
722                 return false;
723         verdict = ((struct ipt_standard_target *)t)->verdict;
724         verdict = -verdict - 1;
725         return verdict == NF_DROP || verdict == NF_ACCEPT;
726 }
727
728 static int
729 check_entry_size_and_hooks(struct ipt_entry *e,
730                            struct xt_table_info *newinfo,
731                            const unsigned char *base,
732                            const unsigned char *limit,
733                            const unsigned int *hook_entries,
734                            const unsigned int *underflows,
735                            unsigned int valid_hooks)
736 {
737         unsigned int h;
738
739         if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
740             (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
741                 duprintf("Bad offset %p\n", e);
742                 return -EINVAL;
743         }
744
745         if (e->next_offset
746             < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
747                 duprintf("checking: element %p size %u\n",
748                          e, e->next_offset);
749                 return -EINVAL;
750         }
751
752         /* Check hooks & underflows */
753         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
754                 if (!(valid_hooks & (1 << h)))
755                         continue;
756                 if ((unsigned char *)e - base == hook_entries[h])
757                         newinfo->hook_entry[h] = hook_entries[h];
758                 if ((unsigned char *)e - base == underflows[h]) {
759                         if (!check_underflow(e)) {
760                                 pr_err("Underflows must be unconditional and "
761                                        "use the STANDARD target with "
762                                        "ACCEPT/DROP\n");
763                                 return -EINVAL;
764                         }
765                         newinfo->underflow[h] = underflows[h];
766                 }
767         }
768
769         /* Clear counters and comefrom */
770         e->counters = ((struct xt_counters) { 0, 0 });
771         e->comefrom = 0;
772         return 0;
773 }
774
775 static void
776 cleanup_entry(struct ipt_entry *e, struct net *net)
777 {
778         struct xt_tgdtor_param par;
779         struct ipt_entry_target *t;
780         struct xt_entry_match *ematch;
781
782         /* Cleanup all matches */
783         xt_ematch_foreach(ematch, e)
784                 cleanup_match(ematch, net);
785         t = ipt_get_target(e);
786
787         par.net      = net;
788         par.target   = t->u.kernel.target;
789         par.targinfo = t->data;
790         par.family   = NFPROTO_IPV4;
791         if (par.target->destroy != NULL)
792                 par.target->destroy(&par);
793         module_put(par.target->me);
794 }
795
796 /* Checks and translates the user-supplied table segment (held in
797    newinfo) */
798 static int
799 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
800                 const struct ipt_replace *repl)
801 {
802         struct ipt_entry *iter;
803         unsigned int i;
804         int ret = 0;
805
806         newinfo->size = repl->size;
807         newinfo->number = repl->num_entries;
808
809         /* Init all hooks to impossible value. */
810         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
811                 newinfo->hook_entry[i] = 0xFFFFFFFF;
812                 newinfo->underflow[i] = 0xFFFFFFFF;
813         }
814
815         duprintf("translate_table: size %u\n", newinfo->size);
816         i = 0;
817         /* Walk through entries, checking offsets. */
818         xt_entry_foreach(iter, entry0, newinfo->size) {
819                 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
820                                                  entry0 + repl->size,
821                                                  repl->hook_entry,
822                                                  repl->underflow,
823                                                  repl->valid_hooks);
824                 if (ret != 0)
825                         return ret;
826                 ++i;
827                 if (strcmp(ipt_get_target(iter)->u.user.name,
828                     XT_ERROR_TARGET) == 0)
829                         ++newinfo->stacksize;
830         }
831
832         if (i != repl->num_entries) {
833                 duprintf("translate_table: %u not %u entries\n",
834                          i, repl->num_entries);
835                 return -EINVAL;
836         }
837
838         /* Check hooks all assigned */
839         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
840                 /* Only hooks which are valid */
841                 if (!(repl->valid_hooks & (1 << i)))
842                         continue;
843                 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
844                         duprintf("Invalid hook entry %u %u\n",
845                                  i, repl->hook_entry[i]);
846                         return -EINVAL;
847                 }
848                 if (newinfo->underflow[i] == 0xFFFFFFFF) {
849                         duprintf("Invalid underflow %u %u\n",
850                                  i, repl->underflow[i]);
851                         return -EINVAL;
852                 }
853         }
854
855         if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
856                 return -ELOOP;
857
858         /* Finally, each sanity check must pass */
859         i = 0;
860         xt_entry_foreach(iter, entry0, newinfo->size) {
861                 ret = find_check_entry(iter, net, repl->name, repl->size);
862                 if (ret != 0)
863                         break;
864                 ++i;
865         }
866
867         if (ret != 0) {
868                 xt_entry_foreach(iter, entry0, newinfo->size) {
869                         if (i-- == 0)
870                                 break;
871                         cleanup_entry(iter, net);
872                 }
873                 return ret;
874         }
875
876         /* And one copy for every other CPU */
877         for_each_possible_cpu(i) {
878                 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
879                         memcpy(newinfo->entries[i], entry0, newinfo->size);
880         }
881
882         return ret;
883 }
884
885 static void
886 get_counters(const struct xt_table_info *t,
887              struct xt_counters counters[])
888 {
889         struct ipt_entry *iter;
890         unsigned int cpu;
891         unsigned int i;
892         unsigned int curcpu;
893
894         /* Instead of clearing (by a previous call to memset())
895          * the counters and using adds, we set the counters
896          * with data used by 'current' CPU.
897          *
898          * Bottom half has to be disabled to prevent deadlock
899          * if new softirq were to run and call ipt_do_table
900          */
901         local_bh_disable();
902         curcpu = smp_processor_id();
903
904         i = 0;
905         xt_entry_foreach(iter, t->entries[curcpu], t->size) {
906                 SET_COUNTER(counters[i], iter->counters.bcnt,
907                             iter->counters.pcnt);
908                 ++i;
909         }
910
911         for_each_possible_cpu(cpu) {
912                 if (cpu == curcpu)
913                         continue;
914                 i = 0;
915                 xt_info_wrlock(cpu);
916                 xt_entry_foreach(iter, t->entries[cpu], t->size) {
917                         ADD_COUNTER(counters[i], iter->counters.bcnt,
918                                     iter->counters.pcnt);
919                         ++i; /* macro does multi eval of i */
920                 }
921                 xt_info_wrunlock(cpu);
922         }
923         local_bh_enable();
924 }
925
926 static struct xt_counters *alloc_counters(const struct xt_table *table)
927 {
928         unsigned int countersize;
929         struct xt_counters *counters;
930         const struct xt_table_info *private = table->private;
931
932         /* We need atomic snapshot of counters: rest doesn't change
933            (other than comefrom, which userspace doesn't care
934            about). */
935         countersize = sizeof(struct xt_counters) * private->number;
936         counters = vmalloc_node(countersize, numa_node_id());
937
938         if (counters == NULL)
939                 return ERR_PTR(-ENOMEM);
940
941         get_counters(private, counters);
942
943         return counters;
944 }
945
946 static int
947 copy_entries_to_user(unsigned int total_size,
948                      const struct xt_table *table,
949                      void __user *userptr)
950 {
951         unsigned int off, num;
952         const struct ipt_entry *e;
953         struct xt_counters *counters;
954         const struct xt_table_info *private = table->private;
955         int ret = 0;
956         const void *loc_cpu_entry;
957
958         counters = alloc_counters(table);
959         if (IS_ERR(counters))
960                 return PTR_ERR(counters);
961
962         /* choose the copy that is on our node/cpu, ...
963          * This choice is lazy (because current thread is
964          * allowed to migrate to another cpu)
965          */
966         loc_cpu_entry = private->entries[raw_smp_processor_id()];
967         if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
968                 ret = -EFAULT;
969                 goto free_counters;
970         }
971
972         /* FIXME: use iterator macros --RR */
973         /* ... then go back and fix counters and names */
974         for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
975                 unsigned int i;
976                 const struct ipt_entry_match *m;
977                 const struct ipt_entry_target *t;
978
979                 e = (struct ipt_entry *)(loc_cpu_entry + off);
980                 if (copy_to_user(userptr + off
981                                  + offsetof(struct ipt_entry, counters),
982                                  &counters[num],
983                                  sizeof(counters[num])) != 0) {
984                         ret = -EFAULT;
985                         goto free_counters;
986                 }
987
988                 for (i = sizeof(struct ipt_entry);
989                      i < e->target_offset;
990                      i += m->u.match_size) {
991                         m = (void *)e + i;
992
993                         if (copy_to_user(userptr + off + i
994                                          + offsetof(struct ipt_entry_match,
995                                                     u.user.name),
996                                          m->u.kernel.match->name,
997                                          strlen(m->u.kernel.match->name)+1)
998                             != 0) {
999                                 ret = -EFAULT;
1000                                 goto free_counters;
1001                         }
1002                 }
1003
1004                 t = ipt_get_target_c(e);
1005                 if (copy_to_user(userptr + off + e->target_offset
1006                                  + offsetof(struct ipt_entry_target,
1007                                             u.user.name),
1008                                  t->u.kernel.target->name,
1009                                  strlen(t->u.kernel.target->name)+1) != 0) {
1010                         ret = -EFAULT;
1011                         goto free_counters;
1012                 }
1013         }
1014
1015  free_counters:
1016         vfree(counters);
1017         return ret;
1018 }
1019
1020 #ifdef CONFIG_COMPAT
1021 static void compat_standard_from_user(void *dst, const void *src)
1022 {
1023         int v = *(compat_int_t *)src;
1024
1025         if (v > 0)
1026                 v += xt_compat_calc_jump(AF_INET, v);
1027         memcpy(dst, &v, sizeof(v));
1028 }
1029
1030 static int compat_standard_to_user(void __user *dst, const void *src)
1031 {
1032         compat_int_t cv = *(int *)src;
1033
1034         if (cv > 0)
1035                 cv -= xt_compat_calc_jump(AF_INET, cv);
1036         return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1037 }
1038
1039 static int compat_calc_entry(const struct ipt_entry *e,
1040                              const struct xt_table_info *info,
1041                              const void *base, struct xt_table_info *newinfo)
1042 {
1043         const struct xt_entry_match *ematch;
1044         const struct ipt_entry_target *t;
1045         unsigned int entry_offset;
1046         int off, i, ret;
1047
1048         off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1049         entry_offset = (void *)e - base;
1050         xt_ematch_foreach(ematch, e)
1051                 off += xt_compat_match_offset(ematch->u.kernel.match);
1052         t = ipt_get_target_c(e);
1053         off += xt_compat_target_offset(t->u.kernel.target);
1054         newinfo->size -= off;
1055         ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1056         if (ret)
1057                 return ret;
1058
1059         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1060                 if (info->hook_entry[i] &&
1061                     (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1062                         newinfo->hook_entry[i] -= off;
1063                 if (info->underflow[i] &&
1064                     (e < (struct ipt_entry *)(base + info->underflow[i])))
1065                         newinfo->underflow[i] -= off;
1066         }
1067         return 0;
1068 }
1069
1070 static int compat_table_info(const struct xt_table_info *info,
1071                              struct xt_table_info *newinfo)
1072 {
1073         struct ipt_entry *iter;
1074         void *loc_cpu_entry;
1075         int ret;
1076
1077         if (!newinfo || !info)
1078                 return -EINVAL;
1079
1080         /* we dont care about newinfo->entries[] */
1081         memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1082         newinfo->initial_entries = 0;
1083         loc_cpu_entry = info->entries[raw_smp_processor_id()];
1084         xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1085                 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1086                 if (ret != 0)
1087                         return ret;
1088         }
1089         return 0;
1090 }
1091 #endif
1092
1093 static int get_info(struct net *net, void __user *user,
1094                     const int *len, int compat)
1095 {
1096         char name[IPT_TABLE_MAXNAMELEN];
1097         struct xt_table *t;
1098         int ret;
1099
1100         if (*len != sizeof(struct ipt_getinfo)) {
1101                 duprintf("length %u != %zu\n", *len,
1102                          sizeof(struct ipt_getinfo));
1103                 return -EINVAL;
1104         }
1105
1106         if (copy_from_user(name, user, sizeof(name)) != 0)
1107                 return -EFAULT;
1108
1109         name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1110 #ifdef CONFIG_COMPAT
1111         if (compat)
1112                 xt_compat_lock(AF_INET);
1113 #endif
1114         t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1115                                     "iptable_%s", name);
1116         if (t && !IS_ERR(t)) {
1117                 struct ipt_getinfo info;
1118                 const struct xt_table_info *private = t->private;
1119 #ifdef CONFIG_COMPAT
1120                 struct xt_table_info tmp;
1121
1122                 if (compat) {
1123                         ret = compat_table_info(private, &tmp);
1124                         xt_compat_flush_offsets(AF_INET);
1125                         private = &tmp;
1126                 }
1127 #endif
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_node(len - size, numa_node_id());
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[IPT_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 ipt_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 ipt_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 ipt_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 ipt_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 ipt_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 ipt_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         }
1756         if (ret) {
1757                 /*
1758                  * The first i matches need cleanup_entry (calls ->destroy)
1759                  * because they had called ->check already. The other j-i
1760                  * entries need only release.
1761                  */
1762                 int skip = i;
1763                 j -= i;
1764                 xt_entry_foreach(iter0, entry0, newinfo->size) {
1765                         if (skip-- > 0)
1766                                 continue;
1767                         if (j-- == 0)
1768                                 break;
1769                         compat_release_entry(iter0);
1770                 }
1771                 xt_entry_foreach(iter1, entry1, newinfo->size) {
1772                         if (i-- == 0)
1773                                 break;
1774                         cleanup_entry(iter1, net);
1775                 }
1776                 xt_free_table_info(newinfo);
1777                 return ret;
1778         }
1779
1780         /* And one copy for every other CPU */
1781         for_each_possible_cpu(i)
1782                 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1783                         memcpy(newinfo->entries[i], entry1, newinfo->size);
1784
1785         *pinfo = newinfo;
1786         *pentry0 = entry1;
1787         xt_free_table_info(info);
1788         return 0;
1789
1790 free_newinfo:
1791         xt_free_table_info(newinfo);
1792 out:
1793         xt_entry_foreach(iter0, entry0, total_size) {
1794                 if (j-- == 0)
1795                         break;
1796                 compat_release_entry(iter0);
1797         }
1798         return ret;
1799 out_unlock:
1800         xt_compat_flush_offsets(AF_INET);
1801         xt_compat_unlock(AF_INET);
1802         goto out;
1803 }
1804
1805 static int
1806 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1807 {
1808         int ret;
1809         struct compat_ipt_replace tmp;
1810         struct xt_table_info *newinfo;
1811         void *loc_cpu_entry;
1812         struct ipt_entry *iter;
1813
1814         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1815                 return -EFAULT;
1816
1817         /* overflow check */
1818         if (tmp.size >= INT_MAX / num_possible_cpus())
1819                 return -ENOMEM;
1820         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1821                 return -ENOMEM;
1822
1823         newinfo = xt_alloc_table_info(tmp.size);
1824         if (!newinfo)
1825                 return -ENOMEM;
1826
1827         /* choose the copy that is on our node/cpu */
1828         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1829         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1830                            tmp.size) != 0) {
1831                 ret = -EFAULT;
1832                 goto free_newinfo;
1833         }
1834
1835         ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1836                                      &newinfo, &loc_cpu_entry, tmp.size,
1837                                      tmp.num_entries, tmp.hook_entry,
1838                                      tmp.underflow);
1839         if (ret != 0)
1840                 goto free_newinfo;
1841
1842         duprintf("compat_do_replace: Translated table\n");
1843
1844         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1845                            tmp.num_counters, compat_ptr(tmp.counters));
1846         if (ret)
1847                 goto free_newinfo_untrans;
1848         return 0;
1849
1850  free_newinfo_untrans:
1851         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1852                 cleanup_entry(iter, net);
1853  free_newinfo:
1854         xt_free_table_info(newinfo);
1855         return ret;
1856 }
1857
1858 static int
1859 compat_do_ipt_set_ctl(struct sock *sk,  int cmd, void __user *user,
1860                       unsigned int len)
1861 {
1862         int ret;
1863
1864         if (!capable(CAP_NET_ADMIN))
1865                 return -EPERM;
1866
1867         switch (cmd) {
1868         case IPT_SO_SET_REPLACE:
1869                 ret = compat_do_replace(sock_net(sk), user, len);
1870                 break;
1871
1872         case IPT_SO_SET_ADD_COUNTERS:
1873                 ret = do_add_counters(sock_net(sk), user, len, 1);
1874                 break;
1875
1876         default:
1877                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
1878                 ret = -EINVAL;
1879         }
1880
1881         return ret;
1882 }
1883
1884 struct compat_ipt_get_entries {
1885         char name[IPT_TABLE_MAXNAMELEN];
1886         compat_uint_t size;
1887         struct compat_ipt_entry entrytable[0];
1888 };
1889
1890 static int
1891 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1892                             void __user *userptr)
1893 {
1894         struct xt_counters *counters;
1895         const struct xt_table_info *private = table->private;
1896         void __user *pos;
1897         unsigned int size;
1898         int ret = 0;
1899         const void *loc_cpu_entry;
1900         unsigned int i = 0;
1901         struct ipt_entry *iter;
1902
1903         counters = alloc_counters(table);
1904         if (IS_ERR(counters))
1905                 return PTR_ERR(counters);
1906
1907         /* choose the copy that is on our node/cpu, ...
1908          * This choice is lazy (because current thread is
1909          * allowed to migrate to another cpu)
1910          */
1911         loc_cpu_entry = private->entries[raw_smp_processor_id()];
1912         pos = userptr;
1913         size = total_size;
1914         xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1915                 ret = compat_copy_entry_to_user(iter, &pos,
1916                                                 &size, counters, i++);
1917                 if (ret != 0)
1918                         break;
1919         }
1920
1921         vfree(counters);
1922         return ret;
1923 }
1924
1925 static int
1926 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1927                    int *len)
1928 {
1929         int ret;
1930         struct compat_ipt_get_entries get;
1931         struct xt_table *t;
1932
1933         if (*len < sizeof(get)) {
1934                 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1935                 return -EINVAL;
1936         }
1937
1938         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1939                 return -EFAULT;
1940
1941         if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1942                 duprintf("compat_get_entries: %u != %zu\n",
1943                          *len, sizeof(get) + get.size);
1944                 return -EINVAL;
1945         }
1946
1947         xt_compat_lock(AF_INET);
1948         t = xt_find_table_lock(net, AF_INET, get.name);
1949         if (t && !IS_ERR(t)) {
1950                 const struct xt_table_info *private = t->private;
1951                 struct xt_table_info info;
1952                 duprintf("t->private->number = %u\n", private->number);
1953                 ret = compat_table_info(private, &info);
1954                 if (!ret && get.size == info.size) {
1955                         ret = compat_copy_entries_to_user(private->size,
1956                                                           t, uptr->entrytable);
1957                 } else if (!ret) {
1958                         duprintf("compat_get_entries: I've got %u not %u!\n",
1959                                  private->size, get.size);
1960                         ret = -EAGAIN;
1961                 }
1962                 xt_compat_flush_offsets(AF_INET);
1963                 module_put(t->me);
1964                 xt_table_unlock(t);
1965         } else
1966                 ret = t ? PTR_ERR(t) : -ENOENT;
1967
1968         xt_compat_unlock(AF_INET);
1969         return ret;
1970 }
1971
1972 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1973
1974 static int
1975 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1976 {
1977         int ret;
1978
1979         if (!capable(CAP_NET_ADMIN))
1980                 return -EPERM;
1981
1982         switch (cmd) {
1983         case IPT_SO_GET_INFO:
1984                 ret = get_info(sock_net(sk), user, len, 1);
1985                 break;
1986         case IPT_SO_GET_ENTRIES:
1987                 ret = compat_get_entries(sock_net(sk), user, len);
1988                 break;
1989         default:
1990                 ret = do_ipt_get_ctl(sk, cmd, user, len);
1991         }
1992         return ret;
1993 }
1994 #endif
1995
1996 static int
1997 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1998 {
1999         int ret;
2000
2001         if (!capable(CAP_NET_ADMIN))
2002                 return -EPERM;
2003
2004         switch (cmd) {
2005         case IPT_SO_SET_REPLACE:
2006                 ret = do_replace(sock_net(sk), user, len);
2007                 break;
2008
2009         case IPT_SO_SET_ADD_COUNTERS:
2010                 ret = do_add_counters(sock_net(sk), user, len, 0);
2011                 break;
2012
2013         default:
2014                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
2015                 ret = -EINVAL;
2016         }
2017
2018         return ret;
2019 }
2020
2021 static int
2022 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2023 {
2024         int ret;
2025
2026         if (!capable(CAP_NET_ADMIN))
2027                 return -EPERM;
2028
2029         switch (cmd) {
2030         case IPT_SO_GET_INFO:
2031                 ret = get_info(sock_net(sk), user, len, 0);
2032                 break;
2033
2034         case IPT_SO_GET_ENTRIES:
2035                 ret = get_entries(sock_net(sk), user, len);
2036                 break;
2037
2038         case IPT_SO_GET_REVISION_MATCH:
2039         case IPT_SO_GET_REVISION_TARGET: {
2040                 struct ipt_get_revision rev;
2041                 int target;
2042
2043                 if (*len != sizeof(rev)) {
2044                         ret = -EINVAL;
2045                         break;
2046                 }
2047                 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2048                         ret = -EFAULT;
2049                         break;
2050                 }
2051
2052                 if (cmd == IPT_SO_GET_REVISION_TARGET)
2053                         target = 1;
2054                 else
2055                         target = 0;
2056
2057                 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2058                                                          rev.revision,
2059                                                          target, &ret),
2060                                         "ipt_%s", rev.name);
2061                 break;
2062         }
2063
2064         default:
2065                 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2066                 ret = -EINVAL;
2067         }
2068
2069         return ret;
2070 }
2071
2072 struct xt_table *ipt_register_table(struct net *net,
2073                                     const struct xt_table *table,
2074                                     const struct ipt_replace *repl)
2075 {
2076         int ret;
2077         struct xt_table_info *newinfo;
2078         struct xt_table_info bootstrap = {0};
2079         void *loc_cpu_entry;
2080         struct xt_table *new_table;
2081
2082         newinfo = xt_alloc_table_info(repl->size);
2083         if (!newinfo) {
2084                 ret = -ENOMEM;
2085                 goto out;
2086         }
2087
2088         /* choose the copy on our node/cpu, but dont care about preemption */
2089         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2090         memcpy(loc_cpu_entry, repl->entries, repl->size);
2091
2092         ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2093         if (ret != 0)
2094                 goto out_free;
2095
2096         new_table = xt_register_table(net, table, &bootstrap, newinfo);
2097         if (IS_ERR(new_table)) {
2098                 ret = PTR_ERR(new_table);
2099                 goto out_free;
2100         }
2101
2102         return new_table;
2103
2104 out_free:
2105         xt_free_table_info(newinfo);
2106 out:
2107         return ERR_PTR(ret);
2108 }
2109
2110 void ipt_unregister_table(struct net *net, struct xt_table *table)
2111 {
2112         struct xt_table_info *private;
2113         void *loc_cpu_entry;
2114         struct module *table_owner = table->me;
2115         struct ipt_entry *iter;
2116
2117         private = xt_unregister_table(table);
2118
2119         /* Decrease module usage counts and free resources */
2120         loc_cpu_entry = private->entries[raw_smp_processor_id()];
2121         xt_entry_foreach(iter, loc_cpu_entry, private->size)
2122                 cleanup_entry(iter, net);
2123         if (private->number > private->initial_entries)
2124                 module_put(table_owner);
2125         xt_free_table_info(private);
2126 }
2127
2128 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2129 static inline bool
2130 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2131                      u_int8_t type, u_int8_t code,
2132                      bool invert)
2133 {
2134         return ((test_type == 0xFF) ||
2135                 (type == test_type && code >= min_code && code <= max_code))
2136                 ^ invert;
2137 }
2138
2139 static bool
2140 icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
2141 {
2142         const struct icmphdr *ic;
2143         struct icmphdr _icmph;
2144         const struct ipt_icmp *icmpinfo = par->matchinfo;
2145
2146         /* Must not be a fragment. */
2147         if (par->fragoff != 0)
2148                 return false;
2149
2150         ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2151         if (ic == NULL) {
2152                 /* We've been asked to examine this packet, and we
2153                  * can't.  Hence, no choice but to drop.
2154                  */
2155                 duprintf("Dropping evil ICMP tinygram.\n");
2156                 par->hotdrop = true;
2157                 return false;
2158         }
2159
2160         return icmp_type_code_match(icmpinfo->type,
2161                                     icmpinfo->code[0],
2162                                     icmpinfo->code[1],
2163                                     ic->type, ic->code,
2164                                     !!(icmpinfo->invflags&IPT_ICMP_INV));
2165 }
2166
2167 static int icmp_checkentry(const struct xt_mtchk_param *par)
2168 {
2169         const struct ipt_icmp *icmpinfo = par->matchinfo;
2170
2171         /* Must specify no unknown invflags */
2172         return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
2173 }
2174
2175 /* The built-in targets: standard (NULL) and error. */
2176 static struct xt_target ipt_standard_target __read_mostly = {
2177         .name           = IPT_STANDARD_TARGET,
2178         .targetsize     = sizeof(int),
2179         .family         = NFPROTO_IPV4,
2180 #ifdef CONFIG_COMPAT
2181         .compatsize     = sizeof(compat_int_t),
2182         .compat_from_user = compat_standard_from_user,
2183         .compat_to_user = compat_standard_to_user,
2184 #endif
2185 };
2186
2187 static struct xt_target ipt_error_target __read_mostly = {
2188         .name           = IPT_ERROR_TARGET,
2189         .target         = ipt_error,
2190         .targetsize     = IPT_FUNCTION_MAXNAMELEN,
2191         .family         = NFPROTO_IPV4,
2192 };
2193
2194 static struct nf_sockopt_ops ipt_sockopts = {
2195         .pf             = PF_INET,
2196         .set_optmin     = IPT_BASE_CTL,
2197         .set_optmax     = IPT_SO_SET_MAX+1,
2198         .set            = do_ipt_set_ctl,
2199 #ifdef CONFIG_COMPAT
2200         .compat_set     = compat_do_ipt_set_ctl,
2201 #endif
2202         .get_optmin     = IPT_BASE_CTL,
2203         .get_optmax     = IPT_SO_GET_MAX+1,
2204         .get            = do_ipt_get_ctl,
2205 #ifdef CONFIG_COMPAT
2206         .compat_get     = compat_do_ipt_get_ctl,
2207 #endif
2208         .owner          = THIS_MODULE,
2209 };
2210
2211 static struct xt_match icmp_matchstruct __read_mostly = {
2212         .name           = "icmp",
2213         .match          = icmp_match,
2214         .matchsize      = sizeof(struct ipt_icmp),
2215         .checkentry     = icmp_checkentry,
2216         .proto          = IPPROTO_ICMP,
2217         .family         = NFPROTO_IPV4,
2218 };
2219
2220 static int __net_init ip_tables_net_init(struct net *net)
2221 {
2222         return xt_proto_init(net, NFPROTO_IPV4);
2223 }
2224
2225 static void __net_exit ip_tables_net_exit(struct net *net)
2226 {
2227         xt_proto_fini(net, NFPROTO_IPV4);
2228 }
2229
2230 static struct pernet_operations ip_tables_net_ops = {
2231         .init = ip_tables_net_init,
2232         .exit = ip_tables_net_exit,
2233 };
2234
2235 static int __init ip_tables_init(void)
2236 {
2237         int ret;
2238
2239         ret = register_pernet_subsys(&ip_tables_net_ops);
2240         if (ret < 0)
2241                 goto err1;
2242
2243         /* Noone else will be downing sem now, so we won't sleep */
2244         ret = xt_register_target(&ipt_standard_target);
2245         if (ret < 0)
2246                 goto err2;
2247         ret = xt_register_target(&ipt_error_target);
2248         if (ret < 0)
2249                 goto err3;
2250         ret = xt_register_match(&icmp_matchstruct);
2251         if (ret < 0)
2252                 goto err4;
2253
2254         /* Register setsockopt */
2255         ret = nf_register_sockopt(&ipt_sockopts);
2256         if (ret < 0)
2257                 goto err5;
2258
2259         pr_info("(C) 2000-2006 Netfilter Core Team\n");
2260         return 0;
2261
2262 err5:
2263         xt_unregister_match(&icmp_matchstruct);
2264 err4:
2265         xt_unregister_target(&ipt_error_target);
2266 err3:
2267         xt_unregister_target(&ipt_standard_target);
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_match(&icmp_matchstruct);
2279         xt_unregister_target(&ipt_error_target);
2280         xt_unregister_target(&ipt_standard_target);
2281
2282         unregister_pernet_subsys(&ip_tables_net_ops);
2283 }
2284
2285 EXPORT_SYMBOL(ipt_register_table);
2286 EXPORT_SYMBOL(ipt_unregister_table);
2287 EXPORT_SYMBOL(ipt_do_table);
2288 module_init(ip_tables_init);
2289 module_exit(ip_tables_fini);