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) &&
479 t->verdict < 0 && unconditional(&e->ip)) ||
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, struct net *net, unsigned int *i)
558 struct xt_mtdtor_param par;
560 if (i && (*i)-- == 0)
564 par.match = m->u.kernel.match;
565 par.matchinfo = m->data;
566 par.family = NFPROTO_IPV4;
567 if (par.match->destroy != NULL)
568 par.match->destroy(&par);
569 module_put(par.match->me);
574 check_entry(struct ipt_entry *e, const char *name)
576 struct ipt_entry_target *t;
578 if (!ip_checkentry(&e->ip)) {
579 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
583 if (e->target_offset + sizeof(struct ipt_entry_target) >
587 t = ipt_get_target(e);
588 if (e->target_offset + t->u.target_size > e->next_offset)
595 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
598 const struct ipt_ip *ip = par->entryinfo;
601 par->match = m->u.kernel.match;
602 par->matchinfo = m->data;
604 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
605 ip->proto, ip->invflags & IPT_INV_PROTO);
607 duprintf("ip_tables: check failed for `%s'.\n",
616 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
619 struct xt_match *match;
622 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
624 "ipt_%s", m->u.user.name);
625 if (IS_ERR(match) || !match) {
626 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
627 return match ? PTR_ERR(match) : -ENOENT;
629 m->u.kernel.match = match;
631 ret = check_match(m, par, i);
637 module_put(m->u.kernel.match->me);
641 static int check_target(struct ipt_entry *e, const char *name)
643 struct ipt_entry_target *t = ipt_get_target(e);
644 struct xt_tgchk_param par = {
647 .target = t->u.kernel.target,
649 .hook_mask = e->comefrom,
650 .family = NFPROTO_IPV4,
654 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
655 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
657 duprintf("ip_tables: check failed for `%s'.\n",
658 t->u.kernel.target->name);
665 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
666 unsigned int size, unsigned int *i)
668 struct ipt_entry_target *t;
669 struct xt_target *target;
672 struct xt_mtchk_param mtpar;
674 ret = check_entry(e, name);
681 mtpar.entryinfo = &e->ip;
682 mtpar.hook_mask = e->comefrom;
683 mtpar.family = NFPROTO_IPV4;
684 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
686 goto cleanup_matches;
688 t = ipt_get_target(e);
689 target = try_then_request_module(xt_find_target(AF_INET,
692 "ipt_%s", t->u.user.name);
693 if (IS_ERR(target) || !target) {
694 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
695 ret = target ? PTR_ERR(target) : -ENOENT;
696 goto cleanup_matches;
698 t->u.kernel.target = target;
700 ret = check_target(e, name);
707 module_put(t->u.kernel.target->me);
709 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
713 static bool check_underflow(struct ipt_entry *e)
715 const struct ipt_entry_target *t;
716 unsigned int verdict;
718 if (!unconditional(&e->ip))
720 t = ipt_get_target(e);
721 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
723 verdict = ((struct ipt_standard_target *)t)->verdict;
724 verdict = -verdict - 1;
725 return verdict == NF_DROP || verdict == NF_ACCEPT;
729 check_entry_size_and_hooks(struct ipt_entry *e,
730 struct xt_table_info *newinfo,
732 unsigned char *limit,
733 const unsigned int *hook_entries,
734 const unsigned int *underflows,
735 unsigned int valid_hooks,
740 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
741 (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
742 duprintf("Bad offset %p\n", e);
747 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
748 duprintf("checking: element %p size %u\n",
753 /* Check hooks & underflows */
754 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
755 if (!(valid_hooks & (1 << h)))
757 if ((unsigned char *)e - base == hook_entries[h])
758 newinfo->hook_entry[h] = hook_entries[h];
759 if ((unsigned char *)e - base == underflows[h]) {
760 if (!check_underflow(e)) {
761 pr_err("Underflows must be unconditional and "
762 "use the STANDARD target with "
766 newinfo->underflow[h] = underflows[h];
770 /* Clear counters and comefrom */
771 e->counters = ((struct xt_counters) { 0, 0 });
779 cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i)
781 struct xt_tgdtor_param par;
782 struct ipt_entry_target *t;
784 if (i && (*i)-- == 0)
787 /* Cleanup all matches */
788 IPT_MATCH_ITERATE(e, cleanup_match, net, NULL);
789 t = ipt_get_target(e);
791 par.target = t->u.kernel.target;
792 par.targinfo = t->data;
793 par.family = NFPROTO_IPV4;
794 if (par.target->destroy != NULL)
795 par.target->destroy(&par);
796 module_put(par.target->me);
800 /* Checks and translates the user-supplied table segment (held in
803 translate_table(struct net *net,
805 unsigned int valid_hooks,
806 struct xt_table_info *newinfo,
810 const unsigned int *hook_entries,
811 const unsigned int *underflows)
816 newinfo->size = size;
817 newinfo->number = number;
819 /* Init all hooks to impossible value. */
820 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
821 newinfo->hook_entry[i] = 0xFFFFFFFF;
822 newinfo->underflow[i] = 0xFFFFFFFF;
825 duprintf("translate_table: size %u\n", newinfo->size);
827 /* Walk through entries, checking offsets. */
828 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
829 check_entry_size_and_hooks,
833 hook_entries, underflows, valid_hooks, &i);
838 duprintf("translate_table: %u not %u entries\n",
843 /* Check hooks all assigned */
844 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
845 /* Only hooks which are valid */
846 if (!(valid_hooks & (1 << i)))
848 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
849 duprintf("Invalid hook entry %u %u\n",
853 if (newinfo->underflow[i] == 0xFFFFFFFF) {
854 duprintf("Invalid underflow %u %u\n",
860 if (!mark_source_chains(newinfo, valid_hooks, entry0))
863 /* Finally, each sanity check must pass */
865 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
866 find_check_entry, net, name, size, &i);
869 IPT_ENTRY_ITERATE(entry0, newinfo->size,
870 cleanup_entry, net, &i);
874 /* And one copy for every other CPU */
875 for_each_possible_cpu(i) {
876 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
877 memcpy(newinfo->entries[i], entry0, newinfo->size);
885 add_entry_to_counter(const struct ipt_entry *e,
886 struct xt_counters total[],
889 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
896 set_entry_to_counter(const struct ipt_entry *e,
897 struct ipt_counters total[],
900 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
907 get_counters(const struct xt_table_info *t,
908 struct xt_counters counters[])
914 /* Instead of clearing (by a previous call to memset())
915 * the counters and using adds, we set the counters
916 * with data used by 'current' CPU.
918 * Bottom half has to be disabled to prevent deadlock
919 * if new softirq were to run and call ipt_do_table
922 curcpu = smp_processor_id();
925 IPT_ENTRY_ITERATE(t->entries[curcpu],
927 set_entry_to_counter,
931 for_each_possible_cpu(cpu) {
936 IPT_ENTRY_ITERATE(t->entries[cpu],
938 add_entry_to_counter,
941 xt_info_wrunlock(cpu);
946 static struct xt_counters * alloc_counters(struct xt_table *table)
948 unsigned int countersize;
949 struct xt_counters *counters;
950 struct xt_table_info *private = table->private;
952 /* We need atomic snapshot of counters: rest doesn't change
953 (other than comefrom, which userspace doesn't care
955 countersize = sizeof(struct xt_counters) * private->number;
956 counters = vmalloc_node(countersize, numa_node_id());
958 if (counters == NULL)
959 return ERR_PTR(-ENOMEM);
961 get_counters(private, counters);
967 copy_entries_to_user(unsigned int total_size,
968 struct xt_table *table,
969 void __user *userptr)
971 unsigned int off, num;
973 struct xt_counters *counters;
974 const struct xt_table_info *private = table->private;
976 const void *loc_cpu_entry;
978 counters = alloc_counters(table);
979 if (IS_ERR(counters))
980 return PTR_ERR(counters);
982 /* choose the copy that is on our node/cpu, ...
983 * This choice is lazy (because current thread is
984 * allowed to migrate to another cpu)
986 loc_cpu_entry = private->entries[raw_smp_processor_id()];
987 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
992 /* FIXME: use iterator macros --RR */
993 /* ... then go back and fix counters and names */
994 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
996 const struct ipt_entry_match *m;
997 const struct ipt_entry_target *t;
999 e = (struct ipt_entry *)(loc_cpu_entry + off);
1000 if (copy_to_user(userptr + off
1001 + offsetof(struct ipt_entry, counters),
1003 sizeof(counters[num])) != 0) {
1008 for (i = sizeof(struct ipt_entry);
1009 i < e->target_offset;
1010 i += m->u.match_size) {
1013 if (copy_to_user(userptr + off + i
1014 + offsetof(struct ipt_entry_match,
1016 m->u.kernel.match->name,
1017 strlen(m->u.kernel.match->name)+1)
1024 t = ipt_get_target(e);
1025 if (copy_to_user(userptr + off + e->target_offset
1026 + offsetof(struct ipt_entry_target,
1028 t->u.kernel.target->name,
1029 strlen(t->u.kernel.target->name)+1) != 0) {
1040 #ifdef CONFIG_COMPAT
1041 static void compat_standard_from_user(void *dst, void *src)
1043 int v = *(compat_int_t *)src;
1046 v += xt_compat_calc_jump(AF_INET, v);
1047 memcpy(dst, &v, sizeof(v));
1050 static int compat_standard_to_user(void __user *dst, void *src)
1052 compat_int_t cv = *(int *)src;
1055 cv -= xt_compat_calc_jump(AF_INET, cv);
1056 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1060 compat_calc_match(struct ipt_entry_match *m, int *size)
1062 *size += xt_compat_match_offset(m->u.kernel.match);
1066 static int compat_calc_entry(struct ipt_entry *e,
1067 const struct xt_table_info *info,
1068 void *base, struct xt_table_info *newinfo)
1070 struct ipt_entry_target *t;
1071 unsigned int entry_offset;
1074 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1075 entry_offset = (void *)e - base;
1076 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1077 t = ipt_get_target(e);
1078 off += xt_compat_target_offset(t->u.kernel.target);
1079 newinfo->size -= off;
1080 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1084 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1085 if (info->hook_entry[i] &&
1086 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1087 newinfo->hook_entry[i] -= off;
1088 if (info->underflow[i] &&
1089 (e < (struct ipt_entry *)(base + info->underflow[i])))
1090 newinfo->underflow[i] -= off;
1095 static int compat_table_info(const struct xt_table_info *info,
1096 struct xt_table_info *newinfo)
1098 void *loc_cpu_entry;
1100 if (!newinfo || !info)
1103 /* we dont care about newinfo->entries[] */
1104 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1105 newinfo->initial_entries = 0;
1106 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1107 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1108 compat_calc_entry, info, loc_cpu_entry,
1113 static int get_info(struct net *net, void __user *user, int *len, int compat)
1115 char name[IPT_TABLE_MAXNAMELEN];
1119 if (*len != sizeof(struct ipt_getinfo)) {
1120 duprintf("length %u != %zu\n", *len,
1121 sizeof(struct ipt_getinfo));
1125 if (copy_from_user(name, user, sizeof(name)) != 0)
1128 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1129 #ifdef CONFIG_COMPAT
1131 xt_compat_lock(AF_INET);
1133 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1134 "iptable_%s", name);
1135 if (t && !IS_ERR(t)) {
1136 struct ipt_getinfo info;
1137 const struct xt_table_info *private = t->private;
1139 #ifdef CONFIG_COMPAT
1141 struct xt_table_info tmp;
1142 ret = compat_table_info(private, &tmp);
1143 xt_compat_flush_offsets(AF_INET);
1147 info.valid_hooks = t->valid_hooks;
1148 memcpy(info.hook_entry, private->hook_entry,
1149 sizeof(info.hook_entry));
1150 memcpy(info.underflow, private->underflow,
1151 sizeof(info.underflow));
1152 info.num_entries = private->number;
1153 info.size = private->size;
1154 strcpy(info.name, name);
1156 if (copy_to_user(user, &info, *len) != 0)
1164 ret = t ? PTR_ERR(t) : -ENOENT;
1165 #ifdef CONFIG_COMPAT
1167 xt_compat_unlock(AF_INET);
1173 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1176 struct ipt_get_entries get;
1179 if (*len < sizeof(get)) {
1180 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1183 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1185 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1186 duprintf("get_entries: %u != %zu\n",
1187 *len, sizeof(get) + get.size);
1191 t = xt_find_table_lock(net, AF_INET, get.name);
1192 if (t && !IS_ERR(t)) {
1193 const struct xt_table_info *private = t->private;
1194 duprintf("t->private->number = %u\n", private->number);
1195 if (get.size == private->size)
1196 ret = copy_entries_to_user(private->size,
1197 t, uptr->entrytable);
1199 duprintf("get_entries: I've got %u not %u!\n",
1200 private->size, get.size);
1206 ret = t ? PTR_ERR(t) : -ENOENT;
1212 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1213 struct xt_table_info *newinfo, unsigned int num_counters,
1214 void __user *counters_ptr)
1218 struct xt_table_info *oldinfo;
1219 struct xt_counters *counters;
1220 void *loc_cpu_old_entry;
1223 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1229 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1230 "iptable_%s", name);
1231 if (!t || IS_ERR(t)) {
1232 ret = t ? PTR_ERR(t) : -ENOENT;
1233 goto free_newinfo_counters_untrans;
1237 if (valid_hooks != t->valid_hooks) {
1238 duprintf("Valid hook crap: %08X vs %08X\n",
1239 valid_hooks, t->valid_hooks);
1244 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1248 /* Update module usage count based on number of rules */
1249 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1250 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1251 if ((oldinfo->number > oldinfo->initial_entries) ||
1252 (newinfo->number <= oldinfo->initial_entries))
1254 if ((oldinfo->number > oldinfo->initial_entries) &&
1255 (newinfo->number <= oldinfo->initial_entries))
1258 /* Get the old counters, and synchronize with replace */
1259 get_counters(oldinfo, counters);
1261 /* Decrease module usage counts and free resource */
1262 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1263 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1265 xt_free_table_info(oldinfo);
1266 if (copy_to_user(counters_ptr, counters,
1267 sizeof(struct xt_counters) * num_counters) != 0)
1276 free_newinfo_counters_untrans:
1283 do_replace(struct net *net, void __user *user, unsigned int len)
1286 struct ipt_replace tmp;
1287 struct xt_table_info *newinfo;
1288 void *loc_cpu_entry;
1290 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1293 /* overflow check */
1294 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1297 newinfo = xt_alloc_table_info(tmp.size);
1301 /* choose the copy that is on our node/cpu */
1302 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1303 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1309 ret = translate_table(net, tmp.name, tmp.valid_hooks,
1310 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1311 tmp.hook_entry, tmp.underflow);
1315 duprintf("ip_tables: Translated table\n");
1317 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1318 tmp.num_counters, tmp.counters);
1320 goto free_newinfo_untrans;
1323 free_newinfo_untrans:
1324 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1326 xt_free_table_info(newinfo);
1330 /* We're lazy, and add to the first CPU; overflow works its fey magic
1331 * and everything is OK. */
1333 add_counter_to_entry(struct ipt_entry *e,
1334 const struct xt_counters addme[],
1337 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1344 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1346 unsigned int i, curcpu;
1347 struct xt_counters_info tmp;
1348 struct xt_counters *paddc;
1349 unsigned int num_counters;
1354 const struct xt_table_info *private;
1356 void *loc_cpu_entry;
1357 #ifdef CONFIG_COMPAT
1358 struct compat_xt_counters_info compat_tmp;
1362 size = sizeof(struct compat_xt_counters_info);
1367 size = sizeof(struct xt_counters_info);
1370 if (copy_from_user(ptmp, user, size) != 0)
1373 #ifdef CONFIG_COMPAT
1375 num_counters = compat_tmp.num_counters;
1376 name = compat_tmp.name;
1380 num_counters = tmp.num_counters;
1384 if (len != size + num_counters * sizeof(struct xt_counters))
1387 paddc = vmalloc_node(len - size, numa_node_id());
1391 if (copy_from_user(paddc, user + size, len - size) != 0) {
1396 t = xt_find_table_lock(net, AF_INET, name);
1397 if (!t || IS_ERR(t)) {
1398 ret = t ? PTR_ERR(t) : -ENOENT;
1403 private = t->private;
1404 if (private->number != num_counters) {
1406 goto unlock_up_free;
1410 /* Choose the copy that is on our node */
1411 curcpu = smp_processor_id();
1412 loc_cpu_entry = private->entries[curcpu];
1413 xt_info_wrlock(curcpu);
1414 IPT_ENTRY_ITERATE(loc_cpu_entry,
1416 add_counter_to_entry,
1419 xt_info_wrunlock(curcpu);
1430 #ifdef CONFIG_COMPAT
1431 struct compat_ipt_replace {
1432 char name[IPT_TABLE_MAXNAMELEN];
1436 u32 hook_entry[NF_INET_NUMHOOKS];
1437 u32 underflow[NF_INET_NUMHOOKS];
1439 compat_uptr_t counters; /* struct ipt_counters * */
1440 struct compat_ipt_entry entries[0];
1444 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1445 unsigned int *size, struct xt_counters *counters,
1448 struct ipt_entry_target *t;
1449 struct compat_ipt_entry __user *ce;
1450 u_int16_t target_offset, next_offset;
1451 compat_uint_t origsize;
1456 ce = (struct compat_ipt_entry __user *)*dstptr;
1457 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1460 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1463 *dstptr += sizeof(struct compat_ipt_entry);
1464 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1466 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1467 target_offset = e->target_offset - (origsize - *size);
1470 t = ipt_get_target(e);
1471 ret = xt_compat_target_to_user(t, dstptr, size);
1475 next_offset = e->next_offset - (origsize - *size);
1476 if (put_user(target_offset, &ce->target_offset))
1478 if (put_user(next_offset, &ce->next_offset))
1488 compat_find_calc_match(struct ipt_entry_match *m,
1490 const struct ipt_ip *ip,
1491 unsigned int hookmask,
1492 int *size, unsigned int *i)
1494 struct xt_match *match;
1496 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1497 m->u.user.revision),
1498 "ipt_%s", m->u.user.name);
1499 if (IS_ERR(match) || !match) {
1500 duprintf("compat_check_calc_match: `%s' not found\n",
1502 return match ? PTR_ERR(match) : -ENOENT;
1504 m->u.kernel.match = match;
1505 *size += xt_compat_match_offset(match);
1512 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1514 if (i && (*i)-- == 0)
1517 module_put(m->u.kernel.match->me);
1522 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1524 struct ipt_entry_target *t;
1526 if (i && (*i)-- == 0)
1529 /* Cleanup all matches */
1530 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1531 t = compat_ipt_get_target(e);
1532 module_put(t->u.kernel.target->me);
1537 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1538 struct xt_table_info *newinfo,
1540 unsigned char *base,
1541 unsigned char *limit,
1542 unsigned int *hook_entries,
1543 unsigned int *underflows,
1547 struct ipt_entry_target *t;
1548 struct xt_target *target;
1549 unsigned int entry_offset;
1553 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1554 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1555 (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1556 duprintf("Bad offset %p, limit = %p\n", e, limit);
1560 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1561 sizeof(struct compat_xt_entry_target)) {
1562 duprintf("checking: element %p size %u\n",
1567 /* For purposes of check_entry casting the compat entry is fine */
1568 ret = check_entry((struct ipt_entry *)e, name);
1572 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1573 entry_offset = (void *)e - (void *)base;
1575 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1576 &e->ip, e->comefrom, &off, &j);
1578 goto release_matches;
1580 t = compat_ipt_get_target(e);
1581 target = try_then_request_module(xt_find_target(AF_INET,
1583 t->u.user.revision),
1584 "ipt_%s", t->u.user.name);
1585 if (IS_ERR(target) || !target) {
1586 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1588 ret = target ? PTR_ERR(target) : -ENOENT;
1589 goto release_matches;
1591 t->u.kernel.target = target;
1593 off += xt_compat_target_offset(target);
1595 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1599 /* Check hooks & underflows */
1600 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1601 if ((unsigned char *)e - base == hook_entries[h])
1602 newinfo->hook_entry[h] = hook_entries[h];
1603 if ((unsigned char *)e - base == underflows[h])
1604 newinfo->underflow[h] = underflows[h];
1607 /* Clear counters and comefrom */
1608 memset(&e->counters, 0, sizeof(e->counters));
1615 module_put(t->u.kernel.target->me);
1617 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1622 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1623 unsigned int *size, const char *name,
1624 struct xt_table_info *newinfo, unsigned char *base)
1626 struct ipt_entry_target *t;
1627 struct xt_target *target;
1628 struct ipt_entry *de;
1629 unsigned int origsize;
1634 de = (struct ipt_entry *)*dstptr;
1635 memcpy(de, e, sizeof(struct ipt_entry));
1636 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1638 *dstptr += sizeof(struct ipt_entry);
1639 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1641 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1645 de->target_offset = e->target_offset - (origsize - *size);
1646 t = compat_ipt_get_target(e);
1647 target = t->u.kernel.target;
1648 xt_compat_target_from_user(t, dstptr, size);
1650 de->next_offset = e->next_offset - (origsize - *size);
1651 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1652 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1653 newinfo->hook_entry[h] -= origsize - *size;
1654 if ((unsigned char *)de - base < newinfo->underflow[h])
1655 newinfo->underflow[h] -= origsize - *size;
1661 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,
1664 struct xt_mtchk_param mtpar;
1671 mtpar.entryinfo = &e->ip;
1672 mtpar.hook_mask = e->comefrom;
1673 mtpar.family = NFPROTO_IPV4;
1674 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1676 goto cleanup_matches;
1678 ret = check_target(e, name);
1680 goto cleanup_matches;
1686 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
1691 translate_compat_table(struct net *net,
1693 unsigned int valid_hooks,
1694 struct xt_table_info **pinfo,
1696 unsigned int total_size,
1697 unsigned int number,
1698 unsigned int *hook_entries,
1699 unsigned int *underflows)
1702 struct xt_table_info *newinfo, *info;
1703 void *pos, *entry0, *entry1;
1710 info->number = number;
1712 /* Init all hooks to impossible value. */
1713 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1714 info->hook_entry[i] = 0xFFFFFFFF;
1715 info->underflow[i] = 0xFFFFFFFF;
1718 duprintf("translate_compat_table: size %u\n", info->size);
1720 xt_compat_lock(AF_INET);
1721 /* Walk through entries, checking offsets. */
1722 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1723 check_compat_entry_size_and_hooks,
1724 info, &size, entry0,
1725 entry0 + total_size,
1726 hook_entries, underflows, &j, name);
1732 duprintf("translate_compat_table: %u not %u entries\n",
1737 /* Check hooks all assigned */
1738 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1739 /* Only hooks which are valid */
1740 if (!(valid_hooks & (1 << i)))
1742 if (info->hook_entry[i] == 0xFFFFFFFF) {
1743 duprintf("Invalid hook entry %u %u\n",
1744 i, hook_entries[i]);
1747 if (info->underflow[i] == 0xFFFFFFFF) {
1748 duprintf("Invalid underflow %u %u\n",
1755 newinfo = xt_alloc_table_info(size);
1759 newinfo->number = number;
1760 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1761 newinfo->hook_entry[i] = info->hook_entry[i];
1762 newinfo->underflow[i] = info->underflow[i];
1764 entry1 = newinfo->entries[raw_smp_processor_id()];
1767 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1768 compat_copy_entry_from_user,
1769 &pos, &size, name, newinfo, entry1);
1770 xt_compat_flush_offsets(AF_INET);
1771 xt_compat_unlock(AF_INET);
1776 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1780 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1784 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1785 compat_release_entry, &j);
1786 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i);
1787 xt_free_table_info(newinfo);
1791 /* And one copy for every other CPU */
1792 for_each_possible_cpu(i)
1793 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1794 memcpy(newinfo->entries[i], entry1, newinfo->size);
1798 xt_free_table_info(info);
1802 xt_free_table_info(newinfo);
1804 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1807 xt_compat_flush_offsets(AF_INET);
1808 xt_compat_unlock(AF_INET);
1813 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1816 struct compat_ipt_replace tmp;
1817 struct xt_table_info *newinfo;
1818 void *loc_cpu_entry;
1820 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1823 /* overflow check */
1824 if (tmp.size >= INT_MAX / num_possible_cpus())
1826 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1829 newinfo = xt_alloc_table_info(tmp.size);
1833 /* choose the copy that is on our node/cpu */
1834 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1835 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1841 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1842 &newinfo, &loc_cpu_entry, tmp.size,
1843 tmp.num_entries, tmp.hook_entry,
1848 duprintf("compat_do_replace: Translated table\n");
1850 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1851 tmp.num_counters, compat_ptr(tmp.counters));
1853 goto free_newinfo_untrans;
1856 free_newinfo_untrans:
1857 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1859 xt_free_table_info(newinfo);
1864 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1869 if (!capable(CAP_NET_ADMIN))
1873 case IPT_SO_SET_REPLACE:
1874 ret = compat_do_replace(sock_net(sk), user, len);
1877 case IPT_SO_SET_ADD_COUNTERS:
1878 ret = do_add_counters(sock_net(sk), user, len, 1);
1882 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1889 struct compat_ipt_get_entries {
1890 char name[IPT_TABLE_MAXNAMELEN];
1892 struct compat_ipt_entry entrytable[0];
1896 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1897 void __user *userptr)
1899 struct xt_counters *counters;
1900 const struct xt_table_info *private = table->private;
1904 const void *loc_cpu_entry;
1907 counters = alloc_counters(table);
1908 if (IS_ERR(counters))
1909 return PTR_ERR(counters);
1911 /* choose the copy that is on our node/cpu, ...
1912 * This choice is lazy (because current thread is
1913 * allowed to migrate to another cpu)
1915 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1918 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1919 compat_copy_entry_to_user,
1920 &pos, &size, counters, &i);
1927 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1931 struct compat_ipt_get_entries get;
1934 if (*len < sizeof(get)) {
1935 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1939 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1942 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1943 duprintf("compat_get_entries: %u != %zu\n",
1944 *len, sizeof(get) + get.size);
1948 xt_compat_lock(AF_INET);
1949 t = xt_find_table_lock(net, AF_INET, get.name);
1950 if (t && !IS_ERR(t)) {
1951 const struct xt_table_info *private = t->private;
1952 struct xt_table_info info;
1953 duprintf("t->private->number = %u\n", private->number);
1954 ret = compat_table_info(private, &info);
1955 if (!ret && get.size == info.size) {
1956 ret = compat_copy_entries_to_user(private->size,
1957 t, uptr->entrytable);
1959 duprintf("compat_get_entries: I've got %u not %u!\n",
1960 private->size, get.size);
1963 xt_compat_flush_offsets(AF_INET);
1967 ret = t ? PTR_ERR(t) : -ENOENT;
1969 xt_compat_unlock(AF_INET);
1973 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1976 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1980 if (!capable(CAP_NET_ADMIN))
1984 case IPT_SO_GET_INFO:
1985 ret = get_info(sock_net(sk), user, len, 1);
1987 case IPT_SO_GET_ENTRIES:
1988 ret = compat_get_entries(sock_net(sk), user, len);
1991 ret = do_ipt_get_ctl(sk, cmd, user, len);
1998 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2002 if (!capable(CAP_NET_ADMIN))
2006 case IPT_SO_SET_REPLACE:
2007 ret = do_replace(sock_net(sk), user, len);
2010 case IPT_SO_SET_ADD_COUNTERS:
2011 ret = do_add_counters(sock_net(sk), user, len, 0);
2015 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2023 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2027 if (!capable(CAP_NET_ADMIN))
2031 case IPT_SO_GET_INFO:
2032 ret = get_info(sock_net(sk), user, len, 0);
2035 case IPT_SO_GET_ENTRIES:
2036 ret = get_entries(sock_net(sk), user, len);
2039 case IPT_SO_GET_REVISION_MATCH:
2040 case IPT_SO_GET_REVISION_TARGET: {
2041 struct ipt_get_revision rev;
2044 if (*len != sizeof(rev)) {
2048 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2053 if (cmd == IPT_SO_GET_REVISION_TARGET)
2058 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2061 "ipt_%s", rev.name);
2066 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2073 struct xt_table *ipt_register_table(struct net *net,
2074 const struct xt_table *table,
2075 const struct ipt_replace *repl)
2078 struct xt_table_info *newinfo;
2079 struct xt_table_info bootstrap
2080 = { 0, 0, 0, { 0 }, { 0 }, { } };
2081 void *loc_cpu_entry;
2082 struct xt_table *new_table;
2084 newinfo = xt_alloc_table_info(repl->size);
2090 /* choose the copy on our node/cpu, but dont care about preemption */
2091 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2092 memcpy(loc_cpu_entry, repl->entries, repl->size);
2094 ret = translate_table(net, table->name, table->valid_hooks,
2095 newinfo, loc_cpu_entry, repl->size,
2102 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2103 if (IS_ERR(new_table)) {
2104 ret = PTR_ERR(new_table);
2111 xt_free_table_info(newinfo);
2113 return ERR_PTR(ret);
2116 void ipt_unregister_table(struct net *net, struct xt_table *table)
2118 struct xt_table_info *private;
2119 void *loc_cpu_entry;
2120 struct module *table_owner = table->me;
2122 private = xt_unregister_table(table);
2124 /* Decrease module usage counts and free resources */
2125 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2126 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL);
2127 if (private->number > private->initial_entries)
2128 module_put(table_owner);
2129 xt_free_table_info(private);
2132 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2134 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2135 u_int8_t type, u_int8_t code,
2138 return ((test_type == 0xFF) ||
2139 (type == test_type && code >= min_code && code <= max_code))
2144 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2146 const struct icmphdr *ic;
2147 struct icmphdr _icmph;
2148 const struct ipt_icmp *icmpinfo = par->matchinfo;
2150 /* Must not be a fragment. */
2151 if (par->fragoff != 0)
2154 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2156 /* We've been asked to examine this packet, and we
2157 * can't. Hence, no choice but to drop.
2159 duprintf("Dropping evil ICMP tinygram.\n");
2160 *par->hotdrop = true;
2164 return icmp_type_code_match(icmpinfo->type,
2168 !!(icmpinfo->invflags&IPT_ICMP_INV));
2171 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2173 const struct ipt_icmp *icmpinfo = par->matchinfo;
2175 /* Must specify no unknown invflags */
2176 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2179 /* The built-in targets: standard (NULL) and error. */
2180 static struct xt_target ipt_standard_target __read_mostly = {
2181 .name = IPT_STANDARD_TARGET,
2182 .targetsize = sizeof(int),
2183 .family = NFPROTO_IPV4,
2184 #ifdef CONFIG_COMPAT
2185 .compatsize = sizeof(compat_int_t),
2186 .compat_from_user = compat_standard_from_user,
2187 .compat_to_user = compat_standard_to_user,
2191 static struct xt_target ipt_error_target __read_mostly = {
2192 .name = IPT_ERROR_TARGET,
2193 .target = ipt_error,
2194 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2195 .family = NFPROTO_IPV4,
2198 static struct nf_sockopt_ops ipt_sockopts = {
2200 .set_optmin = IPT_BASE_CTL,
2201 .set_optmax = IPT_SO_SET_MAX+1,
2202 .set = do_ipt_set_ctl,
2203 #ifdef CONFIG_COMPAT
2204 .compat_set = compat_do_ipt_set_ctl,
2206 .get_optmin = IPT_BASE_CTL,
2207 .get_optmax = IPT_SO_GET_MAX+1,
2208 .get = do_ipt_get_ctl,
2209 #ifdef CONFIG_COMPAT
2210 .compat_get = compat_do_ipt_get_ctl,
2212 .owner = THIS_MODULE,
2215 static struct xt_match icmp_matchstruct __read_mostly = {
2217 .match = icmp_match,
2218 .matchsize = sizeof(struct ipt_icmp),
2219 .checkentry = icmp_checkentry,
2220 .proto = IPPROTO_ICMP,
2221 .family = NFPROTO_IPV4,
2224 static int __net_init ip_tables_net_init(struct net *net)
2226 return xt_proto_init(net, NFPROTO_IPV4);
2229 static void __net_exit ip_tables_net_exit(struct net *net)
2231 xt_proto_fini(net, NFPROTO_IPV4);
2234 static struct pernet_operations ip_tables_net_ops = {
2235 .init = ip_tables_net_init,
2236 .exit = ip_tables_net_exit,
2239 static int __init ip_tables_init(void)
2243 ret = register_pernet_subsys(&ip_tables_net_ops);
2247 /* Noone else will be downing sem now, so we won't sleep */
2248 ret = xt_register_target(&ipt_standard_target);
2251 ret = xt_register_target(&ipt_error_target);
2254 ret = xt_register_match(&icmp_matchstruct);
2258 /* Register setsockopt */
2259 ret = nf_register_sockopt(&ipt_sockopts);
2263 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2267 xt_unregister_match(&icmp_matchstruct);
2269 xt_unregister_target(&ipt_error_target);
2271 xt_unregister_target(&ipt_standard_target);
2273 unregister_pernet_subsys(&ip_tables_net_ops);
2278 static void __exit ip_tables_fini(void)
2280 nf_unregister_sockopt(&ipt_sockopts);
2282 xt_unregister_match(&icmp_matchstruct);
2283 xt_unregister_target(&ipt_error_target);
2284 xt_unregister_target(&ipt_standard_target);
2286 unregister_pernet_subsys(&ip_tables_net_ops);
2289 EXPORT_SYMBOL(ipt_register_table);
2290 EXPORT_SYMBOL(ipt_unregister_table);
2291 EXPORT_SYMBOL(ipt_do_table);
2292 module_init(ip_tables_init);
2293 module_exit(ip_tables_fini);