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 #include <linux/cache.h>
12 #include <linux/capability.h>
13 #include <linux/skbuff.h>
14 #include <linux/kmod.h>
15 #include <linux/vmalloc.h>
16 #include <linux/netdevice.h>
17 #include <linux/module.h>
18 #include <linux/icmp.h>
20 #include <net/compat.h>
21 #include <asm/uaccess.h>
22 #include <linux/mutex.h>
23 #include <linux/proc_fs.h>
24 #include <linux/err.h>
25 #include <linux/cpumask.h>
27 #include <linux/netfilter/x_tables.h>
28 #include <linux/netfilter_ipv4/ip_tables.h>
29 #include <net/netfilter/nf_log.h>
31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
33 MODULE_DESCRIPTION("IPv4 packet filter");
35 /*#define DEBUG_IP_FIREWALL*/
36 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
37 /*#define DEBUG_IP_FIREWALL_USER*/
39 #ifdef DEBUG_IP_FIREWALL
40 #define dprintf(format, args...) printk(format , ## args)
42 #define dprintf(format, args...)
45 #ifdef DEBUG_IP_FIREWALL_USER
46 #define duprintf(format, args...) printk(format , ## args)
48 #define duprintf(format, args...)
51 #ifdef CONFIG_NETFILTER_DEBUG
52 #define IP_NF_ASSERT(x) \
55 printk("IP_NF_ASSERT: %s:%s:%u\n", \
56 __func__, __FILE__, __LINE__); \
59 #define IP_NF_ASSERT(x)
63 /* All the better to debug you with... */
69 We keep a set of rules for each CPU, so we can avoid write-locking
70 them in the softirq when updating the counters and therefore
71 only need to read-lock in the softirq; doing a write_lock_bh() in user
72 context stops packets coming through and allows user context to read
73 the counters or update the rules.
75 Hence the start of any table is given by get_table() below. */
77 /* Returns whether matches rule or not. */
78 /* Performance critical - called for every packet */
80 ip_packet_match(const struct iphdr *ip,
83 const struct ipt_ip *ipinfo,
89 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
91 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
93 || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
95 dprintf("Source or dest mismatch.\n");
97 dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
99 NIPQUAD(ipinfo->smsk.s_addr),
100 NIPQUAD(ipinfo->src.s_addr),
101 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
102 dprintf("DST: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
104 NIPQUAD(ipinfo->dmsk.s_addr),
105 NIPQUAD(ipinfo->dst.s_addr),
106 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
110 /* Look for ifname matches; this should unroll nicely. */
111 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
112 ret |= (((const unsigned long *)indev)[i]
113 ^ ((const unsigned long *)ipinfo->iniface)[i])
114 & ((const unsigned long *)ipinfo->iniface_mask)[i];
117 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
118 dprintf("VIA in mismatch (%s vs %s).%s\n",
119 indev, ipinfo->iniface,
120 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
124 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
125 ret |= (((const unsigned long *)outdev)[i]
126 ^ ((const unsigned long *)ipinfo->outiface)[i])
127 & ((const unsigned long *)ipinfo->outiface_mask)[i];
130 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
131 dprintf("VIA out mismatch (%s vs %s).%s\n",
132 outdev, ipinfo->outiface,
133 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
137 /* Check specific protocol */
139 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
140 dprintf("Packet protocol %hi does not match %hi.%s\n",
141 ip->protocol, ipinfo->proto,
142 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
146 /* If we have a fragment rule but the packet is not a fragment
147 * then we return zero */
148 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
149 dprintf("Fragment rule but not fragment.%s\n",
150 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
158 ip_checkentry(const struct ipt_ip *ip)
160 if (ip->flags & ~IPT_F_MASK) {
161 duprintf("Unknown flag bits set: %08X\n",
162 ip->flags & ~IPT_F_MASK);
165 if (ip->invflags & ~IPT_INV_MASK) {
166 duprintf("Unknown invflag bits set: %08X\n",
167 ip->invflags & ~IPT_INV_MASK);
174 ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
177 printk("ip_tables: error: `%s'\n",
178 (const char *)par->targinfo);
183 /* Performance critical - called for every packet */
185 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
186 struct xt_match_param *par)
188 par->match = m->u.kernel.match;
189 par->matchinfo = m->data;
191 /* Stop iteration if it doesn't match */
192 if (!m->u.kernel.match->match(skb, par))
198 /* Performance critical */
199 static inline struct ipt_entry *
200 get_entry(void *base, unsigned int offset)
202 return (struct ipt_entry *)(base + offset);
205 /* All zeroes == unconditional rule. */
206 /* Mildly perf critical (only if packet tracing is on) */
208 unconditional(const struct ipt_ip *ip)
212 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
213 if (((__u32 *)ip)[i])
220 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
221 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
222 static const char *const hooknames[] = {
223 [NF_INET_PRE_ROUTING] = "PREROUTING",
224 [NF_INET_LOCAL_IN] = "INPUT",
225 [NF_INET_FORWARD] = "FORWARD",
226 [NF_INET_LOCAL_OUT] = "OUTPUT",
227 [NF_INET_POST_ROUTING] = "POSTROUTING",
230 enum nf_ip_trace_comments {
231 NF_IP_TRACE_COMMENT_RULE,
232 NF_IP_TRACE_COMMENT_RETURN,
233 NF_IP_TRACE_COMMENT_POLICY,
236 static const char *const comments[] = {
237 [NF_IP_TRACE_COMMENT_RULE] = "rule",
238 [NF_IP_TRACE_COMMENT_RETURN] = "return",
239 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
242 static struct nf_loginfo trace_loginfo = {
243 .type = NF_LOG_TYPE_LOG,
247 .logflags = NF_LOG_MASK,
252 /* Mildly perf critical (only if packet tracing is on) */
254 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
255 char *hookname, char **chainname,
256 char **comment, unsigned int *rulenum)
258 struct ipt_standard_target *t = (void *)ipt_get_target(s);
260 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
261 /* Head of user chain: ERROR target with chainname */
262 *chainname = t->target.data;
267 if (s->target_offset == sizeof(struct ipt_entry)
268 && strcmp(t->target.u.kernel.target->name,
269 IPT_STANDARD_TARGET) == 0
271 && unconditional(&s->ip)) {
272 /* Tail of chains: STANDARD target (return/policy) */
273 *comment = *chainname == hookname
274 ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
275 : (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
284 static void trace_packet(struct sk_buff *skb,
286 const struct net_device *in,
287 const struct net_device *out,
288 const char *tablename,
289 struct xt_table_info *private,
293 const struct ipt_entry *root;
294 char *hookname, *chainname, *comment;
295 unsigned int rulenum = 0;
297 table_base = (void *)private->entries[smp_processor_id()];
298 root = get_entry(table_base, private->hook_entry[hook]);
300 hookname = chainname = (char *)hooknames[hook];
301 comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
303 IPT_ENTRY_ITERATE(root,
304 private->size - private->hook_entry[hook],
305 get_chainname_rulenum,
306 e, hookname, &chainname, &comment, &rulenum);
308 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
309 "TRACE: %s:%s:%s:%u ",
310 tablename, chainname, comment, rulenum);
314 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
316 ipt_do_table(struct sk_buff *skb,
318 const struct net_device *in,
319 const struct net_device *out,
320 struct xt_table *table)
322 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
323 const struct iphdr *ip;
325 bool hotdrop = false;
326 /* Initializing verdict to NF_DROP keeps gcc happy. */
327 unsigned int verdict = NF_DROP;
328 const char *indev, *outdev;
330 struct ipt_entry *e, *back;
331 struct xt_table_info *private;
332 struct xt_match_param mtpar;
333 struct xt_target_param tgpar;
337 datalen = skb->len - ip->ihl * 4;
338 indev = in ? in->name : nulldevname;
339 outdev = out ? out->name : nulldevname;
340 /* We handle fragments by dealing with the first fragment as
341 * if it was a normal packet. All other fragments are treated
342 * normally, except that they will NEVER match rules that ask
343 * things we don't know, ie. tcp syn flag or ports). If the
344 * rule is also a fragment-specific rule, non-fragments won't
346 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
347 mtpar.thoff = ip_hdrlen(skb);
348 mtpar.hotdrop = &hotdrop;
349 mtpar.in = tgpar.in = in;
350 mtpar.out = tgpar.out = out;
351 mtpar.family = tgpar.family = NFPROTO_IPV4;
352 tgpar.hooknum = hook;
354 read_lock_bh(&table->lock);
355 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
356 private = table->private;
357 table_base = (void *)private->entries[smp_processor_id()];
358 e = get_entry(table_base, private->hook_entry[hook]);
360 /* For return from builtin chain */
361 back = get_entry(table_base, private->underflow[hook]);
366 if (ip_packet_match(ip, indev, outdev,
367 &e->ip, mtpar.fragoff)) {
368 struct ipt_entry_target *t;
370 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
373 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
375 t = ipt_get_target(e);
376 IP_NF_ASSERT(t->u.kernel.target);
378 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
379 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
380 /* The packet is traced: log it */
381 if (unlikely(skb->nf_trace))
382 trace_packet(skb, hook, in, out,
383 table->name, private, e);
385 /* Standard target? */
386 if (!t->u.kernel.target->target) {
389 v = ((struct ipt_standard_target *)t)->verdict;
391 /* Pop from stack? */
392 if (v != IPT_RETURN) {
393 verdict = (unsigned)(-v) - 1;
397 back = get_entry(table_base,
401 if (table_base + v != (void *)e + e->next_offset
402 && !(e->ip.flags & IPT_F_GOTO)) {
403 /* Save old back ptr in next entry */
404 struct ipt_entry *next
405 = (void *)e + e->next_offset;
407 = (void *)back - table_base;
408 /* set back pointer to next entry */
412 e = get_entry(table_base, v);
414 /* Targets which reenter must return
416 tgpar.target = t->u.kernel.target;
417 tgpar.targinfo = t->data;
418 #ifdef CONFIG_NETFILTER_DEBUG
419 ((struct ipt_entry *)table_base)->comefrom
422 verdict = t->u.kernel.target->target(skb,
424 #ifdef CONFIG_NETFILTER_DEBUG
425 if (((struct ipt_entry *)table_base)->comefrom
427 && verdict == IPT_CONTINUE) {
428 printk("Target %s reentered!\n",
429 t->u.kernel.target->name);
432 ((struct ipt_entry *)table_base)->comefrom
435 /* Target might have changed stuff. */
437 datalen = skb->len - ip->ihl * 4;
439 if (verdict == IPT_CONTINUE)
440 e = (void *)e + e->next_offset;
448 e = (void *)e + e->next_offset;
452 read_unlock_bh(&table->lock);
454 #ifdef DEBUG_ALLOW_ALL
463 /* Figures out from what hook each rule can be called: returns 0 if
464 there are loops. Puts hook bitmask in comefrom. */
466 mark_source_chains(struct xt_table_info *newinfo,
467 unsigned int valid_hooks, void *entry0)
471 /* No recursion; use packet counter to save back ptrs (reset
472 to 0 as we leave), and comefrom to save source hook bitmask */
473 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
474 unsigned int pos = newinfo->hook_entry[hook];
475 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
477 if (!(valid_hooks & (1 << hook)))
480 /* Set initial back pointer. */
481 e->counters.pcnt = pos;
484 struct ipt_standard_target *t
485 = (void *)ipt_get_target(e);
486 int visited = e->comefrom & (1 << hook);
488 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
489 printk("iptables: loop hook %u pos %u %08X.\n",
490 hook, pos, e->comefrom);
493 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
495 /* Unconditional return/END. */
496 if ((e->target_offset == sizeof(struct ipt_entry)
497 && (strcmp(t->target.u.user.name,
498 IPT_STANDARD_TARGET) == 0)
500 && unconditional(&e->ip)) || visited) {
501 unsigned int oldpos, size;
503 if (t->verdict < -NF_MAX_VERDICT - 1) {
504 duprintf("mark_source_chains: bad "
505 "negative verdict (%i)\n",
510 /* Return: backtrack through the last
513 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
514 #ifdef DEBUG_IP_FIREWALL_USER
516 & (1 << NF_INET_NUMHOOKS)) {
517 duprintf("Back unset "
524 pos = e->counters.pcnt;
525 e->counters.pcnt = 0;
527 /* We're at the start. */
531 e = (struct ipt_entry *)
533 } while (oldpos == pos + e->next_offset);
536 size = e->next_offset;
537 e = (struct ipt_entry *)
538 (entry0 + pos + size);
539 e->counters.pcnt = pos;
542 int newpos = t->verdict;
544 if (strcmp(t->target.u.user.name,
545 IPT_STANDARD_TARGET) == 0
547 if (newpos > newinfo->size -
548 sizeof(struct ipt_entry)) {
549 duprintf("mark_source_chains: "
550 "bad verdict (%i)\n",
554 /* This a jump; chase it. */
555 duprintf("Jump rule %u -> %u\n",
558 /* ... this is a fallthru */
559 newpos = pos + e->next_offset;
561 e = (struct ipt_entry *)
563 e->counters.pcnt = pos;
568 duprintf("Finished chain %u\n", hook);
574 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
576 struct xt_mtdtor_param par;
578 if (i && (*i)-- == 0)
581 par.match = m->u.kernel.match;
582 par.matchinfo = m->data;
583 par.family = NFPROTO_IPV4;
584 if (par.match->destroy != NULL)
585 par.match->destroy(&par);
586 module_put(par.match->me);
591 check_entry(struct ipt_entry *e, const char *name)
593 struct ipt_entry_target *t;
595 if (!ip_checkentry(&e->ip)) {
596 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
600 if (e->target_offset + sizeof(struct ipt_entry_target) >
604 t = ipt_get_target(e);
605 if (e->target_offset + t->u.target_size > e->next_offset)
612 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
615 const struct ipt_ip *ip = par->entryinfo;
618 par->match = m->u.kernel.match;
619 par->matchinfo = m->data;
621 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
622 ip->proto, ip->invflags & IPT_INV_PROTO);
624 duprintf("ip_tables: check failed for `%s'.\n",
633 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
636 struct xt_match *match;
639 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
641 "ipt_%s", m->u.user.name);
642 if (IS_ERR(match) || !match) {
643 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
644 return match ? PTR_ERR(match) : -ENOENT;
646 m->u.kernel.match = match;
648 ret = check_match(m, par, i);
654 module_put(m->u.kernel.match->me);
658 static int check_target(struct ipt_entry *e, const char *name)
660 struct ipt_entry_target *t = ipt_get_target(e);
661 struct xt_tgchk_param par = {
664 .target = t->u.kernel.target,
666 .hook_mask = e->comefrom,
667 .family = NFPROTO_IPV4,
671 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
672 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
674 duprintf("ip_tables: check failed for `%s'.\n",
675 t->u.kernel.target->name);
682 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
685 struct ipt_entry_target *t;
686 struct xt_target *target;
689 struct xt_mtchk_param mtpar;
691 ret = check_entry(e, name);
697 mtpar.entryinfo = &e->ip;
698 mtpar.hook_mask = e->comefrom;
699 mtpar.family = NFPROTO_IPV4;
700 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
702 goto cleanup_matches;
704 t = ipt_get_target(e);
705 target = try_then_request_module(xt_find_target(AF_INET,
708 "ipt_%s", t->u.user.name);
709 if (IS_ERR(target) || !target) {
710 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
711 ret = target ? PTR_ERR(target) : -ENOENT;
712 goto cleanup_matches;
714 t->u.kernel.target = target;
716 ret = check_target(e, name);
723 module_put(t->u.kernel.target->me);
725 IPT_MATCH_ITERATE(e, cleanup_match, &j);
730 check_entry_size_and_hooks(struct ipt_entry *e,
731 struct xt_table_info *newinfo,
733 unsigned char *limit,
734 const unsigned int *hook_entries,
735 const unsigned int *underflows,
740 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
741 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
742 duprintf("Bad offset %p\n", e);
747 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
748 duprintf("checking: element %p size %u\n",
753 /* Check hooks & underflows */
754 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
755 if ((unsigned char *)e - base == hook_entries[h])
756 newinfo->hook_entry[h] = hook_entries[h];
757 if ((unsigned char *)e - base == underflows[h])
758 newinfo->underflow[h] = underflows[h];
761 /* FIXME: underflows must be unconditional, standard verdicts
762 < 0 (not IPT_RETURN). --RR */
764 /* Clear counters and comefrom */
765 e->counters = ((struct xt_counters) { 0, 0 });
773 cleanup_entry(struct ipt_entry *e, unsigned int *i)
775 struct xt_tgdtor_param par;
776 struct ipt_entry_target *t;
778 if (i && (*i)-- == 0)
781 /* Cleanup all matches */
782 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
783 t = ipt_get_target(e);
785 par.target = t->u.kernel.target;
786 par.targinfo = t->data;
787 par.family = NFPROTO_IPV4;
788 if (par.target->destroy != NULL)
789 par.target->destroy(&par);
790 module_put(par.target->me);
794 /* Checks and translates the user-supplied table segment (held in
797 translate_table(const char *name,
798 unsigned int valid_hooks,
799 struct xt_table_info *newinfo,
803 const unsigned int *hook_entries,
804 const unsigned int *underflows)
809 newinfo->size = size;
810 newinfo->number = number;
812 /* Init all hooks to impossible value. */
813 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
814 newinfo->hook_entry[i] = 0xFFFFFFFF;
815 newinfo->underflow[i] = 0xFFFFFFFF;
818 duprintf("translate_table: size %u\n", newinfo->size);
820 /* Walk through entries, checking offsets. */
821 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
822 check_entry_size_and_hooks,
826 hook_entries, underflows, &i);
831 duprintf("translate_table: %u not %u entries\n",
836 /* Check hooks all assigned */
837 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
838 /* Only hooks which are valid */
839 if (!(valid_hooks & (1 << i)))
841 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
842 duprintf("Invalid hook entry %u %u\n",
846 if (newinfo->underflow[i] == 0xFFFFFFFF) {
847 duprintf("Invalid underflow %u %u\n",
853 if (!mark_source_chains(newinfo, valid_hooks, entry0))
856 /* Finally, each sanity check must pass */
858 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
859 find_check_entry, name, size, &i);
862 IPT_ENTRY_ITERATE(entry0, newinfo->size,
867 /* And one copy for every other CPU */
868 for_each_possible_cpu(i) {
869 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
870 memcpy(newinfo->entries[i], entry0, newinfo->size);
878 add_entry_to_counter(const struct ipt_entry *e,
879 struct xt_counters total[],
882 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
889 set_entry_to_counter(const struct ipt_entry *e,
890 struct ipt_counters total[],
893 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
900 get_counters(const struct xt_table_info *t,
901 struct xt_counters counters[])
907 /* Instead of clearing (by a previous call to memset())
908 * the counters and using adds, we set the counters
909 * with data used by 'current' CPU
910 * We dont care about preemption here.
912 curcpu = raw_smp_processor_id();
915 IPT_ENTRY_ITERATE(t->entries[curcpu],
917 set_entry_to_counter,
921 for_each_possible_cpu(cpu) {
925 IPT_ENTRY_ITERATE(t->entries[cpu],
927 add_entry_to_counter,
933 static struct xt_counters * alloc_counters(struct xt_table *table)
935 unsigned int countersize;
936 struct xt_counters *counters;
937 const struct xt_table_info *private = table->private;
939 /* We need atomic snapshot of counters: rest doesn't change
940 (other than comefrom, which userspace doesn't care
942 countersize = sizeof(struct xt_counters) * private->number;
943 counters = vmalloc_node(countersize, numa_node_id());
945 if (counters == NULL)
946 return ERR_PTR(-ENOMEM);
948 /* First, sum counters... */
949 write_lock_bh(&table->lock);
950 get_counters(private, counters);
951 write_unlock_bh(&table->lock);
957 copy_entries_to_user(unsigned int total_size,
958 struct xt_table *table,
959 void __user *userptr)
961 unsigned int off, num;
963 struct xt_counters *counters;
964 const struct xt_table_info *private = table->private;
966 const void *loc_cpu_entry;
968 counters = alloc_counters(table);
969 if (IS_ERR(counters))
970 return PTR_ERR(counters);
972 /* choose the copy that is on our node/cpu, ...
973 * This choice is lazy (because current thread is
974 * allowed to migrate to another cpu)
976 loc_cpu_entry = private->entries[raw_smp_processor_id()];
977 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
982 /* FIXME: use iterator macros --RR */
983 /* ... then go back and fix counters and names */
984 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
986 const struct ipt_entry_match *m;
987 const struct ipt_entry_target *t;
989 e = (struct ipt_entry *)(loc_cpu_entry + off);
990 if (copy_to_user(userptr + off
991 + offsetof(struct ipt_entry, counters),
993 sizeof(counters[num])) != 0) {
998 for (i = sizeof(struct ipt_entry);
999 i < e->target_offset;
1000 i += m->u.match_size) {
1003 if (copy_to_user(userptr + off + i
1004 + offsetof(struct ipt_entry_match,
1006 m->u.kernel.match->name,
1007 strlen(m->u.kernel.match->name)+1)
1014 t = ipt_get_target(e);
1015 if (copy_to_user(userptr + off + e->target_offset
1016 + offsetof(struct ipt_entry_target,
1018 t->u.kernel.target->name,
1019 strlen(t->u.kernel.target->name)+1) != 0) {
1030 #ifdef CONFIG_COMPAT
1031 static void compat_standard_from_user(void *dst, void *src)
1033 int v = *(compat_int_t *)src;
1036 v += xt_compat_calc_jump(AF_INET, v);
1037 memcpy(dst, &v, sizeof(v));
1040 static int compat_standard_to_user(void __user *dst, void *src)
1042 compat_int_t cv = *(int *)src;
1045 cv -= xt_compat_calc_jump(AF_INET, cv);
1046 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1050 compat_calc_match(struct ipt_entry_match *m, int *size)
1052 *size += xt_compat_match_offset(m->u.kernel.match);
1056 static int compat_calc_entry(struct ipt_entry *e,
1057 const struct xt_table_info *info,
1058 void *base, struct xt_table_info *newinfo)
1060 struct ipt_entry_target *t;
1061 unsigned int entry_offset;
1064 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1065 entry_offset = (void *)e - base;
1066 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1067 t = ipt_get_target(e);
1068 off += xt_compat_target_offset(t->u.kernel.target);
1069 newinfo->size -= off;
1070 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1074 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1075 if (info->hook_entry[i] &&
1076 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1077 newinfo->hook_entry[i] -= off;
1078 if (info->underflow[i] &&
1079 (e < (struct ipt_entry *)(base + info->underflow[i])))
1080 newinfo->underflow[i] -= off;
1085 static int compat_table_info(const struct xt_table_info *info,
1086 struct xt_table_info *newinfo)
1088 void *loc_cpu_entry;
1090 if (!newinfo || !info)
1093 /* we dont care about newinfo->entries[] */
1094 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1095 newinfo->initial_entries = 0;
1096 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1097 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1098 compat_calc_entry, info, loc_cpu_entry,
1103 static int get_info(struct net *net, void __user *user, int *len, int compat)
1105 char name[IPT_TABLE_MAXNAMELEN];
1109 if (*len != sizeof(struct ipt_getinfo)) {
1110 duprintf("length %u != %zu\n", *len,
1111 sizeof(struct ipt_getinfo));
1115 if (copy_from_user(name, user, sizeof(name)) != 0)
1118 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1119 #ifdef CONFIG_COMPAT
1121 xt_compat_lock(AF_INET);
1123 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1124 "iptable_%s", name);
1125 if (t && !IS_ERR(t)) {
1126 struct ipt_getinfo info;
1127 const struct xt_table_info *private = t->private;
1129 #ifdef CONFIG_COMPAT
1131 struct xt_table_info tmp;
1132 ret = compat_table_info(private, &tmp);
1133 xt_compat_flush_offsets(AF_INET);
1137 info.valid_hooks = t->valid_hooks;
1138 memcpy(info.hook_entry, private->hook_entry,
1139 sizeof(info.hook_entry));
1140 memcpy(info.underflow, private->underflow,
1141 sizeof(info.underflow));
1142 info.num_entries = private->number;
1143 info.size = private->size;
1144 strcpy(info.name, name);
1146 if (copy_to_user(user, &info, *len) != 0)
1154 ret = t ? PTR_ERR(t) : -ENOENT;
1155 #ifdef CONFIG_COMPAT
1157 xt_compat_unlock(AF_INET);
1163 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1166 struct ipt_get_entries get;
1169 if (*len < sizeof(get)) {
1170 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1173 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1175 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1176 duprintf("get_entries: %u != %zu\n",
1177 *len, sizeof(get) + get.size);
1181 t = xt_find_table_lock(net, AF_INET, get.name);
1182 if (t && !IS_ERR(t)) {
1183 const struct xt_table_info *private = t->private;
1184 duprintf("t->private->number = %u\n", private->number);
1185 if (get.size == private->size)
1186 ret = copy_entries_to_user(private->size,
1187 t, uptr->entrytable);
1189 duprintf("get_entries: I've got %u not %u!\n",
1190 private->size, get.size);
1196 ret = t ? PTR_ERR(t) : -ENOENT;
1202 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1203 struct xt_table_info *newinfo, unsigned int num_counters,
1204 void __user *counters_ptr)
1208 struct xt_table_info *oldinfo;
1209 struct xt_counters *counters;
1210 void *loc_cpu_old_entry;
1213 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1219 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1220 "iptable_%s", name);
1221 if (!t || IS_ERR(t)) {
1222 ret = t ? PTR_ERR(t) : -ENOENT;
1223 goto free_newinfo_counters_untrans;
1227 if (valid_hooks != t->valid_hooks) {
1228 duprintf("Valid hook crap: %08X vs %08X\n",
1229 valid_hooks, t->valid_hooks);
1234 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1238 /* Update module usage count based on number of rules */
1239 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1240 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1241 if ((oldinfo->number > oldinfo->initial_entries) ||
1242 (newinfo->number <= oldinfo->initial_entries))
1244 if ((oldinfo->number > oldinfo->initial_entries) &&
1245 (newinfo->number <= oldinfo->initial_entries))
1248 /* Get the old counters. */
1249 get_counters(oldinfo, counters);
1250 /* Decrease module usage counts and free resource */
1251 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1252 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1254 xt_free_table_info(oldinfo);
1255 if (copy_to_user(counters_ptr, counters,
1256 sizeof(struct xt_counters) * num_counters) != 0)
1265 free_newinfo_counters_untrans:
1272 do_replace(struct net *net, void __user *user, unsigned int len)
1275 struct ipt_replace tmp;
1276 struct xt_table_info *newinfo;
1277 void *loc_cpu_entry;
1279 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1282 /* overflow check */
1283 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1286 newinfo = xt_alloc_table_info(tmp.size);
1290 /* choose the copy that is on our node/cpu */
1291 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1292 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1298 ret = translate_table(tmp.name, tmp.valid_hooks,
1299 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1300 tmp.hook_entry, tmp.underflow);
1304 duprintf("ip_tables: Translated table\n");
1306 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1307 tmp.num_counters, tmp.counters);
1309 goto free_newinfo_untrans;
1312 free_newinfo_untrans:
1313 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1315 xt_free_table_info(newinfo);
1319 /* We're lazy, and add to the first CPU; overflow works its fey magic
1320 * and everything is OK. */
1322 add_counter_to_entry(struct ipt_entry *e,
1323 const struct xt_counters addme[],
1327 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1329 (long unsigned int)e->counters.pcnt,
1330 (long unsigned int)e->counters.bcnt,
1331 (long unsigned int)addme[*i].pcnt,
1332 (long unsigned int)addme[*i].bcnt);
1335 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1342 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1345 struct xt_counters_info tmp;
1346 struct xt_counters *paddc;
1347 unsigned int num_counters;
1352 const struct xt_table_info *private;
1354 void *loc_cpu_entry;
1355 #ifdef CONFIG_COMPAT
1356 struct compat_xt_counters_info compat_tmp;
1360 size = sizeof(struct compat_xt_counters_info);
1365 size = sizeof(struct xt_counters_info);
1368 if (copy_from_user(ptmp, user, size) != 0)
1371 #ifdef CONFIG_COMPAT
1373 num_counters = compat_tmp.num_counters;
1374 name = compat_tmp.name;
1378 num_counters = tmp.num_counters;
1382 if (len != size + num_counters * sizeof(struct xt_counters))
1385 paddc = vmalloc_node(len - size, numa_node_id());
1389 if (copy_from_user(paddc, user + size, len - size) != 0) {
1394 t = xt_find_table_lock(net, AF_INET, name);
1395 if (!t || IS_ERR(t)) {
1396 ret = t ? PTR_ERR(t) : -ENOENT;
1400 write_lock_bh(&t->lock);
1401 private = t->private;
1402 if (private->number != num_counters) {
1404 goto unlock_up_free;
1408 /* Choose the copy that is on our node */
1409 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1410 IPT_ENTRY_ITERATE(loc_cpu_entry,
1412 add_counter_to_entry,
1416 write_unlock_bh(&t->lock);
1425 #ifdef CONFIG_COMPAT
1426 struct compat_ipt_replace {
1427 char name[IPT_TABLE_MAXNAMELEN];
1431 u32 hook_entry[NF_INET_NUMHOOKS];
1432 u32 underflow[NF_INET_NUMHOOKS];
1434 compat_uptr_t counters; /* struct ipt_counters * */
1435 struct compat_ipt_entry entries[0];
1439 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1440 unsigned int *size, struct xt_counters *counters,
1443 struct ipt_entry_target *t;
1444 struct compat_ipt_entry __user *ce;
1445 u_int16_t target_offset, next_offset;
1446 compat_uint_t origsize;
1451 ce = (struct compat_ipt_entry __user *)*dstptr;
1452 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1455 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1458 *dstptr += sizeof(struct compat_ipt_entry);
1459 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1461 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1462 target_offset = e->target_offset - (origsize - *size);
1465 t = ipt_get_target(e);
1466 ret = xt_compat_target_to_user(t, dstptr, size);
1470 next_offset = e->next_offset - (origsize - *size);
1471 if (put_user(target_offset, &ce->target_offset))
1473 if (put_user(next_offset, &ce->next_offset))
1483 compat_find_calc_match(struct ipt_entry_match *m,
1485 const struct ipt_ip *ip,
1486 unsigned int hookmask,
1487 int *size, unsigned int *i)
1489 struct xt_match *match;
1491 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1492 m->u.user.revision),
1493 "ipt_%s", m->u.user.name);
1494 if (IS_ERR(match) || !match) {
1495 duprintf("compat_check_calc_match: `%s' not found\n",
1497 return match ? PTR_ERR(match) : -ENOENT;
1499 m->u.kernel.match = match;
1500 *size += xt_compat_match_offset(match);
1507 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1509 if (i && (*i)-- == 0)
1512 module_put(m->u.kernel.match->me);
1517 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1519 struct ipt_entry_target *t;
1521 if (i && (*i)-- == 0)
1524 /* Cleanup all matches */
1525 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1526 t = compat_ipt_get_target(e);
1527 module_put(t->u.kernel.target->me);
1532 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1533 struct xt_table_info *newinfo,
1535 unsigned char *base,
1536 unsigned char *limit,
1537 unsigned int *hook_entries,
1538 unsigned int *underflows,
1542 struct ipt_entry_target *t;
1543 struct xt_target *target;
1544 unsigned int entry_offset;
1548 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1549 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1550 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1551 duprintf("Bad offset %p, limit = %p\n", e, limit);
1555 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1556 sizeof(struct compat_xt_entry_target)) {
1557 duprintf("checking: element %p size %u\n",
1562 /* For purposes of check_entry casting the compat entry is fine */
1563 ret = check_entry((struct ipt_entry *)e, name);
1567 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1568 entry_offset = (void *)e - (void *)base;
1570 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1571 &e->ip, e->comefrom, &off, &j);
1573 goto release_matches;
1575 t = compat_ipt_get_target(e);
1576 target = try_then_request_module(xt_find_target(AF_INET,
1578 t->u.user.revision),
1579 "ipt_%s", t->u.user.name);
1580 if (IS_ERR(target) || !target) {
1581 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1583 ret = target ? PTR_ERR(target) : -ENOENT;
1584 goto release_matches;
1586 t->u.kernel.target = target;
1588 off += xt_compat_target_offset(target);
1590 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1594 /* Check hooks & underflows */
1595 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1596 if ((unsigned char *)e - base == hook_entries[h])
1597 newinfo->hook_entry[h] = hook_entries[h];
1598 if ((unsigned char *)e - base == underflows[h])
1599 newinfo->underflow[h] = underflows[h];
1602 /* Clear counters and comefrom */
1603 memset(&e->counters, 0, sizeof(e->counters));
1610 module_put(t->u.kernel.target->me);
1612 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1617 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1618 unsigned int *size, const char *name,
1619 struct xt_table_info *newinfo, unsigned char *base)
1621 struct ipt_entry_target *t;
1622 struct xt_target *target;
1623 struct ipt_entry *de;
1624 unsigned int origsize;
1629 de = (struct ipt_entry *)*dstptr;
1630 memcpy(de, e, sizeof(struct ipt_entry));
1631 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1633 *dstptr += sizeof(struct ipt_entry);
1634 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1636 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1640 de->target_offset = e->target_offset - (origsize - *size);
1641 t = compat_ipt_get_target(e);
1642 target = t->u.kernel.target;
1643 xt_compat_target_from_user(t, dstptr, size);
1645 de->next_offset = e->next_offset - (origsize - *size);
1646 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1647 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1648 newinfo->hook_entry[h] -= origsize - *size;
1649 if ((unsigned char *)de - base < newinfo->underflow[h])
1650 newinfo->underflow[h] -= origsize - *size;
1656 compat_check_entry(struct ipt_entry *e, const char *name,
1659 struct xt_mtchk_param mtpar;
1665 mtpar.entryinfo = &e->ip;
1666 mtpar.hook_mask = e->comefrom;
1667 mtpar.family = NFPROTO_IPV4;
1668 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1670 goto cleanup_matches;
1672 ret = check_target(e, name);
1674 goto cleanup_matches;
1680 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1685 translate_compat_table(const char *name,
1686 unsigned int valid_hooks,
1687 struct xt_table_info **pinfo,
1689 unsigned int total_size,
1690 unsigned int number,
1691 unsigned int *hook_entries,
1692 unsigned int *underflows)
1695 struct xt_table_info *newinfo, *info;
1696 void *pos, *entry0, *entry1;
1703 info->number = number;
1705 /* Init all hooks to impossible value. */
1706 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1707 info->hook_entry[i] = 0xFFFFFFFF;
1708 info->underflow[i] = 0xFFFFFFFF;
1711 duprintf("translate_compat_table: size %u\n", info->size);
1713 xt_compat_lock(AF_INET);
1714 /* Walk through entries, checking offsets. */
1715 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1716 check_compat_entry_size_and_hooks,
1717 info, &size, entry0,
1718 entry0 + total_size,
1719 hook_entries, underflows, &j, name);
1725 duprintf("translate_compat_table: %u not %u entries\n",
1730 /* Check hooks all assigned */
1731 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1732 /* Only hooks which are valid */
1733 if (!(valid_hooks & (1 << i)))
1735 if (info->hook_entry[i] == 0xFFFFFFFF) {
1736 duprintf("Invalid hook entry %u %u\n",
1737 i, hook_entries[i]);
1740 if (info->underflow[i] == 0xFFFFFFFF) {
1741 duprintf("Invalid underflow %u %u\n",
1748 newinfo = xt_alloc_table_info(size);
1752 newinfo->number = number;
1753 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1754 newinfo->hook_entry[i] = info->hook_entry[i];
1755 newinfo->underflow[i] = info->underflow[i];
1757 entry1 = newinfo->entries[raw_smp_processor_id()];
1760 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1761 compat_copy_entry_from_user,
1762 &pos, &size, name, newinfo, entry1);
1763 xt_compat_flush_offsets(AF_INET);
1764 xt_compat_unlock(AF_INET);
1769 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1773 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1777 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1778 compat_release_entry, &j);
1779 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1780 xt_free_table_info(newinfo);
1784 /* And one copy for every other CPU */
1785 for_each_possible_cpu(i)
1786 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1787 memcpy(newinfo->entries[i], entry1, newinfo->size);
1791 xt_free_table_info(info);
1795 xt_free_table_info(newinfo);
1797 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1800 xt_compat_flush_offsets(AF_INET);
1801 xt_compat_unlock(AF_INET);
1806 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1809 struct compat_ipt_replace tmp;
1810 struct xt_table_info *newinfo;
1811 void *loc_cpu_entry;
1813 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1816 /* overflow check */
1817 if (tmp.size >= INT_MAX / num_possible_cpus())
1819 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1822 newinfo = xt_alloc_table_info(tmp.size);
1826 /* choose the copy that is on our node/cpu */
1827 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1828 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1834 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1835 &newinfo, &loc_cpu_entry, tmp.size,
1836 tmp.num_entries, tmp.hook_entry,
1841 duprintf("compat_do_replace: Translated table\n");
1843 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1844 tmp.num_counters, compat_ptr(tmp.counters));
1846 goto free_newinfo_untrans;
1849 free_newinfo_untrans:
1850 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1852 xt_free_table_info(newinfo);
1857 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1862 if (!capable(CAP_NET_ADMIN))
1866 case IPT_SO_SET_REPLACE:
1867 ret = compat_do_replace(sock_net(sk), user, len);
1870 case IPT_SO_SET_ADD_COUNTERS:
1871 ret = do_add_counters(sock_net(sk), user, len, 1);
1875 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1882 struct compat_ipt_get_entries {
1883 char name[IPT_TABLE_MAXNAMELEN];
1885 struct compat_ipt_entry entrytable[0];
1889 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1890 void __user *userptr)
1892 struct xt_counters *counters;
1893 const struct xt_table_info *private = table->private;
1897 const void *loc_cpu_entry;
1900 counters = alloc_counters(table);
1901 if (IS_ERR(counters))
1902 return PTR_ERR(counters);
1904 /* choose the copy that is on our node/cpu, ...
1905 * This choice is lazy (because current thread is
1906 * allowed to migrate to another cpu)
1908 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1911 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1912 compat_copy_entry_to_user,
1913 &pos, &size, counters, &i);
1920 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1924 struct compat_ipt_get_entries get;
1927 if (*len < sizeof(get)) {
1928 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1932 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1935 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1936 duprintf("compat_get_entries: %u != %zu\n",
1937 *len, sizeof(get) + get.size);
1941 xt_compat_lock(AF_INET);
1942 t = xt_find_table_lock(net, AF_INET, get.name);
1943 if (t && !IS_ERR(t)) {
1944 const struct xt_table_info *private = t->private;
1945 struct xt_table_info info;
1946 duprintf("t->private->number = %u\n", private->number);
1947 ret = compat_table_info(private, &info);
1948 if (!ret && get.size == info.size) {
1949 ret = compat_copy_entries_to_user(private->size,
1950 t, uptr->entrytable);
1952 duprintf("compat_get_entries: I've got %u not %u!\n",
1953 private->size, get.size);
1956 xt_compat_flush_offsets(AF_INET);
1960 ret = t ? PTR_ERR(t) : -ENOENT;
1962 xt_compat_unlock(AF_INET);
1966 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1969 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1973 if (!capable(CAP_NET_ADMIN))
1977 case IPT_SO_GET_INFO:
1978 ret = get_info(sock_net(sk), user, len, 1);
1980 case IPT_SO_GET_ENTRIES:
1981 ret = compat_get_entries(sock_net(sk), user, len);
1984 ret = do_ipt_get_ctl(sk, cmd, user, len);
1991 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1995 if (!capable(CAP_NET_ADMIN))
1999 case IPT_SO_SET_REPLACE:
2000 ret = do_replace(sock_net(sk), user, len);
2003 case IPT_SO_SET_ADD_COUNTERS:
2004 ret = do_add_counters(sock_net(sk), user, len, 0);
2008 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2016 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2020 if (!capable(CAP_NET_ADMIN))
2024 case IPT_SO_GET_INFO:
2025 ret = get_info(sock_net(sk), user, len, 0);
2028 case IPT_SO_GET_ENTRIES:
2029 ret = get_entries(sock_net(sk), user, len);
2032 case IPT_SO_GET_REVISION_MATCH:
2033 case IPT_SO_GET_REVISION_TARGET: {
2034 struct ipt_get_revision rev;
2037 if (*len != sizeof(rev)) {
2041 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2046 if (cmd == IPT_SO_GET_REVISION_TARGET)
2051 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2054 "ipt_%s", rev.name);
2059 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2066 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2067 const struct ipt_replace *repl)
2070 struct xt_table_info *newinfo;
2071 struct xt_table_info bootstrap
2072 = { 0, 0, 0, { 0 }, { 0 }, { } };
2073 void *loc_cpu_entry;
2074 struct xt_table *new_table;
2076 newinfo = xt_alloc_table_info(repl->size);
2082 /* choose the copy on our node/cpu, but dont care about preemption */
2083 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2084 memcpy(loc_cpu_entry, repl->entries, repl->size);
2086 ret = translate_table(table->name, table->valid_hooks,
2087 newinfo, loc_cpu_entry, repl->size,
2094 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2095 if (IS_ERR(new_table)) {
2096 ret = PTR_ERR(new_table);
2103 xt_free_table_info(newinfo);
2105 return ERR_PTR(ret);
2108 void ipt_unregister_table(struct xt_table *table)
2110 struct xt_table_info *private;
2111 void *loc_cpu_entry;
2112 struct module *table_owner = table->me;
2114 private = xt_unregister_table(table);
2116 /* Decrease module usage counts and free resources */
2117 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2118 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2119 if (private->number > private->initial_entries)
2120 module_put(table_owner);
2121 xt_free_table_info(private);
2124 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2126 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2127 u_int8_t type, u_int8_t code,
2130 return ((test_type == 0xFF) ||
2131 (type == test_type && code >= min_code && code <= max_code))
2136 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2138 const struct icmphdr *ic;
2139 struct icmphdr _icmph;
2140 const struct ipt_icmp *icmpinfo = par->matchinfo;
2142 /* Must not be a fragment. */
2143 if (par->fragoff != 0)
2146 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2148 /* We've been asked to examine this packet, and we
2149 * can't. Hence, no choice but to drop.
2151 duprintf("Dropping evil ICMP tinygram.\n");
2152 *par->hotdrop = true;
2156 return icmp_type_code_match(icmpinfo->type,
2160 !!(icmpinfo->invflags&IPT_ICMP_INV));
2163 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2165 const struct ipt_icmp *icmpinfo = par->matchinfo;
2167 /* Must specify no unknown invflags */
2168 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2171 /* The built-in targets: standard (NULL) and error. */
2172 static struct xt_target ipt_standard_target __read_mostly = {
2173 .name = IPT_STANDARD_TARGET,
2174 .targetsize = sizeof(int),
2176 #ifdef CONFIG_COMPAT
2177 .compatsize = sizeof(compat_int_t),
2178 .compat_from_user = compat_standard_from_user,
2179 .compat_to_user = compat_standard_to_user,
2183 static struct xt_target ipt_error_target __read_mostly = {
2184 .name = IPT_ERROR_TARGET,
2185 .target = ipt_error,
2186 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2190 static struct nf_sockopt_ops ipt_sockopts = {
2192 .set_optmin = IPT_BASE_CTL,
2193 .set_optmax = IPT_SO_SET_MAX+1,
2194 .set = do_ipt_set_ctl,
2195 #ifdef CONFIG_COMPAT
2196 .compat_set = compat_do_ipt_set_ctl,
2198 .get_optmin = IPT_BASE_CTL,
2199 .get_optmax = IPT_SO_GET_MAX+1,
2200 .get = do_ipt_get_ctl,
2201 #ifdef CONFIG_COMPAT
2202 .compat_get = compat_do_ipt_get_ctl,
2204 .owner = THIS_MODULE,
2207 static struct xt_match icmp_matchstruct __read_mostly = {
2209 .match = icmp_match,
2210 .matchsize = sizeof(struct ipt_icmp),
2211 .checkentry = icmp_checkentry,
2212 .proto = IPPROTO_ICMP,
2216 static int __net_init ip_tables_net_init(struct net *net)
2218 return xt_proto_init(net, AF_INET);
2221 static void __net_exit ip_tables_net_exit(struct net *net)
2223 xt_proto_fini(net, AF_INET);
2226 static struct pernet_operations ip_tables_net_ops = {
2227 .init = ip_tables_net_init,
2228 .exit = ip_tables_net_exit,
2231 static int __init ip_tables_init(void)
2235 ret = register_pernet_subsys(&ip_tables_net_ops);
2239 /* Noone else will be downing sem now, so we won't sleep */
2240 ret = xt_register_target(&ipt_standard_target);
2243 ret = xt_register_target(&ipt_error_target);
2246 ret = xt_register_match(&icmp_matchstruct);
2250 /* Register setsockopt */
2251 ret = nf_register_sockopt(&ipt_sockopts);
2255 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2259 xt_unregister_match(&icmp_matchstruct);
2261 xt_unregister_target(&ipt_error_target);
2263 xt_unregister_target(&ipt_standard_target);
2265 unregister_pernet_subsys(&ip_tables_net_ops);
2270 static void __exit ip_tables_fini(void)
2272 nf_unregister_sockopt(&ipt_sockopts);
2274 xt_unregister_match(&icmp_matchstruct);
2275 xt_unregister_target(&ipt_error_target);
2276 xt_unregister_target(&ipt_standard_target);
2278 unregister_pernet_subsys(&ip_tables_net_ops);
2281 EXPORT_SYMBOL(ipt_register_table);
2282 EXPORT_SYMBOL(ipt_unregister_table);
2283 EXPORT_SYMBOL(ipt_do_table);
2284 module_init(ip_tables_init);
2285 module_exit(ip_tables_fini);