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 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
315 const struct iphdr *ip;
317 bool hotdrop = false;
318 /* Initializing verdict to NF_DROP keeps gcc happy. */
319 unsigned int verdict = NF_DROP;
320 const char *indev, *outdev;
322 struct ipt_entry *e, *back;
323 struct xt_table_info *private;
324 struct xt_match_param mtpar;
325 struct xt_target_param tgpar;
329 datalen = skb->len - ip->ihl * 4;
330 indev = in ? in->name : nulldevname;
331 outdev = out ? out->name : nulldevname;
332 /* We handle fragments by dealing with the first fragment as
333 * if it was a normal packet. All other fragments are treated
334 * normally, except that they will NEVER match rules that ask
335 * things we don't know, ie. tcp syn flag or ports). If the
336 * rule is also a fragment-specific rule, non-fragments won't
338 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
339 mtpar.thoff = ip_hdrlen(skb);
340 mtpar.hotdrop = &hotdrop;
341 mtpar.in = tgpar.in = in;
342 mtpar.out = tgpar.out = out;
343 mtpar.family = tgpar.family = NFPROTO_IPV4;
344 tgpar.hooknum = hook;
346 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
348 private = table->private;
349 table_base = private->entries[smp_processor_id()];
351 e = get_entry(table_base, private->hook_entry[hook]);
353 /* For return from builtin chain */
354 back = get_entry(table_base, private->underflow[hook]);
357 struct ipt_entry_target *t;
361 if (!ip_packet_match(ip, indev, outdev,
362 &e->ip, mtpar.fragoff) ||
363 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
364 e = ipt_next_entry(e);
368 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
370 t = ipt_get_target(e);
371 IP_NF_ASSERT(t->u.kernel.target);
373 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
374 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
375 /* The packet is traced: log it */
376 if (unlikely(skb->nf_trace))
377 trace_packet(skb, hook, in, out,
378 table->name, private, e);
380 /* Standard target? */
381 if (!t->u.kernel.target->target) {
384 v = ((struct ipt_standard_target *)t)->verdict;
386 /* Pop from stack? */
387 if (v != IPT_RETURN) {
388 verdict = (unsigned)(-v) - 1;
392 back = get_entry(table_base, back->comefrom);
395 if (table_base + v != ipt_next_entry(e)
396 && !(e->ip.flags & IPT_F_GOTO)) {
397 /* Save old back ptr in next entry */
398 struct ipt_entry *next = ipt_next_entry(e);
399 next->comefrom = (void *)back - table_base;
400 /* set back pointer to next entry */
404 e = get_entry(table_base, v);
408 /* Targets which reenter must return
410 tgpar.target = t->u.kernel.target;
411 tgpar.targinfo = t->data;
412 #ifdef CONFIG_NETFILTER_DEBUG
413 ((struct ipt_entry *)table_base)->comefrom = 0xeeeeeeec;
415 verdict = t->u.kernel.target->target(skb, &tgpar);
416 #ifdef CONFIG_NETFILTER_DEBUG
417 if (((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec &&
418 verdict == IPT_CONTINUE) {
419 printk("Target %s reentered!\n",
420 t->u.kernel.target->name);
423 ((struct ipt_entry *)table_base)->comefrom = 0x57acc001;
425 /* Target might have changed stuff. */
427 datalen = skb->len - ip->ihl * 4;
429 if (verdict == IPT_CONTINUE)
430 e = ipt_next_entry(e);
435 xt_info_rdunlock_bh();
437 #ifdef DEBUG_ALLOW_ALL
446 /* Figures out from what hook each rule can be called: returns 0 if
447 there are loops. Puts hook bitmask in comefrom. */
449 mark_source_chains(struct xt_table_info *newinfo,
450 unsigned int valid_hooks, void *entry0)
454 /* No recursion; use packet counter to save back ptrs (reset
455 to 0 as we leave), and comefrom to save source hook bitmask */
456 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
457 unsigned int pos = newinfo->hook_entry[hook];
458 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
460 if (!(valid_hooks & (1 << hook)))
463 /* Set initial back pointer. */
464 e->counters.pcnt = pos;
467 struct ipt_standard_target *t
468 = (void *)ipt_get_target(e);
469 int visited = e->comefrom & (1 << hook);
471 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
472 printk("iptables: loop hook %u pos %u %08X.\n",
473 hook, pos, e->comefrom);
476 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
478 /* Unconditional return/END. */
479 if ((e->target_offset == sizeof(struct ipt_entry)
480 && (strcmp(t->target.u.user.name,
481 IPT_STANDARD_TARGET) == 0)
483 && unconditional(&e->ip)) || visited) {
484 unsigned int oldpos, size;
486 if ((strcmp(t->target.u.user.name,
487 IPT_STANDARD_TARGET) == 0) &&
488 t->verdict < -NF_MAX_VERDICT - 1) {
489 duprintf("mark_source_chains: bad "
490 "negative verdict (%i)\n",
495 /* Return: backtrack through the last
498 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
499 #ifdef DEBUG_IP_FIREWALL_USER
501 & (1 << NF_INET_NUMHOOKS)) {
502 duprintf("Back unset "
509 pos = e->counters.pcnt;
510 e->counters.pcnt = 0;
512 /* We're at the start. */
516 e = (struct ipt_entry *)
518 } while (oldpos == pos + e->next_offset);
521 size = e->next_offset;
522 e = (struct ipt_entry *)
523 (entry0 + pos + size);
524 e->counters.pcnt = pos;
527 int newpos = t->verdict;
529 if (strcmp(t->target.u.user.name,
530 IPT_STANDARD_TARGET) == 0
532 if (newpos > newinfo->size -
533 sizeof(struct ipt_entry)) {
534 duprintf("mark_source_chains: "
535 "bad verdict (%i)\n",
539 /* This a jump; chase it. */
540 duprintf("Jump rule %u -> %u\n",
543 /* ... this is a fallthru */
544 newpos = pos + e->next_offset;
546 e = (struct ipt_entry *)
548 e->counters.pcnt = pos;
553 duprintf("Finished chain %u\n", hook);
559 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
561 struct xt_mtdtor_param par;
563 if (i && (*i)-- == 0)
566 par.match = m->u.kernel.match;
567 par.matchinfo = m->data;
568 par.family = NFPROTO_IPV4;
569 if (par.match->destroy != NULL)
570 par.match->destroy(&par);
571 module_put(par.match->me);
576 check_entry(struct ipt_entry *e, const char *name)
578 struct ipt_entry_target *t;
580 if (!ip_checkentry(&e->ip)) {
581 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
585 if (e->target_offset + sizeof(struct ipt_entry_target) >
589 t = ipt_get_target(e);
590 if (e->target_offset + t->u.target_size > e->next_offset)
597 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
600 const struct ipt_ip *ip = par->entryinfo;
603 par->match = m->u.kernel.match;
604 par->matchinfo = m->data;
606 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
607 ip->proto, ip->invflags & IPT_INV_PROTO);
609 duprintf("ip_tables: check failed for `%s'.\n",
618 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
621 struct xt_match *match;
624 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
626 "ipt_%s", m->u.user.name);
627 if (IS_ERR(match) || !match) {
628 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
629 return match ? PTR_ERR(match) : -ENOENT;
631 m->u.kernel.match = match;
633 ret = check_match(m, par, i);
639 module_put(m->u.kernel.match->me);
643 static int check_target(struct ipt_entry *e, const char *name)
645 struct ipt_entry_target *t = ipt_get_target(e);
646 struct xt_tgchk_param par = {
649 .target = t->u.kernel.target,
651 .hook_mask = e->comefrom,
652 .family = NFPROTO_IPV4,
656 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
657 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
659 duprintf("ip_tables: check failed for `%s'.\n",
660 t->u.kernel.target->name);
667 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
670 struct ipt_entry_target *t;
671 struct xt_target *target;
674 struct xt_mtchk_param mtpar;
676 ret = check_entry(e, name);
682 mtpar.entryinfo = &e->ip;
683 mtpar.hook_mask = e->comefrom;
684 mtpar.family = NFPROTO_IPV4;
685 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
687 goto cleanup_matches;
689 t = ipt_get_target(e);
690 target = try_then_request_module(xt_find_target(AF_INET,
693 "ipt_%s", t->u.user.name);
694 if (IS_ERR(target) || !target) {
695 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
696 ret = target ? PTR_ERR(target) : -ENOENT;
697 goto cleanup_matches;
699 t->u.kernel.target = target;
701 ret = check_target(e, name);
708 module_put(t->u.kernel.target->me);
710 IPT_MATCH_ITERATE(e, cleanup_match, &j);
715 check_entry_size_and_hooks(struct ipt_entry *e,
716 struct xt_table_info *newinfo,
718 unsigned char *limit,
719 const unsigned int *hook_entries,
720 const unsigned int *underflows,
725 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
726 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
727 duprintf("Bad offset %p\n", e);
732 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
733 duprintf("checking: element %p size %u\n",
738 /* Check hooks & underflows */
739 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
740 if ((unsigned char *)e - base == hook_entries[h])
741 newinfo->hook_entry[h] = hook_entries[h];
742 if ((unsigned char *)e - base == underflows[h])
743 newinfo->underflow[h] = underflows[h];
746 /* FIXME: underflows must be unconditional, standard verdicts
747 < 0 (not IPT_RETURN). --RR */
749 /* Clear counters and comefrom */
750 e->counters = ((struct xt_counters) { 0, 0 });
758 cleanup_entry(struct ipt_entry *e, unsigned int *i)
760 struct xt_tgdtor_param par;
761 struct ipt_entry_target *t;
763 if (i && (*i)-- == 0)
766 /* Cleanup all matches */
767 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
768 t = ipt_get_target(e);
770 par.target = t->u.kernel.target;
771 par.targinfo = t->data;
772 par.family = NFPROTO_IPV4;
773 if (par.target->destroy != NULL)
774 par.target->destroy(&par);
775 module_put(par.target->me);
779 /* Checks and translates the user-supplied table segment (held in
782 translate_table(const char *name,
783 unsigned int valid_hooks,
784 struct xt_table_info *newinfo,
788 const unsigned int *hook_entries,
789 const unsigned int *underflows)
794 newinfo->size = size;
795 newinfo->number = number;
797 /* Init all hooks to impossible value. */
798 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
799 newinfo->hook_entry[i] = 0xFFFFFFFF;
800 newinfo->underflow[i] = 0xFFFFFFFF;
803 duprintf("translate_table: size %u\n", newinfo->size);
805 /* Walk through entries, checking offsets. */
806 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
807 check_entry_size_and_hooks,
811 hook_entries, underflows, &i);
816 duprintf("translate_table: %u not %u entries\n",
821 /* Check hooks all assigned */
822 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
823 /* Only hooks which are valid */
824 if (!(valid_hooks & (1 << i)))
826 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
827 duprintf("Invalid hook entry %u %u\n",
831 if (newinfo->underflow[i] == 0xFFFFFFFF) {
832 duprintf("Invalid underflow %u %u\n",
838 if (!mark_source_chains(newinfo, valid_hooks, entry0))
841 /* Finally, each sanity check must pass */
843 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
844 find_check_entry, name, size, &i);
847 IPT_ENTRY_ITERATE(entry0, newinfo->size,
852 /* And one copy for every other CPU */
853 for_each_possible_cpu(i) {
854 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
855 memcpy(newinfo->entries[i], entry0, newinfo->size);
863 add_entry_to_counter(const struct ipt_entry *e,
864 struct xt_counters total[],
867 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
874 set_entry_to_counter(const struct ipt_entry *e,
875 struct ipt_counters total[],
878 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
885 get_counters(const struct xt_table_info *t,
886 struct xt_counters counters[])
892 /* Instead of clearing (by a previous call to memset())
893 * the counters and using adds, we set the counters
894 * with data used by 'current' CPU.
896 * Bottom half has to be disabled to prevent deadlock
897 * if new softirq were to run and call ipt_do_table
900 curcpu = smp_processor_id();
903 IPT_ENTRY_ITERATE(t->entries[curcpu],
905 set_entry_to_counter,
909 for_each_possible_cpu(cpu) {
914 IPT_ENTRY_ITERATE(t->entries[cpu],
916 add_entry_to_counter,
919 xt_info_wrunlock(cpu);
924 static struct xt_counters * alloc_counters(struct xt_table *table)
926 unsigned int countersize;
927 struct xt_counters *counters;
928 struct xt_table_info *private = table->private;
930 /* We need atomic snapshot of counters: rest doesn't change
931 (other than comefrom, which userspace doesn't care
933 countersize = sizeof(struct xt_counters) * private->number;
934 counters = vmalloc_node(countersize, numa_node_id());
936 if (counters == NULL)
937 return ERR_PTR(-ENOMEM);
939 get_counters(private, counters);
945 copy_entries_to_user(unsigned int total_size,
946 struct xt_table *table,
947 void __user *userptr)
949 unsigned int off, num;
951 struct xt_counters *counters;
952 const struct xt_table_info *private = table->private;
954 const void *loc_cpu_entry;
956 counters = alloc_counters(table);
957 if (IS_ERR(counters))
958 return PTR_ERR(counters);
960 /* choose the copy that is on our node/cpu, ...
961 * This choice is lazy (because current thread is
962 * allowed to migrate to another cpu)
964 loc_cpu_entry = private->entries[raw_smp_processor_id()];
965 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
970 /* FIXME: use iterator macros --RR */
971 /* ... then go back and fix counters and names */
972 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
974 const struct ipt_entry_match *m;
975 const struct ipt_entry_target *t;
977 e = (struct ipt_entry *)(loc_cpu_entry + off);
978 if (copy_to_user(userptr + off
979 + offsetof(struct ipt_entry, counters),
981 sizeof(counters[num])) != 0) {
986 for (i = sizeof(struct ipt_entry);
987 i < e->target_offset;
988 i += m->u.match_size) {
991 if (copy_to_user(userptr + off + i
992 + offsetof(struct ipt_entry_match,
994 m->u.kernel.match->name,
995 strlen(m->u.kernel.match->name)+1)
1002 t = ipt_get_target(e);
1003 if (copy_to_user(userptr + off + e->target_offset
1004 + offsetof(struct ipt_entry_target,
1006 t->u.kernel.target->name,
1007 strlen(t->u.kernel.target->name)+1) != 0) {
1018 #ifdef CONFIG_COMPAT
1019 static void compat_standard_from_user(void *dst, void *src)
1021 int v = *(compat_int_t *)src;
1024 v += xt_compat_calc_jump(AF_INET, v);
1025 memcpy(dst, &v, sizeof(v));
1028 static int compat_standard_to_user(void __user *dst, void *src)
1030 compat_int_t cv = *(int *)src;
1033 cv -= xt_compat_calc_jump(AF_INET, cv);
1034 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1038 compat_calc_match(struct ipt_entry_match *m, int *size)
1040 *size += xt_compat_match_offset(m->u.kernel.match);
1044 static int compat_calc_entry(struct ipt_entry *e,
1045 const struct xt_table_info *info,
1046 void *base, struct xt_table_info *newinfo)
1048 struct ipt_entry_target *t;
1049 unsigned int entry_offset;
1052 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1053 entry_offset = (void *)e - base;
1054 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1055 t = ipt_get_target(e);
1056 off += xt_compat_target_offset(t->u.kernel.target);
1057 newinfo->size -= off;
1058 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1062 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1063 if (info->hook_entry[i] &&
1064 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1065 newinfo->hook_entry[i] -= off;
1066 if (info->underflow[i] &&
1067 (e < (struct ipt_entry *)(base + info->underflow[i])))
1068 newinfo->underflow[i] -= off;
1073 static int compat_table_info(const struct xt_table_info *info,
1074 struct xt_table_info *newinfo)
1076 void *loc_cpu_entry;
1078 if (!newinfo || !info)
1081 /* we dont care about newinfo->entries[] */
1082 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1083 newinfo->initial_entries = 0;
1084 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1085 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1086 compat_calc_entry, info, loc_cpu_entry,
1091 static int get_info(struct net *net, void __user *user, int *len, int compat)
1093 char name[IPT_TABLE_MAXNAMELEN];
1097 if (*len != sizeof(struct ipt_getinfo)) {
1098 duprintf("length %u != %zu\n", *len,
1099 sizeof(struct ipt_getinfo));
1103 if (copy_from_user(name, user, sizeof(name)) != 0)
1106 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1107 #ifdef CONFIG_COMPAT
1109 xt_compat_lock(AF_INET);
1111 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1112 "iptable_%s", name);
1113 if (t && !IS_ERR(t)) {
1114 struct ipt_getinfo info;
1115 const struct xt_table_info *private = t->private;
1117 #ifdef CONFIG_COMPAT
1119 struct xt_table_info tmp;
1120 ret = compat_table_info(private, &tmp);
1121 xt_compat_flush_offsets(AF_INET);
1125 info.valid_hooks = t->valid_hooks;
1126 memcpy(info.hook_entry, private->hook_entry,
1127 sizeof(info.hook_entry));
1128 memcpy(info.underflow, private->underflow,
1129 sizeof(info.underflow));
1130 info.num_entries = private->number;
1131 info.size = private->size;
1132 strcpy(info.name, name);
1134 if (copy_to_user(user, &info, *len) != 0)
1142 ret = t ? PTR_ERR(t) : -ENOENT;
1143 #ifdef CONFIG_COMPAT
1145 xt_compat_unlock(AF_INET);
1151 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1154 struct ipt_get_entries get;
1157 if (*len < sizeof(get)) {
1158 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1161 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1163 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1164 duprintf("get_entries: %u != %zu\n",
1165 *len, sizeof(get) + get.size);
1169 t = xt_find_table_lock(net, AF_INET, get.name);
1170 if (t && !IS_ERR(t)) {
1171 const struct xt_table_info *private = t->private;
1172 duprintf("t->private->number = %u\n", private->number);
1173 if (get.size == private->size)
1174 ret = copy_entries_to_user(private->size,
1175 t, uptr->entrytable);
1177 duprintf("get_entries: I've got %u not %u!\n",
1178 private->size, get.size);
1184 ret = t ? PTR_ERR(t) : -ENOENT;
1190 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1191 struct xt_table_info *newinfo, unsigned int num_counters,
1192 void __user *counters_ptr)
1196 struct xt_table_info *oldinfo;
1197 struct xt_counters *counters;
1198 void *loc_cpu_old_entry;
1201 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1207 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1208 "iptable_%s", name);
1209 if (!t || IS_ERR(t)) {
1210 ret = t ? PTR_ERR(t) : -ENOENT;
1211 goto free_newinfo_counters_untrans;
1215 if (valid_hooks != t->valid_hooks) {
1216 duprintf("Valid hook crap: %08X vs %08X\n",
1217 valid_hooks, t->valid_hooks);
1222 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1226 /* Update module usage count based on number of rules */
1227 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1228 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1229 if ((oldinfo->number > oldinfo->initial_entries) ||
1230 (newinfo->number <= oldinfo->initial_entries))
1232 if ((oldinfo->number > oldinfo->initial_entries) &&
1233 (newinfo->number <= oldinfo->initial_entries))
1236 /* Get the old counters, and synchronize with replace */
1237 get_counters(oldinfo, counters);
1239 /* Decrease module usage counts and free resource */
1240 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1241 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1243 xt_free_table_info(oldinfo);
1244 if (copy_to_user(counters_ptr, counters,
1245 sizeof(struct xt_counters) * num_counters) != 0)
1254 free_newinfo_counters_untrans:
1261 do_replace(struct net *net, void __user *user, unsigned int len)
1264 struct ipt_replace tmp;
1265 struct xt_table_info *newinfo;
1266 void *loc_cpu_entry;
1268 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1271 /* overflow check */
1272 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1275 newinfo = xt_alloc_table_info(tmp.size);
1279 /* choose the copy that is on our node/cpu */
1280 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1281 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1287 ret = translate_table(tmp.name, tmp.valid_hooks,
1288 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1289 tmp.hook_entry, tmp.underflow);
1293 duprintf("ip_tables: Translated table\n");
1295 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1296 tmp.num_counters, tmp.counters);
1298 goto free_newinfo_untrans;
1301 free_newinfo_untrans:
1302 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1304 xt_free_table_info(newinfo);
1308 /* We're lazy, and add to the first CPU; overflow works its fey magic
1309 * and everything is OK. */
1311 add_counter_to_entry(struct ipt_entry *e,
1312 const struct xt_counters addme[],
1315 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1322 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1324 unsigned int i, curcpu;
1325 struct xt_counters_info tmp;
1326 struct xt_counters *paddc;
1327 unsigned int num_counters;
1332 const struct xt_table_info *private;
1334 void *loc_cpu_entry;
1335 #ifdef CONFIG_COMPAT
1336 struct compat_xt_counters_info compat_tmp;
1340 size = sizeof(struct compat_xt_counters_info);
1345 size = sizeof(struct xt_counters_info);
1348 if (copy_from_user(ptmp, user, size) != 0)
1351 #ifdef CONFIG_COMPAT
1353 num_counters = compat_tmp.num_counters;
1354 name = compat_tmp.name;
1358 num_counters = tmp.num_counters;
1362 if (len != size + num_counters * sizeof(struct xt_counters))
1365 paddc = vmalloc_node(len - size, numa_node_id());
1369 if (copy_from_user(paddc, user + size, len - size) != 0) {
1374 t = xt_find_table_lock(net, AF_INET, name);
1375 if (!t || IS_ERR(t)) {
1376 ret = t ? PTR_ERR(t) : -ENOENT;
1381 private = t->private;
1382 if (private->number != num_counters) {
1384 goto unlock_up_free;
1388 /* Choose the copy that is on our node */
1389 curcpu = smp_processor_id();
1390 loc_cpu_entry = private->entries[curcpu];
1391 xt_info_wrlock(curcpu);
1392 IPT_ENTRY_ITERATE(loc_cpu_entry,
1394 add_counter_to_entry,
1397 xt_info_wrunlock(curcpu);
1408 #ifdef CONFIG_COMPAT
1409 struct compat_ipt_replace {
1410 char name[IPT_TABLE_MAXNAMELEN];
1414 u32 hook_entry[NF_INET_NUMHOOKS];
1415 u32 underflow[NF_INET_NUMHOOKS];
1417 compat_uptr_t counters; /* struct ipt_counters * */
1418 struct compat_ipt_entry entries[0];
1422 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1423 unsigned int *size, struct xt_counters *counters,
1426 struct ipt_entry_target *t;
1427 struct compat_ipt_entry __user *ce;
1428 u_int16_t target_offset, next_offset;
1429 compat_uint_t origsize;
1434 ce = (struct compat_ipt_entry __user *)*dstptr;
1435 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1438 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1441 *dstptr += sizeof(struct compat_ipt_entry);
1442 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1444 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1445 target_offset = e->target_offset - (origsize - *size);
1448 t = ipt_get_target(e);
1449 ret = xt_compat_target_to_user(t, dstptr, size);
1453 next_offset = e->next_offset - (origsize - *size);
1454 if (put_user(target_offset, &ce->target_offset))
1456 if (put_user(next_offset, &ce->next_offset))
1466 compat_find_calc_match(struct ipt_entry_match *m,
1468 const struct ipt_ip *ip,
1469 unsigned int hookmask,
1470 int *size, unsigned int *i)
1472 struct xt_match *match;
1474 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1475 m->u.user.revision),
1476 "ipt_%s", m->u.user.name);
1477 if (IS_ERR(match) || !match) {
1478 duprintf("compat_check_calc_match: `%s' not found\n",
1480 return match ? PTR_ERR(match) : -ENOENT;
1482 m->u.kernel.match = match;
1483 *size += xt_compat_match_offset(match);
1490 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1492 if (i && (*i)-- == 0)
1495 module_put(m->u.kernel.match->me);
1500 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1502 struct ipt_entry_target *t;
1504 if (i && (*i)-- == 0)
1507 /* Cleanup all matches */
1508 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1509 t = compat_ipt_get_target(e);
1510 module_put(t->u.kernel.target->me);
1515 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1516 struct xt_table_info *newinfo,
1518 unsigned char *base,
1519 unsigned char *limit,
1520 unsigned int *hook_entries,
1521 unsigned int *underflows,
1525 struct ipt_entry_target *t;
1526 struct xt_target *target;
1527 unsigned int entry_offset;
1531 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1532 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1533 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1534 duprintf("Bad offset %p, limit = %p\n", e, limit);
1538 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1539 sizeof(struct compat_xt_entry_target)) {
1540 duprintf("checking: element %p size %u\n",
1545 /* For purposes of check_entry casting the compat entry is fine */
1546 ret = check_entry((struct ipt_entry *)e, name);
1550 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1551 entry_offset = (void *)e - (void *)base;
1553 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1554 &e->ip, e->comefrom, &off, &j);
1556 goto release_matches;
1558 t = compat_ipt_get_target(e);
1559 target = try_then_request_module(xt_find_target(AF_INET,
1561 t->u.user.revision),
1562 "ipt_%s", t->u.user.name);
1563 if (IS_ERR(target) || !target) {
1564 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1566 ret = target ? PTR_ERR(target) : -ENOENT;
1567 goto release_matches;
1569 t->u.kernel.target = target;
1571 off += xt_compat_target_offset(target);
1573 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1577 /* Check hooks & underflows */
1578 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1579 if ((unsigned char *)e - base == hook_entries[h])
1580 newinfo->hook_entry[h] = hook_entries[h];
1581 if ((unsigned char *)e - base == underflows[h])
1582 newinfo->underflow[h] = underflows[h];
1585 /* Clear counters and comefrom */
1586 memset(&e->counters, 0, sizeof(e->counters));
1593 module_put(t->u.kernel.target->me);
1595 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1600 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1601 unsigned int *size, const char *name,
1602 struct xt_table_info *newinfo, unsigned char *base)
1604 struct ipt_entry_target *t;
1605 struct xt_target *target;
1606 struct ipt_entry *de;
1607 unsigned int origsize;
1612 de = (struct ipt_entry *)*dstptr;
1613 memcpy(de, e, sizeof(struct ipt_entry));
1614 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1616 *dstptr += sizeof(struct ipt_entry);
1617 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1619 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1623 de->target_offset = e->target_offset - (origsize - *size);
1624 t = compat_ipt_get_target(e);
1625 target = t->u.kernel.target;
1626 xt_compat_target_from_user(t, dstptr, size);
1628 de->next_offset = e->next_offset - (origsize - *size);
1629 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1630 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1631 newinfo->hook_entry[h] -= origsize - *size;
1632 if ((unsigned char *)de - base < newinfo->underflow[h])
1633 newinfo->underflow[h] -= origsize - *size;
1639 compat_check_entry(struct ipt_entry *e, const char *name,
1642 struct xt_mtchk_param mtpar;
1648 mtpar.entryinfo = &e->ip;
1649 mtpar.hook_mask = e->comefrom;
1650 mtpar.family = NFPROTO_IPV4;
1651 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1653 goto cleanup_matches;
1655 ret = check_target(e, name);
1657 goto cleanup_matches;
1663 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1668 translate_compat_table(const char *name,
1669 unsigned int valid_hooks,
1670 struct xt_table_info **pinfo,
1672 unsigned int total_size,
1673 unsigned int number,
1674 unsigned int *hook_entries,
1675 unsigned int *underflows)
1678 struct xt_table_info *newinfo, *info;
1679 void *pos, *entry0, *entry1;
1686 info->number = number;
1688 /* Init all hooks to impossible value. */
1689 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1690 info->hook_entry[i] = 0xFFFFFFFF;
1691 info->underflow[i] = 0xFFFFFFFF;
1694 duprintf("translate_compat_table: size %u\n", info->size);
1696 xt_compat_lock(AF_INET);
1697 /* Walk through entries, checking offsets. */
1698 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1699 check_compat_entry_size_and_hooks,
1700 info, &size, entry0,
1701 entry0 + total_size,
1702 hook_entries, underflows, &j, name);
1708 duprintf("translate_compat_table: %u not %u entries\n",
1713 /* Check hooks all assigned */
1714 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1715 /* Only hooks which are valid */
1716 if (!(valid_hooks & (1 << i)))
1718 if (info->hook_entry[i] == 0xFFFFFFFF) {
1719 duprintf("Invalid hook entry %u %u\n",
1720 i, hook_entries[i]);
1723 if (info->underflow[i] == 0xFFFFFFFF) {
1724 duprintf("Invalid underflow %u %u\n",
1731 newinfo = xt_alloc_table_info(size);
1735 newinfo->number = number;
1736 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1737 newinfo->hook_entry[i] = info->hook_entry[i];
1738 newinfo->underflow[i] = info->underflow[i];
1740 entry1 = newinfo->entries[raw_smp_processor_id()];
1743 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1744 compat_copy_entry_from_user,
1745 &pos, &size, name, newinfo, entry1);
1746 xt_compat_flush_offsets(AF_INET);
1747 xt_compat_unlock(AF_INET);
1752 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1756 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1760 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1761 compat_release_entry, &j);
1762 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1763 xt_free_table_info(newinfo);
1767 /* And one copy for every other CPU */
1768 for_each_possible_cpu(i)
1769 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1770 memcpy(newinfo->entries[i], entry1, newinfo->size);
1774 xt_free_table_info(info);
1778 xt_free_table_info(newinfo);
1780 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1783 xt_compat_flush_offsets(AF_INET);
1784 xt_compat_unlock(AF_INET);
1789 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1792 struct compat_ipt_replace tmp;
1793 struct xt_table_info *newinfo;
1794 void *loc_cpu_entry;
1796 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1799 /* overflow check */
1800 if (tmp.size >= INT_MAX / num_possible_cpus())
1802 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1805 newinfo = xt_alloc_table_info(tmp.size);
1809 /* choose the copy that is on our node/cpu */
1810 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1811 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1817 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1818 &newinfo, &loc_cpu_entry, tmp.size,
1819 tmp.num_entries, tmp.hook_entry,
1824 duprintf("compat_do_replace: Translated table\n");
1826 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1827 tmp.num_counters, compat_ptr(tmp.counters));
1829 goto free_newinfo_untrans;
1832 free_newinfo_untrans:
1833 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1835 xt_free_table_info(newinfo);
1840 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1845 if (!capable(CAP_NET_ADMIN))
1849 case IPT_SO_SET_REPLACE:
1850 ret = compat_do_replace(sock_net(sk), user, len);
1853 case IPT_SO_SET_ADD_COUNTERS:
1854 ret = do_add_counters(sock_net(sk), user, len, 1);
1858 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1865 struct compat_ipt_get_entries {
1866 char name[IPT_TABLE_MAXNAMELEN];
1868 struct compat_ipt_entry entrytable[0];
1872 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1873 void __user *userptr)
1875 struct xt_counters *counters;
1876 const struct xt_table_info *private = table->private;
1880 const void *loc_cpu_entry;
1883 counters = alloc_counters(table);
1884 if (IS_ERR(counters))
1885 return PTR_ERR(counters);
1887 /* choose the copy that is on our node/cpu, ...
1888 * This choice is lazy (because current thread is
1889 * allowed to migrate to another cpu)
1891 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1894 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1895 compat_copy_entry_to_user,
1896 &pos, &size, counters, &i);
1903 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1907 struct compat_ipt_get_entries get;
1910 if (*len < sizeof(get)) {
1911 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1915 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1918 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1919 duprintf("compat_get_entries: %u != %zu\n",
1920 *len, sizeof(get) + get.size);
1924 xt_compat_lock(AF_INET);
1925 t = xt_find_table_lock(net, AF_INET, get.name);
1926 if (t && !IS_ERR(t)) {
1927 const struct xt_table_info *private = t->private;
1928 struct xt_table_info info;
1929 duprintf("t->private->number = %u\n", private->number);
1930 ret = compat_table_info(private, &info);
1931 if (!ret && get.size == info.size) {
1932 ret = compat_copy_entries_to_user(private->size,
1933 t, uptr->entrytable);
1935 duprintf("compat_get_entries: I've got %u not %u!\n",
1936 private->size, get.size);
1939 xt_compat_flush_offsets(AF_INET);
1943 ret = t ? PTR_ERR(t) : -ENOENT;
1945 xt_compat_unlock(AF_INET);
1949 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1952 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1956 if (!capable(CAP_NET_ADMIN))
1960 case IPT_SO_GET_INFO:
1961 ret = get_info(sock_net(sk), user, len, 1);
1963 case IPT_SO_GET_ENTRIES:
1964 ret = compat_get_entries(sock_net(sk), user, len);
1967 ret = do_ipt_get_ctl(sk, cmd, user, len);
1974 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1978 if (!capable(CAP_NET_ADMIN))
1982 case IPT_SO_SET_REPLACE:
1983 ret = do_replace(sock_net(sk), user, len);
1986 case IPT_SO_SET_ADD_COUNTERS:
1987 ret = do_add_counters(sock_net(sk), user, len, 0);
1991 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1999 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2003 if (!capable(CAP_NET_ADMIN))
2007 case IPT_SO_GET_INFO:
2008 ret = get_info(sock_net(sk), user, len, 0);
2011 case IPT_SO_GET_ENTRIES:
2012 ret = get_entries(sock_net(sk), user, len);
2015 case IPT_SO_GET_REVISION_MATCH:
2016 case IPT_SO_GET_REVISION_TARGET: {
2017 struct ipt_get_revision rev;
2020 if (*len != sizeof(rev)) {
2024 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2029 if (cmd == IPT_SO_GET_REVISION_TARGET)
2034 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2037 "ipt_%s", rev.name);
2042 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2049 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2050 const struct ipt_replace *repl)
2053 struct xt_table_info *newinfo;
2054 struct xt_table_info bootstrap
2055 = { 0, 0, 0, { 0 }, { 0 }, { } };
2056 void *loc_cpu_entry;
2057 struct xt_table *new_table;
2059 newinfo = xt_alloc_table_info(repl->size);
2065 /* choose the copy on our node/cpu, but dont care about preemption */
2066 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2067 memcpy(loc_cpu_entry, repl->entries, repl->size);
2069 ret = translate_table(table->name, table->valid_hooks,
2070 newinfo, loc_cpu_entry, repl->size,
2077 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2078 if (IS_ERR(new_table)) {
2079 ret = PTR_ERR(new_table);
2086 xt_free_table_info(newinfo);
2088 return ERR_PTR(ret);
2091 void ipt_unregister_table(struct xt_table *table)
2093 struct xt_table_info *private;
2094 void *loc_cpu_entry;
2095 struct module *table_owner = table->me;
2097 private = xt_unregister_table(table);
2099 /* Decrease module usage counts and free resources */
2100 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2101 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2102 if (private->number > private->initial_entries)
2103 module_put(table_owner);
2104 xt_free_table_info(private);
2107 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2109 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2110 u_int8_t type, u_int8_t code,
2113 return ((test_type == 0xFF) ||
2114 (type == test_type && code >= min_code && code <= max_code))
2119 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2121 const struct icmphdr *ic;
2122 struct icmphdr _icmph;
2123 const struct ipt_icmp *icmpinfo = par->matchinfo;
2125 /* Must not be a fragment. */
2126 if (par->fragoff != 0)
2129 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2131 /* We've been asked to examine this packet, and we
2132 * can't. Hence, no choice but to drop.
2134 duprintf("Dropping evil ICMP tinygram.\n");
2135 *par->hotdrop = true;
2139 return icmp_type_code_match(icmpinfo->type,
2143 !!(icmpinfo->invflags&IPT_ICMP_INV));
2146 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2148 const struct ipt_icmp *icmpinfo = par->matchinfo;
2150 /* Must specify no unknown invflags */
2151 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2154 /* The built-in targets: standard (NULL) and error. */
2155 static struct xt_target ipt_standard_target __read_mostly = {
2156 .name = IPT_STANDARD_TARGET,
2157 .targetsize = sizeof(int),
2158 .family = NFPROTO_IPV4,
2159 #ifdef CONFIG_COMPAT
2160 .compatsize = sizeof(compat_int_t),
2161 .compat_from_user = compat_standard_from_user,
2162 .compat_to_user = compat_standard_to_user,
2166 static struct xt_target ipt_error_target __read_mostly = {
2167 .name = IPT_ERROR_TARGET,
2168 .target = ipt_error,
2169 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2170 .family = NFPROTO_IPV4,
2173 static struct nf_sockopt_ops ipt_sockopts = {
2175 .set_optmin = IPT_BASE_CTL,
2176 .set_optmax = IPT_SO_SET_MAX+1,
2177 .set = do_ipt_set_ctl,
2178 #ifdef CONFIG_COMPAT
2179 .compat_set = compat_do_ipt_set_ctl,
2181 .get_optmin = IPT_BASE_CTL,
2182 .get_optmax = IPT_SO_GET_MAX+1,
2183 .get = do_ipt_get_ctl,
2184 #ifdef CONFIG_COMPAT
2185 .compat_get = compat_do_ipt_get_ctl,
2187 .owner = THIS_MODULE,
2190 static struct xt_match icmp_matchstruct __read_mostly = {
2192 .match = icmp_match,
2193 .matchsize = sizeof(struct ipt_icmp),
2194 .checkentry = icmp_checkentry,
2195 .proto = IPPROTO_ICMP,
2196 .family = NFPROTO_IPV4,
2199 static int __net_init ip_tables_net_init(struct net *net)
2201 return xt_proto_init(net, NFPROTO_IPV4);
2204 static void __net_exit ip_tables_net_exit(struct net *net)
2206 xt_proto_fini(net, NFPROTO_IPV4);
2209 static struct pernet_operations ip_tables_net_ops = {
2210 .init = ip_tables_net_init,
2211 .exit = ip_tables_net_exit,
2214 static int __init ip_tables_init(void)
2218 ret = register_pernet_subsys(&ip_tables_net_ops);
2222 /* Noone else will be downing sem now, so we won't sleep */
2223 ret = xt_register_target(&ipt_standard_target);
2226 ret = xt_register_target(&ipt_error_target);
2229 ret = xt_register_match(&icmp_matchstruct);
2233 /* Register setsockopt */
2234 ret = nf_register_sockopt(&ipt_sockopts);
2238 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2242 xt_unregister_match(&icmp_matchstruct);
2244 xt_unregister_target(&ipt_error_target);
2246 xt_unregister_target(&ipt_standard_target);
2248 unregister_pernet_subsys(&ip_tables_net_ops);
2253 static void __exit ip_tables_fini(void)
2255 nf_unregister_sockopt(&ipt_sockopts);
2257 xt_unregister_match(&icmp_matchstruct);
2258 xt_unregister_target(&ipt_error_target);
2259 xt_unregister_target(&ipt_standard_target);
2261 unregister_pernet_subsys(&ip_tables_net_ops);
2264 EXPORT_SYMBOL(ipt_register_table);
2265 EXPORT_SYMBOL(ipt_unregister_table);
2266 EXPORT_SYMBOL(ipt_do_table);
2267 module_init(ip_tables_init);
2268 module_exit(ip_tables_fini);