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

Michael Tuexen tuexen at freebsd.org
Tue Dec 26 12:41:04 UTC 2017


> On 26. Dec 2017, at 13:35, Michael Tuexen <tuexen at FreeBSD.org> wrote:
> 
> 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.
Thanks to Kevin Bowling. Sorry for the typo.

Best regards
Michael
> 
> 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-all mailing list