Annotation of libelwix/src/crc.c, revision 1.5.28.2
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.28.2! misho 6: * $Id: crc.c,v 1.5.28.1 2019/12/18 20:00:18 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.5.28.1 misho 15: Copyright 2004 - 2019
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:
1.5.28.1 misho 49: /* CRC16 poly */
50: const u_short crc_16poly = 0x1021;
51:
1.1 misho 52: /* Adler module */
53: const u_int crc_modAdler = 0xFFF1L;
54:
55: /* All known library CRC types ... */
56: const crcPoly_t crc_Poly[] = {
57: { 1, (u_int) 0x1, "CRC-1-Parity" },
58: { 4, (u_int) 0x3, "CRC-4-ITU" },
59: { 5, (u_int) 0x15, "CRC-5-ITU" },
60: { 6, (u_int) 0x3, "CRC-6-ITU" },
61: { 7, (u_int) 0x9, "CRC-7-MMC" },
62: { 8, (u_int) 0x8D, "CRC-8-CCITT" },
63: { 10, (u_int) 0x233, "CRC-10" },
64: { 11, (u_int) 0x385, "CRC-11-FlexRay" },
65: { 12, (u_int) 0x80F, "CRC-12-Telco" },
66: { 15, (u_int) 0x4599, "CRC-15-CAN" },
67: { 16, (u_int) 0x8005, "CRC-16-IBM" },
68: { 24, (u_int) 0x864CFB, "CRC-24-Radix64" },
69: { 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" },
70: { 32, (u_int) 0x04C11DB7, "CRC-32-802.3" }
71: };
72:
73:
74: /*
75: * crcReflect() - Reflect all bits of number
76: *
77: * @crcNum = Number for reflection
78: * @crcBits = Number width bits
1.5.28.1 misho 79: * return: reflecting number
1.1 misho 80: */
1.5 misho 81: u_int
1.1 misho 82: crcReflect(u_int crcNum, u_char crcBits)
83: {
1.2 misho 84: register u_int i, j = 1, rev = 0;
1.1 misho 85:
1.2 misho 86: for (i = (u_int) 1 << (crcBits - 1); i; i >>= 1, j <<= 1)
1.1 misho 87: if (crcNum & i)
88: rev |= j;
89: return rev;
90: }
91:
92: /*
93: * crcCalc() - Generic CRC calculation function for many sub variants of CRC algorithms
94: *
95: * @psBuf = Data for calculation
96: * @bufLen = Length of data
97: * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32)
98: * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
99: * @initCRC = Initial CRC value
100: * @xorCRC = Last xor CRC value
1.5.28.1 misho 101: * return: CRC checksum
1.1 misho 102: */
1.5 misho 103: u_int
1.1 misho 104: crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC)
105: {
106: const u_int bits = sizeof(int) * 8 - crcBits;
107: u_int poly, crchibit, crc;
108: register u_int i, j, b, ch;
109:
110: assert(psBuf);
111:
112: switch (crcBits) {
113: case 1:
114: poly = crc_Poly[0].poly_num;
115: break;
116: case 4:
117: poly = crc_Poly[1].poly_num;
118: break;
119: case 5:
120: poly = crc_Poly[2].poly_num;
121: break;
122: case 6:
123: poly = crc_Poly[3].poly_num;
124: break;
125: case 7:
126: poly = crc_Poly[4].poly_num;
127: break;
128: case 8:
129: poly = crc_Poly[5].poly_num;
130: break;
131: case 10:
132: poly = crc_Poly[6].poly_num;
133: break;
134: case 11:
135: poly = crc_Poly[7].poly_num;
136: break;
137: case 12:
138: poly = crc_Poly[8].poly_num;
139: break;
140: case 15:
141: poly = crc_Poly[9].poly_num;
142: break;
143: case 16:
144: poly = crc_Poly[10].poly_num;
145: break;
146: case 24:
147: poly = crc_Poly[11].poly_num;
148: break;
149: case 30:
150: poly = crc_Poly[12].poly_num;
151: break;
152: case 32:
153: poly = crc_Poly[13].poly_num;
154: break;
155: default:
156: elwix_SetErr(EINVAL, "crcCalc(): Unsupported CRC method!!!");
157: return -1;
158: }
159: poly <<= bits;
160:
161: crchibit = (u_int) 1 << (crcBits - 1);
162: crchibit <<= bits;
163: crc = initCRC << bits;
164:
165: for (i = 0; i < bufLen; i++) {
166: ch = (u_int) *psBuf++;
167: if (RevOpts & REVOPTS_REVERTBYTE)
168: ch = crcReflect(ch, 8);
169:
170: for (j = 0x80; j; j >>= 1) {
171: b = crc & crchibit;
172: crc <<= 1;
173:
174: if (ch & j)
175: b ^= crchibit;
176: if (b)
177: crc ^= poly;
178: }
179: }
180:
181: if (RevOpts & REVOPTS_REVERTCRC)
182: crc = crcReflect(crc, sizeof(int) * 8);
183: crc ^= xorCRC << bits;
184: crc &= (((crchibit - 1) << 1) | 1);
185: if (!(RevOpts & REVOPTS_REVERTCRC))
186: crc >>= bits;
187:
188: return crc;
189: }
190:
191:
192: /*
1.5.28.2! misho 193: * crc16_ext() - Checksum ver.2 calculation in X/Y modem communication
1.5.28.1 misho 194: *
195: * @buf = Data for calculation
196: * @bufLen = Length of data
197: * return: Checksum
198: */
199: u_short
1.5.28.2! misho 200: crc16_ext(u_char * __restrict buf, int bufLen)
1.5.28.1 misho 201: {
202: u_short crc, x;
203: register u_short i;
204:
205: assert(buf);
206:
207: for (crc = 0; bufLen > 0; bufLen--, buf++)
208: for (i = 0x80; i; i >>= 1) {
209: x = crc >> 15;
210: crc <<= 1;
211:
212: if (*buf & i)
213: crc++;
214: if (x)
215: crc ^= crc_16poly;
216: }
217:
218: for (i = 0; i < 16; i++) {
219: x = crc >> 15;
220: crc <<= 1;
221:
222: if (x)
223: crc ^= crc_16poly;
1.5.28.2! misho 224: }
! 225:
! 226: return crc;
! 227: }
! 228:
! 229: /*
! 230: * crc16() - Checksum calculation in X/Y modem communication
! 231: *
! 232: * @buf = Data for calculation
! 233: * @bufLen = Length of data
! 234: * return: Checksum
! 235: */
! 236: u_short
! 237: crc16(u_char * __restrict buf, int bufLen)
! 238: {
! 239: u_short crc;
! 240: register u_char i;
! 241:
! 242: for (crc = 0; bufLen > 0; bufLen--, buf++) {
! 243: crc ^= (u_short) *buf << 8;
! 244: for (i = 0x80; i; i >>= 1)
! 245: if (crc & 0x8000)
! 246: crc = crc << 1 ^ crc_16poly;
! 247: else
! 248: crc <<= 1;
1.5.28.1 misho 249: }
250:
251: return crc;
252: }
253:
254: /*
1.1 misho 255: * crcIP() - Checksum in IP communication
256: *
257: * @buf = Data for calculation
258: * @bufLen = Length of data
1.5.28.1 misho 259: * return: Checksum
1.1 misho 260: */
1.5 misho 261: u_short
1.1 misho 262: crcIP(u_char * __restrict buf, int bufLen)
263: {
264: register u_int sum;
265: u_short last = 0, *nBuf = (u_short*) buf;
266:
267: assert(buf);
268:
1.5 misho 269: for (sum = 0; bufLen > 1; bufLen -= 2)
1.1 misho 270: sum += *nBuf++;
271: if (bufLen == 1) {
272: *(u_char*)(&last) += *(u_char*) nBuf;
273: sum += last;
274: }
275:
276: sum = (sum >> 16) + (sum & 0xFFFF);
277: sum += sum >> 16;
278:
279: return (u_short) ~sum;
280: }
281:
282: /*
1.5 misho 283: * crcTCP() - Checksum for TCP v4 communication
284: *
285: * @buf = Data for calculation
286: * @bufLen = Length of data
287: * @th = TCP header
1.5.28.1 misho 288: * return: Checksum
1.5 misho 289: */
290: u_short
291: crcTCP(struct in_addr src, struct in_addr dst, u_char * __restrict th)
292: {
293: struct psd_tcp {
294: struct in_addr src;
295: struct in_addr dst;
296: u_char pad;
297: u_char proto;
298: u_short tcp_len;
299: u_char tcp[20];
300: } buf;
301:
302: buf.src = src;
303: buf.dst = dst;
304: buf.pad = 0;
305: buf.proto = IPPROTO_TCP;
306: buf.tcp_len = htons(sizeof buf.tcp);
307: memcpy(&buf.tcp, th, sizeof buf.tcp);
308:
309: return crcIP((u_char*) &buf, sizeof buf);
310: }
311:
312: /*
313: * crcUDP() - Checksum for UDP v4 communication
314: *
315: * @buf = Data for calculation
316: * @bufLen = Length of data
317: * @uh = UDP header
1.5.28.1 misho 318: * return: Checksum
1.5 misho 319: */
320: u_short
321: crcUDP(struct in_addr src, struct in_addr dst, u_char * __restrict uh)
322: {
323: struct psd_udp {
324: struct in_addr src;
325: struct in_addr dst;
326: u_char pad;
327: u_char proto;
328: u_short udp_len;
329: u_char udp[8];
330: } buf;
331:
332: buf.src = src;
333: buf.dst = dst;
334: buf.pad = 0;
335: buf.proto = IPPROTO_UDP;
336: buf.udp_len = htons(sizeof buf.udp);
337: memcpy(&buf.udp, uh, sizeof buf.udp);
338:
339: return crcIP((u_char*) &buf, sizeof buf);
340: }
341:
342:
343: /*
1.1 misho 344: * crcFletcher16() - Fletcher-16 Checksum computing
345: *
346: * @nBuf = Data for calculation
347: * @bufLen = Length of data
1.5.28.1 misho 348: * return: Checksum
1.1 misho 349: */
1.5 misho 350: u_short
1.1 misho 351: crcFletcher16(u_short * __restrict nBuf, int bufLen)
352: {
353: register u_short s1, s2;
354: register u_int clen;
355:
356: assert(nBuf);
357:
358: s1 = s2 = 0xFF;
359: while (bufLen) {
360: clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen;
361: bufLen -= clen;
362:
363: do {
364: s1 += (u_short) *nBuf++;
365: s2 += s1;
366: } while (--clen);
367:
368: s1 = (s1 >> 8) + (s1 & 0xFF);
369: s2 = (s2 >> 8) + (s2 & 0xFF);
370: }
371:
372: return (s2 << 8) | s1;
373: }
374:
375: /*
376: * crcFletcher() - Fletcher-32 Checksum computing
377: *
378: * @nBuf = Data for calculation
379: * @bufLen = Length of data
1.5.28.1 misho 380: * return: Checksum
1.1 misho 381: */
1.5 misho 382: u_int
1.1 misho 383: crcFletcher(u_short * __restrict nBuf, int bufLen)
384: {
385: register u_int s1, s2, clen;
386:
387: assert(nBuf);
388:
389: s1 = s2 = 0xFFFF;
390: while (bufLen) {
391: clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
392: bufLen -= clen;
393:
394: do {
395: s1 += (u_int) *nBuf++;
396: s2 += s1;
397: } while (--clen);
398:
399: s1 = (s1 >> 16) + (s1 & 0xFFFF);
400: s2 = (s2 >> 16) + (s2 & 0xFFFF);
401: }
402:
403: return (s2 << 16) | s1;
404: }
405:
406: /*
407: * crcAdler() - crcAdler-32 Checksum computing
408: *
409: * @psBuf = Data for calculation
410: * @bufLen = Length of data
1.5.28.1 misho 411: * return: Checksum
1.1 misho 412: */
1.5 misho 413: u_int
1.1 misho 414: crcAdler(u_char * __restrict psBuf, int bufLen)
415: {
1.2 misho 416: register u_int s1 = 1, s2 = 0, clen;
1.1 misho 417:
418: assert(psBuf);
419:
420: while (bufLen) {
421: clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
422: bufLen -= clen;
423:
424: do {
425: s1 += (u_int) *psBuf++;
426: s2 += s1;
427: } while (--clen);
428:
429: s1 %= crc_modAdler;
430: s2 %= crc_modAdler;
431: }
432:
433: return (s2 << 16) | s1;
434: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>