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