[IPV6] MIP6: Add inbound interface of routing header type 2.
Add inbound interface of routing header type 2 for Mobile IPv6. Based on MIPL2 kernel patch. This patch was also written 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> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
642ec62eee
commit
65d4ed9221
@@ -61,6 +61,13 @@ extern int addrconf_set_dstaddr(void __user *arg);
|
|||||||
extern int ipv6_chk_addr(struct in6_addr *addr,
|
extern int ipv6_chk_addr(struct in6_addr *addr,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
int strict);
|
int strict);
|
||||||
|
/* XXX: this is a placeholder till addrconf supports */
|
||||||
|
#ifdef CONFIG_IPV6_MIP6
|
||||||
|
static inline int ipv6_chk_home_addr(struct in6_addr *addr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
|
extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
int strict);
|
int strict);
|
||||||
|
@@ -43,6 +43,9 @@
|
|||||||
#include <net/ndisc.h>
|
#include <net/ndisc.h>
|
||||||
#include <net/ip6_route.h>
|
#include <net/ip6_route.h>
|
||||||
#include <net/addrconf.h>
|
#include <net/addrconf.h>
|
||||||
|
#ifdef CONFIG_IPV6_MIP6
|
||||||
|
#include <net/xfrm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
@@ -219,7 +222,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
|
|||||||
{
|
{
|
||||||
struct sk_buff *skb = *skbp;
|
struct sk_buff *skb = *skbp;
|
||||||
struct inet6_skb_parm *opt = IP6CB(skb);
|
struct inet6_skb_parm *opt = IP6CB(skb);
|
||||||
struct in6_addr *addr;
|
struct in6_addr *addr = NULL;
|
||||||
struct in6_addr daddr;
|
struct in6_addr daddr;
|
||||||
int n, i;
|
int n, i;
|
||||||
|
|
||||||
@@ -244,6 +247,23 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
|
|||||||
|
|
||||||
looped_back:
|
looped_back:
|
||||||
if (hdr->segments_left == 0) {
|
if (hdr->segments_left == 0) {
|
||||||
|
switch (hdr->type) {
|
||||||
|
#ifdef CONFIG_IPV6_MIP6
|
||||||
|
case IPV6_SRCRT_TYPE_2:
|
||||||
|
/* Silently discard type 2 header unless it was
|
||||||
|
* processed by own
|
||||||
|
*/
|
||||||
|
if (!addr) {
|
||||||
|
IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
|
||||||
|
kfree_skb(skb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
opt->lastopt = skb->h.raw - skb->nh.raw;
|
opt->lastopt = skb->h.raw - skb->nh.raw;
|
||||||
opt->srcrt = skb->h.raw - skb->nh.raw;
|
opt->srcrt = skb->h.raw - skb->nh.raw;
|
||||||
skb->h.raw += (hdr->hdrlen + 1) << 3;
|
skb->h.raw += (hdr->hdrlen + 1) << 3;
|
||||||
@@ -253,17 +273,29 @@ looped_back:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdr->type != IPV6_SRCRT_TYPE_0) {
|
switch (hdr->type) {
|
||||||
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
|
case IPV6_SRCRT_TYPE_0:
|
||||||
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hdr->hdrlen & 0x01) {
|
if (hdr->hdrlen & 0x01) {
|
||||||
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
|
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
|
||||||
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
|
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
#ifdef CONFIG_IPV6_MIP6
|
||||||
|
case IPV6_SRCRT_TYPE_2:
|
||||||
|
/* Silently discard invalid RTH type 2 */
|
||||||
|
if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
|
||||||
|
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
|
||||||
|
kfree_skb(skb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
|
||||||
|
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the routing header forwarding algorithm from
|
* This is the routing header forwarding algorithm from
|
||||||
@@ -303,6 +335,27 @@ looped_back:
|
|||||||
addr = rthdr->addr;
|
addr = rthdr->addr;
|
||||||
addr += i - 1;
|
addr += i - 1;
|
||||||
|
|
||||||
|
switch (hdr->type) {
|
||||||
|
#ifdef CONFIG_IPV6_MIP6
|
||||||
|
case IPV6_SRCRT_TYPE_2:
|
||||||
|
if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
|
||||||
|
(xfrm_address_t *)&skb->nh.ipv6h->saddr,
|
||||||
|
IPPROTO_ROUTING) < 0) {
|
||||||
|
IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
|
||||||
|
kfree_skb(skb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!ipv6_chk_home_addr(addr)) {
|
||||||
|
IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
|
||||||
|
kfree_skb(skb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ipv6_addr_is_multicast(addr)) {
|
if (ipv6_addr_is_multicast(addr)) {
|
||||||
IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
|
IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
Reference in New Issue
Block a user