]> bbs.cooldavid.org Git - net-next-2.6.git/blob - net/ipv4/netfilter/ip_tables.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus
[net-next-2.6.git] / net / ipv4 / netfilter / ip_tables.c
1 /*
2  * Packet matching code.
3  *
4  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5  * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/cache.h>
13 #include <linux/capability.h>
14 #include <linux/skbuff.h>
15 #include <linux/kmod.h>
16 #include <linux/vmalloc.h>
17 #include <linux/netdevice.h>
18 #include <linux/module.h>
19 #include <linux/icmp.h>
20 #include <net/ip.h>
21 #include <net/compat.h>
22 #include <asm/uaccess.h>
23 #include <linux/mutex.h>
24 #include <linux/proc_fs.h>
25 #include <linux/err.h>
26 #include <linux/cpumask.h>
27
28 #include <linux/netfilter/x_tables.h>
29 #include <linux/netfilter_ipv4/ip_tables.h>
30 #include <net/netfilter/nf_log.h>
31 #include "../../netfilter/xt_repldata.h"
32
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
35 MODULE_DESCRIPTION("IPv4 packet filter");
36
37 /*#define DEBUG_IP_FIREWALL*/
38 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
39 /*#define DEBUG_IP_FIREWALL_USER*/
40
41 #ifdef DEBUG_IP_FIREWALL
42 #define dprintf(format, args...)  printk(format , ## args)
43 #else
44 #define dprintf(format, args...)
45 #endif
46
47 #ifdef DEBUG_IP_FIREWALL_USER
48 #define duprintf(format, args...) printk(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_target_param *par)
169 {
170         if (net_ratelimit())
171                 printk("ip_tables: error: `%s'\n",
172                        (const char *)par->targinfo);
173
174         return NF_DROP;
175 }
176
177 /* Performance critical - called for every packet */
178 static inline bool
179 do_match(const struct ipt_entry_match *m, const struct sk_buff *skb,
180          struct xt_match_param *par)
181 {
182         par->match     = m->u.kernel.match;
183         par->matchinfo = m->data;
184
185         /* Stop iteration if it doesn't match */
186         if (!m->u.kernel.match->match(skb, par))
187                 return true;
188         else
189                 return false;
190 }
191
192 /* Performance critical */
193 static inline struct ipt_entry *
194 get_entry(const void *base, unsigned int offset)
195 {
196         return (struct ipt_entry *)(base + offset);
197 }
198
199 /* All zeroes == unconditional rule. */
200 /* Mildly perf critical (only if packet tracing is on) */
201 static inline bool unconditional(const struct ipt_ip *ip)
202 {
203         static const struct ipt_ip uncond;
204
205         return memcmp(ip, &uncond, sizeof(uncond)) == 0;
206 #undef FWINV
207 }
208
209 /* for const-correctness */
210 static inline const struct ipt_entry_target *
211 ipt_get_target_c(const struct ipt_entry *e)
212 {
213         return ipt_get_target((struct ipt_entry *)e);
214 }
215
216 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
217     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
218 static const char *const hooknames[] = {
219         [NF_INET_PRE_ROUTING]           = "PREROUTING",
220         [NF_INET_LOCAL_IN]              = "INPUT",
221         [NF_INET_FORWARD]               = "FORWARD",
222         [NF_INET_LOCAL_OUT]             = "OUTPUT",
223         [NF_INET_POST_ROUTING]          = "POSTROUTING",
224 };
225
226 enum nf_ip_trace_comments {
227         NF_IP_TRACE_COMMENT_RULE,
228         NF_IP_TRACE_COMMENT_RETURN,
229         NF_IP_TRACE_COMMENT_POLICY,
230 };
231
232 static const char *const comments[] = {
233         [NF_IP_TRACE_COMMENT_RULE]      = "rule",
234         [NF_IP_TRACE_COMMENT_RETURN]    = "return",
235         [NF_IP_TRACE_COMMENT_POLICY]    = "policy",
236 };
237
238 static struct nf_loginfo trace_loginfo = {
239         .type = NF_LOG_TYPE_LOG,
240         .u = {
241                 .log = {
242                         .level = 4,
243                         .logflags = NF_LOG_MASK,
244                 },
245         },
246 };
247
248 /* Mildly perf critical (only if packet tracing is on) */
249 static inline int
250 get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e,
251                       const char *hookname, const char **chainname,
252                       const char **comment, unsigned int *rulenum)
253 {
254         const struct ipt_standard_target *t = (void *)ipt_get_target_c(s);
255
256         if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
257                 /* Head of user chain: ERROR target with chainname */
258                 *chainname = t->target.data;
259                 (*rulenum) = 0;
260         } else if (s == e) {
261                 (*rulenum)++;
262
263                 if (s->target_offset == sizeof(struct ipt_entry) &&
264                     strcmp(t->target.u.kernel.target->name,
265                            IPT_STANDARD_TARGET) == 0 &&
266                    t->verdict < 0 &&
267                    unconditional(&s->ip)) {
268                         /* Tail of chains: STANDARD target (return/policy) */
269                         *comment = *chainname == hookname
270                                 ? comments[NF_IP_TRACE_COMMENT_POLICY]
271                                 : comments[NF_IP_TRACE_COMMENT_RETURN];
272                 }
273                 return 1;
274         } else
275                 (*rulenum)++;
276
277         return 0;
278 }
279
280 static void trace_packet(const struct sk_buff *skb,
281                          unsigned int hook,
282                          const struct net_device *in,
283                          const struct net_device *out,
284                          const char *tablename,
285                          const struct xt_table_info *private,
286                          const struct ipt_entry *e)
287 {
288         const void *table_base;
289         const struct ipt_entry *root;
290         const char *hookname, *chainname, *comment;
291         const struct ipt_entry *iter;
292         unsigned int rulenum = 0;
293
294         table_base = private->entries[smp_processor_id()];
295         root = get_entry(table_base, private->hook_entry[hook]);
296
297         hookname = chainname = hooknames[hook];
298         comment = comments[NF_IP_TRACE_COMMENT_RULE];
299
300         xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
301                 if (get_chainname_rulenum(iter, e, hookname,
302                     &chainname, &comment, &rulenum) != 0)
303                         break;
304
305         nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
306                       "TRACE: %s:%s:%s:%u ",
307                       tablename, chainname, comment, rulenum);
308 }
309 #endif
310
311 static inline __pure
312 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
313 {
314         return (void *)entry + entry->next_offset;
315 }
316
317 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
318 unsigned int
319 ipt_do_table(struct sk_buff *skb,
320              unsigned int hook,
321              const struct net_device *in,
322              const struct net_device *out,
323              struct xt_table *table)
324 {
325 #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
326
327         static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
328         const struct iphdr *ip;
329         bool hotdrop = false;
330         /* Initializing verdict to NF_DROP keeps gcc happy. */
331         unsigned int verdict = NF_DROP;
332         const char *indev, *outdev;
333         const void *table_base;
334         struct ipt_entry *e, *back;
335         const struct xt_table_info *private;
336         struct xt_match_param mtpar;
337         struct xt_target_param tgpar;
338
339         /* Initialization */
340         ip = ip_hdr(skb);
341         indev = in ? in->name : nulldevname;
342         outdev = out ? out->name : nulldevname;
343         /* We handle fragments by dealing with the first fragment as
344          * if it was a normal packet.  All other fragments are treated
345          * normally, except that they will NEVER match rules that ask
346          * things we don't know, ie. tcp syn flag or ports).  If the
347          * rule is also a fragment-specific rule, non-fragments won't
348          * match it. */
349         mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
350         mtpar.thoff   = ip_hdrlen(skb);
351         mtpar.hotdrop = &hotdrop;
352         mtpar.in      = tgpar.in  = in;
353         mtpar.out     = tgpar.out = out;
354         mtpar.family  = tgpar.family = NFPROTO_IPV4;
355         mtpar.hooknum = tgpar.hooknum = hook;
356
357         IP_NF_ASSERT(table->valid_hooks & (1 << hook));
358         xt_info_rdlock_bh();
359         private = table->private;
360         table_base = private->entries[smp_processor_id()];
361
362         e = get_entry(table_base, private->hook_entry[hook]);
363
364         /* For return from builtin chain */
365         back = get_entry(table_base, private->underflow[hook]);
366
367         do {
368                 const struct ipt_entry_target *t;
369                 const struct xt_entry_match *ematch;
370
371                 IP_NF_ASSERT(e);
372                 IP_NF_ASSERT(back);
373                 if (!ip_packet_match(ip, indev, outdev,
374                     &e->ip, mtpar.fragoff)) {
375  no_match:
376                         e = ipt_next_entry(e);
377                         continue;
378                 }
379
380                 xt_ematch_foreach(ematch, e)
381                         if (do_match(ematch, skb, &mtpar) != 0)
382                                 goto no_match;
383
384                 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
385
386                 t = ipt_get_target(e);
387                 IP_NF_ASSERT(t->u.kernel.target);
388
389 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
390     defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
391                 /* The packet is traced: log it */
392                 if (unlikely(skb->nf_trace))
393                         trace_packet(skb, hook, in, out,
394                                      table->name, private, e);
395 #endif
396                 /* Standard target? */
397                 if (!t->u.kernel.target->target) {
398                         int v;
399
400                         v = ((struct ipt_standard_target *)t)->verdict;
401                         if (v < 0) {
402                                 /* Pop from stack? */
403                                 if (v != IPT_RETURN) {
404                                         verdict = (unsigned)(-v) - 1;
405                                         break;
406                                 }
407                                 e = back;
408                                 back = get_entry(table_base, back->comefrom);
409                                 continue;
410                         }
411                         if (table_base + v != ipt_next_entry(e) &&
412                             !(e->ip.flags & IPT_F_GOTO)) {
413                                 /* Save old back ptr in next entry */
414                                 struct ipt_entry *next = ipt_next_entry(e);
415                                 next->comefrom = (void *)back - table_base;
416                                 /* set back pointer to next entry */
417                                 back = next;
418                         }
419
420                         e = get_entry(table_base, v);
421                         continue;
422                 }
423
424                 /* Targets which reenter must return
425                    abs. verdicts */
426                 tgpar.target   = t->u.kernel.target;
427                 tgpar.targinfo = t->data;
428
429
430 #ifdef CONFIG_NETFILTER_DEBUG
431                 tb_comefrom = 0xeeeeeeec;
432 #endif
433                 verdict = t->u.kernel.target->target(skb, &tgpar);
434 #ifdef CONFIG_NETFILTER_DEBUG
435                 if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
436                         printk("Target %s reentered!\n",
437                                t->u.kernel.target->name);
438                         verdict = NF_DROP;
439                 }
440                 tb_comefrom = 0x57acc001;
441 #endif
442                 /* Target might have changed stuff. */
443                 ip = ip_hdr(skb);
444                 if (verdict == IPT_CONTINUE)
445                         e = ipt_next_entry(e);
446                 else
447                         /* Verdict */
448                         break;
449         } while (!hotdrop);
450         xt_info_rdunlock_bh();
451
452 #ifdef DEBUG_ALLOW_ALL
453         return NF_ACCEPT;
454 #else
455         if (hotdrop)
456                 return NF_DROP;
457         else return verdict;
458 #endif
459
460 #undef tb_comefrom
461 }
462
463 /* Figures out from what hook each rule can be called: returns 0 if
464    there are loops.  Puts hook bitmask in comefrom. */
465 static int
466 mark_source_chains(const struct xt_table_info *newinfo,
467                    unsigned int valid_hooks, void *entry0)
468 {
469         unsigned int hook;
470
471         /* No recursion; use packet counter to save back ptrs (reset
472            to 0 as we leave), and comefrom to save source hook bitmask */
473         for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
474                 unsigned int pos = newinfo->hook_entry[hook];
475                 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
476
477                 if (!(valid_hooks & (1 << hook)))
478                         continue;
479
480                 /* Set initial back pointer. */
481                 e->counters.pcnt = pos;
482
483                 for (;;) {
484                         const struct ipt_standard_target *t
485                                 = (void *)ipt_get_target_c(e);
486                         int visited = e->comefrom & (1 << hook);
487
488                         if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
489                                 printk("iptables: loop hook %u pos %u %08X.\n",
490                                        hook, pos, e->comefrom);
491                                 return 0;
492                         }
493                         e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
494
495                         /* Unconditional return/END. */
496                         if ((e->target_offset == sizeof(struct ipt_entry) &&
497                              (strcmp(t->target.u.user.name,
498                                      IPT_STANDARD_TARGET) == 0) &&
499                              t->verdict < 0 && unconditional(&e->ip)) ||
500                             visited) {
501                                 unsigned int oldpos, size;
502
503                                 if ((strcmp(t->target.u.user.name,
504                                             IPT_STANDARD_TARGET) == 0) &&
505                                     t->verdict < -NF_MAX_VERDICT - 1) {
506                                         duprintf("mark_source_chains: bad "
507                                                 "negative verdict (%i)\n",
508                                                                 t->verdict);
509                                         return 0;
510                                 }
511
512                                 /* Return: backtrack through the last
513                                    big jump. */
514                                 do {
515                                         e->comefrom ^= (1<<NF_INET_NUMHOOKS);
516 #ifdef DEBUG_IP_FIREWALL_USER
517                                         if (e->comefrom
518                                             & (1 << NF_INET_NUMHOOKS)) {
519                                                 duprintf("Back unset "
520                                                          "on hook %u "
521                                                          "rule %u\n",
522                                                          hook, pos);
523                                         }
524 #endif
525                                         oldpos = pos;
526                                         pos = e->counters.pcnt;
527                                         e->counters.pcnt = 0;
528
529                                         /* We're at the start. */
530                                         if (pos == oldpos)
531                                                 goto next;
532
533                                         e = (struct ipt_entry *)
534                                                 (entry0 + pos);
535                                 } while (oldpos == pos + e->next_offset);
536
537                                 /* Move along one */
538                                 size = e->next_offset;
539                                 e = (struct ipt_entry *)
540                                         (entry0 + pos + size);
541                                 e->counters.pcnt = pos;
542                                 pos += size;
543                         } else {
544                                 int newpos = t->verdict;
545
546                                 if (strcmp(t->target.u.user.name,
547                                            IPT_STANDARD_TARGET) == 0 &&
548                                     newpos >= 0) {
549                                         if (newpos > newinfo->size -
550                                                 sizeof(struct ipt_entry)) {
551                                                 duprintf("mark_source_chains: "
552                                                         "bad verdict (%i)\n",
553                                                                 newpos);
554                                                 return 0;
555                                         }
556                                         /* This a jump; chase it. */
557                                         duprintf("Jump rule %u -> %u\n",
558                                                  pos, newpos);
559                                 } else {
560                                         /* ... this is a fallthru */
561                                         newpos = pos + e->next_offset;
562                                 }
563                                 e = (struct ipt_entry *)
564                                         (entry0 + newpos);
565                                 e->counters.pcnt = pos;
566                                 pos = newpos;
567                         }
568                 }
569                 next:
570                 duprintf("Finished chain %u\n", hook);
571         }
572         return 1;
573 }
574
575 static void cleanup_match(struct ipt_entry_match *m, struct net *net)
576 {
577         struct xt_mtdtor_param par;
578
579         par.net       = net;
580         par.match     = m->u.kernel.match;
581         par.matchinfo = m->data;
582         par.family    = NFPROTO_IPV4;
583         if (par.match->destroy != NULL)
584                 par.match->destroy(&par);
585         module_put(par.match->me);
586 }
587
588 static int
589 check_entry(const struct ipt_entry *e, const char *name)
590 {
591         const struct ipt_entry_target *t;
592
593         if (!ip_checkentry(&e->ip)) {
594                 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
595                 return -EINVAL;
596         }
597
598         if (e->target_offset + sizeof(struct ipt_entry_target) >
599             e->next_offset)
600                 return -EINVAL;
601
602         t = ipt_get_target_c(e);
603         if (e->target_offset + t->u.target_size > e->next_offset)
604                 return -EINVAL;
605
606         return 0;
607 }
608
609 static int
610 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
611 {
612         const struct ipt_ip *ip = par->entryinfo;
613         int ret;
614
615         par->match     = m->u.kernel.match;
616         par->matchinfo = m->data;
617
618         ret = xt_check_match(par, m->u.match_size - sizeof(*m),
619               ip->proto, ip->invflags & IPT_INV_PROTO);
620         if (ret < 0) {
621                 duprintf("ip_tables: check failed for `%s'.\n",
622                          par.match->name);
623                 return ret;
624         }
625         return 0;
626 }
627
628 static int
629 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
630 {
631         struct xt_match *match;
632         int ret;
633
634         match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
635                                                       m->u.user.revision),
636                                         "ipt_%s", m->u.user.name);
637         if (IS_ERR(match) || !match) {
638                 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
639                 return match ? PTR_ERR(match) : -ENOENT;
640         }
641         m->u.kernel.match = match;
642
643         ret = check_match(m, par);
644         if (ret)
645                 goto err;
646
647         return 0;
648 err:
649         module_put(m->u.kernel.match->me);
650         return ret;
651 }
652
653 static int check_target(struct ipt_entry *e, struct net *net, const char *name)
654 {
655         struct ipt_entry_target *t = ipt_get_target(e);
656         struct xt_tgchk_param par = {
657                 .net       = net,
658                 .table     = name,
659                 .entryinfo = e,
660                 .target    = t->u.kernel.target,
661                 .targinfo  = t->data,
662                 .hook_mask = e->comefrom,
663                 .family    = NFPROTO_IPV4,
664         };
665         int ret;
666
667         ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
668               e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
669         if (ret < 0) {
670                 duprintf("ip_tables: check failed for `%s'.\n",
671                          t->u.kernel.target->name);
672                 return ret;
673         }
674         return 0;
675 }
676
677 static int
678 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
679                  unsigned int size)
680 {
681         struct ipt_entry_target *t;
682         struct xt_target *target;
683         int ret;
684         unsigned int j;
685         struct xt_mtchk_param mtpar;
686         struct xt_entry_match *ematch;
687
688         ret = check_entry(e, name);
689         if (ret)
690                 return ret;
691
692         j = 0;
693         mtpar.net       = net;
694         mtpar.table     = name;
695         mtpar.entryinfo = &e->ip;
696         mtpar.hook_mask = e->comefrom;
697         mtpar.family    = NFPROTO_IPV4;
698         xt_ematch_foreach(ematch, e) {
699                 ret = find_check_match(ematch, &mtpar);
700                 if (ret != 0)
701                         goto cleanup_matches;
702                 ++j;
703         }
704
705         t = ipt_get_target(e);
706         target = try_then_request_module(xt_find_target(AF_INET,
707                                                         t->u.user.name,
708                                                         t->u.user.revision),
709                                          "ipt_%s", t->u.user.name);
710         if (IS_ERR(target) || !target) {
711                 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
712                 ret = target ? PTR_ERR(target) : -ENOENT;
713                 goto cleanup_matches;
714         }
715         t->u.kernel.target = target;
716
717         ret = check_target(e, net, name);
718         if (ret)
719                 goto err;
720         return 0;
721  err:
722         module_put(t->u.kernel.target->me);
723  cleanup_matches:
724         xt_ematch_foreach(ematch, e) {
725                 if (j-- == 0)
726                         break;
727                 cleanup_match(ematch, net);
728         }
729         return ret;
730 }
731
732 static bool check_underflow(const struct ipt_entry *e)
733 {
734         const struct ipt_entry_target *t;
735         unsigned int verdict;
736
737         if (!unconditional(&e->ip))
738                 return false;
739         t = ipt_get_target_c(e);
740         if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
741                 return false;
742         verdict = ((struct ipt_standard_target *)t)->verdict;
743         verdict = -verdict - 1;
744         return verdict == NF_DROP || verdict == NF_ACCEPT;
745 }
746
747 static int
748 check_entry_size_and_hooks(struct ipt_entry *e,
749                            struct xt_table_info *newinfo,
750                            const unsigned char *base,
751                            const unsigned char *limit,
752                            const unsigned int *hook_entries,
753                            const unsigned int *underflows,
754                            unsigned int valid_hooks)
755 {
756         unsigned int h;
757
758         if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
759             (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
760                 duprintf("Bad offset %p\n", e);
761                 return -EINVAL;
762         }
763
764         if (e->next_offset
765             < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
766                 duprintf("checking: element %p size %u\n",
767                          e, e->next_offset);
768                 return -EINVAL;
769         }
770
771         /* Check hooks & underflows */
772         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
773                 if (!(valid_hooks & (1 << h)))
774                         continue;
775                 if ((unsigned char *)e - base == hook_entries[h])
776                         newinfo->hook_entry[h] = hook_entries[h];
777                 if ((unsigned char *)e - base == underflows[h]) {
778                         if (!check_underflow(e)) {
779                                 pr_err("Underflows must be unconditional and "
780                                        "use the STANDARD target with "
781                                        "ACCEPT/DROP\n");
782                                 return -EINVAL;
783                         }
784                         newinfo->underflow[h] = underflows[h];
785                 }
786         }
787
788         /* Clear counters and comefrom */
789         e->counters = ((struct xt_counters) { 0, 0 });
790         e->comefrom = 0;
791         return 0;
792 }
793
794 static void
795 cleanup_entry(struct ipt_entry *e, struct net *net)
796 {
797         struct xt_tgdtor_param par;
798         struct ipt_entry_target *t;
799         struct xt_entry_match *ematch;
800
801         /* Cleanup all matches */
802         xt_ematch_foreach(ematch, e)
803                 cleanup_match(ematch, net);
804         t = ipt_get_target(e);
805
806         par.net      = net;
807         par.target   = t->u.kernel.target;
808         par.targinfo = t->data;
809         par.family   = NFPROTO_IPV4;
810         if (par.target->destroy != NULL)
811                 par.target->destroy(&par);
812         module_put(par.target->me);
813 }
814
815 /* Checks and translates the user-supplied table segment (held in
816    newinfo) */
817 static int
818 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
819                 const struct ipt_replace *repl)
820 {
821         struct ipt_entry *iter;
822         unsigned int i;
823         int ret = 0;
824
825         newinfo->size = repl->size;
826         newinfo->number = repl->num_entries;
827
828         /* Init all hooks to impossible value. */
829         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
830                 newinfo->hook_entry[i] = 0xFFFFFFFF;
831                 newinfo->underflow[i] = 0xFFFFFFFF;
832         }
833
834         duprintf("translate_table: size %u\n", newinfo->size);
835         i = 0;
836         /* Walk through entries, checking offsets. */
837         xt_entry_foreach(iter, entry0, newinfo->size) {
838                 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
839                                                  entry0 + repl->size,
840                                                  repl->hook_entry,
841                                                  repl->underflow,
842                                                  repl->valid_hooks);
843                 if (ret != 0)
844                         return ret;
845                 ++i;
846         }
847
848         if (i != repl->num_entries) {
849                 duprintf("translate_table: %u not %u entries\n",
850                          i, repl->num_entries);
851                 return -EINVAL;
852         }
853
854         /* Check hooks all assigned */
855         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
856                 /* Only hooks which are valid */
857                 if (!(repl->valid_hooks & (1 << i)))
858                         continue;
859                 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
860                         duprintf("Invalid hook entry %u %u\n",
861                                  i, repl->hook_entry[i]);
862                         return -EINVAL;
863                 }
864                 if (newinfo->underflow[i] == 0xFFFFFFFF) {
865                         duprintf("Invalid underflow %u %u\n",
866                                  i, repl->underflow[i]);
867                         return -EINVAL;
868                 }
869         }
870
871         if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
872                 return -ELOOP;
873
874         /* Finally, each sanity check must pass */
875         i = 0;
876         xt_entry_foreach(iter, entry0, newinfo->size) {
877                 ret = find_check_entry(iter, net, repl->name, repl->size);
878                 if (ret != 0)
879                         break;
880                 ++i;
881         }
882
883         if (ret != 0) {
884                 xt_entry_foreach(iter, entry0, newinfo->size) {
885                         if (i-- == 0)
886                                 break;
887                         cleanup_entry(iter, net);
888                 }
889                 return ret;
890         }
891
892         /* And one copy for every other CPU */
893         for_each_possible_cpu(i) {
894                 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
895                         memcpy(newinfo->entries[i], entry0, newinfo->size);
896         }
897
898         return ret;
899 }
900
901 static void
902 get_counters(const struct xt_table_info *t,
903              struct xt_counters counters[])
904 {
905         struct ipt_entry *iter;
906         unsigned int cpu;
907         unsigned int i;
908         unsigned int curcpu;
909
910         /* Instead of clearing (by a previous call to memset())
911          * the counters and using adds, we set the counters
912          * with data used by 'current' CPU.
913          *
914          * Bottom half has to be disabled to prevent deadlock
915          * if new softirq were to run and call ipt_do_table
916          */
917         local_bh_disable();
918         curcpu = smp_processor_id();
919
920         i = 0;
921         xt_entry_foreach(iter, t->entries[curcpu], t->size) {
922                 SET_COUNTER(counters[i], iter->counters.bcnt,
923                             iter->counters.pcnt);
924                 ++i;
925         }
926
927         for_each_possible_cpu(cpu) {
928                 if (cpu == curcpu)
929                         continue;
930                 i = 0;
931                 xt_info_wrlock(cpu);
932                 xt_entry_foreach(iter, t->entries[cpu], t->size) {
933                         ADD_COUNTER(counters[i], iter->counters.bcnt,
934                                     iter->counters.pcnt);
935                         ++i; /* macro does multi eval of i */
936                 }
937                 xt_info_wrunlock(cpu);
938         }
939         local_bh_enable();
940 }
941
942 static struct xt_counters *alloc_counters(const struct xt_table *table)
943 {
944         unsigned int countersize;
945         struct xt_counters *counters;
946         const struct xt_table_info *private = table->private;
947
948         /* We need atomic snapshot of counters: rest doesn't change
949            (other than comefrom, which userspace doesn't care
950            about). */
951         countersize = sizeof(struct xt_counters) * private->number;
952         counters = vmalloc_node(countersize, numa_node_id());
953
954         if (counters == NULL)
955                 return ERR_PTR(-ENOMEM);
956
957         get_counters(private, counters);
958
959         return counters;
960 }
961
962 static int
963 copy_entries_to_user(unsigned int total_size,
964                      const struct xt_table *table,
965                      void __user *userptr)
966 {
967         unsigned int off, num;
968         const struct ipt_entry *e;
969         struct xt_counters *counters;
970         const struct xt_table_info *private = table->private;
971         int ret = 0;
972         const void *loc_cpu_entry;
973
974         counters = alloc_counters(table);
975         if (IS_ERR(counters))
976                 return PTR_ERR(counters);
977
978         /* choose the copy that is on our node/cpu, ...
979          * This choice is lazy (because current thread is
980          * allowed to migrate to another cpu)
981          */
982         loc_cpu_entry = private->entries[raw_smp_processor_id()];
983         if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
984                 ret = -EFAULT;
985                 goto free_counters;
986         }
987
988         /* FIXME: use iterator macros --RR */
989         /* ... then go back and fix counters and names */
990         for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
991                 unsigned int i;
992                 const struct ipt_entry_match *m;
993                 const struct ipt_entry_target *t;
994
995                 e = (struct ipt_entry *)(loc_cpu_entry + off);
996                 if (copy_to_user(userptr + off
997                                  + offsetof(struct ipt_entry, counters),
998                                  &counters[num],
999                                  sizeof(counters[num])) != 0) {
1000                         ret = -EFAULT;
1001                         goto free_counters;
1002                 }
1003
1004                 for (i = sizeof(struct ipt_entry);
1005                      i < e->target_offset;
1006                      i += m->u.match_size) {
1007                         m = (void *)e + i;
1008
1009                         if (copy_to_user(userptr + off + i
1010                                          + offsetof(struct ipt_entry_match,
1011                                                     u.user.name),
1012                                          m->u.kernel.match->name,
1013                                          strlen(m->u.kernel.match->name)+1)
1014                             != 0) {
1015                                 ret = -EFAULT;
1016                                 goto free_counters;
1017                         }
1018                 }
1019
1020                 t = ipt_get_target_c(e);
1021                 if (copy_to_user(userptr + off + e->target_offset
1022                                  + offsetof(struct ipt_entry_target,
1023                                             u.user.name),
1024                                  t->u.kernel.target->name,
1025                                  strlen(t->u.kernel.target->name)+1) != 0) {
1026                         ret = -EFAULT;
1027                         goto free_counters;
1028                 }
1029         }
1030
1031  free_counters:
1032         vfree(counters);
1033         return ret;
1034 }
1035
1036 #ifdef CONFIG_COMPAT
1037 static void compat_standard_from_user(void *dst, const void *src)
1038 {
1039         int v = *(compat_int_t *)src;
1040
1041         if (v > 0)
1042                 v += xt_compat_calc_jump(AF_INET, v);
1043         memcpy(dst, &v, sizeof(v));
1044 }
1045
1046 static int compat_standard_to_user(void __user *dst, const void *src)
1047 {
1048         compat_int_t cv = *(int *)src;
1049
1050         if (cv > 0)
1051                 cv -= xt_compat_calc_jump(AF_INET, cv);
1052         return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1053 }
1054
1055 static int compat_calc_entry(const struct ipt_entry *e,
1056                              const struct xt_table_info *info,
1057                              const void *base, struct xt_table_info *newinfo)
1058 {
1059         const struct xt_entry_match *ematch;
1060         const struct ipt_entry_target *t;
1061         unsigned int entry_offset;
1062         int off, i, ret;
1063
1064         off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1065         entry_offset = (void *)e - base;
1066         xt_ematch_foreach(ematch, e)
1067                 off += xt_compat_match_offset(ematch->u.kernel.match);
1068         t = ipt_get_target_c(e);
1069         off += xt_compat_target_offset(t->u.kernel.target);
1070         newinfo->size -= off;
1071         ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1072         if (ret)
1073                 return ret;
1074
1075         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1076                 if (info->hook_entry[i] &&
1077                     (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1078                         newinfo->hook_entry[i] -= off;
1079                 if (info->underflow[i] &&
1080                     (e < (struct ipt_entry *)(base + info->underflow[i])))
1081                         newinfo->underflow[i] -= off;
1082         }
1083         return 0;
1084 }
1085
1086 static int compat_table_info(const struct xt_table_info *info,
1087                              struct xt_table_info *newinfo)
1088 {
1089         struct ipt_entry *iter;
1090         void *loc_cpu_entry;
1091         int ret;
1092
1093         if (!newinfo || !info)
1094                 return -EINVAL;
1095
1096         /* we dont care about newinfo->entries[] */
1097         memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1098         newinfo->initial_entries = 0;
1099         loc_cpu_entry = info->entries[raw_smp_processor_id()];
1100         xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1101                 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1102                 if (ret != 0)
1103                         return ret;
1104         }
1105         return 0;
1106 }
1107 #endif
1108
1109 static int get_info(struct net *net, void __user *user,
1110                     const int *len, int compat)
1111 {
1112         char name[IPT_TABLE_MAXNAMELEN];
1113         struct xt_table *t;
1114         int ret;
1115
1116         if (*len != sizeof(struct ipt_getinfo)) {
1117                 duprintf("length %u != %zu\n", *len,
1118                          sizeof(struct ipt_getinfo));
1119                 return -EINVAL;
1120         }
1121
1122         if (copy_from_user(name, user, sizeof(name)) != 0)
1123                 return -EFAULT;
1124
1125         name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1126 #ifdef CONFIG_COMPAT
1127         if (compat)
1128                 xt_compat_lock(AF_INET);
1129 #endif
1130         t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1131                                     "iptable_%s", name);
1132         if (t && !IS_ERR(t)) {
1133                 struct ipt_getinfo info;
1134                 const struct xt_table_info *private = t->private;
1135 #ifdef CONFIG_COMPAT
1136                 struct xt_table_info tmp;
1137
1138                 if (compat) {
1139                         ret = compat_table_info(private, &tmp);
1140                         xt_compat_flush_offsets(AF_INET);
1141                         private = &tmp;
1142                 }
1143 #endif
1144                 info.valid_hooks = t->valid_hooks;
1145                 memcpy(info.hook_entry, private->hook_entry,
1146                        sizeof(info.hook_entry));
1147                 memcpy(info.underflow, private->underflow,
1148                        sizeof(info.underflow));
1149                 info.num_entries = private->number;
1150                 info.size = private->size;
1151                 strcpy(info.name, name);
1152
1153                 if (copy_to_user(user, &info, *len) != 0)
1154                         ret = -EFAULT;
1155                 else
1156                         ret = 0;
1157
1158                 xt_table_unlock(t);
1159                 module_put(t->me);
1160         } else
1161                 ret = t ? PTR_ERR(t) : -ENOENT;
1162 #ifdef CONFIG_COMPAT
1163         if (compat)
1164                 xt_compat_unlock(AF_INET);
1165 #endif
1166         return ret;
1167 }
1168
1169 static int
1170 get_entries(struct net *net, struct ipt_get_entries __user *uptr,
1171             const int *len)
1172 {
1173         int ret;
1174         struct ipt_get_entries get;
1175         struct xt_table *t;
1176
1177         if (*len < sizeof(get)) {
1178                 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1179                 return -EINVAL;
1180         }
1181         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1182                 return -EFAULT;
1183         if (*len != sizeof(struct ipt_get_entries) + get.size) {
1184                 duprintf("get_entries: %u != %zu\n",
1185                          *len, sizeof(get) + get.size);
1186                 return -EINVAL;
1187         }
1188
1189         t = xt_find_table_lock(net, AF_INET, get.name);
1190         if (t && !IS_ERR(t)) {
1191                 const struct xt_table_info *private = t->private;
1192                 duprintf("t->private->number = %u\n", private->number);
1193                 if (get.size == private->size)
1194                         ret = copy_entries_to_user(private->size,
1195                                                    t, uptr->entrytable);
1196                 else {
1197                         duprintf("get_entries: I've got %u not %u!\n",
1198                                  private->size, get.size);
1199                         ret = -EAGAIN;
1200                 }
1201                 module_put(t->me);
1202                 xt_table_unlock(t);
1203         } else
1204                 ret = t ? PTR_ERR(t) : -ENOENT;
1205
1206         return ret;
1207 }
1208
1209 static int
1210 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1211              struct xt_table_info *newinfo, unsigned int num_counters,
1212              void __user *counters_ptr)
1213 {
1214         int ret;
1215         struct xt_table *t;
1216         struct xt_table_info *oldinfo;
1217         struct xt_counters *counters;
1218         void *loc_cpu_old_entry;
1219         struct ipt_entry *iter;
1220
1221         ret = 0;
1222         counters = vmalloc(num_counters * sizeof(struct xt_counters));
1223         if (!counters) {
1224                 ret = -ENOMEM;
1225                 goto out;
1226         }
1227
1228         t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1229                                     "iptable_%s", name);
1230         if (!t || IS_ERR(t)) {
1231                 ret = t ? PTR_ERR(t) : -ENOENT;
1232                 goto free_newinfo_counters_untrans;
1233         }
1234
1235         /* You lied! */
1236         if (valid_hooks != t->valid_hooks) {
1237                 duprintf("Valid hook crap: %08X vs %08X\n",
1238                          valid_hooks, t->valid_hooks);
1239                 ret = -EINVAL;
1240                 goto put_module;
1241         }
1242
1243         oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1244         if (!oldinfo)
1245                 goto put_module;
1246
1247         /* Update module usage count based on number of rules */
1248         duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1249                 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1250         if ((oldinfo->number > oldinfo->initial_entries) ||
1251             (newinfo->number <= oldinfo->initial_entries))
1252                 module_put(t->me);
1253         if ((oldinfo->number > oldinfo->initial_entries) &&
1254             (newinfo->number <= oldinfo->initial_entries))
1255                 module_put(t->me);
1256
1257         /* Get the old counters, and synchronize with replace */
1258         get_counters(oldinfo, counters);
1259
1260         /* Decrease module usage counts and free resource */
1261         loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1262         xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1263                 cleanup_entry(iter, net);
1264
1265         xt_free_table_info(oldinfo);
1266         if (copy_to_user(counters_ptr, counters,
1267                          sizeof(struct xt_counters) * num_counters) != 0)
1268                 ret = -EFAULT;
1269         vfree(counters);
1270         xt_table_unlock(t);
1271         return ret;
1272
1273  put_module:
1274         module_put(t->me);
1275         xt_table_unlock(t);
1276  free_newinfo_counters_untrans:
1277         vfree(counters);
1278  out:
1279         return ret;
1280 }
1281
1282 static int
1283 do_replace(struct net *net, const void __user *user, unsigned int len)
1284 {
1285         int ret;
1286         struct ipt_replace tmp;
1287         struct xt_table_info *newinfo;
1288         void *loc_cpu_entry;
1289         struct ipt_entry *iter;
1290
1291         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1292                 return -EFAULT;
1293
1294         /* overflow check */
1295         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1296                 return -ENOMEM;
1297
1298         newinfo = xt_alloc_table_info(tmp.size);
1299         if (!newinfo)
1300                 return -ENOMEM;
1301
1302         /* choose the copy that is on our node/cpu */
1303         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1304         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1305                            tmp.size) != 0) {
1306                 ret = -EFAULT;
1307                 goto free_newinfo;
1308         }
1309
1310         ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1311         if (ret != 0)
1312                 goto free_newinfo;
1313
1314         duprintf("ip_tables: Translated table\n");
1315
1316         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1317                            tmp.num_counters, tmp.counters);
1318         if (ret)
1319                 goto free_newinfo_untrans;
1320         return 0;
1321
1322  free_newinfo_untrans:
1323         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1324                 cleanup_entry(iter, net);
1325  free_newinfo:
1326         xt_free_table_info(newinfo);
1327         return ret;
1328 }
1329
1330 static int
1331 do_add_counters(struct net *net, const void __user *user,
1332                 unsigned int len, int compat)
1333 {
1334         unsigned int i, curcpu;
1335         struct xt_counters_info tmp;
1336         struct xt_counters *paddc;
1337         unsigned int num_counters;
1338         const char *name;
1339         int size;
1340         void *ptmp;
1341         struct xt_table *t;
1342         const struct xt_table_info *private;
1343         int ret = 0;
1344         void *loc_cpu_entry;
1345         struct ipt_entry *iter;
1346 #ifdef CONFIG_COMPAT
1347         struct compat_xt_counters_info compat_tmp;
1348
1349         if (compat) {
1350                 ptmp = &compat_tmp;
1351                 size = sizeof(struct compat_xt_counters_info);
1352         } else
1353 #endif
1354         {
1355                 ptmp = &tmp;
1356                 size = sizeof(struct xt_counters_info);
1357         }
1358
1359         if (copy_from_user(ptmp, user, size) != 0)
1360                 return -EFAULT;
1361
1362 #ifdef CONFIG_COMPAT
1363         if (compat) {
1364                 num_counters = compat_tmp.num_counters;
1365                 name = compat_tmp.name;
1366         } else
1367 #endif
1368         {
1369                 num_counters = tmp.num_counters;
1370                 name = tmp.name;
1371         }
1372
1373         if (len != size + num_counters * sizeof(struct xt_counters))
1374                 return -EINVAL;
1375
1376         paddc = vmalloc_node(len - size, numa_node_id());
1377         if (!paddc)
1378                 return -ENOMEM;
1379
1380         if (copy_from_user(paddc, user + size, len - size) != 0) {
1381                 ret = -EFAULT;
1382                 goto free;
1383         }
1384
1385         t = xt_find_table_lock(net, AF_INET, name);
1386         if (!t || IS_ERR(t)) {
1387                 ret = t ? PTR_ERR(t) : -ENOENT;
1388                 goto free;
1389         }
1390
1391         local_bh_disable();
1392         private = t->private;
1393         if (private->number != num_counters) {
1394                 ret = -EINVAL;
1395                 goto unlock_up_free;
1396         }
1397
1398         i = 0;
1399         /* Choose the copy that is on our node */
1400         curcpu = smp_processor_id();
1401         loc_cpu_entry = private->entries[curcpu];
1402         xt_info_wrlock(curcpu);
1403         xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1404                 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1405                 ++i;
1406         }
1407         xt_info_wrunlock(curcpu);
1408  unlock_up_free:
1409         local_bh_enable();
1410         xt_table_unlock(t);
1411         module_put(t->me);
1412  free:
1413         vfree(paddc);
1414
1415         return ret;
1416 }
1417
1418 #ifdef CONFIG_COMPAT
1419 struct compat_ipt_replace {
1420         char                    name[IPT_TABLE_MAXNAMELEN];
1421         u32                     valid_hooks;
1422         u32                     num_entries;
1423         u32                     size;
1424         u32                     hook_entry[NF_INET_NUMHOOKS];
1425         u32                     underflow[NF_INET_NUMHOOKS];
1426         u32                     num_counters;
1427         compat_uptr_t           counters;       /* struct ipt_counters * */
1428         struct compat_ipt_entry entries[0];
1429 };
1430
1431 static int
1432 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1433                           unsigned int *size, struct xt_counters *counters,
1434                           unsigned int i)
1435 {
1436         struct ipt_entry_target *t;
1437         struct compat_ipt_entry __user *ce;
1438         u_int16_t target_offset, next_offset;
1439         compat_uint_t origsize;
1440         const struct xt_entry_match *ematch;
1441         int ret = 0;
1442
1443         origsize = *size;
1444         ce = (struct compat_ipt_entry __user *)*dstptr;
1445         if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
1446             copy_to_user(&ce->counters, &counters[i],
1447             sizeof(counters[i])) != 0)
1448                 return -EFAULT;
1449
1450         *dstptr += sizeof(struct compat_ipt_entry);
1451         *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1452
1453         xt_ematch_foreach(ematch, e) {
1454                 ret = xt_compat_match_to_user(ematch, dstptr, size);
1455                 if (ret != 0)
1456                         return ret;
1457         }
1458         target_offset = e->target_offset - (origsize - *size);
1459         t = ipt_get_target(e);
1460         ret = xt_compat_target_to_user(t, dstptr, size);
1461         if (ret)
1462                 return ret;
1463         next_offset = e->next_offset - (origsize - *size);
1464         if (put_user(target_offset, &ce->target_offset) != 0 ||
1465             put_user(next_offset, &ce->next_offset) != 0)
1466                 return -EFAULT;
1467         return 0;
1468 }
1469
1470 static int
1471 compat_find_calc_match(struct ipt_entry_match *m,
1472                        const char *name,
1473                        const struct ipt_ip *ip,
1474                        unsigned int hookmask,
1475                        int *size)
1476 {
1477         struct xt_match *match;
1478
1479         match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1480                                                       m->u.user.revision),
1481                                         "ipt_%s", m->u.user.name);
1482         if (IS_ERR(match) || !match) {
1483                 duprintf("compat_check_calc_match: `%s' not found\n",
1484                          m->u.user.name);
1485                 return match ? PTR_ERR(match) : -ENOENT;
1486         }
1487         m->u.kernel.match = match;
1488         *size += xt_compat_match_offset(match);
1489         return 0;
1490 }
1491
1492 static void compat_release_entry(struct compat_ipt_entry *e)
1493 {
1494         struct ipt_entry_target *t;
1495         struct xt_entry_match *ematch;
1496
1497         /* Cleanup all matches */
1498         xt_ematch_foreach(ematch, e)
1499                 module_put(ematch->u.kernel.match->me);
1500         t = compat_ipt_get_target(e);
1501         module_put(t->u.kernel.target->me);
1502 }
1503
1504 static int
1505 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1506                                   struct xt_table_info *newinfo,
1507                                   unsigned int *size,
1508                                   const unsigned char *base,
1509                                   const unsigned char *limit,
1510                                   const unsigned int *hook_entries,
1511                                   const unsigned int *underflows,
1512                                   const char *name)
1513 {
1514         struct xt_entry_match *ematch;
1515         struct ipt_entry_target *t;
1516         struct xt_target *target;
1517         unsigned int entry_offset;
1518         unsigned int j;
1519         int ret, off, h;
1520
1521         duprintf("check_compat_entry_size_and_hooks %p\n", e);
1522         if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1523             (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1524                 duprintf("Bad offset %p, limit = %p\n", e, limit);
1525                 return -EINVAL;
1526         }
1527
1528         if (e->next_offset < sizeof(struct compat_ipt_entry) +
1529                              sizeof(struct compat_xt_entry_target)) {
1530                 duprintf("checking: element %p size %u\n",
1531                          e, e->next_offset);
1532                 return -EINVAL;
1533         }
1534
1535         /* For purposes of check_entry casting the compat entry is fine */
1536         ret = check_entry((struct ipt_entry *)e, name);
1537         if (ret)
1538                 return ret;
1539
1540         off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1541         entry_offset = (void *)e - (void *)base;
1542         j = 0;
1543         xt_ematch_foreach(ematch, e) {
1544                 ret = compat_find_calc_match(ematch, name,
1545                                              &e->ip, e->comefrom, &off);
1546                 if (ret != 0)
1547                         goto release_matches;
1548                 ++j;
1549         }
1550
1551         t = compat_ipt_get_target(e);
1552         target = try_then_request_module(xt_find_target(AF_INET,
1553                                                         t->u.user.name,
1554                                                         t->u.user.revision),
1555                                          "ipt_%s", t->u.user.name);
1556         if (IS_ERR(target) || !target) {
1557                 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1558                          t->u.user.name);
1559                 ret = target ? PTR_ERR(target) : -ENOENT;
1560                 goto release_matches;
1561         }
1562         t->u.kernel.target = target;
1563
1564         off += xt_compat_target_offset(target);
1565         *size += off;
1566         ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1567         if (ret)
1568                 goto out;
1569
1570         /* Check hooks & underflows */
1571         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1572                 if ((unsigned char *)e - base == hook_entries[h])
1573                         newinfo->hook_entry[h] = hook_entries[h];
1574                 if ((unsigned char *)e - base == underflows[h])
1575                         newinfo->underflow[h] = underflows[h];
1576         }
1577
1578         /* Clear counters and comefrom */
1579         memset(&e->counters, 0, sizeof(e->counters));
1580         e->comefrom = 0;
1581         return 0;
1582
1583 out:
1584         module_put(t->u.kernel.target->me);
1585 release_matches:
1586         xt_ematch_foreach(ematch, e) {
1587                 if (j-- == 0)
1588                         break;
1589                 module_put(ematch->u.kernel.match->me);
1590         }
1591         return ret;
1592 }
1593
1594 static int
1595 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1596                             unsigned int *size, const char *name,
1597                             struct xt_table_info *newinfo, unsigned char *base)
1598 {
1599         struct ipt_entry_target *t;
1600         struct xt_target *target;
1601         struct ipt_entry *de;
1602         unsigned int origsize;
1603         int ret, h;
1604         struct xt_entry_match *ematch;
1605
1606         ret = 0;
1607         origsize = *size;
1608         de = (struct ipt_entry *)*dstptr;
1609         memcpy(de, e, sizeof(struct ipt_entry));
1610         memcpy(&de->counters, &e->counters, sizeof(e->counters));
1611
1612         *dstptr += sizeof(struct ipt_entry);
1613         *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1614
1615         xt_ematch_foreach(ematch, e) {
1616                 ret = xt_compat_match_from_user(ematch, dstptr, size);
1617                 if (ret != 0)
1618                         return ret;
1619         }
1620         de->target_offset = e->target_offset - (origsize - *size);
1621         t = compat_ipt_get_target(e);
1622         target = t->u.kernel.target;
1623         xt_compat_target_from_user(t, dstptr, size);
1624
1625         de->next_offset = e->next_offset - (origsize - *size);
1626         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1627                 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1628                         newinfo->hook_entry[h] -= origsize - *size;
1629                 if ((unsigned char *)de - base < newinfo->underflow[h])
1630                         newinfo->underflow[h] -= origsize - *size;
1631         }
1632         return ret;
1633 }
1634
1635 static int
1636 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1637 {
1638         struct xt_entry_match *ematch;
1639         struct xt_mtchk_param mtpar;
1640         unsigned int j;
1641         int ret = 0;
1642
1643         j = 0;
1644         mtpar.net       = net;
1645         mtpar.table     = name;
1646         mtpar.entryinfo = &e->ip;
1647         mtpar.hook_mask = e->comefrom;
1648         mtpar.family    = NFPROTO_IPV4;
1649         xt_ematch_foreach(ematch, e) {
1650                 ret = check_match(ematch, &mtpar);
1651                 if (ret != 0)
1652                         goto cleanup_matches;
1653                 ++j;
1654         }
1655
1656         ret = check_target(e, net, name);
1657         if (ret)
1658                 goto cleanup_matches;
1659         return 0;
1660
1661  cleanup_matches:
1662         xt_ematch_foreach(ematch, e) {
1663                 if (j-- == 0)
1664                         break;
1665                 cleanup_match(ematch, net);
1666         }
1667         return ret;
1668 }
1669
1670 static int
1671 translate_compat_table(struct net *net,
1672                        const char *name,
1673                        unsigned int valid_hooks,
1674                        struct xt_table_info **pinfo,
1675                        void **pentry0,
1676                        unsigned int total_size,
1677                        unsigned int number,
1678                        unsigned int *hook_entries,
1679                        unsigned int *underflows)
1680 {
1681         unsigned int i, j;
1682         struct xt_table_info *newinfo, *info;
1683         void *pos, *entry0, *entry1;
1684         struct compat_ipt_entry *iter0;
1685         struct ipt_entry *iter1;
1686         unsigned int size;
1687         int ret;
1688
1689         info = *pinfo;
1690         entry0 = *pentry0;
1691         size = total_size;
1692         info->number = number;
1693
1694         /* Init all hooks to impossible value. */
1695         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1696                 info->hook_entry[i] = 0xFFFFFFFF;
1697                 info->underflow[i] = 0xFFFFFFFF;
1698         }
1699
1700         duprintf("translate_compat_table: size %u\n", info->size);
1701         j = 0;
1702         xt_compat_lock(AF_INET);
1703         /* Walk through entries, checking offsets. */
1704         xt_entry_foreach(iter0, entry0, total_size) {
1705                 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1706                                                         entry0,
1707                                                         entry0 + total_size,
1708                                                         hook_entries,
1709                                                         underflows,
1710                                                         name);
1711                 if (ret != 0)
1712                         goto out_unlock;
1713                 ++j;
1714         }
1715
1716         ret = -EINVAL;
1717         if (j != number) {
1718                 duprintf("translate_compat_table: %u not %u entries\n",
1719                          j, number);
1720                 goto out_unlock;
1721         }
1722
1723         /* Check hooks all assigned */
1724         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1725                 /* Only hooks which are valid */
1726                 if (!(valid_hooks & (1 << i)))
1727                         continue;
1728                 if (info->hook_entry[i] == 0xFFFFFFFF) {
1729                         duprintf("Invalid hook entry %u %u\n",
1730                                  i, hook_entries[i]);
1731                         goto out_unlock;
1732                 }
1733                 if (info->underflow[i] == 0xFFFFFFFF) {
1734                         duprintf("Invalid underflow %u %u\n",
1735                                  i, underflows[i]);
1736                         goto out_unlock;
1737                 }
1738         }
1739
1740         ret = -ENOMEM;
1741         newinfo = xt_alloc_table_info(size);
1742         if (!newinfo)
1743                 goto out_unlock;
1744
1745         newinfo->number = number;
1746         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1747                 newinfo->hook_entry[i] = info->hook_entry[i];
1748                 newinfo->underflow[i] = info->underflow[i];
1749         }
1750         entry1 = newinfo->entries[raw_smp_processor_id()];
1751         pos = entry1;
1752         size = total_size;
1753         xt_entry_foreach(iter0, entry0, total_size) {
1754                 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1755                                                   name, newinfo, entry1);
1756                 if (ret != 0)
1757                         break;
1758         }
1759         xt_compat_flush_offsets(AF_INET);
1760         xt_compat_unlock(AF_INET);
1761         if (ret)
1762                 goto free_newinfo;
1763
1764         ret = -ELOOP;
1765         if (!mark_source_chains(newinfo, valid_hooks, entry1))
1766                 goto free_newinfo;
1767
1768         i = 0;
1769         xt_entry_foreach(iter1, entry1, newinfo->size) {
1770                 ret = compat_check_entry(iter1, net, name);
1771                 if (ret != 0)
1772                         break;
1773                 ++i;
1774         }
1775         if (ret) {
1776                 /*
1777                  * The first i matches need cleanup_entry (calls ->destroy)
1778                  * because they had called ->check already. The other j-i
1779                  * entries need only release.
1780                  */
1781                 int skip = i;
1782                 j -= i;
1783                 xt_entry_foreach(iter0, entry0, newinfo->size) {
1784                         if (skip-- > 0)
1785                                 continue;
1786                         if (j-- == 0)
1787                                 break;
1788                         compat_release_entry(iter0);
1789                 }
1790                 xt_entry_foreach(iter1, entry1, newinfo->size) {
1791                         if (i-- == 0)
1792                                 break;
1793                         cleanup_entry(iter1, net);
1794                 }
1795                 xt_free_table_info(newinfo);
1796                 return ret;
1797         }
1798
1799         /* And one copy for every other CPU */
1800         for_each_possible_cpu(i)
1801                 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1802                         memcpy(newinfo->entries[i], entry1, newinfo->size);
1803
1804         *pinfo = newinfo;
1805         *pentry0 = entry1;
1806         xt_free_table_info(info);
1807         return 0;
1808
1809 free_newinfo:
1810         xt_free_table_info(newinfo);
1811 out:
1812         xt_entry_foreach(iter0, entry0, total_size) {
1813                 if (j-- == 0)
1814                         break;
1815                 compat_release_entry(iter0);
1816         }
1817         return ret;
1818 out_unlock:
1819         xt_compat_flush_offsets(AF_INET);
1820         xt_compat_unlock(AF_INET);
1821         goto out;
1822 }
1823
1824 static int
1825 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1826 {
1827         int ret;
1828         struct compat_ipt_replace tmp;
1829         struct xt_table_info *newinfo;
1830         void *loc_cpu_entry;
1831         struct ipt_entry *iter;
1832
1833         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1834                 return -EFAULT;
1835
1836         /* overflow check */
1837         if (tmp.size >= INT_MAX / num_possible_cpus())
1838                 return -ENOMEM;
1839         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1840                 return -ENOMEM;
1841
1842         newinfo = xt_alloc_table_info(tmp.size);
1843         if (!newinfo)
1844                 return -ENOMEM;
1845
1846         /* choose the copy that is on our node/cpu */
1847         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1848         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1849                            tmp.size) != 0) {
1850                 ret = -EFAULT;
1851                 goto free_newinfo;
1852         }
1853
1854         ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1855                                      &newinfo, &loc_cpu_entry, tmp.size,
1856                                      tmp.num_entries, tmp.hook_entry,
1857                                      tmp.underflow);
1858         if (ret != 0)
1859                 goto free_newinfo;
1860
1861         duprintf("compat_do_replace: Translated table\n");
1862
1863         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1864                            tmp.num_counters, compat_ptr(tmp.counters));
1865         if (ret)
1866                 goto free_newinfo_untrans;
1867         return 0;
1868
1869  free_newinfo_untrans:
1870         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1871                 cleanup_entry(iter, net);
1872  free_newinfo:
1873         xt_free_table_info(newinfo);
1874         return ret;
1875 }
1876
1877 static int
1878 compat_do_ipt_set_ctl(struct sock *sk,  int cmd, void __user *user,
1879                       unsigned int len)
1880 {
1881         int ret;
1882
1883         if (!capable(CAP_NET_ADMIN))
1884                 return -EPERM;
1885
1886         switch (cmd) {
1887         case IPT_SO_SET_REPLACE:
1888                 ret = compat_do_replace(sock_net(sk), user, len);
1889                 break;
1890
1891         case IPT_SO_SET_ADD_COUNTERS:
1892                 ret = do_add_counters(sock_net(sk), user, len, 1);
1893                 break;
1894
1895         default:
1896                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
1897                 ret = -EINVAL;
1898         }
1899
1900         return ret;
1901 }
1902
1903 struct compat_ipt_get_entries {
1904         char name[IPT_TABLE_MAXNAMELEN];
1905         compat_uint_t size;
1906         struct compat_ipt_entry entrytable[0];
1907 };
1908
1909 static int
1910 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1911                             void __user *userptr)
1912 {
1913         struct xt_counters *counters;
1914         const struct xt_table_info *private = table->private;
1915         void __user *pos;
1916         unsigned int size;
1917         int ret = 0;
1918         const void *loc_cpu_entry;
1919         unsigned int i = 0;
1920         struct ipt_entry *iter;
1921
1922         counters = alloc_counters(table);
1923         if (IS_ERR(counters))
1924                 return PTR_ERR(counters);
1925
1926         /* choose the copy that is on our node/cpu, ...
1927          * This choice is lazy (because current thread is
1928          * allowed to migrate to another cpu)
1929          */
1930         loc_cpu_entry = private->entries[raw_smp_processor_id()];
1931         pos = userptr;
1932         size = total_size;
1933         xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1934                 ret = compat_copy_entry_to_user(iter, &pos,
1935                                                 &size, counters, i++);
1936                 if (ret != 0)
1937                         break;
1938         }
1939
1940         vfree(counters);
1941         return ret;
1942 }
1943
1944 static int
1945 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1946                    int *len)
1947 {
1948         int ret;
1949         struct compat_ipt_get_entries get;
1950         struct xt_table *t;
1951
1952         if (*len < sizeof(get)) {
1953                 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1954                 return -EINVAL;
1955         }
1956
1957         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1958                 return -EFAULT;
1959
1960         if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1961                 duprintf("compat_get_entries: %u != %zu\n",
1962                          *len, sizeof(get) + get.size);
1963                 return -EINVAL;
1964         }
1965
1966         xt_compat_lock(AF_INET);
1967         t = xt_find_table_lock(net, AF_INET, get.name);
1968         if (t && !IS_ERR(t)) {
1969                 const struct xt_table_info *private = t->private;
1970                 struct xt_table_info info;
1971                 duprintf("t->private->number = %u\n", private->number);
1972                 ret = compat_table_info(private, &info);
1973                 if (!ret && get.size == info.size) {
1974                         ret = compat_copy_entries_to_user(private->size,
1975                                                           t, uptr->entrytable);
1976                 } else if (!ret) {
1977                         duprintf("compat_get_entries: I've got %u not %u!\n",
1978                                  private->size, get.size);
1979                         ret = -EAGAIN;
1980                 }
1981                 xt_compat_flush_offsets(AF_INET);
1982                 module_put(t->me);
1983                 xt_table_unlock(t);
1984         } else
1985                 ret = t ? PTR_ERR(t) : -ENOENT;
1986
1987         xt_compat_unlock(AF_INET);
1988         return ret;
1989 }
1990
1991 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1992
1993 static int
1994 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1995 {
1996         int ret;
1997
1998         if (!capable(CAP_NET_ADMIN))
1999                 return -EPERM;
2000
2001         switch (cmd) {
2002         case IPT_SO_GET_INFO:
2003                 ret = get_info(sock_net(sk), user, len, 1);
2004                 break;
2005         case IPT_SO_GET_ENTRIES:
2006                 ret = compat_get_entries(sock_net(sk), user, len);
2007                 break;
2008         default:
2009                 ret = do_ipt_get_ctl(sk, cmd, user, len);
2010         }
2011         return ret;
2012 }
2013 #endif
2014
2015 static int
2016 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2017 {
2018         int ret;
2019
2020         if (!capable(CAP_NET_ADMIN))
2021                 return -EPERM;
2022
2023         switch (cmd) {
2024         case IPT_SO_SET_REPLACE:
2025                 ret = do_replace(sock_net(sk), user, len);
2026                 break;
2027
2028         case IPT_SO_SET_ADD_COUNTERS:
2029                 ret = do_add_counters(sock_net(sk), user, len, 0);
2030                 break;
2031
2032         default:
2033                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
2034                 ret = -EINVAL;
2035         }
2036
2037         return ret;
2038 }
2039
2040 static int
2041 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2042 {
2043         int ret;
2044
2045         if (!capable(CAP_NET_ADMIN))
2046                 return -EPERM;
2047
2048         switch (cmd) {
2049         case IPT_SO_GET_INFO:
2050                 ret = get_info(sock_net(sk), user, len, 0);
2051                 break;
2052
2053         case IPT_SO_GET_ENTRIES:
2054                 ret = get_entries(sock_net(sk), user, len);
2055                 break;
2056
2057         case IPT_SO_GET_REVISION_MATCH:
2058         case IPT_SO_GET_REVISION_TARGET: {
2059                 struct ipt_get_revision rev;
2060                 int target;
2061
2062                 if (*len != sizeof(rev)) {
2063                         ret = -EINVAL;
2064                         break;
2065                 }
2066                 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2067                         ret = -EFAULT;
2068                         break;
2069                 }
2070
2071                 if (cmd == IPT_SO_GET_REVISION_TARGET)
2072                         target = 1;
2073                 else
2074                         target = 0;
2075
2076                 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2077                                                          rev.revision,
2078                                                          target, &ret),
2079                                         "ipt_%s", rev.name);
2080                 break;
2081         }
2082
2083         default:
2084                 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2085                 ret = -EINVAL;
2086         }
2087
2088         return ret;
2089 }
2090
2091 struct xt_table *ipt_register_table(struct net *net,
2092                                     const struct xt_table *table,
2093                                     const struct ipt_replace *repl)
2094 {
2095         int ret;
2096         struct xt_table_info *newinfo;
2097         struct xt_table_info bootstrap
2098                 = { 0, 0, 0, { 0 }, { 0 }, { } };
2099         void *loc_cpu_entry;
2100         struct xt_table *new_table;
2101
2102         newinfo = xt_alloc_table_info(repl->size);
2103         if (!newinfo) {
2104                 ret = -ENOMEM;
2105                 goto out;
2106         }
2107
2108         /* choose the copy on our node/cpu, but dont care about preemption */
2109         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2110         memcpy(loc_cpu_entry, repl->entries, repl->size);
2111
2112         ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2113         if (ret != 0)
2114                 goto out_free;
2115
2116         new_table = xt_register_table(net, table, &bootstrap, newinfo);
2117         if (IS_ERR(new_table)) {
2118                 ret = PTR_ERR(new_table);
2119                 goto out_free;
2120         }
2121
2122         return new_table;
2123
2124 out_free:
2125         xt_free_table_info(newinfo);
2126 out:
2127         return ERR_PTR(ret);
2128 }
2129
2130 void ipt_unregister_table(struct net *net, struct xt_table *table)
2131 {
2132         struct xt_table_info *private;
2133         void *loc_cpu_entry;
2134         struct module *table_owner = table->me;
2135         struct ipt_entry *iter;
2136
2137         private = xt_unregister_table(table);
2138
2139         /* Decrease module usage counts and free resources */
2140         loc_cpu_entry = private->entries[raw_smp_processor_id()];
2141         xt_entry_foreach(iter, loc_cpu_entry, private->size)
2142                 cleanup_entry(iter, net);
2143         if (private->number > private->initial_entries)
2144                 module_put(table_owner);
2145         xt_free_table_info(private);
2146 }
2147
2148 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2149 static inline bool
2150 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2151                      u_int8_t type, u_int8_t code,
2152                      bool invert)
2153 {
2154         return ((test_type == 0xFF) ||
2155                 (type == test_type && code >= min_code && code <= max_code))
2156                 ^ invert;
2157 }
2158
2159 static bool
2160 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2161 {
2162         const struct icmphdr *ic;
2163         struct icmphdr _icmph;
2164         const struct ipt_icmp *icmpinfo = par->matchinfo;
2165
2166         /* Must not be a fragment. */
2167         if (par->fragoff != 0)
2168                 return false;
2169
2170         ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2171         if (ic == NULL) {
2172                 /* We've been asked to examine this packet, and we
2173                  * can't.  Hence, no choice but to drop.
2174                  */
2175                 duprintf("Dropping evil ICMP tinygram.\n");
2176                 *par->hotdrop = true;
2177                 return false;
2178         }
2179
2180         return icmp_type_code_match(icmpinfo->type,
2181                                     icmpinfo->code[0],
2182                                     icmpinfo->code[1],
2183                                     ic->type, ic->code,
2184                                     !!(icmpinfo->invflags&IPT_ICMP_INV));
2185 }
2186
2187 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2188 {
2189         const struct ipt_icmp *icmpinfo = par->matchinfo;
2190
2191         /* Must specify no unknown invflags */
2192         return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2193 }
2194
2195 /* The built-in targets: standard (NULL) and error. */
2196 static struct xt_target ipt_standard_target __read_mostly = {
2197         .name           = IPT_STANDARD_TARGET,
2198         .targetsize     = sizeof(int),
2199         .family         = NFPROTO_IPV4,
2200 #ifdef CONFIG_COMPAT
2201         .compatsize     = sizeof(compat_int_t),
2202         .compat_from_user = compat_standard_from_user,
2203         .compat_to_user = compat_standard_to_user,
2204 #endif
2205 };
2206
2207 static struct xt_target ipt_error_target __read_mostly = {
2208         .name           = IPT_ERROR_TARGET,
2209         .target         = ipt_error,
2210         .targetsize     = IPT_FUNCTION_MAXNAMELEN,
2211         .family         = NFPROTO_IPV4,
2212 };
2213
2214 static struct nf_sockopt_ops ipt_sockopts = {
2215         .pf             = PF_INET,
2216         .set_optmin     = IPT_BASE_CTL,
2217         .set_optmax     = IPT_SO_SET_MAX+1,
2218         .set            = do_ipt_set_ctl,
2219 #ifdef CONFIG_COMPAT
2220         .compat_set     = compat_do_ipt_set_ctl,
2221 #endif
2222         .get_optmin     = IPT_BASE_CTL,
2223         .get_optmax     = IPT_SO_GET_MAX+1,
2224         .get            = do_ipt_get_ctl,
2225 #ifdef CONFIG_COMPAT
2226         .compat_get     = compat_do_ipt_get_ctl,
2227 #endif
2228         .owner          = THIS_MODULE,
2229 };
2230
2231 static struct xt_match icmp_matchstruct __read_mostly = {
2232         .name           = "icmp",
2233         .match          = icmp_match,
2234         .matchsize      = sizeof(struct ipt_icmp),
2235         .checkentry     = icmp_checkentry,
2236         .proto          = IPPROTO_ICMP,
2237         .family         = NFPROTO_IPV4,
2238 };
2239
2240 static int __net_init ip_tables_net_init(struct net *net)
2241 {
2242         return xt_proto_init(net, NFPROTO_IPV4);
2243 }
2244
2245 static void __net_exit ip_tables_net_exit(struct net *net)
2246 {
2247         xt_proto_fini(net, NFPROTO_IPV4);
2248 }
2249
2250 static struct pernet_operations ip_tables_net_ops = {
2251         .init = ip_tables_net_init,
2252         .exit = ip_tables_net_exit,
2253 };
2254
2255 static int __init ip_tables_init(void)
2256 {
2257         int ret;
2258
2259         ret = register_pernet_subsys(&ip_tables_net_ops);
2260         if (ret < 0)
2261                 goto err1;
2262
2263         /* Noone else will be downing sem now, so we won't sleep */
2264         ret = xt_register_target(&ipt_standard_target);
2265         if (ret < 0)
2266                 goto err2;
2267         ret = xt_register_target(&ipt_error_target);
2268         if (ret < 0)
2269                 goto err3;
2270         ret = xt_register_match(&icmp_matchstruct);
2271         if (ret < 0)
2272                 goto err4;
2273
2274         /* Register setsockopt */
2275         ret = nf_register_sockopt(&ipt_sockopts);
2276         if (ret < 0)
2277                 goto err5;
2278
2279         printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2280         return 0;
2281
2282 err5:
2283         xt_unregister_match(&icmp_matchstruct);
2284 err4:
2285         xt_unregister_target(&ipt_error_target);
2286 err3:
2287         xt_unregister_target(&ipt_standard_target);
2288 err2:
2289         unregister_pernet_subsys(&ip_tables_net_ops);
2290 err1:
2291         return ret;
2292 }
2293
2294 static void __exit ip_tables_fini(void)
2295 {
2296         nf_unregister_sockopt(&ipt_sockopts);
2297
2298         xt_unregister_match(&icmp_matchstruct);
2299         xt_unregister_target(&ipt_error_target);
2300         xt_unregister_target(&ipt_standard_target);
2301
2302         unregister_pernet_subsys(&ip_tables_net_ops);
2303 }
2304
2305 EXPORT_SYMBOL(ipt_register_table);
2306 EXPORT_SYMBOL(ipt_unregister_table);
2307 EXPORT_SYMBOL(ipt_do_table);
2308 module_init(ip_tables_init);
2309 module_exit(ip_tables_fini);