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
129129 #define SCTP_STREAM_SCHEDULER_VALUE 124
130130 #define SCTP_INTERLEAVING_SUPPORTED 125
131131 #define SCTP_SENDMSG_CONNECT 126
132+#define SCTP_EVENT 127
132133
133134 /* PR-SCTP policies */
134135 #define SCTP_PR_SCTP_NONE 0x0000
@@ -1154,6 +1155,12 @@ struct sctp_add_streams { · 1019 unmodified lines
11541155 uint16_t sas_outstrms;
11551156 };
11561157
1158+struct sctp_event {
1159+ sctp_assoc_t se_assoc_id;
1160+ uint16_t se_type;
1161+ uint8_t se_on;
1162+};
1163+
11571164 /* SCTP Stream schedulers */
11581165 enum sctp_sched_type {
11591166 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
42884288 return 0;
42894289 }
42904290
4291+static 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+
4338+out:
4339+ return retval;
4340+}
4341+
42914342 /* API 6.2 setsockopt(), getsockopt()
42924343 *
42934344 * 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
44854536 case SCTP_REUSE_PORT:
44864537 retval = sctp_setsockopt_reuse_port(sk, optval, optlen);
44874538 break;
4539+ case SCTP_EVENT:
4540+ retval = sctp_setsockopt_event(sk, optval, optlen);
4541+ break;
44884542 default:
44894543 retval = -ENOPROTOOPT;
44904544 break;
@@ -7430,6 +7484,37 @@ static int sctp_getsockopt_reuse_port(struct sock *sk, int len, · 2939 unmodified lines
74307484 return 0;
74317485 }
74327486
7487+static 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+
74337518 static int sctp_getsockopt(struct sock *sk, int level, int optname,
74347519 char __user *optval, int __user *optlen)
74357520 {
@@ -7628,6 +7713,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, · 192 unmodified lines
76287713 case SCTP_REUSE_PORT:
76297714 retval = sctp_getsockopt_reuse_port(sk, len, optval, optlen);
76307715 break;
7716+ case SCTP_EVENT:
7717+ retval = sctp_getsockopt_event(sk, len, optval, optlen);
7718+ break;
76317719 default:
76327720 retval = -ENOPROTOOPT;
76337721 break;