]> bbs.cooldavid.org Git - net-next-2.6.git/blob - net/ipv4/netfilter/ip_tables.c
73fdf20263ed402d17e593a4ce10e1c16290cd04
[net-next-2.6.git] / net / ipv4 / netfilter / ip_tables.c
1 /*
2  * Packet matching code.
3  *
4  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5  * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/cache.h>
13 #include <linux/capability.h>
14 #include <linux/skbuff.h>
15 #include <linux/kmod.h>
16 #include <linux/vmalloc.h>
17 #include <linux/netdevice.h>
18 #include <linux/module.h>
19 #include <linux/icmp.h>
20 #include <net/ip.h>
21 #include <net/compat.h>
22 #include <asm/uaccess.h>
23 #include <linux/mutex.h>
24 #include <linux/proc_fs.h>
25 #include <linux/err.h>
26 #include <linux/cpumask.h>
27
28 #include <linux/netfilter/x_tables.h>
29 #include <linux/netfilter_ipv4/ip_tables.h>
30 #include <net/netfilter/nf_log.h>
31 #include "../../netfilter/xt_repldata.h"
32
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
35 MODULE_DESCRIPTION("IPv4 packet filter");
36
37 /*#define DEBUG_IP_FIREWALL*/
38 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
39 /*#define DEBUG_IP_FIREWALL_USER*/
40
41 #ifdef DEBUG_IP_FIREWALL
42 #define dprintf(format, args...) 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 = try_then_request_module(xt_find_target(AF_INET,
705                                                         t->u.user.name,
706                                                         t->u.user.revision),
707                                          "ipt_%s", t->u.user.name);
708         if (IS_ERR(target) || !target) {
709                 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
710                 ret = target ? PTR_ERR(target) : -ENOENT;
711                 goto cleanup_matches;
712         }
713         t->u.kernel.target = target;
714
715         ret = check_target(e, net, name);
716         if (ret)
717                 goto err;
718         return 0;
719  err:
720         module_put(t->u.kernel.target->me);
721  cleanup_matches:
722         xt_ematch_foreach(ematch, e) {
723                 if (j-- == 0)
724                         break;
725                 cleanup_match(ematch, net);
726         }
727         return ret;
728 }
729
730 static bool check_underflow(const struct ipt_entry *e)
731 {
732         const struct ipt_entry_target *t;
733         unsigned int verdict;
734
735         if (!unconditional(&e->ip))
736                 return false;
737         t = ipt_get_target_c(e);
738         if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
739                 return false;
740         verdict = ((struct ipt_standard_target *)t)->verdict;
741         verdict = -verdict - 1;
742         return verdict == NF_DROP || verdict == NF_ACCEPT;
743 }
744
745 static int
746 check_entry_size_and_hooks(struct ipt_entry *e,
747                            struct xt_table_info *newinfo,
748                            const unsigned char *base,
749                            const unsigned char *limit,
750                            const unsigned int *hook_entries,
751                            const unsigned int *underflows,
752                            unsigned int valid_hooks)
753 {
754         unsigned int h;
755
756         if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
757             (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
758                 duprintf("Bad offset %p\n", e);
759                 return -EINVAL;
760         }
761
762         if (e->next_offset
763             < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
764                 duprintf("checking: element %p size %u\n",
765                          e, e->next_offset);
766                 return -EINVAL;
767         }
768
769         /* Check hooks & underflows */
770         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
771                 if (!(valid_hooks & (1 << h)))
772                         continue;
773                 if ((unsigned char *)e - base == hook_entries[h])
774                         newinfo->hook_entry[h] = hook_entries[h];
775                 if ((unsigned char *)e - base == underflows[h]) {
776                         if (!check_underflow(e)) {
777                                 pr_err("Underflows must be unconditional and "
778                                        "use the STANDARD target with "
779                                        "ACCEPT/DROP\n");
780                                 return -EINVAL;
781                         }
782                         newinfo->underflow[h] = underflows[h];
783                 }
784         }
785
786         /* Clear counters and comefrom */
787         e->counters = ((struct xt_counters) { 0, 0 });
788         e->comefrom = 0;
789         return 0;
790 }
791
792 static void
793 cleanup_entry(struct ipt_entry *e, struct net *net)
794 {
795         struct xt_tgdtor_param par;
796         struct ipt_entry_target *t;
797         struct xt_entry_match *ematch;
798
799         /* Cleanup all matches */
800         xt_ematch_foreach(ematch, e)
801                 cleanup_match(ematch, net);
802         t = ipt_get_target(e);
803
804         par.net      = net;
805         par.target   = t->u.kernel.target;
806         par.targinfo = t->data;
807         par.family   = NFPROTO_IPV4;
808         if (par.target->destroy != NULL)
809                 par.target->destroy(&par);
810         module_put(par.target->me);
811 }
812
813 /* Checks and translates the user-supplied table segment (held in
814    newinfo) */
815 static int
816 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
817                 const struct ipt_replace *repl)
818 {
819         struct ipt_entry *iter;
820         unsigned int i;
821         int ret = 0;
822
823         newinfo->size = repl->size;
824         newinfo->number = repl->num_entries;
825
826         /* Init all hooks to impossible value. */
827         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
828                 newinfo->hook_entry[i] = 0xFFFFFFFF;
829                 newinfo->underflow[i] = 0xFFFFFFFF;
830         }
831
832         duprintf("translate_table: size %u\n", newinfo->size);
833         i = 0;
834         /* Walk through entries, checking offsets. */
835         xt_entry_foreach(iter, entry0, newinfo->size) {
836                 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
837                                                  entry0 + repl->size,
838                                                  repl->hook_entry,
839                                                  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("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,
1705                                                         entry0 + total_size,
1706                                                         hook_entries,
1707                                                         underflows,
1708                                                         name);
1709                 if (ret != 0)
1710                         goto out_unlock;
1711                 ++j;
1712         }
1713
1714         ret = -EINVAL;
1715         if (j != number) {
1716                 duprintf("translate_compat_table: %u not %u entries\n",
1717                          j, number);
1718                 goto out_unlock;
1719         }
1720
1721         /* Check hooks all assigned */
1722         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1723                 /* Only hooks which are valid */
1724                 if (!(valid_hooks & (1 << i)))
1725                         continue;
1726                 if (info->hook_entry[i] == 0xFFFFFFFF) {
1727                         duprintf("Invalid hook entry %u %u\n",
1728                                  i, hook_entries[i]);
1729                         goto out_unlock;
1730                 }
1731                 if (info->underflow[i] == 0xFFFFFFFF) {
1732                         duprintf("Invalid underflow %u %u\n",
1733                                  i, underflows[i]);
1734                         goto out_unlock;
1735                 }
1736         }
1737
1738         ret = -ENOMEM;
1739         newinfo = xt_alloc_table_info(size);
1740         if (!newinfo)
1741                 goto out_unlock;
1742
1743         newinfo->number = number;
1744         for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1745                 newinfo->hook_entry[i] = info->hook_entry[i];
1746                 newinfo->underflow[i] = info->underflow[i];
1747         }
1748         entry1 = newinfo->entries[raw_smp_processor_id()];
1749         pos = entry1;
1750         size = total_size;
1751         xt_entry_foreach(iter0, entry0, total_size) {
1752                 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1753                                                   name, newinfo, entry1);
1754                 if (ret != 0)
1755                         break;
1756         }
1757         xt_compat_flush_offsets(AF_INET);
1758         xt_compat_unlock(AF_INET);
1759         if (ret)
1760                 goto free_newinfo;
1761
1762         ret = -ELOOP;
1763         if (!mark_source_chains(newinfo, valid_hooks, entry1))
1764                 goto free_newinfo;
1765
1766         i = 0;
1767         xt_entry_foreach(iter1, entry1, newinfo->size) {
1768                 ret = compat_check_entry(iter1, net, name);
1769                 if (ret != 0)
1770                         break;
1771                 ++i;
1772         }
1773         if (ret) {
1774                 /*
1775                  * The first i matches need cleanup_entry (calls ->destroy)
1776                  * because they had called ->check already. The other j-i
1777                  * entries need only release.
1778                  */
1779                 int skip = i;
1780                 j -= i;
1781                 xt_entry_foreach(iter0, entry0, newinfo->size) {
1782                         if (skip-- > 0)
1783                                 continue;
1784                         if (j-- == 0)
1785                                 break;
1786                         compat_release_entry(iter0);
1787                 }
1788                 xt_entry_foreach(iter1, entry1, newinfo->size) {
1789                         if (i-- == 0)
1790                                 break;
1791                         cleanup_entry(iter1, net);
1792                 }
1793                 xt_free_table_info(newinfo);
1794                 return ret;
1795         }
1796
1797         /* And one copy for every other CPU */
1798         for_each_possible_cpu(i)
1799                 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1800                         memcpy(newinfo->entries[i], entry1, newinfo->size);
1801
1802         *pinfo = newinfo;
1803         *pentry0 = entry1;
1804         xt_free_table_info(info);
1805         return 0;
1806
1807 free_newinfo:
1808         xt_free_table_info(newinfo);
1809 out:
1810         xt_entry_foreach(iter0, entry0, total_size) {
1811                 if (j-- == 0)
1812                         break;
1813                 compat_release_entry(iter0);
1814         }
1815         return ret;
1816 out_unlock:
1817         xt_compat_flush_offsets(AF_INET);
1818         xt_compat_unlock(AF_INET);
1819         goto out;
1820 }
1821
1822 static int
1823 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1824 {
1825         int ret;
1826         struct compat_ipt_replace tmp;
1827         struct xt_table_info *newinfo;
1828         void *loc_cpu_entry;
1829         struct ipt_entry *iter;
1830
1831         if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1832                 return -EFAULT;
1833
1834         /* overflow check */
1835         if (tmp.size >= INT_MAX / num_possible_cpus())
1836                 return -ENOMEM;
1837         if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1838                 return -ENOMEM;
1839
1840         newinfo = xt_alloc_table_info(tmp.size);
1841         if (!newinfo)
1842                 return -ENOMEM;
1843
1844         /* choose the copy that is on our node/cpu */
1845         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1846         if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1847                            tmp.size) != 0) {
1848                 ret = -EFAULT;
1849                 goto free_newinfo;
1850         }
1851
1852         ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1853                                      &newinfo, &loc_cpu_entry, tmp.size,
1854                                      tmp.num_entries, tmp.hook_entry,
1855                                      tmp.underflow);
1856         if (ret != 0)
1857                 goto free_newinfo;
1858
1859         duprintf("compat_do_replace: Translated table\n");
1860
1861         ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1862                            tmp.num_counters, compat_ptr(tmp.counters));
1863         if (ret)
1864                 goto free_newinfo_untrans;
1865         return 0;
1866
1867  free_newinfo_untrans:
1868         xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1869                 cleanup_entry(iter, net);
1870  free_newinfo:
1871         xt_free_table_info(newinfo);
1872         return ret;
1873 }
1874
1875 static int
1876 compat_do_ipt_set_ctl(struct sock *sk,  int cmd, void __user *user,
1877                       unsigned int len)
1878 {
1879         int ret;
1880
1881         if (!capable(CAP_NET_ADMIN))
1882                 return -EPERM;
1883
1884         switch (cmd) {
1885         case IPT_SO_SET_REPLACE:
1886                 ret = compat_do_replace(sock_net(sk), user, len);
1887                 break;
1888
1889         case IPT_SO_SET_ADD_COUNTERS:
1890                 ret = do_add_counters(sock_net(sk), user, len, 1);
1891                 break;
1892
1893         default:
1894                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
1895                 ret = -EINVAL;
1896         }
1897
1898         return ret;
1899 }
1900
1901 struct compat_ipt_get_entries {
1902         char name[IPT_TABLE_MAXNAMELEN];
1903         compat_uint_t size;
1904         struct compat_ipt_entry entrytable[0];
1905 };
1906
1907 static int
1908 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1909                             void __user *userptr)
1910 {
1911         struct xt_counters *counters;
1912         const struct xt_table_info *private = table->private;
1913         void __user *pos;
1914         unsigned int size;
1915         int ret = 0;
1916         const void *loc_cpu_entry;
1917         unsigned int i = 0;
1918         struct ipt_entry *iter;
1919
1920         counters = alloc_counters(table);
1921         if (IS_ERR(counters))
1922                 return PTR_ERR(counters);
1923
1924         /* choose the copy that is on our node/cpu, ...
1925          * This choice is lazy (because current thread is
1926          * allowed to migrate to another cpu)
1927          */
1928         loc_cpu_entry = private->entries[raw_smp_processor_id()];
1929         pos = userptr;
1930         size = total_size;
1931         xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1932                 ret = compat_copy_entry_to_user(iter, &pos,
1933                                                 &size, counters, i++);
1934                 if (ret != 0)
1935                         break;
1936         }
1937
1938         vfree(counters);
1939         return ret;
1940 }
1941
1942 static int
1943 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1944                    int *len)
1945 {
1946         int ret;
1947         struct compat_ipt_get_entries get;
1948         struct xt_table *t;
1949
1950         if (*len < sizeof(get)) {
1951                 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1952                 return -EINVAL;
1953         }
1954
1955         if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1956                 return -EFAULT;
1957
1958         if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1959                 duprintf("compat_get_entries: %u != %zu\n",
1960                          *len, sizeof(get) + get.size);
1961                 return -EINVAL;
1962         }
1963
1964         xt_compat_lock(AF_INET);
1965         t = xt_find_table_lock(net, AF_INET, get.name);
1966         if (t && !IS_ERR(t)) {
1967                 const struct xt_table_info *private = t->private;
1968                 struct xt_table_info info;
1969                 duprintf("t->private->number = %u\n", private->number);
1970                 ret = compat_table_info(private, &info);
1971                 if (!ret && get.size == info.size) {
1972                         ret = compat_copy_entries_to_user(private->size,
1973                                                           t, uptr->entrytable);
1974                 } else if (!ret) {
1975                         duprintf("compat_get_entries: I've got %u not %u!\n",
1976                                  private->size, get.size);
1977                         ret = -EAGAIN;
1978                 }
1979                 xt_compat_flush_offsets(AF_INET);
1980                 module_put(t->me);
1981                 xt_table_unlock(t);
1982         } else
1983                 ret = t ? PTR_ERR(t) : -ENOENT;
1984
1985         xt_compat_unlock(AF_INET);
1986         return ret;
1987 }
1988
1989 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1990
1991 static int
1992 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1993 {
1994         int ret;
1995
1996         if (!capable(CAP_NET_ADMIN))
1997                 return -EPERM;
1998
1999         switch (cmd) {
2000         case IPT_SO_GET_INFO:
2001                 ret = get_info(sock_net(sk), user, len, 1);
2002                 break;
2003         case IPT_SO_GET_ENTRIES:
2004                 ret = compat_get_entries(sock_net(sk), user, len);
2005                 break;
2006         default:
2007                 ret = do_ipt_get_ctl(sk, cmd, user, len);
2008         }
2009         return ret;
2010 }
2011 #endif
2012
2013 static int
2014 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2015 {
2016         int ret;
2017
2018         if (!capable(CAP_NET_ADMIN))
2019                 return -EPERM;
2020
2021         switch (cmd) {
2022         case IPT_SO_SET_REPLACE:
2023                 ret = do_replace(sock_net(sk), user, len);
2024                 break;
2025
2026         case IPT_SO_SET_ADD_COUNTERS:
2027                 ret = do_add_counters(sock_net(sk), user, len, 0);
2028                 break;
2029
2030         default:
2031                 duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
2032                 ret = -EINVAL;
2033         }
2034
2035         return ret;
2036 }
2037
2038 static int
2039 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2040 {
2041         int ret;
2042
2043         if (!capable(CAP_NET_ADMIN))
2044                 return -EPERM;
2045
2046         switch (cmd) {
2047         case IPT_SO_GET_INFO:
2048                 ret = get_info(sock_net(sk), user, len, 0);
2049                 break;
2050
2051         case IPT_SO_GET_ENTRIES:
2052                 ret = get_entries(sock_net(sk), user, len);
2053                 break;
2054
2055         case IPT_SO_GET_REVISION_MATCH:
2056         case IPT_SO_GET_REVISION_TARGET: {
2057                 struct ipt_get_revision rev;
2058                 int target;
2059
2060                 if (*len != sizeof(rev)) {
2061                         ret = -EINVAL;
2062                         break;
2063                 }
2064                 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2065                         ret = -EFAULT;
2066                         break;
2067                 }
2068
2069                 if (cmd == IPT_SO_GET_REVISION_TARGET)
2070                         target = 1;
2071                 else
2072                         target = 0;
2073
2074                 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2075                                                          rev.revision,
2076                                                          target, &ret),
2077                                         "ipt_%s", rev.name);
2078                 break;
2079         }
2080
2081         default:
2082                 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2083                 ret = -EINVAL;
2084         }
2085
2086         return ret;
2087 }
2088
2089 struct xt_table *ipt_register_table(struct net *net,
2090                                     const struct xt_table *table,
2091                                     const struct ipt_replace *repl)
2092 {
2093         int ret;
2094         struct xt_table_info *newinfo;
2095         struct xt_table_info bootstrap
2096                 = { 0, 0, 0, { 0 }, { 0 }, { } };
2097         void *loc_cpu_entry;
2098         struct xt_table *new_table;
2099
2100         newinfo = xt_alloc_table_info(repl->size);
2101         if (!newinfo) {
2102                 ret = -ENOMEM;
2103                 goto out;
2104         }
2105
2106         /* choose the copy on our node/cpu, but dont care about preemption */
2107         loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2108         memcpy(loc_cpu_entry, repl->entries, repl->size);
2109
2110         ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2111         if (ret != 0)
2112                 goto out_free;
2113
2114         new_table = xt_register_table(net, table, &bootstrap, newinfo);
2115         if (IS_ERR(new_table)) {
2116                 ret = PTR_ERR(new_table);
2117                 goto out_free;
2118         }
2119
2120         return new_table;
2121
2122 out_free:
2123         xt_free_table_info(newinfo);
2124 out:
2125         return ERR_PTR(ret);
2126 }
2127
2128 void ipt_unregister_table(struct net *net, struct xt_table *table)
2129 {
2130         struct xt_table_info *private;
2131         void *loc_cpu_entry;
2132         struct module *table_owner = table->me;
2133         struct ipt_entry *iter;
2134
2135         private = xt_unregister_table(table);
2136
2137         /* Decrease module usage counts and free resources */
2138         loc_cpu_entry = private->entries[raw_smp_processor_id()];
2139         xt_entry_foreach(iter, loc_cpu_entry, private->size)
2140                 cleanup_entry(iter, net);
2141         if (private->number > private->initial_entries)
2142                 module_put(table_owner);
2143         xt_free_table_info(private);
2144 }
2145
2146 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2147 static inline bool
2148 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2149                      u_int8_t type, u_int8_t code,
2150                      bool invert)
2151 {
2152         return ((test_type == 0xFF) ||
2153                 (type == test_type && code >= min_code && code <= max_code))
2154                 ^ invert;
2155 }
2156
2157 static bool
2158 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2159 {
2160         const struct icmphdr *ic;
2161         struct icmphdr _icmph;
2162         const struct ipt_icmp *icmpinfo = par->matchinfo;
2163
2164         /* Must not be a fragment. */
2165         if (par->fragoff != 0)
2166                 return false;
2167
2168         ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2169         if (ic == NULL) {
2170                 /* We've been asked to examine this packet, and we
2171                  * can't.  Hence, no choice but to drop.
2172                  */
2173                 duprintf("Dropping evil ICMP tinygram.\n");
2174                 *par->hotdrop = true;
2175                 return false;
2176         }
2177
2178         return icmp_type_code_match(icmpinfo->type,
2179                                     icmpinfo->code[0],
2180                                     icmpinfo->code[1],
2181                                     ic->type, ic->code,
2182                                     !!(icmpinfo->invflags&IPT_ICMP_INV));
2183 }
2184
2185 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2186 {
2187         const struct ipt_icmp *icmpinfo = par->matchinfo;
2188
2189         /* Must specify no unknown invflags */
2190         return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2191 }
2192
2193 /* The built-in targets: standard (NULL) and error. */
2194 static struct xt_target ipt_standard_target __read_mostly = {
2195         .name           = IPT_STANDARD_TARGET,
2196         .targetsize     = sizeof(int),
2197         .family         = NFPROTO_IPV4,
2198 #ifdef CONFIG_COMPAT
2199         .compatsize     = sizeof(compat_int_t),
2200         .compat_from_user = compat_standard_from_user,
2201         .compat_to_user = compat_standard_to_user,
2202 #endif
2203 };
2204
2205 static struct xt_target ipt_error_target __read_mostly = {
2206         .name           = IPT_ERROR_TARGET,
2207         .target         = ipt_error,
2208         .targetsize     = IPT_FUNCTION_MAXNAMELEN,
2209         .family         = NFPROTO_IPV4,
2210 };
2211
2212 static struct nf_sockopt_ops ipt_sockopts = {
2213         .pf             = PF_INET,
2214         .set_optmin     = IPT_BASE_CTL,
2215         .set_optmax     = IPT_SO_SET_MAX+1,
2216         .set            = do_ipt_set_ctl,
2217 #ifdef CONFIG_COMPAT
2218         .compat_set     = compat_do_ipt_set_ctl,
2219 #endif
2220         .get_optmin     = IPT_BASE_CTL,
2221         .get_optmax     = IPT_SO_GET_MAX+1,
2222         .get            = do_ipt_get_ctl,
2223 #ifdef CONFIG_COMPAT
2224         .compat_get     = compat_do_ipt_get_ctl,
2225 #endif
2226         .owner          = THIS_MODULE,
2227 };
2228
2229 static struct xt_match icmp_matchstruct __read_mostly = {
2230         .name           = "icmp",
2231         .match          = icmp_match,
2232         .matchsize      = sizeof(struct ipt_icmp),
2233         .checkentry     = icmp_checkentry,
2234         .proto          = IPPROTO_ICMP,
2235         .family         = NFPROTO_IPV4,
2236 };
2237
2238 static int __net_init ip_tables_net_init(struct net *net)
2239 {
2240         return xt_proto_init(net, NFPROTO_IPV4);
2241 }
2242
2243 static void __net_exit ip_tables_net_exit(struct net *net)
2244 {
2245         xt_proto_fini(net, NFPROTO_IPV4);
2246 }
2247
2248 static struct pernet_operations ip_tables_net_ops = {
2249         .init = ip_tables_net_init,
2250         .exit = ip_tables_net_exit,
2251 };
2252
2253 static int __init ip_tables_init(void)
2254 {
2255         int ret;
2256
2257         ret = register_pernet_subsys(&ip_tables_net_ops);
2258         if (ret < 0)
2259                 goto err1;
2260
2261         /* Noone else will be downing sem now, so we won't sleep */
2262         ret = xt_register_target(&ipt_standard_target);
2263         if (ret < 0)
2264                 goto err2;
2265         ret = xt_register_target(&ipt_error_target);
2266         if (ret < 0)
2267                 goto err3;
2268         ret = xt_register_match(&icmp_matchstruct);
2269         if (ret < 0)
2270                 goto err4;
2271
2272         /* Register setsockopt */
2273         ret = nf_register_sockopt(&ipt_sockopts);
2274         if (ret < 0)
2275                 goto err5;
2276
2277         pr_info("(C) 2000-2006 Netfilter Core Team\n");
2278         return 0;
2279
2280 err5:
2281         xt_unregister_match(&icmp_matchstruct);
2282 err4:
2283         xt_unregister_target(&ipt_error_target);
2284 err3:
2285         xt_unregister_target(&ipt_standard_target);
2286 err2:
2287         unregister_pernet_subsys(&ip_tables_net_ops);
2288 err1:
2289         return ret;
2290 }
2291
2292 static void __exit ip_tables_fini(void)
2293 {
2294         nf_unregister_sockopt(&ipt_sockopts);
2295
2296         xt_unregister_match(&icmp_matchstruct);
2297         xt_unregister_target(&ipt_error_target);
2298         xt_unregister_target(&ipt_standard_target);
2299
2300         unregister_pernet_subsys(&ip_tables_net_ops);
2301 }
2302
2303 EXPORT_SYMBOL(ipt_register_table);
2304 EXPORT_SYMBOL(ipt_unregister_table);
2305 EXPORT_SYMBOL(ipt_do_table);
2306 module_init(ip_tables_init);
2307 module_exit(ip_tables_fini);