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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/cache.h>
13 #include <linux/capability.h>
14 #include <linux/skbuff.h>
15 #include <linux/kmod.h>
16 #include <linux/vmalloc.h>
17 #include <linux/netdevice.h>
18 #include <linux/module.h>
19 #include <linux/icmp.h>
21 #include <net/compat.h>
22 #include <asm/uaccess.h>
23 #include <linux/mutex.h>
24 #include <linux/proc_fs.h>
25 #include <linux/err.h>
26 #include <linux/cpumask.h>
28 #include <linux/netfilter/x_tables.h>
29 #include <linux/netfilter_ipv4/ip_tables.h>
30 #include <net/netfilter/nf_log.h>
32 MODULE_LICENSE("GPL");
33 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
34 MODULE_DESCRIPTION("IPv4 packet filter");
36 /*#define DEBUG_IP_FIREWALL*/
37 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
38 /*#define DEBUG_IP_FIREWALL_USER*/
40 #ifdef DEBUG_IP_FIREWALL
41 #define dprintf(format, args...) printk(format , ## args)
43 #define dprintf(format, args...)
46 #ifdef DEBUG_IP_FIREWALL_USER
47 #define duprintf(format, args...) printk(format , ## args)
49 #define duprintf(format, args...)
52 #ifdef CONFIG_NETFILTER_DEBUG
53 #define IP_NF_ASSERT(x) \
56 printk("IP_NF_ASSERT: %s:%s:%u\n", \
57 __func__, __FILE__, __LINE__); \
60 #define IP_NF_ASSERT(x)
64 /* All the better to debug you with... */
70 We keep a set of rules for each CPU, so we can avoid write-locking
71 them in the softirq when updating the counters and therefore
72 only need to read-lock in the softirq; doing a write_lock_bh() in user
73 context stops packets coming through and allows user context to read
74 the counters or update the rules.
76 Hence the start of any table is given by get_table() below. */
78 /* Returns whether matches rule or not. */
79 /* Performance critical - called for every packet */
81 ip_packet_match(const struct iphdr *ip,
84 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 ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
108 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
109 dprintf("VIA in mismatch (%s vs %s).%s\n",
110 indev, ipinfo->iniface,
111 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
115 ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
117 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
118 dprintf("VIA out mismatch (%s vs %s).%s\n",
119 outdev, ipinfo->outiface,
120 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
124 /* Check specific protocol */
126 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
127 dprintf("Packet protocol %hi does not match %hi.%s\n",
128 ip->protocol, ipinfo->proto,
129 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
133 /* If we have a fragment rule but the packet is not a fragment
134 * then we return zero */
135 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
136 dprintf("Fragment rule but not fragment.%s\n",
137 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
145 ip_checkentry(const struct ipt_ip *ip)
147 if (ip->flags & ~IPT_F_MASK) {
148 duprintf("Unknown flag bits set: %08X\n",
149 ip->flags & ~IPT_F_MASK);
152 if (ip->invflags & ~IPT_INV_MASK) {
153 duprintf("Unknown invflag bits set: %08X\n",
154 ip->invflags & ~IPT_INV_MASK);
161 ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
164 printk("ip_tables: error: `%s'\n",
165 (const char *)par->targinfo);
170 /* Performance critical - called for every packet */
172 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
173 struct xt_match_param *par)
175 par->match = m->u.kernel.match;
176 par->matchinfo = m->data;
178 /* Stop iteration if it doesn't match */
179 if (!m->u.kernel.match->match(skb, par))
185 /* Performance critical */
186 static inline struct ipt_entry *
187 get_entry(void *base, unsigned int offset)
189 return (struct ipt_entry *)(base + offset);
192 /* All zeroes == unconditional rule. */
193 /* Mildly perf critical (only if packet tracing is on) */
194 static inline bool unconditional(const struct ipt_ip *ip)
196 static const struct ipt_ip uncond;
198 return memcmp(ip, &uncond, sizeof(uncond)) == 0;
202 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
203 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
204 static const char *const hooknames[] = {
205 [NF_INET_PRE_ROUTING] = "PREROUTING",
206 [NF_INET_LOCAL_IN] = "INPUT",
207 [NF_INET_FORWARD] = "FORWARD",
208 [NF_INET_LOCAL_OUT] = "OUTPUT",
209 [NF_INET_POST_ROUTING] = "POSTROUTING",
212 enum nf_ip_trace_comments {
213 NF_IP_TRACE_COMMENT_RULE,
214 NF_IP_TRACE_COMMENT_RETURN,
215 NF_IP_TRACE_COMMENT_POLICY,
218 static const char *const comments[] = {
219 [NF_IP_TRACE_COMMENT_RULE] = "rule",
220 [NF_IP_TRACE_COMMENT_RETURN] = "return",
221 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
224 static struct nf_loginfo trace_loginfo = {
225 .type = NF_LOG_TYPE_LOG,
229 .logflags = NF_LOG_MASK,
234 /* Mildly perf critical (only if packet tracing is on) */
236 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
237 const char *hookname, const char **chainname,
238 const char **comment, unsigned int *rulenum)
240 struct ipt_standard_target *t = (void *)ipt_get_target(s);
242 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
243 /* Head of user chain: ERROR target with chainname */
244 *chainname = t->target.data;
249 if (s->target_offset == sizeof(struct ipt_entry)
250 && strcmp(t->target.u.kernel.target->name,
251 IPT_STANDARD_TARGET) == 0
253 && unconditional(&s->ip)) {
254 /* Tail of chains: STANDARD target (return/policy) */
255 *comment = *chainname == hookname
256 ? comments[NF_IP_TRACE_COMMENT_POLICY]
257 : comments[NF_IP_TRACE_COMMENT_RETURN];
266 static void trace_packet(struct sk_buff *skb,
268 const struct net_device *in,
269 const struct net_device *out,
270 const char *tablename,
271 struct xt_table_info *private,
275 const struct ipt_entry *root;
276 const char *hookname, *chainname, *comment;
277 unsigned int rulenum = 0;
279 table_base = private->entries[smp_processor_id()];
280 root = get_entry(table_base, private->hook_entry[hook]);
282 hookname = chainname = hooknames[hook];
283 comment = comments[NF_IP_TRACE_COMMENT_RULE];
285 IPT_ENTRY_ITERATE(root,
286 private->size - private->hook_entry[hook],
287 get_chainname_rulenum,
288 e, hookname, &chainname, &comment, &rulenum);
290 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
291 "TRACE: %s:%s:%s:%u ",
292 tablename, chainname, comment, rulenum);
297 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
299 return (void *)entry + entry->next_offset;
302 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
304 ipt_do_table(struct sk_buff *skb,
306 const struct net_device *in,
307 const struct net_device *out,
308 struct xt_table *table)
310 #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
312 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
313 const struct iphdr *ip;
314 bool hotdrop = false;
315 /* Initializing verdict to NF_DROP keeps gcc happy. */
316 unsigned int verdict = NF_DROP;
317 const char *indev, *outdev;
319 struct ipt_entry *e, *back;
320 struct xt_table_info *private;
321 struct xt_match_param mtpar;
322 struct xt_target_param tgpar;
326 indev = in ? in->name : nulldevname;
327 outdev = out ? out->name : nulldevname;
328 /* We handle fragments by dealing with the first fragment as
329 * if it was a normal packet. All other fragments are treated
330 * normally, except that they will NEVER match rules that ask
331 * things we don't know, ie. tcp syn flag or ports). If the
332 * rule is also a fragment-specific rule, non-fragments won't
334 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
335 mtpar.thoff = ip_hdrlen(skb);
336 mtpar.hotdrop = &hotdrop;
337 mtpar.in = tgpar.in = in;
338 mtpar.out = tgpar.out = out;
339 mtpar.family = tgpar.family = NFPROTO_IPV4;
340 mtpar.hooknum = tgpar.hooknum = hook;
342 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
344 private = table->private;
345 table_base = private->entries[smp_processor_id()];
347 e = get_entry(table_base, private->hook_entry[hook]);
349 /* For return from builtin chain */
350 back = get_entry(table_base, private->underflow[hook]);
353 struct ipt_entry_target *t;
357 if (!ip_packet_match(ip, indev, outdev,
358 &e->ip, mtpar.fragoff) ||
359 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
360 e = ipt_next_entry(e);
364 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
366 t = ipt_get_target(e);
367 IP_NF_ASSERT(t->u.kernel.target);
369 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
370 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
371 /* The packet is traced: log it */
372 if (unlikely(skb->nf_trace))
373 trace_packet(skb, hook, in, out,
374 table->name, private, e);
376 /* Standard target? */
377 if (!t->u.kernel.target->target) {
380 v = ((struct ipt_standard_target *)t)->verdict;
382 /* Pop from stack? */
383 if (v != IPT_RETURN) {
384 verdict = (unsigned)(-v) - 1;
388 back = get_entry(table_base, back->comefrom);
391 if (table_base + v != ipt_next_entry(e)
392 && !(e->ip.flags & IPT_F_GOTO)) {
393 /* Save old back ptr in next entry */
394 struct ipt_entry *next = ipt_next_entry(e);
395 next->comefrom = (void *)back - table_base;
396 /* set back pointer to next entry */
400 e = get_entry(table_base, v);
404 /* Targets which reenter must return
406 tgpar.target = t->u.kernel.target;
407 tgpar.targinfo = t->data;
410 #ifdef CONFIG_NETFILTER_DEBUG
411 tb_comefrom = 0xeeeeeeec;
413 verdict = t->u.kernel.target->target(skb, &tgpar);
414 #ifdef CONFIG_NETFILTER_DEBUG
415 if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
416 printk("Target %s reentered!\n",
417 t->u.kernel.target->name);
420 tb_comefrom = 0x57acc001;
422 /* Target might have changed stuff. */
424 if (verdict == IPT_CONTINUE)
425 e = ipt_next_entry(e);
430 xt_info_rdunlock_bh();
432 #ifdef DEBUG_ALLOW_ALL
443 /* Figures out from what hook each rule can be called: returns 0 if
444 there are loops. Puts hook bitmask in comefrom. */
446 mark_source_chains(struct xt_table_info *newinfo,
447 unsigned int valid_hooks, void *entry0)
451 /* No recursion; use packet counter to save back ptrs (reset
452 to 0 as we leave), and comefrom to save source hook bitmask */
453 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
454 unsigned int pos = newinfo->hook_entry[hook];
455 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
457 if (!(valid_hooks & (1 << hook)))
460 /* Set initial back pointer. */
461 e->counters.pcnt = pos;
464 struct ipt_standard_target *t
465 = (void *)ipt_get_target(e);
466 int visited = e->comefrom & (1 << hook);
468 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
469 printk("iptables: loop hook %u pos %u %08X.\n",
470 hook, pos, e->comefrom);
473 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
475 /* Unconditional return/END. */
476 if ((e->target_offset == sizeof(struct ipt_entry)
477 && (strcmp(t->target.u.user.name,
478 IPT_STANDARD_TARGET) == 0)
480 && unconditional(&e->ip)) || visited) {
481 unsigned int oldpos, size;
483 if ((strcmp(t->target.u.user.name,
484 IPT_STANDARD_TARGET) == 0) &&
485 t->verdict < -NF_MAX_VERDICT - 1) {
486 duprintf("mark_source_chains: bad "
487 "negative verdict (%i)\n",
492 /* Return: backtrack through the last
495 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
496 #ifdef DEBUG_IP_FIREWALL_USER
498 & (1 << NF_INET_NUMHOOKS)) {
499 duprintf("Back unset "
506 pos = e->counters.pcnt;
507 e->counters.pcnt = 0;
509 /* We're at the start. */
513 e = (struct ipt_entry *)
515 } while (oldpos == pos + e->next_offset);
518 size = e->next_offset;
519 e = (struct ipt_entry *)
520 (entry0 + pos + size);
521 e->counters.pcnt = pos;
524 int newpos = t->verdict;
526 if (strcmp(t->target.u.user.name,
527 IPT_STANDARD_TARGET) == 0
529 if (newpos > newinfo->size -
530 sizeof(struct ipt_entry)) {
531 duprintf("mark_source_chains: "
532 "bad verdict (%i)\n",
536 /* This a jump; chase it. */
537 duprintf("Jump rule %u -> %u\n",
540 /* ... this is a fallthru */
541 newpos = pos + e->next_offset;
543 e = (struct ipt_entry *)
545 e->counters.pcnt = pos;
550 duprintf("Finished chain %u\n", hook);
556 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
558 struct xt_mtdtor_param par;
560 if (i && (*i)-- == 0)
563 par.match = m->u.kernel.match;
564 par.matchinfo = m->data;
565 par.family = NFPROTO_IPV4;
566 if (par.match->destroy != NULL)
567 par.match->destroy(&par);
568 module_put(par.match->me);
573 check_entry(struct ipt_entry *e, const char *name)
575 struct ipt_entry_target *t;
577 if (!ip_checkentry(&e->ip)) {
578 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
582 if (e->target_offset + sizeof(struct ipt_entry_target) >
586 t = ipt_get_target(e);
587 if (e->target_offset + t->u.target_size > e->next_offset)
594 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
597 const struct ipt_ip *ip = par->entryinfo;
600 par->match = m->u.kernel.match;
601 par->matchinfo = m->data;
603 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
604 ip->proto, ip->invflags & IPT_INV_PROTO);
606 duprintf("ip_tables: check failed for `%s'.\n",
615 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
618 struct xt_match *match;
621 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
623 "ipt_%s", m->u.user.name);
624 if (IS_ERR(match) || !match) {
625 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
626 return match ? PTR_ERR(match) : -ENOENT;
628 m->u.kernel.match = match;
630 ret = check_match(m, par, i);
636 module_put(m->u.kernel.match->me);
640 static int check_target(struct ipt_entry *e, const char *name)
642 struct ipt_entry_target *t = ipt_get_target(e);
643 struct xt_tgchk_param par = {
646 .target = t->u.kernel.target,
648 .hook_mask = e->comefrom,
649 .family = NFPROTO_IPV4,
653 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
654 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
656 duprintf("ip_tables: check failed for `%s'.\n",
657 t->u.kernel.target->name);
664 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
667 struct ipt_entry_target *t;
668 struct xt_target *target;
671 struct xt_mtchk_param mtpar;
673 ret = check_entry(e, name);
679 mtpar.entryinfo = &e->ip;
680 mtpar.hook_mask = e->comefrom;
681 mtpar.family = NFPROTO_IPV4;
682 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
684 goto cleanup_matches;
686 t = ipt_get_target(e);
687 target = try_then_request_module(xt_find_target(AF_INET,
690 "ipt_%s", t->u.user.name);
691 if (IS_ERR(target) || !target) {
692 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
693 ret = target ? PTR_ERR(target) : -ENOENT;
694 goto cleanup_matches;
696 t->u.kernel.target = target;
698 ret = check_target(e, name);
705 module_put(t->u.kernel.target->me);
707 IPT_MATCH_ITERATE(e, cleanup_match, &j);
712 check_entry_size_and_hooks(struct ipt_entry *e,
713 struct xt_table_info *newinfo,
715 unsigned char *limit,
716 const unsigned int *hook_entries,
717 const unsigned int *underflows,
718 unsigned int valid_hooks,
723 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
724 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
725 duprintf("Bad offset %p\n", e);
730 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
731 duprintf("checking: element %p size %u\n",
736 /* Check hooks & underflows */
737 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
738 if (!(valid_hooks & (1 << h)))
740 if ((unsigned char *)e - base == hook_entries[h])
741 newinfo->hook_entry[h] = hook_entries[h];
742 if ((unsigned char *)e - base == underflows[h]) {
743 if (!unconditional(&e->ip)) {
744 pr_err("Underflows must be unconditional\n");
747 newinfo->underflow[h] = underflows[h];
751 /* Clear counters and comefrom */
752 e->counters = ((struct xt_counters) { 0, 0 });
760 cleanup_entry(struct ipt_entry *e, unsigned int *i)
762 struct xt_tgdtor_param par;
763 struct ipt_entry_target *t;
765 if (i && (*i)-- == 0)
768 /* Cleanup all matches */
769 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
770 t = ipt_get_target(e);
772 par.target = t->u.kernel.target;
773 par.targinfo = t->data;
774 par.family = NFPROTO_IPV4;
775 if (par.target->destroy != NULL)
776 par.target->destroy(&par);
777 module_put(par.target->me);
781 /* Checks and translates the user-supplied table segment (held in
784 translate_table(const char *name,
785 unsigned int valid_hooks,
786 struct xt_table_info *newinfo,
790 const unsigned int *hook_entries,
791 const unsigned int *underflows)
796 newinfo->size = size;
797 newinfo->number = number;
799 /* Init all hooks to impossible value. */
800 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
801 newinfo->hook_entry[i] = 0xFFFFFFFF;
802 newinfo->underflow[i] = 0xFFFFFFFF;
805 duprintf("translate_table: size %u\n", newinfo->size);
807 /* Walk through entries, checking offsets. */
808 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
809 check_entry_size_and_hooks,
813 hook_entries, underflows, valid_hooks, &i);
818 duprintf("translate_table: %u not %u entries\n",
823 /* Check hooks all assigned */
824 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
825 /* Only hooks which are valid */
826 if (!(valid_hooks & (1 << i)))
828 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
829 duprintf("Invalid hook entry %u %u\n",
833 if (newinfo->underflow[i] == 0xFFFFFFFF) {
834 duprintf("Invalid underflow %u %u\n",
840 if (!mark_source_chains(newinfo, valid_hooks, entry0))
843 /* Finally, each sanity check must pass */
845 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
846 find_check_entry, name, size, &i);
849 IPT_ENTRY_ITERATE(entry0, newinfo->size,
854 /* And one copy for every other CPU */
855 for_each_possible_cpu(i) {
856 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
857 memcpy(newinfo->entries[i], entry0, newinfo->size);
865 add_entry_to_counter(const struct ipt_entry *e,
866 struct xt_counters total[],
869 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
876 set_entry_to_counter(const struct ipt_entry *e,
877 struct ipt_counters total[],
880 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
887 get_counters(const struct xt_table_info *t,
888 struct xt_counters counters[])
894 /* Instead of clearing (by a previous call to memset())
895 * the counters and using adds, we set the counters
896 * with data used by 'current' CPU.
898 * Bottom half has to be disabled to prevent deadlock
899 * if new softirq were to run and call ipt_do_table
902 curcpu = smp_processor_id();
905 IPT_ENTRY_ITERATE(t->entries[curcpu],
907 set_entry_to_counter,
911 for_each_possible_cpu(cpu) {
916 IPT_ENTRY_ITERATE(t->entries[cpu],
918 add_entry_to_counter,
921 xt_info_wrunlock(cpu);
926 static struct xt_counters * alloc_counters(struct xt_table *table)
928 unsigned int countersize;
929 struct xt_counters *counters;
930 struct xt_table_info *private = table->private;
932 /* We need atomic snapshot of counters: rest doesn't change
933 (other than comefrom, which userspace doesn't care
935 countersize = sizeof(struct xt_counters) * private->number;
936 counters = vmalloc_node(countersize, numa_node_id());
938 if (counters == NULL)
939 return ERR_PTR(-ENOMEM);
941 get_counters(private, counters);
947 copy_entries_to_user(unsigned int total_size,
948 struct xt_table *table,
949 void __user *userptr)
951 unsigned int off, num;
953 struct xt_counters *counters;
954 const struct xt_table_info *private = table->private;
956 const void *loc_cpu_entry;
958 counters = alloc_counters(table);
959 if (IS_ERR(counters))
960 return PTR_ERR(counters);
962 /* choose the copy that is on our node/cpu, ...
963 * This choice is lazy (because current thread is
964 * allowed to migrate to another cpu)
966 loc_cpu_entry = private->entries[raw_smp_processor_id()];
967 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
972 /* FIXME: use iterator macros --RR */
973 /* ... then go back and fix counters and names */
974 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
976 const struct ipt_entry_match *m;
977 const struct ipt_entry_target *t;
979 e = (struct ipt_entry *)(loc_cpu_entry + off);
980 if (copy_to_user(userptr + off
981 + offsetof(struct ipt_entry, counters),
983 sizeof(counters[num])) != 0) {
988 for (i = sizeof(struct ipt_entry);
989 i < e->target_offset;
990 i += m->u.match_size) {
993 if (copy_to_user(userptr + off + i
994 + offsetof(struct ipt_entry_match,
996 m->u.kernel.match->name,
997 strlen(m->u.kernel.match->name)+1)
1004 t = ipt_get_target(e);
1005 if (copy_to_user(userptr + off + e->target_offset
1006 + offsetof(struct ipt_entry_target,
1008 t->u.kernel.target->name,
1009 strlen(t->u.kernel.target->name)+1) != 0) {
1020 #ifdef CONFIG_COMPAT
1021 static void compat_standard_from_user(void *dst, void *src)
1023 int v = *(compat_int_t *)src;
1026 v += xt_compat_calc_jump(AF_INET, v);
1027 memcpy(dst, &v, sizeof(v));
1030 static int compat_standard_to_user(void __user *dst, void *src)
1032 compat_int_t cv = *(int *)src;
1035 cv -= xt_compat_calc_jump(AF_INET, cv);
1036 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1040 compat_calc_match(struct ipt_entry_match *m, int *size)
1042 *size += xt_compat_match_offset(m->u.kernel.match);
1046 static int compat_calc_entry(struct ipt_entry *e,
1047 const struct xt_table_info *info,
1048 void *base, struct xt_table_info *newinfo)
1050 struct ipt_entry_target *t;
1051 unsigned int entry_offset;
1054 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1055 entry_offset = (void *)e - base;
1056 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1057 t = ipt_get_target(e);
1058 off += xt_compat_target_offset(t->u.kernel.target);
1059 newinfo->size -= off;
1060 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1064 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1065 if (info->hook_entry[i] &&
1066 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1067 newinfo->hook_entry[i] -= off;
1068 if (info->underflow[i] &&
1069 (e < (struct ipt_entry *)(base + info->underflow[i])))
1070 newinfo->underflow[i] -= off;
1075 static int compat_table_info(const struct xt_table_info *info,
1076 struct xt_table_info *newinfo)
1078 void *loc_cpu_entry;
1080 if (!newinfo || !info)
1083 /* we dont care about newinfo->entries[] */
1084 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1085 newinfo->initial_entries = 0;
1086 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1087 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1088 compat_calc_entry, info, loc_cpu_entry,
1093 static int get_info(struct net *net, void __user *user, int *len, int compat)
1095 char name[IPT_TABLE_MAXNAMELEN];
1099 if (*len != sizeof(struct ipt_getinfo)) {
1100 duprintf("length %u != %zu\n", *len,
1101 sizeof(struct ipt_getinfo));
1105 if (copy_from_user(name, user, sizeof(name)) != 0)
1108 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1109 #ifdef CONFIG_COMPAT
1111 xt_compat_lock(AF_INET);
1113 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1114 "iptable_%s", name);
1115 if (t && !IS_ERR(t)) {
1116 struct ipt_getinfo info;
1117 const struct xt_table_info *private = t->private;
1119 #ifdef CONFIG_COMPAT
1121 struct xt_table_info tmp;
1122 ret = compat_table_info(private, &tmp);
1123 xt_compat_flush_offsets(AF_INET);
1127 info.valid_hooks = t->valid_hooks;
1128 memcpy(info.hook_entry, private->hook_entry,
1129 sizeof(info.hook_entry));
1130 memcpy(info.underflow, private->underflow,
1131 sizeof(info.underflow));
1132 info.num_entries = private->number;
1133 info.size = private->size;
1134 strcpy(info.name, name);
1136 if (copy_to_user(user, &info, *len) != 0)
1144 ret = t ? PTR_ERR(t) : -ENOENT;
1145 #ifdef CONFIG_COMPAT
1147 xt_compat_unlock(AF_INET);
1153 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1156 struct ipt_get_entries get;
1159 if (*len < sizeof(get)) {
1160 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1163 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1165 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1166 duprintf("get_entries: %u != %zu\n",
1167 *len, sizeof(get) + get.size);
1171 t = xt_find_table_lock(net, AF_INET, get.name);
1172 if (t && !IS_ERR(t)) {
1173 const struct xt_table_info *private = t->private;
1174 duprintf("t->private->number = %u\n", private->number);
1175 if (get.size == private->size)
1176 ret = copy_entries_to_user(private->size,
1177 t, uptr->entrytable);
1179 duprintf("get_entries: I've got %u not %u!\n",
1180 private->size, get.size);
1186 ret = t ? PTR_ERR(t) : -ENOENT;
1192 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1193 struct xt_table_info *newinfo, unsigned int num_counters,
1194 void __user *counters_ptr)
1198 struct xt_table_info *oldinfo;
1199 struct xt_counters *counters;
1200 void *loc_cpu_old_entry;
1203 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1209 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1210 "iptable_%s", name);
1211 if (!t || IS_ERR(t)) {
1212 ret = t ? PTR_ERR(t) : -ENOENT;
1213 goto free_newinfo_counters_untrans;
1217 if (valid_hooks != t->valid_hooks) {
1218 duprintf("Valid hook crap: %08X vs %08X\n",
1219 valid_hooks, t->valid_hooks);
1224 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1228 /* Update module usage count based on number of rules */
1229 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1230 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1231 if ((oldinfo->number > oldinfo->initial_entries) ||
1232 (newinfo->number <= oldinfo->initial_entries))
1234 if ((oldinfo->number > oldinfo->initial_entries) &&
1235 (newinfo->number <= oldinfo->initial_entries))
1238 /* Get the old counters, and synchronize with replace */
1239 get_counters(oldinfo, counters);
1241 /* Decrease module usage counts and free resource */
1242 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1243 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1245 xt_free_table_info(oldinfo);
1246 if (copy_to_user(counters_ptr, counters,
1247 sizeof(struct xt_counters) * num_counters) != 0)
1256 free_newinfo_counters_untrans:
1263 do_replace(struct net *net, void __user *user, unsigned int len)
1266 struct ipt_replace tmp;
1267 struct xt_table_info *newinfo;
1268 void *loc_cpu_entry;
1270 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1273 /* overflow check */
1274 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1277 newinfo = xt_alloc_table_info(tmp.size);
1281 /* choose the copy that is on our node/cpu */
1282 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1283 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1289 ret = translate_table(tmp.name, tmp.valid_hooks,
1290 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1291 tmp.hook_entry, tmp.underflow);
1295 duprintf("ip_tables: Translated table\n");
1297 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1298 tmp.num_counters, tmp.counters);
1300 goto free_newinfo_untrans;
1303 free_newinfo_untrans:
1304 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1306 xt_free_table_info(newinfo);
1310 /* We're lazy, and add to the first CPU; overflow works its fey magic
1311 * and everything is OK. */
1313 add_counter_to_entry(struct ipt_entry *e,
1314 const struct xt_counters addme[],
1317 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1324 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1326 unsigned int i, curcpu;
1327 struct xt_counters_info tmp;
1328 struct xt_counters *paddc;
1329 unsigned int num_counters;
1334 const struct xt_table_info *private;
1336 void *loc_cpu_entry;
1337 #ifdef CONFIG_COMPAT
1338 struct compat_xt_counters_info compat_tmp;
1342 size = sizeof(struct compat_xt_counters_info);
1347 size = sizeof(struct xt_counters_info);
1350 if (copy_from_user(ptmp, user, size) != 0)
1353 #ifdef CONFIG_COMPAT
1355 num_counters = compat_tmp.num_counters;
1356 name = compat_tmp.name;
1360 num_counters = tmp.num_counters;
1364 if (len != size + num_counters * sizeof(struct xt_counters))
1367 paddc = vmalloc_node(len - size, numa_node_id());
1371 if (copy_from_user(paddc, user + size, len - size) != 0) {
1376 t = xt_find_table_lock(net, AF_INET, name);
1377 if (!t || IS_ERR(t)) {
1378 ret = t ? PTR_ERR(t) : -ENOENT;
1383 private = t->private;
1384 if (private->number != num_counters) {
1386 goto unlock_up_free;
1390 /* Choose the copy that is on our node */
1391 curcpu = smp_processor_id();
1392 loc_cpu_entry = private->entries[curcpu];
1393 xt_info_wrlock(curcpu);
1394 IPT_ENTRY_ITERATE(loc_cpu_entry,
1396 add_counter_to_entry,
1399 xt_info_wrunlock(curcpu);
1410 #ifdef CONFIG_COMPAT
1411 struct compat_ipt_replace {
1412 char name[IPT_TABLE_MAXNAMELEN];
1416 u32 hook_entry[NF_INET_NUMHOOKS];
1417 u32 underflow[NF_INET_NUMHOOKS];
1419 compat_uptr_t counters; /* struct ipt_counters * */
1420 struct compat_ipt_entry entries[0];
1424 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1425 unsigned int *size, struct xt_counters *counters,
1428 struct ipt_entry_target *t;
1429 struct compat_ipt_entry __user *ce;
1430 u_int16_t target_offset, next_offset;
1431 compat_uint_t origsize;
1436 ce = (struct compat_ipt_entry __user *)*dstptr;
1437 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1440 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1443 *dstptr += sizeof(struct compat_ipt_entry);
1444 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1446 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1447 target_offset = e->target_offset - (origsize - *size);
1450 t = ipt_get_target(e);
1451 ret = xt_compat_target_to_user(t, dstptr, size);
1455 next_offset = e->next_offset - (origsize - *size);
1456 if (put_user(target_offset, &ce->target_offset))
1458 if (put_user(next_offset, &ce->next_offset))
1468 compat_find_calc_match(struct ipt_entry_match *m,
1470 const struct ipt_ip *ip,
1471 unsigned int hookmask,
1472 int *size, unsigned int *i)
1474 struct xt_match *match;
1476 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1477 m->u.user.revision),
1478 "ipt_%s", m->u.user.name);
1479 if (IS_ERR(match) || !match) {
1480 duprintf("compat_check_calc_match: `%s' not found\n",
1482 return match ? PTR_ERR(match) : -ENOENT;
1484 m->u.kernel.match = match;
1485 *size += xt_compat_match_offset(match);
1492 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1494 if (i && (*i)-- == 0)
1497 module_put(m->u.kernel.match->me);
1502 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1504 struct ipt_entry_target *t;
1506 if (i && (*i)-- == 0)
1509 /* Cleanup all matches */
1510 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1511 t = compat_ipt_get_target(e);
1512 module_put(t->u.kernel.target->me);
1517 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1518 struct xt_table_info *newinfo,
1520 unsigned char *base,
1521 unsigned char *limit,
1522 unsigned int *hook_entries,
1523 unsigned int *underflows,
1527 struct ipt_entry_target *t;
1528 struct xt_target *target;
1529 unsigned int entry_offset;
1533 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1534 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1535 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1536 duprintf("Bad offset %p, limit = %p\n", e, limit);
1540 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1541 sizeof(struct compat_xt_entry_target)) {
1542 duprintf("checking: element %p size %u\n",
1547 /* For purposes of check_entry casting the compat entry is fine */
1548 ret = check_entry((struct ipt_entry *)e, name);
1552 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1553 entry_offset = (void *)e - (void *)base;
1555 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1556 &e->ip, e->comefrom, &off, &j);
1558 goto release_matches;
1560 t = compat_ipt_get_target(e);
1561 target = try_then_request_module(xt_find_target(AF_INET,
1563 t->u.user.revision),
1564 "ipt_%s", t->u.user.name);
1565 if (IS_ERR(target) || !target) {
1566 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1568 ret = target ? PTR_ERR(target) : -ENOENT;
1569 goto release_matches;
1571 t->u.kernel.target = target;
1573 off += xt_compat_target_offset(target);
1575 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1579 /* Check hooks & underflows */
1580 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1581 if ((unsigned char *)e - base == hook_entries[h])
1582 newinfo->hook_entry[h] = hook_entries[h];
1583 if ((unsigned char *)e - base == underflows[h])
1584 newinfo->underflow[h] = underflows[h];
1587 /* Clear counters and comefrom */
1588 memset(&e->counters, 0, sizeof(e->counters));
1595 module_put(t->u.kernel.target->me);
1597 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1602 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1603 unsigned int *size, const char *name,
1604 struct xt_table_info *newinfo, unsigned char *base)
1606 struct ipt_entry_target *t;
1607 struct xt_target *target;
1608 struct ipt_entry *de;
1609 unsigned int origsize;
1614 de = (struct ipt_entry *)*dstptr;
1615 memcpy(de, e, sizeof(struct ipt_entry));
1616 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1618 *dstptr += sizeof(struct ipt_entry);
1619 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1621 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1625 de->target_offset = e->target_offset - (origsize - *size);
1626 t = compat_ipt_get_target(e);
1627 target = t->u.kernel.target;
1628 xt_compat_target_from_user(t, dstptr, size);
1630 de->next_offset = e->next_offset - (origsize - *size);
1631 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1632 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1633 newinfo->hook_entry[h] -= origsize - *size;
1634 if ((unsigned char *)de - base < newinfo->underflow[h])
1635 newinfo->underflow[h] -= origsize - *size;
1641 compat_check_entry(struct ipt_entry *e, const char *name,
1644 struct xt_mtchk_param mtpar;
1650 mtpar.entryinfo = &e->ip;
1651 mtpar.hook_mask = e->comefrom;
1652 mtpar.family = NFPROTO_IPV4;
1653 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1655 goto cleanup_matches;
1657 ret = check_target(e, name);
1659 goto cleanup_matches;
1665 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1670 translate_compat_table(const char *name,
1671 unsigned int valid_hooks,
1672 struct xt_table_info **pinfo,
1674 unsigned int total_size,
1675 unsigned int number,
1676 unsigned int *hook_entries,
1677 unsigned int *underflows)
1680 struct xt_table_info *newinfo, *info;
1681 void *pos, *entry0, *entry1;
1688 info->number = number;
1690 /* Init all hooks to impossible value. */
1691 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1692 info->hook_entry[i] = 0xFFFFFFFF;
1693 info->underflow[i] = 0xFFFFFFFF;
1696 duprintf("translate_compat_table: size %u\n", info->size);
1698 xt_compat_lock(AF_INET);
1699 /* Walk through entries, checking offsets. */
1700 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1701 check_compat_entry_size_and_hooks,
1702 info, &size, entry0,
1703 entry0 + total_size,
1704 hook_entries, underflows, &j, name);
1710 duprintf("translate_compat_table: %u not %u entries\n",
1715 /* Check hooks all assigned */
1716 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1717 /* Only hooks which are valid */
1718 if (!(valid_hooks & (1 << i)))
1720 if (info->hook_entry[i] == 0xFFFFFFFF) {
1721 duprintf("Invalid hook entry %u %u\n",
1722 i, hook_entries[i]);
1725 if (info->underflow[i] == 0xFFFFFFFF) {
1726 duprintf("Invalid underflow %u %u\n",
1733 newinfo = xt_alloc_table_info(size);
1737 newinfo->number = number;
1738 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1739 newinfo->hook_entry[i] = info->hook_entry[i];
1740 newinfo->underflow[i] = info->underflow[i];
1742 entry1 = newinfo->entries[raw_smp_processor_id()];
1745 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1746 compat_copy_entry_from_user,
1747 &pos, &size, name, newinfo, entry1);
1748 xt_compat_flush_offsets(AF_INET);
1749 xt_compat_unlock(AF_INET);
1754 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1758 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1762 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1763 compat_release_entry, &j);
1764 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1765 xt_free_table_info(newinfo);
1769 /* And one copy for every other CPU */
1770 for_each_possible_cpu(i)
1771 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1772 memcpy(newinfo->entries[i], entry1, newinfo->size);
1776 xt_free_table_info(info);
1780 xt_free_table_info(newinfo);
1782 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1785 xt_compat_flush_offsets(AF_INET);
1786 xt_compat_unlock(AF_INET);
1791 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1794 struct compat_ipt_replace tmp;
1795 struct xt_table_info *newinfo;
1796 void *loc_cpu_entry;
1798 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1801 /* overflow check */
1802 if (tmp.size >= INT_MAX / num_possible_cpus())
1804 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1807 newinfo = xt_alloc_table_info(tmp.size);
1811 /* choose the copy that is on our node/cpu */
1812 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1813 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1819 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1820 &newinfo, &loc_cpu_entry, tmp.size,
1821 tmp.num_entries, tmp.hook_entry,
1826 duprintf("compat_do_replace: Translated table\n");
1828 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1829 tmp.num_counters, compat_ptr(tmp.counters));
1831 goto free_newinfo_untrans;
1834 free_newinfo_untrans:
1835 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1837 xt_free_table_info(newinfo);
1842 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1847 if (!capable(CAP_NET_ADMIN))
1851 case IPT_SO_SET_REPLACE:
1852 ret = compat_do_replace(sock_net(sk), user, len);
1855 case IPT_SO_SET_ADD_COUNTERS:
1856 ret = do_add_counters(sock_net(sk), user, len, 1);
1860 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1867 struct compat_ipt_get_entries {
1868 char name[IPT_TABLE_MAXNAMELEN];
1870 struct compat_ipt_entry entrytable[0];
1874 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1875 void __user *userptr)
1877 struct xt_counters *counters;
1878 const struct xt_table_info *private = table->private;
1882 const void *loc_cpu_entry;
1885 counters = alloc_counters(table);
1886 if (IS_ERR(counters))
1887 return PTR_ERR(counters);
1889 /* choose the copy that is on our node/cpu, ...
1890 * This choice is lazy (because current thread is
1891 * allowed to migrate to another cpu)
1893 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1896 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1897 compat_copy_entry_to_user,
1898 &pos, &size, counters, &i);
1905 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1909 struct compat_ipt_get_entries get;
1912 if (*len < sizeof(get)) {
1913 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1917 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1920 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1921 duprintf("compat_get_entries: %u != %zu\n",
1922 *len, sizeof(get) + get.size);
1926 xt_compat_lock(AF_INET);
1927 t = xt_find_table_lock(net, AF_INET, get.name);
1928 if (t && !IS_ERR(t)) {
1929 const struct xt_table_info *private = t->private;
1930 struct xt_table_info info;
1931 duprintf("t->private->number = %u\n", private->number);
1932 ret = compat_table_info(private, &info);
1933 if (!ret && get.size == info.size) {
1934 ret = compat_copy_entries_to_user(private->size,
1935 t, uptr->entrytable);
1937 duprintf("compat_get_entries: I've got %u not %u!\n",
1938 private->size, get.size);
1941 xt_compat_flush_offsets(AF_INET);
1945 ret = t ? PTR_ERR(t) : -ENOENT;
1947 xt_compat_unlock(AF_INET);
1951 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1954 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1958 if (!capable(CAP_NET_ADMIN))
1962 case IPT_SO_GET_INFO:
1963 ret = get_info(sock_net(sk), user, len, 1);
1965 case IPT_SO_GET_ENTRIES:
1966 ret = compat_get_entries(sock_net(sk), user, len);
1969 ret = do_ipt_get_ctl(sk, cmd, user, len);
1976 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1980 if (!capable(CAP_NET_ADMIN))
1984 case IPT_SO_SET_REPLACE:
1985 ret = do_replace(sock_net(sk), user, len);
1988 case IPT_SO_SET_ADD_COUNTERS:
1989 ret = do_add_counters(sock_net(sk), user, len, 0);
1993 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2001 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2005 if (!capable(CAP_NET_ADMIN))
2009 case IPT_SO_GET_INFO:
2010 ret = get_info(sock_net(sk), user, len, 0);
2013 case IPT_SO_GET_ENTRIES:
2014 ret = get_entries(sock_net(sk), user, len);
2017 case IPT_SO_GET_REVISION_MATCH:
2018 case IPT_SO_GET_REVISION_TARGET: {
2019 struct ipt_get_revision rev;
2022 if (*len != sizeof(rev)) {
2026 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2031 if (cmd == IPT_SO_GET_REVISION_TARGET)
2036 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2039 "ipt_%s", rev.name);
2044 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2051 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2052 const struct ipt_replace *repl)
2055 struct xt_table_info *newinfo;
2056 struct xt_table_info bootstrap
2057 = { 0, 0, 0, { 0 }, { 0 }, { } };
2058 void *loc_cpu_entry;
2059 struct xt_table *new_table;
2061 newinfo = xt_alloc_table_info(repl->size);
2067 /* choose the copy on our node/cpu, but dont care about preemption */
2068 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2069 memcpy(loc_cpu_entry, repl->entries, repl->size);
2071 ret = translate_table(table->name, table->valid_hooks,
2072 newinfo, loc_cpu_entry, repl->size,
2079 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2080 if (IS_ERR(new_table)) {
2081 ret = PTR_ERR(new_table);
2088 xt_free_table_info(newinfo);
2090 return ERR_PTR(ret);
2093 void ipt_unregister_table(struct xt_table *table)
2095 struct xt_table_info *private;
2096 void *loc_cpu_entry;
2097 struct module *table_owner = table->me;
2099 private = xt_unregister_table(table);
2101 /* Decrease module usage counts and free resources */
2102 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2103 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2104 if (private->number > private->initial_entries)
2105 module_put(table_owner);
2106 xt_free_table_info(private);
2109 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2111 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2112 u_int8_t type, u_int8_t code,
2115 return ((test_type == 0xFF) ||
2116 (type == test_type && code >= min_code && code <= max_code))
2121 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2123 const struct icmphdr *ic;
2124 struct icmphdr _icmph;
2125 const struct ipt_icmp *icmpinfo = par->matchinfo;
2127 /* Must not be a fragment. */
2128 if (par->fragoff != 0)
2131 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2133 /* We've been asked to examine this packet, and we
2134 * can't. Hence, no choice but to drop.
2136 duprintf("Dropping evil ICMP tinygram.\n");
2137 *par->hotdrop = true;
2141 return icmp_type_code_match(icmpinfo->type,
2145 !!(icmpinfo->invflags&IPT_ICMP_INV));
2148 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2150 const struct ipt_icmp *icmpinfo = par->matchinfo;
2152 /* Must specify no unknown invflags */
2153 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2156 /* The built-in targets: standard (NULL) and error. */
2157 static struct xt_target ipt_standard_target __read_mostly = {
2158 .name = IPT_STANDARD_TARGET,
2159 .targetsize = sizeof(int),
2160 .family = NFPROTO_IPV4,
2161 #ifdef CONFIG_COMPAT
2162 .compatsize = sizeof(compat_int_t),
2163 .compat_from_user = compat_standard_from_user,
2164 .compat_to_user = compat_standard_to_user,
2168 static struct xt_target ipt_error_target __read_mostly = {
2169 .name = IPT_ERROR_TARGET,
2170 .target = ipt_error,
2171 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2172 .family = NFPROTO_IPV4,
2175 static struct nf_sockopt_ops ipt_sockopts = {
2177 .set_optmin = IPT_BASE_CTL,
2178 .set_optmax = IPT_SO_SET_MAX+1,
2179 .set = do_ipt_set_ctl,
2180 #ifdef CONFIG_COMPAT
2181 .compat_set = compat_do_ipt_set_ctl,
2183 .get_optmin = IPT_BASE_CTL,
2184 .get_optmax = IPT_SO_GET_MAX+1,
2185 .get = do_ipt_get_ctl,
2186 #ifdef CONFIG_COMPAT
2187 .compat_get = compat_do_ipt_get_ctl,
2189 .owner = THIS_MODULE,
2192 static struct xt_match icmp_matchstruct __read_mostly = {
2194 .match = icmp_match,
2195 .matchsize = sizeof(struct ipt_icmp),
2196 .checkentry = icmp_checkentry,
2197 .proto = IPPROTO_ICMP,
2198 .family = NFPROTO_IPV4,
2201 static int __net_init ip_tables_net_init(struct net *net)
2203 return xt_proto_init(net, NFPROTO_IPV4);
2206 static void __net_exit ip_tables_net_exit(struct net *net)
2208 xt_proto_fini(net, NFPROTO_IPV4);
2211 static struct pernet_operations ip_tables_net_ops = {
2212 .init = ip_tables_net_init,
2213 .exit = ip_tables_net_exit,
2216 static int __init ip_tables_init(void)
2220 ret = register_pernet_subsys(&ip_tables_net_ops);
2224 /* Noone else will be downing sem now, so we won't sleep */
2225 ret = xt_register_target(&ipt_standard_target);
2228 ret = xt_register_target(&ipt_error_target);
2231 ret = xt_register_match(&icmp_matchstruct);
2235 /* Register setsockopt */
2236 ret = nf_register_sockopt(&ipt_sockopts);
2240 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2244 xt_unregister_match(&icmp_matchstruct);
2246 xt_unregister_target(&ipt_error_target);
2248 xt_unregister_target(&ipt_standard_target);
2250 unregister_pernet_subsys(&ip_tables_net_ops);
2255 static void __exit ip_tables_fini(void)
2257 nf_unregister_sockopt(&ipt_sockopts);
2259 xt_unregister_match(&icmp_matchstruct);
2260 xt_unregister_target(&ipt_error_target);
2261 xt_unregister_target(&ipt_standard_target);
2263 unregister_pernet_subsys(&ip_tables_net_ops);
2266 EXPORT_SYMBOL(ipt_register_table);
2267 EXPORT_SYMBOL(ipt_unregister_table);
2268 EXPORT_SYMBOL(ipt_do_table);
2269 module_init(ip_tables_init);
2270 module_exit(ip_tables_fini);