[PATCH net-next 0/6] A step closer to RFC 6458 compliancy

STALE4467d

Revision v1 of 2 in this series.

16 messages, 3 authors, 2014-06-17 · open the first message on its own page

[PATCH net-next 0/6] A step closer to RFC 6458 compliancy

From: Geir Ola Vaagland <hidden>
Date: 2014-06-17 11:57:59

Geir Ola Vaagland (6):
  Support for SCTP_RECVRCVINFO socket option
  Support for SCTP_RCVINFO ancillary data
  Support for SCTP_SNDINFO ancillary data
  Support for SCTP_NXTINFO socket option
  Support for receiving SCTP_NXTINFO ancillary data
  Support for SCTP_DEFAULT_SNDINFO socket option

 include/net/sctp/structs.h  |  11 +-
 include/net/sctp/ulpevent.h |   4 +
 include/uapi/linux/sctp.h   |  46 ++++++++
 net/sctp/socket.c           | 260 ++++++++++++++++++++++++++++++++++++++++++--
 net/sctp/ulpevent.c         | 158 +++++++++++++++++++++++++++
 5 files changed, 470 insertions(+), 9 deletions(-)

[PATCH net-next 1/6] Support for SCTP_RECVRCVINFO socket option

From: Geir Ola Vaagland <hidden>
Date: 2014-06-17 11:58:00

CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/net/sctp/structs.h |  1 +
 include/uapi/linux/sctp.h  |  2 ++
 net/sctp/socket.c          | 48 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 0a248b3..75c598a 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -216,6 +216,7 @@ struct sctp_sock {
 	__u8 frag_interleave;
 	__u32 adaptation_ind;
 	__u32 pd_point;
+	__u8 recvrcvinfo;
 
 	atomic_t pd_mode;
 	/* Receive to here while partial delivery is in effect. */
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index ca451e9..a7db3b3 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -97,6 +97,8 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_AUTO_ASCONF       30
 #define SCTP_PEER_ADDR_THLDS	31
 
+#define SCTP_RECVRCVINFO 32
+
 /* Internal Socket Options. Some of the sctp library functions are
  * implemented using these socket options.
  */
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 146b35d..1f3281b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3566,6 +3566,24 @@ static int sctp_setsockopt_paddr_thresholds(struct sock *sk,
 	return 0;
 }
 
+static int sctp_setsockopt_recvrcvinfo(struct sock *sk,
+		char __user *optval,
+		unsigned int optlen){
+
+	int val;
+
+	if(optlen < sizeof(int))
+		return -EINVAL;
+
+	if(get_user(val, (int __user*)optval)){
+		return -EFAULT;
+	}
+	sctp_sk(sk)->recvrcvinfo = (val == 0) ? 0 : 1;
+	return 0;
+}
+
+
+
 /* API 6.2 setsockopt(), getsockopt()
  *
  * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3717,6 +3735,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
 	case SCTP_PEER_ADDR_THLDS:
 		retval = sctp_setsockopt_paddr_thresholds(sk, optval, optlen);
 		break;
+	case SCTP_RECVRCVINFO:
+		retval = sctp_setsockopt_recvrcvinfo(sk, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -3963,6 +3984,9 @@ static int sctp_init_sock(struct sock *sk)
 	/* Enable Nagle algorithm by default.  */
 	sp->nodelay           = 0;
 
+	/* No SCTP_RECVRCVINFO by default. */
+	sp->recvrcvinfo = 0;
+
 	/* Enable by default. */
 	sp->v4mapped          = 1;
 
@@ -5734,6 +5758,27 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
 	return 0;
 }
 
+static int sctp_getsockopt_recvrcvinfo(struct sock *sk,
+		int len,
+		char __user *optval,
+		int __user *optlen){
+
+	int val;
+
+	if (len < sizeof(int))
+		return -EINVAL;
+
+	len = sizeof(int);
+	val = (sctp_sk(sk)->recvrcvinfo == 1);
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &val, len))
+		return -EFAULT;
+	return 0;
+}
+
+
+
 static int sctp_getsockopt(struct sock *sk, int level, int optname,
 			   char __user *optval, int __user *optlen)
 {
@@ -5877,6 +5922,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
 	case SCTP_GET_ASSOC_STATS:
 		retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen);
 		break;
+	case SCTP_RECVRCVINFO:
+		retval = sctp_getsockopt_recvrcvinfo(sk, len, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;

[PATCH net-next 2/6] Support for SCTP_RCVINFO ancillary data

From: Geir Ola Vaagland <hidden>
Date: 2014-06-17 11:58:01

CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/net/sctp/ulpevent.h |  2 +
 include/uapi/linux/sctp.h   | 23 ++++++++++++
 net/sctp/socket.c           |  6 +++
 net/sctp/ulpevent.c         | 91 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+)
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 27b9f5c..2f42831 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -131,6 +131,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 	struct msghdr *);
+void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
+	struct msghdr *);
 __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event);
 
 /* Is this event type enabled? */
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index a7db3b3..7e8736b 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -158,6 +158,27 @@ struct sctp_sndrcvinfo {
 };
 
 /*
+ *  5.3.5 SCTP Receive Information Structure (SCTP_RCVINFO)
+ *
+ *   This cmsghdr structure specifies SCTP options for sendmsg().
+ *
+ *   cmsg_level    cmsg_type      cmsg_data[]
+ *   ------------  ------------   -------------------
+ *   IPPROTO_SCTP  SCTP_RCVINFO   struct sctp_rcvinfo
+ *
+ */
+struct sctp_rcvinfo {
+	__u16 rcv_sid;
+	__u16 rcv_ssn;
+	__u16 rcv_flags;
+	__u32 rcv_ppid;
+	__u32 rcv_tsn;
+	__u32 rcv_cumtsn;
+	__u32 rcv_context;
+	sctp_assoc_t rcv_assoc_id;
+};
+
+/*
  *  sinfo_flags: 16 bits (unsigned integer)
  *
  *   This field may contain any of the following flags and is composed of
@@ -184,6 +205,8 @@ typedef enum sctp_cmsg_type {
 #define SCTP_INIT	SCTP_INIT
 	SCTP_SNDRCV,            /* 5.2.2 SCTP Header Information Structure */
 #define SCTP_SNDRCV	SCTP_SNDRCV
