]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sctp/socket.c
sctp: use SCTP_FUTURE_ASSOC and add SCTP_CURRENT_ASSOC for SCTP_CONTEXT sockopt
[linux.git] / net / sctp / socket.c
index 3d3b4f0b1dbbdc95d24a4194d93cd0942ea4633e..36387be9b66ace81e2217961722c82025da9755c 100644 (file)
@@ -3067,20 +3067,37 @@ static int sctp_setsockopt_default_sndinfo(struct sock *sk,
                return -EINVAL;
 
        asoc = sctp_id2assoc(sk, info.snd_assoc_id);
-       if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP))
+       if (!asoc && info.snd_assoc_id > SCTP_ALL_ASSOC &&
+           sctp_style(sk, UDP))
                return -EINVAL;
+
        if (asoc) {
                asoc->default_stream = info.snd_sid;
                asoc->default_flags = info.snd_flags;
                asoc->default_ppid = info.snd_ppid;
                asoc->default_context = info.snd_context;
-       } else {
+
+               return 0;
+       }
+
+       if (info.snd_assoc_id == SCTP_FUTURE_ASSOC ||
+           info.snd_assoc_id == SCTP_ALL_ASSOC) {
                sp->default_stream = info.snd_sid;
                sp->default_flags = info.snd_flags;
                sp->default_ppid = info.snd_ppid;
                sp->default_context = info.snd_context;
        }
 
+       if (info.snd_assoc_id == SCTP_CURRENT_ASSOC ||
+           info.snd_assoc_id == SCTP_ALL_ASSOC) {
+               list_for_each_entry(asoc, &sp->ep->asocs, asocs) {
+                       asoc->default_stream = info.snd_sid;
+                       asoc->default_flags = info.snd_flags;
+                       asoc->default_ppid = info.snd_ppid;
+                       asoc->default_context = info.snd_context;
+               }
+       }
+
        return 0;
 }
 
@@ -3493,8 +3510,8 @@ static int sctp_setsockopt_adaptation_layer(struct sock *sk, char __user *optval
 static int sctp_setsockopt_context(struct sock *sk, char __user *optval,
                                   unsigned int optlen)
 {
+       struct sctp_sock *sp = sctp_sk(sk);
        struct sctp_assoc_value params;
-       struct sctp_sock *sp;
        struct sctp_association *asoc;
 
        if (optlen != sizeof(struct sctp_assoc_value))
@@ -3502,17 +3519,26 @@ static int sctp_setsockopt_context(struct sock *sk, char __user *optval,
        if (copy_from_user(&params, optval, optlen))
                return -EFAULT;
 
-       sp = sctp_sk(sk);
+       asoc = sctp_id2assoc(sk, params.assoc_id);
+       if (!asoc && params.assoc_id > SCTP_ALL_ASSOC &&
+           sctp_style(sk, UDP))
+               return -EINVAL;
 
-       if (params.assoc_id != 0) {
-               asoc = sctp_id2assoc(sk, params.assoc_id);
-               if (!asoc)
-                       return -EINVAL;
+       if (asoc) {
                asoc->default_rcv_context = params.assoc_value;
-       } else {
-               sp->default_rcv_context = params.assoc_value;
+
+               return 0;
        }
 
+       if (params.assoc_id == SCTP_FUTURE_ASSOC ||
+           params.assoc_id == SCTP_ALL_ASSOC)
+               sp->default_rcv_context = params.assoc_value;
+
+       if (params.assoc_id == SCTP_CURRENT_ASSOC ||
+           params.assoc_id == SCTP_ALL_ASSOC)
+               list_for_each_entry(asoc, &sp->ep->asocs, asocs)
+                       asoc->default_rcv_context = params.assoc_value;
+
        return 0;
 }
 
@@ -6287,8 +6313,10 @@ static int sctp_getsockopt_default_sndinfo(struct sock *sk, int len,
                return -EFAULT;
 
        asoc = sctp_id2assoc(sk, info.snd_assoc_id);
-       if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP))
+       if (!asoc && info.snd_assoc_id != SCTP_FUTURE_ASSOC &&
+           sctp_style(sk, UDP))
                return -EINVAL;
+
        if (asoc) {
                info.snd_sid = asoc->default_stream;
                info.snd_flags = asoc->default_flags;
@@ -6498,7 +6526,6 @@ static int sctp_getsockopt_context(struct sock *sk, int len,
                                   char __user *optval, int __user *optlen)
 {
        struct sctp_assoc_value params;
-       struct sctp_sock *sp;
        struct sctp_association *asoc;
 
        if (len < sizeof(struct sctp_assoc_value))
@@ -6509,16 +6536,13 @@ static int sctp_getsockopt_context(struct sock *sk, int len,
        if (copy_from_user(&params, optval, len))
                return -EFAULT;
 
-       sp = sctp_sk(sk);
+       asoc = sctp_id2assoc(sk, params.assoc_id);
+       if (!asoc && params.assoc_id != SCTP_FUTURE_ASSOC &&
+           sctp_style(sk, UDP))
+               return -EINVAL;
 
-       if (params.assoc_id != 0) {
-               asoc = sctp_id2assoc(sk, params.assoc_id);
-               if (!asoc)
-                       return -EINVAL;
-               params.assoc_value = asoc->default_rcv_context;
-       } else {
-               params.assoc_value = sp->default_rcv_context;
-       }
+       params.assoc_value = asoc ? asoc->default_rcv_context
+                                 : sctp_sk(sk)->default_rcv_context;
 
        if (put_user(len, optlen))
                return -EFAULT;