diff options
-rw-r--r-- | include/net/route.h | 19 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 6 |
3 files changed, 23 insertions, 12 deletions
diff --git a/include/net/route.h b/include/net/route.h index bf790c1c6ac8..b3f89ad04e0b 100644 --- a/include/net/route.h +++ b/include/net/route.h | |||
@@ -200,16 +200,19 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst, | |||
200 | } | 200 | } |
201 | 201 | ||
202 | static inline int ip_route_newports(struct rtable **rp, u8 protocol, | 202 | static inline int ip_route_newports(struct rtable **rp, u8 protocol, |
203 | __be16 orig_sport, __be16 orig_dport, | ||
203 | __be16 sport, __be16 dport, struct sock *sk) | 204 | __be16 sport, __be16 dport, struct sock *sk) |
204 | { | 205 | { |
205 | if (sport != (*rp)->fl.fl_ip_sport || | 206 | if (sport != orig_sport || dport != orig_dport) { |
206 | dport != (*rp)->fl.fl_ip_dport) { | 207 | struct flowi fl = { .oif = (*rp)->fl.oif, |
207 | struct flowi fl; | 208 | .mark = (*rp)->fl.mark, |
208 | 209 | .fl4_dst = (*rp)->fl.fl4_dst, | |
209 | memcpy(&fl, &(*rp)->fl, sizeof(fl)); | 210 | .fl4_src = (*rp)->fl.fl4_src, |
210 | fl.fl_ip_sport = sport; | 211 | .fl4_tos = (*rp)->fl.fl4_tos, |
211 | fl.fl_ip_dport = dport; | 212 | .proto = (*rp)->fl.proto, |
212 | fl.proto = protocol; | 213 | .fl_ip_sport = sport, |
214 | .fl_ip_dport = dport }; | ||
215 | |||
213 | if (inet_sk(sk)->transparent) | 216 | if (inet_sk(sk)->transparent) |
214 | fl.flags |= FLOWI_FLAG_ANYSRC; | 217 | fl.flags |= FLOWI_FLAG_ANYSRC; |
215 | if (protocol == IPPROTO_TCP) | 218 | if (protocol == IPPROTO_TCP) |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 45a434f94169..937989199c80 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -43,6 +43,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
43 | struct inet_sock *inet = inet_sk(sk); | 43 | struct inet_sock *inet = inet_sk(sk); |
44 | struct dccp_sock *dp = dccp_sk(sk); | 44 | struct dccp_sock *dp = dccp_sk(sk); |
45 | const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; | 45 | const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; |
46 | __be16 orig_sport, orig_dport; | ||
46 | struct rtable *rt; | 47 | struct rtable *rt; |
47 | __be32 daddr, nexthop; | 48 | __be32 daddr, nexthop; |
48 | int tmp; | 49 | int tmp; |
@@ -63,10 +64,12 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
63 | nexthop = inet->opt->faddr; | 64 | nexthop = inet->opt->faddr; |
64 | } | 65 | } |
65 | 66 | ||
67 | orig_sport = inet->inet_sport; | ||
68 | orig_dport = usin->sin_port; | ||
66 | tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, | 69 | tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, |
67 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, | 70 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, |
68 | IPPROTO_DCCP, | 71 | IPPROTO_DCCP, |
69 | inet->inet_sport, usin->sin_port, sk, 1); | 72 | orig_sport, orig_dport, sk, 1); |
70 | if (tmp < 0) | 73 | if (tmp < 0) |
71 | return tmp; | 74 | return tmp; |
72 | 75 | ||
@@ -99,8 +102,9 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
99 | if (err != 0) | 102 | if (err != 0) |
100 | goto failure; | 103 | goto failure; |
101 | 104 | ||
102 | err = ip_route_newports(&rt, IPPROTO_DCCP, inet->inet_sport, | 105 | err = ip_route_newports(&rt, IPPROTO_DCCP, |
103 | inet->inet_dport, sk); | 106 | orig_sport, orig_dport, |
107 | inet->inet_sport, inet->inet_dport, sk); | ||
104 | if (err != 0) | 108 | if (err != 0) |
105 | goto failure; | 109 | goto failure; |
106 | 110 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ef5a90beb9b0..27a0cc8cc888 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -149,6 +149,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
149 | struct inet_sock *inet = inet_sk(sk); | 149 | struct inet_sock *inet = inet_sk(sk); |
150 | struct tcp_sock *tp = tcp_sk(sk); | 150 | struct tcp_sock *tp = tcp_sk(sk); |
151 | struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; | 151 | struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; |
152 | __be16 orig_sport, orig_dport; | ||
152 | struct rtable *rt; | 153 | struct rtable *rt; |
153 | __be32 daddr, nexthop; | 154 | __be32 daddr, nexthop; |
154 | int tmp; | 155 | int tmp; |
@@ -167,10 +168,12 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
167 | nexthop = inet->opt->faddr; | 168 | nexthop = inet->opt->faddr; |
168 | } | 169 | } |
169 | 170 | ||
171 | orig_sport = inet->inet_sport; | ||
172 | orig_dport = usin->sin_port; | ||
170 | tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, | 173 | tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, |
171 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, | 174 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, |
172 | IPPROTO_TCP, | 175 | IPPROTO_TCP, |
173 | inet->inet_sport, usin->sin_port, sk, 1); | 176 | orig_sport, orig_dport, sk, 1); |
174 | if (tmp < 0) { | 177 | if (tmp < 0) { |
175 | if (tmp == -ENETUNREACH) | 178 | if (tmp == -ENETUNREACH) |
176 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 179 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
@@ -234,6 +237,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
234 | goto failure; | 237 | goto failure; |
235 | 238 | ||
236 | err = ip_route_newports(&rt, IPPROTO_TCP, | 239 | err = ip_route_newports(&rt, IPPROTO_TCP, |
240 | orig_sport, orig_dport, | ||
237 | inet->inet_sport, inet->inet_dport, sk); | 241 | inet->inet_sport, inet->inet_dport, sk); |
238 | if (err) | 242 | if (err) |
239 | goto failure; | 243 | goto failure; |