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