Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a64e59c7 authored by Xin Long's avatar Xin Long Committed by David S. Miller
Browse files

sctp: factor out sctp_connect_add_peer



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: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f26f9951
Loading
Loading
Loading
Loading
+31 −45
Original line number Diff line number Diff line
@@ -1111,6 +1111,33 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep,
	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 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep,
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,31 +1724,11 @@ 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;