summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2006-08-24 04:18:35 +0200
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-23 00:06:50 +0200
commitc61a404325093250b676f40ad8f4dd00f3bcab5f (patch)
tree8494f117afa5d79fcd97d57fe69e64369d5a78d7
parent[IPV6] MIP6: Add socket option and ancillary data interface of routing header... (diff)
downloadlinux-c61a404325093250b676f40ad8f4dd00f3bcab5f.tar.xz
linux-c61a404325093250b676f40ad8f4dd00f3bcab5f.zip
[IPV6]: Find option offset by type.
This is a helper to search option offset from extension header which can carry TLV option like destination options header. Mobile IPv6 home address option will use it. Based on MIPL2 kernel patch. Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ipv6.h2
-rw-r--r--net/ipv6/exthdrs.c43
2 files changed, 45 insertions, 0 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index ece7e8a84ffd..c4ea12710576 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -506,6 +506,8 @@ extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
extern int ipv6_ext_hdr(u8 nexthdr);
+extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
+
extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk,
struct ipv6_rt_hdr *hdr);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 8d3a0e17314d..50ff49e518bc 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -49,6 +49,49 @@
#include <asm/uaccess.h>
+int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
+{
+ int packet_len = skb->tail - skb->nh.raw;
+ struct ipv6_opt_hdr *hdr;
+ int len;
+
+ if (offset + 2 > packet_len)
+ goto bad;
+ hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+ len = ((hdr->hdrlen + 1) << 3);
+
+ if (offset + len > packet_len)
+ goto bad;
+
+ offset += 2;
+ len -= 2;
+
+ while (len > 0) {
+ int opttype = skb->nh.raw[offset];
+ int optlen;
+
+ if (opttype == type)
+ return offset;
+
+ switch (opttype) {
+ case IPV6_TLV_PAD0:
+ optlen = 1;
+ break;
+ default:
+ optlen = skb->nh.raw[offset + 1] + 2;
+ if (optlen > len)
+ goto bad;
+ break;
+ }
+ offset += optlen;
+ len -= optlen;
+ }
+ /* not_found */
+ return -1;
+ bad:
+ return -1;
+}
+
/*
* Parsing tlv encoded headers.
*