2 * Packet matching code.
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #include <linux/cache.h>
12 #include <linux/capability.h>
13 #include <linux/skbuff.h>
14 #include <linux/kmod.h>
15 #include <linux/vmalloc.h>
16 #include <linux/netdevice.h>
17 #include <linux/module.h>
18 #include <linux/icmp.h>
20 #include <net/compat.h>
21 #include <asm/uaccess.h>
22 #include <linux/mutex.h>
23 #include <linux/proc_fs.h>
24 #include <linux/err.h>
25 #include <linux/cpumask.h>
27 #include <linux/netfilter/x_tables.h>
28 #include <linux/netfilter_ipv4/ip_tables.h>
29 #include <net/netfilter/nf_log.h>
31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
33 MODULE_DESCRIPTION("IPv4 packet filter");
35 /*#define DEBUG_IP_FIREWALL*/
36 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
37 /*#define DEBUG_IP_FIREWALL_USER*/
39 #ifdef DEBUG_IP_FIREWALL
40 #define dprintf(format, args...) printk(format , ## args)
42 #define dprintf(format, args...)
45 #ifdef DEBUG_IP_FIREWALL_USER
46 #define duprintf(format, args...) printk(format , ## args)
48 #define duprintf(format, args...)
51 #ifdef CONFIG_NETFILTER_DEBUG
52 #define IP_NF_ASSERT(x) \
55 printk("IP_NF_ASSERT: %s:%s:%u\n", \
56 __func__, __FILE__, __LINE__); \
59 #define IP_NF_ASSERT(x)
63 /* All the better to debug you with... */
69 We keep a set of rules for each CPU, so we can avoid write-locking
70 them in the softirq when updating the counters and therefore
71 only need to read-lock in the softirq; doing a write_lock_bh() in user
72 context stops packets coming through and allows user context to read
73 the counters or update the rules.
75 Hence the start of any table is given by get_table() below. */
77 /* Returns whether matches rule or not. */
78 /* Performance critical - called for every packet */
80 ip_packet_match(const struct iphdr *ip,
83 const struct ipt_ip *ipinfo,
88 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
90 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
92 || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
94 dprintf("Source or dest mismatch.\n");
96 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
97 &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
98 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
99 dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
100 &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
101 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
105 ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
107 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
108 dprintf("VIA in mismatch (%s vs %s).%s\n",
109 indev, ipinfo->iniface,
110 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
114 ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
116 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
117 dprintf("VIA out mismatch (%s vs %s).%s\n",
118 outdev, ipinfo->outiface,
119 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
123 /* Check specific protocol */
125 && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
126 dprintf("Packet protocol %hi does not match %hi.%s\n",
127 ip->protocol, ipinfo->proto,
128 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
132 /* If we have a fragment rule but the packet is not a fragment
133 * then we return zero */
134 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
135 dprintf("Fragment rule but not fragment.%s\n",
136 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
144 ip_checkentry(const struct ipt_ip *ip)
146 if (ip->flags & ~IPT_F_MASK) {
147 duprintf("Unknown flag bits set: %08X\n",
148 ip->flags & ~IPT_F_MASK);
151 if (ip->invflags & ~IPT_INV_MASK) {
152 duprintf("Unknown invflag bits set: %08X\n",
153 ip->invflags & ~IPT_INV_MASK);
160 ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
163 printk("ip_tables: error: `%s'\n",
164 (const char *)par->targinfo);
169 /* Performance critical - called for every packet */
171 do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
172 struct xt_match_param *par)
174 par->match = m->u.kernel.match;
175 par->matchinfo = m->data;
177 /* Stop iteration if it doesn't match */
178 if (!m->u.kernel.match->match(skb, par))
184 /* Performance critical */
185 static inline struct ipt_entry *
186 get_entry(void *base, unsigned int offset)
188 return (struct ipt_entry *)(base + offset);
191 /* All zeroes == unconditional rule. */
192 /* Mildly perf critical (only if packet tracing is on) */
194 unconditional(const struct ipt_ip *ip)
198 for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
199 if (((__u32 *)ip)[i])
206 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
207 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
208 static const char *const hooknames[] = {
209 [NF_INET_PRE_ROUTING] = "PREROUTING",
210 [NF_INET_LOCAL_IN] = "INPUT",
211 [NF_INET_FORWARD] = "FORWARD",
212 [NF_INET_LOCAL_OUT] = "OUTPUT",
213 [NF_INET_POST_ROUTING] = "POSTROUTING",
216 enum nf_ip_trace_comments {
217 NF_IP_TRACE_COMMENT_RULE,
218 NF_IP_TRACE_COMMENT_RETURN,
219 NF_IP_TRACE_COMMENT_POLICY,
222 static const char *const comments[] = {
223 [NF_IP_TRACE_COMMENT_RULE] = "rule",
224 [NF_IP_TRACE_COMMENT_RETURN] = "return",
225 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
228 static struct nf_loginfo trace_loginfo = {
229 .type = NF_LOG_TYPE_LOG,
233 .logflags = NF_LOG_MASK,
238 /* Mildly perf critical (only if packet tracing is on) */
240 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
241 const char *hookname, const char **chainname,
242 const char **comment, unsigned int *rulenum)
244 struct ipt_standard_target *t = (void *)ipt_get_target(s);
246 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
247 /* Head of user chain: ERROR target with chainname */
248 *chainname = t->target.data;
253 if (s->target_offset == sizeof(struct ipt_entry)
254 && strcmp(t->target.u.kernel.target->name,
255 IPT_STANDARD_TARGET) == 0
257 && unconditional(&s->ip)) {
258 /* Tail of chains: STANDARD target (return/policy) */
259 *comment = *chainname == hookname
260 ? comments[NF_IP_TRACE_COMMENT_POLICY]
261 : comments[NF_IP_TRACE_COMMENT_RETURN];
270 static void trace_packet(struct sk_buff *skb,
272 const struct net_device *in,
273 const struct net_device *out,
274 const char *tablename,
275 struct xt_table_info *private,
279 const struct ipt_entry *root;
280 const char *hookname, *chainname, *comment;
281 unsigned int rulenum = 0;
283 table_base = private->entries[smp_processor_id()];
284 root = get_entry(table_base, private->hook_entry[hook]);
286 hookname = chainname = hooknames[hook];
287 comment = comments[NF_IP_TRACE_COMMENT_RULE];
289 IPT_ENTRY_ITERATE(root,
290 private->size - private->hook_entry[hook],
291 get_chainname_rulenum,
292 e, hookname, &chainname, &comment, &rulenum);
294 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
295 "TRACE: %s:%s:%s:%u ",
296 tablename, chainname, comment, rulenum);
301 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
303 return (void *)entry + entry->next_offset;
306 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
308 ipt_do_table(struct sk_buff *skb,
310 const struct net_device *in,
311 const struct net_device *out,
312 struct xt_table *table)
314 #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
316 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
317 const struct iphdr *ip;
319 bool hotdrop = false;
320 /* Initializing verdict to NF_DROP keeps gcc happy. */
321 unsigned int verdict = NF_DROP;
322 const char *indev, *outdev;
324 struct ipt_entry *e, *back;
325 struct xt_table_info *private;
326 struct xt_match_param mtpar;
327 struct xt_target_param tgpar;
331 datalen = skb->len - ip->ihl * 4;
332 indev = in ? in->name : nulldevname;
333 outdev = out ? out->name : nulldevname;
334 /* We handle fragments by dealing with the first fragment as
335 * if it was a normal packet. All other fragments are treated
336 * normally, except that they will NEVER match rules that ask
337 * things we don't know, ie. tcp syn flag or ports). If the
338 * rule is also a fragment-specific rule, non-fragments won't
340 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
341 mtpar.thoff = ip_hdrlen(skb);
342 mtpar.hotdrop = &hotdrop;
343 mtpar.in = tgpar.in = in;
344 mtpar.out = tgpar.out = out;
345 mtpar.family = tgpar.family = NFPROTO_IPV4;
346 mtpar.hooknum = tgpar.hooknum = hook;
348 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
350 private = table->private;
351 table_base = private->entries[smp_processor_id()];
353 e = get_entry(table_base, private->hook_entry[hook]);
355 /* For return from builtin chain */
356 back = get_entry(table_base, private->underflow[hook]);
359 struct ipt_entry_target *t;
363 if (!ip_packet_match(ip, indev, outdev,
364 &e->ip, mtpar.fragoff) ||
365 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
366 e = ipt_next_entry(e);
370 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
372 t = ipt_get_target(e);
373 IP_NF_ASSERT(t->u.kernel.target);
375 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
376 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
377 /* The packet is traced: log it */
378 if (unlikely(skb->nf_trace))
379 trace_packet(skb, hook, in, out,
380 table->name, private, e);
382 /* Standard target? */
383 if (!t->u.kernel.target->target) {
386 v = ((struct ipt_standard_target *)t)->verdict;
388 /* Pop from stack? */
389 if (v != IPT_RETURN) {
390 verdict = (unsigned)(-v) - 1;
394 back = get_entry(table_base, back->comefrom);
397 if (table_base + v != ipt_next_entry(e)
398 && !(e->ip.flags & IPT_F_GOTO)) {
399 /* Save old back ptr in next entry */
400 struct ipt_entry *next = ipt_next_entry(e);
401 next->comefrom = (void *)back - table_base;
402 /* set back pointer to next entry */
406 e = get_entry(table_base, v);
410 /* Targets which reenter must return
412 tgpar.target = t->u.kernel.target;
413 tgpar.targinfo = t->data;
416 #ifdef CONFIG_NETFILTER_DEBUG
417 tb_comefrom = 0xeeeeeeec;
419 verdict = t->u.kernel.target->target(skb, &tgpar);
420 #ifdef CONFIG_NETFILTER_DEBUG
421 if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
422 printk("Target %s reentered!\n",
423 t->u.kernel.target->name);
426 tb_comefrom = 0x57acc001;
428 /* Target might have changed stuff. */
430 datalen = skb->len - ip->ihl * 4;
432 if (verdict == IPT_CONTINUE)
433 e = ipt_next_entry(e);
438 xt_info_rdunlock_bh();
440 #ifdef DEBUG_ALLOW_ALL
451 /* Figures out from what hook each rule can be called: returns 0 if
452 there are loops. Puts hook bitmask in comefrom. */
454 mark_source_chains(struct xt_table_info *newinfo,
455 unsigned int valid_hooks, void *entry0)
459 /* No recursion; use packet counter to save back ptrs (reset
460 to 0 as we leave), and comefrom to save source hook bitmask */
461 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
462 unsigned int pos = newinfo->hook_entry[hook];
463 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
465 if (!(valid_hooks & (1 << hook)))
468 /* Set initial back pointer. */
469 e->counters.pcnt = pos;
472 struct ipt_standard_target *t
473 = (void *)ipt_get_target(e);
474 int visited = e->comefrom & (1 << hook);
476 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
477 printk("iptables: loop hook %u pos %u %08X.\n",
478 hook, pos, e->comefrom);
481 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
483 /* Unconditional return/END. */
484 if ((e->target_offset == sizeof(struct ipt_entry)
485 && (strcmp(t->target.u.user.name,
486 IPT_STANDARD_TARGET) == 0)
488 && unconditional(&e->ip)) || visited) {
489 unsigned int oldpos, size;
491 if ((strcmp(t->target.u.user.name,
492 IPT_STANDARD_TARGET) == 0) &&
493 t->verdict < -NF_MAX_VERDICT - 1) {
494 duprintf("mark_source_chains: bad "
495 "negative verdict (%i)\n",
500 /* Return: backtrack through the last
503 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
504 #ifdef DEBUG_IP_FIREWALL_USER
506 & (1 << NF_INET_NUMHOOKS)) {
507 duprintf("Back unset "
514 pos = e->counters.pcnt;
515 e->counters.pcnt = 0;
517 /* We're at the start. */
521 e = (struct ipt_entry *)
523 } while (oldpos == pos + e->next_offset);
526 size = e->next_offset;
527 e = (struct ipt_entry *)
528 (entry0 + pos + size);
529 e->counters.pcnt = pos;
532 int newpos = t->verdict;
534 if (strcmp(t->target.u.user.name,
535 IPT_STANDARD_TARGET) == 0
537 if (newpos > newinfo->size -
538 sizeof(struct ipt_entry)) {
539 duprintf("mark_source_chains: "
540 "bad verdict (%i)\n",
544 /* This a jump; chase it. */
545 duprintf("Jump rule %u -> %u\n",
548 /* ... this is a fallthru */
549 newpos = pos + e->next_offset;
551 e = (struct ipt_entry *)
553 e->counters.pcnt = pos;
558 duprintf("Finished chain %u\n", hook);
564 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
566 struct xt_mtdtor_param par;
568 if (i && (*i)-- == 0)
571 par.match = m->u.kernel.match;
572 par.matchinfo = m->data;
573 par.family = NFPROTO_IPV4;
574 if (par.match->destroy != NULL)
575 par.match->destroy(&par);
576 module_put(par.match->me);
581 check_entry(struct ipt_entry *e, const char *name)
583 struct ipt_entry_target *t;
585 if (!ip_checkentry(&e->ip)) {
586 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
590 if (e->target_offset + sizeof(struct ipt_entry_target) >
594 t = ipt_get_target(e);
595 if (e->target_offset + t->u.target_size > e->next_offset)
602 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
605 const struct ipt_ip *ip = par->entryinfo;
608 par->match = m->u.kernel.match;
609 par->matchinfo = m->data;
611 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
612 ip->proto, ip->invflags & IPT_INV_PROTO);
614 duprintf("ip_tables: check failed for `%s'.\n",
623 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
626 struct xt_match *match;
629 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
631 "ipt_%s", m->u.user.name);
632 if (IS_ERR(match) || !match) {
633 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
634 return match ? PTR_ERR(match) : -ENOENT;
636 m->u.kernel.match = match;
638 ret = check_match(m, par, i);
644 module_put(m->u.kernel.match->me);
648 static int check_target(struct ipt_entry *e, const char *name)
650 struct ipt_entry_target *t = ipt_get_target(e);
651 struct xt_tgchk_param par = {
654 .target = t->u.kernel.target,
656 .hook_mask = e->comefrom,
657 .family = NFPROTO_IPV4,
661 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
662 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
664 duprintf("ip_tables: check failed for `%s'.\n",
665 t->u.kernel.target->name);
672 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
675 struct ipt_entry_target *t;
676 struct xt_target *target;
679 struct xt_mtchk_param mtpar;
681 ret = check_entry(e, name);
687 mtpar.entryinfo = &e->ip;
688 mtpar.hook_mask = e->comefrom;
689 mtpar.family = NFPROTO_IPV4;
690 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
692 goto cleanup_matches;
694 t = ipt_get_target(e);
695 target = try_then_request_module(xt_find_target(AF_INET,
698 "ipt_%s", t->u.user.name);
699 if (IS_ERR(target) || !target) {
700 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
701 ret = target ? PTR_ERR(target) : -ENOENT;
702 goto cleanup_matches;
704 t->u.kernel.target = target;
706 ret = check_target(e, name);
713 module_put(t->u.kernel.target->me);
715 IPT_MATCH_ITERATE(e, cleanup_match, &j);
720 check_entry_size_and_hooks(struct ipt_entry *e,
721 struct xt_table_info *newinfo,
723 unsigned char *limit,
724 const unsigned int *hook_entries,
725 const unsigned int *underflows,
730 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
731 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
732 duprintf("Bad offset %p\n", e);
737 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
738 duprintf("checking: element %p size %u\n",
743 /* Check hooks & underflows */
744 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
745 if ((unsigned char *)e - base == hook_entries[h])
746 newinfo->hook_entry[h] = hook_entries[h];
747 if ((unsigned char *)e - base == underflows[h])
748 newinfo->underflow[h] = underflows[h];
751 /* FIXME: underflows must be unconditional, standard verdicts
752 < 0 (not IPT_RETURN). --RR */
754 /* Clear counters and comefrom */
755 e->counters = ((struct xt_counters) { 0, 0 });
763 cleanup_entry(struct ipt_entry *e, unsigned int *i)
765 struct xt_tgdtor_param par;
766 struct ipt_entry_target *t;
768 if (i && (*i)-- == 0)
771 /* Cleanup all matches */
772 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
773 t = ipt_get_target(e);
775 par.target = t->u.kernel.target;
776 par.targinfo = t->data;
777 par.family = NFPROTO_IPV4;
778 if (par.target->destroy != NULL)
779 par.target->destroy(&par);
780 module_put(par.target->me);
784 /* Checks and translates the user-supplied table segment (held in
787 translate_table(const char *name,
788 unsigned int valid_hooks,
789 struct xt_table_info *newinfo,
793 const unsigned int *hook_entries,
794 const unsigned int *underflows)
799 newinfo->size = size;
800 newinfo->number = number;
802 /* Init all hooks to impossible value. */
803 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
804 newinfo->hook_entry[i] = 0xFFFFFFFF;
805 newinfo->underflow[i] = 0xFFFFFFFF;
808 duprintf("translate_table: size %u\n", newinfo->size);
810 /* Walk through entries, checking offsets. */
811 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
812 check_entry_size_and_hooks,
816 hook_entries, underflows, &i);
821 duprintf("translate_table: %u not %u entries\n",
826 /* Check hooks all assigned */
827 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
828 /* Only hooks which are valid */
829 if (!(valid_hooks & (1 << i)))
831 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
832 duprintf("Invalid hook entry %u %u\n",
836 if (newinfo->underflow[i] == 0xFFFFFFFF) {
837 duprintf("Invalid underflow %u %u\n",
843 if (!mark_source_chains(newinfo, valid_hooks, entry0))
846 /* Finally, each sanity check must pass */
848 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
849 find_check_entry, name, size, &i);
852 IPT_ENTRY_ITERATE(entry0, newinfo->size,
857 /* And one copy for every other CPU */
858 for_each_possible_cpu(i) {
859 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
860 memcpy(newinfo->entries[i], entry0, newinfo->size);
868 add_entry_to_counter(const struct ipt_entry *e,
869 struct xt_counters total[],
872 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
879 set_entry_to_counter(const struct ipt_entry *e,
880 struct ipt_counters total[],
883 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
890 get_counters(const struct xt_table_info *t,
891 struct xt_counters counters[])
897 /* Instead of clearing (by a previous call to memset())
898 * the counters and using adds, we set the counters
899 * with data used by 'current' CPU.
901 * Bottom half has to be disabled to prevent deadlock
902 * if new softirq were to run and call ipt_do_table
905 curcpu = smp_processor_id();
908 IPT_ENTRY_ITERATE(t->entries[curcpu],
910 set_entry_to_counter,
914 for_each_possible_cpu(cpu) {
919 IPT_ENTRY_ITERATE(t->entries[cpu],
921 add_entry_to_counter,
924 xt_info_wrunlock(cpu);
929 static struct xt_counters * alloc_counters(struct xt_table *table)
931 unsigned int countersize;
932 struct xt_counters *counters;
933 struct xt_table_info *private = table->private;
935 /* We need atomic snapshot of counters: rest doesn't change
936 (other than comefrom, which userspace doesn't care
938 countersize = sizeof(struct xt_counters) * private->number;
939 counters = vmalloc_node(countersize, numa_node_id());
941 if (counters == NULL)
942 return ERR_PTR(-ENOMEM);
944 get_counters(private, counters);
950 copy_entries_to_user(unsigned int total_size,
951 struct xt_table *table,
952 void __user *userptr)
954 unsigned int off, num;
956 struct xt_counters *counters;
957 const struct xt_table_info *private = table->private;
959 const void *loc_cpu_entry;
961 counters = alloc_counters(table);
962 if (IS_ERR(counters))
963 return PTR_ERR(counters);
965 /* choose the copy that is on our node/cpu, ...
966 * This choice is lazy (because current thread is
967 * allowed to migrate to another cpu)
969 loc_cpu_entry = private->entries[raw_smp_processor_id()];
970 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
975 /* FIXME: use iterator macros --RR */
976 /* ... then go back and fix counters and names */
977 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
979 const struct ipt_entry_match *m;
980 const struct ipt_entry_target *t;
982 e = (struct ipt_entry *)(loc_cpu_entry + off);
983 if (copy_to_user(userptr + off
984 + offsetof(struct ipt_entry, counters),
986 sizeof(counters[num])) != 0) {
991 for (i = sizeof(struct ipt_entry);
992 i < e->target_offset;
993 i += m->u.match_size) {
996 if (copy_to_user(userptr + off + i
997 + offsetof(struct ipt_entry_match,
999 m->u.kernel.match->name,
1000 strlen(m->u.kernel.match->name)+1)
1007 t = ipt_get_target(e);
1008 if (copy_to_user(userptr + off + e->target_offset
1009 + offsetof(struct ipt_entry_target,
1011 t->u.kernel.target->name,
1012 strlen(t->u.kernel.target->name)+1) != 0) {
1023 #ifdef CONFIG_COMPAT
1024 static void compat_standard_from_user(void *dst, void *src)
1026 int v = *(compat_int_t *)src;
1029 v += xt_compat_calc_jump(AF_INET, v);
1030 memcpy(dst, &v, sizeof(v));
1033 static int compat_standard_to_user(void __user *dst, void *src)
1035 compat_int_t cv = *(int *)src;
1038 cv -= xt_compat_calc_jump(AF_INET, cv);
1039 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1043 compat_calc_match(struct ipt_entry_match *m, int *size)
1045 *size += xt_compat_match_offset(m->u.kernel.match);
1049 static int compat_calc_entry(struct ipt_entry *e,
1050 const struct xt_table_info *info,
1051 void *base, struct xt_table_info *newinfo)
1053 struct ipt_entry_target *t;
1054 unsigned int entry_offset;
1057 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1058 entry_offset = (void *)e - base;
1059 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1060 t = ipt_get_target(e);
1061 off += xt_compat_target_offset(t->u.kernel.target);
1062 newinfo->size -= off;
1063 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1067 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1068 if (info->hook_entry[i] &&
1069 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1070 newinfo->hook_entry[i] -= off;
1071 if (info->underflow[i] &&
1072 (e < (struct ipt_entry *)(base + info->underflow[i])))
1073 newinfo->underflow[i] -= off;
1078 static int compat_table_info(const struct xt_table_info *info,
1079 struct xt_table_info *newinfo)
1081 void *loc_cpu_entry;
1083 if (!newinfo || !info)
1086 /* we dont care about newinfo->entries[] */
1087 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1088 newinfo->initial_entries = 0;
1089 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1090 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1091 compat_calc_entry, info, loc_cpu_entry,
1096 static int get_info(struct net *net, void __user *user, int *len, int compat)
1098 char name[IPT_TABLE_MAXNAMELEN];
1102 if (*len != sizeof(struct ipt_getinfo)) {
1103 duprintf("length %u != %zu\n", *len,
1104 sizeof(struct ipt_getinfo));
1108 if (copy_from_user(name, user, sizeof(name)) != 0)
1111 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1112 #ifdef CONFIG_COMPAT
1114 xt_compat_lock(AF_INET);
1116 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1117 "iptable_%s", name);
1118 if (t && !IS_ERR(t)) {
1119 struct ipt_getinfo info;
1120 const struct xt_table_info *private = t->private;
1122 #ifdef CONFIG_COMPAT
1124 struct xt_table_info tmp;
1125 ret = compat_table_info(private, &tmp);
1126 xt_compat_flush_offsets(AF_INET);
1130 info.valid_hooks = t->valid_hooks;
1131 memcpy(info.hook_entry, private->hook_entry,
1132 sizeof(info.hook_entry));
1133 memcpy(info.underflow, private->underflow,
1134 sizeof(info.underflow));
1135 info.num_entries = private->number;
1136 info.size = private->size;
1137 strcpy(info.name, name);
1139 if (copy_to_user(user, &info, *len) != 0)
1147 ret = t ? PTR_ERR(t) : -ENOENT;
1148 #ifdef CONFIG_COMPAT
1150 xt_compat_unlock(AF_INET);
1156 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1159 struct ipt_get_entries get;
1162 if (*len < sizeof(get)) {
1163 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1166 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1168 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1169 duprintf("get_entries: %u != %zu\n",
1170 *len, sizeof(get) + get.size);
1174 t = xt_find_table_lock(net, AF_INET, get.name);
1175 if (t && !IS_ERR(t)) {
1176 const struct xt_table_info *private = t->private;
1177 duprintf("t->private->number = %u\n", private->number);
1178 if (get.size == private->size)
1179 ret = copy_entries_to_user(private->size,
1180 t, uptr->entrytable);
1182 duprintf("get_entries: I've got %u not %u!\n",
1183 private->size, get.size);
1189 ret = t ? PTR_ERR(t) : -ENOENT;
1195 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1196 struct xt_table_info *newinfo, unsigned int num_counters,
1197 void __user *counters_ptr)
1201 struct xt_table_info *oldinfo;
1202 struct xt_counters *counters;
1203 void *loc_cpu_old_entry;
1206 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1212 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1213 "iptable_%s", name);
1214 if (!t || IS_ERR(t)) {
1215 ret = t ? PTR_ERR(t) : -ENOENT;
1216 goto free_newinfo_counters_untrans;
1220 if (valid_hooks != t->valid_hooks) {
1221 duprintf("Valid hook crap: %08X vs %08X\n",
1222 valid_hooks, t->valid_hooks);
1227 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1231 /* Update module usage count based on number of rules */
1232 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1233 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1234 if ((oldinfo->number > oldinfo->initial_entries) ||
1235 (newinfo->number <= oldinfo->initial_entries))
1237 if ((oldinfo->number > oldinfo->initial_entries) &&
1238 (newinfo->number <= oldinfo->initial_entries))
1241 /* Get the old counters, and synchronize with replace */
1242 get_counters(oldinfo, counters);
1244 /* Decrease module usage counts and free resource */
1245 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1246 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1248 xt_free_table_info(oldinfo);
1249 if (copy_to_user(counters_ptr, counters,
1250 sizeof(struct xt_counters) * num_counters) != 0)
1259 free_newinfo_counters_untrans:
1266 do_replace(struct net *net, void __user *user, unsigned int len)
1269 struct ipt_replace tmp;
1270 struct xt_table_info *newinfo;
1271 void *loc_cpu_entry;
1273 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1276 /* overflow check */
1277 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1280 newinfo = xt_alloc_table_info(tmp.size);
1284 /* choose the copy that is on our node/cpu */
1285 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1286 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1292 ret = translate_table(tmp.name, tmp.valid_hooks,
1293 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1294 tmp.hook_entry, tmp.underflow);
1298 duprintf("ip_tables: Translated table\n");
1300 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1301 tmp.num_counters, tmp.counters);
1303 goto free_newinfo_untrans;
1306 free_newinfo_untrans:
1307 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1309 xt_free_table_info(newinfo);
1313 /* We're lazy, and add to the first CPU; overflow works its fey magic
1314 * and everything is OK. */
1316 add_counter_to_entry(struct ipt_entry *e,
1317 const struct xt_counters addme[],
1320 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1327 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1329 unsigned int i, curcpu;
1330 struct xt_counters_info tmp;
1331 struct xt_counters *paddc;
1332 unsigned int num_counters;
1337 const struct xt_table_info *private;
1339 void *loc_cpu_entry;
1340 #ifdef CONFIG_COMPAT
1341 struct compat_xt_counters_info compat_tmp;
1345 size = sizeof(struct compat_xt_counters_info);
1350 size = sizeof(struct xt_counters_info);
1353 if (copy_from_user(ptmp, user, size) != 0)
1356 #ifdef CONFIG_COMPAT
1358 num_counters = compat_tmp.num_counters;
1359 name = compat_tmp.name;
1363 num_counters = tmp.num_counters;
1367 if (len != size + num_counters * sizeof(struct xt_counters))
1370 paddc = vmalloc_node(len - size, numa_node_id());
1374 if (copy_from_user(paddc, user + size, len - size) != 0) {
1379 t = xt_find_table_lock(net, AF_INET, name);
1380 if (!t || IS_ERR(t)) {
1381 ret = t ? PTR_ERR(t) : -ENOENT;
1386 private = t->private;
1387 if (private->number != num_counters) {
1389 goto unlock_up_free;
1393 /* Choose the copy that is on our node */
1394 curcpu = smp_processor_id();
1395 loc_cpu_entry = private->entries[curcpu];
1396 xt_info_wrlock(curcpu);
1397 IPT_ENTRY_ITERATE(loc_cpu_entry,
1399 add_counter_to_entry,
1402 xt_info_wrunlock(curcpu);
1413 #ifdef CONFIG_COMPAT
1414 struct compat_ipt_replace {
1415 char name[IPT_TABLE_MAXNAMELEN];
1419 u32 hook_entry[NF_INET_NUMHOOKS];
1420 u32 underflow[NF_INET_NUMHOOKS];
1422 compat_uptr_t counters; /* struct ipt_counters * */
1423 struct compat_ipt_entry entries[0];
1427 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1428 unsigned int *size, struct xt_counters *counters,
1431 struct ipt_entry_target *t;
1432 struct compat_ipt_entry __user *ce;
1433 u_int16_t target_offset, next_offset;
1434 compat_uint_t origsize;
1439 ce = (struct compat_ipt_entry __user *)*dstptr;
1440 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1443 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1446 *dstptr += sizeof(struct compat_ipt_entry);
1447 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1449 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1450 target_offset = e->target_offset - (origsize - *size);
1453 t = ipt_get_target(e);
1454 ret = xt_compat_target_to_user(t, dstptr, size);
1458 next_offset = e->next_offset - (origsize - *size);
1459 if (put_user(target_offset, &ce->target_offset))
1461 if (put_user(next_offset, &ce->next_offset))
1471 compat_find_calc_match(struct ipt_entry_match *m,
1473 const struct ipt_ip *ip,
1474 unsigned int hookmask,
1475 int *size, unsigned int *i)
1477 struct xt_match *match;
1479 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1480 m->u.user.revision),
1481 "ipt_%s", m->u.user.name);
1482 if (IS_ERR(match) || !match) {
1483 duprintf("compat_check_calc_match: `%s' not found\n",
1485 return match ? PTR_ERR(match) : -ENOENT;
1487 m->u.kernel.match = match;
1488 *size += xt_compat_match_offset(match);
1495 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1497 if (i && (*i)-- == 0)
1500 module_put(m->u.kernel.match->me);
1505 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1507 struct ipt_entry_target *t;
1509 if (i && (*i)-- == 0)
1512 /* Cleanup all matches */
1513 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1514 t = compat_ipt_get_target(e);
1515 module_put(t->u.kernel.target->me);
1520 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1521 struct xt_table_info *newinfo,
1523 unsigned char *base,
1524 unsigned char *limit,
1525 unsigned int *hook_entries,
1526 unsigned int *underflows,
1530 struct ipt_entry_target *t;
1531 struct xt_target *target;
1532 unsigned int entry_offset;
1536 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1537 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1538 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1539 duprintf("Bad offset %p, limit = %p\n", e, limit);
1543 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1544 sizeof(struct compat_xt_entry_target)) {
1545 duprintf("checking: element %p size %u\n",
1550 /* For purposes of check_entry casting the compat entry is fine */
1551 ret = check_entry((struct ipt_entry *)e, name);
1555 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1556 entry_offset = (void *)e - (void *)base;
1558 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1559 &e->ip, e->comefrom, &off, &j);
1561 goto release_matches;
1563 t = compat_ipt_get_target(e);
1564 target = try_then_request_module(xt_find_target(AF_INET,
1566 t->u.user.revision),
1567 "ipt_%s", t->u.user.name);
1568 if (IS_ERR(target) || !target) {
1569 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1571 ret = target ? PTR_ERR(target) : -ENOENT;
1572 goto release_matches;
1574 t->u.kernel.target = target;
1576 off += xt_compat_target_offset(target);
1578 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1582 /* Check hooks & underflows */
1583 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1584 if ((unsigned char *)e - base == hook_entries[h])
1585 newinfo->hook_entry[h] = hook_entries[h];
1586 if ((unsigned char *)e - base == underflows[h])
1587 newinfo->underflow[h] = underflows[h];
1590 /* Clear counters and comefrom */
1591 memset(&e->counters, 0, sizeof(e->counters));
1598 module_put(t->u.kernel.target->me);
1600 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1605 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1606 unsigned int *size, const char *name,
1607 struct xt_table_info *newinfo, unsigned char *base)
1609 struct ipt_entry_target *t;
1610 struct xt_target *target;
1611 struct ipt_entry *de;
1612 unsigned int origsize;
1617 de = (struct ipt_entry *)*dstptr;
1618 memcpy(de, e, sizeof(struct ipt_entry));
1619 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1621 *dstptr += sizeof(struct ipt_entry);
1622 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1624 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1628 de->target_offset = e->target_offset - (origsize - *size);
1629 t = compat_ipt_get_target(e);
1630 target = t->u.kernel.target;
1631 xt_compat_target_from_user(t, dstptr, size);
1633 de->next_offset = e->next_offset - (origsize - *size);
1634 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1635 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1636 newinfo->hook_entry[h] -= origsize - *size;
1637 if ((unsigned char *)de - base < newinfo->underflow[h])
1638 newinfo->underflow[h] -= origsize - *size;
1644 compat_check_entry(struct ipt_entry *e, const char *name,
1647 struct xt_mtchk_param mtpar;
1653 mtpar.entryinfo = &e->ip;
1654 mtpar.hook_mask = e->comefrom;
1655 mtpar.family = NFPROTO_IPV4;
1656 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1658 goto cleanup_matches;
1660 ret = check_target(e, name);
1662 goto cleanup_matches;
1668 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1673 translate_compat_table(const char *name,
1674 unsigned int valid_hooks,
1675 struct xt_table_info **pinfo,
1677 unsigned int total_size,
1678 unsigned int number,
1679 unsigned int *hook_entries,
1680 unsigned int *underflows)
1683 struct xt_table_info *newinfo, *info;
1684 void *pos, *entry0, *entry1;
1691 info->number = number;
1693 /* Init all hooks to impossible value. */
1694 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1695 info->hook_entry[i] = 0xFFFFFFFF;
1696 info->underflow[i] = 0xFFFFFFFF;
1699 duprintf("translate_compat_table: size %u\n", info->size);
1701 xt_compat_lock(AF_INET);
1702 /* Walk through entries, checking offsets. */
1703 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1704 check_compat_entry_size_and_hooks,
1705 info, &size, entry0,
1706 entry0 + total_size,
1707 hook_entries, underflows, &j, name);
1713 duprintf("translate_compat_table: %u not %u entries\n",
1718 /* Check hooks all assigned */
1719 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1720 /* Only hooks which are valid */
1721 if (!(valid_hooks & (1 << i)))
1723 if (info->hook_entry[i] == 0xFFFFFFFF) {
1724 duprintf("Invalid hook entry %u %u\n",
1725 i, hook_entries[i]);
1728 if (info->underflow[i] == 0xFFFFFFFF) {
1729 duprintf("Invalid underflow %u %u\n",
1736 newinfo = xt_alloc_table_info(size);
1740 newinfo->number = number;
1741 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1742 newinfo->hook_entry[i] = info->hook_entry[i];
1743 newinfo->underflow[i] = info->underflow[i];
1745 entry1 = newinfo->entries[raw_smp_processor_id()];
1748 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1749 compat_copy_entry_from_user,
1750 &pos, &size, name, newinfo, entry1);
1751 xt_compat_flush_offsets(AF_INET);
1752 xt_compat_unlock(AF_INET);
1757 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1761 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1765 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1766 compat_release_entry, &j);
1767 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1768 xt_free_table_info(newinfo);
1772 /* And one copy for every other CPU */
1773 for_each_possible_cpu(i)
1774 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1775 memcpy(newinfo->entries[i], entry1, newinfo->size);
1779 xt_free_table_info(info);
1783 xt_free_table_info(newinfo);
1785 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1788 xt_compat_flush_offsets(AF_INET);
1789 xt_compat_unlock(AF_INET);
1794 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1797 struct compat_ipt_replace tmp;
1798 struct xt_table_info *newinfo;
1799 void *loc_cpu_entry;
1801 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1804 /* overflow check */
1805 if (tmp.size >= INT_MAX / num_possible_cpus())
1807 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1810 newinfo = xt_alloc_table_info(tmp.size);
1814 /* choose the copy that is on our node/cpu */
1815 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1816 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1822 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1823 &newinfo, &loc_cpu_entry, tmp.size,
1824 tmp.num_entries, tmp.hook_entry,
1829 duprintf("compat_do_replace: Translated table\n");
1831 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1832 tmp.num_counters, compat_ptr(tmp.counters));
1834 goto free_newinfo_untrans;
1837 free_newinfo_untrans:
1838 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1840 xt_free_table_info(newinfo);
1845 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1850 if (!capable(CAP_NET_ADMIN))
1854 case IPT_SO_SET_REPLACE:
1855 ret = compat_do_replace(sock_net(sk), user, len);
1858 case IPT_SO_SET_ADD_COUNTERS:
1859 ret = do_add_counters(sock_net(sk), user, len, 1);
1863 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1870 struct compat_ipt_get_entries {
1871 char name[IPT_TABLE_MAXNAMELEN];
1873 struct compat_ipt_entry entrytable[0];
1877 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1878 void __user *userptr)
1880 struct xt_counters *counters;
1881 const struct xt_table_info *private = table->private;
1885 const void *loc_cpu_entry;
1888 counters = alloc_counters(table);
1889 if (IS_ERR(counters))
1890 return PTR_ERR(counters);
1892 /* choose the copy that is on our node/cpu, ...
1893 * This choice is lazy (because current thread is
1894 * allowed to migrate to another cpu)
1896 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1899 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1900 compat_copy_entry_to_user,
1901 &pos, &size, counters, &i);
1908 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1912 struct compat_ipt_get_entries get;
1915 if (*len < sizeof(get)) {
1916 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1920 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1923 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1924 duprintf("compat_get_entries: %u != %zu\n",
1925 *len, sizeof(get) + get.size);
1929 xt_compat_lock(AF_INET);
1930 t = xt_find_table_lock(net, AF_INET, get.name);
1931 if (t && !IS_ERR(t)) {
1932 const struct xt_table_info *private = t->private;
1933 struct xt_table_info info;
1934 duprintf("t->private->number = %u\n", private->number);
1935 ret = compat_table_info(private, &info);
1936 if (!ret && get.size == info.size) {
1937 ret = compat_copy_entries_to_user(private->size,
1938 t, uptr->entrytable);
1940 duprintf("compat_get_entries: I've got %u not %u!\n",
1941 private->size, get.size);
1944 xt_compat_flush_offsets(AF_INET);
1948 ret = t ? PTR_ERR(t) : -ENOENT;
1950 xt_compat_unlock(AF_INET);
1954 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1957 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1961 if (!capable(CAP_NET_ADMIN))
1965 case IPT_SO_GET_INFO:
1966 ret = get_info(sock_net(sk), user, len, 1);
1968 case IPT_SO_GET_ENTRIES:
1969 ret = compat_get_entries(sock_net(sk), user, len);
1972 ret = do_ipt_get_ctl(sk, cmd, user, len);
1979 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1983 if (!capable(CAP_NET_ADMIN))
1987 case IPT_SO_SET_REPLACE:
1988 ret = do_replace(sock_net(sk), user, len);
1991 case IPT_SO_SET_ADD_COUNTERS:
1992 ret = do_add_counters(sock_net(sk), user, len, 0);
1996 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2004 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2008 if (!capable(CAP_NET_ADMIN))
2012 case IPT_SO_GET_INFO:
2013 ret = get_info(sock_net(sk), user, len, 0);
2016 case IPT_SO_GET_ENTRIES:
2017 ret = get_entries(sock_net(sk), user, len);
2020 case IPT_SO_GET_REVISION_MATCH:
2021 case IPT_SO_GET_REVISION_TARGET: {
2022 struct ipt_get_revision rev;
2025 if (*len != sizeof(rev)) {
2029 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2034 if (cmd == IPT_SO_GET_REVISION_TARGET)
2039 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2042 "ipt_%s", rev.name);
2047 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2054 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2055 const struct ipt_replace *repl)
2058 struct xt_table_info *newinfo;
2059 struct xt_table_info bootstrap
2060 = { 0, 0, 0, { 0 }, { 0 }, { } };
2061 void *loc_cpu_entry;
2062 struct xt_table *new_table;
2064 newinfo = xt_alloc_table_info(repl->size);
2070 /* choose the copy on our node/cpu, but dont care about preemption */
2071 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2072 memcpy(loc_cpu_entry, repl->entries, repl->size);
2074 ret = translate_table(table->name, table->valid_hooks,
2075 newinfo, loc_cpu_entry, repl->size,
2082 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2083 if (IS_ERR(new_table)) {
2084 ret = PTR_ERR(new_table);
2091 xt_free_table_info(newinfo);
2093 return ERR_PTR(ret);
2096 void ipt_unregister_table(struct xt_table *table)
2098 struct xt_table_info *private;
2099 void *loc_cpu_entry;
2100 struct module *table_owner = table->me;
2102 private = xt_unregister_table(table);
2104 /* Decrease module usage counts and free resources */
2105 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2106 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2107 if (private->number > private->initial_entries)
2108 module_put(table_owner);
2109 xt_free_table_info(private);
2112 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2114 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2115 u_int8_t type, u_int8_t code,
2118 return ((test_type == 0xFF) ||
2119 (type == test_type && code >= min_code && code <= max_code))
2124 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2126 const struct icmphdr *ic;
2127 struct icmphdr _icmph;
2128 const struct ipt_icmp *icmpinfo = par->matchinfo;
2130 /* Must not be a fragment. */
2131 if (par->fragoff != 0)
2134 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2136 /* We've been asked to examine this packet, and we
2137 * can't. Hence, no choice but to drop.
2139 duprintf("Dropping evil ICMP tinygram.\n");
2140 *par->hotdrop = true;
2144 return icmp_type_code_match(icmpinfo->type,
2148 !!(icmpinfo->invflags&IPT_ICMP_INV));
2151 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2153 const struct ipt_icmp *icmpinfo = par->matchinfo;
2155 /* Must specify no unknown invflags */
2156 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2159 /* The built-in targets: standard (NULL) and error. */
2160 static struct xt_target ipt_standard_target __read_mostly = {
2161 .name = IPT_STANDARD_TARGET,
2162 .targetsize = sizeof(int),
2163 .family = NFPROTO_IPV4,
2164 #ifdef CONFIG_COMPAT
2165 .compatsize = sizeof(compat_int_t),
2166 .compat_from_user = compat_standard_from_user,
2167 .compat_to_user = compat_standard_to_user,
2171 static struct xt_target ipt_error_target __read_mostly = {
2172 .name = IPT_ERROR_TARGET,
2173 .target = ipt_error,
2174 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2175 .family = NFPROTO_IPV4,
2178 static struct nf_sockopt_ops ipt_sockopts = {
2180 .set_optmin = IPT_BASE_CTL,
2181 .set_optmax = IPT_SO_SET_MAX+1,
2182 .set = do_ipt_set_ctl,
2183 #ifdef CONFIG_COMPAT
2184 .compat_set = compat_do_ipt_set_ctl,
2186 .get_optmin = IPT_BASE_CTL,
2187 .get_optmax = IPT_SO_GET_MAX+1,
2188 .get = do_ipt_get_ctl,
2189 #ifdef CONFIG_COMPAT
2190 .compat_get = compat_do_ipt_get_ctl,
2192 .owner = THIS_MODULE,
2195 static struct xt_match icmp_matchstruct __read_mostly = {
2197 .match = icmp_match,
2198 .matchsize = sizeof(struct ipt_icmp),
2199 .checkentry = icmp_checkentry,
2200 .proto = IPPROTO_ICMP,
2201 .family = NFPROTO_IPV4,
2204 static int __net_init ip_tables_net_init(struct net *net)
2206 return xt_proto_init(net, NFPROTO_IPV4);
2209 static void __net_exit ip_tables_net_exit(struct net *net)
2211 xt_proto_fini(net, NFPROTO_IPV4);
2214 static struct pernet_operations ip_tables_net_ops = {
2215 .init = ip_tables_net_init,
2216 .exit = ip_tables_net_exit,
2219 static int __init ip_tables_init(void)
2223 ret = register_pernet_subsys(&ip_tables_net_ops);
2227 /* Noone else will be downing sem now, so we won't sleep */
2228 ret = xt_register_target(&ipt_standard_target);
2231 ret = xt_register_target(&ipt_error_target);
2234 ret = xt_register_match(&icmp_matchstruct);
2238 /* Register setsockopt */
2239 ret = nf_register_sockopt(&ipt_sockopts);
2243 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2247 xt_unregister_match(&icmp_matchstruct);
2249 xt_unregister_target(&ipt_error_target);
2251 xt_unregister_target(&ipt_standard_target);
2253 unregister_pernet_subsys(&ip_tables_net_ops);
2258 static void __exit ip_tables_fini(void)
2260 nf_unregister_sockopt(&ipt_sockopts);
2262 xt_unregister_match(&icmp_matchstruct);
2263 xt_unregister_target(&ipt_error_target);
2264 xt_unregister_target(&ipt_standard_target);
2266 unregister_pernet_subsys(&ip_tables_net_ops);
2269 EXPORT_SYMBOL(ipt_register_table);
2270 EXPORT_SYMBOL(ipt_unregister_table);
2271 EXPORT_SYMBOL(ipt_do_table);
2272 module_init(ip_tables_init);
2273 module_exit(ip_tables_fini);