2 * Packet matching code.
4 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
5 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/cache.h>
13 #include <linux/capability.h>
14 #include <linux/skbuff.h>
15 #include <linux/kmod.h>
16 #include <linux/vmalloc.h>
17 #include <linux/netdevice.h>
18 #include <linux/module.h>
19 #include <linux/icmp.h>
21 #include <net/compat.h>
22 #include <asm/uaccess.h>
23 #include <linux/mutex.h>
24 #include <linux/proc_fs.h>
25 #include <linux/err.h>
26 #include <linux/cpumask.h>
28 #include <linux/netfilter/x_tables.h>
29 #include <linux/netfilter_ipv4/ip_tables.h>
30 #include <net/netfilter/nf_log.h>
31 #include "../../netfilter/xt_repldata.h"
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
35 MODULE_DESCRIPTION("IPv4 packet filter");
37 /*#define DEBUG_IP_FIREWALL*/
38 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
39 /*#define DEBUG_IP_FIREWALL_USER*/
41 #ifdef DEBUG_IP_FIREWALL
42 #define dprintf(format, args...) pr_info(format , ## args)
44 #define dprintf(format, args...)
47 #ifdef DEBUG_IP_FIREWALL_USER
48 #define duprintf(format, args...) pr_info(format , ## args)
50 #define duprintf(format, args...)
53 #ifdef CONFIG_NETFILTER_DEBUG
54 #define IP_NF_ASSERT(x) \
57 printk("IP_NF_ASSERT: %s:%s:%u\n", \
58 __func__, __FILE__, __LINE__); \
61 #define IP_NF_ASSERT(x)
65 /* All the better to debug you with... */
70 void *ipt_alloc_initial_table(const struct xt_table *info)
72 return xt_alloc_initial_table(ipt, IPT);
74 EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);
77 We keep a set of rules for each CPU, so we can avoid write-locking
78 them in the softirq when updating the counters and therefore
79 only need to read-lock in the softirq; doing a write_lock_bh() in user
80 context stops packets coming through and allows user context to read
81 the counters or update the rules.
83 Hence the start of any table is given by get_table() below. */
85 /* Returns whether matches rule or not. */
86 /* Performance critical - called for every packet */
88 ip_packet_match(const struct iphdr *ip,
91 const struct ipt_ip *ipinfo,
96 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
98 if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
100 FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
102 dprintf("Source or dest mismatch.\n");
104 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n",
105 &ip->saddr, &ipinfo->smsk.s_addr, &ipinfo->src.s_addr,
106 ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
107 dprintf("DST: %pI4 Mask: %pI4 Target: %pI4.%s\n",
108 &ip->daddr, &ipinfo->dmsk.s_addr, &ipinfo->dst.s_addr,
109 ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
113 ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask);
115 if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
116 dprintf("VIA in mismatch (%s vs %s).%s\n",
117 indev, ipinfo->iniface,
118 ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
122 ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask);
124 if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
125 dprintf("VIA out mismatch (%s vs %s).%s\n",
126 outdev, ipinfo->outiface,
127 ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
131 /* Check specific protocol */
133 FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
134 dprintf("Packet protocol %hi does not match %hi.%s\n",
135 ip->protocol, ipinfo->proto,
136 ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
140 /* If we have a fragment rule but the packet is not a fragment
141 * then we return zero */
142 if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
143 dprintf("Fragment rule but not fragment.%s\n",
144 ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
152 ip_checkentry(const struct ipt_ip *ip)
154 if (ip->flags & ~IPT_F_MASK) {
155 duprintf("Unknown flag bits set: %08X\n",
156 ip->flags & ~IPT_F_MASK);
159 if (ip->invflags & ~IPT_INV_MASK) {
160 duprintf("Unknown invflag bits set: %08X\n",
161 ip->invflags & ~IPT_INV_MASK);
168 ipt_error(struct sk_buff *skb, const struct xt_action_param *par)
171 pr_info("error: `%s'\n", (const char *)par->targinfo);
176 /* Performance critical */
177 static inline struct ipt_entry *
178 get_entry(const void *base, unsigned int offset)
180 return (struct ipt_entry *)(base + offset);
183 /* All zeroes == unconditional rule. */
184 /* Mildly perf critical (only if packet tracing is on) */
185 static inline bool unconditional(const struct ipt_ip *ip)
187 static const struct ipt_ip uncond;
189 return memcmp(ip, &uncond, sizeof(uncond)) == 0;
193 /* for const-correctness */
194 static inline const struct ipt_entry_target *
195 ipt_get_target_c(const struct ipt_entry *e)
197 return ipt_get_target((struct ipt_entry *)e);
200 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
201 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
202 static const char *const hooknames[] = {
203 [NF_INET_PRE_ROUTING] = "PREROUTING",
204 [NF_INET_LOCAL_IN] = "INPUT",
205 [NF_INET_FORWARD] = "FORWARD",
206 [NF_INET_LOCAL_OUT] = "OUTPUT",
207 [NF_INET_POST_ROUTING] = "POSTROUTING",
210 enum nf_ip_trace_comments {
211 NF_IP_TRACE_COMMENT_RULE,
212 NF_IP_TRACE_COMMENT_RETURN,
213 NF_IP_TRACE_COMMENT_POLICY,
216 static const char *const comments[] = {
217 [NF_IP_TRACE_COMMENT_RULE] = "rule",
218 [NF_IP_TRACE_COMMENT_RETURN] = "return",
219 [NF_IP_TRACE_COMMENT_POLICY] = "policy",
222 static struct nf_loginfo trace_loginfo = {
223 .type = NF_LOG_TYPE_LOG,
227 .logflags = NF_LOG_MASK,
232 /* Mildly perf critical (only if packet tracing is on) */
234 get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e,
235 const char *hookname, const char **chainname,
236 const char **comment, unsigned int *rulenum)
238 const struct ipt_standard_target *t = (void *)ipt_get_target_c(s);
240 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
241 /* Head of user chain: ERROR target with chainname */
242 *chainname = t->target.data;
247 if (s->target_offset == sizeof(struct ipt_entry) &&
248 strcmp(t->target.u.kernel.target->name,
249 IPT_STANDARD_TARGET) == 0 &&
251 unconditional(&s->ip)) {
252 /* Tail of chains: STANDARD target (return/policy) */
253 *comment = *chainname == hookname
254 ? comments[NF_IP_TRACE_COMMENT_POLICY]
255 : comments[NF_IP_TRACE_COMMENT_RETURN];
264 static void trace_packet(const struct sk_buff *skb,
266 const struct net_device *in,
267 const struct net_device *out,
268 const char *tablename,
269 const struct xt_table_info *private,
270 const struct ipt_entry *e)
272 const void *table_base;
273 const struct ipt_entry *root;
274 const char *hookname, *chainname, *comment;
275 const struct ipt_entry *iter;
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 xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
285 if (get_chainname_rulenum(iter, e, hookname,
286 &chainname, &comment, &rulenum) != 0)
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 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
310 const struct iphdr *ip;
311 /* Initializing verdict to NF_DROP keeps gcc happy. */
312 unsigned int verdict = NF_DROP;
313 const char *indev, *outdev;
314 const void *table_base;
315 struct ipt_entry *e, **jumpstack;
316 unsigned int *stackptr, origptr, cpu;
317 const struct xt_table_info *private;
318 struct xt_action_param acpar;
322 indev = in ? in->name : nulldevname;
323 outdev = out ? out->name : nulldevname;
324 /* We handle fragments by dealing with the first fragment as
325 * if it was a normal packet. All other fragments are treated
326 * normally, except that they will NEVER match rules that ask
327 * things we don't know, ie. tcp syn flag or ports). If the
328 * rule is also a fragment-specific rule, non-fragments won't
330 acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
331 acpar.thoff = ip_hdrlen(skb);
332 acpar.hotdrop = false;
335 acpar.family = NFPROTO_IPV4;
336 acpar.hooknum = hook;
338 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
340 private = table->private;
341 cpu = smp_processor_id();
342 table_base = private->entries[cpu];
343 jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
344 stackptr = &private->stackptr[cpu];
347 e = get_entry(table_base, private->hook_entry[hook]);
349 pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n",
350 table->name, hook, origptr,
351 get_entry(table_base, private->underflow[hook]));
354 const struct ipt_entry_target *t;
355 const struct xt_entry_match *ematch;
358 if (!ip_packet_match(ip, indev, outdev,
359 &e->ip, acpar.fragoff)) {
361 e = ipt_next_entry(e);
365 xt_ematch_foreach(ematch, e) {
366 acpar.match = ematch->u.kernel.match;
367 acpar.matchinfo = ematch->data;
368 if (!acpar.match->match(skb, &acpar))
372 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
374 t = ipt_get_target(e);
375 IP_NF_ASSERT(t->u.kernel.target);
377 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
378 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
379 /* The packet is traced: log it */
380 if (unlikely(skb->nf_trace))
381 trace_packet(skb, hook, in, out,
382 table->name, private, e);
384 /* Standard target? */
385 if (!t->u.kernel.target->target) {
388 v = ((struct ipt_standard_target *)t)->verdict;
390 /* Pop from stack? */
391 if (v != IPT_RETURN) {
392 verdict = (unsigned)(-v) - 1;
395 if (*stackptr == 0) {
396 e = get_entry(table_base,
397 private->underflow[hook]);
398 pr_debug("Underflow (this is normal) "
401 e = jumpstack[--*stackptr];
402 pr_debug("Pulled %p out from pos %u\n",
404 e = ipt_next_entry(e);
408 if (table_base + v != ipt_next_entry(e) &&
409 !(e->ip.flags & IPT_F_GOTO)) {
410 if (*stackptr >= private->stacksize) {
414 jumpstack[(*stackptr)++] = e;
415 pr_debug("Pushed %p into pos %u\n",
419 e = get_entry(table_base, v);
423 acpar.target = t->u.kernel.target;
424 acpar.targinfo = t->data;
426 verdict = t->u.kernel.target->target(skb, &acpar);
427 /* Target might have changed stuff. */
429 if (verdict == IPT_CONTINUE)
430 e = ipt_next_entry(e);
434 } while (!acpar.hotdrop);
435 xt_info_rdunlock_bh();
436 pr_debug("Exiting %s; resetting sp from %u to %u\n",
437 __func__, *stackptr, origptr);
439 #ifdef DEBUG_ALLOW_ALL
448 /* Figures out from what hook each rule can be called: returns 0 if
449 there are loops. Puts hook bitmask in comefrom. */
451 mark_source_chains(const struct xt_table_info *newinfo,
452 unsigned int valid_hooks, void *entry0)
456 /* No recursion; use packet counter to save back ptrs (reset
457 to 0 as we leave), and comefrom to save source hook bitmask */
458 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
459 unsigned int pos = newinfo->hook_entry[hook];
460 struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);
462 if (!(valid_hooks & (1 << hook)))
465 /* Set initial back pointer. */
466 e->counters.pcnt = pos;
469 const struct ipt_standard_target *t
470 = (void *)ipt_get_target_c(e);
471 int visited = e->comefrom & (1 << hook);
473 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
474 printk("iptables: loop hook %u pos %u %08X.\n",
475 hook, pos, e->comefrom);
478 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
480 /* Unconditional return/END. */
481 if ((e->target_offset == sizeof(struct ipt_entry) &&
482 (strcmp(t->target.u.user.name,
483 IPT_STANDARD_TARGET) == 0) &&
484 t->verdict < 0 && unconditional(&e->ip)) ||
486 unsigned int oldpos, size;
488 if ((strcmp(t->target.u.user.name,
489 IPT_STANDARD_TARGET) == 0) &&
490 t->verdict < -NF_MAX_VERDICT - 1) {
491 duprintf("mark_source_chains: bad "
492 "negative verdict (%i)\n",
497 /* Return: backtrack through the last
500 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
501 #ifdef DEBUG_IP_FIREWALL_USER
503 & (1 << NF_INET_NUMHOOKS)) {
504 duprintf("Back unset "
511 pos = e->counters.pcnt;
512 e->counters.pcnt = 0;
514 /* We're at the start. */
518 e = (struct ipt_entry *)
520 } while (oldpos == pos + e->next_offset);
523 size = e->next_offset;
524 e = (struct ipt_entry *)
525 (entry0 + pos + size);
526 e->counters.pcnt = pos;
529 int newpos = t->verdict;
531 if (strcmp(t->target.u.user.name,
532 IPT_STANDARD_TARGET) == 0 &&
534 if (newpos > newinfo->size -
535 sizeof(struct ipt_entry)) {
536 duprintf("mark_source_chains: "
537 "bad verdict (%i)\n",
541 /* This a jump; chase it. */
542 duprintf("Jump rule %u -> %u\n",
545 /* ... this is a fallthru */
546 newpos = pos + e->next_offset;
548 e = (struct ipt_entry *)
550 e->counters.pcnt = pos;
555 duprintf("Finished chain %u\n", hook);
560 static void cleanup_match(struct ipt_entry_match *m, struct net *net)
562 struct xt_mtdtor_param par;
565 par.match = m->u.kernel.match;
566 par.matchinfo = m->data;
567 par.family = NFPROTO_IPV4;
568 if (par.match->destroy != NULL)
569 par.match->destroy(&par);
570 module_put(par.match->me);
574 check_entry(const struct ipt_entry *e, const char *name)
576 const struct ipt_entry_target *t;
578 if (!ip_checkentry(&e->ip)) {
579 duprintf("ip check failed %p %s.\n", e, par->match->name);
583 if (e->target_offset + sizeof(struct ipt_entry_target) >
587 t = ipt_get_target_c(e);
588 if (e->target_offset + t->u.target_size > e->next_offset)
595 check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
597 const struct ipt_ip *ip = par->entryinfo;
600 par->match = m->u.kernel.match;
601 par->matchinfo = m->data;
603 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
604 ip->proto, ip->invflags & IPT_INV_PROTO);
606 duprintf("check failed for `%s'.\n", par->match->name);
613 find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)
615 struct xt_match *match;
618 match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
621 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
622 return PTR_ERR(match);
624 m->u.kernel.match = match;
626 ret = check_match(m, par);
632 module_put(m->u.kernel.match->me);
636 static int check_target(struct ipt_entry *e, struct net *net, const char *name)
638 struct ipt_entry_target *t = ipt_get_target(e);
639 struct xt_tgchk_param par = {
643 .target = t->u.kernel.target,
645 .hook_mask = e->comefrom,
646 .family = NFPROTO_IPV4,
650 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
651 e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
653 duprintf("check failed for `%s'.\n",
654 t->u.kernel.target->name);
661 find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
664 struct ipt_entry_target *t;
665 struct xt_target *target;
668 struct xt_mtchk_param mtpar;
669 struct xt_entry_match *ematch;
671 ret = check_entry(e, name);
678 mtpar.entryinfo = &e->ip;
679 mtpar.hook_mask = e->comefrom;
680 mtpar.family = NFPROTO_IPV4;
681 xt_ematch_foreach(ematch, e) {
682 ret = find_check_match(ematch, &mtpar);
684 goto cleanup_matches;
688 t = ipt_get_target(e);
689 target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
691 if (IS_ERR(target)) {
692 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
693 ret = PTR_ERR(target);
694 goto cleanup_matches;
696 t->u.kernel.target = target;
698 ret = check_target(e, net, name);
703 module_put(t->u.kernel.target->me);
705 xt_ematch_foreach(ematch, e) {
708 cleanup_match(ematch, net);
713 static bool check_underflow(const struct ipt_entry *e)
715 const struct ipt_entry_target *t;
716 unsigned int verdict;
718 if (!unconditional(&e->ip))
720 t = ipt_get_target_c(e);
721 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
723 verdict = ((struct ipt_standard_target *)t)->verdict;
724 verdict = -verdict - 1;
725 return verdict == NF_DROP || verdict == NF_ACCEPT;
729 check_entry_size_and_hooks(struct ipt_entry *e,
730 struct xt_table_info *newinfo,
731 const unsigned char *base,
732 const unsigned char *limit,
733 const unsigned int *hook_entries,
734 const unsigned int *underflows,
735 unsigned int valid_hooks)
739 if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
740 (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
741 duprintf("Bad offset %p\n", e);
746 < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
747 duprintf("checking: element %p size %u\n",
752 /* Check hooks & underflows */
753 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
754 if (!(valid_hooks & (1 << h)))
756 if ((unsigned char *)e - base == hook_entries[h])
757 newinfo->hook_entry[h] = hook_entries[h];
758 if ((unsigned char *)e - base == underflows[h]) {
759 if (!check_underflow(e)) {
760 pr_err("Underflows must be unconditional and "
761 "use the STANDARD target with "
765 newinfo->underflow[h] = underflows[h];
769 /* Clear counters and comefrom */
770 e->counters = ((struct xt_counters) { 0, 0 });
776 cleanup_entry(struct ipt_entry *e, struct net *net)
778 struct xt_tgdtor_param par;
779 struct ipt_entry_target *t;
780 struct xt_entry_match *ematch;
782 /* Cleanup all matches */
783 xt_ematch_foreach(ematch, e)
784 cleanup_match(ematch, net);
785 t = ipt_get_target(e);
788 par.target = t->u.kernel.target;
789 par.targinfo = t->data;
790 par.family = NFPROTO_IPV4;
791 if (par.target->destroy != NULL)
792 par.target->destroy(&par);
793 module_put(par.target->me);
796 /* Checks and translates the user-supplied table segment (held in
799 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
800 const struct ipt_replace *repl)
802 struct ipt_entry *iter;
806 newinfo->size = repl->size;
807 newinfo->number = repl->num_entries;
809 /* Init all hooks to impossible value. */
810 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
811 newinfo->hook_entry[i] = 0xFFFFFFFF;
812 newinfo->underflow[i] = 0xFFFFFFFF;
815 duprintf("translate_table: size %u\n", newinfo->size);
817 /* Walk through entries, checking offsets. */
818 xt_entry_foreach(iter, entry0, newinfo->size) {
819 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
827 if (strcmp(ipt_get_target(iter)->u.user.name,
828 XT_ERROR_TARGET) == 0)
829 ++newinfo->stacksize;
832 if (i != repl->num_entries) {
833 duprintf("translate_table: %u not %u entries\n",
834 i, repl->num_entries);
838 /* Check hooks all assigned */
839 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
840 /* Only hooks which are valid */
841 if (!(repl->valid_hooks & (1 << i)))
843 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
844 duprintf("Invalid hook entry %u %u\n",
845 i, repl->hook_entry[i]);
848 if (newinfo->underflow[i] == 0xFFFFFFFF) {
849 duprintf("Invalid underflow %u %u\n",
850 i, repl->underflow[i]);
855 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
858 /* Finally, each sanity check must pass */
860 xt_entry_foreach(iter, entry0, newinfo->size) {
861 ret = find_check_entry(iter, net, repl->name, repl->size);
868 xt_entry_foreach(iter, entry0, newinfo->size) {
871 cleanup_entry(iter, net);
876 /* And one copy for every other CPU */
877 for_each_possible_cpu(i) {
878 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
879 memcpy(newinfo->entries[i], entry0, newinfo->size);
886 get_counters(const struct xt_table_info *t,
887 struct xt_counters counters[])
889 struct ipt_entry *iter;
894 /* Instead of clearing (by a previous call to memset())
895 * the counters and using adds, we set the counters
896 * with data used by 'current' CPU.
898 * Bottom half has to be disabled to prevent deadlock
899 * if new softirq were to run and call ipt_do_table
902 curcpu = smp_processor_id();
905 xt_entry_foreach(iter, t->entries[curcpu], t->size) {
906 SET_COUNTER(counters[i], iter->counters.bcnt,
907 iter->counters.pcnt);
911 for_each_possible_cpu(cpu) {
916 xt_entry_foreach(iter, t->entries[cpu], t->size) {
917 ADD_COUNTER(counters[i], iter->counters.bcnt,
918 iter->counters.pcnt);
919 ++i; /* macro does multi eval of i */
921 xt_info_wrunlock(cpu);
926 static struct xt_counters *alloc_counters(const struct xt_table *table)
928 unsigned int countersize;
929 struct xt_counters *counters;
930 const struct xt_table_info *private = table->private;
932 /* We need atomic snapshot of counters: rest doesn't change
933 (other than comefrom, which userspace doesn't care
935 countersize = sizeof(struct xt_counters) * private->number;
936 counters = vmalloc_node(countersize, numa_node_id());
938 if (counters == NULL)
939 return ERR_PTR(-ENOMEM);
941 get_counters(private, counters);
947 copy_entries_to_user(unsigned int total_size,
948 const struct xt_table *table,
949 void __user *userptr)
951 unsigned int off, num;
952 const struct ipt_entry *e;
953 struct xt_counters *counters;
954 const struct xt_table_info *private = table->private;
956 const void *loc_cpu_entry;
958 counters = alloc_counters(table);
959 if (IS_ERR(counters))
960 return PTR_ERR(counters);
962 /* choose the copy that is on our node/cpu, ...
963 * This choice is lazy (because current thread is
964 * allowed to migrate to another cpu)
966 loc_cpu_entry = private->entries[raw_smp_processor_id()];
967 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
972 /* FIXME: use iterator macros --RR */
973 /* ... then go back and fix counters and names */
974 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
976 const struct ipt_entry_match *m;
977 const struct ipt_entry_target *t;
979 e = (struct ipt_entry *)(loc_cpu_entry + off);
980 if (copy_to_user(userptr + off
981 + offsetof(struct ipt_entry, counters),
983 sizeof(counters[num])) != 0) {
988 for (i = sizeof(struct ipt_entry);
989 i < e->target_offset;
990 i += m->u.match_size) {
993 if (copy_to_user(userptr + off + i
994 + offsetof(struct ipt_entry_match,
996 m->u.kernel.match->name,
997 strlen(m->u.kernel.match->name)+1)
1004 t = ipt_get_target_c(e);
1005 if (copy_to_user(userptr + off + e->target_offset
1006 + offsetof(struct ipt_entry_target,
1008 t->u.kernel.target->name,
1009 strlen(t->u.kernel.target->name)+1) != 0) {
1020 #ifdef CONFIG_COMPAT
1021 static void compat_standard_from_user(void *dst, const void *src)
1023 int v = *(compat_int_t *)src;
1026 v += xt_compat_calc_jump(AF_INET, v);
1027 memcpy(dst, &v, sizeof(v));
1030 static int compat_standard_to_user(void __user *dst, const void *src)
1032 compat_int_t cv = *(int *)src;
1035 cv -= xt_compat_calc_jump(AF_INET, cv);
1036 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1039 static int compat_calc_entry(const struct ipt_entry *e,
1040 const struct xt_table_info *info,
1041 const void *base, struct xt_table_info *newinfo)
1043 const struct xt_entry_match *ematch;
1044 const 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 xt_ematch_foreach(ematch, e)
1051 off += xt_compat_match_offset(ematch->u.kernel.match);
1052 t = ipt_get_target_c(e);
1053 off += xt_compat_target_offset(t->u.kernel.target);
1054 newinfo->size -= off;
1055 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1059 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1060 if (info->hook_entry[i] &&
1061 (e < (struct ipt_entry *)(base + info->hook_entry[i])))
1062 newinfo->hook_entry[i] -= off;
1063 if (info->underflow[i] &&
1064 (e < (struct ipt_entry *)(base + info->underflow[i])))
1065 newinfo->underflow[i] -= off;
1070 static int compat_table_info(const struct xt_table_info *info,
1071 struct xt_table_info *newinfo)
1073 struct ipt_entry *iter;
1074 void *loc_cpu_entry;
1077 if (!newinfo || !info)
1080 /* we dont care about newinfo->entries[] */
1081 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1082 newinfo->initial_entries = 0;
1083 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1084 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1085 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1093 static int get_info(struct net *net, void __user *user,
1094 const int *len, int compat)
1096 char name[IPT_TABLE_MAXNAMELEN];
1100 if (*len != sizeof(struct ipt_getinfo)) {
1101 duprintf("length %u != %zu\n", *len,
1102 sizeof(struct ipt_getinfo));
1106 if (copy_from_user(name, user, sizeof(name)) != 0)
1109 name[IPT_TABLE_MAXNAMELEN-1] = '\0';
1110 #ifdef CONFIG_COMPAT
1112 xt_compat_lock(AF_INET);
1114 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1115 "iptable_%s", name);
1116 if (t && !IS_ERR(t)) {
1117 struct ipt_getinfo info;
1118 const struct xt_table_info *private = t->private;
1119 #ifdef CONFIG_COMPAT
1120 struct xt_table_info tmp;
1123 ret = compat_table_info(private, &tmp);
1124 xt_compat_flush_offsets(AF_INET);
1128 info.valid_hooks = t->valid_hooks;
1129 memcpy(info.hook_entry, private->hook_entry,
1130 sizeof(info.hook_entry));
1131 memcpy(info.underflow, private->underflow,
1132 sizeof(info.underflow));
1133 info.num_entries = private->number;
1134 info.size = private->size;
1135 strcpy(info.name, name);
1137 if (copy_to_user(user, &info, *len) != 0)
1145 ret = t ? PTR_ERR(t) : -ENOENT;
1146 #ifdef CONFIG_COMPAT
1148 xt_compat_unlock(AF_INET);
1154 get_entries(struct net *net, struct ipt_get_entries __user *uptr,
1158 struct ipt_get_entries get;
1161 if (*len < sizeof(get)) {
1162 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1165 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1167 if (*len != sizeof(struct ipt_get_entries) + get.size) {
1168 duprintf("get_entries: %u != %zu\n",
1169 *len, sizeof(get) + get.size);
1173 t = xt_find_table_lock(net, AF_INET, get.name);
1174 if (t && !IS_ERR(t)) {
1175 const struct xt_table_info *private = t->private;
1176 duprintf("t->private->number = %u\n", private->number);
1177 if (get.size == private->size)
1178 ret = copy_entries_to_user(private->size,
1179 t, uptr->entrytable);
1181 duprintf("get_entries: I've got %u not %u!\n",
1182 private->size, get.size);
1188 ret = t ? PTR_ERR(t) : -ENOENT;
1194 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1195 struct xt_table_info *newinfo, unsigned int num_counters,
1196 void __user *counters_ptr)
1200 struct xt_table_info *oldinfo;
1201 struct xt_counters *counters;
1202 void *loc_cpu_old_entry;
1203 struct ipt_entry *iter;
1206 counters = vmalloc(num_counters * sizeof(struct xt_counters));
1212 t = try_then_request_module(xt_find_table_lock(net, AF_INET, name),
1213 "iptable_%s", name);
1214 if (!t || IS_ERR(t)) {
1215 ret = t ? PTR_ERR(t) : -ENOENT;
1216 goto free_newinfo_counters_untrans;
1220 if (valid_hooks != t->valid_hooks) {
1221 duprintf("Valid hook crap: %08X vs %08X\n",
1222 valid_hooks, t->valid_hooks);
1227 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1231 /* Update module usage count based on number of rules */
1232 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1233 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1234 if ((oldinfo->number > oldinfo->initial_entries) ||
1235 (newinfo->number <= oldinfo->initial_entries))
1237 if ((oldinfo->number > oldinfo->initial_entries) &&
1238 (newinfo->number <= oldinfo->initial_entries))
1241 /* Get the old counters, and synchronize with replace */
1242 get_counters(oldinfo, counters);
1244 /* Decrease module usage counts and free resource */
1245 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1246 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1247 cleanup_entry(iter, net);
1249 xt_free_table_info(oldinfo);
1250 if (copy_to_user(counters_ptr, counters,
1251 sizeof(struct xt_counters) * num_counters) != 0)
1260 free_newinfo_counters_untrans:
1267 do_replace(struct net *net, const void __user *user, unsigned int len)
1270 struct ipt_replace tmp;
1271 struct xt_table_info *newinfo;
1272 void *loc_cpu_entry;
1273 struct ipt_entry *iter;
1275 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1278 /* overflow check */
1279 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1282 newinfo = xt_alloc_table_info(tmp.size);
1286 /* choose the copy that is on our node/cpu */
1287 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1288 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1294 ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1298 duprintf("Translated table\n");
1300 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1301 tmp.num_counters, tmp.counters);
1303 goto free_newinfo_untrans;
1306 free_newinfo_untrans:
1307 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1308 cleanup_entry(iter, net);
1310 xt_free_table_info(newinfo);
1315 do_add_counters(struct net *net, const void __user *user,
1316 unsigned int len, int compat)
1318 unsigned int i, curcpu;
1319 struct xt_counters_info tmp;
1320 struct xt_counters *paddc;
1321 unsigned int num_counters;
1326 const struct xt_table_info *private;
1328 void *loc_cpu_entry;
1329 struct ipt_entry *iter;
1330 #ifdef CONFIG_COMPAT
1331 struct compat_xt_counters_info compat_tmp;
1335 size = sizeof(struct compat_xt_counters_info);
1340 size = sizeof(struct xt_counters_info);
1343 if (copy_from_user(ptmp, user, size) != 0)
1346 #ifdef CONFIG_COMPAT
1348 num_counters = compat_tmp.num_counters;
1349 name = compat_tmp.name;
1353 num_counters = tmp.num_counters;
1357 if (len != size + num_counters * sizeof(struct xt_counters))
1360 paddc = vmalloc_node(len - size, numa_node_id());
1364 if (copy_from_user(paddc, user + size, len - size) != 0) {
1369 t = xt_find_table_lock(net, AF_INET, name);
1370 if (!t || IS_ERR(t)) {
1371 ret = t ? PTR_ERR(t) : -ENOENT;
1376 private = t->private;
1377 if (private->number != num_counters) {
1379 goto unlock_up_free;
1383 /* Choose the copy that is on our node */
1384 curcpu = smp_processor_id();
1385 loc_cpu_entry = private->entries[curcpu];
1386 xt_info_wrlock(curcpu);
1387 xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1388 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1391 xt_info_wrunlock(curcpu);
1402 #ifdef CONFIG_COMPAT
1403 struct compat_ipt_replace {
1404 char name[IPT_TABLE_MAXNAMELEN];
1408 u32 hook_entry[NF_INET_NUMHOOKS];
1409 u32 underflow[NF_INET_NUMHOOKS];
1411 compat_uptr_t counters; /* struct ipt_counters * */
1412 struct compat_ipt_entry entries[0];
1416 compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
1417 unsigned int *size, struct xt_counters *counters,
1420 struct ipt_entry_target *t;
1421 struct compat_ipt_entry __user *ce;
1422 u_int16_t target_offset, next_offset;
1423 compat_uint_t origsize;
1424 const struct xt_entry_match *ematch;
1428 ce = (struct compat_ipt_entry __user *)*dstptr;
1429 if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
1430 copy_to_user(&ce->counters, &counters[i],
1431 sizeof(counters[i])) != 0)
1434 *dstptr += sizeof(struct compat_ipt_entry);
1435 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1437 xt_ematch_foreach(ematch, e) {
1438 ret = xt_compat_match_to_user(ematch, dstptr, size);
1442 target_offset = e->target_offset - (origsize - *size);
1443 t = ipt_get_target(e);
1444 ret = xt_compat_target_to_user(t, dstptr, size);
1447 next_offset = e->next_offset - (origsize - *size);
1448 if (put_user(target_offset, &ce->target_offset) != 0 ||
1449 put_user(next_offset, &ce->next_offset) != 0)
1455 compat_find_calc_match(struct ipt_entry_match *m,
1457 const struct ipt_ip *ip,
1458 unsigned int hookmask,
1461 struct xt_match *match;
1463 match = xt_request_find_match(NFPROTO_IPV4, m->u.user.name,
1464 m->u.user.revision);
1465 if (IS_ERR(match)) {
1466 duprintf("compat_check_calc_match: `%s' not found\n",
1468 return PTR_ERR(match);
1470 m->u.kernel.match = match;
1471 *size += xt_compat_match_offset(match);
1475 static void compat_release_entry(struct compat_ipt_entry *e)
1477 struct ipt_entry_target *t;
1478 struct xt_entry_match *ematch;
1480 /* Cleanup all matches */
1481 xt_ematch_foreach(ematch, e)
1482 module_put(ematch->u.kernel.match->me);
1483 t = compat_ipt_get_target(e);
1484 module_put(t->u.kernel.target->me);
1488 check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1489 struct xt_table_info *newinfo,
1491 const unsigned char *base,
1492 const unsigned char *limit,
1493 const unsigned int *hook_entries,
1494 const unsigned int *underflows,
1497 struct xt_entry_match *ematch;
1498 struct ipt_entry_target *t;
1499 struct xt_target *target;
1500 unsigned int entry_offset;
1504 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1505 if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
1506 (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
1507 duprintf("Bad offset %p, limit = %p\n", e, limit);
1511 if (e->next_offset < sizeof(struct compat_ipt_entry) +
1512 sizeof(struct compat_xt_entry_target)) {
1513 duprintf("checking: element %p size %u\n",
1518 /* For purposes of check_entry casting the compat entry is fine */
1519 ret = check_entry((struct ipt_entry *)e, name);
1523 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1524 entry_offset = (void *)e - (void *)base;
1526 xt_ematch_foreach(ematch, e) {
1527 ret = compat_find_calc_match(ematch, name,
1528 &e->ip, e->comefrom, &off);
1530 goto release_matches;
1534 t = compat_ipt_get_target(e);
1535 target = xt_request_find_target(NFPROTO_IPV4, t->u.user.name,
1536 t->u.user.revision);
1537 if (IS_ERR(target)) {
1538 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1540 ret = PTR_ERR(target);
1541 goto release_matches;
1543 t->u.kernel.target = target;
1545 off += xt_compat_target_offset(target);
1547 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
1551 /* Check hooks & underflows */
1552 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1553 if ((unsigned char *)e - base == hook_entries[h])
1554 newinfo->hook_entry[h] = hook_entries[h];
1555 if ((unsigned char *)e - base == underflows[h])
1556 newinfo->underflow[h] = underflows[h];
1559 /* Clear counters and comefrom */
1560 memset(&e->counters, 0, sizeof(e->counters));
1565 module_put(t->u.kernel.target->me);
1567 xt_ematch_foreach(ematch, e) {
1570 module_put(ematch->u.kernel.match->me);
1576 compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1577 unsigned int *size, const char *name,
1578 struct xt_table_info *newinfo, unsigned char *base)
1580 struct ipt_entry_target *t;
1581 struct xt_target *target;
1582 struct ipt_entry *de;
1583 unsigned int origsize;
1585 struct xt_entry_match *ematch;
1589 de = (struct ipt_entry *)*dstptr;
1590 memcpy(de, e, sizeof(struct ipt_entry));
1591 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1593 *dstptr += sizeof(struct ipt_entry);
1594 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1596 xt_ematch_foreach(ematch, e) {
1597 ret = xt_compat_match_from_user(ematch, dstptr, size);
1601 de->target_offset = e->target_offset - (origsize - *size);
1602 t = compat_ipt_get_target(e);
1603 target = t->u.kernel.target;
1604 xt_compat_target_from_user(t, dstptr, size);
1606 de->next_offset = e->next_offset - (origsize - *size);
1607 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1608 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1609 newinfo->hook_entry[h] -= origsize - *size;
1610 if ((unsigned char *)de - base < newinfo->underflow[h])
1611 newinfo->underflow[h] -= origsize - *size;
1617 compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
1619 struct xt_entry_match *ematch;
1620 struct xt_mtchk_param mtpar;
1627 mtpar.entryinfo = &e->ip;
1628 mtpar.hook_mask = e->comefrom;
1629 mtpar.family = NFPROTO_IPV4;
1630 xt_ematch_foreach(ematch, e) {
1631 ret = check_match(ematch, &mtpar);
1633 goto cleanup_matches;
1637 ret = check_target(e, net, name);
1639 goto cleanup_matches;
1643 xt_ematch_foreach(ematch, e) {
1646 cleanup_match(ematch, net);
1652 translate_compat_table(struct net *net,
1654 unsigned int valid_hooks,
1655 struct xt_table_info **pinfo,
1657 unsigned int total_size,
1658 unsigned int number,
1659 unsigned int *hook_entries,
1660 unsigned int *underflows)
1663 struct xt_table_info *newinfo, *info;
1664 void *pos, *entry0, *entry1;
1665 struct compat_ipt_entry *iter0;
1666 struct ipt_entry *iter1;
1673 info->number = number;
1675 /* Init all hooks to impossible value. */
1676 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1677 info->hook_entry[i] = 0xFFFFFFFF;
1678 info->underflow[i] = 0xFFFFFFFF;
1681 duprintf("translate_compat_table: size %u\n", info->size);
1683 xt_compat_lock(AF_INET);
1684 /* Walk through entries, checking offsets. */
1685 xt_entry_foreach(iter0, entry0, total_size) {
1686 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1688 entry0 + total_size,
1699 duprintf("translate_compat_table: %u not %u entries\n",
1704 /* Check hooks all assigned */
1705 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1706 /* Only hooks which are valid */
1707 if (!(valid_hooks & (1 << i)))
1709 if (info->hook_entry[i] == 0xFFFFFFFF) {
1710 duprintf("Invalid hook entry %u %u\n",
1711 i, hook_entries[i]);
1714 if (info->underflow[i] == 0xFFFFFFFF) {
1715 duprintf("Invalid underflow %u %u\n",
1722 newinfo = xt_alloc_table_info(size);
1726 newinfo->number = number;
1727 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1728 newinfo->hook_entry[i] = info->hook_entry[i];
1729 newinfo->underflow[i] = info->underflow[i];
1731 entry1 = newinfo->entries[raw_smp_processor_id()];
1734 xt_entry_foreach(iter0, entry0, total_size) {
1735 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1736 name, newinfo, entry1);
1740 xt_compat_flush_offsets(AF_INET);
1741 xt_compat_unlock(AF_INET);
1746 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1750 xt_entry_foreach(iter1, entry1, newinfo->size) {
1751 ret = compat_check_entry(iter1, net, name);
1758 * The first i matches need cleanup_entry (calls ->destroy)
1759 * because they had called ->check already. The other j-i
1760 * entries need only release.
1764 xt_entry_foreach(iter0, entry0, newinfo->size) {
1769 compat_release_entry(iter0);
1771 xt_entry_foreach(iter1, entry1, newinfo->size) {
1774 cleanup_entry(iter1, net);
1776 xt_free_table_info(newinfo);
1780 /* And one copy for every other CPU */
1781 for_each_possible_cpu(i)
1782 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1783 memcpy(newinfo->entries[i], entry1, newinfo->size);
1787 xt_free_table_info(info);
1791 xt_free_table_info(newinfo);
1793 xt_entry_foreach(iter0, entry0, total_size) {
1796 compat_release_entry(iter0);
1800 xt_compat_flush_offsets(AF_INET);
1801 xt_compat_unlock(AF_INET);
1806 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1809 struct compat_ipt_replace tmp;
1810 struct xt_table_info *newinfo;
1811 void *loc_cpu_entry;
1812 struct ipt_entry *iter;
1814 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1817 /* overflow check */
1818 if (tmp.size >= INT_MAX / num_possible_cpus())
1820 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1823 newinfo = xt_alloc_table_info(tmp.size);
1827 /* choose the copy that is on our node/cpu */
1828 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1829 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1835 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1836 &newinfo, &loc_cpu_entry, tmp.size,
1837 tmp.num_entries, tmp.hook_entry,
1842 duprintf("compat_do_replace: Translated table\n");
1844 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1845 tmp.num_counters, compat_ptr(tmp.counters));
1847 goto free_newinfo_untrans;
1850 free_newinfo_untrans:
1851 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1852 cleanup_entry(iter, net);
1854 xt_free_table_info(newinfo);
1859 compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
1864 if (!capable(CAP_NET_ADMIN))
1868 case IPT_SO_SET_REPLACE:
1869 ret = compat_do_replace(sock_net(sk), user, len);
1872 case IPT_SO_SET_ADD_COUNTERS:
1873 ret = do_add_counters(sock_net(sk), user, len, 1);
1877 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
1884 struct compat_ipt_get_entries {
1885 char name[IPT_TABLE_MAXNAMELEN];
1887 struct compat_ipt_entry entrytable[0];
1891 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1892 void __user *userptr)
1894 struct xt_counters *counters;
1895 const struct xt_table_info *private = table->private;
1899 const void *loc_cpu_entry;
1901 struct ipt_entry *iter;
1903 counters = alloc_counters(table);
1904 if (IS_ERR(counters))
1905 return PTR_ERR(counters);
1907 /* choose the copy that is on our node/cpu, ...
1908 * This choice is lazy (because current thread is
1909 * allowed to migrate to another cpu)
1911 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1914 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1915 ret = compat_copy_entry_to_user(iter, &pos,
1916 &size, counters, i++);
1926 compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1930 struct compat_ipt_get_entries get;
1933 if (*len < sizeof(get)) {
1934 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1938 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1941 if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
1942 duprintf("compat_get_entries: %u != %zu\n",
1943 *len, sizeof(get) + get.size);
1947 xt_compat_lock(AF_INET);
1948 t = xt_find_table_lock(net, AF_INET, get.name);
1949 if (t && !IS_ERR(t)) {
1950 const struct xt_table_info *private = t->private;
1951 struct xt_table_info info;
1952 duprintf("t->private->number = %u\n", private->number);
1953 ret = compat_table_info(private, &info);
1954 if (!ret && get.size == info.size) {
1955 ret = compat_copy_entries_to_user(private->size,
1956 t, uptr->entrytable);
1958 duprintf("compat_get_entries: I've got %u not %u!\n",
1959 private->size, get.size);
1962 xt_compat_flush_offsets(AF_INET);
1966 ret = t ? PTR_ERR(t) : -ENOENT;
1968 xt_compat_unlock(AF_INET);
1972 static int do_ipt_get_ctl(struct sock *, int, void __user *, int *);
1975 compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1979 if (!capable(CAP_NET_ADMIN))
1983 case IPT_SO_GET_INFO:
1984 ret = get_info(sock_net(sk), user, len, 1);
1986 case IPT_SO_GET_ENTRIES:
1987 ret = compat_get_entries(sock_net(sk), user, len);
1990 ret = do_ipt_get_ctl(sk, cmd, user, len);
1997 do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2001 if (!capable(CAP_NET_ADMIN))
2005 case IPT_SO_SET_REPLACE:
2006 ret = do_replace(sock_net(sk), user, len);
2009 case IPT_SO_SET_ADD_COUNTERS:
2010 ret = do_add_counters(sock_net(sk), user, len, 0);
2014 duprintf("do_ipt_set_ctl: unknown request %i\n", cmd);
2022 do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2026 if (!capable(CAP_NET_ADMIN))
2030 case IPT_SO_GET_INFO:
2031 ret = get_info(sock_net(sk), user, len, 0);
2034 case IPT_SO_GET_ENTRIES:
2035 ret = get_entries(sock_net(sk), user, len);
2038 case IPT_SO_GET_REVISION_MATCH:
2039 case IPT_SO_GET_REVISION_TARGET: {
2040 struct ipt_get_revision rev;
2043 if (*len != sizeof(rev)) {
2047 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2052 if (cmd == IPT_SO_GET_REVISION_TARGET)
2057 try_then_request_module(xt_find_revision(AF_INET, rev.name,
2060 "ipt_%s", rev.name);
2065 duprintf("do_ipt_get_ctl: unknown request %i\n", cmd);
2072 struct xt_table *ipt_register_table(struct net *net,
2073 const struct xt_table *table,
2074 const struct ipt_replace *repl)
2077 struct xt_table_info *newinfo;
2078 struct xt_table_info bootstrap = {0};
2079 void *loc_cpu_entry;
2080 struct xt_table *new_table;
2082 newinfo = xt_alloc_table_info(repl->size);
2088 /* choose the copy on our node/cpu, but dont care about preemption */
2089 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2090 memcpy(loc_cpu_entry, repl->entries, repl->size);
2092 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2096 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2097 if (IS_ERR(new_table)) {
2098 ret = PTR_ERR(new_table);
2105 xt_free_table_info(newinfo);
2107 return ERR_PTR(ret);
2110 void ipt_unregister_table(struct net *net, struct xt_table *table)
2112 struct xt_table_info *private;
2113 void *loc_cpu_entry;
2114 struct module *table_owner = table->me;
2115 struct ipt_entry *iter;
2117 private = xt_unregister_table(table);
2119 /* Decrease module usage counts and free resources */
2120 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2121 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2122 cleanup_entry(iter, net);
2123 if (private->number > private->initial_entries)
2124 module_put(table_owner);
2125 xt_free_table_info(private);
2128 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2130 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2131 u_int8_t type, u_int8_t code,
2134 return ((test_type == 0xFF) ||
2135 (type == test_type && code >= min_code && code <= max_code))
2140 icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
2142 const struct icmphdr *ic;
2143 struct icmphdr _icmph;
2144 const struct ipt_icmp *icmpinfo = par->matchinfo;
2146 /* Must not be a fragment. */
2147 if (par->fragoff != 0)
2150 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2152 /* We've been asked to examine this packet, and we
2153 * can't. Hence, no choice but to drop.
2155 duprintf("Dropping evil ICMP tinygram.\n");
2156 par->hotdrop = true;
2160 return icmp_type_code_match(icmpinfo->type,
2164 !!(icmpinfo->invflags&IPT_ICMP_INV));
2167 static int icmp_checkentry(const struct xt_mtchk_param *par)
2169 const struct ipt_icmp *icmpinfo = par->matchinfo;
2171 /* Must specify no unknown invflags */
2172 return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
2175 /* The built-in targets: standard (NULL) and error. */
2176 static struct xt_target ipt_standard_target __read_mostly = {
2177 .name = IPT_STANDARD_TARGET,
2178 .targetsize = sizeof(int),
2179 .family = NFPROTO_IPV4,
2180 #ifdef CONFIG_COMPAT
2181 .compatsize = sizeof(compat_int_t),
2182 .compat_from_user = compat_standard_from_user,
2183 .compat_to_user = compat_standard_to_user,
2187 static struct xt_target ipt_error_target __read_mostly = {
2188 .name = IPT_ERROR_TARGET,
2189 .target = ipt_error,
2190 .targetsize = IPT_FUNCTION_MAXNAMELEN,
2191 .family = NFPROTO_IPV4,
2194 static struct nf_sockopt_ops ipt_sockopts = {
2196 .set_optmin = IPT_BASE_CTL,
2197 .set_optmax = IPT_SO_SET_MAX+1,
2198 .set = do_ipt_set_ctl,
2199 #ifdef CONFIG_COMPAT
2200 .compat_set = compat_do_ipt_set_ctl,
2202 .get_optmin = IPT_BASE_CTL,
2203 .get_optmax = IPT_SO_GET_MAX+1,
2204 .get = do_ipt_get_ctl,
2205 #ifdef CONFIG_COMPAT
2206 .compat_get = compat_do_ipt_get_ctl,
2208 .owner = THIS_MODULE,
2211 static struct xt_match icmp_matchstruct __read_mostly = {
2213 .match = icmp_match,
2214 .matchsize = sizeof(struct ipt_icmp),
2215 .checkentry = icmp_checkentry,
2216 .proto = IPPROTO_ICMP,
2217 .family = NFPROTO_IPV4,
2220 static int __net_init ip_tables_net_init(struct net *net)
2222 return xt_proto_init(net, NFPROTO_IPV4);
2225 static void __net_exit ip_tables_net_exit(struct net *net)
2227 xt_proto_fini(net, NFPROTO_IPV4);
2230 static struct pernet_operations ip_tables_net_ops = {
2231 .init = ip_tables_net_init,
2232 .exit = ip_tables_net_exit,
2235 static int __init ip_tables_init(void)
2239 ret = register_pernet_subsys(&ip_tables_net_ops);
2243 /* Noone else will be downing sem now, so we won't sleep */
2244 ret = xt_register_target(&ipt_standard_target);
2247 ret = xt_register_target(&ipt_error_target);
2250 ret = xt_register_match(&icmp_matchstruct);
2254 /* Register setsockopt */
2255 ret = nf_register_sockopt(&ipt_sockopts);
2259 pr_info("(C) 2000-2006 Netfilter Core Team\n");
2263 xt_unregister_match(&icmp_matchstruct);
2265 xt_unregister_target(&ipt_error_target);
2267 xt_unregister_target(&ipt_standard_target);
2269 unregister_pernet_subsys(&ip_tables_net_ops);
2274 static void __exit ip_tables_fini(void)
2276 nf_unregister_sockopt(&ipt_sockopts);
2278 xt_unregister_match(&icmp_matchstruct);
2279 xt_unregister_target(&ipt_error_target);
2280 xt_unregister_target(&ipt_standard_target);
2282 unregister_pernet_subsys(&ip_tables_net_ops);
2285 EXPORT_SYMBOL(ipt_register_table);
2286 EXPORT_SYMBOL(ipt_unregister_table);
2287 EXPORT_SYMBOL(ipt_do_table);
2288 module_init(ip_tables_init);
2289 module_exit(ip_tables_fini);