2 * Packet matching code.
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
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.
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>
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>
28 #include <linux/netfilter/x_tables.h>
29 #include <linux/netfilter_ipv4/ip_tables.h>
30 #include <net/netfilter/nf_log.h>
32 MODULE_LICENSE("GPL");
33 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
34 MODULE_DESCRIPTION("IPv4 packet filter");
36 /*#define DEBUG_IP_FIREWALL*/
37 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
38 /*#define DEBUG_IP_FIREWALL_USER*/
40 #ifdef DEBUG_IP_FIREWALL
41 #define dprintf(format, args...) printk(format , ## args)
43 #define dprintf(format, args...)
46 #ifdef DEBUG_IP_FIREWALL_USER
47 #define duprintf(format, args...) printk(format , ## args)
49 #define duprintf(format, args...)
52 #ifdef CONFIG_NETFILTER_DEBUG
53 #define IP_NF_ASSERT(x) \
56 printk("IP_NF_ASSERT: %s:%s:%u\n", \
57 __func__, __FILE__, __LINE__); \
60 #define IP_NF_ASSERT(x)
64 /* All the better to debug you with... */
70 We keep a set of rules for each CPU, so we can avoid write-locking
71 them in the softirq when updating the counters and therefore
72 only need to read-lock in the softirq; doing a write_lock_bh() in user
73 context stops packets coming through and allows user context to read
74 the counters or update the rules.
76 Hence the start of any table is given by get_table() below. */
78 /* Returns whether matches rule or not. */
79 /* Performance critical - called for every packet */
81 ip_packet_match(const struct iphdr *ip,
84 const struct ipt_ip *ipinfo,
89 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
91 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
93 FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
95 dprintf("Source or dest mismatch.\n");
97 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
98 &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
99 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
100 dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
101 &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
102 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
106 ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
108 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
109 dprintf("VIA in mismatch (%s vs %s).%s\n",
110 indev, ipinfo->iniface,
111 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
115 ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
117 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
118 dprintf("VIA out mismatch (%s vs %s).%s\n",
119 outdev, ipinfo->outiface,
120 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
124 /* Check specific protocol */
126 FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
127 dprintf("Packet protocol %hi does not match %hi.%s\n",
128 ip->protocol, ipinfo->proto,
129 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
133 /* If we have a fragment rule but the packet is not a fragment
134 * then we return zero */
135 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
136 dprintf("Fragment rule but not fragment.%s\n",
137 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
145 ip_checkentry(const struct ipt_ip *ip)
147 if (ip->flags & ~IPT_F_MASK) {
148 duprintf("Unknown flag bits set: %08X\n",
149 ip->flags & ~IPT_F_MASK);
152 if (ip->invflags & ~IPT_INV_MASK) {
153 duprintf("Unknown invflag bits set: %08X\n",
154 ip->invflags & ~IPT_INV_MASK);
161 ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
164 printk("ip_tables: error: `%s'\n",
165 (const char *)par->targinfo);
170 /* Performance critical - called for every packet */
172 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
173 struct xt_match_param *par)
175 par->match = m->u.kernel.match;
176 par->matchinfo = m->data;
178 /* Stop iteration if it doesn't match */
179 if (!m->u.kernel.match->match(skb, par))
185 /* Performance critical */
186 static inline struct ipt_entry *
187 get_entry(void *base, unsigned int offset)
189 return (struct ipt_entry *)(base + offset);
192 /* All zeroes == unconditional rule. */
193 /* Mildly perf critical (only if packet tracing is on) */
194 static inline bool unconditional(const struct ipt_ip *ip)
196 static const struct ipt_ip uncond;
198 return memcmp(ip, &uncond, sizeof(uncond)) == 0;
202 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
203 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
204 static const char *const hooknames[] = {
205 [NF_INET_PRE_ROUTING] = "PREROUTING",
206 [NF_INET_LOCAL_IN] = "INPUT",
207 [NF_INET_FORWARD] = "FORWARD",
208 [NF_INET_LOCAL_OUT] = "OUTPUT",
209 [NF_INET_POST_ROUTING] = "POSTROUTING",
212 enum nf_ip_trace_comments {
213 NF_IP_TRACE_COMMENT_RULE,
214 NF_IP_TRACE_COMMENT_RETURN,
215 NF_IP_TRACE_COMMENT_POLICY,
218 static const char *const comments[] = {
219 [NF_IP_TRACE_COMMENT_RULE] = "rule",
220 [NF_IP_TRACE_COMMENT_RETURN] = "return",
221 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
224 static struct nf_loginfo trace_loginfo = {
225 .type = NF_LOG_TYPE_LOG,
229 .logflags = NF_LOG_MASK,
234 /* Mildly perf critical (only if packet tracing is on) */
236 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
237 const char *hookname, const char **chainname,
238 const char **comment, unsigned int *rulenum)
240 struct ipt_standard_target *t = (void *)ipt_get_target(s);
242 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
243 /* Head of user chain: ERROR target with chainname */
244 *chainname = t->target.data;
249 if (s->target_offset == sizeof(struct ipt_entry) &&
250 strcmp(t->target.u.kernel.target->name,
251 IPT_STANDARD_TARGET) == 0 &&
253 unconditional(&s->ip)) {
254 /* Tail of chains: STANDARD target (return/policy) */
255 *comment = *chainname == hookname
256 ? comments[NF_IP_TRACE_COMMENT_POLICY]
257 : comments[NF_IP_TRACE_COMMENT_RETURN];
266 static void trace_packet(struct sk_buff *skb,
268 const struct net_device *in,
269 const struct net_device *out,
270 const char *tablename,
271 struct xt_table_info *private,
275 const struct ipt_entry *root;
276 const char *hookname, *chainname, *comment;
277 unsigned int rulenum = 0;
279 table_base = private->entries[smp_processor_id()];
280 root = get_entry(table_base, private->hook_entry[hook]);
282 hookname = chainname = hooknames[hook];
283 comment = comments[NF_IP_TRACE_COMMENT_RULE];
285 IPT_ENTRY_ITERATE(root,
286 private->size - private->hook_entry[hook],
287 get_chainname_rulenum,
288 e, hookname, &chainname, &comment, &rulenum);
290 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
291 "TRACE: %s:%s:%s:%u ",
292 tablename, chainname, comment, rulenum);
297 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
299 return (void *)entry + entry->next_offset;
302 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
304 ipt_do_table(struct sk_buff *skb,
306 const struct net_device *in,
307 const struct net_device *out,
308 struct xt_table *table)
310 #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
312 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
313 const struct iphdr *ip;
314 bool hotdrop = false;
315 /* Initializing verdict to NF_DROP keeps gcc happy. */
316 unsigned int verdict = NF_DROP;
317 const char *indev, *outdev;
319 struct ipt_entry *e, *back;
320 struct xt_table_info *private;
321 struct xt_match_param mtpar;
322 struct xt_target_param tgpar;
326 indev = in ? in->name : nulldevname;
327 outdev = out ? out->name : nulldevname;
328 /* We handle fragments by dealing with the first fragment as
329 * if it was a normal packet. All other fragments are treated
330 * normally, except that they will NEVER match rules that ask
331 * things we don't know, ie. tcp syn flag or ports). If the
332 * rule is also a fragment-specific rule, non-fragments won't
334 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
335 mtpar.thoff = ip_hdrlen(skb);
336 mtpar.hotdrop = &hotdrop;
337 mtpar.in = tgpar.in = in;
338 mtpar.out = tgpar.out = out;
339 mtpar.family = tgpar.family = NFPROTO_IPV4;
340 mtpar.hooknum = tgpar.hooknum = hook;
342 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
344 private = table->private;
345 table_base = private->entries[smp_processor_id()];
347 e = get_entry(table_base, private->hook_entry[hook]);
349 /* For return from builtin chain */
350 back = get_entry(table_base, private->underflow[hook]);
353 struct ipt_entry_target *t;
357 if (!ip_packet_match(ip, indev, outdev,
358 &e->ip, mtpar.fragoff) ||
359 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
360 e = ipt_next_entry(e);
364 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
366 t = ipt_get_target(e);
367 IP_NF_ASSERT(t->u.kernel.target);
369 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
370 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
371 /* The packet is traced: log it */
372 if (unlikely(skb->nf_trace))
373 trace_packet(skb, hook, in, out,
374 table->name, private, e);
376 /* Standard target? */
377 if (!t->u.kernel.target->target) {
380 v = ((struct ipt_standard_target *)t)->verdict;
382 /* Pop from stack? */
383 if (v != IPT_RETURN) {
384 verdict = (unsigned)(-v) - 1;
388 back = get_entry(table_base, back->comefrom);
391 if (table_base + v != ipt_next_entry(e) &&
392 !(e->ip.flags & IPT_F_GOTO)) {
393 /* Save old back ptr in next entry */
394 struct ipt_entry *next = ipt_next_entry(e);
395 next->comefrom = (void *)back - table_base;
396 /* set back pointer to next entry */
400 e = get_entry(table_base, v);
404 /* Targets which reenter must return
406 tgpar.target = t->u.kernel.target;
407 tgpar.targinfo = t->data;
410 #ifdef CONFIG_NETFILTER_DEBUG
411 tb_comefrom = 0xeeeeeeec;
413 verdict = t->u.kernel.target->target(skb, &tgpar);
414 #ifdef CONFIG_NETFILTER_DEBUG
415 if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
416 printk("Target %s reentered!\n",
417 t->u.kernel.target->name);
420 tb_comefrom = 0x57acc001;
422 /* Target might have changed stuff. */
424 if (verdict == IPT_CONTINUE)
425 e = ipt_next_entry(e);
430 xt_info_rdunlock_bh();
432 #ifdef DEBUG_ALLOW_ALL
443 /* Figures out from what hook each rule can be called: returns 0 if
444 there are loops. Puts hook bitmask in comefrom. */
446 mark_source_chains(struct xt_table_info *newinfo,
447 unsigned int valid_hooks, void *entry0)
451 /* No recursion; use packet counter to save back ptrs (reset
452 to 0 as we leave), and comefrom to save source hook bitmask */
453 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
454 unsigned int pos = newinfo->hook_entry[hook];
455 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
457 if (!(valid_hooks & (1 << hook)))
460 /* Set initial back pointer. */
461 e->counters.pcnt = pos;
464 struct ipt_standard_target *t
465 = (void *)ipt_get_target(e);
466 int visited = e->comefrom & (1 << hook);
468 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
469 printk("iptables: loop hook %u pos %u %08X.\n",
470 hook, pos, e->comefrom);
473 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
475 /* Unconditional return/END. */
476 if ((e->target_offset == sizeof(struct ipt_entry) &&
477 (strcmp(t->target.u.user.name,
478 IPT_STANDARD_TARGET) == 0) &&
479 t->verdict < 0 && unconditional(&e->ip)) ||
481 unsigned int oldpos, size;
483 if ((strcmp(t->target.u.user.name,
484 IPT_STANDARD_TARGET) == 0) &&
485 t->verdict < -NF_MAX_VERDICT - 1) {
486 duprintf("mark_source_chains: bad "
487 "negative verdict (%i)\n",
492 /* Return: backtrack through the last
495 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
496 #ifdef DEBUG_IP_FIREWALL_USER
498 & (1 << NF_INET_NUMHOOKS)) {
499 duprintf("Back unset "
506 pos = e->counters.pcnt;
507 e->counters.pcnt = 0;
509 /* We're at the start. */
513 e = (struct ipt_entry *)
515 } while (oldpos == pos + e->next_offset);
518 size = e->next_offset;
519 e = (struct ipt_entry *)
520 (entry0 + pos + size);
521 e->counters.pcnt = pos;
524 int newpos = t->verdict;
526 if (strcmp(t->target.u.user.name,
527 IPT_STANDARD_TARGET) == 0 &&
529 if (newpos > newinfo->size -
530 sizeof(struct ipt_entry)) {
531 duprintf("mark_source_chains: "
532 "bad verdict (%i)\n",
536 /* This a jump; chase it. */
537 duprintf("Jump rule %u -> %u\n",
540 /* ... this is a fallthru */
541 newpos = pos + e->next_offset;
543 e = (struct ipt_entry *)
545 e->counters.pcnt = pos;
550 duprintf("Finished chain %u\n", hook);
556 cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i)
558 struct xt_mtdtor_param par;
560 if (i && (*i)-- == 0)
564 par.match = m->u.kernel.match;
565 par.matchinfo = m->data;
566 par.family = NFPROTO_IPV4;
567 if (par.match->destroy != NULL)
568 par.match->destroy(&par);
569 module_put(par.match->me);
574 check_entry(struct ipt_entry *e, const char *name)
576 struct ipt_entry_target *t;
578 if (!ip_checkentry(&e->ip)) {
579 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
583 if (e->target_offset + sizeof(struct ipt_entry_target) >
587 t = ipt_get_target(e);
588 if (e->target_offset + t->u.target_size > e->next_offset)
595 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
598 const struct ipt_ip *ip = par->entryinfo;
601 par->match = m->u.kernel.match;
602 par->matchinfo = m->data;
604 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
605 ip->proto, ip->invflags & IPT_INV_PROTO);
607 duprintf("ip_tables: check failed for `%s'.\n",
616 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
619 struct xt_match *match;
622 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
624 "ipt_%s", m->u.user.name);
625 if (IS_ERR(match) || !match) {
626 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
627 return match ? PTR_ERR(match) : -ENOENT;
629 m->u.kernel.match = match;
631 ret = check_match(m, par, i);
637 module_put(m->u.kernel.match->me);
641 static int check_target(struct ipt_entry *e, struct net *net, const char *name)
643 struct ipt_entry_target *t = ipt_get_target(e);
644 struct xt_tgchk_param par = {
648 .target = t->u.kernel.target,
650 .hook_mask = e->comefrom,
651 .family = NFPROTO_IPV4,
655 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
656 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
658 duprintf("ip_tables: check failed for `%s'.\n",
659 t->u.kernel.target->name);
666 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
667 unsigned int size, unsigned int *i)
669 struct ipt_entry_target *t;
670 struct xt_target *target;
673 struct xt_mtchk_param mtpar;
675 ret = check_entry(e, name);
682 mtpar.entryinfo = &e->ip;
683 mtpar.hook_mask = e->comefrom;
684 mtpar.family = NFPROTO_IPV4;
685 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
687 goto cleanup_matches;
689 t = ipt_get_target(e);
690 target = try_then_request_module(xt_find_target(AF_INET,
693 "ipt_%s", t->u.user.name);
694 if (IS_ERR(target) || !target) {
695 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
696 ret = target ? PTR_ERR(target) : -ENOENT;
697 goto cleanup_matches;
699 t->u.kernel.target = target;
701 ret = check_target(e, net, name);
708 module_put(t->u.kernel.target->me);
710 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
714 static bool check_underflow(struct ipt_entry *e)
716 const struct ipt_entry_target *t;
717 unsigned int verdict;
719 if (!unconditional(&e->ip))
721 t = ipt_get_target(e);
722 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
724 verdict = ((struct ipt_standard_target *)t)->verdict;
725 verdict = -verdict - 1;
726 return verdict == NF_DROP || verdict == NF_ACCEPT;
730 check_entry_size_and_hooks(struct ipt_entry *e,
731 struct xt_table_info *newinfo,
733 unsigned char *limit,
734 const unsigned int *hook_entries,
735 const unsigned int *underflows,
736 unsigned int valid_hooks,
741 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
742 (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
743 duprintf("Bad offset %p\n", e);
748 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
749 duprintf("checking: element %p size %u\n",
754 /* Check hooks & underflows */
755 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
756 if (!(valid_hooks & (1 << h)))
758 if ((unsigned char *)e - base == hook_entries[h])
759 newinfo->hook_entry[h] = hook_entries[h];
760 if ((unsigned char *)e - base == underflows[h]) {
761 if (!check_underflow(e)) {
762 pr_err("Underflows must be unconditional and "
763 "use the STANDARD target with "
767 newinfo->underflow[h] = underflows[h];
771 /* Clear counters and comefrom */
772 e->counters = ((struct xt_counters) { 0, 0 });
780 cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i)
782 struct xt_tgdtor_param par;
783 struct ipt_entry_target *t;
785 if (i && (*i)-- == 0)
788 /* Cleanup all matches */
789 IPT_MATCH_ITERATE(e, cleanup_match, net, NULL);
790 t = ipt_get_target(e);
793 par.target = t->u.kernel.target;
794 par.targinfo = t->data;
795 par.family = NFPROTO_IPV4;
796 if (par.target->destroy != NULL)
797 par.target->destroy(&par);
798 module_put(par.target->me);
802 /* Checks and translates the user-supplied table segment (held in
805 translate_table(struct net *net,
807 unsigned int valid_hooks,
808 struct xt_table_info *newinfo,
812 const unsigned int *hook_entries,
813 const unsigned int *underflows)
818 newinfo->size = size;
819 newinfo->number = number;
821 /* Init all hooks to impossible value. */
822 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
823 newinfo->hook_entry[i] = 0xFFFFFFFF;
824 newinfo->underflow[i] = 0xFFFFFFFF;
827 duprintf("translate_table: size %u\n", newinfo->size);
829 /* Walk through entries, checking offsets. */
830 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
831 check_entry_size_and_hooks,
835 hook_entries, underflows, valid_hooks, &i);
840 duprintf("translate_table: %u not %u entries\n",
845 /* Check hooks all assigned */
846 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
847 /* Only hooks which are valid */
848 if (!(valid_hooks & (1 << i)))
850 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
851 duprintf("Invalid hook entry %u %u\n",
855 if (newinfo->underflow[i] == 0xFFFFFFFF) {
856 duprintf("Invalid underflow %u %u\n",
862 if (!mark_source_chains(newinfo, valid_hooks, entry0))
865 /* Finally, each sanity check must pass */
867 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
868 find_check_entry, net, name, size, &i);
871 IPT_ENTRY_ITERATE(entry0, newinfo->size,
872 cleanup_entry, net, &i);
876 /* And one copy for every other CPU */
877 for_each_possible_cpu(i) {
878 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
879 memcpy(newinfo->entries[i], entry0, newinfo->size);
887 add_entry_to_counter(const struct ipt_entry *e,
888 struct xt_counters total[],
891 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
898 set_entry_to_counter(const struct ipt_entry *e,
899 struct ipt_counters total[],
902 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
909 get_counters(const struct xt_table_info *t,
910 struct xt_counters counters[])
916 /* Instead of clearing (by a previous call to memset())
917 * the counters and using adds, we set the counters
918 * with data used by 'current' CPU.
920 * Bottom half has to be disabled to prevent deadlock
921 * if new softirq were to run and call ipt_do_table
924 curcpu = smp_processor_id();
927 IPT_ENTRY_ITERATE(t->entries[curcpu],
929 set_entry_to_counter,
933 for_each_possible_cpu(cpu) {
938 IPT_ENTRY_ITERATE(t->entries[cpu],
940 add_entry_to_counter,
943 xt_info_wrunlock(cpu);
948 static struct xt_counters * alloc_counters(struct xt_table *table)
950 unsigned int countersize;
951 struct xt_counters *counters;
952 struct xt_table_info *private = table->private;
954 /* We need atomic snapshot of counters: rest doesn't change
955 (other than comefrom, which userspace doesn't care
957 countersize = sizeof(struct xt_counters) * private->number;
958 counters = vmalloc_node(countersize, numa_node_id());
960 if (counters == NULL)
961 return ERR_PTR(-ENOMEM);
963 get_counters(private, counters);
969 copy_entries_to_user(unsigned int total_size,
970 struct xt_table *table,
971 void __user *userptr)
973 unsigned int off, num;
975 struct xt_counters *counters;
976 const struct xt_table_info *private = table->private;
978 const void *loc_cpu_entry;
980 counters = alloc_counters(table);
981 if (IS_ERR(counters))
982 return PTR_ERR(counters);
984 /* choose the copy that is on our node/cpu, ...
985 * This choice is lazy (because current thread is
986 * allowed to migrate to another cpu)
988 loc_cpu_entry = private->entries[raw_smp_processor_id()];
989 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
994 /* FIXME: use iterator macros --RR */
995 /* ... then go back and fix counters and names */
996 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
998 const struct ipt_entry_match *m;
999 const struct ipt_entry_target *t;
1001 e = (struct ipt_entry *)(loc_cpu_entry + off);
1002 if (copy_to_user(userptr + off
1003 + offsetof(struct ipt_entry, counters),
1005 sizeof(counters[num])) != 0) {
1010 for (i = sizeof(struct ipt_entry);
1011 i < e->target_offset;
1012 i += m->u.match_size) {
1015 if (copy_to_user(userptr + off + i
1016 + offsetof(struct ipt_entry_match,
1018 m->u.kernel.match->name,
1019 strlen(m->u.kernel.match->name)+1)
1026 t = ipt_get_target(e);
1027 if (copy_to_user(userptr + off + e->target_offset
1028 + offsetof(struct ipt_entry_target,
1030 t->u.kernel.target->name,
1031 strlen(t->u.kernel.target->name)+1) != 0) {
1042 #ifdef CONFIG_COMPAT
1043 static void compat_standard_from_user(void *dst, void *src)
1045 int v = *(compat_int_t *)src;
1048 v += xt_compat_calc_jump(AF_INET, v);
1049 memcpy(dst, &v, sizeof(v));
1052 static int compat_standard_to_user(void __user *dst, void *src)
1054 compat_int_t cv = *(int *)src;
1057 cv -= xt_compat_calc_jump(AF_INET, cv);
1058 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1062 compat_calc_match(struct ipt_entry_match *m, int *size)
1064 *size += xt_compat_match_offset(m->u.kernel.match);
1068 static int compat_calc_entry(struct ipt_entry *e,
1069 const struct xt_table_info *info,
1070 void *base, struct xt_table_info *newinfo)
1072 struct ipt_entry_target *t;
1073 unsigned int entry_offset;
1076 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1077 entry_offset = (void *)e - base;
1078 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1079 t = ipt_get_target(e);
1080 off += xt_compat_target_offset(t->u.kernel.target);
1081 newinfo->size -= off;
1082 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1086 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1087 if (info->hook_entry[i] &&
1088 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1089 newinfo->hook_entry[i] -= off;
1090 if (info->underflow[i] &&
1091 (e < (struct ipt_entry *)(base + info->underflow[i])))
1092 newinfo->underflow[i] -= off;
1097 static int compat_table_info(const struct xt_table_info *info,
1098 struct xt_table_info *newinfo)
1100 void *loc_cpu_entry;
1102 if (!newinfo || !info)
1105 /* we dont care about newinfo->entries[] */
1106 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1107 newinfo->initial_entries = 0;
1108 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1109 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1110 compat_calc_entry, info, loc_cpu_entry,
1115 static int get_info(struct net *net, void __user *user, int *len, int compat)
1117 char name[IPT_TABLE_MAXNAMELEN];
1121 if (*len != sizeof(struct ipt_getinfo)) {
1122 duprintf("length %u != %zu\n", *len,
1123 sizeof(struct ipt_getinfo));
1127 if (copy_from_user(name, user, sizeof(name)) != 0)
1130 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1131 #ifdef CONFIG_COMPAT
1133 xt_compat_lock(AF_INET);
1135 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1136 "iptable_%s", name);
1137 if (t && !IS_ERR(t)) {
1138 struct ipt_getinfo info;
1139 const struct xt_table_info *private = t->private;
1140 #ifdef CONFIG_COMPAT
1141 struct xt_table_info tmp;
1144 ret = compat_table_info(private, &tmp);
1145 xt_compat_flush_offsets(AF_INET);
1149 info.valid_hooks = t->valid_hooks;
1150 memcpy(info.hook_entry, private->hook_entry,
1151 sizeof(info.hook_entry));
1152 memcpy(info.underflow, private->underflow,
1153 sizeof(info.underflow));
1154 info.num_entries = private->number;
1155 info.size = private->size;
1156 strcpy(info.name, name);
1158 if (copy_to_user(user, &info, *len) != 0)
1166 ret = t ? PTR_ERR(t) : -ENOENT;
1167 #ifdef CONFIG_COMPAT
1169 xt_compat_unlock(AF_INET);
1175 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1178 struct ipt_get_entries get;
1181 if (*len < sizeof(get)) {
1182 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1185 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1187 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1188 duprintf("get_entries: %u != %zu\n",
1189 *len, sizeof(get) + get.size);
1193 t = xt_find_table_lock(net, AF_INET, get.name);
1194 if (t && !IS_ERR(t)) {
1195 const struct xt_table_info *private = t->private;
1196 duprintf("t->private->number = %u\n", private->number);
1197 if (get.size == private->size)
1198 ret = copy_entries_to_user(private->size,
1199 t, uptr->entrytable);
1201 duprintf("get_entries: I've got %u not %u!\n",
1202 private->size, get.size);
1208 ret = t ? PTR_ERR(t) : -ENOENT;
1214 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1215 struct xt_table_info *newinfo, unsigned int num_counters,
1216 void __user *counters_ptr)
1220 struct xt_table_info *oldinfo;
1221 struct xt_counters *counters;
1222 void *loc_cpu_old_entry;
1225 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1231 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1232 "iptable_%s", name);
1233 if (!t || IS_ERR(t)) {
1234 ret = t ? PTR_ERR(t) : -ENOENT;
1235 goto free_newinfo_counters_untrans;
1239 if (valid_hooks != t->valid_hooks) {
1240 duprintf("Valid hook crap: %08X vs %08X\n",
1241 valid_hooks, t->valid_hooks);
1246 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1250 /* Update module usage count based on number of rules */
1251 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1252 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1253 if ((oldinfo->number > oldinfo->initial_entries) ||
1254 (newinfo->number <= oldinfo->initial_entries))
1256 if ((oldinfo->number > oldinfo->initial_entries) &&
1257 (newinfo->number <= oldinfo->initial_entries))
1260 /* Get the old counters, and synchronize with replace */
1261 get_counters(oldinfo, counters);
1263 /* Decrease module usage counts and free resource */
1264 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1265 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1267 xt_free_table_info(oldinfo);
1268 if (copy_to_user(counters_ptr, counters,
1269 sizeof(struct xt_counters) * num_counters) != 0)
1278 free_newinfo_counters_untrans:
1285 do_replace(struct net *net, void __user *user, unsigned int len)
1288 struct ipt_replace tmp;
1289 struct xt_table_info *newinfo;
1290 void *loc_cpu_entry;
1292 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1295 /* overflow check */
1296 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1299 newinfo = xt_alloc_table_info(tmp.size);
1303 /* choose the copy that is on our node/cpu */
1304 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1305 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1311 ret = translate_table(net, tmp.name, tmp.valid_hooks,
1312 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1313 tmp.hook_entry, tmp.underflow);
1317 duprintf("ip_tables: Translated table\n");
1319 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1320 tmp.num_counters, tmp.counters);
1322 goto free_newinfo_untrans;
1325 free_newinfo_untrans:
1326 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1328 xt_free_table_info(newinfo);
1332 /* We're lazy, and add to the first CPU; overflow works its fey magic
1333 * and everything is OK. */
1335 add_counter_to_entry(struct ipt_entry *e,
1336 const struct xt_counters addme[],
1339 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1346 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1348 unsigned int i, curcpu;
1349 struct xt_counters_info tmp;
1350 struct xt_counters *paddc;
1351 unsigned int num_counters;
1356 const struct xt_table_info *private;
1358 void *loc_cpu_entry;
1359 #ifdef CONFIG_COMPAT
1360 struct compat_xt_counters_info compat_tmp;
1364 size = sizeof(struct compat_xt_counters_info);
1369 size = sizeof(struct xt_counters_info);
1372 if (copy_from_user(ptmp, user, size) != 0)
1375 #ifdef CONFIG_COMPAT
1377 num_counters = compat_tmp.num_counters;
1378 name = compat_tmp.name;
1382 num_counters = tmp.num_counters;
1386 if (len != size + num_counters * sizeof(struct xt_counters))
1389 paddc = vmalloc_node(len - size, numa_node_id());
1393 if (copy_from_user(paddc, user + size, len - size) != 0) {
1398 t = xt_find_table_lock(net, AF_INET, name);
1399 if (!t || IS_ERR(t)) {
1400 ret = t ? PTR_ERR(t) : -ENOENT;
1405 private = t->private;
1406 if (private->number != num_counters) {
1408 goto unlock_up_free;
1412 /* Choose the copy that is on our node */
1413 curcpu = smp_processor_id();
1414 loc_cpu_entry = private->entries[curcpu];
1415 xt_info_wrlock(curcpu);
1416 IPT_ENTRY_ITERATE(loc_cpu_entry,
1418 add_counter_to_entry,
1421 xt_info_wrunlock(curcpu);
1432 #ifdef CONFIG_COMPAT
1433 struct compat_ipt_replace {
1434 char name[IPT_TABLE_MAXNAMELEN];
1438 u32 hook_entry[NF_INET_NUMHOOKS];
1439 u32 underflow[NF_INET_NUMHOOKS];
1441 compat_uptr_t counters; /* struct ipt_counters * */
1442 struct compat_ipt_entry entries[0];
1446 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1447 unsigned int *size, struct xt_counters *counters,
1450 struct ipt_entry_target *t;
1451 struct compat_ipt_entry __user *ce;
1452 u_int16_t target_offset, next_offset;
1453 compat_uint_t origsize;
1458 ce = (struct compat_ipt_entry __user *)*dstptr;
1459 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1462 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1465 *dstptr += sizeof(struct compat_ipt_entry);
1466 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1468 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1469 target_offset = e->target_offset - (origsize - *size);
1472 t = ipt_get_target(e);
1473 ret = xt_compat_target_to_user(t, dstptr, size);
1477 next_offset = e->next_offset - (origsize - *size);
1478 if (put_user(target_offset, &ce->target_offset))
1480 if (put_user(next_offset, &ce->next_offset))
1490 compat_find_calc_match(struct ipt_entry_match *m,
1492 const struct ipt_ip *ip,
1493 unsigned int hookmask,
1494 int *size, unsigned int *i)
1496 struct xt_match *match;
1498 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1499 m->u.user.revision),
1500 "ipt_%s", m->u.user.name);
1501 if (IS_ERR(match) || !match) {
1502 duprintf("compat_check_calc_match: `%s' not found\n",
1504 return match ? PTR_ERR(match) : -ENOENT;
1506 m->u.kernel.match = match;
1507 *size += xt_compat_match_offset(match);
1514 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1516 if (i && (*i)-- == 0)
1519 module_put(m->u.kernel.match->me);
1524 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1526 struct ipt_entry_target *t;
1528 if (i && (*i)-- == 0)
1531 /* Cleanup all matches */
1532 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1533 t = compat_ipt_get_target(e);
1534 module_put(t->u.kernel.target->me);
1539 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1540 struct xt_table_info *newinfo,
1542 unsigned char *base,
1543 unsigned char *limit,
1544 unsigned int *hook_entries,
1545 unsigned int *underflows,
1549 struct ipt_entry_target *t;
1550 struct xt_target *target;
1551 unsigned int entry_offset;
1555 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1556 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1557 (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1558 duprintf("Bad offset %p, limit = %p\n", e, limit);
1562 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1563 sizeof(struct compat_xt_entry_target)) {
1564 duprintf("checking: element %p size %u\n",
1569 /* For purposes of check_entry casting the compat entry is fine */
1570 ret = check_entry((struct ipt_entry *)e, name);
1574 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1575 entry_offset = (void *)e - (void *)base;
1577 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1578 &e->ip, e->comefrom, &off, &j);
1580 goto release_matches;
1582 t = compat_ipt_get_target(e);
1583 target = try_then_request_module(xt_find_target(AF_INET,
1585 t->u.user.revision),
1586 "ipt_%s", t->u.user.name);
1587 if (IS_ERR(target) || !target) {
1588 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1590 ret = target ? PTR_ERR(target) : -ENOENT;
1591 goto release_matches;
1593 t->u.kernel.target = target;
1595 off += xt_compat_target_offset(target);
1597 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1601 /* Check hooks & underflows */
1602 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1603 if ((unsigned char *)e - base == hook_entries[h])
1604 newinfo->hook_entry[h] = hook_entries[h];
1605 if ((unsigned char *)e - base == underflows[h])
1606 newinfo->underflow[h] = underflows[h];
1609 /* Clear counters and comefrom */
1610 memset(&e->counters, 0, sizeof(e->counters));
1617 module_put(t->u.kernel.target->me);
1619 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1624 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1625 unsigned int *size, const char *name,
1626 struct xt_table_info *newinfo, unsigned char *base)
1628 struct ipt_entry_target *t;
1629 struct xt_target *target;
1630 struct ipt_entry *de;
1631 unsigned int origsize;
1636 de = (struct ipt_entry *)*dstptr;
1637 memcpy(de, e, sizeof(struct ipt_entry));
1638 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1640 *dstptr += sizeof(struct ipt_entry);
1641 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1643 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1647 de->target_offset = e->target_offset - (origsize - *size);
1648 t = compat_ipt_get_target(e);
1649 target = t->u.kernel.target;
1650 xt_compat_target_from_user(t, dstptr, size);
1652 de->next_offset = e->next_offset - (origsize - *size);
1653 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1654 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1655 newinfo->hook_entry[h] -= origsize - *size;
1656 if ((unsigned char *)de - base < newinfo->underflow[h])
1657 newinfo->underflow[h] -= origsize - *size;
1663 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,
1666 struct xt_mtchk_param mtpar;
1673 mtpar.entryinfo = &e->ip;
1674 mtpar.hook_mask = e->comefrom;
1675 mtpar.family = NFPROTO_IPV4;
1676 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1678 goto cleanup_matches;
1680 ret = check_target(e, net, name);
1682 goto cleanup_matches;
1688 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
1693 translate_compat_table(struct net *net,
1695 unsigned int valid_hooks,
1696 struct xt_table_info **pinfo,
1698 unsigned int total_size,
1699 unsigned int number,
1700 unsigned int *hook_entries,
1701 unsigned int *underflows)
1704 struct xt_table_info *newinfo, *info;
1705 void *pos, *entry0, *entry1;
1712 info->number = number;
1714 /* Init all hooks to impossible value. */
1715 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1716 info->hook_entry[i] = 0xFFFFFFFF;
1717 info->underflow[i] = 0xFFFFFFFF;
1720 duprintf("translate_compat_table: size %u\n", info->size);
1722 xt_compat_lock(AF_INET);
1723 /* Walk through entries, checking offsets. */
1724 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1725 check_compat_entry_size_and_hooks,
1726 info, &size, entry0,
1727 entry0 + total_size,
1728 hook_entries, underflows, &j, name);
1734 duprintf("translate_compat_table: %u not %u entries\n",
1739 /* Check hooks all assigned */
1740 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1741 /* Only hooks which are valid */
1742 if (!(valid_hooks & (1 << i)))
1744 if (info->hook_entry[i] == 0xFFFFFFFF) {
1745 duprintf("Invalid hook entry %u %u\n",
1746 i, hook_entries[i]);
1749 if (info->underflow[i] == 0xFFFFFFFF) {
1750 duprintf("Invalid underflow %u %u\n",
1757 newinfo = xt_alloc_table_info(size);
1761 newinfo->number = number;
1762 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1763 newinfo->hook_entry[i] = info->hook_entry[i];
1764 newinfo->underflow[i] = info->underflow[i];
1766 entry1 = newinfo->entries[raw_smp_processor_id()];
1769 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1770 compat_copy_entry_from_user,
1771 &pos, &size, name, newinfo, entry1);
1772 xt_compat_flush_offsets(AF_INET);
1773 xt_compat_unlock(AF_INET);
1778 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1782 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1786 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1787 compat_release_entry, &j);
1788 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i);
1789 xt_free_table_info(newinfo);
1793 /* And one copy for every other CPU */
1794 for_each_possible_cpu(i)
1795 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1796 memcpy(newinfo->entries[i], entry1, newinfo->size);
1800 xt_free_table_info(info);
1804 xt_free_table_info(newinfo);
1806 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1809 xt_compat_flush_offsets(AF_INET);
1810 xt_compat_unlock(AF_INET);
1815 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1818 struct compat_ipt_replace tmp;
1819 struct xt_table_info *newinfo;
1820 void *loc_cpu_entry;
1822 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1825 /* overflow check */
1826 if (tmp.size >= INT_MAX / num_possible_cpus())
1828 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1831 newinfo = xt_alloc_table_info(tmp.size);
1835 /* choose the copy that is on our node/cpu */
1836 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1837 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1843 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1844 &newinfo, &loc_cpu_entry, tmp.size,
1845 tmp.num_entries, tmp.hook_entry,
1850 duprintf("compat_do_replace: Translated table\n");
1852 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1853 tmp.num_counters, compat_ptr(tmp.counters));
1855 goto free_newinfo_untrans;
1858 free_newinfo_untrans:
1859 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1861 xt_free_table_info(newinfo);
1866 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1871 if (!capable(CAP_NET_ADMIN))
1875 case IPT_SO_SET_REPLACE:
1876 ret = compat_do_replace(sock_net(sk), user, len);
1879 case IPT_SO_SET_ADD_COUNTERS:
1880 ret = do_add_counters(sock_net(sk), user, len, 1);
1884 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1891 struct compat_ipt_get_entries {
1892 char name[IPT_TABLE_MAXNAMELEN];
1894 struct compat_ipt_entry entrytable[0];
1898 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1899 void __user *userptr)
1901 struct xt_counters *counters;
1902 const struct xt_table_info *private = table->private;
1906 const void *loc_cpu_entry;
1909 counters = alloc_counters(table);
1910 if (IS_ERR(counters))
1911 return PTR_ERR(counters);
1913 /* choose the copy that is on our node/cpu, ...
1914 * This choice is lazy (because current thread is
1915 * allowed to migrate to another cpu)
1917 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1920 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1921 compat_copy_entry_to_user,
1922 &pos, &size, counters, &i);
1929 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1933 struct compat_ipt_get_entries get;
1936 if (*len < sizeof(get)) {
1937 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1941 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1944 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1945 duprintf("compat_get_entries: %u != %zu\n",
1946 *len, sizeof(get) + get.size);
1950 xt_compat_lock(AF_INET);
1951 t = xt_find_table_lock(net, AF_INET, get.name);
1952 if (t && !IS_ERR(t)) {
1953 const struct xt_table_info *private = t->private;
1954 struct xt_table_info info;
1955 duprintf("t->private->number = %u\n", private->number);
1956 ret = compat_table_info(private, &info);
1957 if (!ret && get.size == info.size) {
1958 ret = compat_copy_entries_to_user(private->size,
1959 t, uptr->entrytable);
1961 duprintf("compat_get_entries: I've got %u not %u!\n",
1962 private->size, get.size);
1965 xt_compat_flush_offsets(AF_INET);
1969 ret = t ? PTR_ERR(t) : -ENOENT;
1971 xt_compat_unlock(AF_INET);
1975 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1978 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1982 if (!capable(CAP_NET_ADMIN))
1986 case IPT_SO_GET_INFO:
1987 ret = get_info(sock_net(sk), user, len, 1);
1989 case IPT_SO_GET_ENTRIES:
1990 ret = compat_get_entries(sock_net(sk), user, len);
1993 ret = do_ipt_get_ctl(sk, cmd, user, len);
2000 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2004 if (!capable(CAP_NET_ADMIN))
2008 case IPT_SO_SET_REPLACE:
2009 ret = do_replace(sock_net(sk), user, len);
2012 case IPT_SO_SET_ADD_COUNTERS:
2013 ret = do_add_counters(sock_net(sk), user, len, 0);
2017 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2025 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2029 if (!capable(CAP_NET_ADMIN))
2033 case IPT_SO_GET_INFO:
2034 ret = get_info(sock_net(sk), user, len, 0);
2037 case IPT_SO_GET_ENTRIES:
2038 ret = get_entries(sock_net(sk), user, len);
2041 case IPT_SO_GET_REVISION_MATCH:
2042 case IPT_SO_GET_REVISION_TARGET: {
2043 struct ipt_get_revision rev;
2046 if (*len != sizeof(rev)) {
2050 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2055 if (cmd == IPT_SO_GET_REVISION_TARGET)
2060 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2063 "ipt_%s", rev.name);
2068 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2075 struct xt_table *ipt_register_table(struct net *net,
2076 const struct xt_table *table,
2077 const struct ipt_replace *repl)
2080 struct xt_table_info *newinfo;
2081 struct xt_table_info bootstrap
2082 = { 0, 0, 0, { 0 }, { 0 }, { } };
2083 void *loc_cpu_entry;
2084 struct xt_table *new_table;
2086 newinfo = xt_alloc_table_info(repl->size);
2092 /* choose the copy on our node/cpu, but dont care about preemption */
2093 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2094 memcpy(loc_cpu_entry, repl->entries, repl->size);
2096 ret = translate_table(net, table->name, table->valid_hooks,
2097 newinfo, loc_cpu_entry, repl->size,
2104 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2105 if (IS_ERR(new_table)) {
2106 ret = PTR_ERR(new_table);
2113 xt_free_table_info(newinfo);
2115 return ERR_PTR(ret);
2118 void ipt_unregister_table(struct net *net, struct xt_table *table)
2120 struct xt_table_info *private;
2121 void *loc_cpu_entry;
2122 struct module *table_owner = table->me;
2124 private = xt_unregister_table(table);
2126 /* Decrease module usage counts and free resources */
2127 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2128 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL);
2129 if (private->number > private->initial_entries)
2130 module_put(table_owner);
2131 xt_free_table_info(private);
2134 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2136 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2137 u_int8_t type, u_int8_t code,
2140 return ((test_type == 0xFF) ||
2141 (type == test_type && code >= min_code && code <= max_code))
2146 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2148 const struct icmphdr *ic;
2149 struct icmphdr _icmph;
2150 const struct ipt_icmp *icmpinfo = par->matchinfo;
2152 /* Must not be a fragment. */
2153 if (par->fragoff != 0)
2156 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2158 /* We've been asked to examine this packet, and we
2159 * can't. Hence, no choice but to drop.
2161 duprintf("Dropping evil ICMP tinygram.\n");
2162 *par->hotdrop = true;
2166 return icmp_type_code_match(icmpinfo->type,
2170 !!(icmpinfo->invflags&IPT_ICMP_INV));
2173 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2175 const struct ipt_icmp *icmpinfo = par->matchinfo;
2177 /* Must specify no unknown invflags */
2178 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2181 /* The built-in targets: standard (NULL) and error. */
2182 static struct xt_target ipt_standard_target __read_mostly = {
2183 .name = IPT_STANDARD_TARGET,
2184 .targetsize = sizeof(int),
2185 .family = NFPROTO_IPV4,
2186 #ifdef CONFIG_COMPAT
2187 .compatsize = sizeof(compat_int_t),
2188 .compat_from_user = compat_standard_from_user,
2189 .compat_to_user = compat_standard_to_user,
2193 static struct xt_target ipt_error_target __read_mostly = {
2194 .name = IPT_ERROR_TARGET,
2195 .target = ipt_error,
2196 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2197 .family = NFPROTO_IPV4,
2200 static struct nf_sockopt_ops ipt_sockopts = {
2202 .set_optmin = IPT_BASE_CTL,
2203 .set_optmax = IPT_SO_SET_MAX+1,
2204 .set = do_ipt_set_ctl,
2205 #ifdef CONFIG_COMPAT
2206 .compat_set = compat_do_ipt_set_ctl,
2208 .get_optmin = IPT_BASE_CTL,
2209 .get_optmax = IPT_SO_GET_MAX+1,
2210 .get = do_ipt_get_ctl,
2211 #ifdef CONFIG_COMPAT
2212 .compat_get = compat_do_ipt_get_ctl,
2214 .owner = THIS_MODULE,
2217 static struct xt_match icmp_matchstruct __read_mostly = {
2219 .match = icmp_match,
2220 .matchsize = sizeof(struct ipt_icmp),
2221 .checkentry = icmp_checkentry,
2222 .proto = IPPROTO_ICMP,
2223 .family = NFPROTO_IPV4,
2226 static int __net_init ip_tables_net_init(struct net *net)
2228 return xt_proto_init(net, NFPROTO_IPV4);
2231 static void __net_exit ip_tables_net_exit(struct net *net)
2233 xt_proto_fini(net, NFPROTO_IPV4);
2236 static struct pernet_operations ip_tables_net_ops = {
2237 .init = ip_tables_net_init,
2238 .exit = ip_tables_net_exit,
2241 static int __init ip_tables_init(void)
2245 ret = register_pernet_subsys(&ip_tables_net_ops);
2249 /* Noone else will be downing sem now, so we won't sleep */
2250 ret = xt_register_target(&ipt_standard_target);
2253 ret = xt_register_target(&ipt_error_target);
2256 ret = xt_register_match(&icmp_matchstruct);
2260 /* Register setsockopt */
2261 ret = nf_register_sockopt(&ipt_sockopts);
2265 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2269 xt_unregister_match(&icmp_matchstruct);
2271 xt_unregister_target(&ipt_error_target);
2273 xt_unregister_target(&ipt_standard_target);
2275 unregister_pernet_subsys(&ip_tables_net_ops);
2280 static void __exit ip_tables_fini(void)
2282 nf_unregister_sockopt(&ipt_sockopts);
2284 xt_unregister_match(&icmp_matchstruct);
2285 xt_unregister_target(&ipt_error_target);
2286 xt_unregister_target(&ipt_standard_target);
2288 unregister_pernet_subsys(&ip_tables_net_ops);
2291 EXPORT_SYMBOL(ipt_register_table);
2292 EXPORT_SYMBOL(ipt_unregister_table);
2293 EXPORT_SYMBOL(ipt_do_table);
2294 module_init(ip_tables_init);
2295 module_exit(ip_tables_fini);