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 #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
316 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
317 const struct iphdr *ip;
318 bool hotdrop = false;
319 /* Initializing verdict to NF_DROP keeps gcc happy. */
320 unsigned int verdict = NF_DROP;
321 const char *indev, *outdev;
323 struct ipt_entry *e, *back;
324 struct xt_table_info *private;
325 struct xt_match_param mtpar;
326 struct xt_target_param tgpar;
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 mtpar.hooknum = 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]);
357 struct ipt_entry_target *t;
361 if (!ip_packet_match(ip, indev, outdev,
362 &e->ip, mtpar.fragoff) ||
363 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
364 e = ipt_next_entry(e);
368 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
370 t = ipt_get_target(e);
371 IP_NF_ASSERT(t->u.kernel.target);
373 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
374 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
375 /* The packet is traced: log it */
376 if (unlikely(skb->nf_trace))
377 trace_packet(skb, hook, in, out,
378 table->name, private, e);
380 /* Standard target? */
381 if (!t->u.kernel.target->target) {
384 v = ((struct ipt_standard_target *)t)->verdict;
386 /* Pop from stack? */
387 if (v != IPT_RETURN) {
388 verdict = (unsigned)(-v) - 1;
392 back = get_entry(table_base, back->comefrom);
395 if (table_base + v != ipt_next_entry(e)
396 && !(e->ip.flags & IPT_F_GOTO)) {
397 /* Save old back ptr in next entry */
398 struct ipt_entry *next = ipt_next_entry(e);
399 next->comefrom = (void *)back - table_base;
400 /* set back pointer to next entry */
404 e = get_entry(table_base, v);
408 /* Targets which reenter must return
410 tgpar.target = t->u.kernel.target;
411 tgpar.targinfo = t->data;
414 #ifdef CONFIG_NETFILTER_DEBUG
415 tb_comefrom = 0xeeeeeeec;
417 verdict = t->u.kernel.target->target(skb, &tgpar);
418 #ifdef CONFIG_NETFILTER_DEBUG
419 if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
420 printk("Target %s reentered!\n",
421 t->u.kernel.target->name);
424 tb_comefrom = 0x57acc001;
426 /* Target might have changed stuff. */
428 if (verdict == IPT_CONTINUE)
429 e = ipt_next_entry(e);
434 xt_info_rdunlock_bh();
436 #ifdef DEBUG_ALLOW_ALL
447 /* Figures out from what hook each rule can be called: returns 0 if
448 there are loops. Puts hook bitmask in comefrom. */
450 mark_source_chains(struct xt_table_info *newinfo,
451 unsigned int valid_hooks, void *entry0)
455 /* No recursion; use packet counter to save back ptrs (reset
456 to 0 as we leave), and comefrom to save source hook bitmask */
457 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
458 unsigned int pos = newinfo->hook_entry[hook];
459 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
461 if (!(valid_hooks & (1 << hook)))
464 /* Set initial back pointer. */
465 e->counters.pcnt = pos;
468 struct ipt_standard_target *t
469 = (void *)ipt_get_target(e);
470 int visited = e->comefrom & (1 << hook);
472 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
473 printk("iptables: loop hook %u pos %u %08X.\n",
474 hook, pos, e->comefrom);
477 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
479 /* Unconditional return/END. */
480 if ((e->target_offset == sizeof(struct ipt_entry)
481 && (strcmp(t->target.u.user.name,
482 IPT_STANDARD_TARGET) == 0)
484 && unconditional(&e->ip)) || visited) {
485 unsigned int oldpos, size;
487 if ((strcmp(t->target.u.user.name,
488 IPT_STANDARD_TARGET) == 0) &&
489 t->verdict < -NF_MAX_VERDICT - 1) {
490 duprintf("mark_source_chains: bad "
491 "negative verdict (%i)\n",
496 /* Return: backtrack through the last
499 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
500 #ifdef DEBUG_IP_FIREWALL_USER
502 & (1 << NF_INET_NUMHOOKS)) {
503 duprintf("Back unset "
510 pos = e->counters.pcnt;
511 e->counters.pcnt = 0;
513 /* We're at the start. */
517 e = (struct ipt_entry *)
519 } while (oldpos == pos + e->next_offset);
522 size = e->next_offset;
523 e = (struct ipt_entry *)
524 (entry0 + pos + size);
525 e->counters.pcnt = pos;
528 int newpos = t->verdict;
530 if (strcmp(t->target.u.user.name,
531 IPT_STANDARD_TARGET) == 0
533 if (newpos > newinfo->size -
534 sizeof(struct ipt_entry)) {
535 duprintf("mark_source_chains: "
536 "bad verdict (%i)\n",
540 /* This a jump; chase it. */
541 duprintf("Jump rule %u -> %u\n",
544 /* ... this is a fallthru */
545 newpos = pos + e->next_offset;
547 e = (struct ipt_entry *)
549 e->counters.pcnt = pos;
554 duprintf("Finished chain %u\n", hook);
560 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
562 struct xt_mtdtor_param par;
564 if (i && (*i)-- == 0)
567 par.match = m->u.kernel.match;
568 par.matchinfo = m->data;
569 par.family = NFPROTO_IPV4;
570 if (par.match->destroy != NULL)
571 par.match->destroy(&par);
572 module_put(par.match->me);
577 check_entry(struct ipt_entry *e, const char *name)
579 struct ipt_entry_target *t;
581 if (!ip_checkentry(&e->ip)) {
582 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
586 if (e->target_offset + sizeof(struct ipt_entry_target) >
590 t = ipt_get_target(e);
591 if (e->target_offset + t->u.target_size > e->next_offset)
598 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
601 const struct ipt_ip *ip = par->entryinfo;
604 par->match = m->u.kernel.match;
605 par->matchinfo = m->data;
607 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
608 ip->proto, ip->invflags & IPT_INV_PROTO);
610 duprintf("ip_tables: check failed for `%s'.\n",
619 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
622 struct xt_match *match;
625 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
627 "ipt_%s", m->u.user.name);
628 if (IS_ERR(match) || !match) {
629 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
630 return match ? PTR_ERR(match) : -ENOENT;
632 m->u.kernel.match = match;
634 ret = check_match(m, par, i);
640 module_put(m->u.kernel.match->me);
644 static int check_target(struct ipt_entry *e, const char *name)
646 struct ipt_entry_target *t = ipt_get_target(e);
647 struct xt_tgchk_param par = {
650 .target = t->u.kernel.target,
652 .hook_mask = e->comefrom,
653 .family = NFPROTO_IPV4,
657 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
658 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
660 duprintf("ip_tables: check failed for `%s'.\n",
661 t->u.kernel.target->name);
668 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
671 struct ipt_entry_target *t;
672 struct xt_target *target;
675 struct xt_mtchk_param mtpar;
677 ret = check_entry(e, name);
683 mtpar.entryinfo = &e->ip;
684 mtpar.hook_mask = e->comefrom;
685 mtpar.family = NFPROTO_IPV4;
686 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
688 goto cleanup_matches;
690 t = ipt_get_target(e);
691 target = try_then_request_module(xt_find_target(AF_INET,
694 "ipt_%s", t->u.user.name);
695 if (IS_ERR(target) || !target) {
696 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
697 ret = target ? PTR_ERR(target) : -ENOENT;
698 goto cleanup_matches;
700 t->u.kernel.target = target;
702 ret = check_target(e, name);
709 module_put(t->u.kernel.target->me);
711 IPT_MATCH_ITERATE(e, cleanup_match, &j);
716 check_entry_size_and_hooks(struct ipt_entry *e,
717 struct xt_table_info *newinfo,
719 unsigned char *limit,
720 const unsigned int *hook_entries,
721 const unsigned int *underflows,
726 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
727 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
728 duprintf("Bad offset %p\n", e);
733 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
734 duprintf("checking: element %p size %u\n",
739 /* Check hooks & underflows */
740 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
741 if ((unsigned char *)e - base == hook_entries[h])
742 newinfo->hook_entry[h] = hook_entries[h];
743 if ((unsigned char *)e - base == underflows[h])
744 newinfo->underflow[h] = underflows[h];
747 /* FIXME: underflows must be unconditional, standard verdicts
748 < 0 (not IPT_RETURN). --RR */
750 /* Clear counters and comefrom */
751 e->counters = ((struct xt_counters) { 0, 0 });
759 cleanup_entry(struct ipt_entry *e, unsigned int *i)
761 struct xt_tgdtor_param par;
762 struct ipt_entry_target *t;
764 if (i && (*i)-- == 0)
767 /* Cleanup all matches */
768 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
769 t = ipt_get_target(e);
771 par.target = t->u.kernel.target;
772 par.targinfo = t->data;
773 par.family = NFPROTO_IPV4;
774 if (par.target->destroy != NULL)
775 par.target->destroy(&par);
776 module_put(par.target->me);
780 /* Checks and translates the user-supplied table segment (held in
783 translate_table(const char *name,
784 unsigned int valid_hooks,
785 struct xt_table_info *newinfo,
789 const unsigned int *hook_entries,
790 const unsigned int *underflows)
795 newinfo->size = size;
796 newinfo->number = number;
798 /* Init all hooks to impossible value. */
799 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
800 newinfo->hook_entry[i] = 0xFFFFFFFF;
801 newinfo->underflow[i] = 0xFFFFFFFF;
804 duprintf("translate_table: size %u\n", newinfo->size);
806 /* Walk through entries, checking offsets. */
807 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
808 check_entry_size_and_hooks,
812 hook_entries, underflows, &i);
817 duprintf("translate_table: %u not %u entries\n",
822 /* Check hooks all assigned */
823 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
824 /* Only hooks which are valid */
825 if (!(valid_hooks & (1 << i)))
827 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
828 duprintf("Invalid hook entry %u %u\n",
832 if (newinfo->underflow[i] == 0xFFFFFFFF) {
833 duprintf("Invalid underflow %u %u\n",
839 if (!mark_source_chains(newinfo, valid_hooks, entry0))
842 /* Finally, each sanity check must pass */
844 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
845 find_check_entry, name, size, &i);
848 IPT_ENTRY_ITERATE(entry0, newinfo->size,
853 /* And one copy for every other CPU */
854 for_each_possible_cpu(i) {
855 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
856 memcpy(newinfo->entries[i], entry0, newinfo->size);
864 add_entry_to_counter(const struct ipt_entry *e,
865 struct xt_counters total[],
868 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
875 set_entry_to_counter(const struct ipt_entry *e,
876 struct ipt_counters total[],
879 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
886 get_counters(const struct xt_table_info *t,
887 struct xt_counters counters[])
893 /* Instead of clearing (by a previous call to memset())
894 * the counters and using adds, we set the counters
895 * with data used by 'current' CPU.
897 * Bottom half has to be disabled to prevent deadlock
898 * if new softirq were to run and call ipt_do_table
901 curcpu = smp_processor_id();
904 IPT_ENTRY_ITERATE(t->entries[curcpu],
906 set_entry_to_counter,
910 for_each_possible_cpu(cpu) {
915 IPT_ENTRY_ITERATE(t->entries[cpu],
917 add_entry_to_counter,
920 xt_info_wrunlock(cpu);
925 static struct xt_counters * alloc_counters(struct xt_table *table)
927 unsigned int countersize;
928 struct xt_counters *counters;
929 struct xt_table_info *private = table->private;
931 /* We need atomic snapshot of counters: rest doesn't change
932 (other than comefrom, which userspace doesn't care
934 countersize = sizeof(struct xt_counters) * private->number;
935 counters = vmalloc_node(countersize, numa_node_id());
937 if (counters == NULL)
938 return ERR_PTR(-ENOMEM);
940 get_counters(private, counters);
946 copy_entries_to_user(unsigned int total_size,
947 struct xt_table *table,
948 void __user *userptr)
950 unsigned int off, num;
952 struct xt_counters *counters;
953 const struct xt_table_info *private = table->private;
955 const void *loc_cpu_entry;
957 counters = alloc_counters(table);
958 if (IS_ERR(counters))
959 return PTR_ERR(counters);
961 /* choose the copy that is on our node/cpu, ...
962 * This choice is lazy (because current thread is
963 * allowed to migrate to another cpu)
965 loc_cpu_entry = private->entries[raw_smp_processor_id()];
966 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
971 /* FIXME: use iterator macros --RR */
972 /* ... then go back and fix counters and names */
973 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
975 const struct ipt_entry_match *m;
976 const struct ipt_entry_target *t;
978 e = (struct ipt_entry *)(loc_cpu_entry + off);
979 if (copy_to_user(userptr + off
980 + offsetof(struct ipt_entry, counters),
982 sizeof(counters[num])) != 0) {
987 for (i = sizeof(struct ipt_entry);
988 i < e->target_offset;
989 i += m->u.match_size) {
992 if (copy_to_user(userptr + off + i
993 + offsetof(struct ipt_entry_match,
995 m->u.kernel.match->name,
996 strlen(m->u.kernel.match->name)+1)
1003 t = ipt_get_target(e);
1004 if (copy_to_user(userptr + off + e->target_offset
1005 + offsetof(struct ipt_entry_target,
1007 t->u.kernel.target->name,
1008 strlen(t->u.kernel.target->name)+1) != 0) {
1019 #ifdef CONFIG_COMPAT
1020 static void compat_standard_from_user(void *dst, void *src)
1022 int v = *(compat_int_t *)src;
1025 v += xt_compat_calc_jump(AF_INET, v);
1026 memcpy(dst, &v, sizeof(v));
1029 static int compat_standard_to_user(void __user *dst, void *src)
1031 compat_int_t cv = *(int *)src;
1034 cv -= xt_compat_calc_jump(AF_INET, cv);
1035 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1039 compat_calc_match(struct ipt_entry_match *m, int *size)
1041 *size += xt_compat_match_offset(m->u.kernel.match);
1045 static int compat_calc_entry(struct ipt_entry *e,
1046 const struct xt_table_info *info,
1047 void *base, struct xt_table_info *newinfo)
1049 struct ipt_entry_target *t;
1050 unsigned int entry_offset;
1053 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1054 entry_offset = (void *)e - base;
1055 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1056 t = ipt_get_target(e);
1057 off += xt_compat_target_offset(t->u.kernel.target);
1058 newinfo->size -= off;
1059 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1063 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1064 if (info->hook_entry[i] &&
1065 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1066 newinfo->hook_entry[i] -= off;
1067 if (info->underflow[i] &&
1068 (e < (struct ipt_entry *)(base + info->underflow[i])))
1069 newinfo->underflow[i] -= off;
1074 static int compat_table_info(const struct xt_table_info *info,
1075 struct xt_table_info *newinfo)
1077 void *loc_cpu_entry;
1079 if (!newinfo || !info)
1082 /* we dont care about newinfo->entries[] */
1083 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1084 newinfo->initial_entries = 0;
1085 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1086 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1087 compat_calc_entry, info, loc_cpu_entry,
1092 static int get_info(struct net *net, void __user *user, int *len, int compat)
1094 char name[IPT_TABLE_MAXNAMELEN];
1098 if (*len != sizeof(struct ipt_getinfo)) {
1099 duprintf("length %u != %zu\n", *len,
1100 sizeof(struct ipt_getinfo));
1104 if (copy_from_user(name, user, sizeof(name)) != 0)
1107 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1108 #ifdef CONFIG_COMPAT
1110 xt_compat_lock(AF_INET);
1112 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1113 "iptable_%s", name);
1114 if (t && !IS_ERR(t)) {
1115 struct ipt_getinfo info;
1116 const struct xt_table_info *private = t->private;
1118 #ifdef CONFIG_COMPAT
1120 struct xt_table_info tmp;
1121 ret = compat_table_info(private, &tmp);
1122 xt_compat_flush_offsets(AF_INET);
1126 info.valid_hooks = t->valid_hooks;
1127 memcpy(info.hook_entry, private->hook_entry,
1128 sizeof(info.hook_entry));
1129 memcpy(info.underflow, private->underflow,
1130 sizeof(info.underflow));
1131 info.num_entries = private->number;
1132 info.size = private->size;
1133 strcpy(info.name, name);
1135 if (copy_to_user(user, &info, *len) != 0)
1143 ret = t ? PTR_ERR(t) : -ENOENT;
1144 #ifdef CONFIG_COMPAT
1146 xt_compat_unlock(AF_INET);
1152 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1155 struct ipt_get_entries get;
1158 if (*len < sizeof(get)) {
1159 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1162 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1164 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1165 duprintf("get_entries: %u != %zu\n",
1166 *len, sizeof(get) + get.size);
1170 t = xt_find_table_lock(net, AF_INET, get.name);
1171 if (t && !IS_ERR(t)) {
1172 const struct xt_table_info *private = t->private;
1173 duprintf("t->private->number = %u\n", private->number);
1174 if (get.size == private->size)
1175 ret = copy_entries_to_user(private->size,
1176 t, uptr->entrytable);
1178 duprintf("get_entries: I've got %u not %u!\n",
1179 private->size, get.size);
1185 ret = t ? PTR_ERR(t) : -ENOENT;
1191 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1192 struct xt_table_info *newinfo, unsigned int num_counters,
1193 void __user *counters_ptr)
1197 struct xt_table_info *oldinfo;
1198 struct xt_counters *counters;
1199 void *loc_cpu_old_entry;
1202 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1208 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1209 "iptable_%s", name);
1210 if (!t || IS_ERR(t)) {
1211 ret = t ? PTR_ERR(t) : -ENOENT;
1212 goto free_newinfo_counters_untrans;
1216 if (valid_hooks != t->valid_hooks) {
1217 duprintf("Valid hook crap: %08X vs %08X\n",
1218 valid_hooks, t->valid_hooks);
1223 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1227 /* Update module usage count based on number of rules */
1228 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1229 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1230 if ((oldinfo->number > oldinfo->initial_entries) ||
1231 (newinfo->number <= oldinfo->initial_entries))
1233 if ((oldinfo->number > oldinfo->initial_entries) &&
1234 (newinfo->number <= oldinfo->initial_entries))
1237 /* Get the old counters, and synchronize with replace */
1238 get_counters(oldinfo, counters);
1240 /* Decrease module usage counts and free resource */
1241 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1242 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1244 xt_free_table_info(oldinfo);
1245 if (copy_to_user(counters_ptr, counters,
1246 sizeof(struct xt_counters) * num_counters) != 0)
1255 free_newinfo_counters_untrans:
1262 do_replace(struct net *net, void __user *user, unsigned int len)
1265 struct ipt_replace tmp;
1266 struct xt_table_info *newinfo;
1267 void *loc_cpu_entry;
1269 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1272 /* overflow check */
1273 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1276 newinfo = xt_alloc_table_info(tmp.size);
1280 /* choose the copy that is on our node/cpu */
1281 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1282 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1288 ret = translate_table(tmp.name, tmp.valid_hooks,
1289 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1290 tmp.hook_entry, tmp.underflow);
1294 duprintf("ip_tables: Translated table\n");
1296 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1297 tmp.num_counters, tmp.counters);
1299 goto free_newinfo_untrans;
1302 free_newinfo_untrans:
1303 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1305 xt_free_table_info(newinfo);
1309 /* We're lazy, and add to the first CPU; overflow works its fey magic
1310 * and everything is OK. */
1312 add_counter_to_entry(struct ipt_entry *e,
1313 const struct xt_counters addme[],
1316 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1323 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1325 unsigned int i, curcpu;
1326 struct xt_counters_info tmp;
1327 struct xt_counters *paddc;
1328 unsigned int num_counters;
1333 const struct xt_table_info *private;
1335 void *loc_cpu_entry;
1336 #ifdef CONFIG_COMPAT
1337 struct compat_xt_counters_info compat_tmp;
1341 size = sizeof(struct compat_xt_counters_info);
1346 size = sizeof(struct xt_counters_info);
1349 if (copy_from_user(ptmp, user, size) != 0)
1352 #ifdef CONFIG_COMPAT
1354 num_counters = compat_tmp.num_counters;
1355 name = compat_tmp.name;
1359 num_counters = tmp.num_counters;
1363 if (len != size + num_counters * sizeof(struct xt_counters))
1366 paddc = vmalloc_node(len - size, numa_node_id());
1370 if (copy_from_user(paddc, user + size, len - size) != 0) {
1375 t = xt_find_table_lock(net, AF_INET, name);
1376 if (!t || IS_ERR(t)) {
1377 ret = t ? PTR_ERR(t) : -ENOENT;
1382 private = t->private;
1383 if (private->number != num_counters) {
1385 goto unlock_up_free;
1389 /* Choose the copy that is on our node */
1390 curcpu = smp_processor_id();
1391 loc_cpu_entry = private->entries[curcpu];
1392 xt_info_wrlock(curcpu);
1393 IPT_ENTRY_ITERATE(loc_cpu_entry,
1395 add_counter_to_entry,
1398 xt_info_wrunlock(curcpu);
1409 #ifdef CONFIG_COMPAT
1410 struct compat_ipt_replace {
1411 char name[IPT_TABLE_MAXNAMELEN];
1415 u32 hook_entry[NF_INET_NUMHOOKS];
1416 u32 underflow[NF_INET_NUMHOOKS];
1418 compat_uptr_t counters; /* struct ipt_counters * */
1419 struct compat_ipt_entry entries[0];
1423 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1424 unsigned int *size, struct xt_counters *counters,
1427 struct ipt_entry_target *t;
1428 struct compat_ipt_entry __user *ce;
1429 u_int16_t target_offset, next_offset;
1430 compat_uint_t origsize;
1435 ce = (struct compat_ipt_entry __user *)*dstptr;
1436 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1439 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1442 *dstptr += sizeof(struct compat_ipt_entry);
1443 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1445 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1446 target_offset = e->target_offset - (origsize - *size);
1449 t = ipt_get_target(e);
1450 ret = xt_compat_target_to_user(t, dstptr, size);
1454 next_offset = e->next_offset - (origsize - *size);
1455 if (put_user(target_offset, &ce->target_offset))
1457 if (put_user(next_offset, &ce->next_offset))
1467 compat_find_calc_match(struct ipt_entry_match *m,
1469 const struct ipt_ip *ip,
1470 unsigned int hookmask,
1471 int *size, unsigned int *i)
1473 struct xt_match *match;
1475 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1476 m->u.user.revision),
1477 "ipt_%s", m->u.user.name);
1478 if (IS_ERR(match) || !match) {
1479 duprintf("compat_check_calc_match: `%s' not found\n",
1481 return match ? PTR_ERR(match) : -ENOENT;
1483 m->u.kernel.match = match;
1484 *size += xt_compat_match_offset(match);
1491 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1493 if (i && (*i)-- == 0)
1496 module_put(m->u.kernel.match->me);
1501 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1503 struct ipt_entry_target *t;
1505 if (i && (*i)-- == 0)
1508 /* Cleanup all matches */
1509 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1510 t = compat_ipt_get_target(e);
1511 module_put(t->u.kernel.target->me);
1516 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1517 struct xt_table_info *newinfo,
1519 unsigned char *base,
1520 unsigned char *limit,
1521 unsigned int *hook_entries,
1522 unsigned int *underflows,
1526 struct ipt_entry_target *t;
1527 struct xt_target *target;
1528 unsigned int entry_offset;
1532 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1533 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1534 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1535 duprintf("Bad offset %p, limit = %p\n", e, limit);
1539 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1540 sizeof(struct compat_xt_entry_target)) {
1541 duprintf("checking: element %p size %u\n",
1546 /* For purposes of check_entry casting the compat entry is fine */
1547 ret = check_entry((struct ipt_entry *)e, name);
1551 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1552 entry_offset = (void *)e - (void *)base;
1554 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1555 &e->ip, e->comefrom, &off, &j);
1557 goto release_matches;
1559 t = compat_ipt_get_target(e);
1560 target = try_then_request_module(xt_find_target(AF_INET,
1562 t->u.user.revision),
1563 "ipt_%s", t->u.user.name);
1564 if (IS_ERR(target) || !target) {
1565 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1567 ret = target ? PTR_ERR(target) : -ENOENT;
1568 goto release_matches;
1570 t->u.kernel.target = target;
1572 off += xt_compat_target_offset(target);
1574 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1578 /* Check hooks & underflows */
1579 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1580 if ((unsigned char *)e - base == hook_entries[h])
1581 newinfo->hook_entry[h] = hook_entries[h];
1582 if ((unsigned char *)e - base == underflows[h])
1583 newinfo->underflow[h] = underflows[h];
1586 /* Clear counters and comefrom */
1587 memset(&e->counters, 0, sizeof(e->counters));
1594 module_put(t->u.kernel.target->me);
1596 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1601 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1602 unsigned int *size, const char *name,
1603 struct xt_table_info *newinfo, unsigned char *base)
1605 struct ipt_entry_target *t;
1606 struct xt_target *target;
1607 struct ipt_entry *de;
1608 unsigned int origsize;
1613 de = (struct ipt_entry *)*dstptr;
1614 memcpy(de, e, sizeof(struct ipt_entry));
1615 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1617 *dstptr += sizeof(struct ipt_entry);
1618 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1620 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1624 de->target_offset = e->target_offset - (origsize - *size);
1625 t = compat_ipt_get_target(e);
1626 target = t->u.kernel.target;
1627 xt_compat_target_from_user(t, dstptr, size);
1629 de->next_offset = e->next_offset - (origsize - *size);
1630 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1631 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1632 newinfo->hook_entry[h] -= origsize - *size;
1633 if ((unsigned char *)de - base < newinfo->underflow[h])
1634 newinfo->underflow[h] -= origsize - *size;
1640 compat_check_entry(struct ipt_entry *e, const char *name,
1643 struct xt_mtchk_param mtpar;
1649 mtpar.entryinfo = &e->ip;
1650 mtpar.hook_mask = e->comefrom;
1651 mtpar.family = NFPROTO_IPV4;
1652 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1654 goto cleanup_matches;
1656 ret = check_target(e, name);
1658 goto cleanup_matches;
1664 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1669 translate_compat_table(const char *name,
1670 unsigned int valid_hooks,
1671 struct xt_table_info **pinfo,
1673 unsigned int total_size,
1674 unsigned int number,
1675 unsigned int *hook_entries,
1676 unsigned int *underflows)
1679 struct xt_table_info *newinfo, *info;
1680 void *pos, *entry0, *entry1;
1687 info->number = number;
1689 /* Init all hooks to impossible value. */
1690 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1691 info->hook_entry[i] = 0xFFFFFFFF;
1692 info->underflow[i] = 0xFFFFFFFF;
1695 duprintf("translate_compat_table: size %u\n", info->size);
1697 xt_compat_lock(AF_INET);
1698 /* Walk through entries, checking offsets. */
1699 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1700 check_compat_entry_size_and_hooks,
1701 info, &size, entry0,
1702 entry0 + total_size,
1703 hook_entries, underflows, &j, name);
1709 duprintf("translate_compat_table: %u not %u entries\n",
1714 /* Check hooks all assigned */
1715 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1716 /* Only hooks which are valid */
1717 if (!(valid_hooks & (1 << i)))
1719 if (info->hook_entry[i] == 0xFFFFFFFF) {
1720 duprintf("Invalid hook entry %u %u\n",
1721 i, hook_entries[i]);
1724 if (info->underflow[i] == 0xFFFFFFFF) {
1725 duprintf("Invalid underflow %u %u\n",
1732 newinfo = xt_alloc_table_info(size);
1736 newinfo->number = number;
1737 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1738 newinfo->hook_entry[i] = info->hook_entry[i];
1739 newinfo->underflow[i] = info->underflow[i];
1741 entry1 = newinfo->entries[raw_smp_processor_id()];
1744 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1745 compat_copy_entry_from_user,
1746 &pos, &size, name, newinfo, entry1);
1747 xt_compat_flush_offsets(AF_INET);
1748 xt_compat_unlock(AF_INET);
1753 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1757 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1761 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1762 compat_release_entry, &j);
1763 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1764 xt_free_table_info(newinfo);
1768 /* And one copy for every other CPU */
1769 for_each_possible_cpu(i)
1770 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1771 memcpy(newinfo->entries[i], entry1, newinfo->size);
1775 xt_free_table_info(info);
1779 xt_free_table_info(newinfo);
1781 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1784 xt_compat_flush_offsets(AF_INET);
1785 xt_compat_unlock(AF_INET);
1790 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1793 struct compat_ipt_replace tmp;
1794 struct xt_table_info *newinfo;
1795 void *loc_cpu_entry;
1797 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1800 /* overflow check */
1801 if (tmp.size >= INT_MAX / num_possible_cpus())
1803 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1806 newinfo = xt_alloc_table_info(tmp.size);
1810 /* choose the copy that is on our node/cpu */
1811 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1812 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1818 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1819 &newinfo, &loc_cpu_entry, tmp.size,
1820 tmp.num_entries, tmp.hook_entry,
1825 duprintf("compat_do_replace: Translated table\n");
1827 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1828 tmp.num_counters, compat_ptr(tmp.counters));
1830 goto free_newinfo_untrans;
1833 free_newinfo_untrans:
1834 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1836 xt_free_table_info(newinfo);
1841 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1846 if (!capable(CAP_NET_ADMIN))
1850 case IPT_SO_SET_REPLACE:
1851 ret = compat_do_replace(sock_net(sk), user, len);
1854 case IPT_SO_SET_ADD_COUNTERS:
1855 ret = do_add_counters(sock_net(sk), user, len, 1);
1859 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1866 struct compat_ipt_get_entries {
1867 char name[IPT_TABLE_MAXNAMELEN];
1869 struct compat_ipt_entry entrytable[0];
1873 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1874 void __user *userptr)
1876 struct xt_counters *counters;
1877 const struct xt_table_info *private = table->private;
1881 const void *loc_cpu_entry;
1884 counters = alloc_counters(table);
1885 if (IS_ERR(counters))
1886 return PTR_ERR(counters);
1888 /* choose the copy that is on our node/cpu, ...
1889 * This choice is lazy (because current thread is
1890 * allowed to migrate to another cpu)
1892 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1895 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1896 compat_copy_entry_to_user,
1897 &pos, &size, counters, &i);
1904 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1908 struct compat_ipt_get_entries get;
1911 if (*len < sizeof(get)) {
1912 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1916 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1919 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1920 duprintf("compat_get_entries: %u != %zu\n",
1921 *len, sizeof(get) + get.size);
1925 xt_compat_lock(AF_INET);
1926 t = xt_find_table_lock(net, AF_INET, get.name);
1927 if (t && !IS_ERR(t)) {
1928 const struct xt_table_info *private = t->private;
1929 struct xt_table_info info;
1930 duprintf("t->private->number = %u\n", private->number);
1931 ret = compat_table_info(private, &info);
1932 if (!ret && get.size == info.size) {
1933 ret = compat_copy_entries_to_user(private->size,
1934 t, uptr->entrytable);
1936 duprintf("compat_get_entries: I've got %u not %u!\n",
1937 private->size, get.size);
1940 xt_compat_flush_offsets(AF_INET);
1944 ret = t ? PTR_ERR(t) : -ENOENT;
1946 xt_compat_unlock(AF_INET);
1950 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1953 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1957 if (!capable(CAP_NET_ADMIN))
1961 case IPT_SO_GET_INFO:
1962 ret = get_info(sock_net(sk), user, len, 1);
1964 case IPT_SO_GET_ENTRIES:
1965 ret = compat_get_entries(sock_net(sk), user, len);
1968 ret = do_ipt_get_ctl(sk, cmd, user, len);
1975 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1979 if (!capable(CAP_NET_ADMIN))
1983 case IPT_SO_SET_REPLACE:
1984 ret = do_replace(sock_net(sk), user, len);
1987 case IPT_SO_SET_ADD_COUNTERS:
1988 ret = do_add_counters(sock_net(sk), user, len, 0);
1992 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2000 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2004 if (!capable(CAP_NET_ADMIN))
2008 case IPT_SO_GET_INFO:
2009 ret = get_info(sock_net(sk), user, len, 0);
2012 case IPT_SO_GET_ENTRIES:
2013 ret = get_entries(sock_net(sk), user, len);
2016 case IPT_SO_GET_REVISION_MATCH:
2017 case IPT_SO_GET_REVISION_TARGET: {
2018 struct ipt_get_revision rev;
2021 if (*len != sizeof(rev)) {
2025 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2030 if (cmd == IPT_SO_GET_REVISION_TARGET)
2035 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2038 "ipt_%s", rev.name);
2043 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2050 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2051 const struct ipt_replace *repl)
2054 struct xt_table_info *newinfo;
2055 struct xt_table_info bootstrap
2056 = { 0, 0, 0, { 0 }, { 0 }, { } };
2057 void *loc_cpu_entry;
2058 struct xt_table *new_table;
2060 newinfo = xt_alloc_table_info(repl->size);
2066 /* choose the copy on our node/cpu, but dont care about preemption */
2067 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2068 memcpy(loc_cpu_entry, repl->entries, repl->size);
2070 ret = translate_table(table->name, table->valid_hooks,
2071 newinfo, loc_cpu_entry, repl->size,
2078 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2079 if (IS_ERR(new_table)) {
2080 ret = PTR_ERR(new_table);
2087 xt_free_table_info(newinfo);
2089 return ERR_PTR(ret);
2092 void ipt_unregister_table(struct xt_table *table)
2094 struct xt_table_info *private;
2095 void *loc_cpu_entry;
2096 struct module *table_owner = table->me;
2098 private = xt_unregister_table(table);
2100 /* Decrease module usage counts and free resources */
2101 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2102 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2103 if (private->number > private->initial_entries)
2104 module_put(table_owner);
2105 xt_free_table_info(private);
2108 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2110 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2111 u_int8_t type, u_int8_t code,
2114 return ((test_type == 0xFF) ||
2115 (type == test_type && code >= min_code && code <= max_code))
2120 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2122 const struct icmphdr *ic;
2123 struct icmphdr _icmph;
2124 const struct ipt_icmp *icmpinfo = par->matchinfo;
2126 /* Must not be a fragment. */
2127 if (par->fragoff != 0)
2130 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2132 /* We've been asked to examine this packet, and we
2133 * can't. Hence, no choice but to drop.
2135 duprintf("Dropping evil ICMP tinygram.\n");
2136 *par->hotdrop = true;
2140 return icmp_type_code_match(icmpinfo->type,
2144 !!(icmpinfo->invflags&IPT_ICMP_INV));
2147 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2149 const struct ipt_icmp *icmpinfo = par->matchinfo;
2151 /* Must specify no unknown invflags */
2152 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2155 /* The built-in targets: standard (NULL) and error. */
2156 static struct xt_target ipt_standard_target __read_mostly = {
2157 .name = IPT_STANDARD_TARGET,
2158 .targetsize = sizeof(int),
2159 .family = NFPROTO_IPV4,
2160 #ifdef CONFIG_COMPAT
2161 .compatsize = sizeof(compat_int_t),
2162 .compat_from_user = compat_standard_from_user,
2163 .compat_to_user = compat_standard_to_user,
2167 static struct xt_target ipt_error_target __read_mostly = {
2168 .name = IPT_ERROR_TARGET,
2169 .target = ipt_error,
2170 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2171 .family = NFPROTO_IPV4,
2174 static struct nf_sockopt_ops ipt_sockopts = {
2176 .set_optmin = IPT_BASE_CTL,
2177 .set_optmax = IPT_SO_SET_MAX+1,
2178 .set = do_ipt_set_ctl,
2179 #ifdef CONFIG_COMPAT
2180 .compat_set = compat_do_ipt_set_ctl,
2182 .get_optmin = IPT_BASE_CTL,
2183 .get_optmax = IPT_SO_GET_MAX+1,
2184 .get = do_ipt_get_ctl,
2185 #ifdef CONFIG_COMPAT
2186 .compat_get = compat_do_ipt_get_ctl,
2188 .owner = THIS_MODULE,
2191 static struct xt_match icmp_matchstruct __read_mostly = {
2193 .match = icmp_match,
2194 .matchsize = sizeof(struct ipt_icmp),
2195 .checkentry = icmp_checkentry,
2196 .proto = IPPROTO_ICMP,
2197 .family = NFPROTO_IPV4,
2200 static int __net_init ip_tables_net_init(struct net *net)
2202 return xt_proto_init(net, NFPROTO_IPV4);
2205 static void __net_exit ip_tables_net_exit(struct net *net)
2207 xt_proto_fini(net, NFPROTO_IPV4);
2210 static struct pernet_operations ip_tables_net_ops = {
2211 .init = ip_tables_net_init,
2212 .exit = ip_tables_net_exit,
2215 static int __init ip_tables_init(void)
2219 ret = register_pernet_subsys(&ip_tables_net_ops);
2223 /* Noone else will be downing sem now, so we won't sleep */
2224 ret = xt_register_target(&ipt_standard_target);
2227 ret = xt_register_target(&ipt_error_target);
2230 ret = xt_register_match(&icmp_matchstruct);
2234 /* Register setsockopt */
2235 ret = nf_register_sockopt(&ipt_sockopts);
2239 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2243 xt_unregister_match(&icmp_matchstruct);
2245 xt_unregister_target(&ipt_error_target);
2247 xt_unregister_target(&ipt_standard_target);
2249 unregister_pernet_subsys(&ip_tables_net_ops);
2254 static void __exit ip_tables_fini(void)
2256 nf_unregister_sockopt(&ipt_sockopts);
2258 xt_unregister_match(&icmp_matchstruct);
2259 xt_unregister_target(&ipt_error_target);
2260 xt_unregister_target(&ipt_standard_target);
2262 unregister_pernet_subsys(&ip_tables_net_ops);
2265 EXPORT_SYMBOL(ipt_register_table);
2266 EXPORT_SYMBOL(ipt_unregister_table);
2267 EXPORT_SYMBOL(ipt_do_table);
2268 module_init(ip_tables_init);
2269 module_exit(ip_tables_fini);