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