diff options
Diffstat (limited to 'chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c')
-rwxr-xr-x | chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c | 124 |
1 files changed, 63 insertions, 61 deletions
diff --git a/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c index 16ce971c7d2..0be0795cf2a 100755 --- a/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c @@ -34,18 +34,30 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_crc32.c 310590 2016-12-26 11:06:41Z tuexen $"); -#endif +__FBSDID("$FreeBSD: head/sys/netinet/sctp_crc32.c 327200 2017-12-26 12:35:02Z tuexen $"); + +#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> - -#if !defined(SCTP_WITH_NO_CSUM) -#if defined(__FreeBSD__) && __FreeBSD_version >= 800000 +#include <netinet/sctp_crc32.h> +#endif #else +#include <netinet/sctp_os.h> +#include <netinet/sctp.h> +#include <netinet/sctp_crc32.h> +#include <netinet/sctp_pcb.h> +#endif + +#if !defined(__FreeBSD__) /** * * Routine Description: @@ -713,8 +725,8 @@ calculate_crc32c(uint32_t crc32c, return (multitable_crc32c(crc32c, buffer, length)); } } -#endif /* FreeBSD < 80000 || other OS */ +#endif #if defined(__Userspace__) uint32_t #else @@ -723,18 +735,16 @@ 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; @@ -743,66 +753,58 @@ 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)); - } - 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); + + while (offset > 0) { + KASSERT(m != NULL, ("sctp_calculate_cksum, offset > length of mbuf chain")); + if (offset < (uint32_t)m->m_len) { + break; } - 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); } -#endif /* !defined(SCTP_WITH_NO_CSUM) */ - #if defined(__FreeBSD__) +#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) { -#if defined(SCTP_WITH_NO_CSUM) -#ifdef INVARIANTS - panic("sctp_delayed_cksum() called when using no SCTP CRC."); -#endif -#else uint32_t checksum; checksum = sctp_calculate_cksum(m, offset); @@ -810,18 +812,18 @@ sctp_delayed_cksum(struct mbuf *m, uint32_t offset) SCTP_STAT_INCR(sctps_sendswcrc); 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. - */ + if (offset + sizeof(uint32_t) > (uint32_t)(m->m_len)) { +#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 + *(uint32_t *)(m->m_data + offset) = checksum; } #endif +#endif |