aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2018-11-18 03:08:51 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-19 15:25:43 -0500
commit2cc0eeb67636e0339ad7b6cdfa305f63983642af (patch)
tree52dd65d8f7d0efc982b5ee829c5eabc9c0d8ef90
parentf2be6d710d25be7d8d13f49f713d69dea9c71d57 (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.h2
-rw-r--r--include/net/sctp/ulpevent.h39
-rw-r--r--include/uapi/linux/sctp.h6
-rw-r--r--net/sctp/chunk.c4
-rw-r--r--net/sctp/socket.c35
-rw-r--r--net/sctp/stream_interleave.c11
-rw-r--r--net/sctp/ulpqueue.c8
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
167static 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? */
168static inline int sctp_ulpevent_type_enabled(__u16 sn_type, 180static 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? */
180static inline int sctp_ulpevent_is_enabled(const struct sctp_ulpevent *event, 189static 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
634enum sctp_sn_type { 634enum 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,
2304static int sctp_setsockopt_events(struct sock *sk, char __user *optval, 2304static 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,
5267static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, 5274static 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,
1129void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) 1129void 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);