+	SCTP_RCVINFO,
+#define SCTP_RCVINFO SCTP_RCVINFO
 } sctp_cmsg_t;
 
 /*
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1f3281b..aee161b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2094,6 +2094,12 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
 		sp->pf->skb_msgname(skb, msg->msg_name, addr_len);
 	}
 
+
+	/* Check if SCTP_RCVINFO should be included */
+	if(sp->recvrcvinfo){
+		sctp_ulpevent_read_rcvinfo(event, msg);
+	}
+
 	/* Check if we allow SCTP_SNDRCVINFO. */
 	if (sp->subscribe.sctp_data_io_event)
 		sctp_ulpevent_read_sndrcvinfo(event, msg);
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 81089ed..d1b9a02 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -900,6 +900,97 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event)
 	return notification->sn_header.sn_type;
 }
 
+void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
+		struct msghdr *msghdr)
+{
+	struct sctp_rcvinfo rinfo;
+
+	if (sctp_ulpevent_is_notification(event)){
+		return;
+	}
+
+	/* Sockets API Extensions for SCTP
+	 * Section 5.3.5 SCTP Receive Information Structure (SCTP_SNDRCV)
+	 *
+	 * rcv_sid: 16 bits (unsigned integer)
+	 *
+	 * The SCTP stack places the message's stream number in this
+	 * value.
+	 */
+	rinfo.rcv_sid = event->stream;
+
+	/* rcv_ssn: 16 bits (unsigned integer)
+	 * This value contains the stream sequence number that the
+	 * remote endpoint placed in the DATA chunk.  For fragmented
+	 * messages, this is the same number for all deliveries of the
+	 * message (if more than one recvmsg() is needed to read
+	 * the message)
+	 */
+	rinfo.rcv_ssn = event->ssn;
+
+
+	/* rcv_ppid: 32 bits (unsigned integer)
+	 *
+	 * This value is the same information that was passed by the
+	 * upper layer in the peer application.  Please note that the SCTP
+	 * stack performs no byte order modification of this field.
+	 * For example, if the DATA chunk has to contain a given
+	 * value in network byte order, the SCTP user has to perform the
+	 * ntohl() computation.
+	 */
+	rinfo.rcv_ppid = event->ppid;
+
+	/* rcv_flags: 16 bits (unsigned integer)
+	 *
+	 * This field may contain any of the following flags and is composed of
+	 * a bitwise OR of these values.
+	 *
+	 * recvmsg() flags:
+	 *
+	 * SCTP_UNORDERED - This flag is present when the message was sent
+	 *                 non-ordered.
+	 */
+
+	rinfo.rcv_flags = event->flags;
+
+	/* rcv_tsn: 32 bits (unsigned integer)
+	 *
+	 * This field holds a TSN that was assigned to one of the SCTP
+	 * DATA chunks.
+	 */
+	rinfo.rcv_tsn = event->tsn;
+
+	/* rcv_cumtsn: 32 bits (unsigned integer)
+	 *
+	 * This field will hold the current cumulative TSN as known
+	 * by the underlying SCTP layer.
+	 */
+	rinfo.rcv_cumtsn = event->cumtsn;
+
+	/* rcv_assoc_id: sizeof (sctp_assoc_t)
+	 *
+	 * The association handle field, sinfo_assoc_id, holds the identifier
+	 * for the association announced in the COMMUNICATION_UP notification.
+	 * All notifications for a given association have the same identifier.
+	 * Ignored for one-to-one style sockets.
+	 */
+	rinfo.rcv_assoc_id = sctp_assoc2id(event->asoc);
+
+	/* rcv_context: 32 bits (unsigned integer)
+	 *
+	 * This value is an opaque 32-bit context datum that was
+	 * set by the user with the SCTP_CONTEXT socket option.  This
+	 * value is passed back to the upper layer if an error occurs on
+	 * the send of a message and is retrieved with each undelivered
+	 * message.
+	 */
+	rinfo.rcv_context = event->asoc->default_rcv_context;
+
+	put_cmsg(msghdr, IPPROTO_SCTP, SCTP_RCVINFO,
+			sizeof(struct sctp_rcvinfo), (void *)&rinfo);
+}
+
+
 /* Copy out the sndrcvinfo into a msghdr.  */
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *msghdr)

[PATCH net-next 3/6] Support for SCTP_SNDINFO ancillary data

From: Geir Ola Vaagland <hidden>
Date: 2014-06-17 11:58:03

CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/net/sctp/structs.h |  9 +++++++-
 include/uapi/linux/sctp.h  | 19 +++++++++++++++++
 net/sctp/socket.c          | 53 +++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 75c598a..5ed8a3c 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1921,9 +1921,16 @@ struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
 /* A convenience structure to parse out SCTP specific CMSGs. */
 typedef struct sctp_cmsgs {
 	struct sctp_initmsg *init;
-	struct sctp_sndrcvinfo *info;
+	union {
+		struct sctp_sndrcvinfo *srinfo;
+		struct sctp_sndinfo *sinfo;
+	} info;
+	sctp_cmsg_t cmsg_type;
 } sctp_cmsgs_t;
 
