Skip to content

Commit

Permalink
ipv4: Lock socket and use cork flow in ip4_datagram_connect().
Browse files Browse the repository at this point in the history
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 <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 8, 2011
1 parent fdbb0f0 commit 3038eea
Showing 1 changed file with 15 additions and 8 deletions.
23 changes: 15 additions & 8 deletions net/ipv4/datagram.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)) {
Expand All @@ -47,34 +49,39 @@ 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);
if (IS_ERR(rt)) {
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);

0 comments on commit 3038eea

Please sign in to comment.