* [PATCHv2 net-next 0/4] sctp: add subscribe per asoc and sockopt SCTP_EVENT @ 2018-11-13 6:24 ` Xin Long 0 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem 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(-) -- 2.1.0 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 0/4] sctp: add subscribe per asoc and sockopt SCTP_EVENT @ 2018-11-13 6:24 ` Xin Long 0 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem 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(-) -- 2.1.0 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 2018-11-13 6:24 ` Xin Long @ 2018-11-13 6:24 ` Xin Long -1 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem 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. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- 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(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index af9d494..bc7808a 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -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; diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 51b4e06..bd922a0 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -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__ */ diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index c81feb3..66afa5b 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -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 diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index ce80878..6c761af 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -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. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5299add..48e0b45 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -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; } diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c index 2b499a8..ceef5a3 100644 --- a/net/sctp/stream_interleave.c +++ b/net/sctp/stream_interleave.c @@ -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); } } diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 331cc73..b36dd90 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -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); -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 @ 2018-11-13 6:24 ` Xin Long 0 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem 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. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- 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(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index af9d494..bc7808a 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -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; diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 51b4e06..bd922a0 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -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__ */ diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index c81feb3..66afa5b 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -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 diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index ce80878..6c761af 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -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. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5299add..48e0b45 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -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; } diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c index 2b499a8..ceef5a3 100644 --- a/net/sctp/stream_interleave.c +++ b/net/sctp/stream_interleave.c @@ -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); } } diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 331cc73..b36dd90 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -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); -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 2/4] sctp: add subscribe per asoc 2018-11-13 6:24 ` Xin Long @ 2018-11-13 6:24 ` Xin Long -1 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem The member subscribe should be per asoc, so that sockopt SCTP_EVENT in the next patch can subscribe a event from one asoc only. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- 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(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index bc7808a..7eaa294 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -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]; }; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 6a28b96..685c7ef 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -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; diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 6c761af..0b203b8 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -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); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 48e0b45..789008d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -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); diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c index ceef5a3..a6bf215 100644 --- a/net/sctp/stream_interleave.c +++ b/net/sctp/stream_interleave.c @@ -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) { diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index b36dd90..5dde921 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -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, -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 2/4] sctp: add subscribe per asoc @ 2018-11-13 6:24 ` Xin Long 0 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem The member subscribe should be per asoc, so that sockopt SCTP_EVENT in the next patch can subscribe a event from one asoc only. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- 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(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index bc7808a..7eaa294 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -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]; }; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 6a28b96..685c7ef 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -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; diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 6c761af..0b203b8 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -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); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 48e0b45..789008d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -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); diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c index ceef5a3..a6bf215 100644 --- a/net/sctp/stream_interleave.c +++ b/net/sctp/stream_interleave.c @@ -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) { diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index b36dd90..5dde921 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -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, -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 3/4] sctp: rename enum sctp_event to sctp_event_type 2018-11-13 6:24 ` Xin Long @ 2018-11-13 6:24 ` Xin Long -1 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem sctp_event is a structure name defined in RFC for sockopt SCTP_EVENT. To avoid the conflict, rename it. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- 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(-) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 8dadc74..4588bdc 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -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, diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 9e3d327..24825a8 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -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); diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index c0817f7a..a8c4c33 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -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; \ \ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 85d3930..1d143bc 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -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, diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 691d9dc..d239b94 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -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) { -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 3/4] sctp: rename enum sctp_event to sctp_event_type @ 2018-11-13 6:24 ` Xin Long 0 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem sctp_event is a structure name defined in RFC for sockopt SCTP_EVENT. To avoid the conflict, rename it. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- 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(-) diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 8dadc74..4588bdc 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -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, diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 9e3d327..24825a8 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -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); diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index c0817f7a..a8c4c33 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -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; \ \ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 85d3930..1d143bc 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -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, diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 691d9dc..d239b94 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -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) { -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 4/4] sctp: add sockopt SCTP_EVENT 2018-11-13 6:24 ` Xin Long @ 2018-11-13 6:24 ` Xin Long -1 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem 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. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/uapi/linux/sctp.h | 7 ++++ net/sctp/socket.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index 66afa5b..d584073 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -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, diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 789008d..1451211 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4288,6 +4288,57 @@ static int sctp_setsockopt_reuse_port(struct sock *sk, char __user *optval, return 0; } +static int sctp_setsockopt_event(struct sock *sk, char __user *optval, + unsigned int optlen) +{ + struct sctp_association *asoc; + struct sctp_ulpevent *event; + struct sctp_event param; + int retval = 0; + + if (optlen < sizeof(param)) { + retval = -EINVAL; + goto out; + } + + optlen = sizeof(param); + if (copy_from_user(¶m, optval, optlen)) { + retval = -EFAULT; + goto out; + } + + if (param.se_type < SCTP_SN_TYPE_BASE || + param.se_type > SCTP_SN_TYPE_MAX) { + retval = -EINVAL; + goto out; + } + + asoc = sctp_id2assoc(sk, param.se_assoc_id); + if (!asoc) { + sctp_ulpevent_type_set(&sctp_sk(sk)->subscribe, + param.se_type, param.se_on); + goto out; + } + + sctp_ulpevent_type_set(&asoc->subscribe, param.se_type, param.se_on); + + if (param.se_type == SCTP_SENDER_DRY_EVENT && param.se_on) { + if (sctp_outq_is_empty(&asoc->outqueue)) { + event = sctp_ulpevent_make_sender_dry_event(asoc, + GFP_USER | __GFP_NOWARN); + if (!event) { + retval = -ENOMEM; + goto out; + } + + asoc->stream.si->enqueue_event(&asoc->ulpq, event); + } + } + +out: + return retval; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -4485,6 +4536,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_REUSE_PORT: retval = sctp_setsockopt_reuse_port(sk, optval, optlen); break; + case SCTP_EVENT: + retval = sctp_setsockopt_event(sk, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; @@ -7430,6 +7484,38 @@ static int sctp_getsockopt_reuse_port(struct sock *sk, int len, return 0; } +static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval, + int __user *optlen) +{ + struct sctp_association *asoc; + struct sctp_event param; + __u16 subscribe; + + if (len < sizeof(param)) + return -EINVAL; + + len = sizeof(param); + if (copy_from_user(¶m, optval, len)) + return -EFAULT; + + if (param.se_type < SCTP_SN_TYPE_BASE || + param.se_type > SCTP_SN_TYPE_MAX) + return -EINVAL; + + asoc = sctp_id2assoc(sk, param.se_assoc_id); + subscribe = asoc ? asoc->subscribe : sctp_sk(sk)->subscribe; + param.se_on = sctp_ulpevent_type_enabled(subscribe, param.se_type); + + if (put_user(len, optlen)) + return -EFAULT; + + if (copy_to_user(optval, ¶m, len)) + return -EFAULT; + + return 0; +} + + static int sctp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -7628,6 +7714,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, case SCTP_REUSE_PORT: retval = sctp_getsockopt_reuse_port(sk, len, optval, optlen); break; + case SCTP_EVENT: + retval = sctp_getsockopt_event(sk, len, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCHv2 net-next 4/4] sctp: add sockopt SCTP_EVENT @ 2018-11-13 6:24 ` Xin Long 0 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-13 6:24 UTC (permalink / raw) To: network dev, linux-sctp; +Cc: Marcelo Ricardo Leitner, Neil Horman, davem 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. Signed-off-by: Xin Long <lucien.xin@gmail.com> --- include/uapi/linux/sctp.h | 7 ++++ net/sctp/socket.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index 66afa5b..d584073 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h @@ -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, diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 789008d..1451211 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4288,6 +4288,57 @@ static int sctp_setsockopt_reuse_port(struct sock *sk, char __user *optval, return 0; } +static int sctp_setsockopt_event(struct sock *sk, char __user *optval, + unsigned int optlen) +{ + struct sctp_association *asoc; + struct sctp_ulpevent *event; + struct sctp_event param; + int retval = 0; + + if (optlen < sizeof(param)) { + retval = -EINVAL; + goto out; + } + + optlen = sizeof(param); + if (copy_from_user(¶m, optval, optlen)) { + retval = -EFAULT; + goto out; + } + + if (param.se_type < SCTP_SN_TYPE_BASE || + param.se_type > SCTP_SN_TYPE_MAX) { + retval = -EINVAL; + goto out; + } + + asoc = sctp_id2assoc(sk, param.se_assoc_id); + if (!asoc) { + sctp_ulpevent_type_set(&sctp_sk(sk)->subscribe, + param.se_type, param.se_on); + goto out; + } + + sctp_ulpevent_type_set(&asoc->subscribe, param.se_type, param.se_on); + + if (param.se_type = SCTP_SENDER_DRY_EVENT && param.se_on) { + if (sctp_outq_is_empty(&asoc->outqueue)) { + event = sctp_ulpevent_make_sender_dry_event(asoc, + GFP_USER | __GFP_NOWARN); + if (!event) { + retval = -ENOMEM; + goto out; + } + + asoc->stream.si->enqueue_event(&asoc->ulpq, event); + } + } + +out: + return retval; +} + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -4485,6 +4536,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_REUSE_PORT: retval = sctp_setsockopt_reuse_port(sk, optval, optlen); break; + case SCTP_EVENT: + retval = sctp_setsockopt_event(sk, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; @@ -7430,6 +7484,38 @@ static int sctp_getsockopt_reuse_port(struct sock *sk, int len, return 0; } +static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval, + int __user *optlen) +{ + struct sctp_association *asoc; + struct sctp_event param; + __u16 subscribe; + + if (len < sizeof(param)) + return -EINVAL; + + len = sizeof(param); + if (copy_from_user(¶m, optval, len)) + return -EFAULT; + + if (param.se_type < SCTP_SN_TYPE_BASE || + param.se_type > SCTP_SN_TYPE_MAX) + return -EINVAL; + + asoc = sctp_id2assoc(sk, param.se_assoc_id); + subscribe = asoc ? asoc->subscribe : sctp_sk(sk)->subscribe; + param.se_on = sctp_ulpevent_type_enabled(subscribe, param.se_type); + + if (put_user(len, optlen)) + return -EFAULT; + + if (copy_to_user(optval, ¶m, len)) + return -EFAULT; + + return 0; +} + + static int sctp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -7628,6 +7714,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, case SCTP_REUSE_PORT: retval = sctp_getsockopt_reuse_port(sk, len, optval, optlen); break; + case SCTP_EVENT: + retval = sctp_getsockopt_event(sk, len, optval, optlen); + break; default: retval = -ENOPROTOOPT; break; -- 2.1.0 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 2018-11-13 6:24 ` Xin Long @ 2018-11-13 17:15 ` Neil Horman -1 siblings, 0 replies; 14+ messages in thread From: Neil Horman @ 2018-11-13 17:15 UTC (permalink / raw) To: Xin Long; +Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, davem On Tue, Nov 13, 2018 at 02:24:53PM +0800, Xin Long wrote: > > /* 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); > + 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 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 @ 2018-11-13 17:15 ` Neil Horman 0 siblings, 0 replies; 14+ messages in thread From: Neil Horman @ 2018-11-13 17:15 UTC (permalink / raw) To: Xin Long; +Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, davem On Tue, Nov 13, 2018 at 02:24:53PM +0800, Xin Long wrote: > > /* 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); > + 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 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 2018-11-13 17:15 ` Neil Horman @ 2018-11-14 15:11 ` Xin Long -1 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-14 15:11 UTC (permalink / raw) To: Neil Horman; +Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, davem On Wed, Nov 14, 2018 at 2:16 AM Neil Horman <nhorman@tuxdriver.com> wrote: > > On Tue, Nov 13, 2018 at 02:24:53PM +0800, Xin Long wrote: > > > > /* 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); > > + > 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. you're right, thanks. > > Neil > > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 @ 2018-11-14 15:11 ` Xin Long 0 siblings, 0 replies; 14+ messages in thread From: Xin Long @ 2018-11-14 15:11 UTC (permalink / raw) To: Neil Horman; +Cc: network dev, linux-sctp, Marcelo Ricardo Leitner, davem On Wed, Nov 14, 2018 at 2:16 AM Neil Horman <nhorman@tuxdriver.com> wrote: > > On Tue, Nov 13, 2018 at 02:24:53PM +0800, Xin Long wrote: > > > > /* 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); > > + > 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. you're right, thanks. > > Neil > > > ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2018-11-15 1:15 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-11-13 6:24 [PATCHv2 net-next 0/4] sctp: add subscribe per asoc and sockopt SCTP_EVENT Xin Long 2018-11-13 6:24 ` Xin Long 2018-11-13 6:24 ` [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 Xin Long 2018-11-13 6:24 ` Xin Long 2018-11-13 6:24 ` [PATCHv2 net-next 2/4] sctp: add subscribe per asoc Xin Long 2018-11-13 6:24 ` Xin Long 2018-11-13 6:24 ` [PATCHv2 net-next 3/4] sctp: rename enum sctp_event to sctp_event_type Xin Long 2018-11-13 6:24 ` Xin Long 2018-11-13 6:24 ` [PATCHv2 net-next 4/4] sctp: add sockopt SCTP_EVENT Xin Long 2018-11-13 6:24 ` Xin Long 2018-11-13 17:15 ` [PATCHv2 net-next 1/4] sctp: define subscribe in sctp_sock as __u16 Neil Horman 2018-11-13 17:15 ` Neil Horman 2018-11-14 15:11 ` Xin Long 2018-11-14 15:11 ` Xin Long
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.