mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
ipv6: Use ipv6_neigh_lookup() and friends.
syzbot reported the splat below in neigh_mark_dead() [0]
where tbl->lock was not held while neigh_ifdown() should
have acquired one.
This only happens when a neigh_table accidentally has a
neighbour from a different netns.
In ip6_finish_output2(), the net argument is the caller's and
does not always match dev_net(dev) fetched from dst. (e.g. xfrm)
It is error-prone to require callers to fetch netns and
neigh_table and pass it with dev to neigh_lookup(), etc.
Let's replace neigh_lookup() and friends with IPv6 helpers.
Note that __neigh_lookup() is split into ipv6_neigh_lookup()
and ipv6_neigh_create().
[0]:
debug_locks && !(lock_is_held(&(&n->tbl->lock)->dep_map) != 0)
WARNING: net/core/neighbour.c:154 at neigh_mark_dead+0x2fb/0x340 net/core/neighbour.c:154, CPU#0: syz.0.857/9765
Modules linked in:
CPU: 0 UID: 0 PID: 9765 Comm: syz.0.857 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
RIP: 0010:neigh_mark_dead+0x2fb/0x340 net/core/neighbour.c:154
Code: e8 03 42 80 3c 28 00 74 08 48 89 df e8 ee 9a 80 f8 4c 89 33 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc cc e8 86 95 10 f8 90 <0f> 0b 90 e9 8f fd ff ff 48 c7 c1 80 9a 7a 90 80 e1 07 80 c1 03 38
RSP: 0018:ffffc90003726600 EFLAGS: 00010287
RAX: ffffffff89b7467a RBX: ffff888022e86000 RCX: 0000000000080000
RDX: ffffc900047fa000 RSI: 0000000000003e08 RDI: 0000000000003e09
RBP: 0000000000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffff520006e4cb8 R12: ffff888022e8613c
R13: dffffc0000000000 R14: ffff888022e86020 R15: ffff888022e86000
FS: 00007f9c30f046c0(0000) GS:ffff888124cc6000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000076c56000 CR4: 00000000003526f0
Call Trace:
<TASK>
neigh_flush_one+0x27c/0x5a0 net/core/neighbour.c:388
neigh_flush_dev net/core/neighbour.c:432 [inline]
__neigh_ifdown+0x1fb/0xc70 net/core/neighbour.c:465
neigh_ifdown+0x1f/0x30 net/core/neighbour.c:487
rt6_disable_ip+0x751/0x7e0 net/ipv6/route.c:5058
addrconf_ifdown+0x155/0x1ad0 net/ipv6/addrconf.c:3892
addrconf_notify+0x1bc/0x1050 net/ipv6/addrconf.c:-1
notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85
call_netdevice_notifiers_mtu net/core/dev.c:2350 [inline]
netif_set_mtu_ext+0x5ac/0x830 net/core/dev.c:9963
do_setlink+0xa81/0x47a0 net/core/rtnetlink.c:3247
rtnl_setlink+0x578/0x820 net/core/rtnetlink.c:3623
rtnetlink_rcv_msg+0x802/0xc00 net/core/rtnetlink.c:7159
netlink_rcv_skb+0x226/0x4a0 net/netlink/af_netlink.c:2572
netlink_unicast_kernel net/netlink/af_netlink.c:1335 [inline]
netlink_unicast+0x7bd/0x940 net/netlink/af_netlink.c:1361
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1916
sock_sendmsg_nosec+0x13a/0x180 net/socket.c:800
__sock_sendmsg net/socket.c:815 [inline]
sock_write_iter+0x2de/0x3e0 net/socket.c:1266
do_iter_readv_writev+0x612/0x8c0 fs/read_write.c:-1
vfs_writev+0x343/0x990 fs/read_write.c:1058
do_writev+0x154/0x2e0 fs/read_write.c:1104
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f9c2ff9e159
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f9c30f04028 EFLAGS: 00000246 ORIG_RAX: 0000000000000014
RAX: ffffffffffffffda RBX: 00007f9c30225fa0 RCX: 00007f9c2ff9e159
RDX: 0000000000000001 RSI: 00002000000003c0 RDI: 0000000000000004
RBP: 00007f9c3003506b R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f9c30226038 R14: 00007f9c30225fa0 R15: 00007ffed3c74808
</TASK>
Fixes: df5f4f372d ("ipv6: Replace &nd_tbl with nd_table(net).")
Reported-by: syzbot+5a8857f0b4a0a7b12c62@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6abd69a9.80e1c6cc.22483f.0005.GAE@google.com/
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20261003212336.1304988-7-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
98071355ff
commit
0e59523b44
|
|
@ -439,21 +439,18 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
|
|||
if (neigh_used) {
|
||||
struct net_device *dev = READ_ONCE(nhe->neigh_dev);
|
||||
struct net *net = dev_net(dev);
|
||||
struct neigh_table *tbl;
|
||||
|
||||
nhe->reported_lastuse = jiffies;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (m_neigh->family != AF_INET)
|
||||
tbl = nd_table(net);
|
||||
else
|
||||
#endif
|
||||
tbl = arp_table(net);
|
||||
|
||||
/* find the relevant neigh according to the cached device and
|
||||
* dst ip pair
|
||||
*/
|
||||
n = neigh_lookup(tbl, &m_neigh->dst_ip, dev);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (m_neigh->family != AF_INET)
|
||||
n = ipv6_neigh_lookup(dev, &m_neigh->dst_ip);
|
||||
else
|
||||
#endif
|
||||
n = neigh_lookup(arp_table(net), &m_neigh->dst_ip, dev);
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -2450,8 +2450,6 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
|
|||
char *rauhtd_pl,
|
||||
int rec_index)
|
||||
{
|
||||
struct net *net = mlxsw_sp_net(mlxsw_sp);
|
||||
struct neigh_table *tbl;
|
||||
struct net_device *dev;
|
||||
struct neighbour *n;
|
||||
struct in6_addr dip;
|
||||
|
|
@ -2465,9 +2463,8 @@ static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
|
|||
return;
|
||||
}
|
||||
|
||||
tbl = nd_table(net);
|
||||
dev = mlxsw_sp_rif_dev(mlxsw_sp->router->rifs[rif]);
|
||||
n = neigh_lookup(tbl, &dip, dev);
|
||||
n = ipv6_neigh_lookup(dev, &dip);
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
|
|
@ -4313,17 +4310,23 @@ mlxsw_sp_nexthop_neigh_lookup(struct mlxsw_sp_nexthop *nh)
|
|||
net = dev_net(dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (nh->family == AF_INET6)
|
||||
tbl = nd_table(net);
|
||||
else
|
||||
if (nh->family == AF_INET6) {
|
||||
n = ipv6_neigh_lookup(dev, &nh->gw_addr);
|
||||
if (!n) {
|
||||
n = ipv6_neigh_create(dev, &nh->gw_addr);
|
||||
if (!IS_ERR(n))
|
||||
neigh_event_send(n, NULL);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
tbl = arp_table(net);
|
||||
|
||||
n = neigh_lookup(tbl, &nh->gw_addr, dev);
|
||||
if (!n) {
|
||||
n = neigh_create(tbl, &nh->gw_addr, dev);
|
||||
if (!IS_ERR(n))
|
||||
neigh_event_send(n, NULL);
|
||||
n = neigh_lookup(tbl, &nh->gw_addr, dev);
|
||||
if (!n) {
|
||||
n = neigh_create(tbl, &nh->gw_addr, dev);
|
||||
if (!IS_ERR(n))
|
||||
neigh_event_send(n, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
|
|
|
|||
|
|
@ -235,17 +235,23 @@ static int mlxsw_sp_span_dmac(int family,
|
|||
int err = 0;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6_GRE)
|
||||
if (family == AF_INET6)
|
||||
tbl = nd_table(net);
|
||||
else
|
||||
if (family == AF_INET6) {
|
||||
neigh = ipv6_neigh_lookup(dev, pkey);
|
||||
if (!neigh) {
|
||||
neigh = ipv6_neigh_create(dev, pkey);
|
||||
if (IS_ERR(neigh))
|
||||
return PTR_ERR(neigh);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
tbl = arp_table(net);
|
||||
|
||||
neigh = neigh_lookup(tbl, pkey, dev);
|
||||
if (!neigh) {
|
||||
neigh = neigh_create(tbl, pkey, dev);
|
||||
if (IS_ERR(neigh))
|
||||
return PTR_ERR(neigh);
|
||||
neigh = neigh_lookup(tbl, pkey, dev);
|
||||
if (!neigh) {
|
||||
neigh = neigh_create(tbl, pkey, dev);
|
||||
if (IS_ERR(neigh))
|
||||
return PTR_ERR(neigh);
|
||||
}
|
||||
}
|
||||
|
||||
neigh_event_send(neigh, NULL);
|
||||
|
|
|
|||
|
|
@ -253,7 +253,6 @@ void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb)
|
|||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
struct nfp_tun_active_tuns_v6 *payload;
|
||||
struct net_device *netdev;
|
||||
struct neigh_table *tbl;
|
||||
int count, i, pay_len;
|
||||
struct neighbour *n;
|
||||
void *ipv6_add;
|
||||
|
|
@ -280,8 +279,7 @@ void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb)
|
|||
if (!netdev)
|
||||
continue;
|
||||
|
||||
tbl = nd_table(dev_net(netdev));
|
||||
n = neigh_lookup(tbl, ipv6_add, netdev);
|
||||
n = ipv6_neigh_lookup(netdev, ipv6_add);
|
||||
if (!n)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -116,9 +116,8 @@ static void efx_tc_counter_work(struct work_struct *work)
|
|||
encap->neigh->egdev);
|
||||
else
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
n = neigh_lookup(nd_table(net),
|
||||
&encap->neigh->dst_ip6,
|
||||
encap->neigh->egdev);
|
||||
n = ipv6_neigh_lookup(encap->neigh->egdev,
|
||||
&encap->neigh->dst_ip6);
|
||||
#else
|
||||
n = NULL;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -614,9 +614,9 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
|
|||
|
||||
rcu_read_lock();
|
||||
nexthop = rt6_nexthop(dst_rt6_info(dst), &ipv6_hdr(skb)->daddr);
|
||||
neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
|
||||
neigh = __ipv6_neigh_lookup_noref(dev, nexthop);
|
||||
if (unlikely(!neigh))
|
||||
neigh = __neigh_create(nd_table(net), nexthop, dst->dev, false);
|
||||
neigh = ipv6_neigh_create_noref(dev, nexthop);
|
||||
if (!IS_ERR(neigh)) {
|
||||
sock_confirm_neigh(skb, neigh);
|
||||
ret = neigh_output(neigh, skb, false);
|
||||
|
|
|
|||
|
|
@ -2091,8 +2091,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb,
|
|||
ipv6_addr_is_multicast(&msg->target))
|
||||
goto out;
|
||||
|
||||
n = neigh_lookup(nd_table(dev_net(dev)), &msg->target, dev);
|
||||
|
||||
n = ipv6_neigh_lookup(dev, &msg->target);
|
||||
if (n) {
|
||||
struct vxlan_rdst *rdst = NULL;
|
||||
u8 ha[ETH_ALEN] __aligned(2);
|
||||
|
|
@ -2189,9 +2188,8 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb,
|
|||
if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
|
||||
return false;
|
||||
|
||||
tbl = nd_table(dev_net(dev));
|
||||
pip6 = ipv6_hdr(skb);
|
||||
n = neigh_lookup(tbl, &pip6->daddr, dev);
|
||||
n = ipv6_neigh_lookup(dev, &pip6->daddr);
|
||||
if (!n && (cfg->flags & VXLAN_F_L3MISS)) {
|
||||
union vxlan_addr ipa = {
|
||||
.sin6.sin6_addr = pip6->daddr,
|
||||
|
|
|
|||
|
|
@ -423,11 +423,8 @@ static inline struct neighbour *ip_neigh_gw6(struct net_device *dev,
|
|||
struct neighbour *neigh;
|
||||
|
||||
neigh = __ipv6_neigh_lookup_noref(dev, addr);
|
||||
if (unlikely(!neigh)) {
|
||||
struct neigh_table *tbl = nd_table(dev_net(dev));
|
||||
|
||||
neigh = __neigh_create(tbl, addr, dev, false);
|
||||
}
|
||||
if (unlikely(!neigh))
|
||||
neigh = ipv6_neigh_create_noref(dev, addr);
|
||||
|
||||
return neigh;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
|
|||
return;
|
||||
}
|
||||
|
||||
n = neigh_lookup(nd_table(dev_net(vlandev)), &msg->target, vlandev);
|
||||
n = ipv6_neigh_lookup(vlandev, &msg->target);
|
||||
if (n) {
|
||||
struct net_bridge_fdb_entry *f;
|
||||
u8 ha[ETH_ALEN] __aligned(2);
|
||||
|
|
|
|||
|
|
@ -58,9 +58,8 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev,
|
|||
info->daddr.mode = IEEE802154_ADDR_SHORT;
|
||||
} else {
|
||||
__le16 short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
|
||||
struct neigh_table *tbl = nd_table(dev_net(ldev));
|
||||
|
||||
n = neigh_lookup(tbl, &hdr->daddr, ldev);
|
||||
n = ipv6_neigh_lookup(ldev, &hdr->daddr);
|
||||
if (n) {
|
||||
llneigh = lowpan_802154_neigh(neighbour_priv(n));
|
||||
read_lock_bh(&n->lock);
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ static int fib_detect_death(struct fib_info *fi, int order,
|
|||
if (likely(nhc->nhc_gw_family == AF_INET))
|
||||
n = neigh_lookup(arp_table(net), &nhc->nhc_gw.ipv4, nhc->nhc_dev);
|
||||
else if (IS_ENABLED(CONFIG_IPV6) && nhc->nhc_gw_family == AF_INET6)
|
||||
n = neigh_lookup(nd_table(net), &nhc->nhc_gw.ipv6, nhc->nhc_dev);
|
||||
n = ipv6_neigh_lookup(nhc->nhc_dev, &nhc->nhc_gw.ipv6);
|
||||
else
|
||||
n = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
|
|||
|
||||
if (IS_ERR_OR_NULL(neigh)) {
|
||||
if (unlikely(!neigh))
|
||||
neigh = __neigh_create(nd_table(net), nexthop, dev, false);
|
||||
neigh = ipv6_neigh_create_noref(dev, nexthop);
|
||||
if (IS_ERR(neigh)) {
|
||||
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL);
|
||||
|
|
|
|||
|
|
@ -947,8 +947,12 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb)
|
|||
* update / create cache entry
|
||||
* for the source address
|
||||
*/
|
||||
neigh = __neigh_lookup(tbl, saddr, dev,
|
||||
!inc || lladdr || !dev->addr_len);
|
||||
neigh = ipv6_neigh_lookup(dev, saddr);
|
||||
if (!neigh && (!inc || lladdr || !dev->addr_len)) {
|
||||
neigh = ipv6_neigh_create(dev, saddr);
|
||||
if (IS_ERR(neigh))
|
||||
neigh = NULL;
|
||||
}
|
||||
if (neigh)
|
||||
ndisc_update(dev, neigh, lladdr, NUD_STALE,
|
||||
NEIGH_UPDATE_F_WEAK_OVERRIDE|
|
||||
|
|
@ -998,7 +1002,6 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
|
|||
struct net *net = dev_net(dev);
|
||||
struct ndisc_options ndopts;
|
||||
struct inet6_ifaddr *ifp;
|
||||
struct neigh_table *tbl;
|
||||
struct neighbour *neigh;
|
||||
struct inet6_dev *idev;
|
||||
u8 *lladdr = NULL;
|
||||
|
|
@ -1063,8 +1066,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
|
|||
return reason;
|
||||
}
|
||||
|
||||
tbl = nd_table(net);
|
||||
neigh = neigh_lookup(tbl, &msg->target, dev);
|
||||
neigh = ipv6_neigh_lookup(dev, &msg->target);
|
||||
|
||||
/* RFC 9131 updates original Neighbour Discovery RFC 4861.
|
||||
* NAs with Target LL Address option can now create a STALE neighbor
|
||||
|
|
@ -1093,7 +1095,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
|
|||
return reason;
|
||||
}
|
||||
if (!neigh)
|
||||
neigh = neigh_create(tbl, &msg->target, dev);
|
||||
neigh = ipv6_neigh_create(dev, &msg->target);
|
||||
new_state = NUD_STALE;
|
||||
}
|
||||
|
||||
|
|
@ -1108,7 +1110,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
|
|||
if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
|
||||
READ_ONCE(net->ipv6.devconf_all->forwarding) &&
|
||||
READ_ONCE(net->ipv6.devconf_all->proxy_ndp) &&
|
||||
pneigh_lookup(tbl, &msg->target, dev)) {
|
||||
pneigh_lookup(nd_table(dev_net(dev)), &msg->target, dev)) {
|
||||
/* XXX: idev->cnf.proxy_ndp */
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1141,7 +1143,6 @@ static enum skb_drop_reason ndisc_recv_rs(struct sk_buff *skb)
|
|||
unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
|
||||
struct net_device *dev = skb->dev;
|
||||
struct ndisc_options ndopts;
|
||||
struct neigh_table *tbl;
|
||||
struct neighbour *neigh;
|
||||
struct inet6_dev *idev;
|
||||
u8 *lladdr = NULL;
|
||||
|
|
@ -1177,8 +1178,12 @@ static enum skb_drop_reason ndisc_recv_rs(struct sk_buff *skb)
|
|||
goto out;
|
||||
}
|
||||
|
||||
tbl = nd_table(dev_net(dev));
|
||||
neigh = __neigh_lookup(tbl, saddr, dev, 1);
|
||||
neigh = ipv6_neigh_lookup(dev, saddr);
|
||||
if (!neigh) {
|
||||
neigh = ipv6_neigh_create(dev, saddr);
|
||||
if (IS_ERR(neigh))
|
||||
goto out;
|
||||
}
|
||||
if (neigh) {
|
||||
ndisc_update(dev, neigh, lladdr, NUD_STALE,
|
||||
NEIGH_UPDATE_F_WEAK_OVERRIDE|
|
||||
|
|
@ -1478,9 +1483,14 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
|
|||
* Process options.
|
||||
*/
|
||||
|
||||
if (!neigh)
|
||||
neigh = __neigh_lookup(nd_table(net), &ipv6_hdr(skb)->saddr,
|
||||
skb->dev, 1);
|
||||
if (!neigh) {
|
||||
neigh = ipv6_neigh_lookup(skb->dev, &ipv6_hdr(skb)->saddr);
|
||||
if (!neigh) {
|
||||
neigh = ipv6_neigh_create(skb->dev, &ipv6_hdr(skb)->saddr);
|
||||
if (IS_ERR(neigh))
|
||||
neigh = NULL;
|
||||
}
|
||||
}
|
||||
if (neigh) {
|
||||
u8 *lladdr = NULL;
|
||||
if (ndopts.nd_opts_src_lladdr) {
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ struct neighbour *__ip6_dst_neigh_lookup(const struct in6_addr *gw,
|
|||
if (n)
|
||||
return n;
|
||||
|
||||
n = neigh_create(nd_table(dev_net(dev)), daddr, dev);
|
||||
n = ipv6_neigh_create(dev, daddr);
|
||||
return IS_ERR(n) ? NULL : n;
|
||||
}
|
||||
|
||||
|
|
@ -4285,9 +4285,12 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
|
|||
*/
|
||||
dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr);
|
||||
|
||||
neigh = __neigh_lookup(nd_table(dev_net(dev)), &msg->target, dev, 1);
|
||||
if (!neigh)
|
||||
return;
|
||||
neigh = ipv6_neigh_lookup(dev, &msg->target);
|
||||
if (!neigh) {
|
||||
neigh = ipv6_neigh_create(dev, &msg->target);
|
||||
if (IS_ERR(neigh))
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have finally decided to accept it.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <net/dst.h>
|
||||
#include <net/ndisc.h>
|
||||
#include <net/neighbour.h>
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
|
|
@ -257,7 +258,16 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res,
|
|||
if (dst->dev != dev) {
|
||||
struct neighbour *mn;
|
||||
|
||||
mn = __neigh_lookup_errno(n->tbl, n->primary_key, dev);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (n->tbl->family == AF_INET6) {
|
||||
mn = ipv6_neigh_lookup(dev, n->primary_key);
|
||||
if (!mn)
|
||||
mn = ipv6_neigh_create(dev, n->primary_key);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mn = __neigh_lookup_errno(n->tbl, n->primary_key, dev);
|
||||
}
|
||||
neigh_release(n);
|
||||
if (IS_ERR(mn))
|
||||
return PTR_ERR(mn);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user