From patchwork Thu Mar 1 15:05:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xin Long X-Patchwork-Id: 879900 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Bld8cxI/"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zsbND3H3yz9s1S for ; Fri, 2 Mar 2018 02:05:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1031691AbeCAPFq (ORCPT ); Thu, 1 Mar 2018 10:05:46 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:41555 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031556AbeCAPFo (ORCPT ); Thu, 1 Mar 2018 10:05:44 -0500 Received: by mail-pf0-f195.google.com with SMTP id f80so2545831pfa.8; Thu, 01 Mar 2018 07:05:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=8EnZbDKs1autJ0Y3lJXQ0AQoJ23ykdmEvbyMnACfQXg=; b=Bld8cxI/Eodyzdqa6KUM1MKHlKFmcjF57o8X7ggdH3zo0rmIPDv6xuwsah+7PYKaN9 ZmOtQOQn9eFm1YH1bzkcQUQ5bsYyVM+Gvg5KRGWOyH3X1IYAMggmUJGXixePyo62HyK5 8Gd7/X9uVBHwAX0oXES0wsg4xeaOCCA/4bbmmh0owk2WDQO1qrD1npjF7niDkJSxBDs8 qZRlwP5rb9oYfU2AYpBiV0IqJTcs/mjSaVxrM5KZbnqjwaMD2nDCbaIllwIFNnl2fmoy iACCSJa8NCKj1/HU7uElzIL/0Rl5uW/aW0F5/yot03kKJ/QP36PAVgmMBUt9MM55UgB/ M/sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=8EnZbDKs1autJ0Y3lJXQ0AQoJ23ykdmEvbyMnACfQXg=; b=b/BduYnGrtvmlrb6nOSy1qphr7E5S+ZxZjLuYnIG0y+ZNVKKvbFP14gzSO828oztQ9 dL39VlzYSy6MhcuWsjRcvG1qYWU4JDpvpPh/DlzYpGnRlW4j/AcP1K5aNA5rJn+anFfE QjkEspqKk2RWqn2vWOkJILOs4hmOLlpfDizNHkeV1ceOGecG+EAozAaBrfVNrZZJ+9pf n705XsxZ9S2FzQ9CJyL8UMUSNelWVozl0b+4JqMHESVH/+9LRCWf5NsPtXbsksNqtx5G g93JFUjGkTXfYpQyfjEra2mKcI3weilCUykgRM6+mFlTugk2rw54UKIpN0L38IWQFl7h 3LNQ== X-Gm-Message-State: APf1xPCob06Kk+nQc8NTj2AhFksXa2r7rJg+e3Yhve1h0iIaBGCqBX+J USklVWZ99SmgqcKKIWvVYRAk8BHy X-Google-Smtp-Source: AG47ELsdeflCechNAeeNmCRfNjah+1Z9DtG6OOdCQXPEA9Kc8hMKpAuk11oJzb4wwVtFqoboP5f4fA== X-Received: by 10.99.52.203 with SMTP id b194mr1834251pga.349.1519916743637; Thu, 01 Mar 2018 07:05:43 -0800 (PST) Received: from localhost ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id i186sm9453004pfg.25.2018.03.01.07.05.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 01 Mar 2018 07:05:43 -0800 (PST) From: Xin Long To: network dev , linux-sctp@vger.kernel.org Cc: Marcelo Ricardo Leitner , Neil Horman , davem@davemloft.net Subject: [PATCH net-next 2/9] sctp: factor out sctp_sendmsg_new_asoc from sctp_sendmsg Date: Thu, 1 Mar 2018 23:05:11 +0800 Message-Id: X-Mailer: git-send-email 2.1.0 In-Reply-To: <1dbdb93e27d978da9fe883dbe72db78fbb58ec95.1519916440.git.lucien.xin@gmail.com> References: <1dbdb93e27d978da9fe883dbe72db78fbb58ec95.1519916440.git.lucien.xin@gmail.com> In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch is to move the codes for creating a new asoc if no asoc was found into sctp_sendmsg_new_asoc. Signed-off-by: Xin Long --- net/sctp/socket.c | 201 +++++++++++++++++++++++------------------------------- 1 file changed, 86 insertions(+), 115 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 183129e..58bb55d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1606,6 +1606,87 @@ static int sctp_error(struct sock *sk, int flags, int err) static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs); +static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, + struct sctp_cmsgs *cmsgs, + union sctp_addr *daddr, + struct sctp_transport **tp) +{ + struct sctp_endpoint *ep = sctp_sk(sk)->ep; + struct net *net = sock_net(sk); + struct sctp_association *asoc; + enum sctp_scope scope; + int err = -EINVAL; + + *tp = NULL; + + if (sflags & (SCTP_EOF | SCTP_ABORT)) + return -EINVAL; + + if (sctp_style(sk, TCP) && (sctp_sstate(sk, ESTABLISHED) || + sctp_sstate(sk, CLOSING))) + return -EADDRNOTAVAIL; + + if (sctp_endpoint_is_peeled_off(ep, daddr)) + return -EADDRNOTAVAIL; + + if (!ep->base.bind_addr.port) { + if (sctp_autobind(sk)) + return -EAGAIN; + } else { + if (ep->base.bind_addr.port < inet_prot_sock(net) && + !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) + return -EACCES; + } + + scope = sctp_scope(daddr); + + asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); + if (!asoc) + return -ENOMEM; + + if (sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL) < 0) { + err = -ENOMEM; + goto free; + } + + if (cmsgs->init) { + struct sctp_initmsg *init = cmsgs->init; + + if (init->sinit_num_ostreams) { + __u16 outcnt = init->sinit_num_ostreams; + + asoc->c.sinit_num_ostreams = outcnt; + /* outcnt has been changed, need to re-init stream */ + err = sctp_stream_init(&asoc->stream, outcnt, 0, + GFP_KERNEL); + if (err) + goto free; + } + + if (init->sinit_max_instreams) + asoc->c.sinit_max_instreams = init->sinit_max_instreams; + + if (init->sinit_max_attempts) + asoc->max_init_attempts = init->sinit_max_attempts; + + if (init->sinit_max_init_timeo) + asoc->max_init_timeo = + msecs_to_jiffies(init->sinit_max_init_timeo); + } + + *tp = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN); + if (!*tp) { + err = -ENOMEM; + goto free; + } + + return 0; + +free: + sctp_association_free(asoc); + return err; +} + static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, struct msghdr *msg, size_t msg_len, struct sctp_transport *transport, @@ -1715,7 +1796,6 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) struct sctp_initmsg *sinit; sctp_assoc_t associd = 0; struct sctp_cmsgs cmsgs = { NULL }; - enum sctp_scope scope; bool fill_sinfo_ttl = false; __u16 sinfo_flags = 0; int err; @@ -1817,20 +1897,6 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) if (msg_name) { /* Look for a matching association on the endpoint. */ asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); - - /* If we could not find a matching association on the - * endpoint, make sure that it is not a TCP-style - * socket that already has an association or there is - * no peeled-off association on another socket. - */ - if (!asoc && - ((sctp_style(sk, TCP) && - (sctp_sstate(sk, ESTABLISHED) || - sctp_sstate(sk, CLOSING))) || - sctp_endpoint_is_peeled_off(ep, &to))) { - err = -EADDRNOTAVAIL; - goto out_unlock; - } } else { asoc = sctp_id2assoc(sk, associd); if (!asoc) { @@ -1879,108 +1945,13 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) /* Do we need to create the association? */ if (!asoc) { - pr_debug("%s: there is no association yet\n", __func__); - - if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) { - err = -EINVAL; - goto out_unlock; - } - - /* Check for invalid stream against the stream counts, - * either the default or the user specified stream counts. - */ - if (sinfo) { - if (!sinit || !sinit->sinit_num_ostreams) { - /* Check against the defaults. */ - if (sinfo->sinfo_stream >= - sp->initmsg.sinit_num_ostreams) { - err = -EINVAL; - goto out_unlock; - } - } else { - /* Check against the requested. */ - if (sinfo->sinfo_stream >= - sinit->sinit_num_ostreams) { - err = -EINVAL; - goto out_unlock; - } - } - } - - /* - * API 3.1.2 bind() - UDP Style Syntax - * If a bind() or sctp_bindx() is not called prior to a - * sendmsg() call that initiates a new association, the - * system picks an ephemeral port and will choose an address - * set equivalent to binding with a wildcard address. - */ - if (!ep->base.bind_addr.port) { - if (sctp_autobind(sk)) { - err = -EAGAIN; - goto out_unlock; - } - } else { - /* - * If an unprivileged user inherits a one-to-many - * style socket with open associations on a privileged - * port, it MAY be permitted to accept new associations, - * but it SHOULD NOT be permitted to open new - * associations. - */ - if (ep->base.bind_addr.port < inet_prot_sock(net) && - !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) { - err = -EACCES; - goto out_unlock; - } - } - - scope = sctp_scope(&to); - new_asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); - if (!new_asoc) { - err = -ENOMEM; + err = sctp_sendmsg_new_asoc(sk, sinfo_flags, &cmsgs, &to, + &transport); + if (err) goto out_unlock; - } - asoc = new_asoc; - err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); - if (err < 0) { - err = -ENOMEM; - goto out_free; - } - - /* If the SCTP_INIT ancillary data is specified, set all - * the association init values accordingly. - */ - if (sinit) { - if (sinit->sinit_num_ostreams) { - __u16 outcnt = sinit->sinit_num_ostreams; - - asoc->c.sinit_num_ostreams = outcnt; - /* outcnt has been changed, so re-init stream */ - err = sctp_stream_init(&asoc->stream, outcnt, 0, - GFP_KERNEL); - if (err) - goto out_free; - } - if (sinit->sinit_max_instreams) { - asoc->c.sinit_max_instreams = - sinit->sinit_max_instreams; - } - if (sinit->sinit_max_attempts) { - asoc->max_init_attempts - = sinit->sinit_max_attempts; - } - if (sinit->sinit_max_init_timeo) { - asoc->max_init_timeo = - msecs_to_jiffies(sinit->sinit_max_init_timeo); - } - } - /* Prime the peer's transport structures. */ - transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); - if (!transport) { - err = -ENOMEM; - goto out_free; - } + asoc = transport->asoc; + new_asoc = asoc; } /* ASSERT: we have a valid association at this point. */