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