[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: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
55ebaef1d5
commit
3b9f9a1c39
|
@ -39,6 +39,7 @@ enum
|
||||||
#define IFA_F_TEMPORARY IFA_F_SECONDARY
|
#define IFA_F_TEMPORARY IFA_F_SECONDARY
|
||||||
|
|
||||||
#define IFA_F_NODAD 0x02
|
#define IFA_F_NODAD 0x02
|
||||||
|
#define IFA_F_HOMEADDRESS 0x10
|
||||||
#define IFA_F_DEPRECATED 0x20
|
#define IFA_F_DEPRECATED 0x20
|
||||||
#define IFA_F_TENTATIVE 0x40
|
#define IFA_F_TENTATIVE 0x40
|
||||||
#define IFA_F_PERMANENT 0x80
|
#define IFA_F_PERMANENT 0x80
|
||||||
|
|
|
@ -61,12 +61,8 @@ 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
|
#ifdef CONFIG_IPV6_MIP6
|
||||||
static inline int ipv6_chk_home_addr(struct in6_addr *addr)
|
extern int ipv6_chk_home_addr(struct in6_addr *addr);
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
#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,
|
||||||
|
|
|
@ -1038,9 +1038,27 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
|
||||||
continue;
|
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)
|
if (hiscore.rule < 4)
|
||||||
hiscore.rule++;
|
hiscore.rule++;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Rule 5: Prefer outgoing interface */
|
/* Rule 5: Prefer outgoing interface */
|
||||||
if (hiscore.rule < 5) {
|
if (hiscore.rule < 5) {
|
||||||
|
@ -2759,6 +2777,26 @@ void if6_proc_exit(void)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PROC_FS */
|
#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
|
* Periodic address status verification
|
||||||
*/
|
*/
|
||||||
|
@ -2930,7 +2968,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
|
||||||
prefered_lft = 0x7FFFFFFF/HZ;
|
prefered_lft = 0x7FFFFFFF/HZ;
|
||||||
|
|
||||||
spin_lock_bh(&ifp->lock);
|
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->tstamp = jiffies;
|
||||||
ifp->valid_lft = valid_lft;
|
ifp->valid_lft = valid_lft;
|
||||||
ifp->prefered_lft = prefered_lft;
|
ifp->prefered_lft = prefered_lft;
|
||||||
|
@ -2981,7 +3019,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* We ignore other flags so far. */
|
/* 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);
|
ifa = ipv6_get_ifaddr(pfx, dev, 1);
|
||||||
if (ifa == NULL) {
|
if (ifa == NULL) {
|
||||||
|
|
Loading…
Reference in a new issue