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/cache.h>
18 #include <linux/capability.h>
19 #include <linux/skbuff.h>
20 #include <linux/kmod.h>
21 #include <linux/vmalloc.h>
22 #include <linux/netdevice.h>
23 #include <linux/module.h>
24 #include <linux/icmp.h>
26 #include <net/compat.h>
27 #include <asm/uaccess.h>
28 #include <linux/mutex.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 struct xt_target *target,
183 const void *targinfo,
187 printk("ip_tables: error: `%s'\n", (char *)targinfo);
193 int do_match(struct ipt_entry_match *m,
194 const struct sk_buff *skb,
195 const struct net_device *in,
196 const struct net_device *out,
200 /* Stop iteration if it doesn't match */
201 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
202 offset, skb->nh.iph->ihl*4, hotdrop))
208 static inline struct ipt_entry *
209 get_entry(void *base, unsigned int offset)
211 return (struct ipt_entry *)(base + offset);
214 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
216 ipt_do_table(struct sk_buff **pskb,
218 const struct net_device *in,
219 const struct net_device *out,
220 struct ipt_table *table,
223 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
228 /* Initializing verdict to NF_DROP keeps gcc happy. */
229 unsigned int verdict = NF_DROP;
230 const char *indev, *outdev;
232 struct ipt_entry *e, *back;
233 struct xt_table_info *private;
236 ip = (*pskb)->nh.iph;
237 datalen = (*pskb)->len - ip->ihl * 4;
238 indev = in ? in->name : nulldevname;
239 outdev = out ? out->name : nulldevname;
240 /* We handle fragments by dealing with the first fragment as
241 * if it was a normal packet. All other fragments are treated
242 * normally, except that they will NEVER match rules that ask
243 * things we don't know, ie. tcp syn flag or ports). If the
244 * rule is also a fragment-specific rule, non-fragments won't
246 offset = ntohs(ip->frag_off) & IP_OFFSET;
248 read_lock_bh(&table->lock);
249 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
250 private = table->private;
251 table_base = (void *)private->entries[smp_processor_id()];
252 e = get_entry(table_base, private->hook_entry[hook]);
254 /* For return from builtin chain */
255 back = get_entry(table_base, private->underflow[hook]);
260 if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
261 struct ipt_entry_target *t;
263 if (IPT_MATCH_ITERATE(e, do_match,
265 offset, &hotdrop) != 0)
268 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
270 t = ipt_get_target(e);
271 IP_NF_ASSERT(t->u.kernel.target);
272 /* Standard target? */
273 if (!t->u.kernel.target->target) {
276 v = ((struct ipt_standard_target *)t)->verdict;
278 /* Pop from stack? */
279 if (v != IPT_RETURN) {
280 verdict = (unsigned)(-v) - 1;
284 back = get_entry(table_base,
288 if (table_base + v != (void *)e + e->next_offset
289 && !(e->ip.flags & IPT_F_GOTO)) {
290 /* Save old back ptr in next entry */
291 struct ipt_entry *next
292 = (void *)e + e->next_offset;
294 = (void *)back - table_base;
295 /* set back pointer to next entry */
299 e = get_entry(table_base, v);
301 /* Targets which reenter must return
303 #ifdef CONFIG_NETFILTER_DEBUG
304 ((struct ipt_entry *)table_base)->comefrom
307 verdict = t->u.kernel.target->target(pskb,
314 #ifdef CONFIG_NETFILTER_DEBUG
315 if (((struct ipt_entry *)table_base)->comefrom
317 && verdict == IPT_CONTINUE) {
318 printk("Target %s reentered!\n",
319 t->u.kernel.target->name);
322 ((struct ipt_entry *)table_base)->comefrom
325 /* Target might have changed stuff. */
326 ip = (*pskb)->nh.iph;
327 datalen = (*pskb)->len - ip->ihl * 4;
329 if (verdict == IPT_CONTINUE)
330 e = (void *)e + e->next_offset;
338 e = (void *)e + e->next_offset;
342 read_unlock_bh(&table->lock);
344 #ifdef DEBUG_ALLOW_ALL
353 /* All zeroes == unconditional rule. */
355 unconditional(const struct ipt_ip *ip)
359 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
360 if (((__u32 *)ip)[i])
366 /* Figures out from what hook each rule can be called: returns 0 if
367 there are loops. Puts hook bitmask in comefrom. */
369 mark_source_chains(struct xt_table_info *newinfo,
370 unsigned int valid_hooks, void *entry0)
374 /* No recursion; use packet counter to save back ptrs (reset
375 to 0 as we leave), and comefrom to save source hook bitmask */
376 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
377 unsigned int pos = newinfo->hook_entry[hook];
379 = (struct ipt_entry *)(entry0 + pos);
381 if (!(valid_hooks & (1 << hook)))
384 /* Set initial back pointer. */
385 e->counters.pcnt = pos;
388 struct ipt_standard_target *t
389 = (void *)ipt_get_target(e);
391 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
392 printk("iptables: loop hook %u pos %u %08X.\n",
393 hook, pos, e->comefrom);
397 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
399 /* Unconditional return/END. */
400 if (e->target_offset == sizeof(struct ipt_entry)
401 && (strcmp(t->target.u.user.name,
402 IPT_STANDARD_TARGET) == 0)
404 && unconditional(&e->ip)) {
405 unsigned int oldpos, size;
407 if (t->verdict < -NF_MAX_VERDICT - 1) {
408 duprintf("mark_source_chains: bad "
409 "negative verdict (%i)\n",
414 /* Return: backtrack through the last
417 e->comefrom ^= (1<<NF_IP_NUMHOOKS);
418 #ifdef DEBUG_IP_FIREWALL_USER
420 & (1 << NF_IP_NUMHOOKS)) {
421 duprintf("Back unset "
428 pos = e->counters.pcnt;
429 e->counters.pcnt = 0;
431 /* We're at the start. */
435 e = (struct ipt_entry *)
437 } while (oldpos == pos + e->next_offset);
440 size = e->next_offset;
441 e = (struct ipt_entry *)
442 (entry0 + pos + size);
443 e->counters.pcnt = pos;
446 int newpos = t->verdict;
448 if (strcmp(t->target.u.user.name,
449 IPT_STANDARD_TARGET) == 0
451 if (newpos > newinfo->size -
452 sizeof(struct ipt_entry)) {
453 duprintf("mark_source_chains: "
454 "bad verdict (%i)\n",
458 /* This a jump; chase it. */
459 duprintf("Jump rule %u -> %u\n",
462 /* ... this is a fallthru */
463 newpos = pos + e->next_offset;
465 e = (struct ipt_entry *)
467 e->counters.pcnt = pos;
472 duprintf("Finished chain %u\n", hook);
478 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
480 if (i && (*i)-- == 0)
483 if (m->u.kernel.match->destroy)
484 m->u.kernel.match->destroy(m->u.kernel.match, m->data,
485 m->u.match_size - sizeof(*m));
486 module_put(m->u.kernel.match->me);
491 check_match(struct ipt_entry_match *m,
493 const struct ipt_ip *ip,
494 unsigned int hookmask,
497 struct ipt_match *match;
500 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
502 "ipt_%s", m->u.user.name);
503 if (IS_ERR(match) || !match) {
504 duprintf("check_match: `%s' not found\n", m->u.user.name);
505 return match ? PTR_ERR(match) : -ENOENT;
507 m->u.kernel.match = match;
509 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
510 name, hookmask, ip->proto,
511 ip->invflags & IPT_INV_PROTO);
515 if (m->u.kernel.match->checkentry
516 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
517 m->u.match_size - sizeof(*m),
519 duprintf("ip_tables: check failed for `%s'.\n",
520 m->u.kernel.match->name);
528 module_put(m->u.kernel.match->me);
532 static struct ipt_target ipt_standard_target;
535 check_entry(struct ipt_entry *e, const char *name, unsigned int size,
538 struct ipt_entry_target *t;
539 struct ipt_target *target;
543 if (!ip_checkentry(&e->ip)) {
544 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
548 if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
552 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
554 goto cleanup_matches;
556 t = ipt_get_target(e);
558 if (e->target_offset + t->u.target_size > e->next_offset)
559 goto cleanup_matches;
560 target = try_then_request_module(xt_find_target(AF_INET,
563 "ipt_%s", t->u.user.name);
564 if (IS_ERR(target) || !target) {
565 duprintf("check_entry: `%s' not found\n", t->u.user.name);
566 ret = target ? PTR_ERR(target) : -ENOENT;
567 goto cleanup_matches;
569 t->u.kernel.target = target;
571 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
572 name, e->comefrom, e->ip.proto,
573 e->ip.invflags & IPT_INV_PROTO);
577 if (t->u.kernel.target->checkentry
578 && !t->u.kernel.target->checkentry(name, e, target, t->data,
582 duprintf("ip_tables: check failed for `%s'.\n",
583 t->u.kernel.target->name);
591 module_put(t->u.kernel.target->me);
593 IPT_MATCH_ITERATE(e, cleanup_match, &j);
598 check_entry_size_and_hooks(struct ipt_entry *e,
599 struct xt_table_info *newinfo,
601 unsigned char *limit,
602 const unsigned int *hook_entries,
603 const unsigned int *underflows,
608 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
609 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
610 duprintf("Bad offset %p\n", e);
615 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
616 duprintf("checking: element %p size %u\n",
621 /* Check hooks & underflows */
622 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
623 if ((unsigned char *)e - base == hook_entries[h])
624 newinfo->hook_entry[h] = hook_entries[h];
625 if ((unsigned char *)e - base == underflows[h])
626 newinfo->underflow[h] = underflows[h];
629 /* FIXME: underflows must be unconditional, standard verdicts
630 < 0 (not IPT_RETURN). --RR */
632 /* Clear counters and comefrom */
633 e->counters = ((struct xt_counters) { 0, 0 });
641 cleanup_entry(struct ipt_entry *e, unsigned int *i)
643 struct ipt_entry_target *t;
645 if (i && (*i)-- == 0)
648 /* Cleanup all matches */
649 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
650 t = ipt_get_target(e);
651 if (t->u.kernel.target->destroy)
652 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
653 t->u.target_size - sizeof(*t));
654 module_put(t->u.kernel.target->me);
658 /* Checks and translates the user-supplied table segment (held in
661 translate_table(const char *name,
662 unsigned int valid_hooks,
663 struct xt_table_info *newinfo,
667 const unsigned int *hook_entries,
668 const unsigned int *underflows)
673 newinfo->size = size;
674 newinfo->number = number;
676 /* Init all hooks to impossible value. */
677 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
678 newinfo->hook_entry[i] = 0xFFFFFFFF;
679 newinfo->underflow[i] = 0xFFFFFFFF;
682 duprintf("translate_table: size %u\n", newinfo->size);
684 /* Walk through entries, checking offsets. */
685 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
686 check_entry_size_and_hooks,
690 hook_entries, underflows, &i);
695 duprintf("translate_table: %u not %u entries\n",
700 /* Check hooks all assigned */
701 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
702 /* Only hooks which are valid */
703 if (!(valid_hooks & (1 << i)))
705 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
706 duprintf("Invalid hook entry %u %u\n",
710 if (newinfo->underflow[i] == 0xFFFFFFFF) {
711 duprintf("Invalid underflow %u %u\n",
717 if (!mark_source_chains(newinfo, valid_hooks, entry0))
720 /* Finally, each sanity check must pass */
722 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
723 check_entry, name, size, &i);
726 IPT_ENTRY_ITERATE(entry0, newinfo->size,
731 /* And one copy for every other CPU */
732 for_each_possible_cpu(i) {
733 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
734 memcpy(newinfo->entries[i], entry0, newinfo->size);
742 add_entry_to_counter(const struct ipt_entry *e,
743 struct xt_counters total[],
746 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
753 set_entry_to_counter(const struct ipt_entry *e,
754 struct ipt_counters total[],
757 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
764 get_counters(const struct xt_table_info *t,
765 struct xt_counters counters[])
771 /* Instead of clearing (by a previous call to memset())
772 * the counters and using adds, we set the counters
773 * with data used by 'current' CPU
774 * We dont care about preemption here.
776 curcpu = raw_smp_processor_id();
779 IPT_ENTRY_ITERATE(t->entries[curcpu],
781 set_entry_to_counter,
785 for_each_possible_cpu(cpu) {
789 IPT_ENTRY_ITERATE(t->entries[cpu],
791 add_entry_to_counter,
797 static inline struct xt_counters * alloc_counters(struct ipt_table *table)
799 unsigned int countersize;
800 struct xt_counters *counters;
801 struct xt_table_info *private = table->private;
803 /* We need atomic snapshot of counters: rest doesn't change
804 (other than comefrom, which userspace doesn't care
806 countersize = sizeof(struct xt_counters) * private->number;
807 counters = vmalloc_node(countersize, numa_node_id());
809 if (counters == NULL)
810 return ERR_PTR(-ENOMEM);
812 /* First, sum counters... */
813 write_lock_bh(&table->lock);
814 get_counters(private, counters);
815 write_unlock_bh(&table->lock);
821 copy_entries_to_user(unsigned int total_size,
822 struct ipt_table *table,
823 void __user *userptr)
825 unsigned int off, num;
827 struct xt_counters *counters;
828 struct xt_table_info *private = table->private;
832 counters = alloc_counters(table);
833 if (IS_ERR(counters))
834 return PTR_ERR(counters);
836 /* choose the copy that is on our node/cpu, ...
837 * This choice is lazy (because current thread is
838 * allowed to migrate to another cpu)
840 loc_cpu_entry = private->entries[raw_smp_processor_id()];
841 /* ... then copy entire thing ... */
842 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
847 /* FIXME: use iterator macros --RR */
848 /* ... then go back and fix counters and names */
849 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
851 struct ipt_entry_match *m;
852 struct ipt_entry_target *t;
854 e = (struct ipt_entry *)(loc_cpu_entry + off);
855 if (copy_to_user(userptr + off
856 + offsetof(struct ipt_entry, counters),
858 sizeof(counters[num])) != 0) {
863 for (i = sizeof(struct ipt_entry);
864 i < e->target_offset;
865 i += m->u.match_size) {
868 if (copy_to_user(userptr + off + i
869 + offsetof(struct ipt_entry_match,
871 m->u.kernel.match->name,
872 strlen(m->u.kernel.match->name)+1)
879 t = ipt_get_target(e);
880 if (copy_to_user(userptr + off + e->target_offset
881 + offsetof(struct ipt_entry_target,
883 t->u.kernel.target->name,
884 strlen(t->u.kernel.target->name)+1) != 0) {
896 struct compat_delta {
897 struct compat_delta *next;
902 static struct compat_delta *compat_offsets = NULL;
904 static int compat_add_offset(u_int16_t offset, short delta)
906 struct compat_delta *tmp;
908 tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
911 tmp->offset = offset;
913 if (compat_offsets) {
914 tmp->next = compat_offsets->next;
915 compat_offsets->next = tmp;
917 compat_offsets = tmp;
923 static void compat_flush_offsets(void)
925 struct compat_delta *tmp, *next;
927 if (compat_offsets) {
928 for(tmp = compat_offsets; tmp; tmp = next) {
932 compat_offsets = NULL;
936 static short compat_calc_jump(u_int16_t offset)
938 struct compat_delta *tmp;
941 for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
942 if (tmp->offset < offset)
947 struct compat_ipt_standard_target
949 struct compat_xt_entry_target target;
950 compat_int_t verdict;
953 struct compat_ipt_standard
955 struct compat_ipt_entry entry;
956 struct compat_ipt_standard_target target;
959 #define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target))
960 #define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target))
961 #define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN)
963 static int compat_ipt_standard_fn(void *target,
964 void **dstptr, int *size, int convert)
966 struct compat_ipt_standard_target compat_st, *pcompat_st;
967 struct ipt_standard_target st, *pst;
974 memcpy(&compat_st.target, &pst->target,
975 sizeof(compat_st.target));
976 compat_st.verdict = pst->verdict;
977 if (compat_st.verdict > 0)
979 compat_calc_jump(compat_st.verdict);
980 compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN;
981 if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN))
983 *size -= IPT_ST_OFFSET;
984 *dstptr += IPT_ST_COMPAT_LEN;
986 case COMPAT_FROM_USER:
988 memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN);
989 st.verdict = pcompat_st->verdict;
991 st.verdict += compat_calc_jump(st.verdict);
992 st.target.u.user.target_size = IPT_ST_LEN;
993 memcpy(*dstptr, &st, IPT_ST_LEN);
994 *size += IPT_ST_OFFSET;
995 *dstptr += IPT_ST_LEN;
997 case COMPAT_CALC_SIZE:
998 *size += IPT_ST_OFFSET;
1008 compat_calc_match(struct ipt_entry_match *m, int * size)
1010 if (m->u.kernel.match->compat)
1011 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1013 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1017 static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
1018 void *base, struct xt_table_info *newinfo)
1020 struct ipt_entry_target *t;
1021 u_int16_t entry_offset;
1025 entry_offset = (void *)e - base;
1026 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1027 t = ipt_get_target(e);
1028 if (t->u.kernel.target->compat)
1029 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1031 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1032 newinfo->size -= off;
1033 ret = compat_add_offset(entry_offset, off);
1037 for (i = 0; i< NF_IP_NUMHOOKS; i++) {
1038 if (info->hook_entry[i] && (e < (struct ipt_entry *)
1039 (base + info->hook_entry[i])))
1040 newinfo->hook_entry[i] -= off;
1041 if (info->underflow[i] && (e < (struct ipt_entry *)
1042 (base + info->underflow[i])))
1043 newinfo->underflow[i] -= off;
1048 static int compat_table_info(struct xt_table_info *info,
1049 struct xt_table_info *newinfo)
1051 void *loc_cpu_entry;
1054 if (!newinfo || !info)
1057 memset(newinfo, 0, sizeof(struct xt_table_info));
1058 newinfo->size = info->size;
1059 newinfo->number = info->number;
1060 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1061 newinfo->hook_entry[i] = info->hook_entry[i];
1062 newinfo->underflow[i] = info->underflow[i];
1064 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1065 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1066 compat_calc_entry, info, loc_cpu_entry, newinfo);
1070 static int get_info(void __user *user, int *len, int compat)
1072 char name[IPT_TABLE_MAXNAMELEN];
1073 struct ipt_table *t;
1076 if (*len != sizeof(struct ipt_getinfo)) {
1077 duprintf("length %u != %u\n", *len,
1078 (unsigned int)sizeof(struct ipt_getinfo));
1082 if (copy_from_user(name, user, sizeof(name)) != 0)
1085 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1086 #ifdef CONFIG_COMPAT
1088 xt_compat_lock(AF_INET);
1090 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1091 "iptable_%s", name);
1092 if (t && !IS_ERR(t)) {
1093 struct ipt_getinfo info;
1094 struct xt_table_info *private = t->private;
1096 #ifdef CONFIG_COMPAT
1098 struct xt_table_info tmp;
1099 ret = compat_table_info(private, &tmp);
1100 compat_flush_offsets();
1104 info.valid_hooks = t->valid_hooks;
1105 memcpy(info.hook_entry, private->hook_entry,
1106 sizeof(info.hook_entry));
1107 memcpy(info.underflow, private->underflow,
1108 sizeof(info.underflow));
1109 info.num_entries = private->number;
1110 info.size = private->size;
1111 strcpy(info.name, name);
1113 if (copy_to_user(user, &info, *len) != 0)
1121 ret = t ? PTR_ERR(t) : -ENOENT;
1122 #ifdef CONFIG_COMPAT
1124 xt_compat_unlock(AF_INET);
1130 get_entries(struct ipt_get_entries __user *uptr, int *len)
1133 struct ipt_get_entries get;
1134 struct ipt_table *t;
1136 if (*len < sizeof(get)) {
1137 duprintf("get_entries: %u < %d\n", *len,
1138 (unsigned int)sizeof(get));
1141 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1143 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1144 duprintf("get_entries: %u != %u\n", *len,
1145 (unsigned int)(sizeof(struct ipt_get_entries) +
1150 t = xt_find_table_lock(AF_INET, get.name);
1151 if (t && !IS_ERR(t)) {
1152 struct xt_table_info *private = t->private;
1153 duprintf("t->private->number = %u\n",
1155 if (get.size == private->size)
1156 ret = copy_entries_to_user(private->size,
1157 t, uptr->entrytable);
1159 duprintf("get_entries: I've got %u not %u!\n",
1167 ret = t ? PTR_ERR(t) : -ENOENT;
1173 __do_replace(const char *name, unsigned int valid_hooks,
1174 struct xt_table_info *newinfo, unsigned int num_counters,
1175 void __user *counters_ptr)
1178 struct ipt_table *t;
1179 struct xt_table_info *oldinfo;
1180 struct xt_counters *counters;
1181 void *loc_cpu_old_entry;
1184 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1190 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1191 "iptable_%s", name);
1192 if (!t || IS_ERR(t)) {
1193 ret = t ? PTR_ERR(t) : -ENOENT;
1194 goto free_newinfo_counters_untrans;
1198 if (valid_hooks != t->valid_hooks) {
1199 duprintf("Valid hook crap: %08X vs %08X\n",
1200 valid_hooks, t->valid_hooks);
1205 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1209 /* Update module usage count based on number of rules */
1210 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1211 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1212 if ((oldinfo->number > oldinfo->initial_entries) ||
1213 (newinfo->number <= oldinfo->initial_entries))
1215 if ((oldinfo->number > oldinfo->initial_entries) &&
1216 (newinfo->number <= oldinfo->initial_entries))
1219 /* Get the old counters. */
1220 get_counters(oldinfo, counters);
1221 /* Decrease module usage counts and free resource */
1222 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1223 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1224 xt_free_table_info(oldinfo);
1225 if (copy_to_user(counters_ptr, counters,
1226 sizeof(struct xt_counters) * num_counters) != 0)
1235 free_newinfo_counters_untrans:
1242 do_replace(void __user *user, unsigned int len)
1245 struct ipt_replace tmp;
1246 struct xt_table_info *newinfo;
1247 void *loc_cpu_entry;
1249 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1252 /* Hack: Causes ipchains to give correct error msg --RR */
1253 if (len != sizeof(tmp) + tmp.size)
1254 return -ENOPROTOOPT;
1256 /* overflow check */
1257 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1260 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1263 newinfo = xt_alloc_table_info(tmp.size);
1267 /* choose the copy that is our node/cpu */
1268 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1269 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1275 ret = translate_table(tmp.name, tmp.valid_hooks,
1276 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1277 tmp.hook_entry, tmp.underflow);
1281 duprintf("ip_tables: Translated table\n");
1283 ret = __do_replace(tmp.name, tmp.valid_hooks,
1284 newinfo, tmp.num_counters,
1287 goto free_newinfo_untrans;
1290 free_newinfo_untrans:
1291 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1293 xt_free_table_info(newinfo);
1297 /* We're lazy, and add to the first CPU; overflow works its fey magic
1298 * and everything is OK. */
1300 add_counter_to_entry(struct ipt_entry *e,
1301 const struct xt_counters addme[],
1305 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1307 (long unsigned int)e->counters.pcnt,
1308 (long unsigned int)e->counters.bcnt,
1309 (long unsigned int)addme[*i].pcnt,
1310 (long unsigned int)addme[*i].bcnt);
1313 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1320 do_add_counters(void __user *user, unsigned int len, int compat)
1323 struct xt_counters_info tmp;
1324 struct xt_counters *paddc;
1325 unsigned int num_counters;
1329 struct ipt_table *t;
1330 struct xt_table_info *private;
1332 void *loc_cpu_entry;
1333 #ifdef CONFIG_COMPAT
1334 struct compat_xt_counters_info compat_tmp;
1338 size = sizeof(struct compat_xt_counters_info);
1343 size = sizeof(struct xt_counters_info);
1346 if (copy_from_user(ptmp, user, size) != 0)
1349 #ifdef CONFIG_COMPAT
1351 num_counters = compat_tmp.num_counters;
1352 name = compat_tmp.name;
1356 num_counters = tmp.num_counters;
1360 if (len != size + num_counters * sizeof(struct xt_counters))
1363 paddc = vmalloc_node(len - size, numa_node_id());
1367 if (copy_from_user(paddc, user + size, len - size) != 0) {
1372 t = xt_find_table_lock(AF_INET, name);
1373 if (!t || IS_ERR(t)) {
1374 ret = t ? PTR_ERR(t) : -ENOENT;
1378 write_lock_bh(&t->lock);
1379 private = t->private;
1380 if (private->number != num_counters) {
1382 goto unlock_up_free;
1386 /* Choose the copy that is on our node */
1387 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1388 IPT_ENTRY_ITERATE(loc_cpu_entry,
1390 add_counter_to_entry,
1394 write_unlock_bh(&t->lock);
1403 #ifdef CONFIG_COMPAT
1404 struct compat_ipt_replace {
1405 char name[IPT_TABLE_MAXNAMELEN];
1409 u32 hook_entry[NF_IP_NUMHOOKS];
1410 u32 underflow[NF_IP_NUMHOOKS];
1412 compat_uptr_t counters; /* struct ipt_counters * */
1413 struct compat_ipt_entry entries[0];
1416 static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
1417 void __user **dstptr, compat_uint_t *size)
1419 if (m->u.kernel.match->compat)
1420 return m->u.kernel.match->compat(m, dstptr, size,
1423 return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
1426 static int compat_copy_entry_to_user(struct ipt_entry *e,
1427 void __user **dstptr, compat_uint_t *size)
1429 struct ipt_entry_target __user *t;
1430 struct compat_ipt_entry __user *ce;
1431 u_int16_t target_offset, next_offset;
1432 compat_uint_t origsize;
1437 ce = (struct compat_ipt_entry __user *)*dstptr;
1438 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1441 *dstptr += sizeof(struct compat_ipt_entry);
1442 ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
1443 target_offset = e->target_offset - (origsize - *size);
1446 t = ipt_get_target(e);
1447 if (t->u.kernel.target->compat)
1448 ret = t->u.kernel.target->compat(t, dstptr, size,
1451 ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
1455 next_offset = e->next_offset - (origsize - *size);
1456 if (put_user(target_offset, &ce->target_offset))
1458 if (put_user(next_offset, &ce->next_offset))
1466 compat_check_calc_match(struct ipt_entry_match *m,
1468 const struct ipt_ip *ip,
1469 unsigned int hookmask,
1472 struct ipt_match *match;
1474 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1475 m->u.user.revision),
1476 "ipt_%s", m->u.user.name);
1477 if (IS_ERR(match) || !match) {
1478 duprintf("compat_check_calc_match: `%s' not found\n",
1480 return match ? PTR_ERR(match) : -ENOENT;
1482 m->u.kernel.match = match;
1484 if (m->u.kernel.match->compat)
1485 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1487 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1494 check_compat_entry_size_and_hooks(struct ipt_entry *e,
1495 struct xt_table_info *newinfo,
1497 unsigned char *base,
1498 unsigned char *limit,
1499 unsigned int *hook_entries,
1500 unsigned int *underflows,
1504 struct ipt_entry_target *t;
1505 struct ipt_target *target;
1506 u_int16_t entry_offset;
1509 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1510 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1511 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1512 duprintf("Bad offset %p, limit = %p\n", e, limit);
1516 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1517 sizeof(struct compat_xt_entry_target)) {
1518 duprintf("checking: element %p size %u\n",
1523 if (!ip_checkentry(&e->ip)) {
1524 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
1528 if (e->target_offset + sizeof(struct compat_xt_entry_target) >
1533 entry_offset = (void *)e - (void *)base;
1535 ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
1536 e->comefrom, &off, &j);
1538 goto cleanup_matches;
1540 t = ipt_get_target(e);
1542 if (e->target_offset + t->u.target_size > e->next_offset)
1543 goto cleanup_matches;
1544 target = try_then_request_module(xt_find_target(AF_INET,
1546 t->u.user.revision),
1547 "ipt_%s", t->u.user.name);
1548 if (IS_ERR(target) || !target) {
1549 duprintf("check_entry: `%s' not found\n", t->u.user.name);
1550 ret = target ? PTR_ERR(target) : -ENOENT;
1551 goto cleanup_matches;
1553 t->u.kernel.target = target;
1555 if (t->u.kernel.target->compat)
1556 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1558 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1560 ret = compat_add_offset(entry_offset, off);
1564 /* Check hooks & underflows */
1565 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1566 if ((unsigned char *)e - base == hook_entries[h])
1567 newinfo->hook_entry[h] = hook_entries[h];
1568 if ((unsigned char *)e - base == underflows[h])
1569 newinfo->underflow[h] = underflows[h];
1572 /* Clear counters and comefrom */
1573 e->counters = ((struct ipt_counters) { 0, 0 });
1580 module_put(t->u.kernel.target->me);
1582 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1586 static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
1587 void **dstptr, compat_uint_t *size, const char *name,
1588 const struct ipt_ip *ip, unsigned int hookmask)
1590 struct ipt_entry_match *dm;
1591 struct ipt_match *match;
1594 dm = (struct ipt_entry_match *)*dstptr;
1595 match = m->u.kernel.match;
1597 match->compat(m, dstptr, size, COMPAT_FROM_USER);
1599 xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
1601 ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
1602 name, hookmask, ip->proto,
1603 ip->invflags & IPT_INV_PROTO);
1605 if (!ret && m->u.kernel.match->checkentry
1606 && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
1607 dm->u.match_size - sizeof(*dm),
1609 duprintf("ip_tables: check failed for `%s'.\n",
1610 m->u.kernel.match->name);
1616 static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1617 unsigned int *size, const char *name,
1618 struct xt_table_info *newinfo, unsigned char *base)
1620 struct ipt_entry_target *t;
1621 struct ipt_target *target;
1622 struct ipt_entry *de;
1623 unsigned int origsize;
1628 de = (struct ipt_entry *)*dstptr;
1629 memcpy(de, e, sizeof(struct ipt_entry));
1631 *dstptr += sizeof(struct compat_ipt_entry);
1632 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
1633 name, &de->ip, de->comefrom);
1636 de->target_offset = e->target_offset - (origsize - *size);
1637 t = ipt_get_target(e);
1638 target = t->u.kernel.target;
1640 target->compat(t, dstptr, size, COMPAT_FROM_USER);
1642 xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
1644 de->next_offset = e->next_offset - (origsize - *size);
1645 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1646 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1647 newinfo->hook_entry[h] -= origsize - *size;
1648 if ((unsigned char *)de - base < newinfo->underflow[h])
1649 newinfo->underflow[h] -= origsize - *size;
1652 t = ipt_get_target(de);
1653 target = t->u.kernel.target;
1654 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
1655 name, e->comefrom, e->ip.proto,
1656 e->ip.invflags & IPT_INV_PROTO);
1660 if (t->u.kernel.target->checkentry
1661 && !t->u.kernel.target->checkentry(name, de, target,
1662 t->data, t->u.target_size - sizeof(*t),
1664 duprintf("ip_tables: compat: check failed for `%s'.\n",
1665 t->u.kernel.target->name);
1674 translate_compat_table(const char *name,
1675 unsigned int valid_hooks,
1676 struct xt_table_info **pinfo,
1678 unsigned int total_size,
1679 unsigned int number,
1680 unsigned int *hook_entries,
1681 unsigned int *underflows)
1684 struct xt_table_info *newinfo, *info;
1685 void *pos, *entry0, *entry1;
1692 info->number = number;
1694 /* Init all hooks to impossible value. */
1695 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1696 info->hook_entry[i] = 0xFFFFFFFF;
1697 info->underflow[i] = 0xFFFFFFFF;
1700 duprintf("translate_compat_table: size %u\n", info->size);
1702 xt_compat_lock(AF_INET);
1703 /* Walk through entries, checking offsets. */
1704 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1705 check_compat_entry_size_and_hooks,
1706 info, &size, entry0,
1707 entry0 + total_size,
1708 hook_entries, underflows, &j, name);
1714 duprintf("translate_compat_table: %u not %u entries\n",
1719 /* Check hooks all assigned */
1720 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1721 /* Only hooks which are valid */
1722 if (!(valid_hooks & (1 << i)))
1724 if (info->hook_entry[i] == 0xFFFFFFFF) {
1725 duprintf("Invalid hook entry %u %u\n",
1726 i, hook_entries[i]);
1729 if (info->underflow[i] == 0xFFFFFFFF) {
1730 duprintf("Invalid underflow %u %u\n",
1737 newinfo = xt_alloc_table_info(size);
1741 newinfo->number = number;
1742 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1743 newinfo->hook_entry[i] = info->hook_entry[i];
1744 newinfo->underflow[i] = info->underflow[i];
1746 entry1 = newinfo->entries[raw_smp_processor_id()];
1749 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1750 compat_copy_entry_from_user, &pos, &size,
1751 name, newinfo, entry1);
1752 compat_flush_offsets();
1753 xt_compat_unlock(AF_INET);
1758 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1761 /* And one copy for every other CPU */
1762 for_each_possible_cpu(i)
1763 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1764 memcpy(newinfo->entries[i], entry1, newinfo->size);
1768 xt_free_table_info(info);
1772 xt_free_table_info(newinfo);
1774 IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j);
1777 compat_flush_offsets();
1778 xt_compat_unlock(AF_INET);
1783 compat_do_replace(void __user *user, unsigned int len)
1786 struct compat_ipt_replace tmp;
1787 struct xt_table_info *newinfo;
1788 void *loc_cpu_entry;
1790 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1793 /* Hack: Causes ipchains to give correct error msg --RR */
1794 if (len != sizeof(tmp) + tmp.size)
1795 return -ENOPROTOOPT;
1797 /* overflow check */
1798 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1801 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1804 newinfo = xt_alloc_table_info(tmp.size);
1808 /* choose the copy that is our node/cpu */
1809 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1810 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1816 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1817 &newinfo, &loc_cpu_entry, tmp.size,
1818 tmp.num_entries, tmp.hook_entry, tmp.underflow);
1822 duprintf("compat_do_replace: Translated table\n");
1824 ret = __do_replace(tmp.name, tmp.valid_hooks,
1825 newinfo, tmp.num_counters,
1826 compat_ptr(tmp.counters));
1828 goto free_newinfo_untrans;
1831 free_newinfo_untrans:
1832 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1834 xt_free_table_info(newinfo);
1839 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1844 if (!capable(CAP_NET_ADMIN))
1848 case IPT_SO_SET_REPLACE:
1849 ret = compat_do_replace(user, len);
1852 case IPT_SO_SET_ADD_COUNTERS:
1853 ret = do_add_counters(user, len, 1);
1857 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1864 struct compat_ipt_get_entries
1866 char name[IPT_TABLE_MAXNAMELEN];
1868 struct compat_ipt_entry entrytable[0];
1871 static int compat_copy_entries_to_user(unsigned int total_size,
1872 struct ipt_table *table, void __user *userptr)
1874 unsigned int off, num;
1875 struct compat_ipt_entry e;
1876 struct xt_counters *counters;
1877 struct xt_table_info *private = table->private;
1881 void *loc_cpu_entry;
1883 counters = alloc_counters(table);
1884 if (IS_ERR(counters))
1885 return PTR_ERR(counters);
1887 /* choose the copy that is on our node/cpu, ...
1888 * This choice is lazy (because current thread is
1889 * allowed to migrate to another cpu)
1891 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1894 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1895 compat_copy_entry_to_user, &pos, &size);
1899 /* ... then go back and fix counters and names */
1900 for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
1902 struct ipt_entry_match m;
1903 struct ipt_entry_target t;
1906 if (copy_from_user(&e, userptr + off,
1907 sizeof(struct compat_ipt_entry)))
1909 if (copy_to_user(userptr + off +
1910 offsetof(struct compat_ipt_entry, counters),
1911 &counters[num], sizeof(counters[num])))
1914 for (i = sizeof(struct compat_ipt_entry);
1915 i < e.target_offset; i += m.u.match_size) {
1916 if (copy_from_user(&m, userptr + off + i,
1917 sizeof(struct ipt_entry_match)))
1919 if (copy_to_user(userptr + off + i +
1920 offsetof(struct ipt_entry_match, u.user.name),
1921 m.u.kernel.match->name,
1922 strlen(m.u.kernel.match->name) + 1))
1926 if (copy_from_user(&t, userptr + off + e.target_offset,
1927 sizeof(struct ipt_entry_target)))
1929 if (copy_to_user(userptr + off + e.target_offset +
1930 offsetof(struct ipt_entry_target, u.user.name),
1931 t.u.kernel.target->name,
1932 strlen(t.u.kernel.target->name) + 1))
1942 compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
1945 struct compat_ipt_get_entries get;
1946 struct ipt_table *t;
1949 if (*len < sizeof(get)) {
1950 duprintf("compat_get_entries: %u < %u\n",
1951 *len, (unsigned int)sizeof(get));
1955 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1958 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1959 duprintf("compat_get_entries: %u != %u\n", *len,
1960 (unsigned int)(sizeof(struct compat_ipt_get_entries) +
1965 xt_compat_lock(AF_INET);
1966 t = xt_find_table_lock(AF_INET, get.name);
1967 if (t && !IS_ERR(t)) {
1968 struct xt_table_info *private = t->private;
1969 struct xt_table_info info;
1970 duprintf("t->private->number = %u\n",
1972 ret = compat_table_info(private, &info);
1973 if (!ret && get.size == info.size) {
1974 ret = compat_copy_entries_to_user(private->size,
1975 t, uptr->entrytable);
1977 duprintf("compat_get_entries: I've got %u not %u!\n",
1982 compat_flush_offsets();
1986 ret = t ? PTR_ERR(t) : -ENOENT;
1988 xt_compat_unlock(AF_INET);
1993 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1997 if (!capable(CAP_NET_ADMIN))
2001 case IPT_SO_GET_INFO:
2002 ret = get_info(user, len, 1);
2004 case IPT_SO_GET_ENTRIES:
2005 ret = compat_get_entries(user, len);
2008 duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
2016 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2020 if (!capable(CAP_NET_ADMIN))
2024 case IPT_SO_SET_REPLACE:
2025 ret = do_replace(user, len);
2028 case IPT_SO_SET_ADD_COUNTERS:
2029 ret = do_add_counters(user, len, 0);
2033 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2041 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2045 if (!capable(CAP_NET_ADMIN))
2049 case IPT_SO_GET_INFO:
2050 ret = get_info(user, len, 0);
2053 case IPT_SO_GET_ENTRIES:
2054 ret = get_entries(user, len);
2057 case IPT_SO_GET_REVISION_MATCH:
2058 case IPT_SO_GET_REVISION_TARGET: {
2059 struct ipt_get_revision rev;
2062 if (*len != sizeof(rev)) {
2066 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2071 if (cmd == IPT_SO_GET_REVISION_TARGET)
2076 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2079 "ipt_%s", rev.name);
2084 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2091 int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
2094 struct xt_table_info *newinfo;
2095 static struct xt_table_info bootstrap
2096 = { 0, 0, 0, { 0 }, { 0 }, { } };
2097 void *loc_cpu_entry;
2099 newinfo = xt_alloc_table_info(repl->size);
2103 /* choose the copy on our node/cpu
2104 * but dont care of preemption
2106 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2107 memcpy(loc_cpu_entry, repl->entries, repl->size);
2109 ret = translate_table(table->name, table->valid_hooks,
2110 newinfo, loc_cpu_entry, repl->size,
2115 xt_free_table_info(newinfo);
2119 ret = xt_register_table(table, &bootstrap, newinfo);
2121 xt_free_table_info(newinfo);
2128 void ipt_unregister_table(struct ipt_table *table)
2130 struct xt_table_info *private;
2131 void *loc_cpu_entry;
2133 private = xt_unregister_table(table);
2135 /* Decrease module usage counts and free resources */
2136 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2137 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2138 xt_free_table_info(private);
2141 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2143 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2144 u_int8_t type, u_int8_t code,
2147 return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
2152 icmp_match(const struct sk_buff *skb,
2153 const struct net_device *in,
2154 const struct net_device *out,
2155 const struct xt_match *match,
2156 const void *matchinfo,
2158 unsigned int protoff,
2161 struct icmphdr _icmph, *ic;
2162 const struct ipt_icmp *icmpinfo = matchinfo;
2164 /* Must not be a fragment. */
2168 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
2170 /* We've been asked to examine this packet, and we
2171 * can't. Hence, no choice but to drop.
2173 duprintf("Dropping evil ICMP tinygram.\n");
2178 return icmp_type_code_match(icmpinfo->type,
2182 !!(icmpinfo->invflags&IPT_ICMP_INV));
2185 /* Called when user tries to insert an entry of this type. */
2187 icmp_checkentry(const char *tablename,
2189 const struct xt_match *match,
2191 unsigned int matchsize,
2192 unsigned int hook_mask)
2194 const struct ipt_icmp *icmpinfo = matchinfo;
2196 /* Must specify no unknown invflags */
2197 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2200 /* The built-in targets: standard (NULL) and error. */
2201 static struct ipt_target ipt_standard_target = {
2202 .name = IPT_STANDARD_TARGET,
2203 .targetsize = sizeof(int),
2205 #ifdef CONFIG_COMPAT
2206 .compat = &compat_ipt_standard_fn,
2210 static struct ipt_target ipt_error_target = {
2211 .name = IPT_ERROR_TARGET,
2212 .target = ipt_error,
2213 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2217 static struct nf_sockopt_ops ipt_sockopts = {
2219 .set_optmin = IPT_BASE_CTL,
2220 .set_optmax = IPT_SO_SET_MAX+1,
2221 .set = do_ipt_set_ctl,
2222 #ifdef CONFIG_COMPAT
2223 .compat_set = compat_do_ipt_set_ctl,
2225 .get_optmin = IPT_BASE_CTL,
2226 .get_optmax = IPT_SO_GET_MAX+1,
2227 .get = do_ipt_get_ctl,
2228 #ifdef CONFIG_COMPAT
2229 .compat_get = compat_do_ipt_get_ctl,
2233 static struct ipt_match icmp_matchstruct = {
2235 .match = icmp_match,
2236 .matchsize = sizeof(struct ipt_icmp),
2237 .proto = IPPROTO_ICMP,
2239 .checkentry = icmp_checkentry,
2242 static int __init ip_tables_init(void)
2246 ret = xt_proto_init(AF_INET);
2250 /* Noone else will be downing sem now, so we won't sleep */
2251 ret = xt_register_target(&ipt_standard_target);
2254 ret = xt_register_target(&ipt_error_target);
2257 ret = xt_register_match(&icmp_matchstruct);
2261 /* Register setsockopt */
2262 ret = nf_register_sockopt(&ipt_sockopts);
2266 printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2270 xt_unregister_match(&icmp_matchstruct);
2272 xt_unregister_target(&ipt_error_target);
2274 xt_unregister_target(&ipt_standard_target);
2276 xt_proto_fini(AF_INET);
2281 static void __exit ip_tables_fini(void)
2283 nf_unregister_sockopt(&ipt_sockopts);
2285 xt_unregister_match(&icmp_matchstruct);
2286 xt_unregister_target(&ipt_error_target);
2287 xt_unregister_target(&ipt_standard_target);
2289 xt_proto_fini(AF_INET);
2292 EXPORT_SYMBOL(ipt_register_table);
2293 EXPORT_SYMBOL(ipt_unregister_table);
2294 EXPORT_SYMBOL(ipt_do_table);
2295 module_init(ip_tables_init);
2296 module_exit(ip_tables_fini);