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

Commit 3b9f9a1c authored by Noriaki TAKAMIYA's avatar Noriaki TAKAMIYA Committed by David S. Miller
Browse files

[IPV6] ADDRCONF: Mobile IPv6 Home Address support.



IFA_F_HOMEADDRESS is introduced for Mobile IPv6 Home Addresses on
Mobile Node.

The IFA_F_HOMEADDRESS flag should be set for Mobile IPv6 Home
Addresses for 2 purposes. 1) We need to check this on receipt of
Type 2 Routing Header (RFC3775 Secion 6.4), 2) We prefer Home
Address(es) in source address selection (RFC3484 Section 5 Rule 4).

Signed-off-by: default avatarNoriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 55ebaef1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ enum
#define IFA_F_TEMPORARY		IFA_F_SECONDARY

#define	IFA_F_NODAD		0x02
#define	IFA_F_HOMEADDRESS	0x10
#define IFA_F_DEPRECATED	0x20
#define IFA_F_TENTATIVE		0x40
#define IFA_F_PERMANENT		0x80
+1 −5
Original line number Diff line number Diff line
@@ -61,12 +61,8 @@ 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;
}
extern int			ipv6_chk_home_addr(struct in6_addr *addr);
#endif
extern struct inet6_ifaddr *	ipv6_get_ifaddr(struct in6_addr *addr,
						struct net_device *dev,
+41 −3
Original line number Diff line number Diff line
@@ -1038,9 +1038,27 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
					continue;
			}

			/* Rule 4: Prefer home address -- not implemented yet */
			/* Rule 4: Prefer home address */
#ifdef CONFIG_IPV6_MIP6
			if (hiscore.rule < 4) {
				if (ifa_result->flags & IFA_F_HOMEADDRESS)
					hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
				hiscore.rule++;
			}
			if (ifa->flags & IFA_F_HOMEADDRESS) {
				score.attrs |= IPV6_SADDR_SCORE_HOA;
				if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) {
					score.rule = 4;
					goto record_it;
				}
			} else {
				if (hiscore.attrs & IPV6_SADDR_SCORE_HOA)
					continue;
			}
#else
			if (hiscore.rule < 4)
				hiscore.rule++;
#endif

			/* Rule 5: Prefer outgoing interface */
			if (hiscore.rule < 5) {
@@ -2759,6 +2777,26 @@ void if6_proc_exit(void)
}
#endif	/* CONFIG_PROC_FS */

#ifdef CONFIG_IPV6_MIP6
/* Check if address is a home address configured on any interface. */
int ipv6_chk_home_addr(struct in6_addr *addr)
{
	int ret = 0;
	struct inet6_ifaddr * ifp;
	u8 hash = ipv6_addr_hash(addr);
	read_lock_bh(&addrconf_hash_lock);
	for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
		if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
		    (ifp->flags & IFA_F_HOMEADDRESS)) {
			ret = 1;
			break;
		}
	}
	read_unlock_bh(&addrconf_hash_lock);
	return ret;
}
#endif

/*
 *	Periodic address status verification
 */
@@ -2930,7 +2968,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
		prefered_lft = 0x7FFFFFFF/HZ;

	spin_lock_bh(&ifp->lock);
	ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD)) | ifa_flags;
	ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
	ifp->tstamp = jiffies;
	ifp->valid_lft = valid_lft;
	ifp->prefered_lft = prefered_lft;
@@ -2981,7 +3019,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
		return -ENODEV;

	/* We ignore other flags so far. */
	ifa_flags = ifm->ifa_flags & IFA_F_NODAD;
	ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);

	ifa = ipv6_get_ifaddr(pfx, dev, 1);
	if (ifa == NULL) {