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.
Unified · Split
| @@ -129,6 +129,7 @@ typedef __s32 sctp_assoc_t; · 128 unmodified lines | |||
| 129 | #define SCTP_STREAM_SCHEDULER_VALUE 124 | 129 | #define SCTP_STREAM_SCHEDULER_VALUE 124 |
| 130 | #define SCTP_INTERLEAVING_SUPPORTED 125 | 130 | #define SCTP_INTERLEAVING_SUPPORTED 125 |
| 131 | #define SCTP_SENDMSG_CONNECT 126 | 131 | #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 0x0000 | 135 | #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 | ||
| 1158 | struct 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 */ |
| 1158 | enum sctp_sched_type { | 1165 | enum sctp_sched_type { |
| 1159 | SCTP_SS_FCFS, | 1166 | SCTP_SS_FCFS, |
| @@ -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 | ||
| 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(¶m, 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 | |||
| 4291 | /* API 6.2 setsockopt(), getsockopt() | 4342 | /* API 6.2 setsockopt(), getsockopt() |
| 4292 | * | 4343 | * |
| 4293 | * Applications use setsockopt() and getsockopt() to set or retrieve | 4344 | * 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 | ||
| 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(¶m, 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, ¶m, len)) | ||
| 7513 | return -EFAULT; | ||
| 7514 | |||
| 7515 | return 0; | ||
| 7516 | } | ||
| 7517 | |||
| 7433 | static int sctp_getsockopt(struct sock *sk, int level, int optname, | 7518 | static 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; |