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