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/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/poison.h>
20 #include <linux/icmpv6.h>
22 #include <net/compat.h>
23 #include <asm/uaccess.h>
24 #include <linux/mutex.h>
25 #include <linux/proc_fs.h>
26 #include <linux/err.h>
27 #include <linux/cpumask.h>
29 #include <linux/netfilter_ipv6/ip6_tables.h>
30 #include <linux/netfilter/x_tables.h>
31 #include <net/netfilter/nf_log.h>
32 #include "../../netfilter/xt_repldata.h"
34 MODULE_LICENSE("GPL");
35 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
36 MODULE_DESCRIPTION("IPv6 packet filter");
38 /*#define DEBUG_IP_FIREWALL*/
39 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
40 /*#define DEBUG_IP_FIREWALL_USER*/
42 #ifdef DEBUG_IP_FIREWALL
43 #define dprintf(format, args...) printk(format , ## args)
45 #define dprintf(format, args...)
48 #ifdef DEBUG_IP_FIREWALL_USER
49 #define duprintf(format, args...) printk(format , ## args)
51 #define duprintf(format, args...)
54 #ifdef CONFIG_NETFILTER_DEBUG
55 #define IP_NF_ASSERT(x) \
58 printk("IP_NF_ASSERT: %s:%s:%u\n", \
59 __func__, __FILE__, __LINE__); \
62 #define IP_NF_ASSERT(x)
66 /* All the better to debug you with... */
71 void *ip6t_alloc_initial_table(const struct xt_table *info)
73 return xt_alloc_initial_table(ip6t, IP6T);
75 EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);
78 We keep a set of rules for each CPU, so we can avoid write-locking
79 them in the softirq when updating the counters and therefore
80 only need to read-lock in the softirq; doing a write_lock_bh() in user
81 context stops packets coming through and allows user context to read
82 the counters or update the rules.
84 Hence the start of any table is given by get_table() below. */
86 /* Check for an extension */
88 ip6t_ext_hdr(u8 nexthdr)
90 return ( (nexthdr == IPPROTO_HOPOPTS) ||
91 (nexthdr == IPPROTO_ROUTING) ||
92 (nexthdr == IPPROTO_FRAGMENT) ||
93 (nexthdr == IPPROTO_ESP) ||
94 (nexthdr == IPPROTO_AH) ||
95 (nexthdr == IPPROTO_NONE) ||
96 (nexthdr == IPPROTO_DSTOPTS) );
99 /* Returns whether matches rule or not. */
100 /* Performance critical - called for every packet */
102 ip6_packet_match(const struct sk_buff *skb,
105 const struct ip6t_ip6 *ip6info,
106 unsigned int *protoff,
107 int *fragoff, bool *hotdrop)
110 const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
112 #define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg)))
114 if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
115 &ip6info->src), IP6T_INV_SRCIP) ||
116 FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
117 &ip6info->dst), IP6T_INV_DSTIP)) {
118 dprintf("Source or dest mismatch.\n");
120 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
121 ipinfo->smsk.s_addr, ipinfo->src.s_addr,
122 ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : "");
123 dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
124 ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
125 ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
129 ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask);
131 if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
132 dprintf("VIA in mismatch (%s vs %s).%s\n",
133 indev, ip6info->iniface,
134 ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
138 ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask);
140 if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
141 dprintf("VIA out mismatch (%s vs %s).%s\n",
142 outdev, ip6info->outiface,
143 ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
147 /* ... might want to do something with class and flowlabel here ... */
149 /* look for the desired protocol header */
150 if((ip6info->flags & IP6T_F_PROTO)) {
152 unsigned short _frag_off;
154 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
160 *fragoff = _frag_off;
162 dprintf("Packet protocol %hi ?= %s%hi.\n",
164 ip6info->invflags & IP6T_INV_PROTO ? "!":"",
167 if (ip6info->proto == protohdr) {
168 if(ip6info->invflags & IP6T_INV_PROTO) {
174 /* We need match for the '-p all', too! */
175 if ((ip6info->proto != 0) &&
176 !(ip6info->invflags & IP6T_INV_PROTO))
182 /* should be ip6 safe */
184 ip6_checkentry(const struct ip6t_ip6 *ipv6)
186 if (ipv6->flags & ~IP6T_F_MASK) {
187 duprintf("Unknown flag bits set: %08X\n",
188 ipv6->flags & ~IP6T_F_MASK);
191 if (ipv6->invflags & ~IP6T_INV_MASK) {
192 duprintf("Unknown invflag bits set: %08X\n",
193 ipv6->invflags & ~IP6T_INV_MASK);
200 ip6t_error(struct sk_buff *skb, const struct xt_target_param *par)
203 printk("ip6_tables: error: `%s'\n",
204 (const char *)par->targinfo);
209 /* Performance critical - called for every packet */
211 do_match(const struct ip6t_entry_match *m, const struct sk_buff *skb,
212 struct xt_match_param *par)
214 par->match = m->u.kernel.match;
215 par->matchinfo = m->data;
217 /* Stop iteration if it doesn't match */
218 if (!m->u.kernel.match->match(skb, par))
224 static inline struct ip6t_entry *
225 get_entry(const void *base, unsigned int offset)
227 return (struct ip6t_entry *)(base + offset);
230 /* All zeroes == unconditional rule. */
231 /* Mildly perf critical (only if packet tracing is on) */
232 static inline bool unconditional(const struct ip6t_ip6 *ipv6)
234 static const struct ip6t_ip6 uncond;
236 return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
239 static inline const struct ip6t_entry_target *
240 ip6t_get_target_c(const struct ip6t_entry *e)
242 return ip6t_get_target((struct ip6t_entry *)e);
245 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
246 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
247 /* This cries for unification! */
248 static const char *const hooknames[] = {
249 [NF_INET_PRE_ROUTING] = "PREROUTING",
250 [NF_INET_LOCAL_IN] = "INPUT",
251 [NF_INET_FORWARD] = "FORWARD",
252 [NF_INET_LOCAL_OUT] = "OUTPUT",
253 [NF_INET_POST_ROUTING] = "POSTROUTING",
256 enum nf_ip_trace_comments {
257 NF_IP6_TRACE_COMMENT_RULE,
258 NF_IP6_TRACE_COMMENT_RETURN,
259 NF_IP6_TRACE_COMMENT_POLICY,
262 static const char *const comments[] = {
263 [NF_IP6_TRACE_COMMENT_RULE] = "rule",
264 [NF_IP6_TRACE_COMMENT_RETURN] = "return",
265 [NF_IP6_TRACE_COMMENT_POLICY] = "policy",
268 static struct nf_loginfo trace_loginfo = {
269 .type = NF_LOG_TYPE_LOG,
273 .logflags = NF_LOG_MASK,
278 /* Mildly perf critical (only if packet tracing is on) */
280 get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
281 const char *hookname, const char **chainname,
282 const char **comment, unsigned int *rulenum)
284 const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s);
286 if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
287 /* Head of user chain: ERROR target with chainname */
288 *chainname = t->target.data;
293 if (s->target_offset == sizeof(struct ip6t_entry) &&
294 strcmp(t->target.u.kernel.target->name,
295 IP6T_STANDARD_TARGET) == 0 &&
297 unconditional(&s->ipv6)) {
298 /* Tail of chains: STANDARD target (return/policy) */
299 *comment = *chainname == hookname
300 ? comments[NF_IP6_TRACE_COMMENT_POLICY]
301 : comments[NF_IP6_TRACE_COMMENT_RETURN];
310 static void trace_packet(const struct sk_buff *skb,
312 const struct net_device *in,
313 const struct net_device *out,
314 const char *tablename,
315 const struct xt_table_info *private,
316 const struct ip6t_entry *e)
318 const void *table_base;
319 const struct ip6t_entry *root;
320 const char *hookname, *chainname, *comment;
321 const struct ip6t_entry *iter;
322 unsigned int rulenum = 0;
324 table_base = private->entries[smp_processor_id()];
325 root = get_entry(table_base, private->hook_entry[hook]);
327 hookname = chainname = hooknames[hook];
328 comment = comments[NF_IP6_TRACE_COMMENT_RULE];
330 xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
331 if (get_chainname_rulenum(iter, e, hookname,
332 &chainname, &comment, &rulenum) != 0)
335 nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
336 "TRACE: %s:%s:%s:%u ",
337 tablename, chainname, comment, rulenum);
341 static inline __pure struct ip6t_entry *
342 ip6t_next_entry(const struct ip6t_entry *entry)
344 return (void *)entry + entry->next_offset;
347 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
349 ip6t_do_table(struct sk_buff *skb,
351 const struct net_device *in,
352 const struct net_device *out,
353 struct xt_table *table)
355 #define tb_comefrom ((struct ip6t_entry *)table_base)->comefrom
357 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
358 bool hotdrop = false;
359 /* Initializing verdict to NF_DROP keeps gcc happy. */
360 unsigned int verdict = NF_DROP;
361 const char *indev, *outdev;
362 const void *table_base;
363 struct ip6t_entry *e, *back;
364 const struct xt_table_info *private;
365 struct xt_match_param mtpar;
366 struct xt_target_param tgpar;
369 indev = in ? in->name : nulldevname;
370 outdev = out ? out->name : nulldevname;
371 /* We handle fragments by dealing with the first fragment as
372 * if it was a normal packet. All other fragments are treated
373 * normally, except that they will NEVER match rules that ask
374 * things we don't know, ie. tcp syn flag or ports). If the
375 * rule is also a fragment-specific rule, non-fragments won't
377 mtpar.hotdrop = &hotdrop;
378 mtpar.in = tgpar.in = in;
379 mtpar.out = tgpar.out = out;
380 mtpar.family = tgpar.family = NFPROTO_IPV6;
381 mtpar.hooknum = tgpar.hooknum = hook;
383 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
386 private = table->private;
387 table_base = private->entries[smp_processor_id()];
389 e = get_entry(table_base, private->hook_entry[hook]);
391 /* For return from builtin chain */
392 back = get_entry(table_base, private->underflow[hook]);
395 const struct ip6t_entry_target *t;
396 const struct xt_entry_match *ematch;
400 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
401 &mtpar.thoff, &mtpar.fragoff, &hotdrop)) {
403 e = ip6t_next_entry(e);
407 xt_ematch_foreach(ematch, e)
408 if (do_match(ematch, skb, &mtpar) != 0)
411 ADD_COUNTER(e->counters,
412 ntohs(ipv6_hdr(skb)->payload_len) +
413 sizeof(struct ipv6hdr), 1);
415 t = ip6t_get_target_c(e);
416 IP_NF_ASSERT(t->u.kernel.target);
418 #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
419 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
420 /* The packet is traced: log it */
421 if (unlikely(skb->nf_trace))
422 trace_packet(skb, hook, in, out,
423 table->name, private, e);
425 /* Standard target? */
426 if (!t->u.kernel.target->target) {
429 v = ((struct ip6t_standard_target *)t)->verdict;
431 /* Pop from stack? */
432 if (v != IP6T_RETURN) {
433 verdict = (unsigned)(-v) - 1;
437 back = get_entry(table_base, back->comefrom);
440 if (table_base + v != ip6t_next_entry(e) &&
441 !(e->ipv6.flags & IP6T_F_GOTO)) {
442 /* Save old back ptr in next entry */
443 struct ip6t_entry *next = ip6t_next_entry(e);
444 next->comefrom = (void *)back - table_base;
445 /* set back pointer to next entry */
449 e = get_entry(table_base, v);
453 /* Targets which reenter must return
455 tgpar.target = t->u.kernel.target;
456 tgpar.targinfo = t->data;
458 #ifdef CONFIG_NETFILTER_DEBUG
459 tb_comefrom = 0xeeeeeeec;
461 verdict = t->u.kernel.target->target(skb, &tgpar);
463 #ifdef CONFIG_NETFILTER_DEBUG
464 if (tb_comefrom != 0xeeeeeeec && verdict == IP6T_CONTINUE) {
465 printk("Target %s reentered!\n",
466 t->u.kernel.target->name);
469 tb_comefrom = 0x57acc001;
471 if (verdict == IP6T_CONTINUE)
472 e = ip6t_next_entry(e);
478 #ifdef CONFIG_NETFILTER_DEBUG
479 tb_comefrom = NETFILTER_LINK_POISON;
481 xt_info_rdunlock_bh();
483 #ifdef DEBUG_ALLOW_ALL
494 /* Figures out from what hook each rule can be called: returns 0 if
495 there are loops. Puts hook bitmask in comefrom. */
497 mark_source_chains(const struct xt_table_info *newinfo,
498 unsigned int valid_hooks, void *entry0)
502 /* No recursion; use packet counter to save back ptrs (reset
503 to 0 as we leave), and comefrom to save source hook bitmask */
504 for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
505 unsigned int pos = newinfo->hook_entry[hook];
506 struct ip6t_entry *e = (struct ip6t_entry *)(entry0 + pos);
508 if (!(valid_hooks & (1 << hook)))
511 /* Set initial back pointer. */
512 e->counters.pcnt = pos;
515 const struct ip6t_standard_target *t
516 = (void *)ip6t_get_target_c(e);
517 int visited = e->comefrom & (1 << hook);
519 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
520 printk("iptables: loop hook %u pos %u %08X.\n",
521 hook, pos, e->comefrom);
524 e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
526 /* Unconditional return/END. */
527 if ((e->target_offset == sizeof(struct ip6t_entry) &&
528 (strcmp(t->target.u.user.name,
529 IP6T_STANDARD_TARGET) == 0) &&
531 unconditional(&e->ipv6)) || visited) {
532 unsigned int oldpos, size;
534 if ((strcmp(t->target.u.user.name,
535 IP6T_STANDARD_TARGET) == 0) &&
536 t->verdict < -NF_MAX_VERDICT - 1) {
537 duprintf("mark_source_chains: bad "
538 "negative verdict (%i)\n",
543 /* Return: backtrack through the last
546 e->comefrom ^= (1<<NF_INET_NUMHOOKS);
547 #ifdef DEBUG_IP_FIREWALL_USER
549 & (1 << NF_INET_NUMHOOKS)) {
550 duprintf("Back unset "
557 pos = e->counters.pcnt;
558 e->counters.pcnt = 0;
560 /* We're at the start. */
564 e = (struct ip6t_entry *)
566 } while (oldpos == pos + e->next_offset);
569 size = e->next_offset;
570 e = (struct ip6t_entry *)
571 (entry0 + pos + size);
572 e->counters.pcnt = pos;
575 int newpos = t->verdict;
577 if (strcmp(t->target.u.user.name,
578 IP6T_STANDARD_TARGET) == 0 &&
580 if (newpos > newinfo->size -
581 sizeof(struct ip6t_entry)) {
582 duprintf("mark_source_chains: "
583 "bad verdict (%i)\n",
587 /* This a jump; chase it. */
588 duprintf("Jump rule %u -> %u\n",
591 /* ... this is a fallthru */
592 newpos = pos + e->next_offset;
594 e = (struct ip6t_entry *)
596 e->counters.pcnt = pos;
601 duprintf("Finished chain %u\n", hook);
606 static void cleanup_match(struct ip6t_entry_match *m, struct net *net)
608 struct xt_mtdtor_param par;
611 par.match = m->u.kernel.match;
612 par.matchinfo = m->data;
613 par.family = NFPROTO_IPV6;
614 if (par.match->destroy != NULL)
615 par.match->destroy(&par);
616 module_put(par.match->me);
620 check_entry(const struct ip6t_entry *e, const char *name)
622 const struct ip6t_entry_target *t;
624 if (!ip6_checkentry(&e->ipv6)) {
625 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
629 if (e->target_offset + sizeof(struct ip6t_entry_target) >
633 t = ip6t_get_target_c(e);
634 if (e->target_offset + t->u.target_size > e->next_offset)
640 static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
642 const struct ip6t_ip6 *ipv6 = par->entryinfo;
645 par->match = m->u.kernel.match;
646 par->matchinfo = m->data;
648 ret = xt_check_match(par, m->u.match_size - sizeof(*m),
649 ipv6->proto, ipv6->invflags & IP6T_INV_PROTO);
651 duprintf("ip_tables: check failed for `%s'.\n",
659 find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)
661 struct xt_match *match;
664 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
666 "ip6t_%s", m->u.user.name);
667 if (IS_ERR(match) || !match) {
668 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
669 return match ? PTR_ERR(match) : -ENOENT;
671 m->u.kernel.match = match;
673 ret = check_match(m, par);
679 module_put(m->u.kernel.match->me);
683 static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
685 struct ip6t_entry_target *t = ip6t_get_target(e);
686 struct xt_tgchk_param par = {
690 .target = t->u.kernel.target,
692 .hook_mask = e->comefrom,
693 .family = NFPROTO_IPV6,
697 t = ip6t_get_target(e);
698 ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
699 e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
701 duprintf("ip_tables: check failed for `%s'.\n",
702 t->u.kernel.target->name);
709 find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
712 struct ip6t_entry_target *t;
713 struct xt_target *target;
716 struct xt_mtchk_param mtpar;
717 struct xt_entry_match *ematch;
719 ret = check_entry(e, name);
726 mtpar.entryinfo = &e->ipv6;
727 mtpar.hook_mask = e->comefrom;
728 mtpar.family = NFPROTO_IPV6;
729 xt_ematch_foreach(ematch, e) {
730 ret = find_check_match(ematch, &mtpar);
732 goto cleanup_matches;
736 t = ip6t_get_target(e);
737 target = try_then_request_module(xt_find_target(AF_INET6,
740 "ip6t_%s", t->u.user.name);
741 if (IS_ERR(target) || !target) {
742 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
743 ret = target ? PTR_ERR(target) : -ENOENT;
744 goto cleanup_matches;
746 t->u.kernel.target = target;
748 ret = check_target(e, net, name);
753 module_put(t->u.kernel.target->me);
755 xt_ematch_foreach(ematch, e) {
758 cleanup_match(ematch, net);
763 static bool check_underflow(const struct ip6t_entry *e)
765 const struct ip6t_entry_target *t;
766 unsigned int verdict;
768 if (!unconditional(&e->ipv6))
770 t = ip6t_get_target_c(e);
771 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
773 verdict = ((struct ip6t_standard_target *)t)->verdict;
774 verdict = -verdict - 1;
775 return verdict == NF_DROP || verdict == NF_ACCEPT;
779 check_entry_size_and_hooks(struct ip6t_entry *e,
780 struct xt_table_info *newinfo,
781 const unsigned char *base,
782 const unsigned char *limit,
783 const unsigned int *hook_entries,
784 const unsigned int *underflows,
785 unsigned int valid_hooks)
789 if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 ||
790 (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
791 duprintf("Bad offset %p\n", e);
796 < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
797 duprintf("checking: element %p size %u\n",
802 /* Check hooks & underflows */
803 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
804 if (!(valid_hooks & (1 << h)))
806 if ((unsigned char *)e - base == hook_entries[h])
807 newinfo->hook_entry[h] = hook_entries[h];
808 if ((unsigned char *)e - base == underflows[h]) {
809 if (!check_underflow(e)) {
810 pr_err("Underflows must be unconditional and "
811 "use the STANDARD target with "
815 newinfo->underflow[h] = underflows[h];
819 /* Clear counters and comefrom */
820 e->counters = ((struct xt_counters) { 0, 0 });
825 static void cleanup_entry(struct ip6t_entry *e, struct net *net)
827 struct xt_tgdtor_param par;
828 struct ip6t_entry_target *t;
829 struct xt_entry_match *ematch;
831 /* Cleanup all matches */
832 xt_ematch_foreach(ematch, e)
833 cleanup_match(ematch, net);
834 t = ip6t_get_target(e);
837 par.target = t->u.kernel.target;
838 par.targinfo = t->data;
839 par.family = NFPROTO_IPV6;
840 if (par.target->destroy != NULL)
841 par.target->destroy(&par);
842 module_put(par.target->me);
845 /* Checks and translates the user-supplied table segment (held in
848 translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
849 const struct ip6t_replace *repl)
851 struct ip6t_entry *iter;
855 newinfo->size = repl->size;
856 newinfo->number = repl->num_entries;
858 /* Init all hooks to impossible value. */
859 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
860 newinfo->hook_entry[i] = 0xFFFFFFFF;
861 newinfo->underflow[i] = 0xFFFFFFFF;
864 duprintf("translate_table: size %u\n", newinfo->size);
866 /* Walk through entries, checking offsets. */
867 xt_entry_foreach(iter, entry0, newinfo->size) {
868 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
878 if (i != repl->num_entries) {
879 duprintf("translate_table: %u not %u entries\n",
880 i, repl->num_entries);
884 /* Check hooks all assigned */
885 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
886 /* Only hooks which are valid */
887 if (!(repl->valid_hooks & (1 << i)))
889 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
890 duprintf("Invalid hook entry %u %u\n",
891 i, repl->hook_entry[i]);
894 if (newinfo->underflow[i] == 0xFFFFFFFF) {
895 duprintf("Invalid underflow %u %u\n",
896 i, repl->underflow[i]);
901 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
904 /* Finally, each sanity check must pass */
906 xt_entry_foreach(iter, entry0, newinfo->size) {
907 ret = find_check_entry(iter, net, repl->name, repl->size);
914 xt_entry_foreach(iter, entry0, newinfo->size) {
917 cleanup_entry(iter, net);
922 /* And one copy for every other CPU */
923 for_each_possible_cpu(i) {
924 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
925 memcpy(newinfo->entries[i], entry0, newinfo->size);
932 get_counters(const struct xt_table_info *t,
933 struct xt_counters counters[])
935 struct ip6t_entry *iter;
940 /* Instead of clearing (by a previous call to memset())
941 * the counters and using adds, we set the counters
942 * with data used by 'current' CPU
944 * Bottom half has to be disabled to prevent deadlock
945 * if new softirq were to run and call ipt_do_table
948 curcpu = smp_processor_id();
951 xt_entry_foreach(iter, t->entries[curcpu], t->size) {
952 SET_COUNTER(counters[i], iter->counters.bcnt,
953 iter->counters.pcnt);
957 for_each_possible_cpu(cpu) {
962 xt_entry_foreach(iter, t->entries[cpu], t->size) {
963 ADD_COUNTER(counters[i], iter->counters.bcnt,
964 iter->counters.pcnt);
967 xt_info_wrunlock(cpu);
972 static struct xt_counters *alloc_counters(const struct xt_table *table)
974 unsigned int countersize;
975 struct xt_counters *counters;
976 const struct xt_table_info *private = table->private;
978 /* We need atomic snapshot of counters: rest doesn't change
979 (other than comefrom, which userspace doesn't care
981 countersize = sizeof(struct xt_counters) * private->number;
982 counters = vmalloc_node(countersize, numa_node_id());
984 if (counters == NULL)
985 return ERR_PTR(-ENOMEM);
987 get_counters(private, counters);
993 copy_entries_to_user(unsigned int total_size,
994 const struct xt_table *table,
995 void __user *userptr)
997 unsigned int off, num;
998 const struct ip6t_entry *e;
999 struct xt_counters *counters;
1000 const struct xt_table_info *private = table->private;
1002 const void *loc_cpu_entry;
1004 counters = alloc_counters(table);
1005 if (IS_ERR(counters))
1006 return PTR_ERR(counters);
1008 /* choose the copy that is on our node/cpu, ...
1009 * This choice is lazy (because current thread is
1010 * allowed to migrate to another cpu)
1012 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1013 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
1018 /* FIXME: use iterator macros --RR */
1019 /* ... then go back and fix counters and names */
1020 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
1022 const struct ip6t_entry_match *m;
1023 const struct ip6t_entry_target *t;
1025 e = (struct ip6t_entry *)(loc_cpu_entry + off);
1026 if (copy_to_user(userptr + off
1027 + offsetof(struct ip6t_entry, counters),
1029 sizeof(counters[num])) != 0) {
1034 for (i = sizeof(struct ip6t_entry);
1035 i < e->target_offset;
1036 i += m->u.match_size) {
1039 if (copy_to_user(userptr + off + i
1040 + offsetof(struct ip6t_entry_match,
1042 m->u.kernel.match->name,
1043 strlen(m->u.kernel.match->name)+1)
1050 t = ip6t_get_target_c(e);
1051 if (copy_to_user(userptr + off + e->target_offset
1052 + offsetof(struct ip6t_entry_target,
1054 t->u.kernel.target->name,
1055 strlen(t->u.kernel.target->name)+1) != 0) {
1066 #ifdef CONFIG_COMPAT
1067 static void compat_standard_from_user(void *dst, const void *src)
1069 int v = *(compat_int_t *)src;
1072 v += xt_compat_calc_jump(AF_INET6, v);
1073 memcpy(dst, &v, sizeof(v));
1076 static int compat_standard_to_user(void __user *dst, const void *src)
1078 compat_int_t cv = *(int *)src;
1081 cv -= xt_compat_calc_jump(AF_INET6, cv);
1082 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
1085 static int compat_calc_entry(const struct ip6t_entry *e,
1086 const struct xt_table_info *info,
1087 const void *base, struct xt_table_info *newinfo)
1089 const struct xt_entry_match *ematch;
1090 const struct ip6t_entry_target *t;
1091 unsigned int entry_offset;
1094 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1095 entry_offset = (void *)e - base;
1096 xt_ematch_foreach(ematch, e)
1097 off += xt_compat_match_offset(ematch->u.kernel.match);
1098 t = ip6t_get_target_c(e);
1099 off += xt_compat_target_offset(t->u.kernel.target);
1100 newinfo->size -= off;
1101 ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
1105 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1106 if (info->hook_entry[i] &&
1107 (e < (struct ip6t_entry *)(base + info->hook_entry[i])))
1108 newinfo->hook_entry[i] -= off;
1109 if (info->underflow[i] &&
1110 (e < (struct ip6t_entry *)(base + info->underflow[i])))
1111 newinfo->underflow[i] -= off;
1116 static int compat_table_info(const struct xt_table_info *info,
1117 struct xt_table_info *newinfo)
1119 struct ip6t_entry *iter;
1120 void *loc_cpu_entry;
1123 if (!newinfo || !info)
1126 /* we dont care about newinfo->entries[] */
1127 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1128 newinfo->initial_entries = 0;
1129 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1130 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1131 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1139 static int get_info(struct net *net, void __user *user,
1140 const int *len, int compat)
1142 char name[IP6T_TABLE_MAXNAMELEN];
1146 if (*len != sizeof(struct ip6t_getinfo)) {
1147 duprintf("length %u != %zu\n", *len,
1148 sizeof(struct ip6t_getinfo));
1152 if (copy_from_user(name, user, sizeof(name)) != 0)
1155 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1156 #ifdef CONFIG_COMPAT
1158 xt_compat_lock(AF_INET6);
1160 t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
1161 "ip6table_%s", name);
1162 if (t && !IS_ERR(t)) {
1163 struct ip6t_getinfo info;
1164 const struct xt_table_info *private = t->private;
1165 #ifdef CONFIG_COMPAT
1166 struct xt_table_info tmp;
1169 ret = compat_table_info(private, &tmp);
1170 xt_compat_flush_offsets(AF_INET6);
1174 info.valid_hooks = t->valid_hooks;
1175 memcpy(info.hook_entry, private->hook_entry,
1176 sizeof(info.hook_entry));
1177 memcpy(info.underflow, private->underflow,
1178 sizeof(info.underflow));
1179 info.num_entries = private->number;
1180 info.size = private->size;
1181 strcpy(info.name, name);
1183 if (copy_to_user(user, &info, *len) != 0)
1191 ret = t ? PTR_ERR(t) : -ENOENT;
1192 #ifdef CONFIG_COMPAT
1194 xt_compat_unlock(AF_INET6);
1200 get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
1204 struct ip6t_get_entries get;
1207 if (*len < sizeof(get)) {
1208 duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
1211 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1213 if (*len != sizeof(struct ip6t_get_entries) + get.size) {
1214 duprintf("get_entries: %u != %zu\n",
1215 *len, sizeof(get) + get.size);
1219 t = xt_find_table_lock(net, AF_INET6, get.name);
1220 if (t && !IS_ERR(t)) {
1221 struct xt_table_info *private = t->private;
1222 duprintf("t->private->number = %u\n", private->number);
1223 if (get.size == private->size)
1224 ret = copy_entries_to_user(private->size,
1225 t, uptr->entrytable);
1227 duprintf("get_entries: I've got %u not %u!\n",
1228 private->size, get.size);
1234 ret = t ? PTR_ERR(t) : -ENOENT;
1240 __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1241 struct xt_table_info *newinfo, unsigned int num_counters,
1242 void __user *counters_ptr)
1246 struct xt_table_info *oldinfo;
1247 struct xt_counters *counters;
1248 const void *loc_cpu_old_entry;
1249 struct ip6t_entry *iter;
1252 counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
1259 t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
1260 "ip6table_%s", name);
1261 if (!t || IS_ERR(t)) {
1262 ret = t ? PTR_ERR(t) : -ENOENT;
1263 goto free_newinfo_counters_untrans;
1267 if (valid_hooks != t->valid_hooks) {
1268 duprintf("Valid hook crap: %08X vs %08X\n",
1269 valid_hooks, t->valid_hooks);
1274 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
1278 /* Update module usage count based on number of rules */
1279 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1280 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1281 if ((oldinfo->number > oldinfo->initial_entries) ||
1282 (newinfo->number <= oldinfo->initial_entries))
1284 if ((oldinfo->number > oldinfo->initial_entries) &&
1285 (newinfo->number <= oldinfo->initial_entries))
1288 /* Get the old counters, and synchronize with replace */
1289 get_counters(oldinfo, counters);
1291 /* Decrease module usage counts and free resource */
1292 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1293 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1294 cleanup_entry(iter, net);
1296 xt_free_table_info(oldinfo);
1297 if (copy_to_user(counters_ptr, counters,
1298 sizeof(struct xt_counters) * num_counters) != 0)
1307 free_newinfo_counters_untrans:
1314 do_replace(struct net *net, const void __user *user, unsigned int len)
1317 struct ip6t_replace tmp;
1318 struct xt_table_info *newinfo;
1319 void *loc_cpu_entry;
1320 struct ip6t_entry *iter;
1322 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1325 /* overflow check */
1326 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1329 newinfo = xt_alloc_table_info(tmp.size);
1333 /* choose the copy that is on our node/cpu */
1334 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1335 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1341 ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
1345 duprintf("ip_tables: Translated table\n");
1347 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1348 tmp.num_counters, tmp.counters);
1350 goto free_newinfo_untrans;
1353 free_newinfo_untrans:
1354 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1355 cleanup_entry(iter, net);
1357 xt_free_table_info(newinfo);
1362 do_add_counters(struct net *net, const void __user *user, unsigned int len,
1365 unsigned int i, curcpu;
1366 struct xt_counters_info tmp;
1367 struct xt_counters *paddc;
1368 unsigned int num_counters;
1373 const struct xt_table_info *private;
1375 const void *loc_cpu_entry;
1376 struct ip6t_entry *iter;
1377 #ifdef CONFIG_COMPAT
1378 struct compat_xt_counters_info compat_tmp;
1382 size = sizeof(struct compat_xt_counters_info);
1387 size = sizeof(struct xt_counters_info);
1390 if (copy_from_user(ptmp, user, size) != 0)
1393 #ifdef CONFIG_COMPAT
1395 num_counters = compat_tmp.num_counters;
1396 name = compat_tmp.name;
1400 num_counters = tmp.num_counters;
1404 if (len != size + num_counters * sizeof(struct xt_counters))
1407 paddc = vmalloc_node(len - size, numa_node_id());
1411 if (copy_from_user(paddc, user + size, len - size) != 0) {
1416 t = xt_find_table_lock(net, AF_INET6, name);
1417 if (!t || IS_ERR(t)) {
1418 ret = t ? PTR_ERR(t) : -ENOENT;
1424 private = t->private;
1425 if (private->number != num_counters) {
1427 goto unlock_up_free;
1431 /* Choose the copy that is on our node */
1432 curcpu = smp_processor_id();
1433 xt_info_wrlock(curcpu);
1434 loc_cpu_entry = private->entries[curcpu];
1435 xt_entry_foreach(iter, loc_cpu_entry, private->size) {
1436 ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);
1439 xt_info_wrunlock(curcpu);
1451 #ifdef CONFIG_COMPAT
1452 struct compat_ip6t_replace {
1453 char name[IP6T_TABLE_MAXNAMELEN];
1457 u32 hook_entry[NF_INET_NUMHOOKS];
1458 u32 underflow[NF_INET_NUMHOOKS];
1460 compat_uptr_t counters; /* struct ip6t_counters * */
1461 struct compat_ip6t_entry entries[0];
1465 compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
1466 unsigned int *size, struct xt_counters *counters,
1469 struct ip6t_entry_target *t;
1470 struct compat_ip6t_entry __user *ce;
1471 u_int16_t target_offset, next_offset;
1472 compat_uint_t origsize;
1473 const struct xt_entry_match *ematch;
1477 ce = (struct compat_ip6t_entry __user *)*dstptr;
1478 if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 ||
1479 copy_to_user(&ce->counters, &counters[i],
1480 sizeof(counters[i])) != 0)
1483 *dstptr += sizeof(struct compat_ip6t_entry);
1484 *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1486 xt_ematch_foreach(ematch, e) {
1487 ret = xt_compat_match_to_user(ematch, dstptr, size);
1491 target_offset = e->target_offset - (origsize - *size);
1492 t = ip6t_get_target(e);
1493 ret = xt_compat_target_to_user(t, dstptr, size);
1496 next_offset = e->next_offset - (origsize - *size);
1497 if (put_user(target_offset, &ce->target_offset) != 0 ||
1498 put_user(next_offset, &ce->next_offset) != 0)
1504 compat_find_calc_match(struct ip6t_entry_match *m,
1506 const struct ip6t_ip6 *ipv6,
1507 unsigned int hookmask,
1510 struct xt_match *match;
1512 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
1513 m->u.user.revision),
1514 "ip6t_%s", m->u.user.name);
1515 if (IS_ERR(match) || !match) {
1516 duprintf("compat_check_calc_match: `%s' not found\n",
1518 return match ? PTR_ERR(match) : -ENOENT;
1520 m->u.kernel.match = match;
1521 *size += xt_compat_match_offset(match);
1525 static void compat_release_entry(struct compat_ip6t_entry *e)
1527 struct ip6t_entry_target *t;
1528 struct xt_entry_match *ematch;
1530 /* Cleanup all matches */
1531 xt_ematch_foreach(ematch, e)
1532 module_put(ematch->u.kernel.match->me);
1533 t = compat_ip6t_get_target(e);
1534 module_put(t->u.kernel.target->me);
1538 check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1539 struct xt_table_info *newinfo,
1541 const unsigned char *base,
1542 const unsigned char *limit,
1543 const unsigned int *hook_entries,
1544 const unsigned int *underflows,
1547 struct xt_entry_match *ematch;
1548 struct ip6t_entry_target *t;
1549 struct xt_target *target;
1550 unsigned int entry_offset;
1554 duprintf("check_compat_entry_size_and_hooks %p\n", e);
1555 if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
1556 (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) {
1557 duprintf("Bad offset %p, limit = %p\n", e, limit);
1561 if (e->next_offset < sizeof(struct compat_ip6t_entry) +
1562 sizeof(struct compat_xt_entry_target)) {
1563 duprintf("checking: element %p size %u\n",
1568 /* For purposes of check_entry casting the compat entry is fine */
1569 ret = check_entry((struct ip6t_entry *)e, name);
1573 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1574 entry_offset = (void *)e - (void *)base;
1576 xt_ematch_foreach(ematch, e) {
1577 ret = compat_find_calc_match(ematch, name,
1578 &e->ipv6, e->comefrom, &off);
1580 goto release_matches;
1584 t = compat_ip6t_get_target(e);
1585 target = try_then_request_module(xt_find_target(AF_INET6,
1587 t->u.user.revision),
1588 "ip6t_%s", t->u.user.name);
1589 if (IS_ERR(target) || !target) {
1590 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
1592 ret = target ? PTR_ERR(target) : -ENOENT;
1593 goto release_matches;
1595 t->u.kernel.target = target;
1597 off += xt_compat_target_offset(target);
1599 ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
1603 /* Check hooks & underflows */
1604 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1605 if ((unsigned char *)e - base == hook_entries[h])
1606 newinfo->hook_entry[h] = hook_entries[h];
1607 if ((unsigned char *)e - base == underflows[h])
1608 newinfo->underflow[h] = underflows[h];
1611 /* Clear counters and comefrom */
1612 memset(&e->counters, 0, sizeof(e->counters));
1617 module_put(t->u.kernel.target->me);
1619 xt_ematch_foreach(ematch, e) {
1622 module_put(ematch->u.kernel.match->me);
1628 compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1629 unsigned int *size, const char *name,
1630 struct xt_table_info *newinfo, unsigned char *base)
1632 struct ip6t_entry_target *t;
1633 struct xt_target *target;
1634 struct ip6t_entry *de;
1635 unsigned int origsize;
1637 struct xt_entry_match *ematch;
1641 de = (struct ip6t_entry *)*dstptr;
1642 memcpy(de, e, sizeof(struct ip6t_entry));
1643 memcpy(&de->counters, &e->counters, sizeof(e->counters));
1645 *dstptr += sizeof(struct ip6t_entry);
1646 *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1648 xt_ematch_foreach(ematch, e) {
1649 ret = xt_compat_match_from_user(ematch, dstptr, size);
1653 de->target_offset = e->target_offset - (origsize - *size);
1654 t = compat_ip6t_get_target(e);
1655 target = t->u.kernel.target;
1656 xt_compat_target_from_user(t, dstptr, size);
1658 de->next_offset = e->next_offset - (origsize - *size);
1659 for (h = 0; h < NF_INET_NUMHOOKS; h++) {
1660 if ((unsigned char *)de - base < newinfo->hook_entry[h])
1661 newinfo->hook_entry[h] -= origsize - *size;
1662 if ((unsigned char *)de - base < newinfo->underflow[h])
1663 newinfo->underflow[h] -= origsize - *size;
1668 static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1673 struct xt_mtchk_param mtpar;
1674 struct xt_entry_match *ematch;
1679 mtpar.entryinfo = &e->ipv6;
1680 mtpar.hook_mask = e->comefrom;
1681 mtpar.family = NFPROTO_IPV6;
1682 xt_ematch_foreach(ematch, e) {
1683 ret = check_match(ematch, &mtpar);
1685 goto cleanup_matches;
1689 ret = check_target(e, net, name);
1691 goto cleanup_matches;
1695 xt_ematch_foreach(ematch, e) {
1698 cleanup_match(ematch, net);
1704 translate_compat_table(struct net *net,
1706 unsigned int valid_hooks,
1707 struct xt_table_info **pinfo,
1709 unsigned int total_size,
1710 unsigned int number,
1711 unsigned int *hook_entries,
1712 unsigned int *underflows)
1715 struct xt_table_info *newinfo, *info;
1716 void *pos, *entry0, *entry1;
1717 struct compat_ip6t_entry *iter0;
1718 struct ip6t_entry *iter1;
1725 info->number = number;
1727 /* Init all hooks to impossible value. */
1728 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1729 info->hook_entry[i] = 0xFFFFFFFF;
1730 info->underflow[i] = 0xFFFFFFFF;
1733 duprintf("translate_compat_table: size %u\n", info->size);
1735 xt_compat_lock(AF_INET6);
1736 /* Walk through entries, checking offsets. */
1737 xt_entry_foreach(iter0, entry0, total_size) {
1738 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1740 entry0 + total_size,
1751 duprintf("translate_compat_table: %u not %u entries\n",
1756 /* Check hooks all assigned */
1757 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1758 /* Only hooks which are valid */
1759 if (!(valid_hooks & (1 << i)))
1761 if (info->hook_entry[i] == 0xFFFFFFFF) {
1762 duprintf("Invalid hook entry %u %u\n",
1763 i, hook_entries[i]);
1766 if (info->underflow[i] == 0xFFFFFFFF) {
1767 duprintf("Invalid underflow %u %u\n",
1774 newinfo = xt_alloc_table_info(size);
1778 newinfo->number = number;
1779 for (i = 0; i < NF_INET_NUMHOOKS; i++) {
1780 newinfo->hook_entry[i] = info->hook_entry[i];
1781 newinfo->underflow[i] = info->underflow[i];
1783 entry1 = newinfo->entries[raw_smp_processor_id()];
1786 xt_entry_foreach(iter0, entry0, total_size) {
1787 ret = compat_copy_entry_from_user(iter0, &pos, &size,
1788 name, newinfo, entry1);
1792 xt_compat_flush_offsets(AF_INET6);
1793 xt_compat_unlock(AF_INET6);
1798 if (!mark_source_chains(newinfo, valid_hooks, entry1))
1802 xt_entry_foreach(iter1, entry1, newinfo->size) {
1803 ret = compat_check_entry(iter1, net, name);
1810 * The first i matches need cleanup_entry (calls ->destroy)
1811 * because they had called ->check already. The other j-i
1812 * entries need only release.
1816 xt_entry_foreach(iter0, entry0, newinfo->size) {
1821 compat_release_entry(iter0);
1823 xt_entry_foreach(iter1, entry1, newinfo->size) {
1826 cleanup_entry(iter1, net);
1828 xt_free_table_info(newinfo);
1832 /* And one copy for every other CPU */
1833 for_each_possible_cpu(i)
1834 if (newinfo->entries[i] && newinfo->entries[i] != entry1)
1835 memcpy(newinfo->entries[i], entry1, newinfo->size);
1839 xt_free_table_info(info);
1843 xt_free_table_info(newinfo);
1845 xt_entry_foreach(iter0, entry0, total_size) {
1848 compat_release_entry(iter0);
1852 xt_compat_flush_offsets(AF_INET6);
1853 xt_compat_unlock(AF_INET6);
1858 compat_do_replace(struct net *net, void __user *user, unsigned int len)
1861 struct compat_ip6t_replace tmp;
1862 struct xt_table_info *newinfo;
1863 void *loc_cpu_entry;
1864 struct ip6t_entry *iter;
1866 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1869 /* overflow check */
1870 if (tmp.size >= INT_MAX / num_possible_cpus())
1872 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
1875 newinfo = xt_alloc_table_info(tmp.size);
1879 /* choose the copy that is on our node/cpu */
1880 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1881 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1887 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1888 &newinfo, &loc_cpu_entry, tmp.size,
1889 tmp.num_entries, tmp.hook_entry,
1894 duprintf("compat_do_replace: Translated table\n");
1896 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
1897 tmp.num_counters, compat_ptr(tmp.counters));
1899 goto free_newinfo_untrans;
1902 free_newinfo_untrans:
1903 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1904 cleanup_entry(iter, net);
1906 xt_free_table_info(newinfo);
1911 compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
1916 if (!capable(CAP_NET_ADMIN))
1920 case IP6T_SO_SET_REPLACE:
1921 ret = compat_do_replace(sock_net(sk), user, len);
1924 case IP6T_SO_SET_ADD_COUNTERS:
1925 ret = do_add_counters(sock_net(sk), user, len, 1);
1929 duprintf("do_ip6t_set_ctl: unknown request %i\n", cmd);
1936 struct compat_ip6t_get_entries {
1937 char name[IP6T_TABLE_MAXNAMELEN];
1939 struct compat_ip6t_entry entrytable[0];
1943 compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1944 void __user *userptr)
1946 struct xt_counters *counters;
1947 const struct xt_table_info *private = table->private;
1951 const void *loc_cpu_entry;
1953 struct ip6t_entry *iter;
1955 counters = alloc_counters(table);
1956 if (IS_ERR(counters))
1957 return PTR_ERR(counters);
1959 /* choose the copy that is on our node/cpu, ...
1960 * This choice is lazy (because current thread is
1961 * allowed to migrate to another cpu)
1963 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1966 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1967 ret = compat_copy_entry_to_user(iter, &pos,
1968 &size, counters, i++);
1978 compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
1982 struct compat_ip6t_get_entries get;
1985 if (*len < sizeof(get)) {
1986 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
1990 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
1993 if (*len != sizeof(struct compat_ip6t_get_entries) + get.size) {
1994 duprintf("compat_get_entries: %u != %zu\n",
1995 *len, sizeof(get) + get.size);
1999 xt_compat_lock(AF_INET6);
2000 t = xt_find_table_lock(net, AF_INET6, get.name);
2001 if (t && !IS_ERR(t)) {
2002 const struct xt_table_info *private = t->private;
2003 struct xt_table_info info;
2004 duprintf("t->private->number = %u\n", private->number);
2005 ret = compat_table_info(private, &info);
2006 if (!ret && get.size == info.size) {
2007 ret = compat_copy_entries_to_user(private->size,
2008 t, uptr->entrytable);
2010 duprintf("compat_get_entries: I've got %u not %u!\n",
2011 private->size, get.size);
2014 xt_compat_flush_offsets(AF_INET6);
2018 ret = t ? PTR_ERR(t) : -ENOENT;
2020 xt_compat_unlock(AF_INET6);
2024 static int do_ip6t_get_ctl(struct sock *, int, void __user *, int *);
2027 compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2031 if (!capable(CAP_NET_ADMIN))
2035 case IP6T_SO_GET_INFO:
2036 ret = get_info(sock_net(sk), user, len, 1);
2038 case IP6T_SO_GET_ENTRIES:
2039 ret = compat_get_entries(sock_net(sk), user, len);
2042 ret = do_ip6t_get_ctl(sk, cmd, user, len);
2049 do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2053 if (!capable(CAP_NET_ADMIN))
2057 case IP6T_SO_SET_REPLACE:
2058 ret = do_replace(sock_net(sk), user, len);
2061 case IP6T_SO_SET_ADD_COUNTERS:
2062 ret = do_add_counters(sock_net(sk), user, len, 0);
2066 duprintf("do_ip6t_set_ctl: unknown request %i\n", cmd);
2074 do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2078 if (!capable(CAP_NET_ADMIN))
2082 case IP6T_SO_GET_INFO:
2083 ret = get_info(sock_net(sk), user, len, 0);
2086 case IP6T_SO_GET_ENTRIES:
2087 ret = get_entries(sock_net(sk), user, len);
2090 case IP6T_SO_GET_REVISION_MATCH:
2091 case IP6T_SO_GET_REVISION_TARGET: {
2092 struct ip6t_get_revision rev;
2095 if (*len != sizeof(rev)) {
2099 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
2104 if (cmd == IP6T_SO_GET_REVISION_TARGET)
2109 try_then_request_module(xt_find_revision(AF_INET6, rev.name,
2112 "ip6t_%s", rev.name);
2117 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
2124 struct xt_table *ip6t_register_table(struct net *net,
2125 const struct xt_table *table,
2126 const struct ip6t_replace *repl)
2129 struct xt_table_info *newinfo;
2130 struct xt_table_info bootstrap
2131 = { 0, 0, 0, { 0 }, { 0 }, { } };
2132 void *loc_cpu_entry;
2133 struct xt_table *new_table;
2135 newinfo = xt_alloc_table_info(repl->size);
2141 /* choose the copy on our node/cpu, but dont care about preemption */
2142 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2143 memcpy(loc_cpu_entry, repl->entries, repl->size);
2145 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
2149 new_table = xt_register_table(net, table, &bootstrap, newinfo);
2150 if (IS_ERR(new_table)) {
2151 ret = PTR_ERR(new_table);
2157 xt_free_table_info(newinfo);
2159 return ERR_PTR(ret);
2162 void ip6t_unregister_table(struct net *net, struct xt_table *table)
2164 struct xt_table_info *private;
2165 void *loc_cpu_entry;
2166 struct module *table_owner = table->me;
2167 struct ip6t_entry *iter;
2169 private = xt_unregister_table(table);
2171 /* Decrease module usage counts and free resources */
2172 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2173 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2174 cleanup_entry(iter, net);
2175 if (private->number > private->initial_entries)
2176 module_put(table_owner);
2177 xt_free_table_info(private);
2180 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
2182 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
2183 u_int8_t type, u_int8_t code,
2186 return (type == test_type && code >= min_code && code <= max_code)
2191 icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par)
2193 const struct icmp6hdr *ic;
2194 struct icmp6hdr _icmph;
2195 const struct ip6t_icmp *icmpinfo = par->matchinfo;
2197 /* Must not be a fragment. */
2198 if (par->fragoff != 0)
2201 ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
2203 /* We've been asked to examine this packet, and we
2204 * can't. Hence, no choice but to drop.
2206 duprintf("Dropping evil ICMP tinygram.\n");
2207 *par->hotdrop = true;
2211 return icmp6_type_code_match(icmpinfo->type,
2214 ic->icmp6_type, ic->icmp6_code,
2215 !!(icmpinfo->invflags&IP6T_ICMP_INV));
2218 /* Called when user tries to insert an entry of this type. */
2219 static bool icmp6_checkentry(const struct xt_mtchk_param *par)
2221 const struct ip6t_icmp *icmpinfo = par->matchinfo;
2223 /* Must specify no unknown invflags */
2224 return !(icmpinfo->invflags & ~IP6T_ICMP_INV);
2227 /* The built-in targets: standard (NULL) and error. */
2228 static struct xt_target ip6t_standard_target __read_mostly = {
2229 .name = IP6T_STANDARD_TARGET,
2230 .targetsize = sizeof(int),
2231 .family = NFPROTO_IPV6,
2232 #ifdef CONFIG_COMPAT
2233 .compatsize = sizeof(compat_int_t),
2234 .compat_from_user = compat_standard_from_user,
2235 .compat_to_user = compat_standard_to_user,
2239 static struct xt_target ip6t_error_target __read_mostly = {
2240 .name = IP6T_ERROR_TARGET,
2241 .target = ip6t_error,
2242 .targetsize = IP6T_FUNCTION_MAXNAMELEN,
2243 .family = NFPROTO_IPV6,
2246 static struct nf_sockopt_ops ip6t_sockopts = {
2248 .set_optmin = IP6T_BASE_CTL,
2249 .set_optmax = IP6T_SO_SET_MAX+1,
2250 .set = do_ip6t_set_ctl,
2251 #ifdef CONFIG_COMPAT
2252 .compat_set = compat_do_ip6t_set_ctl,
2254 .get_optmin = IP6T_BASE_CTL,
2255 .get_optmax = IP6T_SO_GET_MAX+1,
2256 .get = do_ip6t_get_ctl,
2257 #ifdef CONFIG_COMPAT
2258 .compat_get = compat_do_ip6t_get_ctl,
2260 .owner = THIS_MODULE,
2263 static struct xt_match icmp6_matchstruct __read_mostly = {
2265 .match = icmp6_match,
2266 .matchsize = sizeof(struct ip6t_icmp),
2267 .checkentry = icmp6_checkentry,
2268 .proto = IPPROTO_ICMPV6,
2269 .family = NFPROTO_IPV6,
2272 static int __net_init ip6_tables_net_init(struct net *net)
2274 return xt_proto_init(net, NFPROTO_IPV6);
2277 static void __net_exit ip6_tables_net_exit(struct net *net)
2279 xt_proto_fini(net, NFPROTO_IPV6);
2282 static struct pernet_operations ip6_tables_net_ops = {
2283 .init = ip6_tables_net_init,
2284 .exit = ip6_tables_net_exit,
2287 static int __init ip6_tables_init(void)
2291 ret = register_pernet_subsys(&ip6_tables_net_ops);
2295 /* Noone else will be downing sem now, so we won't sleep */
2296 ret = xt_register_target(&ip6t_standard_target);
2299 ret = xt_register_target(&ip6t_error_target);
2302 ret = xt_register_match(&icmp6_matchstruct);
2306 /* Register setsockopt */
2307 ret = nf_register_sockopt(&ip6t_sockopts);
2311 printk(KERN_INFO "ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
2315 xt_unregister_match(&icmp6_matchstruct);
2317 xt_unregister_target(&ip6t_error_target);
2319 xt_unregister_target(&ip6t_standard_target);
2321 unregister_pernet_subsys(&ip6_tables_net_ops);
2326 static void __exit ip6_tables_fini(void)
2328 nf_unregister_sockopt(&ip6t_sockopts);
2330 xt_unregister_match(&icmp6_matchstruct);
2331 xt_unregister_target(&ip6t_error_target);
2332 xt_unregister_target(&ip6t_standard_target);
2334 unregister_pernet_subsys(&ip6_tables_net_ops);
2338 * find the offset to specified header or the protocol number of last header
2339 * if target < 0. "last header" is transport protocol header, ESP, or
2342 * If target header is found, its offset is set in *offset and return protocol
2343 * number. Otherwise, return -1.
2345 * If the first fragment doesn't contain the final protocol header or
2346 * NEXTHDR_NONE it is considered invalid.
2348 * Note that non-1st fragment is special case that "the protocol number
2349 * of last header" is "next header" field in Fragment header. In this case,
2350 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
2354 int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2355 int target, unsigned short *fragoff)
2357 unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
2358 u8 nexthdr = ipv6_hdr(skb)->nexthdr;
2359 unsigned int len = skb->len - start;
2364 while (nexthdr != target) {
2365 struct ipv6_opt_hdr _hdr, *hp;
2366 unsigned int hdrlen;
2368 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
2374 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
2377 if (nexthdr == NEXTHDR_FRAGMENT) {
2378 unsigned short _frag_off;
2380 fp = skb_header_pointer(skb,
2381 start+offsetof(struct frag_hdr,
2388 _frag_off = ntohs(*fp) & ~0x7;
2391 ((!ipv6_ext_hdr(hp->nexthdr)) ||
2392 hp->nexthdr == NEXTHDR_NONE)) {
2394 *fragoff = _frag_off;
2400 } else if (nexthdr == NEXTHDR_AUTH)
2401 hdrlen = (hp->hdrlen + 2) << 2;
2403 hdrlen = ipv6_optlen(hp);
2405 nexthdr = hp->nexthdr;
2414 EXPORT_SYMBOL(ip6t_register_table);
2415 EXPORT_SYMBOL(ip6t_unregister_table);
2416 EXPORT_SYMBOL(ip6t_do_table);
2417 EXPORT_SYMBOL(ip6t_ext_hdr);
2418 EXPORT_SYMBOL(ipv6_find_hdr);
2420 module_init(ip6_tables_init);
2421 module_exit(ip6_tables_fini);