> On 26. Dec 2017, at 13:35, Michael Tuexen <tue...@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__ */
> 

_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to