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