aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-02-24 16:38:12 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-24 16:38:12 -0500
commitdca8b089c95d94afa1d715df257de0286350e99d (patch)
treef686fef8ef3d80f81bd9f91072ce8c5f347e3e7c
parent33765d06033cc4ba4d9ae6d3d606ef3f28773c1b (diff)
ipv4: Rearrange how ip_route_newports() gets port keys.
ip_route_newports() is the only place in the entire kernel that cares about the port members in the routing cache entry's lookup flow key. Therefore the only reason we store an entire flow inside of the struct rtentry is for this one special case. Rewrite ip_route_newports() such that: 1) The caller passes in the original port values, so we don't need to use the rth->fl.fl_ip_{s,d}port values to remember them. 2) The lookup flow is constructed by hand instead of being copied from the routing cache entry's flow. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/route.h19
-rw-r--r--net/dccp/ipv4.c10
-rw-r--r--net/ipv4/tcp_ipv4.c6
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
202static inline int ip_route_newports(struct rtable **rp, u8 protocol, 202static 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;