diff options
-rw-r--r-- | include/net/inet_connection_sock.h | 2 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 11 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 46 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 11 |
4 files changed, 52 insertions, 18 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 291e7cee14e7..2cf44b4ed2e6 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h | |||
@@ -337,4 +337,6 @@ extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, | |||
337 | char __user *optval, int __user *optlen); | 337 | char __user *optval, int __user *optlen); |
338 | extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, | 338 | extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, |
339 | char __user *optval, unsigned int optlen); | 339 | char __user *optval, unsigned int optlen); |
340 | |||
341 | extern struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); | ||
340 | #endif /* _INET_CONNECTION_SOCK_H */ | 342 | #endif /* _INET_CONNECTION_SOCK_H */ |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 129ed8f74138..683902fcc8ed 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -161,17 +161,10 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk, | |||
161 | if (sk->sk_state == DCCP_LISTEN) | 161 | if (sk->sk_state == DCCP_LISTEN) |
162 | return; | 162 | return; |
163 | 163 | ||
164 | /* We don't check in the destentry if pmtu discovery is forbidden | 164 | dst = inet_csk_update_pmtu(sk, mtu); |
165 | * on this route. We just assume that no packet_to_big packets | 165 | if (!dst) |
166 | * are send back when pmtu discovery is not active. | ||
167 | * There is a small race when the user changes this flag in the | ||
168 | * route, but I think that's acceptable. | ||
169 | */ | ||
170 | if ((dst = __sk_dst_check(sk, 0)) == NULL) | ||
171 | return; | 166 | return; |
172 | 167 | ||
173 | dst->ops->update_pmtu(dst, mtu); | ||
174 | |||
175 | /* Something is about to be wrong... Remember soft error | 168 | /* Something is about to be wrong... Remember soft error |
176 | * for the case, if this connection will not able to recover. | 169 | * for the case, if this connection will not able to recover. |
177 | */ | 170 | */ |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 76825be3b643..200d21809379 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -803,3 +803,49 @@ int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, | |||
803 | } | 803 | } |
804 | EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt); | 804 | EXPORT_SYMBOL_GPL(inet_csk_compat_setsockopt); |
805 | #endif | 805 | #endif |
806 | |||
807 | static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl) | ||
808 | { | ||
809 | struct inet_sock *inet = inet_sk(sk); | ||
810 | struct ip_options_rcu *inet_opt; | ||
811 | __be32 daddr = inet->inet_daddr; | ||
812 | struct flowi4 *fl4; | ||
813 | struct rtable *rt; | ||
814 | |||
815 | rcu_read_lock(); | ||
816 | inet_opt = rcu_dereference(inet->inet_opt); | ||
817 | if (inet_opt && inet_opt->opt.srr) | ||
818 | daddr = inet_opt->opt.faddr; | ||
819 | fl4 = &fl->u.ip4; | ||
820 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, | ||
821 | inet->inet_saddr, inet->inet_dport, | ||
822 | inet->inet_sport, sk->sk_protocol, | ||
823 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); | ||
824 | if (IS_ERR(rt)) | ||
825 | rt = NULL; | ||
826 | if (rt) | ||
827 | sk_setup_caps(sk, &rt->dst); | ||
828 | rcu_read_unlock(); | ||
829 | |||
830 | return &rt->dst; | ||
831 | } | ||
832 | |||
833 | struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu) | ||
834 | { | ||
835 | struct dst_entry *dst = __sk_dst_check(sk, 0); | ||
836 | struct inet_sock *inet = inet_sk(sk); | ||
837 | |||
838 | if (!dst) { | ||
839 | dst = inet_csk_rebuild_route(sk, &inet->cork.fl); | ||
840 | if (!dst) | ||
841 | goto out; | ||
842 | } | ||
843 | dst->ops->update_pmtu(dst, mtu); | ||
844 | |||
845 | dst = __sk_dst_check(sk, 0); | ||
846 | if (!dst) | ||
847 | dst = inet_csk_rebuild_route(sk, &inet->cork.fl); | ||
848 | out: | ||
849 | return dst; | ||
850 | } | ||
851 | EXPORT_SYMBOL_GPL(inet_csk_update_pmtu); | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7a0062cb4ed0..b8e7e0595407 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -289,17 +289,10 @@ static void do_pmtu_discovery(struct sock *sk, const struct iphdr *iph, u32 mtu) | |||
289 | if (sk->sk_state == TCP_LISTEN) | 289 | if (sk->sk_state == TCP_LISTEN) |
290 | return; | 290 | return; |
291 | 291 | ||
292 | /* We don't check in the destentry if pmtu discovery is forbidden | 292 | dst = inet_csk_update_pmtu(sk, mtu); |
293 | * on this route. We just assume that no packet_to_big packets | 293 | if (!dst) |
294 | * are send back when pmtu discovery is not active. | ||
295 | * There is a small race when the user changes this flag in the | ||
296 | * route, but I think that's acceptable. | ||
297 | */ | ||
298 | if ((dst = __sk_dst_check(sk, 0)) == NULL) | ||
299 | return; | 294 | return; |
300 | 295 | ||
301 | dst->ops->update_pmtu(dst, mtu); | ||
302 | |||
303 | /* Something is about to be wrong... Remember soft error | 296 | /* Something is about to be wrong... Remember soft error |
304 | * for the case, if this connection will not able to recover. | 297 | * for the case, if this connection will not able to recover. |
305 | */ | 298 | */ |