/*************************************************************************
* (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
* by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: aitcrc.c,v 1.1.1.1 2008/11/05 17:02:55 misho Exp $
*
*************************************************************************/
#include "global.h"
static int crc_Errno;
static char crc_Error[MAX_STR + 1];
const u_long crc_modAdler = 0xFFF1L;
const crcPoly_t crc_Poly[] = {
{ 1, (u_long) 0x1, "CRC-1-Parity" },
{ 4, (u_long) 0x3, "CRC-4-ITU" },
{ 5, (u_long) 0x15, "CRC-5-ITU" },
{ 6, (u_long) 0x3, "CRC-6-ITU" },
{ 7, (u_long) 0x9, "CRC-7-MMC" },
{ 8, (u_long) 0x8D, "CRC-8-CCITT" },
{ 10, (u_long) 0x233, "CRC-10" },
{ 11, (u_long) 0x385, "CRC-11-FlexRay" },
{ 12, (u_long) 0x80F, "CRC-12-Telco" },
{ 15, (u_long) 0x4599, "CRC-15-CAN" },
{ 16, (u_long) 0x8005, "CRC-16-IBM" },
{ 24, (u_long) 0x864CFB, "CRC-24-Radix64" },
{ 30, (u_long) 0x2030B9C7, "CRC-30-CDMA" },
{ 32, (u_long) 0x04C11DB7, "CRC-32-802.3" }
};
// ----------------------------------------------------------
inline int crc_GetErrno()
{
return crc_Errno;
}
inline const char *crc_GetError()
{
return crc_Error;
}
// ----------------------------------------------------------
inline u_long crcReflect(u_long crcNum, u_char crcBits)
{
register u_long i, j, rev;
for (i = (u_long) 1 << (crcBits - 1), j = 1, rev ^= rev; i; i >>= 1, j <<= 1)
if (crcNum & i)
rev |= j;
crc_Errno ^= crc_Errno;
return rev;
}
inline u_long crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_long initCRC, u_long xorCRC)
{
const u_long bits = sizeof(long) * 8 - crcBits;
u_long poly, crchibit, crc;
register u_long i, j, b, ch;
if (!psBuf) {
crc_Errno = 1;
strlcpy(crc_Error, "crcCalc(): Invalid parameters!", MAX_STR + 1);
return -1;
}
switch (crcBits) {
case 1:
poly = crc_Poly[0].poly_num;
break;
case 4:
poly = crc_Poly[1].poly_num;
break;
case 5:
poly = crc_Poly[2].poly_num;
break;
case 6:
poly = crc_Poly[3].poly_num;
break;
case 7:
poly = crc_Poly[4].poly_num;
break;
case 8:
poly = crc_Poly[5].poly_num;
break;
case 10:
poly = crc_Poly[6].poly_num;
break;
case 11:
poly = crc_Poly[7].poly_num;
break;
case 12:
poly = crc_Poly[8].poly_num;
break;
case 15:
poly = crc_Poly[9].poly_num;
break;
case 16:
poly = crc_Poly[10].poly_num;
break;
case 24:
poly = crc_Poly[11].poly_num;
break;
case 30:
poly = crc_Poly[12].poly_num;
break;
case 32:
poly = crc_Poly[13].poly_num;
break;
default:
crc_Errno = 2;
strlcpy(crc_Error, "crcCalc(): Unsupported CRC method!!!", MAX_STR + 1);
return -1;
}
poly <<= bits;
crchibit = (u_long) 1 << (crcBits - 1);
crchibit <<= bits;
crc = initCRC << bits;
for (i = 0; i < bufLen; i++) {
ch = (u_long) *psBuf++;
if (RevOpts & REVOPTS_REVERTBYTE)
ch = crcReflect(ch, 8);
for (j = 0x80; j; j >>= 1) {
b = crc & crchibit;
crc <<= 1;
if (ch & j)
b ^= crchibit;
if (b)
crc ^= poly;
}
}
if (RevOpts & REVOPTS_REVERTCRC)
crc = crcReflect(crc, sizeof(long) * 8);
crc ^= xorCRC << bits;
crc &= (((crchibit - 1) << 1) | 1);
if (!(RevOpts & REVOPTS_REVERTCRC))
crc >>= bits;
crc_Errno ^= crc_Errno;
return crc;
}
// ----------------------------------------------------------
inline u_short crcIP(u_short * __restrict nBuf, int bufLen)
{
register u_long sum;
if (!nBuf) {
crc_Errno = 1;
strlcpy(crc_Error, "crcIP(): Invalid parameters!", MAX_STR + 1);
return -1;
}
for (sum = 0; bufLen; bufLen--)
sum += *nBuf++;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += sum >> 16;
crc_Errno ^= crc_Errno;
return (u_short) ~sum;
}
inline u_long crcFletcher(u_short * __restrict nBuf, int bufLen)
{
register u_long s1, s2, clen;
if (!nBuf) {
crc_Errno = 1;
strlcpy(crc_Error, "crcFletcher(): Invalid parameters!", MAX_STR + 1);
return -1;
}
s1 = s2 = 0xFFFF;
while (bufLen) {
clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
bufLen -= clen;
do {
s1 += (u_long) *nBuf++;
s2 += s1;
} while (--clen);
s1 = (s1 >> 16) + (s1 & 0xFFFF);
s2 = (s2 >> 16) + (s2 & 0xFFFF);
}
crc_Errno ^= crc_Errno;
return (s2 << 16) | s1;
}
inline u_long crcAdler(u_char * __restrict psBuf, int bufLen)
{
register u_long s1, s2, clen;
if (!psBuf) {
crc_Errno = 1;
strlcpy(crc_Error, "crcAdler(): Invalid parameters!", MAX_STR + 1);
return -1;
}
s1 = 1L;
s2 ^= s2;
while (bufLen) {
clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
bufLen -= clen;
do {
s1 += (u_long) *psBuf++;
s2 += s1;
} while (--clen);
s1 %= crc_modAdler;
s2 %= crc_modAdler;
}
crc_Errno ^= crc_Errno;
return (s2 << 16) | s1;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>