+#define sr_info info.srinfo
+#define s_info info.sinfo
+
 /* Structure for tracking memory objects */
 typedef struct {
 	char *label;
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 7e8736b..d725e30 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -156,6 +156,23 @@ struct sctp_sndrcvinfo {
 	__u32 sinfo_cumtsn;
 	sctp_assoc_t sinfo_assoc_id;
 };
+/*
+ * 5.3.4 SCTP Send Information Structure (SCTP_SNDINFO)
+ *
+ *   This cmsghdr structure specifies SCTP options for sendmsg().
+ *
+ *   cmsg_level    cmsg_type      cmsg_data[]
+ *   ------------  ------------   -------------------
+ *   IPPROTO_SCTP  SCTP_SNDINFO   struct sctp_sndinfo
+ *
+ */
+struct sctp_sndinfo {
+	__u16 snd_sid;
+	__u16 snd_flags;
+	__u32 snd_ppid;
+	__u32 snd_context;
+	sctp_assoc_t snd_assoc_id;
+};
 
 /*
  *  5.3.5 SCTP Receive Information Structure (SCTP_RCVINFO)
@@ -207,6 +224,8 @@ typedef enum sctp_cmsg_type {
 #define SCTP_SNDRCV	SCTP_SNDRCV
 	SCTP_RCVINFO,
 #define SCTP_RCVINFO SCTP_RCVINFO
+	SCTP_SNDINFO,
+#define SCTP_SNDINFO SCTP_SNDINFO
 } sctp_cmsg_t;
 
 /*
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index aee161b..57657b6 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1648,10 +1648,21 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 		msg_name = msg->msg_name;
 	}
 
-	sinfo = cmsgs.info;
+	if(cmsgs.cmsg_type == SCTP_SNDINFO){
+		memset(&default_sinfo, 0, sizeof(default_sinfo));
+		default_sinfo.sinfo_flags = cmsgs.s_info->snd_flags;
+		default_sinfo.sinfo_stream = cmsgs.s_info->snd_sid;
+		default_sinfo.sinfo_assoc_id = cmsgs.s_info->snd_assoc_id;
+		default_sinfo.sinfo_ppid = cmsgs.s_info->snd_ppid;
+		default_sinfo.sinfo_context = cmsgs.s_info->snd_context;
+		sinfo = &default_sinfo;
+	}else{
+		sinfo = cmsgs.sr_info;
+	}
+
 	sinit = cmsgs.init;
 
-	/* Did the user specify SNDRCVINFO?  */
+	/* Did the user specify SNDINFO/SNDRCVINFO?  */
 	if (sinfo) {
 		sinfo_flags = sinfo->sinfo_flags;
 		associd = sinfo->sinfo_assoc_id;
@@ -1858,7 +1869,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 	pr_debug("%s: we have a valid association\n", __func__);
 
 	if (!sinfo) {
-		/* If the user didn't specify SNDRCVINFO, make up one with
+		/* If the user didn't specify SNDINFO/SNDRCVINFO, make up one with
 		 * some defaults.
 		 */
 		memset(&default_sinfo, 0, sizeof(default_sinfo));
@@ -1869,6 +1880,8 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 		default_sinfo.sinfo_timetolive = asoc->default_timetolive;
 		default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc);
 		sinfo = &default_sinfo;
+	}else{
+		sinfo->sinfo_timetolive = asoc->default_timetolive;
 	}
 
 	/* API 7.1.7, the sndbuf size per association bounds the
@@ -6473,16 +6486,46 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs)
 			    CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
 				return -EINVAL;
 
-			cmsgs->info =
+			cmsgs->info.srinfo =
 				(struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
 
 			/* Minimally, validate the sinfo_flags. */
-			if (cmsgs->info->sinfo_flags &
+			if (cmsgs->sr_info->sinfo_flags &
 			    ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
 			      SCTP_ABORT | SCTP_EOF))
 				return -EINVAL;
 			break;
 
+		case SCTP_SNDINFO:
+			/* SCTP Socket API Extension
+			 * 5.3.4 SCTP Send Information Structure (SCTP_SNDINFO)
+			 *
+			 * This cmsghdr structure specifies SCTP options for
+			 * sendmsg(). This structure and SCTP_RCVINFO replaces
+			 * SCTP_SNDRCV which has been depleted.
+			 *
+			 * cmsg_level    cmsg_type      cmsg_data[]
+			 * ------------  ------------   ---------------------
+			 * IPPROTO_SCTP  SCTP_SNDINFO    struct sctp_sndinfo
+			 * */
+			if(cmsg->cmsg_len !=
+					CMSG_LEN(sizeof(struct sctp_sndinfo))){
+
+				return -EINVAL;
+			}
+
+			/* SCTP_SENDALL should also be added here when
+			 * it is implemented */
+			cmsgs->info.sinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
+			cmsgs->cmsg_type = SCTP_SNDINFO;
+
+			if (cmsgs->s_info->snd_flags &
+					~(SCTP_UNORDERED | SCTP_ADDR_OVER |
+						SCTP_ABORT | SCTP_EOF)){
+				return -EINVAL;
+			}
+			break;
+
 		default:
 			return -EINVAL;
 		}

[PATCH net-next 4/6] Support for SCTP_NXTINFO socket option

From: Geir Ola Vaagland <hidden>
Date: 2014-06-17 11:58:04

CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/net/sctp/structs.h |  1 +
 include/uapi/linux/sctp.h  |  1 +
 net/sctp/socket.c          | 43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 5ed8a3c..06585b8 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -217,6 +217,7 @@ struct sctp_sock {
 	__u32 adaptation_ind;
 	__u32 pd_point;
 	__u8 recvrcvinfo;
+	__u8 recvnxtinfo;
 
 	atomic_t pd_mode;
 	/* Receive to here while partial delivery is in effect. */
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index d725e30..986563e 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -98,6 +98,7 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_PEER_ADDR_THLDS	31
 
 #define SCTP_RECVRCVINFO 32
+#define SCTP_RECVNXTINFO 33
 
 /* Internal Socket Options. Some of the sctp library functions are
  * implemented using these socket options.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 57657b6..10e12da 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3602,6 +3602,20 @@ static int sctp_setsockopt_recvrcvinfo(struct sock *sk,
 }
 
 
+static int sctp_setsockopt_recvnxtinfo(struct sock *sk,
+		char __user *optval,
+		unsigned int optlen){
+	int val;
+
+	if(optlen < sizeof(int))
+		return -EINVAL;
+
+	if(get_user(val, (int __user*)optval)){
+		return -EFAULT;
+	}
+	sctp_sk(sk)->recvnxtinfo = (val == 0) ? 0 : 1;
+	return 0;
+}
 
 /* API 6.2 setsockopt(), getsockopt()
  *
@@ -3757,6 +3771,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
 	case SCTP_RECVRCVINFO:
 		retval = sctp_setsockopt_recvrcvinfo(sk, optval, optlen);
 		break;
+	case SCTP_RECVNXTINFO:
+		retval = sctp_setsockopt_recvnxtinfo(sk, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -4006,6 +4023,9 @@ static int sctp_init_sock(struct sock *sk)
 	/* No SCTP_RECVRCVINFO by default. */
 	sp->recvrcvinfo = 0;
 
+	/* No SCTP_RECVNXTINFO by default. */
+	sp->recvnxtinfo = 0;
+
 	/* Enable by default. */
 	sp->v4mapped          = 1;
 
@@ -5777,6 +5797,26 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
 	return 0;
 }
 
