On Thu, Mar 30, 2017 at 5:02 PM, Eric Dumazet <eric.duma...@gmail.com> wrote: > On Thu, 2017-03-30 at 16:36 -0700, Cong Wang wrote: >> On Tue, Mar 28, 2017 at 5:52 PM, Eric Dumazet <eric.duma...@gmail.com> wrote: >> > On Tue, 2017-03-28 at 16:11 -0700, Eric Dumazet wrote: >> > >> >> Yes, this looks better. >> >> >> >> Although you probably need to change a bit later this part : >> >> >> >> if (!inet->inet_saddr) >> >> inet->inet_saddr = fl4->saddr; /* Update source address */ >> >> >> > >> > I came up with the following tested patch for IPv4 >> > >> > diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c >> > index >> > f915abff1350a86af8d5bb89725b751c061b0fb5..1454b6191e0d38ffae0ae260578858285bc5f77b >> > 100644 >> > --- a/net/ipv4/datagram.c >> > +++ b/net/ipv4/datagram.c >> > @@ -40,7 +40,7 @@ int __ip4_datagram_connect(struct sock *sk, struct >> > sockaddr *uaddr, int addr_len >> > sk_dst_reset(sk); >> > >> > oif = sk->sk_bound_dev_if; >> > - saddr = inet->inet_saddr; >> > + saddr = (sk->sk_userlocks & SOCK_BINDADDR_LOCK) ? inet->inet_saddr >> > : 0; >> > if (ipv4_is_multicast(usin->sin_addr.s_addr)) { >> > if (!oif) >> > oif = inet->mc_index; >> > @@ -64,9 +64,8 @@ int __ip4_datagram_connect(struct sock *sk, struct >> > sockaddr *uaddr, int addr_len >> > err = -EACCES; >> > goto out; >> > } >> > - if (!inet->inet_saddr) >> > + if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) { >> > inet->inet_saddr = fl4->saddr; /* Update source address */ >> > - if (!inet->inet_rcv_saddr) { >> > inet->inet_rcv_saddr = fl4->saddr; >> > if (sk->sk_prot->rehash) >> > sk->sk_prot->rehash(sk); >> >> Why do we need this here? If you mean bind() INADDR_ANY is bound, >> then it is totally a different problem? > > > Proper delivery of RX packets will need to find the socket, and this > needs the 2-tuple (source address, source port) info for UDP. > > So after a connect(), we need to rehash
Oh, I didn't notice remove the if (!inet->inet_rcv_saddr) check... [...] >> 1) When a bind() is called before connect()'s, aka: >> >> bind(); >> connect(addr1); // should not change source addr > > It depends. bind() can be only allocating the source port. > > If bind(INADDR_ANY) was used, then we need to determine source addr at > connect() time. Yes, bind() only sets the flag for non-zero address: if (inet->inet_rcv_saddr) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; Please submit your patch formally and with a man page patch too.