]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/sctp/socket.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[mirror_ubuntu-artful-kernel.git] / net / sctp / socket.c
index 318c6786d6539a301ac7b76d82a49a1af3818d10..5fc7122c76deb86c798059e62c72be33cf1e455d 100644 (file)
@@ -235,8 +235,12 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
                                              sctp_assoc_t id)
 {
        struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
-       struct sctp_transport *transport;
+       struct sctp_af *af = sctp_get_af_specific(addr->ss_family);
        union sctp_addr *laddr = (union sctp_addr *)addr;
+       struct sctp_transport *transport;
+
+       if (sctp_verify_addr(sk, laddr, af->sockaddr_len))
+               return NULL;
 
        addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
                                               laddr,
@@ -360,7 +364,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
                }
        }
 
-       if (snum && snum < PROT_SOCK &&
+       if (snum && snum < inet_prot_sock(net) &&
            !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
                return -EACCES;
 
@@ -1152,8 +1156,10 @@ static int __sctp_connect(struct sock *sk,
                                 * accept new associations, but it SHOULD NOT
                                 * be permitted to open new associations.
                                 */
-                               if (ep->base.bind_addr.port < PROT_SOCK &&
-                                   !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
+                               if (ep->base.bind_addr.port <
+                                   inet_prot_sock(net) &&
+                                   !ns_capable(net->user_ns,
+                                   CAP_NET_BIND_SERVICE)) {
                                        err = -EACCES;
                                        goto out_free;
                                }
@@ -1818,7 +1824,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
                         * but it SHOULD NOT be permitted to open new
                         * associations.
                         */
-                       if (ep->base.bind_addr.port < PROT_SOCK &&
+                       if (ep->base.bind_addr.port < inet_prot_sock(net) &&
                            !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
                                err = -EACCES;
                                goto out_unlock;
@@ -2430,7 +2436,6 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
                        sctp_assoc_sync_pmtu(sctp_opt2sk(sp), asoc);
                } else if (asoc) {
                        asoc->pathmtu = params->spp_pathmtu;
-                       sctp_frag_point(asoc, params->spp_pathmtu);
                } else {
                        sp->pathmtu = params->spp_pathmtu;
                }
@@ -3751,6 +3756,68 @@ out:
        return retval;
 }
 
+static int sctp_setsockopt_enable_strreset(struct sock *sk,
+                                          char __user *optval,
+                                          unsigned int optlen)
+{
+       struct sctp_assoc_value params;
+       struct sctp_association *asoc;
+       int retval = -EINVAL;
+
+       if (optlen != sizeof(params))
+               goto out;
+
+       if (copy_from_user(&params, optval, optlen)) {
+               retval = -EFAULT;
+               goto out;
+       }
+
+       if (params.assoc_value & (~SCTP_ENABLE_STRRESET_MASK))
+               goto out;
+
+       asoc = sctp_id2assoc(sk, params.assoc_id);
+       if (asoc) {
+               asoc->strreset_enable = params.assoc_value;
+       } else if (!params.assoc_id) {
+               struct sctp_sock *sp = sctp_sk(sk);
+
+               sp->ep->strreset_enable = params.assoc_value;
+       } else {
+               goto out;
+       }
+
+       retval = 0;
+
+out:
+       return retval;
+}
+
+static int sctp_setsockopt_reset_streams(struct sock *sk,
+                                        char __user *optval,
+                                        unsigned int optlen)
+{
+       struct sctp_reset_streams *params;
+       struct sctp_association *asoc;
+       int retval = -EINVAL;
+
+       if (optlen < sizeof(struct sctp_reset_streams))
+               return -EINVAL;
+
+       params = memdup_user(optval, optlen);
+       if (IS_ERR(params))
+               return PTR_ERR(params);
+
+       asoc = sctp_id2assoc(sk, params->srs_assoc_id);
+       if (!asoc)
+               goto out;
+
+       retval = sctp_send_reset_streams(asoc, params);
+
+out:
+       kfree(params);
+       return retval;
+}
+
 /* API 6.2 setsockopt(), getsockopt()
  *
  * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3917,6 +3984,12 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
        case SCTP_DEFAULT_PRINFO:
                retval = sctp_setsockopt_default_prinfo(sk, optval, optlen);
                break;
+       case SCTP_ENABLE_STREAM_RESET:
+               retval = sctp_setsockopt_enable_strreset(sk, optval, optlen);
+               break;
+       case SCTP_RESET_STREAMS:
+               retval = sctp_setsockopt_reset_streams(sk, optval, optlen);
+               break;
        default:
                retval = -ENOPROTOOPT;
                break;
@@ -6401,6 +6474,47 @@ out:
        return retval;
 }
 
+static int sctp_getsockopt_enable_strreset(struct sock *sk, int len,
+                                          char __user *optval,
+                                          int __user *optlen)
+{
+       struct sctp_assoc_value params;
+       struct sctp_association *asoc;
+       int retval = -EFAULT;
+
+       if (len < sizeof(params)) {
+               retval = -EINVAL;
+               goto out;
+       }
+
+       len = sizeof(params);
+       if (copy_from_user(&params, optval, len))
+               goto out;
+
+       asoc = sctp_id2assoc(sk, params.assoc_id);
+       if (asoc) {
+               params.assoc_value = asoc->strreset_enable;
+       } else if (!params.assoc_id) {
+               struct sctp_sock *sp = sctp_sk(sk);
+
+               params.assoc_value = sp->ep->strreset_enable;
+       } else {
+               retval = -EINVAL;
+               goto out;
+       }
+
+       if (put_user(len, optlen))
+               goto out;
+
+       if (copy_to_user(optval, &params, len))
+               goto out;
+
+       retval = 0;
+
+out:
+       return retval;
+}
+
 static int sctp_getsockopt(struct sock *sk, int level, int optname,
                           char __user *optval, int __user *optlen)
 {
@@ -6568,6 +6682,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
                retval = sctp_getsockopt_pr_assocstatus(sk, len, optval,
                                                        optlen);
                break;
+       case SCTP_ENABLE_STREAM_RESET:
+               retval = sctp_getsockopt_enable_strreset(sk, len, optval,
+                                                        optlen);
+               break;
        default:
                retval = -ENOPROTOOPT;
                break;