diff --git a/src/linux/net/newip/route.c b/src/linux/net/newip/route.c index a7acfd35f3c3189b800f5bb1f24873b9fc17b991..caedcf869e39763953f7e6eda84890d384132bca 100644 --- a/src/linux/net/newip/route.c +++ b/src/linux/net/newip/route.c @@ -657,6 +657,8 @@ static struct neighbour *nip_neigh_lookup(const struct dst_entry *dst, static struct dst_entry *nip_dst_check(struct dst_entry *dst, u32 cookie) { + if (dst->obsolete != DST_OBSOLETE_FORCE_CHK) + return NULL; return dst; } @@ -689,9 +691,28 @@ static unsigned int nip_mtu(const struct dst_entry *dst) return mtu; } +static void nip_dst_ifdown(struct dst_entry *dst, struct net_device *dev, + int how) +{ + struct nip_rt_info *rt = (struct nip_rt_info *)dst; + struct ninet_dev *idev = rt->rt_idev; + struct net_device *loopback_dev = + dev_net(dev)->loopback_dev; + + if (idev && idev->dev != loopback_dev) { + struct ninet_dev *loopback_idev = nin_dev_get(loopback_dev); + + if (loopback_idev) { + rt->rt_idev = loopback_idev; + nin_dev_put(idev); + } + } +} + static struct dst_ops nip_dst_ops_template = { .family = AF_NINET, .destroy = nip_dst_destroy, + .ifdown = nip_dst_ifdown, .neigh_lookup = nip_neigh_lookup, .check = nip_dst_check, .default_advmss = nip_default_advmss, diff --git a/src/linux/net/newip/tcp_nip.c b/src/linux/net/newip/tcp_nip.c index 922ff08dc1c2c4d25e08f9e372407e39c1a4b228..dca377166b9de9b03e20277798667e9e26b629ef 100644 --- a/src/linux/net/newip/tcp_nip.c +++ b/src/linux/net/newip/tcp_nip.c @@ -1300,6 +1300,15 @@ static int tcp_nip_do_rcv(struct sock *sk, struct sk_buff *skb) DEBUG("%s: received newip tcp skb, sk_state=%d", __func__, sk->sk_state); if (sk->sk_state == TCP_ESTABLISHED) { + struct dst_entry *dst = sk->sk_rx_dst; + + if (dst) { + if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || + !dst->ops->check(dst, 0)) { + dst_release(dst); + sk->sk_rx_dst = NULL; + } + } tcp_nip_rcv_established(sk, skb, tcp_hdr(skb), skb->len); return 0; } @@ -1517,6 +1526,8 @@ static void tcp_nip_early_demux(struct sk_buff *skb) if (sk_fullsock(sk)) { struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst); + if (dst) + dst = dst_check(dst, 0); if (dst && inet_sk(sk)->rx_dst_ifindex == skb->skb_iif) { DEBUG("%s: find sock in ehash, set dst for skb", __func__); diff --git a/src/linux/net/newip/tcp_nip_input.c b/src/linux/net/newip/tcp_nip_input.c index 1b01ce13c6921e5bed12aeaae05293bc6a56ab97..c407b77f6c029b026ebf01ad260cb17b6918c7df 100644 --- a/src/linux/net/newip/tcp_nip_input.c +++ b/src/linux/net/newip/tcp_nip_input.c @@ -1293,6 +1293,9 @@ void tcp_nip_rcv_established(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); tcp_mstamp_refresh(tp); + if (unlikely(!sk->sk_rx_dst)) + inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb); + if (!tcp_nip_validate_incoming(sk, skb, th, 1)) return;