svn commit: r252896 - in stable/9/sys: netinet netinet6

Michael Tuexen tuexen at FreeBSD.org
Sat Jul 6 20:35:22 UTC 2013


Author: tuexen
Date: Sat Jul  6 20:35:21 2013
New Revision: 252896
URL: http://svnweb.freebsd.org/changeset/base/252896

Log:
  MFC r238003, r239091:
  Move common code parts to sctp_common_input_processing().
  
  Fix a bug found by dim@:
  Don't use an uninitilized variable, if INVARIANTS is on and an illegal
  packet with destination 0 is received.

Modified:
  stable/9/sys/netinet/sctp_input.c
  stable/9/sys/netinet/sctp_input.h
  stable/9/sys/netinet6/sctp6_usrreq.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/netinet/sctp_input.c
==============================================================================
--- stable/9/sys/netinet/sctp_input.c	Sat Jul  6 20:31:22 2013	(r252895)
+++ stable/9/sys/netinet/sctp_input.c	Sat Jul  6 20:35:21 2013	(r252896)
@@ -5588,26 +5588,141 @@ 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,
-    struct sctp_inpcb *inp, struct sctp_tcb *stcb,
-    struct sctp_nets *net, uint8_t ecn_bits,
+#if !defined(SCTP_WITH_NO_CSUM)
+    uint8_t compute_crc,
+#endif
+    uint8_t ecn_bits,
     uint8_t use_mflowid, uint32_t mflowid,
     uint32_t vrf_id, uint16_t port)
 {
-	/*
-	 * Control chunk processing
-	 */
 	uint32_t high_tsn;
 	int fwd_tsn_seen = 0, data_processed = 0;
 	struct mbuf *m = *mm;
 	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;
 
 	SCTP_STAT_INCR(sctps_recvdatagrams);
 #ifdef SCTP_AUDITING_ENABLED
 	sctp_audit_log(0xE0, 1);
 	sctp_auditing(0, inp, stcb, net);
 #endif
+#if !defined(SCTP_WITH_NO_CSUM)
+	if (compute_crc != 0) {
+		uint32_t check, calc_check;
 
+		check = sh->checksum;
+		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, m, length, iphlen);
+			stcb = sctp_findassociation_addr(m, offset, src, dst,
+			    sh, ch, &inp, &net, vrf_id);
+			if ((net != NULL) && (port != 0)) {
+				if (net->port == 0) {
+					sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
+				}
+				net->port = port;
+			}
+			if ((net != NULL) && (use_mflowid != 0)) {
+				net->flowid = mflowid;
+#ifdef INVARIANTS
+				net->flowidset = 1;
+#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;
+			}
+			SCTP_STAT_INCR(sctps_badsum);
+			SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
+			goto out;
+		}
+	}
+#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 ((net != NULL) && (port != 0)) {
+		if (net->port == 0) {
+			sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
+		}
+		net->port = port;
+	}
+	if ((net != NULL) && (use_mflowid != 0)) {
+		net->flowid = mflowid;
+#ifdef INVARIANTS
+		net->flowidset = 1;
+#endif
+	}
+	if (inp == NULL) {
+		SCTP_STAT_INCR(sctps_noport);
+		if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
+			goto out;
+		}
+		if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
+			sctp_send_shutdown_complete2(src, dst, sh,
+			    use_mflowid, mflowid,
+			    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))) {
+				sctp_send_abort(m, iphlen, src, dst,
+				    sh, 0, NULL,
+				    use_mflowid, mflowid,
+				    vrf_id, port);
+			}
+		}
+		goto out;
+	} else if (stcb == NULL) {
+		inp_decr = inp;
+	}
+#ifdef IPSEC
+	/*-
+	 * 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)) {
+				MODULE_GLOBAL(ipsec4stat).in_polvio++;
+				SCTP_STAT_INCR(sctps_hdrops);
+				goto out;
+			}
+			break;
+#endif
+#ifdef INET6
+		case AF_INET6:
+			if (ipsec6_in_reject(m, &inp->ip_inp.inp)) {
+				MODULE_GLOBAL(ipsec6stat).in_polvio++;
+				SCTP_STAT_INCR(sctps_hdrops);
+				goto out;
+			}
+			break;
+#endif
+		default:
+			break;
+		}
+	}
+#endif
 	SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n",
 	    m, iphlen, offset, length, stcb);
 	if (stcb) {
@@ -5626,10 +5741,11 @@ sctp_common_input_processing(struct mbuf
 			 * NOT respond to any packet.. its OOTB.
 			 */
 			SCTP_TCB_UNLOCK(stcb);
