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 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
12 * - increase module usage count as soon as we have rules inside
14 * 08 Oct 2005 Harald Welte <lafore@netfilter.org>
15 * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables"
17 #include <linux/config.h>
18 #include <linux/cache.h>
19 #include <linux/capability.h>
20 #include <linux/skbuff.h>
21 #include <linux/kmod.h>
22 #include <linux/vmalloc.h>
23 #include <linux/netdevice.h>
24 #include <linux/module.h>
25 #include <linux/icmp.h>
27 #include <asm/uaccess.h>
28 #include <asm/semaphore.h>
29 #include <linux/proc_fs.h>
30 #include <linux/err.h>
31 #include <linux/cpumask.h>
33 #include <linux/netfilter/x_tables.h>
34 #include <linux/netfilter_ipv4/ip_tables.h>
36 MODULE_LICENSE("GPL");
37 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
38 MODULE_DESCRIPTION("IPv4 packet filter");
40 /*#define DEBUG_IP_FIREWALL*/
41 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
42 /*#define DEBUG_IP_FIREWALL_USER*/
44 #ifdef DEBUG_IP_FIREWALL
45 #define dprintf(format, args...) printk(format , ## args)
47 #define dprintf(format, args...)
50 #ifdef DEBUG_IP_FIREWALL_USER
51 #define duprintf(format, args...) printk(format , ## args)
53 #define duprintf(format, args...)
56 #ifdef CONFIG_NETFILTER_DEBUG
57 #define IP_NF_ASSERT(x) \
60 printk("IP_NF_ASSERT: %s:%s:%u\n", \
61 __FUNCTION__, __FILE__, __LINE__); \
64 #define IP_NF_ASSERT(x)
68 /* All the better to debug you with... */
74 We keep a set of rules for each CPU, so we can avoid write-locking
75 them in the softirq when updating the counters and therefore
76 only need to read-lock in the softirq; doing a write_lock_bh() in user
77 context stops packets coming through and allows user context to read
78 the counters or update the rules.
80 Hence the start of any table is given by get_table() below. */
82 /* Returns whether matches rule or not. */
84 ip_packet_match(const struct iphdr *ip,
87 const struct ipt_ip *ipinfo,
93 #define FWINV(bool,invflg) ((bool) ^ !!(ipinfo->invflags & invflg))
95 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
97 || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
99 dprintf("Source or dest mismatch.\n");
101 dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
103 NIPQUAD(ipinfo->smsk.s_addr),
104 NIPQUAD(ipinfo->src.s_addr),
105 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
106 dprintf("DST: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
108 NIPQUAD(ipinfo->dmsk.s_addr),
109 NIPQUAD(ipinfo->dst.s_addr),
110 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
114 /* Look for ifname matches; this should unroll nicely. */
115 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
116 ret |= (((const unsigned long *)indev)[i]
117 ^ ((const unsigned long *)ipinfo->iniface)[i])
118 & ((const unsigned long *)ipinfo->iniface_mask)[i];
121 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
122 dprintf("VIA in mismatch (%s vs %s).%s\n",
123 indev, ipinfo->iniface,
124 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
128 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
129 ret |= (((const unsigned long *)outdev)[i]
130 ^ ((const unsigned long *)ipinfo->outiface)[i])
131 & ((const unsigned long *)ipinfo->outiface_mask)[i];
134 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
135 dprintf("VIA out mismatch (%s vs %s).%s\n",
136 outdev, ipinfo->outiface,
137 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
141 /* Check specific protocol */
143 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
144 dprintf("Packet protocol %hi does not match %hi.%s\n",
145 ip->protocol, ipinfo->proto,
146 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
150 /* If we have a fragment rule but the packet is not a fragment
151 * then we return zero */
152 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
153 dprintf("Fragment rule but not fragment.%s\n",
154 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
162 ip_checkentry(const struct ipt_ip *ip)
164 if (ip->flags & ~IPT_F_MASK) {
165 duprintf("Unknown flag bits set: %08X\n",
166 ip->flags & ~IPT_F_MASK);
169 if (ip->invflags & ~IPT_INV_MASK) {
170 duprintf("Unknown invflag bits set: %08X\n",
171 ip->invflags & ~IPT_INV_MASK);
178 ipt_error(struct sk_buff **pskb,
179 const struct net_device *in,
180 const struct net_device *out,
181 unsigned int hooknum,
182 const void *targinfo,
186 printk("ip_tables: error: `%s'\n", (char *)targinfo);
192 int do_match(struct ipt_entry_match *m,
193 const struct sk_buff *skb,
194 const struct net_device *in,
195 const struct net_device *out,
199 /* Stop iteration if it doesn't match */
200 if (!m->u.kernel.match->match(skb, in, out, m->data, offset,
201 skb->nh.iph->ihl*4, hotdrop))
207 static inline struct ipt_entry *
208 get_entry(void *base, unsigned int offset)
210 return (struct ipt_entry *)(base + offset);
213 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
215 ipt_do_table(struct sk_buff **pskb,
217 const struct net_device *in,
218 const struct net_device *out,
219 struct ipt_table *table,
222 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
227 /* Initializing verdict to NF_DROP keeps gcc happy. */
228 unsigned int verdict = NF_DROP;
229 const char *indev, *outdev;
231 struct ipt_entry *e, *back;
232 struct xt_table_info *private = table->private;
235 ip = (*pskb)->nh.iph;
236 datalen = (*pskb)->len - ip->ihl * 4;
237 indev = in ? in->name : nulldevname;
238 outdev = out ? out->name : nulldevname;
239 /* We handle fragments by dealing with the first fragment as
240 * if it was a normal packet. All other fragments are treated
241 * normally, except that they will NEVER match rules that ask
242 * things we don't know, ie. tcp syn flag or ports). If the
243 * rule is also a fragment-specific rule, non-fragments won't
245 offset = ntohs(ip->frag_off) & IP_OFFSET;
247 read_lock_bh(&table->lock);
248 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
249 table_base = (void *)private->entries[smp_processor_id()];
250 e = get_entry(table_base, private->hook_entry[hook]);
252 /* For return from builtin chain */
253 back = get_entry(table_base, private->underflow[hook]);
258 if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
259 struct ipt_entry_target *t;
261 if (IPT_MATCH_ITERATE(e, do_match,
263 offset, &hotdrop) != 0)
266 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
268 t = ipt_get_target(e);
269 IP_NF_ASSERT(t->u.kernel.target);
270 /* Standard target? */
271 if (!t->u.kernel.target->target) {
274 v = ((struct ipt_standard_target *)t)->verdict;
276 /* Pop from stack? */
277 if (v != IPT_RETURN) {
278 verdict = (unsigned)(-v) - 1;
282 back = get_entry(table_base,
286 if (table_base + v != (void *)e + e->next_offset
287 && !(e->ip.flags & IPT_F_GOTO)) {
288 /* Save old back ptr in next entry */
289 struct ipt_entry *next
290 = (void *)e + e->next_offset;
292 = (void *)back - table_base;
293 /* set back pointer to next entry */
297 e = get_entry(table_base, v);
299 /* Targets which reenter must return
301 #ifdef CONFIG_NETFILTER_DEBUG
302 ((struct ipt_entry *)table_base)->comefrom
305 verdict = t->u.kernel.target->target(pskb,
311 #ifdef CONFIG_NETFILTER_DEBUG
312 if (((struct ipt_entry *)table_base)->comefrom
314 && verdict == IPT_CONTINUE) {
315 printk("Target %s reentered!\n",
316 t->u.kernel.target->name);
319 ((struct ipt_entry *)table_base)->comefrom
322 /* Target might have changed stuff. */
323 ip = (*pskb)->nh.iph;
324 datalen = (*pskb)->len - ip->ihl * 4;
326 if (verdict == IPT_CONTINUE)
327 e = (void *)e + e->next_offset;
335 e = (void *)e + e->next_offset;
339 read_unlock_bh(&table->lock);
341 #ifdef DEBUG_ALLOW_ALL
350 /* All zeroes == unconditional rule. */
352 unconditional(const struct ipt_ip *ip)
356 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
357 if (((__u32 *)ip)[i])
363 /* Figures out from what hook each rule can be called: returns 0 if
364 there are loops. Puts hook bitmask in comefrom. */
366 mark_source_chains(struct xt_table_info *newinfo,
367 unsigned int valid_hooks, void *entry0)
371 /* No recursion; use packet counter to save back ptrs (reset
372 to 0 as we leave), and comefrom to save source hook bitmask */
373 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
374 unsigned int pos = newinfo->hook_entry[hook];
376 = (struct ipt_entry *)(entry0 + pos);
378 if (!(valid_hooks & (1 << hook)))
381 /* Set initial back pointer. */
382 e->counters.pcnt = pos;
385 struct ipt_standard_target *t
386 = (void *)ipt_get_target(e);
388 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
389 printk("iptables: loop hook %u pos %u %08X.\n",
390 hook, pos, e->comefrom);
394 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
396 /* Unconditional return/END. */
397 if (e->target_offset == sizeof(struct ipt_entry)
398 && (strcmp(t->target.u.user.name,
399 IPT_STANDARD_TARGET) == 0)
401 && unconditional(&e->ip)) {
402 unsigned int oldpos, size;
404 /* Return: backtrack through the last
407 e->comefrom ^= (1<<NF_IP_NUMHOOKS);
408 #ifdef DEBUG_IP_FIREWALL_USER
410 & (1 << NF_IP_NUMHOOKS)) {
411 duprintf("Back unset "
418 pos = e->counters.pcnt;
419 e->counters.pcnt = 0;
421 /* We're at the start. */
425 e = (struct ipt_entry *)
427 } while (oldpos == pos + e->next_offset);
430 size = e->next_offset;
431 e = (struct ipt_entry *)
432 (entry0 + pos + size);
433 e->counters.pcnt = pos;
436 int newpos = t->verdict;
438 if (strcmp(t->target.u.user.name,
439 IPT_STANDARD_TARGET) == 0
441 /* This a jump; chase it. */
442 duprintf("Jump rule %u -> %u\n",
445 /* ... this is a fallthru */
446 newpos = pos + e->next_offset;
448 e = (struct ipt_entry *)
450 e->counters.pcnt = pos;
455 duprintf("Finished chain %u\n", hook);
461 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
463 if (i && (*i)-- == 0)
466 if (m->u.kernel.match->destroy)
467 m->u.kernel.match->destroy(m->data,
468 m->u.match_size - sizeof(*m));
469 module_put(m->u.kernel.match->me);
474 standard_check(const struct ipt_entry_target *t,
475 unsigned int max_offset)
477 struct ipt_standard_target *targ = (void *)t;
479 /* Check standard info. */
481 != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
482 duprintf("standard_check: target size %u != %u\n",
484 IPT_ALIGN(sizeof(struct ipt_standard_target)));
488 if (targ->verdict >= 0
489 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
490 duprintf("ipt_standard_check: bad verdict (%i)\n",
495 if (targ->verdict < -NF_MAX_VERDICT - 1) {
496 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
504 check_match(struct ipt_entry_match *m,
506 const struct ipt_ip *ip,
507 unsigned int hookmask,
510 struct ipt_match *match;
512 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
514 "ipt_%s", m->u.user.name);
515 if (IS_ERR(match) || !match) {
516 duprintf("check_match: `%s' not found\n", m->u.user.name);
517 return match ? PTR_ERR(match) : -ENOENT;
519 m->u.kernel.match = match;
521 if (m->u.kernel.match->checkentry
522 && !m->u.kernel.match->checkentry(name, ip, m->data,
523 m->u.match_size - sizeof(*m),
525 module_put(m->u.kernel.match->me);
526 duprintf("ip_tables: check failed for `%s'.\n",
527 m->u.kernel.match->name);
535 static struct ipt_target ipt_standard_target;
538 check_entry(struct ipt_entry *e, const char *name, unsigned int size,
541 struct ipt_entry_target *t;
542 struct ipt_target *target;
546 if (!ip_checkentry(&e->ip)) {
547 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
552 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
554 goto cleanup_matches;
556 t = ipt_get_target(e);
557 target = try_then_request_module(xt_find_target(AF_INET,
560 "ipt_%s", t->u.user.name);
561 if (IS_ERR(target) || !target) {
562 duprintf("check_entry: `%s' not found\n", t->u.user.name);
563 ret = target ? PTR_ERR(target) : -ENOENT;
564 goto cleanup_matches;
566 t->u.kernel.target = target;
568 if (t->u.kernel.target == &ipt_standard_target) {
569 if (!standard_check(t, size)) {
571 goto cleanup_matches;
573 } else if (t->u.kernel.target->checkentry
574 && !t->u.kernel.target->checkentry(name, e, t->data,
578 module_put(t->u.kernel.target->me);
579 duprintf("ip_tables: check failed for `%s'.\n",
580 t->u.kernel.target->name);
582 goto cleanup_matches;
589 IPT_MATCH_ITERATE(e, cleanup_match, &j);
594 check_entry_size_and_hooks(struct ipt_entry *e,
595 struct xt_table_info *newinfo,
597 unsigned char *limit,
598 const unsigned int *hook_entries,
599 const unsigned int *underflows,
604 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
605 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
606 duprintf("Bad offset %p\n", e);
611 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
612 duprintf("checking: element %p size %u\n",
617 /* Check hooks & underflows */
618 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
619 if ((unsigned char *)e - base == hook_entries[h])
620 newinfo->hook_entry[h] = hook_entries[h];
621 if ((unsigned char *)e - base == underflows[h])
622 newinfo->underflow[h] = underflows[h];
625 /* FIXME: underflows must be unconditional, standard verdicts
626 < 0 (not IPT_RETURN). --RR */
628 /* Clear counters and comefrom */
629 e->counters = ((struct xt_counters) { 0, 0 });
637 cleanup_entry(struct ipt_entry *e, unsigned int *i)
639 struct ipt_entry_target *t;
641 if (i && (*i)-- == 0)
644 /* Cleanup all matches */
645 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
646 t = ipt_get_target(e);
647 if (t->u.kernel.target->destroy)
648 t->u.kernel.target->destroy(t->data,
649 t->u.target_size - sizeof(*t));
650 module_put(t->u.kernel.target->me);
654 /* Checks and translates the user-supplied table segment (held in
657 translate_table(const char *name,
658 unsigned int valid_hooks,
659 struct xt_table_info *newinfo,
663 const unsigned int *hook_entries,
664 const unsigned int *underflows)
669 newinfo->size = size;
670 newinfo->number = number;
672 /* Init all hooks to impossible value. */
673 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
674 newinfo->hook_entry[i] = 0xFFFFFFFF;
675 newinfo->underflow[i] = 0xFFFFFFFF;
678 duprintf("translate_table: size %u\n", newinfo->size);
680 /* Walk through entries, checking offsets. */
681 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
682 check_entry_size_and_hooks,
686 hook_entries, underflows, &i);
691 duprintf("translate_table: %u not %u entries\n",
696 /* Check hooks all assigned */
697 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
698 /* Only hooks which are valid */
699 if (!(valid_hooks & (1 << i)))
701 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
702 duprintf("Invalid hook entry %u %u\n",
706 if (newinfo->underflow[i] == 0xFFFFFFFF) {
707 duprintf("Invalid underflow %u %u\n",
713 if (!mark_source_chains(newinfo, valid_hooks, entry0))
716 /* Finally, each sanity check must pass */
718 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
719 check_entry, name, size, &i);
722 IPT_ENTRY_ITERATE(entry0, newinfo->size,
727 /* And one copy for every other CPU */
729 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
730 memcpy(newinfo->entries[i], entry0, newinfo->size);
738 add_entry_to_counter(const struct ipt_entry *e,
739 struct xt_counters total[],
742 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
749 set_entry_to_counter(const struct ipt_entry *e,
750 struct ipt_counters total[],
753 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
760 get_counters(const struct xt_table_info *t,
761 struct xt_counters counters[])
767 /* Instead of clearing (by a previous call to memset())
768 * the counters and using adds, we set the counters
769 * with data used by 'current' CPU
770 * We dont care about preemption here.
772 curcpu = raw_smp_processor_id();
775 IPT_ENTRY_ITERATE(t->entries[curcpu],
777 set_entry_to_counter,
785 IPT_ENTRY_ITERATE(t->entries[cpu],
787 add_entry_to_counter,
794 copy_entries_to_user(unsigned int total_size,
795 struct ipt_table *table,
796 void __user *userptr)
798 unsigned int off, num, countersize;
800 struct xt_counters *counters;
801 struct xt_table_info *private = table->private;
805 /* We need atomic snapshot of counters: rest doesn't change
806 (other than comefrom, which userspace doesn't care
808 countersize = sizeof(struct xt_counters) * private->number;
809 counters = vmalloc_node(countersize, numa_node_id());
811 if (counters == NULL)
814 /* First, sum counters... */
815 write_lock_bh(&table->lock);
816 get_counters(private, counters);
817 write_unlock_bh(&table->lock);
819 /* choose the copy that is on our node/cpu, ...
820 * This choice is lazy (because current thread is
821 * allowed to migrate to another cpu)
823 loc_cpu_entry = private->entries[raw_smp_processor_id()];
824 /* ... then copy entire thing ... */
825 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
830 /* FIXME: use iterator macros --RR */
831 /* ... then go back and fix counters and names */
832 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
834 struct ipt_entry_match *m;
835 struct ipt_entry_target *t;
837 e = (struct ipt_entry *)(loc_cpu_entry + off);
838 if (copy_to_user(userptr + off
839 + offsetof(struct ipt_entry, counters),
841 sizeof(counters[num])) != 0) {
846 for (i = sizeof(struct ipt_entry);
847 i < e->target_offset;
848 i += m->u.match_size) {
851 if (copy_to_user(userptr + off + i
852 + offsetof(struct ipt_entry_match,
854 m->u.kernel.match->name,
855 strlen(m->u.kernel.match->name)+1)
862 t = ipt_get_target(e);
863 if (copy_to_user(userptr + off + e->target_offset
864 + offsetof(struct ipt_entry_target,
866 t->u.kernel.target->name,
867 strlen(t->u.kernel.target->name)+1) != 0) {
879 get_entries(const struct ipt_get_entries *entries,
880 struct ipt_get_entries __user *uptr)
885 t = xt_find_table_lock(AF_INET, entries->name);
886 if (t && !IS_ERR(t)) {
887 struct xt_table_info *private = t->private;
888 duprintf("t->private->number = %u\n",
890 if (entries->size == private->size)
891 ret = copy_entries_to_user(private->size,
892 t, uptr->entrytable);
894 duprintf("get_entries: I've got %u not %u!\n",
902 ret = t ? PTR_ERR(t) : -ENOENT;
908 do_replace(void __user *user, unsigned int len)
911 struct ipt_replace tmp;
913 struct xt_table_info *newinfo, *oldinfo;
914 struct xt_counters *counters;
915 void *loc_cpu_entry, *loc_cpu_old_entry;
917 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
920 /* Hack: Causes ipchains to give correct error msg --RR */
921 if (len != sizeof(tmp) + tmp.size)
925 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
928 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
931 newinfo = xt_alloc_table_info(tmp.size);
935 /* choose the copy that is our node/cpu */
936 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
937 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
943 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
949 ret = translate_table(tmp.name, tmp.valid_hooks,
950 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
951 tmp.hook_entry, tmp.underflow);
953 goto free_newinfo_counters;
955 duprintf("ip_tables: Translated table\n");
957 t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
958 "iptable_%s", tmp.name);
959 if (!t || IS_ERR(t)) {
960 ret = t ? PTR_ERR(t) : -ENOENT;
961 goto free_newinfo_counters_untrans;
965 if (tmp.valid_hooks != t->valid_hooks) {
966 duprintf("Valid hook crap: %08X vs %08X\n",
967 tmp.valid_hooks, t->valid_hooks);
972 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
976 /* Update module usage count based on number of rules */
977 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
978 oldinfo->number, oldinfo->initial_entries, newinfo->number);
979 if ((oldinfo->number > oldinfo->initial_entries) ||
980 (newinfo->number <= oldinfo->initial_entries))
982 if ((oldinfo->number > oldinfo->initial_entries) &&
983 (newinfo->number <= oldinfo->initial_entries))
986 /* Get the old counters. */
987 get_counters(oldinfo, counters);
988 /* Decrease module usage counts and free resource */
989 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
990 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
991 xt_free_table_info(oldinfo);
992 if (copy_to_user(tmp.counters, counters,
993 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1002 free_newinfo_counters_untrans:
1003 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1004 free_newinfo_counters:
1007 xt_free_table_info(newinfo);
1011 /* We're lazy, and add to the first CPU; overflow works its fey magic
1012 * and everything is OK. */
1014 add_counter_to_entry(struct ipt_entry *e,
1015 const struct xt_counters addme[],
1019 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1021 (long unsigned int)e->counters.pcnt,
1022 (long unsigned int)e->counters.bcnt,
1023 (long unsigned int)addme[*i].pcnt,
1024 (long unsigned int)addme[*i].bcnt);
1027 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1034 do_add_counters(void __user *user, unsigned int len)
1037 struct xt_counters_info tmp, *paddc;
1038 struct ipt_table *t;
1039 struct xt_table_info *private;
1041 void *loc_cpu_entry;
1043 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1046 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1049 paddc = vmalloc_node(len, numa_node_id());
1053 if (copy_from_user(paddc, user, len) != 0) {
1058 t = xt_find_table_lock(AF_INET, tmp.name);
1059 if (!t || IS_ERR(t)) {
1060 ret = t ? PTR_ERR(t) : -ENOENT;
1064 write_lock_bh(&t->lock);
1065 private = t->private;
1066 if (private->number != paddc->num_counters) {
1068 goto unlock_up_free;
1072 /* Choose the copy that is on our node */
1073 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1074 IPT_ENTRY_ITERATE(loc_cpu_entry,
1076 add_counter_to_entry,
1080 write_unlock_bh(&t->lock);
1090 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1094 if (!capable(CAP_NET_ADMIN))
1098 case IPT_SO_SET_REPLACE:
1099 ret = do_replace(user, len);
1102 case IPT_SO_SET_ADD_COUNTERS:
1103 ret = do_add_counters(user, len);
1107 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1115 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1119 if (!capable(CAP_NET_ADMIN))
1123 case IPT_SO_GET_INFO: {
1124 char name[IPT_TABLE_MAXNAMELEN];
1125 struct ipt_table *t;
1127 if (*len != sizeof(struct ipt_getinfo)) {
1128 duprintf("length %u != %u\n", *len,
1129 sizeof(struct ipt_getinfo));
1134 if (copy_from_user(name, user, sizeof(name)) != 0) {
1138 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1140 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1141 "iptable_%s", name);
1142 if (t && !IS_ERR(t)) {
1143 struct ipt_getinfo info;
1144 struct xt_table_info *private = t->private;
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 memcpy(info.name, name, sizeof(info.name));
1155 if (copy_to_user(user, &info, *len) != 0)
1162 ret = t ? PTR_ERR(t) : -ENOENT;
1166 case IPT_SO_GET_ENTRIES: {
1167 struct ipt_get_entries get;
1169 if (*len < sizeof(get)) {
1170 duprintf("get_entries: %u < %u\n", *len, sizeof(get));
1172 } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
1174 } else if (*len != sizeof(struct ipt_get_entries) + get.size) {
1175 duprintf("get_entries: %u != %u\n", *len,
1176 sizeof(struct ipt_get_entries) + get.size);
1179 ret = get_entries(&get, user);
1183 case IPT_SO_GET_REVISION_MATCH:
1184 case IPT_SO_GET_REVISION_TARGET: {
1185 struct ipt_get_revision rev;
1188 if (*len != sizeof(rev)) {
1192 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1197 if (cmd == IPT_SO_GET_REVISION_TARGET)
1202 try_then_request_module(xt_find_revision(AF_INET, rev.name,
1205 "ipt_%s", rev.name);
1210 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
1217 int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
1220 struct xt_table_info *newinfo;
1221 static struct xt_table_info bootstrap
1222 = { 0, 0, 0, { 0 }, { 0 }, { } };
1223 void *loc_cpu_entry;
1225 newinfo = xt_alloc_table_info(repl->size);
1229 /* choose the copy on our node/cpu
1230 * but dont care of preemption
1232 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1233 memcpy(loc_cpu_entry, repl->entries, repl->size);
1235 ret = translate_table(table->name, table->valid_hooks,
1236 newinfo, loc_cpu_entry, repl->size,
1241 xt_free_table_info(newinfo);
1245 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1246 xt_free_table_info(newinfo);
1253 void ipt_unregister_table(struct ipt_table *table)
1255 struct xt_table_info *private;
1256 void *loc_cpu_entry;
1258 private = xt_unregister_table(table);
1260 /* Decrease module usage counts and free resources */
1261 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1262 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1263 xt_free_table_info(private);
1266 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
1268 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
1269 u_int8_t type, u_int8_t code,
1272 return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
1277 icmp_match(const struct sk_buff *skb,
1278 const struct net_device *in,
1279 const struct net_device *out,
1280 const void *matchinfo,
1282 unsigned int protoff,
1285 struct icmphdr _icmph, *ic;
1286 const struct ipt_icmp *icmpinfo = matchinfo;
1288 /* Must not be a fragment. */
1292 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
1294 /* We've been asked to examine this packet, and we
1295 * can't. Hence, no choice but to drop.
1297 duprintf("Dropping evil ICMP tinygram.\n");
1302 return icmp_type_code_match(icmpinfo->type,
1306 !!(icmpinfo->invflags&IPT_ICMP_INV));
1309 /* Called when user tries to insert an entry of this type. */
1311 icmp_checkentry(const char *tablename,
1314 unsigned int matchsize,
1315 unsigned int hook_mask)
1317 const struct ipt_ip *ip = info;
1318 const struct ipt_icmp *icmpinfo = matchinfo;
1320 /* Must specify proto == ICMP, and no unknown invflags */
1321 return ip->proto == IPPROTO_ICMP
1322 && !(ip->invflags & IPT_INV_PROTO)
1323 && matchsize == IPT_ALIGN(sizeof(struct ipt_icmp))
1324 && !(icmpinfo->invflags & ~IPT_ICMP_INV);
1327 /* The built-in targets: standard (NULL) and error. */
1328 static struct ipt_target ipt_standard_target = {
1329 .name = IPT_STANDARD_TARGET,
1332 static struct ipt_target ipt_error_target = {
1333 .name = IPT_ERROR_TARGET,
1334 .target = ipt_error,
1337 static struct nf_sockopt_ops ipt_sockopts = {
1339 .set_optmin = IPT_BASE_CTL,
1340 .set_optmax = IPT_SO_SET_MAX+1,
1341 .set = do_ipt_set_ctl,
1342 .get_optmin = IPT_BASE_CTL,
1343 .get_optmax = IPT_SO_GET_MAX+1,
1344 .get = do_ipt_get_ctl,
1347 static struct ipt_match icmp_matchstruct = {
1349 .match = &icmp_match,
1350 .checkentry = &icmp_checkentry,
1353 static int __init init(void)
1357 xt_proto_init(AF_INET);
1359 /* Noone else will be downing sem now, so we won't sleep */
1360 xt_register_target(AF_INET, &ipt_standard_target);
1361 xt_register_target(AF_INET, &ipt_error_target);
1362 xt_register_match(AF_INET, &icmp_matchstruct);
1364 /* Register setsockopt */
1365 ret = nf_register_sockopt(&ipt_sockopts);
1367 duprintf("Unable to register sockopts.\n");
1371 printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
1375 static void __exit fini(void)
1377 nf_unregister_sockopt(&ipt_sockopts);
1379 xt_unregister_match(AF_INET, &icmp_matchstruct);
1380 xt_unregister_target(AF_INET, &ipt_error_target);
1381 xt_unregister_target(AF_INET, &ipt_standard_target);
1383 xt_proto_fini(AF_INET);
1386 EXPORT_SYMBOL(ipt_register_table);
1387 EXPORT_SYMBOL(ipt_unregister_table);
1388 EXPORT_SYMBOL(ipt_do_table);