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

Commit dfe7df51 authored by Hangbin Liu's avatar Hangbin Liu Committed by Greg Kroah-Hartman
Browse files

net/ipv6: remove the old peer route if change it to a new one



[ Upstream commit d0098e4c6b83e502cc1cd96d67ca86bc79a6c559 ]

When we modify the peer route and changed it to a new one, we should
remove the old route first. Before the fix:

+ ip addr add dev dummy1 2001:db8::1 peer 2001:db8::2
+ ip -6 route show dev dummy1
2001:db8::1 proto kernel metric 256 pref medium
2001:db8::2 proto kernel metric 256 pref medium
+ ip addr change dev dummy1 2001:db8::1 peer 2001:db8::3
+ ip -6 route show dev dummy1
2001:db8::1 proto kernel metric 256 pref medium
2001:db8::2 proto kernel metric 256 pref medium

After the fix:
+ ip addr change dev dummy1 2001:db8::1 peer 2001:db8::3
+ ip -6 route show dev dummy1
2001:db8::1 proto kernel metric 256 pref medium
2001:db8::3 proto kernel metric 256 pref medium

This patch depend on the previous patch "net/ipv6: need update peer route
when modify metric" to update new peer route after delete old one.

Signed-off-by: default avatarHangbin Liu <liuhangbin@gmail.com>
Reviewed-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d8cfddaf
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -1175,11 +1175,12 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
}

static void
cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_rt)
cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires,
		     bool del_rt, bool del_peer)
{
	struct fib6_info *f6i;

	f6i = addrconf_get_prefix_route(&ifp->addr,
	f6i = addrconf_get_prefix_route(del_peer ? &ifp->peer_addr : &ifp->addr,
				       ifp->prefix_len,
				       ifp->idev->dev,
				       0, RTF_GATEWAY | RTF_DEFAULT);
@@ -1244,7 +1245,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)

	if (action != CLEANUP_PREFIX_RT_NOP) {
		cleanup_prefix_route(ifp, expires,
			action == CLEANUP_PREFIX_RT_DEL);
			action == CLEANUP_PREFIX_RT_DEL, false);
	}

	/* clean up prefsrc entries */
@@ -4577,6 +4578,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
	unsigned long timeout;
	bool was_managetempaddr;
	bool had_prefixroute;
	bool new_peer = false;

	ASSERT_RTNL();

@@ -4608,6 +4610,13 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
		cfg->preferred_lft = timeout;
	}

	if (cfg->peer_pfx &&
	    memcmp(&ifp->peer_addr, cfg->peer_pfx, sizeof(struct in6_addr))) {
		if (!ipv6_addr_any(&ifp->peer_addr))
			cleanup_prefix_route(ifp, expires, true, true);
		new_peer = true;
	}

	spin_lock_bh(&ifp->lock);
	was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
	had_prefixroute = ifp->flags & IFA_F_PERMANENT &&
@@ -4623,6 +4632,9 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
	if (cfg->rt_priority && cfg->rt_priority != ifp->rt_priority)
		ifp->rt_priority = cfg->rt_priority;

	if (new_peer)
		ifp->peer_addr = *cfg->peer_pfx;

	spin_unlock_bh(&ifp->lock);
	if (!(ifp->flags&IFA_F_TENTATIVE))
		ipv6_ifa_notify(0, ifp);
@@ -4658,7 +4670,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)

		if (action != CLEANUP_PREFIX_RT_NOP) {
			cleanup_prefix_route(ifp, rt_expires,
				action == CLEANUP_PREFIX_RT_DEL);
				action == CLEANUP_PREFIX_RT_DEL, false);
		}
	}