+static int sctp_getsockopt_recvnxtinfo(struct sock *sk,
+		int len,
+		char __user *optval,
+		int __user *optlen){
+
+	int val;
+	if (len < sizeof(int))
+		return -EINVAL;
+
+	len = sizeof(int);
+	val = (sctp_sk(sk)->recvnxtinfo == 1);
+
+	if(put_user(len, optlen))
+		return -EFAULT;
+	if(copy_to_user(optval, &val, len))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int sctp_getsockopt_recvrcvinfo(struct sock *sk,
 		int len,
 		char __user *optval,
@@ -5944,6 +5984,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
 	case SCTP_RECVRCVINFO:
 		retval = sctp_getsockopt_recvrcvinfo(sk, len, optval, optlen);
 		break;
+	case SCTP_RECVNXTINFO:
+		retval = sctp_getsockopt_recvnxtinfo(sk, len, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;

[PATCH net-next 5/6] Support for receiving SCTP_NXTINFO ancillary data

From: Geir Ola Vaagland <hidden>
Date: 2014-06-17 11:58:05

CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/net/sctp/ulpevent.h |  2 ++
 net/sctp/socket.c           | 16 +++++++++--
 net/sctp/ulpevent.c         | 67 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 82 insertions(+), 3 deletions(-)
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 2f42831..d15b835 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -133,6 +133,8 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 	struct msghdr *);
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
 	struct msghdr *);
+void sctp_ulpevent_read_nxtinfo(const struct sctp_ulpevent *event,
+	struct msghdr *, struct sk_buff *);
 __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event);
 
 /* Is this event type enabled? */
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 10e12da..57106e8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2061,11 +2061,11 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
 			struct msghdr *msg, size_t len, int noblock,
 			int flags, int *addr_len)
 {
-	struct sctp_ulpevent *event = NULL;
+	struct sctp_ulpevent *event = NULL, *nxt_event = NULL;
 	struct sctp_sock *sp = sctp_sk(sk);
-	struct sk_buff *skb;
+	struct sk_buff *skb, *nxtskb = NULL;
 	int copied;
-	int err = 0;
+	int err = 0, err2 = 0;
 	int skb_len;
 
 	pr_debug("%s: sk:%p, msghdr:%p, len:%zd, noblock:%d, flags:0x%x, "
@@ -2113,6 +2113,14 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
 		sctp_ulpevent_read_rcvinfo(event, msg);
 	}
 
+	if(sp->recvnxtinfo){
+		nxtskb = sctp_skb_recv_datagram(sk, MSG_PEEK, 1, &err2);
+		if(nxtskb && nxtskb->len){
+			nxt_event = sctp_skb2event(nxtskb);
+			sctp_ulpevent_read_nxtinfo(nxt_event, msg, nxtskb);
+		}
+	}
+
 	/* Check if we allow SCTP_SNDRCVINFO. */
 	if (sp->subscribe.sctp_data_io_event)
 		sctp_ulpevent_read_sndrcvinfo(event, msg);
@@ -2162,6 +2170,8 @@ out_free:
 		sctp_ulpevent_free(event);
 	}
 out:
+	if(nxtskb)
+		kfree_skb(nxtskb);
 	sctp_release_sock(sk);
 	return err;
 }
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index d1b9a02..94da2b4 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -900,6 +900,73 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event)
 	return notification->sn_header.sn_type;
 }
 
