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 read_lock_bh(&table->lock);
351 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
352 private = table->private;
353 table_base = (void *)private->entries[smp_processor_id()];
354 e = get_entry(table_base, private->hook_entry[hook]);
356 /* For return from builtin chain */
357 back = get_entry(table_base, private->underflow[hook]);
362 if (ip_packet_match(ip, indev, outdev,
363 &e->ip, mtpar.fragoff)) {
364 struct ipt_entry_target *t;
366 if (IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0)
369 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
371 t = ipt_get_target(e);
372 IP_NF_ASSERT(t->u.kernel.target);
374 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
375 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
376 /* The packet is traced: log it */
377 if (unlikely(skb->nf_trace))
378 trace_packet(skb, hook, in, out,
379 table->name, private, e);
381 /* Standard target? */
382 if (!t->u.kernel.target->target) {
385 v = ((struct ipt_standard_target *)t)->verdict;
387 /* Pop from stack? */
388 if (v != IPT_RETURN) {
389 verdict = (unsigned)(-v) - 1;
393 back = get_entry(table_base,
397 if (table_base + v != (void *)e + e->next_offset
398 && !(e->ip.flags & IPT_F_GOTO)) {
399 /* Save old back ptr in next entry */
400 struct ipt_entry *next
401 = (void *)e + e->next_offset;
403 = (void *)back - table_base;
404 /* set back pointer to next entry */
408 e = get_entry(table_base, v);
410 /* Targets which reenter must return
412 tgpar.target = t->u.kernel.target;
413 tgpar.targinfo = t->data;
414 #ifdef CONFIG_NETFILTER_DEBUG
415 ((struct ipt_entry *)table_base)->comefrom
418 verdict = t->u.kernel.target->target(skb,
420 #ifdef CONFIG_NETFILTER_DEBUG
421 if (((struct ipt_entry *)table_base)->comefrom
423 && verdict == IPT_CONTINUE) {
424 printk("Target %s reentered!\n",
425 t->u.kernel.target->name);
428 ((struct ipt_entry *)table_base)->comefrom
431 /* Target might have changed stuff. */
433 datalen = skb->len - ip->ihl * 4;
435 if (verdict == IPT_CONTINUE)
436 e = (void *)e + e->next_offset;
444 e = (void *)e + e->next_offset;
448 read_unlock_bh(&table->lock);
450 #ifdef DEBUG_ALLOW_ALL
459 /* Figures out from what hook each rule can be called: returns 0 if
460 there are loops. Puts hook bitmask in comefrom. */
462 mark_source_chains(struct xt_table_info *newinfo,
463 unsigned int valid_hooks, void *entry0)
467 /* No recursion; use packet counter to save back ptrs (reset
468 to 0 as we leave), and comefrom to save source hook bitmask */
469 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
470 unsigned int pos = newinfo->hook_entry[hook];
471 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
473 if (!(valid_hooks & (1 << hook)))
476 /* Set initial back pointer. */
477 e->counters.pcnt = pos;
480 struct ipt_standard_target *t
481 = (void *)ipt_get_target(e);
482 int visited = e->comefrom & (1 << hook);
484 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
485 printk("iptables: loop hook %u pos %u %08X.\n",
486 hook, pos, e->comefrom);
489 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
491 /* Unconditional return/END. */
492 if ((e->target_offset == sizeof(struct ipt_entry)
493 && (strcmp(t->target.u.user.name,
494 IPT_STANDARD_TARGET) == 0)
496 && unconditional(&e->ip)) || visited) {
497 unsigned int oldpos, size;
499 if (t->verdict < -NF_MAX_VERDICT - 1) {
500 duprintf("mark_source_chains: bad "
501 "negative verdict (%i)\n",
506 /* Return: backtrack through the last
509 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
510 #ifdef DEBUG_IP_FIREWALL_USER
512 & (1 << NF_INET_NUMHOOKS)) {
513 duprintf("Back unset "
520 pos = e->counters.pcnt;
521 e->counters.pcnt = 0;
523 /* We're at the start. */
527 e = (struct ipt_entry *)
529 } while (oldpos == pos + e->next_offset);
532 size = e->next_offset;
533 e = (struct ipt_entry *)
534 (entry0 + pos + size);
535 e->counters.pcnt = pos;
538 int newpos = t->verdict;
540 if (strcmp(t->target.u.user.name,
541 IPT_STANDARD_TARGET) == 0
543 if (newpos > newinfo->size -
544 sizeof(struct ipt_entry)) {
545 duprintf("mark_source_chains: "
546 "bad verdict (%i)\n",
550 /* This a jump; chase it. */
551 duprintf("Jump rule %u -> %u\n",
554 /* ... this is a fallthru */
555 newpos = pos + e->next_offset;
557 e = (struct ipt_entry *)
559 e->counters.pcnt = pos;
564 duprintf("Finished chain %u\n", hook);
570 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
572 struct xt_mtdtor_param par;
574 if (i && (*i)-- == 0)
577 par.match = m->u.kernel.match;
578 par.matchinfo = m->data;
579 par.family = NFPROTO_IPV4;
580 if (par.match->destroy != NULL)
581 par.match->destroy(&par);
582 module_put(par.match->me);
587 check_entry(struct ipt_entry *e, const char *name)
589 struct ipt_entry_target *t;
591 if (!ip_checkentry(&e->ip)) {
592 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
596 if (e->target_offset + sizeof(struct ipt_entry_target) >
600 t = ipt_get_target(e);
601 if (e->target_offset + t->u.target_size > e->next_offset)
608 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
611 const struct ipt_ip *ip = par->entryinfo;
614 par->match = m->u.kernel.match;
615 par->matchinfo = m->data;
617 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
618 ip->proto, ip->invflags & IPT_INV_PROTO);
620 duprintf("ip_tables: check failed for `%s'.\n",
629 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
632 struct xt_match *match;
635 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
637 "ipt_%s", m->u.user.name);
638 if (IS_ERR(match) || !match) {
639 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
640 return match ? PTR_ERR(match) : -ENOENT;
642 m->u.kernel.match = match;
644 ret = check_match(m, par, i);
650 module_put(m->u.kernel.match->me);
654 static int check_target(struct ipt_entry *e, const char *name)
656 struct ipt_entry_target *t = ipt_get_target(e);
657 struct xt_tgchk_param par = {
660 .target = t->u.kernel.target,
662 .hook_mask = e->comefrom,
663 .family = NFPROTO_IPV4,
667 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
668 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
670 duprintf("ip_tables: check failed for `%s'.\n",
671 t->u.kernel.target->name);
678 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
681 struct ipt_entry_target *t;
682 struct xt_target *target;
685 struct xt_mtchk_param mtpar;
687 ret = check_entry(e, name);
693 mtpar.entryinfo = &e->ip;
694 mtpar.hook_mask = e->comefrom;
695 mtpar.family = NFPROTO_IPV4;
696 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
698 goto cleanup_matches;
700 t = ipt_get_target(e);
701 target = try_then_request_module(xt_find_target(AF_INET,
704 "ipt_%s", t->u.user.name);
705 if (IS_ERR(target) || !target) {
706 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
707 ret = target ? PTR_ERR(target) : -ENOENT;
708 goto cleanup_matches;
710 t->u.kernel.target = target;
712 ret = check_target(e, name);
719 module_put(t->u.kernel.target->me);
721 IPT_MATCH_ITERATE(e, cleanup_match, &j);
726 check_entry_size_and_hooks(struct ipt_entry *e,
727 struct xt_table_info *newinfo,
729 unsigned char *limit,
730 const unsigned int *hook_entries,
731 const unsigned int *underflows,
736 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
737 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
738 duprintf("Bad offset %p\n", e);
743 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
744 duprintf("checking: element %p size %u\n",
749 /* Check hooks & underflows */
750 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
751 if ((unsigned char *)e - base == hook_entries[h])
752 newinfo->hook_entry[h] = hook_entries[h];
753 if ((unsigned char *)e - base == underflows[h])
754 newinfo->underflow[h] = underflows[h];
757 /* FIXME: underflows must be unconditional, standard verdicts
758 < 0 (not IPT_RETURN). --RR */
760 /* Clear counters and comefrom */
761 e->counters = ((struct xt_counters) { 0, 0 });
769 cleanup_entry(struct ipt_entry *e, unsigned int *i)
771 struct xt_tgdtor_param par;
772 struct ipt_entry_target *t;
774 if (i && (*i)-- == 0)
777 /* Cleanup all matches */
778 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
779 t = ipt_get_target(e);
781 par.target = t->u.kernel.target;
782 par.targinfo = t->data;
783 par.family = NFPROTO_IPV4;
784 if (par.target->destroy != NULL)
785 par.target->destroy(&par);
786 module_put(par.target->me);
790 /* Checks and translates the user-supplied table segment (held in
793 translate_table(const char *name,
794 unsigned int valid_hooks,
795 struct xt_table_info *newinfo,
799 const unsigned int *hook_entries,
800 const unsigned int *underflows)
805 newinfo->size = size;
806 newinfo->number = number;
808 /* Init all hooks to impossible value. */
809 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
810 newinfo->hook_entry[i] = 0xFFFFFFFF;
811 newinfo->underflow[i] = 0xFFFFFFFF;
814 duprintf("translate_table: size %u\n", newinfo->size);
816 /* Walk through entries, checking offsets. */
817 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
818 check_entry_size_and_hooks,
822 hook_entries, underflows, &i);
827 duprintf("translate_table: %u not %u entries\n",
832 /* Check hooks all assigned */
833 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
834 /* Only hooks which are valid */
835 if (!(valid_hooks & (1 << i)))
837 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
838 duprintf("Invalid hook entry %u %u\n",
842 if (newinfo->underflow[i] == 0xFFFFFFFF) {
843 duprintf("Invalid underflow %u %u\n",
849 if (!mark_source_chains(newinfo, valid_hooks, entry0))
852 /* Finally, each sanity check must pass */
854 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
855 find_check_entry, name, size, &i);
858 IPT_ENTRY_ITERATE(entry0, newinfo->size,
863 /* And one copy for every other CPU */
864 for_each_possible_cpu(i) {
865 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
866 memcpy(newinfo->entries[i], entry0, newinfo->size);
874 add_entry_to_counter(const struct ipt_entry *e,
875 struct xt_counters total[],
878 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
885 set_entry_to_counter(const struct ipt_entry *e,
886 struct ipt_counters total[],
889 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
896 get_counters(const struct xt_table_info *t,
897 struct xt_counters counters[])
903 /* Instead of clearing (by a previous call to memset())
904 * the counters and using adds, we set the counters
905 * with data used by 'current' CPU
906 * We dont care about preemption here.
908 curcpu = raw_smp_processor_id();
911 IPT_ENTRY_ITERATE(t->entries[curcpu],
913 set_entry_to_counter,
917 for_each_possible_cpu(cpu) {
921 IPT_ENTRY_ITERATE(t->entries[cpu],
923 add_entry_to_counter,
929 static struct xt_counters * alloc_counters(struct xt_table *table)
931 unsigned int countersize;
932 struct xt_counters *counters;
933 const struct xt_table_info *private = table->private;
935 /* We need atomic snapshot of counters: rest doesn't change
936 (other than comefrom, which userspace doesn't care
938 countersize = sizeof(struct xt_counters) * private->number;
939 counters = vmalloc_node(countersize, numa_node_id());
941 if (counters == NULL)
942 return ERR_PTR(-ENOMEM);
944 /* First, sum counters... */
945 write_lock_bh(&table->lock);
946 get_counters(private, counters);
947 write_unlock_bh(&table->lock);
953 copy_entries_to_user(unsigned int total_size,
954 struct xt_table *table,
955 void __user *userptr)
957 unsigned int off, num;
959 struct xt_counters *counters;
960 const struct xt_table_info *private = table->private;
962 const void *loc_cpu_entry;
964 counters = alloc_counters(table);
965 if (IS_ERR(counters))
966 return PTR_ERR(counters);
968 /* choose the copy that is on our node/cpu, ...
969 * This choice is lazy (because current thread is
970 * allowed to migrate to another cpu)
972 loc_cpu_entry = private->entries[raw_smp_processor_id()];
973 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
978 /* FIXME: use iterator macros --RR */
979 /* ... then go back and fix counters and names */
980 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
982 const struct ipt_entry_match *m;
983 const struct ipt_entry_target *t;
985 e = (struct ipt_entry *)(loc_cpu_entry + off);
986 if (copy_to_user(userptr + off
987 + offsetof(struct ipt_entry, counters),
989 sizeof(counters[num])) != 0) {
994 for (i = sizeof(struct ipt_entry);
995 i < e->target_offset;
996 i += m->u.match_size) {
999 if (copy_to_user(userptr + off + i
1000 + offsetof(struct ipt_entry_match,
1002 m->u.kernel.match->name,
1003 strlen(m->u.kernel.match->name)+1)
1010 t = ipt_get_target(e);
1011 if (copy_to_user(userptr + off + e->target_offset
1012 + offsetof(struct ipt_entry_target,
1014 t->u.kernel.target->name,
1015 strlen(t->u.kernel.target->name)+1) != 0) {
1026 #ifdef CONFIG_COMPAT
1027 static void compat_standard_from_user(void *dst, void *src)
1029 int v = *(compat_int_t *)src;
1032 v += xt_compat_calc_jump(AF_INET, v);
1033 memcpy(dst, &v, sizeof(v));
1036 static int compat_standard_to_user(void __user *dst, void *src)
1038 compat_int_t cv = *(int *)src;
1041 cv -= xt_compat_calc_jump(AF_INET, cv);
1042 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1046 compat_calc_match(struct ipt_entry_match *m, int *size)
1048 *size += xt_compat_match_offset(m->u.kernel.match);
1052 static int compat_calc_entry(struct ipt_entry *e,
1053 const struct xt_table_info *info,
1054 void *base, struct xt_table_info *newinfo)
1056 struct ipt_entry_target *t;
1057 unsigned int entry_offset;
1060 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1061 entry_offset = (void *)e - base;
1062 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1063 t = ipt_get_target(e);
1064 off += xt_compat_target_offset(t->u.kernel.target);
1065 newinfo->size -= off;
1066 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1070 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1071 if (info->hook_entry[i] &&
1072 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1073 newinfo->hook_entry[i] -= off;
1074 if (info->underflow[i] &&
1075 (e < (struct ipt_entry *)(base + info->underflow[i])))
1076 newinfo->underflow[i] -= off;
1081 static int compat_table_info(const struct xt_table_info *info,
1082 struct xt_table_info *newinfo)
1084 void *loc_cpu_entry;
1086 if (!newinfo || !info)
1089 /* we dont care about newinfo->entries[] */
1090 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1091 newinfo->initial_entries = 0;
1092 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1093 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1094 compat_calc_entry, info, loc_cpu_entry,
1099 static int get_info(struct net *net, void __user *user, int *len, int compat)
1101 char name[IPT_TABLE_MAXNAMELEN];
1105 if (*len != sizeof(struct ipt_getinfo)) {
1106 duprintf("length %u != %zu\n", *len,
1107 sizeof(struct ipt_getinfo));
1111 if (copy_from_user(name, user, sizeof(name)) != 0)
1114 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1115 #ifdef CONFIG_COMPAT
1117 xt_compat_lock(AF_INET);
1119 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1120 "iptable_%s", name);
1121 if (t && !IS_ERR(t)) {
1122 struct ipt_getinfo info;
1123 const struct xt_table_info *private = t->private;
1125 #ifdef CONFIG_COMPAT
1127 struct xt_table_info tmp;
1128 ret = compat_table_info(private, &tmp);
1129 xt_compat_flush_offsets(AF_INET);
1133 info.valid_hooks = t->valid_hooks;
1134 memcpy(info.hook_entry, private->hook_entry,
1135 sizeof(info.hook_entry));
1136 memcpy(info.underflow, private->underflow,
1137 sizeof(info.underflow));
1138 info.num_entries = private->number;
1139 info.size = private->size;
1140 strcpy(info.name, name);
1142 if (copy_to_user(user, &info, *len) != 0)
1150 ret = t ? PTR_ERR(t) : -ENOENT;
1151 #ifdef CONFIG_COMPAT
1153 xt_compat_unlock(AF_INET);
1159 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1162 struct ipt_get_entries get;
1165 if (*len < sizeof(get)) {
1166 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1169 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1171 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1172 duprintf("get_entries: %u != %zu\n",
1173 *len, sizeof(get) + get.size);
1177 t = xt_find_table_lock(net, AF_INET, get.name);
1178 if (t && !IS_ERR(t)) {
1179 const struct xt_table_info *private = t->private;
1180 duprintf("t->private->number = %u\n", private->number);
1181 if (get.size == private->size)
1182 ret = copy_entries_to_user(private->size,
1183 t, uptr->entrytable);
1185 duprintf("get_entries: I've got %u not %u!\n",
1186 private->size, get.size);
1192 ret = t ? PTR_ERR(t) : -ENOENT;
1198 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1199 struct xt_table_info *newinfo, unsigned int num_counters,
1200 void __user *counters_ptr)
1204 struct xt_table_info *oldinfo;
1205 struct xt_counters *counters;
1206 void *loc_cpu_old_entry;
1209 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1215 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1216 "iptable_%s", name);
1217 if (!t || IS_ERR(t)) {
1218 ret = t ? PTR_ERR(t) : -ENOENT;
1219 goto free_newinfo_counters_untrans;
1223 if (valid_hooks != t->valid_hooks) {
1224 duprintf("Valid hook crap: %08X vs %08X\n",
1225 valid_hooks, t->valid_hooks);
1230 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1234 /* Update module usage count based on number of rules */
1235 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1236 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1237 if ((oldinfo->number > oldinfo->initial_entries) ||
1238 (newinfo->number <= oldinfo->initial_entries))
1240 if ((oldinfo->number > oldinfo->initial_entries) &&
1241 (newinfo->number <= oldinfo->initial_entries))
1244 /* Get the old counters. */
1245 get_counters(oldinfo, counters);
1246 /* Decrease module usage counts and free resource */
1247 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1248 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1250 xt_free_table_info(oldinfo);
1251 if (copy_to_user(counters_ptr, counters,
1252 sizeof(struct xt_counters) * num_counters) != 0)
1261 free_newinfo_counters_untrans:
1268 do_replace(struct net *net, void __user *user, unsigned int len)
1271 struct ipt_replace tmp;
1272 struct xt_table_info *newinfo;
1273 void *loc_cpu_entry;
1275 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1278 /* overflow check */
1279 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1282 newinfo = xt_alloc_table_info(tmp.size);
1286 /* choose the copy that is on our node/cpu */
1287 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1288 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1294 ret = translate_table(tmp.name, tmp.valid_hooks,
1295 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1296 tmp.hook_entry, tmp.underflow);
1300 duprintf("ip_tables: Translated table\n");
1302 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1303 tmp.num_counters, tmp.counters);
1305 goto free_newinfo_untrans;
1308 free_newinfo_untrans:
1309 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1311 xt_free_table_info(newinfo);
1315 /* We're lazy, and add to the first CPU; overflow works its fey magic
1316 * and everything is OK. */
1318 add_counter_to_entry(struct ipt_entry *e,
1319 const struct xt_counters addme[],
1323 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1325 (long unsigned int)e->counters.pcnt,
1326 (long unsigned int)e->counters.bcnt,
1327 (long unsigned int)addme[*i].pcnt,
1328 (long unsigned int)addme[*i].bcnt);
1331 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1338 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1341 struct xt_counters_info tmp;
1342 struct xt_counters *paddc;
1343 unsigned int num_counters;
1348 const struct xt_table_info *private;
1350 void *loc_cpu_entry;
1351 #ifdef CONFIG_COMPAT
1352 struct compat_xt_counters_info compat_tmp;
1356 size = sizeof(struct compat_xt_counters_info);
1361 size = sizeof(struct xt_counters_info);
1364 if (copy_from_user(ptmp, user, size) != 0)
1367 #ifdef CONFIG_COMPAT
1369 num_counters = compat_tmp.num_counters;
1370 name = compat_tmp.name;
1374 num_counters = tmp.num_counters;
1378 if (len != size + num_counters * sizeof(struct xt_counters))
1381 paddc = vmalloc_node(len - size, numa_node_id());
1385 if (copy_from_user(paddc, user + size, len - size) != 0) {
1390 t = xt_find_table_lock(net, AF_INET, name);
1391 if (!t || IS_ERR(t)) {
1392 ret = t ? PTR_ERR(t) : -ENOENT;
1396 write_lock_bh(&t->lock);
1397 private = t->private;
1398 if (private->number != num_counters) {
1400 goto unlock_up_free;
1404 /* Choose the copy that is on our node */
1405 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1406 IPT_ENTRY_ITERATE(loc_cpu_entry,
1408 add_counter_to_entry,
1412 write_unlock_bh(&t->lock);
1421 #ifdef CONFIG_COMPAT
1422 struct compat_ipt_replace {
1423 char name[IPT_TABLE_MAXNAMELEN];
1427 u32 hook_entry[NF_INET_NUMHOOKS];
1428 u32 underflow[NF_INET_NUMHOOKS];
1430 compat_uptr_t counters; /* struct ipt_counters * */
1431 struct compat_ipt_entry entries[0];
1435 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1436 unsigned int *size, struct xt_counters *counters,
1439 struct ipt_entry_target *t;
1440 struct compat_ipt_entry __user *ce;
1441 u_int16_t target_offset, next_offset;
1442 compat_uint_t origsize;
1447 ce = (struct compat_ipt_entry __user *)*dstptr;
1448 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1451 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1454 *dstptr += sizeof(struct compat_ipt_entry);
1455 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1457 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1458 target_offset = e->target_offset - (origsize - *size);
1461 t = ipt_get_target(e);
1462 ret = xt_compat_target_to_user(t, dstptr, size);
1466 next_offset = e->next_offset - (origsize - *size);
1467 if (put_user(target_offset, &ce->target_offset))
1469 if (put_user(next_offset, &ce->next_offset))
1479 compat_find_calc_match(struct ipt_entry_match *m,
1481 const struct ipt_ip *ip,
1482 unsigned int hookmask,
1483 int *size, unsigned int *i)
1485 struct xt_match *match;
1487 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1488 m->u.user.revision),
1489 "ipt_%s", m->u.user.name);
1490 if (IS_ERR(match) || !match) {
1491 duprintf("compat_check_calc_match: `%s' not found\n",
1493 return match ? PTR_ERR(match) : -ENOENT;
1495 m->u.kernel.match = match;
1496 *size += xt_compat_match_offset(match);
1503 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1505 if (i && (*i)-- == 0)
1508 module_put(m->u.kernel.match->me);
1513 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1515 struct ipt_entry_target *t;
1517 if (i && (*i)-- == 0)
1520 /* Cleanup all matches */
1521 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1522 t = compat_ipt_get_target(e);
1523 module_put(t->u.kernel.target->me);
1528 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1529 struct xt_table_info *newinfo,
1531 unsigned char *base,
1532 unsigned char *limit,
1533 unsigned int *hook_entries,
1534 unsigned int *underflows,
1538 struct ipt_entry_target *t;
1539 struct xt_target *target;
1540 unsigned int entry_offset;
1544 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1545 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1546 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1547 duprintf("Bad offset %p, limit = %p\n", e, limit);
1551 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1552 sizeof(struct compat_xt_entry_target)) {
1553 duprintf("checking: element %p size %u\n",
1558 /* For purposes of check_entry casting the compat entry is fine */
1559 ret = check_entry((struct ipt_entry *)e, name);
1563 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1564 entry_offset = (void *)e - (void *)base;
1566 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1567 &e->ip, e->comefrom, &off, &j);
1569 goto release_matches;
1571 t = compat_ipt_get_target(e);
1572 target = try_then_request_module(xt_find_target(AF_INET,
1574 t->u.user.revision),
1575 "ipt_%s", t->u.user.name);
1576 if (IS_ERR(target) || !target) {
1577 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1579 ret = target ? PTR_ERR(target) : -ENOENT;
1580 goto release_matches;
1582 t->u.kernel.target = target;
1584 off += xt_compat_target_offset(target);
1586 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1590 /* Check hooks & underflows */
1591 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1592 if ((unsigned char *)e - base == hook_entries[h])
1593 newinfo->hook_entry[h] = hook_entries[h];
1594 if ((unsigned char *)e - base == underflows[h])
1595 newinfo->underflow[h] = underflows[h];
1598 /* Clear counters and comefrom */
1599 memset(&e->counters, 0, sizeof(e->counters));
1606 module_put(t->u.kernel.target->me);
1608 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1613 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1614 unsigned int *size, const char *name,
1615 struct xt_table_info *newinfo, unsigned char *base)
1617 struct ipt_entry_target *t;
1618 struct xt_target *target;
1619 struct ipt_entry *de;
1620 unsigned int origsize;
1625 de = (struct ipt_entry *)*dstptr;
1626 memcpy(de, e, sizeof(struct ipt_entry));
1627 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1629 *dstptr += sizeof(struct ipt_entry);
1630 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1632 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1636 de->target_offset = e->target_offset - (origsize - *size);
1637 t = compat_ipt_get_target(e);
1638 target = t->u.kernel.target;
1639 xt_compat_target_from_user(t, dstptr, size);
1641 de->next_offset = e->next_offset - (origsize - *size);
1642 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1643 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1644 newinfo->hook_entry[h] -= origsize - *size;
1645 if ((unsigned char *)de - base < newinfo->underflow[h])
1646 newinfo->underflow[h] -= origsize - *size;
1652 compat_check_entry(struct ipt_entry *e, const char *name,
1655 struct xt_mtchk_param mtpar;
1661 mtpar.entryinfo = &e->ip;
1662 mtpar.hook_mask = e->comefrom;
1663 mtpar.family = NFPROTO_IPV4;
1664 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1666 goto cleanup_matches;
1668 ret = check_target(e, name);
1670 goto cleanup_matches;
1676 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1681 translate_compat_table(const char *name,
1682 unsigned int valid_hooks,
1683 struct xt_table_info **pinfo,
1685 unsigned int total_size,
1686 unsigned int number,
1687 unsigned int *hook_entries,
1688 unsigned int *underflows)
1691 struct xt_table_info *newinfo, *info;
1692 void *pos, *entry0, *entry1;
1699 info->number = number;
1701 /* Init all hooks to impossible value. */
1702 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1703 info->hook_entry[i] = 0xFFFFFFFF;
1704 info->underflow[i] = 0xFFFFFFFF;
1707 duprintf("translate_compat_table: size %u\n", info->size);
1709 xt_compat_lock(AF_INET);
1710 /* Walk through entries, checking offsets. */
1711 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1712 check_compat_entry_size_and_hooks,
1713 info, &size, entry0,
1714 entry0 + total_size,
1715 hook_entries, underflows, &j, name);
1721 duprintf("translate_compat_table: %u not %u entries\n",
1726 /* Check hooks all assigned */
1727 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1728 /* Only hooks which are valid */
1729 if (!(valid_hooks & (1 << i)))
1731 if (info->hook_entry[i] == 0xFFFFFFFF) {
1732 duprintf("Invalid hook entry %u %u\n",
1733 i, hook_entries[i]);
1736 if (info->underflow[i] == 0xFFFFFFFF) {
1737 duprintf("Invalid underflow %u %u\n",
1744 newinfo = xt_alloc_table_info(size);
1748 newinfo->number = number;
1749 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1750 newinfo->hook_entry[i] = info->hook_entry[i];
1751 newinfo->underflow[i] = info->underflow[i];
1753 entry1 = newinfo->entries[raw_smp_processor_id()];
1756 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1757 compat_copy_entry_from_user,
1758 &pos, &size, name, newinfo, entry1);
1759 xt_compat_flush_offsets(AF_INET);
1760 xt_compat_unlock(AF_INET);
1765 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1769 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1773 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1774 compat_release_entry, &j);
1775 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1776 xt_free_table_info(newinfo);
1780 /* And one copy for every other CPU */
1781 for_each_possible_cpu(i)
1782 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1783 memcpy(newinfo->entries[i], entry1, newinfo->size);
1787 xt_free_table_info(info);
1791 xt_free_table_info(newinfo);
1793 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1796 xt_compat_flush_offsets(AF_INET);
1797 xt_compat_unlock(AF_INET);
1802 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1805 struct compat_ipt_replace tmp;
1806 struct xt_table_info *newinfo;
1807 void *loc_cpu_entry;
1809 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1812 /* overflow check */
1813 if (tmp.size >= INT_MAX / num_possible_cpus())
1815 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1818 newinfo = xt_alloc_table_info(tmp.size);
1822 /* choose the copy that is on our node/cpu */
1823 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1824 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1830 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1831 &newinfo, &loc_cpu_entry, tmp.size,
1832 tmp.num_entries, tmp.hook_entry,
1837 duprintf("compat_do_replace: Translated table\n");
1839 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1840 tmp.num_counters, compat_ptr(tmp.counters));
1842 goto free_newinfo_untrans;
1845 free_newinfo_untrans:
1846 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1848 xt_free_table_info(newinfo);
1853 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1858 if (!capable(CAP_NET_ADMIN))
1862 case IPT_SO_SET_REPLACE:
1863 ret = compat_do_replace(sock_net(sk), user, len);
1866 case IPT_SO_SET_ADD_COUNTERS:
1867 ret = do_add_counters(sock_net(sk), user, len, 1);
1871 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1878 struct compat_ipt_get_entries {
1879 char name[IPT_TABLE_MAXNAMELEN];
1881 struct compat_ipt_entry entrytable[0];
1885 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1886 void __user *userptr)
1888 struct xt_counters *counters;
1889 const struct xt_table_info *private = table->private;
1893 const void *loc_cpu_entry;
1896 counters = alloc_counters(table);
1897 if (IS_ERR(counters))
1898 return PTR_ERR(counters);
1900 /* choose the copy that is on our node/cpu, ...
1901 * This choice is lazy (because current thread is
1902 * allowed to migrate to another cpu)
1904 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1907 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1908 compat_copy_entry_to_user,
1909 &pos, &size, counters, &i);
1916 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1920 struct compat_ipt_get_entries get;
1923 if (*len < sizeof(get)) {
1924 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1928 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1931 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1932 duprintf("compat_get_entries: %u != %zu\n",
1933 *len, sizeof(get) + get.size);
1937 xt_compat_lock(AF_INET);
1938 t = xt_find_table_lock(net, AF_INET, get.name);
1939 if (t && !IS_ERR(t)) {
1940 const struct xt_table_info *private = t->private;
1941 struct xt_table_info info;
1942 duprintf("t->private->number = %u\n", private->number);
1943 ret = compat_table_info(private, &info);
1944 if (!ret && get.size == info.size) {
1945 ret = compat_copy_entries_to_user(private->size,
1946 t, uptr->entrytable);
1948 duprintf("compat_get_entries: I've got %u not %u!\n",
1949 private->size, get.size);
1952 xt_compat_flush_offsets(AF_INET);
1956 ret = t ? PTR_ERR(t) : -ENOENT;
1958 xt_compat_unlock(AF_INET);
1962 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1965 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1969 if (!capable(CAP_NET_ADMIN))
1973 case IPT_SO_GET_INFO:
1974 ret = get_info(sock_net(sk), user, len, 1);
1976 case IPT_SO_GET_ENTRIES:
1977 ret = compat_get_entries(sock_net(sk), user, len);
1980 ret = do_ipt_get_ctl(sk, cmd, user, len);
1987 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1991 if (!capable(CAP_NET_ADMIN))
1995 case IPT_SO_SET_REPLACE:
1996 ret = do_replace(sock_net(sk), user, len);
1999 case IPT_SO_SET_ADD_COUNTERS:
2000 ret = do_add_counters(sock_net(sk), user, len, 0);
2004 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2012 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2016 if (!capable(CAP_NET_ADMIN))
2020 case IPT_SO_GET_INFO:
2021 ret = get_info(sock_net(sk), user, len, 0);
2024 case IPT_SO_GET_ENTRIES:
2025 ret = get_entries(sock_net(sk), user, len);
2028 case IPT_SO_GET_REVISION_MATCH:
2029 case IPT_SO_GET_REVISION_TARGET: {
2030 struct ipt_get_revision rev;
2033 if (*len != sizeof(rev)) {
2037 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2042 if (cmd == IPT_SO_GET_REVISION_TARGET)
2047 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2050 "ipt_%s", rev.name);
2055 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2062 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2063 const struct ipt_replace *repl)
2066 struct xt_table_info *newinfo;
2067 struct xt_table_info bootstrap
2068 = { 0, 0, 0, { 0 }, { 0 }, { } };
2069 void *loc_cpu_entry;
2070 struct xt_table *new_table;
2072 newinfo = xt_alloc_table_info(repl->size);
2078 /* choose the copy on our node/cpu, but dont care about preemption */
2079 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2080 memcpy(loc_cpu_entry, repl->entries, repl->size);
2082 ret = translate_table(table->name, table->valid_hooks,
2083 newinfo, loc_cpu_entry, repl->size,
2090 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2091 if (IS_ERR(new_table)) {
2092 ret = PTR_ERR(new_table);
2099 xt_free_table_info(newinfo);
2101 return ERR_PTR(ret);
2104 void ipt_unregister_table(struct xt_table *table)
2106 struct xt_table_info *private;
2107 void *loc_cpu_entry;
2108 struct module *table_owner = table->me;
2110 private = xt_unregister_table(table);
2112 /* Decrease module usage counts and free resources */
2113 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2114 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2115 if (private->number > private->initial_entries)
2116 module_put(table_owner);
2117 xt_free_table_info(private);
2120 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2122 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2123 u_int8_t type, u_int8_t code,
2126 return ((test_type == 0xFF) ||
2127 (type == test_type && code >= min_code && code <= max_code))
2132 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2134 const struct icmphdr *ic;
2135 struct icmphdr _icmph;
2136 const struct ipt_icmp *icmpinfo = par->matchinfo;
2138 /* Must not be a fragment. */
2139 if (par->fragoff != 0)
2142 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2144 /* We've been asked to examine this packet, and we
2145 * can't. Hence, no choice but to drop.
2147 duprintf("Dropping evil ICMP tinygram.\n");
2148 *par->hotdrop = true;
2152 return icmp_type_code_match(icmpinfo->type,
2156 !!(icmpinfo->invflags&IPT_ICMP_INV));
2159 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2161 const struct ipt_icmp *icmpinfo = par->matchinfo;
2163 /* Must specify no unknown invflags */
2164 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2167 /* The built-in targets: standard (NULL) and error. */
2168 static struct xt_target ipt_standard_target __read_mostly = {
2169 .name = IPT_STANDARD_TARGET,
2170 .targetsize = sizeof(int),
2172 #ifdef CONFIG_COMPAT
2173 .compatsize = sizeof(compat_int_t),
2174 .compat_from_user = compat_standard_from_user,
2175 .compat_to_user = compat_standard_to_user,
2179 static struct xt_target ipt_error_target __read_mostly = {
2180 .name = IPT_ERROR_TARGET,
2181 .target = ipt_error,
2182 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2186 static struct nf_sockopt_ops ipt_sockopts = {
2188 .set_optmin = IPT_BASE_CTL,
2189 .set_optmax = IPT_SO_SET_MAX+1,
2190 .set = do_ipt_set_ctl,
2191 #ifdef CONFIG_COMPAT
2192 .compat_set = compat_do_ipt_set_ctl,
2194 .get_optmin = IPT_BASE_CTL,
2195 .get_optmax = IPT_SO_GET_MAX+1,
2196 .get = do_ipt_get_ctl,
2197 #ifdef CONFIG_COMPAT
2198 .compat_get = compat_do_ipt_get_ctl,
2200 .owner = THIS_MODULE,
2203 static struct xt_match icmp_matchstruct __read_mostly = {
2205 .match = icmp_match,
2206 .matchsize = sizeof(struct ipt_icmp),
2207 .checkentry = icmp_checkentry,
2208 .proto = IPPROTO_ICMP,
2212 static int __net_init ip_tables_net_init(struct net *net)
2214 return xt_proto_init(net, AF_INET);
2217 static void __net_exit ip_tables_net_exit(struct net *net)
2219 xt_proto_fini(net, AF_INET);
2222 static struct pernet_operations ip_tables_net_ops = {
2223 .init = ip_tables_net_init,
2224 .exit = ip_tables_net_exit,
2227 static int __init ip_tables_init(void)
2231 ret = register_pernet_subsys(&ip_tables_net_ops);
2235 /* Noone else will be downing sem now, so we won't sleep */
2236 ret = xt_register_target(&ipt_standard_target);
2239 ret = xt_register_target(&ipt_error_target);
2242 ret = xt_register_match(&icmp_matchstruct);
2246 /* Register setsockopt */
2247 ret = nf_register_sockopt(&ipt_sockopts);
2251 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2255 xt_unregister_match(&icmp_matchstruct);
2257 xt_unregister_target(&ipt_error_target);
2259 xt_unregister_target(&ipt_standard_target);
2261 unregister_pernet_subsys(&ip_tables_net_ops);
2266 static void __exit ip_tables_fini(void)
2268 nf_unregister_sockopt(&ipt_sockopts);
2270 xt_unregister_match(&icmp_matchstruct);
2271 xt_unregister_target(&ipt_error_target);
2272 xt_unregister_target(&ipt_standard_target);
2274 unregister_pernet_subsys(&ip_tables_net_ops);
2277 EXPORT_SYMBOL(ipt_register_table);
2278 EXPORT_SYMBOL(ipt_unregister_table);
2279 EXPORT_SYMBOL(ipt_do_table);
2280 module_init(ip_tables_init);
2281 module_exit(ip_tables_fini);