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