svn commit: r270357 - in stable/10: lib/libc/net sys/netinet

Michael Tuexen tuexen at FreeBSD.org
Fri Aug 22 20:01:39 UTC 2014


Author: tuexen
Date: Fri Aug 22 20:01:35 2014
New Revision: 270357
URL: http://svnweb.freebsd.org/changeset/base/270357

Log:
  MFC r269448:
  
  Add support for the SCTP_PR_SUPPORTED socket option as specified in
  http://tools.ietf.org/html/draft-ietf-tsvwg-sctp-prpolicies
  Add also a sysctl controlling the default of the end-points.

Modified:
  stable/10/lib/libc/net/sctp_sys_calls.c
  stable/10/sys/netinet/sctp.h
  stable/10/sys/netinet/sctp_indata.c
  stable/10/sys/netinet/sctp_input.c
  stable/10/sys/netinet/sctp_output.c
  stable/10/sys/netinet/sctp_pcb.c
  stable/10/sys/netinet/sctp_pcb.h
  stable/10/sys/netinet/sctp_peeloff.c
  stable/10/sys/netinet/sctp_structs.h
  stable/10/sys/netinet/sctp_sysctl.c
  stable/10/sys/netinet/sctp_sysctl.h
  stable/10/sys/netinet/sctp_timer.c
  stable/10/sys/netinet/sctp_usrreq.c
  stable/10/sys/netinet/sctputil.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/net/sctp_sys_calls.c
