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)
186 printk("ip_tables: error: `%s'\n", (char *)targinfo);
192 int do_match(struct ipt_entry_match *m,
193 const struct sk_buff *skb,
194 const struct net_device *in,
195 const struct net_device *out,
199 /* Stop iteration if it doesn't match */
200 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
201 offset, skb->nh.iph->ihl*4, hotdrop))
207 static inline struct ipt_entry *
208 get_entry(void *base, unsigned int offset)
210 return (struct ipt_entry *)(base + offset);
213 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
215 ipt_do_table(struct sk_buff **pskb,
217 const struct net_device *in,
218 const struct net_device *out,
219 struct ipt_table *table)
221 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
226 /* Initializing verdict to NF_DROP keeps gcc happy. */
227 unsigned int verdict = NF_DROP;
228 const char *indev, *outdev;
230 struct ipt_entry *e, *back;
231 struct xt_table_info *private;
234 ip = (*pskb)->nh.iph;
235 datalen = (*pskb)->len - ip->ihl * 4;
236 indev = in ? in->name : nulldevname;
237 outdev = out ? out->name : nulldevname;
238 /* We handle fragments by dealing with the first fragment as
239 * if it was a normal packet. All other fragments are treated
240 * normally, except that they will NEVER match rules that ask
241 * things we don't know, ie. tcp syn flag or ports). If the
242 * rule is also a fragment-specific rule, non-fragments won't
244 offset = ntohs(ip->frag_off) & IP_OFFSET;
246 read_lock_bh(&table->lock);
247 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
248 private = table->private;
249 table_base = (void *)private->entries[smp_processor_id()];
250 e = get_entry(table_base, private->hook_entry[hook]);
252 /* For return from builtin chain */
253 back = get_entry(table_base, private->underflow[hook]);
258 if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
259 struct ipt_entry_target *t;
261 if (IPT_MATCH_ITERATE(e, do_match,
263 offset, &hotdrop) != 0)
266 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
268 t = ipt_get_target(e);
269 IP_NF_ASSERT(t->u.kernel.target);
270 /* Standard target? */
271 if (!t->u.kernel.target->target) {
274 v = ((struct ipt_standard_target *)t)->verdict;
276 /* Pop from stack? */
277 if (v != IPT_RETURN) {
278 verdict = (unsigned)(-v) - 1;
282 back = get_entry(table_base,
286 if (table_base + v != (void *)e + e->next_offset
287 && !(e->ip.flags & IPT_F_GOTO)) {
288 /* Save old back ptr in next entry */
289 struct ipt_entry *next
290 = (void *)e + e->next_offset;
292 = (void *)back - table_base;
293 /* set back pointer to next entry */
297 e = get_entry(table_base, v);
299 /* Targets which reenter must return
301 #ifdef CONFIG_NETFILTER_DEBUG
302 ((struct ipt_entry *)table_base)->comefrom
305 verdict = t->u.kernel.target->target(pskb,
311 #ifdef CONFIG_NETFILTER_DEBUG
312 if (((struct ipt_entry *)table_base)->comefrom
314 && verdict == IPT_CONTINUE) {
315 printk("Target %s reentered!\n",
316 t->u.kernel.target->name);
319 ((struct ipt_entry *)table_base)->comefrom
322 /* Target might have changed stuff. */
323 ip = (*pskb)->nh.iph;
324 datalen = (*pskb)->len - ip->ihl * 4;
326 if (verdict == IPT_CONTINUE)
327 e = (void *)e + e->next_offset;
335 e = (void *)e + e->next_offset;
339 read_unlock_bh(&table->lock);
341 #ifdef DEBUG_ALLOW_ALL
350 /* All zeroes == unconditional rule. */
352 unconditional(const struct ipt_ip *ip)
356 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
357 if (((__u32 *)ip)[i])
363 /* Figures out from what hook each rule can be called: returns 0 if
364 there are loops. Puts hook bitmask in comefrom. */
366 mark_source_chains(struct xt_table_info *newinfo,
367 unsigned int valid_hooks, void *entry0)
371 /* No recursion; use packet counter to save back ptrs (reset
372 to 0 as we leave), and comefrom to save source hook bitmask */
373 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
374 unsigned int pos = newinfo->hook_entry[hook];
376 = (struct ipt_entry *)(entry0 + pos);
378 if (!(valid_hooks & (1 << hook)))
381 /* Set initial back pointer. */
382 e->counters.pcnt = pos;
385 struct ipt_standard_target *t
386 = (void *)ipt_get_target(e);
388 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
389 printk("iptables: loop hook %u pos %u %08X.\n",
390 hook, pos, e->comefrom);
394 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
396 /* Unconditional return/END. */
397 if (e->target_offset == sizeof(struct ipt_entry)
398 && (strcmp(t->target.u.user.name,
399 IPT_STANDARD_TARGET) == 0)
401 && unconditional(&e->ip)) {
402 unsigned int oldpos, size;
404 /* Return: backtrack through the last
407 e->comefrom ^= (1<<NF_IP_NUMHOOKS);
408 #ifdef DEBUG_IP_FIREWALL_USER
410 & (1 << NF_IP_NUMHOOKS)) {
411 duprintf("Back unset "
418 pos = e->counters.pcnt;
419 e->counters.pcnt = 0;
421 /* We're at the start. */
425 e = (struct ipt_entry *)
427 } while (oldpos == pos + e->next_offset);
430 size = e->next_offset;
431 e = (struct ipt_entry *)
432 (entry0 + pos + size);
433 e->counters.pcnt = pos;
436 int newpos = t->verdict;
438 if (strcmp(t->target.u.user.name,
439 IPT_STANDARD_TARGET) == 0
441 /* This a jump; chase it. */
442 duprintf("Jump rule %u -> %u\n",
445 /* ... this is a fallthru */
446 newpos = pos + e->next_offset;
448 e = (struct ipt_entry *)
450 e->counters.pcnt = pos;
455 duprintf("Finished chain %u\n", hook);
461 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
463 if (i && (*i)-- == 0)
466 if (m->u.kernel.match->destroy)
467 m->u.kernel.match->destroy(m->u.kernel.match, m->data);
468 module_put(m->u.kernel.match->me);
473 standard_check(const struct ipt_entry_target *t,
474 unsigned int max_offset)
476 struct ipt_standard_target *targ = (void *)t;
478 /* Check standard info. */
479 if (targ->verdict >= 0
480 && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
481 duprintf("ipt_standard_check: bad verdict (%i)\n",
485 if (targ->verdict < -NF_MAX_VERDICT - 1) {
486 duprintf("ipt_standard_check: bad negative verdict (%i)\n",
494 check_match(struct ipt_entry_match *m,
496 const struct ipt_ip *ip,
497 unsigned int hookmask,
500 struct ipt_match *match;
503 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
505 "ipt_%s", m->u.user.name);
506 if (IS_ERR(match) || !match) {
507 duprintf("check_match: `%s' not found\n", m->u.user.name);
508 return match ? PTR_ERR(match) : -ENOENT;
510 m->u.kernel.match = match;
512 ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
513 name, hookmask, ip->proto,
514 ip->invflags & IPT_INV_PROTO);
518 if (m->u.kernel.match->checkentry
519 && !m->u.kernel.match->checkentry(name, ip, match, m->data,
521 duprintf("ip_tables: check failed for `%s'.\n",
522 m->u.kernel.match->name);
530 module_put(m->u.kernel.match->me);
534 static struct ipt_target ipt_standard_target;
537 check_entry(struct ipt_entry *e, const char *name, unsigned int size,
540 struct ipt_entry_target *t;
541 struct ipt_target *target;
545 if (!ip_checkentry(&e->ip)) {
546 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
551 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
553 goto cleanup_matches;
555 t = ipt_get_target(e);
556 target = try_then_request_module(xt_find_target(AF_INET,
559 "ipt_%s", t->u.user.name);
560 if (IS_ERR(target) || !target) {
561 duprintf("check_entry: `%s' not found\n", t->u.user.name);
562 ret = target ? PTR_ERR(target) : -ENOENT;
563 goto cleanup_matches;
565 t->u.kernel.target = target;
567 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
568 name, e->comefrom, e->ip.proto,
569 e->ip.invflags & IPT_INV_PROTO);
573 if (t->u.kernel.target == &ipt_standard_target) {
574 if (!standard_check(t, size)) {
578 } else if (t->u.kernel.target->checkentry
579 && !t->u.kernel.target->checkentry(name, e, target, t->data,
581 duprintf("ip_tables: check failed for `%s'.\n",
582 t->u.kernel.target->name);
590 module_put(t->u.kernel.target->me);
592 IPT_MATCH_ITERATE(e, cleanup_match, &j);
597 check_entry_size_and_hooks(struct ipt_entry *e,
598 struct xt_table_info *newinfo,
600 unsigned char *limit,
601 const unsigned int *hook_entries,
602 const unsigned int *underflows,
607 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
608 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
609 duprintf("Bad offset %p\n", e);
614 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
615 duprintf("checking: element %p size %u\n",
620 /* Check hooks & underflows */
621 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
622 if ((unsigned char *)e - base == hook_entries[h])
623 newinfo->hook_entry[h] = hook_entries[h];
624 if ((unsigned char *)e - base == underflows[h])
625 newinfo->underflow[h] = underflows[h];
628 /* FIXME: underflows must be unconditional, standard verdicts
629 < 0 (not IPT_RETURN). --RR */
631 /* Clear counters and comefrom */
632 e->counters = ((struct xt_counters) { 0, 0 });
640 cleanup_entry(struct ipt_entry *e, unsigned int *i)
642 struct ipt_entry_target *t;
644 if (i && (*i)-- == 0)
647 /* Cleanup all matches */
648 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
649 t = ipt_get_target(e);
650 if (t->u.kernel.target->destroy)
651 t->u.kernel.target->destroy(t->u.kernel.target, t->data);
652 module_put(t->u.kernel.target->me);
656 /* Checks and translates the user-supplied table segment (held in
659 translate_table(const char *name,
660 unsigned int valid_hooks,
661 struct xt_table_info *newinfo,
665 const unsigned int *hook_entries,
666 const unsigned int *underflows)
671 newinfo->size = size;
672 newinfo->number = number;
674 /* Init all hooks to impossible value. */
675 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
676 newinfo->hook_entry[i] = 0xFFFFFFFF;
677 newinfo->underflow[i] = 0xFFFFFFFF;
680 duprintf("translate_table: size %u\n", newinfo->size);
682 /* Walk through entries, checking offsets. */
683 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
684 check_entry_size_and_hooks,
688 hook_entries, underflows, &i);
693 duprintf("translate_table: %u not %u entries\n",
698 /* Check hooks all assigned */
699 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
700 /* Only hooks which are valid */
701 if (!(valid_hooks & (1 << i)))
703 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
704 duprintf("Invalid hook entry %u %u\n",
708 if (newinfo->underflow[i] == 0xFFFFFFFF) {
709 duprintf("Invalid underflow %u %u\n",
715 if (!mark_source_chains(newinfo, valid_hooks, entry0))
718 /* Finally, each sanity check must pass */
720 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
721 check_entry, name, size, &i);
724 IPT_ENTRY_ITERATE(entry0, newinfo->size,
729 /* And one copy for every other CPU */
730 for_each_possible_cpu(i) {
731 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
732 memcpy(newinfo->entries[i], entry0, newinfo->size);
740 add_entry_to_counter(const struct ipt_entry *e,
741 struct xt_counters total[],
744 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
751 set_entry_to_counter(const struct ipt_entry *e,
752 struct ipt_counters total[],
755 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
762 get_counters(const struct xt_table_info *t,
763 struct xt_counters counters[])
769 /* Instead of clearing (by a previous call to memset())
770 * the counters and using adds, we set the counters
771 * with data used by 'current' CPU
772 * We dont care about preemption here.
774 curcpu = raw_smp_processor_id();
777 IPT_ENTRY_ITERATE(t->entries[curcpu],
779 set_entry_to_counter,
783 for_each_possible_cpu(cpu) {
787 IPT_ENTRY_ITERATE(t->entries[cpu],
789 add_entry_to_counter,
795 static inline struct xt_counters * alloc_counters(struct ipt_table *table)
797 unsigned int countersize;
798 struct xt_counters *counters;
799 struct xt_table_info *private = table->private;
801 /* We need atomic snapshot of counters: rest doesn't change
802 (other than comefrom, which userspace doesn't care
804 countersize = sizeof(struct xt_counters) * private->number;
805 counters = vmalloc_node(countersize, numa_node_id());
807 if (counters == NULL)
808 return ERR_PTR(-ENOMEM);
810 /* First, sum counters... */
811 write_lock_bh(&table->lock);
812 get_counters(private, counters);
813 write_unlock_bh(&table->lock);
819 copy_entries_to_user(unsigned int total_size,
820 struct ipt_table *table,
821 void __user *userptr)
823 unsigned int off, num;
825 struct xt_counters *counters;
826 struct xt_table_info *private = table->private;
830 counters = alloc_counters(table);
831 if (IS_ERR(counters))
832 return PTR_ERR(counters);
834 /* choose the copy that is on our node/cpu, ...
835 * This choice is lazy (because current thread is
836 * allowed to migrate to another cpu)
838 loc_cpu_entry = private->entries[raw_smp_processor_id()];
839 /* ... then copy entire thing ... */
840 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
845 /* FIXME: use iterator macros --RR */
846 /* ... then go back and fix counters and names */
847 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
849 struct ipt_entry_match *m;
850 struct ipt_entry_target *t;
852 e = (struct ipt_entry *)(loc_cpu_entry + off);
853 if (copy_to_user(userptr + off
854 + offsetof(struct ipt_entry, counters),
856 sizeof(counters[num])) != 0) {
861 for (i = sizeof(struct ipt_entry);
862 i < e->target_offset;
863 i += m->u.match_size) {
866 if (copy_to_user(userptr + off + i
867 + offsetof(struct ipt_entry_match,
869 m->u.kernel.match->name,
870 strlen(m->u.kernel.match->name)+1)
877 t = ipt_get_target(e);
878 if (copy_to_user(userptr + off + e->target_offset
879 + offsetof(struct ipt_entry_target,
881 t->u.kernel.target->name,
882 strlen(t->u.kernel.target->name)+1) != 0) {
894 struct compat_delta {
895 struct compat_delta *next;
900 static struct compat_delta *compat_offsets = NULL;
902 static int compat_add_offset(u_int16_t offset, short delta)
904 struct compat_delta *tmp;
906 tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
909 tmp->offset = offset;
911 if (compat_offsets) {
912 tmp->next = compat_offsets->next;
913 compat_offsets->next = tmp;
915 compat_offsets = tmp;
921 static void compat_flush_offsets(void)
923 struct compat_delta *tmp, *next;
925 if (compat_offsets) {
926 for(tmp = compat_offsets; tmp; tmp = next) {
930 compat_offsets = NULL;
934 static short compat_calc_jump(u_int16_t offset)
936 struct compat_delta *tmp;
939 for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
940 if (tmp->offset < offset)
945 struct compat_ipt_standard_target
947 struct compat_xt_entry_target target;
948 compat_int_t verdict;
951 struct compat_ipt_standard
953 struct compat_ipt_entry entry;
954 struct compat_ipt_standard_target target;
957 #define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target))
958 #define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target))
959 #define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN)
961 static int compat_ipt_standard_fn(void *target,
962 void **dstptr, int *size, int convert)
964 struct compat_ipt_standard_target compat_st, *pcompat_st;
965 struct ipt_standard_target st, *pst;
972 memcpy(&compat_st.target, &pst->target,
973 sizeof(compat_st.target));
974 compat_st.verdict = pst->verdict;
975 if (compat_st.verdict > 0)
977 compat_calc_jump(compat_st.verdict);
978 compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN;
979 if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN))
981 *size -= IPT_ST_OFFSET;
982 *dstptr += IPT_ST_COMPAT_LEN;
984 case COMPAT_FROM_USER:
986 memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN);
987 st.verdict = pcompat_st->verdict;
989 st.verdict += compat_calc_jump(st.verdict);
990 st.target.u.user.target_size = IPT_ST_LEN;
991 memcpy(*dstptr, &st, IPT_ST_LEN);
992 *size += IPT_ST_OFFSET;
993 *dstptr += IPT_ST_LEN;
995 case COMPAT_CALC_SIZE:
996 *size += IPT_ST_OFFSET;
1006 compat_calc_match(struct ipt_entry_match *m, int * size)
1008 if (m->u.kernel.match->compat)
1009 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1011 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1015 static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
1016 void *base, struct xt_table_info *newinfo)
1018 struct ipt_entry_target *t;
1019 u_int16_t entry_offset;
1023 entry_offset = (void *)e - base;
1024 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1025 t = ipt_get_target(e);
1026 if (t->u.kernel.target->compat)
1027 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1029 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1030 newinfo->size -= off;
1031 ret = compat_add_offset(entry_offset, off);
1035 for (i = 0; i< NF_IP_NUMHOOKS; i++) {
1036 if (info->hook_entry[i] && (e < (struct ipt_entry *)
1037 (base + info->hook_entry[i])))
1038 newinfo->hook_entry[i] -= off;
1039 if (info->underflow[i] && (e < (struct ipt_entry *)
1040 (base + info->underflow[i])))
1041 newinfo->underflow[i] -= off;
1046 static int compat_table_info(struct xt_table_info *info,
1047 struct xt_table_info *newinfo)
1049 void *loc_cpu_entry;
1052 if (!newinfo || !info)
1055 memset(newinfo, 0, sizeof(struct xt_table_info));
1056 newinfo->size = info->size;
1057 newinfo->number = info->number;
1058 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1059 newinfo->hook_entry[i] = info->hook_entry[i];
1060 newinfo->underflow[i] = info->underflow[i];
1062 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1063 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1064 compat_calc_entry, info, loc_cpu_entry, newinfo);
1068 static int get_info(void __user *user, int *len, int compat)
1070 char name[IPT_TABLE_MAXNAMELEN];
1071 struct ipt_table *t;
1074 if (*len != sizeof(struct ipt_getinfo)) {
1075 duprintf("length %u != %u\n", *len,
1076 (unsigned int)sizeof(struct ipt_getinfo));
1080 if (copy_from_user(name, user, sizeof(name)) != 0)
1083 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1084 #ifdef CONFIG_COMPAT
1086 xt_compat_lock(AF_INET);
1088 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1089 "iptable_%s", name);
1090 if (t && !IS_ERR(t)) {
1091 struct ipt_getinfo info;
1092 struct xt_table_info *private = t->private;
1094 #ifdef CONFIG_COMPAT
1096 struct xt_table_info tmp;
1097 ret = compat_table_info(private, &tmp);
1098 compat_flush_offsets();
1102 info.valid_hooks = t->valid_hooks;
1103 memcpy(info.hook_entry, private->hook_entry,
1104 sizeof(info.hook_entry));
1105 memcpy(info.underflow, private->underflow,
1106 sizeof(info.underflow));
1107 info.num_entries = private->number;
1108 info.size = private->size;
1109 strcpy(info.name, name);
1111 if (copy_to_user(user, &info, *len) != 0)
1119 ret = t ? PTR_ERR(t) : -ENOENT;
1120 #ifdef CONFIG_COMPAT
1122 xt_compat_unlock(AF_INET);
1128 get_entries(struct ipt_get_entries __user *uptr, int *len)
1131 struct ipt_get_entries get;
1132 struct ipt_table *t;
1134 if (*len < sizeof(get)) {
1135 duprintf("get_entries: %u < %d\n", *len,
1136 (unsigned int)sizeof(get));
1139 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1141 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1142 duprintf("get_entries: %u != %u\n", *len,
1143 (unsigned int)(sizeof(struct ipt_get_entries) +
1148 t = xt_find_table_lock(AF_INET, get.name);
1149 if (t && !IS_ERR(t)) {
1150 struct xt_table_info *private = t->private;
1151 duprintf("t->private->number = %u\n",
1153 if (get.size == private->size)
1154 ret = copy_entries_to_user(private->size,
1155 t, uptr->entrytable);
1157 duprintf("get_entries: I've got %u not %u!\n",
1165 ret = t ? PTR_ERR(t) : -ENOENT;
1171 __do_replace(const char *name, unsigned int valid_hooks,
1172 struct xt_table_info *newinfo, unsigned int num_counters,
1173 void __user *counters_ptr)
1176 struct ipt_table *t;
1177 struct xt_table_info *oldinfo;
1178 struct xt_counters *counters;
1179 void *loc_cpu_old_entry;
1182 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1188 t = try_then_request_module(xt_find_table_lock(AF_INET, name),
1189 "iptable_%s", name);
1190 if (!t || IS_ERR(t)) {
1191 ret = t ? PTR_ERR(t) : -ENOENT;
1192 goto free_newinfo_counters_untrans;
1196 if (valid_hooks != t->valid_hooks) {
1197 duprintf("Valid hook crap: %08X vs %08X\n",
1198 valid_hooks, t->valid_hooks);
1203 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1207 /* Update module usage count based on number of rules */
1208 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1209 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1210 if ((oldinfo->number > oldinfo->initial_entries) ||
1211 (newinfo->number <= oldinfo->initial_entries))
1213 if ((oldinfo->number > oldinfo->initial_entries) &&
1214 (newinfo->number <= oldinfo->initial_entries))
1217 /* Get the old counters. */
1218 get_counters(oldinfo, counters);
1219 /* Decrease module usage counts and free resource */
1220 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1221 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1222 xt_free_table_info(oldinfo);
1223 if (copy_to_user(counters_ptr, counters,
1224 sizeof(struct xt_counters) * num_counters) != 0)
1233 free_newinfo_counters_untrans:
1240 do_replace(void __user *user, unsigned int len)
1243 struct ipt_replace tmp;
1244 struct xt_table_info *newinfo;
1245 void *loc_cpu_entry;
1247 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1250 /* Hack: Causes ipchains to give correct error msg --RR */
1251 if (len != sizeof(tmp) + tmp.size)
1252 return -ENOPROTOOPT;
1254 /* overflow check */
1255 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1258 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1261 newinfo = xt_alloc_table_info(tmp.size);
1265 /* choose the copy that is our node/cpu */
1266 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1267 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1273 ret = translate_table(tmp.name, tmp.valid_hooks,
1274 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1275 tmp.hook_entry, tmp.underflow);
1279 duprintf("ip_tables: Translated table\n");
1281 ret = __do_replace(tmp.name, tmp.valid_hooks,
1282 newinfo, tmp.num_counters,
1285 goto free_newinfo_untrans;
1288 free_newinfo_untrans:
1289 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1291 xt_free_table_info(newinfo);
1295 /* We're lazy, and add to the first CPU; overflow works its fey magic
1296 * and everything is OK. */
1298 add_counter_to_entry(struct ipt_entry *e,
1299 const struct xt_counters addme[],
1303 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1305 (long unsigned int)e->counters.pcnt,
1306 (long unsigned int)e->counters.bcnt,
1307 (long unsigned int)addme[*i].pcnt,
1308 (long unsigned int)addme[*i].bcnt);
1311 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1318 do_add_counters(void __user *user, unsigned int len, int compat)
1321 struct xt_counters_info tmp;
1322 struct xt_counters *paddc;
1323 unsigned int num_counters;
1327 struct ipt_table *t;
1328 struct xt_table_info *private;
1330 void *loc_cpu_entry;
1331 #ifdef CONFIG_COMPAT
1332 struct compat_xt_counters_info compat_tmp;
1336 size = sizeof(struct compat_xt_counters_info);
1341 size = sizeof(struct xt_counters_info);
1344 if (copy_from_user(ptmp, user, size) != 0)
1347 #ifdef CONFIG_COMPAT
1349 num_counters = compat_tmp.num_counters;
1350 name = compat_tmp.name;
1354 num_counters = tmp.num_counters;
1358 if (len != size + num_counters * sizeof(struct xt_counters))
1361 paddc = vmalloc_node(len - size, numa_node_id());
1365 if (copy_from_user(paddc, user + size, len - size) != 0) {
1370 t = xt_find_table_lock(AF_INET, name);
1371 if (!t || IS_ERR(t)) {
1372 ret = t ? PTR_ERR(t) : -ENOENT;
1376 write_lock_bh(&t->lock);
1377 private = t->private;
1378 if (private->number != num_counters) {
1380 goto unlock_up_free;
1384 /* Choose the copy that is on our node */
1385 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1386 IPT_ENTRY_ITERATE(loc_cpu_entry,
1388 add_counter_to_entry,
1392 write_unlock_bh(&t->lock);
1401 #ifdef CONFIG_COMPAT
1402 struct compat_ipt_replace {
1403 char name[IPT_TABLE_MAXNAMELEN];
1407 u32 hook_entry[NF_IP_NUMHOOKS];
1408 u32 underflow[NF_IP_NUMHOOKS];
1410 compat_uptr_t counters; /* struct ipt_counters * */
1411 struct compat_ipt_entry entries[0];
1414 static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
1415 void __user **dstptr, compat_uint_t *size)
1417 if (m->u.kernel.match->compat)
1418 return m->u.kernel.match->compat(m, dstptr, size,
1421 return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
1424 static int compat_copy_entry_to_user(struct ipt_entry *e,
1425 void __user **dstptr, compat_uint_t *size)
1427 struct ipt_entry_target __user *t;
1428 struct compat_ipt_entry __user *ce;
1429 u_int16_t target_offset, next_offset;
1430 compat_uint_t origsize;
1435 ce = (struct compat_ipt_entry __user *)*dstptr;
1436 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1439 *dstptr += sizeof(struct compat_ipt_entry);
1440 ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
1441 target_offset = e->target_offset - (origsize - *size);
1444 t = ipt_get_target(e);
1445 if (t->u.kernel.target->compat)
1446 ret = t->u.kernel.target->compat(t, dstptr, size,
1449 ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
1453 next_offset = e->next_offset - (origsize - *size);
1454 if (put_user(target_offset, &ce->target_offset))
1456 if (put_user(next_offset, &ce->next_offset))
1464 compat_check_calc_match(struct ipt_entry_match *m,
1466 const struct ipt_ip *ip,
1467 unsigned int hookmask,
1470 struct ipt_match *match;
1472 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1473 m->u.user.revision),
1474 "ipt_%s", m->u.user.name);
1475 if (IS_ERR(match) || !match) {
1476 duprintf("compat_check_calc_match: `%s' not found\n",
1478 return match ? PTR_ERR(match) : -ENOENT;
1480 m->u.kernel.match = match;
1482 if (m->u.kernel.match->compat)
1483 m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
1485 xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
1492 check_compat_entry_size_and_hooks(struct ipt_entry *e,
1493 struct xt_table_info *newinfo,
1495 unsigned char *base,
1496 unsigned char *limit,
1497 unsigned int *hook_entries,
1498 unsigned int *underflows,
1502 struct ipt_entry_target *t;
1503 struct ipt_target *target;
1504 u_int16_t entry_offset;
1507 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1508 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1509 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1510 duprintf("Bad offset %p, limit = %p\n", e, limit);
1514 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1515 sizeof(struct compat_xt_entry_target)) {
1516 duprintf("checking: element %p size %u\n",
1521 if (!ip_checkentry(&e->ip)) {
1522 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
1527 entry_offset = (void *)e - (void *)base;
1529 ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
1530 e->comefrom, &off, &j);
1532 goto cleanup_matches;
1534 t = ipt_get_target(e);
1535 target = try_then_request_module(xt_find_target(AF_INET,
1537 t->u.user.revision),
1538 "ipt_%s", t->u.user.name);
1539 if (IS_ERR(target) || !target) {
1540 duprintf("check_entry: `%s' not found\n", t->u.user.name);
1541 ret = target ? PTR_ERR(target) : -ENOENT;
1542 goto cleanup_matches;
1544 t->u.kernel.target = target;
1546 if (t->u.kernel.target->compat)
1547 t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
1549 xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
1551 ret = compat_add_offset(entry_offset, off);
1555 /* Check hooks & underflows */
1556 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1557 if ((unsigned char *)e - base == hook_entries[h])
1558 newinfo->hook_entry[h] = hook_entries[h];
1559 if ((unsigned char *)e - base == underflows[h])
1560 newinfo->underflow[h] = underflows[h];
1563 /* Clear counters and comefrom */
1564 e->counters = ((struct ipt_counters) { 0, 0 });
1571 module_put(t->u.kernel.target->me);
1573 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1577 static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
1578 void **dstptr, compat_uint_t *size, const char *name,
1579 const struct ipt_ip *ip, unsigned int hookmask, int *i)
1581 struct ipt_entry_match *dm;
1582 struct ipt_match *match;
1585 dm = (struct ipt_entry_match *)*dstptr;
1586 match = m->u.kernel.match;
1588 match->compat(m, dstptr, size, COMPAT_FROM_USER);
1590 xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
1592 ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
1593 name, hookmask, ip->proto,
1594 ip->invflags & IPT_INV_PROTO);
1598 if (m->u.kernel.match->checkentry
1599 && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
1601 duprintf("ip_tables: check failed for `%s'.\n",
1602 m->u.kernel.match->name);
1610 module_put(m->u.kernel.match->me);
1614 static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1615 unsigned int *size, const char *name,
1616 struct xt_table_info *newinfo, unsigned char *base)
1618 struct ipt_entry_target *t;
1619 struct ipt_target *target;
1620 struct ipt_entry *de;
1621 unsigned int origsize;
1626 de = (struct ipt_entry *)*dstptr;
1627 memcpy(de, e, sizeof(struct ipt_entry));
1630 *dstptr += sizeof(struct compat_ipt_entry);
1631 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
1632 name, &de->ip, de->comefrom, &j);
1634 goto cleanup_matches;
1635 de->target_offset = e->target_offset - (origsize - *size);
1636 t = ipt_get_target(e);
1637 target = t->u.kernel.target;
1639 target->compat(t, dstptr, size, COMPAT_FROM_USER);
1641 xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
1643 de->next_offset = e->next_offset - (origsize - *size);
1644 for (h = 0; h < NF_IP_NUMHOOKS; h++) {
1645 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1646 newinfo->hook_entry[h] -= origsize - *size;
1647 if ((unsigned char *)de - base < newinfo->underflow[h])
1648 newinfo->underflow[h] -= origsize - *size;
1651 t = ipt_get_target(de);
1652 target = t->u.kernel.target;
1653 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
1654 name, e->comefrom, e->ip.proto,
1655 e->ip.invflags & IPT_INV_PROTO);
1660 if (t->u.kernel.target == &ipt_standard_target) {
1661 if (!standard_check(t, *size))
1663 } else if (t->u.kernel.target->checkentry
1664 && !t->u.kernel.target->checkentry(name, de, target,
1665 t->data, de->comefrom)) {
1666 duprintf("ip_tables: compat: check failed for `%s'.\n",
1667 t->u.kernel.target->name);
1674 module_put(t->u.kernel.target->me);
1676 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1681 translate_compat_table(const char *name,
1682 unsigned int valid_hooks,
1683 struct xt_table_info **pinfo,
1685 unsigned int total_size,
1686 unsigned int number,
1687 unsigned int *hook_entries,
1688 unsigned int *underflows)
1691 struct xt_table_info *newinfo, *info;
1692 void *pos, *entry0, *entry1;
1699 info->number = number;
1701 /* Init all hooks to impossible value. */
1702 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1703 info->hook_entry[i] = 0xFFFFFFFF;
1704 info->underflow[i] = 0xFFFFFFFF;
1707 duprintf("translate_compat_table: size %u\n", info->size);
1709 xt_compat_lock(AF_INET);
1710 /* Walk through entries, checking offsets. */
1711 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1712 check_compat_entry_size_and_hooks,
1713 info, &size, entry0,
1714 entry0 + total_size,
1715 hook_entries, underflows, &i, name);
1721 duprintf("translate_compat_table: %u not %u entries\n",
1726 /* Check hooks all assigned */
1727 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1728 /* Only hooks which are valid */
1729 if (!(valid_hooks & (1 << i)))
1731 if (info->hook_entry[i] == 0xFFFFFFFF) {
1732 duprintf("Invalid hook entry %u %u\n",
1733 i, hook_entries[i]);
1736 if (info->underflow[i] == 0xFFFFFFFF) {
1737 duprintf("Invalid underflow %u %u\n",
1744 newinfo = xt_alloc_table_info(size);
1748 newinfo->number = number;
1749 for (i = 0; i < NF_IP_NUMHOOKS; i++) {
1750 newinfo->hook_entry[i] = info->hook_entry[i];
1751 newinfo->underflow[i] = info->underflow[i];
1753 entry1 = newinfo->entries[raw_smp_processor_id()];
1756 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1757 compat_copy_entry_from_user, &pos, &size,
1758 name, newinfo, entry1);
1759 compat_flush_offsets();
1760 xt_compat_unlock(AF_INET);
1765 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1768 /* And one copy for every other CPU */
1769 for_each_possible_cpu(i)
1770 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1771 memcpy(newinfo->entries[i], entry1, newinfo->size);
1775 xt_free_table_info(info);
1779 xt_free_table_info(newinfo);
1783 xt_compat_unlock(AF_INET);
1788 compat_do_replace(void __user *user, unsigned int len)
1791 struct compat_ipt_replace tmp;
1792 struct xt_table_info *newinfo;
1793 void *loc_cpu_entry;
1795 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1798 /* Hack: Causes ipchains to give correct error msg --RR */
1799 if (len != sizeof(tmp) + tmp.size)
1800 return -ENOPROTOOPT;
1802 /* overflow check */
1803 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
1806 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1809 newinfo = xt_alloc_table_info(tmp.size);
1813 /* choose the copy that is our node/cpu */
1814 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1815 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1821 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1822 &newinfo, &loc_cpu_entry, tmp.size,
1823 tmp.num_entries, tmp.hook_entry, tmp.underflow);
1827 duprintf("compat_do_replace: Translated table\n");
1829 ret = __do_replace(tmp.name, tmp.valid_hooks,
1830 newinfo, tmp.num_counters,
1831 compat_ptr(tmp.counters));
1833 goto free_newinfo_untrans;
1836 free_newinfo_untrans:
1837 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1839 xt_free_table_info(newinfo);
1844 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1849 if (!capable(CAP_NET_ADMIN))
1853 case IPT_SO_SET_REPLACE:
1854 ret = compat_do_replace(user, len);
1857 case IPT_SO_SET_ADD_COUNTERS:
1858 ret = do_add_counters(user, len, 1);
1862 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1869 struct compat_ipt_get_entries
1871 char name[IPT_TABLE_MAXNAMELEN];
1873 struct compat_ipt_entry entrytable[0];
1876 static int compat_copy_entries_to_user(unsigned int total_size,
1877 struct ipt_table *table, void __user *userptr)
1879 unsigned int off, num;
1880 struct compat_ipt_entry e;
1881 struct xt_counters *counters;
1882 struct xt_table_info *private = table->private;
1886 void *loc_cpu_entry;
1888 counters = alloc_counters(table);
1889 if (IS_ERR(counters))
1890 return PTR_ERR(counters);
1892 /* choose the copy that is on our node/cpu, ...
1893 * This choice is lazy (because current thread is
1894 * allowed to migrate to another cpu)
1896 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1899 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1900 compat_copy_entry_to_user, &pos, &size);
1904 /* ... then go back and fix counters and names */
1905 for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
1907 struct ipt_entry_match m;
1908 struct ipt_entry_target t;
1911 if (copy_from_user(&e, userptr + off,
1912 sizeof(struct compat_ipt_entry)))
1914 if (copy_to_user(userptr + off +
1915 offsetof(struct compat_ipt_entry, counters),
1916 &counters[num], sizeof(counters[num])))
1919 for (i = sizeof(struct compat_ipt_entry);
1920 i < e.target_offset; i += m.u.match_size) {
1921 if (copy_from_user(&m, userptr + off + i,
1922 sizeof(struct ipt_entry_match)))
1924 if (copy_to_user(userptr + off + i +
1925 offsetof(struct ipt_entry_match, u.user.name),
1926 m.u.kernel.match->name,
1927 strlen(m.u.kernel.match->name) + 1))
1931 if (copy_from_user(&t, userptr + off + e.target_offset,
1932 sizeof(struct ipt_entry_target)))
1934 if (copy_to_user(userptr + off + e.target_offset +
1935 offsetof(struct ipt_entry_target, u.user.name),
1936 t.u.kernel.target->name,
1937 strlen(t.u.kernel.target->name) + 1))
1947 compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
1950 struct compat_ipt_get_entries get;
1951 struct ipt_table *t;
1954 if (*len < sizeof(get)) {
1955 duprintf("compat_get_entries: %u < %u\n",
1956 *len, (unsigned int)sizeof(get));
1960 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1963 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1964 duprintf("compat_get_entries: %u != %u\n", *len,
1965 (unsigned int)(sizeof(struct compat_ipt_get_entries) +
1970 xt_compat_lock(AF_INET);
1971 t = xt_find_table_lock(AF_INET, get.name);
1972 if (t && !IS_ERR(t)) {
1973 struct xt_table_info *private = t->private;
1974 struct xt_table_info info;
1975 duprintf("t->private->number = %u\n",
1977 ret = compat_table_info(private, &info);
1978 if (!ret && get.size == info.size) {
1979 ret = compat_copy_entries_to_user(private->size,
1980 t, uptr->entrytable);
1982 duprintf("compat_get_entries: I've got %u not %u!\n",
1987 compat_flush_offsets();
1991 ret = t ? PTR_ERR(t) : -ENOENT;
1993 xt_compat_unlock(AF_INET);
1998 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2003 case IPT_SO_GET_INFO:
2004 ret = get_info(user, len, 1);
2006 case IPT_SO_GET_ENTRIES:
2007 ret = compat_get_entries(user, len);
2010 duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
2018 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2022 if (!capable(CAP_NET_ADMIN))
2026 case IPT_SO_SET_REPLACE:
2027 ret = do_replace(user, len);
2030 case IPT_SO_SET_ADD_COUNTERS:
2031 ret = do_add_counters(user, len, 0);
2035 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2043 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2047 if (!capable(CAP_NET_ADMIN))
2051 case IPT_SO_GET_INFO:
2052 ret = get_info(user, len, 0);
2055 case IPT_SO_GET_ENTRIES:
2056 ret = get_entries(user, len);
2059 case IPT_SO_GET_REVISION_MATCH:
2060 case IPT_SO_GET_REVISION_TARGET: {
2061 struct ipt_get_revision rev;
2064 if (*len != sizeof(rev)) {
2068 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2073 if (cmd == IPT_SO_GET_REVISION_TARGET)
2078 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2081 "ipt_%s", rev.name);
2086 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2093 int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
2096 struct xt_table_info *newinfo;
2097 static struct xt_table_info bootstrap
2098 = { 0, 0, 0, { 0 }, { 0 }, { } };
2099 void *loc_cpu_entry;
2101 newinfo = xt_alloc_table_info(repl->size);
2105 /* choose the copy on our node/cpu
2106 * but dont care of preemption
2108 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2109 memcpy(loc_cpu_entry, repl->entries, repl->size);
2111 ret = translate_table(table->name, table->valid_hooks,
2112 newinfo, loc_cpu_entry, repl->size,
2117 xt_free_table_info(newinfo);
2121 ret = xt_register_table(table, &bootstrap, newinfo);
2123 xt_free_table_info(newinfo);
2130 void ipt_unregister_table(struct ipt_table *table)
2132 struct xt_table_info *private;
2133 void *loc_cpu_entry;
2135 private = xt_unregister_table(table);
2137 /* Decrease module usage counts and free resources */
2138 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2139 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2140 xt_free_table_info(private);
2143 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2145 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2146 u_int8_t type, u_int8_t code,
2149 return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
2154 icmp_match(const struct sk_buff *skb,
2155 const struct net_device *in,
2156 const struct net_device *out,
2157 const struct xt_match *match,
2158 const void *matchinfo,
2160 unsigned int protoff,
2163 struct icmphdr _icmph, *ic;
2164 const struct ipt_icmp *icmpinfo = matchinfo;
2166 /* Must not be a fragment. */
2170 ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
2172 /* We've been asked to examine this packet, and we
2173 * can't. Hence, no choice but to drop.
2175 duprintf("Dropping evil ICMP tinygram.\n");
2180 return icmp_type_code_match(icmpinfo->type,
2184 !!(icmpinfo->invflags&IPT_ICMP_INV));
2187 /* Called when user tries to insert an entry of this type. */
2189 icmp_checkentry(const char *tablename,
2191 const struct xt_match *match,
2193 unsigned int hook_mask)
2195 const struct ipt_icmp *icmpinfo = matchinfo;
2197 /* Must specify no unknown invflags */
2198 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2201 /* The built-in targets: standard (NULL) and error. */
2202 static struct ipt_target ipt_standard_target = {
2203 .name = IPT_STANDARD_TARGET,
2204 .targetsize = sizeof(int),
2206 #ifdef CONFIG_COMPAT
2207 .compat = &compat_ipt_standard_fn,
2211 static struct ipt_target ipt_error_target = {
2212 .name = IPT_ERROR_TARGET,
2213 .target = ipt_error,
2214 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2218 static struct nf_sockopt_ops ipt_sockopts = {
2220 .set_optmin = IPT_BASE_CTL,
2221 .set_optmax = IPT_SO_SET_MAX+1,
2222 .set = do_ipt_set_ctl,
2223 #ifdef CONFIG_COMPAT
2224 .compat_set = compat_do_ipt_set_ctl,
2226 .get_optmin = IPT_BASE_CTL,
2227 .get_optmax = IPT_SO_GET_MAX+1,
2228 .get = do_ipt_get_ctl,
2229 #ifdef CONFIG_COMPAT
2230 .compat_get = compat_do_ipt_get_ctl,
2234 static struct ipt_match icmp_matchstruct = {
2236 .match = icmp_match,
2237 .matchsize = sizeof(struct ipt_icmp),
2238 .proto = IPPROTO_ICMP,
2240 .checkentry = icmp_checkentry,
2243 static int __init ip_tables_init(void)
2247 ret = xt_proto_init(AF_INET);
2251 /* Noone else will be downing sem now, so we won't sleep */
2252 ret = xt_register_target(&ipt_standard_target);
2255 ret = xt_register_target(&ipt_error_target);
2258 ret = xt_register_match(&icmp_matchstruct);
2262 /* Register setsockopt */
2263 ret = nf_register_sockopt(&ipt_sockopts);
2267 printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2271 xt_unregister_match(&icmp_matchstruct);
2273 xt_unregister_target(&ipt_error_target);
2275 xt_unregister_target(&ipt_standard_target);
2277 xt_proto_fini(AF_INET);
2282 static void __exit ip_tables_fini(void)
2284 nf_unregister_sockopt(&ipt_sockopts);
2286 xt_unregister_match(&icmp_matchstruct);
2287 xt_unregister_target(&ipt_error_target);
2288 xt_unregister_target(&ipt_standard_target);
2290 xt_proto_fini(AF_INET);
2293 EXPORT_SYMBOL(ipt_register_table);
2294 EXPORT_SYMBOL(ipt_unregister_table);
2295 EXPORT_SYMBOL(ipt_do_table);
2296 module_init(ip_tables_init);
2297 module_exit(ip_tables_fini);