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