+			stcb = NULL;
 			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
 			    use_mflowid, mflowid,
 			    vrf_id, port);
-			goto out_now;
+			goto out;
 		}
 	}
 	if (IS_SCTP_CONTROL(ch)) {
@@ -5669,21 +5785,19 @@ sctp_common_input_processing(struct mbuf
 		    sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
 			/* "silently" ignore */
 			SCTP_STAT_INCR(sctps_recvauthmissing);
-			SCTP_TCB_UNLOCK(stcb);
-			goto out_now;
+			goto out;
 		}
 		if (stcb == NULL) {
 			/* out of the blue DATA chunk */
 			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
 			    use_mflowid, mflowid,
 			    vrf_id, port);
-			goto out_now;
+			goto out;
 		}
 		if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
 			/* v_tag mismatch! */
 			SCTP_STAT_INCR(sctps_badvtag);
-			SCTP_TCB_UNLOCK(stcb);
-			goto out_now;
+			goto out;
 		}
 	}
 
@@ -5693,7 +5807,7 @@ sctp_common_input_processing(struct mbuf
 		 * packet while processing control, or we're done with this
 		 * packet (done or skip rest of data), so we drop it...
 		 */
-		goto out_now;
+		goto out;
 	}
 	/*
 	 * DATA chunk processing
@@ -5747,8 +5861,7 @@ sctp_common_input_processing(struct mbuf
 			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
 			    use_mflowid, mflowid,
 			    vrf_id, port);
-			SCTP_TCB_UNLOCK(stcb);
-			goto out_now;
+			goto out;
 			/* sa_ignore NOTREACHED */
 			break;
 		case SCTP_STATE_EMPTY:	/* should not happen */
@@ -5756,8 +5869,7 @@ sctp_common_input_processing(struct mbuf
 		case SCTP_STATE_SHUTDOWN_RECEIVED:	/* This is a peer error */
 		case SCTP_STATE_SHUTDOWN_ACK_SENT:
 		default:
-			SCTP_TCB_UNLOCK(stcb);
-			goto out_now;
+			goto out;
 			/* sa_ignore NOTREACHED */
 			break;
 		case SCTP_STATE_OPEN:
@@ -5775,7 +5887,8 @@ sctp_common_input_processing(struct mbuf
 			 * The association aborted, NO UNLOCK needed since
 			 * the association is destroyed.
 			 */
-			goto out_now;
+			stcb = NULL;
+			goto out;
 		}
 		data_processed = 1;
 		/*
@@ -5832,10 +5945,20 @@ trigger_send:
 	sctp_audit_log(0xE0, 3);
 	sctp_auditing(2, inp, stcb, net);
 #endif
-	SCTP_TCB_UNLOCK(stcb);
-out_now:
+out:
+	if (stcb != NULL) {
+		SCTP_TCB_UNLOCK(stcb);
+	}
+	if (inp_decr != NULL) {
+		/* reduce ref-count */
+		SCTP_INP_WLOCK(inp_decr);
+		SCTP_INP_DECR_REF(inp_decr);
+		SCTP_INP_WUNLOCK(inp_decr);
+	}
 #ifdef INVARIANTS
-	sctp_validate_no_locks(inp);
+	if (inp != NULL) {
+		sctp_validate_no_locks(inp);
+	}
 #endif
 	return;
 }
