diff options
author | Xin Long <lucien.xin@gmail.com> | 2018-11-18 03:08:51 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-11-19 15:25:43 -0500 |
commit | 2cc0eeb67636e0339ad7b6cdfa305f63983642af (patch) | |
tree | 52dd65d8f7d0efc982b5ee829c5eabc9c0d8ef90 | |
parent | f2be6d710d25be7d8d13f49f713d69dea9c71d57 (diff) |
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.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sctp/structs.h | 2 | ||||
-rw-r--r-- | include/net/sctp/ulpevent.h | 39 | ||||
-rw-r--r-- | include/uapi/linux/sctp.h | 6 | ||||
-rw-r--r-- | net/sctp/chunk.c | 4 | ||||
-rw-r--r-- | net/sctp/socket.c | 35 | ||||
-rw-r--r-- | net/sctp/stream_interleave.c | 11 | ||||
-rw-r--r-- | 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 af9d494120ba..bc7808aa2760 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -217,7 +217,7 @@ struct sctp_sock { | |||
217 | * These two structures must be grouped together for the usercopy | 217 | * These two structures must be grouped together for the usercopy |
218 | * whitelist region. | 218 | * whitelist region. |
219 | */ | 219 | */ |
220 | struct sctp_event_subscribe subscribe; | 220 | __u16 subscribe; |
221 | struct sctp_initmsg initmsg; | 221 | struct sctp_initmsg initmsg; |
222 | 222 | ||
223 | int user_frag; | 223 | int user_frag; |
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 51b4e0626c34..bd922a0fe914 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, | |||
164 | 164 | ||
165 | __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event); | 165 | __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event); |
166 | 166 | ||
167 | static inline void sctp_ulpevent_type_set(__u16 *subscribe, | ||
168 | __u16 sn_type, __u8 on) | ||
169 | { | ||
170 | if (sn_type > SCTP_SN_TYPE_MAX) | ||
171 | return; | ||
172 | |||
173 | if (on) | ||
174 | *subscribe |= (1 << (sn_type - SCTP_SN_TYPE_BASE)); | ||
175 | else | ||
176 | *subscribe &= ~(1 << (sn_type - SCTP_SN_TYPE_BASE)); | ||
177 | } | ||
178 | |||
167 | /* Is this event type enabled? */ | 179 | /* Is this event type enabled? */ |
168 | static inline int sctp_ulpevent_type_enabled(__u16 sn_type, | 180 | static inline bool sctp_ulpevent_type_enabled(__u16 subscribe, __u16 sn_type) |
169 | struct sctp_event_subscribe *mask) | ||
170 | { | 181 | { |
171 | int offset = sn_type - SCTP_SN_TYPE_BASE; | 182 | if (sn_type > SCTP_SN_TYPE_MAX) |
172 | char *amask = (char *) mask; | 183 | return false; |
173 | 184 | ||
174 | if (offset >= sizeof(struct sctp_event_subscribe)) | 185 | return subscribe & (1 << (sn_type - SCTP_SN_TYPE_BASE)); |
175 | return 0; | ||
176 | return amask[offset]; | ||
177 | } | 186 | } |
178 | 187 | ||
179 | /* Given an event subscription, is this event enabled? */ | 188 | /* Given an event subscription, is this event enabled? */ |
180 | static inline int sctp_ulpevent_is_enabled(const struct sctp_ulpevent *event, | 189 | static inline bool sctp_ulpevent_is_enabled(const struct sctp_ulpevent *event, |
181 | struct sctp_event_subscribe *mask) | 190 | __u16 subscribe) |
182 | { | 191 | { |
183 | __u16 sn_type; | 192 | __u16 sn_type; |
184 | int enabled = 1; | ||
185 | 193 | ||
186 | if (sctp_ulpevent_is_notification(event)) { | 194 | if (!sctp_ulpevent_is_notification(event)) |
187 | sn_type = sctp_ulpevent_get_notification_type(event); | 195 | return true; |
188 | enabled = sctp_ulpevent_type_enabled(sn_type, mask); | 196 | |
189 | } | 197 | sn_type = sctp_ulpevent_get_notification_type(event); |
190 | return enabled; | 198 | |
199 | return sctp_ulpevent_type_enabled(subscribe, sn_type); | ||
191 | } | 200 | } |
192 | 201 | ||
193 | #endif /* __sctp_ulpevent_h__ */ | 202 | #endif /* __sctp_ulpevent_h__ */ |
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h index c81feb373d3e..66afa5b4ab6b 100644 --- a/include/uapi/linux/sctp.h +++ b/include/uapi/linux/sctp.h | |||
@@ -632,7 +632,9 @@ union sctp_notification { | |||
632 | */ | 632 | */ |
633 | 633 | ||
634 | enum sctp_sn_type { | 634 | enum sctp_sn_type { |
635 | SCTP_SN_TYPE_BASE = (1<<15), | 635 | SCTP_SN_TYPE_BASE = (1<<15), |
636 | SCTP_DATA_IO_EVENT = SCTP_SN_TYPE_BASE, | ||
637 | #define SCTP_DATA_IO_EVENT SCTP_DATA_IO_EVENT | ||
636 | SCTP_ASSOC_CHANGE, | 638 | SCTP_ASSOC_CHANGE, |
637 | #define SCTP_ASSOC_CHANGE SCTP_ASSOC_CHANGE | 639 | #define SCTP_ASSOC_CHANGE SCTP_ASSOC_CHANGE |
638 | SCTP_PEER_ADDR_CHANGE, | 640 | SCTP_PEER_ADDR_CHANGE, |
@@ -657,6 +659,8 @@ enum sctp_sn_type { | |||
657 | #define SCTP_ASSOC_RESET_EVENT SCTP_ASSOC_RESET_EVENT | 659 | #define SCTP_ASSOC_RESET_EVENT SCTP_ASSOC_RESET_EVENT |
658 | SCTP_STREAM_CHANGE_EVENT, | 660 | SCTP_STREAM_CHANGE_EVENT, |
659 | #define SCTP_STREAM_CHANGE_EVENT SCTP_STREAM_CHANGE_EVENT | 661 | #define SCTP_STREAM_CHANGE_EVENT SCTP_STREAM_CHANGE_EVENT |
662 | SCTP_SN_TYPE_MAX = SCTP_STREAM_CHANGE_EVENT, | ||
663 | #define SCTP_SN_TYPE_MAX SCTP_SN_TYPE_MAX | ||
660 | }; | 664 | }; |
661 | 665 | ||
662 | /* Notification error codes used to fill up the error fields in some | 666 | /* 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 ce8087846f05..6c761af960fd 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -109,8 +109,8 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg) | |||
109 | error = asoc->outqueue.error; | 109 | error = asoc->outqueue.error; |
110 | 110 | ||
111 | sp = sctp_sk(asoc->base.sk); | 111 | sp = sctp_sk(asoc->base.sk); |
112 | notify = sctp_ulpevent_type_enabled(SCTP_SEND_FAILED, | 112 | notify = sctp_ulpevent_type_enabled(sp->subscribe, |
113 | &sp->subscribe); | 113 | SCTP_SEND_FAILED); |
114 | } | 114 | } |
115 | 115 | ||
116 | /* Generate a SEND FAILED event only if enabled. */ | 116 | /* Generate a SEND FAILED event only if enabled. */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5299add6d7aa..9d7512958a6a 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, | |||
2230 | if (sp->recvrcvinfo) | 2230 | if (sp->recvrcvinfo) |
2231 | sctp_ulpevent_read_rcvinfo(event, msg); | 2231 | sctp_ulpevent_read_rcvinfo(event, msg); |
2232 | /* Check if we allow SCTP_SNDRCVINFO. */ | 2232 | /* Check if we allow SCTP_SNDRCVINFO. */ |
2233 | if (sp->subscribe.sctp_data_io_event) | 2233 | if (sctp_ulpevent_type_enabled(sp->subscribe, SCTP_DATA_IO_EVENT)) |
2234 | sctp_ulpevent_read_sndrcvinfo(event, msg); | 2234 | sctp_ulpevent_read_sndrcvinfo(event, msg); |
2235 | 2235 | ||
2236 | err = copied; | 2236 | err = copied; |
@@ -2304,21 +2304,28 @@ static int sctp_setsockopt_disable_fragments(struct sock *sk, | |||
2304 | static int sctp_setsockopt_events(struct sock *sk, char __user *optval, | 2304 | static int sctp_setsockopt_events(struct sock *sk, char __user *optval, |
2305 | unsigned int optlen) | 2305 | unsigned int optlen) |
2306 | { | 2306 | { |
2307 | struct sctp_association *asoc; | 2307 | struct sctp_event_subscribe subscribe; |
2308 | struct sctp_ulpevent *event; | 2308 | __u8 *sn_type = (__u8 *)&subscribe; |
2309 | struct sctp_sock *sp = sctp_sk(sk); | ||
2310 | int i; | ||
2309 | 2311 | ||
2310 | if (optlen > sizeof(struct sctp_event_subscribe)) | 2312 | if (optlen > sizeof(struct sctp_event_subscribe)) |
2311 | return -EINVAL; | 2313 | return -EINVAL; |
2312 | if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) | 2314 | |
2315 | if (copy_from_user(&subscribe, optval, optlen)) | ||
2313 | return -EFAULT; | 2316 | return -EFAULT; |
2314 | 2317 | ||
2318 | for (i = 0; i < optlen; i++) | ||
2319 | sctp_ulpevent_type_set(&sp->subscribe, SCTP_SN_TYPE_BASE + i, | ||
2320 | sn_type[i]); | ||
2321 | |||
2315 | /* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, | 2322 | /* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, |
2316 | * if there is no data to be sent or retransmit, the stack will | 2323 | * if there is no data to be sent or retransmit, the stack will |
2317 | * immediately send up this notification. | 2324 | * immediately send up this notification. |
2318 | */ | 2325 | */ |
2319 | if (sctp_ulpevent_type_enabled(SCTP_SENDER_DRY_EVENT, | 2326 | if (sctp_ulpevent_type_enabled(sp->subscribe, SCTP_SENDER_DRY_EVENT)) { |
2320 | &sctp_sk(sk)->subscribe)) { | 2327 | struct sctp_association *asoc = sctp_id2assoc(sk, 0); |
2321 | asoc = sctp_id2assoc(sk, 0); | 2328 | struct sctp_ulpevent *event; |
2322 | 2329 | ||
2323 | if (asoc && sctp_outq_is_empty(&asoc->outqueue)) { | 2330 | if (asoc && sctp_outq_is_empty(&asoc->outqueue)) { |
2324 | event = sctp_ulpevent_make_sender_dry_event(asoc, | 2331 | event = sctp_ulpevent_make_sender_dry_event(asoc, |
@@ -4722,7 +4729,7 @@ static int sctp_init_sock(struct sock *sk) | |||
4722 | /* Initialize default event subscriptions. By default, all the | 4729 | /* Initialize default event subscriptions. By default, all the |
4723 | * options are off. | 4730 | * options are off. |
4724 | */ | 4731 | */ |
4725 | memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe)); | 4732 | sp->subscribe = 0; |
4726 | 4733 | ||
4727 | /* Default Peer Address Parameters. These defaults can | 4734 | /* Default Peer Address Parameters. These defaults can |
4728 | * be modified via SCTP_PEER_ADDR_PARAMS | 4735 | * be modified via SCTP_PEER_ADDR_PARAMS |
@@ -5267,14 +5274,24 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, | |||
5267 | static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, | 5274 | static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, |
5268 | int __user *optlen) | 5275 | int __user *optlen) |
5269 | { | 5276 | { |
5277 | struct sctp_event_subscribe subscribe; | ||
5278 | __u8 *sn_type = (__u8 *)&subscribe; | ||
5279 | int i; | ||
5280 | |||
5270 | if (len == 0) | 5281 | if (len == 0) |
5271 | return -EINVAL; | 5282 | return -EINVAL; |
5272 | if (len > sizeof(struct sctp_event_subscribe)) | 5283 | if (len > sizeof(struct sctp_event_subscribe)) |
5273 | len = sizeof(struct sctp_event_subscribe); | 5284 | len = sizeof(struct sctp_event_subscribe); |
5274 | if (put_user(len, optlen)) | 5285 | if (put_user(len, optlen)) |
5275 | return -EFAULT; | 5286 | return -EFAULT; |
5276 | if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) | 5287 | |
5288 | for (i = 0; i < len; i++) | ||
5289 | sn_type[i] = sctp_ulpevent_type_enabled(sctp_sk(sk)->subscribe, | ||
5290 | SCTP_SN_TYPE_BASE + i); | ||
5291 | |||
5292 | if (copy_to_user(optval, &subscribe, len)) | ||
5277 | return -EFAULT; | 5293 | return -EFAULT; |
5294 | |||
5278 | return 0; | 5295 | return 0; |
5279 | } | 5296 | } |
5280 | 5297 | ||
diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c index 2b499a85db0e..ceef5a3a5aac 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, | |||
503 | sk_incoming_cpu_update(sk); | 503 | sk_incoming_cpu_update(sk); |
504 | } | 504 | } |
505 | 505 | ||
506 | if (!sctp_ulpevent_is_enabled(event, &sp->subscribe)) | 506 | if (!sctp_ulpevent_is_enabled(event, sp->subscribe)) |
507 | goto out_free; | 507 | goto out_free; |
508 | 508 | ||
509 | if (skb_list) | 509 | if (skb_list) |
@@ -992,10 +992,11 @@ static void sctp_intl_stream_abort_pd(struct sctp_ulpq *ulpq, __u16 sid, | |||
992 | __u32 mid, __u16 flags, gfp_t gfp) | 992 | __u32 mid, __u16 flags, gfp_t gfp) |
993 | { | 993 | { |
994 | struct sock *sk = ulpq->asoc->base.sk; | 994 | struct sock *sk = ulpq->asoc->base.sk; |
995 | struct sctp_sock *sp = sctp_sk(sk); | ||
995 | struct sctp_ulpevent *ev = NULL; | 996 | struct sctp_ulpevent *ev = NULL; |
996 | 997 | ||
997 | if (!sctp_ulpevent_type_enabled(SCTP_PARTIAL_DELIVERY_EVENT, | 998 | if (!sctp_ulpevent_type_enabled(sp->subscribe, |
998 | &sctp_sk(sk)->subscribe)) | 999 | SCTP_PARTIAL_DELIVERY_EVENT)) |
999 | return; | 1000 | return; |
1000 | 1001 | ||
1001 | ev = sctp_ulpevent_make_pdapi(ulpq->asoc, SCTP_PARTIAL_DELIVERY_ABORTED, | 1002 | 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, | |||
1003 | if (ev) { | 1004 | if (ev) { |
1004 | __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev)); | 1005 | __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev)); |
1005 | 1006 | ||
1006 | if (!sctp_sk(sk)->data_ready_signalled) { | 1007 | if (!sp->data_ready_signalled) { |
1007 | sctp_sk(sk)->data_ready_signalled = 1; | 1008 | sp->data_ready_signalled = 1; |
1008 | sk->sk_data_ready(sk); | 1009 | sk->sk_data_ready(sk); |
1009 | } | 1010 | } |
1010 | } | 1011 | } |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 331cc734e3db..b36dd9024da3 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) | |||
219 | sk_incoming_cpu_update(sk); | 219 | sk_incoming_cpu_update(sk); |
220 | } | 220 | } |
221 | /* Check if the user wishes to receive this event. */ | 221 | /* Check if the user wishes to receive this event. */ |
222 | if (!sctp_ulpevent_is_enabled(event, &sp->subscribe)) | 222 | if (!sctp_ulpevent_is_enabled(event, sp->subscribe)) |
223 | goto out_free; | 223 | goto out_free; |
224 | 224 | ||
225 | /* If we are in partial delivery mode, post to the lobby until | 225 | /* 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, | |||
1129 | void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) | 1129 | void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) |
1130 | { | 1130 | { |
1131 | struct sctp_ulpevent *ev = NULL; | 1131 | struct sctp_ulpevent *ev = NULL; |
1132 | struct sock *sk; | ||
1133 | struct sctp_sock *sp; | 1132 | struct sctp_sock *sp; |
1133 | struct sock *sk; | ||
1134 | 1134 | ||
1135 | if (!ulpq->pd_mode) | 1135 | if (!ulpq->pd_mode) |
1136 | return; | 1136 | return; |
1137 | 1137 | ||
1138 | sk = ulpq->asoc->base.sk; | 1138 | sk = ulpq->asoc->base.sk; |
1139 | sp = sctp_sk(sk); | 1139 | sp = sctp_sk(sk); |
1140 | if (sctp_ulpevent_type_enabled(SCTP_PARTIAL_DELIVERY_EVENT, | 1140 | if (sctp_ulpevent_type_enabled(sp->subscribe, |
1141 | &sctp_sk(sk)->subscribe)) | 1141 | SCTP_PARTIAL_DELIVERY_EVENT)) |
1142 | ev = sctp_ulpevent_make_pdapi(ulpq->asoc, | 1142 | ev = sctp_ulpevent_make_pdapi(ulpq->asoc, |
1143 | SCTP_PARTIAL_DELIVERY_ABORTED, | 1143 | SCTP_PARTIAL_DELIVERY_ABORTED, |
1144 | 0, 0, 0, gfp); | 1144 | 0, 0, 0, gfp); |