Home | History | Annotate | Download | only in inet
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 
     31 /*
     32  * Fast CRC32 calculation algorithm suggested by Ferenc Rakoczi
     33  * (ferenc.rakoczi (at) sun.com).  The basic idea is to look at it
     34  * four bytes (one word) at a time, using four tables.  The
     35  * standard algorithm in RFC 3309 uses one table.
     36  */
     37 
     38 /*
     39  * SCTP uses reflected/reverse polynomial CRC32 with generating
     40  * polynomial 0x1EDC6F41L
     41  */
     42 #define	SCTP_POLY 0x1EDC6F41L
     43 
     44 /* The four CRC tables. */
     45 static uint32_t crctab[4][256];
     46 
     47 static uint32_t
     48 reflect_32(uint32_t b)
     49 {
     50 	int i;
     51 	uint32_t rw = 0;
     52 
     53 	for (i = 0; i < 32; i++) {
     54 		if (b & 1) {
     55 			rw |= 1 << (31 - i);
     56 		}
     57 		b >>= 1;
     58 	}
     59 	return (rw);
     60 }
     61 
     62 #ifdef _BIG_ENDIAN
     63 
     64 /*
     65  * This function is only used for big endian processor.
     66  */
     67 static uint32_t
     68 flip32(uint32_t w)
     69 {
     70 	return (((w >> 24) | ((w >> 8) & 0xff00) | ((w << 8) & 0xff0000) |
     71 		(w << 24)));
     72 }
     73 
     74 #endif
     75 
     76 void
     77 sctp_crc32_init(void)
     78 {
     79 	uint32_t i, j, k, crc;
     80 
     81 	for (i = 0; i < 256; i++) {
     82 		crc = reflect_32(i);
     83 		for (k = 0; k < 4; k++) {
     84 			for (j = 0; j < 8; j++) {
     85 				crc = (crc & 0x80000000) ?
     86 				    (crc << 1) ^ SCTP_POLY : crc << 1;
     87 			}
     88 #ifdef _BIG_ENDIAN
     89 			crctab[3 - k][i] = flip32(reflect_32(crc));
     90 #else
     91 			crctab[k][i] = reflect_32(crc);
     92 #endif
     93 		}
     94 	}
     95 }
     96 
     97 static void
     98 sctp_crc_byte(uint32_t *crcptr, const uint8_t *buf, int len)
     99 {
    100 	uint32_t crc;
    101 	int i;
    102 
    103 	crc = *crcptr;
    104 	for (i = 0; i < len; i++) {
    105 #ifdef _BIG_ENDIAN
    106 		crc = (crc << 8) ^ crctab[3][buf[i] ^ (crc >> 24)];
    107 #else
    108 		crc = (crc >> 8) ^ crctab[0][buf[i] ^ (crc & 0xff)];
    109 #endif
    110 	}
    111 	*crcptr = crc;
    112 }
    113 
    114 static void
    115 sctp_crc_word(uint32_t *crcptr, const uint32_t *buf, int len)
    116 {
    117 	uint32_t w, crc;
    118 	int i;
    119 
    120 	crc = *crcptr;
    121 	for (i = 0; i < len; i++) {
    122 		w = crc ^ buf[i];
    123 		crc = crctab[0][w >> 24] ^ crctab[1][(w >> 16) & 0xff] ^
    124 		    crctab[2][(w >> 8) & 0xff] ^ crctab[3][w & 0xff];
    125 	}
    126 	*crcptr = crc;
    127 }
    128 
    129 uint32_t
    130 sctp_crc32(uint32_t crc32, const uint8_t *buf, int len)
    131 {
    132 	int rem;
    133 
    134 	rem = 4 - ((uintptr_t)buf) & 3;
    135 	if (rem != 0) {
    136 		if (len < rem) {
    137 			rem = len;
    138 		}
    139 		sctp_crc_byte(&crc32, buf, rem);
    140 		buf = buf + rem;
    141 		len = len - rem;
    142 	}
    143 
    144 	if (len > 3) {
    145 		sctp_crc_word(&crc32, (const uint32_t *)buf, len / 4);
    146 	}
    147 
    148 	rem = len & 3;
    149 	if (rem != 0) {
    150 		sctp_crc_byte(&crc32, buf + len - rem, rem);
    151 	}
    152 	return (crc32);
    153 }
    154