+void sctp_ulpevent_read_nxtinfo(const struct sctp_ulpevent *event,
+		struct msghdr *msghdr, struct sk_buff* skb)
+{
+	struct sctp_nxtinfo nxtinfo;
+
+
+	/* Sockets API Extensions for SCTP
+	 * Section 5.3.6 SCTP Next Receive Information Structure (SCTP_NXTINFO)
+	 *
+	 * nxt_sid: 16 bits (unsigned integer)
+	 *
+	 * The SCTP stack places the next message's stream number in
+	 * this value.
+	 */
+	nxtinfo.nxt_sid = event->stream;
+
+	/* nxt_ppid: 32 bits (unsigned integer)
+	 *
+	 * This value is the same information that was passed by the
+	 * upper layer in the peer application for the next message.  Please
+	 * note  that the SCTP stack performs no byte order modification of
+	 * this field.  For example, if the DATA chunk has to contain a given
+	 * value in network byte order, the SCTP user has to perform the
+	 * ntohl() computation.
+	 */
+	nxtinfo.nxt_ppid = event->ppid;
+
+	/* nxt_flags: 16 bits (unsigned integer)
+	 *
+	 * This field may contain any of the following flags and is
+	 * composed of a bitwise OR of these values.
+	 */
+	nxtinfo.nxt_flags = event->flags;
+
+	/*
+	 * SCTP_NOTIFICATION is not set in Linux yet.
+	 *
+	 * if (sctp_ulpevent_is_notification(event)){
+	 *     nxtinfo.nxt_flags |= SCTP_NOTIFICATION;
+	 * }
+	 *
+	 */
+
+	/* nxt_length: 32 bits (unsigned integer)
+	 *
+	 * This value is the length of the message currently within
+	 * the socket buffer.  This might NOT be the entire length of the
+	 * message, since a partial delivery may be in progress.  Only if the
+	 * flag SCTP_COMPLETE is set in the nxt_flags field does this field
+	 * represent the size of the entire next message.
+	 */
+	nxtinfo.nxt_length = skb->len;
+
+	/* nxt_assoc_id: sizeof(sctp_assoc_t)
+	 * The association handle field of the next message,
+	 * nxt_assoc_id, holds the identifier for the association
+	 * announced in the SCTP_COMM_UP notification.  All
+	 * notifications for a given association have the same
+	 * identifier.  This field is ignored for one-to-one style
+	 * sockets.
+	 */
+	nxtinfo.nxt_assoc_id = sctp_assoc2id(event->asoc);
+
+	put_cmsg(msghdr, IPPROTO_SCTP, SCTP_NXTINFO,
+			sizeof(struct sctp_nxtinfo), (void *)&nxtinfo);
+}
+
 void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
 		struct msghdr *msghdr)
 {

[PATCH net-next 6/6] Support for SCTP_DEFAULT_SNDINFO socket option

From: Geir Ola Vaagland <hidden>
Date: 2014-06-17 11:58:07

CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/uapi/linux/sctp.h |  1 +
 net/sctp/socket.c         | 94 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 986563e..133df4e 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -99,6 +99,7 @@ typedef __s32 sctp_assoc_t;
 
 #define SCTP_RECVRCVINFO 32
 #define SCTP_RECVNXTINFO 33
+#define SCTP_DEFAULT_SNDINFO 34
 
 /* Internal Socket Options. Some of the sctp library functions are
  * implemented using these socket options.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 57106e8..a725376 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2801,6 +2801,55 @@ static int sctp_setsockopt_default_send_param(struct sock *sk,
 
 	return 0;
 }
+/*
+ * 8.1.31. Set Default Send Parameters (SCTP_DEFAULT_SNDINFO)
+ *
+ *   Applications that wish to use the sendto() system call may wish to
+ *   specify a default set of parameters that would normally be supplied
+ *   through the inclusion of ancillary data.  This socket option allows
+ *   such an application to set the default sctp_sndinfo structure.  The
+ *   application that wishes to use this socket option simply passes the
+ *   sctp_sndinfo structure (defined in Section 5.3.4) to this call.  The
+ *   input parameters accepted by this call include snd_sid, snd_flags,
+ *   snd_ppid, and snd_context.  The snd_flags parameter is composed of a
+ *   bitwise OR of SCTP_UNORDERED, SCTP_EOF, and SCTP_SENDALL.  The
+ *   snd_assoc_id field specifies the association to which to apply the
+ *   parameters.  For a one-to-many style socket, any of the predefined
+ *   constants are also allowed in this field.  The field is ignored for
+ *   one-to-one style sockets.
+ */
+static int sctp_setsockopt_default_sndinfo(struct sock *sk,
+		char __user *optval,
+		unsigned int optlen){
+	struct sctp_sndinfo info;
+	struct sctp_association *asoc;
+	struct sctp_sock *sp = sctp_sk(sk);
+
+	if (optlen != sizeof(struct sctp_sndinfo))
+		return -EINVAL;
+	if (copy_from_user(&info, optval, optlen))
+		return -EFAULT;
+
+	asoc = sctp_id2assoc(sk, info.snd_assoc_id);
+	if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP))
+		return -EINVAL;
+
+	/* Note! asoc->default_timetolive is not set in this way anymore.
+	 * The PR-SCTP extension needs to be implemented.  */
+	if (asoc) {
+		asoc->default_stream = info.snd_sid;
+		asoc->default_flags = info.snd_flags;
+		asoc->default_ppid = info.snd_ppid;
+		asoc->default_context = info.snd_context;
+	} else {
+		sp->default_stream = info.snd_sid;
+		sp->default_flags = info.snd_flags;
+		sp->default_ppid = info.snd_ppid;
+		sp->default_context = info.snd_context;
+	}
+	return 0;
+}
+
 
 /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
  *
@@ -3724,6 +3773,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
 		retval = sctp_setsockopt_default_send_param(sk, optval,
 							    optlen);
 		break;
+	case SCTP_DEFAULT_SNDINFO:
+		retval = sctp_setsockopt_default_sndinfo(sk, optval, optlen);
+		break;
 	case SCTP_PRIMARY_ADDR:
 		retval = sctp_setsockopt_primary_addr(sk, optval, optlen);
 		break;
@@ -5063,6 +5115,45 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
 
 	return 0;
 }
