Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce5325c1 authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller
Browse files

[SCTP]: Fix the SO_REUSEADDR handling to be similar to TCP.



Update the SO_REUSEADDR handling to also check for listen state.  This
was muliple listening server sockets can't be created and they will
not steal packets from each other.

Reported by Paolo Galtieri <pgaltieri@mvista.com>

Signed-off-by: default avatarVlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 16d00fb7
Loading
Loading
Loading
Loading
+22 −10
Original line number Diff line number Diff line
@@ -5020,7 +5020,8 @@ pp_found:
		struct hlist_node *node;

		SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n");
		if (pp->fastreuse && sk->sk_reuse)
		if (pp->fastreuse && sk->sk_reuse &&
			sk->sk_state != SCTP_SS_LISTENING)
			goto success;

		/* Run through the list of sockets bound to the port
@@ -5037,7 +5038,8 @@ pp_found:
			struct sctp_endpoint *ep2;
			ep2 = sctp_sk(sk2)->ep;

			if (reuse && sk2->sk_reuse)
			if (reuse && sk2->sk_reuse &&
			    sk2->sk_state != SCTP_SS_LISTENING)
				continue;

			if (sctp_bind_addr_match(&ep2->base.bind_addr, addr,
@@ -5058,9 +5060,13 @@ pp_not_found:
	 * if sk->sk_reuse is too (that is, if the caller requested
	 * SO_REUSEADDR on this socket -sk-).
	 */
	if (hlist_empty(&pp->owner))
		pp->fastreuse = sk->sk_reuse ? 1 : 0;
	else if (pp->fastreuse && !sk->sk_reuse)
	if (hlist_empty(&pp->owner)) {
		if (sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING)
			pp->fastreuse = 1;
		else
			pp->fastreuse = 0;
	} else if (pp->fastreuse &&
		(!sk->sk_reuse || sk->sk_state == SCTP_SS_LISTENING))
		pp->fastreuse = 0;

	/* We are set, so fill up all the data in the hash table
@@ -5068,8 +5074,8 @@ pp_not_found:
	 * sockets FIXME: Blurry, NPI (ipg).
	 */
success:
	inet_sk(sk)->num = snum;
	if (!sctp_sk(sk)->bind_hash) {
		inet_sk(sk)->num = snum;
		sk_add_bind_node(sk, &pp->owner);
		sctp_sk(sk)->bind_hash = pp;
	}
@@ -5142,12 +5148,16 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
	 * This is not currently spelled out in the SCTP sockets
	 * extensions draft, but follows the practice as seen in TCP
	 * sockets.
	 *
	 * Additionally, turn off fastreuse flag since we are not listening
	 */
	sk->sk_state = SCTP_SS_LISTENING;
	if (!ep->base.bind_addr.port) {
		if (sctp_autobind(sk))
			return -EAGAIN;
	}
	sk->sk_state = SCTP_SS_LISTENING;
	} else
		sctp_sk(sk)->bind_hash->fastreuse = 0;

	sctp_hash_endpoint(ep);
	return 0;
}
@@ -5185,11 +5195,13 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
	 * extensions draft, but follows the practice as seen in TCP
	 * sockets.
	 */
	sk->sk_state = SCTP_SS_LISTENING;
	if (!ep->base.bind_addr.port) {
		if (sctp_autobind(sk))
			return -EAGAIN;
	}
	sk->sk_state = SCTP_SS_LISTENING;
	} else
		sctp_sk(sk)->bind_hash->fastreuse = 0;

	sk->sk_max_ack_backlog = backlog;
	sctp_hash_endpoint(ep);
	return 0;