Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Aug 2014 11:30:17 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r269858 - in head: lib/libc/net sys/netinet
Message-ID:  <53e9fac9.6e09.1cc546b0@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tuexen
Date: Tue Aug 12 11:30:16 2014
New Revision: 269858
URL: http://svnweb.freebsd.org/changeset/base/269858

Log:
  Add support for the SCTP_AUTH_SUPPORTED and SCTP_ASCONF_SUPPORTED
  socket options. Add also a sysctl to control the support of ASCONF.
  
  MFC after: 1 week

Modified:
  head/lib/libc/net/sctp_sys_calls.c
  head/sys/netinet/sctp.h
  head/sys/netinet/sctp_asconf.c
  head/sys/netinet/sctp_auth.c
  head/sys/netinet/sctp_auth.h
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctp_pcb.c
  head/sys/netinet/sctp_pcb.h
  head/sys/netinet/sctp_peeloff.c
  head/sys/netinet/sctp_structs.h
  head/sys/netinet/sctp_sysctl.c
  head/sys/netinet/sctp_sysctl.h
  head/sys/netinet/sctp_usrreq.c
  head/sys/netinet/sctputil.c

Modified: head/lib/libc/net/sctp_sys_calls.c
==============================================================================
--- head/lib/libc/net/sctp_sys_calls.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/lib/libc/net/sctp_sys_calls.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -356,6 +356,12 @@ sctp_opt_info(int sd, sctp_assoc_t id, i
 	case SCTP_PR_SUPPORTED:
 		((struct sctp_assoc_value *)arg)->assoc_id = id;
 		break;
+	case SCTP_AUTH_SUPPORTED:
+		((struct sctp_assoc_value *)arg)->assoc_id = id;
+		break;
+	case SCTP_ASCONF_SUPPORTED:
+		((struct sctp_assoc_value *)arg)->assoc_id = id;
+		break;
 	case SCTP_RECONFIG_SUPPORTED:
 		((struct sctp_assoc_value *)arg)->assoc_id = id;
 		break;
@@ -590,6 +596,7 @@ sctp_sendmsg(int s,
 	cmsg->cmsg_type = SCTP_SNDRCV;
 	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
 	sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+	memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
 	sinfo->sinfo_stream = stream_no;
 	sinfo->sinfo_ssn = 0;
 	sinfo->sinfo_flags = flags;

Modified: head/sys/netinet/sctp.h
==============================================================================
--- head/sys/netinet/sctp.h	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp.h	Tue Aug 12 11:30:16 2014	(r269858)
@@ -123,9 +123,11 @@ struct sctp_paramhdr {
 #define SCTP_REMOTE_UDP_ENCAPS_PORT     0x00000024
 #define SCTP_ECN_SUPPORTED              0x00000025
 #define SCTP_PR_SUPPORTED               0x00000026
-#define SCTP_NRSACK_SUPPORTED           0x00000027
-#define SCTP_PKTDROP_SUPPORTED          0x00000028
+#define SCTP_AUTH_SUPPORTED             0x00000027
+#define SCTP_ASCONF_SUPPORTED           0x00000028
 #define SCTP_RECONFIG_SUPPORTED         0x00000029
+#define SCTP_NRSACK_SUPPORTED           0x00000030
+#define SCTP_PKTDROP_SUPPORTED          0x00000031
 
 /*
  * read-only options

Modified: head/sys/netinet/sctp_asconf.c
==============================================================================
--- head/sys/netinet/sctp_asconf.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_asconf.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -724,13 +724,11 @@ sctp_handle_asconf(struct mbuf *m, unsig
 		}
 		switch (param_type) {
 		case SCTP_ADD_IP_ADDRESS:
-			asoc->peer_supports_asconf = 1;
 			m_result = sctp_process_asconf_add_ip(src, aph, stcb,
 			    (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
 			cnt++;
 			break;
 		case SCTP_DEL_IP_ADDRESS:
-			asoc->peer_supports_asconf = 1;
 			m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
 			    error);
 			break;
@@ -738,7 +736,6 @@ sctp_handle_asconf(struct mbuf *m, unsig
 			/* not valid in an ASCONF chunk */
 			break;
 		case SCTP_SET_PRIM_ADDR:
-			asoc->peer_supports_asconf = 1;
 			m_result = sctp_process_asconf_set_primary(src, aph,
 			    stcb, error);
 			break;
@@ -930,8 +927,6 @@ sctp_addr_match(struct sctp_paramhdr *ph
 void
 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
 {
-	/* mark peer as ASCONF incapable */
-	stcb->asoc.peer_supports_asconf = 0;
 	/*
 	 * clear out any existing asconfs going out
 	 */
@@ -1340,7 +1335,7 @@ sctp_asconf_queue_add(struct sctp_tcb *s
 	int pending_delete_queued = 0;
 
 	/* see if peer supports ASCONF */
-	if (stcb->asoc.peer_supports_asconf == 0) {
+	if (stcb->asoc.asconf_supported == 0) {
 		return (-1);
 	}
 	/*
@@ -1430,7 +1425,7 @@ sctp_asconf_queue_sa_delete(struct sctp_
 		return (-1);
 	}
 	/* see if peer supports ASCONF */
-	if (stcb->asoc.peer_supports_asconf == 0) {
+	if (stcb->asoc.asconf_supported == 0) {
 		return (-1);
 	}
 	/* make sure the request isn't already in the queue */
@@ -1550,7 +1545,7 @@ sctp_asconf_find_param(struct sctp_tcb *
  * notifications based on the error response
  */
 static void
-sctp_asconf_process_error(struct sctp_tcb *stcb,
+sctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED,
     struct sctp_asconf_paramhdr *aph)
 {
 	struct sctp_error_cause *eh;
@@ -1588,10 +1583,7 @@ sctp_asconf_process_error(struct sctp_tc
 		switch (param_type) {
 		case SCTP_ADD_IP_ADDRESS:
 		case SCTP_DEL_IP_ADDRESS:
-			stcb->asoc.peer_supports_asconf = 0;
-			break;
 		case SCTP_SET_PRIM_ADDR:
-			stcb->asoc.peer_supports_asconf = 0;
 			break;
 		default:
 			break;
@@ -1627,8 +1619,6 @@ sctp_asconf_process_param_ack(struct sct
 		SCTPDBG(SCTP_DEBUG_ASCONF1,
 		    "process_param_ack: set primary IP address\n");
 		/* nothing to do... peer may start using this addr */
-		if (flag == 0)
-			stcb->asoc.peer_supports_asconf = 0;
 		break;
 	default:
 		/* should NEVER happen */
@@ -1646,11 +1636,11 @@ sctp_asconf_process_param_ack(struct sct
  * cleanup from a bad asconf ack parameter
  */
 static void
-sctp_asconf_ack_clear(struct sctp_tcb *stcb)
+sctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED)
 {
 	/* assume peer doesn't really know how to do asconfs */
-	stcb->asoc.peer_supports_asconf = 0;
 	/* XXX we could free the pending queue here */
+
 }
 
 void
@@ -1988,7 +1978,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *
 	/* queue an asconf for this address add/delete */
 	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
 		/* does the peer do asconf? */
-		if (stcb->asoc.peer_supports_asconf) {
+		if (stcb->asoc.asconf_supported) {
 			/* queue an asconf for this addr */
 			status = sctp_asconf_queue_add(stcb, ifa, type);
 
@@ -2238,7 +2228,7 @@ sctp_asconf_iterator_stcb(struct sctp_in
 		}
 		/* queue an asconf for this address add/delete */
 		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
-		    stcb->asoc.peer_supports_asconf) {
+		    stcb->asoc.asconf_supported == 1) {
 			/* queue an asconf for this addr */
 			status = sctp_asconf_queue_add(stcb, ifa, type);
 			/*
@@ -2886,7 +2876,7 @@ sctp_process_initack_addresses(struct sc
 			/* are ASCONFs allowed ? */
 			if ((sctp_is_feature_on(stcb->sctp_ep,
 			    SCTP_PCB_FLAGS_DO_ASCONF)) &&
-			    stcb->asoc.peer_supports_asconf) {
+			    stcb->asoc.asconf_supported) {
 				/* queue an ASCONF DEL_IP_ADDRESS */
 				status = sctp_asconf_queue_sa_delete(stcb, sa);
 				/*

Modified: head/sys/netinet/sctp_auth.c
==============================================================================
--- head/sys/netinet/sctp_auth.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_auth.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -133,11 +133,6 @@ sctp_auth_delete_chunk(uint8_t chunk, sc
 	if (list == NULL)
 		return (-1);
 
-	/* is chunk restricted? */
-	if ((chunk == SCTP_ASCONF) ||
-	    (chunk == SCTP_ASCONF_ACK)) {
-		return (-1);
-	}
 	if (list->chunks[chunk] == 1) {
 		list->chunks[chunk] = 0;
 		list->num_chunks--;
@@ -158,16 +153,6 @@ sctp_auth_get_chklist_size(const sctp_au
 }
 
 /*
- * set the default list of chunks requiring AUTH
- */
-void
-sctp_auth_set_default_chunks(sctp_auth_chklist_t * list)
-{
-	(void)sctp_auth_add_chunk(SCTP_ASCONF, list);
-	(void)sctp_auth_add_chunk(SCTP_ASCONF_ACK, list);
-}
-
-/*
  * return the current number and list of required chunks caller must
  * guarantee ptr has space for up to 256 bytes
  */

Modified: head/sys/netinet/sctp_auth.h
==============================================================================
--- head/sys/netinet/sctp_auth.h	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_auth.h	Tue Aug 12 11:30:16 2014	(r269858)
@@ -112,7 +112,6 @@ extern sctp_auth_chklist_t *sctp_copy_ch
 extern int sctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t * list);
 extern int sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t * list);
 extern size_t sctp_auth_get_chklist_size(const sctp_auth_chklist_t * list);
-extern void sctp_auth_set_default_chunks(sctp_auth_chklist_t * list);
 extern int 
 sctp_serialize_auth_chunks(const sctp_auth_chklist_t * list,
     uint8_t * ptr);

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_input.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -480,7 +480,7 @@ sctp_process_init_ack(struct mbuf *m, in
 		return (-1);
 	}
 	/* if the peer doesn't support asconf, flush the asconf queue */
-	if (asoc->peer_supports_asconf == 0) {
+	if (asoc->asconf_supported == 0) {
 		struct sctp_asconf_addr *param, *nparam;
 
 		TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) {
@@ -756,7 +756,7 @@ sctp_handle_nat_missing_state(struct sct
 	 * return 0 means we want you to proceed with the abort non-zero
 	 * means no abort processing
 	 */
-	if (stcb->asoc.peer_supports_auth == 0) {
+	if (stcb->asoc.auth_supported == 0) {
 		SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n");
 		return (0);
 	}
@@ -1096,6 +1096,7 @@ sctp_process_unrecog_chunk(struct sctp_t
  * Skip past the param header and then we will find the param that caused the
  * problem.  There are a number of param's in a ASCONF OR the prsctp param
  * these will turn of specific features.
+ * XXX: Is this the right thing to do?
  */
 static void
 sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
@@ -1117,14 +1118,14 @@ sctp_process_unrecog_param(struct sctp_t
 	case SCTP_ADD_IP_ADDRESS:
 	case SCTP_DEL_IP_ADDRESS:
 	case SCTP_SET_PRIM_ADDR:
-		stcb->asoc.peer_supports_asconf = 0;
+		stcb->asoc.asconf_supported = 0;
 		break;
 	case SCTP_SUCCESS_REPORT:
 	case SCTP_ERROR_CAUSE_IND:
 		SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n");
 		SCTPDBG(SCTP_DEBUG_INPUT2,
 		    "Turning off ASCONF to this strange peer\n");
-		stcb->asoc.peer_supports_asconf = 0;
+		stcb->asoc.asconf_supported = 0;
 		break;
 	default:
 		SCTPDBG(SCTP_DEBUG_INPUT2,
@@ -2787,6 +2788,8 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 			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->auth_supported = (*inp_p)->auth_supported;
+			inp->asconf_supported = (*inp_p)->asconf_supported;
 			inp->reconfig_supported = (*inp_p)->reconfig_supported;
 			inp->nrsack_supported = (*inp_p)->nrsack_supported;
 			inp->pktdrop_supported = (*inp_p)->pktdrop_supported;
@@ -2966,7 +2969,7 @@ sctp_handle_cookie_ack(struct sctp_cooki
 		 * in flight)
 		 */
 		if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) &&
-		    (stcb->asoc.peer_supports_asconf) &&
+		    (stcb->asoc.asconf_supported == 1) &&
 		    (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) {
 #ifdef SCTP_TIMER_BASED_ASCONF
 			sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
@@ -4439,7 +4442,7 @@ __attribute__((noinline))
 		 */
 		if ((ch->chunk_type == SCTP_AUTHENTICATION) &&
 		    (stcb == NULL) &&
-		    !SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+		    (inp->auth_supported == 1)) {
 			/* save this chunk for later processing */
 			auth_skipped = 1;
 			auth_offset = *offset;
@@ -4706,7 +4709,7 @@ process_control_chunks:
 
 		/* check to see if this chunk required auth, but isn't */
 		if ((stcb != NULL) &&
-		    !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
+		    (stcb->asoc.auth_supported == 1) &&
 		    sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) &&
 		    !stcb->asoc.authenticated) {
 			/* "silently" ignore */
@@ -5225,6 +5228,9 @@ process_control_chunks:
 				return (NULL);
 			}
 			if (stcb) {
+				if (stcb->asoc.ecn_supported == 0) {
+					goto unknown_chunk;
+				}
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
 					    stcb->asoc.overall_error_count,
@@ -5250,6 +5256,9 @@ process_control_chunks:
 				return (NULL);
 			}
 			if (stcb) {
+				if (stcb->asoc.ecn_supported == 0) {
+					goto unknown_chunk;
+				}
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
 					    stcb->asoc.overall_error_count,
@@ -5283,6 +5292,9 @@ process_control_chunks:
 			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n");
 			/* He's alive so give him credit */
 			if (stcb) {
+				if (stcb->asoc.asconf_supported == 0) {
+					goto unknown_chunk;
+				}
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
 					    stcb->asoc.overall_error_count,
@@ -5307,6 +5319,9 @@ process_control_chunks:
 				return (NULL);
 			}
 			if ((stcb) && netp && *netp) {
+				if (stcb->asoc.asconf_supported == 0) {
+					goto unknown_chunk;
+				}
 				/* He's alive so give him credit */
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
@@ -5336,6 +5351,9 @@ process_control_chunks:
 			if (stcb) {
 				int abort_flag = 0;
 
+				if (stcb->asoc.prsctp_supported == 0) {
+					goto unknown_chunk;
+				}
 				stcb->asoc.overall_error_count = 0;
 				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
@@ -5391,12 +5409,7 @@ process_control_chunks:
 				return (NULL);
 			}
 			if (stcb->asoc.reconfig_supported == 0) {
-				/*
-				 * hmm, peer should have announced this, but
-				 * we will turn it on since he is sending us
-				 * a stream reset.
-				 */
-				stcb->asoc.reconfig_supported = 1;
+				goto unknown_chunk;
 			}
 			if (sctp_handle_stream_reset(stcb, m, *offset, ch)) {
 				/* stop processing */
@@ -5416,18 +5429,17 @@ process_control_chunks:
 				return (NULL);
 			}
 			if (ch && (stcb) && netp && (*netp)) {
+				if (stcb->asoc.pktdrop_supported == 0) {
+					goto unknown_chunk;
+				}
 				sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch,
 				    stcb, *netp,
 				    min(chk_length, (sizeof(chunk_buf) - 4)));
 
 			}
 			break;
-
 		case SCTP_AUTHENTICATION:
 			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n");
-			if (SCTP_BASE_SYSCTL(sctp_auth_disable))
-				goto unknown_chunk;
-
 			if (stcb == NULL) {
 				/* save the first AUTH for later processing */
 				if (auth_skipped == 0) {
@@ -5438,6 +5450,9 @@ process_control_chunks:
 				/* skip this chunk (temporarily) */
 				goto next_chunk;
 			}
+			if (stcb->asoc.auth_supported == 0) {
+				goto unknown_chunk;
+			}
 			if ((chk_length < (sizeof(struct sctp_auth_chunk))) ||
 			    (chk_length > (sizeof(struct sctp_auth_chunk) +
 			    SCTP_AUTH_DIGEST_LEN_MAX))) {
@@ -5778,7 +5793,7 @@ sctp_common_input_processing(struct mbuf
 		 * chunks
 		 */
 		if ((stcb != NULL) &&
-		    !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
+		    (stcb->asoc.auth_supported == 1) &&
 		    sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
 			/* "silently" ignore */
 			SCTP_STAT_INCR(sctps_recvauthmissing);
@@ -5820,7 +5835,7 @@ sctp_common_input_processing(struct mbuf
 	 */
 	if ((length > offset) &&
 	    (stcb != NULL) &&
-	    !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
+	    (stcb->asoc.auth_supported == 1) &&
 	    sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) &&
 	    !stcb->asoc.authenticated) {
 		/* "silently" ignore */

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_output.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -4753,12 +4753,6 @@ sctp_send_initiate(struct sctp_inpcb *in
 	}
 	chunk_len = (uint16_t) sizeof(struct sctp_init_chunk);
 	padding_len = 0;
-	/*
-	 * assume peer supports asconf in order to be able to queue local
-	 * address changes while an INIT is in flight and before the assoc
-	 * is established.
-	 */
-	stcb->asoc.peer_supports_asconf = 1;
 	/* Now lets put the chunk header in place */
 	init = mtod(m, struct sctp_init_chunk *);
 	/* now the chunk header */
@@ -4811,31 +4805,34 @@ sctp_send_initiate(struct sctp_inpcb *in
 	/* And now tell the peer which extensions we support */
 	num_ext = 0;
 	pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
-	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;
 	if (stcb->asoc.prsctp_supported == 1) {
 		pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
 	}
-	if (stcb->asoc.pktdrop_supported == 1) {
-		pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+	if (stcb->asoc.auth_supported == 1) {
+		pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
+	}
+	if (stcb->asoc.asconf_supported == 1) {
+		pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
+		pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
 	}
 	if (stcb->asoc.reconfig_supported == 1) {
 		pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
 	}
-	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
-		pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
-	}
 	if (stcb->asoc.nrsack_supported == 1) {
 		pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
 	}
-	parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
-	pr_supported->ph.param_length = htons(parameter_len);
-	padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
-	chunk_len += parameter_len;
-
+	if (stcb->asoc.pktdrop_supported == 1) {
+		pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+	}
+	if (num_ext > 0) {
+		parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
+		pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
+		pr_supported->ph.param_length = htons(parameter_len);
+		padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+		chunk_len += parameter_len;
+	}
 	/* add authentication parameters */
-	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+	if (stcb->asoc.auth_supported) {
 		/* attach RANDOM parameter, if available */
 		if (stcb->asoc.authinfo.random != NULL) {
 			struct sctp_auth_random *randp;
@@ -4853,8 +4850,7 @@ sctp_send_initiate(struct sctp_inpcb *in
 			chunk_len += parameter_len;
 		}
 		/* add HMAC_ALGO parameter */
-		if ((stcb->asoc.local_hmacs != NULL) &&
-		    (stcb->asoc.local_hmacs->num_algo > 0)) {
+		if (stcb->asoc.local_hmacs != NULL) {
 			struct sctp_auth_hmac_algo *hmacs;
 
 			if (padding_len > 0) {
@@ -4872,7 +4868,7 @@ sctp_send_initiate(struct sctp_inpcb *in
 			chunk_len += parameter_len;
 		}
 		/* add CHUNKS parameter */
-		if (sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks) > 0) {
+		if (stcb->asoc.local_auth_chunks != NULL) {
 			struct sctp_auth_chunk_list *chunks;
 
 			if (padding_len > 0) {
@@ -5917,35 +5913,41 @@ do_a_abort:
 	/* And now tell the peer which extensions we support */
 	num_ext = 0;
 	pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
-	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;
 	if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
 	    ((asoc == NULL) && (inp->prsctp_supported == 1))) {
 		pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
 	}
-	if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) ||
-	    ((asoc == NULL) && (inp->pktdrop_supported == 1))) {
-		pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+	if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
+	    ((asoc == NULL) && (inp->auth_supported == 1))) {
+		pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
+	}
+	if (((asoc != NULL) && (asoc->asconf_supported == 1)) ||
+	    ((asoc == NULL) && (inp->asconf_supported == 1))) {
+		pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
+		pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
 	}
 	if (((asoc != NULL) && (asoc->reconfig_supported == 1)) ||
 	    ((asoc == NULL) && (inp->reconfig_supported == 1))) {
 		pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
 	}
-	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
-		pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
-	}
 	if (((asoc != NULL) && (asoc->nrsack_supported == 1)) ||
 	    ((asoc == NULL) && (inp->nrsack_supported == 1))) {
 		pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
 	}
-	parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
-	pr_supported->ph.param_length = htons(parameter_len);
-	padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
-	chunk_len += parameter_len;
-
+	if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) ||
+	    ((asoc == NULL) && (inp->pktdrop_supported == 1))) {
+		pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
+	}
+	if (num_ext > 0) {
+		parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
+		pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
+		pr_supported->ph.param_length = htons(parameter_len);
+		padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+		chunk_len += parameter_len;
+	}
 	/* add authentication parameters */
-	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+	if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
+	    ((asoc == NULL) && (inp->auth_supported == 1))) {
 		struct sctp_auth_random *randp;
 		struct sctp_auth_hmac_algo *hmacs;
 		struct sctp_auth_chunk_list *chunks;
@@ -7806,7 +7808,6 @@ sctp_med_chunk_output(struct sctp_inpcb 
 
 	*num_out = 0;
 	auth_keyid = stcb->asoc.authinfo.active_keyid;
-
 	if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
 	    (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED) ||
 	    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {
@@ -13417,12 +13418,7 @@ sctp_add_auth_chunk(struct mbuf *m, stru
 	    (stcb == NULL))
 		return (m);
 
-	/* sysctl disabled auth? */
-	if (SCTP_BASE_SYSCTL(sctp_auth_disable))
-		return (m);
-
-	/* peer doesn't do auth... */
-	if (!stcb->asoc.peer_supports_auth) {
+	if (stcb->asoc.auth_supported == 0) {
 		return (m);
 	}
 	/* does the requested chunk require auth? */

Modified: head/sys/netinet/sctp_pcb.c
==============================================================================
--- head/sys/netinet/sctp_pcb.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_pcb.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -2485,6 +2485,12 @@ sctp_inpcb_alloc(struct socket *so, uint
 	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);
+	if (SCTP_BASE_SYSCTL(sctp_auth_disable)) {
+		inp->auth_supported = 0;
+	} else {
+		inp->auth_supported = 1;
+	}
+	inp->asconf_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_asconf_enable);
 	inp->reconfig_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_reconfig_enable);
 	inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable);
 	inp->pktdrop_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
@@ -2651,12 +2657,15 @@ sctp_inpcb_alloc(struct socket *so, uint
 	 */
 	m->local_hmacs = sctp_default_supported_hmaclist();
 	m->local_auth_chunks = sctp_alloc_chunklist();
+	if (inp->asconf_supported) {
+		sctp_auth_add_chunk(SCTP_ASCONF, m->local_auth_chunks);
+		sctp_auth_add_chunk(SCTP_ASCONF_ACK, m->local_auth_chunks);
+	}
 	m->default_dscp = 0;
 #ifdef INET6
 	m->default_flowlabel = 0;
 #endif
 	m->port = 0;		/* encapsulation disabled by default */
-	sctp_auth_set_default_chunks(m->local_auth_chunks);
 	LIST_INIT(&m->shared_keys);
 	/* add default NULL key as key id 0 */
 	null_key = sctp_alloc_sharedkey();
@@ -6085,11 +6094,14 @@ sctp_load_addresses_from_init(struct sct
 	sctp_key_t *new_key;
 	uint32_t keylen;
 	int got_random = 0, got_hmacs = 0, got_chklist = 0;
-	uint8_t ecn_supported;
-	uint8_t prsctp_supported;
-	uint8_t reconfig_supported;
-	uint8_t nrsack_supported;
-	uint8_t pktdrop_supported;
+	uint8_t peer_supports_ecn;
+	uint8_t peer_supports_prsctp;
+	uint8_t peer_supports_auth;
+	uint8_t peer_supports_asconf;
+	uint8_t peer_supports_asconf_ack;
+	uint8_t peer_supports_reconfig;
+	uint8_t peer_supports_nrsack;
+	uint8_t peer_supports_pktdrop;
 
 #ifdef INET
 	struct sockaddr_in sin;
@@ -6118,11 +6130,14 @@ sctp_load_addresses_from_init(struct sct
 	} else {
 		sa = src;
 	}
-	ecn_supported = 0;
-	prsctp_supported = 0;
-	reconfig_supported = 0;
-	nrsack_supported = 0;
-	pktdrop_supported = 0;
+	peer_supports_ecn = 0;
+	peer_supports_prsctp = 0;
+	peer_supports_auth = 0;
+	peer_supports_asconf = 0;
+	peer_supports_asconf = 0;
+	peer_supports_reconfig = 0;
+	peer_supports_nrsack = 0;
+	peer_supports_pktdrop = 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;
@@ -6172,12 +6187,6 @@ sctp_load_addresses_from_init(struct sct
 		/* the assoc was freed? */
 		return (-4);
 	}
-	/*
-	 * peer must explicitly turn this on. This may have been initialized
-	 * to be "on" in order to allow local addr changes while INIT's are
-	 * in flight.
-	 */
-	stcb->asoc.peer_supports_asconf = 0;
 	/* now we must go through each of the params. */
 	phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
 	while (phdr) {
@@ -6371,7 +6380,7 @@ sctp_load_addresses_from_init(struct sct
 		} else
 #endif
 		if (ptype == SCTP_ECN_CAPABLE) {
-			ecn_supported = 1;
+			peer_supports_ecn = 1;
 		} else if (ptype == SCTP_ULP_ADAPTATION) {
 			if (stcb->asoc.state != SCTP_STATE_OPEN) {
 				struct sctp_adaptation_layer_indication ai,
@@ -6395,7 +6404,9 @@ sctp_load_addresses_from_init(struct sct
 
 #endif
 
-			stcb->asoc.peer_supports_asconf = 1;
+			if (stcb->asoc.asconf_supported == 0) {
+				return (-100);
+			}
 			if (plen > sizeof(lstore)) {
 				return (-23);
 			}
@@ -6447,7 +6458,7 @@ sctp_load_addresses_from_init(struct sct
 			stcb->asoc.peer_supports_nat = 1;
 		} else if (ptype == SCTP_PRSCTP_SUPPORTED) {
 			/* Peer supports pr-sctp */
-			prsctp_supported = 1;
+			peer_supports_prsctp = 1;
 		} else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
 			/* A supported extension chunk */
 			struct sctp_supported_chunk_types_param *pr_supported;
@@ -6459,30 +6470,29 @@ sctp_load_addresses_from_init(struct sct
 			if (phdr == NULL) {
 				return (-25);
 			}
-			stcb->asoc.peer_supports_asconf = 0;
-			stcb->asoc.peer_supports_auth = 0;
 			pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
 			num_ent = plen - sizeof(struct sctp_paramhdr);
 			for (i = 0; i < num_ent; i++) {
 				switch (pr_supported->chunk_types[i]) {
 				case SCTP_ASCONF:
+					peer_supports_asconf = 1;
 				case SCTP_ASCONF_ACK:
-					stcb->asoc.peer_supports_asconf = 1;
+					peer_supports_asconf_ack = 1;
 					break;
 				case SCTP_FORWARD_CUM_TSN:
-					prsctp_supported = 1;
+					peer_supports_prsctp = 1;
 					break;
 				case SCTP_PACKET_DROPPED:
-					pktdrop_supported = 1;
+					peer_supports_pktdrop = 1;
 					break;
 				case SCTP_NR_SELECTIVE_ACK:
-					nrsack_supported = 1;
+					peer_supports_nrsack = 1;
 					break;
 				case SCTP_STREAM_RESET:
-					reconfig_supported = 1;
+					peer_supports_reconfig = 1;
 					break;
 				case SCTP_AUTHENTICATION:
-					stcb->asoc.peer_supports_auth = 1;
+					peer_supports_auth = 1;
 					break;
 				default:
 					/* one I have not learned yet */
@@ -6619,25 +6629,47 @@ next_param:
 			}
 		}
 	}
-	stcb->asoc.ecn_supported &= ecn_supported;
-	stcb->asoc.prsctp_supported &= prsctp_supported;
-	stcb->asoc.reconfig_supported &= reconfig_supported;
-	stcb->asoc.nrsack_supported &= nrsack_supported;
-	stcb->asoc.pktdrop_supported &= pktdrop_supported;
-	/* validate authentication required parameters */
-	if (got_random && got_hmacs) {
-		stcb->asoc.peer_supports_auth = 1;
-	} else {
-		stcb->asoc.peer_supports_auth = 0;
+	if ((stcb->asoc.ecn_supported == 1) &&
+	    (peer_supports_ecn == 0)) {
+		stcb->asoc.ecn_supported = 0;
+	}
+	if ((stcb->asoc.prsctp_supported == 1) &&
+	    (peer_supports_prsctp == 0)) {
+		stcb->asoc.prsctp_supported = 0;
+	}
+	if ((stcb->asoc.auth_supported == 1) &&
+	    ((peer_supports_auth == 0) ||
+	    (got_random == 0) || (got_hmacs == 0))) {
+		stcb->asoc.auth_supported = 0;
+	}
+	if ((stcb->asoc.asconf_supported == 1) &&
+	    ((peer_supports_asconf == 0) || (peer_supports_asconf_ack == 0) ||
+	    (stcb->asoc.auth_supported == 0) ||
+	    (saw_asconf == 0) || (saw_asconf_ack == 0))) {
+		stcb->asoc.asconf_supported = 0;
+	}
+	if ((stcb->asoc.reconfig_supported == 1) &&
+	    (peer_supports_reconfig == 0)) {
+		stcb->asoc.reconfig_supported = 0;
+	}
+	if ((stcb->asoc.nrsack_supported == 1) &&
+	    (peer_supports_nrsack == 0)) {
+		stcb->asoc.nrsack_supported = 0;
+	}
+	if ((stcb->asoc.pktdrop_supported == 1) &&
+	    (peer_supports_pktdrop == 0)) {
+		stcb->asoc.pktdrop_supported = 0;
 	}
-	if (!stcb->asoc.peer_supports_auth && got_chklist) {
+	/* validate authentication required parameters */
+	if ((peer_supports_auth == 0) && (got_chklist == 1)) {
 		/* peer does not support auth but sent a chunks list? */
 		return (-31);
 	}
-	if (stcb->asoc.peer_supports_asconf && !stcb->asoc.peer_supports_auth) {
+	if ((peer_supports_asconf == 1) && (peer_supports_auth == 0)) {
 		/* peer supports asconf but not auth? */
 		return (-32);
-	} else if ((stcb->asoc.peer_supports_asconf) && (stcb->asoc.peer_supports_auth) &&
+	} else if ((peer_supports_asconf == 1) &&
+		    (peer_supports_auth == 1) &&
 	    ((saw_asconf == 0) || (saw_asconf_ack == 0))) {
 		return (-33);
 	}

Modified: head/sys/netinet/sctp_pcb.h
==============================================================================
--- head/sys/netinet/sctp_pcb.h	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_pcb.h	Tue Aug 12 11:30:16 2014	(r269858)
@@ -408,6 +408,8 @@ struct sctp_inpcb {
 	uint32_t sctp_cmt_on_off;
 	uint8_t ecn_supported;
 	uint8_t prsctp_supported;
+	uint8_t auth_supported;
+	uint8_t asconf_supported;
 	uint8_t reconfig_supported;
 	uint8_t nrsack_supported;
 	uint8_t pktdrop_supported;

Modified: head/sys/netinet/sctp_peeloff.c
==============================================================================
--- head/sys/netinet/sctp_peeloff.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_peeloff.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -120,6 +120,8 @@ sctp_do_peeloff(struct socket *head, str
 	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->auth_supported = inp->auth_supported;
+	n_inp->asconf_supported = inp->asconf_supported;
 	n_inp->reconfig_supported = inp->reconfig_supported;
 	n_inp->nrsack_supported = inp->nrsack_supported;
 	n_inp->pktdrop_supported = inp->pktdrop_supported;

Modified: head/sys/netinet/sctp_structs.h
==============================================================================
--- head/sys/netinet/sctp_structs.h	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_structs.h	Tue Aug 12 11:30:16 2014	(r269858)
@@ -1153,6 +1153,8 @@ struct sctp_association {
 	/* Flags whether an extension is supported or not */
 	uint8_t ecn_supported;
 	uint8_t prsctp_supported;
+	uint8_t auth_supported;
+	uint8_t asconf_supported;
 	uint8_t reconfig_supported;
 	uint8_t nrsack_supported;
 	uint8_t pktdrop_supported;
@@ -1160,10 +1162,6 @@ struct sctp_association {
 	/* Did the peer make the stream config (add out) request */
 	uint8_t peer_req_out;
 
-	/* flag to indicate if peer can do asconf */
-	uint8_t peer_supports_asconf;
-	/* peer authentication support flag */
-	uint8_t peer_supports_auth;
 	uint8_t local_strreset_support;
 
 	uint8_t peer_supports_nat;

Modified: head/sys/netinet/sctp_sysctl.c
==============================================================================
--- head/sys/netinet/sctp_sysctl.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_sysctl.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -55,6 +55,8 @@ sctp_init_sysctls()
 	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_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
+	SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_reconfig_enable) = SCTPCTL_RECONFIG_ENABLE_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_nrsack_enable) = SCTPCTL_NRSACK_ENABLE_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_pktdrop_enable) = SCTPCTL_PKTDROP_ENABLE_DEFAULT;
@@ -90,7 +92,6 @@ sctp_init_sysctls()
 	SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = SCTPCTL_CWND_MAXBURST_DEFAULT;
-	SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_L2_abc_variable) = SCTPCTL_ABC_L_VAR_DEFAULT;
 	SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count) = SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT;
@@ -638,7 +639,6 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_use_dac), SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX);
-		RANGECHK(SCTP_BASE_SYSCTL(sctp_auth_disable), SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_nat_friendly), SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_L2_abc_variable), SCTPCTL_ABC_L_VAR_MIN, SCTPCTL_ABC_L_VAR_MAX);
 		RANGECHK(SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), SCTPCTL_MAX_CHAINED_MBUFS_MIN, SCTPCTL_MAX_CHAINED_MBUFS_MAX);
@@ -677,6 +677,56 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
 	return (error);
 }
 
+static int
+sysctl_sctp_auth_check(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+
+	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+	if (error == 0) {
+		if (SCTP_BASE_SYSCTL(sctp_auth_disable) < SCTPCTL_AUTH_DISABLE_MIN) {
+			SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_MIN;
+		}
+		if (SCTP_BASE_SYSCTL(sctp_auth_disable) > SCTPCTL_AUTH_DISABLE_MAX) {
+			SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_MAX;
+		}
+		if ((SCTP_BASE_SYSCTL(sctp_auth_disable) == 1) &&
+		    (SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1)) {
+			/*
+			 * You can't disable AUTH with disabling ASCONF
+			 * first
+			 */
+			SCTP_BASE_SYSCTL(sctp_auth_disable) = 0;
+		}
+	}
+	return (error);
+}
+
+static int
+sysctl_sctp_asconf_check(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+
+	error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+	if (error == 0) {
+		if (SCTP_BASE_SYSCTL(sctp_asconf_enable) < SCTPCTL_ASCONF_ENABLE_MIN) {
+			SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_MIN;
+		}
+		if (SCTP_BASE_SYSCTL(sctp_asconf_enable) > SCTPCTL_ASCONF_ENABLE_MAX) {
+			SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_MAX;
+		}
+		if ((SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1) &&
+		    (SCTP_BASE_SYSCTL(sctp_auth_disable) == 1)) {
+			/*
+			 * You can't enable ASCONF without enabling AUTH
+			 * first
+			 */
+			SCTP_BASE_SYSCTL(sctp_asconf_enable) = 0;
+		}
+	}
+	return (error);
+}
+
 #if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
 static int
 sysctl_stat_get(SYSCTL_HANDLER_ARGS)
@@ -869,6 +919,14 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUT
     &SCTP_BASE_SYSCTL(sctp_pr_enable), 0, sysctl_sctp_check, "IU",
     SCTPCTL_PR_ENABLE_DESC);
 
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | CTLFLAG_RW,
+    &SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_auth_check, "IU",
+    SCTPCTL_AUTH_DISABLE_DESC);
+
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asconf_enable, CTLTYPE_UINT | CTLFLAG_RW,
+    &SCTP_BASE_SYSCTL(sctp_asconf_enable), 0, sysctl_sctp_asconf_check, "IU",
+    SCTPCTL_ASCONF_ENABLE_DESC);
+
 SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, reconfig_enable, CTLTYPE_UINT | CTLFLAG_RW,
     &SCTP_BASE_SYSCTL(sctp_reconfig_enable), 0, sysctl_sctp_check, "IU",
     SCTPCTL_RECONFIG_ENABLE_DESC);
@@ -1010,10 +1068,6 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUT
     &SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, "IU",
     SCTPCTL_CWND_MAXBURST_DESC);
 
-SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | CTLFLAG_RW,
-    &SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_check, "IU",
-    SCTPCTL_AUTH_DISABLE_DESC);
-
 SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_UINT | CTLFLAG_RW,
     &SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sysctl_sctp_check, "IU",
     SCTPCTL_NAT_FRIENDLY_DESC);

Modified: head/sys/netinet/sctp_sysctl.h
==============================================================================
--- head/sys/netinet/sctp_sysctl.h	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_sysctl.h	Tue Aug 12 11:30:16 2014	(r269858)
@@ -46,6 +46,8 @@ struct sctp_sysctl {
 	uint32_t sctp_multiple_asconfs;
 	uint32_t sctp_ecn_enable;
 	uint32_t sctp_pr_enable;
+	uint32_t sctp_auth_disable;
+	uint32_t sctp_asconf_enable;
 	uint32_t sctp_reconfig_enable;
 	uint32_t sctp_nrsack_enable;
 	uint32_t sctp_pktdrop_enable;
@@ -81,7 +83,6 @@ struct sctp_sysctl {
 	uint32_t sctp_cmt_on_off;
 	uint32_t sctp_cmt_use_dac;
 	uint32_t sctp_use_cwnd_based_maxburst;
-	uint32_t sctp_auth_disable;
 	uint32_t sctp_nat_friendly;
 	uint32_t sctp_L2_abc_variable;
 	uint32_t sctp_mbuf_threshold_count;
@@ -162,6 +163,18 @@ struct sctp_sysctl {
 #define SCTPCTL_PR_ENABLE_MAX		1
 #define SCTPCTL_PR_ENABLE_DEFAULT	1
 
+/* auth_disable: Disable SCTP AUTH function */
+#define SCTPCTL_AUTH_DISABLE_DESC	"Disable SCTP AUTH function"
+#define SCTPCTL_AUTH_DISABLE_MIN	0
+#define SCTPCTL_AUTH_DISABLE_MAX	1
+#define SCTPCTL_AUTH_DISABLE_DEFAULT	0
+
+/* asconf_enable: Enable SCTP ASCONF */
+#define SCTPCTL_ASCONF_ENABLE_DESC	"Enable SCTP ASCONF"
+#define SCTPCTL_ASCONF_ENABLE_MIN	0
+#define SCTPCTL_ASCONF_ENABLE_MAX	1
+#define SCTPCTL_ASCONF_ENABLE_DEFAULT	1
+
 /* reconfig_enable: Enable SCTP RE-CONFIG */
 #define SCTPCTL_RECONFIG_ENABLE_DESC	"Enable SCTP RE-CONFIG"
 #define SCTPCTL_RECONFIG_ENABLE_MIN	0
@@ -379,12 +392,6 @@ struct sctp_sysctl {
 #define SCTPCTL_CWND_MAXBURST_MAX	1
 #define SCTPCTL_CWND_MAXBURST_DEFAULT	1
 
-/* auth_disable: Disable SCTP AUTH function */
-#define SCTPCTL_AUTH_DISABLE_DESC	"Disable SCTP AUTH function"
-#define SCTPCTL_AUTH_DISABLE_MIN	0
-#define SCTPCTL_AUTH_DISABLE_MAX	1
-#define SCTPCTL_AUTH_DISABLE_DEFAULT	0
-
 /* nat_friendly: SCTP NAT friendly operation */
 #define SCTPCTL_NAT_FRIENDLY_DESC	"SCTP NAT friendly operation"
 #define SCTPCTL_NAT_FRIENDLY_MIN	0

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c	Tue Aug 12 10:31:31 2014	(r269857)
+++ head/sys/netinet/sctp_usrreq.c	Tue Aug 12 11:30:16 2014	(r269858)
@@ -3348,6 +3348,60 @@ flags_out:
 			}
 			break;
 		}
+	case SCTP_AUTH_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.auth_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->auth_supported;
+					SCTP_INP_RUNLOCK(inp);
+				} else {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53e9fac9.6e09.1cc546b0>