Skip to content

Commit 2c0dbaa

Browse files
lxindavem330
authored andcommitted
sctp: add support for SCTP_DSTADDRV4/6 Information for sendmsg
This patch is to add support for Destination IPv4/6 Address options for sendmsg, as described in section 5.3.9/10 of RFC6458. With this option, you can provide more than one destination addrs to sendmsg when creating asoc, like sctp_connectx. It's also a necessary send info for sctp_sendv. Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent ed63afb commit 2c0dbaa

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

include/net/sctp/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,6 +2113,7 @@ struct sctp_cmsgs {
21132113
struct sctp_sndrcvinfo *srinfo;
21142114
struct sctp_sndinfo *sinfo;
21152115
struct sctp_prinfo *prinfo;
2116+
struct msghdr *addrs_msg;
21162117
};
21172118

21182119
/* Structure for tracking memory objects */

include/uapi/linux/sctp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@ typedef enum sctp_cmsg_type {
308308
#define SCTP_NXTINFO SCTP_NXTINFO
309309
SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */
310310
#define SCTP_PRINFO SCTP_PRINFO
311+
SCTP_AUTHINFO, /* 5.3.8 SCTP AUTH Information Structure (RESERVED) */
312+
#define SCTP_AUTHINFO SCTP_AUTHINFO
313+
SCTP_DSTADDRV4, /* 5.3.9 SCTP Destination IPv4 Address Structure */
314+
#define SCTP_DSTADDRV4 SCTP_DSTADDRV4
315+
SCTP_DSTADDRV6, /* 5.3.10 SCTP Destination IPv6 Address Structure */
316+
#define SCTP_DSTADDRV6 SCTP_DSTADDRV6
311317
} sctp_cmsg_t;
312318

313319
/*

net/sctp/socket.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
16761676
struct net *net = sock_net(sk);
16771677
struct sctp_association *asoc;
16781678
enum sctp_scope scope;
1679+
struct cmsghdr *cmsg;
16791680
int err = -EINVAL;
16801681

16811682
*tp = NULL;
@@ -1741,6 +1742,67 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,
17411742
goto free;
17421743
}
17431744

1745+
if (!cmsgs->addrs_msg)
1746+
return 0;
1747+
1748+
/* sendv addr list parse */
1749+
for_each_cmsghdr(cmsg, cmsgs->addrs_msg) {
1750+
struct sctp_transport *transport;
1751+
struct sctp_association *old;
1752+
union sctp_addr _daddr;
1753+
int dlen;
1754+
1755+
if (cmsg->cmsg_level != IPPROTO_SCTP ||
1756+
(cmsg->cmsg_type != SCTP_DSTADDRV4 &&
1757+
cmsg->cmsg_type != SCTP_DSTADDRV6))
1758+
continue;
1759+
1760+
daddr = &_daddr;
1761+
memset(daddr, 0, sizeof(*daddr));
1762+
dlen = cmsg->cmsg_len - sizeof(struct cmsghdr);
1763+
if (cmsg->cmsg_type == SCTP_DSTADDRV4) {
1764+
if (dlen < sizeof(struct in_addr))
1765+
goto free;
1766+
1767+
dlen = sizeof(struct in_addr);
1768+
daddr->v4.sin_family = AF_INET;
1769+
daddr->v4.sin_port = htons(asoc->peer.port);
1770+
memcpy(&daddr->v4.sin_addr, CMSG_DATA(cmsg), dlen);
1771+
} else {
1772+
if (dlen < sizeof(struct in6_addr))
1773+
goto free;
1774+
1775+
dlen = sizeof(struct in6_addr);
1776+
daddr->v6.sin6_family = AF_INET6;
1777+
daddr->v6.sin6_port = htons(asoc->peer.port);
1778+
memcpy(&daddr->v6.sin6_addr, CMSG_DATA(cmsg), dlen);
1779+
}
1780+
err = sctp_verify_addr(sk, daddr, sizeof(*daddr));
1781+
if (err)
1782+
goto free;
1783+
1784+
old = sctp_endpoint_lookup_assoc(ep, daddr, &transport);
1785+
if (old && old != asoc) {
1786+
if (old->state >= SCTP_STATE_ESTABLISHED)
1787+
err = -EISCONN;
1788+
else
1789+
err = -EALREADY;
1790+
goto free;
1791+
}
1792+
1793+
if (sctp_endpoint_is_peeled_off(ep, daddr)) {
1794+
err = -EADDRNOTAVAIL;
1795+
goto free;
1796+
}
1797+
1798+
transport = sctp_assoc_add_peer(asoc, daddr, GFP_KERNEL,
1799+
SCTP_UNKNOWN);
1800+
if (!transport) {
1801+
err = -ENOMEM;
1802+
goto free;
1803+
}
1804+
}
1805+
17441806
return 0;
17451807

17461808
free:
@@ -7778,6 +7840,21 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)
77787840
if (cmsgs->prinfo->pr_policy == SCTP_PR_SCTP_NONE)
77797841
cmsgs->prinfo->pr_value = 0;
77807842
break;
7843+
case SCTP_DSTADDRV4:
7844+
case SCTP_DSTADDRV6:
7845+
/* SCTP Socket API Extension
7846+
* 5.3.9/10 SCTP Destination IPv4/6 Address Structure (SCTP_DSTADDRV4/6)
7847+
*
7848+
* This cmsghdr structure specifies SCTP options for sendmsg().
7849+
*
7850+
* cmsg_level cmsg_type cmsg_data[]
7851+
* ------------ ------------ ---------------------
7852+
* IPPROTO_SCTP SCTP_DSTADDRV4 struct in_addr
7853+
* ------------ ------------ ---------------------
7854+
* IPPROTO_SCTP SCTP_DSTADDRV6 struct in6_addr
7855+
*/
7856+
cmsgs->addrs_msg = my_msg;
7857+
break;
77817858
default:
77827859
return -EINVAL;
77837860
}

0 commit comments

Comments
 (0)