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: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f26f995122
commit
a64e59c72c
@ -1111,6 +1111,33 @@ free:
|
|||||||
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 @@ free:
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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));
|
|
||||||
|
err = sctp_connect_add_peer(asoc, daddr, sizeof(*daddr));
|
||||||
if (err)
|
if (err)
|
||||||
goto free;
|
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;
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user