@@ -5865,18 +5988,14 @@ sctp_input_with_port(struct mbuf *i_pak,
 	struct ip *ip;
 	struct sctphdr *sh;
 	struct sctp_chunkhdr *ch;
-	struct sctp_inpcb *inp = NULL;
-	struct sctp_tcb *stcb = NULL;
-	struct sctp_nets *net = NULL;
-	int refcount_up = 0;
 	int length, offset;
-	uint32_t mflowid;
-	uint8_t use_mflowid;
 
 #if !defined(SCTP_WITH_NO_CSUM)
-	uint32_t check, calc_check;
+	uint8_t compute_crc;
 
 #endif
+	uint32_t mflowid;
+	uint8_t use_mflowid;
 
 	iphlen = off;
 	if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
@@ -5901,6 +6020,11 @@ sctp_input_with_port(struct mbuf *i_pak,
 		sctp_packet_log(m);
 	}
 #endif
+	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+	    "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
+	    m->m_pkthdr.len,
+	    if_name(m->m_pkthdr.rcvif),
+	    m->m_pkthdr.csum_flags);
 	if (m->m_flags & M_FLOWID) {
 		mflowid = m->m_pkthdr.flowid;
 		use_mflowid = 1;
@@ -5934,161 +6058,42 @@ sctp_input_with_port(struct mbuf *i_pak,
 	dst.sin_addr = ip->ip_dst;
 	length = ip->ip_len + iphlen;
 	/* Validate mbuf chain length with IP payload length. */
-	if (SCTP_HEADER_LEN(i_pak) != length) {
+	if (SCTP_HEADER_LEN(m) != length) {
 		SCTPDBG(SCTP_DEBUG_INPUT1,
-		    "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(i_pak));
+		    "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
 		SCTP_STAT_INCR(sctps_hdrops);
-		goto bad;
+		goto out;
 	}
 	/* SCTP does not allow broadcasts or multicasts */
 	if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
-		goto bad;
+		goto out;
 	}
 	if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) {
-		goto bad;
+		goto out;
 	}
-	SCTPDBG(SCTP_DEBUG_INPUT1,
-	    "sctp_input() length:%d iphlen:%d\n", length, iphlen);
-	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
-	    "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
-	    m->m_pkthdr.len,
-	    if_name(m->m_pkthdr.rcvif),
-	    m->m_pkthdr.csum_flags);
+	ecn_bits = ip->ip_tos;
 #if defined(SCTP_WITH_NO_CSUM)
 	SCTP_STAT_INCR(sctps_recvnocrc);
 #else
 	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
 		SCTP_STAT_INCR(sctps_recvhwcrc);
-		goto sctp_skip_csum;
-	}
-	check = sh->checksum;
-	sh->checksum = 0;
-	calc_check = sctp_calculate_cksum(m, iphlen);
-	sh->checksum = check;
-	SCTP_STAT_INCR(sctps_recvswcrc);
-	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, m, length, iphlen);
-		stcb = sctp_findassociation_addr(m, offset,
-		    (struct sockaddr *)&src,
-		    (struct sockaddr *)&dst,
-		    sh, ch, &inp, &net, vrf_id);
-		if ((net) && (port)) {
-			if (net->port == 0) {
-				sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
-			}
-			net->port = port;
-		}
-		if ((net != NULL) && (use_mflowid != 0)) {
-			net->flowid = mflowid;
-#ifdef INVARIANTS
-			net->flowidset = 1;
-#endif
-		}
-		if ((inp) && (stcb)) {
-			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)) {
-			refcount_up = 1;
-		}
-		SCTP_STAT_INCR(sctps_badsum);
-		SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
-		goto bad;
-	}
-sctp_skip_csum:
-#endif
-	/* destination port of 0 is illegal, based on RFC2960. */
-	if (sh->dest_port == 0) {
-		SCTP_STAT_INCR(sctps_hdrops);
-		goto bad;
-	}
-	stcb = sctp_findassociation_addr(m, offset,
-	    (struct sockaddr *)&src,
-	    (struct sockaddr *)&dst,
-	    sh, ch, &inp, &net, vrf_id);
-	if ((net) && (port)) {
-		if (net->port == 0) {
-			sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
-		}
-		net->port = port;
-	}
-	if ((net != NULL) && (use_mflowid != 0)) {
-		net->flowid = mflowid;
-#ifdef INVARIANTS
-		net->flowidset = 1;
-#endif
-	}
-	if (inp == NULL) {
-		SCTP_STAT_INCR(sctps_noport);
-		if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0)
-			goto bad;
-		if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
-			sctp_send_shutdown_complete2((struct sockaddr *)&src,
-			    (struct sockaddr *)&dst,
-			    sh,
-			    use_mflowid, mflowid,
-			    vrf_id, port);
-			goto bad;
-		}
-		if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
-			goto bad;
-		}
-		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))) {
-				sctp_send_abort(m, iphlen,
-				    (struct sockaddr *)&src,
-				    (struct sockaddr *)&dst,
-				    sh, 0, NULL,
-				    use_mflowid, mflowid,
-				    vrf_id, port);
-			}
-		}
-		goto bad;
-	} else if (stcb == NULL) {
-		refcount_up = 1;
-	}
-#ifdef IPSEC
-	/*-
-	 * 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 && ipsec4_in_reject(m, &inp->ip_inp.inp)) {
-		MODULE_GLOBAL(ipsec4stat).in_polvio++;
-		SCTP_STAT_INCR(sctps_hdrops);
-		goto bad;
+		compute_crc = 0;
+	} else {
+		SCTP_STAT_INCR(sctps_recvswcrc);
+		compute_crc = 1;
 	}
 #endif
-
-	ecn_bits = ip->ip_tos;
-	/* sa_ignore NO_NULL_CHK */
 	sctp_common_input_processing(&m, iphlen, offset, length,
 	    (struct sockaddr *)&src,
 	    (struct sockaddr *)&dst,
-	    sh, ch, inp, stcb, net, ecn_bits,
+	    sh, ch,
+#if !defined(SCTP_WITH_NO_CSUM)
+	    compute_crc,
+#endif
+	    ecn_bits,
 	    use_mflowid, mflowid,
 	    vrf_id, port);
