diff options
author | Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> | 2005-09-19 18:34:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-09-19 18:34:40 -0400 |
commit | e674d0f38de6109b59dbe30fba8b296a03229b8e (patch) | |
tree | 459271f7cef6319dfa7ca9ab050269c98e551994 /net/ipv6/netfilter/ip6_tables.c | |
parent | 926b50f92a30090da2c1a8675de954c2d9b09732 (diff) |
[NETFILTER] ip6tables: remove duplicate code
Some IPv6 matches have very similar loops to find IPv6 extension header
and we can unify them. This patch introduces ipv6_find_hdr() to do it.
I just checked that it can find the target headers in the packet which has
dst,hbh,rt,frag,ah,esp headers.
Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: Harald Welte <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/netfilter/ip6_tables.c')
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1cb8adb2787..2da514b16d9 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1955,6 +1955,57 @@ static void __exit fini(void) | |||
1955 | #endif | 1955 | #endif |
1956 | } | 1956 | } |
1957 | 1957 | ||
1958 | /* | ||
1959 | * find specified header up to transport protocol header. | ||
1960 | * If found target header, the offset to the header is set to *offset | ||
1961 | * and return 0. otherwise, return -1. | ||
1962 | * | ||
1963 | * Notes: - non-1st Fragment Header isn't skipped. | ||
1964 | * - ESP header isn't skipped. | ||
1965 | * - The target header may be trancated. | ||
1966 | */ | ||
1967 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target) | ||
1968 | { | ||
1969 | unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data; | ||
1970 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | ||
1971 | unsigned int len = skb->len - start; | ||
1972 | |||
1973 | while (nexthdr != target) { | ||
1974 | struct ipv6_opt_hdr _hdr, *hp; | ||
1975 | unsigned int hdrlen; | ||
1976 | |||
1977 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) | ||
1978 | return -1; | ||
1979 | hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); | ||
1980 | if (hp == NULL) | ||
1981 | return -1; | ||
1982 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
1983 | unsigned short _frag_off, *fp; | ||
1984 | fp = skb_header_pointer(skb, | ||
1985 | start+offsetof(struct frag_hdr, | ||
1986 | frag_off), | ||
1987 | sizeof(_frag_off), | ||
1988 | &_frag_off); | ||
1989 | if (fp == NULL) | ||
1990 | return -1; | ||
1991 | |||
1992 | if (ntohs(*fp) & ~0x7) | ||
1993 | return -1; | ||
1994 | hdrlen = 8; | ||
1995 | } else if (nexthdr == NEXTHDR_AUTH) | ||
1996 | hdrlen = (hp->hdrlen + 2) << 2; | ||
1997 | else | ||
1998 | hdrlen = ipv6_optlen(hp); | ||
1999 | |||
2000 | nexthdr = hp->nexthdr; | ||
2001 | len -= hdrlen; | ||
2002 | start += hdrlen; | ||
2003 | } | ||
2004 | |||
2005 | *offset = start; | ||
2006 | return 0; | ||
2007 | } | ||
2008 | |||
1958 | EXPORT_SYMBOL(ip6t_register_table); | 2009 | EXPORT_SYMBOL(ip6t_register_table); |
1959 | EXPORT_SYMBOL(ip6t_unregister_table); | 2010 | EXPORT_SYMBOL(ip6t_unregister_table); |
1960 | EXPORT_SYMBOL(ip6t_do_table); | 2011 | EXPORT_SYMBOL(ip6t_do_table); |
@@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match); | |||
1963 | EXPORT_SYMBOL(ip6t_register_target); | 2014 | EXPORT_SYMBOL(ip6t_register_target); |
1964 | EXPORT_SYMBOL(ip6t_unregister_target); | 2015 | EXPORT_SYMBOL(ip6t_unregister_target); |
1965 | EXPORT_SYMBOL(ip6t_ext_hdr); | 2016 | EXPORT_SYMBOL(ip6t_ext_hdr); |
2017 | EXPORT_SYMBOL(ipv6_find_hdr); | ||
1966 | 2018 | ||
1967 | module_init(init); | 2019 | module_init(init); |
1968 | module_exit(fini); | 2020 | module_exit(fini); |