sctp: add support for some msg_control options from RFC6458
Subsystems (3)
Xin Long
maintainercover sctp: add support for some msg_control options from RFC6458
This patchset is to add support for 3 msg_control options described in RFC6458:
5.3.7. SCTP PR-SCTP Information Structure (SCTP_PRINFO) 5.3.9. SCTP Destination IPv4 Address Structure (SCTP_DSTADDRV4) 5.3.10. SCTP Destination IPv6 Address Structure (SCTP_DSTADDRV6)
one send flag described in RFC6458:
SCTP_SENDALL: This flag, if set, will cause a one-to-many style socket to send the message to all associations that are currently established on this socket. For the one-to- one style socket, this flag has no effect.
Note there is another msg_control option:
5.3.8. SCTP AUTH Information Structure (SCTP_AUTHINFO)
It's a little complicated, I will post it in another patchset after this.
Xin Long (3):
sctp: add support for PR-SCTP Information for sendmsg
sctp: add support for SCTP_DSTADDRV4/6 Information for sendmsg
sctp: add support for snd flag SCTP_SENDALL process in sendmsg
include/net/sctp/structs.h | 2 + include/uapi/linux/sctp.h | 23 ++++++++ net/sctp/socket.c | 143 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 163 insertions(+), 5 deletions(-)
Signature · 1 line
2.1.0
Xin Long
maintainerPATCH 1/3 sctp: add support for PR-SCTP Information for sendmsg
This patch is to add support for PR-SCTP Information for sendmsg, as described in section 5.3.7 of RFC6458.
With this option, you can specify pr_policy and pr_value for user data in sendmsg.
It's also a necessary send info for sctp_sendv.
--- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 15 +++++++++++++++ net/sctp/socket.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-)
include/net/sctp/structs.h +1 -0
@@ -2112,6 +2112,7 @@ struct sctp_cmsgs {struct sctp_initmsg *init;struct sctp_sndrcvinfo *srinfo;struct sctp_sndinfo *sinfo; +struct sctp_prinfo *prinfo; };/* Structure for tracking memory objects */
include/uapi/linux/sctp.h +15 -0
@@ -260,6 +260,19 @@ struct sctp_nxtinfo {sctp_assoc_t nxt_assoc_id; }; +/* 5.3.7 SCTP PR-SCTP Information Structure (SCTP_PRINFO) +* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ ------------------- +* IPPROTO_SCTP SCTP_PRINFO struct sctp_prinfo +*/ +struct sctp_prinfo { +__u16 pr_policy; +__u32 pr_value; +}; +/* * sinfo_flags: 16 bits (unsigned integer) *
@@ -293,6 +306,8 @@ typedef enum sctp_cmsg_type {#define SCTP_RCVINFO SCTP_RCVINFO SCTP_NXTINFO, /* 5.3.6 SCTP Next Receive Information Structure */#define SCTP_NXTINFO SCTP_NXTINFO + SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */ +#define SCTP_PRINFO SCTP_PRINFO } sctp_cmsg_t;/*
net/sctp/socket.c +30 -1
@@ -1644,6 +1644,12 @@ static int sctp_sendmsg_parse(struct sock *sk, struct sctp_cmsgs *cmsgs, srinfo->sinfo_assoc_id = cmsgs->sinfo->snd_assoc_id; } +if (cmsgs->prinfo) { + srinfo->sinfo_timetolive = cmsgs->prinfo->pr_value; +SCTP_PR_SET_POLICY (srinfo->sinfo_flags, + cmsgs->prinfo->pr_policy); + } + sflags = srinfo->sinfo_flags;if (!sflags && msg_len)return 0 ;
@@ -1901,9 +1907,12 @@ static void sctp_sendmsg_update_sinfo(struct sctp_association *asoc, sinfo->sinfo_ppid = asoc->default_ppid; sinfo->sinfo_context = asoc->default_context; sinfo->sinfo_assoc_id =sctp_assoc2id (asoc); + +if (!cmsgs->prinfo) + sinfo->sinfo_flags = asoc->default_flags; } -if (!cmsgs->srinfo) +if (!cmsgs->srinfo && !cmsgs->prinfo) sinfo->sinfo_timetolive = asoc->default_timetolive; }
@@ -7749,6 +7758,26 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs) SCTP_ABORT | SCTP_EOF))return -EINVAL ;break ; +case SCTP_PRINFO : +/* SCTP Socket API Extension +* 5.3.7 SCTP PR-SCTP Information Structure (SCTP_PRINFO) +* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_PRINFO struct sctp_prinfo +*/ +if (cmsg->cmsg_len !=CMSG_LEN (sizeof (struct sctp_prinfo ))) +return -EINVAL ; + + cmsgs->prinfo =CMSG_DATA (cmsg); +if (cmsgs->prinfo->pr_policy & ~SCTP_PR_SCTP_MASK ) +return -EINVAL ; + +if (cmsgs->prinfo->pr_policy =SCTP_PR_SCTP_NONE ) + cmsgs->prinfo->pr_value =0 ; +break ;default :return -EINVAL ; }
Signature · 1 line
2.1.0
Xin Long
maintainerPATCH 2/3 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.
--- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 6 ++++ net/sctp/socket.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+)
include/net/sctp/structs.h +1 -0
@@ -2113,6 +2113,7 @@ struct sctp_cmsgs {struct sctp_sndrcvinfo *srinfo;struct sctp_sndinfo *sinfo;struct sctp_prinfo *prinfo; +struct msghdr *addrs_msg; };/* Structure for tracking memory objects */
include/uapi/linux/sctp.h +6 -0
@@ -308,6 +308,12 @@ typedef enum sctp_cmsg_type {#define SCTP_NXTINFO SCTP_NXTINFO SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */#define SCTP_PRINFO SCTP_PRINFO + SCTP_AUTHINFO, /* 5.3.8 SCTP AUTH Information Structure (RESERVED) */ +#define SCTP_AUTHINFO SCTP_AUTHINFO + SCTP_DSTADDRV4, /* 5.3.9 SCTP Destination IPv4 Address Structure */ +#define SCTP_DSTADDRV4 SCTP_DSTADDRV4 + SCTP_DSTADDRV6, /* 5.3.10 SCTP Destination IPv6 Address Structure */ +#define SCTP_DSTADDRV6 SCTP_DSTADDRV6 } sctp_cmsg_t;/*
net/sctp/socket.c +77 -0
95 lines not on this page · raw message
Signature · 1 line
2.1.0
Xin Long
maintainerPATCH 3/3 sctp: add support for snd flag SCTP_SENDALL process in sendmsg
This patch is to add support for snd flag SCTP_SENDALL process in sendmsg, as described in section 5.3.4 of RFC6458.
With this flag, you can send the same data to all the asocs of this sk once.
--- include/uapi/linux/sctp.h | 2 ++ net/sctp/socket.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-)
include/uapi/linux/sctp.h +2 -0
@@ -284,6 +284,8 @@ enum sctp_sinfo_flags {SCTP_ADDR_OVER = (1 <<1 ),/* Override the primary destination. */ SCTP_ABORT = (1 <<2 ),/* Send an ABORT message to the peer. */ SCTP_SACK_IMMEDIATELY = (1 <<3 ),/* SACK should be sent without delay. */ +/* 2 bits here have been used by SCTP_PR_SCTP_MASK */ +SCTP_SENDALL = (1 <<6 ),SCTP_NOTIFICATION =MSG_NOTIFICATION ,/* Next message is not user msg but notification. */ SCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. */ };
net/sctp/socket.c +31 -4
@@ -1820,6 +1820,10 @@ static int sctp_sendmsg_check_sflags(struct sctp_association *asoc,if (sctp_state (asoc,CLOSED ) &&sctp_style (sk,TCP ))return -EPIPE ; +if ((sflags &SCTP_SENDALL ) &&sctp_style (sk,UDP ) && + !sctp_state (asoc,ESTABLISHED )) +return 0 ; +if (sflags &SCTP_EOF ) {pr_debug ("%s: shutting down association:%p\n" , __func__, asoc);sctp_primitive_SHUTDOWN (net, asoc,NULL );
@@ -2007,6 +2011,29 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)lock_sock (sk); +/* SCTP_SENDALL process */ +if ((sflags &SCTP_SENDALL ) &&sctp_style (sk,UDP )) { +list_for_each_entry (asoc, &ep->asocs, asocs) { + err =sctp_sendmsg_check_sflags (asoc, sflags, msg, + msg_len); +if (err =0 ) +continue ; +if (err <0 ) + goto out_unlock; + +sctp_sendmsg_update_sinfo (asoc, sinfo, &cmsgs); + + err =sctp_sendmsg_to_asoc (asoc, msg, msg_len, +NULL , sinfo); +if (err <0 ) + goto out_unlock; + +iov_iter_revert (&msg->msg_iter, err); + } + + goto out_unlock; + } +/* Get and check or create asoc */ if (daddr) { asoc =sctp_endpoint_lookup_assoc (ep, daddr, &transport);
@@ -7792,8 +7819,8 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->srinfo->sinfo_flags & ~(SCTP_UNORDERED |SCTP_ADDR_OVER | -SCTP_SACK_IMMEDIATELY |SCTP_PR_SCTP_MASK | -SCTP_ABORT |SCTP_EOF )) +SCTP_SACK_IMMEDIATELY |SCTP_SENDALL | +SCTP_PR_SCTP_MASK |SCTP_ABORT |SCTP_EOF ))return -EINVAL ;break ;
@@ -7816,8 +7843,8 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->sinfo->snd_flags & ~(SCTP_UNORDERED |SCTP_ADDR_OVER | -SCTP_SACK_IMMEDIATELY |SCTP_PR_SCTP_MASK | -SCTP_ABORT |SCTP_EOF )) +SCTP_SACK_IMMEDIATELY |SCTP_SENDALL | +SCTP_PR_SCTP_MASK |SCTP_ABORT |SCTP_EOF ))return -EINVAL ;break ;case SCTP_PRINFO :
Signature · 1 line
2.1.0
Re: [PATCH net-next 3/3] sctp: add support for snd flag SCTP_SENDALL process in sendmsg
Quoted 7 lines · Xin Long
This patch is to add support for snd flag
SCTP_SENDALLprocess in sendmsg, as described in section 5.3.4 of RFC6458.With this flag, you can send the same data to all the asocs of this sk once.
Signed-off-by Xin Long <[email protected]>
Quoted 88 lines
--- include/uapi/linux/sctp.h | 2 ++ net/sctp/socket.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-)include/uapi/linux/sctp.h +2
-0@@ -284,6 +284,8 @@ enum sctp_sinfo_flags {SCTP_ADDR_OVER = (1 <<1 ),/* Override the primary destination. */ SCTP_ABORT = (1 <<2 ),/* Send an ABORT message to the peer. */ SCTP_SACK_IMMEDIATELY = (1 <<3 ),/* SACK should be sent without delay. */ +/* 2 bits here have been used by SCTP_PR_SCTP_MASK */ +SCTP_SENDALL = (1 <<6 ),SCTP_NOTIFICATION =MSG_NOTIFICATION ,/* Next message is not user msg but notification. */ SCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. */ };net/sctp/socket.c +31
-4@@ -1820,6 +1820,10 @@ static int sctp_sendmsg_check_sflags(struct sctp_association *asoc,if (sctp_state (asoc,CLOSED ) &&sctp_style (sk,TCP ))return -EPIPE ; +if ((sflags &SCTP_SENDALL ) &&sctp_style (sk,UDP ) && + !sctp_state (asoc,ESTABLISHED )) +return 0 ; +if (sflags &SCTP_EOF ) {pr_debug ("%s: shutting down association:%p\n" , __func__, asoc);sctp_primitive_SHUTDOWN (net, asoc,NULL );@@ -2007,6 +2011,29 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)lock_sock (sk); +/* SCTP_SENDALL process */ +if ((sflags &SCTP_SENDALL ) &&sctp_style (sk,UDP )) { +list_for_each_entry (asoc, &ep->asocs, asocs) { + err =sctp_sendmsg_check_sflags (asoc, sflags, msg, + msg_len); +if (err =0 ) +continue ; +if (err <0 ) + goto out_unlock; + +sctp_sendmsg_update_sinfo (asoc, sinfo, &cmsgs); + + err =sctp_sendmsg_to_asoc (asoc, msg, msg_len, +NULL , sinfo); +if (err <0 ) + goto out_unlock; + +iov_iter_revert (&msg->msg_iter, err); + } + + goto out_unlock; + } +/* Get and check or create asoc */ if (daddr) { asoc =sctp_endpoint_lookup_assoc (ep, daddr, &transport);@@ -7792,8 +7819,8 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->srinfo->sinfo_flags & ~(SCTP_UNORDERED |SCTP_ADDR_OVER | -SCTP_SACK_IMMEDIATELY |SCTP_PR_SCTP_MASK | -SCTP_ABORT |SCTP_EOF )) +SCTP_SACK_IMMEDIATELY |SCTP_SENDALL | +SCTP_PR_SCTP_MASK |SCTP_ABORT |SCTP_EOF ))return -EINVAL ;break ;@@ -7816,8 +7843,8 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->sinfo->snd_flags & ~(SCTP_UNORDERED |SCTP_ADDR_OVER | -SCTP_SACK_IMMEDIATELY |SCTP_PR_SCTP_MASK | -SCTP_ABORT |SCTP_EOF )) +SCTP_SACK_IMMEDIATELY |SCTP_SENDALL | +SCTP_PR_SCTP_MASK |SCTP_ABORT |SCTP_EOF ))return -EINVAL ;break ;case SCTP_PRINFO :Signature · 1 line
2.1.0
Marcelo Ricardo Leitner
maintainerRe: [PATCH net-next 2/3] sctp: add support for SCTP_DSTADDRV4/6 Information for sendmsg
In reply to Xin LongQuoted 132 lines · Xin Long
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 <[email protected]>--- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 6 ++++ net/sctp/socket.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+)include/net/sctp/structs.h +1
-0@@ -2113,6 +2113,7 @@ struct sctp_cmsgs {struct sctp_sndrcvinfo *srinfo;struct sctp_sndinfo *sinfo;struct sctp_prinfo *prinfo; +struct msghdr *addrs_msg; };/* Structure for tracking memory objects */ include/uapi/linux/sctp.h +6
-0@@ -308,6 +308,12 @@ typedef enum sctp_cmsg_type {#define SCTP_NXTINFO SCTP_NXTINFO SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */#define SCTP_PRINFO SCTP_PRINFO + SCTP_AUTHINFO, /* 5.3.8 SCTP AUTH Information Structure (RESERVED) */ +#define SCTP_AUTHINFO SCTP_AUTHINFO + SCTP_DSTADDRV4, /* 5.3.9 SCTP Destination IPv4 Address Structure */ +#define SCTP_DSTADDRV4 SCTP_DSTADDRV4 + SCTP_DSTADDRV6, /* 5.3.10 SCTP Destination IPv6 Address Structure */ +#define SCTP_DSTADDRV6 SCTP_DSTADDRV6 } sctp_cmsg_t;/* net/sctp/socket.c +66
-0@@ -1676,6 +1676,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,struct net *net =sock_net (sk);struct sctp_association *asoc;enum sctp_scope scope; +struct cmsghdr *cmsg;int err = -EINVAL ; *tp =NULL ;@@ -1741,6 +1742,67 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, goto free; } +if (!cmsgs->addrs_msg) +return 0 ; + +/* 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; + +if (cmsg->cmsg_level !=IPPROTO_SCTP || + (cmsg->cmsg_type !=SCTP_DSTADDRV4 && + cmsg->cmsg_type !=SCTP_DSTADDRV6 )) +continue ; + + daddr = &_daddr; +memset (daddr,0 ,sizeof (*daddr)); + dlen = cmsg->cmsg_len -sizeof (struct cmsghdr ); +if (cmsg->cmsg_type =SCTP_DSTADDRV4 ) { +if (dlen <sizeof (struct in_addr )) + goto free; + + dlen =sizeof (struct in_addr ); + daddr->v4.sin_family =AF_INET ; + daddr->v4.sin_port =htons (asoc->peer.port); +memcpy (&daddr->v4.sin_addr,CMSG_DATA (cmsg), dlen); + }else { +if (dlen <sizeof (struct in6_addr )) + goto free; + + dlen =sizeof (struct in6_addr ); + daddr->v6.sin6_family =AF_INET6 ; + 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 ; + goto free; + } + } +return 0 ; free:@@ -7778,6 +7840,21 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->prinfo->pr_policy =SCTP_PR_SCTP_NONE ) cmsgs->prinfo->pr_value =0 ;break ; +case SCTP_DSTADDRV4 : +case SCTP_DSTADDRV6 : +/* SCTP Socket API Extension +* 5.3.9/10 SCTP Destination IPv4/6 Address Structure (SCTP_DSTADDRV4/6)
net/sctp/socket.c static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs) · line 7856
Quoted 10 lines
net/sctp/socket.c +10
-0+* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV4 struct in_addr +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV6 struct in6_addr +*/ + cmsgs->addrs_msg = my_msg;
I think this is being handled differently from what the RFC specifies. AFAIU the rfc defines these two options being each one an array of a specific element type, in_addr and in6_addr.
The patch is saving both options into a single pointer, which later is processed as a list of (in_addr or in6_addr) elements.
If an application specifies both options, each with a list of its own addresses, it will ignore one of the options.
Quoted 7 lines
net/sctp/socket.c +1
-0+break ;default :return -EINVAL ; }Signature · 1 line
2.1.0
Xin Long
maintainerRe: [PATCH net-next 2/3] sctp: add support for SCTP_DSTADDRV4/6 Information for sendmsg
Quoted 139 lines · Marcelo Ricardo Leitner
Quoted 138 lines · Xin Long
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 <[email protected]>--- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 6 ++++ net/sctp/socket.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+)include/net/sctp/structs.h +1
-0@@ -2113,6 +2113,7 @@ struct sctp_cmsgs {struct sctp_sndrcvinfo *srinfo;struct sctp_sndinfo *sinfo;struct sctp_prinfo *prinfo; +struct msghdr *addrs_msg; };/* Structure for tracking memory objects */ include/uapi/linux/sctp.h +6
-0@@ -308,6 +308,12 @@ typedef enum sctp_cmsg_type {#define SCTP_NXTINFO SCTP_NXTINFO SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */#define SCTP_PRINFO SCTP_PRINFO + SCTP_AUTHINFO, /* 5.3.8 SCTP AUTH Information Structure (RESERVED) */ +#define SCTP_AUTHINFO SCTP_AUTHINFO + SCTP_DSTADDRV4, /* 5.3.9 SCTP Destination IPv4 Address Structure */ +#define SCTP_DSTADDRV4 SCTP_DSTADDRV4 + SCTP_DSTADDRV6, /* 5.3.10 SCTP Destination IPv6 Address Structure */ +#define SCTP_DSTADDRV6 SCTP_DSTADDRV6 } sctp_cmsg_t;/* net/sctp/socket.c +72
-0@@ -1676,6 +1676,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,struct net *net =sock_net (sk);struct sctp_association *asoc;enum sctp_scope scope; +struct cmsghdr *cmsg;int err = -EINVAL ; *tp =NULL ;@@ -1741,6 +1742,67 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, goto free; } +if (!cmsgs->addrs_msg) +return 0 ; + +/* 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; + +if (cmsg->cmsg_level !=IPPROTO_SCTP || + (cmsg->cmsg_type !=SCTP_DSTADDRV4 && + cmsg->cmsg_type !=SCTP_DSTADDRV6 )) +continue ; + + daddr = &_daddr; +memset (daddr,0 ,sizeof (*daddr)); + dlen = cmsg->cmsg_len -sizeof (struct cmsghdr ); +if (cmsg->cmsg_type =SCTP_DSTADDRV4 ) { +if (dlen <sizeof (struct in_addr )) + goto free; + + dlen =sizeof (struct in_addr ); + daddr->v4.sin_family =AF_INET ; + daddr->v4.sin_port =htons (asoc->peer.port); +memcpy (&daddr->v4.sin_addr,CMSG_DATA (cmsg), dlen); + }else { +if (dlen <sizeof (struct in6_addr )) + goto free; + + dlen =sizeof (struct in6_addr ); + daddr->v6.sin6_family =AF_INET6 ; + 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 ; + goto free; + } + } +return 0 ; free:@@ -7778,6 +7840,21 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->prinfo->pr_policy =SCTP_PR_SCTP_NONE ) cmsgs->prinfo->pr_value =0 ;break ; +case SCTP_DSTADDRV4 : +case SCTP_DSTADDRV6 : +/* SCTP Socket API Extension +* 5.3.9/10 SCTP Destination IPv4/6 Address Structure (SCTP_DSTADDRV4/6) +* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV4 struct in_addr
Quoted 8 lines
net/sctp/socket.c static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs) · line 7856
Quoted 4 lines
net/sctp/socket.c +4
-0+* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV6 struct in6_addr +*/ + cmsgs->addrs_msg = my_msg;I think this is being handled differently from what the RFC specifies. AFAIU the rfc defines these two options being each one an array of a specific element type,
in_addrandin6_addr.
Hi, Marcelo.
From section 5.3.9 of RFC6458:
This ancillary data can be used to provide more than one destination address to sendmsg(). It can be used to implement sctp_sendv() using sendmsg().
It doesn't say to put "more than one destination address" into an array of one option, or put "more than one destination address" into many options.
I was also confused, then I checked sctp_process_cmsgs_for_init() in freebsd, I think it's in MANY options.
Quoted 3 lines
The patch is saving both options into a single pointer, which later is processed as a list of (
in_addrorin6_addr) elements.
It's not, 'my_msg' is the whole msghdr, not only in_addr or in6_addr. later in sctp_sendmsg_new_asoc, it will parse this msghdr again but this time only to pick up SCTP_DSTADDRV4/6 options.
(by this way I don't need to alloc list or array to save them)
Note that: one option is just one address, NOT a list of addresses. like, it can even be:SCTP_DSTADDRV4 (one option)SCTP_DSTADDRV6 (one option)SCTP_DSTADDRV4 (one option)SCTP_DSTADDRV4 (one option)SCTP_DSTADDRV6 (one option)
Maybe the name of cmsgs->addrs_msg is confusing here, but I actually think it as a flag to see if there is addrs info in the msghdr, and also as a parameter to pass the msghdr into sctp_sendmsg_new_asoc.
Quoted 3 lines
If an application specifies both options, each with a list of its own addresses, it will ignore one of the options.
If an application specifies many options, some are SCTP_DSTADDRV4 and some are SCTP_DSTADDRV6, none of them will be ignored in sctp_sendmsg_new_asoc().
Quoted 8 lines
Quoted 8 lines
net/sctp/socket.c +1
-1+break ;default :return -EINVAL ; } --2.1.0
Marcelo Ricardo Leitner
maintainerRe: [PATCH net-next 2/3] sctp: add support for SCTP_DSTADDRV4/6 Information for sendmsg
Quoted 151 lines · Xin Long
Quoted 139 lines · Marcelo Ricardo Leitner
Quoted 138 lines · Xin Long
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 <[email protected]>--- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 6 ++++ net/sctp/socket.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+)include/net/sctp/structs.h +1
-0@@ -2113,6 +2113,7 @@ struct sctp_cmsgs {struct sctp_sndrcvinfo *srinfo;struct sctp_sndinfo *sinfo;struct sctp_prinfo *prinfo; +struct msghdr *addrs_msg; };/* Structure for tracking memory objects */ include/uapi/linux/sctp.h +6
-0@@ -308,6 +308,12 @@ typedef enum sctp_cmsg_type {#define SCTP_NXTINFO SCTP_NXTINFO SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */#define SCTP_PRINFO SCTP_PRINFO + SCTP_AUTHINFO, /* 5.3.8 SCTP AUTH Information Structure (RESERVED) */ +#define SCTP_AUTHINFO SCTP_AUTHINFO + SCTP_DSTADDRV4, /* 5.3.9 SCTP Destination IPv4 Address Structure */ +#define SCTP_DSTADDRV4 SCTP_DSTADDRV4 + SCTP_DSTADDRV6, /* 5.3.10 SCTP Destination IPv6 Address Structure */ +#define SCTP_DSTADDRV6 SCTP_DSTADDRV6 } sctp_cmsg_t;/* net/sctp/socket.c +72
-0@@ -1676,6 +1676,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,struct net *net =sock_net (sk);struct sctp_association *asoc;enum sctp_scope scope; +struct cmsghdr *cmsg;int err = -EINVAL ; *tp =NULL ;@@ -1741,6 +1742,67 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, goto free; } +if (!cmsgs->addrs_msg) +return 0 ; + +/* 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; + +if (cmsg->cmsg_level !=IPPROTO_SCTP || + (cmsg->cmsg_type !=SCTP_DSTADDRV4 && + cmsg->cmsg_type !=SCTP_DSTADDRV6 )) +continue ; + + daddr = &_daddr; +memset (daddr,0 ,sizeof (*daddr)); + dlen = cmsg->cmsg_len -sizeof (struct cmsghdr ); +if (cmsg->cmsg_type =SCTP_DSTADDRV4 ) { +if (dlen <sizeof (struct in_addr )) + goto free; + + dlen =sizeof (struct in_addr ); + daddr->v4.sin_family =AF_INET ; + daddr->v4.sin_port =htons (asoc->peer.port); +memcpy (&daddr->v4.sin_addr,CMSG_DATA (cmsg), dlen); + }else { +if (dlen <sizeof (struct in6_addr )) + goto free; + + dlen =sizeof (struct in6_addr ); + daddr->v6.sin6_family =AF_INET6 ; + 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 ; + goto free; + } + } +return 0 ; free:@@ -7778,6 +7840,21 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->prinfo->pr_policy =SCTP_PR_SCTP_NONE ) cmsgs->prinfo->pr_value =0 ;break ; +case SCTP_DSTADDRV4 : +case SCTP_DSTADDRV6 : +/* SCTP Socket API Extension +* 5.3.9/10 SCTP Destination IPv4/6 Address Structure (SCTP_DSTADDRV4/6) +* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV4 struct in_addr Quoted 8 lines
net/sctp/socket.c static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs) · line 7856
Quoted 4 lines
net/sctp/socket.c +4
-0+* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV6 struct in6_addr +*/ + cmsgs->addrs_msg = my_msg;I think this is being handled differently from what the RFC specifies. AFAIU the rfc defines these two options being each one an array of a specific element type,
in_addrandin6_addr.Hi, Marcelo.
Quoted 8 lines
From section 5.3.9 of RFC6458:
This ancillary data can be used to provide more than one destination address to
sendmsg(). It can be used to implementsctp_sendv()usingsendmsg().It doesn't say to put "more than one destination address" into an array of one option, or put "more than one destination address" into many options.
Spot on. And I went with the first interpretation, thus why the difference.
Quoted 3 lines
I was also confused, then I checked
sctp_process_cmsgs_for_init()in freebsd, I think it's in MANY options.
Nice, ok
Quoted 9 lines
Quoted 5 lines
The patch is saving both options into a single pointer, which later is processed as a list of (
in_addrorin6_addr) elements.It's not, '
my_msg' is the whole msghdr, not onlyin_addrorin6_addr. later insctp_sendmsg_new_asoc, it will parse this msghdr again but this time only to pick up SCTP_DSTADDRV4/6 options.
(by this way I don't need to alloc list or array to save them)
Which is nice, btw.
Quoted 9 lines
Note that: one option is just one address, NOT a list of addresses. like, it can even be:
SCTP_DSTADDRV4(one option)SCTP_DSTADDRV6(one option)SCTP_DSTADDRV4(one option)SCTP_DSTADDRV4(one option)SCTP_DSTADDRV6(one option)
Quoted 3 lines
Maybe the name of
cmsgs->addrs_msgis confusing here, but I actually think it as a flag to see if there is addrs info in the msghdr, and also as a parameter to pass the msghdr intosctp_sendmsg_new_asoc.
What was more confusing to me is that it seems to overwrite the pointer at every other addr option, but I should have noticed that it is saving the entire cmsg.
Quoted 7 lines
Quoted 4 lines
If an application specifies both options, each with a list of its own addresses, it will ignore one of the options.
If an application specifies many options, some are
SCTP_DSTADDRV4and some areSCTP_DSTADDRV6, none of them will be ignored insctp_sendmsg_new_asoc().
Yep. Thanks.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
net/sctp/socket.c +1
-1+break ;default :return -EINVAL ; } --2.1.0
Re: [PATCH net-next 2/3] sctp: add support for SCTP_DSTADDRV4/6 Information for sendmsg
In reply to Xin LongQuoted 9 lines · Xin Long
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 <[email protected]>
Quoted 140 lines
--- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 6 ++++ net/sctp/socket.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+)include/net/sctp/structs.h +1
-0@@ -2113,6 +2113,7 @@ struct sctp_cmsgs {struct sctp_sndrcvinfo *srinfo;struct sctp_sndinfo *sinfo;struct sctp_prinfo *prinfo; +struct msghdr *addrs_msg; };/* Structure for tracking memory objects */ include/uapi/linux/sctp.h +6
-0@@ -308,6 +308,12 @@ typedef enum sctp_cmsg_type {#define SCTP_NXTINFO SCTP_NXTINFO SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */#define SCTP_PRINFO SCTP_PRINFO + SCTP_AUTHINFO, /* 5.3.8 SCTP AUTH Information Structure (RESERVED) */ +#define SCTP_AUTHINFO SCTP_AUTHINFO + SCTP_DSTADDRV4, /* 5.3.9 SCTP Destination IPv4 Address Structure */ +#define SCTP_DSTADDRV4 SCTP_DSTADDRV4 + SCTP_DSTADDRV6, /* 5.3.10 SCTP Destination IPv6 Address Structure */ +#define SCTP_DSTADDRV6 SCTP_DSTADDRV6 } sctp_cmsg_t;/* net/sctp/socket.c +77
-0@@ -1676,6 +1676,7 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags,struct net *net =sock_net (sk);struct sctp_association *asoc;enum sctp_scope scope; +struct cmsghdr *cmsg;int err = -EINVAL ; *tp =NULL ;@@ -1741,6 +1742,67 @@ static int sctp_sendmsg_new_asoc(struct sock *sk, __u16 sflags, goto free; } +if (!cmsgs->addrs_msg) +return 0 ; + +/* 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; + +if (cmsg->cmsg_level !=IPPROTO_SCTP || + (cmsg->cmsg_type !=SCTP_DSTADDRV4 && + cmsg->cmsg_type !=SCTP_DSTADDRV6 )) +continue ; + + daddr = &_daddr; +memset (daddr,0 ,sizeof (*daddr)); + dlen = cmsg->cmsg_len -sizeof (struct cmsghdr ); +if (cmsg->cmsg_type =SCTP_DSTADDRV4 ) { +if (dlen <sizeof (struct in_addr )) + goto free; + + dlen =sizeof (struct in_addr ); + daddr->v4.sin_family =AF_INET ; + daddr->v4.sin_port =htons (asoc->peer.port); +memcpy (&daddr->v4.sin_addr,CMSG_DATA (cmsg), dlen); + }else { +if (dlen <sizeof (struct in6_addr )) + goto free; + + dlen =sizeof (struct in6_addr ); + daddr->v6.sin6_family =AF_INET6 ; + 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 ; + goto free; + } + } +return 0 ; free:@@ -7778,6 +7840,21 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs)if (cmsgs->prinfo->pr_policy =SCTP_PR_SCTP_NONE ) cmsgs->prinfo->pr_value =0 ;break ; +case SCTP_DSTADDRV4 : +case SCTP_DSTADDRV6 : +/* SCTP Socket API Extension +* 5.3.9/10 SCTP Destination IPv4/6 Address Structure (SCTP_DSTADDRV4/6) +* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV4 struct in_addr +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_DSTADDRV6 struct in6_addr +*/ + cmsgs->addrs_msg = my_msg; +break ;default :return -EINVAL ; }Signature · 1 line
2.1.0
Re: [PATCH net-next 1/3] sctp: add support for PR-SCTP Information for sendmsg
In reply to Xin LongQuoted 9 lines · Xin Long
This patch is to add support for PR-SCTP Information for sendmsg, as described in section 5.3.7 of RFC6458.
With this option, you can specify
pr_policyandpr_valuefor user data in sendmsg.It's also a necessary send info for
sctp_sendv.Signed-off-by Xin Long <[email protected]>
Quoted 112 lines
--- include/net/sctp/structs.h | 1 + include/uapi/linux/sctp.h | 15 +++++++++++++++ net/sctp/socket.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-)include/net/sctp/structs.h +1
-0@@ -2112,6 +2112,7 @@ struct sctp_cmsgs {struct sctp_initmsg *init;struct sctp_sndrcvinfo *srinfo;struct sctp_sndinfo *sinfo; +struct sctp_prinfo *prinfo; };/* Structure for tracking memory objects */ include/uapi/linux/sctp.h +15
-0@@ -260,6 +260,19 @@ struct sctp_nxtinfo {sctp_assoc_t nxt_assoc_id; }; +/* 5.3.7 SCTP PR-SCTP Information Structure (SCTP_PRINFO) +* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ ------------------- +* IPPROTO_SCTP SCTP_PRINFO struct sctp_prinfo +*/ +struct sctp_prinfo { +__u16 pr_policy; +__u32 pr_value; +}; +/* * sinfo_flags: 16 bits (unsigned integer) * @@ -293,6 +306,8 @@ typedef enum sctp_cmsg_type {#define SCTP_RCVINFO SCTP_RCVINFO SCTP_NXTINFO, /* 5.3.6 SCTP Next Receive Information Structure */#define SCTP_NXTINFO SCTP_NXTINFO + SCTP_PRINFO, /* 5.3.7 SCTP PR-SCTP Information Structure */ +#define SCTP_PRINFO SCTP_PRINFO } sctp_cmsg_t;/* net/sctp/socket.c +30
-1@@ -1644,6 +1644,12 @@ static int sctp_sendmsg_parse(struct sock *sk, struct sctp_cmsgs *cmsgs, srinfo->sinfo_assoc_id = cmsgs->sinfo->snd_assoc_id; } +if (cmsgs->prinfo) { + srinfo->sinfo_timetolive = cmsgs->prinfo->pr_value; +SCTP_PR_SET_POLICY (srinfo->sinfo_flags, + cmsgs->prinfo->pr_policy); + } + sflags = srinfo->sinfo_flags;if (!sflags && msg_len)return 0 ;@@ -1901,9 +1907,12 @@ static void sctp_sendmsg_update_sinfo(struct sctp_association *asoc, sinfo->sinfo_ppid = asoc->default_ppid; sinfo->sinfo_context = asoc->default_context; sinfo->sinfo_assoc_id =sctp_assoc2id (asoc); + +if (!cmsgs->prinfo) + sinfo->sinfo_flags = asoc->default_flags; } -if (!cmsgs->srinfo) +if (!cmsgs->srinfo && !cmsgs->prinfo) sinfo->sinfo_timetolive = asoc->default_timetolive; }@@ -7749,6 +7758,26 @@ static int sctp_msghdr_parse(const struct msghdr *msg, struct sctp_cmsgs *cmsgs) SCTP_ABORT | SCTP_EOF))return -EINVAL ;break ; +case SCTP_PRINFO : +/* SCTP Socket API Extension +* 5.3.7 SCTP PR-SCTP Information Structure (SCTP_PRINFO) +* +* This cmsghdr structure specifies SCTP options for sendmsg(). +* +* cmsg_level cmsg_type cmsg_data[] +* ------------ ------------ --------------------- +* IPPROTO_SCTP SCTP_PRINFO struct sctp_prinfo +*/ +if (cmsg->cmsg_len !=CMSG_LEN (sizeof (struct sctp_prinfo ))) +return -EINVAL ; + + cmsgs->prinfo =CMSG_DATA (cmsg); +if (cmsgs->prinfo->pr_policy & ~SCTP_PR_SCTP_MASK ) +return -EINVAL ; + +if (cmsgs->prinfo->pr_policy =SCTP_PR_SCTP_NONE ) + cmsgs->prinfo->pr_value =0 ; +break ;default :return -EINVAL ; }Signature · 1 line
2.1.0
Marcelo Ricardo Leitner
maintainerQuoted 7 lines · Xin Long
This patchset is to add support for 3
msg_controloptions described in RFC6458:5.3.7. SCTP PR-SCTP Information Structure (
SCTP_PRINFO) 5.3.9. SCTP Destination IPv4 Address Structure (SCTP_DSTADDRV4) 5.3.10. SCTP Destination IPv6 Address Structure (SCTP_DSTADDRV6)
Quoted 6 lines
one send flag described in RFC6458:
SCTP_SENDALL: This flag, if set, will cause a one-to-many style socket to send the message to all associations that are currently established on this socket. For the one-to- one style socket, this flag has no effect.
Other patches (than the 2nd one) LGTM.
Marcelo
David Miller
maintainerFrom: Xin Long <[email protected]>
Date: Mon, 5 Mar 2018 20:44:17 +0800
Quoted 14 lines
This patchset is to add support for 3
msg_controloptions described in RFC6458:5.3.7. SCTP PR-SCTP Information Structure (
SCTP_PRINFO) 5.3.9. SCTP Destination IPv4 Address Structure (SCTP_DSTADDRV4) 5.3.10. SCTP Destination IPv6 Address Structure (SCTP_DSTADDRV6)one send flag described in RFC6458:
SCTP_SENDALL: This flag, if set, will cause a one-to-many style socket to send the message to all associations that are currently established on this socket. For the one-to- one style socket, this flag has no effect.
Quoted 6 lines
Note there is another
msg_controloption:5.3.8. SCTP AUTH Information Structure (
SCTP_AUTHINFO)It's a little complicated, I will post it in another patchset after this.
Series applied, thanks Xin.