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