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