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