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>
31 #include "../../netfilter/xt_repldata.h"
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
35 MODULE_DESCRIPTION("IPv4 packet filter");
37 /*#define DEBUG_IP_FIREWALL*/
38 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
39 /*#define DEBUG_IP_FIREWALL_USER*/
41 #ifdef DEBUG_IP_FIREWALL
42 #define dprintf(format, args...) printk(format , ## args)
44 #define dprintf(format, args...)
47 #ifdef DEBUG_IP_FIREWALL_USER
48 #define duprintf(format, args...) printk(format , ## args)
50 #define duprintf(format, args...)
53 #ifdef CONFIG_NETFILTER_DEBUG
54 #define IP_NF_ASSERT(x) \
57 printk("IP_NF_ASSERT: %s:%s:%u\n", \
58 __func__, __FILE__, __LINE__); \
61 #define IP_NF_ASSERT(x)
65 /* All the better to debug you with... */
70 void *ipt_alloc_initial_table(const struct xt_table *info)
72 return xt_alloc_initial_table(ipt, IPT);
74 EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);
77 We keep a set of rules for each CPU, so we can avoid write-locking
78 them in the softirq when updating the counters and therefore
79 only need to read-lock in the softirq; doing a write_lock_bh() in user
80 context stops packets coming through and allows user context to read
81 the counters or update the rules.
83 Hence the start of any table is given by get_table() below. */
85 /* Returns whether matches rule or not. */
86 /* Performance critical - called for every packet */
88 ip_packet_match(const struct iphdr *ip,
91 const struct ipt_ip *ipinfo,
96 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
98 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
100 FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
102 dprintf("Source or dest mismatch.\n");
104 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
105 &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
106 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
107 dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
108 &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
109 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
113 ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
115 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
116 dprintf("VIA in mismatch (%s vs %s).%s\n",
117 indev, ipinfo->iniface,
118 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
122 ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
124 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
125 dprintf("VIA out mismatch (%s vs %s).%s\n",
126 outdev, ipinfo->outiface,
127 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
131 /* Check specific protocol */
133 FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
134 dprintf("Packet protocol %hi does not match %hi.%s\n",
135 ip->protocol, ipinfo->proto,
136 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
140 /* If we have a fragment rule but the packet is not a fragment
141 * then we return zero */
142 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
143 dprintf("Fragment rule but not fragment.%s\n",
144 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
152 ip_checkentry(const struct ipt_ip *ip)
154 if (ip->flags & ~IPT_F_MASK) {
155 duprintf("Unknown flag bits set: %08X\n",
156 ip->flags & ~IPT_F_MASK);
159 if (ip->invflags & ~IPT_INV_MASK) {
160 duprintf("Unknown invflag bits set: %08X\n",
161 ip->invflags & ~IPT_INV_MASK);
168 ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
171 printk("ip_tables: error: `%s'\n",
172 (const char *)par->targinfo);
177 /* Performance critical - called for every packet */
179 do_match(const struct ipt_entry_match *m, const struct sk_buff *skb,
180 struct xt_match_param *par)
182 par->match = m->u.kernel.match;
183 par->matchinfo = m->data;
185 /* Stop iteration if it doesn't match */
186 if (!m->u.kernel.match->match(skb, par))
192 /* Performance critical */
193 static inline struct ipt_entry *
194 get_entry(const void *base, unsigned int offset)
196 return (struct ipt_entry *)(base + offset);
199 /* All zeroes == unconditional rule. */
200 /* Mildly perf critical (only if packet tracing is on) */
201 static inline bool unconditional(const struct ipt_ip *ip)
203 static const struct ipt_ip uncond;
205 return memcmp(ip, &uncond, sizeof(uncond)) == 0;
209 /* for const-correctness */
210 static inline const struct ipt_entry_target *
211 ipt_get_target_c(const struct ipt_entry *e)
213 return ipt_get_target((struct ipt_entry *)e);
216 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
217 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
218 static const char *const hooknames[] = {
219 [NF_INET_PRE_ROUTING] = "PREROUTING",
220 [NF_INET_LOCAL_IN] = "INPUT",
221 [NF_INET_FORWARD] = "FORWARD",
222 [NF_INET_LOCAL_OUT] = "OUTPUT",
223 [NF_INET_POST_ROUTING] = "POSTROUTING",
226 enum nf_ip_trace_comments {
227 NF_IP_TRACE_COMMENT_RULE,
228 NF_IP_TRACE_COMMENT_RETURN,
229 NF_IP_TRACE_COMMENT_POLICY,
232 static const char *const comments[] = {
233 [NF_IP_TRACE_COMMENT_RULE] = "rule",
234 [NF_IP_TRACE_COMMENT_RETURN] = "return",
235 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
238 static struct nf_loginfo trace_loginfo = {
239 .type = NF_LOG_TYPE_LOG,
243 .logflags = NF_LOG_MASK,
248 /* Mildly perf critical (only if packet tracing is on) */
250 get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e,
251 const char *hookname, const char **chainname,
252 const char **comment, unsigned int *rulenum)
254 const struct ipt_standard_target *t = (void *)ipt_get_target_c(s);
256 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
257 /* Head of user chain: ERROR target with chainname */
258 *chainname = t->target.data;
263 if (s->target_offset == sizeof(struct ipt_entry) &&
264 strcmp(t->target.u.kernel.target->name,
265 IPT_STANDARD_TARGET) == 0 &&
267 unconditional(&s->ip)) {
268 /* Tail of chains: STANDARD target (return/policy) */
269 *comment = *chainname == hookname
270 ? comments[NF_IP_TRACE_COMMENT_POLICY]
271 : comments[NF_IP_TRACE_COMMENT_RETURN];
280 static void trace_packet(const struct sk_buff *skb,
282 const struct net_device *in,
283 const struct net_device *out,
284 const char *tablename,
285 const struct xt_table_info *private,
286 const struct ipt_entry *e)
288 const void *table_base;
289 const struct ipt_entry *root;
290 const char *hookname, *chainname, *comment;
291 const struct ipt_entry *iter;
292 unsigned int rulenum = 0;
294 table_base = private->entries[smp_processor_id()];
295 root = get_entry(table_base, private->hook_entry[hook]);
297 hookname = chainname = hooknames[hook];
298 comment = comments[NF_IP_TRACE_COMMENT_RULE];
300 xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
301 if (get_chainname_rulenum(iter, e, hookname,
302 &chainname, &comment, &rulenum) != 0)
305 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
306 "TRACE: %s:%s:%s:%u ",
307 tablename, chainname, comment, rulenum);
312 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
314 return (void *)entry + entry->next_offset;
317 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
319 ipt_do_table(struct sk_buff *skb,
321 const struct net_device *in,
322 const struct net_device *out,
323 struct xt_table *table)
325 #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
327 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
328 const struct iphdr *ip;
329 bool hotdrop = false;
330 /* Initializing verdict to NF_DROP keeps gcc happy. */
331 unsigned int verdict = NF_DROP;
332 const char *indev, *outdev;
333 const void *table_base;
334 struct ipt_entry *e, *back;
335 const struct xt_table_info *private;
336 struct xt_match_param mtpar;
337 struct xt_target_param tgpar;
341 indev = in ? in->name : nulldevname;
342 outdev = out ? out->name : nulldevname;
343 /* We handle fragments by dealing with the first fragment as
344 * if it was a normal packet. All other fragments are treated
345 * normally, except that they will NEVER match rules that ask
346 * things we don't know, ie. tcp syn flag or ports). If the
347 * rule is also a fragment-specific rule, non-fragments won't
349 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
350 mtpar.thoff = ip_hdrlen(skb);
351 mtpar.hotdrop = &hotdrop;
352 mtpar.in = tgpar.in = in;
353 mtpar.out = tgpar.out = out;
354 mtpar.family = tgpar.family = NFPROTO_IPV4;
355 mtpar.hooknum = tgpar.hooknum = hook;
357 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
359 private = table->private;
360 table_base = private->entries[smp_processor_id()];
362 e = get_entry(table_base, private->hook_entry[hook]);
364 /* For return from builtin chain */
365 back = get_entry(table_base, private->underflow[hook]);
368 const struct ipt_entry_target *t;
372 if (!ip_packet_match(ip, indev, outdev,
373 &e->ip, mtpar.fragoff) ||
374 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
375 e = ipt_next_entry(e);
379 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
381 t = ipt_get_target(e);
382 IP_NF_ASSERT(t->u.kernel.target);
384 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
385 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
386 /* The packet is traced: log it */
387 if (unlikely(skb->nf_trace))
388 trace_packet(skb, hook, in, out,
389 table->name, private, e);
391 /* Standard target? */
392 if (!t->u.kernel.target->target) {
395 v = ((struct ipt_standard_target *)t)->verdict;
397 /* Pop from stack? */
398 if (v != IPT_RETURN) {
399 verdict = (unsigned)(-v) - 1;
403 back = get_entry(table_base, back->comefrom);
406 if (table_base + v != ipt_next_entry(e) &&
407 !(e->ip.flags & IPT_F_GOTO)) {
408 /* Save old back ptr in next entry */
409 struct ipt_entry *next = ipt_next_entry(e);
410 next->comefrom = (void *)back - table_base;
411 /* set back pointer to next entry */
415 e = get_entry(table_base, v);
419 /* Targets which reenter must return
421 tgpar.target = t->u.kernel.target;
422 tgpar.targinfo = t->data;
425 #ifdef CONFIG_NETFILTER_DEBUG
426 tb_comefrom = 0xeeeeeeec;
428 verdict = t->u.kernel.target->target(skb, &tgpar);
429 #ifdef CONFIG_NETFILTER_DEBUG
430 if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
431 printk("Target %s reentered!\n",
432 t->u.kernel.target->name);
435 tb_comefrom = 0x57acc001;
437 /* Target might have changed stuff. */
439 if (verdict == IPT_CONTINUE)
440 e = ipt_next_entry(e);
445 xt_info_rdunlock_bh();
447 #ifdef DEBUG_ALLOW_ALL
458 /* Figures out from what hook each rule can be called: returns 0 if
459 there are loops. Puts hook bitmask in comefrom. */
461 mark_source_chains(const struct xt_table_info *newinfo,
462 unsigned int valid_hooks, void *entry0)
466 /* No recursion; use packet counter to save back ptrs (reset
467 to 0 as we leave), and comefrom to save source hook bitmask */
468 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
469 unsigned int pos = newinfo->hook_entry[hook];
470 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
472 if (!(valid_hooks & (1 << hook)))
475 /* Set initial back pointer. */
476 e->counters.pcnt = pos;
479 const struct ipt_standard_target *t
480 = (void *)ipt_get_target_c(e);
481 int visited = e->comefrom & (1 << hook);
483 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
484 printk("iptables: loop hook %u pos %u %08X.\n",
485 hook, pos, e->comefrom);
488 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
490 /* Unconditional return/END. */
491 if ((e->target_offset == sizeof(struct ipt_entry) &&
492 (strcmp(t->target.u.user.name,
493 IPT_STANDARD_TARGET) == 0) &&
494 t->verdict < 0 && unconditional(&e->ip)) ||
496 unsigned int oldpos, size;
498 if ((strcmp(t->target.u.user.name,
499 IPT_STANDARD_TARGET) == 0) &&
500 t->verdict < -NF_MAX_VERDICT - 1) {
501 duprintf("mark_source_chains: bad "
502 "negative verdict (%i)\n",
507 /* Return: backtrack through the last
510 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
511 #ifdef DEBUG_IP_FIREWALL_USER
513 & (1 << NF_INET_NUMHOOKS)) {
514 duprintf("Back unset "
521 pos = e->counters.pcnt;
522 e->counters.pcnt = 0;
524 /* We're at the start. */
528 e = (struct ipt_entry *)
530 } while (oldpos == pos + e->next_offset);
533 size = e->next_offset;
534 e = (struct ipt_entry *)
535 (entry0 + pos + size);
536 e->counters.pcnt = pos;
539 int newpos = t->verdict;
541 if (strcmp(t->target.u.user.name,
542 IPT_STANDARD_TARGET) == 0 &&
544 if (newpos > newinfo->size -
545 sizeof(struct ipt_entry)) {
546 duprintf("mark_source_chains: "
547 "bad verdict (%i)\n",
551 /* This a jump; chase it. */
552 duprintf("Jump rule %u -> %u\n",
555 /* ... this is a fallthru */
556 newpos = pos + e->next_offset;
558 e = (struct ipt_entry *)
560 e->counters.pcnt = pos;
565 duprintf("Finished chain %u\n", hook);
571 cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i)
573 struct xt_mtdtor_param par;
575 if (i && (*i)-- == 0)
579 par.match = m->u.kernel.match;
580 par.matchinfo = m->data;
581 par.family = NFPROTO_IPV4;
582 if (par.match->destroy != NULL)
583 par.match->destroy(&par);
584 module_put(par.match->me);
589 check_entry(const struct ipt_entry *e, const char *name)
591 const struct ipt_entry_target *t;
593 if (!ip_checkentry(&e->ip)) {
594 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
598 if (e->target_offset + sizeof(struct ipt_entry_target) >
602 t = ipt_get_target_c(e);
603 if (e->target_offset + t->u.target_size > e->next_offset)
610 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
613 const struct ipt_ip *ip = par->entryinfo;
616 par->match = m->u.kernel.match;
617 par->matchinfo = m->data;
619 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
620 ip->proto, ip->invflags & IPT_INV_PROTO);
622 duprintf("ip_tables: check failed for `%s'.\n",
631 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
634 struct xt_match *match;
637 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
639 "ipt_%s", m->u.user.name);
640 if (IS_ERR(match) || !match) {
641 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
642 return match ? PTR_ERR(match) : -ENOENT;
644 m->u.kernel.match = match;
646 ret = check_match(m, par, i);
652 module_put(m->u.kernel.match->me);
656 static int check_target(struct ipt_entry *e, struct net *net, const char *name)
658 struct ipt_entry_target *t = ipt_get_target(e);
659 struct xt_tgchk_param par = {
663 .target = t->u.kernel.target,
665 .hook_mask = e->comefrom,
666 .family = NFPROTO_IPV4,
670 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
671 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
673 duprintf("ip_tables: check failed for `%s'.\n",
674 t->u.kernel.target->name);
681 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
682 unsigned int size, unsigned int *i)
684 struct ipt_entry_target *t;
685 struct xt_target *target;
688 struct xt_mtchk_param mtpar;
690 ret = check_entry(e, name);
697 mtpar.entryinfo = &e->ip;
698 mtpar.hook_mask = e->comefrom;
699 mtpar.family = NFPROTO_IPV4;
700 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
702 goto cleanup_matches;
704 t = ipt_get_target(e);
705 target = try_then_request_module(xt_find_target(AF_INET,
708 "ipt_%s", t->u.user.name);
709 if (IS_ERR(target) || !target) {
710 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
711 ret = target ? PTR_ERR(target) : -ENOENT;
712 goto cleanup_matches;
714 t->u.kernel.target = target;
716 ret = check_target(e, net, name);
723 module_put(t->u.kernel.target->me);
725 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
729 static bool check_underflow(const struct ipt_entry *e)
731 const struct ipt_entry_target *t;
732 unsigned int verdict;
734 if (!unconditional(&e->ip))
736 t = ipt_get_target_c(e);
737 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
739 verdict = ((struct ipt_standard_target *)t)->verdict;
740 verdict = -verdict - 1;
741 return verdict == NF_DROP || verdict == NF_ACCEPT;
745 check_entry_size_and_hooks(struct ipt_entry *e,
746 struct xt_table_info *newinfo,
747 const unsigned char *base,
748 const unsigned char *limit,
749 const unsigned int *hook_entries,
750 const unsigned int *underflows,
751 unsigned int valid_hooks,
756 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
757 (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
758 duprintf("Bad offset %p\n", e);
763 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
764 duprintf("checking: element %p size %u\n",
769 /* Check hooks & underflows */
770 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
771 if (!(valid_hooks & (1 << h)))
773 if ((unsigned char *)e - base == hook_entries[h])
774 newinfo->hook_entry[h] = hook_entries[h];
775 if ((unsigned char *)e - base == underflows[h]) {
776 if (!check_underflow(e)) {
777 pr_err("Underflows must be unconditional and "
778 "use the STANDARD target with "
782 newinfo->underflow[h] = underflows[h];
786 /* Clear counters and comefrom */
787 e->counters = ((struct xt_counters) { 0, 0 });
795 cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i)
797 struct xt_tgdtor_param par;
798 struct ipt_entry_target *t;
800 if (i && (*i)-- == 0)
803 /* Cleanup all matches */
804 IPT_MATCH_ITERATE(e, cleanup_match, net, NULL);
805 t = ipt_get_target(e);
808 par.target = t->u.kernel.target;
809 par.targinfo = t->data;
810 par.family = NFPROTO_IPV4;
811 if (par.target->destroy != NULL)
812 par.target->destroy(&par);
813 module_put(par.target->me);
817 /* Checks and translates the user-supplied table segment (held in
820 translate_table(struct net *net,
822 unsigned int valid_hooks,
823 struct xt_table_info *newinfo,
827 const unsigned int *hook_entries,
828 const unsigned int *underflows)
830 struct ipt_entry *iter;
834 newinfo->size = size;
835 newinfo->number = number;
837 /* Init all hooks to impossible value. */
838 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
839 newinfo->hook_entry[i] = 0xFFFFFFFF;
840 newinfo->underflow[i] = 0xFFFFFFFF;
843 duprintf("translate_table: size %u\n", newinfo->size);
845 /* Walk through entries, checking offsets. */
846 xt_entry_foreach(iter, entry0, newinfo->size) {
847 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
848 entry0 + size, hook_entries, underflows,
857 duprintf("translate_table: %u not %u entries\n",
862 /* Check hooks all assigned */
863 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
864 /* Only hooks which are valid */
865 if (!(valid_hooks & (1 << i)))
867 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
868 duprintf("Invalid hook entry %u %u\n",
872 if (newinfo->underflow[i] == 0xFFFFFFFF) {
873 duprintf("Invalid underflow %u %u\n",
879 if (!mark_source_chains(newinfo, valid_hooks, entry0))
882 /* Finally, each sanity check must pass */
884 xt_entry_foreach(iter, entry0, newinfo->size) {
885 ret = find_check_entry(iter, net, name, size, &i);
891 xt_entry_foreach(iter, entry0, newinfo->size)
892 if (cleanup_entry(iter, net, &i) != 0)
897 /* And one copy for every other CPU */
898 for_each_possible_cpu(i) {
899 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
900 memcpy(newinfo->entries[i], entry0, newinfo->size);
908 add_entry_to_counter(const struct ipt_entry *e,
909 struct xt_counters total[],
912 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
919 set_entry_to_counter(const struct ipt_entry *e,
920 struct ipt_counters total[],
923 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
930 get_counters(const struct xt_table_info *t,
931 struct xt_counters counters[])
933 struct ipt_entry *iter;
938 /* Instead of clearing (by a previous call to memset())
939 * the counters and using adds, we set the counters
940 * with data used by 'current' CPU.
942 * Bottom half has to be disabled to prevent deadlock
943 * if new softirq were to run and call ipt_do_table
946 curcpu = smp_processor_id();
949 xt_entry_foreach(iter, t->entries[curcpu], t->size)
950 if (set_entry_to_counter(iter, counters, &i) != 0)
953 for_each_possible_cpu(cpu) {
958 xt_entry_foreach(iter, t->entries[cpu], t->size)
959 if (add_entry_to_counter(iter, counters, &i) != 0)
961 xt_info_wrunlock(cpu);
966 static struct xt_counters *alloc_counters(const struct xt_table *table)
968 unsigned int countersize;
969 struct xt_counters *counters;
970 const struct xt_table_info *private = table->private;
972 /* We need atomic snapshot of counters: rest doesn't change
973 (other than comefrom, which userspace doesn't care
975 countersize = sizeof(struct xt_counters) * private->number;
976 counters = vmalloc_node(countersize, numa_node_id());
978 if (counters == NULL)
979 return ERR_PTR(-ENOMEM);
981 get_counters(private, counters);
987 copy_entries_to_user(unsigned int total_size,
988 const struct xt_table *table,
989 void __user *userptr)
991 unsigned int off, num;
992 const struct ipt_entry *e;
993 struct xt_counters *counters;
994 const struct xt_table_info *private = table->private;
996 const void *loc_cpu_entry;
998 counters = alloc_counters(table);
999 if (IS_ERR(counters))
1000 return PTR_ERR(counters);
1002 /* choose the copy that is on our node/cpu, ...
1003 * This choice is lazy (because current thread is
1004 * allowed to migrate to another cpu)
1006 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1007 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1012 /* FIXME: use iterator macros --RR */
1013 /* ... then go back and fix counters and names */
1014 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
1016 const struct ipt_entry_match *m;
1017 const struct ipt_entry_target *t;
1019 e = (struct ipt_entry *)(loc_cpu_entry + off);
1020 if (copy_to_user(userptr + off
1021 + offsetof(struct ipt_entry, counters),
1023 sizeof(counters[num])) != 0) {
1028 for (i = sizeof(struct ipt_entry);
1029 i < e->target_offset;
1030 i += m->u.match_size) {
1033 if (copy_to_user(userptr + off + i
1034 + offsetof(struct ipt_entry_match,
1036 m->u.kernel.match->name,
1037 strlen(m->u.kernel.match->name)+1)
1044 t = ipt_get_target_c(e);
1045 if (copy_to_user(userptr + off + e->target_offset
1046 + offsetof(struct ipt_entry_target,
1048 t->u.kernel.target->name,
1049 strlen(t->u.kernel.target->name)+1) != 0) {
1060 #ifdef CONFIG_COMPAT
1061 static void compat_standard_from_user(void *dst, const void *src)
1063 int v = *(compat_int_t *)src;
1066 v += xt_compat_calc_jump(AF_INET, v);
1067 memcpy(dst, &v, sizeof(v));
1070 static int compat_standard_to_user(void __user *dst, const void *src)
1072 compat_int_t cv = *(int *)src;
1075 cv -= xt_compat_calc_jump(AF_INET, cv);
1076 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1080 compat_calc_match(const struct ipt_entry_match *m, int *size)
1082 *size += xt_compat_match_offset(m->u.kernel.match);
1086 static int compat_calc_entry(const struct ipt_entry *e,
1087 const struct xt_table_info *info,
1088 const void *base, struct xt_table_info *newinfo)
1090 const struct ipt_entry_target *t;
1091 unsigned int entry_offset;
1094 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1095 entry_offset = (void *)e - base;
1096 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1097 t = ipt_get_target_c(e);
1098 off += xt_compat_target_offset(t->u.kernel.target);
1099 newinfo->size -= off;
1100 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1104 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1105 if (info->hook_entry[i] &&
1106 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1107 newinfo->hook_entry[i] -= off;
1108 if (info->underflow[i] &&
1109 (e < (struct ipt_entry *)(base + info->underflow[i])))
1110 newinfo->underflow[i] -= off;
1115 static int compat_table_info(const struct xt_table_info *info,
1116 struct xt_table_info *newinfo)
1118 struct ipt_entry *iter;
1119 void *loc_cpu_entry;
1122 if (!newinfo || !info)
1125 /* we dont care about newinfo->entries[] */
1126 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1127 newinfo->initial_entries = 0;
1128 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1129 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1130 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1138 static int get_info(struct net *net, void __user *user,
1139 const int *len, int compat)
1141 char name[IPT_TABLE_MAXNAMELEN];
1145 if (*len != sizeof(struct ipt_getinfo)) {
1146 duprintf("length %u != %zu\n", *len,
1147 sizeof(struct ipt_getinfo));
1151 if (copy_from_user(name, user, sizeof(name)) != 0)
1154 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1155 #ifdef CONFIG_COMPAT
1157 xt_compat_lock(AF_INET);
1159 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1160 "iptable_%s", name);
1161 if (t && !IS_ERR(t)) {
1162 struct ipt_getinfo info;
1163 const struct xt_table_info *private = t->private;
1164 #ifdef CONFIG_COMPAT
1165 struct xt_table_info tmp;
1168 ret = compat_table_info(private, &tmp);
1169 xt_compat_flush_offsets(AF_INET);
1173 info.valid_hooks = t->valid_hooks;
1174 memcpy(info.hook_entry, private->hook_entry,
1175 sizeof(info.hook_entry));
1176 memcpy(info.underflow, private->underflow,
1177 sizeof(info.underflow));
1178 info.num_entries = private->number;
1179 info.size = private->size;
1180 strcpy(info.name, name);
1182 if (copy_to_user(user, &info, *len) != 0)
1190 ret = t ? PTR_ERR(t) : -ENOENT;
1191 #ifdef CONFIG_COMPAT
1193 xt_compat_unlock(AF_INET);
1199 get_entries(struct net *net, struct ipt_get_entries __user *uptr,
1203 struct ipt_get_entries get;
1206 if (*len < sizeof(get)) {
1207 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1210 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1212 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1213 duprintf("get_entries: %u != %zu\n",
1214 *len, sizeof(get) + get.size);
1218 t = xt_find_table_lock(net, AF_INET, get.name);
1219 if (t && !IS_ERR(t)) {
1220 const struct xt_table_info *private = t->private;
1221 duprintf("t->private->number = %u\n", private->number);
1222 if (get.size == private->size)
1223 ret = copy_entries_to_user(private->size,
1224 t, uptr->entrytable);
1226 duprintf("get_entries: I've got %u not %u!\n",
1227 private->size, get.size);
1233 ret = t ? PTR_ERR(t) : -ENOENT;
1239 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1240 struct xt_table_info *newinfo, unsigned int num_counters,
1241 void __user *counters_ptr)
1245 struct xt_table_info *oldinfo;
1246 struct xt_counters *counters;
1247 void *loc_cpu_old_entry;
1248 struct ipt_entry *iter;
1251 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1257 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1258 "iptable_%s", name);
1259 if (!t || IS_ERR(t)) {
1260 ret = t ? PTR_ERR(t) : -ENOENT;
1261 goto free_newinfo_counters_untrans;
1265 if (valid_hooks != t->valid_hooks) {
1266 duprintf("Valid hook crap: %08X vs %08X\n",
1267 valid_hooks, t->valid_hooks);
1272 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1276 /* Update module usage count based on number of rules */
1277 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1278 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1279 if ((oldinfo->number > oldinfo->initial_entries) ||
1280 (newinfo->number <= oldinfo->initial_entries))
1282 if ((oldinfo->number > oldinfo->initial_entries) &&
1283 (newinfo->number <= oldinfo->initial_entries))
1286 /* Get the old counters, and synchronize with replace */
1287 get_counters(oldinfo, counters);
1289 /* Decrease module usage counts and free resource */
1290 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1291 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1292 if (cleanup_entry(iter, net, NULL) != 0)
1295 xt_free_table_info(oldinfo);
1296 if (copy_to_user(counters_ptr, counters,
1297 sizeof(struct xt_counters) * num_counters) != 0)
1306 free_newinfo_counters_untrans:
1313 do_replace(struct net *net, const void __user *user, unsigned int len)
1316 struct ipt_replace tmp;
1317 struct xt_table_info *newinfo;
1318 void *loc_cpu_entry;
1319 struct ipt_entry *iter;
1321 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1324 /* overflow check */
1325 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1328 newinfo = xt_alloc_table_info(tmp.size);
1332 /* choose the copy that is on our node/cpu */
1333 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1334 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1340 ret = translate_table(net, tmp.name, tmp.valid_hooks,
1341 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1342 tmp.hook_entry, tmp.underflow);
1346 duprintf("ip_tables: Translated table\n");
1348 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1349 tmp.num_counters, tmp.counters);
1351 goto free_newinfo_untrans;
1354 free_newinfo_untrans:
1355 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1356 if (cleanup_entry(iter, net, NULL) != 0)
1359 xt_free_table_info(newinfo);
1363 /* We're lazy, and add to the first CPU; overflow works its fey magic
1364 * and everything is OK. */
1366 add_counter_to_entry(struct ipt_entry *e,
1367 const struct xt_counters addme[],
1370 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1377 do_add_counters(struct net *net, const void __user *user,
1378 unsigned int len, int compat)
1380 unsigned int i, curcpu;
1381 struct xt_counters_info tmp;
1382 struct xt_counters *paddc;
1383 unsigned int num_counters;
1388 const struct xt_table_info *private;
1390 void *loc_cpu_entry;
1391 struct ipt_entry *iter;
1392 #ifdef CONFIG_COMPAT
1393 struct compat_xt_counters_info compat_tmp;
1397 size = sizeof(struct compat_xt_counters_info);
1402 size = sizeof(struct xt_counters_info);
1405 if (copy_from_user(ptmp, user, size) != 0)
1408 #ifdef CONFIG_COMPAT
1410 num_counters = compat_tmp.num_counters;
1411 name = compat_tmp.name;
1415 num_counters = tmp.num_counters;
1419 if (len != size + num_counters * sizeof(struct xt_counters))
1422 paddc = vmalloc_node(len - size, numa_node_id());
1426 if (copy_from_user(paddc, user + size, len - size) != 0) {
1431 t = xt_find_table_lock(net, AF_INET, name);
1432 if (!t || IS_ERR(t)) {
1433 ret = t ? PTR_ERR(t) : -ENOENT;
1438 private = t->private;
1439 if (private->number != num_counters) {
1441 goto unlock_up_free;
1445 /* Choose the copy that is on our node */
1446 curcpu = smp_processor_id();
1447 loc_cpu_entry = private->entries[curcpu];
1448 xt_info_wrlock(curcpu);
1449 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1450 if (add_counter_to_entry(iter, paddc, &i) != 0)
1452 xt_info_wrunlock(curcpu);
1463 #ifdef CONFIG_COMPAT
1464 struct compat_ipt_replace {
1465 char name[IPT_TABLE_MAXNAMELEN];
1469 u32 hook_entry[NF_INET_NUMHOOKS];
1470 u32 underflow[NF_INET_NUMHOOKS];
1472 compat_uptr_t counters; /* struct ipt_counters * */
1473 struct compat_ipt_entry entries[0];
1477 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1478 unsigned int *size, struct xt_counters *counters,
1481 struct ipt_entry_target *t;
1482 struct compat_ipt_entry __user *ce;
1483 u_int16_t target_offset, next_offset;
1484 compat_uint_t origsize;
1489 ce = (struct compat_ipt_entry __user *)*dstptr;
1490 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1493 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1496 *dstptr += sizeof(struct compat_ipt_entry);
1497 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1499 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1500 target_offset = e->target_offset - (origsize - *size);
1503 t = ipt_get_target(e);
1504 ret = xt_compat_target_to_user(t, dstptr, size);
1508 next_offset = e->next_offset - (origsize - *size);
1509 if (put_user(target_offset, &ce->target_offset))
1511 if (put_user(next_offset, &ce->next_offset))
1521 compat_find_calc_match(struct ipt_entry_match *m,
1523 const struct ipt_ip *ip,
1524 unsigned int hookmask,
1525 int *size, unsigned int *i)
1527 struct xt_match *match;
1529 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1530 m->u.user.revision),
1531 "ipt_%s", m->u.user.name);
1532 if (IS_ERR(match) || !match) {
1533 duprintf("compat_check_calc_match: `%s' not found\n",
1535 return match ? PTR_ERR(match) : -ENOENT;
1537 m->u.kernel.match = match;
1538 *size += xt_compat_match_offset(match);
1545 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1547 if (i && (*i)-- == 0)
1550 module_put(m->u.kernel.match->me);
1555 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1557 struct ipt_entry_target *t;
1559 if (i && (*i)-- == 0)
1562 /* Cleanup all matches */
1563 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1564 t = compat_ipt_get_target(e);
1565 module_put(t->u.kernel.target->me);
1570 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1571 struct xt_table_info *newinfo,
1573 const unsigned char *base,
1574 const unsigned char *limit,
1575 const unsigned int *hook_entries,
1576 const unsigned int *underflows,
1580 struct ipt_entry_target *t;
1581 struct xt_target *target;
1582 unsigned int entry_offset;
1586 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1587 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1588 (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1589 duprintf("Bad offset %p, limit = %p\n", e, limit);
1593 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1594 sizeof(struct compat_xt_entry_target)) {
1595 duprintf("checking: element %p size %u\n",
1600 /* For purposes of check_entry casting the compat entry is fine */
1601 ret = check_entry((struct ipt_entry *)e, name);
1605 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1606 entry_offset = (void *)e - (void *)base;
1608 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1609 &e->ip, e->comefrom, &off, &j);
1611 goto release_matches;
1613 t = compat_ipt_get_target(e);
1614 target = try_then_request_module(xt_find_target(AF_INET,
1616 t->u.user.revision),
1617 "ipt_%s", t->u.user.name);
1618 if (IS_ERR(target) || !target) {
1619 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1621 ret = target ? PTR_ERR(target) : -ENOENT;
1622 goto release_matches;
1624 t->u.kernel.target = target;
1626 off += xt_compat_target_offset(target);
1628 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1632 /* Check hooks & underflows */
1633 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1634 if ((unsigned char *)e - base == hook_entries[h])
1635 newinfo->hook_entry[h] = hook_entries[h];
1636 if ((unsigned char *)e - base == underflows[h])
1637 newinfo->underflow[h] = underflows[h];
1640 /* Clear counters and comefrom */
1641 memset(&e->counters, 0, sizeof(e->counters));
1648 module_put(t->u.kernel.target->me);
1650 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1655 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1656 unsigned int *size, const char *name,
1657 struct xt_table_info *newinfo, unsigned char *base)
1659 struct ipt_entry_target *t;
1660 struct xt_target *target;
1661 struct ipt_entry *de;
1662 unsigned int origsize;
1667 de = (struct ipt_entry *)*dstptr;
1668 memcpy(de, e, sizeof(struct ipt_entry));
1669 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1671 *dstptr += sizeof(struct ipt_entry);
1672 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1674 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1678 de->target_offset = e->target_offset - (origsize - *size);
1679 t = compat_ipt_get_target(e);
1680 target = t->u.kernel.target;
1681 xt_compat_target_from_user(t, dstptr, size);
1683 de->next_offset = e->next_offset - (origsize - *size);
1684 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1685 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1686 newinfo->hook_entry[h] -= origsize - *size;
1687 if ((unsigned char *)de - base < newinfo->underflow[h])
1688 newinfo->underflow[h] -= origsize - *size;
1694 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,
1697 struct xt_mtchk_param mtpar;
1704 mtpar.entryinfo = &e->ip;
1705 mtpar.hook_mask = e->comefrom;
1706 mtpar.family = NFPROTO_IPV4;
1707 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1709 goto cleanup_matches;
1711 ret = check_target(e, net, name);
1713 goto cleanup_matches;
1719 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
1724 translate_compat_table(struct net *net,
1726 unsigned int valid_hooks,
1727 struct xt_table_info **pinfo,
1729 unsigned int total_size,
1730 unsigned int number,
1731 unsigned int *hook_entries,
1732 unsigned int *underflows)
1735 struct xt_table_info *newinfo, *info;
1736 void *pos, *entry0, *entry1;
1737 struct compat_ipt_entry *iter0;
1738 struct ipt_entry *iter1;
1745 info->number = number;
1747 /* Init all hooks to impossible value. */
1748 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1749 info->hook_entry[i] = 0xFFFFFFFF;
1750 info->underflow[i] = 0xFFFFFFFF;
1753 duprintf("translate_compat_table: size %u\n", info->size);
1755 xt_compat_lock(AF_INET);
1756 /* Walk through entries, checking offsets. */
1757 xt_entry_foreach(iter0, entry0, total_size) {
1758 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1759 entry0, entry0 + total_size, hook_entries, underflows,
1769 duprintf("translate_compat_table: %u not %u entries\n",
1774 /* Check hooks all assigned */
1775 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1776 /* Only hooks which are valid */
1777 if (!(valid_hooks & (1 << i)))
1779 if (info->hook_entry[i] == 0xFFFFFFFF) {
1780 duprintf("Invalid hook entry %u %u\n",
1781 i, hook_entries[i]);
1784 if (info->underflow[i] == 0xFFFFFFFF) {
1785 duprintf("Invalid underflow %u %u\n",
1792 newinfo = xt_alloc_table_info(size);
1796 newinfo->number = number;
1797 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1798 newinfo->hook_entry[i] = info->hook_entry[i];
1799 newinfo->underflow[i] = info->underflow[i];
1801 entry1 = newinfo->entries[raw_smp_processor_id()];
1804 xt_entry_foreach(iter0, entry0, total_size) {
1805 ret = compat_copy_entry_from_user(iter0, &pos,
1806 &size, name, newinfo, entry1);
1810 xt_compat_flush_offsets(AF_INET);
1811 xt_compat_unlock(AF_INET);
1816 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1820 xt_entry_foreach(iter1, entry1, newinfo->size) {
1821 ret = compat_check_entry(iter1, net, name, &i);
1827 * The first i matches need cleanup_entry (calls ->destroy)
1828 * because they had called ->check already. The other j-i
1829 * entries need only release.
1833 xt_entry_foreach(iter0, entry0, newinfo->size) {
1836 if (compat_release_entry(iter0, &i) != 0)
1839 xt_entry_foreach(iter1, entry1, newinfo->size)
1840 if (cleanup_entry(iter1, net, &i) != 0)
1842 xt_free_table_info(newinfo);
1846 /* And one copy for every other CPU */
1847 for_each_possible_cpu(i)
1848 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1849 memcpy(newinfo->entries[i], entry1, newinfo->size);
1853 xt_free_table_info(info);
1857 xt_free_table_info(newinfo);
1859 xt_entry_foreach(iter0, entry0, total_size)
1860 if (compat_release_entry(iter0, &j) != 0)
1864 xt_compat_flush_offsets(AF_INET);
1865 xt_compat_unlock(AF_INET);
1870 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1873 struct compat_ipt_replace tmp;
1874 struct xt_table_info *newinfo;
1875 void *loc_cpu_entry;
1876 struct ipt_entry *iter;
1878 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1881 /* overflow check */
1882 if (tmp.size >= INT_MAX / num_possible_cpus())
1884 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1887 newinfo = xt_alloc_table_info(tmp.size);
1891 /* choose the copy that is on our node/cpu */
1892 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1893 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1899 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1900 &newinfo, &loc_cpu_entry, tmp.size,
1901 tmp.num_entries, tmp.hook_entry,
1906 duprintf("compat_do_replace: Translated table\n");
1908 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1909 tmp.num_counters, compat_ptr(tmp.counters));
1911 goto free_newinfo_untrans;
1914 free_newinfo_untrans:
1915 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1916 if (cleanup_entry(iter, net, NULL) != 0)
1919 xt_free_table_info(newinfo);
1924 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1929 if (!capable(CAP_NET_ADMIN))
1933 case IPT_SO_SET_REPLACE:
1934 ret = compat_do_replace(sock_net(sk), user, len);
1937 case IPT_SO_SET_ADD_COUNTERS:
1938 ret = do_add_counters(sock_net(sk), user, len, 1);
1942 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1949 struct compat_ipt_get_entries {
1950 char name[IPT_TABLE_MAXNAMELEN];
1952 struct compat_ipt_entry entrytable[0];
1956 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1957 void __user *userptr)
1959 struct xt_counters *counters;
1960 const struct xt_table_info *private = table->private;
1964 const void *loc_cpu_entry;
1966 struct ipt_entry *iter;
1968 counters = alloc_counters(table);
1969 if (IS_ERR(counters))
1970 return PTR_ERR(counters);
1972 /* choose the copy that is on our node/cpu, ...
1973 * This choice is lazy (because current thread is
1974 * allowed to migrate to another cpu)
1976 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1979 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1980 ret = compat_copy_entry_to_user(iter, &pos,
1981 &size, counters, &i);
1991 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1995 struct compat_ipt_get_entries get;
1998 if (*len < sizeof(get)) {
1999 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
2003 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
2006 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
2007 duprintf("compat_get_entries: %u != %zu\n",
2008 *len, sizeof(get) + get.size);
2012 xt_compat_lock(AF_INET);
2013 t = xt_find_table_lock(net, AF_INET, get.name);
2014 if (t && !IS_ERR(t)) {
2015 const struct xt_table_info *private = t->private;
2016 struct xt_table_info info;
2017 duprintf("t->private->number = %u\n", private->number);
2018 ret = compat_table_info(private, &info);
2019 if (!ret && get.size == info.size) {
2020 ret = compat_copy_entries_to_user(private->size,
2021 t, uptr->entrytable);
2023 duprintf("compat_get_entries: I've got %u not %u!\n",
2024 private->size, get.size);
2027 xt_compat_flush_offsets(AF_INET);
2031 ret = t ? PTR_ERR(t) : -ENOENT;
2033 xt_compat_unlock(AF_INET);
2037 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
2040 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2044 if (!capable(CAP_NET_ADMIN))
2048 case IPT_SO_GET_INFO:
2049 ret = get_info(sock_net(sk), user, len, 1);
2051 case IPT_SO_GET_ENTRIES:
2052 ret = compat_get_entries(sock_net(sk), user, len);
2055 ret = do_ipt_get_ctl(sk, cmd, user, len);
2062 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2066 if (!capable(CAP_NET_ADMIN))
2070 case IPT_SO_SET_REPLACE:
2071 ret = do_replace(sock_net(sk), user, len);
2074 case IPT_SO_SET_ADD_COUNTERS:
2075 ret = do_add_counters(sock_net(sk), user, len, 0);
2079 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2087 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2091 if (!capable(CAP_NET_ADMIN))
2095 case IPT_SO_GET_INFO:
2096 ret = get_info(sock_net(sk), user, len, 0);
2099 case IPT_SO_GET_ENTRIES:
2100 ret = get_entries(sock_net(sk), user, len);
2103 case IPT_SO_GET_REVISION_MATCH:
2104 case IPT_SO_GET_REVISION_TARGET: {
2105 struct ipt_get_revision rev;
2108 if (*len != sizeof(rev)) {
2112 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2117 if (cmd == IPT_SO_GET_REVISION_TARGET)
2122 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2125 "ipt_%s", rev.name);
2130 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2137 struct xt_table *ipt_register_table(struct net *net,
2138 const struct xt_table *table,
2139 const struct ipt_replace *repl)
2142 struct xt_table_info *newinfo;
2143 struct xt_table_info bootstrap
2144 = { 0, 0, 0, { 0 }, { 0 }, { } };
2145 void *loc_cpu_entry;
2146 struct xt_table *new_table;
2148 newinfo = xt_alloc_table_info(repl->size);
2154 /* choose the copy on our node/cpu, but dont care about preemption */
2155 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2156 memcpy(loc_cpu_entry, repl->entries, repl->size);
2158 ret = translate_table(net, table->name, table->valid_hooks,
2159 newinfo, loc_cpu_entry, repl->size,
2166 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2167 if (IS_ERR(new_table)) {
2168 ret = PTR_ERR(new_table);
2175 xt_free_table_info(newinfo);
2177 return ERR_PTR(ret);
2180 void ipt_unregister_table(struct net *net, struct xt_table *table)
2182 struct xt_table_info *private;
2183 void *loc_cpu_entry;
2184 struct module *table_owner = table->me;
2185 struct ipt_entry *iter;
2187 private = xt_unregister_table(table);
2189 /* Decrease module usage counts and free resources */
2190 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2191 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2192 if (cleanup_entry(iter, net, NULL) != 0)
2194 if (private->number > private->initial_entries)
2195 module_put(table_owner);
2196 xt_free_table_info(private);
2199 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2201 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2202 u_int8_t type, u_int8_t code,
2205 return ((test_type == 0xFF) ||
2206 (type == test_type && code >= min_code && code <= max_code))
2211 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2213 const struct icmphdr *ic;
2214 struct icmphdr _icmph;
2215 const struct ipt_icmp *icmpinfo = par->matchinfo;
2217 /* Must not be a fragment. */
2218 if (par->fragoff != 0)
2221 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2223 /* We've been asked to examine this packet, and we
2224 * can't. Hence, no choice but to drop.
2226 duprintf("Dropping evil ICMP tinygram.\n");
2227 *par->hotdrop = true;
2231 return icmp_type_code_match(icmpinfo->type,
2235 !!(icmpinfo->invflags&IPT_ICMP_INV));
2238 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2240 const struct ipt_icmp *icmpinfo = par->matchinfo;
2242 /* Must specify no unknown invflags */
2243 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2246 /* The built-in targets: standard (NULL) and error. */
2247 static struct xt_target ipt_standard_target __read_mostly = {
2248 .name = IPT_STANDARD_TARGET,
2249 .targetsize = sizeof(int),
2250 .family = NFPROTO_IPV4,
2251 #ifdef CONFIG_COMPAT
2252 .compatsize = sizeof(compat_int_t),
2253 .compat_from_user = compat_standard_from_user,
2254 .compat_to_user = compat_standard_to_user,
2258 static struct xt_target ipt_error_target __read_mostly = {
2259 .name = IPT_ERROR_TARGET,
2260 .target = ipt_error,
2261 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2262 .family = NFPROTO_IPV4,
2265 static struct nf_sockopt_ops ipt_sockopts = {
2267 .set_optmin = IPT_BASE_CTL,
2268 .set_optmax = IPT_SO_SET_MAX+1,
2269 .set = do_ipt_set_ctl,
2270 #ifdef CONFIG_COMPAT
2271 .compat_set = compat_do_ipt_set_ctl,
2273 .get_optmin = IPT_BASE_CTL,
2274 .get_optmax = IPT_SO_GET_MAX+1,
2275 .get = do_ipt_get_ctl,
2276 #ifdef CONFIG_COMPAT
2277 .compat_get = compat_do_ipt_get_ctl,
2279 .owner = THIS_MODULE,
2282 static struct xt_match icmp_matchstruct __read_mostly = {
2284 .match = icmp_match,
2285 .matchsize = sizeof(struct ipt_icmp),
2286 .checkentry = icmp_checkentry,
2287 .proto = IPPROTO_ICMP,
2288 .family = NFPROTO_IPV4,
2291 static int __net_init ip_tables_net_init(struct net *net)
2293 return xt_proto_init(net, NFPROTO_IPV4);
2296 static void __net_exit ip_tables_net_exit(struct net *net)
2298 xt_proto_fini(net, NFPROTO_IPV4);
2301 static struct pernet_operations ip_tables_net_ops = {
2302 .init = ip_tables_net_init,
2303 .exit = ip_tables_net_exit,
2306 static int __init ip_tables_init(void)
2310 ret = register_pernet_subsys(&ip_tables_net_ops);
2314 /* Noone else will be downing sem now, so we won't sleep */
2315 ret = xt_register_target(&ipt_standard_target);
2318 ret = xt_register_target(&ipt_error_target);
2321 ret = xt_register_match(&icmp_matchstruct);
2325 /* Register setsockopt */
2326 ret = nf_register_sockopt(&ipt_sockopts);
2330 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2334 xt_unregister_match(&icmp_matchstruct);
2336 xt_unregister_target(&ipt_error_target);
2338 xt_unregister_target(&ipt_standard_target);
2340 unregister_pernet_subsys(&ip_tables_net_ops);
2345 static void __exit ip_tables_fini(void)
2347 nf_unregister_sockopt(&ipt_sockopts);
2349 xt_unregister_match(&icmp_matchstruct);
2350 xt_unregister_target(&ipt_error_target);
2351 xt_unregister_target(&ipt_standard_target);
2353 unregister_pernet_subsys(&ip_tables_net_ops);
2356 EXPORT_SYMBOL(ipt_register_table);
2357 EXPORT_SYMBOL(ipt_unregister_table);
2358 EXPORT_SYMBOL(ipt_do_table);
2359 module_init(ip_tables_init);
2360 module_exit(ip_tables_fini);