char __user *optval, int __user *optlen);
 extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
                                      char __user *optval, unsigned int optlen);
+
+extern struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
 #endif /* _INET_CONNECTION_SOCK_H */
 
        if (sk->sk_state == DCCP_LISTEN)
                return;
 
-       /* We don't check in the destentry if pmtu discovery is forbidden
-        * on this route. We just assume that no packet_to_big packets
-        * are send back when pmtu discovery is not active.
-        * There is a small race when the user changes this flag in the
-        * route, but I think that's acceptable.
-        */
-       if ((dst = __sk_dst_check(sk, 0)) == NULL)
+       dst = inet_csk_update_pmtu(sk, mtu);
+       if (!dst)
                return;
 
-       dst->ops->update_pmtu(dst, mtu);
-
        /* Something is about to be wrong... Remember soft error
         * for the case, if this connection will not able to recover.
         */
 
 }
 EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt);
 #endif
+
+static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl)
+{
+       struct inet_sock *inet = inet_sk(sk);
+       struct ip_options_rcu *inet_opt;
+       __be32 daddr = inet->inet_daddr;
+       struct flowi4 *fl4;
+       struct rtable *rt;
+
+       rcu_read_lock();
+       inet_opt = rcu_dereference(inet->inet_opt);
+       if (inet_opt && inet_opt->opt.srr)
+               daddr = inet_opt->opt.faddr;
+       fl4 = &fl->u.ip4;
+       rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr,
+                                  inet->inet_saddr, inet->inet_dport,
+                                  inet->inet_sport, sk->sk_protocol,
+                                  RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
+       if (IS_ERR(rt))
+               rt = NULL;
+       if (rt)
+               sk_setup_caps(sk, &rt->dst);
+       rcu_read_unlock();
+
+       return &rt->dst;
+}
+
+struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu)
+{
+       struct dst_entry *dst = __sk_dst_check(sk, 0);
+       struct inet_sock *inet = inet_sk(sk);
+
+       if (!dst) {
+               dst = inet_csk_rebuild_route(sk, &inet->cork.fl);
+               if (!dst)
+                       goto out;
+       }
+       dst->ops->update_pmtu(dst, mtu);
+
+       dst = __sk_dst_check(sk, 0);
+       if (!dst)
+               dst = inet_csk_rebuild_route(sk, &inet->cork.fl);
+out:
+       return dst;
+}
+EXPORT_SYMBOL_GPL(inet_csk_update_pmtu);
 
        if (sk->sk_state == TCP_LISTEN)
                return;
 
-       /* We don't check in the destentry if pmtu discovery is forbidden
-        * on this route. We just assume that no packet_to_big packets
-        * are send back when pmtu discovery is not active.
-        * There is a small race when the user changes this flag in the
-        * route, but I think that's acceptable.
-        */
-       if ((dst = __sk_dst_check(sk, 0)) == NULL)
+       dst = inet_csk_update_pmtu(sk, mtu);
+       if (!dst)
                return;
 
-       dst->ops->update_pmtu(dst, mtu);
-
        /* Something is about to be wrong... Remember soft error
         * for the case, if this connection will not able to recover.
         */