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 void *targinfo,
239 printk("ip6_tables: error: `%s'\n", (char *)targinfo);
245 int do_match(struct ip6t_entry_match *m,
246 const struct sk_buff *skb,
247 const struct net_device *in,
248 const struct net_device *out,
250 unsigned int protoff,
253 /* Stop iteration if it doesn't match */
254 if (!m->u.kernel.match->match(skb, in, out, m->data,
255 offset, protoff, hotdrop))
261 static inline struct ip6t_entry *
262 get_entry(void *base, unsigned int offset)
264 return (struct ip6t_entry *)(base + offset);
267 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
269 ip6t_do_table(struct sk_buff **pskb,
271 const struct net_device *in,
272 const struct net_device *out,
273 struct xt_table *table,
276 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
278 unsigned int protoff = 0;
280 /* Initializing verdict to NF_DROP keeps gcc happy. */
281 unsigned int verdict = NF_DROP;
282 const char *indev, *outdev;
284 struct ip6t_entry *e, *back;
285 struct xt_table_info *private;
288 indev = in ? in->name : nulldevname;
289 outdev = out ? out->name : nulldevname;
290 /* We handle fragments by dealing with the first fragment as
291 * if it was a normal packet. All other fragments are treated
292 * normally, except that they will NEVER match rules that ask
293 * things we don't know, ie. tcp syn flag or ports). If the
294 * rule is also a fragment-specific rule, non-fragments won't
297 read_lock_bh(&table->lock);
298 private = table->private;
299 IP_NF_ASSERT(table->valid_hooks & (1 << hook));
300 table_base = (void *)private->entries[smp_processor_id()];
301 e = get_entry(table_base, private->hook_entry[hook]);
303 #ifdef CONFIG_NETFILTER_DEBUG
304 /* Check noone else using our table */
305 if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
306 && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
307 printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
310 &((struct ip6t_entry *)table_base)->comefrom,
311 ((struct ip6t_entry *)table_base)->comefrom);
313 ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
316 /* For return from builtin chain */
317 back = get_entry(table_base, private->underflow[hook]);
322 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
323 &protoff, &offset)) {
324 struct ip6t_entry_target *t;
326 if (IP6T_MATCH_ITERATE(e, do_match,
328 offset, protoff, &hotdrop) != 0)
331 ADD_COUNTER(e->counters,
332 ntohs((*pskb)->nh.ipv6h->payload_len)
336 t = ip6t_get_target(e);
337 IP_NF_ASSERT(t->u.kernel.target);
338 /* Standard target? */
339 if (!t->u.kernel.target->target) {
342 v = ((struct ip6t_standard_target *)t)->verdict;
344 /* Pop from stack? */
345 if (v != IP6T_RETURN) {
346 verdict = (unsigned)(-v) - 1;
350 back = get_entry(table_base,
354 if (table_base + v != (void *)e + e->next_offset
355 && !(e->ipv6.flags & IP6T_F_GOTO)) {
356 /* Save old back ptr in next entry */
357 struct ip6t_entry *next
358 = (void *)e + e->next_offset;
360 = (void *)back - table_base;
361 /* set back pointer to next entry */
365 e = get_entry(table_base, v);
367 /* Targets which reenter must return
369 #ifdef CONFIG_NETFILTER_DEBUG
370 ((struct ip6t_entry *)table_base)->comefrom
373 verdict = t->u.kernel.target->target(pskb,
379 #ifdef CONFIG_NETFILTER_DEBUG
380 if (((struct ip6t_entry *)table_base)->comefrom
382 && verdict == IP6T_CONTINUE) {
383 printk("Target %s reentered!\n",
384 t->u.kernel.target->name);
387 ((struct ip6t_entry *)table_base)->comefrom
390 if (verdict == IP6T_CONTINUE)
391 e = (void *)e + e->next_offset;
399 e = (void *)e + e->next_offset;
403 #ifdef CONFIG_NETFILTER_DEBUG
404 ((struct ip6t_entry *)table_base)->comefrom = 0xdead57ac;
406 read_unlock_bh(&table->lock);
408 #ifdef DEBUG_ALLOW_ALL
417 /* All zeroes == unconditional rule. */
419 unconditional(const struct ip6t_ip6 *ipv6)
423 for (i = 0; i < sizeof(*ipv6); i++)
424 if (((char *)ipv6)[i])
427 return (i == sizeof(*ipv6));
430 /* Figures out from what hook each rule can be called: returns 0 if
431 there are loops. Puts hook bitmask in comefrom. */
433 mark_source_chains(struct xt_table_info *newinfo,
434 unsigned int valid_hooks, void *entry0)
438 /* No recursion; use packet counter to save back ptrs (reset
439 to 0 as we leave), and comefrom to save source hook bitmask */
440 for (hook = 0; hook < NF_IP6_NUMHOOKS; hook++) {
441 unsigned int pos = newinfo->hook_entry[hook];
443 = (struct ip6t_entry *)(entry0 + pos);
445 if (!(valid_hooks & (1 << hook)))
448 /* Set initial back pointer. */
449 e->counters.pcnt = pos;
452 struct ip6t_standard_target *t
453 = (void *)ip6t_get_target(e);
455 if (e->comefrom & (1 << NF_IP6_NUMHOOKS)) {
456 printk("iptables: loop hook %u pos %u %08X.\n",
457 hook, pos, e->comefrom);
461 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
463 /* Unconditional return/END. */
464 if (e->target_offset == sizeof(struct ip6t_entry)
465 && (strcmp(t->target.u.user.name,
466 IP6T_STANDARD_TARGET) == 0)
468 && unconditional(&e->ipv6)) {
469 unsigned int oldpos, size;
471 /* Return: backtrack through the last
474 e->comefrom ^= (1<<NF_IP6_NUMHOOKS);
475 #ifdef DEBUG_IP_FIREWALL_USER
477 & (1 << NF_IP6_NUMHOOKS)) {
478 duprintf("Back unset "
485 pos = e->counters.pcnt;
486 e->counters.pcnt = 0;
488 /* We're at the start. */
492 e = (struct ip6t_entry *)
494 } while (oldpos == pos + e->next_offset);
497 size = e->next_offset;
498 e = (struct ip6t_entry *)
499 (entry0 + pos + size);
500 e->counters.pcnt = pos;
503 int newpos = t->verdict;
505 if (strcmp(t->target.u.user.name,
506 IP6T_STANDARD_TARGET) == 0
508 /* This a jump; chase it. */
509 duprintf("Jump rule %u -> %u\n",
512 /* ... this is a fallthru */
513 newpos = pos + e->next_offset;
515 e = (struct ip6t_entry *)
517 e->counters.pcnt = pos;
522 duprintf("Finished chain %u\n", hook);
528 cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
530 if (i && (*i)-- == 0)
533 if (m->u.kernel.match->destroy)
534 m->u.kernel.match->destroy(m->data,
535 m->u.match_size - sizeof(*m));
536 module_put(m->u.kernel.match->me);
541 standard_check(const struct ip6t_entry_target *t,
542 unsigned int max_offset)
544 struct ip6t_standard_target *targ = (void *)t;
546 /* Check standard info. */
547 if (targ->verdict >= 0
548 && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
549 duprintf("ip6t_standard_check: bad verdict (%i)\n",
553 if (targ->verdict < -NF_MAX_VERDICT - 1) {
554 duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
562 check_match(struct ip6t_entry_match *m,
564 const struct ip6t_ip6 *ipv6,
565 unsigned int hookmask,
568 struct ip6t_match *match;
571 match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
573 "ip6t_%s", m->u.user.name);
574 if (IS_ERR(match) || !match) {
575 duprintf("check_match: `%s' not found\n", m->u.user.name);
576 return match ? PTR_ERR(match) : -ENOENT;
578 m->u.kernel.match = match;
580 ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m),
581 name, hookmask, ipv6->proto,
582 ipv6->invflags & IP6T_INV_PROTO);
586 if (m->u.kernel.match->checkentry
587 && !m->u.kernel.match->checkentry(name, ipv6, m->data,
588 m->u.match_size - sizeof(*m),
590 duprintf("ip_tables: check failed for `%s'.\n",
591 m->u.kernel.match->name);
599 module_put(m->u.kernel.match->me);
603 static struct ip6t_target ip6t_standard_target;
606 check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
609 struct ip6t_entry_target *t;
610 struct ip6t_target *target;
614 if (!ip6_checkentry(&e->ipv6)) {
615 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
620 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
622 goto cleanup_matches;
624 t = ip6t_get_target(e);
625 target = try_then_request_module(xt_find_target(AF_INET6,
628 "ip6t_%s", t->u.user.name);
629 if (IS_ERR(target) || !target) {
630 duprintf("check_entry: `%s' not found\n", t->u.user.name);
631 ret = target ? PTR_ERR(target) : -ENOENT;
632 goto cleanup_matches;
634 t->u.kernel.target = target;
636 ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t),
637 name, e->comefrom, e->ipv6.proto,
638 e->ipv6.invflags & IP6T_INV_PROTO);
642 if (t->u.kernel.target == &ip6t_standard_target) {
643 if (!standard_check(t, size)) {
645 goto cleanup_matches;
647 } else if (t->u.kernel.target->checkentry
648 && !t->u.kernel.target->checkentry(name, e, t->data,
652 duprintf("ip_tables: check failed for `%s'.\n",
653 t->u.kernel.target->name);
661 module_put(t->u.kernel.target->me);
663 IP6T_MATCH_ITERATE(e, cleanup_match, &j);
668 check_entry_size_and_hooks(struct ip6t_entry *e,
669 struct xt_table_info *newinfo,
671 unsigned char *limit,
672 const unsigned int *hook_entries,
673 const unsigned int *underflows,
678 if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0
679 || (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
680 duprintf("Bad offset %p\n", e);
685 < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
686 duprintf("checking: element %p size %u\n",
691 /* Check hooks & underflows */
692 for (h = 0; h < NF_IP6_NUMHOOKS; h++) {
693 if ((unsigned char *)e - base == hook_entries[h])
694 newinfo->hook_entry[h] = hook_entries[h];
695 if ((unsigned char *)e - base == underflows[h])
696 newinfo->underflow[h] = underflows[h];
699 /* FIXME: underflows must be unconditional, standard verdicts
700 < 0 (not IP6T_RETURN). --RR */
702 /* Clear counters and comefrom */
703 e->counters = ((struct xt_counters) { 0, 0 });
711 cleanup_entry(struct ip6t_entry *e, unsigned int *i)
713 struct ip6t_entry_target *t;
715 if (i && (*i)-- == 0)
718 /* Cleanup all matches */
719 IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
720 t = ip6t_get_target(e);
721 if (t->u.kernel.target->destroy)
722 t->u.kernel.target->destroy(t->data,
723 t->u.target_size - sizeof(*t));
724 module_put(t->u.kernel.target->me);
728 /* Checks and translates the user-supplied table segment (held in
731 translate_table(const char *name,
732 unsigned int valid_hooks,
733 struct xt_table_info *newinfo,
737 const unsigned int *hook_entries,
738 const unsigned int *underflows)
743 newinfo->size = size;
744 newinfo->number = number;
746 /* Init all hooks to impossible value. */
747 for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
748 newinfo->hook_entry[i] = 0xFFFFFFFF;
749 newinfo->underflow[i] = 0xFFFFFFFF;
752 duprintf("translate_table: size %u\n", newinfo->size);
754 /* Walk through entries, checking offsets. */
755 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
756 check_entry_size_and_hooks,
760 hook_entries, underflows, &i);
765 duprintf("translate_table: %u not %u entries\n",
770 /* Check hooks all assigned */
771 for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
772 /* Only hooks which are valid */
773 if (!(valid_hooks & (1 << i)))
775 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
776 duprintf("Invalid hook entry %u %u\n",
780 if (newinfo->underflow[i] == 0xFFFFFFFF) {
781 duprintf("Invalid underflow %u %u\n",
787 if (!mark_source_chains(newinfo, valid_hooks, entry0))
790 /* Finally, each sanity check must pass */
792 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
793 check_entry, name, size, &i);
796 IP6T_ENTRY_ITERATE(entry0, newinfo->size,
801 /* And one copy for every other CPU */
803 if (newinfo->entries[i] && newinfo->entries[i] != entry0)
804 memcpy(newinfo->entries[i], entry0, newinfo->size);
812 add_entry_to_counter(const struct ip6t_entry *e,
813 struct xt_counters total[],
816 ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
823 set_entry_to_counter(const struct ip6t_entry *e,
824 struct ip6t_counters total[],
827 SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
834 get_counters(const struct xt_table_info *t,
835 struct xt_counters counters[])
841 /* Instead of clearing (by a previous call to memset())
842 * the counters and using adds, we set the counters
843 * with data used by 'current' CPU
844 * We dont care about preemption here.
846 curcpu = raw_smp_processor_id();
849 IP6T_ENTRY_ITERATE(t->entries[curcpu],
851 set_entry_to_counter,
859 IP6T_ENTRY_ITERATE(t->entries[cpu],
861 add_entry_to_counter,
868 copy_entries_to_user(unsigned int total_size,
869 struct xt_table *table,
870 void __user *userptr)
872 unsigned int off, num, countersize;
873 struct ip6t_entry *e;
874 struct xt_counters *counters;
875 struct xt_table_info *private = table->private;
879 /* We need atomic snapshot of counters: rest doesn't change
880 (other than comefrom, which userspace doesn't care
882 countersize = sizeof(struct xt_counters) * private->number;
883 counters = vmalloc(countersize);
885 if (counters == NULL)
888 /* First, sum counters... */
889 write_lock_bh(&table->lock);
890 get_counters(private, counters);
891 write_unlock_bh(&table->lock);
893 /* choose the copy that is on ourc node/cpu */
894 loc_cpu_entry = private->entries[raw_smp_processor_id()];
895 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
900 /* FIXME: use iterator macros --RR */
901 /* ... then go back and fix counters and names */
902 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
904 struct ip6t_entry_match *m;
905 struct ip6t_entry_target *t;
907 e = (struct ip6t_entry *)(loc_cpu_entry + off);
908 if (copy_to_user(userptr + off
909 + offsetof(struct ip6t_entry, counters),
911 sizeof(counters[num])) != 0) {
916 for (i = sizeof(struct ip6t_entry);
917 i < e->target_offset;
918 i += m->u.match_size) {
921 if (copy_to_user(userptr + off + i
922 + offsetof(struct ip6t_entry_match,
924 m->u.kernel.match->name,
925 strlen(m->u.kernel.match->name)+1)
932 t = ip6t_get_target(e);
933 if (copy_to_user(userptr + off + e->target_offset
934 + offsetof(struct ip6t_entry_target,
936 t->u.kernel.target->name,
937 strlen(t->u.kernel.target->name)+1) != 0) {
949 get_entries(const struct ip6t_get_entries *entries,
950 struct ip6t_get_entries __user *uptr)
955 t = xt_find_table_lock(AF_INET6, entries->name);
956 if (t && !IS_ERR(t)) {
957 struct xt_table_info *private = t->private;
958 duprintf("t->private->number = %u\n", private->number);
959 if (entries->size == private->size)
960 ret = copy_entries_to_user(private->size,
961 t, uptr->entrytable);
963 duprintf("get_entries: I've got %u not %u!\n",
964 private->size, entries->size);
970 ret = t ? PTR_ERR(t) : -ENOENT;
976 do_replace(void __user *user, unsigned int len)
979 struct ip6t_replace tmp;
981 struct xt_table_info *newinfo, *oldinfo;
982 struct xt_counters *counters;
983 void *loc_cpu_entry, *loc_cpu_old_entry;
985 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
989 if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
992 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
995 newinfo = xt_alloc_table_info(tmp.size);
999 /* choose the copy that is on our node/cpu */
1000 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1001 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
1007 counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
1013 ret = translate_table(tmp.name, tmp.valid_hooks,
1014 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1015 tmp.hook_entry, tmp.underflow);
1017 goto free_newinfo_counters;
1019 duprintf("ip_tables: Translated table\n");
1021 t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
1022 "ip6table_%s", tmp.name);
1023 if (!t || IS_ERR(t)) {
1024 ret = t ? PTR_ERR(t) : -ENOENT;
1025 goto free_newinfo_counters_untrans;
1029 if (tmp.valid_hooks != t->valid_hooks) {
1030 duprintf("Valid hook crap: %08X vs %08X\n",
1031 tmp.valid_hooks, t->valid_hooks);
1036 oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
1040 /* Update module usage count based on number of rules */
1041 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
1042 oldinfo->number, oldinfo->initial_entries, newinfo->number);
1043 if ((oldinfo->number > oldinfo->initial_entries) ||
1044 (newinfo->number <= oldinfo->initial_entries))
1046 if ((oldinfo->number > oldinfo->initial_entries) &&
1047 (newinfo->number <= oldinfo->initial_entries))
1050 /* Get the old counters. */
1051 get_counters(oldinfo, counters);
1052 /* Decrease module usage counts and free resource */
1053 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1054 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
1055 xt_free_table_info(oldinfo);
1056 if (copy_to_user(tmp.counters, counters,
1057 sizeof(struct xt_counters) * tmp.num_counters) != 0)
1066 free_newinfo_counters_untrans:
1067 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
1068 free_newinfo_counters:
1071 xt_free_table_info(newinfo);
1075 /* We're lazy, and add to the first CPU; overflow works its fey magic
1076 * and everything is OK. */
1078 add_counter_to_entry(struct ip6t_entry *e,
1079 const struct xt_counters addme[],
1083 duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
1085 (long unsigned int)e->counters.pcnt,
1086 (long unsigned int)e->counters.bcnt,
1087 (long unsigned int)addme[*i].pcnt,
1088 (long unsigned int)addme[*i].bcnt);
1091 ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
1098 do_add_counters(void __user *user, unsigned int len)
1101 struct xt_counters_info tmp, *paddc;
1102 struct xt_table_info *private;
1105 void *loc_cpu_entry;
1107 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1110 if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
1113 paddc = vmalloc(len);
1117 if (copy_from_user(paddc, user, len) != 0) {
1122 t = xt_find_table_lock(AF_INET6, tmp.name);
1123 if (!t || IS_ERR(t)) {
1124 ret = t ? PTR_ERR(t) : -ENOENT;
1128 write_lock_bh(&t->lock);
1129 private = t->private;
1130 if (private->number != paddc->num_counters) {
1132 goto unlock_up_free;
1136 /* Choose the copy that is on our node */
1137 loc_cpu_entry = private->entries[smp_processor_id()];
1138 IP6T_ENTRY_ITERATE(loc_cpu_entry,
1140 add_counter_to_entry,
1144 write_unlock_bh(&t->lock);
1154 do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
1158 if (!capable(CAP_NET_ADMIN))
1162 case IP6T_SO_SET_REPLACE:
1163 ret = do_replace(user, len);
1166 case IP6T_SO_SET_ADD_COUNTERS:
1167 ret = do_add_counters(user, len);
1171 duprintf("do_ip6t_set_ctl: unknown request %i\n", cmd);
1179 do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1183 if (!capable(CAP_NET_ADMIN))
1187 case IP6T_SO_GET_INFO: {
1188 char name[IP6T_TABLE_MAXNAMELEN];
1191 if (*len != sizeof(struct ip6t_getinfo)) {
1192 duprintf("length %u != %u\n", *len,
1193 sizeof(struct ip6t_getinfo));
1198 if (copy_from_user(name, user, sizeof(name)) != 0) {
1202 name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
1204 t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
1205 "ip6table_%s", name);
1206 if (t && !IS_ERR(t)) {
1207 struct ip6t_getinfo info;
1208 struct xt_table_info *private = t->private;
1210 info.valid_hooks = t->valid_hooks;
1211 memcpy(info.hook_entry, private->hook_entry,
1212 sizeof(info.hook_entry));
1213 memcpy(info.underflow, private->underflow,
1214 sizeof(info.underflow));
1215 info.num_entries = private->number;
1216 info.size = private->size;
1217 memcpy(info.name, name, sizeof(info.name));
1219 if (copy_to_user(user, &info, *len) != 0)
1226 ret = t ? PTR_ERR(t) : -ENOENT;
1230 case IP6T_SO_GET_ENTRIES: {
1231 struct ip6t_get_entries get;
1233 if (*len < sizeof(get)) {
1234 duprintf("get_entries: %u < %u\n", *len, sizeof(get));
1236 } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
1238 } else if (*len != sizeof(struct ip6t_get_entries) + get.size) {
1239 duprintf("get_entries: %u != %u\n", *len,
1240 sizeof(struct ip6t_get_entries) + get.size);
1243 ret = get_entries(&get, user);
1247 case IP6T_SO_GET_REVISION_MATCH:
1248 case IP6T_SO_GET_REVISION_TARGET: {
1249 struct ip6t_get_revision rev;
1252 if (*len != sizeof(rev)) {
1256 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1261 if (cmd == IP6T_SO_GET_REVISION_TARGET)
1266 try_then_request_module(xt_find_revision(AF_INET6, rev.name,
1269 "ip6t_%s", rev.name);
1274 duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
1281 int ip6t_register_table(struct xt_table *table,
1282 const struct ip6t_replace *repl)
1285 struct xt_table_info *newinfo;
1286 static struct xt_table_info bootstrap
1287 = { 0, 0, 0, { 0 }, { 0 }, { } };
1288 void *loc_cpu_entry;
1290 newinfo = xt_alloc_table_info(repl->size);
1294 /* choose the copy on our node/cpu */
1295 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
1296 memcpy(loc_cpu_entry, repl->entries, repl->size);
1298 ret = translate_table(table->name, table->valid_hooks,
1299 newinfo, loc_cpu_entry, repl->size,
1304 xt_free_table_info(newinfo);
1308 if (xt_register_table(table, &bootstrap, newinfo) != 0) {
1309 xt_free_table_info(newinfo);
1316 void ip6t_unregister_table(struct xt_table *table)
1318 struct xt_table_info *private;
1319 void *loc_cpu_entry;
1321 private = xt_unregister_table(table);
1323 /* Decrease module usage counts and free resources */
1324 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1325 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
1326 xt_free_table_info(private);
1329 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
1331 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
1332 u_int8_t type, u_int8_t code,
1335 return (type == test_type && code >= min_code && code <= max_code)
1340 icmp6_match(const struct sk_buff *skb,
1341 const struct net_device *in,
1342 const struct net_device *out,
1343 const void *matchinfo,
1345 unsigned int protoff,
1348 struct icmp6hdr _icmp, *ic;
1349 const struct ip6t_icmp *icmpinfo = matchinfo;
1351 /* Must not be a fragment. */
1355 ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
1357 /* We've been asked to examine this packet, and we
1358 can't. Hence, no choice but to drop. */
1359 duprintf("Dropping evil ICMP tinygram.\n");
1364 return icmp6_type_code_match(icmpinfo->type,
1367 ic->icmp6_type, ic->icmp6_code,
1368 !!(icmpinfo->invflags&IP6T_ICMP_INV));
1371 /* Called when user tries to insert an entry of this type. */
1373 icmp6_checkentry(const char *tablename,
1376 unsigned int matchsize,
1377 unsigned int hook_mask)
1379 const struct ip6t_icmp *icmpinfo = matchinfo;
1381 /* Must specify no unknown invflags */
1382 return !(icmpinfo->invflags & ~IP6T_ICMP_INV);
1385 /* The built-in targets: standard (NULL) and error. */
1386 static struct ip6t_target ip6t_standard_target = {
1387 .name = IP6T_STANDARD_TARGET,
1388 .targetsize = sizeof(int),
1391 static struct ip6t_target ip6t_error_target = {
1392 .name = IP6T_ERROR_TARGET,
1393 .target = ip6t_error,
1394 .targetsize = IP6T_FUNCTION_MAXNAMELEN,
1397 static struct nf_sockopt_ops ip6t_sockopts = {
1399 .set_optmin = IP6T_BASE_CTL,
1400 .set_optmax = IP6T_SO_SET_MAX+1,
1401 .set = do_ip6t_set_ctl,
1402 .get_optmin = IP6T_BASE_CTL,
1403 .get_optmax = IP6T_SO_GET_MAX+1,
1404 .get = do_ip6t_get_ctl,
1407 static struct ip6t_match icmp6_matchstruct = {
1409 .match = &icmp6_match,
1410 .matchsize = sizeof(struct ip6t_icmp),
1411 .checkentry = icmp6_checkentry,
1412 .proto = IPPROTO_ICMPV6,
1415 static int __init init(void)
1419 xt_proto_init(AF_INET6);
1421 /* Noone else will be downing sem now, so we won't sleep */
1422 xt_register_target(AF_INET6, &ip6t_standard_target);
1423 xt_register_target(AF_INET6, &ip6t_error_target);
1424 xt_register_match(AF_INET6, &icmp6_matchstruct);
1426 /* Register setsockopt */
1427 ret = nf_register_sockopt(&ip6t_sockopts);
1429 duprintf("Unable to register sockopts.\n");
1430 xt_proto_fini(AF_INET6);
1434 printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
1438 static void __exit fini(void)
1440 nf_unregister_sockopt(&ip6t_sockopts);
1441 xt_unregister_match(AF_INET6, &icmp6_matchstruct);
1442 xt_unregister_target(AF_INET6, &ip6t_error_target);
1443 xt_unregister_target(AF_INET6, &ip6t_standard_target);
1444 xt_proto_fini(AF_INET6);
1448 * find the offset to specified header or the protocol number of last header
1449 * if target < 0. "last header" is transport protocol header, ESP, or
1452 * If target header is found, its offset is set in *offset and return protocol
1453 * number. Otherwise, return -1.
1455 * Note that non-1st fragment is special case that "the protocol number
1456 * of last header" is "next header" field in Fragment header. In this case,
1457 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
1461 int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
1462 int target, unsigned short *fragoff)
1464 unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data;
1465 u8 nexthdr = skb->nh.ipv6h->nexthdr;
1466 unsigned int len = skb->len - start;
1471 while (nexthdr != target) {
1472 struct ipv6_opt_hdr _hdr, *hp;
1473 unsigned int hdrlen;
1475 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
1481 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
1484 if (nexthdr == NEXTHDR_FRAGMENT) {
1485 unsigned short _frag_off, *fp;
1486 fp = skb_header_pointer(skb,
1487 start+offsetof(struct frag_hdr,
1494 _frag_off = ntohs(*fp) & ~0x7;
1497 ((!ipv6_ext_hdr(hp->nexthdr)) ||
1498 nexthdr == NEXTHDR_NONE)) {
1500 *fragoff = _frag_off;
1506 } else if (nexthdr == NEXTHDR_AUTH)
1507 hdrlen = (hp->hdrlen + 2) << 2;
1509 hdrlen = ipv6_optlen(hp);
1511 nexthdr = hp->nexthdr;
1520 EXPORT_SYMBOL(ip6t_register_table);
1521 EXPORT_SYMBOL(ip6t_unregister_table);
1522 EXPORT_SYMBOL(ip6t_do_table);
1523 EXPORT_SYMBOL(ip6t_ext_hdr);
1524 EXPORT_SYMBOL(ipv6_find_hdr);
1525 EXPORT_SYMBOL(ip6_masked_addrcmp);