+static int sctp_getsockopt_default_sndinfo(struct sock *sk,
+		int len, char __user *optval,
+		int __user *optlen)
+{
+	struct sctp_sndinfo info;
+	struct sctp_association *asoc;
+	struct sctp_sock *sp = sctp_sk(sk);
+
+	if (len < sizeof(struct sctp_sndinfo))
+		return -EINVAL;
+
+	len = sizeof(struct sctp_sndinfo);
+
+	if (copy_from_user(&info, optval, len))
+		return -EFAULT;
+
+	asoc = sctp_id2assoc(sk, info.snd_assoc_id);
+	if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP))
+		return -EINVAL;
+
+	if (asoc) {
+		info.snd_sid = asoc->default_stream;
+		info.snd_flags = asoc->default_flags;
+		info.snd_ppid = asoc->default_ppid;
+		info.snd_context = asoc->default_context;
+	} else {
+		info.snd_sid = sp->default_stream;
+		info.snd_flags = sp->default_flags;
+		info.snd_ppid = sp->default_ppid;
+		info.snd_context = sp->default_context;
+	}
+
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &info, len))
+		return -EFAULT;
+
+	return 0;
+}
 
 /*
  *
@@ -5917,6 +6008,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
 		retval = sctp_getsockopt_default_send_param(sk, len,
 							    optval, optlen);
 		break;
+	case SCTP_DEFAULT_SNDINFO:
+		retval = sctp_getsockopt_default_sndinfo(sk, len, optval, optlen);
+		break;
 	case SCTP_PRIMARY_ADDR:
 		retval = sctp_getsockopt_primary_addr(sk, len, optval, optlen);
 		break;

RE: [PATCH net-next 0/6] A step closer to RFC 6458 compliancy

From: David Laight <hidden>
Date: 2014-06-17 12:33:29

From: Geir Ola Vaagland
Geir Ola Vaagland (6):
  Support for SCTP_RECVRCVINFO socket option
  Support for SCTP_RCVINFO ancillary data
  Support for SCTP_SNDINFO ancillary data
  Support for SCTP_NXTINFO socket option
  Support for receiving SCTP_NXTINFO ancillary data
  Support for SCTP_DEFAULT_SNDINFO socket option

 include/net/sctp/structs.h  |  11 +-
 include/net/sctp/ulpevent.h |   4 +
 include/uapi/linux/sctp.h   |  46 ++++++++
 net/sctp/socket.c           | 260 ++++++++++++++++++++++++++++++++++++++++++--
 net/sctp/ulpevent.c         | 158 +++++++++++++++++++++++++++
 5 files changed, 470 insertions(+), 9 deletions(-)
You need to make your C match the expected layout for kernel code.
In particular the whitespace rules.

	David

RE: [PATCH net-next 1/6] Support for SCTP_RECVRCVINFO socket option

From: David Laight <hidden>
Date: 2014-06-17 12:36:28

From: Geir Ola Vaagland
quoted hunk
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 0a248b3..75c598a 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -216,6 +216,7 @@ struct sctp_sock {
 	__u8 frag_interleave;
 	__u32 adaptation_ind;
 	__u32 pd_point;
+	__u8 recvrcvinfo;
This adds a lot of padding.
Possibly it should also be a 'bool'

...
+static int sctp_setsockopt_recvrcvinfo(struct sock *sk,
+		char __user *optval,
+		unsigned int optlen){
+
+	int val;
+
+	if(optlen < sizeof(int))
+		return -EINVAL;
+
+	if(get_user(val, (int __user*)optval)){
+		return -EFAULT;
+	}
I suspect the above code is quite common, and should be put into
a separate function.
+	sctp_sk(sk)->recvrcvinfo = (val == 0) ? 0 : 1;
See 'bool'

...
+static int sctp_getsockopt_recvrcvinfo(struct sock *sk,
+		int len,
+		char __user *optval,
+		int __user *optlen){
+
+	int val;
+
+	if (len < sizeof(int))
+		return -EINVAL;
+
+	len = sizeof(int);
+	val = (sctp_sk(sk)->recvrcvinfo == 1);
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &val, len))
+		return -EFAULT;
This wants factoring out as well.

...
	David

RE: [PATCH net-next 2/6] Support for SCTP_RCVINFO ancillary data

From: David Laight <hidden>
Date: 2014-06-17 12:37:54

From: Geir Ola Vaagland
...
+struct sctp_rcvinfo {
+	__u16 rcv_sid;
+	__u16 rcv_ssn;
+	__u16 rcv_flags;
+	__u32 rcv_ppid;
+	__u32 rcv_tsn;
+	__u32 rcv_cumtsn;
+	__u32 rcv_context;
+	sctp_assoc_t rcv_assoc_id;
+};
There are two pad bytes in the middle of the above.
You leak kernel data to userspace.

...
	David

RE: [PATCH net-next 3/6] Support for SCTP_SNDINFO ancillary data

From: David Laight <hidden>
Date: 2014-06-17 12:39:38

From: Geir Ola Vaagland
...
+		case SCTP_SNDINFO:
+			/* SCTP Socket API Extension
+			 * 5.3.4 SCTP Send Information Structure (SCTP_SNDINFO)
+			 *
+			 * This cmsghdr structure specifies SCTP options for
+			 * sendmsg(). This structure and SCTP_RCVINFO replaces
+			 * SCTP_SNDRCV which has been depleted.
What do you mean by 'depleted'?
Support for it cannot be removed because it will break existing
applications.

	David

Re: [PATCH net-next 0/6] A step closer to RFC 6458 compliancy

From: Vlad Yasevich <hidden>
Date: 2014-06-17 13:40:59

On 06/17/2014 07:57 AM, Geir Ola Vaagland wrote:

Hi Geir

Please provide a bit more description for the those who are not familiar
with the series.

Thanks
-vlad

Geir Ola Vaagland (6):
  Support for SCTP_RECVRCVINFO socket option
  Support for SCTP_RCVINFO ancillary data
  Support for SCTP_SNDINFO ancillary data
  Support for SCTP_NXTINFO socket option
  Support for receiving SCTP_NXTINFO ancillary data
  Support for SCTP_DEFAULT_SNDINFO socket option

 include/net/sctp/structs.h  |  11 +-
 include/net/sctp/ulpevent.h |   4 +
 include/uapi/linux/sctp.h   |  46 ++++++++
 net/sctp/socket.c           | 260 ++++++++++++++++++++++++++++++++++++++++++--
 net/sctp/ulpevent.c         | 158 +++++++++++++++++++++++++++
 5 files changed, 470 insertions(+), 9 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: [PATCH net-next 1/6] Support for SCTP_RECVRCVINFO socket option

From: Vlad Yasevich <hidden>
Date: 2014-06-17 13:57:05

On 06/17/2014 07:57 AM, Geir Ola Vaagland wrote:

Again,  some description and a pointer to RFC/Section
for what this patch is implementing.
quoted hunk
CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/net/sctp/structs.h |  1 +
 include/uapi/linux/sctp.h  |  2 ++
 net/sctp/socket.c          | 48 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 0a248b3..75c598a 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -216,6 +216,7 @@ struct sctp_sock {
 	__u8 frag_interleave;
 	__u32 adaptation_ind;
 	__u32 pd_point;
+	__u8 recvrcvinfo;
 
 	atomic_t pd_mode;
 	/* Receive to here while partial delivery is in effect. */
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index ca451e9..a7db3b3 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -97,6 +97,8 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_AUTO_ASCONF       30
 #define SCTP_PEER_ADDR_THLDS	31
 
