Bug 1139020: Update SCTP library from upstream to rev 9168 rs=jesup
authorRandell Jesup <rjesup@jesup.org>
Thu, 05 Mar 2015 00:17:42 -0500
changeset 262273 01f4c9a6e84048db839265ccb44006f5e4f94a3d
parent 262272 322a307d48ce325a00780630d420b4008fae3571
child 262274 96c9564229e74899d2e0ae7196f8c7826821f57d
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1139020
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1139020: Update SCTP library from upstream to rev 9168 rs=jesup
netwerk/sctp/sctp_update.log
netwerk/sctp/src/netinet/sctp.h
netwerk/sctp/src/netinet/sctp_asconf.c
netwerk/sctp/src/netinet/sctp_auth.c
netwerk/sctp/src/netinet/sctp_auth.h
netwerk/sctp/src/netinet/sctp_bsd_addr.c
netwerk/sctp/src/netinet/sctp_callout.c
netwerk/sctp/src/netinet/sctp_cc_functions.c
netwerk/sctp/src/netinet/sctp_constants.h
netwerk/sctp/src/netinet/sctp_header.h
netwerk/sctp/src/netinet/sctp_indata.c
netwerk/sctp/src/netinet/sctp_input.c
netwerk/sctp/src/netinet/sctp_input.h
netwerk/sctp/src/netinet/sctp_os_userspace.h
netwerk/sctp/src/netinet/sctp_output.c
netwerk/sctp/src/netinet/sctp_output.h
netwerk/sctp/src/netinet/sctp_pcb.c
netwerk/sctp/src/netinet/sctp_pcb.h
netwerk/sctp/src/netinet/sctp_peeloff.c
netwerk/sctp/src/netinet/sctp_structs.h
netwerk/sctp/src/netinet/sctp_sysctl.c
netwerk/sctp/src/netinet/sctp_sysctl.h
netwerk/sctp/src/netinet/sctp_timer.c
netwerk/sctp/src/netinet/sctp_uio.h
netwerk/sctp/src/netinet/sctp_userspace.c
netwerk/sctp/src/netinet/sctp_usrreq.c
netwerk/sctp/src/netinet/sctp_var.h
netwerk/sctp/src/netinet/sctputil.c
netwerk/sctp/src/netinet/sctputil.h
netwerk/sctp/src/netinet6/sctp6_usrreq.c
netwerk/sctp/src/netinet6/sctp6_var.h
netwerk/sctp/src/user_environment.h
netwerk/sctp/src/user_ip_icmp.h
netwerk/sctp/src/user_malloc.h
netwerk/sctp/src/user_route.h
netwerk/sctp/src/user_socket.c
netwerk/sctp/src/user_socketvar.h
netwerk/sctp/src/usrsctp.h
--- a/netwerk/sctp/sctp_update.log
+++ b/netwerk/sctp/sctp_update.log
@@ -9,8 +9,9 @@ sctp updated to version 8119 from SVN on
 sctp updated to version 8131 from SVN on Tue Sep  4 00:26:11 EDT 2012
 sctp updated to version 8165 from SVN on Wed Sep  5 09:39:43 EDT 2012
 sctp updated to version 8176 from SVN on Wed Sep  5 18:02:08 EDT 2012
 sctp updated to version 8263 from SVN on Sun Sep 16 00:48:48 EDT 2012
 sctp updated to version 8279 from SVN on Thu Sep 20 18:19:24 EDT 2012
 sctp updated to version 8397 from SVN on Wed Jan  9 00:41:16 EST 2013
 sctp updated to version 8443 from SVN on Sun Mar 31 09:05:07 EDT 2013
 sctp updated to version 8815 from SVN on Tue Mar  4 08:50:51 EST 2014
+sctp updated to version 9168 from SVN on Tue Mar  3 12:11:40 EST 2015
--- a/netwerk/sctp/src/netinet/sctp.h
+++ b/netwerk/sctp/src/netinet/sctp.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 254248 2013-08-12 13:52:15Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 269945 2014-08-13 15:50:16Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_H_
 #define _NETINET_SCTP_H_
 
 #if (defined(__APPLE__) || defined(__Userspace_os_Linux) || defined(__Userspace_os_Darwin))
 #include <stdint.h>
 #endif
@@ -48,23 +48,23 @@
 #if !defined(__Userspace_os_Windows)
 #define SCTP_PACKED __attribute__((packed))
 #else
 #pragma pack (push, 1)
 #define SCTP_PACKED
 #endif
 
 /*
- * SCTP protocol - RFC2960.
+ * SCTP protocol - RFC4960.
  */
 struct sctphdr {
 	uint16_t src_port;	/* source port */
 	uint16_t dest_port;	/* destination port */
 	uint32_t v_tag;		/* verification tag of packet */
-	uint32_t checksum;	/* Adler32 C-Sum */
+	uint32_t checksum;	/* CRC32C checksum */
 	/* chunks follow... */
 } SCTP_PACKED;
 
 /*
  * SCTP Chunks
  */
 struct sctp_chunkhdr {
 	uint8_t chunk_type;	/* chunk type */
@@ -126,28 +126,37 @@ struct sctp_paramhdr {
 #define SCTP_AUTH_DEACTIVATE_KEY	0x0000001d
 #define SCTP_EVENT                      0x0000001e
 #define SCTP_RECVRCVINFO                0x0000001f
 #define SCTP_RECVNXTINFO                0x00000020
 #define SCTP_DEFAULT_SNDINFO            0x00000021
 #define SCTP_DEFAULT_PRINFO             0x00000022
 #define SCTP_PEER_ADDR_THLDS            0x00000023
 #define SCTP_REMOTE_UDP_ENCAPS_PORT     0x00000024
+#define SCTP_ECN_SUPPORTED              0x00000025
+#define SCTP_PR_SUPPORTED               0x00000026
+#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
  */
 #define SCTP_STATUS			0x00000100
 #define SCTP_GET_PEER_ADDR_INFO		0x00000101
 /* authentication support */
 #define SCTP_PEER_AUTH_CHUNKS 		0x00000102
 #define SCTP_LOCAL_AUTH_CHUNKS 		0x00000103
 #define SCTP_GET_ASSOC_NUMBER           0x00000104 /* ro */
 #define SCTP_GET_ASSOC_ID_LIST          0x00000105 /* ro */
 #define SCTP_TIMEOUTS                   0x00000106
+#define SCTP_PR_STREAM_STATUS           0x00000107
+#define SCTP_PR_ASSOC_STATUS            0x00000108
 
 /*
  * user socket options: BSD implementation specific
  */
 /*
  * Blocking I/O is enabled on any TCP type socket by default. For the UDP
  * model if this is turned on then the socket buffer is shared for send
  * resources amongst all associations.  The default for the UDP model is that
@@ -374,16 +383,22 @@ struct sctp_paramhdr {
 #define SCTP_CAUSE_NAT_MISSING_STATE    0x00b1
 
 /* Error causes from RFC4895 */
 #define SCTP_CAUSE_UNSUPPORTED_HMACID	0x0105
 
 /*
  * error cause parameters (user visible)
  */
+struct sctp_gen_error_cause {
+	uint16_t code;
+	uint16_t length;
+	uint8_t info[];
+} SCTP_PACKED;
+
 struct sctp_error_cause {
 	uint16_t code;
 	uint16_t length;
 	/* optional cause-specific info may follow */
 } SCTP_PACKED;
 
 struct sctp_error_invalid_stream {
 	struct sctp_error_cause cause;	/* code=SCTP_ERROR_INVALID_STREAM */
@@ -411,16 +426,21 @@ struct sctp_error_unresolv_addr {
 
 } SCTP_PACKED;
 
 struct sctp_error_unrecognized_chunk {
 	struct sctp_error_cause cause;	/* code=SCTP_ERROR_UNRECOG_CHUNK */
 	struct sctp_chunkhdr ch;/* header from chunk in error */
 } SCTP_PACKED;
 
+struct sctp_error_no_user_data {
+	struct sctp_error_cause cause;	/* code=SCTP_CAUSE_NO_USER_DATA */
+	uint32_t tsn;			/* TSN of the empty data chunk */
+} SCTP_PACKED;
+
 /*
  * Main SCTP chunk types we place these here so natd and f/w's in user land
  * can find them.
  */
 /************0x00 series ***********/
 #define SCTP_DATA		0x00
 #define SCTP_INITIATION		0x01
 #define SCTP_INITIATION_ACK	0x02
--- a/netwerk/sctp/src/netinet/sctp_asconf.c
+++ b/netwerk/sctp/src/netinet/sctp_asconf.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 257803 2013-11-07 17:08:09Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 277347 2015-01-18 20:53:20Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
@@ -148,17 +148,17 @@ sctp_asconf_error_response(uint32_t id, 
 }
 
 static struct mbuf *
 sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph,
                            struct sctp_tcb *stcb, int send_hb, int response_required)
 {
 	struct sctp_nets *net;
 	struct mbuf *m_reply = NULL;
-	struct sockaddr_storage sa_store;
+	union sctp_sockstore store;
 	struct sctp_paramhdr *ph;
 	uint16_t param_type, aparam_length;
 #if defined(INET) || defined(INET6)
 	uint16_t param_length;
 #endif
 	struct sockaddr *sa;
 	int zero_address = 0;
 	int bad_address = 0;
@@ -172,26 +172,26 @@ sctp_process_asconf_add_ip(struct sockad
 #endif
 
 	aparam_length = ntohs(aph->ph.param_length);
 	ph = (struct sctp_paramhdr *)(aph + 1);
 	param_type = ntohs(ph->param_type);
 #if defined(INET) || defined(INET6)
 	param_length = ntohs(ph->param_length);
 #endif
-	sa = (struct sockaddr *)&sa_store;
+	sa = &store.sa;
 	switch (param_type) {
 #ifdef INET
 	case SCTP_IPV4_ADDRESS:
 		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
 			/* invalid param size */
 			return (NULL);
 		}
 		v4addr = (struct sctp_ipv4addr_param *)ph;
-		sin = (struct sockaddr_in *)&sa_store;
+		sin = &store.sin;
 		bzero(sin, sizeof(*sin));
 		sin->sin_family = AF_INET;
 #ifdef HAVE_SIN_LEN
 		sin->sin_len = sizeof(struct sockaddr_in);
 #endif
 		sin->sin_port = stcb->rport;
 		sin->sin_addr.s_addr = v4addr->addr;
 		if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
@@ -206,17 +206,17 @@ sctp_process_asconf_add_ip(struct sockad
 #endif
 #ifdef INET6
 	case SCTP_IPV6_ADDRESS:
 		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
 			/* invalid param size */
 			return (NULL);
 		}
 		v6addr = (struct sctp_ipv6addr_param *)ph;
-		sin6 = (struct sockaddr_in6 *)&sa_store;
+		sin6 = &store.sin6;
 		bzero(sin6, sizeof(*sin6));
 		sin6->sin6_family = AF_INET6;
 #ifdef HAVE_SIN6_LEN
 		sin6->sin6_len = sizeof(struct sockaddr_in6);
 #endif
 		sin6->sin6_port = stcb->rport;
 		memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
 		    sizeof(struct in6_addr));
@@ -302,17 +302,17 @@ sctp_asconf_del_remote_addrs_except(stru
 }
 
 static struct mbuf *
 sctp_process_asconf_delete_ip(struct sockaddr *src,
                               struct sctp_asconf_paramhdr *aph,
 			      struct sctp_tcb *stcb, int response_required)
 {
 	struct mbuf *m_reply = NULL;
-	struct sockaddr_storage sa_store;
+	union sctp_sockstore store;
 	struct sctp_paramhdr *ph;
 	uint16_t param_type, aparam_length;
 #if defined(INET) || defined(INET6)
 	uint16_t param_length;
 #endif
 	struct sockaddr *sa;
 	int zero_address = 0;
 	int result;
@@ -326,26 +326,26 @@ sctp_process_asconf_delete_ip(struct soc
 #endif
 
 	aparam_length = ntohs(aph->ph.param_length);
 	ph = (struct sctp_paramhdr *)(aph + 1);
 	param_type = ntohs(ph->param_type);
 #if defined(INET) || defined(INET6)
 	param_length = ntohs(ph->param_length);
 #endif
-	sa = (struct sockaddr *)&sa_store;
+	sa = &store.sa;
 	switch (param_type) {
 #ifdef INET
 	case SCTP_IPV4_ADDRESS:
 		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
 			/* invalid param size */
 			return (NULL);
 		}
 		v4addr = (struct sctp_ipv4addr_param *)ph;
-		sin = (struct sockaddr_in *)&sa_store;
+		sin = &store.sin;
 		bzero(sin, sizeof(*sin));
 		sin->sin_family = AF_INET;
 #ifdef HAVE_SIN_LEN
 		sin->sin_len = sizeof(struct sockaddr_in);
 #endif
 		sin->sin_port = stcb->rport;
 		sin->sin_addr.s_addr = v4addr->addr;
 		if (sin->sin_addr.s_addr == INADDR_ANY)
@@ -357,17 +357,17 @@ sctp_process_asconf_delete_ip(struct soc
 #endif
 #ifdef INET6
 	case SCTP_IPV6_ADDRESS:
 		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
 			/* invalid param size */
 			return (NULL);
 		}
 		v6addr = (struct sctp_ipv6addr_param *)ph;
-		sin6 = (struct sockaddr_in6 *)&sa_store;
+		sin6 = &store.sin6;
 		bzero(sin6, sizeof(*sin6));
 		sin6->sin6_family = AF_INET6;
 #ifdef HAVE_SIN6_LEN
 		sin6->sin6_len = sizeof(struct sockaddr_in6);
 #endif
 		sin6->sin6_port = stcb->rport;
 		memcpy(&sin6->sin6_addr, v6addr->addr,
 		    sizeof(struct in6_addr));
@@ -424,31 +424,31 @@ sctp_process_asconf_delete_ip(struct soc
 	if (result == -1) {
 		/* only one address in the asoc */
 		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n");
 		m_reply = sctp_asconf_error_response(aph->correlation_id,
 		    SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph,
 		    aparam_length);
 	} else {
 		if (response_required) {
-	 		m_reply = sctp_asconf_success_response(aph->correlation_id);
+			m_reply = sctp_asconf_success_response(aph->correlation_id);
 		}
 		/* notify upper layer */
 		sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
 	}
 	return (m_reply);
 }
 
 static struct mbuf *
 sctp_process_asconf_set_primary(struct sockaddr *src,
 				struct sctp_asconf_paramhdr *aph,
 				struct sctp_tcb *stcb, int response_required)
 {
 	struct mbuf *m_reply = NULL;
-	struct sockaddr_storage sa_store;
+	union sctp_sockstore store;
 	struct sctp_paramhdr *ph;
 	uint16_t param_type, aparam_length;
 #if defined(INET) || defined(INET6)
 	uint16_t param_length;
 #endif
 	struct sockaddr *sa;
 	int zero_address = 0;
 #ifdef INET
@@ -461,26 +461,26 @@ sctp_process_asconf_set_primary(struct s
 #endif
 
 	aparam_length = ntohs(aph->ph.param_length);
 	ph = (struct sctp_paramhdr *)(aph + 1);
 	param_type = ntohs(ph->param_type);
 #if defined(INET) || defined(INET6)
 	param_length = ntohs(ph->param_length);
 #endif
-	sa = (struct sockaddr *)&sa_store;
+	sa = &store.sa;
 	switch (param_type) {
 #ifdef INET
 	case SCTP_IPV4_ADDRESS:
 		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
 			/* invalid param size */
 			return (NULL);
 		}
 		v4addr = (struct sctp_ipv4addr_param *)ph;
-		sin = (struct sockaddr_in *)&sa_store;
+		sin = &store.sin;
 		bzero(sin, sizeof(*sin));
 		sin->sin_family = AF_INET;
 #ifdef HAVE_SIN_LEN
 		sin->sin_len = sizeof(struct sockaddr_in);
 #endif
 		sin->sin_addr.s_addr = v4addr->addr;
 		if (sin->sin_addr.s_addr == INADDR_ANY)
 			zero_address = 1;
@@ -490,17 +490,17 @@ sctp_process_asconf_set_primary(struct s
 #endif
 #ifdef INET6
 	case SCTP_IPV6_ADDRESS:
 		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
 			/* invalid param size */
 			return (NULL);
 		}
 		v6addr = (struct sctp_ipv6addr_param *)ph;
-		sin6 = (struct sockaddr_in6 *)&sa_store;
+		sin6 = &store.sin6;
 		bzero(sin6, sizeof(*sin6));
 		sin6->sin6_family = AF_INET6;
 #ifdef HAVE_SIN6_LEN
 		sin6->sin6_len = sizeof(struct sockaddr_in6);
 #endif
 		memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
 		    sizeof(struct in6_addr));
 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
@@ -547,21 +547,21 @@ sctp_process_asconf_set_primary(struct s
 		   The retransmission occur when reception of the
 		   HEARTBEAT-ACK.  (See sctp_handle_heartbeat_ack in
 		   sctp_input.c)
 		   Also, when change of the primary destination, it is better
 		   that all subsequent new DATA containing already queued DATA
 		   are transmitted to the new primary destination. (by micchie)
 		 */
 		if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
-				       	SCTP_MOBILITY_BASE) ||
+		                                 SCTP_MOBILITY_BASE) ||
 		    sctp_is_mobility_feature_on(stcb->sctp_ep,
-			    		SCTP_MOBILITY_FASTHANDOFF)) &&
+		                                SCTP_MOBILITY_FASTHANDOFF)) &&
 		    sctp_is_mobility_feature_on(stcb->sctp_ep,
-			   		 SCTP_MOBILITY_PRIM_DELETED) &&
+		                                SCTP_MOBILITY_PRIM_DELETED) &&
 		    (stcb->asoc.primary_destination->dest_state &
 		     SCTP_ADDR_UNCONFIRMED) == 0) {
 
 			sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7);
 			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 					SCTP_MOBILITY_FASTHANDOFF)) {
 				sctp_assoc_immediate_retrans(stcb,
 						stcb->asoc.primary_destination);
@@ -596,17 +596,17 @@ sctp_handle_asconf(struct mbuf *m, unsig
                    struct sockaddr *src,
 		   struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb,
 		   int first)
 {
 	struct sctp_association *asoc;
 	uint32_t serial_num;
 	struct mbuf *n, *m_ack, *m_result, *m_tail;
 	struct sctp_asconf_ack_chunk *ack_cp;
-	struct sctp_asconf_paramhdr *aph, *ack_aph;
+	struct sctp_asconf_paramhdr *aph;
 	struct sctp_ipv6addr_param *p_addr;
 	unsigned int asconf_limit, cnt;
 	int error = 0;		/* did an error occur? */
 
 	/* asconf param buffer */
 	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
 	struct sctp_asconf_ack *ack, *ack_next;
 
@@ -681,23 +681,16 @@ sctp_handle_asconf(struct mbuf *m, unsig
 	if (p_addr == NULL) {
 		SCTPDBG(SCTP_DEBUG_ASCONF1,
 			"handle_asconf: couldn't get lookup addr!\n");
 		/* respond with a missing/invalid mandatory parameter error */
 		return;
 	}
 	/* param_length is already validated in process_control... */
 	offset += ntohs(p_addr->ph.param_length);	/* skip lookup addr */
-
-	/* get pointer to first asconf param in ASCONF-ACK */
-	ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t) + sizeof(struct sctp_asconf_ack_chunk));
-	if (ack_aph == NULL) {
-		SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n");
-		return;
-	}
 	/* get pointer to first asconf param in ASCONF */
 	aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *)&aparam_buf);
 	if (aph == NULL) {
 		SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n");
 		goto send_reply;
 	}
 	/* process through all parameters */
 	cnt = 0;
@@ -726,31 +719,28 @@ sctp_handle_asconf(struct mbuf *m, unsig
 		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
 		if (aph == NULL) {
 			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n");
 			sctp_m_freem(m_ack);
 			return;
 		}
 		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;
 		case SCTP_ERROR_CAUSE_IND:
 			/* 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;
 		case SCTP_NAT_VTAGS:
 		        SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n");
 		        break;
 		case SCTP_SUCCESS_REPORT:
 			/* not valid in an ASCONF chunk */
@@ -931,18 +921,16 @@ sctp_addr_match(struct sctp_paramhdr *ph
 	return (0);
 }
 /*
  * Cleanup for non-responded/OP ERR'd ASCONF
  */
 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
 	 */
 	sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
 			SCTP_FROM_SCTP_ASCONF+SCTP_LOC_2);
 	stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out;
 	/* remove the old ASCONF on our outbound queue */
 	sctp_toss_old_asconf(stcb);
@@ -1094,17 +1082,17 @@ sctp_path_check_and_react(struct sctp_tc
 			}
 			if (net->src_addr_selected) {
 				sctp_free_ifa(net->ro._s_addr);
 				net->ro._s_addr = NULL;
 				net->src_addr_selected = 0;
 			}
 			/* Retransmit unacknowledged DATA chunks immediately */
 			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
-		    		SCTP_MOBILITY_FASTHANDOFF)) {
+			                                SCTP_MOBILITY_FASTHANDOFF)) {
 				sctp_net_immediate_retrans(stcb, net);
 			}
 			/* also, SET PRIMARY is maybe already sent */
 		}
 		return;
 	}
 
 	/* Multiple local addresses exsist in the association.  */
@@ -1152,17 +1140,17 @@ sctp_path_check_and_react(struct sctp_tc
 		}
 		/* if the newly added address does not relate routing
 		   information, we skip.
 		 */
 		if (changed == 0)
 			continue;
 		/* Retransmit unacknowledged DATA chunks immediately */
 		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
-		   		SCTP_MOBILITY_FASTHANDOFF)) {
+		                                SCTP_MOBILITY_FASTHANDOFF)) {
 			sctp_net_immediate_retrans(stcb, net);
 		}
 		/* Send SET PRIMARY for this new address */
 		if (net == stcb->asoc.primary_destination) {
 			(void)sctp_asconf_queue_mgmt(stcb, newifa,
 						     SCTP_SET_PRIM_ADDR);
 		}
 	}
@@ -1188,19 +1176,19 @@ sctp_asconf_addr_mgmt_ack(struct sctp_tc
 	 * DEL_IP_ADDRESS is never actually added to the list...
 	 */
 	if (flag) {
 		/* success case, so remove from the restricted list */
 		sctp_del_local_addr_restricted(stcb, addr);
 
 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
 		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
-						SCTP_MOBILITY_BASE) ||
+		                                SCTP_MOBILITY_BASE) ||
 		    sctp_is_mobility_feature_on(stcb->sctp_ep,
-			    			SCTP_MOBILITY_FASTHANDOFF)) {
+		                                SCTP_MOBILITY_FASTHANDOFF)) {
 			sctp_path_check_and_react(stcb, addr);
 			return;
 		}
 #endif /* __FreeBSD__ __APPLE__ __Userspace__ */
 		/* clear any cached/topologically incorrect source addresses */
 		sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
 	}
 	/* else, leave it on the list */
@@ -1276,32 +1264,32 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *
 	atomic_add_int(&ifa->refcount, 1);
 	/* correlation_id filled in during send routine later... */
 	switch (ifa->address.sa.sa_family) {
 #ifdef INET6
 	case AF_INET6:
 	{
 		struct sockaddr_in6 *sin6;
 
-		sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
+		sin6 = &ifa->address.sin6;
 		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 		    sizeof(struct sctp_ipv6addr_param);
 		memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
 		       sizeof(struct in6_addr));
 		break;
 	}
 #endif
 #ifdef INET
 	case AF_INET:
 	{
 		struct sockaddr_in *sin;
 
-		sin= (struct sockaddr_in *)&ifa->address.sa;
+		sin = &ifa->address.sin;
 		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
 		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
 		    sizeof(struct sctp_ipv4addr_param);
 		memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
 		       sizeof(struct in_addr));
 		break;
 	}
@@ -1343,17 +1331,17 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *
 static int
 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
 		      uint16_t type)
 {
 	uint32_t status;
 	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);
 	}
 
 	/*
 	 * if this is deleting the last address from the assoc, mark it as
 	 * pending.
 	 */
 	if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
@@ -1429,23 +1417,22 @@ sctp_asconf_queue_add(struct sctp_tcb *s
  * remove it from queue.  If a duplicate operation is found, ignore the
  * new one.
  */
 static int
 sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
 {
 	struct sctp_ifa *ifa;
 	struct sctp_asconf_addr *aa, *aa_next;
-	uint32_t vrf_id;
 
 	if (stcb == NULL) {
 		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 */
 	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
 		/* address match? */
 		if (sctp_asconf_addr_match(aa, sa) == 0)
 			continue;
 		/* is the request already in queue (sent or not) */
@@ -1461,22 +1448,17 @@ sctp_asconf_queue_sa_delete(struct sctp_
 			sctp_del_local_addr_restricted(stcb, aa->ifa);
 			/* free the entry */
 			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
 			return (-1);
 		}
 	} /* for each aa */
 
 	/* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
-	if (stcb) {
-		vrf_id = stcb->asoc.vrf_id;
-	} else {
-		vrf_id = SCTP_DEFAULT_VRFID;
-	}
-	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
+	ifa = sctp_find_ifa_by_addr(sa, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
 
 	/* adding new request to the queue */
 	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 		    SCTP_M_ASC_ADDR);
 	if (aa == NULL) {
 		/* didn't get memory */
 		SCTPDBG(SCTP_DEBUG_ASCONF1,
 			"sctp_asconf_queue_sa_delete: failed to get memory!\n");
@@ -1555,17 +1537,17 @@ sctp_asconf_find_param(struct sctp_tcb *
 	return (NULL);
 }
 
 /*
  * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
  * 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;
 	struct sctp_paramhdr *ph;
 	uint16_t param_type;
 	uint16_t error_code;
 
 	eh = (struct sctp_error_cause *)(aph + 1);
@@ -1593,20 +1575,17 @@ sctp_asconf_process_error(struct sctp_tc
 	case SCTP_CAUSE_RESOURCE_SHORTAGE:
 		/* we allow ourselves to "try again" for this error */
 		break;
 	default:
 		/* peer can't handle it... */
 		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;
 		}
 	}
 }
 
 /*
@@ -1632,18 +1611,16 @@ sctp_asconf_process_param_ack(struct sct
 		SCTPDBG(SCTP_DEBUG_ASCONF1,
 			"process_param_ack: deleted IP address\n");
 		/* nothing really to do... lists already updated */
 		break;
 	case SCTP_SET_PRIM_ADDR:
 		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 */
 		break;
 	}
 
 	/* remove the param and free it */
 	TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
@@ -1651,21 +1628,21 @@ sctp_asconf_process_param_ack(struct sct
 		sctp_free_ifa(aparam->ifa);
 	SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
 }
 
 /*
  * 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
 sctp_handle_asconf_ack(struct mbuf *m, int offset,
 		       struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
 		       struct sctp_nets *net, int *abort_no_unlock)
 {
 	struct sctp_association *asoc;
@@ -1895,24 +1872,36 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *
 		/* subset bound, no ASCONF allowed case, so ignore */
 		return;
 	}
 	/*
 	 * note: we know this is not the subset bound, no ASCONF case eg.
 	 * this is boundall or subset bound w/ASCONF allowed
 	 */
 
-	/* first, make sure it's a good address family */
+	/* first, make sure that the address is IPv4 or IPv6 and not jailed */
 	switch (ifa->address.sa.sa_family) {
 #ifdef INET6
 	case AF_INET6:
+#if defined(__FreeBSD__)
+		if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+		                     &ifa->address.sin6.sin6_addr) != 0) {
+			return;
+		}
+#endif
 		break;
 #endif
 #ifdef INET
 	case AF_INET:
+#if defined(__FreeBSD__)
+		if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+		                     &ifa->address.sin.sin_addr) != 0) {
+			return;
+		}
+#endif
 		break;
 #endif
 	default:
 		return;
 	}
 #ifdef INET6
 	/* make sure we're "allowed" to add this type of addr */
 	if (ifa->address.sa.sa_family == AF_INET6) {
@@ -1933,17 +1922,17 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *
 	 * asoc lists
 	 */
 	switch (ifa->address.sa.sa_family) {
 #ifdef INET6
 	case AF_INET6:
 	{
 		struct sockaddr_in6 *sin6;
 
-		sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
+		sin6 = &ifa->address.sin6;
 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 			/* we skip unspecifed addresses */
 			return;
 		}
 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 			if (stcb->asoc.scope.local_scope == 0) {
 				return;
 			}
@@ -1966,17 +1955,17 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *
 		struct in6pcb *inp6;
 
 		inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 		/* invalid if we are a v6 only endpoint */
 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 		    SCTP_IPV6_V6ONLY(inp6))
 			return;
 
-		sin = (struct sockaddr_in *)&ifa->address.sa;
+		sin = &ifa->address.sin;
 		if (sin->sin_addr.s_addr == 0) {
 			/* we skip unspecifed addresses */
 			return;
 		}
 		if (stcb->asoc.scope.ipv4_local_scope == 0 &&
 		    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 			return;
 		}
@@ -1986,17 +1975,17 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *
 	default:
 		/* else, not AF_INET or AF_INET6, so skip */
 		return;
 	}
 
 	/* 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);
 
 			/*
 			 * if queued ok, and in the open state, send out the
 			 * ASCONF.  If in the non-open state, these will be
 			 * sent when the state goes open.
 			 */
@@ -2124,21 +2113,27 @@ sctp_asconf_iterator_stcb(struct sctp_in
 
 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
 				cnt_invalid++;
 				if (asc->cnt == cnt_invalid)
 					return;
 				else
 					continue;
 			}
-			sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
+			sin6 = &ifa->address.sin6;
 			if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 				/* we skip unspecifed addresses */
 				continue;
 			}
+#if defined(__FreeBSD__)
+			if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+			                     &sin6->sin6_addr) != 0) {
+				continue;
+			}
+#endif
 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 				if (stcb->asoc.scope.local_scope == 0) {
 					continue;
 				}
 				/* is it the right link local scope? */
 				if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
 					continue;
 				}
@@ -2154,21 +2149,27 @@ sctp_asconf_iterator_stcb(struct sctp_in
 			struct sockaddr_in *sin;
 
 			inp6 = (struct in6pcb *)&inp->ip_inp.inp;
 			/* invalid if we are a v6 only endpoint */
 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 			    SCTP_IPV6_V6ONLY(inp6))
 				continue;
 
-			sin = (struct sockaddr_in *)&ifa->address.sa;
+			sin = &ifa->address.sin;
 			if (sin->sin_addr.s_addr == 0) {
 				/* we skip unspecifed addresses */
 				continue;
 			}
+#if defined(__FreeBSD__)
+			if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+			                     &sin->sin_addr) != 0) {
+				continue;
+			}
+#endif
 			if (stcb->asoc.scope.ipv4_local_scope == 0 &&
 			    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 				continue;
 			}
 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
 			    SCTP_IPV6_V6ONLY(inp6)) {
 				cnt_invalid++;
 				if (asc->cnt == cnt_invalid)
@@ -2216,29 +2217,29 @@ sctp_asconf_iterator_stcb(struct sctp_in
 					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
 					net->RTO = 0;
 
 				}
 			}
 		} else if (type == SCTP_SET_PRIM_ADDR) {
 			if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
 				/* must validate the ifa is in the ep */
-				if (sctp_is_addr_in_ep(stcb->sctp_ep,ifa) == 0) {
+				if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
 					continue;
 				}
 			} else {
 				/* Need to check scopes for this guy */
 				if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) {
 					continue;
 				}
 			}
 		}
 		/* 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);
 			/*
 			 * if queued ok, and in the open state, update the
 			 * count of queued params.  If in the non-open state,
 			 * these get sent when the assoc goes open.
 			 */
 			if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
@@ -2279,17 +2280,17 @@ sctp_asconf_iterator_end(void *ptr, uint
 
 /*
  * sa is the sockaddr to ask the peer to set primary to.
  * returns: 0 = completed, -1 = error
  */
 int32_t
 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
 {
- 	uint32_t vrf_id;
+	uint32_t vrf_id;
 	struct sctp_ifa *ifa;
 
 	/* find the ifa for the desired set primary */
 	vrf_id = stcb->asoc.vrf_id;
 	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 	if (ifa == NULL) {
 		/* Invalid address */
 		return (-1);
@@ -2467,21 +2468,27 @@ sctp_find_valid_localaddr(struct sctp_tc
 		}
 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 			switch (sctp_ifa->address.sa.sa_family) {
 #ifdef INET
 			case AF_INET:
 				if (stcb->asoc.scope.ipv4_addr_legal) {
 					struct sockaddr_in *sin;
 
-					sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
+					sin = &sctp_ifa->address.sin;
 					if (sin->sin_addr.s_addr == 0) {
 						/* skip unspecifed addresses */
 						continue;
 					}
+#if defined(__FreeBSD__)
+					if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
+					                     &sin->sin_addr) != 0) {
+						continue;
+					}
+#endif
 					if (stcb->asoc.scope.ipv4_local_scope == 0 &&
 					    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
 						continue;
 
 					if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
 					    (!sctp_is_addr_pending(stcb, sctp_ifa)))
 						continue;
 					/* found a valid local v4 address to use */
@@ -2495,21 +2502,27 @@ sctp_find_valid_localaddr(struct sctp_tc
 			case AF_INET6:
 				if (stcb->asoc.scope.ipv6_addr_legal) {
 					struct sockaddr_in6 *sin6;
 
 					if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 						continue;
 					}
 
-					sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
+					sin6 = &sctp_ifa->address.sin6;
 					if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 						/* we skip unspecifed addresses */
 						continue;
 					}
+#if defined(__FreeBSD__)
+					if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
+					                     &sin6->sin6_addr) != 0) {
+						continue;
+					}
+#endif
 					if (stcb->asoc.scope.local_scope == 0 &&
 					    IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 						continue;
 					if (stcb->asoc.scope.site_scope == 0 &&
 					    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
 						continue;
 
 					if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
@@ -2757,56 +2770,34 @@ sctp_compose_asconf(struct sctp_tcb *stc
  */
 static void
 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
     unsigned int offset, unsigned int length)
 {
 	struct sctp_paramhdr tmp_param, *ph;
 	uint16_t plen, ptype;
 	struct sctp_ifa *sctp_ifa;
+	union sctp_sockstore store;
 #ifdef INET6
 	struct sctp_ipv6addr_param addr6_store;
-	struct sockaddr_in6 sin6;
 #endif
 #ifdef INET
 	struct sctp_ipv4addr_param addr4_store;
-	struct sockaddr_in sin;
 #endif
-	struct sockaddr *sa;
-	uint32_t vrf_id;
 
 	SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
 	if (stcb == NULL) /* Un-needed check for SA */
 		return;
 
 	/* convert to upper bound */
 	length += offset;
 
 	if ((offset + sizeof(struct sctp_paramhdr)) > length) {
 		return;
 	}
-	/* init the addresses */
-#ifdef INET6
-	bzero(&sin6, sizeof(sin6));
-	sin6.sin6_family = AF_INET6;
-#ifdef HAVE_SIN6_LEN
-	sin6.sin6_len = sizeof(sin6);
-#endif
-	sin6.sin6_port = stcb->rport;
-#endif
-
-#ifdef INET
-	bzero(&sin, sizeof(sin));
-	sin.sin_family = AF_INET;
-#ifdef HAVE_SIN_LEN
-	sin.sin_len = sizeof(sin);
-#endif
-	sin.sin_port = stcb->rport;
-#endif
-
 	/* go through the addresses in the init-ack */
 	ph = (struct sctp_paramhdr *)
 	     sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
 	                   (uint8_t *)&tmp_param);
 	while (ph != NULL) {
 		ptype = ntohs(ph->param_type);
 		plen = ntohs(ph->param_length);
 		switch (ptype) {
@@ -2819,62 +2810,66 @@ sctp_process_initack_addresses(struct sc
 			a6p = (struct sctp_ipv6addr_param *)
 			    sctp_m_getptr(m, offset,
 			    sizeof(struct sctp_ipv6addr_param),
 			    (uint8_t *)&addr6_store);
 			if (plen != sizeof(struct sctp_ipv6addr_param) ||
 			    a6p == NULL) {
 				return;
 			}
-			memcpy(&sin6.sin6_addr, a6p->addr,
-			    sizeof(struct in6_addr));
-			sa = (struct sockaddr *)&sin6;
+			memset(&store, 0, sizeof(union sctp_sockstore));
+			store.sin6.sin6_family = AF_INET6;
+#ifdef HAVE_SIN6_LEN
+			store.sin6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+			store.sin6.sin6_port = stcb->rport;
+			memcpy(&store.sin6.sin6_addr, a6p->addr, sizeof(struct in6_addr));
 			break;
 		}
 #endif
 #ifdef INET
 		case SCTP_IPV4_ADDRESS:
 		{
 			struct sctp_ipv4addr_param *a4p;
 
 			/* get the entire IPv4 address param */
 			a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
 									  sizeof(struct sctp_ipv4addr_param),
 									  (uint8_t *)&addr4_store);
 			if (plen != sizeof(struct sctp_ipv4addr_param) ||
 			    a4p == NULL) {
 				return;
 			}
-			sin.sin_addr.s_addr = a4p->addr;
-			sa = (struct sockaddr *)&sin;
+			memset(&store, 0, sizeof(union sctp_sockstore));
+			store.sin.sin_family = AF_INET;
+#ifdef HAVE_SIN_LEN
+			store.sin.sin_len = sizeof(struct sockaddr_in);
+#endif
+			store.sin.sin_port = stcb->rport;
+			store.sin.sin_addr.s_addr = a4p->addr;
 			break;
 		}
 #endif
 		default:
 			goto next_addr;
 		}
 
 		/* see if this address really (still) exists */
-		if (stcb) {
-			vrf_id = stcb->asoc.vrf_id;
-		} else {
-			vrf_id = SCTP_DEFAULT_VRFID;
-		}
-		sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
+		sctp_ifa = sctp_find_ifa_by_addr(&store.sa, stcb->asoc.vrf_id,
 						 SCTP_ADDR_NOT_LOCKED);
 		if (sctp_ifa == NULL) {
 			/* address doesn't exist anymore */
 			int status;
 
 			/* 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);
+				status = sctp_asconf_queue_sa_delete(stcb, &store.sa);
 				/*
 				 * if queued ok, and in correct state, send
 				 * out the ASCONF.
 				 */
 				if (status == 0 &&
 				    SCTP_GET_STATE(&stcb->asoc) ==
 				    SCTP_STATE_OPEN) {
 #ifdef SCTP_TIMER_BASED_ASCONF
@@ -2898,17 +2893,17 @@ next_addr:
 				    plen, ptype);
 			return;
 		}
 		/* get next parameter */
 		offset += SCTP_SIZE32(plen);
 		if ((offset + sizeof(struct sctp_paramhdr)) > length)
 			return;
 		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
-		    sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
+		    sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
 	} /* while */
 }
 
 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
 /*
  * checks to see if a specific address is in the initack address list returns
  * 1 if found, 0 if not
  */
@@ -3110,27 +3105,39 @@ sctp_check_address_list_all(struct sctp_
 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 			/* do i have it implicitly? */
 			if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
 				continue;
 			}
 			switch (sctp_ifa->address.sa.sa_family) {
 #ifdef INET
 			case AF_INET:
-				sin = (struct sockaddr_in *)&sctp_ifa->address.sin;
+				sin = &sctp_ifa->address.sin;
+#if defined(__FreeBSD__)
+				if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
+				                     &sin->sin_addr) != 0) {
+					continue;
+				}
+#endif
 				if ((ipv4_scope == 0) &&
 				    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
 					/* private address not in scope */
 					continue;
 				}
 				break;
 #endif
 #ifdef INET6
 			case AF_INET6:
-				sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6;
+				sin6 = &sctp_ifa->address.sin6;
+#if defined(__FreeBSD__)
+				if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
+				                     &sin6->sin6_addr) != 0) {
+					continue;
+				}
+#endif
 				if ((local_scope == 0) &&
 				    (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
 					continue;
 				}
 				if ((site_scope == 0) &&
 				    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
 					continue;
 				}
@@ -3197,17 +3204,17 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *
 #ifdef HAVE_SA_LEN
 	if (sa->sa_len == 0) {
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
 		return (EINVAL);
 	}
 #endif
 	if (sctp_ifap) {
 		ifa = sctp_ifap;
-	} else 	if (type == SCTP_ADD_IP_ADDRESS) {
+	} else if (type == SCTP_ADD_IP_ADDRESS) {
 		/* For an add the address MUST be on the system */
 		ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
 	} else if (type == SCTP_DEL_IP_ADDRESS) {
 		/* For a delete we need to find it in the inp */
 		ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
 	} else {
 		ifa = NULL;
 	}
@@ -3355,16 +3362,21 @@ sctp_asconf_send_nat_state_update(struct
 		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
 		/* No need to add an address, we are using 0.0.0.0 */
 		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 		break;
 #endif
+	default:
+		SCTPDBG(SCTP_DEBUG_ASCONF1,
+		        "sctp_asconf_send_nat_state_update: unknown address family\n");
+		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
+		return;
 	}
 	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
 	            SCTP_M_ASC_ADDR);
 	if (aa == NULL) {
 		/* didn't get memory */
 		SCTPDBG(SCTP_DEBUG_ASCONF1,
 		        "sctp_asconf_send_nat_state_update: failed to get memory!\n");
 		return;
@@ -3388,16 +3400,21 @@ sctp_asconf_send_nat_state_update(struct
 		aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
 		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
 		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
 		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
 		/* No need to add an address, we are using 0.0.0.0 */
 		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
 		break;
 #endif
+	default:
+		SCTPDBG(SCTP_DEBUG_ASCONF1,
+		        "sctp_asconf_send_nat_state_update: unknown address family\n");
+		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
+		return;
 	}
 	/* Now we must hunt the addresses and add all global addresses */
 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 		struct sctp_vrf *vrf = NULL;
 		struct sctp_ifn *sctp_ifnp;
 		uint32_t vrf_id;
 
 		vrf_id = stcb->sctp_ep->def_vrf_id;
@@ -3408,27 +3425,39 @@ sctp_asconf_send_nat_state_update(struct
 
 		SCTP_IPI_ADDR_RLOCK();
 		LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
 			LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
 				switch (sctp_ifap->address.sa.sa_family) {
 #ifdef INET
 				case AF_INET:
 					to = &sctp_ifap->address.sin;
+#if defined(__FreeBSD__)
+					if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
+					                     &to->sin_addr) != 0) {
+						continue;
+					}
+#endif
 					if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
 						continue;
 					}
 					if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 						continue;
 					}
 					break;
 #endif
 #ifdef INET6
 				case AF_INET6:
 					to6 = &sctp_ifap->address.sin6;
+#if defined(__FreeBSD__)
+					if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
+					                     &to6->sin6_addr) != 0) {
+						continue;
+					}
+#endif
 					if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
 						continue;
 					}
 					if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
 						continue;
 					}
 					break;
 #endif
--- a/netwerk/sctp/src/netinet/sctp_auth.c
+++ b/netwerk/sctp/src/netinet/sctp_auth.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 257804 2013-11-07 18:50:11Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 271673 2014-09-16 14:20:33Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
@@ -130,21 +130,16 @@ sctp_auth_add_chunk(uint8_t chunk, sctp_
  * delete a chunk from the required chunks list
  */
 int
 sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list)
 {
 	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--;
 		SCTPDBG(SCTP_DEBUG_AUTH1,
 			"SCTP: deleted chunk %u (0x%02x) from Auth list\n",
 			chunk, chunk);
 	}
 	return (0);
@@ -155,26 +150,16 @@ sctp_auth_get_chklist_size(const sctp_au
 {
 	if (list == NULL)
 		return (0);
 	else
 		return (list->num_chunks);
 }
 
 /*
- * 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
  */
 int
 sctp_serialize_auth_chunks(const sctp_auth_chklist_t *list, uint8_t *ptr)
 {
 	int i, count = 0;
 
@@ -392,19 +377,19 @@ sctp_compare_key(sctp_key_t *key1, sctp_
 	key_1 = key1->key;
 	key_2 = key2->key;
 	/* check for numeric equality */
 	for (i = 0; i < maxlen; i++) {
 		/* left-pad with zeros */
 		val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++);
 		val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++);
 		if (val1 > val2) {
- 			return (1);
+			return (1);
 		} else if (val1 < val2) {
- 			return (-1);
+			return (-1);
 		}
 	}
 	/* keys are equal value, so check lengths */
 	if (key1len == key2len)
 		return (0);
 	else if (key1len < key2len)
 		return (-1);
 	else
@@ -643,17 +628,17 @@ sctp_copy_skeylist(const struct sctp_key
 			count++;
 		}
 	}
 	return (count);
 }
 
 
 sctp_hmaclist_t *
-sctp_alloc_hmaclist(uint8_t num_hmacs)
+sctp_alloc_hmaclist(uint16_t num_hmacs)
 {
 	sctp_hmaclist_t *new_list;
 	int alloc_size;
 
 	alloc_size = sizeof(*new_list) + num_hmacs * sizeof(new_list->hmac[0]);
 	SCTP_MALLOC(new_list, sctp_hmaclist_t *, alloc_size,
 		    SCTP_M_AUTH_HL);
 	if (new_list == NULL) {
@@ -795,17 +780,17 @@ sctp_serialize_hmaclist(sctp_hmaclist_t 
 
 int
 sctp_verify_hmac_param (struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs)
 {
 	uint32_t i;
 
 	for (i = 0; i < num_hmacs; i++) {
 		if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) {
-	 		return (0);
+			return (0);
 		}
 	}
 	return (-1);
 }
 
 sctp_authinfo_t *
 sctp_alloc_authinfo(void)
 {
@@ -1474,18 +1459,18 @@ sctp_auth_get_cookie_params(struct sctp_
 			phdr = sctp_get_next_param(m, offset,
 			    (struct sctp_paramhdr *)random_store, min(plen, sizeof(random_store)));
 			if (phdr == NULL)
 				return;
 			/* save the random and length for the key */
 			p_random = (struct sctp_auth_random *)phdr;
 			random_len = plen - sizeof(*p_random);
 		} else if (ptype == SCTP_HMAC_LIST) {
-			int num_hmacs;
-			int i;
+			uint16_t num_hmacs;
+			uint16_t i;
 
 			if (plen > sizeof(hmacs_store))
 				break;
 			phdr = sctp_get_next_param(m, offset,
 			    (struct sctp_paramhdr *)hmacs_store, min(plen,sizeof(hmacs_store)));
 			if (phdr == NULL)
 				return;
 			/* save the hmacs list and num for the key */
@@ -1549,17 +1534,17 @@ sctp_auth_get_cookie_params(struct sctp_
 	    }
 	    /* append in the HMACs */
 	    if (hmacs != NULL) {
 		bcopy(hmacs, new_key->key + keylen,
 		      sizeof(*hmacs) + hmacs_len);
 	    }
 	}
 	if (stcb->asoc.authinfo.random != NULL)
-	    sctp_free_key(stcb->asoc.authinfo.random);
+		sctp_free_key(stcb->asoc.authinfo.random);
 	stcb->asoc.authinfo.random = new_key;
 	stcb->asoc.authinfo.random_len = random_len;
 	sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.assoc_keyid);
 	sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.recv_keyid);
 
 	/* negotiate what HMAC to use for the peer */
 	stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
 	    stcb->asoc.local_hmacs);
@@ -1813,16 +1798,17 @@ sctp_notify_authentication(struct sctp_t
 	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_authkey_event),
 					  0, M_NOWAIT, 1, MT_HEADER);
 	if (m_notify == NULL)
 		/* no space left */
 		return;
 
 	SCTP_BUF_LEN(m_notify) = 0;
 	auth = mtod(m_notify, struct sctp_authkey_event *);
+	memset(auth, 0, sizeof(struct sctp_authkey_event));
 	auth->auth_type = SCTP_AUTHENTICATION_EVENT;
 	auth->auth_flags = 0;
 	auth->auth_length = sizeof(*auth);
 	auth->auth_keynumber = keyid;
 	auth->auth_altkeynumber = alt_keyid;
 	auth->auth_indication = indication;
 	auth->auth_assoc_id = sctp_get_associd(stcb);
 
@@ -1970,18 +1956,17 @@ sctp_validate_init_auth_params(struct mb
 	} else {
 		peer_supports_auth = 0;
 	}
 	if (!peer_supports_auth && got_chklist) {
 		SCTPDBG(SCTP_DEBUG_AUTH1,
 			"SCTP: peer sent chunk list w/o AUTH\n");
 		return (-1);
 	}
-	if (!SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) && peer_supports_asconf &&
-	    !peer_supports_auth) {
+	if (peer_supports_asconf && !peer_supports_auth) {
 		SCTPDBG(SCTP_DEBUG_AUTH1,
 			"SCTP: peer supports ASCONF but not AUTH\n");
 		return (-1);
 	} else if ((peer_supports_asconf) && (peer_supports_auth) &&
 		   ((saw_asconf == 0) || (saw_asconf_ack == 0))) {
 		return (-2);
 	}
 	return (0);
--- a/netwerk/sctp/src/netinet/sctp_auth.h
+++ b/netwerk/sctp/src/netinet/sctp_auth.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 257804 2013-11-07 18:50:11Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 271673 2014-09-16 14:20:33Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_AUTH_H_
 #define _NETINET_SCTP_AUTH_H_
 
 #include <netinet/sctp_os.h>
 
 /* digest lengths */
@@ -111,17 +111,16 @@ typedef struct sctp_authinformation {
 /* socket option api functions */
 extern sctp_auth_chklist_t *sctp_alloc_chunklist(void);
 extern void sctp_free_chunklist(sctp_auth_chklist_t *chklist);
 extern void sctp_clear_chunklist(sctp_auth_chklist_t *chklist);
 extern sctp_auth_chklist_t *sctp_copy_chunklist(sctp_auth_chklist_t *chklist);
 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);
 extern int sctp_pack_auth_chunks(const sctp_auth_chklist_t *list,
     uint8_t *ptr);
 extern int sctp_unpack_auth_chunks(const uint8_t *ptr, uint8_t num_chunks,
     sctp_auth_chklist_t *list);
 
 /* key handling */
@@ -145,17 +144,17 @@ extern int sctp_copy_skeylist(const stru
     struct sctp_keyhead *dest);
 /* ref counts on shared keys, by key id */
 extern void sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t keyid);
 extern void sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t keyid,
     int so_locked);
 
 
 /* hmac list handling */
-extern sctp_hmaclist_t *sctp_alloc_hmaclist(uint8_t num_hmacs);
+extern sctp_hmaclist_t *sctp_alloc_hmaclist(uint16_t num_hmacs);
 extern void sctp_free_hmaclist(sctp_hmaclist_t *list);
 extern int sctp_auth_add_hmacid(sctp_hmaclist_t *list, uint16_t hmac_id);
 extern sctp_hmaclist_t *sctp_copy_hmaclist(sctp_hmaclist_t *list);
 extern sctp_hmaclist_t *sctp_default_supported_hmaclist(void);
 extern uint16_t sctp_negotiate_hmacid(sctp_hmaclist_t *peer,
     sctp_hmaclist_t *local);
 extern int sctp_serialize_hmaclist(sctp_hmaclist_t *list, uint8_t *ptr);
 extern int sctp_verify_hmac_param(struct sctp_auth_hmac_algo *hmacs,
--- a/netwerk/sctp/src/netinet/sctp_bsd_addr.c
+++ b/netwerk/sctp/src/netinet/sctp_bsd_addr.c
@@ -27,40 +27,35 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 258765 2013-11-30 12:51:19Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 276914 2015-01-10 20:49:57Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
 #include <netinet/sctp_output.h>
 #include <netinet/sctp_bsd_addr.h>
 #include <netinet/sctp_uio.h>
 #include <netinet/sctputil.h>
 #include <netinet/sctp_timer.h>
 #include <netinet/sctp_asconf.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_indata.h>
-#if defined(ANDROID)
-#include <unistd.h>
-#include <ifaddrs-android-ext.h>
-#else
 #if defined(__FreeBSD__)
 #include <sys/unistd.h>
 #endif
-#endif
 
 /* Declare all of our malloc named types */
 #ifndef __Panda__
 MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor");
 MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array");
 MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array");
 MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address");
 MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator");
@@ -355,17 +350,17 @@ sctp_init_ifns_for_vrf(int vrfid)
 	/* Enumerate through each returned adapter and save its information */
 	for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
 		if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
 			for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
 				if (IN4_ISLINKLOCAL_ADDRESS(&(((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))->sin_addr))) {
 					continue;
 				}
 				ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
-				ifa->ifa_name = strdup(pAdapt->AdapterName);
+				ifa->ifa_name = _strdup(pAdapt->AdapterName);
 				ifa->ifa_flags = pAdapt->Flags;
 				ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
 				memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in));
 
 				sctp_ifa = sctp_add_addr_to_vrf(0,
 				                                ifa,
 				                                pAdapt->IfIndex,
 				                                (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType,
@@ -403,17 +398,17 @@ sctp_init_ifns_for_vrf(int vrfid)
 		SCTP_PRINTF("GetAdaptersV6Addresses() failed with error code %d\n", Err);
 		return;
 	}
 	/* Enumerate through each returned adapter and save its information */
 	for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
 		if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
 			for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
 				ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
-				ifa->ifa_name = strdup(pAdapt->AdapterName);
+				ifa->ifa_name = _strdup(pAdapt->AdapterName);
 				ifa->ifa_flags = pAdapt->Flags;
 				ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
 				memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in6));
 				sctp_ifa = sctp_add_addr_to_vrf(0,
 				                                ifa,
 				                                pAdapt->Ipv6IfIndex,
 				                                (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType,
 				                                ifa->ifa_name,
@@ -745,17 +740,17 @@ sctp_addr_change(struct ifaddr *ifa, int
 		sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
 #if defined(__APPLE__)
 		                       ifnet_index(ifa->ifa_ifp),
 		                       ifnet_name(ifa->ifa_ifp));
 #else
 		                       ifa->ifa_ifp->if_index,
 		                       ifa->ifa_ifp->if_xname);
 #endif
-		                      
+
 		/* We don't bump refcount here so when it completes
 		 * the final delete will happen.
 		 */
 	}
 #endif
 }
 
 #if defined(__FreeBSD__)
@@ -837,34 +832,51 @@ sctp_get_mbuf_for_msg(unsigned int space
 
 	if ((int)space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
 		MCLGET(m, how);
 		if (m == NULL) {
 			return (NULL);
 		}
 
 		if (SCTP_BUF_IS_EXTENDED(m) == 0) {
-		  sctp_m_freem(m);
-		  return (NULL);
+			sctp_m_freem(m);
+			return (NULL);
 		}
 	}
 	SCTP_BUF_LEN(m) = 0;
 	SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
 
-#if defined(__Userspace__)
 	/* __Userspace__
 	 * Check if anything need to be done to ensure logging works
 	 */
-#endif
 #ifdef SCTP_MBUF_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		if (SCTP_BUF_IS_EXTENDED(m)) {
-			sctp_log_mb(m, SCTP_MBUF_IALLOC);
+		sctp_log_mb(m, SCTP_MBUF_IALLOC);
+	}
+#endif
+#elif defined(__FreeBSD__) && __FreeBSD_version > 1100052
+	m =  m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
+	if (m == NULL) {
+		/* bad, no memory */
+		return (m);
+	}
+	if (allonebuf) {
+		if (SCTP_BUF_SIZE(m) < space_needed) {
+			m_freem(m);
+			return (NULL);
 		}
 	}
+	if (SCTP_BUF_NEXT(m)) {
+		sctp_m_freem(SCTP_BUF_NEXT(m));
+		SCTP_BUF_NEXT(m) = NULL;
+	}
+#ifdef SCTP_MBUF_LOGGING
+	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+		sctp_log_mb(m, SCTP_MBUF_IALLOC);
+	}
 #endif
 #elif defined(__FreeBSD__) && __FreeBSD_version > 602000
 	m =  m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
 	if (m == NULL) {
 		/* bad, no memory */
 		return (m);
 	}
 	if (allonebuf) {
@@ -878,24 +890,22 @@ sctp_get_mbuf_for_msg(unsigned int space
 				siz = MLEN;
 		}
 		if (siz < space_needed) {
 			m_freem(m);
 			return (NULL);
 		}
 	}
 	if (SCTP_BUF_NEXT(m)) {
-		sctp_m_freem( SCTP_BUF_NEXT(m));
+		sctp_m_freem(SCTP_BUF_NEXT(m));
 		SCTP_BUF_NEXT(m) = NULL;
 	}
 #ifdef SCTP_MBUF_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		if (SCTP_BUF_IS_EXTENDED(m)) {
-			sctp_log_mb(m, SCTP_MBUF_IALLOC);
-		}
+		sctp_log_mb(m, SCTP_MBUF_IALLOC);
 	}
 #endif
 #else
 #if defined(__FreeBSD__) && __FreeBSD_version >= 601000
 	int aloc_size;
 	int index = 0;
 #endif
 	int mbuf_threshold;
@@ -946,19 +956,17 @@ sctp_get_mbuf_for_msg(unsigned int space
 			return (NULL);
 		}
 #endif
 	}
 	SCTP_BUF_LEN(m) = 0;
 	SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
 #ifdef SCTP_MBUF_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		if (SCTP_BUF_IS_EXTENDED(m)) {
-			sctp_log_mb(m, SCTP_MBUF_IALLOC);
-		}
+		sctp_log_mb(m, SCTP_MBUF_IALLOC);
 	}
 #endif
 #endif
 	return (m);
 }
 
 
 #ifdef SCTP_PACKET_LOGGING
--- a/netwerk/sctp/src/netinet/sctp_callout.c
+++ b/netwerk/sctp/src/netinet/sctp_callout.c
@@ -59,20 +59,18 @@
 int ticks = 0;
 #else
 extern int ticks;
 #endif
 
 /*
  * SCTP_TIMERQ_LOCK protects:
  * - SCTP_BASE_INFO(callqueue)
- * - sctp_os_timer_current: current timer in process
  * - sctp_os_timer_next: next timer to check
  */
-static sctp_os_timer_t *sctp_os_timer_current = NULL;
 static sctp_os_timer_t *sctp_os_timer_next = NULL;
 
 void
 sctp_os_timer_init(sctp_os_timer_t *c)
 {
 	bzero(c, sizeof(*c));
 }
 
@@ -148,21 +146,19 @@ sctp_handle_tick(int delta)
 	c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue));
 	while (c) {
 		if (c->c_time <= ticks) {
 			sctp_os_timer_next = TAILQ_NEXT(c, tqe);
 			TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe);
 			c_func = c->c_func;
 			c_arg = c->c_arg;
 			c->c_flags &= ~SCTP_CALLOUT_PENDING;
-			sctp_os_timer_current = c;
 			SCTP_TIMERQ_UNLOCK();
 			c_func(c_arg);
 			SCTP_TIMERQ_LOCK();
-			sctp_os_timer_current = NULL;
 			c = sctp_os_timer_next;
 		} else {
 			c = TAILQ_NEXT(c, tqe);
 		}
 	}
 	sctp_os_timer_next = NULL;
 	SCTP_TIMERQ_UNLOCK();
 }
--- a/netwerk/sctp/src/netinet/sctp_cc_functions.c
+++ b/netwerk/sctp/src/netinet/sctp_cc_functions.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 240158 2012-09-06 07:03:56Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 271672 2014-09-16 13:48:46Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
@@ -1213,34 +1213,32 @@ sctp_cwnd_update_after_ecn_echo_common(s
 }
 
 static void
 sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
 	struct sctp_nets *net, struct sctp_pktdrop_chunk *cp,
 	uint32_t *bottle_bw, uint32_t *on_queue)
 {
 	uint32_t bw_avail;
-	int rtt;
 	unsigned int incr;
 	int old_cwnd = net->cwnd;
 
-	/* need real RTT in msd for this calc */
-	rtt = net->rtt / 1000;
 	/* get bottle neck bw */
 	*bottle_bw = ntohl(cp->bottle_bw);
 	/* and whats on queue */
 	*on_queue = ntohl(cp->current_onq);
 	/*
 	 * adjust the on-queue if our flight is more it could be
 	 * that the router has not yet gotten data "in-flight" to it
 	 */
-	if (*on_queue < net->flight_size)
+	if (*on_queue < net->flight_size) {
 		*on_queue = net->flight_size;
-		/* calculate the available space */
-	bw_avail = (*bottle_bw * rtt) / 1000;
+	}
+	/* rtt is measured in micro seconds, bottle_bw in bytes per second */
+	bw_avail = (uint32_t)(((uint64_t)(*bottle_bw) * net->rtt) / (uint64_t)1000000);
 	if (bw_avail > *bottle_bw) {
 		/*
 		 * Cap the growth to no more than the bottle neck.
 		 * This can happen as RTT slides up due to queues.
 		 * It also means if you have more than a 1 second
 		 * RTT with a empty queue you will be limited to the
 		 * bottle_bw per second no matter if other points
 		 * have 1/2 the RTT and you could get more out...
@@ -1248,18 +1246,18 @@ sctp_cwnd_update_after_packet_dropped(st
 		bw_avail = *bottle_bw;
 	}
 	if (*on_queue > bw_avail) {
 		/*
 		 * No room for anything else don't allow anything
 		 * else to be "added to the fire".
 		 */
 		int seg_inflight, seg_onqueue, my_portion;
-			net->partial_bytes_acked = 0;
 
+		net->partial_bytes_acked = 0;
 		/* how much are we over queue size? */
 		incr = *on_queue - bw_avail;
 		if (stcb->asoc.seen_a_sack_this_pkt) {
 			/*
 			 * undo any cwnd adjustment that the sack
 			 * might have made
 			 */
 			net->cwnd = net->prev_cwnd;
--- a/netwerk/sctp/src/netinet/sctp_constants.h
+++ b/netwerk/sctp/src/netinet/sctp_constants.h
@@ -27,39 +27,29 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 256556 2013-10-15 20:21:27Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 271204 2014-09-06 19:12:14Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_CONSTANTS_H_
 #define _NETINET_SCTP_CONSTANTS_H_
 
 #if defined(__Userspace_os_Windows)
 extern void getwintimeofday(struct timeval *tv);
 #endif
+
 /* IANA assigned port number for SCTP over UDP encapsulation */
-#ifdef __FreeBSD__
-/* For freebsd we cannot bind the port at
- * startup. Otherwise what will happen is
- * we really won't be bound. The user must
- * put it into the sysctl... or we need
- * to build a special timer for this to allow
- * us to wait 1 second or so after the system
- * comes up.
- */
-#define SCTP_OVER_UDP_TUNNELING_PORT 0
-#else
 #define SCTP_OVER_UDP_TUNNELING_PORT 9899
-#endif
+
 /* Number of packets to get before sack sent by default */
 #define SCTP_DEFAULT_SACK_FREQ 2
 
 /* Address limit - This variable is calculated
  * based on an 65535 byte max ip packet. We take out 100 bytes
  * for the cookie, 40 bytes for a v6 header and 32
  * bytes for the init structure. A second init structure
  * for the init-ack and then finally a third one for the
@@ -277,52 +267,19 @@ extern void getwintimeofday(struct timev
 #define SCTP_LOCK_UNKNOWN 2
 
 
 /* number of associations by default for zone allocation */
 #define SCTP_MAX_NUM_OF_ASOC	40000
 /* how many addresses per assoc remote and local */
 #define SCTP_SCALE_FOR_ADDR	2
 
-/* default AUTO_ASCONF mode enable(1)/disable(0) value (sysctl) */
-#if defined(__APPLE__)
-#if !defined(SCTP_APPLE_AUTO_ASCONF)
-#define SCTP_DEFAULT_AUTO_ASCONF        0
-#else
-#define SCTP_DEFAULT_AUTO_ASCONF	1
-#endif
-#else
-#define SCTP_DEFAULT_AUTO_ASCONF	1
-#endif
-
 /* default MULTIPLE_ASCONF mode enable(1)/disable(0) value (sysctl) */
 #define SCTP_DEFAULT_MULTIPLE_ASCONFS	0
 
-/* default MOBILITY_BASE mode enable(1)/disable(0) value (sysctl) */
-#if defined(__APPLE__)
-#if !defined(SCTP_APPLE_MOBILITY_BASE)
-#define SCTP_DEFAULT_MOBILITY_BASE      0
-#else
-#define SCTP_DEFAULT_MOBILITY_BASE	1
-#endif
-#else
-#define SCTP_DEFAULT_MOBILITY_BASE	0
-#endif
-
-/* default MOBILITY_FASTHANDOFF mode enable(1)/disable(0) value (sysctl) */
-#if defined(__APPLE__)
-#if !defined(SCTP_APPLE_MOBILITY_FASTHANDOFF)
-#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF	0
-#else
-#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF	1
-#endif
-#else
-#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF	0
-#endif
-
 /*
  * Theshold for rwnd updates, we have to read (sb_hiwat >>
  * SCTP_RWND_HIWAT_SHIFT) before we will look to see if we need to send a
  * window update sack. When we look, we compare the last rwnd we sent vs the
  * current rwnd. It too must be greater than this value. Using 3 divdes the
  * hiwat by 8, so for 200k rwnd we need to read 24k. For a 64k rwnd we need
  * to read 8k. This seems about right.. I hope :-D.. we do set a
  * min of a MTU on it so if the rwnd is real small we will insist
@@ -814,16 +771,19 @@ extern void getwintimeofday(struct timev
 /* This is the value for messages that are NOT completely
  * copied down where we will start to split the message.
  * So, with our default, we split only if the piece we
  * want to take will fill up a full MTU (assuming
  * a 1500 byte MTU).
  */
 #define SCTP_DEFAULT_SPLIT_POINT_MIN 2904
 
+/* Maximum length of diagnostic information in error causes */
+#define SCTP_DIAG_INFO_LEN 64
+
 /* ABORT CODES and other tell-tale location
  * codes are generated by adding the below
  * to the instance id.
  */
 
 /* File defines */
 #define SCTP_FROM_SCTP_INPUT   0x10000000
 #define SCTP_FROM_SCTP_PCB     0x20000000
--- a/netwerk/sctp/src/netinet/sctp_header.h
+++ b/netwerk/sctp/src/netinet/sctp_header.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 240198 2012-09-07 13:36:42Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 273168 2014-10-16 15:36:04Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_HEADER_H_
 #define _NETINET_SCTP_HEADER_H_
 
 #if defined(__Windows__) && !defined(__Userspace_os_Windows)
 #include <packon.h>
 #endif
@@ -89,22 +89,16 @@ struct sctp_host_name_param {
  */
 #define SCTP_MAX_ADDR_PARAMS_SIZE 12
 /* supported address type */
 struct sctp_supported_addr_param {
 	struct sctp_paramhdr ph;/* type=SCTP_SUPPORTED_ADDRTYPE */
 	uint16_t addr_type[2];	/* array of supported address types */
 } SCTP_PACKED;
 
-/* ECN parameter */
-struct sctp_ecn_supported_param {
-	struct sctp_paramhdr ph;/* type=SCTP_ECN_CAPABLE */
-} SCTP_PACKED;
-
-
 /* heartbeat info parameter */
 struct sctp_heartbeat_info_param {
 	struct sctp_paramhdr ph;
 	uint32_t time_value_1;
 	uint32_t time_value_2;
 	uint32_t random_value1;
 	uint32_t random_value2;
 	uint8_t addr_family;
@@ -469,31 +463,35 @@ struct sctp_pktdrop_chunk {
 	uint32_t current_onq;
 	uint16_t trunc_len;
 	uint16_t reserved;
 	uint8_t data[];
 } SCTP_PACKED;
 
 /**********STREAM RESET STUFF ******************/
 
+struct sctp_stream_reset_request {
+	struct sctp_paramhdr ph;
+	uint32_t request_seq;
+} SCTP_PACKED;
+
 struct sctp_stream_reset_out_request {
 	struct sctp_paramhdr ph;
 	uint32_t request_seq;	/* monotonically increasing seq no */
 	uint32_t response_seq;	/* if a response, the resp seq no */
 	uint32_t send_reset_at_tsn;	/* last TSN I assigned outbound */
 	uint16_t list_of_streams[];	/* if not all list of streams */
 } SCTP_PACKED;
 
 struct sctp_stream_reset_in_request {
 	struct sctp_paramhdr ph;
 	uint32_t request_seq;
 	uint16_t list_of_streams[];	/* if not all list of streams */
 } SCTP_PACKED;
 
-
 struct sctp_stream_reset_tsn_request {
 	struct sctp_paramhdr ph;
 	uint32_t request_seq;
 } SCTP_PACKED;
 
 struct sctp_stream_reset_response {
 	struct sctp_paramhdr ph;
 	uint32_t response_seq;	/* if a response, the resp seq no */
--- a/netwerk/sctp/src/netinet/sctp_indata.c
+++ b/netwerk/sctp/src/netinet/sctp_indata.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 258228 2013-11-16 16:09:09Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 276914 2015-01-10 20:49:57Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
@@ -256,16 +256,21 @@ sctp_build_ctl_nchunk(struct sctp_inpcb 
 	SCTP_BUF_LEN(ret) = 0;
 
 	/* We need a CMSG header followed by the struct */
 #if defined(__Userspace_os_Windows)
 	cmh = mtod(ret, WSACMSGHDR *);
 #else
 	cmh = mtod(ret, struct cmsghdr *);
 #endif
+	/*
+	 * Make sure that there is no un-initialized padding between
+	 * the cmsg header and cmsg data and after the cmsg data.
+	 */
+	memset(cmh, 0, len);
 	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
 		cmh->cmsg_level = IPPROTO_SCTP;
 		cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo));
 		cmh->cmsg_type = SCTP_RCVINFO;
 		rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmh);
 		rcvinfo->rcv_sid = sinfo->sinfo_stream;
 		rcvinfo->rcv_ssn = sinfo->sinfo_ssn;
 		rcvinfo->rcv_flags = sinfo->sinfo_flags;
@@ -406,17 +411,17 @@ sctp_service_reassembly(struct sctp_tcb 
 			 * buffer
 			 */
 			if (chk->data) {
 				sctp_m_freem(chk->data);
 				chk->data = NULL;
 			}
 			/* Now free the address and data */
 			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
-        		/*sa_ignore FREED_MEMORY*/
+			/*sa_ignore FREED_MEMORY*/
 		}
 		return;
 	}
 	SCTP_TCB_LOCK_ASSERT(stcb);
 	TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
 		if (chk->rec.data.TSN_seq != (asoc->tsn_last_delivered + 1)) {
 			/* Can't deliver more :< */
 			return;
@@ -574,60 +579,48 @@ sctp_queue_data_to_stream(struct sctp_tc
 	 * a violation. So for now I am undecided an will leave the sort by
 	 * SSN alone. Maybe a hybred approach is the answer
 	 *
 	 */
 	struct sctp_stream_in *strm;
 	struct sctp_queued_to_read *at;
 	int queue_needed;
 	uint16_t nxt_todel;
-	struct mbuf *oper;
+	struct mbuf *op_err;
+	char msg[SCTP_DIAG_INFO_LEN];
 
 	queue_needed = 1;
 	asoc->size_on_all_streams += control->length;
 	sctp_ucount_incr(asoc->cnt_on_all_streams);
 	strm = &asoc->strmin[control->sinfo_stream];
 	nxt_todel = strm->last_sequence_delivered + 1;
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
 		sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD);
 	}
 	SCTPDBG(SCTP_DEBUG_INDATA1,
 		"queue to stream called for ssn:%u lastdel:%u nxt:%u\n",
 		(uint32_t) control->sinfo_stream,
 		(uint32_t) strm->last_sequence_delivered,
 		(uint32_t) nxt_todel);
 	if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) {
 		/* The incoming sseq is behind where we last delivered? */
-		SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort  association\n",
+		SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n",
 			control->sinfo_ssn, strm->last_sequence_delivered);
 	protocol_error:
 		/*
 		 * throw it in the stream so it gets cleaned up in
 		 * association destruction
 		 */
 		TAILQ_INSERT_HEAD(&strm->inqueue, control, next);
-		oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-					     0, M_NOWAIT, 1, MT_DATA);
-		if (oper) {
-			struct sctp_paramhdr *ph;
-			uint32_t *ippp;
-			SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
-			    (sizeof(uint32_t) * 3);
-			ph = mtod(oper, struct sctp_paramhdr *);
-			ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-			ph->param_length = htons(SCTP_BUF_LEN(oper));
-			ippp = (uint32_t *) (ph + 1);
-			*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_1);
-			ippp++;
-			*ippp = control->sinfo_tsn;
-			ippp++;
-			*ippp = ((control->sinfo_stream << 16) | control->sinfo_ssn);
-		}
+		snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+		         strm->last_sequence_delivered, control->sinfo_tsn,
+			 control->sinfo_stream, control->sinfo_ssn);
+		op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 		stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_1;
-		sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 		*abort_flag = 1;
 		return;
 
 	}
 	if (nxt_todel == control->sinfo_ssn) {
 		/* can be delivered right away? */
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
 			sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_IMMED_DEL);
@@ -672,18 +665,18 @@ sctp_queue_data_to_stream(struct sctp_tc
 			break;
 		}
 	}
 	if (queue_needed) {
 		/*
 		 * Ok, we did not deliver this guy, find the correct place
 		 * to put it on the queue.
 		 */
-  	        if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) {
-		        goto protocol_error;
+		if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) {
+			goto protocol_error;
 		}
 		if (TAILQ_EMPTY(&strm->inqueue)) {
 			/* Empty queue */
 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
 				sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INSERT_HD);
 			}
 			TAILQ_INSERT_HEAD(&strm->inqueue, control, next);
 		} else {
@@ -849,17 +842,18 @@ sctp_deliver_reasm_check(struct sctp_tcb
  * queue, see if anthing can be delivered. If so pull it off (or as much as
  * we can. If we run out of space then we must dump what we can and set the
  * appropriate flag to say we queued what we could.
  */
 static void
 sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
     struct sctp_tmit_chunk *chk, int *abort_flag)
 {
-	struct mbuf *oper;
+	struct mbuf *op_err;
+	char msg[SCTP_DIAG_INFO_LEN];
 	uint32_t cum_ackp1, prev_tsn, post_tsn;
 	struct sctp_tmit_chunk *at, *prev, *next;
 
 	prev = next = NULL;
 	cum_ackp1 = asoc->tsn_last_delivered + 1;
 	if (TAILQ_EMPTY(&asoc->reasmqueue)) {
 		/* This is the first one on the queue */
 		TAILQ_INSERT_HEAD(&asoc->reasmqueue, chk, sctp_next);
@@ -874,140 +868,79 @@ sctp_queue_data_for_reasm(struct sctp_tc
 			    (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) !=
 			    SCTP_DATA_FIRST_FRAG) {
 				/*
 				 * An empty queue, no delivery inprogress,
 				 * we hit the next one and it does NOT have
 				 * a FIRST fragment mark.
 				 */
 				SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not first, no fragmented delivery in progress\n");
-				oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-							       0, M_NOWAIT, 1, MT_DATA);
-
-				if (oper) {
-					struct sctp_paramhdr *ph;
-					uint32_t *ippp;
-
-					SCTP_BUF_LEN(oper) =
-					    sizeof(struct sctp_paramhdr) +
-					    (sizeof(uint32_t) * 3);
-					ph = mtod(oper, struct sctp_paramhdr *);
-					ph->param_type =
-					    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-					ph->param_length = htons(SCTP_BUF_LEN(oper));
-					ippp = (uint32_t *) (ph + 1);
-					*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_2);
-					ippp++;
-					*ippp = chk->rec.data.TSN_seq;
-					ippp++;
-					*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-
-				}
+				snprintf(msg, sizeof(msg),
+				         "Expected B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+				         chk->rec.data.TSN_seq,
+				         chk->rec.data.stream_number,
+				         chk->rec.data.stream_seq);
+				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_2;
-				sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 				*abort_flag = 1;
 			} else if (asoc->fragmented_delivery_inprogress &&
 			    (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) {
 				/*
 				 * We are doing a partial delivery and the
 				 * NEXT chunk MUST be either the LAST or
 				 * MIDDLE fragment NOT a FIRST
 				 */
 				SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS a first and fragmented delivery in progress\n");
-				oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-							     0, M_NOWAIT, 1, MT_DATA);
-				if (oper) {
-					struct sctp_paramhdr *ph;
-					uint32_t *ippp;
-
-					SCTP_BUF_LEN(oper) =
-					    sizeof(struct sctp_paramhdr) +
-					    (3 *sizeof(uint32_t));
-					ph = mtod(oper, struct sctp_paramhdr *);
-					ph->param_type =
-					    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-					ph->param_length = htons(SCTP_BUF_LEN(oper));
-					ippp = (uint32_t *) (ph + 1);
-					*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_3);
-					ippp++;
-					*ippp = chk->rec.data.TSN_seq;
-					ippp++;
-					*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-				}
+				snprintf(msg, sizeof(msg),
+				         "Didn't expect B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+				         chk->rec.data.TSN_seq,
+				         chk->rec.data.stream_number,
+				         chk->rec.data.stream_seq);
+				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_3;
-				sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 				*abort_flag = 1;
 			} else if (asoc->fragmented_delivery_inprogress) {
 				/*
 				 * Here we are ok with a MIDDLE or LAST
 				 * piece
 				 */
 				if (chk->rec.data.stream_number !=
 				    asoc->str_of_pdapi) {
 					/* Got to be the right STR No */
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream number %d vs %d\n",
 						chk->rec.data.stream_number,
 						asoc->str_of_pdapi);
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (sizeof(uint32_t) * 3);
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_4);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-					}
+					snprintf(msg, sizeof(msg),
+					         "Expected SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         asoc->str_of_pdapi,
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_4;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 				} else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) !=
 					    SCTP_DATA_UNORDERED &&
 					    chk->rec.data.stream_seq != asoc->ssn_of_pdapi) {
 					/* Got to be the right STR Seq */
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream seq %d vs %d\n",
 						chk->rec.data.stream_seq,
 						asoc->ssn_of_pdapi);
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_5);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-
-					}
+					snprintf(msg, sizeof(msg),
+					         "Expected SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         asoc->ssn_of_pdapi,
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_5;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 				}
 			}
 		}
 		return;
 	}
 	/* Find its place */
 	TAILQ_FOREACH(at, &asoc->reasmqueue, sctp_next) {
@@ -1067,148 +1000,102 @@ sctp_queue_data_for_reasm(struct sctp_tc
 				/*
 				 * Insert chk MUST be a MIDDLE or LAST
 				 * fragment
 				 */
 				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
 				    SCTP_DATA_FIRST_FRAG) {
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - It can be a midlle or last but not a first\n");
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it's a FIRST!\n");
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_6);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-
-					}
+					snprintf(msg, sizeof(msg),
+					         "Can't handle B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_6;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 				if (chk->rec.data.stream_number !=
 				    prev->rec.data.stream_number) {
 					/*
 					 * Huh, need the correct STR here,
 					 * they must be the same.
 					 */
-					SCTP_PRINTF("Prev check - Gak, Evil plot, ssn:%d not the same as at:%d\n",
-						    chk->rec.data.stream_number,
-						    prev->rec.data.stream_number);
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_7);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-					}
+					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sid:%d not the same as at:%d\n",
+					        chk->rec.data.stream_number,
+					        prev->rec.data.stream_number);
+					snprintf(msg, sizeof(msg),
+					         "Expect SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         prev->rec.data.stream_number,
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+					*abort_flag = 1;
+					return;
+				}
+				if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
+				    (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) {
+					/*
+					 * Huh, need the same ordering here,
+					 * they must be the same.
+					 */
+					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, U-bit not constant\n");
+					snprintf(msg, sizeof(msg),
+					         "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d",
+					         (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0,
+					         chk->rec.data.TSN_seq,
+					         (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7;
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 				if ((prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 &&
 				    chk->rec.data.stream_seq !=
 				    prev->rec.data.stream_seq) {
 					/*
 					 * Huh, need the correct STR here,
 					 * they must be the same.
 					 */
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sseq:%d not the same as at:%d\n",
 						chk->rec.data.stream_seq,
 						prev->rec.data.stream_seq);
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_8);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-					}
+					snprintf(msg, sizeof(msg),
+					         "Expect SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         prev->rec.data.stream_seq,
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_8;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 			} else if ((prev->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
 			    SCTP_DATA_LAST_FRAG) {
 				/* Insert chk MUST be a FIRST */
 				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) !=
 				    SCTP_DATA_FIRST_FRAG) {
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, evil plot, its not FIRST and it must be!\n");
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_9);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-
-					}
+					snprintf(msg, sizeof(msg),
+					         "Expect B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_9;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 			}
 		}
 	}
 	if (next) {
 		post_tsn = chk->rec.data.TSN_seq + 1;
@@ -1218,154 +1105,108 @@ sctp_queue_data_for_reasm(struct sctp_tc
 			 * one. A bit of valdiation here.
 			 */
 			if (next->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
 				/* Insert chk MUST be a last fragment */
 				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK)
 				    != SCTP_DATA_LAST_FRAG) {
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is FIRST, we must be LAST\n");
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not a last!\n");
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    ( 3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_10);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-					}
+					snprintf(msg, sizeof(msg),
+					         "Expect only E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_10;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 			} else if ((next->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
 				    SCTP_DATA_MIDDLE_FRAG ||
 				    (next->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
 			    SCTP_DATA_LAST_FRAG) {
 				/*
 				 * Insert chk CAN be MIDDLE or FIRST NOT
 				 * LAST
 				 */
 				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
 				    SCTP_DATA_LAST_FRAG) {
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is a MIDDLE/LAST\n");
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, new prev chunk is a LAST\n");
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_11);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-
-					}
+					snprintf(msg, sizeof(msg),
+					         "Didn't expect E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_11;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 				if (chk->rec.data.stream_number !=
 				    next->rec.data.stream_number) {
 					/*
 					 * Huh, need the correct STR here,
 					 * they must be the same.
 					 */
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, ssn:%d not the same as at:%d\n",
 						chk->rec.data.stream_number,
 						next->rec.data.stream_number);
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_12);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-
-					}
+					snprintf(msg, sizeof(msg),
+					         "Required SID %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         next->rec.data.stream_number,
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+					*abort_flag = 1;
+					return;
+				}
+				if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
+				    (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) {
+					/*
+					 * Huh, need the same ordering here,
+					 * they must be the same.
+					 */
+					SCTPDBG(SCTP_DEBUG_INDATA1, "Next check - Gak, Evil plot, U-bit not constant\n");
+					snprintf(msg, sizeof(msg),
+					         "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d",
+					         (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0,
+					         chk->rec.data.TSN_seq,
+					         (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12;
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 				if ((next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 &&
 				    chk->rec.data.stream_seq !=
 				    next->rec.data.stream_seq) {
 					/*
 					 * Huh, need the correct STR here,
 					 * they must be the same.
 					 */
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, sseq:%d not the same as at:%d\n",
 						chk->rec.data.stream_seq,
 						next->rec.data.stream_seq);
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_13);
-						ippp++;
-						*ippp = chk->rec.data.TSN_seq;
-						ippp++;
-						*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
-					}
+					snprintf(msg, sizeof(msg),
+					         "Required SSN %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         next->rec.data.stream_seq,
+					         chk->rec.data.TSN_seq,
+					         chk->rec.data.stream_number,
+					         chk->rec.data.stream_seq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_13;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 					*abort_flag = 1;
 					return;
 				}
 			}
 		}
 	}
 	/* Do we need to do some delivery? check */
 	sctp_deliver_reasm_check(stcb, asoc);
@@ -1440,17 +1281,18 @@ sctp_process_a_data_chunk(struct sctp_tc
 	/* Process a data chunk */
 	/* struct sctp_tmit_chunk *chk; */
 	struct sctp_tmit_chunk *chk;
 	uint32_t tsn, gap;
 	struct mbuf *dmbuf;
 	int the_len;
 	int need_reasm_check = 0;
 	uint16_t strmno, strmseq;
-	struct mbuf *oper;
+	struct mbuf *op_err;
+	char msg[SCTP_DIAG_INFO_LEN];
 	struct sctp_queued_to_read *control;
 	int ordered;
 	uint32_t protocol_id;
 	uint8_t chunk_flags;
 	struct sctp_stream_reset_list *liste;
 
 	chk = NULL;
 	tsn = ntohl(ch->dp.tsn);
@@ -1507,25 +1349,22 @@ sctp_process_a_data_chunk(struct sctp_tc
 		return (0);
 	}
 	/*
 	 * Check to see about the GONE flag, duplicates would cause a sack
 	 * to be sent up above
 	 */
 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
 	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
-	     (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET))
-		) {
+	     (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET))) {
 		/*
 		 * wait a minute, this guy is gone, there is no longer a
 		 * receiver. Send peer an ABORT!
 		 */
-		struct mbuf *op_err;
-
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
+		op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
 		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 		*abort_flag = 1;
 		return (0);
 	}
 	/*
 	 * Now before going further we see if there is room. If NOT then we
 	 * MAY let one through only IF this TSN is the one we are waiting
 	 * for on a partial delivery API.
@@ -1643,59 +1482,39 @@ sctp_process_a_data_chunk(struct sctp_tc
 #endif
 	if ((chunk_flags & SCTP_DATA_FIRST_FRAG) &&
 	    (TAILQ_EMPTY(&asoc->resetHead)) &&
 	    (chunk_flags & SCTP_DATA_UNORDERED) == 0 &&
 	    SCTP_SSN_GE(asoc->strmin[strmno].last_sequence_delivered, strmseq)) {
 		/* The incoming sseq is behind where we last delivered? */
 		SCTPDBG(SCTP_DEBUG_INDATA1, "EVIL/Broken-Dup S-SEQ:%d delivered:%d from peer, Abort!\n",
 			strmseq, asoc->strmin[strmno].last_sequence_delivered);
-		oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-					     0, M_NOWAIT, 1, MT_DATA);
-		if (oper) {
-			struct sctp_paramhdr *ph;
-			uint32_t *ippp;
-
-			SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
-			    (3 * sizeof(uint32_t));
-			ph = mtod(oper, struct sctp_paramhdr *);
-			ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-			ph->param_length = htons(SCTP_BUF_LEN(oper));
-			ippp = (uint32_t *) (ph + 1);
-			*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_14);
-			ippp++;
-			*ippp = tsn;
-			ippp++;
-			*ippp = ((strmno << 16) | strmseq);
-
-		}
+
+		snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+		         asoc->strmin[strmno].last_sequence_delivered,
+		         tsn, strmno, strmseq);
+		op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 		stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_14;
-		sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 		*abort_flag = 1;
 		return (0);
 	}
 	/************************************
 	 * From here down we may find ch-> invalid
 	 * so its a good idea NOT to use it.
 	 *************************************/
 
 	the_len = (chk_length - sizeof(struct sctp_data_chunk));
 	if (last_chunk == 0) {
 		dmbuf = SCTP_M_COPYM(*m,
 				     (offset + sizeof(struct sctp_data_chunk)),
 				     the_len, M_NOWAIT);
 #ifdef SCTP_MBUF_LOGGING
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-			struct mbuf *mat;
-
-			for (mat = dmbuf; mat; mat = SCTP_BUF_NEXT(mat)) {
-				if (SCTP_BUF_IS_EXTENDED(mat)) {
-					sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-				}
-			}
+			sctp_log_mbc(dmbuf, SCTP_MBUF_ICOPY);
 		}
 #endif
 	} else {
 		/* We can steal the last chunk */
 		int l_len;
 		dmbuf = *m;
 		/* lop off the top part */
 		m_adj(dmbuf, (offset + sizeof(struct sctp_data_chunk)));
@@ -1898,75 +1717,44 @@ failed_express_del:
 				/* Evil/Broke peer */
 				sctp_m_freem(control->data);
 				control->data = NULL;
 				if (control->whoFrom) {
 					sctp_free_remote_addr(control->whoFrom);
 					control->whoFrom = NULL;
 				}
 				sctp_free_a_readq(stcb, control);
-				oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-							     0, M_NOWAIT, 1, MT_DATA);
-				if (oper) {
-					struct sctp_paramhdr *ph;
-					uint32_t *ippp;
-
-					SCTP_BUF_LEN(oper) =
-					    sizeof(struct sctp_paramhdr) +
-					    (3 * sizeof(uint32_t));
-					ph = mtod(oper, struct sctp_paramhdr *);
-					ph->param_type =
-					    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-					ph->param_length = htons(SCTP_BUF_LEN(oper));
-					ippp = (uint32_t *) (ph + 1);
-					*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_15);
-					ippp++;
-					*ippp = tsn;
-					ippp++;
-					*ippp = ((strmno << 16) | strmseq);
+				snprintf(msg, sizeof(msg), "Reas. queue emtpy, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+				         tsn, strmno, strmseq);
+				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_15;
+				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+				*abort_flag = 1;
+				if (last_chunk) {
+					*m = NULL;
 				}
-				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_15;
-				sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
-				*abort_flag = 1;
 				return (0);
 			} else {
 				if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) {
 					sctp_m_freem(control->data);
 					control->data = NULL;
 					if (control->whoFrom) {
 						sctp_free_remote_addr(control->whoFrom);
 						control->whoFrom = NULL;
 					}
 					sctp_free_a_readq(stcb, control);
-
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    ( 3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_16);
-						ippp++;
-						*ippp = tsn;
-						ippp++;
-						*ippp = ((strmno << 16) | strmseq);
+					snprintf(msg, sizeof(msg), "PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         tsn, strmno, strmseq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_16;
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+					*abort_flag = 1;
+					if (last_chunk) {
+						*m = NULL;
 					}
-					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_16;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
-					*abort_flag = 1;
 					return (0);
 				}
 			}
 		} else {
 			/* No PDAPI running */
 			if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
 				/*
 				 * Reassembly queue is NOT empty validate
@@ -1977,41 +1765,25 @@ failed_express_del:
 				if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) {
 					sctp_m_freem(control->data);
 					control->data = NULL;
 					if (control->whoFrom) {
 						sctp_free_remote_addr(control->whoFrom);
 						control->whoFrom = NULL;
 					}
 					sctp_free_a_readq(stcb, control);
-					oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-								     0, M_NOWAIT, 1, MT_DATA);
-					if (oper) {
-						struct sctp_paramhdr *ph;
-						uint32_t *ippp;
-
-						SCTP_BUF_LEN(oper) =
-						    sizeof(struct sctp_paramhdr) +
-						    (3 * sizeof(uint32_t));
-						ph = mtod(oper,
-						    struct sctp_paramhdr *);
-						ph->param_type =
-						    htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-						ph->param_length =
-						    htons(SCTP_BUF_LEN(oper));
-						ippp = (uint32_t *) (ph + 1);
-						*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_17);
-						ippp++;
-						*ippp = tsn;
-						ippp++;
-						*ippp = ((strmno << 16) | strmseq);
+					snprintf(msg, sizeof(msg), "No PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
+					         tsn, strmno, strmseq);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_17;
+					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+					*abort_flag = 1;
+					if (last_chunk) {
+						*m = NULL;
 					}
-					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_17;
-					sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
-					*abort_flag = 1;
 					return (0);
 				}
 			}
 		}
 		/* ok, if we reach here we have passed the sanity checks */
 		if (chunk_flags & SCTP_DATA_UNORDERED) {
 			/* queue directly into socket buffer */
 			sctp_mark_non_revokable(asoc, control->sinfo_tsn);
@@ -2064,29 +1836,34 @@ failed_express_del:
 						 * loop) to setup nextP.
 						 */
 						TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next);
 					}
 				}
 			} else {
 				sctp_queue_data_to_stream(stcb, asoc, control, abort_flag);
 				if (*abort_flag) {
+					if (last_chunk) {
+						*m = NULL;
+					}
 					return (0);
 				}
 			}
 		}
 	} else {
 		/* Into the re-assembly queue */
 		sctp_queue_data_for_reasm(stcb, asoc, chk, abort_flag);
 		if (*abort_flag) {
 			/*
 			 * the assoc is now gone and chk was put onto the
 			 * reasm queue, which has all been freed.
 			 */
-			*m = NULL;
+			if (last_chunk) {
+				*m = NULL;
+			}
 			return (0);
 		}
 	}
 finish_express_del:
 	if (tsn == (asoc->cumulative_tsn + 1)) {
 		/* Update cum-ack */
 		asoc->cumulative_tsn = tsn;
 	}
@@ -2522,17 +2299,17 @@ sctp_service_queues(struct sctp_tcb *stc
 }
 
 int
 sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
                   struct sockaddr *src, struct sockaddr *dst,
                   struct sctphdr *sh, struct sctp_inpcb *inp,
                   struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t *high_tsn,
 #if defined(__FreeBSD__)
-                  uint8_t use_mflowid, uint32_t mflowid,
+                  uint8_t mflowtype, uint32_t mflowid,
 #endif
 		  uint32_t vrf_id, uint16_t port)
 {
 	struct sctp_data_chunk *ch, chunk_buf;
 	struct sctp_association *asoc;
 	int num_chunks = 0;	/* number of control chunks processed */
 	int stop_proc = 0;
 	int chk_length, break_flag, last_chunk;
@@ -2605,47 +2382,49 @@ sctp_process_data(struct mbuf **mm, int 
 		/* validate chunk length */
 		chk_length = ntohs(ch->ch.chunk_length);
 		if (length - *offset < chk_length) {
 			/* all done, mutulated chunk */
 			stop_proc = 1;
 			continue;
 		}
 		if (ch->ch.chunk_type == SCTP_DATA) {
-			if ((size_t)chk_length < sizeof(struct sctp_data_chunk) + 1) {
+			if ((size_t)chk_length < sizeof(struct sctp_data_chunk)) {
 				/*
 				 * Need to send an abort since we had a
 				 * invalid data chunk.
 				 */
 				struct mbuf *op_err;
-
-				op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 2 * sizeof(uint32_t)),
-							       0, M_NOWAIT, 1, MT_DATA);
-
-				if (op_err) {
-					struct sctp_paramhdr *ph;
-					uint32_t *ippp;
-
-					SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr) +
-						(2 * sizeof(uint32_t));
-					ph = mtod(op_err, struct sctp_paramhdr *);
-					ph->param_type =
-						htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-					ph->param_length = htons(SCTP_BUF_LEN(op_err));
-					ippp = (uint32_t *) (ph + 1);
-					*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_19);
-					ippp++;
-					*ippp = asoc->cumulative_tsn;
-
-				}
+				char msg[SCTP_DIAG_INFO_LEN];
+
+				snprintf(msg, sizeof(msg), "DATA chunk of length %d",
+				         chk_length);
+				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19;
 				sctp_abort_association(inp, stcb, m, iphlen,
 				                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-				                       use_mflowid, mflowid,
+				                       mflowtype, mflowid,
+#endif
+				                       vrf_id, port);
+				return (2);
+			}
+			if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) {
+				/*
+				 * Need to send an abort since we had an
+				 * empty data chunk.
+				 */
+				struct mbuf *op_err;
+
+				op_err = sctp_generate_no_user_data_cause(ch->dp.tsn);
+				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19;
+				sctp_abort_association(inp, stcb, m, iphlen,
+				                       src, dst, sh, op_err,
+#if defined(__FreeBSD__)
+				                       mflowtype, mflowid,
 #endif
 				                       vrf_id, port);
 				return (2);
 			}
 #ifdef SCTP_AUDITING_ENABLED
 			sctp_audit_log(0xB1, 0);
 #endif
 			if (SCTP_SIZE32(chk_length) == (length - *offset)) {
@@ -2700,23 +2479,23 @@ sctp_process_data(struct mbuf **mm, int 
 				 * For now, I do nothing but ignore them. We
 				 * may later want to add sysctl stuff to
 				 * switch out and do either an ABORT() or
 				 * possibly process them.
 				 */
 				if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) {
 					struct mbuf *op_err;
 
-					op_err = sctp_generate_invmanparam(SCTP_CAUSE_PROTOCOL_VIOLATION);
+					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, "");
 					sctp_abort_association(inp, stcb,
 					                       m, iphlen,
 					                       src, dst,
 					                       sh, op_err,
 #if defined(__FreeBSD__)
-					                       use_mflowid, mflowid,
+					                       mflowtype, mflowid,
 #endif
 					                       vrf_id, port);
 					return (2);
 				}
 				break;
 			default:
 				/* unknown chunk type, use bit rules */
 				if (ch->ch.chunk_type & 0x40) {
@@ -2737,17 +2516,17 @@ sctp_process_data(struct mbuf **mm, int 
 						 */
 						phd->param_type =
 							htons(SCTP_CAUSE_UNRECOG_CHUNK);
 						phd->param_length =
 							htons(chk_length + sizeof(*phd));
 						SCTP_BUF_LEN(merr) = sizeof(*phd);
 						SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
 						if (SCTP_BUF_NEXT(merr)) {
-							if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
+							if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) {
 								sctp_m_freem(merr);
 							} else {
 								sctp_queue_op_err(stcb, merr);
 							}
 						} else {
 							sctp_m_freem(merr);
 						}
 					}
@@ -3188,17 +2967,17 @@ sctp_strike_gap_ack_chunks(struct sctp_t
 	/* CMT DAC algo: finding out if SACK is a mixed SACK */
 	if ((asoc->sctp_cmt_on_off > 0) &&
 	    SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
 		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
 			if (net->saw_newack)
 				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) {
 		strike_flag = 0;
 		if (tp1->no_fr_allowed) {
 			/* this one had a timeout or something */
 			continue;
 		}
@@ -3209,17 +2988,17 @@ sctp_strike_gap_ack_chunks(struct sctp_t
 					    tp1->sent,
 					    SCTP_FR_LOG_CHECK_STRIKE);
 		}
 		if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked) ||
 		    tp1->sent == SCTP_DATAGRAM_UNSENT) {
 			/* 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? */
 #ifndef __FreeBSD__
 				if (timercmp(&now, &tp1->rec.data.timetodrop, >)) {
 #else
 				if (timevalcmp(&now, &tp1->rec.data.timetodrop, >)) {
 #endif
 					/* Yes so drop it */
@@ -3462,17 +3241,17 @@ sctp_strike_gap_ack_chunks(struct sctp_t
 					      asoc->peers_rwnd, tp1->send_size, SCTP_BASE_SYSCTL(sctp_peer_chunk_oh));
 			}
 			/* add back to the rwnd */
 			asoc->peers_rwnd += (tp1->send_size + SCTP_BASE_SYSCTL(sctp_peer_chunk_oh));
 
 			/* 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? - we store the retran count there. */
 				if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) {
 					/* Yes, so drop it */
 					if (tp1->data != NULL) {
 						(void)sctp_release_pr_sctp_chunk(stcb, tp1, 1,
 										 SCTP_SO_NOT_LOCKED);
 					}
@@ -3594,17 +3373,17 @@ sctp_strike_gap_ack_chunks(struct sctp_t
 struct sctp_tmit_chunk *
 sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
     struct sctp_association *asoc)
 {
 	struct sctp_tmit_chunk *tp1, *tp2, *a_adv = NULL;
 	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) {
 		if (tp1->sent != SCTP_FORWARD_TSN_SKIP &&
 		    tp1->sent != SCTP_DATAGRAM_RESEND &&
 		    tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
 			/* no chance to advance, out of here */
 			break;
@@ -3838,41 +3617,31 @@ sctp_express_handle_sack(struct sctp_tcb
 			tp1 = TAILQ_LAST(&asoc->sent_queue,
 					 sctpchunk_listhead);
 			send_s = tp1->rec.data.TSN_seq + 1;
 		} else {
 			send_s = asoc->sending_seq;
 		}
 		if (SCTP_TSN_GE(cumack, send_s)) {
 #ifndef INVARIANTS
-			struct mbuf *oper;
+			struct mbuf *op_err;
+			char msg[SCTP_DIAG_INFO_LEN];
 
 #endif
 #ifdef INVARIANTS
 			panic("Impossible sack 1");
 #else
 
 			*abort_now = 1;
 			/* XXX */
-			oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
-						     0, M_NOWAIT, 1, MT_DATA);
-			if (oper) {
-				struct sctp_paramhdr *ph;
-				uint32_t *ippp;
-
-				SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
-					sizeof(uint32_t);
-				ph = mtod(oper, struct sctp_paramhdr *);
-				ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-				ph->param_length = htons(SCTP_BUF_LEN(oper));
-				ippp = (uint32_t *) (ph + 1);
-				*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25);
-			}
+			snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x",
+			         cumack, send_s);
+			op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 			stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
-			sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+			sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 			return;
 #endif
 		}
 	}
 	asoc->this_sack_highest_gap = cumack;
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
 		sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
 			       stcb->asoc.overall_error_count,
@@ -4229,33 +3998,24 @@ again:
 					asoc->stream_queue_cnt--;
 				}
 			}
 		}
 		if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
 		    (asoc->stream_queue_cnt == 0)) {
 			if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
 				/* Need to abort here */
-				struct mbuf *oper;
+				struct mbuf *op_err;
 
 			abort_out_now:
 				*abort_now = 1;
 				/* XXX */
-				oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
-							     0, M_NOWAIT, 1, MT_DATA);
-				if (oper) {
-					struct sctp_paramhdr *ph;
-
-					SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr);
-					ph = mtod(oper, struct sctp_paramhdr *);
-					ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
-					ph->param_length = htons(SCTP_BUF_LEN(oper));
-				}
+				op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
 				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
-				sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 			} else {
 				struct sctp_nets *netp;
 
 				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
 				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
 					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
 				}
 				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
@@ -4297,17 +4057,17 @@ again:
 	/* Here we perform PR-SCTP procedures        */
 	/* (section 4.2)                             */
 	/*********************************************/
 	/* C1. update advancedPeerAckPoint */
 	if (SCTP_TSN_GT(cumack, asoc->advanced_peer_ack_point)) {
 		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;
 
 		old_adv_peer_ack_point = asoc->advanced_peer_ack_point;
 		lchk = sctp_try_advance_peer_ack_point(stcb, asoc);
 		/* C3. See if we need to send a Fwd-TSN */
 		if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cumack)) {
 			/*
@@ -4438,46 +4198,37 @@ sctp_handle_sack(struct mbuf *m, int off
 			tp1 = TAILQ_LAST(&asoc->sent_queue,
 			                 sctpchunk_listhead);
 			send_s = tp1->rec.data.TSN_seq + 1;
 		} else {
 			tp1 = NULL;
 			send_s = asoc->sending_seq;
 		}
 		if (SCTP_TSN_GE(cum_ack, send_s)) {
-			struct mbuf *oper;
+			struct mbuf *op_err;
+			char msg[SCTP_DIAG_INFO_LEN];
+
 			/*
 			 * no way, we have not even sent this TSN out yet.
 			 * Peer is hopelessly messed up with us.
 			 */
 			SCTP_PRINTF("NEW cum_ack:%x send_s:%x is smaller or equal\n",
 			            cum_ack, send_s);
 			if (tp1) {
 				SCTP_PRINTF("Got send_s from tsn:%x + 1 of tp1:%p\n",
 				            tp1->rec.data.TSN_seq, (void *)tp1);
 			}
 		hopeless_peer:
 			*abort_now = 1;
 			/* XXX */
-			oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
-			                             0, M_NOWAIT, 1, MT_DATA);
-			if (oper) {
-				struct sctp_paramhdr *ph;
-				uint32_t *ippp;
-
-				SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
-					sizeof(uint32_t);
-				ph = mtod(oper, struct sctp_paramhdr *);
-				ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-				ph->param_length = htons(SCTP_BUF_LEN(oper));
-				ippp = (uint32_t *) (ph + 1);
-				*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25);
-			}
+			snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x",
+			         cum_ack, send_s);
+			op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 			stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
-			sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+			sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 			return;
 		}
 	}
 	/**********************/
 	/* 1) check the range */
 	/**********************/
 	if (SCTP_TSN_GT(asoc->last_acked_seq, last_tsn)) {
 		/* acking something behind */
@@ -4744,17 +4495,17 @@ sctp_handle_sack(struct mbuf *m, int off
 				asoc->pr_sctp_cnt--;
 		}
 		asoc->sent_queue_cnt--;
 		if (tp1->data) {
 			/* sa_ignore NO_NULL_CHK */
 			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--;
 			}
 		}
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
 			sctp_log_sack(asoc->last_acked_seq,
 			              cum_ack,
 			              tp1->rec.data.TSN_seq,
 			              0,
@@ -4983,32 +4734,24 @@ sctp_handle_sack(struct mbuf *m, int off
 					asoc->stream_queue_cnt--;
 				}
 			}
 		}
 		if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
 		    (asoc->stream_queue_cnt == 0)) {
 			if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
 				/* Need to abort here */
-				struct mbuf *oper;
+				struct mbuf *op_err;
+
 			abort_out_now:
 				*abort_now = 1;
 				/* XXX */
-				oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
-				                             0, M_NOWAIT, 1, MT_DATA);
-				if (oper) {
-					struct sctp_paramhdr *ph;
-
-					SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr);
-					ph = mtod(oper, struct sctp_paramhdr *);
-					ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
-					ph->param_length = htons(SCTP_BUF_LEN(oper));
-				}
+				op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
 				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31;
-				sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 				return;
 			} else {
 				struct sctp_nets *netp;
 
 				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
 				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
 					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
 				}
@@ -5187,17 +4930,17 @@ again:
 	/* Here we perform PR-SCTP procedures        */
 	/* (section 4.2)                             */
 	/*********************************************/
 	/* C1. update advancedPeerAckPoint */
 	if (SCTP_TSN_GT(cum_ack, asoc->advanced_peer_ack_point)) {
 		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;
 
 		old_adv_peer_ack_point = asoc->advanced_peer_ack_point;
 		lchk = sctp_try_advance_peer_ack_point(stcb, asoc);
 		/* C3. See if we need to send a Fwd-TSN */
 		if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cum_ack)) {
 			/*
@@ -5423,41 +5166,30 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 	/*
 	 * now we know the new TSN is more advanced, let's find the actual
 	 * gap
 	 */
 	SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn);
 	asoc->cumulative_tsn = new_cum_tsn;
 	if (gap >= m_size) {
 		if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) {
-			struct mbuf *oper;
+			struct mbuf *op_err;
+			char msg[SCTP_DIAG_INFO_LEN];
+
 			/*
 			 * out of range (of single byte chunks in the rwnd I
 			 * give out). This must be an attacker.
 			 */
 			*abort_flag = 1;
-			oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)),
-					     0, M_NOWAIT, 1, MT_DATA);
-			if (oper) {
-				struct sctp_paramhdr *ph;
-				uint32_t *ippp;
-				SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
-					(sizeof(uint32_t) * 3);
-				ph = mtod(oper, struct sctp_paramhdr *);
-				ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
-				ph->param_length = htons(SCTP_BUF_LEN(oper));
-				ippp = (uint32_t *) (ph + 1);
-				*ippp = htonl(SCTP_FROM_SCTP_INDATA+SCTP_LOC_33);
-				ippp++;
-				*ippp = asoc->highest_tsn_inside_map;
-				ippp++;
-				*ippp = new_cum_tsn;
-			}
+			snprintf(msg, sizeof(msg),
+			         "New cum ack %8.8x too high, highest TSN %8.8x",
+			         new_cum_tsn, asoc->highest_tsn_inside_map);
+			op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
 			stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_33;
-			sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
+			sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
 			return;
 		}
 		SCTP_STAT_INCR(sctps_fwdtsn_map_over);
 
 		memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
 		asoc->mapping_array_base_tsn = new_cum_tsn + 1;
 		asoc->highest_tsn_inside_map = new_cum_tsn;
 
--- a/netwerk/sctp/src/netinet/sctp_input.c
+++ b/netwerk/sctp/src/netinet/sctp_input.c
@@ -27,36 +27,38 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 262252 2014-02-20 20:14:43Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 277805 2015-01-27 19:35:38Z delphij $");
 #endif
 
 #include <netinet/sctp_os.h>
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_pcb.h>
 #include <netinet/sctp_header.h>
 #include <netinet/sctputil.h>
 #include <netinet/sctp_output.h>
 #include <netinet/sctp_input.h>
 #include <netinet/sctp_auth.h>
 #include <netinet/sctp_indata.h>
 #include <netinet/sctp_asconf.h>
 #include <netinet/sctp_bsd_addr.h>
 #include <netinet/sctp_timer.h>
 #include <netinet/sctp_crc32.h>
+#if defined(INET) || defined(INET6)
 #if !defined(__Userspace_os_Windows)
 #include <netinet/udp.h>
 #endif
+#endif
 #if defined(__FreeBSD__)
 #include <sys/smp.h>
 #endif
 
 #if defined(__APPLE__)
 #define APPLE_FILE_NO 2
 #endif
 
@@ -89,96 +91,98 @@ sctp_stop_all_cookie_timers(struct sctp_
 
 /* INIT handler */
 static void
 sctp_handle_init(struct mbuf *m, int iphlen, int offset,
                  struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
                  struct sctp_init_chunk *cp, struct sctp_inpcb *inp,
                  struct sctp_tcb *stcb, int *abort_no_unlock,
 #if defined(__FreeBSD__)
-                 uint8_t use_mflowid, uint32_t mflowid,
+                 uint8_t mflowtype, uint32_t mflowid,
 #endif
                  uint32_t vrf_id, uint16_t port)
 {
 	struct sctp_init *init;
 	struct mbuf *op_err;
 
 	SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n",
 		(void *)stcb);
 	if (stcb == NULL) {
 		SCTP_INP_RLOCK(inp);
 	}
 	/* validate length */
 	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 				       vrf_id, port);
 		if (stcb)
 			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	/* validate parameters */
 	init = &cp->init;
 	if (init->initiate_tag == 0) {
 		/* protocol error... send abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 				       vrf_id, port);
 		if (stcb)
 			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
 		/* invalid parameter... send abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 				       vrf_id, port);
 		if (stcb)
 			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	if (init->num_inbound_streams == 0) {
 		/* protocol error... send abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 				       vrf_id, port);
 		if (stcb)
 			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	if (init->num_outbound_streams == 0) {
 		/* protocol error... send abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 				       vrf_id, port);
 		if (stcb)
 			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	if (sctp_validate_init_auth_params(m, offset + sizeof(*cp),
 					   offset + ntohs(cp->ch.chunk_length))) {
 		/* auth parameter(s) error... send abort */
-		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, NULL,
+		op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+		                             "Problem with AUTH parameters");
+		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, port);
 		if (stcb)
 			*abort_no_unlock = 1;
 		goto outnow;
 	}
 	/* We are only accepting if we have a socket with positive so_qlimit.*/
 	if ((stcb == NULL) &&
@@ -194,35 +198,37 @@ sctp_handle_init(struct mbuf *m, int iph
 		 * since we COULD just send back the INIT-ACK and hope that
 		 * the app did accept()'s by the time the COOKIE was sent. But
 		 * there is a price to pay for COOKIE generation and I don't
 		 * want to pay it on the chance that the app will actually do
 		 * some accepts(). The App just looses and should NOT be in
 		 * this state :-)
 		 */
 		if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) {
-			sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL,
+			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+			                             "No listener");
+			sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err,
 #if defined(__FreeBSD__)
-			                use_mflowid, mflowid,
+			                mflowtype, mflowid,
 #endif
 			                vrf_id, port);
 		}
 		goto outnow;
 	}
 	if ((stcb != NULL) &&
 	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
 		SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n");
 		sctp_send_shutdown_ack(stcb, NULL);
 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
 	} else {
 		SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n");
 		sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst,
 		                       sh, cp,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, port,
 		                       ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
 	}
  outnow:
 	if (stcb == NULL) {
 		SCTP_INP_RUNLOCK(inp);
 	}
@@ -447,17 +453,17 @@ sctp_process_init(struct sctp_init_chunk
  * INIT-ACK message processing/consumption returns value < 0 on error
  */
 static int
 sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
                       struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
                       struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
                       struct sctp_nets *net, int *abort_no_unlock,
 #if defined(__FreeBSD__)
-		      uint8_t use_mflowid, uint32_t mflowid,
+		      uint8_t mflowtype, uint32_t mflowid,
 #endif
                       uint32_t vrf_id)
 {
 	struct sctp_association *asoc;
 	struct mbuf *op_err;
 	int retval, abort_flag;
 	uint32_t initack_limit;
 	int nat_friendly = 0;
@@ -481,31 +487,32 @@ sctp_process_init_ack(struct mbuf *m, in
 	if (retval < 0) {
 		return (retval);
 	}
 	initack_limit = offset + ntohs(cp->ch.chunk_length);
 	/* load all addresses */
 	if ((retval = sctp_load_addresses_from_init(stcb, m,
 	    (offset + sizeof(struct sctp_init_chunk)), initack_limit,
 	    src, dst, NULL))) {
-		/* Huh, we should abort */
+		op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+		                             "Problem with address parameters");
 		SCTPDBG(SCTP_DEBUG_INPUT1,
 			"Load addresses from INIT causes an abort %d\n",
 			retval);
 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
-		                       src, dst, sh, NULL,
+		                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, net->port);
 		*abort_no_unlock = 1;
 		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) {
 			TAILQ_REMOVE(&asoc->asconf_queue, param, next);
 			SCTP_FREE(param, SCTP_M_ASC_ADDR);
 		}
 	}
 
@@ -544,18 +551,17 @@ sctp_process_init_ack(struct mbuf *m, in
 	if (retval < 0) {
 		/*
 		 * No cookie, we probably should send a op error. But in any
 		 * case if there is no cookie in the INIT-ACK, we can
 		 * abandon the peer, its broke.
 		 */
 		if (retval == -3) {
 			/* We abort with an error of missing mandatory param */
-			op_err =
-			    sctp_generate_invmanparam(SCTP_CAUSE_MISSING_PARAM);
+			op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, "");
 			if (op_err) {
 				/*
 				 * Expand beyond to include the mandatory
 				 * param cookie
 				 */
 				struct sctp_inv_mandatory_param *mp;
 
 				SCTP_BUF_LEN(op_err) =
@@ -567,105 +573,91 @@ sctp_process_init_ack(struct mbuf *m, in
 				    htons(sizeof(struct sctp_inv_mandatory_param) - 2);
 				mp->num_param = htonl(1);
 				mp->param = htons(SCTP_STATE_COOKIE);
 				mp->resv = 0;
 			}
 			sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
 			                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-			                       use_mflowid, mflowid,
+			                       mflowtype, mflowid,
 #endif
 			                       vrf_id, net->port);
 			*abort_no_unlock = 1;
 		}
 		return (retval);
 	}
 
 	return (0);
 }
 
 static void
 sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
     struct sctp_tcb *stcb, struct sctp_nets *net)
 {
-	struct sockaddr_storage store;
+	union sctp_sockstore store;
 	struct sctp_nets *r_net, *f_net;
 	struct timeval tv;
 	int req_prim = 0;
 	uint16_t old_error_counter;
-#ifdef INET
-	struct sockaddr_in *sin;
-#endif
-#ifdef INET6
-	struct sockaddr_in6 *sin6;
-#endif
-#if defined(__Userspace__)
-	struct sockaddr_conn *sconn;
-#endif
 
 	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
 		/* Invalid length */
 		return;
 	}
 
 	memset(&store, 0, sizeof(store));
 	switch (cp->heartbeat.hb_info.addr_family) {
 #ifdef INET
 	case AF_INET:
 		if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
-			sin = (struct sockaddr_in *)&store;
-			sin->sin_family = cp->heartbeat.hb_info.addr_family;
+			store.sin.sin_family = cp->heartbeat.hb_info.addr_family;
 #ifdef HAVE_SIN_LEN
-			sin->sin_len = cp->heartbeat.hb_info.addr_len;
-#endif
-			sin->sin_port = stcb->rport;
-			memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
-			       sizeof(sin->sin_addr));
+			store.sin.sin_len = cp->heartbeat.hb_info.addr_len;
+#endif
+			store.sin.sin_port = stcb->rport;
+			memcpy(&store.sin.sin_addr, cp->heartbeat.hb_info.address,
+			       sizeof(store.sin.sin_addr));
 		} else {
 			return;
 		}
 		break;
 #endif
 #ifdef INET6
 	case AF_INET6:
 		if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
-			sin6 = (struct sockaddr_in6 *)&store;
-			sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
+			store.sin6.sin6_family = cp->heartbeat.hb_info.addr_family;
 #ifdef HAVE_SIN6_LEN
-			sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
-#endif
-			sin6->sin6_port = stcb->rport;
-			memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
-			       sizeof(sin6->sin6_addr));
+			store.sin6.sin6_len = cp->heartbeat.hb_info.addr_len;
+#endif
+			store.sin6.sin6_port = stcb->rport;
+			memcpy(&store.sin6.sin6_addr, cp->heartbeat.hb_info.address, sizeof(struct in6_addr));
 		} else {
 			return;
 		}
 		break;
 #endif
 #if defined(__Userspace__)
 	case AF_CONN:
 		if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_conn)) {
-			sconn = (struct sockaddr_conn *)&store;
-			sconn->sconn_family = cp->heartbeat.hb_info.addr_family;
+			store.sconn.sconn_family = cp->heartbeat.hb_info.addr_family;
 #ifdef HAVE_SCONN_LEN
-			sconn->sconn_len = cp->heartbeat.hb_info.addr_len;
-#endif
-			sconn->sconn_port = stcb->rport;
-			memcpy(&sconn->sconn_addr, cp->heartbeat.hb_info.address,
-			       sizeof(sconn->sconn_addr));
+			store.sconn.sconn_len = cp->heartbeat.hb_info.addr_len;
+#endif
+			store.sconn.sconn_port = stcb->rport;
+			memcpy(&store.sconn.sconn_addr, cp->heartbeat.hb_info.address, sizeof(void *));
 		} else {
 			return;
 		}
 		break;
 #endif
 	default:
 		return;
 	}
-	r_net = sctp_findnet(stcb, (struct sockaddr *)&store);
+	r_net = sctp_findnet(stcb, &store.sa);
 	if (r_net == NULL) {
 		SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n");
 		return;
 	}
 	if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
 	    (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) &&
 	    (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) {
 		/*
@@ -719,21 +711,21 @@ sctp_handle_heartbeat_ack(struct sctp_he
 			/* release the alternate, primary is good */
 			sctp_free_remote_addr(stcb->asoc.alternate);
 			stcb->asoc.alternate = NULL;
 		}
 	}
 	/* Mobility adaptation */
 	if (req_prim) {
 		if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
-				       	SCTP_MOBILITY_BASE) ||
-	    	    sctp_is_mobility_feature_on(stcb->sctp_ep,
-			    		SCTP_MOBILITY_FASTHANDOFF)) &&
-	    	    sctp_is_mobility_feature_on(stcb->sctp_ep,
-					SCTP_MOBILITY_PRIM_DELETED)) {
+		                                 SCTP_MOBILITY_BASE) ||
+		    sctp_is_mobility_feature_on(stcb->sctp_ep,
+		                                SCTP_MOBILITY_FASTHANDOFF)) &&
+		    sctp_is_mobility_feature_on(stcb->sctp_ep,
+		                                SCTP_MOBILITY_PRIM_DELETED)) {
 
 			sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7);
 			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
 					SCTP_MOBILITY_FASTHANDOFF)) {
 				sctp_assoc_immediate_retrans(stcb,
 					stcb->asoc.primary_destination);
 			}
 			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
@@ -785,27 +777,26 @@ sctp_handle_nat_colliding_state(struct s
 		return (1);
 	}
 	return (0);
 }
 
 static int
 sctp_handle_nat_missing_state(struct sctp_tcb *stcb,
 			      struct sctp_nets *net)
-
 {
-  /* return 0 means we want you to proceed with the abort
-   * non-zero means no abort processing
-   */
-  if (stcb->asoc.peer_supports_auth == 0) {
-    SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n");
-    return (0);
-  }
-  sctp_asconf_send_nat_state_update(stcb, net);
-  return (1);
+	/* return 0 means we want you to proceed with the abort
+	 * non-zero means no abort processing
+	 */
+	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);
+	}
+	sctp_asconf_send_nat_state_update(stcb, net);
+	return (1);
 }
 
 
 static void
 sctp_handle_abort(struct sctp_abort_chunk *abort,
     struct sctp_tcb *stcb, struct sctp_nets *net)
 {
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -1111,59 +1102,60 @@ sctp_process_unrecog_chunk(struct sctp_t
 
 	chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr));
 	switch (chk->chunk_type) {
 	case SCTP_ASCONF_ACK:
 	case SCTP_ASCONF:
 		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,
 			"Peer does not support chunk type %d(%x)??\n",
 			chk->chunk_type, (uint32_t) chk->chunk_type);
 		break;
 	}
 }
 
 /*
  * 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)
 {
 	struct sctp_paramhdr *pbad;
 
 	pbad = phdr + 1;
 	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;
 		/* draft-ietf-tsvwg-addip-sctp */
 	case SCTP_HAS_NAT_SUPPORT:
 	        stcb->asoc.peer_supports_nat = 0;
 	        break;
 	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,
 			"Peer does not support param type %d(%x)??\n",
 			pbad->param_type, (uint32_t) pbad->param_type);
 		break;
 	}
 }
@@ -1323,88 +1315,88 @@ sctp_handle_error(struct sctp_chunkhdr *
 }
 
 static int
 sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
                      struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
                      struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
                      struct sctp_nets *net, int *abort_no_unlock,
 #if defined(__FreeBSD__)
-                     uint8_t use_mflowid, uint32_t mflowid,
+                     uint8_t mflowtype, uint32_t mflowid,
 #endif
                      uint32_t vrf_id)
 {
 	struct sctp_init_ack *init_ack;
 	struct mbuf *op_err;
 
 	SCTPDBG(SCTP_DEBUG_INPUT2,
 		"sctp_handle_init_ack: handling INIT-ACK\n");
 
 	if (stcb == NULL) {
 		SCTPDBG(SCTP_DEBUG_INPUT2,
 			"sctp_handle_init_ack: TCB is null\n");
 		return (-1);
 	}
 	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) {
 		/* Invalid length */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
 		                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, net->port);
 		*abort_no_unlock = 1;
 		return (-1);
 	}
 	init_ack = &cp->init;
 	/* validate parameters */
 	if (init_ack->initiate_tag == 0) {
 		/* protocol error... send an abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
 		                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, net->port);
 		*abort_no_unlock = 1;
 		return (-1);
 	}
 	if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) {
 		/* protocol error... send an abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
 		                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, net->port);
 		*abort_no_unlock = 1;
 		return (-1);
 	}
 	if (init_ack->num_inbound_streams == 0) {
 		/* protocol error... send an abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
 		                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, net->port);
 		*abort_no_unlock = 1;
 		return (-1);
 	}
 	if (init_ack->num_outbound_streams == 0) {
 		/* protocol error... send an abort */
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
+		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
 		                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, net->port);
 		*abort_no_unlock = 1;
 		return (-1);
 	}
 	/* process according to association state... */
 	switch (stcb->asoc.state & SCTP_STATE_MASK) {
 	case SCTP_STATE_COOKIE_WAIT:
@@ -1421,17 +1413,17 @@ sctp_handle_init_ack(struct mbuf *m, int
 			stcb->asoc.primary_destination->dest_state &=
 			    ~SCTP_ADDR_UNCONFIRMED;
 			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
 			    stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED);
 		}
 		if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb,
 		                          net, abort_no_unlock,
 #if defined(__FreeBSD__)
-		                          use_mflowid, mflowid,
+		                          mflowtype, mflowid,
 #endif
 		                          vrf_id) < 0) {
 			/* error in parsing parameters */
 			return (-1);
 		}
 		/* update our state */
 		SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n");
 		SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED);
@@ -1480,17 +1472,17 @@ sctp_handle_init_ack(struct mbuf *m, int
 static struct sctp_tcb *
 sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
     struct sockaddr *src, struct sockaddr *dst,
     struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
     struct sctp_inpcb *inp, struct sctp_nets **netp,
     struct sockaddr *init_src, int *notification,
     int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
 #if defined(__FreeBSD__)
-    uint8_t use_mflowid, uint32_t mflowid,
+    uint8_t mflowtype, uint32_t mflowid,
 #endif
     uint32_t vrf_id, uint16_t port);
 
 
 /*
  * handle a state cookie for an existing association m: input packet mbuf
  * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a
  * "split" mbuf and the cookie signature does not exist offset: offset into
@@ -1499,58 +1491,50 @@ sctp_process_cookie_new(struct mbuf *m, 
 static struct sctp_tcb *
 sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
     struct sockaddr *src, struct sockaddr *dst,
     struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
     struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp,
     struct sockaddr *init_src, int *notification,
     int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
 #if defined(__FreeBSD__)
-    uint8_t use_mflowid, uint32_t mflowid,
+    uint8_t mflowtype, uint32_t mflowid,
 #endif
     uint32_t vrf_id, uint16_t port)
 {
 	struct sctp_association *asoc;
 	struct sctp_init_chunk *init_cp, init_buf;
 	struct sctp_init_ack_chunk *initack_cp, initack_buf;
 	struct sctp_nets *net;
 	struct mbuf *op_err;
-	struct sctp_paramhdr *ph;
 	int init_offset, initack_offset, i;
 	int retval;
 	int spec_flag = 0;
 	uint32_t how_indx;
+#if defined(SCTP_DETAILED_STR_STATS)
+	int j;
+#endif
 
 	net = *netp;
 	/* I know that the TCB is non-NULL from the caller */
 	asoc = &stcb->asoc;
 	for (how_indx = 0; how_indx  < sizeof(asoc->cookie_how); how_indx++) {
 		if (asoc->cookie_how[how_indx] == 0)
 			break;
 	}
 	if (how_indx < sizeof(asoc->cookie_how)) {
 		asoc->cookie_how[how_indx] = 1;
 	}
 	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
 		/* SHUTDOWN came in after sending INIT-ACK */
 		sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
-		op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
-					       0, M_NOWAIT, 1, MT_DATA);
-		if (op_err == NULL) {
-			/* FOOBAR */
-			return (NULL);
-		}
-		/* Set the len */
-		SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
-		ph = mtod(op_err, struct sctp_paramhdr *);
-		ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN);
-		ph->param_length = htons(sizeof(struct sctp_paramhdr));
+		op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, "");
 		sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
 #if defined(__FreeBSD__)
-		                   use_mflowid, mflowid,
+		                   mflowtype, mflowid,
 #endif
 		                   vrf_id, net->port);
 		if (how_indx < sizeof(asoc->cookie_how))
 			asoc->cookie_how[how_indx] = 2;
 		return (NULL);
 	}
 	/*
 	 * find and validate the INIT chunk in the cookie (peer's info) the
@@ -1605,17 +1589,17 @@ sctp_process_cookie_existing(struct mbuf
 			 * tag t'. Which means we would throw away the CE and send
 			 * ours instead. Basically this is case C (throw away side).
 			 */
 			if (how_indx < sizeof(asoc->cookie_how))
 				asoc->cookie_how[how_indx] = 17;
 			return (NULL);
 
 		}
- 		switch (SCTP_GET_STATE(asoc)) {
+		switch (SCTP_GET_STATE(asoc)) {
 			case SCTP_STATE_COOKIE_WAIT:
 			case SCTP_STATE_COOKIE_ECHOED:
 				/*
 				 * INIT was sent but got a COOKIE_ECHO with the
 				 * correct tags... just accept it...but we must
 				 * process the init so that we can make sure we
 				 * have the right seq no's.
 				 */
@@ -1662,17 +1646,17 @@ sctp_process_cookie_existing(struct mbuf
 					so = SCTP_INP_SO(stcb->sctp_ep);
 					atomic_add_int(&stcb->asoc.refcnt, 1);
 					SCTP_TCB_UNLOCK(stcb);
 					SCTP_SOCKET_LOCK(so, 1);
 					SCTP_TCB_LOCK(stcb);
 					atomic_add_int(&stcb->asoc.refcnt, -1);
 					if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
 						SCTP_SOCKET_UNLOCK(so, 1);
- 						return (NULL);
+						return (NULL);
 					}
 #endif
 					soisconnected(stcb->sctp_socket);
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 					SCTP_SOCKET_UNLOCK(so, 1);
 #endif
 				}
 				/* notify upper layer */
@@ -1744,38 +1728,20 @@ sctp_process_cookie_existing(struct mbuf
 		 * two init's that we gave out the same tag on since
 		 * one was not established.. i.e. we get INIT from host-1
 		 * behind the nat and we respond tag-a, we get a INIT from
 		 * host-2 behind the nat and we get tag-a again. Then we
 		 * bring up host-1 (or 2's) assoc, Then comes the cookie
 		 * from hsot-2 (or 1). Now we have colliding state. We must
 		 * send an abort here with colliding state indication.
 		 */
-		op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
-		                               0, M_NOWAIT, 1, MT_DATA);
-		if (op_err == NULL) {
-			/* FOOBAR */
-			return (NULL);
-		}
-		/* pre-reserve some space */
-#ifdef INET6
-		SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
-#else
-		SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
-#endif
-		SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
-		SCTP_BUF_RESV_UF(op_err,  sizeof(struct sctp_chunkhdr));
-		/* Set the len */
-		SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
-		ph = mtod(op_err, struct sctp_paramhdr *);
-		ph->param_type = htons(SCTP_CAUSE_NAT_COLLIDING_STATE);
-		ph->param_length = htons(sizeof(struct sctp_paramhdr));
+		op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, "");
 		sctp_send_abort(m, iphlen,  src, dst, sh, 0, op_err,
 #if defined(__FreeBSD__)
-		                use_mflowid, mflowid,
+		                mflowtype, mflowid,
 #endif
 		                vrf_id, port);
 		return (NULL);
 	}
 	if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
 	    ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) ||
 	     (asoc->peer_vtag == 0))) {
 		/*
@@ -1932,17 +1898,17 @@ sctp_process_cookie_existing(struct mbuf
 			 * are allowing a duplicate association.
 			 * I hope this works...
 			 */
 			return (sctp_process_cookie_new(m, iphlen, offset, src, dst,
 			                                sh, cookie, cookie_len,
 			                                inp, netp, init_src,notification,
 			                                auth_skipped, auth_offset, auth_len,
 #if defined(__FreeBSD__)
-			                                use_mflowid, mflowid,
+			                                mflowtype, mflowid,
 #endif
 			                                vrf_id, port));
 		}
 		/*
 		 * case A in Section 5.2.4 Table 2: XXMM (peer restarted)
 		 */
 		/* temp code */
 		if (how_indx < sizeof(asoc->cookie_how))
@@ -2001,16 +1967,25 @@ sctp_process_cookie_existing(struct mbuf
 		SCTP_TCB_LOCK(stcb);
 		atomic_add_int(&stcb->asoc.refcnt, -1);
 		/* send up all the data */
 		SCTP_TCB_SEND_LOCK(stcb);
 
 		sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
 		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
 			stcb->asoc.strmout[i].chunks_on_queues = 0;
+#if defined(SCTP_DETAILED_STR_STATS)
+			for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
+				asoc->strmout[i].abandoned_sent[j] = 0;
+				asoc->strmout[i].abandoned_unsent[j] = 0;
+			}
+#else
+			asoc->strmout[i].abandoned_sent[0] = 0;
+			asoc->strmout[i].abandoned_unsent[0] = 0;
+#endif
 			stcb->asoc.strmout[i].stream_no = i;
 			stcb->asoc.strmout[i].next_sequence_send = 0;
 			stcb->asoc.strmout[i].last_msg_incomplete = 0;
 		}
 		/* process the INIT-ACK info (my info) */
 		asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
 		asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
 
@@ -2081,39 +2056,29 @@ sctp_process_cookie_existing(struct mbuf
 static struct sctp_tcb *
 sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
     struct sockaddr *src, struct sockaddr *dst,
     struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
     struct sctp_inpcb *inp, struct sctp_nets **netp,
     struct sockaddr *init_src, int *notification,
     int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
 #if defined(__FreeBSD__)
-    uint8_t use_mflowid, uint32_t mflowid,
+    uint8_t mflowtype, uint32_t mflowid,
 #endif
     uint32_t vrf_id, uint16_t port)
 {
 	struct sctp_tcb *stcb;
 	struct sctp_init_chunk *init_cp, init_buf;
 	struct sctp_init_ack_chunk *initack_cp, initack_buf;
-	struct sockaddr_storage sa_store;
-	struct sockaddr *initack_src = (struct sockaddr *)&sa_store;
+	union sctp_sockstore store;
 	struct sctp_association *asoc;
 	int init_offset, initack_offset, initack_limit;
 	int retval;
 	int error = 0;
 	uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
-#ifdef INET
-	struct sockaddr_in *sin;
-#endif
-#ifdef INET6
-	struct sockaddr_in6 *sin6;
-#endif
-#if defined(__Userspace__)
-	struct sockaddr_conn *sconn;
-#endif
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 	struct socket *so;
 
 	so = SCTP_INP_SO(inp);
 #endif
 
 	/*
 	 * find and validate the INIT chunk in the cookie (peer's info) the
@@ -2180,22 +2145,21 @@ sctp_process_cookie_new(struct mbuf *m, 
 #endif
 			       );
 	if (stcb == NULL) {
 		struct mbuf *op_err;
 
 		/* memory problem? */
 		SCTPDBG(SCTP_DEBUG_INPUT1,
 			"process_cookie_new: no room for another TCB!\n");
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
-
+		op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
 		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
 		                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, port);
 		return (NULL);
 	}
 	/* get the correct sctp_nets */
 	if (netp)
 		*netp = sctp_findnet(stcb, init_src);
 
@@ -2217,21 +2181,21 @@ sctp_process_cookie_new(struct mbuf *m, 
 		struct mbuf *op_err;
 
 		/*
 		 * Houston we have a problem. The EP changed while the
 		 * cookie was in flight. Only recourse is to abort the
 		 * association.
 		 */
 		atomic_add_int(&stcb->asoc.refcnt, 1);
-		op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
+		op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
 		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
 				       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-		                       use_mflowid, mflowid,
+		                       mflowtype, mflowid,
 #endif
 		                       vrf_id, port);
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 		SCTP_TCB_UNLOCK(stcb);
 		SCTP_SOCKET_LOCK(so, 1);
 		SCTP_TCB_LOCK(stcb);
 #endif
 		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
@@ -2344,49 +2308,45 @@ sctp_process_cookie_new(struct mbuf *m, 
 	 */
 
 	/* warning, we re-use sin, sin6, sa_store here! */
 	/* pull in local_address (our "from" address) */
 	switch (cookie->laddr_type) {
 #ifdef INET
 	case SCTP_IPV4_ADDRESS:
 		/* source addr is IPv4 */
-		sin = (struct sockaddr_in *)initack_src;
-		memset(sin, 0, sizeof(*sin));
-		sin->sin_family = AF_INET;
+		memset(&store.sin, 0, sizeof(struct sockaddr_in));
+		store.sin.sin_family = AF_INET;
 #ifdef HAVE_SIN_LEN
-		sin->sin_len = sizeof(struct sockaddr_in);
-#endif
-		sin->sin_addr.s_addr = cookie->laddress[0];
+		store.sin.sin_len = sizeof(struct sockaddr_in);
+#endif
+		store.sin.sin_addr.s_addr = cookie->laddress[0];
 		break;
 #endif
 #ifdef INET6
 	case SCTP_IPV6_ADDRESS:
 		/* source addr is IPv6 */
-		sin6 = (struct sockaddr_in6 *)initack_src;
-		memset(sin6, 0, sizeof(*sin6));
-		sin6->sin6_family = AF_INET6;
+		memset(&store.sin6, 0, sizeof(struct sockaddr_in6));
+		store.sin6.sin6_family = AF_INET6;
 #ifdef HAVE_SIN6_LEN
-		sin6->sin6_len = sizeof(struct sockaddr_in6);
-#endif
-		sin6->sin6_scope_id = cookie->scope_id;
-		memcpy(&sin6->sin6_addr, cookie->laddress,
-		    sizeof(sin6->sin6_addr));
+		store.sin6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+		store.sin6.sin6_scope_id = cookie->scope_id;
+		memcpy(&store.sin6.sin6_addr, cookie->laddress, sizeof(struct in6_addr));
 		break;
 #endif
 #if defined(__Userspace__)
 	case SCTP_CONN_ADDRESS:
-		/* source addr is IPv4 */
-		sconn = (struct sockaddr_conn *)initack_src;
-		memset(sconn, 0, sizeof(struct sockaddr_conn));
-		sconn->sconn_family = AF_CONN;
+		/* source addr is conn */
+		memset(&store.sconn, 0, sizeof(struct sockaddr_conn));
+		store.sconn.sconn_family = AF_CONN;
 #ifdef HAVE_SCONN_LEN
-		sconn->sconn_len = sizeof(struct sockaddr_conn);
-#endif
-		memcpy(&sconn->sconn_addr, cookie->laddress, sizeof(void *));
+		store.sconn.sconn_len = sizeof(struct sockaddr_conn);
+#endif
+		memcpy(&store.sconn.sconn_addr, cookie->laddress, sizeof(void *));
 		break;
 #endif
 	default:
 		atomic_add_int(&stcb->asoc.refcnt, 1);
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 		SCTP_TCB_UNLOCK(stcb);
 		SCTP_SOCKET_LOCK(so, 1);
 		SCTP_TCB_LOCK(stcb);
@@ -2457,17 +2417,17 @@ sctp_process_cookie_new(struct mbuf *m, 
 
 	/*
 	 * check the address lists for any ASCONFs that need to be sent
 	 * AFTER the cookie-ack is sent
 	 */
 	sctp_check_address_list(stcb, m,
 	    initack_offset + sizeof(struct sctp_init_ack_chunk),
 	    initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)),
-	    initack_src, cookie->local_scope, cookie->site_scope,
+	    &store.sa, cookie->local_scope, cookie->site_scope,
 	    cookie->ipv4_scope, cookie->loopback_scope);
 
 
 	return (stcb);
 }
 
 /*
  * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e
@@ -2489,17 +2449,17 @@ sctp_process_cookie_new(struct mbuf *m, 
 static struct mbuf *
 sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
     struct sockaddr *src, struct sockaddr *dst,
     struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp,
     struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp,
     int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
     struct sctp_tcb **locked_tcb,
 #if defined(__FreeBSD__)
-    uint8_t use_mflowid, uint32_t mflowid,
+    uint8_t mflowtype, uint32_t mflowid,
 #endif
     uint32_t vrf_id, uint16_t port)
 {
 	struct sctp_state_cookie *cookie;
 	struct sctp_tcb *l_stcb = *stcb;
 	struct sctp_inpcb *l_inp;
 	struct sockaddr *to;
 	struct sctp_pcb *ep;
@@ -2560,23 +2520,17 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 	sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE;
 	m_sig = m_split(m, sig_offset, M_NOWAIT);
 	if (m_sig == NULL) {
 		/* out of memory or ?? */
 		return (NULL);
 	}
 #ifdef SCTP_MBUF_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		struct mbuf *mat;
-
-		for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) {
-			if (SCTP_BUF_IS_EXTENDED(mat)) {
-				sctp_log_mb(mat, SCTP_MBUF_SPLIT);
-			}
-		}
+		sctp_log_mbc(m_sig, SCTP_MBUF_SPLIT);
 	}
 #endif
 
 	/*
 	 * compute the signature/digest for the cookie
 	 */
 	ep = &(*inp_p)->sctp_ep;
 	l_inp = *inp_p;
@@ -2682,17 +2636,17 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 		/* seconds to usec */
 		tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
 		/* add in usec */
 		if (tim == 0)
 			tim = now.tv_usec - cookie->time_entered.tv_usec;
 		scm->time_usec = htonl(tim);
 		sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
 #if defined(__FreeBSD__)
-		                   use_mflowid, mflowid,
+		                   mflowtype, mflowid,
 #endif
 		                   vrf_id, port);
 		return (NULL);
 	}
 	/*
 	 * Now we must see with the lookup address if we have an existing
 	 * asoc. This will only happen if we were in the COOKIE-WAIT state
 	 * and a INIT collided with us and somewhere the peer sent the
@@ -2740,17 +2694,17 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 		memcpy(&sconn.sconn_addr, cookie->address, sizeof(void *));
 		to = (struct sockaddr *)&sconn;
 		break;
 #endif
 	default:
 		/* This should not happen */
 		return (NULL);
 	}
-	if ((*stcb == NULL) && to) {
+	if (*stcb == NULL) {
 		/* Yep, lets check */
 		*stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL);
 		if (*stcb == NULL) {
 			/*
 			 * We should have only got back the same inp. If we
 			 * got back a different ep we have a problem. The
 			 * original findep got back l_inp and now
 			 */
@@ -2776,54 +2730,48 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 				SCTP_INP_INCR_REF((*stcb)->sctp_ep);
 				if ((*stcb)->sctp_ep != l_inp) {
 					SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n",
 						    (void *)(*stcb)->sctp_ep, (void *)l_inp);
 				}
 			}
 		}
 	}
-	if (to == NULL) {
-		return (NULL);
-	}
 
 	cookie_len -= SCTP_SIGNATURE_SIZE;
 	if (*stcb == NULL) {
 		/* this is the "normal" case... get a new TCB */
 		*stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh,
 		                                cookie, cookie_len, *inp_p,
 		                                netp, to, &notification,
 		                                auth_skipped, auth_offset, auth_len,
 #if defined(__FreeBSD__)
-		                                use_mflowid, mflowid,
+		                                mflowtype, mflowid,
 #endif
 		                                vrf_id, port);
 	} else {
 		/* this is abnormal... cookie-echo on existing TCB */
 		had_a_existing_tcb = 1;
 		*stcb = sctp_process_cookie_existing(m, iphlen, offset,
 		                                     src, dst, sh,
 						     cookie, cookie_len, *inp_p, *stcb, netp, to,
 						     &notification, auth_skipped, auth_offset, auth_len,
 #if defined(__FreeBSD__)
-		                                     use_mflowid, mflowid,
+		                                     mflowtype, mflowid,
 #endif
 		                                     vrf_id, port);
 	}
 
 	if (*stcb == NULL) {
 		/* still no TCB... must be bad cookie-echo */
 		return (NULL);
 	}
 #if defined(__FreeBSD__)
-	if ((*netp != NULL) && (use_mflowid != 0)) {
-		(*netp)->flowid = mflowid;
-#ifdef INVARIANTS
-		(*netp)->flowidset = 1;
-#endif
+	if ((*netp != NULL) && (mflowtype != M_HASHTYPE_NONE)) {
+		(*netp)->flowtype = mflowtype;
 	}
 #endif
 	/*
 	 * Ok, we built an association so confirm the address we sent the
 	 * INIT-ACK to.
 	 */
 	netl = sctp_findnet(*stcb, to);
 	/*
@@ -2859,17 +2807,17 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 			if (notification == SCTP_NOTIFY_ASSOC_RESTART) {
 				/*
 				 * For a restart we will keep the same
 				 * socket, no need to do anything. I THINK!!
 				 */
 				sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
 				if (send_int_conf) {
 					sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
-			    		                (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
+					                (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
 				}
 				return (m);
 			}
 			oso = (*inp_p)->sctp_socket;
 #if (defined(__FreeBSD__) && __FreeBSD_version < 700000)
 			/*
 			 * We do this to keep the sockets side happy during
 			 * the sonewcon ONLY.
@@ -2906,21 +2854,21 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 
 			if (so == NULL) {
 				struct mbuf *op_err;
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 				struct socket *pcb_so;
 #endif
 				/* Too many sockets */
 				SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n");
-				op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
+				op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
 				sctp_abort_association(*inp_p, NULL, m, iphlen,
 						       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-				                       use_mflowid, mflowid,
+				                       mflowtype, mflowid,
 #endif
 				                       vrf_id, port);
 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
 				pcb_so = SCTP_INP_SO(*inp_p);
 				atomic_add_int(&(*stcb)->asoc.refcnt, 1);
 				SCTP_TCB_UNLOCK((*stcb));
 				SCTP_SOCKET_LOCK(pcb_so, 1);
 				SCTP_TCB_LOCK((*stcb));
@@ -2937,25 +2885,31 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 			/*
 			 * We add the unbound flag here so that
 			 * if we get an soabort() before we get the
 			 * move_pcb done, we will properly cleanup.
 			 */
 			inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
 			    SCTP_PCB_FLAGS_CONNECTED |
 			    SCTP_PCB_FLAGS_IN_TCPPOOL |
- 			    SCTP_PCB_FLAGS_UNBOUND |
+			    SCTP_PCB_FLAGS_UNBOUND |
 			    (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
 			    SCTP_PCB_FLAGS_DONT_WAKE);
 			inp->sctp_features = (*inp_p)->sctp_features;
 			inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features;
 			inp->sctp_socket = so;
 			inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
 			inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
-			inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable;
+			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;
 			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;
 			inp->inp_starting_point_for_iterator = NULL;
 #if defined(__Userspace__)
 			inp->ulp_info = (*inp_p)->ulp_info;
 			inp->recv_callback = (*inp_p)->recv_callback;
 			inp->send_callback = (*inp_p)->send_callback;
@@ -3050,18 +3004,19 @@ static void
 sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
     struct sctp_tcb *stcb, struct sctp_nets *net)
 {
 	/* cp must not be used, others call this without a c-ack :-) */
 	struct sctp_association *asoc;
 
 	SCTPDBG(SCTP_DEBUG_INPUT2,
 		"sctp_handle_cookie_ack: handling COOKIE-ACK\n");
-	if (stcb == NULL)
+	if ((stcb == NULL) || (net == NULL)) {
 		return;
+	}
 
 	asoc = &stcb->asoc;
 
 	sctp_stop_all_cookie_timers(stcb);
 	/* process according to association state */
 	if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
 		/* state change only needed when I am in right state */
 		SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
@@ -3127,17 +3082,17 @@ sctp_handle_cookie_ack(struct sctp_cooki
 			    stcb->sctp_ep, stcb, NULL);
 		}
 		/*
 		 * send ASCONF if parameters are pending and ASCONFs are
 		 * allowed (eg. addresses changed when init/cookie echo were
 		 * 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,
 					 stcb->sctp_ep, stcb,
 					 stcb->asoc.primary_destination);
 #else
 			sctp_send_asconf(stcb, stcb->asoc.primary_destination,
 					 SCTP_ADDR_NOT_LOCKED);
@@ -3282,37 +3237,35 @@ sctp_handle_ecn_cwr(struct sctp_cwr_chun
 	 * Here we get a CWR from the peer. We must look in the outqueue and
 	 * make sure that we have a covered ECNE in the control chunk part.
 	 * If so remove it.
 	 */
 	struct sctp_tmit_chunk *chk;
 	struct sctp_ecne_chunk *ecne;
 	int override;
 	uint32_t cwr_tsn;
+
 	cwr_tsn = ntohl(cp->tsn);
-
 	override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE;
 	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
 		if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) {
 			continue;
 		}
 		if ((override == 0) && (chk->whoTo != net)) {
 			/* Must be from the right src unless override is set */
 			continue;
 		}
 		ecne = mtod(chk->data, struct sctp_ecne_chunk *);
 		if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) {
 			/* this covers this ECNE, we can remove it */
 			stcb->asoc.ecn_echo_cnt_onq--;
 			TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk,
 			    sctp_next);
-			if (chk->data) {
-				sctp_m_freem(chk->data);
-				chk->data = NULL;
-			}
+			sctp_m_freem(chk->data);
+			chk->data = NULL;
 			stcb->asoc.ctrl_queue_cnt--;
 			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
 			if (override == 0) {
 				break;
 			}
 		}
 	}
 }
@@ -3654,22 +3607,22 @@ sctp_reset_out_streams(struct sctp_tcb *
 		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
 			stcb->asoc.strmout[i].next_sequence_send = 0;
 		}
 	}
 	sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
 }
 
 
-struct sctp_stream_reset_out_request *
+struct sctp_stream_reset_request *
 sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk)
 {
 	struct sctp_association *asoc;
 	struct sctp_chunkhdr *ch;
-	struct sctp_stream_reset_out_request *r;
+	struct sctp_stream_reset_request *r;
 	struct sctp_tmit_chunk *chk;
 	int len, clen;
 
 	asoc = &stcb->asoc;
 	if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
 		asoc->stream_reset_outstanding = 0;
 		return (NULL);
 	}
@@ -3682,25 +3635,25 @@ sctp_find_stream_reset(struct sctp_tcb *
 		return (NULL);
 	}
 	if (bchk) {
 		/* he wants a copy of the chk pointer */
 		*bchk = chk;
 	}
 	clen = chk->send_size;
 	ch = mtod(chk->data, struct sctp_chunkhdr *);
-	r = (struct sctp_stream_reset_out_request *)(ch + 1);
+	r = (struct sctp_stream_reset_request *)(ch + 1);
 	if (ntohl(r->request_seq) == seq) {
 		/* found it */
 		return (r);
 	}
 	len = SCTP_SIZE32(ntohs(r->ph.param_length));
 	if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) {
 		/* move to the next one, there can only be a max of two */
-		r = (struct sctp_stream_reset_out_request *)((caddr_t)r + len);
+		r = (struct sctp_stream_reset_request *)((caddr_t)r + len);
 		if (ntohl(r->request_seq) == seq) {
 			return (r);
 		}
 	}
 	/* that seq is not here */
 	return (NULL);
 }
 
@@ -3734,53 +3687,56 @@ static int
 sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
 				  uint32_t seq, uint32_t action,
 				  struct sctp_stream_reset_response *respin)
 {
 	uint16_t type;
 	int lparm_len;
 	struct sctp_association *asoc = &stcb->asoc;
 	struct sctp_tmit_chunk *chk;
-	struct sctp_stream_reset_out_request *srparam;
+	struct sctp_stream_reset_request *req_param;
+	struct sctp_stream_reset_out_request *req_out_param;
+	struct sctp_stream_reset_in_request *req_in_param;
 	uint32_t number_entries;
 
 	if (asoc->stream_reset_outstanding == 0) {
 		/* duplicate */
 		return (0);
 	}
 	if (seq == stcb->asoc.str_reset_seq_out) {
-		srparam = sctp_find_stream_reset(stcb, seq, &chk);
-		if (srparam) {
+		req_param = sctp_find_stream_reset(stcb, seq, &chk);
+		if (req_param != NULL) {
 			stcb->asoc.str_reset_seq_out++;
-			type = ntohs(srparam->ph.param_type);
-			lparm_len = ntohs(srparam->ph.param_length);
+			type = ntohs(req_param->ph.param_type);
+			lparm_len = ntohs(req_param->ph.param_length);
 			if (type == SCTP_STR_RESET_OUT_REQUEST) {
+				req_out_param = (struct sctp_stream_reset_out_request *)req_param;
 				number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t);
 				asoc->stream_reset_out_is_outstanding = 0;
 				if (asoc->stream_reset_outstanding)
 					asoc->stream_reset_outstanding--;
 				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
 					/* do it */
-					sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams);
+					sctp_reset_out_streams(stcb, number_entries, req_out_param->list_of_streams);
 				} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
-					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
+					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED);
 				} else {
-					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
+					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED);
 				}
 			} else if (type == SCTP_STR_RESET_IN_REQUEST) {
-				/* Answered my request */
+				req_in_param = (struct sctp_stream_reset_in_request *)req_param;
 				number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t);
 				if (asoc->stream_reset_outstanding)
 					asoc->stream_reset_outstanding--;
 				if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
 					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb,
-							number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
+							number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED);
 				} else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) {
 					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb,
-							number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
+							number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED);
 				}
 			} else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) {
 				/* Ok we now may have more streams */
 				int num_stream;
 
 				num_stream = stcb->asoc.strm_pending_add_size;
 				if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) {
 					/* TSNH */
@@ -3818,16 +3774,19 @@ sctp_handle_stream_reset_response(struct
 				 */
 				struct sctp_stream_reset_response_tsn *resp;
 				struct sctp_forward_tsn_chunk fwdtsn;
 				int abort_flag = 0;
 				if (respin == NULL) {
 					/* huh ? */
 					return (0);
 				}
+				if (ntohs(respin->ph.param_length) < sizeof(struct sctp_stream_reset_response_tsn)) {
+					return (0);
+				}
 				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
 					resp = (struct sctp_stream_reset_response_tsn *)respin;
 					asoc->stream_reset_outstanding--;
 					fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
 					fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN;
 					fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1);
 					sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0);
 					if (abort_flag) {
@@ -4210,38 +4169,40 @@ sctp_handle_str_reset_add_out_strm(struc
 #ifdef __GNUC__
 __attribute__ ((noinline))
 #endif
 #endif
 static int
 sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 			 struct sctp_chunkhdr *ch_req)
 {
-	int chk_length, param_len, ptype;
+	uint16_t remaining_length, param_len, ptype;
 	struct sctp_paramhdr pstore;
 	uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE];
 	uint32_t seq = 0;
 	int num_req = 0;
 	int trunc = 0;
 	struct sctp_tmit_chunk *chk;
 	struct sctp_chunkhdr *ch;
 	struct sctp_paramhdr *ph;
 	int ret_code = 0;
 	int num_param = 0;
 
 	/* now it may be a reset or a reset-response */
-	chk_length = ntohs(ch_req->chunk_length);
+	remaining_length = ntohs(ch_req->chunk_length) - sizeof(struct sctp_chunkhdr);
 
 	/* setup for adding the response */
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		return (ret_code);
 	}
+	chk->copy_by_ref = 0;
 	chk->rec.chunk_id.id = SCTP_STREAM_RESET;
 	chk->rec.chunk_id.can_take_data = 0;
+	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->no_fr_allowed = 0;
 	chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr);
 	chk->book_size_scale = 0;
 	chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
 	if (chk->data == NULL) {
 	strres_nochunk:
 		if (chk->data) {
@@ -4259,90 +4220,119 @@ sctp_handle_stream_reset(struct sctp_tcb
 	chk->whoTo = NULL;
 
 	ch = mtod(chk->data, struct sctp_chunkhdr *);
 	ch->chunk_type = SCTP_STREAM_RESET;
 	ch->chunk_flags = 0;
 	ch->chunk_length = htons(chk->send_size);
 	SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
 	offset += sizeof(struct sctp_chunkhdr);
-	while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) {
+	while (remaining_length >= sizeof(struct sctp_paramhdr)) {
 		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *)&pstore);
-		if (ph == NULL)
-			break;
-		param_len = ntohs(ph->param_length);
-		if (param_len < (int)sizeof(struct sctp_stream_reset_tsn_request)) {
-			/* bad param */
+		if (ph == NULL) {
+			/* TSNH */
 			break;
 		}
-		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, (int)sizeof(cstore)),
+		param_len = ntohs(ph->param_length);
+		if ((param_len > remaining_length) ||
+		    (param_len < (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)))) {
+			/* bad parameter length */
+			break;
+		}
+		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, sizeof(cstore)),
 							   (uint8_t *)&cstore);
+		if (ph == NULL) {
+			/* TSNH */
+			break;
+		}
 		ptype = ntohs(ph->param_type);
 		num_param++;
-		if (param_len > (int)sizeof(cstore)) {
+		if (param_len > sizeof(cstore)) {
 			trunc = 1;
 		} else {
 			trunc = 0;
 		}
 		if (num_param > SCTP_MAX_RESET_PARAMS) {
 			/* hit the max of parameters already sorry.. */
 			break;
 		}
 		if (ptype == SCTP_STR_RESET_OUT_REQUEST) {
 			struct sctp_stream_reset_out_request *req_out;
+
+			if (param_len < sizeof(struct sctp_stream_reset_out_request)) {
+				break;
+			}
 			req_out = (struct sctp_stream_reset_out_request *)ph;
 			num_req++;
 			if (stcb->asoc.stream_reset_outstanding) {
 				seq = ntohl(req_out->response_seq);
 				if (seq == stcb->asoc.str_reset_seq_out) {
 					/* implicit ack */
 					(void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL);
 				}
 			}
 			sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc);
 		} else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) {
 			struct sctp_stream_reset_add_strm  *str_add;
+
+			if (param_len < sizeof(struct sctp_stream_reset_add_strm)) {
+				break;
+			}
 			str_add = (struct sctp_stream_reset_add_strm  *)ph;
 			num_req++;
 			sctp_handle_str_reset_add_strm(stcb, chk, str_add);
 		} else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) {
 			struct sctp_stream_reset_add_strm  *str_add;
+
+			if (param_len < sizeof(struct sctp_stream_reset_add_strm)) {
+				break;
+			}
 			str_add = (struct sctp_stream_reset_add_strm  *)ph;
 			num_req++;
 			sctp_handle_str_reset_add_out_strm(stcb, chk, str_add);
 		} else if (ptype == SCTP_STR_RESET_IN_REQUEST) {
 			struct sctp_stream_reset_in_request *req_in;
+
 			num_req++;
 			req_in = (struct sctp_stream_reset_in_request *)ph;
 			sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc);
 		} else if (ptype == SCTP_STR_RESET_TSN_REQUEST) {
 			struct sctp_stream_reset_tsn_request *req_tsn;
+
 			num_req++;
 			req_tsn = (struct sctp_stream_reset_tsn_request *)ph;
 			if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) {
 				ret_code = 1;
 				goto strres_nochunk;
 			}
 			/* no more */
 			break;
 		} else if (ptype == SCTP_STR_RESET_RESPONSE) {
 			struct sctp_stream_reset_response *resp;
 			uint32_t result;
+
+			if (param_len < sizeof(struct sctp_stream_reset_response)) {
+				break;
+			}
 			resp = (struct sctp_stream_reset_response *)ph;
 			seq = ntohl(resp->response_seq);
 			result = ntohl(resp->result);
 			if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) {
 				ret_code = 1;
 				goto strres_nochunk;
 			}
 		} else {
 			break;
 		}
 		offset += SCTP_SIZE32(param_len);
-		chk_length -= SCTP_SIZE32(param_len);
+		if (remaining_length >= SCTP_SIZE32(param_len)) {
+			remaining_length -= SCTP_SIZE32(param_len);
+		} else {
+			remaining_length = 0;
+		}
 	}
 	if (num_req == 0) {
 		/* we have no response free the stuff */
 		goto strres_nochunk;
 	}
 	/* ok we have a chunk to link in */
 	TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue,
 			  chk,
@@ -4522,21 +4512,23 @@ sctp_handle_packet_dropped(struct sctp_p
 #endif
 #endif
 static struct sctp_tcb *
 sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
     struct sockaddr *src, struct sockaddr *dst,
     struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp,
     struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen,
 #if defined(__FreeBSD__)
-    uint8_t use_mflowid, uint32_t mflowid,
+    uint8_t mflowtype, uint32_t mflowid,
 #endif
     uint32_t vrf_id, uint16_t port)
 {
 	struct sctp_association *asoc;
+	struct mbuf *op_err;
+	char msg[SCTP_DIAG_INFO_LEN];
 	uint32_t vtag_in;
 	int num_chunks = 0;	/* number of control chunks processed */
 	uint32_t chk_length;
 	int ret;
 	int abort_no_unlock = 0;
 	int ecne_seen = 0;
 	/*
 	 * How big should this be, and should it be alloc'd? Lets try the
@@ -4587,17 +4579,17 @@ sctp_process_control(struct mbuf *m, int
 	} else if (ch->chunk_type != SCTP_COOKIE_ECHO) {
 		/*
 		 * If there is no stcb, skip the AUTH chunk and process
 		 * later after a stcb is found (to validate the lookup was
 		 * valid.
 		 */
 		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;
 			auth_len = ntohs(ch->chunk_length);
 
 			/* (temporarily) move past this chunk */
 			*offset += SCTP_SIZE32(auth_len);
 			if (*offset >= length) {
@@ -4677,20 +4669,23 @@ sctp_process_control(struct mbuf *m, int
 					return (NULL);
 				} else {
 					/* remaining chunks are HMAC checked */
 					stcb->asoc.authenticated = 1;
 				}
 			}
 		}
 		if (stcb == NULL) {
+			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+			                             msg);
 			/* no association, so it's out of the blue... */
-			sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp,
+			sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err,
 #if defined(__FreeBSD__)
-			                 use_mflowid, mflowid,
+			                 mflowtype, mflowid,
 #endif
 					 vrf_id, port);
 			*offset = length;
 			if (locked_tcb) {
 				SCTP_TCB_UNLOCK(locked_tcb);
 			}
 			return (NULL);
 		}
@@ -4720,20 +4715,23 @@ sctp_process_control(struct mbuf *m, int
 				 * peer never got the SHUTDOWN-COMPLETE and
 				 * is still hung; we have started a new asoc
 				 * but it won't complete until the shutdown
 				 * is completed
 				 */
 				if (locked_tcb) {
 					SCTP_TCB_UNLOCK(locked_tcb);
 				}
+				snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+				op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+				                             msg);
 				sctp_handle_ootb(m, iphlen, *offset, src, dst,
-				                 sh, inp,
+				                 sh, inp, op_err,
 #if defined(__FreeBSD__)
-				                 use_mflowid, mflowid,
+				                 mflowtype, mflowid,
 #endif
 				                 vrf_id, port);
 				return (NULL);
 			}
 		} else {
 			/* for all other chunks, vtag must match */
 			if (vtag_in != asoc->my_vtag) {
 				/* invalid vtag... */
@@ -4853,72 +4851,72 @@ sctp_process_control(struct mbuf *m, int
 			}
 		}
 #ifdef SCTP_AUDITING_ENABLED
 		sctp_audit_log(0xB0, ch->chunk_type);
 #endif
 
 		/* 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 */
 			SCTP_STAT_INCR(sctps_recvauthmissing);
 			goto next_chunk;
 		}
 		switch (ch->chunk_type) {
 		case SCTP_INITIATION:
 			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n");
 			/* The INIT chunk must be the only chunk. */
 			if ((num_chunks > 1) ||
 			    (length - *offset > (int)SCTP_SIZE32(chk_length))) {
+				op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+				                             "INIT not the only chunk");
 				sctp_abort_association(inp, stcb, m, iphlen,
-				                       src, dst, sh, NULL,
+				                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-				                       use_mflowid, mflowid,
+				                       mflowtype, mflowid,
 #endif
 				                       vrf_id, port);
 				*offset = length;
 				return (NULL);
 			}
 			/* Honor our resource limit. */
 			if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) {
-				struct mbuf *op_err;
-
-				op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
+				op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
 				sctp_abort_association(inp, stcb, m, iphlen,
 						       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-				                       use_mflowid, mflowid,
+				                       mflowtype, mflowid,
 #endif
 				                       vrf_id, port);
 				*offset = length;
 				return (NULL);
 			}
 			sctp_handle_init(m, iphlen, *offset, src, dst, sh,
 			                 (struct sctp_init_chunk *)ch, inp,
 			                 stcb, &abort_no_unlock,
 #if defined(__FreeBSD__)
-			                 use_mflowid, mflowid,
+			                 mflowtype, mflowid,
 #endif
 			                 vrf_id, port);
 			*offset = length;
 			if ((!abort_no_unlock) && (locked_tcb)) {
 				SCTP_TCB_UNLOCK(locked_tcb);
 			}
 			return (NULL);
 			break;
 		case SCTP_PAD_CHUNK:
 			break;
 		case SCTP_INITIATION_ACK:
 			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n");
 			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
 				/* We are not interested anymore */
- 				if ((stcb) && (stcb->asoc.total_output_queue_size)) {
+				if ((stcb) && (stcb->asoc.total_output_queue_size)) {
 					;
 				} else {
 					if (locked_tcb != stcb) {
 						/* Very unlikely */
 						SCTP_TCB_UNLOCK(locked_tcb);
 					}
 					*offset = length;
 					if (stcb) {
@@ -4949,17 +4947,17 @@ sctp_process_control(struct mbuf *m, int
 			}
 			if ((netp) && (*netp)) {
 				ret = sctp_handle_init_ack(m, iphlen, *offset,
 				                           src, dst, sh,
 				                           (struct sctp_init_ack_chunk *)ch,
 				                           stcb, *netp,
 				                           &abort_no_unlock,
 #if defined(__FreeBSD__)
-				                           use_mflowid, mflowid,
+				                           mflowtype, mflowid,
 #endif
 				                           vrf_id);
 			} else {
 				ret = -1;
 			}
 			*offset = length;
 			if (abort_no_unlock) {
 				return (NULL);
@@ -5062,18 +5060,17 @@ sctp_process_control(struct mbuf *m, int
 				int offset_seg, offset_dup;
 
 				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n");
 				SCTP_STAT_INCR(sctps_recvsacks);
 				if (stcb == NULL) {
 					SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n");
 					break;
 				}
-				if ((stcb->asoc.sctp_nr_sack_on_off == 0) ||
-				    (stcb->asoc.peer_supports_nr_sack == 0)) {
+				if (stcb->asoc.nrsack_supported == 0) {
 					goto unknown_chunk;
 				}
 				if (chk_length < sizeof(struct sctp_nr_sack_chunk)) {
 					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n");
 					break;
 				}
 				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
 					/*-
@@ -5246,23 +5243,21 @@ sctp_process_control(struct mbuf *m, int
 			 * listening responded to a INIT-ACK and then
 			 * closed. We opened and bound.. and are now no
 			 * longer listening.
 			 */
 
 			if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) {
 				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
 				    (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) {
-					struct mbuf *op_err;
-
-					op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
+					op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
 					sctp_abort_association(inp, stcb, m, iphlen,
 					                       src, dst, sh, op_err,
 #if defined(__FreeBSD__)
-					                       use_mflowid, mflowid,
+					                       mflowtype, mflowid,
 #endif
 					                       vrf_id, port);
 				}
 				*offset = length;
 				return (NULL);
 			} else {
 				struct mbuf *ret_buf;
 				struct sctp_inpcb *linp;
@@ -5289,17 +5284,17 @@ sctp_process_control(struct mbuf *m, int
 						                        sh,
 						                        (struct sctp_cookie_echo_chunk *)ch,
 						                        &inp, &stcb, netp,
 						                        auth_skipped,
 						                        auth_offset,
 						                        auth_len,
 						                        &locked_tcb,
 #if defined(__FreeBSD__)
-						                        use_mflowid,
+						                        mflowtype,
 						                        mflowid,
 #endif
 						                        vrf_id,
 						                        port);
 				} else {
 					ret_buf = NULL;
 				}
 				if (linp) {
@@ -5380,16 +5375,19 @@ sctp_process_control(struct mbuf *m, int
 				/* Its not ours */
 				if (locked_tcb) {
 					SCTP_TCB_UNLOCK(locked_tcb);
 				}
 				*offset = length;
 				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,
 						       0,
 						       SCTP_FROM_SCTP_INPUT,
 						       __LINE__);
 				}
 				stcb->asoc.overall_error_count = 0;
@@ -5405,16 +5403,19 @@ sctp_process_control(struct mbuf *m, int
 				/* Its not ours */
 				if (locked_tcb) {
 					SCTP_TCB_UNLOCK(locked_tcb);
 				}
 				*offset = length;
 				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,
 						       0,
 						       SCTP_FROM_SCTP_INPUT,
 						       __LINE__);
 				}
 				stcb->asoc.overall_error_count = 0;
@@ -5438,16 +5439,19 @@ sctp_process_control(struct mbuf *m, int
 			}
 			*offset = length;
 			return (NULL);
 			break;
 		case SCTP_ASCONF:
 			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,
 						       0,
 						       SCTP_FROM_SCTP_INPUT,
 						       __LINE__);
 				}
 				stcb->asoc.overall_error_count = 0;
@@ -5462,16 +5466,19 @@ sctp_process_control(struct mbuf *m, int
 				/* Its not ours */
 				if (locked_tcb) {
 					SCTP_TCB_UNLOCK(locked_tcb);
 				}
 				*offset = length;
 				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,
 						       stcb->asoc.overall_error_count,
 						       0,
 						       SCTP_FROM_SCTP_INPUT,
 						       __LINE__);
 				}
@@ -5491,16 +5498,20 @@ sctp_process_control(struct mbuf *m, int
 				}
 				*offset = length;
 				return (NULL);
 			}
 
 			/* He's alive so give him credit */
 			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,
 						       stcb->asoc.overall_error_count,
 						       0,
 						       SCTP_FROM_SCTP_INPUT,
 						       __LINE__);
 				}
@@ -5545,23 +5556,18 @@ sctp_process_control(struct mbuf *m, int
 			if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) {
 				/* Its not ours */
 				if (locked_tcb) {
 					SCTP_TCB_UNLOCK(locked_tcb);
 				}
 				*offset = length;
 				return (NULL);
 			}
-			if (stcb->asoc.peer_supports_strreset == 0) {
-				/*
-				 * hmm, peer should have announced this, but
-				 * we will turn it on since he is sending us
-				 * a stream reset.
-				 */
-				stcb->asoc.peer_supports_strreset = 1;
+			if (stcb->asoc.reconfig_supported == 0) {
+				goto unknown_chunk;
 			}
 			if (sctp_handle_stream_reset(stcb, m, *offset, ch)) {
 				/* stop processing */
 				*offset = length;
 				return (NULL);
 			}
 			break;
 		case SCTP_PACKET_DROPPED:
@@ -5573,39 +5579,41 @@ sctp_process_control(struct mbuf *m, int
 					SCTP_TCB_UNLOCK(locked_tcb);
 				}
 				*offset = length;
 				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) {
 					auth_offset = *offset;
 					auth_len = chk_length;
 					auth_skipped = 1;
 				}
 				/* 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))) {
 				/* Its not ours */
 				if (locked_tcb) {
 					SCTP_TCB_UNLOCK(locked_tcb);
 				}
 				*offset = length;
@@ -5628,45 +5636,41 @@ sctp_process_control(struct mbuf *m, int
 			break;
 
 		default:
 		unknown_chunk:
 			/* it's an unknown chunk! */
 			if ((ch->chunk_type & 0x40) && (stcb != NULL)) {
 				struct mbuf *mm;
 				struct sctp_paramhdr *phd;
+				int len;
 
 				mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
 							   0, M_NOWAIT, 1, MT_DATA);
 				if (mm) {
+					len = min(SCTP_SIZE32(chk_length), (uint32_t)(length - *offset));
 					phd = mtod(mm, struct sctp_paramhdr *);
 					/*
 					 * We cheat and use param type since
 					 * we did not bother to define a
 					 * error cause struct. They are the
 					 * same basic format with different
 					 * names.
 					 */
 					phd->param_type =  htons(SCTP_CAUSE_UNRECOG_CHUNK);
-					phd->param_length = htons(chk_length + sizeof(*phd));
+					phd->param_length = htons(len + sizeof(*phd));
 					SCTP_BUF_LEN(mm) = sizeof(*phd);
-					SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
+					SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
 					if (SCTP_BUF_NEXT(mm)) {
-						if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
+						if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(len) - len, NULL) == NULL) {
 							sctp_m_freem(mm);
 						} else {
 #ifdef SCTP_MBUF_LOGGING
 							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-								struct mbuf *mat;
-
-								for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) {
-									if (SCTP_BUF_IS_EXTENDED(mat)) {
-										sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-									}
-								}
+								sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY);
 							}
 #endif
 							sctp_queue_op_err(stcb, mm);
 						}
 					} else {
 						sctp_m_freem(mm);
 					}
 				}
@@ -5737,23 +5741,24 @@ void
 sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length,
                              struct sockaddr *src, struct sockaddr *dst,
                              struct sctphdr *sh, struct sctp_chunkhdr *ch,
 #if !defined(SCTP_WITH_NO_CSUM)
                              uint8_t compute_crc,
 #endif
                              uint8_t ecn_bits,
 #if defined(__FreeBSD__)
-                             uint8_t use_mflowid, uint32_t mflowid,
+                             uint8_t mflowtype, uint32_t mflowid,
 #endif
                              uint32_t vrf_id, uint16_t port)
 {
 	uint32_t high_tsn;
 	int fwd_tsn_seen = 0, data_processed = 0;
-	struct mbuf *m = *mm;
+	struct mbuf *m = *mm, *op_err;
+	char msg[SCTP_DIAG_INFO_LEN];
 	int un_sent;
 	int cnt_ctrl_ready = 0;
 	struct sctp_inpcb *inp = NULL, *inp_decr = NULL;
 	struct sctp_tcb *stcb = NULL;
 	struct sctp_nets *net = NULL;
 
 	SCTP_STAT_INCR(sctps_recvdatagrams);
 #ifdef SCTP_AUDITING_ENABLED
@@ -5768,28 +5773,27 @@ sctp_common_input_processing(struct mbuf
 		sh->checksum = 0;
 		calc_check = sctp_calculate_cksum(m, iphlen);
 		sh->checksum = check;
 		if (calc_check != check) {
 			SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x  m:%p mlen:%d iphlen:%d\n",
 			        calc_check, check, (void *)m, length, iphlen);
 			stcb = sctp_findassociation_addr(m, offset, src, dst,
 			                                 sh, ch, &inp, &net, vrf_id);
+#if defined(INET) || defined(INET6)
 			if ((net != NULL) && (port != 0)) {
 				if (net->port == 0) {
 					sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
 				}
 				net->port = port;
 			}
+#endif
 #if defined(__FreeBSD__)
-			if ((net != NULL) && (use_mflowid != 0)) {
-				net->flowid = mflowid;
-#ifdef INVARIANTS
-				net->flowidset = 1;
-#endif
+			if ((net != NULL) && (mflowtype != M_HASHTYPE_NONE)) {
+				net->flowtype = mflowtype;
 			}
 #endif
 			if ((inp != NULL) && (stcb != NULL)) {
 				sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
 				sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
 			} else if ((inp != NULL) && (stcb == NULL)) {
 				inp_decr = inp;
 			}
@@ -5801,56 +5805,57 @@ sctp_common_input_processing(struct mbuf
 #endif
 	/* Destination port of 0 is illegal, based on RFC4960. */
 	if (sh->dest_port == 0) {
 		SCTP_STAT_INCR(sctps_hdrops);
 		goto out;
 	}
 	stcb = sctp_findassociation_addr(m, offset, src, dst,
 	                                 sh, ch, &inp, &net, vrf_id);
+#if defined(INET) || defined(INET6)
 	if ((net != NULL) && (port != 0)) {
 		if (net->port == 0) {
 			sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
 		}
 		net->port = port;
 	}
+#endif
 #if defined(__FreeBSD__)
-	if ((net != NULL) && (use_mflowid != 0)) {
-		net->flowid = mflowid;
-#ifdef INVARIANTS
-		net->flowidset = 1;
-#endif
+	if ((net != NULL) && (mflowtype != M_HASHTYPE_NONE)) {
+		net->flowtype = mflowtype;
 	}
 #endif
 	if (inp == NULL) {
 		SCTP_STAT_INCR(sctps_noport);
 #if defined(__FreeBSD__) && (((__FreeBSD_version < 900000) && (__FreeBSD_version >= 804000)) || (__FreeBSD_version > 900000))
 		if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
 			goto out;
 		}
 #endif
 		if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
 			sctp_send_shutdown_complete2(src, dst, sh,
 #if defined(__FreeBSD__)
-			                             use_mflowid, mflowid,
+			                             mflowtype, mflowid,
 #endif
 			                             vrf_id, port);
 			goto out;
 		}
 		if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
 			goto out;
 		}
 		if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
 			if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
 			    ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
 			     (ch->chunk_type != SCTP_INIT))) {
+				op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+				                             "Out of the blue");
 				sctp_send_abort(m, iphlen, src, dst,
-				                sh, 0, NULL,
+				                sh, 0, op_err,
 #if defined(__FreeBSD__)
-				                use_mflowid, mflowid,
+				                mflowtype, mflowid,
 #endif
 				                vrf_id, port);
 			}
 		}
 		goto out;
 	} else if (stcb == NULL) {
 		inp_decr = inp;
 	}
@@ -5859,34 +5864,24 @@ sctp_common_input_processing(struct mbuf
 	 * I very much doubt any of the IPSEC stuff will work but I have no
 	 * idea, so I will leave it in place.
 	 */
 	if (inp != NULL) {
 		switch (dst->sa_family) {
 #ifdef INET
 		case AF_INET:
 			if (ipsec4_in_reject(m, &inp->ip_inp.inp)) {
-#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036)
-				IPSECSTAT_INC(ips_in_polvio);
-#else
-				MODULE_GLOBAL(ipsec4stat).in_polvio++;
-#endif
 				SCTP_STAT_INCR(sctps_hdrops);
 				goto out;
 			}
 			break;
 #endif
 #ifdef INET6
 		case AF_INET6:
 			if (ipsec6_in_reject(m, &inp->ip_inp.inp)) {
-#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036)
-				IPSEC6STAT_INC(ips_in_polvio);
-#else
-				MODULE_GLOBAL(ipsec6stat).in_polvio++;
-#endif
 				SCTP_STAT_INCR(sctps_hdrops);
 				goto out;
 			}
 			break;
 #endif
 		default:
 			break;
 		}
@@ -5904,72 +5899,80 @@ sctp_common_input_processing(struct mbuf
 		if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) ||
 		    (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
 			/*-
 			 * If we hit here, we had a ref count
 			 * up when the assoc was aborted and the
 			 * timer is clearing out the assoc, we should
 			 * NOT respond to any packet.. its OOTB.
 			 */
- 			SCTP_TCB_UNLOCK(stcb);
+			SCTP_TCB_UNLOCK(stcb);
 			stcb = NULL;
-			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
+			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+			                             msg);
+			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
 #if defined(__FreeBSD__)
-			                 use_mflowid, mflowid,
-#endif
-					 vrf_id, port);
+			                 mflowtype, mflowid,
+#endif
+			                 vrf_id, port);
 			goto out;
 		}
 
 	}
 	if (IS_SCTP_CONTROL(ch)) {
 		/* process the control portion of the SCTP packet */
 		/* sa_ignore NO_NULL_CHK */
 		stcb = sctp_process_control(m, iphlen, &offset, length,
 		                            src, dst, sh, ch,
 		                            inp, stcb, &net, &fwd_tsn_seen,
 #if defined(__FreeBSD__)
-					    use_mflowid, mflowid,
+		                            mflowtype, mflowid,
 #endif
 		                            vrf_id, port);
 		if (stcb) {
 			/* This covers us if the cookie-echo was there
 			 * and it changes our INP.
 			 */
- 			inp = stcb->sctp_ep;
+			inp = stcb->sctp_ep;
+#if defined(INET) || defined(INET6)
 			if ((net) && (port)) {
 				if (net->port == 0) {
 					sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
 				}
 				net->port = port;
 			}
+#endif
 		}
 	} else {
 		/*
 		 * no control chunks, so pre-process DATA chunks (these
 		 * checks are taken care of by control processing)
 		 */
 
 		/*
 		 * if DATA only packet, and auth is required, then punt...
 		 * can't have authenticated without any AUTH (control)
 		 * 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);
 			goto out;
 		}
 		if (stcb == NULL) {
 			/* out of the blue DATA chunk */
-			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
+			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+			                             msg);
+			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
 #if defined(__FreeBSD__)
-			                 use_mflowid, mflowid,
+			                 mflowtype, mflowid,
 #endif
 					 vrf_id, port);
 			goto out;
 		}
 		if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
 			/* v_tag mismatch! */
 			SCTP_STAT_INCR(sctps_badvtag);
 			goto out;
@@ -5991,17 +5994,17 @@ sctp_common_input_processing(struct mbuf
 	/* plow through the data chunks while length > offset */
 
 	/*
 	 * Rest should be DATA only.  Check authentication state if AUTH for
 	 * DATA is required.
 	 */
 	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 */
 		SCTP_STAT_INCR(sctps_recvauthmissing);
 		SCTPDBG(SCTP_DEBUG_AUTH1,
 			"Data chunk requires AUTH, skipped\n");
 		goto trigger_send;
 	}
@@ -6029,19 +6032,22 @@ sctp_common_input_processing(struct mbuf
 			}
 			stcb->asoc.overall_error_count = 0;
 			sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net);
 			break;
 		case SCTP_STATE_COOKIE_WAIT:
 			/*
 			 * We consider OOTB any data sent during asoc setup.
 			 */
-			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
+			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+			                             msg);
+			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
 #if defined(__FreeBSD__)
-			                 use_mflowid, mflowid,
+			                 mflowtype, mflowid,
 #endif
 					 vrf_id, port);
 			goto out;
 			/*sa_ignore NOTREACHED*/
 			break;
 		case SCTP_STATE_EMPTY:	/* should not happen */
 		case SCTP_STATE_INUSE:	/* should not happen */
 		case SCTP_STATE_SHUTDOWN_RECEIVED:	/* This is a peer error */
@@ -6054,17 +6060,17 @@ sctp_common_input_processing(struct mbuf
 		case SCTP_STATE_SHUTDOWN_SENT:
 			break;
 		}
 		/* plow through the data chunks while length > offset */
 		retval = sctp_process_data(mm, iphlen, &offset, length,
 		                           src, dst, sh,
 		                           inp, stcb, net, &high_tsn,
 #if defined(__FreeBSD__)
-		                           use_mflowid, mflowid,
+		                           mflowtype, mflowid,
 #endif
 		                           vrf_id, port);
 		if (retval == 2) {
 			/*
 			 * The association aborted, NO UNLOCK needed since
 			 * the association is destroyed.
 			 */
 			stcb = NULL;
@@ -6074,17 +6080,17 @@ sctp_common_input_processing(struct mbuf
 		/*
 		 * Anything important needs to have been m_copy'ed in
 		 * process_data
 		 */
 	}
 
 	/* take care of ecn */
 	if ((data_processed == 1) &&
-	    (stcb->asoc.ecn_allowed == 1) &&
+	    (stcb->asoc.ecn_supported == 1) &&
 	    ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) {
 		/* Yep, we need to add a ECNE */
 		sctp_send_ecn_echo(stcb, net, high_tsn);
 	}
 
 	if ((data_processed == 0) && (fwd_tsn_seen)) {
 		int was_a_gap;
 		uint32_t highest_tsn;
@@ -6140,28 +6146,16 @@ trigger_send:
 #ifdef INVARIANTS
 	if (inp != NULL) {
 		sctp_validate_no_locks(inp);
 	}
 #endif
 	return;
 }
 
-#if 0
-static void
-sctp_print_mbuf_chain(struct mbuf *m)
-{
-	for (; m; m = SCTP_BUF_NEXT(m)) {
-		SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m));
-		if (SCTP_BUF_IS_EXTENDED(m))
-			SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m));
-	}
-}
-#endif
-
 #ifdef INET
 #if !defined(__Userspace__)
 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
 void
 sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
 #elif defined(__Panda__)
 void
 sctp_input(pakhandle_type i_pak)
@@ -6184,17 +6178,17 @@ sctp_input(i_pak, va_alist)
 	struct sctphdr *sh;
 	struct sctp_chunkhdr *ch;
 	int length, offset;
 #if !defined(SCTP_WITH_NO_CSUM)
 	uint8_t compute_crc;
 #endif
 #if defined(__FreeBSD__)
 	uint32_t mflowid;
-	uint8_t use_mflowid;
+	uint8_t mflowtype;
 #endif
 #if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__))
 	uint16_t port = 0;
 #endif
 
 #if defined(__Panda__)
 	/* This is Evil, but its the only way to make panda work right. */
 	iphlen = sizeof(struct ip);
@@ -6208,23 +6202,17 @@ sctp_input(i_pak, va_alist)
 	m = SCTP_HEADER_TO_CHAIN(i_pak);
 #ifdef __Panda__
 	SCTP_DETACH_HEADER_FROM_CHAIN(i_pak);
 	(void)SCTP_RELEASE_HEADER(i_pak);
 #endif
 #ifdef SCTP_MBUF_LOGGING
 	/* Log in any input mbufs */
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		struct mbuf *mat;
-
-		for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
-			if (SCTP_BUF_IS_EXTENDED(mat)) {
-				sctp_log_mb(mat, SCTP_MBUF_INPUT);
-			}
-		}
+		sctp_log_mbc(m, SCTP_MBUF_INPUT);
 	}
 #endif
 #ifdef SCTP_PACKET_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
 		sctp_packet_log(m);
 	}
 #endif
 #if defined(__FreeBSD__)
@@ -6259,23 +6247,18 @@ sctp_input(i_pak, va_alist)
 #if defined(__Windows__)
 	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
 	        "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
 	        m->m_pkthdr.len,
 	        m->m_pkthdr.rcvif->if_xname,
 	        m->m_pkthdr.csum_flags);
 #endif
 #if defined(__FreeBSD__)
-	if (m->m_flags & M_FLOWID) {
-		mflowid = m->m_pkthdr.flowid;
-		use_mflowid = 1;
-	} else {
-		mflowid = 0;
-		use_mflowid = 0;
-	}
+	mflowid = m->m_pkthdr.flowid;
+	mflowtype = M_HASHTYPE_GET(m);
 #endif
 	SCTP_STAT_INCR(sctps_recvpackets);
 	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
 	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
 	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
 	if (SCTP_BUF_LEN(m) < offset) {
 		if ((m = m_pullup(m, offset)) == NULL) {
 			SCTP_STAT_INCR(sctps_hdrops);
@@ -6362,62 +6345,84 @@ sctp_input(i_pak, va_alist)
 	                             (struct sockaddr *)&src,
 	                             (struct sockaddr *)&dst,
 	                             sh, ch,
 #if !defined(SCTP_WITH_NO_CSUM)
 	                             compute_crc,
 #endif
 	                             ecn_bits,
 #if defined(__FreeBSD__)
-	                             use_mflowid, mflowid,
+	                             mflowtype, mflowid,
 #endif
 	                             vrf_id, port);
  out:
 	if (m) {
 		sctp_m_freem(m);
 	}
 	return;
 }
 
 #if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
 extern int *sctp_cpuarry;
 #endif
 
+#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020  
+int
+sctp_input(struct mbuf **mp, int *offp, int proto SCTP_UNUSED)
+{
+	struct mbuf *m;
+	int off;
+
+	m = *mp;
+	off = *offp;
+#else
 void
 sctp_input(struct mbuf *m, int off)
 {
+#endif
 #if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
-	struct ip *ip;
-	struct sctphdr *sh;
-	int offset;
-	int cpu_to_use;
-	uint32_t flowid, tag;
-
 	if (mp_ncpus > 1) {
-		if (m->m_flags & M_FLOWID) {
+		struct ip *ip;
+		struct sctphdr *sh;
+		int offset;
+		int cpu_to_use;
+		uint32_t flowid, tag;
+
+		if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
 			flowid = m->m_pkthdr.flowid;
 		} else {
 			/* No flow id built by lower layers
 			 * fix it so we create one.
 			 */
 			offset = off + sizeof(struct sctphdr);
 			if (SCTP_BUF_LEN(m) < offset) {
 				if ((m = m_pullup(m, offset)) == NULL) {
 					SCTP_STAT_INCR(sctps_hdrops);
+#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020  
+					return (IPPROTO_DONE);
+#else
 					return;
+#endif
 				}
 			}
 			ip = mtod(m, struct ip *);
 			sh = (struct sctphdr *)((caddr_t)ip + off);
 			tag = htonl(sh->v_tag);
 			flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port);
 			m->m_pkthdr.flowid = flowid;
-			m->m_flags |= M_FLOWID;
+			M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE);
 		}
 		cpu_to_use = sctp_cpuarry[flowid % mp_ncpus];
 		sctp_queue_to_mcore(m, off, cpu_to_use);
+#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020  
+		return (IPPROTO_DONE);
+#else
 		return;
+#endif
 	}
 #endif
 	sctp_input_with_port(m, off, 0);
+#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020  
+	return (IPPROTO_DONE);
+#endif
 }
 #endif
 #endif
--- a/netwerk/sctp/src/netinet/sctp_input.h
+++ b/netwerk/sctp/src/netinet/sctp_input.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.h 240198 2012-09-07 13:36:42Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.h 273168 2014-10-16 15:36:04Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_INPUT_H_
 #define _NETINET_SCTP_INPUT_H_
 
 #if defined(_KERNEL) || defined(__Userspace__)
 void
 sctp_common_input_processing(struct mbuf **, int, int, int,
@@ -47,17 +47,17 @@ sctp_common_input_processing(struct mbuf
                              uint8_t,
 #endif
                              uint8_t,
 #if defined(__FreeBSD__)
                              uint8_t, uint32_t,
 #endif
                              uint32_t, uint16_t);
 
-struct sctp_stream_reset_out_request *
+struct sctp_stream_reset_request *
 sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq,
     struct sctp_tmit_chunk **bchk);
 
 void sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries,
     uint16_t *list);
 
 
 int sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked);
--- a/netwerk/sctp/src/netinet/sctp_os_userspace.h
+++ b/netwerk/sctp/src/netinet/sctp_os_userspace.h
@@ -98,17 +98,16 @@ typedef HANDLE userland_thread_t;
 #define u_int16_t  unsigned __int16
 #define u_int8_t   unsigned __int8
 #define u_char     unsigned char
 #define n_short    unsigned __int16
 #define u_short    unsigned __int16
 #define n_time     unsigned __int32
 #define sa_family_t unsigned __int8
 #define ssize_t    __int64
-#define IFNAMSIZ   64
 #define __func__	__FUNCTION__
 
 #ifndef EWOULDBLOCK
 #define EWOULDBLOCK             WSAEWOULDBLOCK
 #endif
 #ifndef EINPROGRESS
 #define EINPROGRESS             WSAEINPROGRESS
 #endif
@@ -215,22 +214,20 @@ typedef HANDLE userland_thread_t;
 #define EREMOTE                 WSAEREMOTE
 #endif
 
 typedef char* caddr_t;
 
 #define bzero(buf, len) memset(buf, 0, len)
 #define bcopy(srcKey, dstKey, len) memcpy(dstKey, srcKey, len)
 #if _MSC_VER < 1900
-#define snprintf(data, size, format, name) _snprintf_s(data, size, _TRUNCATE, format, name)
+#define snprintf(data, size, format, ...) _snprintf_s(data, size, _TRUNCATE, format, __VA_ARGS__)
 #endif
 #define inline __inline
 #define __inline__ __inline
-#define random() rand()
-#define srandom(s) srand(s)
 #define	MSG_EOR		0x8		/* data completes record */
 #define	MSG_DONTWAIT	0x80		/* this message should be nonblocking */
 
 #ifdef CMSG_DATA
 #undef CMSG_DATA
 #endif
 /*
  * The following definitions should apply iff WINVER < 0x0600
@@ -262,16 +259,42 @@ typedef char* caddr_t;
 #define SCTP_GET_IFN_VOID_FROM_ROUTE(ro) \
 	((ro)->ro_rt != NULL ? (ro)->ro_rt->rt_ifp : NULL)
 #define SCTP_ROUTE_HAS_VALID_IFN(ro) \
 	((ro)->ro_rt && (ro)->ro_rt->rt_ifp)
 /******************************************/
 
 #define SCTP_GET_IF_INDEX_FROM_ROUTE(ro) 1 /* compiles...  TODO use routing socket to determine */
 
+#define BIG_ENDIAN 1
+#define LITTLE_ENDIAN 0
+#ifdef WORDS_BIGENDIAN
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+#else /* !defined(Userspace_os_Windows) */
+#include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
+#include <sys/socket.h>
+#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_NaCl)
+#include <pthread.h>
+#endif
+typedef pthread_mutex_t userland_mutex_t;
+typedef pthread_cond_t userland_cond_t;
+typedef pthread_t userland_thread_t;
+#endif
+
+#if defined(__Userspace_os_Windows) || defined(__Userspace_os_NaCl)
+
+#define IFNAMSIZ 64
+
+#define random() rand()
+#define srandom(s) srand(s)
+
 #define timeradd(tvp, uvp, vvp)   \
 	do {                          \
 	    (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;  \
 		(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec;  \
 		if ((vvp)->tv_usec >= 1000000) {                   \
 		    (vvp)->tv_sec++;                        \
 			(vvp)->tv_usec -= 1000000;             \
 		}                         \
@@ -282,40 +305,67 @@ typedef char* caddr_t;
 	    (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;  \
 		(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;  \
 		if ((vvp)->tv_usec < 0) {                   \
 		    (vvp)->tv_sec--;                        \
 			(vvp)->tv_usec += 1000000;             \
 		}                       \
 	} while (0)
 
-#define BIG_ENDIAN 1
-#define LITTLE_ENDIAN 0
-#ifdef WORDS_BIGENDIAN
-#define BYTE_ORDER BIG_ENDIAN
-#else
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
+/*#include <packon.h>
+#pragma pack(push, 1)*/
+struct ip {
+	u_char    ip_hl:4, ip_v:4;
+	u_char    ip_tos;
+	u_short   ip_len;
+	u_short   ip_id;
+	u_short   ip_off;
+#define IP_RP 0x8000
+#define IP_DF 0x4000
+#define IP_MF 0x2000
+#define IP_OFFMASK 0x1fff
+	u_char    ip_ttl;
+	u_char    ip_p;
+	u_short   ip_sum;
+    struct in_addr ip_src, ip_dst;
+};
+
+struct ifaddrs {
+	struct ifaddrs  *ifa_next;
+	char		*ifa_name;
+	unsigned int		 ifa_flags;
+	struct sockaddr	*ifa_addr;
+	struct sockaddr	*ifa_netmask;
+	struct sockaddr	*ifa_dstaddr;
+	void		*ifa_data;
+};
+
+struct udphdr {
+	uint16_t uh_sport;
+	uint16_t uh_dport;
+	uint16_t uh_ulen;
+	uint16_t uh_sum;
+};
 
 struct iovec {
-	ULONG len;
-	CHAR FAR *buf;
+	unsigned long len;
+	char *buf;
 };
 
 #define iov_base buf
 #define iov_len	len
 
 struct ifa_msghdr {
-	unsigned __int16 ifam_msglen;
+	uint16_t         ifam_msglen;
 	unsigned char    ifam_version;
 	unsigned char    ifam_type;
-	__int32          ifam_addrs;
-	__int32          ifam_flags;
-	unsigned __int16 ifam_index;
-	__int32          ifam_metric;
+	uint32_t         ifam_addrs;
+	uint32_t         ifam_flags;
+	uint16_t         ifam_index;
+	uint32_t         ifam_metric;
 };
 
 struct ifdevmtu {
 	int ifdm_current;
 	int ifdm_min;
 	int ifdm_max;
 };
 
@@ -338,17 +388,17 @@ struct ifreq {
 		int ifru_metric;
 		int ifru_mtu;
 		int ifru_phys;
 		int ifru_media;
 		int    ifru_intval;
 		char*  ifru_data;
 		struct ifdevmtu ifru_devmtu;
 		struct ifkpi  ifru_kpi;
-		unsigned __int32 ifru_wake_flags;
+		uint32_t ifru_wake_flags;
 	} ifr_ifru;
 #define ifr_addr        ifr_ifru.ifru_addr
 #define ifr_dstaddr     ifr_ifru.ifru_dstaddr
 #define ifr_broadaddr   ifr_ifru.ifru_broadaddr
 #define ifr_flags       ifr_ifru.ifru_flags[0]
 #define ifr_prevflags   ifr_ifru.ifru_flags[1]
 #define ifr_metric      ifr_ifru.ifru_metric
 #define ifr_mtu         ifr_ifru.ifru_mtu
@@ -356,65 +406,23 @@ struct ifreq {
 #define ifr_media       ifr_ifru.ifru_media
 #define ifr_data        ifr_ifru.ifru_data
 #define ifr_devmtu      ifr_ifru.ifru_devmtu
 #define ifr_intval      ifr_ifru.ifru_intval
 #define ifr_kpi         ifr_ifru.ifru_kpi
 #define ifr_wake_flags  ifr_ifru.ifru_wake_flags
 };
 
-/*#include <packon.h>
-#pragma pack(push, 1)*/
-struct ip {
-	u_char    ip_hl:4, ip_v:4;
-	u_char    ip_tos;
-	u_short   ip_len;
-	u_short   ip_id;
-	u_short   ip_off;
-#define IP_RP 0x8000
-#define IP_DF 0x4000
-#define IP_MF 0x2000
-#define IP_OFFMASK 0x1fff
-	u_char    ip_ttl;
-	u_char    ip_p;
-	u_short   ip_sum;
-    struct in_addr ip_src, ip_dst;
-};
+#endif
 
-struct ifaddrs {
-	struct ifaddrs  *ifa_next;
-	char		*ifa_name;
-	unsigned int		 ifa_flags;
-	struct sockaddr	*ifa_addr;
-	struct sockaddr	*ifa_netmask;
-	struct sockaddr	*ifa_dstaddr;
-	void		*ifa_data;
-};
-
-struct udphdr {
-	unsigned __int16 uh_sport;
-	unsigned __int16 uh_dport;
-	unsigned __int16 uh_ulen;
-	unsigned __int16 uh_sum;
-};
-
+#if defined(__Userspace_os_Windows)
 int Win_getifaddrs(struct ifaddrs**);
 #define getifaddrs(interfaces)  (int)Win_getifaddrs(interfaces)
 int win_if_nametoindex(const char *);
 #define if_nametoindex(x) win_if_nametoindex(x)
-
-#else /* !defined(Userspace_os_Windows) */
-#include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
-#include <sys/socket.h>
-#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID)
-#include <pthread.h>
-#endif
-typedef pthread_mutex_t userland_mutex_t;
-typedef pthread_cond_t userland_cond_t;
-typedef pthread_t userland_thread_t;
 #endif
 
 #define mtx_lock(arg1)
 #define mtx_unlock(arg1)
 #define mtx_assert(arg1,arg2)
 #define MA_OWNED 7 /* sys/mutex.h typically on FreeBSD */
 #if !defined(__Userspace_os_FreeBSD)
 struct mtx {int dummy;};
@@ -466,32 +474,34 @@ struct sx {int dummy;};
 #if defined(__Userspace_os_FreeBSD)
 #include <net/if_types.h>
 /* #include <net/if_var.h> was a 0 byte file.  causes struct mtx redefinition */
 #endif
 /* OOTB only - dummy route used at the moment. should we port route to
  *  userspace as well? */
 /* on FreeBSD, this results in a redefintion of struct route */
 /* #include <net/route.h> */
-#if !defined(__Userspace_os_Windows)
+#if !defined(__Userspace_os_Windows) && !defined(__Userspace_os_NaCl)
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
+#endif
+#if defined(HAVE_NETINET_IP_ICMP_H)
 #include <netinet/ip_icmp.h>
 #else
 #include <user_ip_icmp.h>
 #endif
 /* #include <netinet/in_pcb.h> ported to userspace */
 #include <user_inpcb.h>
 
 /* for getifaddrs */
 #include <sys/types.h>
 #if !defined(__Userspace_os_Windows)
-#if !defined(ANDROID) && (defined(INET) || defined(INET6))
+#if defined(INET) || defined(INET6)
 #include <ifaddrs.h>
 #endif
 
 /* for ioctl */
 #include <sys/ioctl.h>
 
 /* for close, etc. */
 #include <unistd.h>
@@ -1088,17 +1098,17 @@ extern void sctp_userspace_ip6_output(in
 
 struct mbuf *
 sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int allonebuf, int type);
 
 
 /* with the current included files, this is defined in Linux but
  *  in FreeBSD, it is behind a _KERNEL in sys/socket.h ...
  */
-#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD)
+#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_NaCl)
 /* stolen from /usr/include/sys/socket.h */
 #define CMSG_ALIGN(n)   _ALIGN(n)
 #elif defined(__Userspace_os_NetBSD)
 #define CMSG_ALIGN(n)   (((n) + __ALIGNBYTES) & ~__ALIGNBYTES)
 #elif defined(__Userspace_os_Darwin)
 #if !defined(__DARWIN_ALIGNBYTES)
 #define	__DARWIN_ALIGNBYTES	(sizeof(__darwin_size_t) - 1)
 #endif
@@ -1146,9 +1156,17 @@ sctp_get_mbuf_for_msg(unsigned int space
               (var) && ((tvar) = LIST_NEXT((var), field), 1);  \
               (var) = (tvar))
 #endif
 #endif
 #if defined(__Userspace_os_DragonFly)
 #define TAILQ_FOREACH_SAFE TAILQ_FOREACH_MUTABLE
 #define LIST_FOREACH_SAFE LIST_FOREACH_MUTABLE
 #endif
+
+#if defined(__Userspace_os_NaCl)
+#define	timercmp(tvp, uvp, cmp)						\
+	(((tvp)->tv_sec == (uvp)->tv_sec) ?				\
+	    ((tvp)->tv_usec cmp (uvp)->tv_usec) :			\
+	    ((tvp)->tv_sec cmp (uvp)->tv_sec))
 #endif
+
+#endif
--- a/netwerk/sctp/src/netinet/sctp_output.c
+++ b/netwerk/sctp/src/netinet/sctp_output.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 262252 2014-02-20 20:14:43Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 277350 2015-01-18 22:00:39Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #ifdef __FreeBSD__
 #include <sys/proc.h>
 #endif
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
@@ -52,19 +52,21 @@
 #include <netinet/sctp_asconf.h>
 #include <netinet/sctp_indata.h>
 #include <netinet/sctp_bsd_addr.h>
 #include <netinet/sctp_input.h>
 #include <netinet/sctp_crc32.h>
 #if defined(__Userspace_os_Linux)
 #define __FAVOR_BSD    /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */
 #endif
+#if defined(INET) || defined(INET6)
 #if !defined(__Userspace_os_Windows)
 #include <netinet/udp.h>
 #endif
+#endif
 #if defined(__APPLE__)
 #include <netinet/in.h>
 #endif
 #if defined(__FreeBSD__)
 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
 #include <netinet/udp_var.h>
 #endif
 #include <machine/in_cksum.h>
@@ -1901,17 +1903,17 @@ sctp_is_address_in_scope(struct sctp_ifa
 		return (0);
 	}
 	switch (ifa->address.sa.sa_family) {
 #ifdef INET
 	case AF_INET:
 		if (scope->ipv4_addr_legal) {
 			struct sockaddr_in *sin;
 
-			sin = (struct sockaddr_in *)&ifa->address.sin;
+			sin = &ifa->address.sin;
 			if (sin->sin_addr.s_addr == 0) {
 				/* not in scope , unspecified */
 				return (0);
 			}
 			if ((scope->ipv4_local_scope == 0) &&
 			    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
 				/* private address not in scope */
 				return (0);
@@ -1933,17 +1935,17 @@ sctp_is_address_in_scope(struct sctp_ifa
 			if (do_update) {
 				sctp_gather_internal_ifa_flags(ifa);
 			}
 #endif
 			if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
 				return (0);
 			}
 			/* ok to use deprecated addresses? */
-			sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
+			sin6 = &ifa->address.sin6;
 			if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 				/* skip unspecifed addresses */
 				return (0);
 			}
 			if (		/* (local_scope == 0) && */
 			    (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
 				return (0);
 			}
@@ -2014,32 +2016,32 @@ sctp_add_addr_to_mbuf(struct mbuf *m, st
 	/* now add the parameter */
 	switch (ifa->address.sa.sa_family) {
 #ifdef INET
 	case AF_INET:
 	{
 		struct sctp_ipv4addr_param *ipv4p;
 		struct sockaddr_in *sin;
 
-		sin = (struct sockaddr_in *)&ifa->address.sin;
+		sin = &ifa->address.sin;
 		ipv4p = (struct sctp_ipv4addr_param *)parmh;
 		parmh->param_type = htons(SCTP_IPV4_ADDRESS);
 		parmh->param_length = htons(plen);
 		ipv4p->addr = sin->sin_addr.s_addr;
 		SCTP_BUF_LEN(mret) += plen;
 		break;
 	}
 #endif
 #ifdef INET6
 	case AF_INET6:
 	{
 		struct sctp_ipv6addr_param *ipv6p;
 		struct sockaddr_in6 *sin6;
 
-		sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
+		sin6 = &ifa->address.sin6;
 		ipv6p = (struct sctp_ipv6addr_param *)parmh;
 		parmh->param_type = htons(SCTP_IPV6_ADDRESS);
 		parmh->param_length = htons(plen);
 		memcpy(ipv6p->addr, &sin6->sin6_addr,
 		    sizeof(ipv6p->addr));
 #if defined(SCTP_EMBEDDED_V6_SCOPE)
 		/* clear embedded scope in the address */
 		in6_clearscope((struct in6_addr *)ipv6p->addr);
@@ -2091,16 +2093,32 @@ sctp_add_addresses_to_i_ia(struct sctp_i
 			    SCTP_IFN_IS_IFT_LOOP(sctp_ifnp)) {
 				/*
 				 * Skip loopback devices if loopback_scope
 				 * not set
 				 */
 				continue;
 			}
 			LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+				if ((sctp_ifap->address.sa.sa_family == AF_INET) &&
+				    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+				                      &sctp_ifap->address.sin.sin_addr) != 0)) {
+					continue;
+				}
+#endif
+#ifdef INET6
+				if ((sctp_ifap->address.sa.sa_family == AF_INET6) &&
+				    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+				                      &sctp_ifap->address.sin6.sin6_addr) != 0)) {
+					continue;
+				}
+#endif
+#endif
 				if (sctp_is_addr_restricted(stcb, sctp_ifap)) {
 					continue;
 				}
 #if defined(__Userspace__)
 				if (sctp_ifap->address.sa.sa_family == AF_CONN) {
 					continue;
 				}
 #endif
@@ -2125,16 +2143,32 @@ sctp_add_addresses_to_i_ia(struct sctp_i
 				    SCTP_IFN_IS_IFT_LOOP(sctp_ifnp)) {
 					/*
 					 * Skip loopback devices if
 					 * loopback_scope not set
 					 */
 					continue;
 				}
 				LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+					if ((sctp_ifap->address.sa.sa_family == AF_INET) &&
+					    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+					                      &sctp_ifap->address.sin.sin_addr) != 0)) {
+						continue;
+					}
+#endif
+#ifdef INET6
+					if ((sctp_ifap->address.sa.sa_family == AF_INET6) &&
+					    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+					                      &sctp_ifap->address.sin6.sin6_addr) != 0)) {
+						continue;
+					}
+#endif
+#endif
 					if (sctp_is_addr_restricted(stcb, sctp_ifap)) {
 						continue;
 					}
 #if defined(__Userspace__)
 					if (sctp_ifap->address.sa.sa_family == AF_CONN) {
 						continue;
 					}
 #endif
@@ -2171,17 +2205,17 @@ sctp_add_addresses_to_i_ia(struct sctp_i
 
 		cnt = cnt_inits_to;
 		/* First, how many ? */
 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
 			if (laddr->ifa == NULL) {
 				continue;
 			}
 			if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
-                                /* Address being deleted by the system, dont
+				/* Address being deleted by the system, dont
 				 * list.
 				 */
 				continue;
 			if (laddr->action == SCTP_DEL_IP_ADDRESS) {
 				/* Address being deleted on this ep
 				 * don't list.
 				 */
 				continue;
@@ -2497,16 +2531,32 @@ sctp_choose_boundspecific_inp(struct sct
 	/*
 	 * first question, is the ifn we will emit on in our list, if so, we
 	 * want such an address. Note that we first looked for a
 	 * preferred address.
 	 */
 	if (sctp_ifn) {
 		/* is a preferred one on the interface we route out? */
 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+			if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
+			    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin.sin_addr) != 0)) {
+				continue;
+			}
+#endif
+#ifdef INET6
+			if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
+			    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin6.sin6_addr) != 0)) {
+				continue;
+			}
+#endif
+#endif
 			if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
 			    (non_asoc_addr_ok == 0))
 				continue;
 			sifa = sctp_is_ifa_addr_preferred(sctp_ifa,
 							  dest_is_loop,
 							  dest_is_priv, fam);
 			if (sifa == NULL)
 				continue;
@@ -2616,23 +2666,39 @@ sctp_choose_boundspecific_stcb(struct sc
 	if (vrf == NULL)
 		return (NULL);
 
 	ifn = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
 	ifn_index = SCTP_GET_IF_INDEX_FROM_ROUTE(ro);
 	sctp_ifn = sctp_find_ifn( ifn, ifn_index);
 
 	/*
- 	 * first question, is the ifn we will emit on in our list?  If so,
+	 * first question, is the ifn we will emit on in our list?  If so,
 	 * we want that one. First we look for a preferred. Second, we go
 	 * for an acceptable.
 	 */
 	if (sctp_ifn) {
 		/* first try for a preferred address on the ep */
 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+			if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
+			    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin.sin_addr) != 0)) {
+				continue;
+			}
+#endif
+#ifdef INET6
+			if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
+			    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin6.sin6_addr) != 0)) {
+				continue;
+			}
+#endif
+#endif
 			if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
 				continue;
 			if (sctp_is_addr_in_ep(inp, sctp_ifa)) {
 				sifa = sctp_is_ifa_addr_preferred(sctp_ifa, dest_is_loop, dest_is_priv, fam);
 				if (sifa == NULL)
 					continue;
 				if (((non_asoc_addr_ok == 0) &&
 				     (sctp_is_addr_restricted(stcb, sifa))) ||
@@ -2643,16 +2709,32 @@ sctp_choose_boundspecific_stcb(struct sc
 					continue;
 				}
 				atomic_add_int(&sifa->refcount, 1);
 				return (sifa);
 			}
 		}
 		/* next try for an acceptable address on the ep */
 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+			if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
+			    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin.sin_addr) != 0)) {
+				continue;
+			}
+#endif
+#ifdef INET6
+			if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
+			    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin6.sin6_addr) != 0)) {
+				continue;
+			}
+#endif
+#endif
 			if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
 				continue;
 			if (sctp_is_addr_in_ep(inp, sctp_ifa)) {
 				sifa= sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv,fam);
 				if (sifa == NULL)
 					continue;
 				if (((non_asoc_addr_ok == 0) &&
 				     (sctp_is_addr_restricted(stcb, sifa))) ||
@@ -2748,16 +2830,21 @@ sctp_choose_boundspecific_stcb(struct sc
 		stcb->asoc.last_used_address = NULL;
 		goto sctp_from_the_top2;
 	}
 	return (NULL);
 }
 
 static struct sctp_ifa *
 sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn,
+#if defined(__FreeBSD__)
+                                                 struct sctp_inpcb *inp,
+#else
+                                                 struct sctp_inpcb *inp SCTP_UNUSED,
+#endif
 						 struct sctp_tcb *stcb,
 						 int non_asoc_addr_ok,
 						 uint8_t dest_is_loop,
 						 uint8_t dest_is_priv,
 						 int addr_wanted,
 						 sa_family_t fam,
 						 sctp_route_t *ro
 						 )
@@ -2774,16 +2861,32 @@ sctp_select_nth_preferred_addr_from_ifn_
 		(void)sa6_recoverscope(&sin6);
 #else
 		(void)in6_recoverscope(&sin6, &sin6.sin6_addr, NULL);
 #endif  /* SCTP_KAME */
 	}
 #endif  /* SCTP_EMBEDDED_V6_SCOPE */
 #endif	/* INET6 */
 	LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+		if ((ifa->address.sa.sa_family == AF_INET) &&
+		    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+		                      &ifa->address.sin.sin_addr) != 0)) {
+			continue;
+		}
+#endif
+#ifdef INET6
+		if ((ifa->address.sa.sa_family == AF_INET6) &&
+		    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+		                      &ifa->address.sin6.sin6_addr) != 0)) {
+			continue;
+		}
+#endif
+#endif
 		if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
 		    (non_asoc_addr_ok == 0))
 			continue;
 		sifa = sctp_is_ifa_addr_preferred(ifa, dest_is_loop,
 						  dest_is_priv, fam);
 		if (sifa == NULL)
 			continue;
 #ifdef INET6
@@ -2861,26 +2964,48 @@ sctp_select_nth_preferred_addr_from_ifn_
 		num_eligible_addr++;
 	}
 	return (NULL);
 }
 
 
 static int
 sctp_count_num_preferred_boundall(struct sctp_ifn *ifn,
+#if defined(__FreeBSD__)
+                                  struct sctp_inpcb *inp,
+#else
+                                  struct sctp_inpcb *inp SCTP_UNUSED,
+#endif
 				  struct sctp_tcb *stcb,
 				  int non_asoc_addr_ok,
 				  uint8_t dest_is_loop,
 				  uint8_t dest_is_priv,
 				  sa_family_t fam)
 {
 	struct sctp_ifa *ifa, *sifa;
 	int num_eligible_addr = 0;
 
 	LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+		if ((ifa->address.sa.sa_family == AF_INET) &&
+		    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+		                      &ifa->address.sin.sin_addr) != 0)) {
+			continue;
+		}
+#endif
+#ifdef INET6
+		if ((ifa->address.sa.sa_family == AF_INET6) &&
+		    (stcb != NULL) &&
+		    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+		                      &ifa->address.sin6.sin6_addr) != 0)) {
+			continue;
+		}
+#endif
+#endif
 		if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
 		    (non_asoc_addr_ok == 0)) {
 			continue;
 		}
 		sifa = sctp_is_ifa_addr_preferred(ifa, dest_is_loop,
 						  dest_is_priv, fam);
 		if (sifa == NULL) {
 			continue;
@@ -2902,17 +3027,18 @@ sctp_count_num_preferred_boundall(struct
 			}
 		}
 		num_eligible_addr++;
 	}
 	return (num_eligible_addr);
 }
 
 static struct sctp_ifa *
-sctp_choose_boundall(struct sctp_tcb *stcb,
+sctp_choose_boundall(struct sctp_inpcb *inp,
+                     struct sctp_tcb *stcb,
 		     struct sctp_nets *net,
 		     sctp_route_t *ro,
 		     uint32_t vrf_id,
 		     uint8_t dest_is_priv,
 		     uint8_t dest_is_loop,
 		     int non_asoc_addr_ok,
 		     sa_family_t fam)
 {
@@ -2955,17 +3081,17 @@ sctp_choose_boundall(struct sctp_tcb *st
 	}
 	SCTPDBG(SCTP_DEBUG_OUTPUT2,"ifn_index:%d name:%s is emit interface\n",
 		ifn_index, sctp_ifn->ifn_name);
 
 	if (net) {
 		cur_addr_num = net->indx_of_eligible_next_to_use;
 	}
 	num_preferred = sctp_count_num_preferred_boundall(sctp_ifn,
-							  stcb,
+							  inp, stcb,
 							  non_asoc_addr_ok,
 							  dest_is_loop,
 							  dest_is_priv, fam);
 	SCTPDBG(SCTP_DEBUG_OUTPUT2, "Found %d preferred source addresses for intf:%s\n",
 		num_preferred, sctp_ifn->ifn_name);
 	if (num_preferred == 0) {
 		/*
 		 * no eligible addresses, we must use some other interface
@@ -2982,17 +3108,17 @@ sctp_choose_boundall(struct sctp_tcb *st
 		cur_addr_num = 0;
 	}
 	/*
 	 * select the nth address from the list (where cur_addr_num is the
 	 * nth) and 0 is the first one, 1 is the second one etc...
 	 */
 	SCTPDBG(SCTP_DEBUG_OUTPUT2, "cur_addr_num:%d\n", cur_addr_num);
 
-	sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
+	sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop,
                                                                     dest_is_priv, cur_addr_num, fam, ro);
 
 	/* if sctp_ifa is NULL something changed??, fall to plan b. */
 	if (sctp_ifa) {
 		atomic_add_int(&sctp_ifa->refcount, 1);
 		if (net) {
 			/* save off where the next one we will want */
 			net->indx_of_eligible_next_to_use = cur_addr_num + 1;
@@ -3013,17 +3139,17 @@ sctp_choose_boundall(struct sctp_tcb *st
 			SCTPDBG(SCTP_DEBUG_OUTPUT2, "skip\n");
 			continue;
 		}
 		if ((sctp_ifn == looked_at) && looked_at) {
 			/* already looked at this guy */
 			SCTPDBG(SCTP_DEBUG_OUTPUT2, "already seen\n");
 			continue;
 		}
-		num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok,
+		num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok,
                                                                   dest_is_loop, dest_is_priv, fam);
 		SCTPDBG(SCTP_DEBUG_OUTPUT2,
 			"Found ifn:%p %d preferred source addresses\n",
 			ifn, num_preferred);
 		if (num_preferred == 0) {
 			/* None on this interface. */
 			SCTPDBG(SCTP_DEBUG_OUTPUT2, "No prefered -- skipping to next\n");
 			continue;
@@ -3035,17 +3161,17 @@ sctp_choose_boundall(struct sctp_tcb *st
 		/*
 		 * Ok we have num_eligible_addr set with how many we can
 		 * use, this may vary from call to call due to addresses
 		 * being deprecated etc..
 		 */
 		if (cur_addr_num >= num_preferred) {
 			cur_addr_num = 0;
 		}
-		sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
+		sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, inp, stcb, non_asoc_addr_ok, dest_is_loop,
                                                                         dest_is_priv, cur_addr_num, fam, ro);
 		if (sifa == NULL)
 			continue;
 		if (net) {
 			net->indx_of_eligible_next_to_use = cur_addr_num + 1;
 			SCTPDBG(SCTP_DEBUG_OUTPUT2, "we selected %d\n",
 				cur_addr_num);
 			SCTPDBG(SCTP_DEBUG_OUTPUT2, "Source:");
@@ -3063,16 +3189,34 @@ again_with_private_addresses_allowed:
 	sifa = NULL;
 	SCTPDBG(SCTP_DEBUG_OUTPUT2,"Trying Plan C: find acceptable on interface\n");
 	if (emit_ifn == NULL) {
 		SCTPDBG(SCTP_DEBUG_OUTPUT2,"Jump to Plan D - no emit_ifn\n");
 		goto plan_d;
 	}
 	LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) {
 		SCTPDBG(SCTP_DEBUG_OUTPUT2, "ifa:%p\n", (void *)sctp_ifa);
+#if defined(__FreeBSD__)
+#ifdef INET
+		if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
+		    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+		                      &sctp_ifa->address.sin.sin_addr) != 0)) {
+			SCTPDBG(SCTP_DEBUG_OUTPUT2,"Jailed\n");
+			continue;
+		}
+#endif
+#ifdef INET6
+		if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
+		    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+		                      &sctp_ifa->address.sin6.sin6_addr) != 0)) {
+			SCTPDBG(SCTP_DEBUG_OUTPUT2,"Jailed\n");
+			continue;
+		}
+#endif
+#endif
 		if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
 		    (non_asoc_addr_ok == 0)) {
 			SCTPDBG(SCTP_DEBUG_OUTPUT2,"Defer\n");
 			continue;
 		}
 		sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop,
 						   dest_is_priv, fam);
 		if (sifa == NULL) {
@@ -3113,16 +3257,32 @@ again_with_private_addresses_allowed:
 	 */
 	SCTPDBG(SCTP_DEBUG_OUTPUT2, "Trying Plan D looked_at is %p\n", (void *)looked_at);
 	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 		if (dest_is_loop == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 			/* wrong base scope */
 			continue;
 		}
 		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
+#if defined(__FreeBSD__)
+#ifdef INET
+			if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
+			    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin.sin_addr) != 0)) {
+				continue;
+			}
+#endif
+#ifdef INET6
+			if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
+			    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+			                      &sctp_ifa->address.sin6.sin6_addr) != 0)) {
+				continue;
+			}
+#endif
+#endif
 			if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
 			    (non_asoc_addr_ok == 0))
 				continue;
 			sifa = sctp_is_ifa_addr_acceptable(sctp_ifa,
 							   dest_is_loop,
 							   dest_is_priv, fam);
 			if (sifa == NULL)
 				continue;
@@ -3163,16 +3323,32 @@ out:
 			LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
 				if (dest_is_loop == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
 					/* wrong base scope */
 					continue;
 				}
 				LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
 					struct sctp_ifa *tmp_sifa;
 
+#if defined(__FreeBSD__)
+#ifdef INET
+					if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
+					    (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+					                      &sctp_ifa->address.sin.sin_addr) != 0)) {
+						continue;
+					}
+#endif
+#ifdef INET6
+					if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
+					    (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+					                      &sctp_ifa->address.sin6.sin6_addr) != 0)) {
+						continue;
+					}
+#endif
+#endif
 					if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
 					    (non_asoc_addr_ok == 0))
 						continue;
 					tmp_sifa = sctp_is_ifa_addr_acceptable(sctp_ifa,
 					                                       dest_is_loop,
 					                                       dest_is_priv, fam);
 					if (tmp_sifa == NULL) {
 						continue;
@@ -3296,17 +3472,22 @@ sctp_source_address_selection(struct sct
 		/*
 		 * Need a route to cache.
 		 */
 		SCTP_RTALLOC(ro, vrf_id);
 	}
 	if (ro->ro_rt == NULL) {
 		return (NULL);
 	}
+#if defined(__Userspace_os_Windows)
+	/* On Windows the sa_family is U_SHORT or ADDRESS_FAMILY */
+	fam = (sa_family_t)ro->ro_dst.sa_family;
+#else
 	fam = ro->ro_dst.sa_family;
+#endif
 	dest_is_priv = dest_is_loop = 0;
 	/* Setup our scopes for the destination */
 	switch (fam) {
 #ifdef INET
 	case AF_INET:
 		/* Scope based on outbound address */
 		if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
 			dest_is_loop = 1;
@@ -3347,17 +3528,17 @@ sctp_source_address_selection(struct sct
 	}
 	SCTPDBG(SCTP_DEBUG_OUTPUT2, "Select source addr for:");
 	SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&ro->ro_dst);
 	SCTP_IPI_ADDR_RLOCK();
 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
 		/*
 		 * Bound all case
 		 */
-		answer = sctp_choose_boundall(stcb, net, ro, vrf_id,
+		answer = sctp_choose_boundall(inp, stcb, net, ro, vrf_id,
 					      dest_is_priv, dest_is_loop,
 					      non_asoc_addr_ok, fam);
 		SCTP_IPI_ADDR_RUNLOCK();
 		return (answer);
 	}
 	/*
 	 * Subset bound case
 	 */
@@ -3526,16 +3707,19 @@ sctp_process_cmsgs_for_init(struct sctp_
 					stcb->asoc.pre_open_streams = initmsg.sinit_num_ostreams;
 				if (initmsg.sinit_max_instreams)
 					stcb->asoc.max_inbound_streams = initmsg.sinit_max_instreams;
 				if (initmsg.sinit_max_init_timeo)
 					stcb->asoc.initial_init_rto_max = initmsg.sinit_max_init_timeo;
 				if (stcb->asoc.streamoutcnt < stcb->asoc.pre_open_streams) {
 					struct sctp_stream_out *tmp_str;
 					unsigned int i;
+#if defined(SCTP_DETAILED_STR_STATS)
+					int j;
+#endif
 
 					/* Default is NOT correct */
 					SCTPDBG(SCTP_DEBUG_OUTPUT1, "Ok, default:%d pre_open:%d\n",
 						stcb->asoc.streamoutcnt, stcb->asoc.pre_open_streams);
 					SCTP_TCB_UNLOCK(stcb);
 					SCTP_MALLOC(tmp_str,
 					            struct sctp_stream_out *,
 					            (stcb->asoc.pre_open_streams * sizeof(struct sctp_stream_out)),
@@ -3547,16 +3731,25 @@ sctp_process_cmsgs_for_init(struct sctp_
 						stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt = stcb->asoc.pre_open_streams;
 					} else {
 						stcb->asoc.pre_open_streams = stcb->asoc.streamoutcnt;
 					}
 					for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
 						TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
 						stcb->asoc.strmout[i].chunks_on_queues = 0;
 						stcb->asoc.strmout[i].next_sequence_send = 0;
+#if defined(SCTP_DETAILED_STR_STATS)
+						for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
+							stcb->asoc.strmout[i].abandoned_sent[j] = 0;
+							stcb->asoc.strmout[i].abandoned_unsent[j] = 0;
+						}
+#else
+						stcb->asoc.strmout[i].abandoned_sent[0] = 0;
+						stcb->asoc.strmout[i].abandoned_unsent[0] = 0;
+#endif
 						stcb->asoc.strmout[i].stream_no = i;
 						stcb->asoc.strmout[i].last_msg_incomplete = 0;
 						stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
 					}
 				}
 				break;
 #ifdef INET
 			case SCTP_DSTADDRV4:
@@ -3750,41 +3943,29 @@ sctp_add_cookie(struct mbuf *init, int i
 	}
 	copy_init = SCTP_M_COPYM(init, init_offset, M_COPYALL, M_NOWAIT);
 	if (copy_init == NULL) {
 		sctp_m_freem(mret);
 		return (NULL);
 	}
 #ifdef SCTP_MBUF_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		struct mbuf *mat;
-
-		for (mat = copy_init; mat; mat = SCTP_BUF_NEXT(mat)) {
-			if (SCTP_BUF_IS_EXTENDED(mat)) {
-				sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-			}
-		}
+		sctp_log_mbc(copy_init, SCTP_MBUF_ICOPY);
 	}
 #endif
 	copy_initack = SCTP_M_COPYM(initack, initack_offset, M_COPYALL,
 	    M_NOWAIT);
 	if (copy_initack == NULL) {
 		sctp_m_freem(mret);
 		sctp_m_freem(copy_init);
 		return (NULL);
 	}
 #ifdef SCTP_MBUF_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		struct mbuf *mat;
-
-		for (mat = copy_initack; mat; mat = SCTP_BUF_NEXT(mat)) {
-			if (SCTP_BUF_IS_EXTENDED(mat)) {
-				sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-			}
-		}
+		sctp_log_mbc(copy_initack, SCTP_MBUF_ICOPY);
 	}
 #endif
 	/* easy side we just drop it on the end */
 	ph = mtod(mret, struct sctp_paramhdr *);
 	SCTP_BUF_LEN(mret) = sizeof(struct sctp_state_cookie) +
 	    sizeof(struct sctp_paramhdr);
 	stc = (struct sctp_state_cookie *)((caddr_t)ph +
 	    sizeof(struct sctp_paramhdr));
@@ -3832,17 +4013,17 @@ sctp_add_cookie(struct mbuf *init, int i
 	ph->param_length = htons(cookie_sz);
 	return (mret);
 }
 
 
 static uint8_t
 sctp_get_ect(struct sctp_tcb *stcb)
 {
-	if ((stcb != NULL) && (stcb->asoc.ecn_allowed == 1)) {
+	if ((stcb != NULL) && (stcb->asoc.ecn_supported == 1)) {
 		return (SCTP_ECT0_BIT);
 	} else {
 		return (0);
 	}
 }
 
 #if defined(INET) || defined(INET6)
 static void
@@ -3903,17 +4084,17 @@ sctp_lowlevel_chunk_output(struct sctp_i
     int ecn_ok,
     int out_of_asoc_ok,
     uint16_t src_port,
     uint16_t dest_port,
     uint32_t v_tag,
     uint16_t port,
     union sctp_sockstore *over_addr,
 #if defined(__FreeBSD__)
-    uint8_t use_mflowid, uint32_t mflowid,
+    uint8_t mflowtype, uint32_t mflowid,
 #endif
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     int so_locked SCTP_UNUSED
 #else
     int so_locked
 #endif
     )
 /* nofragment_flag to tell if IP_DF should be set (IPv4 only) */
@@ -4005,29 +4186,22 @@ sctp_lowlevel_chunk_output(struct sctp_i
 			return (ENOMEM);
 		}
 		SCTP_ALIGN_TO_END(newm, len);
 		SCTP_BUF_LEN(newm) = len;
 		SCTP_BUF_NEXT(newm) = m;
 		m = newm;
 #if defined(__FreeBSD__)
 		if (net != NULL) {
-#ifdef INVARIANTS
-			if (net->flowidset == 0) {
-				panic("Flow ID not set");
-			}
-#endif
 			m->m_pkthdr.flowid = net->flowid;
-			m->m_flags |= M_FLOWID;
-		} else {
-			if (use_mflowid != 0) {
-				m->m_pkthdr.flowid = mflowid;
-				m->m_flags |= M_FLOWID;
-			}
-		}
+			M_HASHTYPE_SET(m, net->flowtype);
+		} else {
+			m->m_pkthdr.flowid = mflowid;
+			M_HASHTYPE_SET(m, mflowtype);
+ 		}
 #endif
 		packet_length = sctp_calculate_len(m);
 		ip = mtod(m, struct ip *);
 		ip->ip_v = IPVERSION;
 		ip->ip_hl = (sizeof(struct ip) >> 2);
 		if (tos_value == 0) {
 			/*
 			 * This means especially, that it is not set at the
@@ -4237,17 +4411,17 @@ sctp_lowlevel_chunk_output(struct sctp_i
 			SCTP_ENABLE_UDP_CSUM(o_pak);
 #endif
 		} else {
 #if defined(SCTP_WITH_NO_CSUM)
 			SCTP_STAT_INCR(sctps_sendnocrc);
 #else
 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
 			m->m_pkthdr.csum_flags = CSUM_SCTP;
-			m->m_pkthdr.csum_data = 0;
+			m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum);
 			SCTP_STAT_INCR(sctps_sendhwcrc);
 #else
 			if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
 			      (stcb) && (stcb->asoc.scope.loopback_scope))) {
 				sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip));
 				SCTP_STAT_INCR(sctps_sendswcrc);
 			} else {
 				SCTP_STAT_INCR(sctps_sendnocrc);
@@ -4366,29 +4540,22 @@ sctp_lowlevel_chunk_output(struct sctp_i
 			return (ENOMEM);
 		}
 		SCTP_ALIGN_TO_END(newm, len);
 		SCTP_BUF_LEN(newm) = len;
 		SCTP_BUF_NEXT(newm) = m;
 		m = newm;
 #if defined(__FreeBSD__)
 		if (net != NULL) {
-#ifdef INVARIANTS
-			if (net->flowidset == 0) {
-				panic("Flow ID not set");
-			}
-#endif
 			m->m_pkthdr.flowid = net->flowid;
-			m->m_flags |= M_FLOWID;
-		} else {
-			if (use_mflowid != 0) {
-				m->m_pkthdr.flowid = mflowid;
-				m->m_flags |= M_FLOWID;
-			}
-		}
+			M_HASHTYPE_SET(m, net->flowtype);
+		} else {
+			m->m_pkthdr.flowid = mflowid;
+			M_HASHTYPE_SET(m, mflowtype);
+ 		}
 #endif
 		packet_length = sctp_calculate_len(m);
 
 		ip6h = mtod(m, struct ip6_hdr *);
 		/* protect *sin6 from overwrite */
 		sin6 = (struct sockaddr_in6 *)to;
 		tmp = *sin6;
 		sin6 = &tmp;
@@ -4692,17 +4859,17 @@ sctp_lowlevel_chunk_output(struct sctp_i
 			sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr));
 			SCTP_STAT_INCR(sctps_sendswcrc);
 #else
 #if __FreeBSD_version > 901000
 			m->m_pkthdr.csum_flags = CSUM_SCTP_IPV6;
 #else
 			m->m_pkthdr.csum_flags = CSUM_SCTP;
 #endif
-			m->m_pkthdr.csum_data = 0;
+			m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum);
 			SCTP_STAT_INCR(sctps_sendhwcrc);
 #endif
 #else
 			if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
 			      (stcb) && (stcb->asoc.scope.loopback_scope))) {
 				sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr));
 				SCTP_STAT_INCR(sctps_sendswcrc);
 			} else {
@@ -4861,17 +5028,17 @@ sctp_lowlevel_chunk_output(struct sctp_i
 
 void
 sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif
     )
 {
-	struct mbuf *m;
+	struct mbuf *m, *m_last;
 	struct sctp_nets *net;
 	struct sctp_init_chunk *init;
 	struct sctp_supported_addr_param *sup_addr;
 	struct sctp_adaptation_layer_indication *ali;
 	struct sctp_supported_chunk_types_param *pr_supported;
 	struct sctp_paramhdr *ph;
 	int cnt_inits_to = 0;
 	int ret;
@@ -4921,41 +5088,180 @@ sctp_send_initiate(struct sctp_inpcb *in
 	m = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_NOWAIT, 1, MT_DATA);
 	if (m == NULL) {
 		/* No memory, INIT timer will re-attempt. */
 		SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - mbuf?\n");
 		return;
 	}
 	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 */
 	init->ch.chunk_type = SCTP_INITIATION;
 	init->ch.chunk_flags = 0;
 	/* fill in later from mbuf we build */
 	init->ch.chunk_length = 0;
 	/* place in my tag */
 	init->init.initiate_tag = htonl(stcb->asoc.my_vtag);
 	/* set up some of the credits. */
 	init->init.a_rwnd = htonl(max(inp->sctp_socket?SCTP_SB_LIMIT_RCV(inp->sctp_socket):0,
 	                              SCTP_MINIMAL_RWND));
 	init->init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
 	init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams);
 	init->init.initial_tsn = htonl(stcb->asoc.init_seq_number);
 
+	/* Adaptation layer indication parameter */
+	if (inp->sctp_ep.adaptation_layer_indicator_provided) {
+		parameter_len = (uint16_t)sizeof(struct sctp_adaptation_layer_indication);
+		ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t) + chunk_len);
+		ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
+		ali->ph.param_length = htons(parameter_len);
+		ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator);
+		chunk_len += parameter_len;
+	}
+
+	/* ECN parameter */
+	if (stcb->asoc.ecn_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_ECN_CAPABLE);
+		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);
+		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len);
+		ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
+		ph->param_length = htons(parameter_len);
+		chunk_len += parameter_len;
+	}
+
+	/* 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);
+	if (stcb->asoc.prsctp_supported == 1) {
+		pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
+	}
+	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 (stcb->asoc.nrsack_supported == 1) {
+		pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
+	}
+	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 (stcb->asoc.auth_supported) {
+		/* attach RANDOM parameter, if available */
+		if (stcb->asoc.authinfo.random != NULL) {
+			struct sctp_auth_random *randp;
+
+			if (padding_len > 0) {
+				memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+				chunk_len += padding_len;
+				padding_len = 0;
+			}
+			randp = (struct sctp_auth_random *)(mtod(m, caddr_t) + chunk_len);
+			parameter_len = (uint16_t)sizeof(struct sctp_auth_random) + stcb->asoc.authinfo.random_len;
+			/* random key already contains the header */
+			memcpy(randp, stcb->asoc.authinfo.random->key, parameter_len);
+			padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+			chunk_len += parameter_len;
+		}
+		/* add HMAC_ALGO parameter */
+		if (stcb->asoc.local_hmacs != NULL) {
+			struct sctp_auth_hmac_algo *hmacs;
+
+			if (padding_len > 0) {
+				memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+				chunk_len += padding_len;
+				padding_len = 0;
+			}
+			hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t) + chunk_len);
+			parameter_len = (uint16_t)(sizeof(struct sctp_auth_hmac_algo) +
+			                           stcb->asoc.local_hmacs->num_algo * sizeof(uint16_t));
+			hmacs->ph.param_type = htons(SCTP_HMAC_LIST);
+			hmacs->ph.param_length = htons(parameter_len);
+			sctp_serialize_hmaclist(stcb->asoc.local_hmacs, (uint8_t *)hmacs->hmac_ids);
+			padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+			chunk_len += parameter_len;
+		}
+		/* add CHUNKS parameter */
+		if (stcb->asoc.local_auth_chunks != NULL) {
+			struct sctp_auth_chunk_list *chunks;
+
+			if (padding_len > 0) {
+				memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+				chunk_len += padding_len;
+				padding_len = 0;
+			}
+			chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t) + chunk_len);
+			parameter_len = (uint16_t)(sizeof(struct sctp_auth_chunk_list) +
+			                           sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks));
+			chunks->ph.param_type = htons(SCTP_CHUNK_LIST);
+			chunks->ph.param_length = htons(parameter_len);
+			sctp_serialize_auth_chunks(stcb->asoc.local_auth_chunks, chunks->chunk_types);
+			padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+			chunk_len += parameter_len;
+		}
+	}
+
+	/* now any cookie time extensions */
+	if (stcb->asoc.cookie_preserve_req) {
+		struct sctp_cookie_perserve_param *cookie_preserve;
+
+		if (padding_len > 0) {
+			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+			chunk_len += padding_len;
+			padding_len = 0;
+		}
+		parameter_len = (uint16_t)sizeof(struct sctp_cookie_perserve_param);
+		cookie_preserve = (struct sctp_cookie_perserve_param *)(mtod(m, caddr_t) + chunk_len);
+		cookie_preserve->ph.param_type = htons(SCTP_COOKIE_PRESERVE);
+		cookie_preserve->ph.param_length = htons(parameter_len);
+		cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req);
+		stcb->asoc.cookie_preserve_req = 0;
+		chunk_len += parameter_len;
+	}
+
 	if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) {
 		uint8_t i;
 
+		if (padding_len > 0) {
+			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+			chunk_len += padding_len;
+			padding_len = 0;
+		}
 		parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
 		if (stcb->asoc.scope.ipv4_addr_legal) {
 			parameter_len += (uint16_t)sizeof(uint16_t);
 		}
 		if (stcb->asoc.scope.ipv6_addr_legal) {
 			parameter_len += (uint16_t)sizeof(uint16_t);
 		}
 		sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t) + chunk_len);
@@ -4967,186 +5273,31 @@ sctp_send_initiate(struct sctp_inpcb *in
 		}
 		if (stcb->asoc.scope.ipv6_addr_legal) {
 			sup_addr->addr_type[i++] = htons(SCTP_IPV6_ADDRESS);
 		}
 		padding_len = 4 - 2 * i;
 		chunk_len += parameter_len;
 	}
 
-	/* Adaptation layer indication parameter */
-	if (inp->sctp_ep.adaptation_layer_indicator_provided) {
-		if (padding_len > 0) {
-			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-			chunk_len += padding_len;
-			padding_len = 0;
-		}
-		parameter_len = (uint16_t)sizeof(struct sctp_adaptation_layer_indication);
-		ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t) + chunk_len);
-		ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
-		ali->ph.param_length = htons(parameter_len);
-		ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
-		chunk_len += parameter_len;
-	}
-
-	if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
-		/* Add NAT friendly parameter. */
-		if (padding_len > 0) {
-			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-			chunk_len += padding_len;
-			padding_len = 0;
-		}
-		parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
-		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len);
-		ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
-		ph->param_length = htons(parameter_len);
-		chunk_len += parameter_len;
-	}
-
-	/* now any cookie time extensions */
-	if (stcb->asoc.cookie_preserve_req) {
-		struct sctp_cookie_perserve_param *cookie_preserve;
-
-		if (padding_len > 0) {
-			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-			chunk_len += padding_len;
-			padding_len = 0;
-		}
-		parameter_len = (uint16_t)sizeof(struct sctp_cookie_perserve_param);
-		cookie_preserve = (struct sctp_cookie_perserve_param *)(mtod(m, caddr_t) + chunk_len);
-		cookie_preserve->ph.param_type = htons(SCTP_COOKIE_PRESERVE);
-		cookie_preserve->ph.param_length = htons(parameter_len);
-		cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req);
-		stcb->asoc.cookie_preserve_req = 0;
-		chunk_len += parameter_len;
-	}
-
-	/* ECN parameter */
-	if (stcb->asoc.ecn_allowed == 1) {
-		if (padding_len > 0) {
-			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-			chunk_len += padding_len;
-			padding_len = 0;
-		}
-		parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
-		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len);
-		ph->param_type = htons(SCTP_ECN_CAPABLE);
-		ph->param_length = htons(parameter_len);
-		chunk_len += parameter_len;
-	}
-
-	/* And now tell the peer we do support PR-SCTP. */
-	if (padding_len > 0) {
-		memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-		chunk_len += padding_len;
-		padding_len = 0;
-	}
-	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;
-
-	/* And now tell the peer we do all the extensions */
-	pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t) + chunk_len);
-	pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
-	num_ext = 0;
-	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;
-	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)) {
-		pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
-	}
-	if (stcb->asoc.sctp_nr_sack_on_off == 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;
-
-	/* add authentication parameters */
-	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
-		/* attach RANDOM parameter, if available */
-		if (stcb->asoc.authinfo.random != NULL) {
-			struct sctp_auth_random *randp;
-
-			if (padding_len > 0) {
-				memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-				chunk_len += padding_len;
-				padding_len = 0;
-			}
-			randp = (struct sctp_auth_random *)(mtod(m, caddr_t) + chunk_len);
-			parameter_len = (uint16_t)sizeof(struct sctp_auth_random) + stcb->asoc.authinfo.random_len;
-			/* random key already contains the header */
-			memcpy(randp, stcb->asoc.authinfo.random->key, parameter_len);
-			padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
-			chunk_len += parameter_len;
-		}
-		/* add HMAC_ALGO parameter */
-		if ((stcb->asoc.local_hmacs != NULL) &&
-		    (stcb->asoc.local_hmacs->num_algo > 0)) {
-			struct sctp_auth_hmac_algo *hmacs;
-
-			if (padding_len > 0) {
-				memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-				chunk_len += padding_len;
-				padding_len = 0;
-			}
-			hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t) + chunk_len);
-			parameter_len = (uint16_t)(sizeof(struct sctp_auth_hmac_algo) +
-			                           stcb->asoc.local_hmacs->num_algo * sizeof(uint16_t));
-			hmacs->ph.param_type = htons(SCTP_HMAC_LIST);
-			hmacs->ph.param_length = htons(parameter_len);
-			sctp_serialize_hmaclist(stcb->asoc.local_hmacs, (uint8_t *)hmacs->hmac_ids);
-			padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
-			chunk_len += parameter_len;
-		}
-		/* add CHUNKS parameter */
-		if (sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks) > 0) {
-			struct sctp_auth_chunk_list *chunks;
-
-			if (padding_len > 0) {
-				memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
-				chunk_len += padding_len;
-				padding_len = 0;
-			}
-			chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t) + chunk_len);
-			parameter_len = (uint16_t)(sizeof(struct sctp_auth_chunk_list) +
-			                           sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks));
-			chunks->ph.param_type = htons(SCTP_CHUNK_LIST);
-			chunks->ph.param_length = htons(parameter_len);
-			sctp_serialize_auth_chunks(stcb->asoc.local_auth_chunks, chunks->chunk_types);
-			padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
-			chunk_len += parameter_len;
-		}
-	}
 	SCTP_BUF_LEN(m) = chunk_len;
-
 	/* now the addresses */
 	/* To optimize this we could put the scoping stuff
 	 * into a structure and remove the individual uint8's from
 	 * the assoc structure. Then we could just sifa in the
 	 * address within the stcb. But for now this is a quick
 	 * hack to get the address stuff teased apart.
 	 */
-	sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope, m, cnt_inits_to, &padding_len, &chunk_len);
+	m_last = sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope,
+	                                    m, cnt_inits_to,
+	                                    &padding_len, &chunk_len);
 
 	init->ch.chunk_length = htons(chunk_len);
 	if (padding_len > 0) {
-		struct mbuf *m_at, *mp_last;
-
-		mp_last = NULL;
-		for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
-			if (SCTP_BUF_NEXT(m_at) == NULL)
-				mp_last = m_at;
-		}
-		if ((mp_last == NULL) || sctp_add_pad_tombuf(mp_last, padding_len)) {
+		if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) {
 			sctp_m_freem(m);
 			return;
 		}
 	}
 	SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - calls lowlevel_output\n");
 	ret = sctp_lowlevel_chunk_output(inp, stcb, net,
 	                                 (struct sockaddr *)&net->ro._l_addr,
 	                                 m, 0, NULL, 0, 0, 0, 0,
@@ -5272,28 +5423,27 @@ sctp_arethere_unrecognized_parameters(st
 		case SCTP_COOKIE_PRESERVE:
 			if (padded_size != sizeof(struct sctp_cookie_perserve_param)) {
 				SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error cookie-preserve %d\n", plen);
 				goto invalid_size;
 			}
 			at += padded_size;
 			break;
 		case SCTP_HAS_NAT_SUPPORT:
-		  *nat_friendly = 1;
-		  /* fall through */
+			*nat_friendly = 1;
+			/* fall through */
 		case SCTP_PRSCTP_SUPPORTED:
-
 			if (padded_size != sizeof(struct sctp_paramhdr)) {
 				SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error prsctp/nat support %d\n", plen);
 				goto invalid_size;
 			}
 			at += padded_size;
 			break;
 		case SCTP_ECN_CAPABLE:
-			if (padded_size != sizeof(struct sctp_ecn_supported_param)) {
+			if (padded_size != sizeof(struct sctp_paramhdr)) {
 				SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error ecn %d\n", plen);
 				goto invalid_size;
 			}
 			at += padded_size;
 			break;
 		case SCTP_ULP_ADAPTATION:
 			if (padded_size != sizeof(struct sctp_adaptation_layer_indication)) {
 				SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error adapatation %d\n", plen);
@@ -5459,26 +5609,26 @@ sctp_arethere_unrecognized_parameters(st
 		int l_len;
 #ifdef INET6
 		l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
 #else
 		l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
 #endif
 		l_len += (2 * sizeof(struct sctp_paramhdr));
 		op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA);
-        if (op_err) {
-    		SCTP_BUF_LEN(op_err) = 0;
+		if (op_err) {
+			SCTP_BUF_LEN(op_err) = 0;
 #ifdef INET6
-	    	SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
-#else
-	    	SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
-#endif
-		SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
-    		SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
-        }
+			SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
+#else
+			SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
+#endif
+			SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
+			SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
+		}
 	}
 	if ((op_err) && phdr) {
 		struct sctp_paramhdr s;
 
 		if (err_at % 4) {
 			uint32_t cpthis = 0;
 
 			pad_needed = 4 - (err_at % 4);
@@ -5662,28 +5812,28 @@ sctp_are_there_new_addresses(struct sctp
  * message (i.e. the struct sctp_init_msg).
  */
 void
 sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
                        struct mbuf *init_pkt, int iphlen, int offset,
                        struct sockaddr *src, struct sockaddr *dst,
                        struct sctphdr *sh, struct sctp_init_chunk *init_chk,
 #if defined(__FreeBSD__)
-		       uint8_t use_mflowid, uint32_t mflowid,
+		       uint8_t mflowtype, uint32_t mflowid,
 #endif
                        uint32_t vrf_id, uint16_t port, int hold_inp_lock)
 {
 	struct sctp_association *asoc;
-	struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last;
+	struct mbuf *m, *m_tmp, *m_last, *m_cookie, *op_err;
 	struct sctp_init_ack_chunk *initack;
 	struct sctp_adaptation_layer_indication *ali;
-	struct sctp_ecn_supported_param *ecn;
-	struct sctp_prsctp_supported_param *prsctp;
 	struct sctp_supported_chunk_types_param *pr_supported;
+	struct sctp_paramhdr *ph;
 	union sctp_sockstore *over_addr;
+	struct sctp_scoping scp;
 #ifdef INET
 	struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
 	struct sockaddr_in *src4 = (struct sockaddr_in *)src;
 	struct sockaddr_in *sin;
 #endif
 #ifdef INET6
 	struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
 	struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src;
@@ -5695,66 +5845,74 @@ sctp_send_initiate_ack(struct sctp_inpcb
 	struct sockaddr_conn *sconn;
 #endif
 	struct sockaddr *to;
 	struct sctp_state_cookie stc;
 	struct sctp_nets *net = NULL;
 	uint8_t *signature = NULL;
 	int cnt_inits_to = 0;
 	uint16_t his_limit, i_want;
-	int abort_flag, padval;
-	int num_ext;
-	int p_len;
+	int abort_flag;
 	int nat_friendly = 0;
 	struct socket *so;
+	uint16_t num_ext, chunk_len, padding_len, parameter_len;
 
 	if (stcb) {
 		asoc = &stcb->asoc;
 	} else {
 		asoc = NULL;
 	}
-	mp_last = NULL;
 	if ((asoc != NULL) &&
 	    (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
 	    (sctp_are_there_new_addresses(asoc, init_pkt, offset, src))) {
 		/* new addresses, out of here in non-cookie-wait states */
 		/*
 		 * Send a ABORT, we don't add the new address error clause
 		 * though we even set the T bit and copy in the 0 tag.. this
 		 * looks no different than if no listener was present.
 		 */
-		sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, NULL,
+		op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+		                             "Address added");
+		sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err,
 #if defined(__FreeBSD__)
-		                use_mflowid, mflowid,
+		                mflowtype, mflowid,
 #endif
 		                vrf_id, port);
 		return;
 	}
 	abort_flag = 0;
 	op_err = sctp_arethere_unrecognized_parameters(init_pkt,
 						       (offset + sizeof(struct sctp_init_chunk)),
 						       &abort_flag, (struct sctp_chunkhdr *)init_chk, &nat_friendly);
 	if (abort_flag) {
 	do_a_abort:
+		if (op_err == NULL) {
+			char msg[SCTP_DIAG_INFO_LEN];
+
+			snprintf(msg, sizeof(msg), "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+			                             msg);
+		}
 		sctp_send_abort(init_pkt, iphlen, src, dst, sh,
 				init_chk->init.initiate_tag, op_err,
 #if defined(__FreeBSD__)
-		                use_mflowid, mflowid,
+		                mflowtype, mflowid,
 #endif
 		                vrf_id, port);
 		return;
 	}
 	m = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
 	if (m == NULL) {
 		/* No memory, INIT timer will re-attempt. */
 		if (op_err)
 			sctp_m_freem(op_err);
 		return;
 	}
-	SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
+	chunk_len = (uint16_t)sizeof(struct sctp_init_ack_chunk);
+	padding_len = 0;
 
 	/*
 	 * We might not overwrite the identification[] completely and on
 	 * some platforms time_entered will contain some padding.
 	 * Therefore zero out the cookie to avoid putting
 	 * uninitialized memory on the wire.
 	 */
 	memset(&stc, 0, sizeof(struct sctp_state_cookie));
@@ -6121,243 +6279,263 @@ sctp_send_initiate_ack(struct sctp_inpcb
 		initack->init.num_outbound_streams = htons(i_want);
 	}
 	/* tell him his limit. */
 	initack->init.num_inbound_streams =
 		htons(inp->sctp_ep.max_open_streams_intome);
 
 	/* adaptation layer indication parameter */
 	if (inp->sctp_ep.adaptation_layer_indicator_provided) {
-		ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack));
+		parameter_len = (uint16_t)sizeof(struct sctp_adaptation_layer_indication);
+		ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t) + chunk_len);
 		ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
-		ali->ph.param_length = htons(sizeof(*ali));
-		ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
-		SCTP_BUF_LEN(m) += sizeof(*ali);
-		ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali));
-	} else {
-		ecn = (struct sctp_ecn_supported_param *)((caddr_t)initack + sizeof(*initack));
+		ali->ph.param_length = htons(parameter_len);
+		ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator);
+		chunk_len += parameter_len;
 	}
 
 	/* ECN parameter */
-	if (((asoc != NULL) && (asoc->ecn_allowed == 1)) ||
-	    (inp->sctp_ecn_enable == 1)) {
-		ecn->ph.param_type = htons(SCTP_ECN_CAPABLE);
-		ecn->ph.param_length = htons(sizeof(*ecn));
-		SCTP_BUF_LEN(m) += sizeof(*ecn);
-
-		prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn +
-								sizeof(*ecn));
-	} else {
-		prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn);
-	}
-	/* And now tell the peer we do  pr-sctp */
-	prsctp->ph.param_type = htons(SCTP_PRSCTP_SUPPORTED);
-	prsctp->ph.param_length = htons(sizeof(*prsctp));
-	SCTP_BUF_LEN(m) += sizeof(*prsctp);
+	if (((asoc != NULL) && (asoc->ecn_supported == 1)) ||
+	    ((asoc == NULL) && (inp->ecn_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_ECN_CAPABLE);
+		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) {
-		/* Add NAT friendly parameter */
-		struct sctp_paramhdr *ph;
-
-		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m));
+		parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
+		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len);
 		ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
-		ph->param_length = htons(sizeof(struct sctp_paramhdr));
-		SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr);
-	}
-	/* And now tell the peer we do all the extensions */
-	pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m));
-	pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
+		ph->param_length = htons(parameter_len);
+		chunk_len += parameter_len;
+	}
+
+	/* And now tell the peer which extensions we support */
 	num_ext = 0;
-	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;
-	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))
+	pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t) + chunk_len);
+	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->auth_supported == 1)) ||
+	    ((asoc == NULL) && (inp->auth_supported == 1))) {
 		pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
-	if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
+	}
+	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 (((asoc != NULL) && (asoc->nrsack_supported == 1)) ||
+	    ((asoc == NULL) && (inp->nrsack_supported == 1))) {
 		pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
-	p_len = sizeof(*pr_supported) + num_ext;
-	pr_supported->ph.param_length = htons(p_len);
-	bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len);
-	SCTP_BUF_LEN(m) += SCTP_SIZE32(p_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;
-		uint16_t random_len;
-
+
+		if (padding_len > 0) {
+			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+			chunk_len += padding_len;
+			padding_len = 0;
+		}
 		/* generate and add RANDOM parameter */
-		random_len = SCTP_AUTH_RANDOM_SIZE_DEFAULT;
-		randp = (struct sctp_auth_random *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m));
+		randp = (struct sctp_auth_random *)(mtod(m, caddr_t) + chunk_len);
+		parameter_len = (uint16_t)sizeof(struct sctp_auth_random) +
+		                SCTP_AUTH_RANDOM_SIZE_DEFAULT;
 		randp->ph.param_type = htons(SCTP_RANDOM);
-		p_len = sizeof(*randp) + random_len;
-		randp->ph.param_length = htons(p_len);
-		SCTP_READ_RANDOM(randp->random_data, random_len);
-		/* zero out any padding required */
-		bzero((caddr_t)randp + p_len, SCTP_SIZE32(p_len) - p_len);
-		SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
-
+		randp->ph.param_length = htons(parameter_len);
+		SCTP_READ_RANDOM(randp->random_data, SCTP_AUTH_RANDOM_SIZE_DEFAULT);
+		padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+		chunk_len += parameter_len;
+
+		if (padding_len > 0) {
+			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+			chunk_len += padding_len;
+			padding_len = 0;
+		}
 		/* add HMAC_ALGO parameter */
-		hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m));
-		p_len = sctp_serialize_hmaclist(inp->sctp_ep.local_hmacs,
-						(uint8_t *) hmacs->hmac_ids);
-		if (p_len > 0) {
-			p_len += sizeof(*hmacs);
-			hmacs->ph.param_type = htons(SCTP_HMAC_LIST);
-			hmacs->ph.param_length = htons(p_len);
-			/* zero out any padding required */
-			bzero((caddr_t)hmacs + p_len, SCTP_SIZE32(p_len) - p_len);
-			SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
+		hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t) + chunk_len);
+		parameter_len = (uint16_t)sizeof(struct sctp_auth_hmac_algo) +
+		                sctp_serialize_hmaclist(inp->sctp_ep.local_hmacs,
+		                                        (uint8_t *)hmacs->hmac_ids);
+		hmacs->ph.param_type = htons(SCTP_HMAC_LIST);
+		hmacs->ph.param_length = htons(parameter_len);
+		padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+		chunk_len += parameter_len;
+
+		if (padding_len > 0) {
+			memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+			chunk_len += padding_len;
+			padding_len = 0;
 		}
 		/* add CHUNKS parameter */
-		chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m));
-		p_len = sctp_serialize_auth_chunks(inp->sctp_ep.local_auth_chunks,
-						   chunks->chunk_types);
-		if (p_len > 0) {
-			p_len += sizeof(*chunks);
-			chunks->ph.param_type = htons(SCTP_CHUNK_LIST);
-			chunks->ph.param_length = htons(p_len);
-			/* zero out any padding required */
-			bzero((caddr_t)chunks + p_len, SCTP_SIZE32(p_len) - p_len);
-			SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
-		}
-	}
-	m_at = m;
+		chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t) + chunk_len);
+		parameter_len = (uint16_t)sizeof(struct sctp_auth_chunk_list) +
+		                sctp_serialize_auth_chunks(inp->sctp_ep.local_auth_chunks,
+		                                           chunks->chunk_types);
+		chunks->ph.param_type = htons(SCTP_CHUNK_LIST);
+		chunks->ph.param_length = htons(parameter_len);
+		padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+		chunk_len += parameter_len;
+	}
+	SCTP_BUF_LEN(m) = chunk_len;
+	m_last = m;
 	/* now the addresses */
-	{
-		struct sctp_scoping scp;
-		/* To optimize this we could put the scoping stuff
-		 * into a structure and remove the individual uint8's from
-		 * the stc structure. Then we could just sifa in the
-		 * address within the stc.. but for now this is a quick
-		 * hack to get the address stuff teased apart.
-		 */
- 		scp.ipv4_addr_legal = stc.ipv4_addr_legal;
-		scp.ipv6_addr_legal = stc.ipv6_addr_legal;
+	/* To optimize this we could put the scoping stuff
+	 * into a structure and remove the individual uint8's from
+	 * the stc structure. Then we could just sifa in the
+	 * address within the stc.. but for now this is a quick
+	 * hack to get the address stuff teased apart.
+	 */
+	scp.ipv4_addr_legal = stc.ipv4_addr_legal;
+	scp.ipv6_addr_legal = stc.ipv6_addr_legal;
 #if defined(__Userspace__)
-		scp.conn_addr_legal = stc.conn_addr_legal;
-#endif
-		scp.loopback_scope = stc.loopback_scope;
-		scp.ipv4_local_scope = stc.ipv4_scope;
-		scp.local_scope = stc.local_scope;
-		scp.site_scope = stc.site_scope;
-		m_at = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_at, cnt_inits_to, NULL, NULL);
+	scp.conn_addr_legal = stc.conn_addr_legal;
+#endif
+	scp.loopback_scope = stc.loopback_scope;
+	scp.ipv4_local_scope = stc.ipv4_scope;
+	scp.local_scope = stc.local_scope;
+	scp.site_scope = stc.site_scope;
+	m_last = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_last,
+	                                    cnt_inits_to,
+	                                    &padding_len, &chunk_len);
+	/* padding_len can only be positive, if no addresses have been added */
+	if (padding_len > 0) {
+		memset(mtod(m, caddr_t) + chunk_len, 0, padding_len);
+		chunk_len += padding_len;
+		SCTP_BUF_LEN(m) += padding_len;
+		padding_len = 0;
 	}
 
 	/* tack on the operational error if present */
 	if (op_err) {
-		struct mbuf *ol;
-		int llen;
-		llen = 0;
-		ol = op_err;
-
-		while (ol) {
-			llen += SCTP_BUF_LEN(ol);
-			ol = SCTP_BUF_NEXT(ol);
-		}
-		if (llen % 4) {
-			/* must add a pad to the param */
-			uint32_t cpthis = 0;
-			int padlen;
-
-			padlen = 4 - (llen % 4);
-			m_copyback(op_err, llen, padlen, (caddr_t)&cpthis);
-		}
-		while (SCTP_BUF_NEXT(m_at) != NULL) {
-			m_at = SCTP_BUF_NEXT(m_at);
-		}
-		SCTP_BUF_NEXT(m_at) = op_err;
-		while (SCTP_BUF_NEXT(m_at) != NULL) {
-			m_at = SCTP_BUF_NEXT(m_at);
-		}
-	}
-	/* pre-calulate the size and update pkt header and chunk header */
-	p_len = 0;
-	for (m_tmp = m; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
-		p_len += SCTP_BUF_LEN(m_tmp);
-		if (SCTP_BUF_NEXT(m_tmp) == NULL) {
-			/* m_tmp should now point to last one */
-			break;
-		}
-	}
-
+		parameter_len = 0;
+		for (m_tmp = op_err; m_tmp != NULL; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
+			parameter_len += SCTP_BUF_LEN(m_tmp);
+		}
+		padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+		SCTP_BUF_NEXT(m_last) = op_err;
+		while (SCTP_BUF_NEXT(m_last) != NULL) {
+			m_last = SCTP_BUF_NEXT(m_last);
+		}
+		chunk_len += parameter_len;
+	}
+	if (padding_len > 0) {
+		m_last = sctp_add_pad_tombuf(m_last, padding_len);
+		if (m_last == NULL) {
+			/* Houston we have a problem, no space */
+			sctp_m_freem(m);
+			return;
+		}
+		chunk_len += padding_len;
+		padding_len = 0;
+	}
 	/* Now we must build a cookie */
 	m_cookie = sctp_add_cookie(init_pkt, offset, m, 0, &stc, &signature);
 	if (m_cookie == NULL) {
 		/* memory problem */
 		sctp_m_freem(m);
 		return;
 	}
 	/* Now append the cookie to the end and update the space/size */
-	SCTP_BUF_NEXT(m_tmp) = m_cookie;
-
-	for (m_tmp = m_cookie; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
-		p_len += SCTP_BUF_LEN(m_tmp);
+	SCTP_BUF_NEXT(m_last) = m_cookie;
+	parameter_len = 0;
+	for (m_tmp = m_cookie; m_tmp != NULL; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
+		parameter_len += SCTP_BUF_LEN(m_tmp);
 		if (SCTP_BUF_NEXT(m_tmp) == NULL) {
-			/* m_tmp should now point to last one */
-			mp_last = m_tmp;
-			break;
-		}
-	}
+			m_last = m_tmp;
+		}
+	}
+	padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
+	chunk_len += parameter_len;
+
 	/* Place in the size, but we don't include
 	 * the last pad (if any) in the INIT-ACK.
 	 */
-	initack->ch.chunk_length = htons(p_len);
+	initack->ch.chunk_length = htons(chunk_len);
 
 	/* Time to sign the cookie, we don't sign over the cookie
 	 * signature though thus we set trailer.
 	 */
 	(void)sctp_hmac_m(SCTP_HMAC,
 			  (uint8_t *)inp->sctp_ep.secret_key[(int)(inp->sctp_ep.current_secret_number)],
 			  SCTP_SECRET_SIZE, m_cookie, sizeof(struct sctp_paramhdr),
 			  (uint8_t *)signature, SCTP_SIGNATURE_SIZE);
 	/*
 	 * We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
 	 * here since the timer will drive a retranmission.
 	 */
-	padval = p_len % 4;
-	if ((padval) && (mp_last)) {
-		/* see my previous comments on mp_last */
-		if (sctp_add_pad_tombuf(mp_last, (4 - padval))) {
-			/* Houston we have a problem, no space */
+	if (padding_len > 0) {
+		if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) {
 			sctp_m_freem(m);
 			return;
 		}
 	}
 	if (stc.loopback_scope) {
 		over_addr = (union sctp_sockstore *)dst;
 	} else {
 		over_addr = NULL;
 	}
 
 	(void)sctp_lowlevel_chunk_output(inp, NULL, NULL, to, m, 0, NULL, 0, 0,
 	                                 0, 0,
 	                                 inp->sctp_lport, sh->src_port, init_chk->init.initiate_tag,
 	                                 port, over_addr,
 #if defined(__FreeBSD__)
-	                                 use_mflowid, mflowid,
+	                                 mflowtype, mflowid,
 #endif
 	                                 SCTP_SO_NOT_LOCKED);
 	SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
 }
 
 
 static void
 sctp_prune_prsctp(struct sctp_tcb *stcb,
     struct sctp_association *asoc,
     struct sctp_sndrcvinfo *srcv,
     int dataout)
 {
 	int freed_spc = 0;
 	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) {
 			/*
 			 * Look for chunks marked with the PR_SCTP flag AND
 			 * the buffer space flag. If the one being sent is
 			 * equal or greater priority then purge the old one
 			 * and free some space.
 			 */
@@ -6715,23 +6893,17 @@ sctp_copy_mbufchain(struct mbuf *clonech
 				SCTP_BUF_LEN((*endofchain)) += sizeofcpy;
 			}
 			return (outchain);
 		} else {
 			/* copy the old fashion way */
 			appendchain = SCTP_M_COPYM(clonechain, 0, M_COPYALL, M_NOWAIT);
 #ifdef SCTP_MBUF_LOGGING
 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-				struct mbuf *mat;
-
-				for (mat = appendchain; mat; mat = SCTP_BUF_NEXT(mat)) {
-					if (SCTP_BUF_IS_EXTENDED(mat)) {
-						sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-					}
-				}
+				sctp_log_mbc(appendchain, SCTP_MBUF_ICOPY);
 			}
 #endif
 		}
 	}
 	if (appendchain == NULL) {
 		/* error */
 		if (outchain)
 			sctp_m_freem(outchain);
@@ -6815,23 +6987,17 @@ sctp_sendall_iterator(struct sctp_inpcb 
 		m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_NOWAIT);
 		if (m == NULL) {
 			/* can't copy so we are done */
 			ca->cnt_failed++;
 			return;
 		}
 #ifdef SCTP_MBUF_LOGGING
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-			struct mbuf *mat;
-
-			for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
-				if (SCTP_BUF_IS_EXTENDED(mat)) {
-					sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-				}
-			}
+			sctp_log_mbc(m, SCTP_MBUF_ICOPY);
 		}
 #endif
 	} else {
 		m = NULL;
 	}
 	SCTP_TCB_LOCK_ASSERT(stcb);
 	if (stcb->asoc.alternate) {
 		net = stcb->asoc.alternate;
@@ -6956,19 +7122,20 @@ sctp_sendall_iterator(struct sctp_inpcb 
 	if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
 	    (stcb->asoc.total_flight > 0) &&
 	    (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) {
 		do_chunk_output = 0;
 	}
 	if (do_chunk_output)
 		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_NOT_LOCKED);
 	else if (added_control) {
-		int num_out = 0, reason = 0, now_filled = 0;
+		int num_out, reason, now_filled = 0;
 		struct timeval now;
 		int frag_point;
+
 		frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
 		(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
 				      &reason, 1, 1, &now, &now_filled, frag_point, SCTP_SO_NOT_LOCKED);
 	}
  no_chunk_output:
 	if (ret) {
 		ca->cnt_failed++;
 	} else {
@@ -6991,23 +7158,16 @@ sctp_sendall_completes(void *ptr, uint32
 	 * user you can't send the data :->
 	 */
 
 	/* now free everything */
 	sctp_m_freem(ca->m);
 	SCTP_FREE(ca, SCTP_M_COPYAL);
 }
 
-
-#define	MC_ALIGN(m, len) do {						\
-	SCTP_BUF_RESV_UF(m, ((MCLBYTES - (len)) & ~(sizeof(long) - 1));	\
-} while (0)
-
-
-
 static struct mbuf *
 sctp_copy_out_all(struct uio *uio, int len)
 {
 	struct mbuf *ret, *at;
 	int left, willcpy, cancpy, error;
 
 	ret = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_WAITOK, 1, MT_DATA);
 	if (ret == NULL) {
@@ -7605,23 +7765,17 @@ re_look:
 			sp->some_taken = some_taken;
 			sctp_free_a_chunk(stcb, chk, so_locked);
 			*bail = 1;
 			to_move = 0;
 			goto out_of;
 		}
 #ifdef SCTP_MBUF_LOGGING
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-			struct mbuf *mat;
-
-			for (mat = chk->data; mat; mat = SCTP_BUF_NEXT(mat)) {
-				if (SCTP_BUF_IS_EXTENDED(mat)) {
-					sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-				}
-			}
+			sctp_log_mbc(chk->data, SCTP_MBUF_ICOPY);
 		}
 #endif
 		/* Pull off the data */
 		m_adj(sp->data, to_move);
 		/* Now lets work our way down and compact it */
 		m = sp->data;
 		while (m && (SCTP_BUF_LEN(m) == 0)) {
 			sp->data  = SCTP_BUF_NEXT(m);
@@ -7672,28 +7826,29 @@ re_look:
 		sp->length = 0;
 #endif
 	} else {
 		atomic_subtract_int(&sp->length, to_move);
 	}
 	if (M_LEADINGSPACE(chk->data) < (int)sizeof(struct sctp_data_chunk)) {
 		/* Not enough room for a chunk header, get some */
 		struct mbuf *m;
+
 		m = sctp_get_mbuf_for_msg(1, 0, M_NOWAIT, 0, MT_DATA);
 		if (m == NULL) {
 			/*
 			 * we're in trouble here. _PREPEND below will free
 			 * all the data if there is no leading space, so we
 			 * must put the data back and restore.
 			 */
 			if (send_lock_up == 0) {
 				SCTP_TCB_SEND_LOCK(stcb);
 				send_lock_up = 1;
 			}
-			if (chk->data == NULL) {
+			if (sp->data == NULL) {
 				/* unsteal the data */
 				sp->data = chk->data;
 				sp->tail_mbuf = chk->last_mbuf;
 			} else {
 				struct mbuf *m_tmp;
 				/* reassemble the data */
 				m_tmp = sp->data;
 				sp->data = chk->data;
@@ -7731,17 +7886,18 @@ re_look:
 	chk->book_size_scale = 0;
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 
 	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->pad_inplace = 0;
 	chk->no_fr_allowed = 0;
 	chk->rec.data.stream_seq = strq->next_sequence_send;
-	if (rcv_flags & SCTP_DATA_LAST_FRAG) {
+	if ((rcv_flags & SCTP_DATA_LAST_FRAG) &&
+	    !(rcv_flags & SCTP_DATA_UNORDERED)) {
 		strq->next_sequence_send++;
 	}
 	chk->rec.data.stream_number = sp->stream;
 	chk->rec.data.payloadtype = sp->ppid;
 	chk->rec.data.context = sp->context;
 	chk->rec.data.doing_fast_retransmit = 0;
 
 	chk->rec.data.timetodrop = sp->ts;
@@ -7753,17 +7909,16 @@ re_look:
 	} else
 		chk->whoTo = NULL;
 
 	if (sp->holds_key_ref) {
 		chk->auth_keyid = sp->auth_keyid;
 		sctp_auth_key_acquire(stcb, chk->auth_keyid);
 		chk->holds_key_ref = 1;
 	}
-
 #if defined(__FreeBSD__) || defined(__Panda__)
 	chk->rec.data.TSN_seq = atomic_fetchadd_int(&asoc->sending_seq, 1);
 #else
 	chk->rec.data.TSN_seq = asoc->sending_seq++;
 #endif
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_AT_SEND_2_OUTQ) {
 		sctp_misc_ints(SCTP_STRMOUT_LOG_SEND,
 		               (uintptr_t)stcb, sp->length,
@@ -7802,23 +7957,21 @@ re_look:
 	dchkh->ch.chunk_length = htons(chk->send_size);
 	/* Now advance the chk->send_size by the actual pad needed. */
 	if (chk->send_size < SCTP_SIZE32(chk->book_size)) {
 		/* need a pad */
 		struct mbuf *lm;
 		int pads;
 
 		pads = SCTP_SIZE32(chk->book_size) - chk->send_size;
-		if (sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf) == 0) {
+		lm = sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf);
+		if (lm != NULL) {
+			chk->last_mbuf = lm;
 			chk->pad_inplace = 1;
 		}
-		if ((lm = SCTP_BUF_NEXT(chk->last_mbuf)) != NULL) {
-			/* pad added an mbuf */
-			chk->last_mbuf = lm;
-		}
 		chk->send_size += pads;
 	}
 	if (PR_SCTP_ENABLED(chk->flags)) {
 		asoc->pr_sctp_cnt++;
 	}
 	if (sp->msg_is_complete && (sp->length == 0) && (sp->sender_all_done)) {
 		/* All done pull and kill the message */
 		atomic_subtract_int(&asoc->stream_queue_cnt, 1);
@@ -8047,18 +8200,18 @@ sctp_med_chunk_output(struct sctp_inpcb 
 #if defined(__APPLE__)
 	if (so_locked) {
 		sctp_lock_assert(SCTP_INP_SO(inp));
 	} else {
 		sctp_unlock_assert(SCTP_INP_SO(inp));
 	}
 #endif
 	*num_out = 0;
+	*reason_code = 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))) {
 		eeor_mode = 1;
 	} else {
 		eeor_mode = 0;
 	}
 	ctl_cnt = no_out_cnt = asconf = cookie = 0;
@@ -8235,34 +8388,16 @@ again_one_more_time:
 		endoutchain = outchain = NULL;
 		no_fragmentflg = 1;
 		one_chunk = 0;
 		if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
 			skip_data_for_this_net = 1;
 		} else {
 			skip_data_for_this_net = 0;
 		}
-#if !(defined(__Panda__) || defined(__Windows__) || defined(__Userspace__) || defined(__APPLE__))
-		if ((net->ro.ro_rt) && (net->ro.ro_rt->rt_ifp)) {
-			/*
-			 * if we have a route and an ifp check to see if we
-			 * have room to send to this guy
-			 */
-			struct ifnet *ifp;
-
-			ifp = net->ro.ro_rt->rt_ifp;
-			if ((ifp->if_snd.ifq_len + 2) >= ifp->if_snd.ifq_maxlen) {
-				SCTP_STAT_INCR(sctps_ifnomemqueued);
-				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_MAXBURST_ENABLE) {
-					sctp_log_maxburst(stcb, net, ifp->if_snd.ifq_len, ifp->if_snd.ifq_maxlen, SCTP_MAX_IFP_APPLIED);
-				}
-				continue;
-			}
-		}
-#endif
 		switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
 #ifdef INET
 		case AF_INET:
 			mtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr));
 			break;
 #endif
 #ifdef INET6
 		case AF_INET6:
@@ -9171,26 +9306,21 @@ sctp_queue_op_err(struct sctp_tcb *stcb,
 	}
 	chk->copy_by_ref = 0;
 	SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT);
 	if (op_err == NULL) {
 		sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
 		return;
 	}
 	chk->send_size = 0;
-	mat = op_err;
-	while (mat != NULL) {
+	for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) {
 		chk->send_size += SCTP_BUF_LEN(mat);
-		mat = SCTP_BUF_NEXT(mat);
-	}
-	chk->rec.chunk_id.id = SCTP_OPERATION_ERROR;
-	chk->rec.chunk_id.can_take_data = 1;
+	}
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
-	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->data = op_err;
 	chk->whoTo = NULL;
 	hdr = mtod(op_err, struct sctp_chunkhdr *);
 	hdr->chunk_type = SCTP_OPERATION_ERROR;
 	hdr->chunk_flags = 0;
 	hdr->chunk_length = htons(chk->send_size);
 	TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue,
@@ -9211,22 +9341,21 @@ sctp_send_cookie_echo(struct mbuf *m,
 	 */
 	int at;
 	struct mbuf *cookie;
 	struct sctp_paramhdr parm, *phdr;
 	struct sctp_chunkhdr *hdr;
 	struct sctp_tmit_chunk *chk;
 	uint16_t ptype, plen;
 
+	SCTP_TCB_LOCK_ASSERT(stcb);
 	/* First find the cookie in the param area */
 	cookie = NULL;
 	at = offset + sizeof(struct sctp_init_chunk);
-
-	SCTP_TCB_LOCK_ASSERT(stcb);
-	do {
+	for (;;) {
 		phdr = sctp_get_next_param(m, at, &parm, sizeof(parm));
 		if (phdr == NULL) {
 			return (-3);
 		}
 		ptype = ntohs(phdr->param_type);
 		plen = ntohs(phdr->param_length);
 		if (ptype == SCTP_STATE_COOKIE) {
 			int pad;
@@ -9237,53 +9366,42 @@ sctp_send_cookie_echo(struct mbuf *m,
 			}
 			cookie = SCTP_M_COPYM(m, at, plen, M_NOWAIT);
 			if (cookie == NULL) {
 				/* No memory */
 				return (-2);
 			}
 #ifdef SCTP_MBUF_LOGGING
 			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-				struct mbuf *mat;
-
-				for (mat = cookie; mat; mat = SCTP_BUF_NEXT(mat)) {
-					if (SCTP_BUF_IS_EXTENDED(mat)) {
-						sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-					}
-				}
+				sctp_log_mbc(cookie, SCTP_MBUF_ICOPY);
 			}
 #endif
 			break;
 		}
 		at += SCTP_SIZE32(plen);
-	} while (phdr);
-	if (cookie == NULL) {
-		/* Did not find the cookie */
-		return (-3);
 	}
 	/* ok, we got the cookie lets change it into a cookie echo chunk */
-
 	/* first the change from param to cookie */
 	hdr = mtod(cookie, struct sctp_chunkhdr *);
 	hdr->chunk_type = SCTP_COOKIE_ECHO;
 	hdr->chunk_flags = 0;
 	/* get the chunk stuff now and place it in the FRONT of the queue */
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		/* no memory */
 		sctp_m_freem(cookie);
 		return (-5);
 	}
 	chk->copy_by_ref = 0;
-	chk->send_size = plen;
 	chk->rec.chunk_id.id = SCTP_COOKIE_ECHO;
 	chk->rec.chunk_id.can_take_data = 0;
+	chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
+	chk->send_size = plen;
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
-	chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
 	chk->asoc = &stcb->asoc;
 	chk->data = cookie;
 	chk->whoTo = net;
 	atomic_add_int(&chk->whoTo->ref_count, 1);
 	TAILQ_INSERT_HEAD(&chk->asoc->control_send_queue, chk, sctp_next);
 	chk->asoc->ctrl_queue_cnt++;
 	return (0);
 }
@@ -9309,23 +9427,17 @@ sctp_send_heartbeat_ack(struct sctp_tcb 
 
 	outchain = SCTP_M_COPYM(m, offset, chk_length, M_NOWAIT);
 	if (outchain == NULL) {
 		/* gak out of memory */
 		return;
 	}
 #ifdef SCTP_MBUF_LOGGING
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-		struct mbuf *mat;
-
-		for (mat = outchain; mat; mat = SCTP_BUF_NEXT(mat)) {
-			if (SCTP_BUF_IS_EXTENDED(mat)) {
-				sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-			}
-		}
+		sctp_log_mbc(outchain, SCTP_MBUF_ICOPY);
 	}
 #endif
 	chdr = mtod(outchain, struct sctp_chunkhdr *);
 	chdr->chunk_type = SCTP_HEARTBEAT_ACK;
 	chdr->chunk_flags = 0;
 	if (chk_length % 4) {
 		/* need pad */
 		uint32_t cpthis = 0;
@@ -9336,22 +9448,22 @@ sctp_send_heartbeat_ack(struct sctp_tcb 
 	}
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		/* no memory */
 		sctp_m_freem(outchain);
 		return;
 	}
 	chk->copy_by_ref = 0;
-	chk->send_size = chk_length;
 	chk->rec.chunk_id.id = SCTP_HEARTBEAT_ACK;
 	chk->rec.chunk_id.can_take_data = 1;
+	chk->flags = 0;
+	chk->send_size = chk_length;
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
-	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->data = outchain;
 	chk->whoTo = net;
 	atomic_add_int(&chk->whoTo->ref_count, 1);
 	TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
 	chk->asoc->ctrl_queue_cnt++;
 }
 
@@ -9373,22 +9485,22 @@ sctp_send_cookie_ack(struct sctp_tcb *st
 	SCTP_BUF_RESV_UF(cookie_ack, SCTP_MIN_OVERHEAD);
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		/* no memory */
 		sctp_m_freem(cookie_ack);
 		return;
 	}
 	chk->copy_by_ref = 0;
-	chk->send_size = sizeof(struct sctp_chunkhdr);
 	chk->rec.chunk_id.id = SCTP_COOKIE_ACK;
 	chk->rec.chunk_id.can_take_data = 1;
+	chk->flags = 0;
+	chk->send_size = sizeof(struct sctp_chunkhdr);
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
-	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->data = cookie_ack;
 	if (chk->asoc->last_control_chunk_from != NULL) {
 		chk->whoTo = chk->asoc->last_control_chunk_from;
 		atomic_add_int(&chk->whoTo->ref_count, 1);
 	} else {
 		chk->whoTo = NULL;
 	}
@@ -9419,19 +9531,20 @@ sctp_send_shutdown_ack(struct sctp_tcb *
 	SCTP_BUF_RESV_UF(m_shutdown_ack, SCTP_MIN_OVERHEAD);
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		/* no memory */
 		sctp_m_freem(m_shutdown_ack);
 		return;
 	}
 	chk->copy_by_ref = 0;
-	chk->send_size = sizeof(struct sctp_chunkhdr);
 	chk->rec.chunk_id.id = SCTP_SHUTDOWN_ACK;
 	chk->rec.chunk_id.can_take_data = 1;
+	chk->flags = 0;
+	chk->send_size = sizeof(struct sctp_chunkhdr);
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
 	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->data = m_shutdown_ack;
 	chk->whoTo = net;
 	if (chk->whoTo) {
 		atomic_add_int(&chk->whoTo->ref_count, 1);
@@ -9462,19 +9575,20 @@ sctp_send_shutdown(struct sctp_tcb *stcb
 	SCTP_BUF_RESV_UF(m_shutdown, SCTP_MIN_OVERHEAD);
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		/* no memory */
 		sctp_m_freem(m_shutdown);
 		return;
 	}
 	chk->copy_by_ref = 0;
-	chk->send_size = sizeof(struct sctp_shutdown_chunk);
 	chk->rec.chunk_id.id = SCTP_SHUTDOWN;
 	chk->rec.chunk_id.can_take_data = 1;
+	chk->flags = 0;
+	chk->send_size = sizeof(struct sctp_shutdown_chunk);
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
 	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->data = m_shutdown;
 	chk->whoTo = net;
 	if (chk->whoTo) {
 		atomic_add_int(&chk->whoTo->ref_count, 1);
@@ -9518,23 +9632,23 @@ sctp_send_asconf(struct sctp_tcb *stcb, 
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		/* no memory */
 		sctp_m_freem(m_asconf);
 		return;
 	}
 
 	chk->copy_by_ref = 0;
-	chk->data = m_asconf;
-	chk->send_size = len;
 	chk->rec.chunk_id.id = SCTP_ASCONF;
 	chk->rec.chunk_id.can_take_data = 0;
+	chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
+	chk->data = m_asconf;
+	chk->send_size = len;
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
-	chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
 	chk->asoc = &stcb->asoc;
 	chk->whoTo = net;
 	if (chk->whoTo) {
 		atomic_add_int(&chk->whoTo->ref_count, 1);
 	}
 	TAILQ_INSERT_TAIL(&chk->asoc->asconf_send_queue, chk, sctp_next);
 	chk->asoc->ctrl_queue_cnt++;
 	return;
@@ -9596,48 +9710,41 @@ sctp_send_asconf_ack(struct sctp_tcb *st
 		/* copy the asconf_ack */
 		m_ack = SCTP_M_COPYM(ack->data, 0, M_COPYALL, M_NOWAIT);
 		if (m_ack == NULL) {
 			/* couldn't copy it */
 			return;
 		}
 #ifdef SCTP_MBUF_LOGGING
 		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-			struct mbuf *mat;
-
-			for (mat = m_ack; mat; mat = SCTP_BUF_NEXT(mat)) {
-				if (SCTP_BUF_IS_EXTENDED(mat)) {
-					sctp_log_mb(mat, SCTP_MBUF_ICOPY);
-				}
-			}
+			sctp_log_mbc(m_ack, SCTP_MBUF_ICOPY);
 		}
 #endif
 
 		sctp_alloc_a_chunk(stcb, chk);
 		if (chk == NULL) {
 			/* no memory */
 			if (m_ack)
 				sctp_m_freem(m_ack);
 			return;
 		}
 		chk->copy_by_ref = 0;
-
+		chk->rec.chunk_id.id = SCTP_ASCONF_ACK;
+		chk->rec.chunk_id.can_take_data = 1;
+		chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
 		chk->whoTo = net;
 		if (chk->whoTo) {
 			atomic_add_int(&chk->whoTo->ref_count, 1);
 		}
 		chk->data = m_ack;
 		chk->send_size = 0;
 		/* Get size */
 		chk->send_size = ack->len;
-		chk->rec.chunk_id.id = SCTP_ASCONF_ACK;
-		chk->rec.chunk_id.can_take_data = 1;
 		chk->sent = SCTP_DATAGRAM_UNSENT;
 		chk->snd_count = 0;
-		chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; /* XXX */
 		chk->asoc = &stcb->asoc;
 
 		TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
 		chk->asoc->ctrl_queue_cnt++;
 	}
 	return;
 }
 
@@ -10210,17 +10317,17 @@ sctp_chunk_output (struct sctp_inpcb *in
 	 *   FIRST/MIDDLE and LAST to the out queue in one pass) and assigning
 	 *   TSN's
 	 * - Check to see if the cwnd/rwnd allows any output, if so we
 	 *   go ahead and fomulate and send the low level chunks. Making sure
 	 *   to combine any control in the control chunk queue also.
 	 */
 	struct sctp_association *asoc;
 	struct sctp_nets *net;
-	int error = 0, num_out = 0, tot_out = 0, ret = 0, reason_code = 0;
+	int error = 0, num_out, tot_out = 0, ret = 0, reason_code;
 	unsigned int burst_cnt = 0;
 	struct timeval now;
 	int now_filled = 0;
 	int nagle_on;
 	int frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
 	int un_sent = 0;
 	int fr_done;
 	unsigned int tot_frs = 0;
@@ -10252,32 +10359,32 @@ sctp_chunk_output (struct sctp_inpcb *in
 	    (TAILQ_EMPTY(&asoc->asconf_send_queue)) &&
 	    (asoc->sent_queue_retran_cnt == 0)) {
 		/* Nothing to do unless there is something to be sent left */
 		return;
 	}
 	/* Do we have something to send, data or control AND
 	 * a sack timer running, if so piggy-back the sack.
 	 */
- 	if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
+	if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
 		sctp_send_sack(stcb, so_locked);
 		(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
 	}
 	while (asoc->sent_queue_retran_cnt) {
 		/*-
 		 * Ok, it is retransmission time only, we send out only ONE
 		 * packet with a single call off to the retran code.
 		 */
 		if (from_where == SCTP_OUTPUT_FROM_COOKIE_ACK) {
 			/*-
 			 * Special hook for handling cookiess discarded
 			 * by peer that carried data. Send cookie-ack only
 			 * and then the next call with get the retran's.
 			 */
- 			(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
+			(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
 						    from_where,
 						    &now, &now_filled, frag_point, so_locked);
 			return;
 		} else if (from_where != SCTP_OUTPUT_FROM_HB_TMR) {
 			/* if its not from a HB then do it */
 			fr_done = 0;
 			ret = sctp_chunk_retransmission(inp, stcb, asoc, &num_out, &now, &now_filled, &fr_done, so_locked);
 			if (fr_done) {
@@ -10540,16 +10647,17 @@ send_forward_tsn(struct sctp_tcb *stcb,
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		return;
 	}
 	asoc->fwd_tsn_cnt++;
 	chk->copy_by_ref = 0;
 	chk->rec.chunk_id.id = SCTP_FORWARD_CUM_TSN;
 	chk->rec.chunk_id.can_take_data = 0;
+	chk->flags = 0;
 	chk->asoc = asoc;
 	chk->whoTo = NULL;
 	chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
 	if (chk->data == NULL) {
 		sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
 		return;
 	}
 	SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -10721,18 +10829,17 @@ sctp_send_sack(struct sctp_tcb *stcb, in
 	unsigned int num_gap_blocks = 0, num_nr_gap_blocks = 0, space;
 	int num_dups = 0;
 	int space_req;
 	uint32_t highest_tsn;
 	uint8_t flags;
 	uint8_t type;
 	uint8_t tsn_map;
 
-	if ((stcb->asoc.sctp_nr_sack_on_off == 1) &&
-	    (stcb->asoc.peer_supports_nr_sack == 1)) {
+	if (stcb->asoc.nrsack_supported == 1) {
 		type = SCTP_NR_SELECTIVE_ACK;
 	} else {
 		type = SCTP_SELECTIVE_ACK;
 	}
 	a_chk = NULL;
 	asoc = &stcb->asoc;
 	SCTP_TCB_LOCK_ASSERT(stcb);
 	if (asoc->last_data_chunk_from == NULL) {
@@ -10774,16 +10881,17 @@ sctp_send_sack(struct sctp_tcb *stcb, in
 		}
 		a_chk->copy_by_ref = 0;
 		a_chk->rec.chunk_id.id = type;
 		a_chk->rec.chunk_id.can_take_data = 1;
 	}
 	/* Clear our pkt counts */
 	asoc->data_pkts_seen = 0;
 
+	a_chk->flags = 0;
 	a_chk->asoc = asoc;
 	a_chk->snd_count = 0;
 	a_chk->send_size = 0;	/* fill in later */
 	a_chk->sent = SCTP_DATAGRAM_UNSENT;
 	a_chk->whoTo = NULL;
 
 	if ((asoc->numduptsns) ||
 	    (!(asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE))) {
@@ -11183,17 +11291,18 @@ sctp_send_abort_tcb(struct sctp_tcb *stc
 		abort->ch.chunk_flags = SCTP_HAD_NO_TCB;
 	} else {
 		vtag = stcb->asoc.peer_vtag;
 		abort->ch.chunk_flags = 0;
 	}
 	abort->ch.chunk_length = htons(chunk_len);
 	/* Add padding, if necessary. */
 	if (padding_len > 0) {
-		if ((m_last == NULL) || sctp_add_pad_tombuf(m_last, padding_len)) {
+		if ((m_last == NULL) ||
+		    (sctp_add_pad_tombuf(m_last, padding_len) == NULL)) {
 			sctp_m_freem(m_out);
 			return;
 		}
 	}
 	(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
 	                                 (struct sockaddr *)&net->ro._l_addr,
 	                                 m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, 0,
 	                                 stcb->sctp_ep->sctp_lport, stcb->rport, htonl(vtag),
@@ -11247,17 +11356,17 @@ sctp_send_shutdown_complete(struct sctp_
 	return;
 }
 
 #if defined(__FreeBSD__)
 static void
 sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
                    struct sctphdr *sh, uint32_t vtag,
                    uint8_t type, struct mbuf *cause,
-                   uint8_t use_mflowid, uint32_t mflowid,
+                   uint8_t mflowtype, uint32_t mflowid,
                    uint32_t vrf_id, uint16_t port)
 #else
 static void
 sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
                    struct sctphdr *sh, uint32_t vtag,
                    uint8_t type, struct mbuf *cause,
                    uint32_t vrf_id SCTP_UNUSED, uint16_t port)
 #endif
@@ -11265,21 +11374,21 @@ sctp_send_resp_msg(struct sockaddr *src,
 #ifdef __Panda__
 	pakhandle_type o_pak;
 #else
 	struct mbuf *o_pak;
 #endif
 	struct mbuf *mout;
 	struct sctphdr *shout;
 	struct sctp_chunkhdr *ch;
+#if defined(INET) || defined(INET6)
 	struct udphdr *udp;
+	int ret;
+#endif
 	int len, cause_len, padding_len;
-#if defined(INET) || defined(INET6)
-	int ret;
-#endif
 #ifdef INET
 #if defined(__APPLE__) || defined(__Panda__)
 	sctp_route_t ro;
 #endif
 	struct sockaddr_in *src_sin, *dst_sin;
 	struct ip *ip;
 #endif
 #ifdef INET6
@@ -11297,17 +11406,17 @@ sctp_send_resp_msg(struct sockaddr *src,
 				m_last = m_at;
 			cause_len += SCTP_BUF_LEN(m_at);
 		}
 		padding_len = cause_len % 4;
 		if (padding_len != 0) {
 			padding_len = 4 - padding_len;
 		}
 		if (padding_len != 0) {
-			if (sctp_add_pad_tombuf(m_last, padding_len)) {
+			if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) {
 				sctp_m_freem(cause);
 				return;
 			}
 		}
 	} else {
 		padding_len = 0;
 	}
 	/* Get an mbuf for the header. */
@@ -11321,19 +11430,21 @@ sctp_send_resp_msg(struct sockaddr *src,
 #ifdef INET6
 	case AF_INET6:
 		len += sizeof(struct ip6_hdr);
 		break;
 #endif
 	default:
 		break;
 	}
+#if defined(INET) || defined(INET6)
 	if (port) {
 		len += sizeof(struct udphdr);
 	}
+#endif
 #if defined(__APPLE__)
 #if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD)
 	mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_NOWAIT, 1, MT_DATA);
 #else
 	mout = sctp_get_mbuf_for_msg(len + SCTP_MAX_LINKHDR, 1, M_NOWAIT, 1, MT_DATA);
 #endif
 #else
 	mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_NOWAIT, 1, MT_DATA);
@@ -11351,20 +11462,18 @@ sctp_send_resp_msg(struct sockaddr *src,
 	SCTP_BUF_RESV_UF(mout, SCTP_MAX_LINKHDR);
 #endif
 #else
 	SCTP_BUF_RESV_UF(mout, max_linkhdr);
 #endif
 	SCTP_BUF_LEN(mout) = len;
 	SCTP_BUF_NEXT(mout) = cause;
 #if defined(__FreeBSD__)
-	if (use_mflowid != 0) {
-		mout->m_pkthdr.flowid = mflowid;
-		mout->m_flags |= M_FLOWID;
-	}
+	mout->m_pkthdr.flowid = mflowid;
+	M_HASHTYPE_SET(mout, mflowtype);
 #endif
 #ifdef INET
 	ip = NULL;
 #endif
 #ifdef INET6
 	ip6 = NULL;
 #endif
 	switch (dst->sa_family) {
@@ -11428,16 +11537,17 @@ sctp_send_resp_msg(struct sockaddr *src,
 		shout = (struct sctphdr *)((caddr_t)ip6 + len);
 		break;
 #endif
 	default:
 		len = 0;
 		shout = mtod(mout, struct sctphdr *);
 		break;
 	}
+#if defined(INET) || defined(INET6)
 	if (port) {
 		if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) {
 			sctp_m_freem(mout);
 			return;
 		}
 		udp = (struct udphdr *)shout;
 		udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
 		udp->uh_dport = port;
@@ -11446,16 +11556,17 @@ sctp_send_resp_msg(struct sockaddr *src,
 		                     sizeof(struct sctphdr) +
 		                     sizeof(struct sctp_chunkhdr) +
 		                     cause_len + padding_len);
 		len += sizeof(struct udphdr);
 		shout = (struct sctphdr *)((caddr_t)shout + sizeof(struct udphdr));
 	} else {
 		udp = NULL;
 	}
+#endif
 	shout->src_port = sh->dest_port;
 	shout->dest_port = sh->src_port;
 	shout->checksum = 0;
 	if (vtag) {
 		shout->v_tag = htonl(vtag);
 	} else {
 		shout->v_tag = sh->v_tag;
 	}
@@ -11527,17 +11638,17 @@ sctp_send_resp_msg(struct sockaddr *src,
 			SCTP_ENABLE_UDP_CSUM(o_pak);
 #endif
 		} else {
 #if defined(SCTP_WITH_NO_CSUM)
 			SCTP_STAT_INCR(sctps_sendnocrc);
 #else
 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
 			mout->m_pkthdr.csum_flags = CSUM_SCTP;
-			mout->m_pkthdr.csum_data = 0;
+			mout->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum);
 			SCTP_STAT_INCR(sctps_sendhwcrc);
 #else
 			shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip));
 			SCTP_STAT_INCR(sctps_sendswcrc);
 #endif
 #endif
 		}
 #ifdef SCTP_PACKET_LOGGING
@@ -11579,17 +11690,17 @@ sctp_send_resp_msg(struct sockaddr *src,
 			SCTP_STAT_INCR(sctps_sendnocrc);
 #else
 #if defined(__FreeBSD__) && __FreeBSD_version >= 900000
 #if __FreeBSD_version > 901000
 			mout->m_pkthdr.csum_flags = CSUM_SCTP_IPV6;
 #else
 			mout->m_pkthdr.csum_flags = CSUM_SCTP;
 #endif
-			mout->m_pkthdr.csum_data = 0;
+			mout->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum);
 			SCTP_STAT_INCR(sctps_sendhwcrc);
 #else
 			shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip6_hdr));
 			SCTP_STAT_INCR(sctps_sendswcrc);
 #endif
 #endif
 		}
 #ifdef SCTP_PACKET_LOGGING
@@ -11640,23 +11751,23 @@ sctp_send_resp_msg(struct sockaddr *src,
 	SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
 	return;
 }
 
 void
 sctp_send_shutdown_complete2(struct sockaddr *src, struct sockaddr *dst,
                              struct sctphdr *sh,
 #if defined(__FreeBSD__)
-                             uint8_t use_mflowid, uint32_t mflowid,
+                             uint8_t mflowtype, uint32_t mflowid,
 #endif
                              uint32_t vrf_id, uint16_t port)
 {
 	sctp_send_resp_msg(src, dst, sh, 0, SCTP_SHUTDOWN_COMPLETE, NULL,
 #if defined(__FreeBSD__)
-	                   use_mflowid, mflowid,
+	                   mflowtype, mflowid,
 #endif
 	                   vrf_id, port);
 }
 
 void
 sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net,int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
 	SCTP_UNUSED
@@ -11692,16 +11803,17 @@ sctp_send_hb(struct sctp_tcb *stcb, stru
 	if (chk == NULL) {
 		SCTPDBG(SCTP_DEBUG_OUTPUT4, "Gak, can't get a chunk for hb\n");
 		return;
 	}
 
 	chk->copy_by_ref = 0;
 	chk->rec.chunk_id.id = SCTP_HEARTBEAT_REQUEST;
 	chk->rec.chunk_id.can_take_data = 1;
+	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->send_size = sizeof(struct sctp_heartbeat_chunk);
 
 	chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_NOWAIT, 1, MT_HEADER);
 	if (chk->data == NULL) {
 		sctp_free_a_chunk(stcb, chk, so_locked);
 		return;
 	}
@@ -11719,17 +11831,17 @@ sctp_send_hb(struct sctp_tcb *stcb, stru
 	hb->ch.chunk_flags = 0;
 	hb->ch.chunk_length = htons(chk->send_size);
 	/* Fill out hb parameter */
 	hb->heartbeat.hb_info.ph.param_type = htons(SCTP_HEARTBEAT_INFO);
 	hb->heartbeat.hb_info.ph.param_length = htons(sizeof(struct sctp_heartbeat_info_param));
 	hb->heartbeat.hb_info.time_value_1 = now.tv_sec;
 	hb->heartbeat.hb_info.time_value_2 = now.tv_usec;
 	/* Did our user request this one, put it in */
-	hb->heartbeat.hb_info.addr_family = net->ro._l_addr.sa.sa_family;
+	hb->heartbeat.hb_info.addr_family = (uint8_t)net->ro._l_addr.sa.sa_family;
 #ifdef HAVE_SA_LEN
 	hb->heartbeat.hb_info.addr_len = net->ro._l_addr.sa.sa_len;
 #else
 	switch (net->ro._l_addr.sa.sa_family) {
 #ifdef INET
 	case AF_INET:
 		hb->heartbeat.hb_info.addr_len = sizeof(struct sockaddr_in);
 		break;
@@ -11822,20 +11934,21 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb
 			return;
 		}
 	}
 	/* nope could not find one to update so we must build one */
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		return;
 	}
+	SCTP_STAT_INCR(sctps_queue_upd_ecne);
 	chk->copy_by_ref = 0;
-	SCTP_STAT_INCR(sctps_queue_upd_ecne);
 	chk->rec.chunk_id.id = SCTP_ECN_ECHO;
 	chk->rec.chunk_id.can_take_data = 0;
+	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->send_size = sizeof(struct sctp_ecne_chunk);
 	chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_NOWAIT, 1, MT_HEADER);
 	if (chk->data == NULL) {
 		sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
 		return;
 	}
 	SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -11871,30 +11984,33 @@ sctp_send_packet_dropped(struct sctp_tcb
 	struct sctp_chunkhdr *ch, chunk_buf;
 	unsigned int chk_length;
 
         if (!stcb) {
             return;
         }
 	asoc = &stcb->asoc;
 	SCTP_TCB_LOCK_ASSERT(stcb);
-	if (asoc->peer_supports_pktdrop == 0) {
+	if (asoc->pktdrop_supported == 0) {
 		/*-
 		 * peer must declare support before I send one.
 		 */
 		return;
 	}
 	if (stcb->sctp_socket == NULL) {
 		return;
 	}
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		return;
 	}
 	chk->copy_by_ref = 0;
+	chk->rec.chunk_id.id = SCTP_PACKET_DROPPED;
+	chk->rec.chunk_id.can_take_data = 1;
+	chk->flags = 0;
 	len -= iphlen;
 	chk->send_size = len;
         /* Validate that we do not have an ABORT in here. */
 	offset = iphlen + sizeof(struct sctphdr);
 	ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
 						   sizeof(*ch), (uint8_t *) & chunk_buf);
 	while (ch != NULL) {
 		chk_length = ntohs(ch->chunk_length);
@@ -11970,18 +12086,16 @@ jump_out:
 	chk->snd_count = 0;
 	if (net) {
 		/* we should hit here */
 		chk->whoTo = net;
 		atomic_add_int(&chk->whoTo->ref_count, 1);
 	} else {
 		chk->whoTo = NULL;
 	}
-	chk->rec.chunk_id.id = SCTP_PACKET_DROPPED;
-	chk->rec.chunk_id.can_take_data = 1;
 	drp->ch.chunk_type = SCTP_PACKET_DROPPED;
 	drp->ch.chunk_length = htons(chk->send_size);
 	spc = SCTP_SB_LIMIT_RCV(stcb->sctp_socket);
 	if (spc < 0) {
 		spc = 0;
 	}
 	drp->bottle_bw = htonl(spc);
 	if (asoc->my_rwnd) {
@@ -12033,16 +12147,17 @@ sctp_send_cwr(struct sctp_tcb *stcb, str
 	}
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		return;
 	}
 	chk->copy_by_ref = 0;
 	chk->rec.chunk_id.id = SCTP_ECN_CWR;
 	chk->rec.chunk_id.can_take_data = 1;
+	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->send_size = sizeof(struct sctp_cwr_chunk);
 	chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_NOWAIT, 1, MT_HEADER);
 	if (chk->data == NULL) {
 		sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
 		return;
 	}
 	SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -12295,17 +12410,17 @@ sctp_add_an_in_stream(struct sctp_tmit_c
 	chk->book_size = SCTP_SIZE32(chk->send_size);
 	chk->book_size_scale = 0;
 	SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
 	return;
 }
 
 int
 sctp_send_str_reset_req(struct sctp_tcb *stcb,
-                        int number_entries, uint16_t *list,
+                        uint16_t number_entries, uint16_t *list,
                         uint8_t send_out_req,
                         uint8_t send_in_req,
                         uint8_t send_tsn_req,
                         uint8_t add_stream,
                         uint16_t adding_o,
                         uint16_t adding_i, uint8_t peer_asked)
 {
 
@@ -12328,24 +12443,33 @@ sctp_send_str_reset_req(struct sctp_tcb 
 		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
 		return (EINVAL);
 	}
 	if (send_tsn_req && (send_out_req || send_in_req)) {
 		/* error, can't do that */
 		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
 		return (EINVAL);
 	}
+	if (number_entries > (MCLBYTES -
+	                      SCTP_MIN_OVERHEAD -
+	                      sizeof(struct sctp_chunkhdr) -
+	                      sizeof(struct sctp_stream_reset_out_request)) /
+	                     sizeof(uint16_t)) {
+		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+		return (ENOMEM);
+	}
 	sctp_alloc_a_chunk(stcb, chk);
 	if (chk == NULL) {
 		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
 		return (ENOMEM);
 	}
 	chk->copy_by_ref = 0;
 	chk->rec.chunk_id.id = SCTP_STREAM_RESET;
 	chk->rec.chunk_id.can_take_data = 0;
+	chk->flags = 0;
 	chk->asoc = &stcb->asoc;
 	chk->book_size = sizeof(struct sctp_chunkhdr);
 	chk->send_size = SCTP_SIZE32(chk->book_size);
 	chk->book_size_scale = 0;
 
 	chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
 	if (chk->data == NULL) {
 		sctp_free_a_chunk(stcb, chk, SCTP_SO_LOCKED);
@@ -12378,16 +12502,19 @@ sctp_send_str_reset_req(struct sctp_tcb 
 		asoc->stream_reset_outstanding++;
 	}
 	if ((add_stream & 1) &&
 	    ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < adding_o)) {
 		/* Need to allocate more */
 		struct sctp_stream_out *oldstream;
 		struct sctp_stream_queue_pending *sp, *nsp;
 		int i;
+#if defined(SCTP_DETAILED_STR_STATS)
+		int j;
+#endif
 
 		oldstream = stcb->asoc.strmout;
 		/* get some more */
 		SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *,
 			    ((stcb->asoc.streamoutcnt+adding_o) * sizeof(struct sctp_stream_out)),
 			    SCTP_M_STRMO);
 		if (stcb->asoc.strmout == NULL) {
 			uint8_t x;
@@ -12422,16 +12549,25 @@ sctp_send_str_reset_req(struct sctp_tcb 
 				stcb->asoc.locked_on_sending = &stcb->asoc.strmout[i];
 			}
 		}
 		/* now the new streams */
 		stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
 		for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt + adding_o); i++) {
 			TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
 			stcb->asoc.strmout[i].chunks_on_queues = 0;
+#if defined(SCTP_DETAILED_STR_STATS)
+			for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
+				stcb->asoc.strmout[i].abandoned_sent[j] = 0;
+				stcb->asoc.strmout[i].abandoned_unsent[j] = 0;
+			}
+#else
+			stcb->asoc.strmout[i].abandoned_sent[0] = 0;
+			stcb->asoc.strmout[i].abandoned_unsent[0] = 0;
+#endif
 			stcb->asoc.strmout[i].next_sequence_send = 0x0;
 			stcb->asoc.strmout[i].stream_no = i;
 			stcb->asoc.strmout[i].last_msg_incomplete = 0;
 			stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
 		}
 		stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + adding_o;
 		SCTP_FREE(oldstream, SCTP_M_STRMO);
 		SCTP_TCB_SEND_UNLOCK(stcb);
@@ -12467,45 +12603,45 @@ skip_stuff:
 	sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
 	return (0);
 }
 
 void
 sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockaddr *dst,
                 struct sctphdr *sh, uint32_t vtag, struct mbuf *cause,
 #if defined(__FreeBSD__)
-                uint8_t use_mflowid, uint32_t mflowid,
+                uint8_t mflowtype, uint32_t mflowid,
 #endif
                 uint32_t vrf_id, uint16_t port)
 {
 	/* Don't respond to an ABORT with an ABORT. */
 	if (sctp_is_there_an_abort_here(m, iphlen, &vtag)) {
 		if (cause)
 			sctp_m_freem(cause);
 		return;
 	}
 	sctp_send_resp_msg(src, dst, sh, vtag, SCTP_ABORT_ASSOCIATION, cause,
 #if defined(__FreeBSD__)
-	                   use_mflowid, mflowid,
+	                   mflowtype, mflowid,
 #endif
 	                   vrf_id, port);
 	return;
 }
 
 void
 sctp_send_operr_to(struct sockaddr *src, struct sockaddr *dst,
                    struct sctphdr *sh, uint32_t vtag, struct mbuf *cause,
 #if defined(__FreeBSD__)
-                   uint8_t use_mflowid, uint32_t mflowid,
+                   uint8_t mflowtype, uint32_t mflowid,
 #endif
                    uint32_t vrf_id, uint16_t port)
 {
 	sctp_send_resp_msg(src, dst, sh, vtag, SCTP_OPERATION_ERROR, cause,
 #if defined(__FreeBSD__)
-	                   use_mflowid, mflowid,
+	                   mflowtype, mflowid,
 #endif
 	                   vrf_id, port);
 	return;
 }
 
 static struct mbuf *
 sctp_copy_resume(struct uio *uio,
 		 int max_send_len,
@@ -12517,54 +12653,54 @@ sctp_copy_resume(struct uio *uio,
 		 struct mbuf **new_tail)
 {
 #if defined(__Panda__)
 	struct mbuf *m;
 
 	m = m_uiotombuf(uio, M_WAITOK, max_send_len, 0,
 			(user_marks_eor ? M_EOR : 0));
 	if (m == NULL) {
-		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-		*error = ENOMEM;
+		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+		*error = ENOBUFS;
 	} else {
 		*sndout = m_length(m, NULL);
 		*new_tail = m_last(m);
 	}
 	return (m);
 #elif defined(__FreeBSD__) && __FreeBSD_version > 602000
 	struct mbuf *m;
 
 	m = m_uiotombuf(uio, M_WAITOK, max_send_len, 0,
 		(M_PKTHDR | (user_marks_eor ? M_EOR : 0)));
 	if (m == NULL) {
-		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-		*error = ENOMEM;
+		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+		*error = ENOBUFS;
 	} else {
 		*sndout = m_length(m, NULL);
 		*new_tail = m_last(m);
 	}
 	return (m);
 #else
 	int left, cancpy, willcpy;
 	struct mbuf *m, *head;
 
 #if defined(__APPLE__)
 #if defined(APPLE_LEOPARD)
-        left = min(uio->uio_resid, max_send_len);
-#else
-        left = min(uio_resid(uio), max_send_len);
-#endif
-#else
-        left = min(uio->uio_resid, max_send_len);
+	left = min(uio->uio_resid, max_send_len);
+#else
+	left = min(uio_resid(uio), max_send_len);
+#endif
+#else
+	left = min(uio->uio_resid, max_send_len);
 #endif
 	/* Always get a header just in case */
 	head = sctp_get_mbuf_for_msg(left, 0, M_WAITOK, 0, MT_DATA);
 	if (head == NULL) {
-		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-		*error = ENOMEM;
+		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+		*error = ENOBUFS;
 		return (NULL);
 	}
 	cancpy = M_TRAILINGSPACE(head);
 	willcpy = min(cancpy, left);
 	*error = uiomove(mtod(head, caddr_t), willcpy, uio);
 	if (*error) {
 		sctp_m_freem(head);
 		return (NULL);
@@ -12575,18 +12711,18 @@ sctp_copy_resume(struct uio *uio,
 	m = head;
 	*new_tail = head;
 	while (left > 0) {
 		/* move in user data */
 		SCTP_BUF_NEXT(m) = sctp_get_mbuf_for_msg(left, 0, M_WAITOK, 0, MT_DATA);
 		if (SCTP_BUF_NEXT(m) == NULL) {
 			sctp_m_freem(head);
 			*new_tail = NULL;
-			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-			*error = ENOMEM;
+			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+			*error = ENOBUFS;
 			return (NULL);
 		}
 		m = SCTP_BUF_NEXT(m);
 		cancpy = M_TRAILINGSPACE(m);
 		willcpy = min(cancpy, left);
 		*error = uiomove(mtod(m, caddr_t), willcpy, uio);
 		if (*error) {
 			sctp_m_freem(head);
@@ -12604,54 +12740,54 @@ sctp_copy_resume(struct uio *uio,
 		}
 	}
 	return (head);
 #endif
 }
 
 static int
 sctp_copy_one(struct sctp_stream_queue_pending *sp,
-	      struct uio *uio,
-	      int resv_upfront)
+              struct uio *uio,
+              int resv_upfront)
 {
 	int left;
 #if defined(__Panda__)
 	left = sp->length;
 	sp->data = m_uiotombuf(uio, M_WAITOK, sp->length,
-			       resv_upfront, 0);
+	                       resv_upfront, 0);
 	if (sp->data == NULL) {
-		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-		return (ENOMEM);
+		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+		return (ENOBUFS);
 	}
 
 	sp->tail_mbuf = m_last(sp->data);
 	return (0);
 
 #elif defined(__FreeBSD__) && __FreeBSD_version > 602000
 	left = sp->length;
 	sp->data = m_uiotombuf(uio, M_WAITOK, sp->length,
-			       resv_upfront, 0);
+	                       resv_upfront, 0);
 	if (sp->data == NULL) {
-		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-		return (ENOMEM);
+		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+		return (ENOBUFS);
 	}
 
 	sp->tail_mbuf = m_last(sp->data);
 	return (0);
 #else
 	int cancpy, willcpy, error;
 	struct mbuf *m, *head;
 	int cpsz = 0;
 
 	/* First one gets a header */
 	left = sp->length;
 	head = m = sctp_get_mbuf_for_msg((left + resv_upfront), 0, M_WAITOK, 0, MT_DATA);
 	if (m == NULL) {
-		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-		return (ENOMEM);
+		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+		return (ENOBUFS);
 	}
 	/*-
 	 * Add this one for m in now, that way if the alloc fails we won't
 	 * have a bad cnt.
 	 */
 	SCTP_BUF_RESV_UF(m, resv_upfront);
 	cancpy = M_TRAILINGSPACE(m);
 	willcpy = min(cancpy, left);
@@ -12668,18 +12804,18 @@ sctp_copy_one(struct sctp_stream_queue_p
 		if (left > 0) {
 			SCTP_BUF_NEXT(m) = sctp_get_mbuf_for_msg(left, 0, M_WAITOK, 0, MT_DATA);
 			if (SCTP_BUF_NEXT(m) == NULL) {
 				/*
 				 * the head goes back to caller, he can free
 				 * the rest
 				 */
 				sctp_m_freem(head);
-				SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
-				return (ENOMEM);
+				SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
+				return (ENOBUFS);
 			}
 			m = SCTP_BUF_NEXT(m);
 			cancpy = M_TRAILINGSPACE(m);
 			willcpy = min(cancpy, left);
 		} else {
 			sp->tail_mbuf = m;
 			SCTP_BUF_NEXT(m) = NULL;
 		}
@@ -13295,25 +13431,24 @@ sctp_lower_sosend(struct socket *so,
 			error = EMSGSIZE;
 			goto out_unlocked;
 		}
 	}
 #if defined(__Userspace__)
 	if (inp->recv_callback) {
 		non_blocking = 1;
 	}
-#else
+#endif
 	if (SCTP_SO_IS_NBIO(so)
 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
 	     || (flags & MSG_NBIO)
 #endif
 	    ) {
 		non_blocking = 1;
 	}
-#endif
 	/* would we block? */
 	if (non_blocking) {
 		if (hold_tcblock == 0) {
 			SCTP_TCB_LOCK(stcb);
 			hold_tcblock = 1;
 		}
 		inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
 		if ((SCTP_SB_LIMIT_SND(so) <  (sndlen + inqueue_bytes + stcb->asoc.sb_send_resv)) ||
@@ -13782,17 +13917,17 @@ skip_preblock:
 #endif
 #else
 			if (uio->uio_resid == 0) {
 #endif
 				/* got it all? */
 				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 */
 				if (hold_tcblock == 0) {
 					SCTP_TCB_LOCK(stcb);
 					hold_tcblock = 1;
 				}
 				sctp_prune_prsctp(stcb, asoc, srcv, sndlen);
 				inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
 				if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size)
@@ -14281,22 +14416,17 @@ sctp_add_auth_chunk(struct mbuf *m, stru
 	struct sctp_auth_chunk *auth;
 	int chunk_len;
 	struct mbuf *cn;
 
 	if ((m_end == NULL) || (auth_ret == NULL) || (offset == NULL) ||
 	    (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? */
 	if (!sctp_auth_is_required_chunk(chunk, stcb->asoc.peer_auth_chunks)) {
 		return (m);
 	}
 	m_auth = sctp_get_mbuf_for_msg(sizeof(*auth), 0, M_NOWAIT, 1, MT_HEADER);
 	if (m_auth == NULL) {
@@ -14395,17 +14525,17 @@ sctp_v4src_match_nexthop(struct sctp_ifa
 	struct in_addr srcnetaddr, gwnetaddr;
 
 	if (ro == NULL || ro->ro_rt == NULL ||
 	    sifa->address.sa.sa_family != AF_INET) {
 		return (0);
 	}
 	ifa = (struct ifaddr *)sifa->ifa;
 	mask = (struct sockaddr_in *)(ifa->ifa_netmask);
-	sin = (struct sockaddr_in *)&sifa->address.sin;
+	sin = &sifa->address.sin;
 	srcnetaddr.s_addr = (sin->sin_addr.s_addr & mask->sin_addr.s_addr);
 	SCTPDBG(SCTP_DEBUG_OUTPUT1, "match_nexthop4: src address is ");
 	SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, &sifa->address.sa);
 	SCTPDBG(SCTP_DEBUG_OUTPUT1, "network address is %x\n", srcnetaddr.s_addr);
 
 	sin = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
 	gwnetaddr.s_addr = (sin->sin_addr.s_addr & mask->sin_addr.s_addr);
 	SCTPDBG(SCTP_DEBUG_OUTPUT1, "match_nexthop4: nexthop is ");
--- a/netwerk/sctp/src/netinet/sctp_output.h
+++ b/netwerk/sctp/src/netinet/sctp_output.h
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 246595 2013-02-09 17:26:14Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 272751 2014-10-08 15:30:59Z tuexen $");
 #endif
 
 #ifndef _NETINET_SCTP_OUTPUT_H_
 #define _NETINET_SCTP_OUTPUT_H_
 
 #include <netinet/sctp_header.h>
 
 #if defined(_KERNEL) || defined(__Userspace__)
@@ -203,18 +203,18 @@ sctp_add_stream_reset_out(struct sctp_tm
 void
 sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t);
 
 void
 sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *,
                                  uint32_t, uint32_t, uint32_t, uint32_t);
 
 int
-sctp_send_str_reset_req(struct sctp_tcb *, int , uint16_t *, uint8_t, uint8_t,
-			uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
+sctp_send_str_reset_req(struct sctp_tcb *, uint16_t , uint16_t *, uint8_t,
+                        uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
 
 void
 sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *,
                 struct sctphdr *, uint32_t, struct mbuf *,
 #if defined(__FreeBSD__)
                 uint8_t, uint32_t,
 #endif
                 uint32_t, uint16_t);
--- a/netwerk/sctp/src/netinet/sctp_pcb.c
+++ b/netwerk/sctp/src/netinet/sctp_pcb.c
@@ -27,17 +27,17 @@
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 258765 2013-11-30 12:51:19Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 277031 2015-01-11 21:55:30Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
 #ifdef __FreeBSD__
 #include <sys/proc.h>
 #endif
 #include <netinet/sctp_var.h>
 #include <netinet/sctp_sysctl.h>
@@ -47,19 +47,21 @@
 #include <netinet/sctp_header.h>
 #include <netinet/sctp_asconf.h>
 #include <netinet/sctp_output.h>
 #include <netinet/sctp_timer.h>
 #include <netinet/sctp_bsd_addr.h>
 #if defined(__FreeBSD__) && __FreeBSD_version >= 803000
 #include <netinet/sctp_dtrace_define.h>
 #endif
+#if defined(INET) || defined(INET6)
 #if !defined(__Userspace_os_Windows)
 #include <netinet/udp.h>
 #endif
+#endif
 #ifdef INET6
 #if defined(__Userspace__)
 #include "user_ip6_var.h"
 #else
 #include <netinet6/ip6_var.h>
 #endif
 #endif
 #if defined(__FreeBSD__)
@@ -217,18 +219,18 @@ sctp_allocate_vrf(int vrf_id)
 	/* First allocate the VRF structure */
 	vrf = sctp_find_vrf(vrf_id);
 	if (vrf) {
 		/* Already allocated */
 		return (vrf);
 	}
 	SCTP_MALLOC(vrf, struct sctp_vrf *, sizeof(struct sctp_vrf),
 		    SCTP_M_VRF);
- 	if (vrf == NULL) {
- 		/* No memory */
+	if (vrf == NULL) {
+		/* No memory */
 #ifdef INVARIANTS
 		panic("No memory for VRF:%d", vrf_id);
 #endif
 		return (NULL);
 	}
 	/* setup the VRF */
 	memset(vrf, 0, sizeof(struct sctp_vrf));
 	vrf->vrf_id = vrf_id;
@@ -236,17 +238,17 @@ sctp_allocate_vrf(int vrf_id)
 	vrf->total_ifa_count = 0;
 	vrf->refcount = 0;
 	/* now also setup table ids */
 	SCTP_INIT_VRF_TABLEID(vrf);
 	/* Init the HASH of addresses */
 	vrf->vrf_addr_hash = SCTP_HASH_INIT(SCTP_VRF_ADDR_HASH_SIZE,
 					    &vrf->vrf_addr_hashmark);
 	if (vrf->vrf_addr_hash == NULL) {
- 		/* No memory */
+		/* No memory */
 #ifdef INVARIANTS
 		panic("No memory for VRF:%d", vrf_id);
 #endif
 		SCTP_FREE(vrf, SCTP_M_VRF);
 		return (NULL);
 	}
 
 	/* Add it to the hash table */
@@ -649,17 +651,17 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, vo
 				SCTPDBG(SCTP_DEBUG_PCB4, "Moving ifa %p from %s (0x%x) to %s (0x%x)\n",
 					(void *)sctp_ifap, sctp_ifap->ifn_p->ifn_name,
 					sctp_ifap->ifn_p->ifn_index, if_name,
 					ifn_index);
 				/* remove the address from the old ifn */
 				sctp_remove_ifa_from_ifn(sctp_ifap);
 				/* move the address over to the new ifn */
 				sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap);
- 				goto exit_stage_left;
+				goto exit_stage_left;
 			} else {
 				/* repair ifnp which was NULL ? */
 				sctp_ifap->localifa_flags = SCTP_ADDR_VALID;
 				SCTPDBG(SCTP_DEBUG_PCB4, "Repairing ifn %p for ifa %p\n",
 					(void *)sctp_ifnp, (void *)sctp_ifap);
 				sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap);
 			}
 			goto exit_stage_left;
@@ -706,17 +708,17 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, vo
 	sctp_ifap->flags = ifa_flags;
 	/* Set scope */
 	switch (sctp_ifap->address.sa.sa_family) {
 #ifdef INET
 	case AF_INET:
 	{
 		struct sockaddr_in *sin;
 
-		sin = (struct sockaddr_in *)&sctp_ifap->address.sin;
+		sin = &sctp_ifap->address.sin;
 		if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) ||
 		    (IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) {
 			sctp_ifap->src_is_loop = 1;
 		}
 		if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
 			sctp_ifap->src_is_priv = 1;
 		}
 		sctp_ifnp->num_v4++;
@@ -726,17 +728,17 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, vo
 	}
 #endif
 #ifdef INET6
 	case AF_INET6:
 	{
 		/* ok to use deprecated addresses? */
 		struct sockaddr_in6 *sin6;
 
-		sin6 = (struct sockaddr_in6 *)&sctp_ifap->address.sin6;
+		sin6 = &sctp_ifap->address.sin6;
 		if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) ||
 		    (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) {
 			sctp_ifap->src_is_loop = 1;
 		}
 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 			sctp_ifap->src_is_priv = 1;
 		}
 		sctp_ifnp->num_v6++;
@@ -860,17 +862,23 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, 
 				SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d ifname:%s - ignoring delete\n",
 					sctp_ifap->ifn_p->ifn_index, sctp_ifap->ifn_p->ifn_name);
 				SCTP_IPI_ADDR_WUNLOCK();
 				return;
 			}
 		}
 		SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", (void *)sctp_ifap);
 		sctp_ifap->localifa_flags &= SCTP_ADDR_VALID;
-		sctp_ifap->localifa_flags |= SCTP_BEING_DELETED;
+                /*
+		 * We don't set the flag. This means that the structure will
+		 * hang around in EP's that have bound specific to it until
+		 * they close. This gives us TCP like behavior if someone
+		 * removes an address (or for that matter adds it right back).
+		 */
+		/* sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; */
 		vrf->total_ifa_count--;
 		LIST_REMOVE(sctp_ifap, next_bucket);
 		sctp_remove_ifa_from_ifn(sctp_ifap);
 	}
 #ifdef SCTP_DEBUG
 	else {
 		SCTPDBG(SCTP_DEBUG_PCB4, "Del Addr-ifn:%d Could not find address:",
 			ifn_index);
@@ -981,32 +989,44 @@ sctp_does_stcb_own_this_addr(struct sctp
 						struct sockaddr_in *sin, *rsin;
 
 						sin = &sctp_ifa->address.sin;
 						rsin = (struct sockaddr_in *)to;
 						if ((ipv4_local_scope == 0) &&
 						    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
 							continue;
 						}
+#if defined(__FreeBSD__)
+						if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
+						                     &sin->sin_addr) != 0) {
+							continue;
+						}
+#endif
 						if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
 							SCTP_IPI_ADDR_RUNLOCK();
 							return (1);
 						}
 					}
 					break;
 #endif
 #ifdef INET6
 				case AF_INET6:
 					if (ipv6_addr_legal) {
 						struct sockaddr_in6 *sin6, *rsin6;
 #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
 						struct sockaddr_in6 lsa6;
 #endif
 						sin6 = &sctp_ifa->address.sin6;
 						rsin6 = (struct sockaddr_in6 *)to;
+#if defined(__FreeBSD__)
+						if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
+						                     &sin6->sin6_addr) != 0) {
+							continue;
+						}
+#endif
 						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 							if (local_scope == 0)
 								continue;
 #if defined(SCTP_EMBEDDED_V6_SCOPE)
 							if (sin6->sin6_scope_id == 0) {
 #ifdef SCTP_KAME
 								if (sa6_recoverscope(sin6) != 0)
 									continue;
@@ -1072,46 +1092,46 @@ sctp_does_stcb_own_this_addr(struct sctp
 				continue;
 			}
 			switch (to->sa_family) {
 #ifdef INET
 			case AF_INET:
 			{
 				struct sockaddr_in *sin, *rsin;
 
-				sin = (struct sockaddr_in *)&laddr->ifa->address.sin;
+				sin = &laddr->ifa->address.sin;
 				rsin = (struct sockaddr_in *)to;
 				if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
 					SCTP_IPI_ADDR_RUNLOCK();
 					return (1);
 				}
 				break;
 			}
 #endif
 #ifdef INET6
 			case AF_INET6:
 			{
 				struct sockaddr_in6 *sin6, *rsin6;
 
-				sin6 = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
+				sin6 = &laddr->ifa->address.sin6;
 				rsin6 = (struct sockaddr_in6 *)to;
 				if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
 					SCTP_IPI_ADDR_RUNLOCK();
 					return (1);
 				}
 				break;
 			}
 
 #endif
 #if defined(__Userspace__)
 			case AF_CONN:
 			{
 				struct sockaddr_conn *sconn, *rsconn;
 
-				sconn = (struct sockaddr_conn *)&laddr->ifa->address.sconn;
+				sconn = &laddr->ifa->address.sconn;
 				rsconn = (struct sockaddr_conn *)to;
 				if (sconn->sconn_addr == rsconn->sconn_addr) {
 					SCTP_IPI_ADDR_RUNLOCK();
 					return (1);
 				}
 				break;
 			}
 #endif
@@ -1196,16 +1216,51 @@ sctp_tcb_special_locate(struct sctp_inpc
 		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
 			SCTP_INP_RUNLOCK(inp);
 			continue;
 		}
 		if (lport != inp->sctp_lport) {
 			SCTP_INP_RUNLOCK(inp);
 			continue;
 		}
+#if defined(__FreeBSD__)
+		switch (to->sa_family) {
+#ifdef INET
+		case AF_INET:
+		{
+			struct sockaddr_in *sin;
+
+			sin = (struct sockaddr_in *)to;
+			if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+			                     &sin->sin_addr) != 0) {
+				SCTP_INP_RUNLOCK(inp);
+				continue;
+			}
+			break;
+		}
+#endif
+#ifdef INET6
+		case AF_INET6:
+		{
+			struct sockaddr_in6 *sin6;
+
+			sin6 = (struct sockaddr_in6 *)to;
+			if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+			                     &sin6->sin6_addr) != 0) {
+				SCTP_INP_RUNLOCK(inp);
+				continue;
+			}
+			break;
+		}
+#endif
+		default:
+			SCTP_INP_RUNLOCK(inp);
+			continue;
+		}
+#endif
 #ifdef SCTP_MVRF
 		fnd = 0;
 		for (i = 0; i < inp->num_vrfs; i++) {
 			if (inp->m_vrf_ids[i] == vrf_id) {
 				fnd = 1;
 				break;
 			}
 		}
@@ -1629,20 +1684,17 @@ sctp_findassociation_ep_addr(struct sctp
 			SCTP_TCB_UNLOCK(stcb);
 		}
 	} else {
 		SCTP_INP_WLOCK(inp);
 		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
 			goto null_return;
 		}
 		head = &inp->sctp_tcbhash[SCTP_PCBHASH_ALLADDR(rport,
-		    inp->sctp_hashmark)];
-		if (head == NULL) {
-			goto null_return;
-		}
+		                                               inp->sctp_hashmark)];
 		LIST_FOREACH(stcb, head, sctp_tcbhash) {
 			if (stcb->rport != rport) {
 				/* remote port does not match */
 				continue;
 			}
 			SCTP_TCB_LOCK(stcb);
 			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
 				SCTP_TCB_UNLOCK(stcb);
@@ -1896,33 +1948,53 @@ sctp_endpoint_probe(struct sockaddr *nam
 		SCTP_INP_RLOCK(inp);
 		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
 			SCTP_INP_RUNLOCK(inp);
 			continue;
 		}
 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) &&
 		    (inp->sctp_lport == lport)) {
 			/* got it */
+			switch (nam->sa_family) {
 #ifdef INET
-			if ((nam->sa_family == AF_INET) &&
-			    (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
-			    SCTP_IPV6_V6ONLY(inp)) {
-				/* IPv4 on a IPv6 socket with ONLY IPv6 set */
-				SCTP_INP_RUNLOCK(inp);
-				continue;
-			}
+			case AF_INET:
+				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
+				    SCTP_IPV6_V6ONLY(inp)) {
+					/* IPv4 on a IPv6 socket with ONLY IPv6 set */
+					SCTP_INP_RUNLOCK(inp);
+					continue;
+				}
+#if defined(__FreeBSD__)
+				if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
+				                     &sin->sin_addr) != 0) {
+					SCTP_INP_RUNLOCK(inp);
+					continue;
+				}
+#endif
+				break;
 #endif
 #ifdef INET6
-			/* A V6 address and the endpoint is NOT bound V6 */
-			if (nam->sa_family == AF_INET6 &&
-			    (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
-				SCTP_INP_RUNLOCK(inp);
-				continue;
-			}
-#endif
+			case AF_INET6:
+				/* A V6 address and the endpoint is NOT bound V6 */
+				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
+					SCTP_INP_RUNLOCK(inp);
+					continue;
+				}
+#if defined(__FreeBSD__)
+				if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
+				                     &sin6->sin6_addr) != 0) {
+					SCTP_INP_RUNLOCK(inp);
+					continue;
+				}
+#endif
+				break;
+#endif
+			default:
+				break;
+			}
 			/* does a VRF id match? */
 			fnd = 0;
 #ifdef SCTP_MVRF
 			for (i = 0; i < inp->num_vrfs; i++) {
 				if (inp->m_vrf_ids[i] == vrf_id) {
 					fnd = 1;
 					break;
 				}
@@ -2427,22 +2499,17 @@ sctp_findassoc_by_vtag(struct sockaddr *
 	struct sctp_nets *net;
 	struct sctp_tcb *stcb;
 #ifdef SCTP_MVRF
 	unsigned int i;
 #endif
 
 	SCTP_INP_INFO_RLOCK();
 	head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(vtag,
-	    SCTP_BASE_INFO(hashasocmark))];
-	if (head == NULL) {
-		/* invalid vtag */
-		SCTP_INP_INFO_RUNLOCK();
-		return (NULL);
-	}
+	                                                        SCTP_BASE_INFO(hashasocmark))];
 	LIST_FOREACH(stcb, head, sctp_asocs) {
 		SCTP_INP_RLOCK(stcb->sctp_ep);
 		if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
 			SCTP_INP_RUNLOCK(stcb->sctp_ep);
 			continue;
 		}
 #ifdef SCTP_MVRF
 		for (i = 0; i < stcb->sctp_ep->num_vrfs; i++) {
@@ -2600,17 +2667,17 @@ sctp_findassociation_addr(struct mbuf *m
  * if the lookup address is 0.0.0.0 or ::0, use the vtag to do the lookup
  */
 struct sctp_tcb *
 sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
 			       struct sockaddr *dst, struct sctphdr *sh,
                                struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
 {
 	struct sctp_tcb *stcb;
-	struct sockaddr_storage remote_store;
+	union sctp_sockstore remote_store;
 	struct sctp_paramhdr parm_buf, *phdr;
 	int ptype;
 	int zero_address = 0;
 #ifdef INET
 	struct sockaddr_in *sin;
 #endif
 #ifdef INET6
 	struct sockaddr_in6 *sin6;
@@ -2639,17 +2706,17 @@ sctp_findassociation_ep_asconf(struct mb
 		p6 = (struct sctp_ipv6addr_param *)sctp_get_next_param(m,
 								       offset + sizeof(struct sctp_asconf_chunk),
 								       &p6_buf.ph, sizeof(*p6));
 		if (p6 == NULL) {
 			SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n",
 				__FUNCTION__);
 			return (NULL);
 		}
-		sin6 = (struct sockaddr_in6 *)&remote_store;
+		sin6 = &remote_store.sin6;
 		sin6->sin6_family = AF_INET6;
 #ifdef HAVE_SIN6_LEN
 		sin6->sin6_len = sizeof(*sin6);
 #endif
 		sin6->sin6_port = sh->src_port;
 		memcpy(&sin6->sin6_addr, &p6->addr, sizeof(struct in6_addr));
 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
 			zero_address = 1;
@@ -2668,17 +2735,17 @@ sctp_findassociation_ep_asconf(struct mb
 		p4 = (struct sctp_ipv4addr_param *)sctp_get_next_param(m,
 								       offset + sizeof(struct sctp_asconf_chunk),
 								       &p4_buf.ph, sizeof(*p4));
 		if (p4 == NULL) {
 			SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n",
 				__FUNCTION__);
 			return (NULL);
 		}
-		sin = (struct sockaddr_in *)&remote_store;
+		sin = &remote_store.sin;
 		sin->sin_family = AF_INET;
 #ifdef HAVE_SIN_LEN
 		sin->sin_len = sizeof(*sin);
 #endif
 		sin->sin_port = sh->src_port;
 		memcpy(&sin->sin_addr, &p4->addr, sizeof(struct in_addr));
 		if (sin->sin_addr.s_addr == INADDR_ANY)
 			zero_address = 1;
@@ -2693,17 +2760,17 @@ sctp_findassociation_ep_asconf(struct mb
 	if (zero_address) {
 	        stcb = sctp_findassoc_by_vtag(NULL, dst, ntohl(sh->v_tag), inp_p,
 					      netp, sh->src_port, sh->dest_port, 1, vrf_id, 0);
 		if (stcb != NULL) {
 			SCTP_INP_DECR_REF(*inp_p);
 		}
 	} else {
 		stcb = sctp_findassociation_ep_addr(inp_p,
-		    (struct sockaddr *)&remote_store, netp,
+		    &remote_store.sa, netp,
 		    dst, NULL);
 	}
 	return (stcb);
 }
 
 
 /*
  * allocate a sctp_inpcb and setup a temporary binding to a port/all
@@ -2742,42 +2809,54 @@ sctp_inpcb_alloc(struct socket *so, uint
 
 	/* bump generations */
 #if defined(__APPLE__)
 	inp->ip_inp.inp.inp_state = INPCB_STATE_INUSE;
 #endif
 	/* setup socket pointers */
 	inp->sctp_socket = so;
 	inp->ip_inp.inp.inp_socket = so;
+#if defined(__FreeBSD__)
+	inp->ip_inp.inp.inp_cred = crhold(so->so_cred);
+#endif
 #ifdef INET6
 #if !defined(__Userspace__) && !defined(__Windows__)
 	if (INP_SOCKAF(so) == AF_INET6) {
 		if (MODULE_GLOBAL(ip6_auto_flowlabel)) {
 			inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL;
 		}
 		if (MODULE_GLOBAL(ip6_v6only)) {
 			inp->ip_inp.inp.inp_flags |= IN6P_IPV6_V6ONLY;
 		}
 	}
 #endif
 #endif
 	inp->sctp_associd_counter = 1;
 	inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
 	inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
 	inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
-	inp->sctp_ecn_enable = SCTP_BASE_SYSCTL(sctp_ecn_enable);
+	inp->ecn_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_ecn_enable);
+	inp->prsctp_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pr_enable);
+	inp->auth_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_auth_enable);
+	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);
 #if defined(__Userspace__)
 	inp->ulp_info = NULL;
 	inp->recv_callback = NULL;
 	inp->send_callback = NULL;
 	inp->send_sb_threshold = 0;
 #endif
 	/* 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) {
+#if defined(__FreeBSD__)
+		crfree(inp->ip_inp.inp.inp_cred);
+#endif
 		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
 		SCTP_INP_INFO_WUNLOCK();
 		return (ENOBUFS);
 	}
 #ifdef IPSEC
 #if !(defined(__APPLE__))
 	{
 		struct inpcbpolicy *pcb_sp = NULL;
@@ -2787,16 +2866,19 @@ sctp_inpcb_alloc(struct socket *so, uint
 		inp->ip_inp.inp.inp_sp = pcb_sp;
 		((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp;
 	}
 #else
 	/* not sure what to do for openbsd here */
 	error = 0;
 #endif
 	if (error != 0) {
+#if defined(__FreeBSD__)
+		crfree(inp->ip_inp.inp.inp_cred);
+#endif
 		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
 		SCTP_INP_INFO_WUNLOCK();
 		return error;
 	}
 #endif				/* IPSEC */
 	SCTP_INCR_EP_COUNT();
 	inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
 	SCTP_INP_INFO_WUNLOCK();
@@ -2832,16 +2914,19 @@ sctp_inpcb_alloc(struct socket *so, uint
 #endif
 	} else {
 		/*
 		 * unsupported socket type (RAW, etc)- in case we missed it
 		 * in protosw
 		 */
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP);
 		so->so_pcb = NULL;
+#if defined(__FreeBSD__)
+		crfree(inp->ip_inp.inp.inp_cred);
+#endif
 		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
 		return (EOPNOTSUPP);
 	}
 	if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_1) {
 		sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
 		sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
 	} else if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_2) {
 		sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
@@ -2851,27 +2936,33 @@ sctp_inpcb_alloc(struct socket *so, uint
 		sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
 	}
 	inp->sctp_tcbhash = SCTP_HASH_INIT(SCTP_BASE_SYSCTL(sctp_pcbtblsize),
 					   &inp->sctp_hashmark);
 	if (inp->sctp_tcbhash == NULL) {
 		SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n");
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
 		so->so_pcb = NULL;
+#if defined(__FreeBSD__)
+		crfree(inp->ip_inp.inp.inp_cred);
+#endif
 		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
 		return (ENOBUFS);
 	}
 #ifdef SCTP_MVRF
 	inp->vrf_size = SCTP_DEFAULT_VRF_SIZE;
 	SCTP_MALLOC(inp->m_vrf_ids, uint32_t *,
 		    (sizeof(uint32_t) * inp->vrf_size), SCTP_M_MVRF);
 	if (inp->m_vrf_ids == NULL) {
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
 		so->so_pcb = NULL;
 		SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
+#if defined(__FreeBSD__)
+		crfree(inp->ip_inp.inp.inp_cred);
+#endif
 		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
 		return (ENOBUFS);
 	}
 	inp->m_vrf_ids[0] = vrf_id;
 	inp->num_vrfs = 1;
 #endif
 	inp->def_vrf_id = vrf_id;
 
@@ -2880,16 +2971,19 @@ sctp_inpcb_alloc(struct socket *so, uint
 	inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr);
 	if (inp->ip_inp.inp.inpcb_mtx == NULL) {
 		SCTP_PRINTF("in_pcballoc: can't alloc mutex! so=%p\n", (void *)so);
 #ifdef SCTP_MVRF
 		SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
 #endif
 		SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
 		so->so_pcb = NULL;
+#if defined(__FreeBSD__)
+		crfree(inp->ip_inp.inp.inp_cred);
+#endif
 		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
 		SCTP_UNLOCK_EXC(SCTP_BASE_INFO(sctbinfo).ipi_lock);
 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM);
 		return (ENOMEM);
 	}
 #elif defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
 	lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr);
 #else
@@ -2989,22 +3083,25 @@ sctp_inpcb_alloc(struct socket *so, uint
 
 	/* How long is a cookie good for ? */
 	m->def_cookie_life = MSEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default));
 	/*
 	 * Initialize authentication parameters
 	 */
 	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();
 	sctp_insert_sharedkey(&m->shared_keys, null_key);
 	SCTP_INP_WUNLOCK(inp);
 #ifdef SCTP_LOG_CLOSING
 	sctp_log_closing(inp, NULL, 12);
 #endif
@@ -3141,23 +3238,23 @@ sctp_move_pcb_and_assoc(struct sctp_inpc
 extern void in6_sin6_2_sin(struct sockaddr_in *, struct sockaddr_in6 *sin6);
 #endif
 
 
 /* sctp_ifap is used to bypass normal local address validation checks */
 int
 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
 sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
-		struct sctp_ifa *sctp_ifap, struct thread *p)
+                struct sctp_ifa *sctp_ifap, struct thread *p)
 #elif defined(__Windows__)
 sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
-		struct sctp_ifa *sctp_ifap, PKTHREAD p)
+                struct sctp_ifa *sctp_ifap, PKTHREAD p)
 #else
 sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
-		struct sctp_ifa *sctp_ifap, struct proc *p)
+                struct sctp_ifa *sctp_ifap, struct proc *p)
 #endif
 {
 	/* bind a ep to a socket address */
 	struct sctppcbhead *head;
 	struct sctp_inpcb *inp, *inp_tmp;
 #if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__)
 	struct inpcb *ip_inp;
 #endif
@@ -3212,24 +3309,24 @@ sctp_inpcb_bind(struct socket *so, struc
 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
 				return (EINVAL);
 			}
 #endif
 
 			sin = (struct sockaddr_in *)addr;
 			lport = sin->sin_port;
 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
- 			/*
- 			 * For LOOPBACK the prison_local_ip4() call will transmute the ip address
- 			 * to the proper value.
- 			 */
- 			if (p && (error = prison_local_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
- 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
- 				return (error);
-  			}
+			/*
+			 * For LOOPBACK the prison_local_ip4() call will transmute the ip address
+			 * to the proper value.
+			 */
+			if (p && (error = prison_local_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
+				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+				return (error);
+			}
 #endif
 			if (sin->sin_addr.s_addr != INADDR_ANY) {
 				bindall = 0;
 			}
 			break;
 		}
 #endif
 #ifdef INET6
@@ -3243,25 +3340,25 @@ sctp_inpcb_bind(struct socket *so, struc
 #ifdef HAVE_SA_LEN
 			if (addr->sa_len != sizeof(*sin6)) {
 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
 				return (EINVAL);
 			}
 #endif
 			lport = sin6->sin6_port;
 #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
-  			/*
- 			 * For LOOPBACK the prison_local_ip6() call will transmute the ipv6 address
- 			 * to the proper value.
-  			 */
- 			if (p && (error = prison_local_ip6(p->td_ucred, &sin6->sin6_addr,
- 			    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
- 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
- 				return (error);
- 			}
+			/*
+			 * For LOOPBACK the prison_local_ip6() call will transmute the ipv6 address
+			 * to the proper value.
+			 */
+			if (p && (error = prison_local_ip6(p->td_ucred, &sin6->sin6_addr,
+			    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
+				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
+				return (error);
+			}
 #endif
 			if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 				bindall = 0;
 #ifdef SCTP_EMBEDDED_V6_SCOPE
 				/* KAME hack: embed scopeid */
 #if defined(SCTP_KAME)
 				if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) {
 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
@@ -3319,17 +3416,17 @@ sctp_inpcb_bind(struct socket *so, struc
 		default:
 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EAFNOSUPPORT);
 			return (EAFNOSUPPORT);
 		}
 	}
 	SCTP_INP_INFO_WLOCK();
 	SCTP_INP_WLOCK(inp);
 	/* Setup a vrf_id to be the default for the non-bind-all case. */
- 	vrf_id = inp->def_vrf_id;
+	vrf_id = inp->def_vrf_id;
 
 	/* increase our count due to the unlock we do */
 	SCTP_INP_INCR_REF(inp);
 	if (lport) {
 		/*
 		 * Did the caller specify a port? if so we must see if an ep
 		 * already has this one bound.
 		 */
@@ -3343,17 +3440,17 @@ sctp_inpcb_bind(struct socket *so, struc
 #elif __FreeBSD_version >= 500000
 				  suser_cred(p->td_ucred, 0)
 #else
 				  suser(p)
 #endif
 #elif defined(__APPLE__)
 				  suser(p->p_ucred, &p->p_acflag)
 #elif defined(__Userspace__) /* must be true to use raw socket */
-                                  1
+				  1
 #else
 				  suser(p, 0)
 #endif
 				    )) {
 				SCTP_INP_DECR_REF(inp);
 				SCTP_INP_WUNLOCK(inp);
 				SCTP_INP_INFO_WUNLOCK();
 				return (error);
@@ -3363,25 +3460,16 @@ sctp_inpcb_bind(struct socket *so, struc
 				SCTP_INP_DECR_REF(inp);
 				SCTP_INP_WUNLOCK(inp);
 				SCTP_INP_INFO_WUNLOCK();
 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EACCES);
 				return (EACCES);
 			}
 #endif
 		}
-#if !defined(__Panda__) && !defined(__Userspace__)
-		if (p == NULL) {
-			SCTP_INP_DECR_REF(inp);
-			SCTP_INP_WUNLOCK(inp);
-			SCTP_INP_INFO_WUNLOCK();
-			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
-			return (error);
-		}
-#endif
 #endif /* __Windows__ */
 		SCTP_INP_WUNLOCK(inp);
 		if (bindall) {
 #ifdef SCTP_MVRF
 			for (i = 0; i < inp->num_vrfs; i++) {
 				vrf_id = inp->m_vrf_ids[i];
 #else
 				vrf_id = inp->def_vrf_id;
@@ -3452,30 +3540,30 @@ sctp_inpcb_bind(struct socket *so, struc
 					SCTP_INP_INFO_WUNLOCK();
 					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
 					return (EADDRINUSE);
 				}
 			}
 		}
 	} else {
 		uint16_t first, last, candidate;
-                uint16_t count;
+		uint16_t count;
 		int done;
 
 #if defined(__Windows__)
 		first = 1;
 		last = 0xffff;
 #else
 #if defined(__Userspace__)
-                /* TODO ensure uid is 0, etc... */
+		/* TODO ensure uid is 0, etc... */
 #elif defined(__FreeBSD__) || defined(__APPLE__)
-                if (ip_inp->inp_flags & INP_HIGHPORT) {
-                        first = MODULE_GLOBAL(ipport_hifirstauto);