Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65d4ed92 authored by Masahide NAKAMURA's avatar Masahide NAKAMURA Committed by David S. Miller
Browse files

[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: default avatarMasahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 642ec62e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -61,6 +61,13 @@ extern int addrconf_set_dstaddr(void __user *arg);
extern int			ipv6_chk_addr(struct in6_addr *addr,
					      struct net_device *dev,
					      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,
						struct net_device *dev,
						int strict);
+61 −8
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@
#include <net/ndisc.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
#ifdef CONFIG_IPV6_MIP6
#include <net/xfrm.h>
#endif

#include <asm/uaccess.h>

@@ -219,7 +222,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
{
	struct sk_buff *skb = *skbp;
	struct inet6_skb_parm *opt = IP6CB(skb);
	struct in6_addr *addr;
	struct in6_addr *addr = NULL;
	struct in6_addr daddr;
	int n, i;

@@ -244,6 +247,23 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)

looped_back:
	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->srcrt = skb->h.raw - skb->nh.raw;
		skb->h.raw += (hdr->hdrlen + 1) << 3;
@@ -253,15 +273,27 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
		return 1;
	}

	if (hdr->type != IPV6_SRCRT_TYPE_0) {
	switch (hdr->type) {
	case IPV6_SRCRT_TYPE_0:
		if (hdr->hdrlen & 0x01) {
			IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw);
			icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
			return -1;
		}
	
	if (hdr->hdrlen & 0x01) {
		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);
		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw);
			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;
	}

@@ -303,6 +335,27 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
	addr = rthdr->addr;
	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)) {
		IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
		kfree_skb(skb);