+#define SCTP_RECVRCVINFO 32
+
The above probably shouldn't have an empty line between options 31 and 32.
quoted hunk
 /* Internal Socket Options. Some of the sctp library functions are
  * implemented using these socket options.
  */
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 146b35d..1f3281b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3566,6 +3566,24 @@ static int sctp_setsockopt_paddr_thresholds(struct sock *sk,
 	return 0;
 }
 
+static int sctp_setsockopt_recvrcvinfo(struct sock *sk,
+		char __user *optval,
+		unsigned int optlen){
Coding style. Please put a space between ) and {.  Also,
please align definitions with above 'struct sock'.
As in:
+static int sctp_setsockopt_recvrcvinfo(struct sock *sk,
+		                        char __user *optval,
+		                        unsigned int optlen) {

For more info on coding style see Documentation/CodingStyle
in the kernel tree.
quoted hunk
+
+	int val;
+
+	if(optlen < sizeof(int))
+		return -EINVAL;
+
+	if(get_user(val, (int __user*)optval)){
+		return -EFAULT;
+	}
+	sctp_sk(sk)->recvrcvinfo = (val == 0) ? 0 : 1;
+	return 0;
+}
+
+
+
 /* API 6.2 setsockopt(), getsockopt()
  *
  * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3717,6 +3735,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
 	case SCTP_PEER_ADDR_THLDS:
 		retval = sctp_setsockopt_paddr_thresholds(sk, optval, optlen);
 		break;
+	case SCTP_RECVRCVINFO:
+		retval = sctp_setsockopt_recvrcvinfo(sk, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -3963,6 +3984,9 @@ static int sctp_init_sock(struct sock *sk)
 	/* Enable Nagle algorithm by default.  */
 	sp->nodelay           = 0;
 
+	/* No SCTP_RECVRCVINFO by default. */
+	sp->recvrcvinfo = 0;
+
 	/* Enable by default. */
 	sp->v4mapped          = 1;
 
@@ -5734,6 +5758,27 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
 	return 0;
 }
 
+static int sctp_getsockopt_recvrcvinfo(struct sock *sk,
+		int len,
+		char __user *optval,
+		int __user *optlen){
+
Indent issue.

-vlad
quoted hunk
+	int val;
+
+	if (len < sizeof(int))
+		return -EINVAL;
+
+	len = sizeof(int);
+	val = (sctp_sk(sk)->recvrcvinfo == 1);
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &val, len))
+		return -EFAULT;
+	return 0;
+}
+
+
+
 static int sctp_getsockopt(struct sock *sk, int level, int optname,
 			   char __user *optval, int __user *optlen)
 {
@@ -5877,6 +5922,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
 	case SCTP_GET_ASSOC_STATS:
 		retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen);
 		break;
+	case SCTP_RECVRCVINFO:
+		retval = sctp_getsockopt_recvrcvinfo(sk, len, optval, optlen);
+		break;
 	default:
 		retval = -ENOPROTOOPT;
 		break;

Re: [PATCH net-next 2/6] Support for SCTP_RCVINFO ancillary data

From: Vlad Yasevich <hidden>
Date: 2014-06-17 14:07:45

On 06/17/2014 07:57 AM, Geir Ola Vaagland wrote:
quoted hunk
CC: Vlad Yasevich <redacted>
Signed-off-by: Geir Ola Vaagland <redacted>
---
 include/net/sctp/ulpevent.h |  2 +
 include/uapi/linux/sctp.h   | 23 ++++++++++++
 net/sctp/socket.c           |  6 +++
 net/sctp/ulpevent.c         | 91 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+)
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 27b9f5c..2f42831 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -131,6 +131,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 	struct msghdr *);
+void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
+	struct msghdr *);
Gah...  This whole file doesn't conform to coding style. :(

Please make this change conform to style standards, and we can clean up the
file later.
quoted hunk
 __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event);
 
 /* Is this event type enabled? */
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index a7db3b3..7e8736b 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -158,6 +158,27 @@ struct sctp_sndrcvinfo {
 };
 
 /*
+ *  5.3.5 SCTP Receive Information Structure (SCTP_RCVINFO)
+ *
+ *   This cmsghdr structure specifies SCTP options for sendmsg().
+ *
+ *   cmsg_level    cmsg_type      cmsg_data[]
+ *   ------------  ------------   -------------------
+ *   IPPROTO_SCTP  SCTP_RCVINFO   struct sctp_rcvinfo
+ *
+ */
+struct sctp_rcvinfo {
+	__u16 rcv_sid;
+	__u16 rcv_ssn;
+	__u16 rcv_flags;
+	__u32 rcv_ppid;
+	__u32 rcv_tsn;
+	__u32 rcv_cumtsn;
+	__u32 rcv_context;
+	sctp_assoc_t rcv_assoc_id;
+};
+
+/*
  *  sinfo_flags: 16 bits (unsigned integer)
  *
  *   This field may contain any of the following flags and is composed of
@@ -184,6 +205,8 @@ typedef enum sctp_cmsg_type {
 #define SCTP_INIT	SCTP_INIT
 	SCTP_SNDRCV,            /* 5.2.2 SCTP Header Information Structure */
 #define SCTP_SNDRCV	SCTP_SNDRCV