==============================================================================
--- stable/10/lib/libc/net/sctp_sys_calls.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/lib/libc/net/sctp_sys_calls.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -353,6 +353,9 @@ sctp_opt_info(int sd, sctp_assoc_t id, i
 	case SCTP_ECN_SUPPORTED:
 		((struct sctp_assoc_value *)arg)->assoc_id = id;
 		break;
+	case SCTP_PR_SUPPORTED:
+		((struct sctp_assoc_value *)arg)->assoc_id = id;
+		break;
 	case SCTP_MAX_BURST:
 		((struct sctp_assoc_value *)arg)->assoc_id = id;
 		break;

Modified: stable/10/sys/netinet/sctp.h
==============================================================================
--- stable/10/sys/netinet/sctp.h	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp.h	Fri Aug 22 20:01:35 2014	(r270357)
@@ -122,6 +122,7 @@ struct sctp_paramhdr {
 #define SCTP_PEER_ADDR_THLDS            0x00000023
 #define SCTP_REMOTE_UDP_ENCAPS_PORT     0x00000024
 #define SCTP_ECN_SUPPORTED              0x00000025
+#define SCTP_PR_SUPPORTED               0x00000026
 
 /*
  * read-only options

Modified: stable/10/sys/netinet/sctp_indata.c
==============================================================================
--- stable/10/sys/netinet/sctp_indata.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_indata.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -2960,7 +2960,7 @@ sctp_strike_gap_ack_chunks(struct sctp_t
 				num_dests_sacked++;
 		}
 	}
-	if (stcb->asoc.peer_supports_prsctp) {
+	if (stcb->asoc.prsctp_supported) {
 		(void)SCTP_GETTIME_TIMEVAL(&now);
 	}
 	TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
@@ -2981,7 +2981,7 @@ sctp_strike_gap_ack_chunks(struct sctp_t
 			/* done */
 			break;
 		}
-		if (stcb->asoc.peer_supports_prsctp) {
+		if (stcb->asoc.prsctp_supported) {
 			if ((PR_SCTP_TTL_ENABLED(tp1->flags)) && tp1->sent < SCTP_DATAGRAM_ACKED) {
 				/* Is it expired? */
 				if (timevalcmp(&now, &tp1->rec.data.timetodrop, >)) {
@@ -3235,7 +3235,7 @@ sctp_strike_gap_ack_chunks(struct sctp_t
 			/* remove from the total flight */
 			sctp_total_flight_decrease(stcb, tp1);
 
-			if ((stcb->asoc.peer_supports_prsctp) &&
+			if ((stcb->asoc.prsctp_supported) &&
 			    (PR_SCTP_RTX_ENABLED(tp1->flags))) {
 				/*
 				 * Has it been retransmitted tv_sec times? -
@@ -3380,7 +3380,7 @@ sctp_try_advance_peer_ack_point(struct s
 	struct timeval now;
 	int now_filled = 0;
 
-	if (asoc->peer_supports_prsctp == 0) {
+	if (asoc->prsctp_supported == 0) {
 		return (NULL);
 	}
 	TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
@@ -4042,7 +4042,7 @@ again:
 		asoc->advanced_peer_ack_point = cumack;
 	}
 	/* PR-Sctp issues need to be addressed too */
-	if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) {
+	if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) {
 		struct sctp_tmit_chunk *lchk;
 		uint32_t old_adv_peer_ack_point;
 
@@ -4479,7 +4479,7 @@ sctp_handle_sack(struct mbuf *m, int off
 			sctp_free_bufspace(stcb, asoc, tp1, 1);
 			sctp_m_freem(tp1->data);
 			tp1->data = NULL;
-			if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) {
+			if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(tp1->flags)) {
 				asoc->sent_queue_cnt_removeable--;
 			}
 		}
@@ -4891,7 +4891,7 @@ again:
 		asoc->advanced_peer_ack_point = cum_ack;
 	}
 	/* C2. try to further move advancedPeerAckPoint ahead */
-	if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) {
+	if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) {
 		struct sctp_tmit_chunk *lchk;
 		uint32_t old_adv_peer_ack_point;
 

Modified: stable/10/sys/netinet/sctp_input.c
==============================================================================
--- stable/10/sys/netinet/sctp_input.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_input.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -1082,7 +1082,7 @@ sctp_process_unrecog_chunk(struct sctp_t
 		sctp_asconf_cleanup(stcb, net);
 		break;
 	case SCTP_FORWARD_CUM_TSN:
-		stcb->asoc.peer_supports_prsctp = 0;
+		stcb->asoc.prsctp_supported = 0;
 		break;
 	default:
 		SCTPDBG(SCTP_DEBUG_INPUT2,
@@ -1106,7 +1106,7 @@ sctp_process_unrecog_param(struct sctp_t
 	switch (ntohs(pbad->param_type)) {
 		/* pr-sctp draft */
 	case SCTP_PRSCTP_SUPPORTED:
-		stcb->asoc.peer_supports_prsctp = 0;
+		stcb->asoc.prsctp_supported = 0;
 		break;
 	case SCTP_SUPPORTED_CHUNK_EXT:
 		break;
@@ -2786,6 +2786,7 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 			inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
 			inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
 			inp->ecn_supported = (*inp_p)->ecn_supported;
+			inp->prsctp_supported = (*inp_p)->prsctp_supported;
 			inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
 			inp->sctp_context = (*inp_p)->sctp_context;
 			inp->local_strreset_support = (*inp_p)->local_strreset_support;

Modified: stable/10/sys/netinet/sctp_output.c
==============================================================================
--- stable/10/sys/netinet/sctp_output.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_output.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -4792,13 +4792,14 @@ sctp_send_initiate(struct sctp_inpcb *in
 		ph->param_length = htons(parameter_len);
 		chunk_len += parameter_len;
 	}
-	/* And now tell the peer we do support PR-SCTP. */
-	parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
-	ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
-	ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
-	ph->param_length = htons(parameter_len);
-	chunk_len += parameter_len;
-
+	/* PR-SCTP supported parameter */
+	if (stcb->asoc.prsctp_supported == 1) {
+		parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
+		ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
+		ph->param_length = htons(parameter_len);
+		chunk_len += parameter_len;
+	}
 	/* Add NAT friendly parameter. */
 	if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
 		parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
@@ -4813,7 +4814,9 @@ sctp_send_initiate(struct sctp_inpcb *in
 	pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
 	pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
 	pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
-	pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+	if (stcb->asoc.prsctp_supported == 1) {
+		pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+	}
 	pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
 	pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
 	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
@@ -5890,13 +5893,15 @@ do_a_abort:
 		ph->param_length = htons(parameter_len);
 		chunk_len += parameter_len;
 	}
-	/* And now tell the peer we do pr-sctp */
-	parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
-	ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
-	ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
-	ph->param_length = htons(parameter_len);
-	chunk_len += parameter_len;
-
+	/* PR-SCTP supported parameter */
+	if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
+	    ((asoc == NULL) && (inp->prsctp_supported == 1))) {
+		parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
+		ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
+		ph->param_length = htons(parameter_len);
+		chunk_len += parameter_len;
+	}
 	/* Add NAT friendly parameter */
 	if (nat_friendly) {
 		parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
@@ -5911,7 +5916,10 @@ do_a_abort:
 	pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
 	pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
 	pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
-	pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+	if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
+	    ((asoc == NULL) && (inp->prsctp_supported == 1))) {
+		pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+	}
 	pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
 	pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
 	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
@@ -6093,7 +6101,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
 	struct sctp_tmit_chunk *chk, *nchk;
 
 	SCTP_TCB_LOCK_ASSERT(stcb);
-	if ((asoc->peer_supports_prsctp) &&
+	if ((asoc->prsctp_supported) &&
 	    (asoc->sent_queue_cnt_removeable > 0)) {
 		TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
 			/*
@@ -12948,7 +12956,7 @@ skip_preblock:
 				continue;
 			}
 			/* PR-SCTP? */
-			if ((asoc->peer_supports_prsctp) && (asoc->sent_queue_cnt_removeable > 0)) {
+			if ((asoc->prsctp_supported) && (asoc->sent_queue_cnt_removeable > 0)) {
 				/*
 				 * This is ugly but we must assure locking
 				 * order

Modified: stable/10/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_pcb.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -2484,6 +2484,7 @@ sctp_inpcb_alloc(struct socket *so, uint
 	inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
 	inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
 	inp->ecn_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_ecn_enable);
+	inp->prsctp_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pr_enable);
 	/* init the small hash table we use to track asocid <-> tcb */
 	inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark);
 	if (inp->sctp_asocidhash == NULL) {
@@ -6082,6 +6083,7 @@ sctp_load_addresses_from_init(struct sct
 	uint32_t keylen;
 	int got_random = 0, got_hmacs = 0, got_chklist = 0;
 	uint8_t ecn_supported;
+	uint8_t prsctp_supported;
 
 #ifdef INET
 	struct sockaddr_in sin;
@@ -6112,6 +6114,7 @@ sctp_load_addresses_from_init(struct sct
 	}
 	/* Turn off ECN until we get through all params */
 	ecn_supported = 0;
+	prsctp_supported = 0;
 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
 		/* mark all addresses that we have currently on the list */
 		net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC;
@@ -6436,7 +6439,7 @@ sctp_load_addresses_from_init(struct sct
 			stcb->asoc.peer_supports_nat = 1;
 		} else if (ptype == SCTP_PRSCTP_SUPPORTED) {
 			/* Peer supports pr-sctp */
-			stcb->asoc.peer_supports_prsctp = 1;
+			prsctp_supported = 1;
 		} else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
 			/* A supported extension chunk */
 			struct sctp_supported_chunk_types_param *pr_supported;
@@ -6449,7 +6452,6 @@ sctp_load_addresses_from_init(struct sct
 				return (-25);
 			}
 			stcb->asoc.peer_supports_asconf = 0;
-			stcb->asoc.peer_supports_prsctp = 0;
 			stcb->asoc.peer_supports_pktdrop = 0;
 			stcb->asoc.peer_supports_strreset = 0;
 			stcb->asoc.peer_supports_nr_sack = 0;
@@ -6463,7 +6465,7 @@ sctp_load_addresses_from_init(struct sct
 					stcb->asoc.peer_supports_asconf = 1;
 					break;
 				case SCTP_FORWARD_CUM_TSN:
-					stcb->asoc.peer_supports_prsctp = 1;
+					prsctp_supported = 1;
 					break;
 				case SCTP_PACKET_DROPPED:
 					stcb->asoc.peer_supports_pktdrop = 1;
@@ -6613,6 +6615,7 @@ next_param:
 		}
 	}
 	stcb->asoc.ecn_supported &= ecn_supported;
+	stcb->asoc.prsctp_supported &= prsctp_supported;
 	/* validate authentication required parameters */
 	if (got_random && got_hmacs) {
 		stcb->asoc.peer_supports_auth = 1;

Modified: stable/10/sys/netinet/sctp_pcb.h
==============================================================================
--- stable/10/sys/netinet/sctp_pcb.h	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_pcb.h	Fri Aug 22 20:01:35 2014	(r270357)
@@ -407,6 +407,7 @@ struct sctp_inpcb {
 	uint8_t local_strreset_support;
 	uint32_t sctp_cmt_on_off;
 	uint8_t ecn_supported;
+	uint8_t prsctp_supported;
 	struct sctp_nonpad_sndrcvinfo def_send;
 	/*-
 	 * These three are here for the sosend_dgram

Modified: stable/10/sys/netinet/sctp_peeloff.c
==============================================================================
--- stable/10/sys/netinet/sctp_peeloff.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_peeloff.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -119,6 +119,7 @@ sctp_do_peeloff(struct socket *head, str
 	n_inp->sctp_frag_point = inp->sctp_frag_point;
 	n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
 	n_inp->ecn_supported = inp->ecn_supported;
+	n_inp->prsctp_supported = inp->prsctp_supported;
 	n_inp->partial_delivery_point = inp->partial_delivery_point;
 	n_inp->sctp_context = inp->sctp_context;
 	n_inp->local_strreset_support = inp->local_strreset_support;

Modified: stable/10/sys/netinet/sctp_structs.h
==============================================================================
--- stable/10/sys/netinet/sctp_structs.h	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_structs.h	Fri Aug 22 20:01:35 2014	(r270357)
@@ -1150,8 +1150,9 @@ struct sctp_association {
 	 * sum is updated as well.
 	 */
 
-	/* Flag to tell if ECN is allowed */
+	/* Flags whether an extension is supported or not */
 	uint8_t ecn_supported;
+	uint8_t prsctp_supported;
 
 	/* Did the peer make the stream config (add out) request */
 	uint8_t peer_req_out;
@@ -1160,8 +1161,6 @@ struct sctp_association {
 	uint8_t peer_supports_asconf;
 	/* EY - flag to indicate if peer can do nr_sack */
 	uint8_t peer_supports_nr_sack;
-	/* pr-sctp support flag */
-	uint8_t peer_supports_prsctp;
 	/* peer authentication support flag */
 	uint8_t peer_supports_auth;
 	/* stream resets are supported by the peer */

Modified: stable/10/sys/netinet/sctp_sysctl.c
==============================================================================
--- stable/10/sys/netinet/sctp_sysctl.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_sysctl.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -55,6 +55,7 @@ sctp_init_sysctls()
 	SCTP_BASE_SYSCTL(sctp_auto_asconf) = SCTPCTL_AUTOASCONF_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = SCTPCTL_MULTIPLEASCONFS_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
+	SCTP_BASE_SYSCTL(sctp_pr_enable) = SCTPCTL_PR_ENABLE_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_peer_chunk_oh) = SCTPCTL_PEER_CHKOH_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_max_burst_default) = SCTPCTL_MAXBURST_DEFAULT;
@@ -602,6 +603,7 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_recvspace), SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
+		RANGECHK(SCTP_BASE_SYSCTL(sctp_pr_enable), SCTPCTL_PR_ENABLE_MIN, SCTPCTL_PR_ENABLE_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX);
@@ -863,6 +865,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUT
     &SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sysctl_sctp_check, "IU",
     SCTPCTL_ECN_ENABLE_DESC);
 
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pr_enable, CTLTYPE_UINT | CTLFLAG_RW,
+    &SCTP_BASE_SYSCTL(sctp_pr_enable), 0, sysctl_sctp_check, "IU",
+    SCTPCTL_PR_ENABLE_DESC);
+
 SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT | CTLFLAG_RW,
     &SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, "IU",
     SCTPCTL_STRICT_SACKS_DESC);

Modified: stable/10/sys/netinet/sctp_sysctl.h
==============================================================================
--- stable/10/sys/netinet/sctp_sysctl.h	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_sysctl.h	Fri Aug 22 20:01:35 2014	(r270357)
@@ -45,6 +45,7 @@ struct sctp_sysctl {
 	uint32_t sctp_auto_asconf;
 	uint32_t sctp_multiple_asconfs;
 	uint32_t sctp_ecn_enable;
+	uint32_t sctp_pr_enable;
 	uint32_t sctp_fr_max_burst_default;
 	uint32_t sctp_strict_sacks;
 	uint32_t sctp_peer_chunk_oh;
@@ -154,6 +155,12 @@ struct sctp_sysctl {
 #define SCTPCTL_ECN_ENABLE_MAX		1
 #define SCTPCTL_ECN_ENABLE_DEFAULT	1
 
+/* pr_enable: Enable PR-SCTP */
+#define SCTPCTL_PR_ENABLE_DESC		"Enable PR-SCTP"
+#define SCTPCTL_PR_ENABLE_MIN		0
+#define SCTPCTL_PR_ENABLE_MAX		1
+#define SCTPCTL_PR_ENABLE_DEFAULT	1
+
 /* strict_sacks: Enable SCTP Strict SACK checking */
 #define SCTPCTL_STRICT_SACKS_DESC	"Enable SCTP Strict SACK checking"
 #define SCTPCTL_STRICT_SACKS_MIN	0

Modified: stable/10/sys/netinet/sctp_timer.c
==============================================================================
--- stable/10/sys/netinet/sctp_timer.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_timer.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -445,7 +445,7 @@ sctp_recover_sent_list(struct sctp_tcb *
 				sctp_free_bufspace(stcb, asoc, chk, 1);
 				sctp_m_freem(chk->data);
 				chk->data = NULL;
-				if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) {
+				if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(chk->flags)) {
 					asoc->sent_queue_cnt_removeable--;
 				}
 			}
@@ -600,7 +600,7 @@ start_again:
 					continue;
 				}
 			}
-			if (stcb->asoc.peer_supports_prsctp && PR_SCTP_TTL_ENABLED(chk->flags)) {
+			if (stcb->asoc.prsctp_supported && PR_SCTP_TTL_ENABLED(chk->flags)) {
 				/* Is it expired? */
 				if (timevalcmp(&now, &chk->rec.data.timetodrop, >)) {
 					/* Yes so drop it */
@@ -614,7 +614,7 @@ start_again:
 					continue;
 				}
 			}
-			if (stcb->asoc.peer_supports_prsctp && PR_SCTP_RTX_ENABLED(chk->flags)) {
+			if (stcb->asoc.prsctp_supported && PR_SCTP_RTX_ENABLED(chk->flags)) {
 				/* Has it been retransmitted tv_sec times? */
 				if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) {
 					if (chk->data) {
@@ -957,7 +957,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
 		sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
 		return (0);
 	}
-	if (stcb->asoc.peer_supports_prsctp) {
+	if (stcb->asoc.prsctp_supported) {
 		struct sctp_tmit_chunk *lchk;
 
 		lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);

Modified: stable/10/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/10/sys/netinet/sctp_usrreq.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctp_usrreq.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -3321,6 +3321,33 @@ flags_out:
 			}
 			break;
 		}
+	case SCTP_PR_SUPPORTED:
+		{
+			struct sctp_assoc_value *av;
+
+			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+			if (stcb) {
+				av->assoc_value = stcb->asoc.prsctp_supported;
+				SCTP_TCB_UNLOCK(stcb);
+			} else {
+				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+					SCTP_INP_RLOCK(inp);
+					av->assoc_value = inp->prsctp_supported;
+					SCTP_INP_RUNLOCK(inp);
+				} else {
+					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+					error = EINVAL;
+				}
+			}
+			if (error == 0) {
+				*optsize = sizeof(struct sctp_assoc_value);
+			}
+			break;
+		}
 	case SCTP_ENABLE_STREAM_RESET:
 		{
 			struct sctp_assoc_value *av;
@@ -5913,6 +5940,35 @@ sctp_setopt(struct socket *so, int optna
 			}
 			break;
 		}
+	case SCTP_PR_SUPPORTED:
+		{
+			struct sctp_assoc_value *av;
+
+			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
+
+			if (stcb) {
+				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+				error = EINVAL;
+				SCTP_TCB_UNLOCK(stcb);
+			} else {
+				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+				    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
+					SCTP_INP_WLOCK(inp);
+					if (av->assoc_value == 0) {
+						inp->prsctp_supported = 0;
+					} else {
+						inp->prsctp_supported = 1;
+					}
+					SCTP_INP_WUNLOCK(inp);
+				} else {
+					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+					error = EINVAL;
+				}
+			}
+			break;
+		}
 	default:
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
 		error = ENOPROTOOPT;

Modified: stable/10/sys/netinet/sctputil.c
==============================================================================
--- stable/10/sys/netinet/sctputil.c	Fri Aug 22 19:57:39 2014	(r270356)
+++ stable/10/sys/netinet/sctputil.c	Fri Aug 22 20:01:35 2014	(r270357)
@@ -905,6 +905,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, s
 	asoc->cookie_life = inp->sctp_ep.def_cookie_life;
 	asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
 	asoc->ecn_supported = inp->ecn_supported;
+	asoc->prsctp_supported = inp->prsctp_supported;
 	asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
 	asoc->sctp_cmt_pf = (uint8_t) 0;
 	asoc->sctp_frag_point = inp->sctp_frag_point;
@@ -2620,7 +2621,7 @@ sctp_notify_assoc_change(uint16_t state,
 		if (notif_len > sizeof(struct sctp_assoc_change)) {
 			if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
 				i = 0;
-				if (stcb->asoc.peer_supports_prsctp) {
+				if (stcb->asoc.prsctp_supported) {
 					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
 				}
 				if (stcb->asoc.peer_supports_auth) {


More information about the svn-src-all mailing list