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

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
...@@ -1111,6 +1111,33 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep, ...@@ -1111,6 +1111,33 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep,
return err; 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) /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
* *
* Common routine for handling connect() and sctp_connectx(). * Common routine for handling connect() and sctp_connectx().
...@@ -1119,10 +1146,10 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep, ...@@ -1119,10 +1146,10 @@ static int sctp_connect_new_asoc(struct sctp_endpoint *ep,
static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs,
int addrs_size, int flags, sctp_assoc_t *assoc_id) int addrs_size, int flags, sctp_assoc_t *assoc_id)
{ {
struct sctp_association *old, *asoc;
struct sctp_sock *sp = sctp_sk(sk); struct sctp_sock *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep; struct sctp_endpoint *ep = sp->ep;
struct sctp_transport *transport; struct sctp_transport *transport;
struct sctp_association *asoc;
void *addr_buf = kaddrs; void *addr_buf = kaddrs;
union sctp_addr *daddr; union sctp_addr *daddr;
struct sctp_af *af; struct sctp_af *af;
...@@ -1167,29 +1194,10 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs, ...@@ -1167,29 +1194,10 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs,
if (asoc->peer.port != ntohs(daddr->v4.sin_port)) if (asoc->peer.port != ntohs(daddr->v4.sin_port))
goto out_free; goto out_free;
err = sctp_verify_addr(sk, daddr, af->sockaddr_len); err = sctp_connect_add_peer(asoc, daddr, af->sockaddr_len);
if (err) if (err)
goto out_free; 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; addr_buf += af->sockaddr_len;
walk_size += af->sockaddr_len; walk_size += af->sockaddr_len;
} }
...@@ -1683,8 +1691,6 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, ...@@ -1683,8 +1691,6 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
/* sendv addr list parse */ /* sendv addr list parse */
for_each_cmsghdr(cmsg, cmsgs->addrs_msg) { for_each_cmsghdr(cmsg, cmsgs->addrs_msg) {
struct sctp_transport *transport;
struct sctp_association *old;
union sctp_addr _daddr; union sctp_addr _daddr;
int dlen; int dlen;
...@@ -1718,30 +1724,10 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, ...@@ -1718,30 +1724,10 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
daddr->v6.sin6_port = htons(asoc->peer.port); daddr->v6.sin6_port = htons(asoc->peer.port);
memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen); 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 = sctp_connect_add_peer(asoc, daddr, sizeof(*daddr));
err = -EADDRNOTAVAIL; if (err)
goto free;
}
transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL,
SCTP_UNKNOWN);
if (!transport) {
err = -ENOMEM;
goto free; goto free;
}
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment