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 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
12 * - increase module usage count as soon as we have rules inside
14 * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu>
15 * - new extension header parser code
16 * 15 Oct 2005 Harald Welte <laforge@netfilter.org>
17 * - Unification of {ip,ip6}_tables into x_tables
18 * - Removed tcp and udp code, since it's not ipv6 specific
21 #include <linux/capability.h>
22 #include <linux/config.h>
24 #include <linux/skbuff.h>
25 #include <linux/kmod.h>
26 #include <linux/vmalloc.h>
27 #include <linux/netdevice.h>
28 #include <linux/module.h>
29 #include <linux/icmpv6.h>
31 #include <asm/uaccess.h>
32 #include <asm/semaphore.h>
33 #include <linux/proc_fs.h>
34 #include <linux/cpumask.h>
36 #include <linux/netfilter_ipv6/ip6_tables.h>
37 #include <linux/netfilter/x_tables.h>
39 MODULE_LICENSE("GPL");
40 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
41 MODULE_DESCRIPTION("IPv6 packet filter");
43 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
44 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
46 /*#define DEBUG_IP_FIREWALL*/
47 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
48 /*#define DEBUG_IP_FIREWALL_USER*/
50 #ifdef DEBUG_IP_FIREWALL
51 #define dprintf(format, args...) printk(format , ## args)
53 #define dprintf(format, args...)
56 #ifdef DEBUG_IP_FIREWALL_USER
57 #define duprintf(format, args...) printk(format , ## args)
59 #define duprintf(format, args...)
62 #ifdef CONFIG_NETFILTER_DEBUG
63 #define IP_NF_ASSERT(x) \
66 printk("IP_NF_ASSERT: %s:%s:%u\n", \
67 __FUNCTION__, __FILE__, __LINE__); \
70 #define IP_NF_ASSERT(x)
74 #include <linux/netfilter_ipv4/listhelp.h>
77 /* All the better to debug you with... */
83 We keep a set of rules for each CPU, so we can avoid write-locking
84 them in the softirq when updating the counters and therefore
85 only need to read-lock in the softirq; doing a write_lock_bh() in user
86 context stops packets coming through and allows user context to read
87 the counters or update the rules.
89 Hence the start of any table is given by get_table() below. */
92 #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
93 #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
94 #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
98 ip6_masked_addrcmp(const struct in6_addr *addr1, const struct in6_addr *mask,
99 const struct in6_addr *addr2)
102 for( i = 0; i < 16; i++){
103 if((addr1->s6_addr[i] & mask->s6_addr[i]) !=
104 (addr2->s6_addr[i] & mask->s6_addr[i]))
110 /* Check for an extension */
112 ip6t_ext_hdr(u8 nexthdr)
114 return ( (nexthdr == IPPROTO_HOPOPTS) ||
115 (nexthdr == IPPROTO_ROUTING) ||
116 (nexthdr == IPPROTO_FRAGMENT) ||
117 (nexthdr == IPPROTO_ESP) ||
118 (nexthdr == IPPROTO_AH) ||
119 (nexthdr == IPPROTO_NONE) ||
120 (nexthdr == IPPROTO_DSTOPTS) );
123 /* Returns whether matches rule or not. */
125 ip6_packet_match(const struct sk_buff *skb,
128 const struct ip6t_ip6 *ip6info,
129 unsigned int *protoff,
134 const struct ipv6hdr *ipv6 = skb->nh.ipv6h;
136 #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
138 if (FWINV(ip6_masked_addrcmp(&ipv6->saddr, &ip6info->smsk,
139 &ip6info->src), IP6T_INV_SRCIP)
140 || FWINV(ip6_masked_addrcmp(&ipv6->daddr, &ip6info->dmsk,
141 &ip6info->dst), IP6T_INV_DSTIP)) {
142 dprintf("Source or dest mismatch.\n");
144 dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
145 ipinfo->smsk.s_addr, ipinfo->src.s_addr,
146 ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : "");
147 dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
148 ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
149 ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
153 /* Look for ifname matches; this should unroll nicely. */
154 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
155 ret |= (((const unsigned long *)indev)[i]
156 ^ ((const unsigned long *)ip6info->iniface)[i])
157 & ((const unsigned long *)ip6info->iniface_mask)[i];
160 if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
161 dprintf("VIA in mismatch (%s vs %s).%s\n",
162 indev, ip6info->iniface,
163 ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
167 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
168 ret |= (((const unsigned long *)outdev)[i]
169 ^ ((const unsigned long *)ip6info->outiface)[i])
170 & ((const unsigned long *)ip6info->outiface_mask)[i];
173 if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
174 dprintf("VIA out mismatch (%s vs %s).%s\n",
175 outdev, ip6info->outiface,
176 ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
180 /* ... might want to do something with class and flowlabel here ... */
182 /* look for the desired protocol header */
183 if((ip6info->flags & IP6T_F_PROTO)) {
185 unsigned short _frag_off;
187 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
191 *fragoff = _frag_off;
193 dprintf("Packet protocol %hi ?= %s%hi.\n",
195 ip6info->invflags & IP6T_INV_PROTO ? "!":"",
198 if (ip6info->proto == protohdr) {
199 if(ip6info->invflags & IP6T_INV_PROTO) {
205 /* We need match for the '-p all', too! */
206 if ((ip6info->proto != 0) &&
207 !(ip6info->invflags & IP6T_INV_PROTO))
213 /* should be ip6 safe */
215 ip6_checkentry(const struct ip6t_ip6 *ipv6)
217 if (ipv6->flags & ~IP6T_F_MASK) {
218 duprintf("Unknown flag bits set: %08X\n",
219 ipv6->flags & ~IP6T_F_MASK);
222 if (ipv6->invflags & ~IP6T_INV_MASK) {
223 duprintf("Unknown invflag bits set: %08X\n",
224 ipv6->invflags & ~IP6T_INV_MASK);
231 ip6t_error(struct sk_buff **pskb,
232 const struct net_device *in,
233 const struct net_device *out,
234 unsigned int hooknum,
235 const struct xt_target *target,
236 const void *targinfo,
240 printk("ip6_tables: error: `%s'\n", (char *)targinfo);
246 int do_match(struct ip6t_entry_match *m,
247 const struct sk_buff *skb,
248 const struct net_device *in,
249 const struct net_device *out,
251 unsigned int protoff,
254 /* Stop iteration if it doesn't match */
255 if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
256 offset, protoff, hotdrop))
262 static inline struct ip6t_entry *
263 get_entry(void *base, unsigned int offset)
265 return (struct ip6t_entry *)(base + offset);
268 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
270 ip6t_do_table(struct sk_buff **pskb,
272 const struct net_device *in,
273 const struct net_device *out,
274 struct xt_table *table,
277 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
279 unsigned int protoff = 0;
281 /* Initializing verdict to NF_DROP keeps gcc happy. */
282 unsigned int verdict = NF_DROP;
283 const char *indev, *outdev;
285 struct ip6t_entry *e, *back;
286 struct xt_table_info *private;
289 indev = in ? in->name : nulldevname;
290 outdev = out ? out->name : nulldevname;
291 /* We handle fragments by dealing with the first fragment as
292 * if it was a normal packet. All other fragments are treated
293 * normally, except that they will NEVER match rules that ask
294 * things we don't know, ie. tcp syn flag or ports). If the
295 * rule is also a fragment-specific rule, non-fragments won't
298 read_lock_bh(&table->lock);
299 private = table->private;
300 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
301 table_base = (void *)private->entries[smp_processor_id()];
302 e = get_entry(table_base, private->hook_entry[hook]);
304 #ifdef CONFIG_NETFILTER_DEBUG
305 /* Check noone else using our table */
306 if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
307 && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
308 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
311 &((struct ip6t_entry *)table_base)->comefrom,
312 ((struct ip6t_entry *)table_base)->comefrom);
314 ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
317 /* For return from builtin chain */
318 back = get_entry(table_base, private->underflow[hook]);
323 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
324 &protoff, &offset)) {
325 struct ip6t_entry_target *t;
327 if (IP6T_MATCH_ITERATE(e, do_match,
329 offset, protoff, &hotdrop) != 0)
332 ADD_COUNTER(e->counters,
333 ntohs((*pskb)->nh.ipv6h->payload_len)
337 t = ip6t_get_target(e);
338 IP_NF_ASSERT(t->u.kernel.target);
339 /* Standard target? */
340 if (!t->u.kernel.target->target) {
343 v = ((struct ip6t_standard_target *)t)->verdict;
345 /* Pop from stack? */
346 if (v != IP6T_RETURN) {
347 verdict = (unsigned)(-v) - 1;
351 back = get_entry(table_base,
355 if (table_base + v != (void *)e + e->next_offset
356 && !(e->ipv6.flags & IP6T_F_GOTO)) {
357 /* Save old back ptr in next entry */
358 struct ip6t_entry *next
359 = (void *)e + e->next_offset;
361 = (void *)back - table_base;
362 /* set back pointer to next entry */
366 e = get_entry(table_base, v);
368 /* Targets which reenter must return
370 #ifdef CONFIG_NETFILTER_DEBUG
371 ((struct ip6t_entry *)table_base)->comefrom
374 verdict = t->u.kernel.target->target(pskb,
381 #ifdef CONFIG_NETFILTER_DEBUG
382 if (((struct ip6t_entry *)table_base)->comefrom
384 && verdict == IP6T_CONTINUE) {
385 printk("Target %s reentered!\n",
386 t->u.kernel.target->name);
389 ((struct ip6t_entry *)table_base)->comefrom
392 if (verdict == IP6T_CONTINUE)
393 e = (void *)e + e->next_offset;
401 e = (void *)e + e->next_offset;
405 #ifdef CONFIG_NETFILTER_DEBUG
406 ((struct ip6t_entry *)table_base)->comefrom = 0xdead57ac;
408 read_unlock_bh(&table->lock);
410 #ifdef DEBUG_ALLOW_ALL
419 /* All zeroes == unconditional rule. */
421 unconditional(const struct ip6t_ip6 *ipv6)
425 for (i = 0; i < sizeof(*ipv6); i++)
426 if (((char *)ipv6)[i])
429 return (i == sizeof(*ipv6));
432 /* Figures out from what hook each rule can be called: returns 0 if
433 there are loops. Puts hook bitmask in comefrom. */
435 mark_source_chains(struct xt_table_info *newinfo,
436 unsigned int valid_hooks, void *entry0)
440 /* No recursion; use packet counter to save back ptrs (reset
441 to 0 as we leave), and comefrom to save source hook bitmask */
442 for (hook = 0; hook < NF_IP6_NUMHOOKS; hook++) {
443 unsigned int pos = newinfo->hook_entry[hook];
445 = (struct ip6t_entry *)(entry0 + pos);
447 if (!(valid_hooks & (1 << hook)))
450 /* Set initial back pointer. */
451 e->counters.pcnt = pos;
454 struct ip6t_standard_target *t
455 = (void *)ip6t_get_target(e);
457 if (e->comefrom & (1 << NF_IP6_NUMHOOKS)) {
458 printk("iptables: loop hook %u pos %u %08X.\n",
459 hook, pos, e->comefrom);
463 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
465 /* Unconditional return/END. */
466 if (e->target_offset == sizeof(struct ip6t_entry)
467 && (strcmp(t->target.u.user.name,
468 IP6T_STANDARD_TARGET) == 0)
470 && unconditional(&e->ipv6)) {
471 unsigned int oldpos, size;
473 /* Return: backtrack through the last
476 e->comefrom ^= (1<<NF_IP6_NUMHOOKS);
477 #ifdef DEBUG_IP_FIREWALL_USER
479 & (1 << NF_IP6_NUMHOOKS)) {
480 duprintf("Back unset "
487 pos = e->counters.pcnt;
488 e->counters.pcnt = 0;
490 /* We're at the start. */
494 e = (struct ip6t_entry *)
496 } while (oldpos == pos + e->next_offset);
499 size = e->next_offset;
500 e = (struct ip6t_entry *)
501 (entry0 + pos + size);
502 e->counters.pcnt = pos;
505 int newpos = t->verdict;
507 if (strcmp(t->target.u.user.name,
508 IP6T_STANDARD_TARGET) == 0
510 /* This a jump; chase it. */
511 duprintf("Jump rule %u -> %u\n",
514 /* ... this is a fallthru */
515 newpos = pos + e->next_offset;
517 e = (struct ip6t_entry *)
519 e->counters.pcnt = pos;
524 duprintf("Finished chain %u\n", hook);
530 cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
532 if (i && (*i)-- == 0)
535 if (m->u.kernel.match->destroy)
536 m->u.kernel.match->destroy(m->u.kernel.match, m->data,
537 m->u.match_size - sizeof(*m));
538 module_put(m->u.kernel.match->me);
543 standard_check(const struct ip6t_entry_target *t,
544 unsigned int max_offset)
546 struct ip6t_standard_target *targ = (void *)t;
548 /* Check standard info. */
549 if (targ->verdict >= 0
550 && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
551 duprintf("ip6t_standard_check: bad verdict (%i)\n",
555 if (targ->verdict < -NF_MAX_VERDICT - 1) {
556 duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
564 check_match(struct ip6t_entry_match *m,
566 const struct ip6t_ip6 *ipv6,
567 unsigned int hookmask,
570 struct ip6t_match *match;
573 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
575 "ip6t_%s", m->u.user.name);
576 if (IS_ERR(match) || !match) {
577 duprintf("check_match: `%s' not found\n", m->u.user.name);
578 return match ? PTR_ERR(match) : -ENOENT;
580 m->u.kernel.match = match;
582 ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m),
583 name, hookmask, ipv6->proto,
584 ipv6->invflags & IP6T_INV_PROTO);
588 if (m->u.kernel.match->checkentry
589 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data,
590 m->u.match_size - sizeof(*m),
592 duprintf("ip_tables: check failed for `%s'.\n",
593 m->u.kernel.match->name);
601 module_put(m->u.kernel.match->me);
605 static struct ip6t_target ip6t_standard_target;
608 check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
611 struct ip6t_entry_target *t;
612 struct ip6t_target *target;
616 if (!ip6_checkentry(&e->ipv6)) {
617 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
622 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
624 goto cleanup_matches;
626 t = ip6t_get_target(e);
627 target = try_then_request_module(xt_find_target(AF_INET6,
630 "ip6t_%s", t->u.user.name);
631 if (IS_ERR(target) || !target) {
632 duprintf("check_entry: `%s' not found\n", t->u.user.name);
633 ret = target ? PTR_ERR(target) : -ENOENT;
634 goto cleanup_matches;
636 t->u.kernel.target = target;
638 ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t),
639 name, e->comefrom, e->ipv6.proto,
640 e->ipv6.invflags & IP6T_INV_PROTO);
644 if (t->u.kernel.target == &ip6t_standard_target) {
645 if (!standard_check(t, size)) {
647 goto cleanup_matches;
649 } else if (t->u.kernel.target->checkentry
650 && !t->u.kernel.target->checkentry(name, e, target, t->data,
654 duprintf("ip_tables: check failed for `%s'.\n",
655 t->u.kernel.target->name);
663 module_put(t->u.kernel.target->me);
665 IP6T_MATCH_ITERATE(e, cleanup_match, &j);
670 check_entry_size_and_hooks(struct ip6t_entry *e,
671 struct xt_table_info *newinfo,
673 unsigned char *limit,
674 const unsigned int *hook_entries,
675 const unsigned int *underflows,
680 if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0
681 || (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
682 duprintf("Bad offset %p\n", e);
687 < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
688 duprintf("checking: element %p size %u\n",
693 /* Check hooks & underflows */
694 for (h = 0; h < NF_IP6_NUMHOOKS; h++) {
695 if ((unsigned char *)e - base == hook_entries[h])
696 newinfo->hook_entry[h] = hook_entries[h];
697 if ((unsigned char *)e - base == underflows[h])
698 newinfo->underflow[h] = underflows[h];
701 /* FIXME: underflows must be unconditional, standard verdicts
702 < 0 (not IP6T_RETURN). --RR */
704 /* Clear counters and comefrom */
705 e->counters = ((struct xt_counters) { 0, 0 });
713 cleanup_entry(struct ip6t_entry *e, unsigned int *i)
715 struct ip6t_entry_target *t;
717 if (i && (*i)-- == 0)
720 /* Cleanup all matches */
721 IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
722 t = ip6t_get_target(e);
723 if (t->u.kernel.target->destroy)
724 t->u.kernel.target->destroy(t->u.kernel.target, t->data,
725 t->u.target_size - sizeof(*t));
726 module_put(t->u.kernel.target->me);
730 /* Checks and translates the user-supplied table segment (held in
733 translate_table(const char *name,
734 unsigned int valid_hooks,
735 struct xt_table_info *newinfo,
739 const unsigned int *hook_entries,
740 const unsigned int *underflows)
745 newinfo->size = size;
746 newinfo->number = number;
748 /* Init all hooks to impossible value. */
749 for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
750 newinfo->hook_entry[i] = 0xFFFFFFFF;
751 newinfo->underflow[i] = 0xFFFFFFFF;
754 duprintf("translate_table: size %u\n", newinfo->size);
756 /* Walk through entries, checking offsets. */
757 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
758 check_entry_size_and_hooks,
762 hook_entries, underflows, &i);
767 duprintf("translate_table: %u not %u entries\n",
772 /* Check hooks all assigned */
773 for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
774 /* Only hooks which are valid */
775 if (!(valid_hooks & (1 << i)))
777 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
778 duprintf("Invalid hook entry %u %u\n",
782 if (newinfo->underflow[i] == 0xFFFFFFFF) {
783 duprintf("Invalid underflow %u %u\n",
789 if (!mark_source_chains(newinfo, valid_hooks, entry0))
792 /* Finally, each sanity check must pass */
794 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
795 check_entry, name, size, &i);
798 IP6T_ENTRY_ITERATE(entry0, newinfo->size,
803 /* And one copy for every other CPU */
805 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
806 memcpy(newinfo->entries[i], entry0, newinfo->size);
814 add_entry_to_counter(const struct ip6t_entry *e,
815 struct xt_counters total[],
818 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
825 set_entry_to_counter(const struct ip6t_entry *e,
826 struct ip6t_counters total[],
829 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
836 get_counters(const struct xt_table_info *t,
837 struct xt_counters counters[])
843 /* Instead of clearing (by a previous call to memset())
844 * the counters and using adds, we set the counters
845 * with data used by 'current' CPU
846 * We dont care about preemption here.
848 curcpu = raw_smp_processor_id();
851 IP6T_ENTRY_ITERATE(t->entries[curcpu],
853 set_entry_to_counter,
861 IP6T_ENTRY_ITERATE(t->entries[cpu],
863 add_entry_to_counter,
870 copy_entries_to_user(unsigned int total_size,
871 struct xt_table *table,
872 void __user *userptr)
874 unsigned int off, num, countersize;
875 struct ip6t_entry *e;
876 struct xt_counters *counters;
877 struct xt_table_info *private = table->private;
881 /* We need atomic snapshot of counters: rest doesn't change
882 (other than comefrom, which userspace doesn't care
884 countersize = sizeof(struct xt_counters) * private->number;
885 counters = vmalloc(countersize);
887 if (counters == NULL)
890 /* First, sum counters... */
891 write_lock_bh(&table->lock);
892 get_counters(private, counters);
893 write_unlock_bh(&table->lock);
895 /* choose the copy that is on ourc node/cpu */
896 loc_cpu_entry = private->entries[raw_smp_processor_id()];
897 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
902 /* FIXME: use iterator macros --RR */
903 /* ... then go back and fix counters and names */
904 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
906 struct ip6t_entry_match *m;
907 struct ip6t_entry_target *t;
909 e = (struct ip6t_entry *)(loc_cpu_entry + off);
910 if (copy_to_user(userptr + off
911 + offsetof(struct ip6t_entry, counters),
913 sizeof(counters[num])) != 0) {
918 for (i = sizeof(struct ip6t_entry);
919 i < e->target_offset;
920 i += m->u.match_size) {
923 if (copy_to_user(userptr + off + i
924 + offsetof(struct ip6t_entry_match,
926 m->u.kernel.match->name,
927 strlen(m->u.kernel.match->name)+1)
934 t = ip6t_get_target(e);
935 if (copy_to_user(userptr + off + e->target_offset
936 + offsetof(struct ip6t_entry_target,
938 t->u.kernel.target->name,
939 strlen(t->u.kernel.target->name)+1) != 0) {
951 get_entries(const struct ip6t_get_entries *entries,
952 struct ip6t_get_entries __user *uptr)
957 t = xt_find_table_lock(AF_INET6, entries->name);
958 if (t && !IS_ERR(t)) {
959 struct xt_table_info *private = t->private;
960 duprintf("t->private->number = %u\n", private->number);
961 if (entries->size == private->size)
962 ret = copy_entries_to_user(private->size,
963 t, uptr->entrytable);
965 duprintf("get_entries: I've got %u not %u!\n",
966 private->size, entries->size);
972 ret = t ? PTR_ERR(t) : -ENOENT;
978 do_replace(void __user *user, unsigned int len)
981 struct ip6t_replace tmp;
983 struct xt_table_info *newinfo, *oldinfo;
984 struct xt_counters *counters;
985 void *loc_cpu_entry, *loc_cpu_old_entry;
987 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
991 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
994 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
997 newinfo = xt_alloc_table_info(tmp.size);
1001 /* choose the copy that is on our node/cpu */
1002 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1003 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1009 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1015 ret = translate_table(tmp.name, tmp.valid_hooks,
1016 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1017 tmp.hook_entry, tmp.underflow);
1019 goto free_newinfo_counters;
1021 duprintf("ip_tables: Translated table\n");
1023 t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
1024 "ip6table_%s", tmp.name);
1025 if (!t || IS_ERR(t)) {
1026 ret = t ? PTR_ERR(t) : -ENOENT;
1027 goto free_newinfo_counters_untrans;
1031 if (tmp.valid_hooks != t->valid_hooks) {
1032 duprintf("Valid hook crap: %08X vs %08X\n",
1033 tmp.valid_hooks, t->valid_hooks);
1038 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1042 /* Update module usage count based on number of rules */
1043 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1044 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1045 if ((oldinfo->number > oldinfo->initial_entries) ||
1046 (newinfo->number <= oldinfo->initial_entries))
1048 if ((oldinfo->number > oldinfo->initial_entries) &&
1049 (newinfo->number <= oldinfo->initial_entries))
1052 /* Get the old counters. */
1053 get_counters(oldinfo, counters);
1054 /* Decrease module usage counts and free resource */
1055 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1056 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1057 xt_free_table_info(oldinfo);
1058 if (copy_to_user(tmp.counters, counters,
1059 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1068 free_newinfo_counters_untrans:
1069 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1070 free_newinfo_counters:
1073 xt_free_table_info(newinfo);
1077 /* We're lazy, and add to the first CPU; overflow works its fey magic
1078 * and everything is OK. */
1080 add_counter_to_entry(struct ip6t_entry *e,
1081 const struct xt_counters addme[],
1085 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1087 (long unsigned int)e->counters.pcnt,
1088 (long unsigned int)e->counters.bcnt,
1089 (long unsigned int)addme[*i].pcnt,
1090 (long unsigned int)addme[*i].bcnt);
1093 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1100 do_add_counters(void __user *user, unsigned int len)
1103 struct xt_counters_info tmp, *paddc;
1104 struct xt_table_info *private;
1107 void *loc_cpu_entry;
1109 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1112 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1115 paddc = vmalloc(len);
1119 if (copy_from_user(paddc, user, len) != 0) {
1124 t = xt_find_table_lock(AF_INET6, tmp.name);
1125 if (!t || IS_ERR(t)) {
1126 ret = t ? PTR_ERR(t) : -ENOENT;
1130 write_lock_bh(&t->lock);
1131 private = t->private;
1132 if (private->number != paddc->num_counters) {
1134 goto unlock_up_free;
1138 /* Choose the copy that is on our node */
1139 loc_cpu_entry = private->entries[smp_processor_id()];
1140 IP6T_ENTRY_ITERATE(loc_cpu_entry,
1142 add_counter_to_entry,
1146 write_unlock_bh(&t->lock);
1156 do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1160 if (!capable(CAP_NET_ADMIN))
1164 case IP6T_SO_SET_REPLACE:
1165 ret = do_replace(user, len);
1168 case IP6T_SO_SET_ADD_COUNTERS:
1169 ret = do_add_counters(user, len);
1173 duprintf("do_ip6t_set_ctl: unknown request %i\n", cmd);
1181 do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1185 if (!capable(CAP_NET_ADMIN))
1189 case IP6T_SO_GET_INFO: {
1190 char name[IP6T_TABLE_MAXNAMELEN];
1193 if (*len != sizeof(struct ip6t_getinfo)) {
1194 duprintf("length %u != %u\n", *len,
1195 sizeof(struct ip6t_getinfo));
1200 if (copy_from_user(name, user, sizeof(name)) != 0) {
1204 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1206 t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
1207 "ip6table_%s", name);
1208 if (t && !IS_ERR(t)) {
1209 struct ip6t_getinfo info;
1210 struct xt_table_info *private = t->private;
1212 info.valid_hooks = t->valid_hooks;
1213 memcpy(info.hook_entry, private->hook_entry,
1214 sizeof(info.hook_entry));
1215 memcpy(info.underflow, private->underflow,
1216 sizeof(info.underflow));
1217 info.num_entries = private->number;
1218 info.size = private->size;
1219 memcpy(info.name, name, sizeof(info.name));
1221 if (copy_to_user(user, &info, *len) != 0)
1228 ret = t ? PTR_ERR(t) : -ENOENT;
1232 case IP6T_SO_GET_ENTRIES: {
1233 struct ip6t_get_entries get;
1235 if (*len < sizeof(get)) {
1236 duprintf("get_entries: %u < %u\n", *len, sizeof(get));
1238 } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
1240 } else if (*len != sizeof(struct ip6t_get_entries) + get.size) {
1241 duprintf("get_entries: %u != %u\n", *len,
1242 sizeof(struct ip6t_get_entries) + get.size);
1245 ret = get_entries(&get, user);
1249 case IP6T_SO_GET_REVISION_MATCH:
1250 case IP6T_SO_GET_REVISION_TARGET: {
1251 struct ip6t_get_revision rev;
1254 if (*len != sizeof(rev)) {
1258 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1263 if (cmd == IP6T_SO_GET_REVISION_TARGET)
1268 try_then_request_module(xt_find_revision(AF_INET6, rev.name,
1271 "ip6t_%s", rev.name);
1276 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
1283 int ip6t_register_table(struct xt_table *table,
1284 const struct ip6t_replace *repl)
1287 struct xt_table_info *newinfo;
1288 static struct xt_table_info bootstrap
1289 = { 0, 0, 0, { 0 }, { 0 }, { } };
1290 void *loc_cpu_entry;
1292 newinfo = xt_alloc_table_info(repl->size);
1296 /* choose the copy on our node/cpu */
1297 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1298 memcpy(loc_cpu_entry, repl->entries, repl->size);
1300 ret = translate_table(table->name, table->valid_hooks,
1301 newinfo, loc_cpu_entry, repl->size,
1306 xt_free_table_info(newinfo);
1310 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1311 xt_free_table_info(newinfo);
1318 void ip6t_unregister_table(struct xt_table *table)
1320 struct xt_table_info *private;
1321 void *loc_cpu_entry;
1323 private = xt_unregister_table(table);
1325 /* Decrease module usage counts and free resources */
1326 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1327 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1328 xt_free_table_info(private);
1331 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
1333 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
1334 u_int8_t type, u_int8_t code,
1337 return (type == test_type && code >= min_code && code <= max_code)
1342 icmp6_match(const struct sk_buff *skb,
1343 const struct net_device *in,
1344 const struct net_device *out,
1345 const struct xt_match *match,
1346 const void *matchinfo,
1348 unsigned int protoff,
1351 struct icmp6hdr _icmp, *ic;
1352 const struct ip6t_icmp *icmpinfo = matchinfo;
1354 /* Must not be a fragment. */
1358 ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
1360 /* We've been asked to examine this packet, and we
1361 can't. Hence, no choice but to drop. */
1362 duprintf("Dropping evil ICMP tinygram.\n");
1367 return icmp6_type_code_match(icmpinfo->type,
1370 ic->icmp6_type, ic->icmp6_code,
1371 !!(icmpinfo->invflags&IP6T_ICMP_INV));
1374 /* Called when user tries to insert an entry of this type. */
1376 icmp6_checkentry(const char *tablename,
1378 const struct xt_match *match,
1380 unsigned int matchsize,
1381 unsigned int hook_mask)
1383 const struct ip6t_icmp *icmpinfo = matchinfo;
1385 /* Must specify no unknown invflags */
1386 return !(icmpinfo->invflags & ~IP6T_ICMP_INV);
1389 /* The built-in targets: standard (NULL) and error. */
1390 static struct ip6t_target ip6t_standard_target = {
1391 .name = IP6T_STANDARD_TARGET,
1392 .targetsize = sizeof(int),
1395 static struct ip6t_target ip6t_error_target = {
1396 .name = IP6T_ERROR_TARGET,
1397 .target = ip6t_error,
1398 .targetsize = IP6T_FUNCTION_MAXNAMELEN,
1401 static struct nf_sockopt_ops ip6t_sockopts = {
1403 .set_optmin = IP6T_BASE_CTL,
1404 .set_optmax = IP6T_SO_SET_MAX+1,
1405 .set = do_ip6t_set_ctl,
1406 .get_optmin = IP6T_BASE_CTL,
1407 .get_optmax = IP6T_SO_GET_MAX+1,
1408 .get = do_ip6t_get_ctl,
1411 static struct ip6t_match icmp6_matchstruct = {
1413 .match = &icmp6_match,
1414 .matchsize = sizeof(struct ip6t_icmp),
1415 .checkentry = icmp6_checkentry,
1416 .proto = IPPROTO_ICMPV6,
1419 static int __init init(void)
1423 xt_proto_init(AF_INET6);
1425 /* Noone else will be downing sem now, so we won't sleep */
1426 xt_register_target(AF_INET6, &ip6t_standard_target);
1427 xt_register_target(AF_INET6, &ip6t_error_target);
1428 xt_register_match(AF_INET6, &icmp6_matchstruct);
1430 /* Register setsockopt */
1431 ret = nf_register_sockopt(&ip6t_sockopts);
1433 duprintf("Unable to register sockopts.\n");
1434 xt_proto_fini(AF_INET6);
1438 printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
1442 static void __exit fini(void)
1444 nf_unregister_sockopt(&ip6t_sockopts);
1445 xt_unregister_match(AF_INET6, &icmp6_matchstruct);
1446 xt_unregister_target(AF_INET6, &ip6t_error_target);
1447 xt_unregister_target(AF_INET6, &ip6t_standard_target);
1448 xt_proto_fini(AF_INET6);
1452 * find the offset to specified header or the protocol number of last header
1453 * if target < 0. "last header" is transport protocol header, ESP, or
1456 * If target header is found, its offset is set in *offset and return protocol
1457 * number. Otherwise, return -1.
1459 * Note that non-1st fragment is special case that "the protocol number
1460 * of last header" is "next header" field in Fragment header. In this case,
1461 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
1465 int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
1466 int target, unsigned short *fragoff)
1468 unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data;
1469 u8 nexthdr = skb->nh.ipv6h->nexthdr;
1470 unsigned int len = skb->len - start;
1475 while (nexthdr != target) {
1476 struct ipv6_opt_hdr _hdr, *hp;
1477 unsigned int hdrlen;
1479 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
1485 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
1488 if (nexthdr == NEXTHDR_FRAGMENT) {
1489 unsigned short _frag_off, *fp;
1490 fp = skb_header_pointer(skb,
1491 start+offsetof(struct frag_hdr,
1498 _frag_off = ntohs(*fp) & ~0x7;
1501 ((!ipv6_ext_hdr(hp->nexthdr)) ||
1502 nexthdr == NEXTHDR_NONE)) {
1504 *fragoff = _frag_off;
1510 } else if (nexthdr == NEXTHDR_AUTH)
1511 hdrlen = (hp->hdrlen + 2) << 2;
1513 hdrlen = ipv6_optlen(hp);
1515 nexthdr = hp->nexthdr;
1524 EXPORT_SYMBOL(ip6t_register_table);
1525 EXPORT_SYMBOL(ip6t_unregister_table);
1526 EXPORT_SYMBOL(ip6t_do_table);
1527 EXPORT_SYMBOL(ip6t_ext_hdr);
1528 EXPORT_SYMBOL(ipv6_find_hdr);
1529 EXPORT_SYMBOL(ip6_masked_addrcmp);