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 tgpar.hooknum = hook;
353 read_lock_bh(&table->lock);
354 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
355 private = table->private;
356 table_base = (void *)private->entries[smp_processor_id()];
357 e = get_entry(table_base, private->hook_entry[hook]);
359 /* For return from builtin chain */
360 back = get_entry(table_base, private->underflow[hook]);
365 if (ip_packet_match(ip, indev, outdev,
366 &e->ip, mtpar.fragoff)) {
367 struct ipt_entry_target *t;
369 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
372 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
374 t = ipt_get_target(e);
375 IP_NF_ASSERT(t->u.kernel.target);
377 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
378 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
379 /* The packet is traced: log it */
380 if (unlikely(skb->nf_trace))
381 trace_packet(skb, hook, in, out,
382 table->name, private, e);
384 /* Standard target? */
385 if (!t->u.kernel.target->target) {
388 v = ((struct ipt_standard_target *)t)->verdict;
390 /* Pop from stack? */
391 if (v != IPT_RETURN) {
392 verdict = (unsigned)(-v) - 1;
396 back = get_entry(table_base,
400 if (table_base + v != (void *)e + e->next_offset
401 && !(e->ip.flags & IPT_F_GOTO)) {
402 /* Save old back ptr in next entry */
403 struct ipt_entry *next
404 = (void *)e + e->next_offset;
406 = (void *)back - table_base;
407 /* set back pointer to next entry */
411 e = get_entry(table_base, v);
413 /* Targets which reenter must return
415 tgpar.target = t->u.kernel.target;
416 tgpar.targinfo = t->data;
417 #ifdef CONFIG_NETFILTER_DEBUG
418 ((struct ipt_entry *)table_base)->comefrom
421 verdict = t->u.kernel.target->target(skb,
423 #ifdef CONFIG_NETFILTER_DEBUG
424 if (((struct ipt_entry *)table_base)->comefrom
426 && verdict == IPT_CONTINUE) {
427 printk("Target %s reentered!\n",
428 t->u.kernel.target->name);
431 ((struct ipt_entry *)table_base)->comefrom
434 /* Target might have changed stuff. */
436 datalen = skb->len - ip->ihl * 4;
438 if (verdict == IPT_CONTINUE)
439 e = (void *)e + e->next_offset;
447 e = (void *)e + e->next_offset;
451 read_unlock_bh(&table->lock);
453 #ifdef DEBUG_ALLOW_ALL
462 /* Figures out from what hook each rule can be called: returns 0 if
463 there are loops. Puts hook bitmask in comefrom. */
465 mark_source_chains(struct xt_table_info *newinfo,
466 unsigned int valid_hooks, void *entry0)
470 /* No recursion; use packet counter to save back ptrs (reset
471 to 0 as we leave), and comefrom to save source hook bitmask */
472 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
473 unsigned int pos = newinfo->hook_entry[hook];
474 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
476 if (!(valid_hooks & (1 << hook)))
479 /* Set initial back pointer. */
480 e->counters.pcnt = pos;
483 struct ipt_standard_target *t
484 = (void *)ipt_get_target(e);
485 int visited = e->comefrom & (1 << hook);
487 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
488 printk("iptables: loop hook %u pos %u %08X.\n",
489 hook, pos, e->comefrom);
492 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
494 /* Unconditional return/END. */
495 if ((e->target_offset == sizeof(struct ipt_entry)
496 && (strcmp(t->target.u.user.name,
497 IPT_STANDARD_TARGET) == 0)
499 && unconditional(&e->ip)) || visited) {
500 unsigned int oldpos, size;
502 if (t->verdict < -NF_MAX_VERDICT - 1) {
503 duprintf("mark_source_chains: bad "
504 "negative verdict (%i)\n",
509 /* Return: backtrack through the last
512 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
513 #ifdef DEBUG_IP_FIREWALL_USER
515 & (1 << NF_INET_NUMHOOKS)) {
516 duprintf("Back unset "
523 pos = e->counters.pcnt;
524 e->counters.pcnt = 0;
526 /* We're at the start. */
530 e = (struct ipt_entry *)
532 } while (oldpos == pos + e->next_offset);
535 size = e->next_offset;
536 e = (struct ipt_entry *)
537 (entry0 + pos + size);
538 e->counters.pcnt = pos;
541 int newpos = t->verdict;
543 if (strcmp(t->target.u.user.name,
544 IPT_STANDARD_TARGET) == 0
546 if (newpos > newinfo->size -
547 sizeof(struct ipt_entry)) {
548 duprintf("mark_source_chains: "
549 "bad verdict (%i)\n",
553 /* This a jump; chase it. */
554 duprintf("Jump rule %u -> %u\n",
557 /* ... this is a fallthru */
558 newpos = pos + e->next_offset;
560 e = (struct ipt_entry *)
562 e->counters.pcnt = pos;
567 duprintf("Finished chain %u\n", hook);
573 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
575 struct xt_mtdtor_param par;
577 if (i && (*i)-- == 0)
580 par.match = m->u.kernel.match;
581 par.matchinfo = m->data;
582 if (par.match->destroy != NULL)
583 par.match->destroy(&par);
584 module_put(par.match->me);
589 check_entry(struct ipt_entry *e, const char *name)
591 struct ipt_entry_target *t;
593 if (!ip_checkentry(&e->ip)) {
594 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
598 if (e->target_offset + sizeof(struct ipt_entry_target) >
602 t = ipt_get_target(e);
603 if (e->target_offset + t->u.target_size > e->next_offset)
610 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
613 const struct ipt_ip *ip = par->entryinfo;
616 par->match = m->u.kernel.match;
617 par->matchinfo = m->data;
619 ret = xt_check_match(par, NFPROTO_IPV4, m->u.match_size - sizeof(*m),
620 ip->proto, ip->invflags & IPT_INV_PROTO);
622 duprintf("ip_tables: check failed for `%s'.\n",
631 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
634 struct xt_match *match;
637 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
639 "ipt_%s", m->u.user.name);
640 if (IS_ERR(match) || !match) {
641 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
642 return match ? PTR_ERR(match) : -ENOENT;
644 m->u.kernel.match = match;
646 ret = check_match(m, par, i);
652 module_put(m->u.kernel.match->me);
656 static int check_target(struct ipt_entry *e, const char *name)
658 struct ipt_entry_target *t = ipt_get_target(e);
659 struct xt_tgchk_param par = {
662 .target = t->u.kernel.target,
664 .hook_mask = e->comefrom,
668 ret = xt_check_target(&par, NFPROTO_IPV4, t->u.target_size - sizeof(*t),
669 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
671 duprintf("ip_tables: check failed for `%s'.\n",
672 t->u.kernel.target->name);
679 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
682 struct ipt_entry_target *t;
683 struct xt_target *target;
686 struct xt_mtchk_param mtpar;
688 ret = check_entry(e, name);
694 mtpar.entryinfo = &e->ip;
695 mtpar.hook_mask = e->comefrom;
696 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
698 goto cleanup_matches;
700 t = ipt_get_target(e);
701 target = try_then_request_module(xt_find_target(AF_INET,
704 "ipt_%s", t->u.user.name);
705 if (IS_ERR(target) || !target) {
706 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
707 ret = target ? PTR_ERR(target) : -ENOENT;
708 goto cleanup_matches;
710 t->u.kernel.target = target;
712 ret = check_target(e, name);
719 module_put(t->u.kernel.target->me);
721 IPT_MATCH_ITERATE(e, cleanup_match, &j);
726 check_entry_size_and_hooks(struct ipt_entry *e,
727 struct xt_table_info *newinfo,
729 unsigned char *limit,
730 const unsigned int *hook_entries,
731 const unsigned int *underflows,
736 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
737 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
738 duprintf("Bad offset %p\n", e);
743 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
744 duprintf("checking: element %p size %u\n",
749 /* Check hooks & underflows */
750 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
751 if ((unsigned char *)e - base == hook_entries[h])
752 newinfo->hook_entry[h] = hook_entries[h];
753 if ((unsigned char *)e - base == underflows[h])
754 newinfo->underflow[h] = underflows[h];
757 /* FIXME: underflows must be unconditional, standard verdicts
758 < 0 (not IPT_RETURN). --RR */
760 /* Clear counters and comefrom */
761 e->counters = ((struct xt_counters) { 0, 0 });
769 cleanup_entry(struct ipt_entry *e, unsigned int *i)
771 struct xt_tgdtor_param par;
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);
781 par.target = t->u.kernel.target;
782 par.targinfo = t->data;
783 if (par.target->destroy != NULL)
784 par.target->destroy(&par);
785 module_put(par.target->me);
789 /* Checks and translates the user-supplied table segment (held in
792 translate_table(const char *name,
793 unsigned int valid_hooks,
794 struct xt_table_info *newinfo,
798 const unsigned int *hook_entries,
799 const unsigned int *underflows)
804 newinfo->size = size;
805 newinfo->number = number;
807 /* Init all hooks to impossible value. */
808 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
809 newinfo->hook_entry[i] = 0xFFFFFFFF;
810 newinfo->underflow[i] = 0xFFFFFFFF;
813 duprintf("translate_table: size %u\n", newinfo->size);
815 /* Walk through entries, checking offsets. */
816 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
817 check_entry_size_and_hooks,
821 hook_entries, underflows, &i);
826 duprintf("translate_table: %u not %u entries\n",
831 /* Check hooks all assigned */
832 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
833 /* Only hooks which are valid */
834 if (!(valid_hooks & (1 << i)))
836 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
837 duprintf("Invalid hook entry %u %u\n",
841 if (newinfo->underflow[i] == 0xFFFFFFFF) {
842 duprintf("Invalid underflow %u %u\n",
848 if (!mark_source_chains(newinfo, valid_hooks, entry0))
851 /* Finally, each sanity check must pass */
853 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
854 find_check_entry, name, size, &i);
857 IPT_ENTRY_ITERATE(entry0, newinfo->size,
862 /* And one copy for every other CPU */
863 for_each_possible_cpu(i) {
864 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
865 memcpy(newinfo->entries[i], entry0, newinfo->size);
873 add_entry_to_counter(const struct ipt_entry *e,
874 struct xt_counters total[],
877 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
884 set_entry_to_counter(const struct ipt_entry *e,
885 struct ipt_counters total[],
888 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
895 get_counters(const struct xt_table_info *t,
896 struct xt_counters counters[])
902 /* Instead of clearing (by a previous call to memset())
903 * the counters and using adds, we set the counters
904 * with data used by 'current' CPU
905 * We dont care about preemption here.
907 curcpu = raw_smp_processor_id();
910 IPT_ENTRY_ITERATE(t->entries[curcpu],
912 set_entry_to_counter,
916 for_each_possible_cpu(cpu) {
920 IPT_ENTRY_ITERATE(t->entries[cpu],
922 add_entry_to_counter,
928 static struct xt_counters * alloc_counters(struct xt_table *table)
930 unsigned int countersize;
931 struct xt_counters *counters;
932 const struct xt_table_info *private = table->private;
934 /* We need atomic snapshot of counters: rest doesn't change
935 (other than comefrom, which userspace doesn't care
937 countersize = sizeof(struct xt_counters) * private->number;
938 counters = vmalloc_node(countersize, numa_node_id());
940 if (counters == NULL)
941 return ERR_PTR(-ENOMEM);
943 /* First, sum counters... */
944 write_lock_bh(&table->lock);
945 get_counters(private, counters);
946 write_unlock_bh(&table->lock);
952 copy_entries_to_user(unsigned int total_size,
953 struct xt_table *table,
954 void __user *userptr)
956 unsigned int off, num;
958 struct xt_counters *counters;
959 const struct xt_table_info *private = table->private;
961 const void *loc_cpu_entry;
963 counters = alloc_counters(table);
964 if (IS_ERR(counters))
965 return PTR_ERR(counters);
967 /* choose the copy that is on our node/cpu, ...
968 * This choice is lazy (because current thread is
969 * allowed to migrate to another cpu)
971 loc_cpu_entry = private->entries[raw_smp_processor_id()];
972 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
977 /* FIXME: use iterator macros --RR */
978 /* ... then go back and fix counters and names */
979 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
981 const struct ipt_entry_match *m;
982 const struct ipt_entry_target *t;
984 e = (struct ipt_entry *)(loc_cpu_entry + off);
985 if (copy_to_user(userptr + off
986 + offsetof(struct ipt_entry, counters),
988 sizeof(counters[num])) != 0) {
993 for (i = sizeof(struct ipt_entry);
994 i < e->target_offset;
995 i += m->u.match_size) {
998 if (copy_to_user(userptr + off + i
999 + offsetof(struct ipt_entry_match,
1001 m->u.kernel.match->name,
1002 strlen(m->u.kernel.match->name)+1)
1009 t = ipt_get_target(e);
1010 if (copy_to_user(userptr + off + e->target_offset
1011 + offsetof(struct ipt_entry_target,
1013 t->u.kernel.target->name,
1014 strlen(t->u.kernel.target->name)+1) != 0) {
1025 #ifdef CONFIG_COMPAT
1026 static void compat_standard_from_user(void *dst, void *src)
1028 int v = *(compat_int_t *)src;
1031 v += xt_compat_calc_jump(AF_INET, v);
1032 memcpy(dst, &v, sizeof(v));
1035 static int compat_standard_to_user(void __user *dst, void *src)
1037 compat_int_t cv = *(int *)src;
1040 cv -= xt_compat_calc_jump(AF_INET, cv);
1041 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1045 compat_calc_match(struct ipt_entry_match *m, int *size)
1047 *size += xt_compat_match_offset(m->u.kernel.match);
1051 static int compat_calc_entry(struct ipt_entry *e,
1052 const struct xt_table_info *info,
1053 void *base, struct xt_table_info *newinfo)
1055 struct ipt_entry_target *t;
1056 unsigned int entry_offset;
1059 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1060 entry_offset = (void *)e - base;
1061 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1062 t = ipt_get_target(e);
1063 off += xt_compat_target_offset(t->u.kernel.target);
1064 newinfo->size -= off;
1065 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1069 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1070 if (info->hook_entry[i] &&
1071 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1072 newinfo->hook_entry[i] -= off;
1073 if (info->underflow[i] &&
1074 (e < (struct ipt_entry *)(base + info->underflow[i])))
1075 newinfo->underflow[i] -= off;
1080 static int compat_table_info(const struct xt_table_info *info,
1081 struct xt_table_info *newinfo)
1083 void *loc_cpu_entry;
1085 if (!newinfo || !info)
1088 /* we dont care about newinfo->entries[] */
1089 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1090 newinfo->initial_entries = 0;
1091 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1092 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1093 compat_calc_entry, info, loc_cpu_entry,
1098 static int get_info(struct net *net, void __user *user, int *len, int compat)
1100 char name[IPT_TABLE_MAXNAMELEN];
1104 if (*len != sizeof(struct ipt_getinfo)) {
1105 duprintf("length %u != %zu\n", *len,
1106 sizeof(struct ipt_getinfo));
1110 if (copy_from_user(name, user, sizeof(name)) != 0)
1113 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1114 #ifdef CONFIG_COMPAT
1116 xt_compat_lock(AF_INET);
1118 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1119 "iptable_%s", name);
1120 if (t && !IS_ERR(t)) {
1121 struct ipt_getinfo info;
1122 const struct xt_table_info *private = t->private;
1124 #ifdef CONFIG_COMPAT
1126 struct xt_table_info tmp;
1127 ret = compat_table_info(private, &tmp);
1128 xt_compat_flush_offsets(AF_INET);
1132 info.valid_hooks = t->valid_hooks;
1133 memcpy(info.hook_entry, private->hook_entry,
1134 sizeof(info.hook_entry));
1135 memcpy(info.underflow, private->underflow,
1136 sizeof(info.underflow));
1137 info.num_entries = private->number;
1138 info.size = private->size;
1139 strcpy(info.name, name);
1141 if (copy_to_user(user, &info, *len) != 0)
1149 ret = t ? PTR_ERR(t) : -ENOENT;
1150 #ifdef CONFIG_COMPAT
1152 xt_compat_unlock(AF_INET);
1158 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1161 struct ipt_get_entries get;
1164 if (*len < sizeof(get)) {
1165 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1168 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1170 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1171 duprintf("get_entries: %u != %zu\n",
1172 *len, sizeof(get) + get.size);
1176 t = xt_find_table_lock(net, AF_INET, get.name);
1177 if (t && !IS_ERR(t)) {
1178 const struct xt_table_info *private = t->private;
1179 duprintf("t->private->number = %u\n", private->number);
1180 if (get.size == private->size)
1181 ret = copy_entries_to_user(private->size,
1182 t, uptr->entrytable);
1184 duprintf("get_entries: I've got %u not %u!\n",
1185 private->size, get.size);
1191 ret = t ? PTR_ERR(t) : -ENOENT;
1197 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1198 struct xt_table_info *newinfo, unsigned int num_counters,
1199 void __user *counters_ptr)
1203 struct xt_table_info *oldinfo;
1204 struct xt_counters *counters;
1205 void *loc_cpu_old_entry;
1208 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1214 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1215 "iptable_%s", name);
1216 if (!t || IS_ERR(t)) {
1217 ret = t ? PTR_ERR(t) : -ENOENT;
1218 goto free_newinfo_counters_untrans;
1222 if (valid_hooks != t->valid_hooks) {
1223 duprintf("Valid hook crap: %08X vs %08X\n",
1224 valid_hooks, t->valid_hooks);
1229 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1233 /* Update module usage count based on number of rules */
1234 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1235 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1236 if ((oldinfo->number > oldinfo->initial_entries) ||
1237 (newinfo->number <= oldinfo->initial_entries))
1239 if ((oldinfo->number > oldinfo->initial_entries) &&
1240 (newinfo->number <= oldinfo->initial_entries))
1243 /* Get the old counters. */
1244 get_counters(oldinfo, counters);
1245 /* Decrease module usage counts and free resource */
1246 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1247 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1249 xt_free_table_info(oldinfo);
1250 if (copy_to_user(counters_ptr, counters,
1251 sizeof(struct xt_counters) * num_counters) != 0)
1260 free_newinfo_counters_untrans:
1267 do_replace(struct net *net, void __user *user, unsigned int len)
1270 struct ipt_replace tmp;
1271 struct xt_table_info *newinfo;
1272 void *loc_cpu_entry;
1274 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1277 /* overflow check */
1278 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1281 newinfo = xt_alloc_table_info(tmp.size);
1285 /* choose the copy that is on our node/cpu */
1286 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1287 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1293 ret = translate_table(tmp.name, tmp.valid_hooks,
1294 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1295 tmp.hook_entry, tmp.underflow);
1299 duprintf("ip_tables: Translated table\n");
1301 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1302 tmp.num_counters, tmp.counters);
1304 goto free_newinfo_untrans;
1307 free_newinfo_untrans:
1308 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1310 xt_free_table_info(newinfo);
1314 /* We're lazy, and add to the first CPU; overflow works its fey magic
1315 * and everything is OK. */
1317 add_counter_to_entry(struct ipt_entry *e,
1318 const struct xt_counters addme[],
1322 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1324 (long unsigned int)e->counters.pcnt,
1325 (long unsigned int)e->counters.bcnt,
1326 (long unsigned int)addme[*i].pcnt,
1327 (long unsigned int)addme[*i].bcnt);
1330 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1337 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1340 struct xt_counters_info tmp;
1341 struct xt_counters *paddc;
1342 unsigned int num_counters;
1347 const struct xt_table_info *private;
1349 void *loc_cpu_entry;
1350 #ifdef CONFIG_COMPAT
1351 struct compat_xt_counters_info compat_tmp;
1355 size = sizeof(struct compat_xt_counters_info);
1360 size = sizeof(struct xt_counters_info);
1363 if (copy_from_user(ptmp, user, size) != 0)
1366 #ifdef CONFIG_COMPAT
1368 num_counters = compat_tmp.num_counters;
1369 name = compat_tmp.name;
1373 num_counters = tmp.num_counters;
1377 if (len != size + num_counters * sizeof(struct xt_counters))
1380 paddc = vmalloc_node(len - size, numa_node_id());
1384 if (copy_from_user(paddc, user + size, len - size) != 0) {
1389 t = xt_find_table_lock(net, AF_INET, name);
1390 if (!t || IS_ERR(t)) {
1391 ret = t ? PTR_ERR(t) : -ENOENT;
1395 write_lock_bh(&t->lock);
1396 private = t->private;
1397 if (private->number != num_counters) {
1399 goto unlock_up_free;
1403 /* Choose the copy that is on our node */
1404 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1405 IPT_ENTRY_ITERATE(loc_cpu_entry,
1407 add_counter_to_entry,
1411 write_unlock_bh(&t->lock);
1420 #ifdef CONFIG_COMPAT
1421 struct compat_ipt_replace {
1422 char name[IPT_TABLE_MAXNAMELEN];
1426 u32 hook_entry[NF_INET_NUMHOOKS];
1427 u32 underflow[NF_INET_NUMHOOKS];
1429 compat_uptr_t counters; /* struct ipt_counters * */
1430 struct compat_ipt_entry entries[0];
1434 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1435 unsigned int *size, struct xt_counters *counters,
1438 struct ipt_entry_target *t;
1439 struct compat_ipt_entry __user *ce;
1440 u_int16_t target_offset, next_offset;
1441 compat_uint_t origsize;
1446 ce = (struct compat_ipt_entry __user *)*dstptr;
1447 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1450 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1453 *dstptr += sizeof(struct compat_ipt_entry);
1454 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1456 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1457 target_offset = e->target_offset - (origsize - *size);
1460 t = ipt_get_target(e);
1461 ret = xt_compat_target_to_user(t, dstptr, size);
1465 next_offset = e->next_offset - (origsize - *size);
1466 if (put_user(target_offset, &ce->target_offset))
1468 if (put_user(next_offset, &ce->next_offset))
1478 compat_find_calc_match(struct ipt_entry_match *m,
1480 const struct ipt_ip *ip,
1481 unsigned int hookmask,
1482 int *size, unsigned int *i)
1484 struct xt_match *match;
1486 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1487 m->u.user.revision),
1488 "ipt_%s", m->u.user.name);
1489 if (IS_ERR(match) || !match) {
1490 duprintf("compat_check_calc_match: `%s' not found\n",
1492 return match ? PTR_ERR(match) : -ENOENT;
1494 m->u.kernel.match = match;
1495 *size += xt_compat_match_offset(match);
1502 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1504 if (i && (*i)-- == 0)
1507 module_put(m->u.kernel.match->me);
1512 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1514 struct ipt_entry_target *t;
1516 if (i && (*i)-- == 0)
1519 /* Cleanup all matches */
1520 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1521 t = compat_ipt_get_target(e);
1522 module_put(t->u.kernel.target->me);
1527 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1528 struct xt_table_info *newinfo,
1530 unsigned char *base,
1531 unsigned char *limit,
1532 unsigned int *hook_entries,
1533 unsigned int *underflows,
1537 struct ipt_entry_target *t;
1538 struct xt_target *target;
1539 unsigned int entry_offset;
1543 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1544 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1545 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1546 duprintf("Bad offset %p, limit = %p\n", e, limit);
1550 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1551 sizeof(struct compat_xt_entry_target)) {
1552 duprintf("checking: element %p size %u\n",
1557 /* For purposes of check_entry casting the compat entry is fine */
1558 ret = check_entry((struct ipt_entry *)e, name);
1562 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1563 entry_offset = (void *)e - (void *)base;
1565 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1566 &e->ip, e->comefrom, &off, &j);
1568 goto release_matches;
1570 t = compat_ipt_get_target(e);
1571 target = try_then_request_module(xt_find_target(AF_INET,
1573 t->u.user.revision),
1574 "ipt_%s", t->u.user.name);
1575 if (IS_ERR(target) || !target) {
1576 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1578 ret = target ? PTR_ERR(target) : -ENOENT;
1579 goto release_matches;
1581 t->u.kernel.target = target;
1583 off += xt_compat_target_offset(target);
1585 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1589 /* Check hooks & underflows */
1590 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1591 if ((unsigned char *)e - base == hook_entries[h])
1592 newinfo->hook_entry[h] = hook_entries[h];
1593 if ((unsigned char *)e - base == underflows[h])
1594 newinfo->underflow[h] = underflows[h];
1597 /* Clear counters and comefrom */
1598 memset(&e->counters, 0, sizeof(e->counters));
1605 module_put(t->u.kernel.target->me);
1607 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1612 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1613 unsigned int *size, const char *name,
1614 struct xt_table_info *newinfo, unsigned char *base)
1616 struct ipt_entry_target *t;
1617 struct xt_target *target;
1618 struct ipt_entry *de;
1619 unsigned int origsize;
1624 de = (struct ipt_entry *)*dstptr;
1625 memcpy(de, e, sizeof(struct ipt_entry));
1626 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1628 *dstptr += sizeof(struct ipt_entry);
1629 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1631 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1635 de->target_offset = e->target_offset - (origsize - *size);
1636 t = compat_ipt_get_target(e);
1637 target = t->u.kernel.target;
1638 xt_compat_target_from_user(t, dstptr, size);
1640 de->next_offset = e->next_offset - (origsize - *size);
1641 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1642 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1643 newinfo->hook_entry[h] -= origsize - *size;
1644 if ((unsigned char *)de - base < newinfo->underflow[h])
1645 newinfo->underflow[h] -= origsize - *size;
1651 compat_check_entry(struct ipt_entry *e, const char *name,
1654 struct xt_mtchk_param mtpar;
1660 mtpar.entryinfo = &e->ip;
1661 mtpar.hook_mask = e->comefrom;
1662 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1664 goto cleanup_matches;
1666 ret = check_target(e, name);
1668 goto cleanup_matches;
1674 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1679 translate_compat_table(const char *name,
1680 unsigned int valid_hooks,
1681 struct xt_table_info **pinfo,
1683 unsigned int total_size,
1684 unsigned int number,
1685 unsigned int *hook_entries,
1686 unsigned int *underflows)
1689 struct xt_table_info *newinfo, *info;
1690 void *pos, *entry0, *entry1;
1697 info->number = number;
1699 /* Init all hooks to impossible value. */
1700 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1701 info->hook_entry[i] = 0xFFFFFFFF;
1702 info->underflow[i] = 0xFFFFFFFF;
1705 duprintf("translate_compat_table: size %u\n", info->size);
1707 xt_compat_lock(AF_INET);
1708 /* Walk through entries, checking offsets. */
1709 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1710 check_compat_entry_size_and_hooks,
1711 info, &size, entry0,
1712 entry0 + total_size,
1713 hook_entries, underflows, &j, name);
1719 duprintf("translate_compat_table: %u not %u entries\n",
1724 /* Check hooks all assigned */
1725 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1726 /* Only hooks which are valid */
1727 if (!(valid_hooks & (1 << i)))
1729 if (info->hook_entry[i] == 0xFFFFFFFF) {
1730 duprintf("Invalid hook entry %u %u\n",
1731 i, hook_entries[i]);
1734 if (info->underflow[i] == 0xFFFFFFFF) {
1735 duprintf("Invalid underflow %u %u\n",
1742 newinfo = xt_alloc_table_info(size);
1746 newinfo->number = number;
1747 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1748 newinfo->hook_entry[i] = info->hook_entry[i];
1749 newinfo->underflow[i] = info->underflow[i];
1751 entry1 = newinfo->entries[raw_smp_processor_id()];
1754 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1755 compat_copy_entry_from_user,
1756 &pos, &size, name, newinfo, entry1);
1757 xt_compat_flush_offsets(AF_INET);
1758 xt_compat_unlock(AF_INET);
1763 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1767 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1771 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1772 compat_release_entry, &j);
1773 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1774 xt_free_table_info(newinfo);
1778 /* And one copy for every other CPU */
1779 for_each_possible_cpu(i)
1780 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1781 memcpy(newinfo->entries[i], entry1, newinfo->size);
1785 xt_free_table_info(info);
1789 xt_free_table_info(newinfo);
1791 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1794 xt_compat_flush_offsets(AF_INET);
1795 xt_compat_unlock(AF_INET);
1800 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1803 struct compat_ipt_replace tmp;
1804 struct xt_table_info *newinfo;
1805 void *loc_cpu_entry;
1807 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1810 /* overflow check */
1811 if (tmp.size >= INT_MAX / num_possible_cpus())
1813 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1816 newinfo = xt_alloc_table_info(tmp.size);
1820 /* choose the copy that is on our node/cpu */
1821 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1822 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1828 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1829 &newinfo, &loc_cpu_entry, tmp.size,
1830 tmp.num_entries, tmp.hook_entry,
1835 duprintf("compat_do_replace: Translated table\n");
1837 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1838 tmp.num_counters, compat_ptr(tmp.counters));
1840 goto free_newinfo_untrans;
1843 free_newinfo_untrans:
1844 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1846 xt_free_table_info(newinfo);
1851 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1856 if (!capable(CAP_NET_ADMIN))
1860 case IPT_SO_SET_REPLACE:
1861 ret = compat_do_replace(sock_net(sk), user, len);
1864 case IPT_SO_SET_ADD_COUNTERS:
1865 ret = do_add_counters(sock_net(sk), user, len, 1);
1869 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1876 struct compat_ipt_get_entries {
1877 char name[IPT_TABLE_MAXNAMELEN];
1879 struct compat_ipt_entry entrytable[0];
1883 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1884 void __user *userptr)
1886 struct xt_counters *counters;
1887 const struct xt_table_info *private = table->private;
1891 const void *loc_cpu_entry;
1894 counters = alloc_counters(table);
1895 if (IS_ERR(counters))
1896 return PTR_ERR(counters);
1898 /* choose the copy that is on our node/cpu, ...
1899 * This choice is lazy (because current thread is
1900 * allowed to migrate to another cpu)
1902 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1905 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1906 compat_copy_entry_to_user,
1907 &pos, &size, counters, &i);
1914 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1918 struct compat_ipt_get_entries get;
1921 if (*len < sizeof(get)) {
1922 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1926 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1929 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1930 duprintf("compat_get_entries: %u != %zu\n",
1931 *len, sizeof(get) + get.size);
1935 xt_compat_lock(AF_INET);
1936 t = xt_find_table_lock(net, AF_INET, get.name);
1937 if (t && !IS_ERR(t)) {
1938 const struct xt_table_info *private = t->private;
1939 struct xt_table_info info;
1940 duprintf("t->private->number = %u\n", private->number);
1941 ret = compat_table_info(private, &info);
1942 if (!ret && get.size == info.size) {
1943 ret = compat_copy_entries_to_user(private->size,
1944 t, uptr->entrytable);
1946 duprintf("compat_get_entries: I've got %u not %u!\n",
1947 private->size, get.size);
1950 xt_compat_flush_offsets(AF_INET);
1954 ret = t ? PTR_ERR(t) : -ENOENT;
1956 xt_compat_unlock(AF_INET);
1960 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1963 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1967 if (!capable(CAP_NET_ADMIN))
1971 case IPT_SO_GET_INFO:
1972 ret = get_info(sock_net(sk), user, len, 1);
1974 case IPT_SO_GET_ENTRIES:
1975 ret = compat_get_entries(sock_net(sk), user, len);
1978 ret = do_ipt_get_ctl(sk, cmd, user, len);
1985 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1989 if (!capable(CAP_NET_ADMIN))
1993 case IPT_SO_SET_REPLACE:
1994 ret = do_replace(sock_net(sk), user, len);
1997 case IPT_SO_SET_ADD_COUNTERS:
1998 ret = do_add_counters(sock_net(sk), user, len, 0);
2002 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2010 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2014 if (!capable(CAP_NET_ADMIN))
2018 case IPT_SO_GET_INFO:
2019 ret = get_info(sock_net(sk), user, len, 0);
2022 case IPT_SO_GET_ENTRIES:
2023 ret = get_entries(sock_net(sk), user, len);
2026 case IPT_SO_GET_REVISION_MATCH:
2027 case IPT_SO_GET_REVISION_TARGET: {
2028 struct ipt_get_revision rev;
2031 if (*len != sizeof(rev)) {
2035 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2040 if (cmd == IPT_SO_GET_REVISION_TARGET)
2045 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2048 "ipt_%s", rev.name);
2053 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2060 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2061 const struct ipt_replace *repl)
2064 struct xt_table_info *newinfo;
2065 struct xt_table_info bootstrap
2066 = { 0, 0, 0, { 0 }, { 0 }, { } };
2067 void *loc_cpu_entry;
2068 struct xt_table *new_table;
2070 newinfo = xt_alloc_table_info(repl->size);
2076 /* choose the copy on our node/cpu, but dont care about preemption */
2077 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2078 memcpy(loc_cpu_entry, repl->entries, repl->size);
2080 ret = translate_table(table->name, table->valid_hooks,
2081 newinfo, loc_cpu_entry, repl->size,
2088 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2089 if (IS_ERR(new_table)) {
2090 ret = PTR_ERR(new_table);
2097 xt_free_table_info(newinfo);
2099 return ERR_PTR(ret);
2102 void ipt_unregister_table(struct xt_table *table)
2104 struct xt_table_info *private;
2105 void *loc_cpu_entry;
2106 struct module *table_owner = table->me;
2108 private = xt_unregister_table(table);
2110 /* Decrease module usage counts and free resources */
2111 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2112 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2113 if (private->number > private->initial_entries)
2114 module_put(table_owner);
2115 xt_free_table_info(private);
2118 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2120 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2121 u_int8_t type, u_int8_t code,
2124 return ((test_type == 0xFF) ||
2125 (type == test_type && code >= min_code && code <= max_code))
2130 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2132 const struct icmphdr *ic;
2133 struct icmphdr _icmph;
2134 const struct ipt_icmp *icmpinfo = par->matchinfo;
2136 /* Must not be a fragment. */
2137 if (par->fragoff != 0)
2140 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2142 /* We've been asked to examine this packet, and we
2143 * can't. Hence, no choice but to drop.
2145 duprintf("Dropping evil ICMP tinygram.\n");
2146 *par->hotdrop = true;
2150 return icmp_type_code_match(icmpinfo->type,
2154 !!(icmpinfo->invflags&IPT_ICMP_INV));
2157 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2159 const struct ipt_icmp *icmpinfo = par->matchinfo;
2161 /* Must specify no unknown invflags */
2162 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2165 /* The built-in targets: standard (NULL) and error. */
2166 static struct xt_target ipt_standard_target __read_mostly = {
2167 .name = IPT_STANDARD_TARGET,
2168 .targetsize = sizeof(int),
2170 #ifdef CONFIG_COMPAT
2171 .compatsize = sizeof(compat_int_t),
2172 .compat_from_user = compat_standard_from_user,
2173 .compat_to_user = compat_standard_to_user,
2177 static struct xt_target ipt_error_target __read_mostly = {
2178 .name = IPT_ERROR_TARGET,
2179 .target = ipt_error,
2180 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2184 static struct nf_sockopt_ops ipt_sockopts = {
2186 .set_optmin = IPT_BASE_CTL,
2187 .set_optmax = IPT_SO_SET_MAX+1,
2188 .set = do_ipt_set_ctl,
2189 #ifdef CONFIG_COMPAT
2190 .compat_set = compat_do_ipt_set_ctl,
2192 .get_optmin = IPT_BASE_CTL,
2193 .get_optmax = IPT_SO_GET_MAX+1,
2194 .get = do_ipt_get_ctl,
2195 #ifdef CONFIG_COMPAT
2196 .compat_get = compat_do_ipt_get_ctl,
2198 .owner = THIS_MODULE,
2201 static struct xt_match icmp_matchstruct __read_mostly = {
2203 .match = icmp_match,
2204 .matchsize = sizeof(struct ipt_icmp),
2205 .checkentry = icmp_checkentry,
2206 .proto = IPPROTO_ICMP,
2210 static int __net_init ip_tables_net_init(struct net *net)
2212 return xt_proto_init(net, AF_INET);
2215 static void __net_exit ip_tables_net_exit(struct net *net)
2217 xt_proto_fini(net, AF_INET);
2220 static struct pernet_operations ip_tables_net_ops = {
2221 .init = ip_tables_net_init,
2222 .exit = ip_tables_net_exit,
2225 static int __init ip_tables_init(void)
2229 ret = register_pernet_subsys(&ip_tables_net_ops);
2233 /* Noone else will be downing sem now, so we won't sleep */
2234 ret = xt_register_target(&ipt_standard_target);
2237 ret = xt_register_target(&ipt_error_target);
2240 ret = xt_register_match(&icmp_matchstruct);
2244 /* Register setsockopt */
2245 ret = nf_register_sockopt(&ipt_sockopts);
2249 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2253 xt_unregister_match(&icmp_matchstruct);
2255 xt_unregister_target(&ipt_error_target);
2257 xt_unregister_target(&ipt_standard_target);
2259 unregister_pernet_subsys(&ip_tables_net_ops);
2264 static void __exit ip_tables_fini(void)
2266 nf_unregister_sockopt(&ipt_sockopts);
2268 xt_unregister_match(&icmp_matchstruct);
2269 xt_unregister_target(&ipt_error_target);
2270 xt_unregister_target(&ipt_standard_target);
2272 unregister_pernet_subsys(&ip_tables_net_ops);
2275 EXPORT_SYMBOL(ipt_register_table);
2276 EXPORT_SYMBOL(ipt_unregister_table);
2277 EXPORT_SYMBOL(ipt_do_table);
2278 module_init(ip_tables_init);
2279 module_exit(ip_tables_fini);