svn commit: r327200 - in head/sys: conf netinet

Michael Tuexen tuexen at FreeBSD.org
Tue Dec 26 12:35:04 UTC 2017


Author: tuexen
Date: Tue Dec 26 12:35:02 2017
New Revision: 327200
URL: https://svnweb.freebsd.org/changeset/base/327200

Log:
  When adding support for sending SCTP packets containing an ABORT chunk
  to ipfw in https://svnweb.freebsd.org/changeset/base/326233,
  a dependency on the SCTP stack was added to ipfw by accident.
  
  This was noted by Kevel Bowling in https://reviews.freebsd.org/D13594
  where also a solution was suggested. This patch is based on Kevin's
  suggestion, but implements the required SCTP checksum computation
  without any dependency on other SCTP sources.
  
  While there, do some cleanups and improve comments.
  
  Thanks to Kevin Kevin Browling for reporting the issue and suggesting
  a fix.

Modified:
  head/sys/conf/files
  head/sys/netinet/sctp_crc32.c
  head/sys/netinet/sctp_crc32.h

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Dec 26 12:11:04 2017	(r327199)
+++ head/sys/conf/files	Tue Dec 26 12:35:02 2017	(r327200)
@@ -4255,7 +4255,7 @@ netinet/sctp_asconf.c		optional inet sctp | inet6 sctp
 netinet/sctp_auth.c		optional inet sctp | inet6 sctp
 netinet/sctp_bsd_addr.c		optional inet sctp | inet6 sctp
 netinet/sctp_cc_functions.c	optional inet sctp | inet6 sctp
-netinet/sctp_crc32.c		optional inet sctp | inet6 sctp
+netinet/sctp_crc32.c		optional inet | inet6
 netinet/sctp_indata.c		optional inet sctp | inet6 sctp
 netinet/sctp_input.c		optional inet sctp | inet6 sctp
 netinet/sctp_output.c		optional inet sctp | inet6 sctp

Modified: head/sys/netinet/sctp_crc32.c
==============================================================================
--- head/sys/netinet/sctp_crc32.c	Tue Dec 26 12:11:04 2017	(r327199)
+++ head/sys/netinet/sctp_crc32.c	Tue Dec 26 12:35:02 2017	(r327200)
@@ -35,29 +35,36 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_sctp.h"
+
+#ifdef SCTP
 #include <netinet/sctp_os.h>
 #include <netinet/sctp.h>
 #include <netinet/sctp_crc32.h>
 #include <netinet/sctp_pcb.h>
+#else
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
 
+#include <netinet/sctp_crc32.h>
+#endif
 
-
 static uint32_t
 sctp_finalize_crc32c(uint32_t crc32c)
 {
 	uint32_t result;
-
 #if BYTE_ORDER == BIG_ENDIAN
 	uint8_t byte0, byte1, byte2, byte3;
-
 #endif
+
 	/* Complement the result */
 	result = ~crc32c;
 #if BYTE_ORDER == BIG_ENDIAN
 	/*
-	 * For BIG-ENDIAN.. aka Motorola byte order the result is in
-	 * little-endian form. So we must manually swap the bytes. Then we
-	 * can call htonl() which does nothing...
+	 * For BIG-ENDIAN platforms the result is in little-endian form. So
+	 * we must swap the bytes to return the result in network byte
+	 * order.
 	 */
 	byte0 = result & 0x000000ff;
 	byte1 = (result >> 8) & 0x000000ff;
@@ -66,56 +73,54 @@ sctp_finalize_crc32c(uint32_t crc32c)
 	crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
 #else
 	/*
-	 * For INTEL platforms the result comes out in network order. No
-	 * htonl is required or the swap above. So we optimize out both the
-	 * htonl and the manual swap above.
+	 * For LITTLE ENDIAN platforms the result is in already in network
+	 * byte order.
 	 */
 	crc32c = result;
 #endif
 	return (crc32c);
 }
 
