Annotation of libelwix/src/crc.c, revision 1.5
1.1 misho 1: /*************************************************************************
2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.5 ! misho 6: * $Id: crc.c,v 1.4.18.1 2017/12/08 00:07:13 misho Exp $
1.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.4 misho 15: Copyright 2004 - 2015
1.1 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
49: /* Adler module */
50: const u_int crc_modAdler = 0xFFF1L;
51:
52: /* All known library CRC types ... */
53: const crcPoly_t crc_Poly[] = {
54: { 1, (u_int) 0x1, "CRC-1-Parity" },
55: { 4, (u_int) 0x3, "CRC-4-ITU" },
56: { 5, (u_int) 0x15, "CRC-5-ITU" },
57: { 6, (u_int) 0x3, "CRC-6-ITU" },
58: { 7, (u_int) 0x9, "CRC-7-MMC" },
59: { 8, (u_int) 0x8D, "CRC-8-CCITT" },
60: { 10, (u_int) 0x233, "CRC-10" },
61: { 11, (u_int) 0x385, "CRC-11-FlexRay" },
62: { 12, (u_int) 0x80F, "CRC-12-Telco" },
63: { 15, (u_int) 0x4599, "CRC-15-CAN" },
64: { 16, (u_int) 0x8005, "CRC-16-IBM" },
65: { 24, (u_int) 0x864CFB, "CRC-24-Radix64" },
66: { 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" },
67: { 32, (u_int) 0x04C11DB7, "CRC-32-802.3" }
68: };
69:
70:
71: /*
72: * crcReflect() - Reflect all bits of number
73: *
74: * @crcNum = Number for reflection
75: * @crcBits = Number width bits
76: * return: -1 error, !=-1 reflecting number
77: */
1.5 ! misho 78: u_int
1.1 misho 79: crcReflect(u_int crcNum, u_char crcBits)
80: {
1.2 misho 81: register u_int i, j = 1, rev = 0;
1.1 misho 82:
1.2 misho 83: for (i = (u_int) 1 << (crcBits - 1); i; i >>= 1, j <<= 1)
1.1 misho 84: if (crcNum & i)
85: rev |= j;
86: return rev;
87: }
88:
89: /*
90: * crcCalc() - Generic CRC calculation function for many sub variants of CRC algorithms
91: *
92: * @psBuf = Data for calculation
93: * @bufLen = Length of data
94: * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32)
95: * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
96: * @initCRC = Initial CRC value
97: * @xorCRC = Last xor CRC value
98: * return: -1 error, !=-1 CRC checksum
99: */
1.5 ! misho 100: u_int
1.1 misho 101: crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC)
102: {
103: const u_int bits = sizeof(int) * 8 - crcBits;
104: u_int poly, crchibit, crc;
105: register u_int i, j, b, ch;
106:
107: assert(psBuf);
108:
109: switch (crcBits) {
110: case 1:
111: poly = crc_Poly[0].poly_num;
112: break;
113: case 4:
114: poly = crc_Poly[1].poly_num;
115: break;
116: case 5:
117: poly = crc_Poly[2].poly_num;
118: break;
119: case 6:
120: poly = crc_Poly[3].poly_num;
121: break;
122: case 7:
123: poly = crc_Poly[4].poly_num;
124: break;
125: case 8:
126: poly = crc_Poly[5].poly_num;
127: break;
128: case 10:
129: poly = crc_Poly[6].poly_num;
130: break;
131: case 11:
132: poly = crc_Poly[7].poly_num;
133: break;
134: case 12:
135: poly = crc_Poly[8].poly_num;
136: break;
137: case 15:
138: poly = crc_Poly[9].poly_num;
139: break;
140: case 16:
141: poly = crc_Poly[10].poly_num;
142: break;
143: case 24:
144: poly = crc_Poly[11].poly_num;
145: break;
146: case 30:
147: poly = crc_Poly[12].poly_num;
148: break;
149: case 32:
150: poly = crc_Poly[13].poly_num;
151: break;
152: default:
153: elwix_SetErr(EINVAL, "crcCalc(): Unsupported CRC method!!!");
154: return -1;
155: }
156: poly <<= bits;
157:
158: crchibit = (u_int) 1 << (crcBits - 1);
159: crchibit <<= bits;
160: crc = initCRC << bits;
161:
162: for (i = 0; i < bufLen; i++) {
163: ch = (u_int) *psBuf++;
164: if (RevOpts & REVOPTS_REVERTBYTE)
165: ch = crcReflect(ch, 8);
166:
167: for (j = 0x80; j; j >>= 1) {
168: b = crc & crchibit;
169: crc <<= 1;
170:
171: if (ch & j)
172: b ^= crchibit;
173: if (b)
174: crc ^= poly;
175: }
176: }
177:
178: if (RevOpts & REVOPTS_REVERTCRC)
179: crc = crcReflect(crc, sizeof(int) * 8);
180: crc ^= xorCRC << bits;
181: crc &= (((crchibit - 1) << 1) | 1);
182: if (!(RevOpts & REVOPTS_REVERTCRC))
183: crc >>= bits;
184:
185: return crc;
186: }
187:
188:
189: /*
190: * crcIP() - Checksum in IP communication
191: *
192: * @buf = Data for calculation
193: * @bufLen = Length of data
194: * return: -1 error, !=-1 Checksum
195: */
1.5 ! misho 196: u_short
1.1 misho 197: crcIP(u_char * __restrict buf, int bufLen)
198: {
199: register u_int sum;
200: u_short last = 0, *nBuf = (u_short*) buf;
201:
202: assert(buf);
203:
1.5 ! misho 204: for (sum = 0; bufLen > 1; bufLen -= 2)
1.1 misho 205: sum += *nBuf++;
206: if (bufLen == 1) {
207: *(u_char*)(&last) += *(u_char*) nBuf;
208: sum += last;
209: }
210:
211: sum = (sum >> 16) + (sum & 0xFFFF);
212: sum += sum >> 16;
213:
214: return (u_short) ~sum;
215: }
216:
217: /*
1.5 ! misho 218: * crcTCP() - Checksum for TCP v4 communication
! 219: *
! 220: * @buf = Data for calculation
! 221: * @bufLen = Length of data
! 222: * @th = TCP header
! 223: * return: -1 error, !=-1 Checksum
! 224: */
! 225: u_short
! 226: crcTCP(struct in_addr src, struct in_addr dst, u_char * __restrict th)
! 227: {
! 228: struct psd_tcp {
! 229: struct in_addr src;
! 230: struct in_addr dst;
! 231: u_char pad;
! 232: u_char proto;
! 233: u_short tcp_len;
! 234: u_char tcp[20];
! 235: } buf;
! 236:
! 237: buf.src = src;
! 238: buf.dst = dst;
! 239: buf.pad = 0;
! 240: buf.proto = IPPROTO_TCP;
! 241: buf.tcp_len = htons(sizeof buf.tcp);
! 242: memcpy(&buf.tcp, th, sizeof buf.tcp);
! 243:
! 244: return crcIP((u_char*) &buf, sizeof buf);
! 245: }
! 246:
! 247: /*
! 248: * crcUDP() - Checksum for UDP v4 communication
! 249: *
! 250: * @buf = Data for calculation
! 251: * @bufLen = Length of data
! 252: * @uh = UDP header
! 253: * return: -1 error, !=-1 Checksum
! 254: */
! 255: u_short
! 256: crcUDP(struct in_addr src, struct in_addr dst, u_char * __restrict uh)
! 257: {
! 258: struct psd_udp {
! 259: struct in_addr src;
! 260: struct in_addr dst;
! 261: u_char pad;
! 262: u_char proto;
! 263: u_short udp_len;
! 264: u_char udp[8];
! 265: } buf;
! 266:
! 267: buf.src = src;
! 268: buf.dst = dst;
! 269: buf.pad = 0;
! 270: buf.proto = IPPROTO_UDP;
! 271: buf.udp_len = htons(sizeof buf.udp);
! 272: memcpy(&buf.udp, uh, sizeof buf.udp);
! 273:
! 274: return crcIP((u_char*) &buf, sizeof buf);
! 275: }
! 276:
! 277:
! 278: /*
1.1 misho 279: * crcFletcher16() - Fletcher-16 Checksum computing
280: *
281: * @nBuf = Data for calculation
282: * @bufLen = Length of data
283: * return: -1 error, !=-1 Checksum
284: */
1.5 ! misho 285: u_short
1.1 misho 286: crcFletcher16(u_short * __restrict nBuf, int bufLen)
287: {
288: register u_short s1, s2;
289: register u_int clen;
290:
291: assert(nBuf);
292:
293: s1 = s2 = 0xFF;
294: while (bufLen) {
295: clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen;
296: bufLen -= clen;
297:
298: do {
299: s1 += (u_short) *nBuf++;
300: s2 += s1;
301: } while (--clen);
302:
303: s1 = (s1 >> 8) + (s1 & 0xFF);
304: s2 = (s2 >> 8) + (s2 & 0xFF);
305: }
306:
307: return (s2 << 8) | s1;
308: }
309:
310: /*
311: * crcFletcher() - Fletcher-32 Checksum computing
312: *
313: * @nBuf = Data for calculation
314: * @bufLen = Length of data
315: * return: -1 error, !=-1 Checksum
316: */
1.5 ! misho 317: u_int
1.1 misho 318: crcFletcher(u_short * __restrict nBuf, int bufLen)
319: {
320: register u_int s1, s2, clen;
321:
322: assert(nBuf);
323:
324: s1 = s2 = 0xFFFF;
325: while (bufLen) {
326: clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
327: bufLen -= clen;
328:
329: do {
330: s1 += (u_int) *nBuf++;
331: s2 += s1;
332: } while (--clen);
333:
334: s1 = (s1 >> 16) + (s1 & 0xFFFF);
335: s2 = (s2 >> 16) + (s2 & 0xFFFF);
336: }
337:
338: return (s2 << 16) | s1;
339: }
340:
341: /*
342: * crcAdler() - crcAdler-32 Checksum computing
343: *
344: * @psBuf = Data for calculation
345: * @bufLen = Length of data
346: * return: -1 error, !=-1 Checksum
347: */
1.5 ! misho 348: u_int
1.1 misho 349: crcAdler(u_char * __restrict psBuf, int bufLen)
350: {
1.2 misho 351: register u_int s1 = 1, s2 = 0, clen;
1.1 misho 352:
353: assert(psBuf);
354:
355: while (bufLen) {
356: clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
357: bufLen -= clen;
358:
359: do {
360: s1 += (u_int) *psBuf++;
361: s2 += s1;
362: } while (--clen);
363:
364: s1 %= crc_modAdler;
365: s2 %= crc_modAdler;
366: }
367:
368: return (s2 << 16) | s1;
369: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>