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) */
193 static inline bool unconditional(const struct ipt_ip *ip)
195 static const struct ipt_ip uncond;
197 return memcmp(ip, &uncond, sizeof(uncond)) == 0;
201 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
202 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
203 static const char *const hooknames[] = {
204 [NF_INET_PRE_ROUTING] = "PREROUTING",
205 [NF_INET_LOCAL_IN] = "INPUT",
206 [NF_INET_FORWARD] = "FORWARD",
207 [NF_INET_LOCAL_OUT] = "OUTPUT",
208 [NF_INET_POST_ROUTING] = "POSTROUTING",
211 enum nf_ip_trace_comments {
212 NF_IP_TRACE_COMMENT_RULE,
213 NF_IP_TRACE_COMMENT_RETURN,
214 NF_IP_TRACE_COMMENT_POLICY,
217 static const char *const comments[] = {
218 [NF_IP_TRACE_COMMENT_RULE] = "rule",
219 [NF_IP_TRACE_COMMENT_RETURN] = "return",
220 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
223 static struct nf_loginfo trace_loginfo = {
224 .type = NF_LOG_TYPE_LOG,
228 .logflags = NF_LOG_MASK,
233 /* Mildly perf critical (only if packet tracing is on) */
235 get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
236 const char *hookname, const char **chainname,
237 const char **comment, unsigned int *rulenum)
239 struct ipt_standard_target *t = (void *)ipt_get_target(s);
241 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
242 /* Head of user chain: ERROR target with chainname */
243 *chainname = t->target.data;
248 if (s->target_offset == sizeof(struct ipt_entry)
249 && strcmp(t->target.u.kernel.target->name,
250 IPT_STANDARD_TARGET) == 0
252 && unconditional(&s->ip)) {
253 /* Tail of chains: STANDARD target (return/policy) */
254 *comment = *chainname == hookname
255 ? comments[NF_IP_TRACE_COMMENT_POLICY]
256 : comments[NF_IP_TRACE_COMMENT_RETURN];
265 static void trace_packet(struct sk_buff *skb,
267 const struct net_device *in,
268 const struct net_device *out,
269 const char *tablename,
270 struct xt_table_info *private,
274 const struct ipt_entry *root;
275 const char *hookname, *chainname, *comment;
276 unsigned int rulenum = 0;
278 table_base = private->entries[smp_processor_id()];
279 root = get_entry(table_base, private->hook_entry[hook]);
281 hookname = chainname = hooknames[hook];
282 comment = comments[NF_IP_TRACE_COMMENT_RULE];
284 IPT_ENTRY_ITERATE(root,
285 private->size - private->hook_entry[hook],
286 get_chainname_rulenum,
287 e, hookname, &chainname, &comment, &rulenum);
289 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
290 "TRACE: %s:%s:%s:%u ",
291 tablename, chainname, comment, rulenum);
296 struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
298 return (void *)entry + entry->next_offset;
301 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
303 ipt_do_table(struct sk_buff *skb,
305 const struct net_device *in,
306 const struct net_device *out,
307 struct xt_table *table)
309 #define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
311 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
312 const struct iphdr *ip;
313 bool hotdrop = false;
314 /* Initializing verdict to NF_DROP keeps gcc happy. */
315 unsigned int verdict = NF_DROP;
316 const char *indev, *outdev;
318 struct ipt_entry *e, *back;
319 struct xt_table_info *private;
320 struct xt_match_param mtpar;
321 struct xt_target_param tgpar;
325 indev = in ? in->name : nulldevname;
326 outdev = out ? out->name : nulldevname;
327 /* We handle fragments by dealing with the first fragment as
328 * if it was a normal packet. All other fragments are treated
329 * normally, except that they will NEVER match rules that ask
330 * things we don't know, ie. tcp syn flag or ports). If the
331 * rule is also a fragment-specific rule, non-fragments won't
333 mtpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
334 mtpar.thoff = ip_hdrlen(skb);
335 mtpar.hotdrop = &hotdrop;
336 mtpar.in = tgpar.in = in;
337 mtpar.out = tgpar.out = out;
338 mtpar.family = tgpar.family = NFPROTO_IPV4;
339 mtpar.hooknum = tgpar.hooknum = hook;
341 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
343 private = table->private;
344 table_base = private->entries[smp_processor_id()];
346 e = get_entry(table_base, private->hook_entry[hook]);
348 /* For return from builtin chain */
349 back = get_entry(table_base, private->underflow[hook]);
352 struct ipt_entry_target *t;
356 if (!ip_packet_match(ip, indev, outdev,
357 &e->ip, mtpar.fragoff) ||
358 IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {
359 e = ipt_next_entry(e);
363 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
365 t = ipt_get_target(e);
366 IP_NF_ASSERT(t->u.kernel.target);
368 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
369 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
370 /* The packet is traced: log it */
371 if (unlikely(skb->nf_trace))
372 trace_packet(skb, hook, in, out,
373 table->name, private, e);
375 /* Standard target? */
376 if (!t->u.kernel.target->target) {
379 v = ((struct ipt_standard_target *)t)->verdict;
381 /* Pop from stack? */
382 if (v != IPT_RETURN) {
383 verdict = (unsigned)(-v) - 1;
387 back = get_entry(table_base, back->comefrom);
390 if (table_base + v != ipt_next_entry(e)
391 && !(e->ip.flags & IPT_F_GOTO)) {
392 /* Save old back ptr in next entry */
393 struct ipt_entry *next = ipt_next_entry(e);
394 next->comefrom = (void *)back - table_base;
395 /* set back pointer to next entry */
399 e = get_entry(table_base, v);
403 /* Targets which reenter must return
405 tgpar.target = t->u.kernel.target;
406 tgpar.targinfo = t->data;
409 #ifdef CONFIG_NETFILTER_DEBUG
410 tb_comefrom = 0xeeeeeeec;
412 verdict = t->u.kernel.target->target(skb, &tgpar);
413 #ifdef CONFIG_NETFILTER_DEBUG
414 if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
415 printk("Target %s reentered!\n",
416 t->u.kernel.target->name);
419 tb_comefrom = 0x57acc001;
421 /* Target might have changed stuff. */
423 if (verdict == IPT_CONTINUE)
424 e = ipt_next_entry(e);
429 xt_info_rdunlock_bh();
431 #ifdef DEBUG_ALLOW_ALL
442 /* Figures out from what hook each rule can be called: returns 0 if
443 there are loops. Puts hook bitmask in comefrom. */
445 mark_source_chains(struct xt_table_info *newinfo,
446 unsigned int valid_hooks, void *entry0)
450 /* No recursion; use packet counter to save back ptrs (reset
451 to 0 as we leave), and comefrom to save source hook bitmask */
452 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
453 unsigned int pos = newinfo->hook_entry[hook];
454 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
456 if (!(valid_hooks & (1 << hook)))
459 /* Set initial back pointer. */
460 e->counters.pcnt = pos;
463 struct ipt_standard_target *t
464 = (void *)ipt_get_target(e);
465 int visited = e->comefrom & (1 << hook);
467 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
468 printk("iptables: loop hook %u pos %u %08X.\n",
469 hook, pos, e->comefrom);
472 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
474 /* Unconditional return/END. */
475 if ((e->target_offset == sizeof(struct ipt_entry)
476 && (strcmp(t->target.u.user.name,
477 IPT_STANDARD_TARGET) == 0)
479 && unconditional(&e->ip)) || visited) {
480 unsigned int oldpos, size;
482 if ((strcmp(t->target.u.user.name,
483 IPT_STANDARD_TARGET) == 0) &&
484 t->verdict < -NF_MAX_VERDICT - 1) {
485 duprintf("mark_source_chains: bad "
486 "negative verdict (%i)\n",
491 /* Return: backtrack through the last
494 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
495 #ifdef DEBUG_IP_FIREWALL_USER
497 & (1 << NF_INET_NUMHOOKS)) {
498 duprintf("Back unset "
505 pos = e->counters.pcnt;
506 e->counters.pcnt = 0;
508 /* We're at the start. */
512 e = (struct ipt_entry *)
514 } while (oldpos == pos + e->next_offset);
517 size = e->next_offset;
518 e = (struct ipt_entry *)
519 (entry0 + pos + size);
520 e->counters.pcnt = pos;
523 int newpos = t->verdict;
525 if (strcmp(t->target.u.user.name,
526 IPT_STANDARD_TARGET) == 0
528 if (newpos > newinfo->size -
529 sizeof(struct ipt_entry)) {
530 duprintf("mark_source_chains: "
531 "bad verdict (%i)\n",
535 /* This a jump; chase it. */
536 duprintf("Jump rule %u -> %u\n",
539 /* ... this is a fallthru */
540 newpos = pos + e->next_offset;
542 e = (struct ipt_entry *)
544 e->counters.pcnt = pos;
549 duprintf("Finished chain %u\n", hook);
555 cleanup_match(struct ipt_entry_match *m, unsigned int *i)
557 struct xt_mtdtor_param par;
559 if (i && (*i)-- == 0)
562 par.match = m->u.kernel.match;
563 par.matchinfo = m->data;
564 par.family = NFPROTO_IPV4;
565 if (par.match->destroy != NULL)
566 par.match->destroy(&par);
567 module_put(par.match->me);
572 check_entry(struct ipt_entry *e, const char *name)
574 struct ipt_entry_target *t;
576 if (!ip_checkentry(&e->ip)) {
577 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
581 if (e->target_offset + sizeof(struct ipt_entry_target) >
585 t = ipt_get_target(e);
586 if (e->target_offset + t->u.target_size > e->next_offset)
593 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
596 const struct ipt_ip *ip = par->entryinfo;
599 par->match = m->u.kernel.match;
600 par->matchinfo = m->data;
602 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
603 ip->proto, ip->invflags & IPT_INV_PROTO);
605 duprintf("ip_tables: check failed for `%s'.\n",
614 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
617 struct xt_match *match;
620 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
622 "ipt_%s", m->u.user.name);
623 if (IS_ERR(match) || !match) {
624 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
625 return match ? PTR_ERR(match) : -ENOENT;
627 m->u.kernel.match = match;
629 ret = check_match(m, par, i);
635 module_put(m->u.kernel.match->me);
639 static int check_target(struct ipt_entry *e, const char *name)
641 struct ipt_entry_target *t = ipt_get_target(e);
642 struct xt_tgchk_param par = {
645 .target = t->u.kernel.target,
647 .hook_mask = e->comefrom,
648 .family = NFPROTO_IPV4,
652 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
653 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
655 duprintf("ip_tables: check failed for `%s'.\n",
656 t->u.kernel.target->name);
663 find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
666 struct ipt_entry_target *t;
667 struct xt_target *target;
670 struct xt_mtchk_param mtpar;
672 ret = check_entry(e, name);
678 mtpar.entryinfo = &e->ip;
679 mtpar.hook_mask = e->comefrom;
680 mtpar.family = NFPROTO_IPV4;
681 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
683 goto cleanup_matches;
685 t = ipt_get_target(e);
686 target = try_then_request_module(xt_find_target(AF_INET,
689 "ipt_%s", t->u.user.name);
690 if (IS_ERR(target) || !target) {
691 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
692 ret = target ? PTR_ERR(target) : -ENOENT;
693 goto cleanup_matches;
695 t->u.kernel.target = target;
697 ret = check_target(e, name);
704 module_put(t->u.kernel.target->me);
706 IPT_MATCH_ITERATE(e, cleanup_match, &j);
711 check_entry_size_and_hooks(struct ipt_entry *e,
712 struct xt_table_info *newinfo,
714 unsigned char *limit,
715 const unsigned int *hook_entries,
716 const unsigned int *underflows,
721 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
722 || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
723 duprintf("Bad offset %p\n", e);
728 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
729 duprintf("checking: element %p size %u\n",
734 /* Check hooks & underflows */
735 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
736 if ((unsigned char *)e - base == hook_entries[h])
737 newinfo->hook_entry[h] = hook_entries[h];
738 if ((unsigned char *)e - base == underflows[h])
739 newinfo->underflow[h] = underflows[h];
742 /* FIXME: underflows must be unconditional, standard verdicts
743 < 0 (not IPT_RETURN). --RR */
745 /* Clear counters and comefrom */
746 e->counters = ((struct xt_counters) { 0, 0 });
754 cleanup_entry(struct ipt_entry *e, unsigned int *i)
756 struct xt_tgdtor_param par;
757 struct ipt_entry_target *t;
759 if (i && (*i)-- == 0)
762 /* Cleanup all matches */
763 IPT_MATCH_ITERATE(e, cleanup_match, NULL);
764 t = ipt_get_target(e);
766 par.target = t->u.kernel.target;
767 par.targinfo = t->data;
768 par.family = NFPROTO_IPV4;
769 if (par.target->destroy != NULL)
770 par.target->destroy(&par);
771 module_put(par.target->me);
775 /* Checks and translates the user-supplied table segment (held in
778 translate_table(const char *name,
779 unsigned int valid_hooks,
780 struct xt_table_info *newinfo,
784 const unsigned int *hook_entries,
785 const unsigned int *underflows)
790 newinfo->size = size;
791 newinfo->number = number;
793 /* Init all hooks to impossible value. */
794 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
795 newinfo->hook_entry[i] = 0xFFFFFFFF;
796 newinfo->underflow[i] = 0xFFFFFFFF;
799 duprintf("translate_table: size %u\n", newinfo->size);
801 /* Walk through entries, checking offsets. */
802 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
803 check_entry_size_and_hooks,
807 hook_entries, underflows, &i);
812 duprintf("translate_table: %u not %u entries\n",
817 /* Check hooks all assigned */
818 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
819 /* Only hooks which are valid */
820 if (!(valid_hooks & (1 << i)))
822 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
823 duprintf("Invalid hook entry %u %u\n",
827 if (newinfo->underflow[i] == 0xFFFFFFFF) {
828 duprintf("Invalid underflow %u %u\n",
834 if (!mark_source_chains(newinfo, valid_hooks, entry0))
837 /* Finally, each sanity check must pass */
839 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
840 find_check_entry, name, size, &i);
843 IPT_ENTRY_ITERATE(entry0, newinfo->size,
848 /* And one copy for every other CPU */
849 for_each_possible_cpu(i) {
850 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
851 memcpy(newinfo->entries[i], entry0, newinfo->size);
859 add_entry_to_counter(const struct ipt_entry *e,
860 struct xt_counters total[],
863 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
870 set_entry_to_counter(const struct ipt_entry *e,
871 struct ipt_counters total[],
874 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
881 get_counters(const struct xt_table_info *t,
882 struct xt_counters counters[])
888 /* Instead of clearing (by a previous call to memset())
889 * the counters and using adds, we set the counters
890 * with data used by 'current' CPU.
892 * Bottom half has to be disabled to prevent deadlock
893 * if new softirq were to run and call ipt_do_table
896 curcpu = smp_processor_id();
899 IPT_ENTRY_ITERATE(t->entries[curcpu],
901 set_entry_to_counter,
905 for_each_possible_cpu(cpu) {
910 IPT_ENTRY_ITERATE(t->entries[cpu],
912 add_entry_to_counter,
915 xt_info_wrunlock(cpu);
920 static struct xt_counters * alloc_counters(struct xt_table *table)
922 unsigned int countersize;
923 struct xt_counters *counters;
924 struct xt_table_info *private = table->private;
926 /* We need atomic snapshot of counters: rest doesn't change
927 (other than comefrom, which userspace doesn't care
929 countersize = sizeof(struct xt_counters) * private->number;
930 counters = vmalloc_node(countersize, numa_node_id());
932 if (counters == NULL)
933 return ERR_PTR(-ENOMEM);
935 get_counters(private, counters);
941 copy_entries_to_user(unsigned int total_size,
942 struct xt_table *table,
943 void __user *userptr)
945 unsigned int off, num;
947 struct xt_counters *counters;
948 const struct xt_table_info *private = table->private;
950 const void *loc_cpu_entry;
952 counters = alloc_counters(table);
953 if (IS_ERR(counters))
954 return PTR_ERR(counters);
956 /* choose the copy that is on our node/cpu, ...
957 * This choice is lazy (because current thread is
958 * allowed to migrate to another cpu)
960 loc_cpu_entry = private->entries[raw_smp_processor_id()];
961 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
966 /* FIXME: use iterator macros --RR */
967 /* ... then go back and fix counters and names */
968 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
970 const struct ipt_entry_match *m;
971 const struct ipt_entry_target *t;
973 e = (struct ipt_entry *)(loc_cpu_entry + off);
974 if (copy_to_user(userptr + off
975 + offsetof(struct ipt_entry, counters),
977 sizeof(counters[num])) != 0) {
982 for (i = sizeof(struct ipt_entry);
983 i < e->target_offset;
984 i += m->u.match_size) {
987 if (copy_to_user(userptr + off + i
988 + offsetof(struct ipt_entry_match,
990 m->u.kernel.match->name,
991 strlen(m->u.kernel.match->name)+1)
998 t = ipt_get_target(e);
999 if (copy_to_user(userptr + off + e->target_offset
1000 + offsetof(struct ipt_entry_target,
1002 t->u.kernel.target->name,
1003 strlen(t->u.kernel.target->name)+1) != 0) {
1014 #ifdef CONFIG_COMPAT
1015 static void compat_standard_from_user(void *dst, void *src)
1017 int v = *(compat_int_t *)src;
1020 v += xt_compat_calc_jump(AF_INET, v);
1021 memcpy(dst, &v, sizeof(v));
1024 static int compat_standard_to_user(void __user *dst, void *src)
1026 compat_int_t cv = *(int *)src;
1029 cv -= xt_compat_calc_jump(AF_INET, cv);
1030 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1034 compat_calc_match(struct ipt_entry_match *m, int *size)
1036 *size += xt_compat_match_offset(m->u.kernel.match);
1040 static int compat_calc_entry(struct ipt_entry *e,
1041 const struct xt_table_info *info,
1042 void *base, struct xt_table_info *newinfo)
1044 struct ipt_entry_target *t;
1045 unsigned int entry_offset;
1048 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1049 entry_offset = (void *)e - base;
1050 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1051 t = ipt_get_target(e);
1052 off += xt_compat_target_offset(t->u.kernel.target);
1053 newinfo->size -= off;
1054 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1058 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1059 if (info->hook_entry[i] &&
1060 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1061 newinfo->hook_entry[i] -= off;
1062 if (info->underflow[i] &&
1063 (e < (struct ipt_entry *)(base + info->underflow[i])))
1064 newinfo->underflow[i] -= off;
1069 static int compat_table_info(const struct xt_table_info *info,
1070 struct xt_table_info *newinfo)
1072 void *loc_cpu_entry;
1074 if (!newinfo || !info)
1077 /* we dont care about newinfo->entries[] */
1078 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1079 newinfo->initial_entries = 0;
1080 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1081 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
1082 compat_calc_entry, info, loc_cpu_entry,
1087 static int get_info(struct net *net, void __user *user, int *len, int compat)
1089 char name[IPT_TABLE_MAXNAMELEN];
1093 if (*len != sizeof(struct ipt_getinfo)) {
1094 duprintf("length %u != %zu\n", *len,
1095 sizeof(struct ipt_getinfo));
1099 if (copy_from_user(name, user, sizeof(name)) != 0)
1102 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1103 #ifdef CONFIG_COMPAT
1105 xt_compat_lock(AF_INET);
1107 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1108 "iptable_%s", name);
1109 if (t && !IS_ERR(t)) {
1110 struct ipt_getinfo info;
1111 const struct xt_table_info *private = t->private;
1113 #ifdef CONFIG_COMPAT
1115 struct xt_table_info tmp;
1116 ret = compat_table_info(private, &tmp);
1117 xt_compat_flush_offsets(AF_INET);
1121 info.valid_hooks = t->valid_hooks;
1122 memcpy(info.hook_entry, private->hook_entry,
1123 sizeof(info.hook_entry));
1124 memcpy(info.underflow, private->underflow,
1125 sizeof(info.underflow));
1126 info.num_entries = private->number;
1127 info.size = private->size;
1128 strcpy(info.name, name);
1130 if (copy_to_user(user, &info, *len) != 0)
1138 ret = t ? PTR_ERR(t) : -ENOENT;
1139 #ifdef CONFIG_COMPAT
1141 xt_compat_unlock(AF_INET);
1147 get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1150 struct ipt_get_entries get;
1153 if (*len < sizeof(get)) {
1154 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1157 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1159 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1160 duprintf("get_entries: %u != %zu\n",
1161 *len, sizeof(get) + get.size);
1165 t = xt_find_table_lock(net, AF_INET, get.name);
1166 if (t && !IS_ERR(t)) {
1167 const struct xt_table_info *private = t->private;
1168 duprintf("t->private->number = %u\n", private->number);
1169 if (get.size == private->size)
1170 ret = copy_entries_to_user(private->size,
1171 t, uptr->entrytable);
1173 duprintf("get_entries: I've got %u not %u!\n",
1174 private->size, get.size);
1180 ret = t ? PTR_ERR(t) : -ENOENT;
1186 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1187 struct xt_table_info *newinfo, unsigned int num_counters,
1188 void __user *counters_ptr)
1192 struct xt_table_info *oldinfo;
1193 struct xt_counters *counters;
1194 void *loc_cpu_old_entry;
1197 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1203 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1204 "iptable_%s", name);
1205 if (!t || IS_ERR(t)) {
1206 ret = t ? PTR_ERR(t) : -ENOENT;
1207 goto free_newinfo_counters_untrans;
1211 if (valid_hooks != t->valid_hooks) {
1212 duprintf("Valid hook crap: %08X vs %08X\n",
1213 valid_hooks, t->valid_hooks);
1218 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1222 /* Update module usage count based on number of rules */
1223 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1224 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1225 if ((oldinfo->number > oldinfo->initial_entries) ||
1226 (newinfo->number <= oldinfo->initial_entries))
1228 if ((oldinfo->number > oldinfo->initial_entries) &&
1229 (newinfo->number <= oldinfo->initial_entries))
1232 /* Get the old counters, and synchronize with replace */
1233 get_counters(oldinfo, counters);
1235 /* Decrease module usage counts and free resource */
1236 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1237 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1239 xt_free_table_info(oldinfo);
1240 if (copy_to_user(counters_ptr, counters,
1241 sizeof(struct xt_counters) * num_counters) != 0)
1250 free_newinfo_counters_untrans:
1257 do_replace(struct net *net, void __user *user, unsigned int len)
1260 struct ipt_replace tmp;
1261 struct xt_table_info *newinfo;
1262 void *loc_cpu_entry;
1264 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1267 /* overflow check */
1268 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1271 newinfo = xt_alloc_table_info(tmp.size);
1275 /* choose the copy that is on our node/cpu */
1276 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1277 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1283 ret = translate_table(tmp.name, tmp.valid_hooks,
1284 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1285 tmp.hook_entry, tmp.underflow);
1289 duprintf("ip_tables: Translated table\n");
1291 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1292 tmp.num_counters, tmp.counters);
1294 goto free_newinfo_untrans;
1297 free_newinfo_untrans:
1298 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1300 xt_free_table_info(newinfo);
1304 /* We're lazy, and add to the first CPU; overflow works its fey magic
1305 * and everything is OK. */
1307 add_counter_to_entry(struct ipt_entry *e,
1308 const struct xt_counters addme[],
1311 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1318 do_add_counters(struct net *net, void __user *user, unsigned int len, int compat)
1320 unsigned int i, curcpu;
1321 struct xt_counters_info tmp;
1322 struct xt_counters *paddc;
1323 unsigned int num_counters;
1328 const struct xt_table_info *private;
1330 void *loc_cpu_entry;
1331 #ifdef CONFIG_COMPAT
1332 struct compat_xt_counters_info compat_tmp;
1336 size = sizeof(struct compat_xt_counters_info);
1341 size = sizeof(struct xt_counters_info);
1344 if (copy_from_user(ptmp, user, size) != 0)
1347 #ifdef CONFIG_COMPAT
1349 num_counters = compat_tmp.num_counters;
1350 name = compat_tmp.name;
1354 num_counters = tmp.num_counters;
1358 if (len != size + num_counters * sizeof(struct xt_counters))
1361 paddc = vmalloc_node(len - size, numa_node_id());
1365 if (copy_from_user(paddc, user + size, len - size) != 0) {
1370 t = xt_find_table_lock(net, AF_INET, name);
1371 if (!t || IS_ERR(t)) {
1372 ret = t ? PTR_ERR(t) : -ENOENT;
1377 private = t->private;
1378 if (private->number != num_counters) {
1380 goto unlock_up_free;
1384 /* Choose the copy that is on our node */
1385 curcpu = smp_processor_id();
1386 loc_cpu_entry = private->entries[curcpu];
1387 xt_info_wrlock(curcpu);
1388 IPT_ENTRY_ITERATE(loc_cpu_entry,
1390 add_counter_to_entry,
1393 xt_info_wrunlock(curcpu);
1404 #ifdef CONFIG_COMPAT
1405 struct compat_ipt_replace {
1406 char name[IPT_TABLE_MAXNAMELEN];
1410 u32 hook_entry[NF_INET_NUMHOOKS];
1411 u32 underflow[NF_INET_NUMHOOKS];
1413 compat_uptr_t counters; /* struct ipt_counters * */
1414 struct compat_ipt_entry entries[0];
1418 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1419 unsigned int *size, struct xt_counters *counters,
1422 struct ipt_entry_target *t;
1423 struct compat_ipt_entry __user *ce;
1424 u_int16_t target_offset, next_offset;
1425 compat_uint_t origsize;
1430 ce = (struct compat_ipt_entry __user *)*dstptr;
1431 if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
1434 if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))
1437 *dstptr += sizeof(struct compat_ipt_entry);
1438 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1440 ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);
1441 target_offset = e->target_offset - (origsize - *size);
1444 t = ipt_get_target(e);
1445 ret = xt_compat_target_to_user(t, dstptr, size);
1449 next_offset = e->next_offset - (origsize - *size);
1450 if (put_user(target_offset, &ce->target_offset))
1452 if (put_user(next_offset, &ce->next_offset))
1462 compat_find_calc_match(struct ipt_entry_match *m,
1464 const struct ipt_ip *ip,
1465 unsigned int hookmask,
1466 int *size, unsigned int *i)
1468 struct xt_match *match;
1470 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1471 m->u.user.revision),
1472 "ipt_%s", m->u.user.name);
1473 if (IS_ERR(match) || !match) {
1474 duprintf("compat_check_calc_match: `%s' not found\n",
1476 return match ? PTR_ERR(match) : -ENOENT;
1478 m->u.kernel.match = match;
1479 *size += xt_compat_match_offset(match);
1486 compat_release_match(struct ipt_entry_match *m, unsigned int *i)
1488 if (i && (*i)-- == 0)
1491 module_put(m->u.kernel.match->me);
1496 compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)
1498 struct ipt_entry_target *t;
1500 if (i && (*i)-- == 0)
1503 /* Cleanup all matches */
1504 COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);
1505 t = compat_ipt_get_target(e);
1506 module_put(t->u.kernel.target->me);
1511 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1512 struct xt_table_info *newinfo,
1514 unsigned char *base,
1515 unsigned char *limit,
1516 unsigned int *hook_entries,
1517 unsigned int *underflows,
1521 struct ipt_entry_target *t;
1522 struct xt_target *target;
1523 unsigned int entry_offset;
1527 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1528 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
1529 || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1530 duprintf("Bad offset %p, limit = %p\n", e, limit);
1534 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1535 sizeof(struct compat_xt_entry_target)) {
1536 duprintf("checking: element %p size %u\n",
1541 /* For purposes of check_entry casting the compat entry is fine */
1542 ret = check_entry((struct ipt_entry *)e, name);
1546 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1547 entry_offset = (void *)e - (void *)base;
1549 ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,
1550 &e->ip, e->comefrom, &off, &j);
1552 goto release_matches;
1554 t = compat_ipt_get_target(e);
1555 target = try_then_request_module(xt_find_target(AF_INET,
1557 t->u.user.revision),
1558 "ipt_%s", t->u.user.name);
1559 if (IS_ERR(target) || !target) {
1560 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1562 ret = target ? PTR_ERR(target) : -ENOENT;
1563 goto release_matches;
1565 t->u.kernel.target = target;
1567 off += xt_compat_target_offset(target);
1569 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1573 /* Check hooks & underflows */
1574 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1575 if ((unsigned char *)e - base == hook_entries[h])
1576 newinfo->hook_entry[h] = hook_entries[h];
1577 if ((unsigned char *)e - base == underflows[h])
1578 newinfo->underflow[h] = underflows[h];
1581 /* Clear counters and comefrom */
1582 memset(&e->counters, 0, sizeof(e->counters));
1589 module_put(t->u.kernel.target->me);
1591 IPT_MATCH_ITERATE(e, compat_release_match, &j);
1596 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1597 unsigned int *size, const char *name,
1598 struct xt_table_info *newinfo, unsigned char *base)
1600 struct ipt_entry_target *t;
1601 struct xt_target *target;
1602 struct ipt_entry *de;
1603 unsigned int origsize;
1608 de = (struct ipt_entry *)*dstptr;
1609 memcpy(de, e, sizeof(struct ipt_entry));
1610 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1612 *dstptr += sizeof(struct ipt_entry);
1613 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1615 ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,
1619 de->target_offset = e->target_offset - (origsize - *size);
1620 t = compat_ipt_get_target(e);
1621 target = t->u.kernel.target;
1622 xt_compat_target_from_user(t, dstptr, size);
1624 de->next_offset = e->next_offset - (origsize - *size);
1625 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1626 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1627 newinfo->hook_entry[h] -= origsize - *size;
1628 if ((unsigned char *)de - base < newinfo->underflow[h])
1629 newinfo->underflow[h] -= origsize - *size;
1635 compat_check_entry(struct ipt_entry *e, const char *name,
1638 struct xt_mtchk_param mtpar;
1644 mtpar.entryinfo = &e->ip;
1645 mtpar.hook_mask = e->comefrom;
1646 mtpar.family = NFPROTO_IPV4;
1647 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
1649 goto cleanup_matches;
1651 ret = check_target(e, name);
1653 goto cleanup_matches;
1659 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1664 translate_compat_table(const char *name,
1665 unsigned int valid_hooks,
1666 struct xt_table_info **pinfo,
1668 unsigned int total_size,
1669 unsigned int number,
1670 unsigned int *hook_entries,
1671 unsigned int *underflows)
1674 struct xt_table_info *newinfo, *info;
1675 void *pos, *entry0, *entry1;
1682 info->number = number;
1684 /* Init all hooks to impossible value. */
1685 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1686 info->hook_entry[i] = 0xFFFFFFFF;
1687 info->underflow[i] = 0xFFFFFFFF;
1690 duprintf("translate_compat_table: size %u\n", info->size);
1692 xt_compat_lock(AF_INET);
1693 /* Walk through entries, checking offsets. */
1694 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1695 check_compat_entry_size_and_hooks,
1696 info, &size, entry0,
1697 entry0 + total_size,
1698 hook_entries, underflows, &j, name);
1704 duprintf("translate_compat_table: %u not %u entries\n",
1709 /* Check hooks all assigned */
1710 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1711 /* Only hooks which are valid */
1712 if (!(valid_hooks & (1 << i)))
1714 if (info->hook_entry[i] == 0xFFFFFFFF) {
1715 duprintf("Invalid hook entry %u %u\n",
1716 i, hook_entries[i]);
1719 if (info->underflow[i] == 0xFFFFFFFF) {
1720 duprintf("Invalid underflow %u %u\n",
1727 newinfo = xt_alloc_table_info(size);
1731 newinfo->number = number;
1732 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1733 newinfo->hook_entry[i] = info->hook_entry[i];
1734 newinfo->underflow[i] = info->underflow[i];
1736 entry1 = newinfo->entries[raw_smp_processor_id()];
1739 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,
1740 compat_copy_entry_from_user,
1741 &pos, &size, name, newinfo, entry1);
1742 xt_compat_flush_offsets(AF_INET);
1743 xt_compat_unlock(AF_INET);
1748 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1752 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1756 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1757 compat_release_entry, &j);
1758 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
1759 xt_free_table_info(newinfo);
1763 /* And one copy for every other CPU */
1764 for_each_possible_cpu(i)
1765 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1766 memcpy(newinfo->entries[i], entry1, newinfo->size);
1770 xt_free_table_info(info);
1774 xt_free_table_info(newinfo);
1776 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
1779 xt_compat_flush_offsets(AF_INET);
1780 xt_compat_unlock(AF_INET);
1785 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1788 struct compat_ipt_replace tmp;
1789 struct xt_table_info *newinfo;
1790 void *loc_cpu_entry;
1792 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1795 /* overflow check */
1796 if (tmp.size >= INT_MAX / num_possible_cpus())
1798 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1801 newinfo = xt_alloc_table_info(tmp.size);
1805 /* choose the copy that is on our node/cpu */
1806 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1807 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1813 ret = translate_compat_table(tmp.name, tmp.valid_hooks,
1814 &newinfo, &loc_cpu_entry, tmp.size,
1815 tmp.num_entries, tmp.hook_entry,
1820 duprintf("compat_do_replace: Translated table\n");
1822 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1823 tmp.num_counters, compat_ptr(tmp.counters));
1825 goto free_newinfo_untrans;
1828 free_newinfo_untrans:
1829 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
1831 xt_free_table_info(newinfo);
1836 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1841 if (!capable(CAP_NET_ADMIN))
1845 case IPT_SO_SET_REPLACE:
1846 ret = compat_do_replace(sock_net(sk), user, len);
1849 case IPT_SO_SET_ADD_COUNTERS:
1850 ret = do_add_counters(sock_net(sk), user, len, 1);
1854 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1861 struct compat_ipt_get_entries {
1862 char name[IPT_TABLE_MAXNAMELEN];
1864 struct compat_ipt_entry entrytable[0];
1868 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1869 void __user *userptr)
1871 struct xt_counters *counters;
1872 const struct xt_table_info *private = table->private;
1876 const void *loc_cpu_entry;
1879 counters = alloc_counters(table);
1880 if (IS_ERR(counters))
1881 return PTR_ERR(counters);
1883 /* choose the copy that is on our node/cpu, ...
1884 * This choice is lazy (because current thread is
1885 * allowed to migrate to another cpu)
1887 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1890 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
1891 compat_copy_entry_to_user,
1892 &pos, &size, counters, &i);
1899 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1903 struct compat_ipt_get_entries get;
1906 if (*len < sizeof(get)) {
1907 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1911 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1914 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1915 duprintf("compat_get_entries: %u != %zu\n",
1916 *len, sizeof(get) + get.size);
1920 xt_compat_lock(AF_INET);
1921 t = xt_find_table_lock(net, AF_INET, get.name);
1922 if (t && !IS_ERR(t)) {
1923 const struct xt_table_info *private = t->private;
1924 struct xt_table_info info;
1925 duprintf("t->private->number = %u\n", private->number);
1926 ret = compat_table_info(private, &info);
1927 if (!ret && get.size == info.size) {
1928 ret = compat_copy_entries_to_user(private->size,
1929 t, uptr->entrytable);
1931 duprintf("compat_get_entries: I've got %u not %u!\n",
1932 private->size, get.size);
1935 xt_compat_flush_offsets(AF_INET);
1939 ret = t ? PTR_ERR(t) : -ENOENT;
1941 xt_compat_unlock(AF_INET);
1945 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1948 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1952 if (!capable(CAP_NET_ADMIN))
1956 case IPT_SO_GET_INFO:
1957 ret = get_info(sock_net(sk), user, len, 1);
1959 case IPT_SO_GET_ENTRIES:
1960 ret = compat_get_entries(sock_net(sk), user, len);
1963 ret = do_ipt_get_ctl(sk, cmd, user, len);
1970 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1974 if (!capable(CAP_NET_ADMIN))
1978 case IPT_SO_SET_REPLACE:
1979 ret = do_replace(sock_net(sk), user, len);
1982 case IPT_SO_SET_ADD_COUNTERS:
1983 ret = do_add_counters(sock_net(sk), user, len, 0);
1987 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1995 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1999 if (!capable(CAP_NET_ADMIN))
2003 case IPT_SO_GET_INFO:
2004 ret = get_info(sock_net(sk), user, len, 0);
2007 case IPT_SO_GET_ENTRIES:
2008 ret = get_entries(sock_net(sk), user, len);
2011 case IPT_SO_GET_REVISION_MATCH:
2012 case IPT_SO_GET_REVISION_TARGET: {
2013 struct ipt_get_revision rev;
2016 if (*len != sizeof(rev)) {
2020 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2025 if (cmd == IPT_SO_GET_REVISION_TARGET)
2030 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2033 "ipt_%s", rev.name);
2038 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2045 struct xt_table *ipt_register_table(struct net *net, struct xt_table *table,
2046 const struct ipt_replace *repl)
2049 struct xt_table_info *newinfo;
2050 struct xt_table_info bootstrap
2051 = { 0, 0, 0, { 0 }, { 0 }, { } };
2052 void *loc_cpu_entry;
2053 struct xt_table *new_table;
2055 newinfo = xt_alloc_table_info(repl->size);
2061 /* choose the copy on our node/cpu, but dont care about preemption */
2062 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2063 memcpy(loc_cpu_entry, repl->entries, repl->size);
2065 ret = translate_table(table->name, table->valid_hooks,
2066 newinfo, loc_cpu_entry, repl->size,
2073 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2074 if (IS_ERR(new_table)) {
2075 ret = PTR_ERR(new_table);
2082 xt_free_table_info(newinfo);
2084 return ERR_PTR(ret);
2087 void ipt_unregister_table(struct xt_table *table)
2089 struct xt_table_info *private;
2090 void *loc_cpu_entry;
2091 struct module *table_owner = table->me;
2093 private = xt_unregister_table(table);
2095 /* Decrease module usage counts and free resources */
2096 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2097 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
2098 if (private->number > private->initial_entries)
2099 module_put(table_owner);
2100 xt_free_table_info(private);
2103 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2105 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2106 u_int8_t type, u_int8_t code,
2109 return ((test_type == 0xFF) ||
2110 (type == test_type && code >= min_code && code <= max_code))
2115 icmp_match(const struct sk_buff *skb, const struct xt_match_param *par)
2117 const struct icmphdr *ic;
2118 struct icmphdr _icmph;
2119 const struct ipt_icmp *icmpinfo = par->matchinfo;
2121 /* Must not be a fragment. */
2122 if (par->fragoff != 0)
2125 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2127 /* We've been asked to examine this packet, and we
2128 * can't. Hence, no choice but to drop.
2130 duprintf("Dropping evil ICMP tinygram.\n");
2131 *par->hotdrop = true;
2135 return icmp_type_code_match(icmpinfo->type,
2139 !!(icmpinfo->invflags&IPT_ICMP_INV));
2142 static bool icmp_checkentry(const struct xt_mtchk_param *par)
2144 const struct ipt_icmp *icmpinfo = par->matchinfo;
2146 /* Must specify no unknown invflags */
2147 return !(icmpinfo->invflags & ~IPT_ICMP_INV);
2150 /* The built-in targets: standard (NULL) and error. */
2151 static struct xt_target ipt_standard_target __read_mostly = {
2152 .name = IPT_STANDARD_TARGET,
2153 .targetsize = sizeof(int),
2154 .family = NFPROTO_IPV4,
2155 #ifdef CONFIG_COMPAT
2156 .compatsize = sizeof(compat_int_t),
2157 .compat_from_user = compat_standard_from_user,
2158 .compat_to_user = compat_standard_to_user,
2162 static struct xt_target ipt_error_target __read_mostly = {
2163 .name = IPT_ERROR_TARGET,
2164 .target = ipt_error,
2165 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2166 .family = NFPROTO_IPV4,
2169 static struct nf_sockopt_ops ipt_sockopts = {
2171 .set_optmin = IPT_BASE_CTL,
2172 .set_optmax = IPT_SO_SET_MAX+1,
2173 .set = do_ipt_set_ctl,
2174 #ifdef CONFIG_COMPAT
2175 .compat_set = compat_do_ipt_set_ctl,
2177 .get_optmin = IPT_BASE_CTL,
2178 .get_optmax = IPT_SO_GET_MAX+1,
2179 .get = do_ipt_get_ctl,
2180 #ifdef CONFIG_COMPAT
2181 .compat_get = compat_do_ipt_get_ctl,
2183 .owner = THIS_MODULE,
2186 static struct xt_match icmp_matchstruct __read_mostly = {
2188 .match = icmp_match,
2189 .matchsize = sizeof(struct ipt_icmp),
2190 .checkentry = icmp_checkentry,
2191 .proto = IPPROTO_ICMP,
2192 .family = NFPROTO_IPV4,
2195 static int __net_init ip_tables_net_init(struct net *net)
2197 return xt_proto_init(net, NFPROTO_IPV4);
2200 static void __net_exit ip_tables_net_exit(struct net *net)
2202 xt_proto_fini(net, NFPROTO_IPV4);
2205 static struct pernet_operations ip_tables_net_ops = {
2206 .init = ip_tables_net_init,
2207 .exit = ip_tables_net_exit,
2210 static int __init ip_tables_init(void)
2214 ret = register_pernet_subsys(&ip_tables_net_ops);
2218 /* Noone else will be downing sem now, so we won't sleep */
2219 ret = xt_register_target(&ipt_standard_target);
2222 ret = xt_register_target(&ipt_error_target);
2225 ret = xt_register_match(&icmp_matchstruct);
2229 /* Register setsockopt */
2230 ret = nf_register_sockopt(&ipt_sockopts);
2234 printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
2238 xt_unregister_match(&icmp_matchstruct);
2240 xt_unregister_target(&ipt_error_target);
2242 xt_unregister_target(&ipt_standard_target);
2244 unregister_pernet_subsys(&ip_tables_net_ops);
2249 static void __exit ip_tables_fini(void)
2251 nf_unregister_sockopt(&ipt_sockopts);
2253 xt_unregister_match(&icmp_matchstruct);
2254 xt_unregister_target(&ipt_error_target);
2255 xt_unregister_target(&ipt_standard_target);
2257 unregister_pernet_subsys(&ip_tables_net_ops);
2260 EXPORT_SYMBOL(ipt_register_table);
2261 EXPORT_SYMBOL(ipt_unregister_table);
2262 EXPORT_SYMBOL(ipt_do_table);
2263 module_init(ip_tables_init);
2264 module_exit(ip_tables_fini);