Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Aug 2014 12:42:38 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r269376 - head/sys/netinet
Message-ID:  <201408011242.s71CgcfJ072859@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tuexen
Date: Fri Aug  1 12:42:37 2014
New Revision: 269376
URL: http://svnweb.freebsd.org/changeset/base/269376

Log:
  Cleanup sctp_send_initiate() and sctp_send_initiate_ack() to be
  in sync as much as possible. This simplifies upcoming changes.

Modified:
  head/sys/netinet/sctp_header.h
  head/sys/netinet/sctp_indata.c
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctputil.c
  head/sys/netinet/sctputil.h

Modified: head/sys/netinet/sctp_header.h
==============================================================================
--- head/sys/netinet/sctp_header.h	Fri Aug  1 10:35:35 2014	(r269375)
+++ head/sys/netinet/sctp_header.h	Fri Aug  1 12:42:37 2014	(r269376)
@@ -82,12 +82,6 @@ struct sctp_supported_addr_param {
 	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;

Modified: head/sys/netinet/sctp_indata.c
==============================================================================
--- head/sys/netinet/sctp_indata.c	Fri Aug  1 10:35:35 2014	(r269375)
+++ head/sys/netinet/sctp_indata.c	Fri Aug  1 12:42:37 2014	(r269376)
@@ -2505,7 +2505,7 @@ sctp_process_data(struct mbuf **mm, int 
 						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);

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c	Fri Aug  1 10:35:35 2014	(r269375)
+++ head/sys/netinet/sctp_input.c	Fri Aug  1 12:42:37 2014	(r269376)
@@ -5484,7 +5484,7 @@ process_control_chunks:
 					SCTP_BUF_LEN(mm) = sizeof(*phd);
 					SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, 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(chk_length) - chk_length, NULL) == NULL) {
 							sctp_m_freem(mm);
 						} else {
 #ifdef SCTP_MBUF_LOGGING

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c	Fri Aug  1 10:35:35 2014	(r269375)
+++ head/sys/netinet/sctp_output.c	Fri Aug  1 12:42:37 2014	(r269376)
@@ -4700,7 +4700,7 @@ sctp_send_initiate(struct sctp_inpcb *in
 #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;
@@ -4775,80 +4775,17 @@ sctp_send_initiate(struct sctp_inpcb *in
 	init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams);
 	init->init.initial_tsn = htonl(stcb->asoc.init_seq_number);
 
-	if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) {
-		uint8_t i;
-
-		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);
-		sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
-		sup_addr->ph.param_length = htons(parameter_len);
-		i = 0;
-		if (stcb->asoc.scope.ipv4_addr_legal) {
-			sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS);
-		}
-		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;
+		ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator);
 		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);
@@ -4856,21 +4793,24 @@ sctp_send_initiate(struct sctp_inpcb *in
 		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 */
+	/* 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);
 	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;
@@ -4943,8 +4883,52 @@ sctp_send_initiate(struct sctp_inpcb *in
 			chunk_len += parameter_len;
 		}
 	}
-	SCTP_BUF_LEN(m) = chunk_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);
+		sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
+		sup_addr->ph.param_length = htons(parameter_len);
+		i = 0;
+		if (stcb->asoc.scope.ipv4_addr_legal) {
+			sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS);
+		}
+		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;
+	}
+	SCTP_BUF_LEN(m) = chunk_len;
 	/* now the addresses */
 	/*
 	 * To optimize this we could put the scoping stuff into a structure
@@ -4952,18 +4936,13 @@ sctp_send_initiate(struct sctp_inpcb *in
 	 * 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;
 		}
@@ -5100,7 +5079,6 @@ sctp_arethere_unrecognized_parameters(st
 			*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;
@@ -5108,7 +5086,7 @@ sctp_arethere_unrecognized_parameters(st
 			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;
 			}
@@ -5493,13 +5471,13 @@ sctp_send_initiate_ack(struct sctp_inpcb
     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;
@@ -5519,18 +5497,16 @@ sctp_send_initiate_ack(struct sctp_inpcb
 	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))) {
@@ -5573,7 +5549,8 @@ do_a_abort:
 			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
@@ -5897,161 +5874,156 @@ do_a_abort:
 
 	/* 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 (nat_friendly) {
-		/* Add NAT friendly parameter */
-		struct sctp_paramhdr *ph;
+	    ((asoc == NULL) && (inp->sctp_ecn_enable == 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;
+	}
+	/* And now tell the peer we do pr-sctp */
+	parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
+	ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
+	ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
+	ph->param_length = htons(parameter_len);
+	chunk_len += parameter_len;
 
-		ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
+	/* Add NAT friendly parameter */
+	if (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(sizeof(struct sctp_paramhdr));
-		SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr);
+		chunk_len += 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);
+	/* And now tell the peer which extensions we support */
 	num_ext = 0;
+	pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
+	pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
 	pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
 	pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
 	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))
+	if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
 		pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
-	if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
+	}
+	if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) {
 		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);
+	}
+	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)) {
 		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,
+		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);
-		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->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 = (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);
-		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);
-		}
+		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;
 	}
