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