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