sctp: factor out sctp_connect_add_peer
authorXin Long <lucien.xin@gmail.com>
Tue, 30 Jul 2019 12:38:23 +0000 (20:38 +0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 30 Jul 2019 21:18:14 +0000 (14:18 -0700)
In this function factored out from sctp_sendmsg_new_asoc() and
__sctp_connect(), it adds a peer with the other addr into the
asoc after this asoc is created with the 1st addr.

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

index 6f77853..2f7e88c 100644 (file)
@@ -1111,6 +1111,33 @@ free:
        return err;
 }
 
+static int sctp_connect_add_peer(struct sctp_association *asoc,
+                                union sctp_addr *daddr, int addr_len)
+{
+       struct sctp_endpoint *ep = asoc->ep;
+       struct sctp_association *old;
+       struct sctp_transport *t;
+       int err;
+
+       err = sctp_verify_addr(ep->base.sk, daddr, addr_len);
+       if (err)
+               return err;
+
+       old = sctp_endpoint_lookup_assoc(ep, daddr, &t);
+       if (old && old != asoc)
+               return old->state >= SCTP_STATE_ESTABLISHED ? -EISCONN
+                                                           : -EALREADY;
+
+       if (sctp_endpoint_is_peeled_off(ep, daddr))
+               return -EADDRNOTAVAIL;
+
+       t = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL, SCTP_UNKNOWN);
+       if (!t)
+               return -ENOMEM;
+
+       return 0;
+}
+
 /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
  *
  * Common routine for handling connect() and sctp_connectx().
@@ -1119,10 +1146,10 @@ free:
 static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs,
                          int addrs_size, int flags, sctp_assoc_t *assoc_id)
 {
-       struct sctp_association *old, *asoc;
        struct sctp_sock *sp = sctp_sk(sk);
        struct sctp_endpoint *ep = sp->ep;
        struct sctp_transport *transport;
+       struct sctp_association *asoc;
        void *addr_buf = kaddrs;
        union sctp_addr *daddr;
        struct sctp_af *af;
@@ -1167,29 +1194,10 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs,
                if (asoc->peer.port != ntohs(daddr->v4.sin_port))
                        goto out_free;
 
-               err = sctp_verify_addr(sk, daddr, af->sockaddr_len);
+               err = sctp_connect_add_peer(asoc, daddr, af->sockaddr_len);
                if (err)
                        goto out_free;
 
-               old = sctp_endpoint_lookup_assoc(ep, daddr, &transport);
-               if (old && old != asoc) {
-                       err = old->state >= SCTP_STATE_ESTABLISHED ? -EISCONN
-                                                                  : -EALREADY;
-                       goto out_free;
-               }
-
-               if (sctp_endpoint_is_peeled_off(ep, daddr)) {
-                       err = -EADDRNOTAVAIL;
-                       goto out_free;
-               }
-
-               transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL,
-                                               SCTP_UNKNOWN);
-               if (!transport) {
-                       err = -ENOMEM;
-                       goto out_free;
-               }
-
                addr_buf  += af->sockaddr_len;
                walk_size += af->sockaddr_len;
        }
@@ -1683,8 +1691,6 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
 
        /* sendv addr list parse */
        for_each_cmsghdr(cmsg, cmsgs->addrs_msg) {
-               struct sctp_transport *transport;
-               struct sctp_association *old;
                union sctp_addr _daddr;
                int dlen;
 
@@ -1718,30 +1724,10 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
                        daddr->v6.sin6_port = htons(asoc->peer.port);
                        memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen);
                }
-               err = sctp_verify_addr(sk, daddr, sizeof(*daddr));
-               if (err)
-                       goto free;
-
-               old = sctp_endpoint_lookup_assoc(ep, daddr, &transport);
-               if (old && old != asoc) {
-                       if (old->state >= SCTP_STATE_ESTABLISHED)
-                               err = -EISCONN;
-                       else
-                               err = -EALREADY;
-                       goto free;
-               }
 
-               if (sctp_endpoint_is_peeled_off(ep, daddr)) {
-                       err = -EADDRNOTAVAIL;
-                       goto free;
-               }
-
-               transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL,
-                                               SCTP_UNKNOWN);
-               if (!transport) {
-                       err = -ENOMEM;
+               err = sctp_connect_add_peer(asoc, daddr, sizeof(*daddr));
+               if (err)
                        goto free;
-               }
        }
 
        return 0;