sctp: implement sender-side procedures for SSN/TSN Reset Request Parameter
authorXin Long <lucien.xin@gmail.com>
Wed, 8 Feb 2017 17:18:18 +0000 (01:18 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 9 Feb 2017 21:57:38 +0000 (16:57 -0500)
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: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sctp/sctp.h
include/uapi/linux/sctp.h
net/sctp/socket.c
net/sctp/stream.c

index 480b65a24aff1ccd9ed3b0698a819a09a897c15b..b60ca14068d840728908b19173289e01e144563a 100644 (file)
@@ -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
index 03c27cefffb1467cac8417ee0bed09eb6f5da72e..c0bd8c3d565a8bc09c66267613e4ad0c3a637882 100644 (file)
@@ -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
index a8b4252fe0842882fa4a067a25204689cd1b12cd..45a7c417eb7f3c8b9e22ef49102d3b30ce395352 100644 (file)
@@ -3818,6 +3818,32 @@ out:
        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;
index 6a686e330c57e1799b5254ef7a90a0666549e9a2..53e49fc2f0a3665877cba375bc7b3a44ad9decf5 100644 (file)
@@ -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;
+}