-	if (m) {
-		sctp_m_freem(m);
-	}
-	if ((inp) && (refcount_up)) {
-		/* reduce ref-count */
-		SCTP_INP_WLOCK(inp);
-		SCTP_INP_DECR_REF(inp);
-		SCTP_INP_WUNLOCK(inp);
-	}
-	return;
-bad:
-	if (stcb) {
-		SCTP_TCB_UNLOCK(stcb);
-	}
-	if ((inp) && (refcount_up)) {
-		/* reduce ref-count */
-		SCTP_INP_WLOCK(inp);
-		SCTP_INP_DECR_REF(inp);
-		SCTP_INP_WUNLOCK(inp);
-	}
+out:
 	if (m) {
 		sctp_m_freem(m);
 	}

Modified: stable/9/sys/netinet/sctp_input.h
==============================================================================
--- stable/9/sys/netinet/sctp_input.h	Sat Jul  6 20:31:22 2013	(r252895)
+++ stable/9/sys/netinet/sctp_input.h	Sat Jul  6 20:35:21 2013	(r252896)
@@ -41,8 +41,10 @@ void
 sctp_common_input_processing(struct mbuf **, int, int, int,
     struct sockaddr *, struct sockaddr *,
     struct sctphdr *, struct sctp_chunkhdr *,
-    struct sctp_inpcb *, struct sctp_tcb *,
-    struct sctp_nets *, uint8_t,
+#if !defined(SCTP_WITH_NO_CSUM)
+    uint8_t,
+#endif
+    uint8_t,
     uint8_t, uint32_t,
     uint32_t, uint16_t);
 

