From 2d7192d6cbab20e153c47fa1559ffd41ceef0e79 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Apr 2011 13:28:44 -0700 Subject: ipv4: Sanitize and simplify ip_route_{connect,newports}() These functions are used together as a unit for route resolution during connect(). They address the chicken-and-egg problem that exists when ports need to be allocated during connect() processing, yet such port allocations require addressing information from the routing code. It's currently more heavy handed than it needs to be, and in particular we allocate and initialize a flow object twice. Let the callers provide the on-stack flow object. That way we only need to initialize it once in the ip_route_connect() call. Later, if ip_route_newports() needs to do anything, it re-uses that flow object as-is except for the ports which it updates before the route re-lookup. Also, describe why this set of facilities are needed and how it works in a big comment. Signed-off-by: David S. Miller Reviewed-by: Eric Dumazet --- net/ipv4/datagram.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/ipv4/datagram.c') diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 85bd24c..216ba23 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -24,6 +24,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; + struct flowi4 fl4; struct rtable *rt; __be32 saddr; int oif; @@ -46,7 +47,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (!saddr) saddr = inet->mc_addr; } - rt = ip_route_connect(usin->sin_addr.s_addr, saddr, + rt = ip_route_connect(&fl4, usin->sin_addr.s_addr, saddr, RT_CONN_FLAGS(sk), oif, sk->sk_protocol, inet->inet_sport, usin->sin_port, sk, true); -- cgit v1.1 From a406b611b5f26a18773e4237d79f6df3eaed1d32 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:17:16 -0700 Subject: ipv4: Fetch route saddr from flow key in ip4_datagram_connect(). Now that output route lookups update the flow with source address selection, we can fetch it from fl4->saddr instead of rt->rt_src Signed-off-by: David S. Miller --- net/ipv4/datagram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/ipv4/datagram.c') diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 216ba23..b7f583c 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -63,9 +63,9 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) return -EACCES; } if (!inet->inet_saddr) - inet->inet_saddr = rt->rt_src; /* Update source address */ + inet->inet_saddr = fl4.saddr; /* Update source address */ if (!inet->inet_rcv_saddr) { - inet->inet_rcv_saddr = rt->rt_src; + inet->inet_rcv_saddr = fl4.saddr; if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk); } -- cgit v1.1 From 87321c839fb4a65b5d78c16d79d1674cf223a452 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Apr 2011 23:49:45 -0700 Subject: ipv4: Get route daddr from flow key in ip4_datagram_connect(). Now that output route lookups update the flow with destination address selection, we can fetch it from fl4->daddr instead of rt->rt_dst Signed-off-by: David S. Miller --- net/ipv4/datagram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv4/datagram.c') diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index b7f583c..d5a2e69 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -69,7 +69,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk); } - inet->inet_daddr = rt->rt_dst; + inet->inet_daddr = fl4.daddr; inet->inet_dport = usin->sin_port; sk->sk_state = TCP_ESTABLISHED; inet->inet_id = jiffies; -- cgit v1.1 From 3038eeac027d8ec62e4936143498f2b37baf4cb5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 May 2011 22:27:25 -0700 Subject: ipv4: Lock socket and use cork flow in ip4_datagram_connect(). This is to make sure that an l2tp socket's inet cork flow is fully filled in, when it's encapsulated in UDP. Signed-off-by: David S. Miller --- net/ipv4/datagram.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'net/ipv4/datagram.c') diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index d5a2e69..424fafb 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -24,7 +24,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; - struct flowi4 fl4; + struct flowi4 *fl4; struct rtable *rt; __be32 saddr; int oif; @@ -39,6 +39,8 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) sk_dst_reset(sk); + lock_sock(sk); + oif = sk->sk_bound_dev_if; saddr = inet->inet_saddr; if (ipv4_is_multicast(usin->sin_addr.s_addr)) { @@ -47,7 +49,8 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (!saddr) saddr = inet->mc_addr; } - rt = ip_route_connect(&fl4, usin->sin_addr.s_addr, saddr, + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr, RT_CONN_FLAGS(sk), oif, sk->sk_protocol, inet->inet_sport, usin->sin_port, sk, true); @@ -55,26 +58,30 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) err = PTR_ERR(rt); if (err == -ENETUNREACH) IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); - return err; + goto out; } if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { ip_rt_put(rt); - return -EACCES; + err = -EACCES; + goto out; } if (!inet->inet_saddr) - inet->inet_saddr = fl4.saddr; /* Update source address */ + inet->inet_saddr = fl4->saddr; /* Update source address */ if (!inet->inet_rcv_saddr) { - inet->inet_rcv_saddr = fl4.saddr; + inet->inet_rcv_saddr = fl4->saddr; if (sk->sk_prot->rehash) sk->sk_prot->rehash(sk); } - inet->inet_daddr = fl4.daddr; + inet->inet_daddr = fl4->daddr; inet->inet_dport = usin->sin_port; sk->sk_state = TCP_ESTABLISHED; inet->inet_id = jiffies; sk_dst_set(sk, &rt->dst); - return 0; + err = 0; +out: + release_sock(sk); + return err; } EXPORT_SYMBOL(ip4_datagram_connect); -- cgit v1.1