-	m_at = m;
+	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;
-		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);
+	/*
+	 * 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;
+	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);
+		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;
 	}
-	/* 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;
+	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) {
@@ -6060,21 +6032,22 @@ do_a_abort:
 		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
@@ -6088,11 +6061,8 @@ do_a_abort:
 	 * 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;
 		}
@@ -7582,12 +7552,10 @@ dont_do_it:
 		int pads;
 
 		pads = SCTP_SIZE32(chk->book_size) - chk->send_size;
-		if (sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf) == 0) {
-			chk->pad_inplace = 1;
-		}
-		if ((lm = SCTP_BUF_NEXT(chk->last_mbuf)) != NULL) {
-			/* pad added an mbuf */
+		lm = sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf);
+		if (lm != NULL) {
 			chk->last_mbuf = lm;
+			chk->pad_inplace = 1;
 		}
 		chk->send_size += pads;
 	}
@@ -10900,7 +10868,8 @@ sctp_send_abort_tcb(struct sctp_tcb *stc
 	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;
 		}
@@ -11000,7 +10969,7 @@ sctp_send_resp_msg(struct sockaddr *src,
 			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;
 			}

Modified: head/sys/netinet/sctputil.c
==============================================================================
--- head/sys/netinet/sctputil.c	Fri Aug  1 10:35:35 2014	(r269375)
+++ head/sys/netinet/sctputil.c	Fri Aug  1 12:42:37 2014	(r269376)
@@ -2516,58 +2516,44 @@ sctp_get_next_param(struct mbuf *m,
 }
 
 
-int
+struct mbuf *
 sctp_add_pad_tombuf(struct mbuf *m, int padlen)
 {
-	/*
-	 * add padlen bytes of 0 filled padding to the end of the mbuf. If
-	 * padlen is > 3 this routine will fail.
-	 */
-	uint8_t *dp;
-	int i;
+	struct mbuf *m_last;
+	caddr_t dp;
 
 	if (padlen > 3) {
-		SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
-		return (ENOBUFS);
+		return (NULL);
 	}
 	if (padlen <= M_TRAILINGSPACE(m)) {
 		/*
 		 * The easy way. We hope the majority of the time we hit
 		 * here :)
 		 */
-		dp = (uint8_t *) (mtod(m, caddr_t)+SCTP_BUF_LEN(m));
-		SCTP_BUF_LEN(m) += padlen;
+		m_last = m;
 	} else {
-		/* Hard way we must grow the mbuf */
-		struct mbuf *tmp;
-
-		tmp = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
-		if (tmp == NULL) {
-			/* Out of space GAK! we are in big trouble. */
-			SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
-			return (ENOBUFS);
-		}
-		/* setup and insert in middle */
-		SCTP_BUF_LEN(tmp) = padlen;
-		SCTP_BUF_NEXT(tmp) = NULL;
-		SCTP_BUF_NEXT(m) = tmp;
-		dp = mtod(tmp, uint8_t *);
-	}
-	/* zero out the pad */
-	for (i = 0; i < padlen; i++) {
-		*dp = 0;
-		dp++;
-	}
-	return (0);
+		/* Hard way we must grow the mbuf chain */
+		m_last = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
+		if (m_last == NULL) {
+			return (NULL);
+		}
+		SCTP_BUF_LEN(m_last) = 0;
+		SCTP_BUF_NEXT(m_last) = NULL;
+		SCTP_BUF_NEXT(m) = m_last;
+	}
+	dp = mtod(m_last, caddr_t)+SCTP_BUF_LEN(m_last);
+	SCTP_BUF_LEN(m_last) += padlen;
+	memset(dp, 0, padlen);
+	return (m_last);
 }
 
-int
+struct mbuf *
 sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
 {
 	/* find the last mbuf in chain and pad it */
 	struct mbuf *m_at;
 
-	if (last_mbuf) {
+	if (last_mbuf != NULL) {
 		return (sctp_add_pad_tombuf(last_mbuf, padval));
 	} else {
 		for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
@@ -2576,8 +2562,7 @@ sctp_pad_lastmbuf(struct mbuf *m, int pa
 			}
 		}
 	}
-	SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
-	return (EFAULT);
+	return (NULL);
 }
 
 static void

Modified: head/sys/netinet/sctputil.h
==============================================================================
--- head/sys/netinet/sctputil.h	Fri Aug  1 10:35:35 2014	(r269375)
+++ head/sys/netinet/sctputil.h	Fri Aug  1 12:42:37 2014	(r269376)
@@ -147,9 +147,11 @@ struct sctp_paramhdr *
 sctp_get_next_param(struct mbuf *, int,
     struct sctp_paramhdr *, int);
 
-int sctp_add_pad_tombuf(struct mbuf *, int);
+struct mbuf *
+     sctp_add_pad_tombuf(struct mbuf *, int);
 
-int sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
+struct mbuf *
+     sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
 
 void 
 sctp_ulp_notify(uint32_t, struct sctp_tcb *, uint32_t, void *, int



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408011242.s71CgcfJ072859>