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, unsigned int *i)
558 struct xt_mtdtor_param par;
560 if (i && (*i)-- == 0)
563 par.match = m->u.kernel.match;
564 par.matchinfo = m->data;
565 par.family = NFPROTO_IPV4;
566 if (par.match->destroy != NULL)
567 par.match->destroy(&par);
568 module_put(par.match->me);
573 check_entry(struct ipt_entry *e, const char *name)
575 struct ipt_entry_target *t;
577 if (!ip_checkentry(&e->ip)) {
578 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
582 if (e->target_offset + sizeof(struct ipt_entry_target) >
586 t = ipt_get_target(e);
587 if (e->target_offset + t->u.target_size > e->next_offset)
594 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
597 const struct ipt_ip *ip = par->entryinfo;
600 par->match = m->u.kernel.match;
601 par->matchinfo = m->data;
603 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
604 ip->proto, ip->invflags & IPT_INV_PROTO);
606 duprintf("ip_tables: check failed for `%s'.\n",
615 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
618 struct xt_match *match;
621 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
623 "ipt_%s", m->u.user.name);
624 if (IS_ERR(match) || !match) {
625 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
626 return match ? PTR_ERR(match) : -ENOENT;
628 m->u.kernel.match = match;
630 ret = check_match(m, par, i);
636 module_put(m->u.kernel.match->me);
640 static int check_target(struct ipt_entry *e, const char *name)
642 struct ipt_entry_target *t = ipt_get_target(e);
643 struct xt_tgchk_param par = {
646 .target = t->u.kernel.target,
648 .hook_mask = e->comefrom,
649 .family = NFPROTO_IPV4,
653 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
654 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
656 duprintf("ip_tables: check failed for `%s'.\n",
657 t->u.kernel.target->name);
664 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
665 unsigned int size, unsigned int *i)
667 struct ipt_entry_target *t;
668 struct xt_target *target;
671 struct xt_mtchk_param mtpar;
673 ret = check_entry(e, name);
680 mtpar.entryinfo = &e->ip;
681 mtpar.hook_mask = e->comefrom;
682 mtpar.family = NFPROTO_IPV4;
683 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
685 goto cleanup_matches;
687 t = ipt_get_target(e);
688 target = try_then_request_module(xt_find_target(AF_INET,
691 "ipt_%s", t->u.user.name);
692 if (IS_ERR(target) || !target) {
693 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
694 ret = target ? PTR_ERR(target) : -ENOENT;
695 goto cleanup_matches;
697 t->u.kernel.target = target;
699 ret = check_target(e, name);
706 module_put(t->u.kernel.target->me);
708 IPT_MATCH_ITERATE(e, cleanup_match, &j);
712 static bool check_underflow(struct ipt_entry *e)
714 const struct ipt_entry_target *t;
715 unsigned int verdict;
717 if (!unconditional(&e->ip))
719 t = ipt_get_target(e);
720 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
722 verdict = ((struct ipt_standard_target *)t)->verdict;
723 verdict = -verdict - 1;
724 return verdict == NF_DROP || verdict == NF_ACCEPT;
728 check_entry_size_and_hooks(struct ipt_entry *e,
729 struct xt_table_info *newinfo,
731 unsigned char *limit,
732 const unsigned int *hook_entries,
733 const unsigned int *underflows,
734 unsigned int valid_hooks,
739 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
740 (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
741 duprintf("Bad offset %p\n", e);
746 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
747 duprintf("checking: element %p size %u\n",
752 /* Check hooks & underflows */
753 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
754 if (!(valid_hooks & (1 << h)))
756 if ((unsigned char *)e - base == hook_entries[h])
757 newinfo->hook_entry[h] = hook_entries[h];
758 if ((unsigned char *)e - base == underflows[h]) {
759 if (!check_underflow(e)) {
760 pr_err("Underflows must be unconditional and "
761 "use the STANDARD target with "
765 newinfo->underflow[h] = underflows[h];
769 /* Clear counters and comefrom */
770 e->counters = ((struct xt_counters) { 0, 0 });
778 cleanup_entry(struct ipt_entry *e, unsigned int *i)
780 struct xt_tgdtor_param par;
781 struct ipt_entry_target *t;
783 if (i && (*i)-- == 0)
786 /* Cleanup all matches */
787 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
788 t = ipt_get_target(e);
790 par.target = t->u.kernel.target;
791 par.targinfo = t->data;
792 par.family = NFPROTO_IPV4;
793 if (par.target->destroy != NULL)
794 par.target->destroy(&par);
795 module_put(par.target->me);
799 /* Checks and translates the user-supplied table segment (held in
802 translate_table(struct net *net,
804 unsigned int valid_hooks,
805 struct xt_table_info *newinfo,
809 const unsigned int *hook_entries,
810 const unsigned int *underflows)
815 newinfo->size = size;
816 newinfo->number = number;
818 /* Init all hooks to impossible value. */
819 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
820 newinfo->hook_entry[i] = 0xFFFFFFFF;
821 newinfo->underflow[i] = 0xFFFFFFFF;
824 duprintf("translate_table: size %u\n", newinfo->size);
826 /* Walk through entries, checking offsets. */
827 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
828 check_entry_size_and_hooks,
832 hook_entries, underflows, valid_hooks, &i);
837 duprintf("translate_table: %u not %u entries\n",
842 /* Check hooks all assigned */
843 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
844 /* Only hooks which are valid */
845 if (!(valid_hooks & (1 << i)))
847 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
848 duprintf("Invalid hook entry %u %u\n",
852 if (newinfo->underflow[i] == 0xFFFFFFFF) {
853 duprintf("Invalid underflow %u %u\n",
859 if (!mark_source_chains(newinfo, valid_hooks, entry0))
862 /* Finally, each sanity check must pass */
864 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
865 find_check_entry, net, name, size, &i);
868 IPT_ENTRY_ITERATE(entry0, newinfo->size,
873 /* And one copy for every other CPU */
874 for_each_possible_cpu(i) {
875 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
876 memcpy(newinfo->entries[i], entry0, newinfo->size);
884 add_entry_to_counter(const struct ipt_entry *e,
885 struct xt_counters total[],
888 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
895 set_entry_to_counter(const struct ipt_entry *e,
896 struct ipt_counters total[],
899 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
906 get_counters(const struct xt_table_info *t,
907 struct xt_counters counters[])
913 /* Instead of clearing (by a previous call to memset())
914 * the counters and using adds, we set the counters
915 * with data used by 'current' CPU.
917 * Bottom half has to be disabled to prevent deadlock
918 * if new softirq were to run and call ipt_do_table
921 curcpu = smp_processor_id();
924 IPT_ENTRY_ITERATE(t->entries[curcpu],
926 set_entry_to_counter,
930 for_each_possible_cpu(cpu) {
935 IPT_ENTRY_ITERATE(t->entries[cpu],
937 add_entry_to_counter,
940 xt_info_wrunlock(cpu);
945 static struct xt_counters * alloc_counters(struct xt_table *table)
947 unsigned int countersize;
948 struct xt_counters *counters;
949 struct xt_table_info *private = table->private;
951 /* We need atomic snapshot of counters: rest doesn't change
952 (other than comefrom, which userspace doesn't care
954 countersize = sizeof(struct xt_counters) * private->number;
955 counters = vmalloc_node(countersize, numa_node_id());
957 if (counters == NULL)
958 return ERR_PTR(-ENOMEM);
960 get_counters(private, counters);
966 copy_entries_to_user(unsigned int total_size,
967 struct xt_table *table,
968 void __user *userptr)
970 unsigned int off, num;
972 struct xt_counters *counters;
973 const struct xt_table_info *private = table->private;
975 const void *loc_cpu_entry;
977 counters = alloc_counters(table);
978 if (IS_ERR(counters))
979 return PTR_ERR(counters);
981 /* choose the copy that is on our node/cpu, ...
982 * This choice is lazy (because current thread is
983 * allowed to migrate to another cpu)
985 loc_cpu_entry = private->entries[raw_smp_processor_id()];
986 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
991 /* FIXME: use iterator macros --RR */
992 /* ... then go back and fix counters and names */
993 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
995 const struct ipt_entry_match *m;
996 const struct ipt_entry_target *t;
998 e = (struct ipt_entry *)(loc_cpu_entry + off);
999 if (copy_to_user(userptr + off
1000 + offsetof(struct ipt_entry, counters),
1002 sizeof(counters[num])) != 0) {
1007 for (i = sizeof(struct ipt_entry);
1008 i < e->target_offset;
1009 i += m->u.match_size) {
1012 if (copy_to_user(userptr + off + i
1013 + offsetof(struct ipt_entry_match,
1015 m->u.kernel.match->name,
1016 strlen(m->u.kernel.match->name)+1)
1023 t = ipt_get_target(e);
1024 if (copy_to_user(userptr + off + e->target_offset
1025 + offsetof(struct ipt_entry_target,
1027 t->u.kernel.target->name,
1028 strlen(t->u.kernel.target->name)+1) != 0) {
1039 #ifdef CONFIG_COMPAT
1040 static void compat_standard_from_user(void *dst, void *src)
1042 int v = *(compat_int_t *)src;
1045 v += xt_compat_calc_jump(AF_INET, v);
1046 memcpy(dst, &v, sizeof(v));
1049 static int compat_standard_to_user(void __user *dst, void *src)
1051 compat_int_t cv = *(int *)src;
1054 cv -= xt_compat_calc_jump(AF_INET, cv);
1055 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1059 compat_calc_match(struct ipt_entry_match *m, int *size)
1061 *size += xt_compat_match_offset(m->u.kernel.match);
1065 static int compat_calc_entry(struct ipt_entry *e,
1066 const struct xt_table_info *info,
1067 void *base, struct xt_table_info *newinfo)
1069 struct ipt_entry_target *t;
1070 unsigned int entry_offset;
1073 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1074 entry_offset = (void *)e - base;
1075 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1076 t = ipt_get_target(e);
1077 off += xt_compat_target_offset(t->u.kernel.target);
1078 newinfo->size -= off;
1079 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1083 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1084 if (info->hook_entry[i] &&
1085 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1086 newinfo->hook_entry[i] -= off;
1087 if (info->underflow[i] &&
1088 (e < (struct ipt_entry *)(base + info->underflow[i])))
1089 newinfo->underflow[i] -= off;
1094 static int compat_table_info(const struct xt_table_info *info,
1095 struct xt_table_info *newinfo)
1097 void *loc_cpu_entry;
1099 if (!newinfo || !info)
1102 /* we dont care about newinfo->entries[] */
1103 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1104 newinfo->initial_entries = 0;
1105 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1106 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1107 compat_calc_entry, info, loc_cpu_entry,
1112 static int get_info(struct net *net, void __user *user, int *len, int compat)
1114 char name[IPT_TABLE_MAXNAMELEN];
1118 if (*len != sizeof(struct ipt_getinfo)) {
1119 duprintf("length %u != %zu\n", *len,
1120 sizeof(struct ipt_getinfo));
1124 if (copy_from_user(name, user, sizeof(name)) != 0)
1127 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1128 #ifdef CONFIG_COMPAT
1130 xt_compat_lock(AF_INET);
1132 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1133 "iptable_%s", name);
1134 if (t && !IS_ERR(t)) {
1135 struct ipt_getinfo info;
1136 const struct xt_table_info *private = t->private;
1138 #ifdef CONFIG_COMPAT
1140 struct xt_table_info tmp;
1141 ret = compat_table_info(private, &tmp);
1142 xt_compat_flush_offsets(AF_INET);
1146 info.valid_hooks = t->valid_hooks;
1147 memcpy(info.hook_entry, private->hook_entry,
1148 sizeof(info.hook_entry));
1149 memcpy(info.underflow, private->underflow,
1150 sizeof(info.underflow));
1151 info.num_entries = private->number;
1152 info.size = private->size;
1153 strcpy(info.name, name);
1155 if (copy_to_user(user, &info, *len) != 0)
1163 ret = t ? PTR_ERR(t) : -ENOENT;
1164 #ifdef CONFIG_COMPAT
1166 xt_compat_unlock(AF_INET);
1172 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1175 struct ipt_get_entries get;
1178 if (*len < sizeof(get)) {
1179 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1182 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1184 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1185 duprintf("get_entries: %u != %zu\n",
1186 *len, sizeof(get) + get.size);
1190 t = xt_find_table_lock(net, AF_INET, get.name);
1191 if (t && !IS_ERR(t)) {
1192 const struct xt_table_info *private = t->private;
1193 duprintf("t->private->number = %u\n", private->number);
1194 if (get.size == private->size)
1195 ret = copy_entries_to_user(private->size,
1196 t, uptr->entrytable);
1198 duprintf("get_entries: I've got %u not %u!\n",
1199 private->size, get.size);
1205 ret = t ? PTR_ERR(t) : -ENOENT;
1211 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1212 struct xt_table_info *newinfo, unsigned int num_counters,
1213 void __user *counters_ptr)
1217 struct xt_table_info *oldinfo;
1218 struct xt_counters *counters;
1219 void *loc_cpu_old_entry;
1222 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1228 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1229 "iptable_%s", name);
1230 if (!t || IS_ERR(t)) {
1231 ret = t ? PTR_ERR(t) : -ENOENT;
1232 goto free_newinfo_counters_untrans;
1236 if (valid_hooks != t->valid_hooks) {
1237 duprintf("Valid hook crap: %08X vs %08X\n",
1238 valid_hooks, t->valid_hooks);
1243 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1247 /* Update module usage count based on number of rules */
1248 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1249 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1250 if ((oldinfo->number > oldinfo->initial_entries) ||
1251 (newinfo->number <= oldinfo->initial_entries))
1253 if ((oldinfo->number > oldinfo->initial_entries) &&
1254 (newinfo->number <= oldinfo->initial_entries))
1257 /* Get the old counters, and synchronize with replace */
1258 get_counters(oldinfo, counters);
1260 /* Decrease module usage counts and free resource */
1261 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1262 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1264 xt_free_table_info(oldinfo);
1265 if (copy_to_user(counters_ptr, counters,
1266 sizeof(struct xt_counters) * num_counters) != 0)
1275 free_newinfo_counters_untrans:
1282 do_replace(struct net *net, void __user *user, unsigned int len)
1285 struct ipt_replace tmp;
1286 struct xt_table_info *newinfo;
1287 void *loc_cpu_entry;
1289 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1292 /* overflow check */
1293 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1296 newinfo = xt_alloc_table_info(tmp.size);
1300 /* choose the copy that is on our node/cpu */
1301 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1302 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1308 ret = translate_table(net, tmp.name, tmp.valid_hooks,
1309 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1310 tmp.hook_entry, tmp.underflow);
1314 duprintf("ip_tables: Translated table\n");
1316 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1317 tmp.num_counters, tmp.counters);
1319 goto free_newinfo_untrans;
1322 free_newinfo_untrans:
1323 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1325 xt_free_table_info(newinfo);
1329 /* We're lazy, and add to the first CPU; overflow works its fey magic
1330 * and everything is OK. */
1332 add_counter_to_entry(struct ipt_entry *e,
1333 const struct xt_counters addme[],
1336 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1343 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1345 unsigned int i, curcpu;
1346 struct xt_counters_info tmp;
1347 struct xt_counters *paddc;
1348 unsigned int num_counters;
1353 const struct xt_table_info *private;
1355 void *loc_cpu_entry;
1356 #ifdef CONFIG_COMPAT
1357 struct compat_xt_counters_info compat_tmp;
1361 size = sizeof(struct compat_xt_counters_info);
1366 size = sizeof(struct xt_counters_info);
1369 if (copy_from_user(ptmp, user, size) != 0)
1372 #ifdef CONFIG_COMPAT
1374 num_counters = compat_tmp.num_counters;
1375 name = compat_tmp.name;
1379 num_counters = tmp.num_counters;
1383 if (len != size + num_counters * sizeof(struct xt_counters))
1386 paddc = vmalloc_node(len - size, numa_node_id());
1390 if (copy_from_user(paddc, user + size, len - size) != 0) {
1395 t = xt_find_table_lock(net, AF_INET, name);
1396 if (!t || IS_ERR(t)) {
1397 ret = t ? PTR_ERR(t) : -ENOENT;
1402 private = t->private;
1403 if (private->number != num_counters) {
1405 goto unlock_up_free;
1409 /* Choose the copy that is on our node */
1410 curcpu = smp_processor_id();
1411 loc_cpu_entry = private->entries[curcpu];
1412 xt_info_wrlock(curcpu);
1413 IPT_ENTRY_ITERATE(loc_cpu_entry,
1415 add_counter_to_entry,
1418 xt_info_wrunlock(curcpu);
1429 #ifdef CONFIG_COMPAT
1430 struct compat_ipt_replace {
1431 char name[IPT_TABLE_MAXNAMELEN];
1435 u32 hook_entry[NF_INET_NUMHOOKS];
1436 u32 underflow[NF_INET_NUMHOOKS];
1438 compat_uptr_t counters; /* struct ipt_counters * */
1439 struct compat_ipt_entry entries[0];
1443 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1444 unsigned int *size, struct xt_counters *counters,
1447 struct ipt_entry_target *t;
1448 struct compat_ipt_entry __user *ce;
1449 u_int16_t target_offset, next_offset;
1450 compat_uint_t origsize;
1455 ce = (struct compat_ipt_entry __user *)*dstptr;
1456 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1459 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1462 *dstptr += sizeof(struct compat_ipt_entry);
1463 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1465 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1466 target_offset = e->target_offset - (origsize - *size);
1469 t = ipt_get_target(e);
1470 ret = xt_compat_target_to_user(t, dstptr, size);
1474 next_offset = e->next_offset - (origsize - *size);
1475 if (put_user(target_offset, &ce->target_offset))
1477 if (put_user(next_offset, &ce->next_offset))
1487 compat_find_calc_match(struct ipt_entry_match *m,
1489 const struct ipt_ip *ip,
1490 unsigned int hookmask,
1491 int *size, unsigned int *i)
1493 struct xt_match *match;
1495 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1496 m->u.user.revision),
1497 "ipt_%s", m->u.user.name);
1498 if (IS_ERR(match) || !match) {
1499 duprintf("compat_check_calc_match: `%s' not found\n",
1501 return match ? PTR_ERR(match) : -ENOENT;
1503 m->u.kernel.match = match;
1504 *size += xt_compat_match_offset(match);
1511 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1513 if (i && (*i)-- == 0)
1516 module_put(m->u.kernel.match->me);
1521 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1523 struct ipt_entry_target *t;
1525 if (i && (*i)-- == 0)
1528 /* Cleanup all matches */
1529 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1530 t = compat_ipt_get_target(e);
1531 module_put(t->u.kernel.target->me);
1536 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1537 struct xt_table_info *newinfo,
1539 unsigned char *base,
1540 unsigned char *limit,
1541 unsigned int *hook_entries,
1542 unsigned int *underflows,
1546 struct ipt_entry_target *t;
1547 struct xt_target *target;
1548 unsigned int entry_offset;
1552 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1553 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1554 (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1555 duprintf("Bad offset %p, limit = %p\n", e, limit);
1559 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1560 sizeof(struct compat_xt_entry_target)) {
1561 duprintf("checking: element %p size %u\n",
1566 /* For purposes of check_entry casting the compat entry is fine */
1567 ret = check_entry((struct ipt_entry *)e, name);
1571 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1572 entry_offset = (void *)e - (void *)base;
1574 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1575 &e->ip, e->comefrom, &off, &j);
1577 goto release_matches;
1579 t = compat_ipt_get_target(e);
1580 target = try_then_request_module(xt_find_target(AF_INET,
1582 t->u.user.revision),
1583 "ipt_%s", t->u.user.name);
1584 if (IS_ERR(target) || !target) {
1585 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1587 ret = target ? PTR_ERR(target) : -ENOENT;
1588 goto release_matches;
1590 t->u.kernel.target = target;
1592 off += xt_compat_target_offset(target);
1594 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1598 /* Check hooks & underflows */
1599 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1600 if ((unsigned char *)e - base == hook_entries[h])
1601 newinfo->hook_entry[h] = hook_entries[h];
1602 if ((unsigned char *)e - base == underflows[h])
1603 newinfo->underflow[h] = underflows[h];
1606 /* Clear counters and comefrom */
1607 memset(&e->counters, 0, sizeof(e->counters));
1614 module_put(t->u.kernel.target->me);
1616 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1621 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1622 unsigned int *size, const char *name,
1623 struct xt_table_info *newinfo, unsigned char *base)
1625 struct ipt_entry_target *t;
1626 struct xt_target *target;
1627 struct ipt_entry *de;
1628 unsigned int origsize;
1633 de = (struct ipt_entry *)*dstptr;
1634 memcpy(de, e, sizeof(struct ipt_entry));
1635 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1637 *dstptr += sizeof(struct ipt_entry);
1638 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1640 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1644 de->target_offset = e->target_offset - (origsize - *size);
1645 t = compat_ipt_get_target(e);
1646 target = t->u.kernel.target;
1647 xt_compat_target_from_user(t, dstptr, size);
1649 de->next_offset = e->next_offset - (origsize - *size);
1650 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1651 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1652 newinfo->hook_entry[h] -= origsize - *size;
1653 if ((unsigned char *)de - base < newinfo->underflow[h])
1654 newinfo->underflow[h] -= origsize - *size;
1660 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,
1663 struct xt_mtchk_param mtpar;
1670 mtpar.entryinfo = &e->ip;
1671 mtpar.hook_mask = e->comefrom;
1672 mtpar.family = NFPROTO_IPV4;
1673 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1675 goto cleanup_matches;
1677 ret = check_target(e, name);
1679 goto cleanup_matches;
1685 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1690 translate_compat_table(struct net *net,
1692 unsigned int valid_hooks,
1693 struct xt_table_info **pinfo,
1695 unsigned int total_size,
1696 unsigned int number,
1697 unsigned int *hook_entries,
1698 unsigned int *underflows)
1701 struct xt_table_info *newinfo, *info;
1702 void *pos, *entry0, *entry1;
1709 info->number = number;
1711 /* Init all hooks to impossible value. */
1712 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1713 info->hook_entry[i] = 0xFFFFFFFF;
1714 info->underflow[i] = 0xFFFFFFFF;
1717 duprintf("translate_compat_table: size %u\n", info->size);
1719 xt_compat_lock(AF_INET);
1720 /* Walk through entries, checking offsets. */
1721 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1722 check_compat_entry_size_and_hooks,
1723 info, &size, entry0,
1724 entry0 + total_size,
1725 hook_entries, underflows, &j, name);
1731 duprintf("translate_compat_table: %u not %u entries\n",
1736 /* Check hooks all assigned */
1737 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1738 /* Only hooks which are valid */
1739 if (!(valid_hooks & (1 << i)))
1741 if (info->hook_entry[i] == 0xFFFFFFFF) {
1742 duprintf("Invalid hook entry %u %u\n",
1743 i, hook_entries[i]);
1746 if (info->underflow[i] == 0xFFFFFFFF) {
1747 duprintf("Invalid underflow %u %u\n",
1754 newinfo = xt_alloc_table_info(size);
1758 newinfo->number = number;
1759 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1760 newinfo->hook_entry[i] = info->hook_entry[i];
1761 newinfo->underflow[i] = info->underflow[i];
1763 entry1 = newinfo->entries[raw_smp_processor_id()];
1766 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1767 compat_copy_entry_from_user,
1768 &pos, &size, name, newinfo, entry1);
1769 xt_compat_flush_offsets(AF_INET);
1770 xt_compat_unlock(AF_INET);
1775 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1779 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1783 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1784 compat_release_entry, &j);
1785 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1786 xt_free_table_info(newinfo);
1790 /* And one copy for every other CPU */
1791 for_each_possible_cpu(i)
1792 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1793 memcpy(newinfo->entries[i], entry1, newinfo->size);
1797 xt_free_table_info(info);
1801 xt_free_table_info(newinfo);
1803 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1806 xt_compat_flush_offsets(AF_INET);
1807 xt_compat_unlock(AF_INET);
1812 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1815 struct compat_ipt_replace tmp;
1816 struct xt_table_info *newinfo;
1817 void *loc_cpu_entry;
1819 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1822 /* overflow check */
1823 if (tmp.size >= INT_MAX / num_possible_cpus())
1825 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1828 newinfo = xt_alloc_table_info(tmp.size);
1832 /* choose the copy that is on our node/cpu */
1833 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1834 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1840 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1841 &newinfo, &loc_cpu_entry, tmp.size,
1842 tmp.num_entries, tmp.hook_entry,
1847 duprintf("compat_do_replace: Translated table\n");
1849 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1850 tmp.num_counters, compat_ptr(tmp.counters));
1852 goto free_newinfo_untrans;
1855 free_newinfo_untrans:
1856 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1858 xt_free_table_info(newinfo);
1863 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1868 if (!capable(CAP_NET_ADMIN))
1872 case IPT_SO_SET_REPLACE:
1873 ret = compat_do_replace(sock_net(sk), user, len);
1876 case IPT_SO_SET_ADD_COUNTERS:
1877 ret = do_add_counters(sock_net(sk), user, len, 1);
1881 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1888 struct compat_ipt_get_entries {
1889 char name[IPT_TABLE_MAXNAMELEN];
1891 struct compat_ipt_entry entrytable[0];
1895 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1896 void __user *userptr)
1898 struct xt_counters *counters;
1899 const struct xt_table_info *private = table->private;
1903 const void *loc_cpu_entry;
1906 counters = alloc_counters(table);
1907 if (IS_ERR(counters))
1908 return PTR_ERR(counters);
1910 /* choose the copy that is on our node/cpu, ...
1911 * This choice is lazy (because current thread is
1912 * allowed to migrate to another cpu)
1914 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1917 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1918 compat_copy_entry_to_user,
1919 &pos, &size, counters, &i);
1926 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1930 struct compat_ipt_get_entries get;
1933 if (*len < sizeof(get)) {
1934 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1938 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1941 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1942 duprintf("compat_get_entries: %u != %zu\n",
1943 *len, sizeof(get) + get.size);
1947 xt_compat_lock(AF_INET);
1948 t = xt_find_table_lock(net, AF_INET, get.name);
1949 if (t && !IS_ERR(t)) {
1950 const struct xt_table_info *private = t->private;
1951 struct xt_table_info info;
1952 duprintf("t->private->number = %u\n", private->number);
1953 ret = compat_table_info(private, &info);
1954 if (!ret && get.size == info.size) {
1955 ret = compat_copy_entries_to_user(private->size,
1956 t, uptr->entrytable);
1958 duprintf("compat_get_entries: I've got %u not %u!\n",
1959 private->size, get.size);
1962 xt_compat_flush_offsets(AF_INET);
1966 ret = t ? PTR_ERR(t) : -ENOENT;
1968 xt_compat_unlock(AF_INET);
1972 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1975 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1979 if (!capable(CAP_NET_ADMIN))
1983 case IPT_SO_GET_INFO:
1984 ret = get_info(sock_net(sk), user, len, 1);
1986 case IPT_SO_GET_ENTRIES:
1987 ret = compat_get_entries(sock_net(sk), user, len);
1990 ret = do_ipt_get_ctl(sk, cmd, user, len);
1997 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2001 if (!capable(CAP_NET_ADMIN))
2005 case IPT_SO_SET_REPLACE:
2006 ret = do_replace(sock_net(sk), user, len);
2009 case IPT_SO_SET_ADD_COUNTERS:
2010 ret = do_add_counters(sock_net(sk), user, len, 0);
2014 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2022 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2026 if (!capable(CAP_NET_ADMIN))
2030 case IPT_SO_GET_INFO:
2031 ret = get_info(sock_net(sk), user, len, 0);
2034 case IPT_SO_GET_ENTRIES:
2035 ret = get_entries(sock_net(sk), user, len);
2038 case IPT_SO_GET_REVISION_MATCH:
2039 case IPT_SO_GET_REVISION_TARGET: {
2040 struct ipt_get_revision rev;
2043 if (*len != sizeof(rev)) {
2047 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2052 if (cmd == IPT_SO_GET_REVISION_TARGET)
2057 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2060 "ipt_%s", rev.name);
2065 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2072 struct xt_table *ipt_register_table(struct net *net,
2073 const struct xt_table *table,
2074 const struct ipt_replace *repl)
2077 struct xt_table_info *newinfo;
2078 struct xt_table_info bootstrap
2079 = { 0, 0, 0, { 0 }, { 0 }, { } };
2080 void *loc_cpu_entry;
2081 struct xt_table *new_table;
2083 newinfo = xt_alloc_table_info(repl->size);
2089 /* choose the copy on our node/cpu, but dont care about preemption */
2090 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2091 memcpy(loc_cpu_entry, repl->entries, repl->size);
2093 ret = translate_table(net, table->name, table->valid_hooks,
2094 newinfo, loc_cpu_entry, repl->size,
2101 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2102 if (IS_ERR(new_table)) {
2103 ret = PTR_ERR(new_table);
2110 xt_free_table_info(newinfo);
2112 return ERR_PTR(ret);
2115 void ipt_unregister_table(struct xt_table *table)
2117 struct xt_table_info *private;
2118 void *loc_cpu_entry;
2119 struct module *table_owner = table->me;
2121 private = xt_unregister_table(table);
2123 /* Decrease module usage counts and free resources */
2124 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2125 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2126 if (private->number > private->initial_entries)
2127 module_put(table_owner);
2128 xt_free_table_info(private);
2131 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2133 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2134 u_int8_t type, u_int8_t code,
2137 return ((test_type == 0xFF) ||
2138 (type == test_type && code >= min_code && code <= max_code))
2143 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2145 const struct icmphdr *ic;
2146 struct icmphdr _icmph;
2147 const struct ipt_icmp *icmpinfo = par->matchinfo;
2149 /* Must not be a fragment. */
2150 if (par->fragoff != 0)
2153 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2155 /* We've been asked to examine this packet, and we
2156 * can't. Hence, no choice but to drop.
2158 duprintf("Dropping evil ICMP tinygram.\n");
2159 *par->hotdrop = true;
2163 return icmp_type_code_match(icmpinfo->type,
2167 !!(icmpinfo->invflags&IPT_ICMP_INV));
2170 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2172 const struct ipt_icmp *icmpinfo = par->matchinfo;
2174 /* Must specify no unknown invflags */
2175 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2178 /* The built-in targets: standard (NULL) and error. */
2179 static struct xt_target ipt_standard_target __read_mostly = {
2180 .name = IPT_STANDARD_TARGET,
2181 .targetsize = sizeof(int),
2182 .family = NFPROTO_IPV4,
2183 #ifdef CONFIG_COMPAT
2184 .compatsize = sizeof(compat_int_t),
2185 .compat_from_user = compat_standard_from_user,
2186 .compat_to_user = compat_standard_to_user,
2190 static struct xt_target ipt_error_target __read_mostly = {
2191 .name = IPT_ERROR_TARGET,
2192 .target = ipt_error,
2193 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2194 .family = NFPROTO_IPV4,
2197 static struct nf_sockopt_ops ipt_sockopts = {
2199 .set_optmin = IPT_BASE_CTL,
2200 .set_optmax = IPT_SO_SET_MAX+1,
2201 .set = do_ipt_set_ctl,
2202 #ifdef CONFIG_COMPAT
2203 .compat_set = compat_do_ipt_set_ctl,
2205 .get_optmin = IPT_BASE_CTL,
2206 .get_optmax = IPT_SO_GET_MAX+1,
2207 .get = do_ipt_get_ctl,
2208 #ifdef CONFIG_COMPAT
2209 .compat_get = compat_do_ipt_get_ctl,
2211 .owner = THIS_MODULE,
2214 static struct xt_match icmp_matchstruct __read_mostly = {
2216 .match = icmp_match,
2217 .matchsize = sizeof(struct ipt_icmp),
2218 .checkentry = icmp_checkentry,
2219 .proto = IPPROTO_ICMP,
2220 .family = NFPROTO_IPV4,
2223 static int __net_init ip_tables_net_init(struct net *net)
2225 return xt_proto_init(net, NFPROTO_IPV4);
2228 static void __net_exit ip_tables_net_exit(struct net *net)
2230 xt_proto_fini(net, NFPROTO_IPV4);
2233 static struct pernet_operations ip_tables_net_ops = {
2234 .init = ip_tables_net_init,
2235 .exit = ip_tables_net_exit,
2238 static int __init ip_tables_init(void)
2242 ret = register_pernet_subsys(&ip_tables_net_ops);
2246 /* Noone else will be downing sem now, so we won't sleep */
2247 ret = xt_register_target(&ipt_standard_target);
2250 ret = xt_register_target(&ipt_error_target);
2253 ret = xt_register_match(&icmp_matchstruct);
2257 /* Register setsockopt */
2258 ret = nf_register_sockopt(&ipt_sockopts);
2262 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2266 xt_unregister_match(&icmp_matchstruct);
2268 xt_unregister_target(&ipt_error_target);
2270 xt_unregister_target(&ipt_standard_target);
2272 unregister_pernet_subsys(&ip_tables_net_ops);
2277 static void __exit ip_tables_fini(void)
2279 nf_unregister_sockopt(&ipt_sockopts);
2281 xt_unregister_match(&icmp_matchstruct);
2282 xt_unregister_target(&ipt_error_target);
2283 xt_unregister_target(&ipt_standard_target);
2285 unregister_pernet_subsys(&ip_tables_net_ops);
2288 EXPORT_SYMBOL(ipt_register_table);
2289 EXPORT_SYMBOL(ipt_unregister_table);
2290 EXPORT_SYMBOL(ipt_do_table);
2291 module_init(ip_tables_init);
2292 module_exit(ip_tables_fini);