mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 07:00:48 +00:00
ipv6: Pull main logic of rt6_redirect() into rt6_do_redirect().
Hook it into dst_ops->redirect as well. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e8599ff4b1
commit
6e157b6ac6
@ -79,6 +79,7 @@ static int ip6_pkt_discard(struct sk_buff *skb);
|
||||
static int ip6_pkt_discard_out(struct sk_buff *skb);
|
||||
static void ip6_link_failure(struct sk_buff *skb);
|
||||
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
|
||||
static void rt6_do_redirect(struct dst_entry *dst, struct sk_buff *skb);
|
||||
|
||||
#ifdef CONFIG_IPV6_ROUTE_INFO
|
||||
static struct rt6_info *rt6_add_route_info(struct net *net,
|
||||
@ -174,6 +175,7 @@ static struct dst_ops ip6_dst_ops_template = {
|
||||
.negative_advice = ip6_negative_advice,
|
||||
.link_failure = ip6_link_failure,
|
||||
.update_pmtu = ip6_rt_update_pmtu,
|
||||
.redirect = rt6_do_redirect,
|
||||
.local_out = __ip6_local_out,
|
||||
.neigh_lookup = ip6_neigh_lookup,
|
||||
};
|
||||
@ -1690,28 +1692,26 @@ static struct rt6_info *ip6_route_redirect(const struct in6_addr *dest,
|
||||
flags, __ip6_route_redirect);
|
||||
}
|
||||
|
||||
void rt6_redirect(struct sk_buff *skb)
|
||||
static void rt6_do_redirect(struct dst_entry *dst, struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct netevent_redirect netevent;
|
||||
struct rt6_info *rt, *nrt = NULL;
|
||||
const struct in6_addr *target;
|
||||
struct neighbour *old_neigh;
|
||||
const struct in6_addr *dest;
|
||||
const struct in6_addr *src;
|
||||
const struct in6_addr *saddr;
|
||||
struct ndisc_options ndopts;
|
||||
const struct in6_addr *dest;
|
||||
struct neighbour *old_neigh;
|
||||
struct inet6_dev *in6_dev;
|
||||
struct neighbour *neigh;
|
||||
struct icmp6hdr *icmph;
|
||||
int on_link, optlen;
|
||||
u8 *lladdr = NULL;
|
||||
int optlen, on_link;
|
||||
u8 *lladdr;
|
||||
|
||||
optlen = skb->tail - skb->transport_header;
|
||||
optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
|
||||
|
||||
if (optlen < 0) {
|
||||
net_dbg_ratelimited("rt6_redirect: packet too short\n");
|
||||
net_dbg_ratelimited("rt6_do_redirect: packet too short\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1720,15 +1720,16 @@ void rt6_redirect(struct sk_buff *skb)
|
||||
dest = target + 1;
|
||||
|
||||
if (ipv6_addr_is_multicast(dest)) {
|
||||
net_dbg_ratelimited("rt6_redirect: destination address is multicast\n");
|
||||
net_dbg_ratelimited("rt6_do_redirect: destination address is multicast\n");
|
||||
return;
|
||||
}
|
||||
|
||||
on_link = 0;
|
||||
if (ipv6_addr_equal(dest, target)) {
|
||||
on_link = 1;
|
||||
} else if (ipv6_addr_type(target) !=
|
||||
(IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
|
||||
net_dbg_ratelimited("rt6_redirect: target address is not link-local unicast\n");
|
||||
net_dbg_ratelimited("rt6_do_redirect: target address is not link-local unicast\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1747,6 +1748,8 @@ void rt6_redirect(struct sk_buff *skb)
|
||||
net_dbg_ratelimited("rt6_redirect: invalid ND options\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lladdr = NULL;
|
||||
if (ndopts.nd_opts_tgt_lladdr) {
|
||||
lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
|
||||
skb->dev);
|
||||
@ -1756,19 +1759,26 @@ void rt6_redirect(struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
rt = (struct rt6_info *) dst;
|
||||
if (rt == net->ipv6.ip6_null_entry) {
|
||||
net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Redirect received -> path was valid.
|
||||
* Look, redirects are sent only in response to data packets,
|
||||
* so that this nexthop apparently is reachable. --ANK
|
||||
*/
|
||||
dst_confirm(&rt->dst);
|
||||
|
||||
neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
|
||||
if (!neigh)
|
||||
return;
|
||||
|
||||
src = &ipv6_hdr(skb)->daddr;
|
||||
saddr = &ipv6_hdr(skb)->saddr;
|
||||
|
||||
rt = ip6_route_redirect(dest, src, saddr, neigh->dev);
|
||||
|
||||
if (rt == net->ipv6.ip6_null_entry) {
|
||||
net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n");
|
||||
/* Duplicate redirect: silently ignore. */
|
||||
old_neigh = rt->n;
|
||||
if (neigh == old_neigh)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have finally decided to accept it.
|
||||
@ -1781,18 +1791,6 @@ void rt6_redirect(struct sk_buff *skb)
|
||||
NEIGH_UPDATE_F_ISROUTER))
|
||||
);
|
||||
|
||||
/*
|
||||
* Redirect received -> path was valid.
|
||||
* Look, redirects are sent only in response to data packets,
|
||||
* so that this nexthop apparently is reachable. --ANK
|
||||
*/
|
||||
dst_confirm(&rt->dst);
|
||||
|
||||
/* Duplicate redirect: silently ignore. */
|
||||
old_neigh = rt->n;
|
||||
if (neigh == old_neigh)
|
||||
goto out;
|
||||
|
||||
nrt = ip6_rt_copy(rt, dest);
|
||||
if (!nrt)
|
||||
goto out;
|
||||
@ -1815,12 +1813,32 @@ void rt6_redirect(struct sk_buff *skb)
|
||||
call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
|
||||
|
||||
if (rt->rt6i_flags & RTF_CACHE) {
|
||||
rt = (struct rt6_info *) dst_clone(&rt->dst);
|
||||
ip6_del_rt(rt);
|
||||
return;
|
||||
}
|
||||
|
||||
out:
|
||||
neigh_release(neigh);
|
||||
}
|
||||
|
||||
void rt6_redirect(struct sk_buff *skb)
|
||||
{
|
||||
const struct in6_addr *target;
|
||||
const struct in6_addr *dest;
|
||||
const struct in6_addr *src;
|
||||
const struct in6_addr *saddr;
|
||||
struct icmp6hdr *icmph;
|
||||
struct rt6_info *rt;
|
||||
|
||||
icmph = icmp6_hdr(skb);
|
||||
target = (const struct in6_addr *) (icmph + 1);
|
||||
dest = target + 1;
|
||||
|
||||
src = &ipv6_hdr(skb)->daddr;
|
||||
saddr = &ipv6_hdr(skb)->saddr;
|
||||
|
||||
rt = ip6_route_redirect(dest, src, saddr, skb->dev);
|
||||
rt6_do_redirect(&rt->dst, skb);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user