+/*
+ * Compute the SCTP checksum in network byte order for a given mbuf chain m
+ * which contains an SCTP packet starting at offset.
+ * Since this function is also called by ipfw, don't assume that
+ * it is compiled on a kernel with SCTP support.
+ */
 uint32_t
 sctp_calculate_cksum(struct mbuf *m, uint32_t offset)
 {
-	/*
-	 * given a mbuf chain with a packetheader offset by 'offset'
-	 * pointing at a sctphdr (with csum set to 0) go through the chain
-	 * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
-	 * has a side bonus as it will calculate the total length of the
-	 * mbuf chain. Note: if offset is greater than the total mbuf
-	 * length, checksum=1, pktlen=0 is returned (ie. no real error code)
-	 */
 	uint32_t base = 0xffffffff;
-	struct mbuf *at;
 
-	at = m;
-	/* find the correct mbuf and offset into mbuf */
-	while ((at != NULL) && (offset > (uint32_t)SCTP_BUF_LEN(at))) {
-		offset -= SCTP_BUF_LEN(at);	/* update remaining offset
-						 * left */
-		at = SCTP_BUF_NEXT(at);
-	}
-	while (at != NULL) {
-		if ((SCTP_BUF_LEN(at) - offset) > 0) {
-			base = calculate_crc32c(base,
-			    (unsigned char *)(SCTP_BUF_AT(at, offset)),
-			    (unsigned int)(SCTP_BUF_LEN(at) - offset));
+	while (offset > 0) {
+		KASSERT(m != NULL, ("sctp_calculate_cksum, offset > length of mbuf chain"));
+		if (offset < (uint32_t)m->m_len) {
+			break;
 		}
-		if (offset) {
-			/* we only offset once into the first mbuf */
-			if (offset < (uint32_t)SCTP_BUF_LEN(at))
-				offset = 0;
-			else
-				offset -= SCTP_BUF_LEN(at);
-		}
-		at = SCTP_BUF_NEXT(at);
+		offset -= m->m_len;
+		m = m->m_next;
 	}
+	if (offset > 0) {
+		base = calculate_crc32c(base,
+		    (unsigned char *)(m->m_data + offset),
+		    (unsigned int)(m->m_len - offset));
+		m = m->m_next;
+	}
+	while (m != NULL) {
+		base = calculate_crc32c(base,
+		    (unsigned char *)m->m_data,
+		    (unsigned int)m->m_len);
+		m = m->m_next;
+	}
 	base = sctp_finalize_crc32c(base);
 	return (base);
 }
 
-
+#ifdef SCTP
+/*
+ * Compute and insert the SCTP checksum in network byte order for a given
+ * mbuf chain m which contains an SCTP packet starting at offset.
+ */
 void
 sctp_delayed_cksum(struct mbuf *m, uint32_t offset)
 {
@@ -127,14 +132,15 @@ sctp_delayed_cksum(struct mbuf *m, uint32_t offset)
 	offset += offsetof(struct sctphdr, checksum);
 
 	if (offset + sizeof(uint32_t) > (uint32_t)(m->m_len)) {
-		SCTP_PRINTF("sctp_delayed_cksum(): m->len: %d,  off: %d.\n",
-		    (uint32_t)m->m_len, offset);
-		/*
-		 * XXX this shouldn't happen, but if it does, the correct
-		 * behavior may be to insert the checksum in the appropriate
-		 * next mbuf in the chain.
-		 */
+#ifdef INVARIANTS
+		panic("sctp_delayed_cksum(): m->m_len: %d, offset: %u.",
+		    m->m_len, offset);
+#else
+		SCTP_PRINTF("sctp_delayed_cksum(): m->m_len: %d, offset: %u.\n",
+		    m->m_len, offset);
+#endif
 		return;
 	}
 	*(uint32_t *)(m->m_data + offset) = checksum;
 }
+#endif

Modified: head/sys/netinet/sctp_crc32.h
==============================================================================
--- head/sys/netinet/sctp_crc32.h	Tue Dec 26 12:11:04 2017	(r327199)
+++ head/sys/netinet/sctp_crc32.h	Tue Dec 26 12:35:02 2017	(r327200)
@@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
 
 #if defined(_KERNEL)
 uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t);
+#ifdef SCTP
 void sctp_delayed_cksum(struct mbuf *, uint32_t offset);
+#endif
 #endif				/* _KERNEL */
 #endif				/* __crc32c_h__ */


More information about the svn-src-head mailing list