diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-23 16:49:31 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-23 16:49:31 -0700 |
commit | a4c12d6c5dde48c69464baf7c703e425ee511433 (patch) | |
tree | 73c375e41a353e2da0461ff30d744bff73958b08 /net/ipv6/xfrm6_input.c | |
parent | 73af07de3e32b9ac328c3d1417258bb98a9b0a9b (diff) | |
parent | 3b9f9a1c3903b64c38505f9fed3bb11e48dbc931 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (353 commits)
[IPV6] ADDRCONF: Mobile IPv6 Home Address support.
[IPV6] ADDRCONF: Allow non-DAD'able addresses.
[IPV6] NDISC: Fix is_router flag setting.
[IPV6] ADDRCONF: Convert addrconf_lock to RCU.
[IPV6] NDISC: Add proxy_ndp sysctl.
[IPV6] NDISC: Set per-entry is_router flag in Proxy NA.
[IPV6] NDISC: Avoid updating neighbor cache for proxied address in receiving NA.
[IPV6]: Don't forward packets to proxied link-local address.
[IPV6] NDISC: Handle NDP messages to proxied addresses.
[NETFILTER]: PPTP conntrack: fix another GRE keymap leak
[NETFILTER]: PPTP conntrack: fix GRE keymap leak
[NETFILTER]: PPTP conntrack: fix PPTP_IN_CALL message types
[NETFILTER]: PPTP conntrack: check call ID before changing state
[NETFILTER]: PPTP conntrack: clean up debugging cruft
[NETFILTER]: PPTP conntrack: consolidate header parsing
[NETFILTER]: PPTP conntrack: consolidate header size checks
[NETFILTER]: PPTP conntrack: simplify expectation handling
[NETFILTER]: PPTP conntrack: remove unnecessary cid/pcid header pointers
[NETFILTER]: PPTP conntrack: fix header definitions
[NETFILTER]: PPTP conntrack: remove more dead code
...
Diffstat (limited to 'net/ipv6/xfrm6_input.c')
-rw-r--r-- | net/ipv6/xfrm6_input.c | 110 |
1 files changed, 109 insertions, 1 deletions
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 0405d74ff910..a40a05789013 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -72,7 +72,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) if (x->mode->input(x, skb)) goto drop; - if (x->props.mode) { /* XXX */ + if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */ decaps = 1; break; } @@ -138,3 +138,111 @@ int xfrm6_rcv(struct sk_buff **pskb) { return xfrm6_rcv_spi(*pskb, 0); } + +int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, + xfrm_address_t *saddr, u8 proto) +{ + struct xfrm_state *x = NULL; + int wildcard = 0; + struct in6_addr any; + xfrm_address_t *xany; + struct xfrm_state *xfrm_vec_one = NULL; + int nh = 0; + int i = 0; + + ipv6_addr_set(&any, 0, 0, 0, 0); + xany = (xfrm_address_t *)&any; + + for (i = 0; i < 3; i++) { + xfrm_address_t *dst, *src; + switch (i) { + case 0: + dst = daddr; + src = saddr; + break; + case 1: + /* lookup state with wild-card source address */ + wildcard = 1; + dst = daddr; + src = xany; + break; + case 2: + default: + /* lookup state with wild-card addresses */ + wildcard = 1; /* XXX */ + dst = xany; + src = xany; + break; + } + + x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6); + if (!x) + continue; + + spin_lock(&x->lock); + + if (wildcard) { + if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) { + spin_unlock(&x->lock); + xfrm_state_put(x); + x = NULL; + continue; + } + } + + if (unlikely(x->km.state != XFRM_STATE_VALID)) { + spin_unlock(&x->lock); + xfrm_state_put(x); + x = NULL; + continue; + } + if (xfrm_state_check_expire(x)) { + spin_unlock(&x->lock); + xfrm_state_put(x); + x = NULL; + continue; + } + + nh = x->type->input(x, skb); + if (nh <= 0) { + spin_unlock(&x->lock); + xfrm_state_put(x); + x = NULL; + continue; + } + + x->curlft.bytes += skb->len; + x->curlft.packets++; + + spin_unlock(&x->lock); + + xfrm_vec_one = x; + break; + } + + if (!xfrm_vec_one) + goto drop; + + /* Allocate new secpath or COW existing one. */ + if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { + struct sec_path *sp; + sp = secpath_dup(skb->sp); + if (!sp) + goto drop; + if (skb->sp) + secpath_put(skb->sp); + skb->sp = sp; + } + + if (1 + skb->sp->len > XFRM_MAX_DEPTH) + goto drop; + + skb->sp->xvec[skb->sp->len] = xfrm_vec_one; + skb->sp->len ++; + + return 1; +drop: + if (xfrm_vec_one) + xfrm_state_put(xfrm_vec_one); + return -1; +} |