aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Nuorvala <vnuorval@tcs.hut.fi>2006-09-22 14:41:44 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 15:20:21 -0700
commite21e0b5f19ac7835a244c2016f7ed726f971b3e9 (patch)
tree93c12a003ed5a86caf0fe28ade960da219835cd3
parent4c5de695cf7f71c85ad8cfff509f6475b8bd4d27 (diff)
[IPV6] NDISC: Handle NDP messages to proxied addresses.
It is required to respond to NDP messages sent directly to the "target" unicast address. Proxying node (router) is required to handle such messages. To achieve this, check if the packet in forwarding patch is NDP message. With this patch, the proxy neighbor entries are always looked up in forwarding path. We may want to optimize further. Based on MIPL2 kernel patch. Signed-off-by: Ville Nuorvala <vnuorval@tcs.hut.fi> Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
-rw-r--r--net/ipv6/ip6_output.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index c14ea1ecf37..0f56e9e69a8 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -308,6 +308,46 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel)
return 0;
}
+static int ip6_forward_proxy_check(struct sk_buff *skb)
+{
+ struct ipv6hdr *hdr = skb->nh.ipv6h;
+ u8 nexthdr = hdr->nexthdr;
+ int offset;
+
+ if (ipv6_ext_hdr(nexthdr)) {
+ offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr);
+ if (offset < 0)
+ return 0;
+ } else
+ offset = sizeof(struct ipv6hdr);
+
+ if (nexthdr == IPPROTO_ICMPV6) {
+ struct icmp6hdr *icmp6;
+
+ if (!pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data))
+ return 0;
+
+ icmp6 = (struct icmp6hdr *)(skb->nh.raw + offset);
+
+ switch (icmp6->icmp6_type) {
+ case NDISC_ROUTER_SOLICITATION:
+ case NDISC_ROUTER_ADVERTISEMENT:
+ case NDISC_NEIGHBOUR_SOLICITATION:
+ case NDISC_NEIGHBOUR_ADVERTISEMENT:
+ case NDISC_REDIRECT:
+ /* For reaction involving unicast neighbor discovery
+ * message destined to the proxied address, pass it to
+ * input function.
+ */
+ return 1;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
static inline int ip6_forward_finish(struct sk_buff *skb)
{
return dst_output(skb);
@@ -362,6 +402,11 @@ int ip6_forward(struct sk_buff *skb)
return -ETIMEDOUT;
}
+ if (pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) {
+ if (ip6_forward_proxy_check(skb))
+ return ip6_input(skb);
+ }
+
if (!xfrm6_route_forward(skb)) {
IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
goto drop;