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,
175 const struct net_device *in,
176 const struct net_device *out,
177 unsigned int hooknum,
178 const struct xt_target *target,
179 const void *targinfo)
182 printk("ip_tables: error: `%s'\n", (char *)targinfo);
187 /* Performance critical - called for every packet */
189 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
190 struct xt_match_param *par)
192 par->match = m->u.kernel.match;
193 par->matchinfo = m->data;
195 /* Stop iteration if it doesn't match */
196 if (!m->u.kernel.match->match(skb, par))
202 /* Performance critical */
203 static inline struct ipt_entry *
204 get_entry(void *base, unsigned int offset)
206 return (struct ipt_entry *)(base + offset);
209 /* All zeroes == unconditional rule. */
210 /* Mildly perf critical (only if packet tracing is on) */
212 unconditional(const struct ipt_ip *ip)
216 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
217 if (((__u32 *)ip)[i])
224 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
225 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
226 static const char *const hooknames[] = {
227 [NF_INET_PRE_ROUTING] = "PREROUTING",
228 [NF_INET_LOCAL_IN] = "INPUT",
229 [NF_INET_FORWARD] = "FORWARD",
230 [NF_INET_LOCAL_OUT] = "OUTPUT",
231 [NF_INET_POST_ROUTING] = "POSTROUTING",
234 enum nf_ip_trace_comments {
235 NF_IP_TRACE_COMMENT_RULE,
236 NF_IP_TRACE_COMMENT_RETURN,
237 NF_IP_TRACE_COMMENT_POLICY,
240 static const char *const comments[] = {
241 [NF_IP_TRACE_COMMENT_RULE] = "rule",
242 [NF_IP_TRACE_COMMENT_RETURN] = "return",
243 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
246 static struct nf_loginfo trace_loginfo = {
247 .type = NF_LOG_TYPE_LOG,
251 .logflags = NF_LOG_MASK,
256 /* Mildly perf critical (only if packet tracing is on) */
258 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
259 char *hookname, char **chainname,
260 char **comment, unsigned int *rulenum)
262 struct ipt_standard_target *t = (void *)ipt_get_target(s);
264 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
265 /* Head of user chain: ERROR target with chainname */
266 *chainname = t->target.data;
271 if (s->target_offset == sizeof(struct ipt_entry)
272 && strcmp(t->target.u.kernel.target->name,
273 IPT_STANDARD_TARGET) == 0
275 && unconditional(&s->ip)) {
276 /* Tail of chains: STANDARD target (return/policy) */
277 *comment = *chainname == hookname
278 ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
279 : (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
288 static void trace_packet(struct sk_buff *skb,
290 const struct net_device *in,
291 const struct net_device *out,
292 const char *tablename,
293 struct xt_table_info *private,
297 const struct ipt_entry *root;
298 char *hookname, *chainname, *comment;
299 unsigned int rulenum = 0;
301 table_base = (void *)private->entries[smp_processor_id()];
302 root = get_entry(table_base, private->hook_entry[hook]);
304 hookname = chainname = (char *)hooknames[hook];
305 comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
307 IPT_ENTRY_ITERATE(root,
308 private->size - private->hook_entry[hook],
309 get_chainname_rulenum,
310 e, hookname, &chainname, &comment, &rulenum);
312 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
313 "TRACE: %s:%s:%s:%u ",
314 tablename, chainname, comment, rulenum);
318 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
320 ipt_do_table(struct sk_buff *skb,
322 const struct net_device *in,
323 const struct net_device *out,
324 struct xt_table *table)
326 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
327 const struct iphdr *ip;
329 bool hotdrop = false;
330 /* Initializing verdict to NF_DROP keeps gcc happy. */
331 unsigned int verdict = NF_DROP;
332 const char *indev, *outdev;
334 struct ipt_entry *e, *back;
335 struct xt_table_info *private;
336 struct xt_match_param mtpar;
340 datalen = skb->len - ip->ihl * 4;
341 indev = in ? in->name : nulldevname;
342 outdev = out ? out->name : nulldevname;
343 /* We handle fragments by dealing with the first fragment as
344 * if it was a normal packet. All other fragments are treated
345 * normally, except that they will NEVER match rules that ask
346 * things we don't know, ie. tcp syn flag or ports). If the
347 * rule is also a fragment-specific rule, non-fragments won't
349 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
350 mtpar.thoff = ip_hdrlen(skb);
351 mtpar.hotdrop = &hotdrop;
355 read_lock_bh(&table->lock);
356 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
357 private = table->private;
358 table_base = (void *)private->entries[smp_processor_id()];
359 e = get_entry(table_base, private->hook_entry[hook]);
361 /* For return from builtin chain */
362 back = get_entry(table_base, private->underflow[hook]);
367 if (ip_packet_match(ip, indev, outdev,
368 &e->ip, mtpar.fragoff)) {
369 struct ipt_entry_target *t;
371 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
374 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
376 t = ipt_get_target(e);
377 IP_NF_ASSERT(t->u.kernel.target);
379 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
380 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
381 /* The packet is traced: log it */
382 if (unlikely(skb->nf_trace))
383 trace_packet(skb, hook, in, out,
384 table->name, private, e);
386 /* Standard target? */
387 if (!t->u.kernel.target->target) {
390 v = ((struct ipt_standard_target *)t)->verdict;
392 /* Pop from stack? */
393 if (v != IPT_RETURN) {
394 verdict = (unsigned)(-v) - 1;
398 back = get_entry(table_base,
402 if (table_base + v != (void *)e + e->next_offset
403 && !(e->ip.flags & IPT_F_GOTO)) {
404 /* Save old back ptr in next entry */
405 struct ipt_entry *next
406 = (void *)e + e->next_offset;
408 = (void *)back - table_base;
409 /* set back pointer to next entry */
413 e = get_entry(table_base, v);
415 /* Targets which reenter must return
417 #ifdef CONFIG_NETFILTER_DEBUG
418 ((struct ipt_entry *)table_base)->comefrom
421 verdict = t->u.kernel.target->target(skb,
427 #ifdef CONFIG_NETFILTER_DEBUG
428 if (((struct ipt_entry *)table_base)->comefrom
430 && verdict == IPT_CONTINUE) {
431 printk("Target %s reentered!\n",
432 t->u.kernel.target->name);
435 ((struct ipt_entry *)table_base)->comefrom
438 /* Target might have changed stuff. */
440 datalen = skb->len - ip->ihl * 4;
442 if (verdict == IPT_CONTINUE)
443 e = (void *)e + e->next_offset;
451 e = (void *)e + e->next_offset;
455 read_unlock_bh(&table->lock);
457 #ifdef DEBUG_ALLOW_ALL
466 /* Figures out from what hook each rule can be called: returns 0 if
467 there are loops. Puts hook bitmask in comefrom. */
469 mark_source_chains(struct xt_table_info *newinfo,
470 unsigned int valid_hooks, void *entry0)
474 /* No recursion; use packet counter to save back ptrs (reset
475 to 0 as we leave), and comefrom to save source hook bitmask */
476 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
477 unsigned int pos = newinfo->hook_entry[hook];
478 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
480 if (!(valid_hooks & (1 << hook)))
483 /* Set initial back pointer. */
484 e->counters.pcnt = pos;
487 struct ipt_standard_target *t
488 = (void *)ipt_get_target(e);
489 int visited = e->comefrom & (1 << hook);
491 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
492 printk("iptables: loop hook %u pos %u %08X.\n",
493 hook, pos, e->comefrom);
496 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
498 /* Unconditional return/END. */
499 if ((e->target_offset == sizeof(struct ipt_entry)
500 && (strcmp(t->target.u.user.name,
501 IPT_STANDARD_TARGET) == 0)
503 && unconditional(&e->ip)) || visited) {
504 unsigned int oldpos, size;
506 if (t->verdict < -NF_MAX_VERDICT - 1) {
507 duprintf("mark_source_chains: bad "
508 "negative verdict (%i)\n",
513 /* Return: backtrack through the last
516 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
517 #ifdef DEBUG_IP_FIREWALL_USER
519 & (1 << NF_INET_NUMHOOKS)) {
520 duprintf("Back unset "
527 pos = e->counters.pcnt;
528 e->counters.pcnt = 0;
530 /* We're at the start. */
534 e = (struct ipt_entry *)
536 } while (oldpos == pos + e->next_offset);
539 size = e->next_offset;
540 e = (struct ipt_entry *)
541 (entry0 + pos + size);
542 e->counters.pcnt = pos;
545 int newpos = t->verdict;
547 if (strcmp(t->target.u.user.name,
548 IPT_STANDARD_TARGET) == 0
550 if (newpos > newinfo->size -
551 sizeof(struct ipt_entry)) {
552 duprintf("mark_source_chains: "
553 "bad verdict (%i)\n",
557 /* This a jump; chase it. */
558 duprintf("Jump rule %u -> %u\n",
561 /* ... this is a fallthru */
562 newpos = pos + e->next_offset;
564 e = (struct ipt_entry *)
566 e->counters.pcnt = pos;
571 duprintf("Finished chain %u\n", hook);
577 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
579 struct xt_mtdtor_param par;
581 if (i && (*i)-- == 0)
584 par.match = m->u.kernel.match;
585 par.matchinfo = m->data;
586 if (par.match->destroy != NULL)
587 par.match->destroy(&par);
588 module_put(par.match->me);
593 check_entry(struct ipt_entry *e, const char *name)
595 struct ipt_entry_target *t;
597 if (!ip_checkentry(&e->ip)) {
598 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
602 if (e->target_offset + sizeof(struct ipt_entry_target) >
606 t = ipt_get_target(e);
607 if (e->target_offset + t->u.target_size > e->next_offset)
614 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
617 const struct ipt_ip *ip = par->entryinfo;
620 par->match = m->u.kernel.match;
621 par->matchinfo = m->data;
623 ret = xt_check_match(par, NFPROTO_IPV4, m->u.match_size - sizeof(*m),
624 ip->proto, ip->invflags & IPT_INV_PROTO);
626 duprintf("ip_tables: check failed for `%s'.\n",
635 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
638 struct xt_match *match;
641 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
643 "ipt_%s", m->u.user.name);
644 if (IS_ERR(match) || !match) {
645 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
646 return match ? PTR_ERR(match) : -ENOENT;
648 m->u.kernel.match = match;
650 ret = check_match(m, par, i);
656 module_put(m->u.kernel.match->me);
660 static int check_target(struct ipt_entry *e, const char *name)
662 struct ipt_entry_target *t;
663 struct xt_target *target;
666 t = ipt_get_target(e);
667 target = t->u.kernel.target;
668 ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
669 name, e->comefrom, e->ip.proto,
670 e->ip.invflags & IPT_INV_PROTO, e, t->data);
672 duprintf("ip_tables: check failed for `%s'.\n",
673 t->u.kernel.target->name);
680 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
683 struct ipt_entry_target *t;
684 struct xt_target *target;
687 struct xt_mtchk_param mtpar;
689 ret = check_entry(e, name);
695 mtpar.entryinfo = &e->ip;
696 mtpar.hook_mask = e->comefrom;
697 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
699 goto cleanup_matches;
701 t = ipt_get_target(e);
702 target = try_then_request_module(xt_find_target(AF_INET,
705 "ipt_%s", t->u.user.name);
706 if (IS_ERR(target) || !target) {
707 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
708 ret = target ? PTR_ERR(target) : -ENOENT;
709 goto cleanup_matches;
711 t->u.kernel.target = target;
713 ret = check_target(e, name);
720 module_put(t->u.kernel.target->me);
722 IPT_MATCH_ITERATE(e, cleanup_match, &j);
727 check_entry_size_and_hooks(struct ipt_entry *e,
728 struct xt_table_info *newinfo,
730 unsigned char *limit,
731 const unsigned int *hook_entries,
732 const unsigned int *underflows,
737 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
738 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
739 duprintf("Bad offset %p\n", e);
744 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
745 duprintf("checking: element %p size %u\n",
750 /* Check hooks & underflows */
751 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
752 if ((unsigned char *)e - base == hook_entries[h])
753 newinfo->hook_entry[h] = hook_entries[h];
754 if ((unsigned char *)e - base == underflows[h])
755 newinfo->underflow[h] = underflows[h];
758 /* FIXME: underflows must be unconditional, standard verdicts
759 < 0 (not IPT_RETURN). --RR */
761 /* Clear counters and comefrom */
762 e->counters = ((struct xt_counters) { 0, 0 });
770 cleanup_entry(struct ipt_entry *e, unsigned int *i)
772 struct ipt_entry_target *t;
774 if (i && (*i)-- == 0)
777 /* Cleanup all matches */
778 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
779 t = ipt_get_target(e);
780 if (t->u.kernel.target->destroy)
781 t->u.kernel.target->destroy(t->u.kernel.target, t->data);
782 module_put(t->u.kernel.target->me);
786 /* Checks and translates the user-supplied table segment (held in
789 translate_table(const char *name,
790 unsigned int valid_hooks,
791 struct xt_table_info *newinfo,
795 const unsigned int *hook_entries,
796 const unsigned int *underflows)
801 newinfo->size = size;
802 newinfo->number = number;
804 /* Init all hooks to impossible value. */
805 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
806 newinfo->hook_entry[i] = 0xFFFFFFFF;
807 newinfo->underflow[i] = 0xFFFFFFFF;
810 duprintf("translate_table: size %u\n", newinfo->size);
812 /* Walk through entries, checking offsets. */
813 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
814 check_entry_size_and_hooks,
818 hook_entries, underflows, &i);
823 duprintf("translate_table: %u not %u entries\n",
828 /* Check hooks all assigned */
829 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
830 /* Only hooks which are valid */
831 if (!(valid_hooks & (1 << i)))
833 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
834 duprintf("Invalid hook entry %u %u\n",
838 if (newinfo->underflow[i] == 0xFFFFFFFF) {
839 duprintf("Invalid underflow %u %u\n",
845 if (!mark_source_chains(newinfo, valid_hooks, entry0))
848 /* Finally, each sanity check must pass */
850 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
851 find_check_entry, name, size, &i);
854 IPT_ENTRY_ITERATE(entry0, newinfo->size,
859 /* And one copy for every other CPU */
860 for_each_possible_cpu(i) {
861 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
862 memcpy(newinfo->entries[i], entry0, newinfo->size);
870 add_entry_to_counter(const struct ipt_entry *e,
871 struct xt_counters total[],
874 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
881 set_entry_to_counter(const struct ipt_entry *e,
882 struct ipt_counters total[],
885 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
892 get_counters(const struct xt_table_info *t,
893 struct xt_counters counters[])
899 /* Instead of clearing (by a previous call to memset())
900 * the counters and using adds, we set the counters
901 * with data used by 'current' CPU
902 * We dont care about preemption here.
904 curcpu = raw_smp_processor_id();
907 IPT_ENTRY_ITERATE(t->entries[curcpu],
909 set_entry_to_counter,
913 for_each_possible_cpu(cpu) {
917 IPT_ENTRY_ITERATE(t->entries[cpu],
919 add_entry_to_counter,
925 static struct xt_counters * alloc_counters(struct xt_table *table)
927 unsigned int countersize;
928 struct xt_counters *counters;
929 const struct xt_table_info *private = table->private;
931 /* We need atomic snapshot of counters: rest doesn't change
932 (other than comefrom, which userspace doesn't care
934 countersize = sizeof(struct xt_counters) * private->number;
935 counters = vmalloc_node(countersize, numa_node_id());
937 if (counters == NULL)
938 return ERR_PTR(-ENOMEM);
940 /* First, sum counters... */
941 write_lock_bh(&table->lock);
942 get_counters(private, counters);
943 write_unlock_bh(&table->lock);
949 copy_entries_to_user(unsigned int total_size,
950 struct xt_table *table,
951 void __user *userptr)
953 unsigned int off, num;
955 struct xt_counters *counters;
956 const struct xt_table_info *private = table->private;
958 const void *loc_cpu_entry;
960 counters = alloc_counters(table);
961 if (IS_ERR(counters))
962 return PTR_ERR(counters);
964 /* choose the copy that is on our node/cpu, ...
965 * This choice is lazy (because current thread is
966 * allowed to migrate to another cpu)
968 loc_cpu_entry = private->entries[raw_smp_processor_id()];
969 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
974 /* FIXME: use iterator macros --RR */
975 /* ... then go back and fix counters and names */
976 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
978 const struct ipt_entry_match *m;
979 const struct ipt_entry_target *t;
981 e = (struct ipt_entry *)(loc_cpu_entry + off);
982 if (copy_to_user(userptr + off
983 + offsetof(struct ipt_entry, counters),
985 sizeof(counters[num])) != 0) {
990 for (i = sizeof(struct ipt_entry);
991 i < e->target_offset;
992 i += m->u.match_size) {
995 if (copy_to_user(userptr + off + i
996 + offsetof(struct ipt_entry_match,
998 m->u.kernel.match->name,
999 strlen(m->u.kernel.match->name)+1)
1006 t = ipt_get_target(e);
1007 if (copy_to_user(userptr + off + e->target_offset
1008 + offsetof(struct ipt_entry_target,
1010 t->u.kernel.target->name,
1011 strlen(t->u.kernel.target->name)+1) != 0) {
1022 #ifdef CONFIG_COMPAT
1023 static void compat_standard_from_user(void *dst, void *src)
1025 int v = *(compat_int_t *)src;
1028 v += xt_compat_calc_jump(AF_INET, v);
1029 memcpy(dst, &v, sizeof(v));
1032 static int compat_standard_to_user(void __user *dst, void *src)
1034 compat_int_t cv = *(int *)src;
1037 cv -= xt_compat_calc_jump(AF_INET, cv);
1038 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1042 compat_calc_match(struct ipt_entry_match *m, int *size)
1044 *size += xt_compat_match_offset(m->u.kernel.match);
1048 static int compat_calc_entry(struct ipt_entry *e,
1049 const struct xt_table_info *info,
1050 void *base, struct xt_table_info *newinfo)
1052 struct ipt_entry_target *t;
1053 unsigned int entry_offset;
1056 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1057 entry_offset = (void *)e - base;
1058 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1059 t = ipt_get_target(e);
1060 off += xt_compat_target_offset(t->u.kernel.target);
1061 newinfo->size -= off;
1062 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1066 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1067 if (info->hook_entry[i] &&
1068 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1069 newinfo->hook_entry[i] -= off;
1070 if (info->underflow[i] &&
1071 (e < (struct ipt_entry *)(base + info->underflow[i])))
1072 newinfo->underflow[i] -= off;
1077 static int compat_table_info(const struct xt_table_info *info,
1078 struct xt_table_info *newinfo)
1080 void *loc_cpu_entry;
1082 if (!newinfo || !info)
1085 /* we dont care about newinfo->entries[] */
1086 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1087 newinfo->initial_entries = 0;
1088 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1089 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1090 compat_calc_entry, info, loc_cpu_entry,
1095 static int get_info(struct net *net, void __user *user, int *len, int compat)
1097 char name[IPT_TABLE_MAXNAMELEN];
1101 if (*len != sizeof(struct ipt_getinfo)) {
1102 duprintf("length %u != %zu\n", *len,
1103 sizeof(struct ipt_getinfo));
1107 if (copy_from_user(name, user, sizeof(name)) != 0)
1110 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1111 #ifdef CONFIG_COMPAT
1113 xt_compat_lock(AF_INET);
1115 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1116 "iptable_%s", name);
1117 if (t && !IS_ERR(t)) {
1118 struct ipt_getinfo info;
1119 const struct xt_table_info *private = t->private;
1121 #ifdef CONFIG_COMPAT
1123 struct xt_table_info tmp;
1124 ret = compat_table_info(private, &tmp);
1125 xt_compat_flush_offsets(AF_INET);
1129 info.valid_hooks = t->valid_hooks;
1130 memcpy(info.hook_entry, private->hook_entry,
1131 sizeof(info.hook_entry));
1132 memcpy(info.underflow, private->underflow,
1133 sizeof(info.underflow));
1134 info.num_entries = private->number;
1135 info.size = private->size;
1136 strcpy(info.name, name);
1138 if (copy_to_user(user, &info, *len) != 0)
1146 ret = t ? PTR_ERR(t) : -ENOENT;
1147 #ifdef CONFIG_COMPAT
1149 xt_compat_unlock(AF_INET);
1155 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1158 struct ipt_get_entries get;
1161 if (*len < sizeof(get)) {
1162 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1165 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1167 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1168 duprintf("get_entries: %u != %zu\n",
1169 *len, sizeof(get) + get.size);
1173 t = xt_find_table_lock(net, AF_INET, get.name);
1174 if (t && !IS_ERR(t)) {
1175 const struct xt_table_info *private = t->private;
1176 duprintf("t->private->number = %u\n", private->number);
1177 if (get.size == private->size)
1178 ret = copy_entries_to_user(private->size,
1179 t, uptr->entrytable);
1181 duprintf("get_entries: I've got %u not %u!\n",
1182 private->size, get.size);
1188 ret = t ? PTR_ERR(t) : -ENOENT;
1194 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1195 struct xt_table_info *newinfo, unsigned int num_counters,
1196 void __user *counters_ptr)
1200 struct xt_table_info *oldinfo;
1201 struct xt_counters *counters;
1202 void *loc_cpu_old_entry;
1205 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1211 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1212 "iptable_%s", name);
1213 if (!t || IS_ERR(t)) {
1214 ret = t ? PTR_ERR(t) : -ENOENT;
1215 goto free_newinfo_counters_untrans;
1219 if (valid_hooks != t->valid_hooks) {
1220 duprintf("Valid hook crap: %08X vs %08X\n",
1221 valid_hooks, t->valid_hooks);
1226 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1230 /* Update module usage count based on number of rules */
1231 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1232 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1233 if ((oldinfo->number > oldinfo->initial_entries) ||
1234 (newinfo->number <= oldinfo->initial_entries))
1236 if ((oldinfo->number > oldinfo->initial_entries) &&
1237 (newinfo->number <= oldinfo->initial_entries))
1240 /* Get the old counters. */
1241 get_counters(oldinfo, counters);
1242 /* Decrease module usage counts and free resource */
1243 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1244 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1246 xt_free_table_info(oldinfo);
1247 if (copy_to_user(counters_ptr, counters,
1248 sizeof(struct xt_counters) * num_counters) != 0)
1257 free_newinfo_counters_untrans:
1264 do_replace(struct net *net, void __user *user, unsigned int len)
1267 struct ipt_replace tmp;
1268 struct xt_table_info *newinfo;
1269 void *loc_cpu_entry;
1271 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1274 /* overflow check */
1275 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1278 newinfo = xt_alloc_table_info(tmp.size);
1282 /* choose the copy that is on our node/cpu */
1283 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1284 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1290 ret = translate_table(tmp.name, tmp.valid_hooks,
1291 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1292 tmp.hook_entry, tmp.underflow);
1296 duprintf("ip_tables: Translated table\n");
1298 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1299 tmp.num_counters, tmp.counters);
1301 goto free_newinfo_untrans;
1304 free_newinfo_untrans:
1305 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1307 xt_free_table_info(newinfo);
1311 /* We're lazy, and add to the first CPU; overflow works its fey magic
1312 * and everything is OK. */
1314 add_counter_to_entry(struct ipt_entry *e,
1315 const struct xt_counters addme[],
1319 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1321 (long unsigned int)e->counters.pcnt,
1322 (long unsigned int)e->counters.bcnt,
1323 (long unsigned int)addme[*i].pcnt,
1324 (long unsigned int)addme[*i].bcnt);
1327 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1334 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1337 struct xt_counters_info tmp;
1338 struct xt_counters *paddc;
1339 unsigned int num_counters;
1344 const struct xt_table_info *private;
1346 void *loc_cpu_entry;
1347 #ifdef CONFIG_COMPAT
1348 struct compat_xt_counters_info compat_tmp;
1352 size = sizeof(struct compat_xt_counters_info);
1357 size = sizeof(struct xt_counters_info);
1360 if (copy_from_user(ptmp, user, size) != 0)
1363 #ifdef CONFIG_COMPAT
1365 num_counters = compat_tmp.num_counters;
1366 name = compat_tmp.name;
1370 num_counters = tmp.num_counters;
1374 if (len != size + num_counters * sizeof(struct xt_counters))
1377 paddc = vmalloc_node(len - size, numa_node_id());
1381 if (copy_from_user(paddc, user + size, len - size) != 0) {
1386 t = xt_find_table_lock(net, AF_INET, name);
1387 if (!t || IS_ERR(t)) {
1388 ret = t ? PTR_ERR(t) : -ENOENT;
1392 write_lock_bh(&t->lock);
1393 private = t->private;
1394 if (private->number != num_counters) {
1396 goto unlock_up_free;
1400 /* Choose the copy that is on our node */
1401 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1402 IPT_ENTRY_ITERATE(loc_cpu_entry,
1404 add_counter_to_entry,
1408 write_unlock_bh(&t->lock);
1417 #ifdef CONFIG_COMPAT
1418 struct compat_ipt_replace {
1419 char name[IPT_TABLE_MAXNAMELEN];
1423 u32 hook_entry[NF_INET_NUMHOOKS];
1424 u32 underflow[NF_INET_NUMHOOKS];
1426 compat_uptr_t counters; /* struct ipt_counters * */
1427 struct compat_ipt_entry entries[0];
1431 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1432 unsigned int *size, struct xt_counters *counters,
1435 struct ipt_entry_target *t;
1436 struct compat_ipt_entry __user *ce;
1437 u_int16_t target_offset, next_offset;
1438 compat_uint_t origsize;
1443 ce = (struct compat_ipt_entry __user *)*dstptr;
1444 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1447 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1450 *dstptr += sizeof(struct compat_ipt_entry);
1451 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1453 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1454 target_offset = e->target_offset - (origsize - *size);
1457 t = ipt_get_target(e);
1458 ret = xt_compat_target_to_user(t, dstptr, size);
1462 next_offset = e->next_offset - (origsize - *size);
1463 if (put_user(target_offset, &ce->target_offset))
1465 if (put_user(next_offset, &ce->next_offset))
1475 compat_find_calc_match(struct ipt_entry_match *m,
1477 const struct ipt_ip *ip,
1478 unsigned int hookmask,
1479 int *size, unsigned int *i)
1481 struct xt_match *match;
1483 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1484 m->u.user.revision),
1485 "ipt_%s", m->u.user.name);
1486 if (IS_ERR(match) || !match) {
1487 duprintf("compat_check_calc_match: `%s' not found\n",
1489 return match ? PTR_ERR(match) : -ENOENT;
1491 m->u.kernel.match = match;
1492 *size += xt_compat_match_offset(match);
1499 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1501 if (i && (*i)-- == 0)
1504 module_put(m->u.kernel.match->me);
1509 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1511 struct ipt_entry_target *t;
1513 if (i && (*i)-- == 0)
1516 /* Cleanup all matches */
1517 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1518 t = compat_ipt_get_target(e);
1519 module_put(t->u.kernel.target->me);
1524 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1525 struct xt_table_info *newinfo,
1527 unsigned char *base,
1528 unsigned char *limit,
1529 unsigned int *hook_entries,
1530 unsigned int *underflows,
1534 struct ipt_entry_target *t;
1535 struct xt_target *target;
1536 unsigned int entry_offset;
1540 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1541 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1542 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1543 duprintf("Bad offset %p, limit = %p\n", e, limit);
1547 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1548 sizeof(struct compat_xt_entry_target)) {
1549 duprintf("checking: element %p size %u\n",
1554 /* For purposes of check_entry casting the compat entry is fine */
1555 ret = check_entry((struct ipt_entry *)e, name);
1559 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1560 entry_offset = (void *)e - (void *)base;
1562 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1563 &e->ip, e->comefrom, &off, &j);
1565 goto release_matches;
1567 t = compat_ipt_get_target(e);
1568 target = try_then_request_module(xt_find_target(AF_INET,
1570 t->u.user.revision),
1571 "ipt_%s", t->u.user.name);
1572 if (IS_ERR(target) || !target) {
1573 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1575 ret = target ? PTR_ERR(target) : -ENOENT;
1576 goto release_matches;
1578 t->u.kernel.target = target;
1580 off += xt_compat_target_offset(target);
1582 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1586 /* Check hooks & underflows */
1587 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1588 if ((unsigned char *)e - base == hook_entries[h])
1589 newinfo->hook_entry[h] = hook_entries[h];
1590 if ((unsigned char *)e - base == underflows[h])
1591 newinfo->underflow[h] = underflows[h];
1594 /* Clear counters and comefrom */
1595 memset(&e->counters, 0, sizeof(e->counters));
1602 module_put(t->u.kernel.target->me);
1604 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1609 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1610 unsigned int *size, const char *name,
1611 struct xt_table_info *newinfo, unsigned char *base)
1613 struct ipt_entry_target *t;
1614 struct xt_target *target;
1615 struct ipt_entry *de;
1616 unsigned int origsize;
1621 de = (struct ipt_entry *)*dstptr;
1622 memcpy(de, e, sizeof(struct ipt_entry));
1623 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1625 *dstptr += sizeof(struct ipt_entry);
1626 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1628 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1632 de->target_offset = e->target_offset - (origsize - *size);
1633 t = compat_ipt_get_target(e);
1634 target = t->u.kernel.target;
1635 xt_compat_target_from_user(t, dstptr, size);
1637 de->next_offset = e->next_offset - (origsize - *size);
1638 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1639 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1640 newinfo->hook_entry[h] -= origsize - *size;
1641 if ((unsigned char *)de - base < newinfo->underflow[h])
1642 newinfo->underflow[h] -= origsize - *size;
1648 compat_check_entry(struct ipt_entry *e, const char *name,
1651 struct xt_mtchk_param mtpar;
1657 mtpar.entryinfo = &e->ip;
1658 mtpar.hook_mask = e->comefrom;
1659 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1661 goto cleanup_matches;
1663 ret = check_target(e, name);
1665 goto cleanup_matches;
1671 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1676 translate_compat_table(const char *name,
1677 unsigned int valid_hooks,
1678 struct xt_table_info **pinfo,
1680 unsigned int total_size,
1681 unsigned int number,
1682 unsigned int *hook_entries,
1683 unsigned int *underflows)
1686 struct xt_table_info *newinfo, *info;
1687 void *pos, *entry0, *entry1;
1694 info->number = number;
1696 /* Init all hooks to impossible value. */
1697 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1698 info->hook_entry[i] = 0xFFFFFFFF;
1699 info->underflow[i] = 0xFFFFFFFF;
1702 duprintf("translate_compat_table: size %u\n", info->size);
1704 xt_compat_lock(AF_INET);
1705 /* Walk through entries, checking offsets. */
1706 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1707 check_compat_entry_size_and_hooks,
1708 info, &size, entry0,
1709 entry0 + total_size,
1710 hook_entries, underflows, &j, name);
1716 duprintf("translate_compat_table: %u not %u entries\n",
1721 /* Check hooks all assigned */
1722 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1723 /* Only hooks which are valid */
1724 if (!(valid_hooks & (1 << i)))
1726 if (info->hook_entry[i] == 0xFFFFFFFF) {
1727 duprintf("Invalid hook entry %u %u\n",
1728 i, hook_entries[i]);
1731 if (info->underflow[i] == 0xFFFFFFFF) {
1732 duprintf("Invalid underflow %u %u\n",
1739 newinfo = xt_alloc_table_info(size);
1743 newinfo->number = number;
1744 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1745 newinfo->hook_entry[i] = info->hook_entry[i];
1746 newinfo->underflow[i] = info->underflow[i];
1748 entry1 = newinfo->entries[raw_smp_processor_id()];
1751 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1752 compat_copy_entry_from_user,
1753 &pos, &size, name, newinfo, entry1);
1754 xt_compat_flush_offsets(AF_INET);
1755 xt_compat_unlock(AF_INET);
1760 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1764 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1768 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1769 compat_release_entry, &j);
1770 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1771 xt_free_table_info(newinfo);
1775 /* And one copy for every other CPU */
1776 for_each_possible_cpu(i)
1777 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1778 memcpy(newinfo->entries[i], entry1, newinfo->size);
1782 xt_free_table_info(info);
1786 xt_free_table_info(newinfo);
1788 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1791 xt_compat_flush_offsets(AF_INET);
1792 xt_compat_unlock(AF_INET);
1797 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1800 struct compat_ipt_replace tmp;
1801 struct xt_table_info *newinfo;
1802 void *loc_cpu_entry;
1804 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1807 /* overflow check */
1808 if (tmp.size >= INT_MAX / num_possible_cpus())
1810 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1813 newinfo = xt_alloc_table_info(tmp.size);
1817 /* choose the copy that is on our node/cpu */
1818 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1819 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1825 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1826 &newinfo, &loc_cpu_entry, tmp.size,
1827 tmp.num_entries, tmp.hook_entry,
1832 duprintf("compat_do_replace: Translated table\n");
1834 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1835 tmp.num_counters, compat_ptr(tmp.counters));
1837 goto free_newinfo_untrans;
1840 free_newinfo_untrans:
1841 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1843 xt_free_table_info(newinfo);
1848 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1853 if (!capable(CAP_NET_ADMIN))
1857 case IPT_SO_SET_REPLACE:
1858 ret = compat_do_replace(sock_net(sk), user, len);
1861 case IPT_SO_SET_ADD_COUNTERS:
1862 ret = do_add_counters(sock_net(sk), user, len, 1);
1866 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1873 struct compat_ipt_get_entries {
1874 char name[IPT_TABLE_MAXNAMELEN];
1876 struct compat_ipt_entry entrytable[0];
1880 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1881 void __user *userptr)
1883 struct xt_counters *counters;
1884 const struct xt_table_info *private = table->private;
1888 const void *loc_cpu_entry;
1891 counters = alloc_counters(table);
1892 if (IS_ERR(counters))
1893 return PTR_ERR(counters);
1895 /* choose the copy that is on our node/cpu, ...
1896 * This choice is lazy (because current thread is
1897 * allowed to migrate to another cpu)
1899 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1902 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1903 compat_copy_entry_to_user,
1904 &pos, &size, counters, &i);
1911 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1915 struct compat_ipt_get_entries get;
1918 if (*len < sizeof(get)) {
1919 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1923 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1926 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1927 duprintf("compat_get_entries: %u != %zu\n",
1928 *len, sizeof(get) + get.size);
1932 xt_compat_lock(AF_INET);
1933 t = xt_find_table_lock(net, AF_INET, get.name);
1934 if (t && !IS_ERR(t)) {
1935 const struct xt_table_info *private = t->private;
1936 struct xt_table_info info;
1937 duprintf("t->private->number = %u\n", private->number);
1938 ret = compat_table_info(private, &info);
1939 if (!ret && get.size == info.size) {
1940 ret = compat_copy_entries_to_user(private->size,
1941 t, uptr->entrytable);
1943 duprintf("compat_get_entries: I've got %u not %u!\n",
1944 private->size, get.size);
1947 xt_compat_flush_offsets(AF_INET);
1951 ret = t ? PTR_ERR(t) : -ENOENT;
1953 xt_compat_unlock(AF_INET);
1957 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1960 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1964 if (!capable(CAP_NET_ADMIN))
1968 case IPT_SO_GET_INFO:
1969 ret = get_info(sock_net(sk), user, len, 1);
1971 case IPT_SO_GET_ENTRIES:
1972 ret = compat_get_entries(sock_net(sk), user, len);
1975 ret = do_ipt_get_ctl(sk, cmd, user, len);
1982 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1986 if (!capable(CAP_NET_ADMIN))
1990 case IPT_SO_SET_REPLACE:
1991 ret = do_replace(sock_net(sk), user, len);
1994 case IPT_SO_SET_ADD_COUNTERS:
1995 ret = do_add_counters(sock_net(sk), user, len, 0);
1999 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2007 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2011 if (!capable(CAP_NET_ADMIN))
2015 case IPT_SO_GET_INFO:
2016 ret = get_info(sock_net(sk), user, len, 0);
2019 case IPT_SO_GET_ENTRIES:
2020 ret = get_entries(sock_net(sk), user, len);
2023 case IPT_SO_GET_REVISION_MATCH:
2024 case IPT_SO_GET_REVISION_TARGET: {
2025 struct ipt_get_revision rev;
2028 if (*len != sizeof(rev)) {
2032 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2037 if (cmd == IPT_SO_GET_REVISION_TARGET)
2042 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2045 "ipt_%s", rev.name);
2050 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2057 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2058 const struct ipt_replace *repl)
2061 struct xt_table_info *newinfo;
2062 struct xt_table_info bootstrap
2063 = { 0, 0, 0, { 0 }, { 0 }, { } };
2064 void *loc_cpu_entry;
2065 struct xt_table *new_table;
2067 newinfo = xt_alloc_table_info(repl->size);
2073 /* choose the copy on our node/cpu, but dont care about preemption */
2074 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2075 memcpy(loc_cpu_entry, repl->entries, repl->size);
2077 ret = translate_table(table->name, table->valid_hooks,
2078 newinfo, loc_cpu_entry, repl->size,
2085 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2086 if (IS_ERR(new_table)) {
2087 ret = PTR_ERR(new_table);
2094 xt_free_table_info(newinfo);
2096 return ERR_PTR(ret);
2099 void ipt_unregister_table(struct xt_table *table)
2101 struct xt_table_info *private;
2102 void *loc_cpu_entry;
2103 struct module *table_owner = table->me;
2105 private = xt_unregister_table(table);
2107 /* Decrease module usage counts and free resources */
2108 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2109 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2110 if (private->number > private->initial_entries)
2111 module_put(table_owner);
2112 xt_free_table_info(private);
2115 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2117 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2118 u_int8_t type, u_int8_t code,
2121 return ((test_type == 0xFF) ||
2122 (type == test_type && code >= min_code && code <= max_code))
2127 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2129 const struct icmphdr *ic;
2130 struct icmphdr _icmph;
2131 const struct ipt_icmp *icmpinfo = par->matchinfo;
2133 /* Must not be a fragment. */
2134 if (par->fragoff != 0)
2137 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2139 /* We've been asked to examine this packet, and we
2140 * can't. Hence, no choice but to drop.
2142 duprintf("Dropping evil ICMP tinygram.\n");
2143 *par->hotdrop = true;
2147 return icmp_type_code_match(icmpinfo->type,
2151 !!(icmpinfo->invflags&IPT_ICMP_INV));
2154 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2156 const struct ipt_icmp *icmpinfo = par->matchinfo;
2158 /* Must specify no unknown invflags */
2159 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2162 /* The built-in targets: standard (NULL) and error. */
2163 static struct xt_target ipt_standard_target __read_mostly = {
2164 .name = IPT_STANDARD_TARGET,
2165 .targetsize = sizeof(int),
2167 #ifdef CONFIG_COMPAT
2168 .compatsize = sizeof(compat_int_t),
2169 .compat_from_user = compat_standard_from_user,
2170 .compat_to_user = compat_standard_to_user,
2174 static struct xt_target ipt_error_target __read_mostly = {
2175 .name = IPT_ERROR_TARGET,
2176 .target = ipt_error,
2177 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2181 static struct nf_sockopt_ops ipt_sockopts = {
2183 .set_optmin = IPT_BASE_CTL,
2184 .set_optmax = IPT_SO_SET_MAX+1,
2185 .set = do_ipt_set_ctl,
2186 #ifdef CONFIG_COMPAT
2187 .compat_set = compat_do_ipt_set_ctl,
2189 .get_optmin = IPT_BASE_CTL,
2190 .get_optmax = IPT_SO_GET_MAX+1,
2191 .get = do_ipt_get_ctl,
2192 #ifdef CONFIG_COMPAT
2193 .compat_get = compat_do_ipt_get_ctl,
2195 .owner = THIS_MODULE,
2198 static struct xt_match icmp_matchstruct __read_mostly = {
2200 .match = icmp_match,
2201 .matchsize = sizeof(struct ipt_icmp),
2202 .checkentry = icmp_checkentry,
2203 .proto = IPPROTO_ICMP,
2207 static int __net_init ip_tables_net_init(struct net *net)
2209 return xt_proto_init(net, AF_INET);
2212 static void __net_exit ip_tables_net_exit(struct net *net)
2214 xt_proto_fini(net, AF_INET);
2217 static struct pernet_operations ip_tables_net_ops = {
2218 .init = ip_tables_net_init,
2219 .exit = ip_tables_net_exit,
2222 static int __init ip_tables_init(void)
2226 ret = register_pernet_subsys(&ip_tables_net_ops);
2230 /* Noone else will be downing sem now, so we won't sleep */
2231 ret = xt_register_target(&ipt_standard_target);
2234 ret = xt_register_target(&ipt_error_target);
2237 ret = xt_register_match(&icmp_matchstruct);
2241 /* Register setsockopt */
2242 ret = nf_register_sockopt(&ipt_sockopts);
2246 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2250 xt_unregister_match(&icmp_matchstruct);
2252 xt_unregister_target(&ipt_error_target);
2254 xt_unregister_target(&ipt_standard_target);
2256 unregister_pernet_subsys(&ip_tables_net_ops);
2261 static void __exit ip_tables_fini(void)
2263 nf_unregister_sockopt(&ipt_sockopts);
2265 xt_unregister_match(&icmp_matchstruct);
2266 xt_unregister_target(&ipt_error_target);
2267 xt_unregister_target(&ipt_standard_target);
2269 unregister_pernet_subsys(&ip_tables_net_ops);
2272 EXPORT_SYMBOL(ipt_register_table);
2273 EXPORT_SYMBOL(ipt_unregister_table);
2274 EXPORT_SYMBOL(ipt_do_table);
2275 module_init(ip_tables_init);
2276 module_exit(ip_tables_fini);