OSDN Git Service

sctp: use SCTP_FUTURE_ASSOC and add SCTP_CURRENT_ASSOC for SCTP_DEFAULT_PRINFO sockopt
authorXin Long <lucien.xin@gmail.com>
Mon, 28 Jan 2019 07:08:43 +0000 (15:08 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 30 Jan 2019 08:44:08 +0000 (00:44 -0800)
Check with SCTP_ALL_ASSOC instead in sctp_setsockopt_default_prinfo and
check with SCTP_FUTURE_ASSOC instead in sctp_getsockopt_default_prinfo,
it's compatible with 0.

SCTP_CURRENT_ASSOC is supported for SCTP_DEFAULT_PRINFO in this patch.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sctp/socket.c

index 3a954ac..2f70171 100644 (file)
@@ -4136,6 +4136,7 @@ static int sctp_setsockopt_default_prinfo(struct sock *sk,
                                          char __user *optval,
                                          unsigned int optlen)
 {
+       struct sctp_sock *sp = sctp_sk(sk);
        struct sctp_default_prinfo info;
        struct sctp_association *asoc;
        int retval = -EINVAL;
@@ -4155,19 +4156,31 @@ static int sctp_setsockopt_default_prinfo(struct sock *sk,
                info.pr_value = 0;
 
        asoc = sctp_id2assoc(sk, info.pr_assoc_id);
+       if (!asoc && info.pr_assoc_id > SCTP_ALL_ASSOC &&
+           sctp_style(sk, UDP))
+               goto out;
+
+       retval = 0;
+
        if (asoc) {
                SCTP_PR_SET_POLICY(asoc->default_flags, info.pr_policy);
                asoc->default_timetolive = info.pr_value;
-       } else if (!info.pr_assoc_id) {
-               struct sctp_sock *sp = sctp_sk(sk);
+               goto out;
+       }
 
+       if (info.pr_assoc_id == SCTP_FUTURE_ASSOC ||
+           info.pr_assoc_id == SCTP_ALL_ASSOC) {
                SCTP_PR_SET_POLICY(sp->default_flags, info.pr_policy);
                sp->default_timetolive = info.pr_value;
-       } else {
-               goto out;
        }
 
-       retval = 0;
+       if (info.pr_assoc_id == SCTP_CURRENT_ASSOC ||
+           info.pr_assoc_id == SCTP_ALL_ASSOC) {
+               list_for_each_entry(asoc, &sp->ep->asocs, asocs) {
+                       SCTP_PR_SET_POLICY(asoc->default_flags, info.pr_policy);
+                       asoc->default_timetolive = info.pr_value;
+               }
+       }
 
 out:
        return retval;
@@ -7288,17 +7301,20 @@ static int sctp_getsockopt_default_prinfo(struct sock *sk, int len,
                goto out;
 
        asoc = sctp_id2assoc(sk, info.pr_assoc_id);
+       if (!asoc && info.pr_assoc_id != SCTP_FUTURE_ASSOC &&
+           sctp_style(sk, UDP)) {
+               retval = -EINVAL;
+               goto out;
+       }
+
        if (asoc) {
                info.pr_policy = SCTP_PR_POLICY(asoc->default_flags);
                info.pr_value = asoc->default_timetolive;
-       } else if (!info.pr_assoc_id) {
+       } else {
                struct sctp_sock *sp = sctp_sk(sk);
 
                info.pr_policy = SCTP_PR_POLICY(sp->default_flags);
                info.pr_value = sp->default_timetolive;
-       } else {
-               retval = -EINVAL;
-               goto out;
        }
 
        if (put_user(len, optlen))