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,
88 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
90 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
92 || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
94 dprintf("Source or dest mismatch.\n");
96 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
97 &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
98 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
99 dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
100 &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
101 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
105 ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
107 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
108 dprintf("VIA in mismatch (%s vs %s).%s\n",
109 indev, ipinfo->iniface,
110 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
114 ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
116 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
117 dprintf("VIA out mismatch (%s vs %s).%s\n",
118 outdev, ipinfo->outiface,
119 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
123 /* Check specific protocol */
125 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
126 dprintf("Packet protocol %hi does not match %hi.%s\n",
127 ip->protocol, ipinfo->proto,
128 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
132 /* If we have a fragment rule but the packet is not a fragment
133 * then we return zero */
134 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
135 dprintf("Fragment rule but not fragment.%s\n",
136 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
144 ip_checkentry(const struct ipt_ip *ip)
146 if (ip->flags & ~IPT_F_MASK) {
147 duprintf("Unknown flag bits set: %08X\n",
148 ip->flags & ~IPT_F_MASK);
151 if (ip->invflags & ~IPT_INV_MASK) {
152 duprintf("Unknown invflag bits set: %08X\n",
153 ip->invflags & ~IPT_INV_MASK);
160 ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
163 printk("ip_tables: error: `%s'\n",
164 (const char *)par->targinfo);
169 /* Performance critical - called for every packet */
171 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
172 struct xt_match_param *par)
174 par->match = m->u.kernel.match;
175 par->matchinfo = m->data;
177 /* Stop iteration if it doesn't match */
178 if (!m->u.kernel.match->match(skb, par))
184 /* Performance critical */
185 static inline struct ipt_entry *
186 get_entry(void *base, unsigned int offset)
188 return (struct ipt_entry *)(base + offset);
191 /* All zeroes == unconditional rule. */
192 /* Mildly perf critical (only if packet tracing is on) */
194 unconditional(const struct ipt_ip *ip)
198 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
199 if (((__u32 *)ip)[i])
206 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
207 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
208 static const char *const hooknames[] = {
209 [NF_INET_PRE_ROUTING] = "PREROUTING",
210 [NF_INET_LOCAL_IN] = "INPUT",
211 [NF_INET_FORWARD] = "FORWARD",
212 [NF_INET_LOCAL_OUT] = "OUTPUT",
213 [NF_INET_POST_ROUTING] = "POSTROUTING",
216 enum nf_ip_trace_comments {
217 NF_IP_TRACE_COMMENT_RULE,
218 NF_IP_TRACE_COMMENT_RETURN,
219 NF_IP_TRACE_COMMENT_POLICY,
222 static const char *const comments[] = {
223 [NF_IP_TRACE_COMMENT_RULE] = "rule",
224 [NF_IP_TRACE_COMMENT_RETURN] = "return",
225 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
228 static struct nf_loginfo trace_loginfo = {
229 .type = NF_LOG_TYPE_LOG,
233 .logflags = NF_LOG_MASK,
238 /* Mildly perf critical (only if packet tracing is on) */
240 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
241 const char *hookname, const char **chainname,
242 const char **comment, unsigned int *rulenum)
244 struct ipt_standard_target *t = (void *)ipt_get_target(s);
246 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
247 /* Head of user chain: ERROR target with chainname */
248 *chainname = t->target.data;
253 if (s->target_offset == sizeof(struct ipt_entry)
254 && strcmp(t->target.u.kernel.target->name,
255 IPT_STANDARD_TARGET) == 0
257 && unconditional(&s->ip)) {
258 /* Tail of chains: STANDARD target (return/policy) */
259 *comment = *chainname == hookname
260 ? comments[NF_IP_TRACE_COMMENT_POLICY]
261 : comments[NF_IP_TRACE_COMMENT_RETURN];
270 static void trace_packet(struct sk_buff *skb,
272 const struct net_device *in,
273 const struct net_device *out,
274 const char *tablename,
275 struct xt_table_info *private,
279 const struct ipt_entry *root;
280 const char *hookname, *chainname, *comment;
281 unsigned int rulenum = 0;
283 table_base = private->entries[smp_processor_id()];
284 root = get_entry(table_base, private->hook_entry[hook]);
286 hookname = chainname = hooknames[hook];
287 comment = comments[NF_IP_TRACE_COMMENT_RULE];
289 IPT_ENTRY_ITERATE(root,
290 private->size - private->hook_entry[hook],
291 get_chainname_rulenum,
292 e, hookname, &chainname, &comment, &rulenum);
294 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
295 "TRACE: %s:%s:%s:%u ",
296 tablename, chainname, comment, rulenum);
301 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
303 return (void *)entry + entry->next_offset;
306 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
308 ipt_do_table(struct sk_buff *skb,
310 const struct net_device *in,
311 const struct net_device *out,
312 struct xt_table *table)
314 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
315 const struct iphdr *ip;
317 bool hotdrop = false;
318 /* Initializing verdict to NF_DROP keeps gcc happy. */
319 unsigned int verdict = NF_DROP;
320 const char *indev, *outdev;
322 struct ipt_entry *e, *back;
323 struct xt_table_info *private;
324 struct xt_match_param mtpar;
325 struct xt_target_param tgpar;
329 datalen = skb->len - ip->ihl * 4;
330 indev = in ? in->name : nulldevname;
331 outdev = out ? out->name : nulldevname;
332 /* We handle fragments by dealing with the first fragment as
333 * if it was a normal packet. All other fragments are treated
334 * normally, except that they will NEVER match rules that ask
335 * things we don't know, ie. tcp syn flag or ports). If the
336 * rule is also a fragment-specific rule, non-fragments won't
338 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
339 mtpar.thoff = ip_hdrlen(skb);
340 mtpar.hotdrop = &hotdrop;
341 mtpar.in = tgpar.in = in;
342 mtpar.out = tgpar.out = out;
343 mtpar.family = tgpar.family = NFPROTO_IPV4;
344 tgpar.hooknum = hook;
346 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
348 private = table->private;
349 table_base = private->entries[smp_processor_id()];
351 e = get_entry(table_base, private->hook_entry[hook]);
353 /* For return from builtin chain */
354 back = get_entry(table_base, private->underflow[hook]);
359 if (ip_packet_match(ip, indev, outdev,
360 &e->ip, mtpar.fragoff)) {
361 struct ipt_entry_target *t;
363 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
366 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
368 t = ipt_get_target(e);
369 IP_NF_ASSERT(t->u.kernel.target);
371 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
372 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
373 /* The packet is traced: log it */
374 if (unlikely(skb->nf_trace))
375 trace_packet(skb, hook, in, out,
376 table->name, private, e);
378 /* Standard target? */
379 if (!t->u.kernel.target->target) {
382 v = ((struct ipt_standard_target *)t)->verdict;
384 /* Pop from stack? */
385 if (v != IPT_RETURN) {
386 verdict = (unsigned)(-v) - 1;
390 back = get_entry(table_base,
394 if (table_base + v != ipt_next_entry(e)
395 && !(e->ip.flags & IPT_F_GOTO)) {
396 /* Save old back ptr in next entry */
397 struct ipt_entry *next
400 = (void *)back - table_base;
401 /* set back pointer to next entry */
405 e = get_entry(table_base, v);
407 /* Targets which reenter must return
409 tgpar.target = t->u.kernel.target;
410 tgpar.targinfo = t->data;
411 #ifdef CONFIG_NETFILTER_DEBUG
412 ((struct ipt_entry *)table_base)->comefrom
415 verdict = t->u.kernel.target->target(skb,
417 #ifdef CONFIG_NETFILTER_DEBUG
418 if (((struct ipt_entry *)table_base)->comefrom
420 && verdict == IPT_CONTINUE) {
421 printk("Target %s reentered!\n",
422 t->u.kernel.target->name);
425 ((struct ipt_entry *)table_base)->comefrom
428 /* Target might have changed stuff. */
430 datalen = skb->len - ip->ihl * 4;
432 if (verdict == IPT_CONTINUE)
433 e = ipt_next_entry(e);
441 e = ipt_next_entry(e);
444 xt_info_rdunlock_bh();
446 #ifdef DEBUG_ALLOW_ALL
455 /* Figures out from what hook each rule can be called: returns 0 if
456 there are loops. Puts hook bitmask in comefrom. */
458 mark_source_chains(struct xt_table_info *newinfo,
459 unsigned int valid_hooks, void *entry0)
463 /* No recursion; use packet counter to save back ptrs (reset
464 to 0 as we leave), and comefrom to save source hook bitmask */
465 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
466 unsigned int pos = newinfo->hook_entry[hook];
467 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
469 if (!(valid_hooks & (1 << hook)))
472 /* Set initial back pointer. */
473 e->counters.pcnt = pos;
476 struct ipt_standard_target *t
477 = (void *)ipt_get_target(e);
478 int visited = e->comefrom & (1 << hook);
480 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
481 printk("iptables: loop hook %u pos %u %08X.\n",
482 hook, pos, e->comefrom);
485 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
487 /* Unconditional return/END. */
488 if ((e->target_offset == sizeof(struct ipt_entry)
489 && (strcmp(t->target.u.user.name,
490 IPT_STANDARD_TARGET) == 0)
492 && unconditional(&e->ip)) || visited) {
493 unsigned int oldpos, size;
495 if ((strcmp(t->target.u.user.name,
496 IPT_STANDARD_TARGET) == 0) &&
497 t->verdict < -NF_MAX_VERDICT - 1) {
498 duprintf("mark_source_chains: bad "
499 "negative verdict (%i)\n",
504 /* Return: backtrack through the last
507 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
508 #ifdef DEBUG_IP_FIREWALL_USER
510 & (1 << NF_INET_NUMHOOKS)) {
511 duprintf("Back unset "
518 pos = e->counters.pcnt;
519 e->counters.pcnt = 0;
521 /* We're at the start. */
525 e = (struct ipt_entry *)
527 } while (oldpos == pos + e->next_offset);
530 size = e->next_offset;
531 e = (struct ipt_entry *)
532 (entry0 + pos + size);
533 e->counters.pcnt = pos;
536 int newpos = t->verdict;
538 if (strcmp(t->target.u.user.name,
539 IPT_STANDARD_TARGET) == 0
541 if (newpos > newinfo->size -
542 sizeof(struct ipt_entry)) {
543 duprintf("mark_source_chains: "
544 "bad verdict (%i)\n",
548 /* This a jump; chase it. */
549 duprintf("Jump rule %u -> %u\n",
552 /* ... this is a fallthru */
553 newpos = pos + e->next_offset;
555 e = (struct ipt_entry *)
557 e->counters.pcnt = pos;
562 duprintf("Finished chain %u\n", hook);
568 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
570 struct xt_mtdtor_param par;
572 if (i && (*i)-- == 0)
575 par.match = m->u.kernel.match;
576 par.matchinfo = m->data;
577 par.family = NFPROTO_IPV4;
578 if (par.match->destroy != NULL)
579 par.match->destroy(&par);
580 module_put(par.match->me);
585 check_entry(struct ipt_entry *e, const char *name)
587 struct ipt_entry_target *t;
589 if (!ip_checkentry(&e->ip)) {
590 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
594 if (e->target_offset + sizeof(struct ipt_entry_target) >
598 t = ipt_get_target(e);
599 if (e->target_offset + t->u.target_size > e->next_offset)
606 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
609 const struct ipt_ip *ip = par->entryinfo;
612 par->match = m->u.kernel.match;
613 par->matchinfo = m->data;
615 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
616 ip->proto, ip->invflags & IPT_INV_PROTO);
618 duprintf("ip_tables: check failed for `%s'.\n",
627 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
630 struct xt_match *match;
633 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
635 "ipt_%s", m->u.user.name);
636 if (IS_ERR(match) || !match) {
637 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
638 return match ? PTR_ERR(match) : -ENOENT;
640 m->u.kernel.match = match;
642 ret = check_match(m, par, i);
648 module_put(m->u.kernel.match->me);
652 static int check_target(struct ipt_entry *e, const char *name)
654 struct ipt_entry_target *t = ipt_get_target(e);
655 struct xt_tgchk_param par = {
658 .target = t->u.kernel.target,
660 .hook_mask = e->comefrom,
661 .family = NFPROTO_IPV4,
665 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
666 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
668 duprintf("ip_tables: check failed for `%s'.\n",
669 t->u.kernel.target->name);
676 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
679 struct ipt_entry_target *t;
680 struct xt_target *target;
683 struct xt_mtchk_param mtpar;
685 ret = check_entry(e, name);
691 mtpar.entryinfo = &e->ip;
692 mtpar.hook_mask = e->comefrom;
693 mtpar.family = NFPROTO_IPV4;
694 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
696 goto cleanup_matches;
698 t = ipt_get_target(e);
699 target = try_then_request_module(xt_find_target(AF_INET,
702 "ipt_%s", t->u.user.name);
703 if (IS_ERR(target) || !target) {
704 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
705 ret = target ? PTR_ERR(target) : -ENOENT;
706 goto cleanup_matches;
708 t->u.kernel.target = target;
710 ret = check_target(e, name);
717 module_put(t->u.kernel.target->me);
719 IPT_MATCH_ITERATE(e, cleanup_match, &j);
724 check_entry_size_and_hooks(struct ipt_entry *e,
725 struct xt_table_info *newinfo,
727 unsigned char *limit,
728 const unsigned int *hook_entries,
729 const unsigned int *underflows,
734 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
735 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
736 duprintf("Bad offset %p\n", e);
741 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
742 duprintf("checking: element %p size %u\n",
747 /* Check hooks & underflows */
748 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
749 if ((unsigned char *)e - base == hook_entries[h])
750 newinfo->hook_entry[h] = hook_entries[h];
751 if ((unsigned char *)e - base == underflows[h])
752 newinfo->underflow[h] = underflows[h];
755 /* FIXME: underflows must be unconditional, standard verdicts
756 < 0 (not IPT_RETURN). --RR */
758 /* Clear counters and comefrom */
759 e->counters = ((struct xt_counters) { 0, 0 });
767 cleanup_entry(struct ipt_entry *e, unsigned int *i)
769 struct xt_tgdtor_param par;
770 struct ipt_entry_target *t;
772 if (i && (*i)-- == 0)
775 /* Cleanup all matches */
776 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
777 t = ipt_get_target(e);
779 par.target = t->u.kernel.target;
780 par.targinfo = t->data;
781 par.family = NFPROTO_IPV4;
782 if (par.target->destroy != NULL)
783 par.target->destroy(&par);
784 module_put(par.target->me);
788 /* Checks and translates the user-supplied table segment (held in
791 translate_table(const char *name,
792 unsigned int valid_hooks,
793 struct xt_table_info *newinfo,
797 const unsigned int *hook_entries,
798 const unsigned int *underflows)
803 newinfo->size = size;
804 newinfo->number = number;
806 /* Init all hooks to impossible value. */
807 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
808 newinfo->hook_entry[i] = 0xFFFFFFFF;
809 newinfo->underflow[i] = 0xFFFFFFFF;
812 duprintf("translate_table: size %u\n", newinfo->size);
814 /* Walk through entries, checking offsets. */
815 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
816 check_entry_size_and_hooks,
820 hook_entries, underflows, &i);
825 duprintf("translate_table: %u not %u entries\n",
830 /* Check hooks all assigned */
831 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
832 /* Only hooks which are valid */
833 if (!(valid_hooks & (1 << i)))
835 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
836 duprintf("Invalid hook entry %u %u\n",
840 if (newinfo->underflow[i] == 0xFFFFFFFF) {
841 duprintf("Invalid underflow %u %u\n",
847 if (!mark_source_chains(newinfo, valid_hooks, entry0))
850 /* Finally, each sanity check must pass */
852 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
853 find_check_entry, name, size, &i);
856 IPT_ENTRY_ITERATE(entry0, newinfo->size,
861 /* And one copy for every other CPU */
862 for_each_possible_cpu(i) {
863 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
864 memcpy(newinfo->entries[i], entry0, newinfo->size);
872 add_entry_to_counter(const struct ipt_entry *e,
873 struct xt_counters total[],
876 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
883 set_entry_to_counter(const struct ipt_entry *e,
884 struct ipt_counters total[],
887 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
894 get_counters(const struct xt_table_info *t,
895 struct xt_counters counters[])
901 /* Instead of clearing (by a previous call to memset())
902 * the counters and using adds, we set the counters
903 * with data used by 'current' CPU.
905 * Bottom half has to be disabled to prevent deadlock
906 * if new softirq were to run and call ipt_do_table
909 curcpu = smp_processor_id();
912 IPT_ENTRY_ITERATE(t->entries[curcpu],
914 set_entry_to_counter,
918 for_each_possible_cpu(cpu) {
923 IPT_ENTRY_ITERATE(t->entries[cpu],
925 add_entry_to_counter,
928 xt_info_wrunlock(cpu);
933 static struct xt_counters * alloc_counters(struct xt_table *table)
935 unsigned int countersize;
936 struct xt_counters *counters;
937 struct xt_table_info *private = table->private;
939 /* We need atomic snapshot of counters: rest doesn't change
940 (other than comefrom, which userspace doesn't care
942 countersize = sizeof(struct xt_counters) * private->number;
943 counters = vmalloc_node(countersize, numa_node_id());
945 if (counters == NULL)
946 return ERR_PTR(-ENOMEM);
948 get_counters(private, counters);
954 copy_entries_to_user(unsigned int total_size,
955 struct xt_table *table,
956 void __user *userptr)
958 unsigned int off, num;
960 struct xt_counters *counters;
961 const struct xt_table_info *private = table->private;
963 const void *loc_cpu_entry;
965 counters = alloc_counters(table);
966 if (IS_ERR(counters))
967 return PTR_ERR(counters);
969 /* choose the copy that is on our node/cpu, ...
970 * This choice is lazy (because current thread is
971 * allowed to migrate to another cpu)
973 loc_cpu_entry = private->entries[raw_smp_processor_id()];
974 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
979 /* FIXME: use iterator macros --RR */
980 /* ... then go back and fix counters and names */
981 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
983 const struct ipt_entry_match *m;
984 const struct ipt_entry_target *t;
986 e = (struct ipt_entry *)(loc_cpu_entry + off);
987 if (copy_to_user(userptr + off
988 + offsetof(struct ipt_entry, counters),
990 sizeof(counters[num])) != 0) {
995 for (i = sizeof(struct ipt_entry);
996 i < e->target_offset;
997 i += m->u.match_size) {
1000 if (copy_to_user(userptr + off + i
1001 + offsetof(struct ipt_entry_match,
1003 m->u.kernel.match->name,
1004 strlen(m->u.kernel.match->name)+1)
1011 t = ipt_get_target(e);
1012 if (copy_to_user(userptr + off + e->target_offset
1013 + offsetof(struct ipt_entry_target,
1015 t->u.kernel.target->name,
1016 strlen(t->u.kernel.target->name)+1) != 0) {
1027 #ifdef CONFIG_COMPAT
1028 static void compat_standard_from_user(void *dst, void *src)
1030 int v = *(compat_int_t *)src;
1033 v += xt_compat_calc_jump(AF_INET, v);
1034 memcpy(dst, &v, sizeof(v));
1037 static int compat_standard_to_user(void __user *dst, void *src)
1039 compat_int_t cv = *(int *)src;
1042 cv -= xt_compat_calc_jump(AF_INET, cv);
1043 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1047 compat_calc_match(struct ipt_entry_match *m, int *size)
1049 *size += xt_compat_match_offset(m->u.kernel.match);
1053 static int compat_calc_entry(struct ipt_entry *e,
1054 const struct xt_table_info *info,
1055 void *base, struct xt_table_info *newinfo)
1057 struct ipt_entry_target *t;
1058 unsigned int entry_offset;
1061 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1062 entry_offset = (void *)e - base;
1063 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1064 t = ipt_get_target(e);
1065 off += xt_compat_target_offset(t->u.kernel.target);
1066 newinfo->size -= off;
1067 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1071 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1072 if (info->hook_entry[i] &&
1073 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1074 newinfo->hook_entry[i] -= off;
1075 if (info->underflow[i] &&
1076 (e < (struct ipt_entry *)(base + info->underflow[i])))
1077 newinfo->underflow[i] -= off;
1082 static int compat_table_info(const struct xt_table_info *info,
1083 struct xt_table_info *newinfo)
1085 void *loc_cpu_entry;
1087 if (!newinfo || !info)
1090 /* we dont care about newinfo->entries[] */
1091 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1092 newinfo->initial_entries = 0;
1093 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1094 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1095 compat_calc_entry, info, loc_cpu_entry,
1100 static int get_info(struct net *net, void __user *user, int *len, int compat)
1102 char name[IPT_TABLE_MAXNAMELEN];
1106 if (*len != sizeof(struct ipt_getinfo)) {
1107 duprintf("length %u != %zu\n", *len,
1108 sizeof(struct ipt_getinfo));
1112 if (copy_from_user(name, user, sizeof(name)) != 0)
1115 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1116 #ifdef CONFIG_COMPAT
1118 xt_compat_lock(AF_INET);
1120 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1121 "iptable_%s", name);
1122 if (t && !IS_ERR(t)) {
1123 struct ipt_getinfo info;
1124 const struct xt_table_info *private = t->private;
1126 #ifdef CONFIG_COMPAT
1128 struct xt_table_info tmp;
1129 ret = compat_table_info(private, &tmp);
1130 xt_compat_flush_offsets(AF_INET);
1134 info.valid_hooks = t->valid_hooks;
1135 memcpy(info.hook_entry, private->hook_entry,
1136 sizeof(info.hook_entry));
1137 memcpy(info.underflow, private->underflow,
1138 sizeof(info.underflow));
1139 info.num_entries = private->number;
1140 info.size = private->size;
1141 strcpy(info.name, name);
1143 if (copy_to_user(user, &info, *len) != 0)
1151 ret = t ? PTR_ERR(t) : -ENOENT;
1152 #ifdef CONFIG_COMPAT
1154 xt_compat_unlock(AF_INET);
1160 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1163 struct ipt_get_entries get;
1166 if (*len < sizeof(get)) {
1167 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1170 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1172 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1173 duprintf("get_entries: %u != %zu\n",
1174 *len, sizeof(get) + get.size);
1178 t = xt_find_table_lock(net, AF_INET, get.name);
1179 if (t && !IS_ERR(t)) {
1180 const struct xt_table_info *private = t->private;
1181 duprintf("t->private->number = %u\n", private->number);
1182 if (get.size == private->size)
1183 ret = copy_entries_to_user(private->size,
1184 t, uptr->entrytable);
1186 duprintf("get_entries: I've got %u not %u!\n",
1187 private->size, get.size);
1193 ret = t ? PTR_ERR(t) : -ENOENT;
1199 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1200 struct xt_table_info *newinfo, unsigned int num_counters,
1201 void __user *counters_ptr)
1205 struct xt_table_info *oldinfo;
1206 struct xt_counters *counters;
1207 void *loc_cpu_old_entry;
1210 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1216 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1217 "iptable_%s", name);
1218 if (!t || IS_ERR(t)) {
1219 ret = t ? PTR_ERR(t) : -ENOENT;
1220 goto free_newinfo_counters_untrans;
1224 if (valid_hooks != t->valid_hooks) {
1225 duprintf("Valid hook crap: %08X vs %08X\n",
1226 valid_hooks, t->valid_hooks);
1231 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1235 /* Update module usage count based on number of rules */
1236 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1237 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1238 if ((oldinfo->number > oldinfo->initial_entries) ||
1239 (newinfo->number <= oldinfo->initial_entries))
1241 if ((oldinfo->number > oldinfo->initial_entries) &&
1242 (newinfo->number <= oldinfo->initial_entries))
1245 /* Get the old counters, and synchronize with replace */
1246 get_counters(oldinfo, counters);
1248 /* Decrease module usage counts and free resource */
1249 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1250 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1252 xt_free_table_info(oldinfo);
1253 if (copy_to_user(counters_ptr, counters,
1254 sizeof(struct xt_counters) * num_counters) != 0)
1263 free_newinfo_counters_untrans:
1270 do_replace(struct net *net, void __user *user, unsigned int len)
1273 struct ipt_replace tmp;
1274 struct xt_table_info *newinfo;
1275 void *loc_cpu_entry;
1277 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1280 /* overflow check */
1281 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1284 newinfo = xt_alloc_table_info(tmp.size);
1288 /* choose the copy that is on our node/cpu */
1289 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1290 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1296 ret = translate_table(tmp.name, tmp.valid_hooks,
1297 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1298 tmp.hook_entry, tmp.underflow);
1302 duprintf("ip_tables: Translated table\n");
1304 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1305 tmp.num_counters, tmp.counters);
1307 goto free_newinfo_untrans;
1310 free_newinfo_untrans:
1311 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1313 xt_free_table_info(newinfo);
1317 /* We're lazy, and add to the first CPU; overflow works its fey magic
1318 * and everything is OK. */
1320 add_counter_to_entry(struct ipt_entry *e,
1321 const struct xt_counters addme[],
1324 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1331 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1333 unsigned int i, curcpu;
1334 struct xt_counters_info tmp;
1335 struct xt_counters *paddc;
1336 unsigned int num_counters;
1341 const struct xt_table_info *private;
1343 void *loc_cpu_entry;
1344 #ifdef CONFIG_COMPAT
1345 struct compat_xt_counters_info compat_tmp;
1349 size = sizeof(struct compat_xt_counters_info);
1354 size = sizeof(struct xt_counters_info);
1357 if (copy_from_user(ptmp, user, size) != 0)
1360 #ifdef CONFIG_COMPAT
1362 num_counters = compat_tmp.num_counters;
1363 name = compat_tmp.name;
1367 num_counters = tmp.num_counters;
1371 if (len != size + num_counters * sizeof(struct xt_counters))
1374 paddc = vmalloc_node(len - size, numa_node_id());
1378 if (copy_from_user(paddc, user + size, len - size) != 0) {
1383 t = xt_find_table_lock(net, AF_INET, name);
1384 if (!t || IS_ERR(t)) {
1385 ret = t ? PTR_ERR(t) : -ENOENT;
1390 private = t->private;
1391 if (private->number != num_counters) {
1393 goto unlock_up_free;
1397 /* Choose the copy that is on our node */
1398 curcpu = smp_processor_id();
1399 loc_cpu_entry = private->entries[curcpu];
1400 xt_info_wrlock(curcpu);
1401 IPT_ENTRY_ITERATE(loc_cpu_entry,
1403 add_counter_to_entry,
1406 xt_info_wrunlock(curcpu);
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 mtpar.family = NFPROTO_IPV4;
1660 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1662 goto cleanup_matches;
1664 ret = check_target(e, name);
1666 goto cleanup_matches;
1672 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1677 translate_compat_table(const char *name,
1678 unsigned int valid_hooks,
1679 struct xt_table_info **pinfo,
1681 unsigned int total_size,
1682 unsigned int number,
1683 unsigned int *hook_entries,
1684 unsigned int *underflows)
1687 struct xt_table_info *newinfo, *info;
1688 void *pos, *entry0, *entry1;
1695 info->number = number;
1697 /* Init all hooks to impossible value. */
1698 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1699 info->hook_entry[i] = 0xFFFFFFFF;
1700 info->underflow[i] = 0xFFFFFFFF;
1703 duprintf("translate_compat_table: size %u\n", info->size);
1705 xt_compat_lock(AF_INET);
1706 /* Walk through entries, checking offsets. */
1707 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1708 check_compat_entry_size_and_hooks,
1709 info, &size, entry0,
1710 entry0 + total_size,
1711 hook_entries, underflows, &j, name);
1717 duprintf("translate_compat_table: %u not %u entries\n",
1722 /* Check hooks all assigned */
1723 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1724 /* Only hooks which are valid */
1725 if (!(valid_hooks & (1 << i)))
1727 if (info->hook_entry[i] == 0xFFFFFFFF) {
1728 duprintf("Invalid hook entry %u %u\n",
1729 i, hook_entries[i]);
1732 if (info->underflow[i] == 0xFFFFFFFF) {
1733 duprintf("Invalid underflow %u %u\n",
1740 newinfo = xt_alloc_table_info(size);
1744 newinfo->number = number;
1745 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1746 newinfo->hook_entry[i] = info->hook_entry[i];
1747 newinfo->underflow[i] = info->underflow[i];
1749 entry1 = newinfo->entries[raw_smp_processor_id()];
1752 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1753 compat_copy_entry_from_user,
1754 &pos, &size, name, newinfo, entry1);
1755 xt_compat_flush_offsets(AF_INET);
1756 xt_compat_unlock(AF_INET);
1761 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1765 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1769 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1770 compat_release_entry, &j);
1771 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1772 xt_free_table_info(newinfo);
1776 /* And one copy for every other CPU */
1777 for_each_possible_cpu(i)
1778 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1779 memcpy(newinfo->entries[i], entry1, newinfo->size);
1783 xt_free_table_info(info);
1787 xt_free_table_info(newinfo);
1789 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1792 xt_compat_flush_offsets(AF_INET);
1793 xt_compat_unlock(AF_INET);
1798 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1801 struct compat_ipt_replace tmp;
1802 struct xt_table_info *newinfo;
1803 void *loc_cpu_entry;
1805 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1808 /* overflow check */
1809 if (tmp.size >= INT_MAX / num_possible_cpus())
1811 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1814 newinfo = xt_alloc_table_info(tmp.size);
1818 /* choose the copy that is on our node/cpu */
1819 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1820 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1826 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1827 &newinfo, &loc_cpu_entry, tmp.size,
1828 tmp.num_entries, tmp.hook_entry,
1833 duprintf("compat_do_replace: Translated table\n");
1835 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1836 tmp.num_counters, compat_ptr(tmp.counters));
1838 goto free_newinfo_untrans;
1841 free_newinfo_untrans:
1842 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1844 xt_free_table_info(newinfo);
1849 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1854 if (!capable(CAP_NET_ADMIN))
1858 case IPT_SO_SET_REPLACE:
1859 ret = compat_do_replace(sock_net(sk), user, len);
1862 case IPT_SO_SET_ADD_COUNTERS:
1863 ret = do_add_counters(sock_net(sk), user, len, 1);
1867 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1874 struct compat_ipt_get_entries {
1875 char name[IPT_TABLE_MAXNAMELEN];
1877 struct compat_ipt_entry entrytable[0];
1881 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1882 void __user *userptr)
1884 struct xt_counters *counters;
1885 const struct xt_table_info *private = table->private;
1889 const void *loc_cpu_entry;
1892 counters = alloc_counters(table);
1893 if (IS_ERR(counters))
1894 return PTR_ERR(counters);
1896 /* choose the copy that is on our node/cpu, ...
1897 * This choice is lazy (because current thread is
1898 * allowed to migrate to another cpu)
1900 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1903 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1904 compat_copy_entry_to_user,
1905 &pos, &size, counters, &i);
1912 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1916 struct compat_ipt_get_entries get;
1919 if (*len < sizeof(get)) {
1920 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1924 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1927 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1928 duprintf("compat_get_entries: %u != %zu\n",
1929 *len, sizeof(get) + get.size);
1933 xt_compat_lock(AF_INET);
1934 t = xt_find_table_lock(net, AF_INET, get.name);
1935 if (t && !IS_ERR(t)) {
1936 const struct xt_table_info *private = t->private;
1937 struct xt_table_info info;
1938 duprintf("t->private->number = %u\n", private->number);
1939 ret = compat_table_info(private, &info);
1940 if (!ret && get.size == info.size) {
1941 ret = compat_copy_entries_to_user(private->size,
1942 t, uptr->entrytable);
1944 duprintf("compat_get_entries: I've got %u not %u!\n",
1945 private->size, get.size);
1948 xt_compat_flush_offsets(AF_INET);
1952 ret = t ? PTR_ERR(t) : -ENOENT;
1954 xt_compat_unlock(AF_INET);
1958 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1961 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1965 if (!capable(CAP_NET_ADMIN))
1969 case IPT_SO_GET_INFO:
1970 ret = get_info(sock_net(sk), user, len, 1);
1972 case IPT_SO_GET_ENTRIES:
1973 ret = compat_get_entries(sock_net(sk), user, len);
1976 ret = do_ipt_get_ctl(sk, cmd, user, len);
1983 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1987 if (!capable(CAP_NET_ADMIN))
1991 case IPT_SO_SET_REPLACE:
1992 ret = do_replace(sock_net(sk), user, len);
1995 case IPT_SO_SET_ADD_COUNTERS:
1996 ret = do_add_counters(sock_net(sk), user, len, 0);
2000 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2008 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2012 if (!capable(CAP_NET_ADMIN))
2016 case IPT_SO_GET_INFO:
2017 ret = get_info(sock_net(sk), user, len, 0);
2020 case IPT_SO_GET_ENTRIES:
2021 ret = get_entries(sock_net(sk), user, len);
2024 case IPT_SO_GET_REVISION_MATCH:
2025 case IPT_SO_GET_REVISION_TARGET: {
2026 struct ipt_get_revision rev;
2029 if (*len != sizeof(rev)) {
2033 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2038 if (cmd == IPT_SO_GET_REVISION_TARGET)
2043 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2046 "ipt_%s", rev.name);
2051 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2058 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2059 const struct ipt_replace *repl)
2062 struct xt_table_info *newinfo;
2063 struct xt_table_info bootstrap
2064 = { 0, 0, 0, { 0 }, { 0 }, { } };
2065 void *loc_cpu_entry;
2066 struct xt_table *new_table;
2068 newinfo = xt_alloc_table_info(repl->size);
2074 /* choose the copy on our node/cpu, but dont care about preemption */
2075 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2076 memcpy(loc_cpu_entry, repl->entries, repl->size);
2078 ret = translate_table(table->name, table->valid_hooks,
2079 newinfo, loc_cpu_entry, repl->size,
2086 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2087 if (IS_ERR(new_table)) {
2088 ret = PTR_ERR(new_table);
2095 xt_free_table_info(newinfo);
2097 return ERR_PTR(ret);
2100 void ipt_unregister_table(struct xt_table *table)
2102 struct xt_table_info *private;
2103 void *loc_cpu_entry;
2104 struct module *table_owner = table->me;
2106 private = xt_unregister_table(table);
2108 /* Decrease module usage counts and free resources */
2109 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2110 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2111 if (private->number > private->initial_entries)
2112 module_put(table_owner);
2113 xt_free_table_info(private);
2116 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2118 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2119 u_int8_t type, u_int8_t code,
2122 return ((test_type == 0xFF) ||
2123 (type == test_type && code >= min_code && code <= max_code))
2128 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2130 const struct icmphdr *ic;
2131 struct icmphdr _icmph;
2132 const struct ipt_icmp *icmpinfo = par->matchinfo;
2134 /* Must not be a fragment. */
2135 if (par->fragoff != 0)
2138 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2140 /* We've been asked to examine this packet, and we
2141 * can't. Hence, no choice but to drop.
2143 duprintf("Dropping evil ICMP tinygram.\n");
2144 *par->hotdrop = true;
2148 return icmp_type_code_match(icmpinfo->type,
2152 !!(icmpinfo->invflags&IPT_ICMP_INV));
2155 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2157 const struct ipt_icmp *icmpinfo = par->matchinfo;
2159 /* Must specify no unknown invflags */
2160 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2163 /* The built-in targets: standard (NULL) and error. */
2164 static struct xt_target ipt_standard_target __read_mostly = {
2165 .name = IPT_STANDARD_TARGET,
2166 .targetsize = sizeof(int),
2167 .family = NFPROTO_IPV4,
2168 #ifdef CONFIG_COMPAT
2169 .compatsize = sizeof(compat_int_t),
2170 .compat_from_user = compat_standard_from_user,
2171 .compat_to_user = compat_standard_to_user,
2175 static struct xt_target ipt_error_target __read_mostly = {
2176 .name = IPT_ERROR_TARGET,
2177 .target = ipt_error,
2178 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2179 .family = NFPROTO_IPV4,
2182 static struct nf_sockopt_ops ipt_sockopts = {
2184 .set_optmin = IPT_BASE_CTL,
2185 .set_optmax = IPT_SO_SET_MAX+1,
2186 .set = do_ipt_set_ctl,
2187 #ifdef CONFIG_COMPAT
2188 .compat_set = compat_do_ipt_set_ctl,
2190 .get_optmin = IPT_BASE_CTL,
2191 .get_optmax = IPT_SO_GET_MAX+1,
2192 .get = do_ipt_get_ctl,
2193 #ifdef CONFIG_COMPAT
2194 .compat_get = compat_do_ipt_get_ctl,
2196 .owner = THIS_MODULE,
2199 static struct xt_match icmp_matchstruct __read_mostly = {
2201 .match = icmp_match,
2202 .matchsize = sizeof(struct ipt_icmp),
2203 .checkentry = icmp_checkentry,
2204 .proto = IPPROTO_ICMP,
2205 .family = NFPROTO_IPV4,
2208 static int __net_init ip_tables_net_init(struct net *net)
2210 return xt_proto_init(net, NFPROTO_IPV4);
2213 static void __net_exit ip_tables_net_exit(struct net *net)
2215 xt_proto_fini(net, NFPROTO_IPV4);
2218 static struct pernet_operations ip_tables_net_ops = {
2219 .init = ip_tables_net_init,
2220 .exit = ip_tables_net_exit,
2223 static int __init ip_tables_init(void)
2227 ret = register_pernet_subsys(&ip_tables_net_ops);
2231 /* Noone else will be downing sem now, so we won't sleep */
2232 ret = xt_register_target(&ipt_standard_target);
2235 ret = xt_register_target(&ipt_error_target);
2238 ret = xt_register_match(&icmp_matchstruct);
2242 /* Register setsockopt */
2243 ret = nf_register_sockopt(&ipt_sockopts);
2247 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2251 xt_unregister_match(&icmp_matchstruct);
2253 xt_unregister_target(&ipt_error_target);
2255 xt_unregister_target(&ipt_standard_target);
2257 unregister_pernet_subsys(&ip_tables_net_ops);
2262 static void __exit ip_tables_fini(void)
2264 nf_unregister_sockopt(&ipt_sockopts);
2266 xt_unregister_match(&icmp_matchstruct);
2267 xt_unregister_target(&ipt_error_target);
2268 xt_unregister_target(&ipt_standard_target);
2270 unregister_pernet_subsys(&ip_tables_net_ops);
2273 EXPORT_SYMBOL(ipt_register_table);
2274 EXPORT_SYMBOL(ipt_unregister_table);
2275 EXPORT_SYMBOL(ipt_do_table);
2276 module_init(ip_tables_init);
2277 module_exit(ip_tables_fini);