sctp: add subscribe per asoc and sockopt SCTP_EVENT
Subsystems (3)
Xin Long
maintainerv2 cover sctp: add subscribe per asoc and sockopt SCTP_EVENT
This patchset mainly adds the Event Subscription sockopt described in rfc6525#section-6.2:
"Subscribing to events as described in [RFC6458] uses a setsockopt() call with the SCTP_EVENT socket option. This option takes the following structure, which specifies the association, the event type (using the same value found in the event type field), and an on/off boolean.
struct sctp_event {
sctp_assoc_t se_assoc_id;
uint16_t se_type;
uint8_t se_on;
};The user fills in the se_type field with the same value found in the strreset_type field, i.e., SCTP_STREAM_RESET_EVENT. The user will also fill in the se_assoc_id field with either the association to set this event on (this field is ignored for one-to-one style sockets) or one of the reserved constant values defined in [RFC6458]. Finally, the se_on field is set with a 1 to enable the event or a 0 to disable the event."
As for the old SCTP_EVENTS Option with struct sctp_event_subscribe, it's being DEPRECATED.
Xin Long (4):
sctp: define subscribe in sctp_sock as __u16
sctp: add subscribe per asoc
sctp: rename enum sctp_event to sctp_event_type
sctp: add sockopt SCTP_EVENT
include/net/sctp/constants.h | 2 +- include/net/sctp/sm.h | 4 +- include/net/sctp/structs.h | 4 +- include/net/sctp/ulpevent.h | 39 ++++++++------ include/uapi/linux/sctp.h | 13 ++++- net/sctp/associola.c | 2 + net/sctp/chunk.c | 8 ++- net/sctp/primitive.c | 2 +- net/sctp/sm_sideeffect.c | 12 ++--- net/sctp/sm_statetable.c | 2 +- net/sctp/socket.c | 126 ++++++++++++++++++++++++++++++++++++++++--- net/sctp/stream_interleave.c | 12 +++-- net/sctp/ulpqueue.c | 8 +-- 13 files changed, 184 insertions(+), 50 deletions(-)
Signature · 1 line
2.1.0
Xin Long
maintainerPATCH v2 1/4 sctp: define subscribe in sctp_sock as __u16
The member subscribe in sctp_sock is used to indicate to which of the events it is subscribed, more like a group of flags. So it's better to be defined as __u16 (2 bytpes), instead of struct sctp_event_subscribe (13 bytes).
Note that sctp_event_subscribe is an UAPI struct, used on sockopt calls, and thus it will not be removed. This patch only changes the internal storage of the flags.
--- include/net/sctp/structs.h | 2 +- include/net/sctp/ulpevent.h | 39 ++++++++++++++++++++++++--------------- include/uapi/linux/sctp.h | 6 +++++- net/sctp/chunk.c | 4 ++-- net/sctp/socket.c | 35 ++++++++++++++++++++++++++--------- net/sctp/stream_interleave.c | 11 ++++++----- net/sctp/ulpqueue.c | 8 ++++---- 7 files changed, 68 insertions(+), 37 deletions(-)
include/net/sctp/structs.h +1 -1
@@ -217,7 +217,7 @@ struct sctp_sock {* These two structures must be grouped together for the usercopy * whitelist region. */ -struct sctp_event_subscribe subscribe; +__u16 subscribe;struct sctp_initmsg initmsg;int user_frag;
include/net/sctp/ulpevent.h +24 -15
@@ -164,30 +164,39 @@ void sctp_ulpevent_read_nxtinfo(const struct sctp_ulpevent *event,__u16 sctp_ulpevent_get_notification_type (const struct sctp_ulpevent *event); +static inline void sctp_ulpevent_type_set (__u16 *subscribe, +__u16 sn_type,__u8 on) +{ +if (sn_type >SCTP_SN_TYPE_MAX ) +return ; + +if (on) + *subscribe |= (1 << (sn_type -SCTP_SN_TYPE_BASE )); +else + *subscribe &= ~(1 << (sn_type -SCTP_SN_TYPE_BASE )); +} +/* Is this event type enabled? */ -static inline int sctp_ulpevent_type_enabled (__u16 sn_type, -struct sctp_event_subscribe *mask) +static inline bool sctp_ulpevent_type_enabled (__u16 subscribe,__u16 sn_type) { -int offset = sn_type -SCTP_SN_TYPE_BASE ; -char *amask = (char *) mask; +if (sn_type >SCTP_SN_TYPE_MAX ) +return false; -if (offset >=sizeof (struct sctp_event_subscribe )) -return 0 ; -return amask[offset]; +return subscribe & (1 << (sn_type -SCTP_SN_TYPE_BASE )); }/* Given an event subscription, is this event enabled? */ -static inline int sctp_ulpevent_is_enabled (const struct sctp_ulpevent *event, -struct sctp_event_subscribe *mask) +static inline bool sctp_ulpevent_is_enabled (const struct sctp_ulpevent *event, +__u16 subscribe) {__u16 sn_type; -int enabled =1 ; -if (sctp_ulpevent_is_notification (event)) { - sn_type =sctp_ulpevent_get_notification_type (event); - enabled =sctp_ulpevent_type_enabled (sn_type, mask); - } -return enabled; +if (!sctp_ulpevent_is_notification (event)) +return true; + + sn_type =sctp_ulpevent_get_notification_type (event); + +return sctp_ulpevent_type_enabled (subscribe, sn_type); }#endif /* __sctp_ulpevent_h__ */
include/uapi/linux/sctp.h +5 -1
@@ -632,7 +632,9 @@ union sctp_notification {*/ enum sctp_sn_type { -SCTP_SN_TYPE_BASE = (1 <<15 ), +SCTP_SN_TYPE_BASE = (1 <<15 ), +SCTP_DATA_IO_EVENT =SCTP_SN_TYPE_BASE , +#define SCTP_DATA_IO_EVENT SCTP_DATA_IO_EVENT SCTP_ASSOC_CHANGE,#define SCTP_ASSOC_CHANGE SCTP_ASSOC_CHANGE SCTP_PEER_ADDR_CHANGE,
@@ -657,6 +659,8 @@ enum sctp_sn_type {#define SCTP_ASSOC_RESET_EVENT SCTP_ASSOC_RESET_EVENT SCTP_STREAM_CHANGE_EVENT,#define SCTP_STREAM_CHANGE_EVENT SCTP_STREAM_CHANGE_EVENT + SCTP_SN_TYPE_MAX = SCTP_STREAM_CHANGE_EVENT, +#define SCTP_SN_TYPE_MAX SCTP_SN_TYPE_MAX };/* Notification error codes used to fill up the error fields in some
net/sctp/chunk.c +2 -2
@@ -109,8 +109,8 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg) error = asoc->outqueue.error; sp =sctp_sk (asoc->base.sk); - notify =sctp_ulpevent_type_enabled (SCTP_SEND_FAILED , - &sp->subscribe); + notify =sctp_ulpevent_type_enabled (sp->subscribe, +SCTP_SEND_FAILED ); }/* Generate a SEND FAILED event only if enabled. */
net/sctp/socket.c +26 -9
@@ -2230,7 +2230,7 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,if (sp->recvrcvinfo)sctp_ulpevent_read_rcvinfo (event, msg);/* Check if we allow SCTP_SNDRCVINFO. */ -if (sp->subscribe.sctp_data_io_event) +if (sctp_ulpevent_type_enabled (sp->subscribe,SCTP_DATA_IO_EVENT ))sctp_ulpevent_read_sndrcvinfo (event, msg); err = copied;
@@ -2304,21 +2304,28 @@ static int sctp_setsockopt_disable_fragments(struct sock *sk,static int sctp_setsockopt_events (struct sock *sk,char __user *optval,unsigned int optlen) { -struct sctp_association *asoc; -struct sctp_ulpevent *event; +struct sctp_event_subscribe subscribe; +__u8 *sn_type = (__u8 *)&subscribe; +struct sctp_sock *sp =sctp_sk (sk); +int i;if (optlen >sizeof (struct sctp_event_subscribe ))return -EINVAL ; -if (copy_from_user (&sctp_sk (sk)->subscribe, optval, optlen)) + +if (copy_from_user (&subscribe, optval, optlen))return -EFAULT ; +for (i =0 ; i < optlen; i++) +sctp_ulpevent_type_set (&sp->subscribe,SCTP_SN_TYPE_BASE + i, + sn_type[i]); +/* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, * if there is no data to be sent or retransmit, the stack will * immediately send up this notification. */ -if (sctp_ulpevent_type_enabled (SCTP_SENDER_DRY_EVENT , - &sctp_sk (sk)->subscribe)) { - asoc =sctp_id2assoc (sk,0 ); +if (sctp_ulpevent_type_enabled (sp->subscribe,SCTP_SENDER_DRY_EVENT )) { +struct sctp_association *asoc =sctp_id2assoc (sk,0 ); +struct sctp_ulpevent *event;if (asoc &&sctp_outq_is_empty (&asoc->outqueue)) { event = sctp_ulpevent_make_sender_dry_event(asoc,
@@ -4722,7 +4729,7 @@ static int sctp_init_sock(struct sock *sk)/* Initialize default event subscriptions. By default, all the * options are off. */ -memset (&sp->subscribe,0 ,sizeof (struct sctp_event_subscribe )); + sp->subscribe =0 ;/* Default Peer Address Parameters. These defaults can * be modified via SCTP_PEER_ADDR_PARAMS
@@ -5267,14 +5274,24 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,static int sctp_getsockopt_events (struct sock *sk,int len,char __user *optval,int __user *optlen) { +struct sctp_event_subscribe subscribe; +__u8 *sn_type = (__u8 *)&subscribe; +int i; +if (len =0 )return -EINVAL ;if (len >sizeof (struct sctp_event_subscribe )) len =sizeof (struct sctp_event_subscribe );if (put_user (len, optlen))return -EFAULT ; -if (copy_to_user (optval, &sctp_sk (sk)->subscribe, len)) + +for (i =0 ; i <= len; i++) + sn_type[i] =sctp_ulpevent_type_enabled (sctp_sk (sk)->subscribe, +SCTP_SN_TYPE_BASE + i); + +if (copy_to_user (optval, &subscribe, len))return -EFAULT ; +return 0 ; }
net/sctp/stream_interleave.c +6 -5
@@ -503,7 +503,7 @@ static int sctp_enqueue_event(struct sctp_ulpq *ulpq,sk_incoming_cpu_update (sk); } -if (!sctp_ulpevent_is_enabled (event, &sp->subscribe)) +if (!sctp_ulpevent_is_enabled (event, sp->subscribe)) goto out_free;if (skb_list)
@@ -992,10 +992,11 @@ static void sctp_intl_stream_abort_pd(struct sctp_ulpq *ulpq, __u16 sid, __u32 mid, __u16 flags, gfp_t gfp) { struct sock *sk = ulpq->asoc->base.sk; +struct sctp_sock *sp =sctp_sk (sk);struct sctp_ulpevent *ev =NULL ; -if (!sctp_ulpevent_type_enabled (SCTP_PARTIAL_DELIVERY_EVENT , - &sctp_sk (sk)->subscribe)) +if (!sctp_ulpevent_type_enabled (sp->subscribe, +SCTP_PARTIAL_DELIVERY_EVENT ))return ; ev = sctp_ulpevent_make_pdapi(ulpq->asoc, SCTP_PARTIAL_DELIVERY_ABORTED,
@@ -1003,8 +1004,8 @@ static void sctp_intl_stream_abort_pd(struct sctp_ulpq *ulpq, __u16 sid,if (ev) {__skb_queue_tail (&sk->sk_receive_queue,sctp_event2skb (ev)); -if (!sctp_sk (sk)->data_ready_signalled) { -sctp_sk (sk)->data_ready_signalled =1 ; +if (!sp->data_ready_signalled) { + sp->data_ready_signalled =1 ; sk->sk_data_ready (sk); } }
net/sctp/ulpqueue.c +4 -4
@@ -219,7 +219,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)sk_incoming_cpu_update (sk); }/* Check if the user wishes to receive this event. */ -if (!sctp_ulpevent_is_enabled (event, &sp->subscribe)) +if (!sctp_ulpevent_is_enabled (event, sp->subscribe)) goto out_free;/* If we are in partial delivery mode, post to the lobby until
@@ -1129,16 +1129,16 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,void sctp_ulpq_abort_pd (struct sctp_ulpq *ulpq,gfp_t gfp) {struct sctp_ulpevent *ev =NULL ; -struct sock *sk;struct sctp_sock *sp; +struct sock *sk;if (!ulpq->pd_mode)return ; sk = ulpq->asoc->base.sk; sp =sctp_sk (sk); -if (sctp_ulpevent_type_enabled (SCTP_PARTIAL_DELIVERY_EVENT , - &sctp_sk (sk)->subscribe)) +if (sctp_ulpevent_type_enabled (sp->subscribe, +SCTP_PARTIAL_DELIVERY_EVENT )) ev =sctp_ulpevent_make_pdapi (ulpq->asoc,SCTP_PARTIAL_DELIVERY_ABORTED ,0 ,0 ,0 , gfp);
Signature · 1 line
2.1.0
Xin Long
maintainerPATCH v2 2/4 sctp: add subscribe per asoc
The member subscribe should be per asoc, so that sockopt SCTP_EVENT in the next patch can subscribe a event from one asoc only.
--- include/net/sctp/structs.h | 2 ++ net/sctp/associola.c | 2 ++ net/sctp/chunk.c | 6 ++---- net/sctp/socket.c | 6 +++++- net/sctp/stream_interleave.c | 7 ++++--- net/sctp/ulpqueue.c | 4 ++-- 6 files changed, 17 insertions(+), 10 deletions(-)
include/net/sctp/structs.h +2 -0
@@ -2077,6 +2077,8 @@ struct sctp_association {int sent_cnt_removable; +__u16 subscribe; +__u64 abandoned_unsent[SCTP_PR_INDEX (MAX ) +1 ];__u64 abandoned_sent[SCTP_PR_INDEX (MAX ) +1 ]; };
net/sctp/associola.c +2 -0
@@ -135,6 +135,8 @@ static struct sctp_association *sctp_association_init(*/ asoc->max_burst = sp->max_burst; + asoc->subscribe = sp->subscribe; +/* initialize association timers */ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE ] = asoc->rto_initial; asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT ] = asoc->rto_initial;
net/sctp/chunk.c +2 -4
@@ -86,11 +86,10 @@ void sctp_datamsg_free(struct sctp_datamsg *msg)/* Final destructruction of datamsg memory. */ static void sctp_datamsg_destroy (struct sctp_datamsg *msg) { +struct sctp_association *asoc =NULL ;struct list_head *pos, *temp;struct sctp_chunk *chunk; -struct sctp_sock *sp;struct sctp_ulpevent *ev; -struct sctp_association *asoc =NULL ;int error =0 , notify;/* If we failed, we may need to notify. */
@@ -108,8 +107,7 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)else error = asoc->outqueue.error; - sp =sctp_sk (asoc->base.sk); - notify =sctp_ulpevent_type_enabled (sp->subscribe, + notify =sctp_ulpevent_type_enabled (asoc->subscribe,SCTP_SEND_FAILED ); }
net/sctp/socket.c +5 -1
@@ -2307,6 +2307,7 @@ static int sctp_setsockopt_events(struct sock *sk, char __user *optval,struct sctp_event_subscribe subscribe;__u8 *sn_type = (__u8 *)&subscribe;struct sctp_sock *sp =sctp_sk (sk); +struct sctp_association *asoc;int i;if (optlen >sizeof (struct sctp_event_subscribe ))
@@ -2319,14 +2320,17 @@ static int sctp_setsockopt_events(struct sock *sk, char __user *optval,sctp_ulpevent_type_set (&sp->subscribe,SCTP_SN_TYPE_BASE + i, sn_type[i]); +list_for_each_entry (asoc, &sp->ep->asocs, asocs) + asoc->subscribe =sctp_sk (sk)->subscribe; +/* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, * if there is no data to be sent or retransmit, the stack will * immediately send up this notification. */ if (sctp_ulpevent_type_enabled (sp->subscribe,SCTP_SENDER_DRY_EVENT )) { -struct sctp_association *asoc =sctp_id2assoc (sk,0 );struct sctp_ulpevent *event; + asoc =sctp_id2assoc (sk,0 );if (asoc &&sctp_outq_is_empty (&asoc->outqueue)) { event =sctp_ulpevent_make_sender_dry_event (asoc,GFP_USER | __GFP_NOWARN);
net/sctp/stream_interleave.c +4 -3
@@ -503,7 +503,7 @@ static int sctp_enqueue_event(struct sctp_ulpq *ulpq,sk_incoming_cpu_update (sk); } -if (!sctp_ulpevent_is_enabled (event, sp->subscribe)) +if (!sctp_ulpevent_is_enabled (event, ulpq->asoc->subscribe)) goto out_free;if (skb_list)
@@ -992,16 +992,17 @@ static void sctp_intl_stream_abort_pd(struct sctp_ulpq *ulpq, __u16 sid, __u32 mid, __u16 flags, gfp_t gfp) { struct sock *sk = ulpq->asoc->base.sk; -struct sctp_sock *sp =sctp_sk (sk);struct sctp_ulpevent *ev =NULL ; -if (!sctp_ulpevent_type_enabled (sp->subscribe, +if (!sctp_ulpevent_type_enabled (ulpq->asoc->subscribe,SCTP_PARTIAL_DELIVERY_EVENT ))return ; ev =sctp_ulpevent_make_pdapi (ulpq->asoc,SCTP_PARTIAL_DELIVERY_ABORTED , sid, mid, flags, gfp);if (ev) { +struct sctp_sock *sp =sctp_sk (sk); +__skb_queue_tail (&sk->sk_receive_queue,sctp_event2skb (ev));if (!sp->data_ready_signalled) {
net/sctp/ulpqueue.c +2 -2
@@ -219,7 +219,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)sk_incoming_cpu_update (sk); }/* Check if the user wishes to receive this event. */ -if (!sctp_ulpevent_is_enabled (event, sp->subscribe)) +if (!sctp_ulpevent_is_enabled (event, ulpq->asoc->subscribe)) goto out_free;/* If we are in partial delivery mode, post to the lobby until
@@ -1137,7 +1137,7 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) sk = ulpq->asoc->base.sk; sp =sctp_sk (sk); -if (sctp_ulpevent_type_enabled (sp->subscribe, +if (sctp_ulpevent_type_enabled (ulpq->asoc->subscribe,SCTP_PARTIAL_DELIVERY_EVENT )) ev = sctp_ulpevent_make_pdapi(ulpq->asoc, SCTP_PARTIAL_DELIVERY_ABORTED,
Signature · 1 line
2.1.0
Xin Long
maintainerPATCH v2 3/4 sctp: rename enum sctp_event to sctp_event_type
sctp_event is a structure name defined in RFC for sockopt SCTP_EVENT. To avoid the conflict, rename it.
--- include/net/sctp/constants.h | 2 +- include/net/sctp/sm.h | 4 ++-- net/sctp/primitive.c | 2 +- net/sctp/sm_sideeffect.c | 12 ++++++------ net/sctp/sm_statetable.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-)
include/net/sctp/constants.h +1 -1
@@ -71,7 +71,7 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM }; SCTP_NUM_AUTH_CHUNK_TYPES)/* These are the different flavours of event. */ -enum sctp_event { +enum sctp_event_type {SCTP_EVENT_T_CHUNK =1 ,SCTP_EVENT_T_TIMEOUT ,SCTP_EVENT_T_OTHER ,
include/net/sctp/sm.h +2 -2
@@ -173,7 +173,7 @@ sctp_state_fn_t sctp_sf_autoclose_timer_expire;__u8 sctp_get_chunk_type (struct sctp_chunk *chunk);const struct sctp_sm_table_entry *sctp_sm_lookup_event (struct net *net, -enum sctp_event event_type, +enum sctp_event_type event_type,enum sctp_state state,union sctp_subtype event_subtype);int sctp_chunk_iif (const struct sctp_chunk *);
@@ -313,7 +313,7 @@ struct sctp_chunk *sctp_process_strreset_resp(/* Prototypes for statetable processing. */ -int sctp_do_sm (struct net *net,enum sctp_event event_type, +int sctp_do_sm (struct net *net,enum sctp_event_type event_type,union sctp_subtype subtype,enum sctp_state state,struct sctp_endpoint *ep,struct sctp_association *asoc,void *event_arg,gfp_t gfp);
net/sctp/primitive.c +1 -1
@@ -53,7 +53,7 @@ int sctp_primitive_ ## name(struct net *net, struct sctp_association *asoc, \ void *arg) { \ int error = 0; \ - enum sctp_event event_type; union sctp_subtype subtype; \ + enum sctp_event_type event_type; union sctp_subtype subtype; \ enum sctp_state state; \ struct sctp_endpoint *ep; \ \
net/sctp/sm_sideeffect.c +6 -6
@@ -52,7 +52,7 @@#include <net/sctp/sm.h> #include <net/sctp/stream_sched.h> -static int sctp_cmd_interpreter(enum sctp_event event_type, +static int sctp_cmd_interpreter(enum sctp_event_type event_type, union sctp_subtype subtype, enum sctp_state state, struct sctp_endpoint *ep,
@@ -61,7 +61,7 @@ static int sctp_cmd_interpreter(enum sctp_event event_type,enum sctp_disposition status, struct sctp_cmd_seq *commands, gfp_t gfp); -static int sctp_side_effects(enum sctp_event event_type, +static int sctp_side_effects(enum sctp_event_type event_type, union sctp_subtype subtype, enum sctp_state state, struct sctp_endpoint *ep,
@@ -623,7 +623,7 @@ static void sctp_cmd_init_failed(struct sctp_cmd_seq *commands,/* Worker routine to handle SCTP_CMD_ASSOC_FAILED. */ static void sctp_cmd_assoc_failed (struct sctp_cmd_seq *commands,struct sctp_association *asoc, -enum sctp_event event_type, +enum sctp_event_type event_type,union sctp_subtype subtype,struct sctp_chunk *chunk,unsigned int error)
@@ -1162,7 +1162,7 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc)* If you want to understand all of lksctp, this is a * good place to start. */ -int sctp_do_sm (struct net *net,enum sctp_event event_type, +int sctp_do_sm (struct net *net,enum sctp_event_type event_type,union sctp_subtype subtype,enum sctp_state state,struct sctp_endpoint *ep,struct sctp_association *asoc,void *event_arg,gfp_t gfp)
@@ -1199,7 +1199,7 @@ int sctp_do_sm(struct net *net, enum sctp_event event_type,/***************************************************************** * This the master state function side effect processing function. *****************************************************************/ -static int sctp_side_effects(enum sctp_event event_type, +static int sctp_side_effects(enum sctp_event_type event_type, union sctp_subtype subtype, enum sctp_state state, struct sctp_endpoint *ep,
@@ -1285,7 +1285,7 @@ static int sctp_side_effects(enum sctp_event event_type,********************************************************************/ /* This is the side-effect interpreter. */ -static int sctp_cmd_interpreter(enum sctp_event event_type, +static int sctp_cmd_interpreter(enum sctp_event_type event_type, union sctp_subtype subtype, enum sctp_state state, struct sctp_endpoint *ep,
net/sctp/sm_statetable.c +1 -1
@@ -79,7 +79,7 @@ static const struct sctp_sm_table_entry bug = {const struct sctp_sm_table_entry *sctp_sm_lookup_event (struct net *net, -enum sctp_event event_type, +enum sctp_event_type event_type,enum sctp_state state,union sctp_subtype event_subtype) {
Signature · 1 line
2.1.0
Xin Long
maintainerPATCH v2 4/4 sctp: add sockopt SCTP_EVENT
This patch adds sockopt SCTP_EVENT described in rfc6525#section-6.2. With this sockopt users can subscribe to an event from a specified asoc.
--- include/uapi/linux/sctp.h | 7 ++++ net/sctp/socket.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+)
include/uapi/linux/sctp.h +7 -0
@@ -129,6 +129,7 @@ typedef __s32 sctp_assoc_t;#define SCTP_STREAM_SCHEDULER_VALUE 124#define SCTP_INTERLEAVING_SUPPORTED 125#define SCTP_SENDMSG_CONNECT 126 +#define SCTP_EVENT 127/* PR-SCTP policies */ #define SCTP_PR_SCTP_NONE 0x0000
@@ -1154,6 +1155,12 @@ struct sctp_add_streams {uint16_t sas_outstrms; }; +struct sctp_event { +sctp_assoc_t se_assoc_id; +uint16_t se_type; +uint8_t se_on; +}; +/* SCTP Stream schedulers */ enum sctp_sched_type {SCTP_SS_FCFS ,
net/sctp/socket.c +89 -0
113 lines not on this page · raw message
Signature · 1 line
2.1.0
Re: [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16
In reply to Xin LongQuoted 13 lines · Xin Long
net/sctp/socket.c +4
-0/* Default Peer Address Parameters. These defaults can * be modified via SCTP_PEER_ADDR_PARAMS @@ -5267,14 +5274,24 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,static int sctp_getsockopt_events (struct sock *sk,int len,char __user *optval,int __user *optlen) { +struct sctp_event_subscribe subscribe; +__u8 *sn_type = (__u8 *)&subscribe; +int i; +if (len =0 )return -EINVAL ;
net/sctp/socket.c static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, · line 5291
Quoted 10 lines
net/sctp/socket.c +5
-1if (len >sizeof (struct sctp_event_subscribe )) len =sizeof (struct sctp_event_subscribe );if (put_user (len, optlen))return -EFAULT ; -if (copy_to_user (optval, &sctp_sk (sk)->subscribe, len)) + +for (i =0 ; i <= len; i++) + sn_type[i] =sctp_ulpevent_type_enabled (sctp_sk (sk)->subscribe, +SCTP_SN_TYPE_BASE + i); +
This seems like an off by one error. sctp_event_subscribe has N bytes in it (1 byte for each event), meaning that that events 0-(N-1) are subscribable. Iterating this loop imples that you are going to check N events, overrunning the sctp_event_subscribe struct.
Neil
Quoted 1 line
Xin Long
maintainerRe: [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16
Quoted 21 lines · Neil Horman
Quoted 19 lines · Xin Long
/* Default Peer Address Parameters. These defaults can
* be modified viaSCTP_PEER_ADDR_PARAMSnet/sctp/socket.c +5
-1@@ -5267,14 +5274,24 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,static int sctp_getsockopt_events (struct sock *sk,int len,char __user *optval,int __user *optlen) { +struct sctp_event_subscribe subscribe; +__u8 *sn_type = (__u8 *)&subscribe; +int i; +if (len =0 )return -EINVAL ;if (len >sizeof (struct sctp_event_subscribe )) len =sizeof (struct sctp_event_subscribe );if (put_user (len, optlen))return -EFAULT ; -if (copy_to_user (optval, &sctp_sk (sk)->subscribe, len)) +
Quoted 8 lines
net/sctp/socket.c static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, · line 5291
Quoted 4 lines
net/sctp/socket.c +4
-0+for (i =0 ; i <= len; i++) + sn_type[i] =sctp_ulpevent_type_enabled (sctp_sk (sk)->subscribe, +SCTP_SN_TYPE_BASE + i); +This seems like an off by one error.
sctp_event_subscribehas N bytes in it (1 byte for each event), meaning that that events 0-(N-1) are subscribable. Iterating this loop imples that you are going to check N events, overrunning thesctp_event_subscribestruct.
you're right, thanks.
Quoted 4 lines
Neil
Quoted 1 line