+	SCTP_RCVINFO,
+#define SCTP_RCVINFO SCTP_RCVINFO
 } sctp_cmsg_t;
 
 /*
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1f3281b..aee161b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2094,6 +2094,12 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
 		sp->pf->skb_msgname(skb, msg->msg_name, addr_len);
 	}
 
+
+	/* Check if SCTP_RCVINFO should be included */
+	if(sp->recvrcvinfo){
+		sctp_ulpevent_read_rcvinfo(event, msg);
+	}
+
 	/* Check if we allow SCTP_SNDRCVINFO. */
 	if (sp->subscribe.sctp_data_io_event)
 		sctp_ulpevent_read_sndrcvinfo(event, msg);
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 81089ed..d1b9a02 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -900,6 +900,97 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event)
 	return notification->sn_header.sn_type;
 }
 
+void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event,
+		struct msghdr *msghdr)
+{
+	struct sctp_rcvinfo rinfo;
+
+	if (sctp_ulpevent_is_notification(event)){
+		return;
+	}
+
As David Laight mentioned, the spec defines sctp_rcvinfo with a hole in it.
To prevent passing kernel stack data to user space, you need to zero-out the
data first.

-vlad
+	/* Sockets API Extensions for SCTP
+	 * Section 5.3.5 SCTP Receive Information Structure (SCTP_SNDRCV)
+	 *
+	 * rcv_sid: 16 bits (unsigned integer)
+	 *
+	 * The SCTP stack places the message's stream number in this
+	 * value.
+	 */
+	rinfo.rcv_sid = event->stream;
+
+	/* rcv_ssn: 16 bits (unsigned integer)
+	 * This value contains the stream sequence number that the
+	 * remote endpoint placed in the DATA chunk.  For fragmented
+	 * messages, this is the same number for all deliveries of the
+	 * message (if more than one recvmsg() is needed to read
+	 * the message)
+	 */
+	rinfo.rcv_ssn = event->ssn;
+
+
+	/* rcv_ppid: 32 bits (unsigned integer)
+	 *
+	 * This value is the same information that was passed by the
+	 * upper layer in the peer application.  Please note that the SCTP
+	 * stack performs no byte order modification of this field.
+	 * For example, if the DATA chunk has to contain a given
+	 * value in network byte order, the SCTP user has to perform the
+	 * ntohl() computation.
+	 */
+	rinfo.rcv_ppid = event->ppid;
+
+	/* rcv_flags: 16 bits (unsigned integer)
+	 *
+	 * This field may contain any of the following flags and is composed of
+	 * a bitwise OR of these values.
+	 *
+	 * recvmsg() flags:
+	 *
+	 * SCTP_UNORDERED - This flag is present when the message was sent
+	 *                 non-ordered.
+	 */
+
+	rinfo.rcv_flags = event->flags;
+
+	/* rcv_tsn: 32 bits (unsigned integer)
+	 *
+	 * This field holds a TSN that was assigned to one of the SCTP
+	 * DATA chunks.
+	 */
+	rinfo.rcv_tsn = event->tsn;
+
+	/* rcv_cumtsn: 32 bits (unsigned integer)
+	 *
+	 * This field will hold the current cumulative TSN as known
+	 * by the underlying SCTP layer.
+	 */
+	rinfo.rcv_cumtsn = event->cumtsn;
+
+	/* rcv_assoc_id: sizeof (sctp_assoc_t)
+	 *
+	 * The association handle field, sinfo_assoc_id, holds the identifier
+	 * for the association announced in the COMMUNICATION_UP notification.
+	 * All notifications for a given association have the same identifier.
+	 * Ignored for one-to-one style sockets.
+	 */
+	rinfo.rcv_assoc_id = sctp_assoc2id(event->asoc);
+
+	/* rcv_context: 32 bits (unsigned integer)
+	 *
+	 * This value is an opaque 32-bit context datum that was
+	 * set by the user with the SCTP_CONTEXT socket option.  This
+	 * value is passed back to the upper layer if an error occurs on
+	 * the send of a message and is retrieved with each undelivered
+	 * message.
+	 */
+	rinfo.rcv_context = event->asoc->default_rcv_context;
+
+	put_cmsg(msghdr, IPPROTO_SCTP, SCTP_RCVINFO,
+			sizeof(struct sctp_rcvinfo), (void *)&rinfo);
+}
+
+
 /* Copy out the sndrcvinfo into a msghdr.  */
 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
 				   struct msghdr *msghdr)

Re: [PATCH net-next 3/6] Support for SCTP_SNDINFO ancillary data

From: Vlad Yasevich <hidden>
Date: 2014-06-17 14:29:11

On 06/17/2014 08:38 AM, David Laight wrote:
From: Geir Ola Vaagland
...
quoted
+		case SCTP_SNDINFO:
+			/* SCTP Socket API Extension
+			 * 5.3.4 SCTP Send Information Structure (SCTP_SNDINFO)
+			 *
+			 * This cmsghdr structure specifies SCTP options for
+			 * sendmsg(). This structure and SCTP_RCVINFO replaces
+			 * SCTP_SNDRCV which has been depleted.
What do you mean by 'depleted'?
I think he meant deprecated.

-vlad
Support for it cannot be removed because it will break existing
applications.

	David

RE: [PATCH net-next 3/6] Support for SCTP_SNDINFO ancillary data

From: David Laight <hidden>
Date: 2014-06-17 14:43:32

From: Vlad Yasevich
On 06/17/2014 08:38 AM, David Laight wrote:
quoted
From: Geir Ola Vaagland
...
quoted
+		case SCTP_SNDINFO:
+			/* SCTP Socket API Extension
+			 * 5.3.4 SCTP Send Information Structure (SCTP_SNDINFO)
+			 *
+			 * This cmsghdr structure specifies SCTP options for
+			 * sendmsg(). This structure and SCTP_RCVINFO replaces
+			 * SCTP_SNDRCV which has been depleted.
What do you mean by 'depleted'?
I think he meant deprecated.
Hmm.... that isn't going to work well, is it!

I presume the 'standard' only requires that the structure contain
the required fields?
Which probably means it could contain the required padding to make
it binary compatible with the existing 'struct sctp_sndrcvinfo'
(which also contains pad bytes!)

	David
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help