netfilter: xtables: remove some goto
[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                 } else {
406                         /* Targets which reenter must return
407                            abs. verdicts */
408                         tgpar.target   = t->u.kernel.target;
409                         tgpar.targinfo = t->data;
410 #ifdef CONFIG_NETFILTER_DEBUG
411                         ((struct ipt_entry *)table_base)->comefrom
412                                 = 0xeeeeeeec;
413 #endif
414                         verdict = t->u.kernel.target->target(skb, &tgpar);
415 #ifdef CONFIG_NETFILTER_DEBUG
416                         if (((struct ipt_entry *)table_base)->comefrom
417                             != 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
424                                 = 0x57acc001;
425 #endif
426                         /* Target might have changed stuff. */
427                         ip = ip_hdr(skb);
428                         datalen = skb->len - ip->ihl * 4;
429
430                         if (verdict == IPT_CONTINUE)
431                                 e = ipt_next_entry(e);
432                         else
433                                 /* Verdict */
434                                 break;
435                 }
436         } while (!hotdrop);
437         xt_info_rdunlock_bh();
438
439 #ifdef DEBUG_ALLOW_ALL
440         return NF_ACCEPT;
441 #else
442         if (hotdrop)
443                 return NF_DROP;
444         else return verdict;
445 #endif
446 }
447
448 /* Figures out from what hook each rule can be called: returns 0 if
449    there are loops.  Puts hook bitmask in comefrom. */
450 static int
451 mark_source_chains(struct xt_table_info *newinfo,
452                    unsigned int valid_hooks, void *entry0)
453 {
454         unsigned int hook;
455
456         /* No recursion; use packet counter to save back ptrs (reset
457            to 0 as we leave), and comefrom to save source hook bitmask */
458         for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
459                 unsigned int pos = newinfo->hook_entry[hook];
460                 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
461
462                 if (!(valid_hooks & (1 << hook)))
463                         continue;
464
465                 /* Set initial back pointer. */
466                 e->counters.pcnt = pos;
467
468                 for (;;) {
469                         struct ipt_standard_target *t
470                                 = (void *)ipt_get_target(e);
471                         int visited = e->comefrom & (1 << hook);
472
473                         if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
474                                 printk("iptables: loop hook %u pos %u %08X.\n",
475                                        hook, pos, e->comefrom);
476                                 return 0;
477                         }
478                         e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
479
480                         /* Unconditional return/END. */
481                         if ((e->target_offset == sizeof(struct ipt_entry)
482                             && (strcmp(t->target.u.user.name,
483                                        IPT_STANDARD_TARGET) == 0)
484                             && t->verdict < 0
485                             && unconditional(&e->ip)) || visited) {
486                                 unsigned int oldpos, size;
487
488                                 if ((strcmp(t->target.u.user.name,
489                                             IPT_STANDARD_TARGET) == 0) &&
490                                     t->verdict < -NF_MAX_VERDICT - 1) {
491                                         duprintf("mark_source_chains: bad "
492                                                 "negative verdict (%i)\n",
493                                                                 t->verdict);
494                                         return 0;
495                                 }
496
497                                 /* Return: backtrack through the last
498                                    big jump. */
499                                 do {
500                                         e->comefrom ^= (1<<NF_INET_NUMHOOKS);
501 #ifdef DEBUG_IP_FIREWALL_USER
502                                         if (e->comefrom
503                                             & (1 << NF_INET_NUMHOOKS)) {
504                                                 duprintf("Back unset "
505                                                          "on hook %u "
506                                                          "rule %u\n",
507                                                          hook, pos);
508                                         }
509 #endif
510                                         oldpos = pos;
511                                         pos = e->counters.pcnt;
512                                         e->counters.pcnt = 0;
513
514                                         /* We're at the start. */
515                                         if (pos == oldpos)
516                                                 goto next;
517
518                                         e = (struct ipt_entry *)
519                                                 (entry0 + pos);
520                                 } while (oldpos == pos + e->next_offset);
521
522                                 /* Move along one */
523                                 size = e->next_offset;
524                                 e = (struct ipt_entry *)
525                                         (entry0 + pos + size);
526                                 e->counters.pcnt = pos;
527                                 pos += size;
528                         } else {
529                                 int newpos = t->verdict;
530
531                                 if (strcmp(t->target.u.user.name,
532                                            IPT_STANDARD_TARGET) == 0
533                                     && newpos >= 0) {
534                                         if (newpos > newinfo->size -
535                                                 sizeof(struct ipt_entry)) {
536                                                 duprintf("mark_source_chains: "
537                                                         "bad verdict (%i)\n",
538                                                                 newpos);
539                                                 return 0;
540                                         }
541                                         /* This a jump; chase it. */
542                                         duprintf("Jump rule %u -> %u\n",
543                                                  pos, newpos);
544                                 } else {
545                                         /* ... this is a fallthru */
546                                         newpos = pos + e->next_offset;
547                                 }
548                                 e = (struct ipt_entry *)
549                                         (entry0 + newpos);
550                                 e->counters.pcnt = pos;
551                                 pos = newpos;
552                         }
553                 }
554                 next:
555                 duprintf("Finished chain %u\n", hook);
556         }
557         return 1;
558 }
559
560 static int
561 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
562 {
563         struct xt_mtdtor_param par;
564
565         if (i && (*i)-- == 0)
566                 return 1;
567
568         par.match     = m->u.kernel.match;
569         par.matchinfo = m->data;
570         par.family    = NFPROTO_IPV4;
571         if (par.match->destroy != NULL)
572                 par.match->destroy(&par);
573         module_put(par.match->me);
574         return 0;
575 }
576
577 static int
578 check_entry(struct ipt_entry *e, const char *name)
579 {
580         struct ipt_entry_target *t;
581
582         if (!ip_checkentry(&e->ip)) {
583                 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
584                 return -EINVAL;
585         }
586
587         if (e->target_offset + sizeof(struct ipt_entry_target) >
588             e->next_offset)
589                 return -EINVAL;
590
591         t = ipt_get_target(e);
592         if (e->target_offset + t->u.target_size > e->next_offset)
593                 return -EINVAL;
594
595         return 0;
596 }
597
598 static int
599 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
600             unsigned int *i)
601 {
602         const struct ipt_ip *ip = par->entryinfo;
603         int ret;
604
605         par->match     = m->u.kernel.match;
606         par->matchinfo = m->data;
607
608         ret = xt_check_match(par, m->u.match_size - sizeof(*m),
609               ip->proto, ip->invflags & IPT_INV_PROTO);
610         if (ret < 0) {
611                 duprintf("ip_tables: check failed for `%s'.\n",
612                          par.match->name);
613                 return ret;
614         }
615         ++*i;
616         return 0;
617 }
618
619 static int
620 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
621                  unsigned int *i)
622 {
623         struct xt_match *match;
624         int ret;
625
626         match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
627                                                       m->u.user.revision),
628                                         "ipt_%s", m->u.user.name);
629         if (IS_ERR(match) || !match) {
630                 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
631                 return match ? PTR_ERR(match) : -ENOENT;
632         }
633         m->u.kernel.match = match;
634
635         ret = check_match(m, par, i);
636         if (ret)
637                 goto err;
638
639         return 0;
640 err:
641         module_put(m->u.kernel.match->me);
642         return ret;
643 }
644
645 static int check_target(struct ipt_entry *e, const char *name)
646 {
647         struct ipt_entry_target *t = ipt_get_target(e);
648         struct xt_tgchk_param par = {
649                 .table     = name,
650                 .entryinfo = e,
651                 .target    = t->u.kernel.target,
652                 .targinfo  = t->data,
653                 .hook_mask = e->comefrom,
654                 .family    = NFPROTO_IPV4,
655         };
656         int ret;
657
658         ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
659               e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
660         if (ret < 0) {
661                 duprintf("ip_tables: check failed for `%s'.\n",
662                          t->u.kernel.target->name);
663                 return ret;
664         }
665         return 0;
666 }
667
668 static int
669 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
670                  unsigned int *i)
671 {
672         struct ipt_entry_target *t;
673         struct xt_target *target;
674         int ret;
675         unsigned int j;
676         struct xt_mtchk_param mtpar;
677
678         ret = check_entry(e, name);
679         if (ret)
680                 return ret;
681
682         j = 0;
683         mtpar.table     = name;
684         mtpar.entryinfo = &e->ip;
685         mtpar.hook_mask = e->comefrom;
686         mtpar.family    = NFPROTO_IPV4;
687         ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
688         if (ret != 0)
689                 goto cleanup_matches;
690
691         t = ipt_get_target(e);
692         target = try_then_request_module(xt_find_target(AF_INET,
693                                                         t->u.user.name,
694                                                         t->u.user.revision),
695                                          "ipt_%s", t->u.user.name);
696         if (IS_ERR(target) || !target) {
697                 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
698                 ret = target ? PTR_ERR(target) : -ENOENT;
699                 goto cleanup_matches;
700         }
701         t->u.kernel.target = target;
702
703         ret = check_target(e, name);
704         if (ret)
705                 goto err;
706
707         (*i)++;
708         return 0;
709  err:
710         module_put(t->u.kernel.target->me);
711  cleanup_matches:
712         IPT_MATCH_ITERATE(e, cleanup_match, &j);
713         return ret;
714 }
715
716 static int
717 check_entry_size_and_hooks(struct ipt_entry *e,
718                            struct xt_table_info *newinfo,
719                            unsigned char *base,
720                            unsigned char *limit,
721                            const unsigned int *hook_entries,
722                            const unsigned int *underflows,
723                            unsigned int *i)
724 {
725         unsigned int h;
726
727         if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
728             || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
729                 duprintf("Bad offset %p\n", e);
730                 return -EINVAL;
731         }
732
733         if (e->next_offset
734             < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
735                 duprintf("checking: element %p size %u\n",
736                          e, e->next_offset);
737                 return -EINVAL;
738         }
739
740         /* Check hooks & underflows */
741         for (h = 0; h < NF_INET_NUMHOOKS; h++) {
742                 if ((unsigned char *)e - base == hook_entries[h])
743                         newinfo->hook_entry[h] = hook_entries[h];
744                 if ((unsigned char *)e - base == underflows[h])
745                         newinfo->underflow[h] = underflows[h];
746         }
747
748         /* FIXME: underflows must be unconditional, standard verdicts
749            < 0 (not IPT_RETURN). --RR */
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, &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);