2 * Packet matching code.
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #include <linux/cache.h>
12 #include <linux/capability.h>
13 #include <linux/skbuff.h>
14 #include <linux/kmod.h>
15 #include <linux/vmalloc.h>
16 #include <linux/netdevice.h>
17 #include <linux/module.h>
18 #include <linux/icmp.h>
20 #include <net/compat.h>
21 #include <asm/uaccess.h>
22 #include <linux/mutex.h>
23 #include <linux/proc_fs.h>
24 #include <linux/err.h>
25 #include <linux/cpumask.h>
27 #include <linux/netfilter/x_tables.h>
28 #include <linux/netfilter_ipv4/ip_tables.h>
29 #include <net/netfilter/nf_log.h>
31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
33 MODULE_DESCRIPTION("IPv4 packet filter");
35 /*#define DEBUG_IP_FIREWALL*/
36 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
37 /*#define DEBUG_IP_FIREWALL_USER*/
39 #ifdef DEBUG_IP_FIREWALL
40 #define dprintf(format, args...) printk(format , ## args)
42 #define dprintf(format, args...)
45 #ifdef DEBUG_IP_FIREWALL_USER
46 #define duprintf(format, args...) printk(format , ## args)
48 #define duprintf(format, args...)
51 #ifdef CONFIG_NETFILTER_DEBUG
52 #define IP_NF_ASSERT(x) \
55 printk("IP_NF_ASSERT: %s:%s:%u\n", \
56 __func__, __FILE__, __LINE__); \
59 #define IP_NF_ASSERT(x)
63 /* All the better to debug you with... */
69 We keep a set of rules for each CPU, so we can avoid write-locking
70 them in the softirq when updating the counters and therefore
71 only need to read-lock in the softirq; doing a write_lock_bh() in user
72 context stops packets coming through and allows user context to read
73 the counters or update the rules.
75 Hence the start of any table is given by get_table() below. */
77 /* Returns whether matches rule or not. */
78 /* Performance critical - called for every packet */
80 ip_packet_match(const struct iphdr *ip,
83 const struct ipt_ip *ipinfo,
89 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
91 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
93 || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
95 dprintf("Source or dest mismatch.\n");
97 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
98 &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
99 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
100 dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
101 &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
102 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
106 /* Look for ifname matches; this should unroll nicely. */
107 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
108 ret |= (((const unsigned long *)indev)[i]
109 ^ ((const unsigned long *)ipinfo->iniface)[i])
110 & ((const unsigned long *)ipinfo->iniface_mask)[i];
113 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
114 dprintf("VIA in mismatch (%s vs %s).%s\n",
115 indev, ipinfo->iniface,
116 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
120 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
121 ret |= (((const unsigned long *)outdev)[i]
122 ^ ((const unsigned long *)ipinfo->outiface)[i])
123 & ((const unsigned long *)ipinfo->outiface_mask)[i];
126 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
127 dprintf("VIA out mismatch (%s vs %s).%s\n",
128 outdev, ipinfo->outiface,
129 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
133 /* Check specific protocol */
135 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
136 dprintf("Packet protocol %hi does not match %hi.%s\n",
137 ip->protocol, ipinfo->proto,
138 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
142 /* If we have a fragment rule but the packet is not a fragment
143 * then we return zero */
144 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
145 dprintf("Fragment rule but not fragment.%s\n",
146 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
154 ip_checkentry(const struct ipt_ip *ip)
156 if (ip->flags & ~IPT_F_MASK) {
157 duprintf("Unknown flag bits set: %08X\n",
158 ip->flags & ~IPT_F_MASK);
161 if (ip->invflags & ~IPT_INV_MASK) {
162 duprintf("Unknown invflag bits set: %08X\n",
163 ip->invflags & ~IPT_INV_MASK);
170 ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
173 printk("ip_tables: error: `%s'\n",
174 (const char *)par->targinfo);
179 /* Performance critical - called for every packet */
181 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
182 struct xt_match_param *par)
184 par->match = m->u.kernel.match;
185 par->matchinfo = m->data;
187 /* Stop iteration if it doesn't match */
188 if (!m->u.kernel.match->match(skb, par))
194 /* Performance critical */
195 static inline struct ipt_entry *
196 get_entry(void *base, unsigned int offset)
198 return (struct ipt_entry *)(base + offset);
201 /* All zeroes == unconditional rule. */
202 /* Mildly perf critical (only if packet tracing is on) */
204 unconditional(const struct ipt_ip *ip)
208 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
209 if (((__u32 *)ip)[i])
216 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
217 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
218 static const char *const hooknames[] = {
219 [NF_INET_PRE_ROUTING] = "PREROUTING",
220 [NF_INET_LOCAL_IN] = "INPUT",
221 [NF_INET_FORWARD] = "FORWARD",
222 [NF_INET_LOCAL_OUT] = "OUTPUT",
223 [NF_INET_POST_ROUTING] = "POSTROUTING",
226 enum nf_ip_trace_comments {
227 NF_IP_TRACE_COMMENT_RULE,
228 NF_IP_TRACE_COMMENT_RETURN,
229 NF_IP_TRACE_COMMENT_POLICY,
232 static const char *const comments[] = {
233 [NF_IP_TRACE_COMMENT_RULE] = "rule",
234 [NF_IP_TRACE_COMMENT_RETURN] = "return",
235 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
238 static struct nf_loginfo trace_loginfo = {
239 .type = NF_LOG_TYPE_LOG,
243 .logflags = NF_LOG_MASK,
248 /* Mildly perf critical (only if packet tracing is on) */
250 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
251 char *hookname, char **chainname,
252 char **comment, unsigned int *rulenum)
254 struct ipt_standard_target *t = (void *)ipt_get_target(s);
256 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
257 /* Head of user chain: ERROR target with chainname */
258 *chainname = t->target.data;
263 if (s->target_offset == sizeof(struct ipt_entry)
264 && strcmp(t->target.u.kernel.target->name,
265 IPT_STANDARD_TARGET) == 0
267 && unconditional(&s->ip)) {
268 /* Tail of chains: STANDARD target (return/policy) */
269 *comment = *chainname == hookname
270 ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
271 : (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
280 static void trace_packet(struct sk_buff *skb,
282 const struct net_device *in,
283 const struct net_device *out,
284 const char *tablename,
285 struct xt_table_info *private,
289 const struct ipt_entry *root;
290 char *hookname, *chainname, *comment;
291 unsigned int rulenum = 0;
293 table_base = (void *)private->entries[smp_processor_id()];
294 root = get_entry(table_base, private->hook_entry[hook]);
296 hookname = chainname = (char *)hooknames[hook];
297 comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
299 IPT_ENTRY_ITERATE(root,
300 private->size - private->hook_entry[hook],
301 get_chainname_rulenum,
302 e, hookname, &chainname, &comment, &rulenum);
304 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
305 "TRACE: %s:%s:%s:%u ",
306 tablename, chainname, comment, rulenum);
310 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
312 ipt_do_table(struct sk_buff *skb,
314 const struct net_device *in,
315 const struct net_device *out,
316 struct xt_table *table)
318 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
319 const struct iphdr *ip;
321 bool hotdrop = false;
322 /* Initializing verdict to NF_DROP keeps gcc happy. */
323 unsigned int verdict = NF_DROP;
324 const char *indev, *outdev;
326 struct ipt_entry *e, *back;
327 struct xt_table_info *private;
328 struct xt_match_param mtpar;
329 struct xt_target_param tgpar;
333 datalen = skb->len - ip->ihl * 4;
334 indev = in ? in->name : nulldevname;
335 outdev = out ? out->name : nulldevname;
336 /* We handle fragments by dealing with the first fragment as
337 * if it was a normal packet. All other fragments are treated
338 * normally, except that they will NEVER match rules that ask
339 * things we don't know, ie. tcp syn flag or ports). If the
340 * rule is also a fragment-specific rule, non-fragments won't
342 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
343 mtpar.thoff = ip_hdrlen(skb);
344 mtpar.hotdrop = &hotdrop;
345 mtpar.in = tgpar.in = in;
346 mtpar.out = tgpar.out = out;
347 mtpar.family = tgpar.family = NFPROTO_IPV4;
348 tgpar.hooknum = hook;
350 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
353 private = rcu_dereference(table->private);
354 table_base = rcu_dereference(private->entries[smp_processor_id()]);
356 e = get_entry(table_base, private->hook_entry[hook]);
358 /* For return from builtin chain */
359 back = get_entry(table_base, private->underflow[hook]);
364 if (ip_packet_match(ip, indev, outdev,
365 &e->ip, mtpar.fragoff)) {
366 struct ipt_entry_target *t;
368 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
371 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
373 t = ipt_get_target(e);
374 IP_NF_ASSERT(t->u.kernel.target);
376 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
377 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
378 /* The packet is traced: log it */
379 if (unlikely(skb->nf_trace))
380 trace_packet(skb, hook, in, out,
381 table->name, private, e);
383 /* Standard target? */
384 if (!t->u.kernel.target->target) {
387 v = ((struct ipt_standard_target *)t)->verdict;
389 /* Pop from stack? */
390 if (v != IPT_RETURN) {
391 verdict = (unsigned)(-v) - 1;
395 back = get_entry(table_base,
399 if (table_base + v != (void *)e + e->next_offset
400 && !(e->ip.flags & IPT_F_GOTO)) {
401 /* Save old back ptr in next entry */
402 struct ipt_entry *next
403 = (void *)e + e->next_offset;
405 = (void *)back - table_base;
406 /* set back pointer to next entry */
410 e = get_entry(table_base, v);
412 /* Targets which reenter must return
414 tgpar.target = t->u.kernel.target;
415 tgpar.targinfo = t->data;
416 #ifdef CONFIG_NETFILTER_DEBUG
417 ((struct ipt_entry *)table_base)->comefrom
420 verdict = t->u.kernel.target->target(skb,
422 #ifdef CONFIG_NETFILTER_DEBUG
423 if (((struct ipt_entry *)table_base)->comefrom
425 && verdict == IPT_CONTINUE) {
426 printk("Target %s reentered!\n",
427 t->u.kernel.target->name);
430 ((struct ipt_entry *)table_base)->comefrom
433 /* Target might have changed stuff. */
435 datalen = skb->len - ip->ihl * 4;
437 if (verdict == IPT_CONTINUE)
438 e = (void *)e + e->next_offset;
446 e = (void *)e + e->next_offset;
452 #ifdef DEBUG_ALLOW_ALL
461 /* Figures out from what hook each rule can be called: returns 0 if
462 there are loops. Puts hook bitmask in comefrom. */
464 mark_source_chains(struct xt_table_info *newinfo,
465 unsigned int valid_hooks, void *entry0)
469 /* No recursion; use packet counter to save back ptrs (reset
470 to 0 as we leave), and comefrom to save source hook bitmask */
471 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
472 unsigned int pos = newinfo->hook_entry[hook];
473 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
475 if (!(valid_hooks & (1 << hook)))
478 /* Set initial back pointer. */
479 e->counters.pcnt = pos;
482 struct ipt_standard_target *t
483 = (void *)ipt_get_target(e);
484 int visited = e->comefrom & (1 << hook);
486 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
487 printk("iptables: loop hook %u pos %u %08X.\n",
488 hook, pos, e->comefrom);
491 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
493 /* Unconditional return/END. */
494 if ((e->target_offset == sizeof(struct ipt_entry)
495 && (strcmp(t->target.u.user.name,
496 IPT_STANDARD_TARGET) == 0)
498 && unconditional(&e->ip)) || visited) {
499 unsigned int oldpos, size;
501 if (t->verdict < -NF_MAX_VERDICT - 1) {
502 duprintf("mark_source_chains: bad "
503 "negative verdict (%i)\n",
508 /* Return: backtrack through the last
511 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
512 #ifdef DEBUG_IP_FIREWALL_USER
514 & (1 << NF_INET_NUMHOOKS)) {
515 duprintf("Back unset "
522 pos = e->counters.pcnt;
523 e->counters.pcnt = 0;
525 /* We're at the start. */
529 e = (struct ipt_entry *)
531 } while (oldpos == pos + e->next_offset);
534 size = e->next_offset;
535 e = (struct ipt_entry *)
536 (entry0 + pos + size);
537 e->counters.pcnt = pos;
540 int newpos = t->verdict;
542 if (strcmp(t->target.u.user.name,
543 IPT_STANDARD_TARGET) == 0
545 if (newpos > newinfo->size -
546 sizeof(struct ipt_entry)) {
547 duprintf("mark_source_chains: "
548 "bad verdict (%i)\n",
552 /* This a jump; chase it. */
553 duprintf("Jump rule %u -> %u\n",
556 /* ... this is a fallthru */
557 newpos = pos + e->next_offset;
559 e = (struct ipt_entry *)
561 e->counters.pcnt = pos;
566 duprintf("Finished chain %u\n", hook);
572 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
574 struct xt_mtdtor_param par;
576 if (i && (*i)-- == 0)
579 par.match = m->u.kernel.match;
580 par.matchinfo = m->data;
581 par.family = NFPROTO_IPV4;
582 if (par.match->destroy != NULL)
583 par.match->destroy(&par);
584 module_put(par.match->me);
589 check_entry(struct ipt_entry *e, const char *name)
591 struct ipt_entry_target *t;
593 if (!ip_checkentry(&e->ip)) {
594 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
598 if (e->target_offset + sizeof(struct ipt_entry_target) >
602 t = ipt_get_target(e);
603 if (e->target_offset + t->u.target_size > e->next_offset)
610 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
613 const struct ipt_ip *ip = par->entryinfo;
616 par->match = m->u.kernel.match;
617 par->matchinfo = m->data;
619 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
620 ip->proto, ip->invflags & IPT_INV_PROTO);
622 duprintf("ip_tables: check failed for `%s'.\n",
631 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
634 struct xt_match *match;
637 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
639 "ipt_%s", m->u.user.name);
640 if (IS_ERR(match) || !match) {
641 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
642 return match ? PTR_ERR(match) : -ENOENT;
644 m->u.kernel.match = match;
646 ret = check_match(m, par, i);
652 module_put(m->u.kernel.match->me);
656 static int check_target(struct ipt_entry *e, const char *name)
658 struct ipt_entry_target *t = ipt_get_target(e);
659 struct xt_tgchk_param par = {
662 .target = t->u.kernel.target,
664 .hook_mask = e->comefrom,
665 .family = NFPROTO_IPV4,
669 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
670 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
672 duprintf("ip_tables: check failed for `%s'.\n",
673 t->u.kernel.target->name);
680 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
683 struct ipt_entry_target *t;
684 struct xt_target *target;
687 struct xt_mtchk_param mtpar;
689 ret = check_entry(e, name);
695 mtpar.entryinfo = &e->ip;
696 mtpar.hook_mask = e->comefrom;
697 mtpar.family = NFPROTO_IPV4;
698 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
700 goto cleanup_matches;
702 t = ipt_get_target(e);
703 target = try_then_request_module(xt_find_target(AF_INET,
706 "ipt_%s", t->u.user.name);
707 if (IS_ERR(target) || !target) {
708 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
709 ret = target ? PTR_ERR(target) : -ENOENT;
710 goto cleanup_matches;
712 t->u.kernel.target = target;
714 ret = check_target(e, name);
721 module_put(t->u.kernel.target->me);
723 IPT_MATCH_ITERATE(e, cleanup_match, &j);
728 check_entry_size_and_hooks(struct ipt_entry *e,
729 struct xt_table_info *newinfo,
731 unsigned char *limit,
732 const unsigned int *hook_entries,
733 const unsigned int *underflows,
738 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
739 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
740 duprintf("Bad offset %p\n", e);
745 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
746 duprintf("checking: element %p size %u\n",
751 /* Check hooks & underflows */
752 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
753 if ((unsigned char *)e - base == hook_entries[h])
754 newinfo->hook_entry[h] = hook_entries[h];
755 if ((unsigned char *)e - base == underflows[h])
756 newinfo->underflow[h] = underflows[h];
759 /* FIXME: underflows must be unconditional, standard verdicts
760 < 0 (not IPT_RETURN). --RR */
762 /* Clear counters and comefrom */
763 e->counters = ((struct xt_counters) { 0, 0 });
771 cleanup_entry(struct ipt_entry *e, unsigned int *i)
773 struct xt_tgdtor_param par;
774 struct ipt_entry_target *t;
776 if (i && (*i)-- == 0)
779 /* Cleanup all matches */
780 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
781 t = ipt_get_target(e);
783 par.target = t->u.kernel.target;
784 par.targinfo = t->data;
785 par.family = NFPROTO_IPV4;
786 if (par.target->destroy != NULL)
787 par.target->destroy(&par);
788 module_put(par.target->me);
792 /* Checks and translates the user-supplied table segment (held in
795 translate_table(const char *name,
796 unsigned int valid_hooks,
797 struct xt_table_info *newinfo,
801 const unsigned int *hook_entries,
802 const unsigned int *underflows)
807 newinfo->size = size;
808 newinfo->number = number;
810 /* Init all hooks to impossible value. */
811 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
812 newinfo->hook_entry[i] = 0xFFFFFFFF;
813 newinfo->underflow[i] = 0xFFFFFFFF;
816 duprintf("translate_table: size %u\n", newinfo->size);
818 /* Walk through entries, checking offsets. */
819 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
820 check_entry_size_and_hooks,
824 hook_entries, underflows, &i);
829 duprintf("translate_table: %u not %u entries\n",
834 /* Check hooks all assigned */
835 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
836 /* Only hooks which are valid */
837 if (!(valid_hooks & (1 << i)))
839 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
840 duprintf("Invalid hook entry %u %u\n",
844 if (newinfo->underflow[i] == 0xFFFFFFFF) {
845 duprintf("Invalid underflow %u %u\n",
851 if (!mark_source_chains(newinfo, valid_hooks, entry0))
854 /* Finally, each sanity check must pass */
856 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
857 find_check_entry, name, size, &i);
860 IPT_ENTRY_ITERATE(entry0, newinfo->size,
865 /* And one copy for every other CPU */
866 for_each_possible_cpu(i) {
867 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
868 memcpy(newinfo->entries[i], entry0, newinfo->size);
876 add_entry_to_counter(const struct ipt_entry *e,
877 struct xt_counters total[],
880 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
887 set_entry_to_counter(const struct ipt_entry *e,
888 struct ipt_counters total[],
891 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
898 get_counters(const struct xt_table_info *t,
899 struct xt_counters counters[])
905 /* Instead of clearing (by a previous call to memset())
906 * the counters and using adds, we set the counters
907 * with data used by 'current' CPU
908 * We dont care about preemption here.
910 curcpu = raw_smp_processor_id();
913 IPT_ENTRY_ITERATE(t->entries[curcpu],
915 set_entry_to_counter,
919 for_each_possible_cpu(cpu) {
923 IPT_ENTRY_ITERATE(t->entries[cpu],
925 add_entry_to_counter,
932 /* We're lazy, and add to the first CPU; overflow works its fey magic
933 * and everything is OK. */
935 add_counter_to_entry(struct ipt_entry *e,
936 const struct xt_counters addme[],
939 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
945 /* Take values from counters and add them back onto the current cpu */
946 static void put_counters(struct xt_table_info *t,
947 const struct xt_counters counters[])
952 cpu = smp_processor_id();
954 IPT_ENTRY_ITERATE(t->entries[cpu],
956 add_counter_to_entry,
964 zero_entry_counter(struct ipt_entry *e, void *arg)
966 e->counters.bcnt = 0;
967 e->counters.pcnt = 0;
972 clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info)
975 const void *loc_cpu_entry = info->entries[raw_smp_processor_id()];
977 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
978 for_each_possible_cpu(cpu) {
979 memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size);
980 IPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size,
981 zero_entry_counter, NULL);
985 static struct xt_counters * alloc_counters(struct xt_table *table)
987 unsigned int countersize;
988 struct xt_counters *counters;
989 struct xt_table_info *private = table->private;
990 struct xt_table_info *info;
992 /* We need atomic snapshot of counters: rest doesn't change
993 (other than comefrom, which userspace doesn't care
995 countersize = sizeof(struct xt_counters) * private->number;
996 counters = vmalloc_node(countersize, numa_node_id());
998 if (counters == NULL)
1001 info = xt_alloc_table_info(private->size);
1005 clone_counters(info, private);
1007 mutex_lock(&table->lock);
1008 xt_table_entry_swap_rcu(private, info);
1009 synchronize_net(); /* Wait until smoke has cleared */
1011 get_counters(info, counters);
1012 put_counters(private, counters);
1013 mutex_unlock(&table->lock);
1015 xt_free_table_info(info);
1022 return ERR_PTR(-ENOMEM);
1026 copy_entries_to_user(unsigned int total_size,
1027 struct xt_table *table,
1028 void __user *userptr)
1030 unsigned int off, num;
1031 struct ipt_entry *e;
1032 struct xt_counters *counters;
1033 const struct xt_table_info *private = table->private;
1035 const void *loc_cpu_entry;
1037 counters = alloc_counters(table);
1038 if (IS_ERR(counters))
1039 return PTR_ERR(counters);
1041 /* choose the copy that is on our node/cpu, ...
1042 * This choice is lazy (because current thread is
1043 * allowed to migrate to another cpu)
1045 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1046 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1051 /* FIXME: use iterator macros --RR */
1052 /* ... then go back and fix counters and names */
1053 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
1055 const struct ipt_entry_match *m;
1056 const struct ipt_entry_target *t;
1058 e = (struct ipt_entry *)(loc_cpu_entry + off);
1059 if (copy_to_user(userptr + off
1060 + offsetof(struct ipt_entry, counters),
1062 sizeof(counters[num])) != 0) {
1067 for (i = sizeof(struct ipt_entry);
1068 i < e->target_offset;
1069 i += m->u.match_size) {
1072 if (copy_to_user(userptr + off + i
1073 + offsetof(struct ipt_entry_match,
1075 m->u.kernel.match->name,
1076 strlen(m->u.kernel.match->name)+1)
1083 t = ipt_get_target(e);
1084 if (copy_to_user(userptr + off + e->target_offset
1085 + offsetof(struct ipt_entry_target,
1087 t->u.kernel.target->name,
1088 strlen(t->u.kernel.target->name)+1) != 0) {
1099 #ifdef CONFIG_COMPAT
1100 static void compat_standard_from_user(void *dst, void *src)
1102 int v = *(compat_int_t *)src;
1105 v += xt_compat_calc_jump(AF_INET, v);
1106 memcpy(dst, &v, sizeof(v));
1109 static int compat_standard_to_user(void __user *dst, void *src)
1111 compat_int_t cv = *(int *)src;
1114 cv -= xt_compat_calc_jump(AF_INET, cv);
1115 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1119 compat_calc_match(struct ipt_entry_match *m, int *size)
1121 *size += xt_compat_match_offset(m->u.kernel.match);
1125 static int compat_calc_entry(struct ipt_entry *e,
1126 const struct xt_table_info *info,
1127 void *base, struct xt_table_info *newinfo)
1129 struct ipt_entry_target *t;
1130 unsigned int entry_offset;
1133 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1134 entry_offset = (void *)e - base;
1135 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1136 t = ipt_get_target(e);
1137 off += xt_compat_target_offset(t->u.kernel.target);
1138 newinfo->size -= off;
1139 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1143 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1144 if (info->hook_entry[i] &&
1145 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1146 newinfo->hook_entry[i] -= off;
1147 if (info->underflow[i] &&
1148 (e < (struct ipt_entry *)(base + info->underflow[i])))
1149 newinfo->underflow[i] -= off;
1154 static int compat_table_info(const struct xt_table_info *info,
1155 struct xt_table_info *newinfo)
1157 void *loc_cpu_entry;
1159 if (!newinfo || !info)
1162 /* we dont care about newinfo->entries[] */
1163 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1164 newinfo->initial_entries = 0;
1165 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1166 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1167 compat_calc_entry, info, loc_cpu_entry,
1172 static int get_info(struct net *net, void __user *user, int *len, int compat)
1174 char name[IPT_TABLE_MAXNAMELEN];
1178 if (*len != sizeof(struct ipt_getinfo)) {
1179 duprintf("length %u != %zu\n", *len,
1180 sizeof(struct ipt_getinfo));
1184 if (copy_from_user(name, user, sizeof(name)) != 0)
1187 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1188 #ifdef CONFIG_COMPAT
1190 xt_compat_lock(AF_INET);
1192 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1193 "iptable_%s", name);
1194 if (t && !IS_ERR(t)) {
1195 struct ipt_getinfo info;
1196 const struct xt_table_info *private = t->private;
1198 #ifdef CONFIG_COMPAT
1200 struct xt_table_info tmp;
1201 ret = compat_table_info(private, &tmp);
1202 xt_compat_flush_offsets(AF_INET);
1206 info.valid_hooks = t->valid_hooks;
1207 memcpy(info.hook_entry, private->hook_entry,
1208 sizeof(info.hook_entry));
1209 memcpy(info.underflow, private->underflow,
1210 sizeof(info.underflow));
1211 info.num_entries = private->number;
1212 info.size = private->size;
1213 strcpy(info.name, name);
1215 if (copy_to_user(user, &info, *len) != 0)
1223 ret = t ? PTR_ERR(t) : -ENOENT;
1224 #ifdef CONFIG_COMPAT
1226 xt_compat_unlock(AF_INET);
1232 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1235 struct ipt_get_entries get;
1238 if (*len < sizeof(get)) {
1239 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1242 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1244 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1245 duprintf("get_entries: %u != %zu\n",
1246 *len, sizeof(get) + get.size);
1250 t = xt_find_table_lock(net, AF_INET, get.name);
1251 if (t && !IS_ERR(t)) {
1252 const struct xt_table_info *private = t->private;
1253 duprintf("t->private->number = %u\n", private->number);
1254 if (get.size == private->size)
1255 ret = copy_entries_to_user(private->size,
1256 t, uptr->entrytable);
1258 duprintf("get_entries: I've got %u not %u!\n",
1259 private->size, get.size);
1265 ret = t ? PTR_ERR(t) : -ENOENT;
1271 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1272 struct xt_table_info *newinfo, unsigned int num_counters,
1273 void __user *counters_ptr)
1277 struct xt_table_info *oldinfo;
1278 struct xt_counters *counters;
1279 void *loc_cpu_old_entry;
1282 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1288 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1289 "iptable_%s", name);
1290 if (!t || IS_ERR(t)) {
1291 ret = t ? PTR_ERR(t) : -ENOENT;
1292 goto free_newinfo_counters_untrans;
1296 if (valid_hooks != t->valid_hooks) {
1297 duprintf("Valid hook crap: %08X vs %08X\n",
1298 valid_hooks, t->valid_hooks);
1303 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1307 /* Update module usage count based on number of rules */
1308 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1309 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1310 if ((oldinfo->number > oldinfo->initial_entries) ||
1311 (newinfo->number <= oldinfo->initial_entries))
1313 if ((oldinfo->number > oldinfo->initial_entries) &&
1314 (newinfo->number <= oldinfo->initial_entries))
1317 /* Get the old counters. */
1318 get_counters(oldinfo, counters);
1319 /* Decrease module usage counts and free resource */
1320 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1321 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1323 xt_free_table_info(oldinfo);
1324 if (copy_to_user(counters_ptr, counters,
1325 sizeof(struct xt_counters) * num_counters) != 0)
1334 free_newinfo_counters_untrans:
1341 do_replace(struct net *net, void __user *user, unsigned int len)
1344 struct ipt_replace tmp;
1345 struct xt_table_info *newinfo;
1346 void *loc_cpu_entry;
1348 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1351 /* overflow check */
1352 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1355 newinfo = xt_alloc_table_info(tmp.size);
1359 /* choose the copy that is on our node/cpu */
1360 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1361 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1367 ret = translate_table(tmp.name, tmp.valid_hooks,
1368 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1369 tmp.hook_entry, tmp.underflow);
1373 duprintf("ip_tables: Translated table\n");
1375 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1376 tmp.num_counters, tmp.counters);
1378 goto free_newinfo_untrans;
1381 free_newinfo_untrans:
1382 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1384 xt_free_table_info(newinfo);
1390 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1393 struct xt_counters_info tmp;
1394 struct xt_counters *paddc;
1395 unsigned int num_counters;
1400 const struct xt_table_info *private;
1402 void *loc_cpu_entry;
1403 #ifdef CONFIG_COMPAT
1404 struct compat_xt_counters_info compat_tmp;
1408 size = sizeof(struct compat_xt_counters_info);
1413 size = sizeof(struct xt_counters_info);
1416 if (copy_from_user(ptmp, user, size) != 0)
1419 #ifdef CONFIG_COMPAT
1421 num_counters = compat_tmp.num_counters;
1422 name = compat_tmp.name;
1426 num_counters = tmp.num_counters;
1430 if (len != size + num_counters * sizeof(struct xt_counters))
1433 paddc = vmalloc_node(len - size, numa_node_id());
1437 if (copy_from_user(paddc, user + size, len - size) != 0) {
1442 t = xt_find_table_lock(net, AF_INET, name);
1443 if (!t || IS_ERR(t)) {
1444 ret = t ? PTR_ERR(t) : -ENOENT;
1448 mutex_lock(&t->lock);
1449 private = t->private;
1450 if (private->number != num_counters) {
1452 goto unlock_up_free;
1457 /* Choose the copy that is on our node */
1458 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1459 IPT_ENTRY_ITERATE(loc_cpu_entry,
1461 add_counter_to_entry,
1466 mutex_unlock(&t->lock);
1475 #ifdef CONFIG_COMPAT
1476 struct compat_ipt_replace {
1477 char name[IPT_TABLE_MAXNAMELEN];
1481 u32 hook_entry[NF_INET_NUMHOOKS];
1482 u32 underflow[NF_INET_NUMHOOKS];
1484 compat_uptr_t counters; /* struct ipt_counters * */
1485 struct compat_ipt_entry entries[0];
1489 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1490 unsigned int *size, struct xt_counters *counters,
1493 struct ipt_entry_target *t;
1494 struct compat_ipt_entry __user *ce;
1495 u_int16_t target_offset, next_offset;
1496 compat_uint_t origsize;
1501 ce = (struct compat_ipt_entry __user *)*dstptr;
1502 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1505 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1508 *dstptr += sizeof(struct compat_ipt_entry);
1509 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1511 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1512 target_offset = e->target_offset - (origsize - *size);
1515 t = ipt_get_target(e);
1516 ret = xt_compat_target_to_user(t, dstptr, size);
1520 next_offset = e->next_offset - (origsize - *size);
1521 if (put_user(target_offset, &ce->target_offset))
1523 if (put_user(next_offset, &ce->next_offset))
1533 compat_find_calc_match(struct ipt_entry_match *m,
1535 const struct ipt_ip *ip,
1536 unsigned int hookmask,
1537 int *size, unsigned int *i)
1539 struct xt_match *match;
1541 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1542 m->u.user.revision),
1543 "ipt_%s", m->u.user.name);
1544 if (IS_ERR(match) || !match) {
1545 duprintf("compat_check_calc_match: `%s' not found\n",
1547 return match ? PTR_ERR(match) : -ENOENT;
1549 m->u.kernel.match = match;
1550 *size += xt_compat_match_offset(match);
1557 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1559 if (i && (*i)-- == 0)
1562 module_put(m->u.kernel.match->me);
1567 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1569 struct ipt_entry_target *t;
1571 if (i && (*i)-- == 0)
1574 /* Cleanup all matches */
1575 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1576 t = compat_ipt_get_target(e);
1577 module_put(t->u.kernel.target->me);
1582 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1583 struct xt_table_info *newinfo,
1585 unsigned char *base,
1586 unsigned char *limit,
1587 unsigned int *hook_entries,
1588 unsigned int *underflows,
1592 struct ipt_entry_target *t;
1593 struct xt_target *target;
1594 unsigned int entry_offset;
1598 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1599 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1600 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1601 duprintf("Bad offset %p, limit = %p\n", e, limit);
1605 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1606 sizeof(struct compat_xt_entry_target)) {
1607 duprintf("checking: element %p size %u\n",
1612 /* For purposes of check_entry casting the compat entry is fine */
1613 ret = check_entry((struct ipt_entry *)e, name);
1617 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1618 entry_offset = (void *)e - (void *)base;
1620 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1621 &e->ip, e->comefrom, &off, &j);
1623 goto release_matches;
1625 t = compat_ipt_get_target(e);
1626 target = try_then_request_module(xt_find_target(AF_INET,
1628 t->u.user.revision),
1629 "ipt_%s", t->u.user.name);
1630 if (IS_ERR(target) || !target) {
1631 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1633 ret = target ? PTR_ERR(target) : -ENOENT;
1634 goto release_matches;
1636 t->u.kernel.target = target;
1638 off += xt_compat_target_offset(target);
1640 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1644 /* Check hooks & underflows */
1645 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1646 if ((unsigned char *)e - base == hook_entries[h])
1647 newinfo->hook_entry[h] = hook_entries[h];
1648 if ((unsigned char *)e - base == underflows[h])
1649 newinfo->underflow[h] = underflows[h];
1652 /* Clear counters and comefrom */
1653 memset(&e->counters, 0, sizeof(e->counters));
1660 module_put(t->u.kernel.target->me);
1662 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1667 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1668 unsigned int *size, const char *name,
1669 struct xt_table_info *newinfo, unsigned char *base)
1671 struct ipt_entry_target *t;
1672 struct xt_target *target;
1673 struct ipt_entry *de;
1674 unsigned int origsize;
1679 de = (struct ipt_entry *)*dstptr;
1680 memcpy(de, e, sizeof(struct ipt_entry));
1681 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1683 *dstptr += sizeof(struct ipt_entry);
1684 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1686 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1690 de->target_offset = e->target_offset - (origsize - *size);
1691 t = compat_ipt_get_target(e);
1692 target = t->u.kernel.target;
1693 xt_compat_target_from_user(t, dstptr, size);
1695 de->next_offset = e->next_offset - (origsize - *size);
1696 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1697 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1698 newinfo->hook_entry[h] -= origsize - *size;
1699 if ((unsigned char *)de - base < newinfo->underflow[h])
1700 newinfo->underflow[h] -= origsize - *size;
1706 compat_check_entry(struct ipt_entry *e, const char *name,
1709 struct xt_mtchk_param mtpar;
1715 mtpar.entryinfo = &e->ip;
1716 mtpar.hook_mask = e->comefrom;
1717 mtpar.family = NFPROTO_IPV4;
1718 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1720 goto cleanup_matches;
1722 ret = check_target(e, name);
1724 goto cleanup_matches;
1730 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1735 translate_compat_table(const char *name,
1736 unsigned int valid_hooks,
1737 struct xt_table_info **pinfo,
1739 unsigned int total_size,
1740 unsigned int number,
1741 unsigned int *hook_entries,
1742 unsigned int *underflows)
1745 struct xt_table_info *newinfo, *info;
1746 void *pos, *entry0, *entry1;
1753 info->number = number;
1755 /* Init all hooks to impossible value. */
1756 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1757 info->hook_entry[i] = 0xFFFFFFFF;
1758 info->underflow[i] = 0xFFFFFFFF;
1761 duprintf("translate_compat_table: size %u\n", info->size);
1763 xt_compat_lock(AF_INET);
1764 /* Walk through entries, checking offsets. */
1765 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1766 check_compat_entry_size_and_hooks,
1767 info, &size, entry0,
1768 entry0 + total_size,
1769 hook_entries, underflows, &j, name);
1775 duprintf("translate_compat_table: %u not %u entries\n",
1780 /* Check hooks all assigned */
1781 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1782 /* Only hooks which are valid */
1783 if (!(valid_hooks & (1 << i)))
1785 if (info->hook_entry[i] == 0xFFFFFFFF) {
1786 duprintf("Invalid hook entry %u %u\n",
1787 i, hook_entries[i]);
1790 if (info->underflow[i] == 0xFFFFFFFF) {
1791 duprintf("Invalid underflow %u %u\n",
1798 newinfo = xt_alloc_table_info(size);
1802 newinfo->number = number;
1803 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1804 newinfo->hook_entry[i] = info->hook_entry[i];
1805 newinfo->underflow[i] = info->underflow[i];
1807 entry1 = newinfo->entries[raw_smp_processor_id()];
1810 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1811 compat_copy_entry_from_user,
1812 &pos, &size, name, newinfo, entry1);
1813 xt_compat_flush_offsets(AF_INET);
1814 xt_compat_unlock(AF_INET);
1819 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1823 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1827 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1828 compat_release_entry, &j);
1829 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1830 xt_free_table_info(newinfo);
1834 /* And one copy for every other CPU */
1835 for_each_possible_cpu(i)
1836 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1837 memcpy(newinfo->entries[i], entry1, newinfo->size);
1841 xt_free_table_info(info);
1845 xt_free_table_info(newinfo);
1847 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1850 xt_compat_flush_offsets(AF_INET);
1851 xt_compat_unlock(AF_INET);
1856 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1859 struct compat_ipt_replace tmp;
1860 struct xt_table_info *newinfo;
1861 void *loc_cpu_entry;
1863 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1866 /* overflow check */
1867 if (tmp.size >= INT_MAX / num_possible_cpus())
1869 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1872 newinfo = xt_alloc_table_info(tmp.size);
1876 /* choose the copy that is on our node/cpu */
1877 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1878 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1884 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1885 &newinfo, &loc_cpu_entry, tmp.size,
1886 tmp.num_entries, tmp.hook_entry,
1891 duprintf("compat_do_replace: Translated table\n");
1893 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1894 tmp.num_counters, compat_ptr(tmp.counters));
1896 goto free_newinfo_untrans;
1899 free_newinfo_untrans:
1900 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1902 xt_free_table_info(newinfo);
1907 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1912 if (!capable(CAP_NET_ADMIN))
1916 case IPT_SO_SET_REPLACE:
1917 ret = compat_do_replace(sock_net(sk), user, len);
1920 case IPT_SO_SET_ADD_COUNTERS:
1921 ret = do_add_counters(sock_net(sk), user, len, 1);
1925 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1932 struct compat_ipt_get_entries {
1933 char name[IPT_TABLE_MAXNAMELEN];
1935 struct compat_ipt_entry entrytable[0];
1939 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1940 void __user *userptr)
1942 struct xt_counters *counters;
1943 const struct xt_table_info *private = table->private;
1947 const void *loc_cpu_entry;
1950 counters = alloc_counters(table);
1951 if (IS_ERR(counters))
1952 return PTR_ERR(counters);
1954 /* choose the copy that is on our node/cpu, ...
1955 * This choice is lazy (because current thread is
1956 * allowed to migrate to another cpu)
1958 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1961 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1962 compat_copy_entry_to_user,
1963 &pos, &size, counters, &i);
1970 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1974 struct compat_ipt_get_entries get;
1977 if (*len < sizeof(get)) {
1978 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1982 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1985 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1986 duprintf("compat_get_entries: %u != %zu\n",
1987 *len, sizeof(get) + get.size);
1991 xt_compat_lock(AF_INET);
1992 t = xt_find_table_lock(net, AF_INET, get.name);
1993 if (t && !IS_ERR(t)) {
1994 const struct xt_table_info *private = t->private;
1995 struct xt_table_info info;
1996 duprintf("t->private->number = %u\n", private->number);
1997 ret = compat_table_info(private, &info);
1998 if (!ret && get.size == info.size) {
1999 ret = compat_copy_entries_to_user(private->size,
2000 t, uptr->entrytable);
2002 duprintf("compat_get_entries: I've got %u not %u!\n",
2003 private->size, get.size);
2006 xt_compat_flush_offsets(AF_INET);
2010 ret = t ? PTR_ERR(t) : -ENOENT;
2012 xt_compat_unlock(AF_INET);
2016 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
2019 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2023 if (!capable(CAP_NET_ADMIN))
2027 case IPT_SO_GET_INFO:
2028 ret = get_info(sock_net(sk), user, len, 1);
2030 case IPT_SO_GET_ENTRIES:
2031 ret = compat_get_entries(sock_net(sk), user, len);
2034 ret = do_ipt_get_ctl(sk, cmd, user, len);
2041 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2045 if (!capable(CAP_NET_ADMIN))
2049 case IPT_SO_SET_REPLACE:
2050 ret = do_replace(sock_net(sk), user, len);
2053 case IPT_SO_SET_ADD_COUNTERS:
2054 ret = do_add_counters(sock_net(sk), user, len, 0);
2058 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2066 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2070 if (!capable(CAP_NET_ADMIN))
2074 case IPT_SO_GET_INFO:
2075 ret = get_info(sock_net(sk), user, len, 0);
2078 case IPT_SO_GET_ENTRIES:
2079 ret = get_entries(sock_net(sk), user, len);
2082 case IPT_SO_GET_REVISION_MATCH:
2083 case IPT_SO_GET_REVISION_TARGET: {
2084 struct ipt_get_revision rev;
2087 if (*len != sizeof(rev)) {
2091 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2096 if (cmd == IPT_SO_GET_REVISION_TARGET)
2101 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2104 "ipt_%s", rev.name);
2109 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2116 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2117 const struct ipt_replace *repl)
2120 struct xt_table_info *newinfo;
2121 struct xt_table_info bootstrap
2122 = { 0, 0, 0, { 0 }, { 0 }, { } };
2123 void *loc_cpu_entry;
2124 struct xt_table *new_table;
2126 newinfo = xt_alloc_table_info(repl->size);
2132 /* choose the copy on our node/cpu, but dont care about preemption */
2133 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2134 memcpy(loc_cpu_entry, repl->entries, repl->size);
2136 ret = translate_table(table->name, table->valid_hooks,
2137 newinfo, loc_cpu_entry, repl->size,
2144 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2145 if (IS_ERR(new_table)) {
2146 ret = PTR_ERR(new_table);
2153 xt_free_table_info(newinfo);
2155 return ERR_PTR(ret);
2158 void ipt_unregister_table(struct xt_table *table)
2160 struct xt_table_info *private;
2161 void *loc_cpu_entry;
2162 struct module *table_owner = table->me;
2164 private = xt_unregister_table(table);
2166 /* Decrease module usage counts and free resources */
2167 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2168 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2169 if (private->number > private->initial_entries)
2170 module_put(table_owner);
2171 xt_free_table_info(private);
2174 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2176 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2177 u_int8_t type, u_int8_t code,
2180 return ((test_type == 0xFF) ||
2181 (type == test_type && code >= min_code && code <= max_code))
2186 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2188 const struct icmphdr *ic;
2189 struct icmphdr _icmph;
2190 const struct ipt_icmp *icmpinfo = par->matchinfo;
2192 /* Must not be a fragment. */
2193 if (par->fragoff != 0)
2196 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2198 /* We've been asked to examine this packet, and we
2199 * can't. Hence, no choice but to drop.
2201 duprintf("Dropping evil ICMP tinygram.\n");
2202 *par->hotdrop = true;
2206 return icmp_type_code_match(icmpinfo->type,
2210 !!(icmpinfo->invflags&IPT_ICMP_INV));
2213 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2215 const struct ipt_icmp *icmpinfo = par->matchinfo;
2217 /* Must specify no unknown invflags */
2218 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2221 /* The built-in targets: standard (NULL) and error. */
2222 static struct xt_target ipt_standard_target __read_mostly = {
2223 .name = IPT_STANDARD_TARGET,
2224 .targetsize = sizeof(int),
2226 #ifdef CONFIG_COMPAT
2227 .compatsize = sizeof(compat_int_t),
2228 .compat_from_user = compat_standard_from_user,
2229 .compat_to_user = compat_standard_to_user,
2233 static struct xt_target ipt_error_target __read_mostly = {
2234 .name = IPT_ERROR_TARGET,
2235 .target = ipt_error,
2236 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2240 static struct nf_sockopt_ops ipt_sockopts = {
2242 .set_optmin = IPT_BASE_CTL,
2243 .set_optmax = IPT_SO_SET_MAX+1,
2244 .set = do_ipt_set_ctl,
2245 #ifdef CONFIG_COMPAT
2246 .compat_set = compat_do_ipt_set_ctl,
2248 .get_optmin = IPT_BASE_CTL,
2249 .get_optmax = IPT_SO_GET_MAX+1,
2250 .get = do_ipt_get_ctl,
2251 #ifdef CONFIG_COMPAT
2252 .compat_get = compat_do_ipt_get_ctl,
2254 .owner = THIS_MODULE,
2257 static struct xt_match icmp_matchstruct __read_mostly = {
2259 .match = icmp_match,
2260 .matchsize = sizeof(struct ipt_icmp),
2261 .checkentry = icmp_checkentry,
2262 .proto = IPPROTO_ICMP,
2266 static int __net_init ip_tables_net_init(struct net *net)
2268 return xt_proto_init(net, AF_INET);
2271 static void __net_exit ip_tables_net_exit(struct net *net)
2273 xt_proto_fini(net, AF_INET);
2276 static struct pernet_operations ip_tables_net_ops = {
2277 .init = ip_tables_net_init,
2278 .exit = ip_tables_net_exit,
2281 static int __init ip_tables_init(void)
2285 ret = register_pernet_subsys(&ip_tables_net_ops);
2289 /* Noone else will be downing sem now, so we won't sleep */
2290 ret = xt_register_target(&ipt_standard_target);
2293 ret = xt_register_target(&ipt_error_target);
2296 ret = xt_register_match(&icmp_matchstruct);
2300 /* Register setsockopt */
2301 ret = nf_register_sockopt(&ipt_sockopts);
2305 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2309 xt_unregister_match(&icmp_matchstruct);
2311 xt_unregister_target(&ipt_error_target);
2313 xt_unregister_target(&ipt_standard_target);
2315 unregister_pernet_subsys(&ip_tables_net_ops);
2320 static void __exit ip_tables_fini(void)
2322 nf_unregister_sockopt(&ipt_sockopts);
2324 xt_unregister_match(&icmp_matchstruct);
2325 xt_unregister_target(&ipt_error_target);
2326 xt_unregister_target(&ipt_standard_target);
2328 unregister_pernet_subsys(&ip_tables_net_ops);
2331 EXPORT_SYMBOL(ipt_register_table);
2332 EXPORT_SYMBOL(ipt_unregister_table);
2333 EXPORT_SYMBOL(ipt_do_table);
2334 module_init(ip_tables_init);
2335 module_exit(ip_tables_fini);