History

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.

Xin Long committed 7 years ago

Commit 480ba9c1 parent 88ee48c2 files · +95 −0Browse files

Unified · Split

2 files
  1. include/uapi/linux/sctp.h +7 −0
  2. net/sctp/socket.c +88 −0
include/uapi/linux/sctp.h+7−0
@@ -129,6 +129,7 @@ typedef __s32 sctp_assoc_t; · 128 unmodified lines
129#define SCTP_STREAM_SCHEDULER_VALUE 124129#define SCTP_STREAM_SCHEDULER_VALUE 124
130#define SCTP_INTERLEAVING_SUPPORTED 125130#define SCTP_INTERLEAVING_SUPPORTED 125
131#define SCTP_SENDMSG_CONNECT 126131#define SCTP_SENDMSG_CONNECT 126
132#define SCTP_EVENT 127
132 133
133/* PR-SCTP policies */134/* PR-SCTP policies */
134#define SCTP_PR_SCTP_NONE 0x0000135#define SCTP_PR_SCTP_NONE 0x0000
@@ -1154,6 +1155,12 @@ struct sctp_add_streams { · 1019 unmodified lines
1154 uint16_t sas_outstrms;1155 uint16_t sas_outstrms;
1155};1156};
1156 1157
1158struct sctp_event {
1159 sctp_assoc_t se_assoc_id;
1160 uint16_t se_type;
1161 uint8_t se_on;
1162};
1163
1157/* SCTP Stream schedulers */1164/* SCTP Stream schedulers */
1158enum sctp_sched_type {1165enum sctp_sched_type {
1159 SCTP_SS_FCFS,1166 SCTP_SS_FCFS,
net/sctp/socket.c+88−0
@@ -4288,6 +4288,57 @@ static int sctp_setsockopt_reuse_port(struct sock *sk, char __user *optval, · 4287 unmodified lines
4288 return 0;4288 return 0;
4289}4289}
4290 4290
4291static int sctp_setsockopt_event(struct sock *sk, char __user *optval,
4292 unsigned int optlen)
4293{
4294 struct sctp_association *asoc;
4295 struct sctp_ulpevent *event;
4296 struct sctp_event param;
4297 int retval = 0;
4298
4299 if (optlen < sizeof(param)) {
4300 retval = -EINVAL;
4301 goto out;
4302 }
4303
4304 optlen = sizeof(param);
4305 if (copy_from_user(&param, optval, optlen)) {
4306 retval = -EFAULT;
4307 goto out;
4308 }
4309
4310 if (param.se_type < SCTP_SN_TYPE_BASE ||
4311 param.se_type > SCTP_SN_TYPE_MAX) {
4312 retval = -EINVAL;
4313 goto out;
4314 }
4315
4316 asoc = sctp_id2assoc(sk, param.se_assoc_id);
4317 if (!asoc) {
4318 sctp_ulpevent_type_set(&sctp_sk(sk)->subscribe,
4319 param.se_type, param.se_on);
4320 goto out;
4321 }
4322
4323 sctp_ulpevent_type_set(&asoc->subscribe, param.se_type, param.se_on);
4324
4325 if (param.se_type == SCTP_SENDER_DRY_EVENT && param.se_on) {
4326 if (sctp_outq_is_empty(&asoc->outqueue)) {
4327 event = sctp_ulpevent_make_sender_dry_event(asoc,
4328 GFP_USER | __GFP_NOWARN);
4329 if (!event) {
4330 retval = -ENOMEM;
4331 goto out;
4332 }
4333
4334 asoc->stream.si->enqueue_event(&asoc->ulpq, event);
4335 }
4336 }
4337
4338out:
4339 return retval;
4340}
4341
4291/* API 6.2 setsockopt(), getsockopt()4342/* API 6.2 setsockopt(), getsockopt()
4292 *4343 *
4293 * Applications use setsockopt() and getsockopt() to set or retrieve4344 * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -4485,6 +4536,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, · 191 unmodified lines
4485 case SCTP_REUSE_PORT:4536 case SCTP_REUSE_PORT:
4486 retval = sctp_setsockopt_reuse_port(sk, optval, optlen);4537 retval = sctp_setsockopt_reuse_port(sk, optval, optlen);
4487 break;4538 break;
4539 case SCTP_EVENT:
4540 retval = sctp_setsockopt_event(sk, optval, optlen);
4541 break;
4488 default:4542 default:
4489 retval = -ENOPROTOOPT;4543 retval = -ENOPROTOOPT;
4490 break;4544 break;
@@ -7430,6 +7484,37 @@ static int sctp_getsockopt_reuse_port(struct sock *sk, int len, · 2939 unmodified lines
7430 return 0;7484 return 0;
7431}7485}
7432 7486
7487static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval,
7488 int __user *optlen)
7489{
7490 struct sctp_association *asoc;
7491 struct sctp_event param;
7492 __u16 subscribe;
7493
7494 if (len < sizeof(param))
7495 return -EINVAL;
7496
7497 len = sizeof(param);
7498 if (copy_from_user(&param, optval, len))
7499 return -EFAULT;
7500
7501 if (param.se_type < SCTP_SN_TYPE_BASE ||
7502 param.se_type > SCTP_SN_TYPE_MAX)
7503 return -EINVAL;
7504
7505 asoc = sctp_id2assoc(sk, param.se_assoc_id);
7506 subscribe = asoc ? asoc->subscribe : sctp_sk(sk)->subscribe;
7507 param.se_on = sctp_ulpevent_type_enabled(subscribe, param.se_type);
7508
7509 if (put_user(len, optlen))
7510 return -EFAULT;
7511
7512 if (copy_to_user(optval, &param, len))
7513 return -EFAULT;
7514
7515 return 0;
7516}
7517
7433static int sctp_getsockopt(struct sock *sk, int level, int optname,7518static int sctp_getsockopt(struct sock *sk, int level, int optname,
7434 char __user *optval, int __user *optlen)7519 char __user *optval, int __user *optlen)
7435{7520{
@@ -7628,6 +7713,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, · 192 unmodified lines
7628 case SCTP_REUSE_PORT:7713 case SCTP_REUSE_PORT:
7629 retval = sctp_getsockopt_reuse_port(sk, len, optval, optlen);7714 retval = sctp_getsockopt_reuse_port(sk, len, optval, optlen);
7630 break;7715 break;
7716 case SCTP_EVENT:
7717 retval = sctp_getsockopt_event(sk, len, optval, optlen);
7718 break;
7631 default:7719 default:
7632 retval = -ENOPROTOOPT;7720 retval = -ENOPROTOOPT;
7633 break;7721 break;