Skip to content
This repository has been archived by the owner on Sep 18, 2022. It is now read-only.

Commit

Permalink
net: Add optional SKB arg to dst_ops->neigh_lookup().
Browse files Browse the repository at this point in the history
Causes the handler to use the daddr in the ipv4/ipv6 header when
the route gateway is unspecified (local subnet).

Change-Id: I563e067266122902f7a2bc3c7e5822156765c919
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 authored and MSe1969 committed Nov 8, 2020
1 parent 33e8415 commit 588d67f
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 15 deletions.
8 changes: 7 additions & 1 deletion include/net/dst.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,13 @@ static inline void dst_confirm(struct dst_entry *dst)

static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
{
return dst->ops->neigh_lookup(dst, daddr);
return dst->ops->neigh_lookup(dst, NULL, daddr);
}

static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
struct sk_buff *skb)
{
return dst->ops->neigh_lookup(dst, skb, NULL);
}

static inline void dst_link_failure(struct sk_buff *skb)
Expand Down
4 changes: 3 additions & 1 deletion include/net/dst_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ struct dst_ops {
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
int (*local_out)(struct sk_buff *skb);
struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, const void *daddr);
struct neighbour * (*neigh_lookup)(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr);

struct kmem_cache *kmem_cachep;

Expand Down
4 changes: 3 additions & 1 deletion net/bridge/br_netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
return NULL;
}

static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr)
static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{
return NULL;
}
Expand Down
8 changes: 6 additions & 2 deletions net/decnet/dn_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ static void dn_dst_destroy(struct dst_entry *);
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
static void dn_dst_link_failure(struct sk_buff *);
static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr);
static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr);
static int dn_route_input(struct sk_buff *);
static void dn_run_flush(unsigned long dummy);

Expand Down Expand Up @@ -831,7 +833,9 @@ static unsigned int dn_dst_mtu(const struct dst_entry *dst)
return mtu ? : dst->dev->mtu;
}

static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{
return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
}
Expand Down
14 changes: 10 additions & 4 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
return p;
}

static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr);
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr);

static struct dst_ops ipv4_dst_ops = {
.family = AF_INET,
Expand Down Expand Up @@ -1140,7 +1142,9 @@ static int slow_chain_length(const struct rtable *head)
return length >> FRACT_BITS;
}

static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr)
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{
static const __be32 inaddr_any = 0;
struct net_device *dev = dst->dev;
Expand All @@ -1154,6 +1158,8 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo
pkey = &inaddr_any;
else if (rt->rt_gateway)
pkey = (const __be32 *) &rt->rt_gateway;
else if (skb)
pkey = &ip_hdr(skb)->daddr;

n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey);
if (n)
Expand All @@ -1163,7 +1169,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo

static int rt_bind_neighbour(struct rtable *rt)
{
struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
struct neighbour *n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
if (IS_ERR(n))
return PTR_ERR(n);
dst_set_neighbour(&rt->dst, n);
Expand Down Expand Up @@ -1448,7 +1454,7 @@ static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)

rt->rt_gateway = peer->redirect_learned.a4;

n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
if (IS_ERR(n)) {
rt->rt_gateway = orig_gw;
return;
Expand Down
14 changes: 10 additions & 4 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,27 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
return p;
}

static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr)
static inline const void *choose_neigh_daddr(struct rt6_info *rt,
struct sk_buff *skb,
const void *daddr)
{
struct in6_addr *p = &rt->rt6i_gateway;

if (!ipv6_addr_any(p))
return (const void *) p;
else if (skb)
return &ipv6_hdr(skb)->daddr;
return daddr;
}

static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{
struct rt6_info *rt = (struct rt6_info *) dst;
struct neighbour *n;

daddr = choose_neigh_daddr(rt, daddr);
daddr = choose_neigh_daddr(rt, skb, daddr);
n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
if (n)
return n;
Expand Down Expand Up @@ -1153,7 +1159,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
if (neigh)
neigh_hold(neigh);
else {
neigh = ip6_neigh_lookup(&rt->dst, &fl6->daddr);
neigh = ip6_neigh_lookup(&rt->dst, NULL, &fl6->daddr);
if (IS_ERR(neigh)) {
in6_dev_put(idev);
dst_free(&rt->dst);
Expand Down
6 changes: 4 additions & 2 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -2410,9 +2410,11 @@ static unsigned int xfrm_mtu(const struct dst_entry *dst)
return mtu ? : dst_mtu(dst->path);
}

static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr)
static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{
return dst_neigh_lookup(dst->path, daddr);
return dst->path->ops->neigh_lookup(dst, skb, daddr);
}

int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
Expand Down

0 comments on commit 588d67f

Please sign in to comment.