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 = table->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 table_base = (void *)private->entries[smp_processor_id()];
251 e = get_entry(table_base, private->hook_entry[hook]);
253 /* For return from builtin chain */
254 back = get_entry(table_base, private->underflow[hook]);
259 if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
260 struct ipt_entry_target *t;
262 if (IPT_MATCH_ITERATE(e, do_match,
264 offset, &hotdrop) != 0)
267 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
269 t = ipt_get_target(e);
270 IP_NF_ASSERT(t->u.kernel.target);
271 /* Standard target? */
272 if (!t->u.kernel.target->target) {
275 v = ((struct ipt_standard_target *)t)->verdict;
277 /* Pop from stack? */
278 if (v != IPT_RETURN) {
279 verdict = (unsigned)(-v) - 1;
283 back = get_entry(table_base,
287 if (table_base + v != (void *)e + e->next_offset
288 && !(e->ip.flags & IPT_F_GOTO)) {
289 /* Save old back ptr in next entry */
290 struct ipt_entry *next
291 = (void *)e + e->next_offset;
293 = (void *)back - table_base;
294 /* set back pointer to next entry */
298 e = get_entry(table_base, v);
300 /* Targets which reenter must return
302 #ifdef CONFIG_NETFILTER_DEBUG
303 ((struct ipt_entry *)table_base)->comefrom
306 verdict = t->u.kernel.target->target(pskb,
313 #ifdef CONFIG_NETFILTER_DEBUG
314 if (((struct ipt_entry *)table_base)->comefrom
316 && verdict == IPT_CONTINUE) {
317 printk("Target %s reentered!\n",
318 t->u.kernel.target->name);
321 ((struct ipt_entry *)table_base)->comefrom
324 /* Target might have changed stuff. */
325 ip = (*pskb)->nh.iph;
326 datalen = (*pskb)->len - ip->ihl * 4;
328 if (verdict == IPT_CONTINUE)
329 e = (void *)e + e->next_offset;
337 e = (void *)e + e->next_offset;
341 read_unlock_bh(&table->lock);
343 #ifdef DEBUG_ALLOW_ALL
352 /* All zeroes == unconditional rule. */
354 unconditional(const struct ipt_ip *ip)
358 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
359 if (((__u32 *)ip)[i])
365 /* Figures out from what hook each rule can be called: returns 0 if
366 there are loops. Puts hook bitmask in comefrom. */
368 mark_source_chains(struct xt_table_info *newinfo,
369 unsigned int valid_hooks, void *entry0)
373 /* No recursion; use packet counter to save back ptrs (reset
374 to 0 as we leave), and comefrom to save source hook bitmask */
375 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
376 unsigned int pos = newinfo->hook_entry[hook];
378 = (struct ipt_entry *)(entry0 + pos);
380 if (!(valid_hooks & (1 << hook)))
383 /* Set initial back pointer. */
384 e->counters.pcnt = pos;
387 struct ipt_standard_target *t
388 = (void *)ipt_get_target(e);
390 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
391 printk("iptables: loop hook %u pos %u %08X.\n",
392 hook, pos, e->comefrom);
396 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
398 /* Unconditional return/END. */
399 if (e->target_offset == sizeof(struct ipt_entry)
400 && (strcmp(t->target.u.user.name,
401 IPT_STANDARD_TARGET) == 0)
403 && unconditional(&e->ip)) {
404 unsigned int oldpos, size;
406 /* Return: backtrack through the last
409 e->comefrom ^= (1<<NF_IP_NUMHOOKS);
410 #ifdef DEBUG_IP_FIREWALL_USER
412 & (1 << NF_IP_NUMHOOKS)) {
413 duprintf("Back unset "
420 pos = e->counters.pcnt;
421 e->counters.pcnt = 0;
423 /* We're at the start. */
427 e = (struct ipt_entry *)
429 } while (oldpos == pos + e->next_offset);
432 size = e->next_offset;
433 e = (struct ipt_entry *)
434 (entry0 + pos + size);
435 e->counters.pcnt = pos;
438 int newpos = t->verdict;
440 if (strcmp(t->target.u.user.name,
441 IPT_STANDARD_TARGET) == 0
443 /* This a jump; chase it. */
444 duprintf("Jump rule %u -> %u\n",
447 /* ... this is a fallthru */
448 newpos = pos + e->next_offset;
450 e = (struct ipt_entry *)
452 e->counters.pcnt = pos;
457 duprintf("Finished chain %u\n", hook);
463 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
465 if (i && (*i)-- == 0)
468 if (m->u.kernel.match->destroy)
469 m->u.kernel.match->destroy(m->u.kernel.match, m->data,
470 m->u.match_size - sizeof(*m));
471 module_put(m->u.kernel.match->me);
476 standard_check(const struct ipt_entry_target *t,
477 unsigned int max_offset)
479 struct ipt_standard_target *targ = (void *)t;
481 /* Check standard info. */
482 if (targ->verdict >= 0
483 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
484 duprintf("ipt_standard_check: bad verdict (%i)\n",
488 if (targ->verdict < -NF_MAX_VERDICT - 1) {
489 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
497 check_match(struct ipt_entry_match *m,
499 const struct ipt_ip *ip,
500 unsigned int hookmask,
503 struct ipt_match *match;
506 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
508 "ipt_%s", m->u.user.name);
509 if (IS_ERR(match) || !match) {
510 duprintf("check_match: `%s' not found\n", m->u.user.name);
511 return match ? PTR_ERR(match) : -ENOENT;
513 m->u.kernel.match = match;
515 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
516 name, hookmask, ip->proto,
517 ip->invflags & IPT_INV_PROTO);
521 if (m->u.kernel.match->checkentry
522 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
523 m->u.match_size - sizeof(*m),
525 duprintf("ip_tables: check failed for `%s'.\n",
526 m->u.kernel.match->name);
534 module_put(m->u.kernel.match->me);
538 static struct ipt_target ipt_standard_target;
541 check_entry(struct ipt_entry *e, const char *name, unsigned int size,
544 struct ipt_entry_target *t;
545 struct ipt_target *target;
549 if (!ip_checkentry(&e->ip)) {
550 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
555 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
557 goto cleanup_matches;
559 t = ipt_get_target(e);
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 == &ipt_standard_target) {
578 if (!standard_check(t, size)) {
580 goto cleanup_matches;
582 } else if (t->u.kernel.target->checkentry
583 && !t->u.kernel.target->checkentry(name, e, target, t->data,
587 duprintf("ip_tables: check failed for `%s'.\n",
588 t->u.kernel.target->name);
596 module_put(t->u.kernel.target->me);
598 IPT_MATCH_ITERATE(e, cleanup_match, &j);
603 check_entry_size_and_hooks(struct ipt_entry *e,
604 struct xt_table_info *newinfo,
606 unsigned char *limit,
607 const unsigned int *hook_entries,
608 const unsigned int *underflows,
613 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
614 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
615 duprintf("Bad offset %p\n", e);
620 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
621 duprintf("checking: element %p size %u\n",
626 /* Check hooks & underflows */
627 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
628 if ((unsigned char *)e - base == hook_entries[h])
629 newinfo->hook_entry[h] = hook_entries[h];
630 if ((unsigned char *)e - base == underflows[h])
631 newinfo->underflow[h] = underflows[h];
634 /* FIXME: underflows must be unconditional, standard verdicts
635 < 0 (not IPT_RETURN). --RR */
637 /* Clear counters and comefrom */
638 e->counters = ((struct xt_counters) { 0, 0 });
646 cleanup_entry(struct ipt_entry *e, unsigned int *i)
648 struct ipt_entry_target *t;
650 if (i && (*i)-- == 0)
653 /* Cleanup all matches */
654 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
655 t = ipt_get_target(e);
656 if (t->u.kernel.target->destroy)
657 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
658 t->u.target_size - sizeof(*t));
659 module_put(t->u.kernel.target->me);
663 /* Checks and translates the user-supplied table segment (held in
666 translate_table(const char *name,
667 unsigned int valid_hooks,
668 struct xt_table_info *newinfo,
672 const unsigned int *hook_entries,
673 const unsigned int *underflows)
678 newinfo->size = size;
679 newinfo->number = number;
681 /* Init all hooks to impossible value. */
682 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
683 newinfo->hook_entry[i] = 0xFFFFFFFF;
684 newinfo->underflow[i] = 0xFFFFFFFF;
687 duprintf("translate_table: size %u\n", newinfo->size);
689 /* Walk through entries, checking offsets. */
690 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
691 check_entry_size_and_hooks,
695 hook_entries, underflows, &i);
700 duprintf("translate_table: %u not %u entries\n",
705 /* Check hooks all assigned */
706 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
707 /* Only hooks which are valid */
708 if (!(valid_hooks & (1 << i)))
710 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
711 duprintf("Invalid hook entry %u %u\n",
715 if (newinfo->underflow[i] == 0xFFFFFFFF) {
716 duprintf("Invalid underflow %u %u\n",
722 if (!mark_source_chains(newinfo, valid_hooks, entry0))
725 /* Finally, each sanity check must pass */
727 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
728 check_entry, name, size, &i);
731 IPT_ENTRY_ITERATE(entry0, newinfo->size,
736 /* And one copy for every other CPU */
737 for_each_possible_cpu(i) {
738 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
739 memcpy(newinfo->entries[i], entry0, newinfo->size);
747 add_entry_to_counter(const struct ipt_entry *e,
748 struct xt_counters total[],
751 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
758 set_entry_to_counter(const struct ipt_entry *e,
759 struct ipt_counters total[],
762 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
769 get_counters(const struct xt_table_info *t,
770 struct xt_counters counters[])
776 /* Instead of clearing (by a previous call to memset())
777 * the counters and using adds, we set the counters
778 * with data used by 'current' CPU
779 * We dont care about preemption here.
781 curcpu = raw_smp_processor_id();
784 IPT_ENTRY_ITERATE(t->entries[curcpu],
786 set_entry_to_counter,
790 for_each_possible_cpu(cpu) {
794 IPT_ENTRY_ITERATE(t->entries[cpu],
796 add_entry_to_counter,
802 static inline struct xt_counters * alloc_counters(struct ipt_table *table)
804 unsigned int countersize;
805 struct xt_counters *counters;
806 struct xt_table_info *private = table->private;
808 /* We need atomic snapshot of counters: rest doesn't change
809 (other than comefrom, which userspace doesn't care
811 countersize = sizeof(struct xt_counters) * private->number;
812 counters = vmalloc_node(countersize, numa_node_id());
814 if (counters == NULL)
815 return ERR_PTR(-ENOMEM);
817 /* First, sum counters... */
818 write_lock_bh(&table->lock);
819 get_counters(private, counters);
820 write_unlock_bh(&table->lock);
826 copy_entries_to_user(unsigned int total_size,
827 struct ipt_table *table,
828 void __user *userptr)
830 unsigned int off, num;
832 struct xt_counters *counters;
833 struct xt_table_info *private = table->private;
837 counters = alloc_counters(table);
838 if (IS_ERR(counters))
839 return PTR_ERR(counters);
841 /* choose the copy that is on our node/cpu, ...
842 * This choice is lazy (because current thread is
843 * allowed to migrate to another cpu)
845 loc_cpu_entry = private->entries[raw_smp_processor_id()];
846 /* ... then copy entire thing ... */
847 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
852 /* FIXME: use iterator macros --RR */
853 /* ... then go back and fix counters and names */
854 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
856 struct ipt_entry_match *m;
857 struct ipt_entry_target *t;
859 e = (struct ipt_entry *)(loc_cpu_entry + off);
860 if (copy_to_user(userptr + off
861 + offsetof(struct ipt_entry, counters),
863 sizeof(counters[num])) != 0) {
868 for (i = sizeof(struct ipt_entry);
869 i < e->target_offset;
870 i += m->u.match_size) {
873 if (copy_to_user(userptr + off + i
874 + offsetof(struct ipt_entry_match,
876 m->u.kernel.match->name,
877 strlen(m->u.kernel.match->name)+1)
884 t = ipt_get_target(e);
885 if (copy_to_user(userptr + off + e->target_offset
886 + offsetof(struct ipt_entry_target,
888 t->u.kernel.target->name,
889 strlen(t->u.kernel.target->name)+1) != 0) {
901 struct compat_delta {
902 struct compat_delta *next;
907 static struct compat_delta *compat_offsets = NULL;
909 static int compat_add_offset(u_int16_t offset, short delta)
911 struct compat_delta *tmp;
913 tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
916 tmp->offset = offset;
918 if (compat_offsets) {
919 tmp->next = compat_offsets->next;
920 compat_offsets->next = tmp;
922 compat_offsets = tmp;
928 static void compat_flush_offsets(void)
930 struct compat_delta *tmp, *next;
932 if (compat_offsets) {
933 for(tmp = compat_offsets; tmp; tmp = next) {
937 compat_offsets = NULL;
941 static short compat_calc_jump(u_int16_t offset)
943 struct compat_delta *tmp;
946 for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
947 if (tmp->offset < offset)
952 struct compat_ipt_standard_target
954 struct compat_xt_entry_target target;
955 compat_int_t verdict;
958 struct compat_ipt_standard
960 struct compat_ipt_entry entry;
961 struct compat_ipt_standard_target target;
964 #define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target))
965 #define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target))
966 #define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN)
968 static int compat_ipt_standard_fn(void *target,
969 void **dstptr, int *size, int convert)
971 struct compat_ipt_standard_target compat_st, *pcompat_st;
972 struct ipt_standard_target st, *pst;
979 memcpy(&compat_st.target, &pst->target,
980 sizeof(compat_st.target));
981 compat_st.verdict = pst->verdict;
982 if (compat_st.verdict > 0)
984 compat_calc_jump(compat_st.verdict);
985 compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN;
986 if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN))
988 *size -= IPT_ST_OFFSET;
989 *dstptr += IPT_ST_COMPAT_LEN;
991 case COMPAT_FROM_USER:
993 memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN);
994 st.verdict = pcompat_st->verdict;
996 st.verdict += compat_calc_jump(st.verdict);
997 st.target.u.user.target_size = IPT_ST_LEN;
998 memcpy(*dstptr, &st, IPT_ST_LEN);
999 *size += IPT_ST_OFFSET;
1000 *dstptr += IPT_ST_LEN;
1002 case COMPAT_CALC_SIZE:
1003 *size += IPT_ST_OFFSET;
1013 compat_calc_match(struct ipt_entry_match *m, int * size)
1015 if (m->u.kernel.match->compat)
1016 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1018 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1022 static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
1023 void *base, struct xt_table_info *newinfo)
1025 struct ipt_entry_target *t;
1026 u_int16_t entry_offset;
1030 entry_offset = (void *)e - base;
1031 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1032 t = ipt_get_target(e);
1033 if (t->u.kernel.target->compat)
1034 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1036 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1037 newinfo->size -= off;
1038 ret = compat_add_offset(entry_offset, off);
1042 for (i = 0; i< NF_IP_NUMHOOKS; i++) {
1043 if (info->hook_entry[i] && (e < (struct ipt_entry *)
1044 (base + info->hook_entry[i])))
1045 newinfo->hook_entry[i] -= off;
1046 if (info->underflow[i] && (e < (struct ipt_entry *)
1047 (base + info->underflow[i])))
1048 newinfo->underflow[i] -= off;
1053 static int compat_table_info(struct xt_table_info *info,
1054 struct xt_table_info *newinfo)
1056 void *loc_cpu_entry;
1059 if (!newinfo || !info)
1062 memset(newinfo, 0, sizeof(struct xt_table_info));
1063 newinfo->size = info->size;
1064 newinfo->number = info->number;
1065 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1066 newinfo->hook_entry[i] = info->hook_entry[i];
1067 newinfo->underflow[i] = info->underflow[i];
1069 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1070 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1071 compat_calc_entry, info, loc_cpu_entry, newinfo);
1075 static int get_info(void __user *user, int *len, int compat)
1077 char name[IPT_TABLE_MAXNAMELEN];
1078 struct ipt_table *t;
1081 if (*len != sizeof(struct ipt_getinfo)) {
1082 duprintf("length %u != %u\n", *len,
1083 (unsigned int)sizeof(struct ipt_getinfo));
1087 if (copy_from_user(name, user, sizeof(name)) != 0)
1090 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1091 #ifdef CONFIG_COMPAT
1093 xt_compat_lock(AF_INET);
1095 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1096 "iptable_%s", name);
1097 if (t && !IS_ERR(t)) {
1098 struct ipt_getinfo info;
1099 struct xt_table_info *private = t->private;
1101 #ifdef CONFIG_COMPAT
1103 struct xt_table_info tmp;
1104 ret = compat_table_info(private, &tmp);
1105 compat_flush_offsets();
1109 info.valid_hooks = t->valid_hooks;
1110 memcpy(info.hook_entry, private->hook_entry,
1111 sizeof(info.hook_entry));
1112 memcpy(info.underflow, private->underflow,
1113 sizeof(info.underflow));
1114 info.num_entries = private->number;
1115 info.size = private->size;
1116 strcpy(info.name, name);
1118 if (copy_to_user(user, &info, *len) != 0)
1126 ret = t ? PTR_ERR(t) : -ENOENT;
1127 #ifdef CONFIG_COMPAT
1129 xt_compat_unlock(AF_INET);
1135 get_entries(struct ipt_get_entries __user *uptr, int *len)
1138 struct ipt_get_entries get;
1139 struct ipt_table *t;
1141 if (*len < sizeof(get)) {
1142 duprintf("get_entries: %u < %d\n", *len,
1143 (unsigned int)sizeof(get));
1146 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1148 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1149 duprintf("get_entries: %u != %u\n", *len,
1150 (unsigned int)(sizeof(struct ipt_get_entries) +
1155 t = xt_find_table_lock(AF_INET, get.name);
1156 if (t && !IS_ERR(t)) {
1157 struct xt_table_info *private = t->private;
1158 duprintf("t->private->number = %u\n",
1160 if (get.size == private->size)
1161 ret = copy_entries_to_user(private->size,
1162 t, uptr->entrytable);
1164 duprintf("get_entries: I've got %u not %u!\n",
1172 ret = t ? PTR_ERR(t) : -ENOENT;
1178 __do_replace(const char *name, unsigned int valid_hooks,
1179 struct xt_table_info *newinfo, unsigned int num_counters,
1180 void __user *counters_ptr)
1183 struct ipt_table *t;
1184 struct xt_table_info *oldinfo;
1185 struct xt_counters *counters;
1186 void *loc_cpu_old_entry;
1189 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1195 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1196 "iptable_%s", name);
1197 if (!t || IS_ERR(t)) {
1198 ret = t ? PTR_ERR(t) : -ENOENT;
1199 goto free_newinfo_counters_untrans;
1203 if (valid_hooks != t->valid_hooks) {
1204 duprintf("Valid hook crap: %08X vs %08X\n",
1205 valid_hooks, t->valid_hooks);
1210 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1214 /* Update module usage count based on number of rules */
1215 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1216 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1217 if ((oldinfo->number > oldinfo->initial_entries) ||
1218 (newinfo->number <= oldinfo->initial_entries))
1220 if ((oldinfo->number > oldinfo->initial_entries) &&
1221 (newinfo->number <= oldinfo->initial_entries))
1224 /* Get the old counters. */
1225 get_counters(oldinfo, counters);
1226 /* Decrease module usage counts and free resource */
1227 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1228 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1229 xt_free_table_info(oldinfo);
1230 if (copy_to_user(counters_ptr, counters,
1231 sizeof(struct xt_counters) * num_counters) != 0)
1240 free_newinfo_counters_untrans:
1247 do_replace(void __user *user, unsigned int len)
1250 struct ipt_replace tmp;
1251 struct xt_table_info *newinfo;
1252 void *loc_cpu_entry;
1254 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1257 /* Hack: Causes ipchains to give correct error msg --RR */
1258 if (len != sizeof(tmp) + tmp.size)
1259 return -ENOPROTOOPT;
1261 /* overflow check */
1262 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1265 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1268 newinfo = xt_alloc_table_info(tmp.size);
1272 /* choose the copy that is our node/cpu */
1273 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1274 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1280 ret = translate_table(tmp.name, tmp.valid_hooks,
1281 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1282 tmp.hook_entry, tmp.underflow);
1286 duprintf("ip_tables: Translated table\n");
1288 ret = __do_replace(tmp.name, tmp.valid_hooks,
1289 newinfo, tmp.num_counters,
1292 goto free_newinfo_untrans;
1295 free_newinfo_untrans:
1296 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1298 xt_free_table_info(newinfo);
1302 /* We're lazy, and add to the first CPU; overflow works its fey magic
1303 * and everything is OK. */
1305 add_counter_to_entry(struct ipt_entry *e,
1306 const struct xt_counters addme[],
1310 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1312 (long unsigned int)e->counters.pcnt,
1313 (long unsigned int)e->counters.bcnt,
1314 (long unsigned int)addme[*i].pcnt,
1315 (long unsigned int)addme[*i].bcnt);
1318 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1325 do_add_counters(void __user *user, unsigned int len, int compat)
1328 struct xt_counters_info tmp;
1329 struct xt_counters *paddc;
1330 unsigned int num_counters;
1334 struct ipt_table *t;
1335 struct xt_table_info *private;
1337 void *loc_cpu_entry;
1338 #ifdef CONFIG_COMPAT
1339 struct compat_xt_counters_info compat_tmp;
1343 size = sizeof(struct compat_xt_counters_info);
1348 size = sizeof(struct xt_counters_info);
1351 if (copy_from_user(ptmp, user, size) != 0)
1354 #ifdef CONFIG_COMPAT
1356 num_counters = compat_tmp.num_counters;
1357 name = compat_tmp.name;
1361 num_counters = tmp.num_counters;
1365 if (len != size + num_counters * sizeof(struct xt_counters))
1368 paddc = vmalloc_node(len - size, numa_node_id());
1372 if (copy_from_user(paddc, user + size, len - size) != 0) {
1377 t = xt_find_table_lock(AF_INET, name);
1378 if (!t || IS_ERR(t)) {
1379 ret = t ? PTR_ERR(t) : -ENOENT;
1383 write_lock_bh(&t->lock);
1384 private = t->private;
1385 if (private->number != num_counters) {
1387 goto unlock_up_free;
1391 /* Choose the copy that is on our node */
1392 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1393 IPT_ENTRY_ITERATE(loc_cpu_entry,
1395 add_counter_to_entry,
1399 write_unlock_bh(&t->lock);
1408 #ifdef CONFIG_COMPAT
1409 struct compat_ipt_replace {
1410 char name[IPT_TABLE_MAXNAMELEN];
1414 u32 hook_entry[NF_IP_NUMHOOKS];
1415 u32 underflow[NF_IP_NUMHOOKS];
1417 compat_uptr_t counters; /* struct ipt_counters * */
1418 struct compat_ipt_entry entries[0];
1421 static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
1422 void __user **dstptr, compat_uint_t *size)
1424 if (m->u.kernel.match->compat)
1425 return m->u.kernel.match->compat(m, dstptr, size,
1428 return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
1431 static int compat_copy_entry_to_user(struct ipt_entry *e,
1432 void __user **dstptr, compat_uint_t *size)
1434 struct ipt_entry_target __user *t;
1435 struct compat_ipt_entry __user *ce;
1436 u_int16_t target_offset, next_offset;
1437 compat_uint_t origsize;
1442 ce = (struct compat_ipt_entry __user *)*dstptr;
1443 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1446 *dstptr += sizeof(struct compat_ipt_entry);
1447 ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
1448 target_offset = e->target_offset - (origsize - *size);
1451 t = ipt_get_target(e);
1452 if (t->u.kernel.target->compat)
1453 ret = t->u.kernel.target->compat(t, dstptr, size,
1456 ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
1460 next_offset = e->next_offset - (origsize - *size);
1461 if (put_user(target_offset, &ce->target_offset))
1463 if (put_user(next_offset, &ce->next_offset))
1471 compat_check_calc_match(struct ipt_entry_match *m,
1473 const struct ipt_ip *ip,
1474 unsigned int hookmask,
1477 struct ipt_match *match;
1479 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1480 m->u.user.revision),
1481 "ipt_%s", m->u.user.name);
1482 if (IS_ERR(match) || !match) {
1483 duprintf("compat_check_calc_match: `%s' not found\n",
1485 return match ? PTR_ERR(match) : -ENOENT;
1487 m->u.kernel.match = match;
1489 if (m->u.kernel.match->compat)
1490 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1492 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1499 check_compat_entry_size_and_hooks(struct ipt_entry *e,
1500 struct xt_table_info *newinfo,
1502 unsigned char *base,
1503 unsigned char *limit,
1504 unsigned int *hook_entries,
1505 unsigned int *underflows,
1509 struct ipt_entry_target *t;
1510 struct ipt_target *target;
1511 u_int16_t entry_offset;
1514 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1515 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1516 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1517 duprintf("Bad offset %p, limit = %p\n", e, limit);
1521 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1522 sizeof(struct compat_xt_entry_target)) {
1523 duprintf("checking: element %p size %u\n",
1528 if (!ip_checkentry(&e->ip)) {
1529 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
1534 entry_offset = (void *)e - (void *)base;
1536 ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
1537 e->comefrom, &off, &j);
1541 t = ipt_get_target(e);
1542 target = try_then_request_module(xt_find_target(AF_INET,
1544 t->u.user.revision),
1545 "ipt_%s", t->u.user.name);
1546 if (IS_ERR(target) || !target) {
1547 duprintf("check_entry: `%s' not found\n", t->u.user.name);
1548 ret = target ? PTR_ERR(target) : -ENOENT;
1551 t->u.kernel.target = target;
1553 if (t->u.kernel.target->compat)
1554 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1556 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1558 ret = compat_add_offset(entry_offset, off);
1562 /* Check hooks & underflows */
1563 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1564 if ((unsigned char *)e - base == hook_entries[h])
1565 newinfo->hook_entry[h] = hook_entries[h];
1566 if ((unsigned char *)e - base == underflows[h])
1567 newinfo->underflow[h] = underflows[h];
1570 /* Clear counters and comefrom */
1571 e->counters = ((struct ipt_counters) { 0, 0 });
1577 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1581 static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
1582 void **dstptr, compat_uint_t *size, const char *name,
1583 const struct ipt_ip *ip, unsigned int hookmask)
1585 struct ipt_entry_match *dm;
1586 struct ipt_match *match;
1589 dm = (struct ipt_entry_match *)*dstptr;
1590 match = m->u.kernel.match;
1592 match->compat(m, dstptr, size, COMPAT_FROM_USER);
1594 xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
1596 ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
1597 name, hookmask, ip->proto,
1598 ip->invflags & IPT_INV_PROTO);
1602 if (m->u.kernel.match->checkentry
1603 && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
1604 dm->u.match_size - sizeof(*dm),
1606 duprintf("ip_tables: check failed for `%s'.\n",
1607 m->u.kernel.match->name);
1613 static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1614 unsigned int *size, const char *name,
1615 struct xt_table_info *newinfo, unsigned char *base)
1617 struct ipt_entry_target *t;
1618 struct ipt_target *target;
1619 struct ipt_entry *de;
1620 unsigned int origsize;
1625 de = (struct ipt_entry *)*dstptr;
1626 memcpy(de, e, sizeof(struct ipt_entry));
1628 *dstptr += sizeof(struct compat_ipt_entry);
1629 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
1630 name, &de->ip, de->comefrom);
1633 de->target_offset = e->target_offset - (origsize - *size);
1634 t = ipt_get_target(e);
1635 target = t->u.kernel.target;
1637 target->compat(t, dstptr, size, COMPAT_FROM_USER);
1639 xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
1641 de->next_offset = e->next_offset - (origsize - *size);
1642 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1643 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1644 newinfo->hook_entry[h] -= origsize - *size;
1645 if ((unsigned char *)de - base < newinfo->underflow[h])
1646 newinfo->underflow[h] -= origsize - *size;
1649 t = ipt_get_target(de);
1650 target = t->u.kernel.target;
1651 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
1652 name, e->comefrom, e->ip.proto,
1653 e->ip.invflags & IPT_INV_PROTO);
1658 if (t->u.kernel.target == &ipt_standard_target) {
1659 if (!standard_check(t, *size))
1661 } else if (t->u.kernel.target->checkentry
1662 && !t->u.kernel.target->checkentry(name, de, target,
1663 t->data, t->u.target_size - sizeof(*t),
1665 duprintf("ip_tables: compat: check failed for `%s'.\n",
1666 t->u.kernel.target->name);
1675 translate_compat_table(const char *name,
1676 unsigned int valid_hooks,
1677 struct xt_table_info **pinfo,
1679 unsigned int total_size,
1680 unsigned int number,
1681 unsigned int *hook_entries,
1682 unsigned int *underflows)
1685 struct xt_table_info *newinfo, *info;
1686 void *pos, *entry0, *entry1;
1693 info->number = number;
1695 /* Init all hooks to impossible value. */
1696 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1697 info->hook_entry[i] = 0xFFFFFFFF;
1698 info->underflow[i] = 0xFFFFFFFF;
1701 duprintf("translate_compat_table: size %u\n", info->size);
1703 xt_compat_lock(AF_INET);
1704 /* Walk through entries, checking offsets. */
1705 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1706 check_compat_entry_size_and_hooks,
1707 info, &size, entry0,
1708 entry0 + total_size,
1709 hook_entries, underflows, &i, name);
1715 duprintf("translate_compat_table: %u not %u entries\n",
1720 /* Check hooks all assigned */
1721 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1722 /* Only hooks which are valid */
1723 if (!(valid_hooks & (1 << i)))
1725 if (info->hook_entry[i] == 0xFFFFFFFF) {
1726 duprintf("Invalid hook entry %u %u\n",
1727 i, hook_entries[i]);
1730 if (info->underflow[i] == 0xFFFFFFFF) {
1731 duprintf("Invalid underflow %u %u\n",
1738 newinfo = xt_alloc_table_info(size);
1742 newinfo->number = number;
1743 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1744 newinfo->hook_entry[i] = info->hook_entry[i];
1745 newinfo->underflow[i] = info->underflow[i];
1747 entry1 = newinfo->entries[raw_smp_processor_id()];
1750 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1751 compat_copy_entry_from_user, &pos, &size,
1752 name, newinfo, entry1);
1753 compat_flush_offsets();
1754 xt_compat_unlock(AF_INET);
1759 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1762 /* And one copy for every other CPU */
1763 for_each_possible_cpu(i)
1764 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1765 memcpy(newinfo->entries[i], entry1, newinfo->size);
1769 xt_free_table_info(info);
1773 xt_free_table_info(newinfo);
1777 xt_compat_unlock(AF_INET);
1782 compat_do_replace(void __user *user, unsigned int len)
1785 struct compat_ipt_replace tmp;
1786 struct xt_table_info *newinfo;
1787 void *loc_cpu_entry;
1789 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1792 /* Hack: Causes ipchains to give correct error msg --RR */
1793 if (len != sizeof(tmp) + tmp.size)
1794 return -ENOPROTOOPT;
1796 /* overflow check */
1797 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1800 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1803 newinfo = xt_alloc_table_info(tmp.size);
1807 /* choose the copy that is our node/cpu */
1808 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1809 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1815 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1816 &newinfo, &loc_cpu_entry, tmp.size,
1817 tmp.num_entries, tmp.hook_entry, tmp.underflow);
1821 duprintf("compat_do_replace: Translated table\n");
1823 ret = __do_replace(tmp.name, tmp.valid_hooks,
1824 newinfo, tmp.num_counters,
1825 compat_ptr(tmp.counters));
1827 goto free_newinfo_untrans;
1830 free_newinfo_untrans:
1831 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1833 xt_free_table_info(newinfo);
1838 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1843 if (!capable(CAP_NET_ADMIN))
1847 case IPT_SO_SET_REPLACE:
1848 ret = compat_do_replace(user, len);
1851 case IPT_SO_SET_ADD_COUNTERS:
1852 ret = do_add_counters(user, len, 1);
1856 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1863 struct compat_ipt_get_entries
1865 char name[IPT_TABLE_MAXNAMELEN];
1867 struct compat_ipt_entry entrytable[0];
1870 static int compat_copy_entries_to_user(unsigned int total_size,
1871 struct ipt_table *table, void __user *userptr)
1873 unsigned int off, num;
1874 struct compat_ipt_entry e;
1875 struct xt_counters *counters;
1876 struct xt_table_info *private = table->private;
1880 void *loc_cpu_entry;
1882 counters = alloc_counters(table);
1883 if (IS_ERR(counters))
1884 return PTR_ERR(counters);
1886 /* choose the copy that is on our node/cpu, ...
1887 * This choice is lazy (because current thread is
1888 * allowed to migrate to another cpu)
1890 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1893 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1894 compat_copy_entry_to_user, &pos, &size);
1898 /* ... then go back and fix counters and names */
1899 for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
1901 struct ipt_entry_match m;
1902 struct ipt_entry_target t;
1905 if (copy_from_user(&e, userptr + off,
1906 sizeof(struct compat_ipt_entry)))
1908 if (copy_to_user(userptr + off +
1909 offsetof(struct compat_ipt_entry, counters),
1910 &counters[num], sizeof(counters[num])))
1913 for (i = sizeof(struct compat_ipt_entry);
1914 i < e.target_offset; i += m.u.match_size) {
1915 if (copy_from_user(&m, userptr + off + i,
1916 sizeof(struct ipt_entry_match)))
1918 if (copy_to_user(userptr + off + i +
1919 offsetof(struct ipt_entry_match, u.user.name),
1920 m.u.kernel.match->name,
1921 strlen(m.u.kernel.match->name) + 1))
1925 if (copy_from_user(&t, userptr + off + e.target_offset,
1926 sizeof(struct ipt_entry_target)))
1928 if (copy_to_user(userptr + off + e.target_offset +
1929 offsetof(struct ipt_entry_target, u.user.name),
1930 t.u.kernel.target->name,
1931 strlen(t.u.kernel.target->name) + 1))
1941 compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
1944 struct compat_ipt_get_entries get;
1945 struct ipt_table *t;
1948 if (*len < sizeof(get)) {
1949 duprintf("compat_get_entries: %u < %u\n",
1950 *len, (unsigned int)sizeof(get));
1954 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1957 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1958 duprintf("compat_get_entries: %u != %u\n", *len,
1959 (unsigned int)(sizeof(struct compat_ipt_get_entries) +
1964 xt_compat_lock(AF_INET);
1965 t = xt_find_table_lock(AF_INET, get.name);
1966 if (t && !IS_ERR(t)) {
1967 struct xt_table_info *private = t->private;
1968 struct xt_table_info info;
1969 duprintf("t->private->number = %u\n",
1971 ret = compat_table_info(private, &info);
1972 if (!ret && get.size == info.size) {
1973 ret = compat_copy_entries_to_user(private->size,
1974 t, uptr->entrytable);
1976 duprintf("compat_get_entries: I've got %u not %u!\n",
1981 compat_flush_offsets();
1985 ret = t ? PTR_ERR(t) : -ENOENT;
1987 xt_compat_unlock(AF_INET);
1992 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1997 case IPT_SO_GET_INFO:
1998 ret = get_info(user, len, 1);
2000 case IPT_SO_GET_ENTRIES:
2001 ret = compat_get_entries(user, len);
2004 duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
2012 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2016 if (!capable(CAP_NET_ADMIN))
2020 case IPT_SO_SET_REPLACE:
2021 ret = do_replace(user, len);
2024 case IPT_SO_SET_ADD_COUNTERS:
2025 ret = do_add_counters(user, len, 0);
2029 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2037 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2041 if (!capable(CAP_NET_ADMIN))
2045 case IPT_SO_GET_INFO:
2046 ret = get_info(user, len, 0);
2049 case IPT_SO_GET_ENTRIES:
2050 ret = get_entries(user, len);
2053 case IPT_SO_GET_REVISION_MATCH:
2054 case IPT_SO_GET_REVISION_TARGET: {
2055 struct ipt_get_revision rev;
2058 if (*len != sizeof(rev)) {
2062 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2067 if (cmd == IPT_SO_GET_REVISION_TARGET)
2072 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2075 "ipt_%s", rev.name);
2080 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2087 int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
2090 struct xt_table_info *newinfo;
2091 static struct xt_table_info bootstrap
2092 = { 0, 0, 0, { 0 }, { 0 }, { } };
2093 void *loc_cpu_entry;
2095 newinfo = xt_alloc_table_info(repl->size);
2099 /* choose the copy on our node/cpu
2100 * but dont care of preemption
2102 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2103 memcpy(loc_cpu_entry, repl->entries, repl->size);
2105 ret = translate_table(table->name, table->valid_hooks,
2106 newinfo, loc_cpu_entry, repl->size,
2111 xt_free_table_info(newinfo);
2115 ret = xt_register_table(table, &bootstrap, newinfo);
2117 xt_free_table_info(newinfo);
2124 void ipt_unregister_table(struct ipt_table *table)
2126 struct xt_table_info *private;
2127 void *loc_cpu_entry;
2129 private = xt_unregister_table(table);
2131 /* Decrease module usage counts and free resources */
2132 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2133 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2134 xt_free_table_info(private);
2137 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2139 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2140 u_int8_t type, u_int8_t code,
2143 return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
2148 icmp_match(const struct sk_buff *skb,
2149 const struct net_device *in,
2150 const struct net_device *out,
2151 const struct xt_match *match,
2152 const void *matchinfo,
2154 unsigned int protoff,
2157 struct icmphdr _icmph, *ic;
2158 const struct ipt_icmp *icmpinfo = matchinfo;
2160 /* Must not be a fragment. */
2164 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
2166 /* We've been asked to examine this packet, and we
2167 * can't. Hence, no choice but to drop.
2169 duprintf("Dropping evil ICMP tinygram.\n");
2174 return icmp_type_code_match(icmpinfo->type,
2178 !!(icmpinfo->invflags&IPT_ICMP_INV));
2181 /* Called when user tries to insert an entry of this type. */
2183 icmp_checkentry(const char *tablename,
2185 const struct xt_match *match,
2187 unsigned int matchsize,
2188 unsigned int hook_mask)
2190 const struct ipt_icmp *icmpinfo = matchinfo;
2192 /* Must specify no unknown invflags */
2193 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2196 /* The built-in targets: standard (NULL) and error. */
2197 static struct ipt_target ipt_standard_target = {
2198 .name = IPT_STANDARD_TARGET,
2199 .targetsize = sizeof(int),
2201 #ifdef CONFIG_COMPAT
2202 .compat = &compat_ipt_standard_fn,
2206 static struct ipt_target ipt_error_target = {
2207 .name = IPT_ERROR_TARGET,
2208 .target = ipt_error,
2209 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2213 static struct nf_sockopt_ops ipt_sockopts = {
2215 .set_optmin = IPT_BASE_CTL,
2216 .set_optmax = IPT_SO_SET_MAX+1,
2217 .set = do_ipt_set_ctl,
2218 #ifdef CONFIG_COMPAT
2219 .compat_set = compat_do_ipt_set_ctl,
2221 .get_optmin = IPT_BASE_CTL,
2222 .get_optmax = IPT_SO_GET_MAX+1,
2223 .get = do_ipt_get_ctl,
2224 #ifdef CONFIG_COMPAT
2225 .compat_get = compat_do_ipt_get_ctl,
2229 static struct ipt_match icmp_matchstruct = {
2231 .match = icmp_match,
2232 .matchsize = sizeof(struct ipt_icmp),
2233 .proto = IPPROTO_ICMP,
2235 .checkentry = icmp_checkentry,
2238 static int __init ip_tables_init(void)
2242 xt_proto_init(AF_INET);
2244 /* Noone else will be downing sem now, so we won't sleep */
2245 xt_register_target(&ipt_standard_target);
2246 xt_register_target(&ipt_error_target);
2247 xt_register_match(&icmp_matchstruct);
2249 /* Register setsockopt */
2250 ret = nf_register_sockopt(&ipt_sockopts);
2252 duprintf("Unable to register sockopts.\n");
2256 printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2260 static void __exit ip_tables_fini(void)
2262 nf_unregister_sockopt(&ipt_sockopts);
2264 xt_unregister_match(&icmp_matchstruct);
2265 xt_unregister_target(&ipt_error_target);
2266 xt_unregister_target(&ipt_standard_target);
2268 xt_proto_fini(AF_INET);
2271 EXPORT_SYMBOL(ipt_register_table);
2272 EXPORT_SYMBOL(ipt_unregister_table);
2273 EXPORT_SYMBOL(ipt_do_table);
2274 module_init(ip_tables_init);
2275 module_exit(ip_tables_fini);