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

Commit a92ce1a4 authored by Xin Long's avatar Xin Long Committed by David S. Miller
Browse files

sctp: implement sender-side procedures for SSN/TSN Reset Request Parameter



This patch is to implement Sender-Side Procedures for the SSN/TSN
Reset Request Parameter descibed in rfc6525 section 5.1.4.

It is also to add sockopt SCTP_RESET_ASSOC in rfc6525 section 6.3.3
for users.

Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Acked-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c56480a1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ int sctp_offload_init(void);
 */
int sctp_send_reset_streams(struct sctp_association *asoc,
			    struct sctp_reset_streams *params);
int sctp_send_reset_assoc(struct sctp_association *asoc);

/*
 * Module global variables
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_PR_ASSOC_STATUS	115
#define SCTP_ENABLE_STREAM_RESET	118
#define SCTP_RESET_STREAMS	119
#define SCTP_RESET_ASSOC	120

/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE	0x0000
+29 −0
Original line number Diff line number Diff line
@@ -3818,6 +3818,32 @@ static int sctp_setsockopt_reset_streams(struct sock *sk,
	return retval;
}

static int sctp_setsockopt_reset_assoc(struct sock *sk,
				       char __user *optval,
				       unsigned int optlen)
{
	struct sctp_association *asoc;
	sctp_assoc_t associd;
	int retval = -EINVAL;

	if (optlen != sizeof(associd))
		goto out;

	if (copy_from_user(&associd, optval, optlen)) {
		retval = -EFAULT;
		goto out;
	}

	asoc = sctp_id2assoc(sk, associd);
	if (!asoc)
		goto out;

	retval = sctp_send_reset_assoc(asoc);

out:
	return retval;
}

/* API 6.2 setsockopt(), getsockopt()
 *
 * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3990,6 +4016,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
	case SCTP_RESET_STREAMS:
		retval = sctp_setsockopt_reset_streams(sk, optval, optlen);
		break;
	case SCTP_RESET_ASSOC:
		retval = sctp_setsockopt_reset_assoc(sk, optval, optlen);
		break;
	default:
		retval = -ENOPROTOOPT;
		break;
+40 −0
Original line number Diff line number Diff line
@@ -177,3 +177,43 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
out:
	return retval;
}

int sctp_send_reset_assoc(struct sctp_association *asoc)
{
	struct sctp_chunk *chunk = NULL;
	int retval;
	__u16 i;

	if (!asoc->peer.reconf_capable ||
	    !(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
		return -ENOPROTOOPT;

	if (asoc->strreset_outstanding)
		return -EINPROGRESS;

	chunk = sctp_make_strreset_tsnreq(asoc);
	if (!chunk)
		return -ENOMEM;

	/* Block further xmit of data until this request is completed */
	for (i = 0; i < asoc->stream->outcnt; i++)
		asoc->stream->out[i].state = SCTP_STREAM_CLOSED;

	asoc->strreset_chunk = chunk;
	sctp_chunk_hold(asoc->strreset_chunk);

	retval = sctp_send_reconf(asoc, chunk);
	if (retval) {
		sctp_chunk_put(asoc->strreset_chunk);
		asoc->strreset_chunk = NULL;

		for (i = 0; i < asoc->stream->outcnt; i++)
			asoc->stream->out[i].state = SCTP_STREAM_OPEN;

		return retval;
	}

	asoc->strreset_outstanding = 1;

	return 0;
}