Modified: stable/9/sys/netinet6/sctp6_usrreq.c
==============================================================================
--- stable/9/sys/netinet6/sctp6_usrreq.c	Sat Jul  6 20:31:22 2013	(r252895)
+++ stable/9/sys/netinet6/sctp6_usrreq.c	Sat Jul  6 20:35:21 2013	(r252896)
@@ -70,24 +70,20 @@ sctp6_input(struct mbuf **i_pak, int *of
 {
 	struct mbuf *m;
 	int iphlen;
-	uint32_t vrf_id = 0;
+	uint32_t vrf_id;
 	uint8_t ecn_bits;
 	struct sockaddr_in6 src, dst;
 	struct ip6_hdr *ip6;
 	struct sctphdr *sh;
 	struct sctp_chunkhdr *ch;
-	struct sctp_inpcb *inp = NULL;
-	struct sctp_tcb *stcb = NULL;
-	struct sctp_nets *net = NULL;
-	int refcount_up = 0;
 	int length, offset;
-	uint32_t mflowid;
-	uint8_t use_mflowid;
 
 #if !defined(SCTP_WITH_NO_CSUM)
-	uint32_t check, calc_check;
+	uint8_t compute_crc;
 
 #endif
+	uint32_t mflowid;
+	uint8_t use_mflowid;
 	uint16_t port = 0;
 
 	iphlen = *offp;
@@ -113,6 +109,11 @@ sctp6_input(struct mbuf **i_pak, int *of
 		sctp_packet_log(m);
 	}
 #endif
+	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+	    "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
+	    m->m_pkthdr.len,
+	    if_name(m->m_pkthdr.rcvif),
+	    m->m_pkthdr.csum_flags);
 	if (m->m_flags & M_FLOWID) {
 		mflowid = m->m_pkthdr.flowid;
 		use_mflowid = 1;
@@ -123,8 +124,8 @@ sctp6_input(struct mbuf **i_pak, int *of
 	SCTP_STAT_INCR(sctps_recvpackets);
 	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
 	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
-	ip6 = mtod(m, struct ip6_hdr *);
 	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
+	ip6 = mtod(m, struct ip6_hdr *);
 	IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen,
 	    (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
 	if (sh == NULL) {
@@ -139,7 +140,7 @@ sctp6_input(struct mbuf **i_pak, int *of
 	src.sin6_port = sh->src_port;
 	src.sin6_addr = ip6->ip6_src;
 	if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
-		goto bad;
+		goto out;
 	}
 	memset(&dst, 0, sizeof(struct sockaddr_in6));
 	dst.sin6_family = AF_INET6;
@@ -147,165 +148,46 @@ sctp6_input(struct mbuf **i_pak, int *of
 	dst.sin6_port = sh->dest_port;
 	dst.sin6_addr = ip6->ip6_dst;
 	if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
-		goto bad;
+		goto out;
 	}
 	if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) {
 		/* XXX send icmp6 host/port unreach? */
-		goto bad;
+		goto out;
 	}
 	length = ntohs(ip6->ip6_plen) + iphlen;
 	/* Validate mbuf chain length with IP payload length. */
-	if (SCTP_HEADER_LEN(*i_pak) != length) {
+	if (SCTP_HEADER_LEN(m) != length) {
 		SCTPDBG(SCTP_DEBUG_INPUT1,
-		    "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(*i_pak));
+		    "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
 		SCTP_STAT_INCR(sctps_hdrops);
-		goto bad;
+		goto out;
 	}
 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
-		goto bad;
+		goto out;
 	}
-	SCTPDBG(SCTP_DEBUG_INPUT1,
-	    "sctp6_input() length:%d iphlen:%d\n", length, iphlen);
-	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
-	    "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
-	    m->m_pkthdr.len,
-	    if_name(m->m_pkthdr.rcvif),
-	    m->m_pkthdr.csum_flags);
+	ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
 #if defined(SCTP_WITH_NO_CSUM)
 	SCTP_STAT_INCR(sctps_recvnocrc);
 #else
 	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
 		SCTP_STAT_INCR(sctps_recvhwcrc);
-		goto sctp_skip_csum;
-	}
-	check = sh->checksum;
-	sh->checksum = 0;
-	calc_check = sctp_calculate_cksum(m, iphlen);
-	sh->checksum = check;
-	SCTP_STAT_INCR(sctps_recvswcrc);
-	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, m, length, iphlen);
-		stcb = sctp_findassociation_addr(m, offset,
-		    (struct sockaddr *)&src,
-		    (struct sockaddr *)&dst,
-		    sh, ch, &inp, &net, vrf_id);
-		if ((net) && (port)) {
-			if (net->port == 0) {
-				sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
-			}
-			net->port = port;
-		}
-		if ((net != NULL) && (use_mflowid != 0)) {
-			net->flowid = mflowid;
-#ifdef INVARIANTS
-			net->flowidset = 1;
-#endif
-		}
-		if ((inp) && (stcb)) {
-			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)) {
-			refcount_up = 1;
-		}
-		SCTP_STAT_INCR(sctps_badsum);
-		SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
-		goto bad;
-	}
-sctp_skip_csum:
-#endif
-	/* destination port of 0 is illegal, based on RFC2960. */
-	if (sh->dest_port == 0) {
-		SCTP_STAT_INCR(sctps_hdrops);
-		goto bad;
-	}
-	stcb = sctp_findassociation_addr(m, offset,
-	    (struct sockaddr *)&src,
-	    (struct sockaddr *)&dst,
-	    sh, ch, &inp, &net, vrf_id);
-	if ((net) && (port)) {
-		if (net->port == 0) {
-			sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
-		}
-		net->port = port;
-	}
-	if ((net != NULL) && (use_mflowid != 0)) {
-		net->flowid = mflowid;
-#ifdef INVARIANTS
-		net->flowidset = 1;
-#endif
-	}
-	if (inp == NULL) {
-		SCTP_STAT_INCR(sctps_noport);
-		if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0)
-			goto bad;
-		if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
-			sctp_send_shutdown_complete2((struct sockaddr *)&src,
-			    (struct sockaddr *)&dst,
-			    sh,
-			    use_mflowid, mflowid,
-			    vrf_id, port);
-			goto bad;
-		}
-		if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
-			goto bad;
-		}
-		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))) {
-				sctp_send_abort(m, iphlen,
-				    (struct sockaddr *)&src,
-				    (struct sockaddr *)&dst,
-				    sh, 0, NULL,
-				    use_mflowid, mflowid,
-				    vrf_id, port);
-			}
-		}
-		goto bad;
-	} else if (stcb == NULL) {
-		refcount_up = 1;
-	}
-#ifdef IPSEC
-	/*-
-	 * 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 && ipsec6_in_reject(m, &inp->ip_inp.inp)) {
-		MODULE_GLOBAL(ipsec6stat).in_polvio++;
-		SCTP_STAT_INCR(sctps_hdrops);
-		goto bad;
+		compute_crc = 0;
+	} else {
+		SCTP_STAT_INCR(sctps_recvswcrc);
+		compute_crc = 1;
 	}
 #endif
-
-	ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
-	/* sa_ignore NO_NULL_CHK */
 	sctp_common_input_processing(&m, iphlen, offset, length,
 	    (struct sockaddr *)&src,
 	    (struct sockaddr *)&dst,
-	    sh, ch, inp, stcb, net, ecn_bits,
+	    sh, ch,
+#if !defined(SCTP_WITH_NO_CSUM)
+	    compute_crc,
+#endif
+	    ecn_bits,
 	    use_mflowid, mflowid,
 	    vrf_id, port);
-	if (m) {
-		sctp_m_freem(m);
-	}
-	if ((inp) && (refcount_up)) {
-		/* reduce ref-count */
-		SCTP_INP_WLOCK(inp);
-		SCTP_INP_DECR_REF(inp);
-		SCTP_INP_WUNLOCK(inp);
-	}
-	return (IPPROTO_DONE);
-bad:
-	if (stcb) {
-		SCTP_TCB_UNLOCK(stcb);
-	}
-	if ((inp) && (refcount_up)) {
-		/* reduce ref-count */
-		SCTP_INP_WLOCK(inp);
-		SCTP_INP_DECR_REF(inp);
-		SCTP_INP_WUNLOCK(inp);
-	}
+out:
 	if (m) {
 		sctp_m_freem(m);
 	}


More information about the svn-src-stable-9 mailing list