|
79 | 79 | #include <net/sock.h>
|
80 | 80 | #include <net/sctp/sctp.h>
|
81 | 81 | #include <net/sctp/sm.h>
|
| 82 | +#include <net/sctp/stream_sched.h> |
82 | 83 |
|
83 | 84 | /* Forward declarations for internal helper functions. */
|
84 | 85 | static int sctp_writeable(struct sock *sk);
|
@@ -3914,6 +3915,36 @@ static int sctp_setsockopt_add_streams(struct sock *sk,
|
3914 | 3915 | return retval;
|
3915 | 3916 | }
|
3916 | 3917 |
|
| 3918 | +static int sctp_setsockopt_scheduler(struct sock *sk, |
| 3919 | + char __user *optval, |
| 3920 | + unsigned int optlen) |
| 3921 | +{ |
| 3922 | + struct sctp_association *asoc; |
| 3923 | + struct sctp_assoc_value params; |
| 3924 | + int retval = -EINVAL; |
| 3925 | + |
| 3926 | + if (optlen < sizeof(params)) |
| 3927 | + goto out; |
| 3928 | + |
| 3929 | + optlen = sizeof(params); |
| 3930 | + if (copy_from_user(¶ms, optval, optlen)) { |
| 3931 | + retval = -EFAULT; |
| 3932 | + goto out; |
| 3933 | + } |
| 3934 | + |
| 3935 | + if (params.assoc_value > SCTP_SS_MAX) |
| 3936 | + goto out; |
| 3937 | + |
| 3938 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
| 3939 | + if (!asoc) |
| 3940 | + goto out; |
| 3941 | + |
| 3942 | + retval = sctp_sched_set_sched(asoc, params.assoc_value); |
| 3943 | + |
| 3944 | +out: |
| 3945 | + return retval; |
| 3946 | +} |
| 3947 | + |
3917 | 3948 | /* API 6.2 setsockopt(), getsockopt()
|
3918 | 3949 | *
|
3919 | 3950 | * Applications use setsockopt() and getsockopt() to set or retrieve
|
@@ -4095,6 +4126,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
|
4095 | 4126 | case SCTP_ADD_STREAMS:
|
4096 | 4127 | retval = sctp_setsockopt_add_streams(sk, optval, optlen);
|
4097 | 4128 | break;
|
| 4129 | + case SCTP_STREAM_SCHEDULER: |
| 4130 | + retval = sctp_setsockopt_scheduler(sk, optval, optlen); |
| 4131 | + break; |
4098 | 4132 | default:
|
4099 | 4133 | retval = -ENOPROTOOPT;
|
4100 | 4134 | break;
|
@@ -6793,6 +6827,43 @@ static int sctp_getsockopt_enable_strreset(struct sock *sk, int len,
|
6793 | 6827 | return retval;
|
6794 | 6828 | }
|
6795 | 6829 |
|
| 6830 | +static int sctp_getsockopt_scheduler(struct sock *sk, int len, |
| 6831 | + char __user *optval, |
| 6832 | + int __user *optlen) |
| 6833 | +{ |
| 6834 | + struct sctp_assoc_value params; |
| 6835 | + struct sctp_association *asoc; |
| 6836 | + int retval = -EFAULT; |
| 6837 | + |
| 6838 | + if (len < sizeof(params)) { |
| 6839 | + retval = -EINVAL; |
| 6840 | + goto out; |
| 6841 | + } |
| 6842 | + |
| 6843 | + len = sizeof(params); |
| 6844 | + if (copy_from_user(¶ms, optval, len)) |
| 6845 | + goto out; |
| 6846 | + |
| 6847 | + asoc = sctp_id2assoc(sk, params.assoc_id); |
| 6848 | + if (!asoc) { |
| 6849 | + retval = -EINVAL; |
| 6850 | + goto out; |
| 6851 | + } |
| 6852 | + |
| 6853 | + params.assoc_value = sctp_sched_get_sched(asoc); |
| 6854 | + |
| 6855 | + if (put_user(len, optlen)) |
| 6856 | + goto out; |
| 6857 | + |
| 6858 | + if (copy_to_user(optval, ¶ms, len)) |
| 6859 | + goto out; |
| 6860 | + |
| 6861 | + retval = 0; |
| 6862 | + |
| 6863 | +out: |
| 6864 | + return retval; |
| 6865 | +} |
| 6866 | + |
6796 | 6867 | static int sctp_getsockopt(struct sock *sk, int level, int optname,
|
6797 | 6868 | char __user *optval, int __user *optlen)
|
6798 | 6869 | {
|
@@ -6975,6 +7046,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
|
6975 | 7046 | retval = sctp_getsockopt_enable_strreset(sk, len, optval,
|
6976 | 7047 | optlen);
|
6977 | 7048 | break;
|
| 7049 | + case SCTP_STREAM_SCHEDULER: |
| 7050 | + retval = sctp_getsockopt_scheduler(sk, len, optval, |
| 7051 | + optlen); |
| 7052 | + break; |
6978 | 7053 | default:
|
6979 | 7054 | retval = -ENOPROTOOPT;
|
6980 | 7055 | break;
|
|
0 commit comments