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