* [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk @ 2017-02-17 4:45 Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk Xin Long 2017-02-19 23:18 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk David Miller 0 siblings, 2 replies; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem Patch 3/7 and 4/7 are to implement receiver-side procedures for the Outgoing and Incoming SSN Reset Request Parameter described in rfc6525 section 5.2.2 and 5.2.3 Patch 1/7 and 2/7 are ahead of them to define some apis. Patch 5/7-7/7 are to add the process of reconf chunk event in rx path. Note that with this patchset, asoc->reconf_enable has no chance yet to be set, until the patch "sctp: add get and set sockopt for reconf_enable" is applied in the future. As we can not just enable it when sctp is not capable of processing reconf chunk yet. v1->v2: - re-split the patchset and make sure it has no dead codes for review. - rename the titles of the commits and improve some changelogs. - drop __packed from some structures in patch 1/7. - fix some kbuild warnings in patch 3/7 by initializing str_p = NULL. - sctp_chunk_lookup_strreset_param changes to return sctp_paramhdr_t * and uses sctp_strreset_tsnreq to access request_seq in patch 3/7. - use __u<size> in uapi sctp.h in patch 1/7. - do str_list endian conversion when generating stream_reset_event in patch 2/7. - remove str_list endian conversion, pass resp_seq param with network endian to lookup_strreset_param in 3/7. - move str_list endian conversion out of sctp_make_strreset_req, so that sctp_make_strreset_req can be used more conveniently to process inreq in patch 4/7. - remove sctp_merge_reconf_chunk and not support response with multiparam in patch 6/7. Xin Long (7): sctp: add support for generating stream reconf resp chunk sctp: add support for generating stream ssn reset event notification sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter sctp: implement receiver-side procedures for the Incoming SSN Reset Request Parameter sctp: add a function to verify the sctp reconf chunk sctp: add reconf chunk process sctp: add reconf chunk event include/linux/sctp.h | 24 ++++++ include/net/sctp/constants.h | 3 + include/net/sctp/sm.h | 21 +++++ include/net/sctp/ulpevent.h | 4 + include/uapi/linux/sctp.h | 16 ++++ net/sctp/sm_make_chunk.c | 141 +++++++++++++++++++++++++++++++-- net/sctp/sm_statefuns.c | 54 +++++++++++++ net/sctp/sm_statetable.c | 30 +++++++ net/sctp/stream.c | 183 +++++++++++++++++++++++++++++++++++++++++++ net/sctp/ulpevent.c | 29 +++++++ 10 files changed, 498 insertions(+), 7 deletions(-) -- 2.1.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk 2017-02-17 4:45 [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk Xin Long @ 2017-02-17 4:45 ` Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 2/7] sctp: add support for generating stream ssn reset event notification Xin Long 2017-02-19 23:18 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk David Miller 1 sibling, 1 reply; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem This patch is to define Re-configuration Response Parameter described in rfc6525 section 4.4. As optional fields are only for SSN/TSN Reset Request Parameter, it uses another function to make that. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/linux/sctp.h | 24 ++++++++++++++++ include/net/sctp/sm.h | 7 +++++ net/sctp/sm_make_chunk.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/include/linux/sctp.h b/include/linux/sctp.h index b055788..7a4804c 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -749,4 +749,28 @@ struct sctp_strreset_addstrm { __u16 reserved; }; +enum { + SCTP_STRRESET_NOTHING_TO_DO = 0x00, + SCTP_STRRESET_PERFORMED = 0x01, + SCTP_STRRESET_DENIED = 0x02, + SCTP_STRRESET_ERR_WRONG_SSN = 0x03, + SCTP_STRRESET_ERR_IN_PROGRESS = 0x04, + SCTP_STRRESET_ERR_BAD_SEQNO = 0x05, + SCTP_STRRESET_IN_PROGRESS = 0x06, +}; + +struct sctp_strreset_resp { + sctp_paramhdr_t param_hdr; + __u32 response_seq; + __u32 result; +}; + +struct sctp_strreset_resptsn { + sctp_paramhdr_t param_hdr; + __u32 response_seq; + __u32 result; + __u32 senders_next_tsn; + __u32 receivers_next_tsn; +}; + #endif /* __LINUX_SCTP_H__ */ diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 3675fde..8a85dd7 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -270,6 +270,13 @@ struct sctp_chunk *sctp_make_strreset_tsnreq( struct sctp_chunk *sctp_make_strreset_addstrm( const struct sctp_association *asoc, __u16 out, __u16 in); +struct sctp_chunk *sctp_make_strreset_resp( + const struct sctp_association *asoc, + __u32 result, __u32 sn); +struct sctp_chunk *sctp_make_strreset_tsnresp( + struct sctp_association *asoc, + __u32 result, __u32 sn, + __u32 sender_tsn, __u32 receiver_tsn); void sctp_chunk_assign_tsn(struct sctp_chunk *); void sctp_chunk_assign_ssn(struct sctp_chunk *); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 7f8dbf2..9680c58 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3733,3 +3733,77 @@ struct sctp_chunk *sctp_make_strreset_addstrm( return retval; } + +/* RE-CONFIG 4.4 (RESP) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Parameter Type = 16 | Parameter Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Re-configuration Response Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Result | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct sctp_chunk *sctp_make_strreset_resp( + const struct sctp_association *asoc, + __u32 result, __u32 sn) +{ + struct sctp_strreset_resp resp; + __u16 length = sizeof(resp); + struct sctp_chunk *retval; + + retval = sctp_make_reconf(asoc, length); + if (!retval) + return NULL; + + resp.param_hdr.type = SCTP_PARAM_RESET_RESPONSE; + resp.param_hdr.length = htons(length); + resp.response_seq = htonl(sn); + resp.result = htonl(result); + + sctp_addto_chunk(retval, sizeof(resp), &resp); + + return retval; +} + +/* RE-CONFIG 4.4 OPTIONAL (TSNRESP) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Parameter Type = 16 | Parameter Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Re-configuration Response Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Result | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sender's Next TSN (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Receiver's Next TSN (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +struct sctp_chunk *sctp_make_strreset_tsnresp( + struct sctp_association *asoc, + __u32 result, __u32 sn, + __u32 sender_tsn, __u32 receiver_tsn) +{ + struct sctp_strreset_resptsn tsnresp; + __u16 length = sizeof(tsnresp); + struct sctp_chunk *retval; + + retval = sctp_make_reconf(asoc, length); + if (!retval) + return NULL; + + tsnresp.param_hdr.type = SCTP_PARAM_RESET_RESPONSE; + tsnresp.param_hdr.length = htons(length); + + tsnresp.response_seq = htonl(sn); + tsnresp.result = htonl(result); + tsnresp.senders_next_tsn = htonl(sender_tsn); + tsnresp.receivers_next_tsn = htonl(receiver_tsn); + + sctp_addto_chunk(retval, sizeof(tsnresp), &tsnresp); + + return retval; +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 net-next 2/7] sctp: add support for generating stream ssn reset event notification 2017-02-17 4:45 ` [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk Xin Long @ 2017-02-17 4:45 ` Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter Xin Long 0 siblings, 1 reply; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem This patch is to add Stream Reset Event described in rfc6525 section 6.1.1. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/ulpevent.h | 4 ++++ include/uapi/linux/sctp.h | 16 ++++++++++++++++ net/sctp/ulpevent.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 2c098cd..324b596 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -128,6 +128,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_authkey( struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event( const struct sctp_association *asoc, gfp_t gfp); +struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event( + const struct sctp_association *asoc, __u16 flags, + __u16 stream_num, __u16 *stream_list, gfp_t gfp); + void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, struct msghdr *); void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event, diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index a91a9cc..d3ae381 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -490,6 +490,18 @@ struct sctp_sender_dry_event { sctp_assoc_t sender_dry_assoc_id; }; +#define SCTP_STREAM_RESET_INCOMING_SSN 0x0001 +#define SCTP_STREAM_RESET_OUTGOING_SSN 0x0002 +#define SCTP_STREAM_RESET_DENIED 0x0004 +#define SCTP_STREAM_RESET_FAILED 0x0008 +struct sctp_stream_reset_event { + __u16 strreset_type; + __u16 strreset_flags; + __u32 strreset_length; + sctp_assoc_t strreset_assoc_id; + __u16 strreset_stream_list[]; +}; + /* * Described in Section 7.3 * Ancillary Data and Notification Interest Options @@ -505,6 +517,7 @@ struct sctp_event_subscribe { __u8 sctp_adaptation_layer_event; __u8 sctp_authentication_event; __u8 sctp_sender_dry_event; + __u8 sctp_stream_reset_event; }; /* @@ -529,6 +542,7 @@ union sctp_notification { struct sctp_pdapi_event sn_pdapi_event; struct sctp_authkey_event sn_authkey_event; struct sctp_sender_dry_event sn_sender_dry_event; + struct sctp_stream_reset_event sn_strreset_event; }; /* Section 5.3.1 @@ -556,6 +570,8 @@ enum sctp_sn_type { #define SCTP_AUTHENTICATION_INDICATION SCTP_AUTHENTICATION_EVENT SCTP_SENDER_DRY_EVENT, #define SCTP_SENDER_DRY_EVENT SCTP_SENDER_DRY_EVENT + SCTP_STREAM_RESET_EVENT, +#define SCTP_STREAM_RESET_EVENT SCTP_STREAM_RESET_EVENT }; /* Notification error codes used to fill up the error fields in some diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index bea0005..c8881bc5 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -854,6 +854,35 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event( return event; } +struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event( + const struct sctp_association *asoc, __u16 flags, __u16 stream_num, + __u16 *stream_list, gfp_t gfp) +{ + struct sctp_stream_reset_event *sreset; + struct sctp_ulpevent *event; + struct sk_buff *skb; + int length, i; + + length = sizeof(struct sctp_stream_reset_event) + 2 * stream_num; + event = sctp_ulpevent_new(length, MSG_NOTIFICATION, gfp); + if (!event) + return NULL; + + skb = sctp_event2skb(event); + sreset = (struct sctp_stream_reset_event *)skb_put(skb, length); + + sreset->strreset_type = SCTP_STREAM_RESET_EVENT; + sreset->strreset_flags = flags; + sreset->strreset_length = length; + sctp_ulpevent_set_owner(event, asoc); + sreset->strreset_assoc_id = sctp_assoc2id(asoc); + + for (i = 0; i < stream_num; i++) + sreset->strreset_stream_list[i] = ntohs(stream_list[i]); + + return event; +} + /* Return the notification type, assuming this is a notification * event. */ -- 2.1.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter 2017-02-17 4:45 ` [PATCHv2 net-next 2/7] sctp: add support for generating stream ssn reset event notification Xin Long @ 2017-02-17 4:45 ` Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming " Xin Long 0 siblings, 1 reply; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem This patch is to implement Receiver-Side Procedures for the Outgoing SSN Reset Request Parameter described in rfc6525 section 5.2.2. Note that some checks must be after request_seq check, as even those checks fail, strreset_inseq still has to be increase by 1. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 6 +++ net/sctp/stream.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 8a85dd7..c0f9bea 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -280,6 +280,12 @@ struct sctp_chunk *sctp_make_strreset_tsnresp( void sctp_chunk_assign_tsn(struct sctp_chunk *); void sctp_chunk_assign_ssn(struct sctp_chunk *); +/* Prototypes for stream-processing functions. */ +struct sctp_chunk *sctp_process_strreset_outreq( + struct sctp_association *asoc, + union sctp_params param, + struct sctp_ulpevent **evp); + /* Prototypes for statetable processing. */ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype, diff --git a/net/sctp/stream.c b/net/sctp/stream.c index eb02490..531fcc4 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -294,3 +294,116 @@ int sctp_send_add_streams(struct sctp_association *asoc, out: return retval; } + +static sctp_paramhdr_t *sctp_chunk_lookup_strreset_param( + struct sctp_association *asoc, __u32 resp_seq) +{ + struct sctp_chunk *chunk = asoc->strreset_chunk; + struct sctp_reconf_chunk *hdr; + union sctp_params param; + + if (ntohl(resp_seq) != asoc->strreset_outseq || !chunk) + return NULL; + + hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr; + sctp_walk_params(param, hdr, params) { + /* sctp_strreset_tsnreq is actually the basic structure + * of all stream reconf params, so it's safe to use it + * to access request_seq. + */ + struct sctp_strreset_tsnreq *req = param.v; + + if (req->request_seq == resp_seq) + return param.v; + } + + return NULL; +} + +struct sctp_chunk *sctp_process_strreset_outreq( + struct sctp_association *asoc, + union sctp_params param, + struct sctp_ulpevent **evp) +{ + struct sctp_strreset_outreq *outreq = param.v; + struct sctp_stream *stream = asoc->stream; + __u16 i, nums, flags = 0, *str_p = NULL; + __u32 result = SCTP_STRRESET_DENIED; + __u32 request_seq; + + request_seq = ntohl(outreq->request_seq); + + if (ntohl(outreq->send_reset_at_tsn) > + sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map)) { + result = SCTP_STRRESET_IN_PROGRESS; + goto out; + } + + if (request_seq > asoc->strreset_inseq) { + result = SCTP_STRRESET_ERR_BAD_SEQNO; + goto out; + } else if (request_seq == asoc->strreset_inseq) { + asoc->strreset_inseq++; + } + + /* Check strreset_enable after inseq inc, as sender cannot tell + * the peer doesn't enable strreset after receiving response with + * result denied, as well as to keep consistent with bsd. + */ + if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) + goto out; + + if (asoc->strreset_chunk) { + sctp_paramhdr_t *param_hdr; + struct sctp_transport *t; + + param_hdr = sctp_chunk_lookup_strreset_param( + asoc, outreq->response_seq); + if (!param_hdr || param_hdr->type != + SCTP_PARAM_RESET_IN_REQUEST) { + /* same process with outstanding isn't 0 */ + result = SCTP_STRRESET_ERR_IN_PROGRESS; + goto out; + } + + asoc->strreset_outstanding--; + asoc->strreset_outseq++; + + if (!asoc->strreset_outstanding) { + t = asoc->strreset_chunk->transport; + if (del_timer(&t->reconf_timer)) + sctp_transport_put(t); + + sctp_chunk_put(asoc->strreset_chunk); + asoc->strreset_chunk = NULL; + } + + flags = SCTP_STREAM_RESET_INCOMING_SSN; + } + + nums = (ntohs(param.p->length) - sizeof(*outreq)) / 2; + if (nums) { + str_p = outreq->list_of_streams; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->incnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; + goto out; + } + } + + for (i = 0; i < nums; i++) + stream->in[ntohs(str_p[i])].ssn = 0; + } else { + for (i = 0; i < stream->incnt; i++) + stream->in[i].ssn = 0; + } + + result = SCTP_STRRESET_PERFORMED; + + *evp = sctp_ulpevent_make_stream_reset_event(asoc, + flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, + GFP_ATOMIC); + +out: + return sctp_make_strreset_resp(asoc, result, request_seq); +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming SSN Reset Request Parameter 2017-02-17 4:45 ` [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter Xin Long @ 2017-02-17 4:45 ` Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 5/7] sctp: add a function to verify the sctp reconf chunk Xin Long 0 siblings, 1 reply; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem This patch is to implement Receiver-Side Procedures for the Incoming SSN Reset Request Parameter described in rfc6525 section 5.2.3. It's also to move str_list endian conversion out of sctp_make_strreset_req, so that sctp_make_strreset_req can be used more conveniently to process inreq. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 4 +++ net/sctp/sm_make_chunk.c | 8 +----- net/sctp/stream.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index c0f9bea..f6a828d 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -285,6 +285,10 @@ struct sctp_chunk *sctp_process_strreset_outreq( struct sctp_association *asoc, union sctp_params param, struct sctp_ulpevent **evp); +struct sctp_chunk *sctp_process_strreset_inreq( + struct sctp_association *asoc, + union sctp_params param, + struct sctp_ulpevent **evp); /* Prototypes for statetable processing. */ diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9680c58..60d9fdc 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3617,7 +3617,7 @@ struct sctp_chunk *sctp_make_strreset_req( __u16 stream_len = stream_num * 2; struct sctp_strreset_inreq inreq; struct sctp_chunk *retval; - __u16 outlen, inlen, i; + __u16 outlen, inlen; outlen = (sizeof(outreq) + stream_len) * out; inlen = (sizeof(inreq) + stream_len) * in; @@ -3626,9 +3626,6 @@ struct sctp_chunk *sctp_make_strreset_req( if (!retval) return NULL; - for (i = 0; i < stream_num; i++) - stream_list[i] = htons(stream_list[i]); - if (outlen) { outreq.param_hdr.type = SCTP_PARAM_RESET_OUT_REQUEST; outreq.param_hdr.length = htons(outlen); @@ -3653,9 +3650,6 @@ struct sctp_chunk *sctp_make_strreset_req( sctp_addto_chunk(retval, stream_len, stream_list); } - for (i = 0; i < stream_num; i++) - stream_list[i] = ntohs(stream_list[i]); - return retval; } diff --git a/net/sctp/stream.c b/net/sctp/stream.c index 531fcc4..1c6cc04 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -135,7 +135,14 @@ int sctp_send_reset_streams(struct sctp_association *asoc, if (str_list[i] >= stream->incnt) goto out; + for (i = 0; i < str_nums; i++) + str_list[i] = htons(str_list[i]); + chunk = sctp_make_strreset_req(asoc, str_nums, str_list, out, in); + + for (i = 0; i < str_nums; i++) + str_list[i] = ntohs(str_list[i]); + if (!chunk) { retval = -ENOMEM; goto out; @@ -407,3 +414,66 @@ struct sctp_chunk *sctp_process_strreset_outreq( out: return sctp_make_strreset_resp(asoc, result, request_seq); } + +struct sctp_chunk *sctp_process_strreset_inreq( + struct sctp_association *asoc, + union sctp_params param, + struct sctp_ulpevent **evp) +{ + struct sctp_strreset_inreq *inreq = param.v; + struct sctp_stream *stream = asoc->stream; + __u32 result = SCTP_STRRESET_DENIED; + struct sctp_chunk *chunk = NULL; + __u16 i, nums, *str_p; + __u32 request_seq; + + request_seq = ntohl(inreq->request_seq); + if (request_seq > asoc->strreset_inseq) { + result = SCTP_STRRESET_ERR_BAD_SEQNO; + goto out; + } else if (request_seq == asoc->strreset_inseq) { + asoc->strreset_inseq++; + } + + if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) + goto out; + + if (asoc->strreset_outstanding) { + result = SCTP_STRRESET_ERR_IN_PROGRESS; + goto out; + } + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / 2; + str_p = inreq->list_of_streams; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; + goto out; + } + } + + chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0); + if (!chunk) + goto out; + + if (nums) + for (i = 0; i < nums; i++) + stream->out[ntohs(str_p[i])].state = + SCTP_STREAM_CLOSED; + else + for (i = 0; i < stream->outcnt; i++) + stream->out[i].state = SCTP_STREAM_CLOSED; + + asoc->strreset_chunk = chunk; + asoc->strreset_outstanding = 1; + sctp_chunk_hold(asoc->strreset_chunk); + + *evp = sctp_ulpevent_make_stream_reset_event(asoc, + SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC); + +out: + if (!chunk) + chunk = sctp_make_strreset_resp(asoc, result, request_seq); + + return chunk; +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 net-next 5/7] sctp: add a function to verify the sctp reconf chunk 2017-02-17 4:45 ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming " Xin Long @ 2017-02-17 4:45 ` Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 6/7] sctp: add reconf chunk process Xin Long 0 siblings, 1 reply; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem This patch is to add a function sctp_verify_reconf to do some length check and multi-params check for sctp stream reconf according to rfc6525 section 3.1. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 3 +++ net/sctp/sm_make_chunk.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index f6a828d..ca9fbfb 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -277,6 +277,9 @@ struct sctp_chunk *sctp_make_strreset_tsnresp( struct sctp_association *asoc, __u32 result, __u32 sn, __u32 sender_tsn, __u32 receiver_tsn); +bool sctp_verify_reconf(const struct sctp_association *asoc, + struct sctp_chunk *chunk, + struct sctp_paramhdr **errp); void sctp_chunk_assign_tsn(struct sctp_chunk *); void sctp_chunk_assign_ssn(struct sctp_chunk *); diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 60d9fdc..969a30c 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -3801,3 +3801,62 @@ struct sctp_chunk *sctp_make_strreset_tsnresp( return retval; } + +bool sctp_verify_reconf(const struct sctp_association *asoc, + struct sctp_chunk *chunk, + struct sctp_paramhdr **errp) +{ + struct sctp_reconf_chunk *hdr; + union sctp_params param; + __u16 last = 0, cnt = 0; + + hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr; + sctp_walk_params(param, hdr, params) { + __u16 length = ntohs(param.p->length); + + *errp = param.p; + if (cnt++ > 2) + return false; + switch (param.p->type) { + case SCTP_PARAM_RESET_OUT_REQUEST: + if (length < sizeof(struct sctp_strreset_outreq) || + (last && last != SCTP_PARAM_RESET_RESPONSE && + last != SCTP_PARAM_RESET_IN_REQUEST)) + return false; + break; + case SCTP_PARAM_RESET_IN_REQUEST: + if (length < sizeof(struct sctp_strreset_inreq) || + (last && last != SCTP_PARAM_RESET_OUT_REQUEST)) + return false; + break; + case SCTP_PARAM_RESET_RESPONSE: + if ((length != sizeof(struct sctp_strreset_resp) && + length != sizeof(struct sctp_strreset_resptsn)) || + (last && last != SCTP_PARAM_RESET_RESPONSE && + last != SCTP_PARAM_RESET_OUT_REQUEST)) + return false; + break; + case SCTP_PARAM_RESET_TSN_REQUEST: + if (length != + sizeof(struct sctp_strreset_tsnreq) || last) + return false; + break; + case SCTP_PARAM_RESET_ADD_IN_STREAMS: + if (length != sizeof(struct sctp_strreset_addstrm) || + (last && last != SCTP_PARAM_RESET_ADD_OUT_STREAMS)) + return false; + break; + case SCTP_PARAM_RESET_ADD_OUT_STREAMS: + if (length != sizeof(struct sctp_strreset_addstrm) || + (last && last != SCTP_PARAM_RESET_ADD_IN_STREAMS)) + return false; + break; + default: + return false; + } + + last = param.p->type; + } + + return true; +} -- 2.1.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 net-next 6/7] sctp: add reconf chunk process 2017-02-17 4:45 ` [PATCHv2 net-next 5/7] sctp: add a function to verify the sctp reconf chunk Xin Long @ 2017-02-17 4:45 ` Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 7/7] sctp: add reconf chunk event Xin Long 0 siblings, 1 reply; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem This patch is to add a function to process the incoming reconf chunk, in which it verifies the chunk, and traverses the param and process it with the right function one by one. sctp_sf_do_reconf would be the process function of reconf chunk event. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/sm.h | 1 + net/sctp/sm_statefuns.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index ca9fbfb..b6f682e 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -135,6 +135,7 @@ sctp_state_fn_t sctp_sf_do_8_5_1_E_sa; sctp_state_fn_t sctp_sf_cookie_echoed_err; sctp_state_fn_t sctp_sf_do_asconf; sctp_state_fn_t sctp_sf_do_asconf_ack; +sctp_state_fn_t sctp_sf_do_reconf; sctp_state_fn_t sctp_sf_do_9_2_reshutack; sctp_state_fn_t sctp_sf_eat_fwd_tsn; sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index d8798dd..e03bb1a 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -3834,6 +3834,60 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net, return SCTP_DISPOSITION_DISCARD; } +/* RE-CONFIG Section 5.2 Upon reception of an RECONF Chunk. */ +sctp_disposition_t sctp_sf_do_reconf(struct net *net, + const struct sctp_endpoint *ep, + const struct sctp_association *asoc, + const sctp_subtype_t type, void *arg, + sctp_cmd_seq_t *commands) +{ + struct sctp_paramhdr *err_param = NULL; + struct sctp_chunk *chunk = arg; + struct sctp_reconf_chunk *hdr; + union sctp_params param; + + if (!sctp_vtag_verify(chunk, asoc)) { + sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, + SCTP_NULL()); + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + } + + /* Make sure that the RECONF chunk has a valid length. */ + if (!sctp_chunk_length_valid(chunk, sizeof(*hdr))) + return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, + commands); + + if (!sctp_verify_reconf(asoc, chunk, &err_param)) + return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, + (void *)err_param, commands); + + hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr; + sctp_walk_params(param, hdr, params) { + struct sctp_chunk *reply = NULL; + struct sctp_ulpevent *ev = NULL; + + if (param.p->type == SCTP_PARAM_RESET_OUT_REQUEST) + reply = sctp_process_strreset_outreq( + (struct sctp_association *)asoc, param, &ev); + else if (param.p->type == SCTP_PARAM_RESET_IN_REQUEST) + reply = sctp_process_strreset_inreq( + (struct sctp_association *)asoc, param, &ev); + /* More handles for other types will be added here, by now it + * just ignores other types. + */ + + if (ev) + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, + SCTP_ULPEVENT(ev)); + + if (reply) + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, + SCTP_CHUNK(reply)); + } + + return SCTP_DISPOSITION_CONSUME; +} + /* * PR-SCTP Section 3.6 Receiver Side Implementation of PR-SCTP * -- 2.1.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCHv2 net-next 7/7] sctp: add reconf chunk event 2017-02-17 4:45 ` [PATCHv2 net-next 6/7] sctp: add reconf chunk process Xin Long @ 2017-02-17 4:45 ` Xin Long 0 siblings, 0 replies; 9+ messages in thread From: Xin Long @ 2017-02-17 4:45 UTC (permalink / raw) To: network dev, linux-sctp Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem This patch is to add reconf chunk event based on the sctp event frame in rx path, it will call sctp_sf_do_reconf to process the reconf chunk. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/net/sctp/constants.h | 3 +++ net/sctp/sm_statetable.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 3567c97..b07a745 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -60,11 +60,14 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM }; #define SCTP_NUM_PRSCTP_CHUNK_TYPES 1 +#define SCTP_NUM_RECONF_CHUNK_TYPES 1 + #define SCTP_NUM_AUTH_CHUNK_TYPES 1 #define SCTP_NUM_CHUNK_TYPES (SCTP_NUM_BASE_CHUNK_TYPES + \ SCTP_NUM_ADDIP_CHUNK_TYPES +\ SCTP_NUM_PRSCTP_CHUNK_TYPES +\ + SCTP_NUM_RECONF_CHUNK_TYPES +\ SCTP_NUM_AUTH_CHUNK_TYPES) /* These are the different flavours of event. */ diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index b5438b4..419b18e 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -482,6 +482,32 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN TYPE_SCTP_FWD_TSN, }; /*state_fn_t prsctp_chunk_event_table[][] */ +#define TYPE_SCTP_RECONF { \ + /* SCTP_STATE_CLOSED */ \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ + /* SCTP_STATE_COOKIE_WAIT */ \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ + /* SCTP_STATE_COOKIE_ECHOED */ \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ + /* SCTP_STATE_ESTABLISHED */ \ + TYPE_SCTP_FUNC(sctp_sf_do_reconf), \ + /* SCTP_STATE_SHUTDOWN_PENDING */ \ + TYPE_SCTP_FUNC(sctp_sf_do_reconf), \ + /* SCTP_STATE_SHUTDOWN_SENT */ \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ + /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ + /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ + TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ +} /* TYPE_SCTP_RECONF */ + +/* The primary index for this table is the chunk type. + * The secondary index for this table is the state. + */ +static const sctp_sm_table_entry_t reconf_chunk_event_table[SCTP_NUM_RECONF_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = { + TYPE_SCTP_RECONF, +}; /*state_fn_t reconf_chunk_event_table[][] */ + #define TYPE_SCTP_AUTH { \ /* SCTP_STATE_CLOSED */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ @@ -964,6 +990,10 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net, return &addip_chunk_event_table[1][state]; } + if (net->sctp.reconf_enable) + if (cid == SCTP_CID_RECONF) + return &reconf_chunk_event_table[0][state]; + if (net->sctp.auth_enable) { if (cid == SCTP_CID_AUTH) return &auth_chunk_event_table[0][state]; -- 2.1.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk 2017-02-17 4:45 [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk Xin Long @ 2017-02-19 23:18 ` David Miller 1 sibling, 0 replies; 9+ messages in thread From: David Miller @ 2017-02-19 23:18 UTC (permalink / raw) To: lucien.xin; +Cc: netdev, linux-sctp, marcelo.leitner, nhorman, vyasevich From: Xin Long <lucien.xin@gmail.com> Date: Fri, 17 Feb 2017 12:45:36 +0800 > Patch 3/7 and 4/7 are to implement receiver-side procedures for the > Outgoing and Incoming SSN Reset Request Parameter described in rfc6525 > section 5.2.2 and 5.2.3 > > Patch 1/7 and 2/7 are ahead of them to define some apis. > > Patch 5/7-7/7 are to add the process of reconf chunk event in rx path. > > Note that with this patchset, asoc->reconf_enable has no chance yet to > be set, until the patch "sctp: add get and set sockopt for reconf_enable" > is applied in the future. As we can not just enable it when sctp is not > capable of processing reconf chunk yet. ... Series applied, thanks. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2017-02-19 23:18 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-02-17 4:45 [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 1/7] sctp: add support for generating stream reconf resp chunk Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 2/7] sctp: add support for generating stream ssn reset event notification Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 3/7] sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 4/7] sctp: implement receiver-side procedures for the Incoming " Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 5/7] sctp: add a function to verify the sctp reconf chunk Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 6/7] sctp: add reconf chunk process Xin Long 2017-02-17 4:45 ` [PATCHv2 net-next 7/7] sctp: add reconf chunk event Xin Long 2017-02-19 23:18 ` [PATCHv2 net-next 0/7] sctp: add receiver-side procedures for stream reconf ssn reset request chunk David Miller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).