--- libelwix/src/crc.c	2013/08/12 02:10:44	1.2
+++ libelwix/src/crc.c	2024/10/10 23:55:48	1.7
@@ -3,7 +3,7 @@
 *  by Michael Pounov <misho@openbsd-bg.org>
 *
 * $Author: misho $
-* $Id: crc.c,v 1.2 2013/08/12 02:10:44 misho Exp $
+* $Id: crc.c,v 1.7 2024/10/10 23:55:48 misho Exp $
 *
 **************************************************************************
 The ELWIX and AITNET software is distributed under the following
@@ -12,7 +12,7 @@ terms:
 All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
 
-Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
+Copyright 2004 - 2024
 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,9 @@ SUCH DAMAGE.
 #include "global.h"
 
 
+/* CRC16 poly */
+const u_short crc_16poly = 0x1021;
+
 /* Adler module */
 const u_int crc_modAdler = 0xFFF1L;
 
@@ -64,7 +67,9 @@ const crcPoly_t crc_Poly[] = {
 	{ 16, (u_int) 0x8005, "CRC-16-IBM" }, 
 	{ 24, (u_int) 0x864CFB, "CRC-24-Radix64" }, 
 	{ 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" }, 
-	{ 32, (u_int) 0x04C11DB7, "CRC-32-802.3" }
+	{ 32, (u_int) 0x04C11DB7, "CRC-32-802.3" },
+	{ 16, (u_int) 0x1021, "CRC-16-CCITT" },
+	{ 16, (u_int) 0x8408, "CRC-16-XMODEM" }
 };
 
 
@@ -73,9 +78,9 @@ const crcPoly_t crc_Poly[] = {
  *
  * @crcNum = Number for reflection
  * @crcBits = Number width bits 
- * return: -1 error, !=-1 reflecting number
+ * return: reflecting number
  */
-inline u_int
+u_int
 crcReflect(u_int crcNum, u_char crcBits)
 {
 	register u_int i, j = 1, rev = 0;
@@ -95,12 +100,12 @@ crcReflect(u_int crcNum, u_char crcBits)
  * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
  * @initCRC = Initial CRC value
  * @xorCRC = Last xor CRC value
- * return: -1 error, !=-1 CRC checksum
+ * return: CRC checksum
  */
-inline u_int
+u_int
 crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC)
 {
-	const u_int bits = sizeof(int) * 8 - crcBits;
+	u_int bits = sizeof(int) * 8;
 	u_int poly, crchibit, crc;
 	register u_int i, j, b, ch;
 
@@ -109,46 +114,70 @@ crcCalc(u_char * __restrict psBuf, u_int bufLen, u_cha
 	switch (crcBits) {
 		case 1:
 			poly = crc_Poly[0].poly_num;
+			bits -= crc_Poly[0].poly_bits;
 			break;
 		case 4:
 			poly = crc_Poly[1].poly_num;
+			bits -= crc_Poly[1].poly_bits;
 			break;
 		case 5:
 			poly = crc_Poly[2].poly_num;
+			bits -= crc_Poly[2].poly_bits;
 			break;
 		case 6:
 			poly = crc_Poly[3].poly_num;
+			bits -= crc_Poly[3].poly_bits;
 			break;
 		case 7:
 			poly = crc_Poly[4].poly_num;
+			bits -= crc_Poly[4].poly_bits;
 			break;
 		case 8:
 			poly = crc_Poly[5].poly_num;
+			bits -= crc_Poly[5].poly_bits;
 			break;
 		case 10:
 			poly = crc_Poly[6].poly_num;
+			bits -= crc_Poly[6].poly_bits;
 			break;
 		case 11:
 			poly = crc_Poly[7].poly_num;
+			bits -= crc_Poly[7].poly_bits;
 			break;
 		case 12:
 			poly = crc_Poly[8].poly_num;
+			bits -= crc_Poly[8].poly_bits;
 			break;
 		case 15:
 			poly = crc_Poly[9].poly_num;
+			bits -= crc_Poly[9].poly_bits;
 			break;
 		case 16:
 			poly = crc_Poly[10].poly_num;
+			bits -= crc_Poly[10].poly_bits;
 			break;
 		case 24:
 			poly = crc_Poly[11].poly_num;
+			bits -= crc_Poly[11].poly_bits;
 			break;
 		case 30:
 			poly = crc_Poly[12].poly_num;
+			bits -= crc_Poly[12].poly_bits;
 			break;
 		case 32:
 			poly = crc_Poly[13].poly_num;
+			bits -= crc_Poly[13].poly_bits;
 			break;
+		case 161:
+			poly = crc_Poly[14].poly_num;
+			bits -= crc_Poly[14].poly_bits;
+			crcBits = crc_Poly[14].poly_bits;
+			break;
+		case 162:
+			poly = crc_Poly[15].poly_num;
+			bits -= crc_Poly[15].poly_bits;
+			crcBits = crc_Poly[15].poly_bits;
+			break;
 		default:
 			elwix_SetErr(EINVAL, "crcCalc(): Unsupported CRC method!!!");
 			return -1;
@@ -187,13 +216,75 @@ crcCalc(u_char * __restrict psBuf, u_int bufLen, u_cha
 
 
 /*
+ * crc16_xy() - Checksum calculation in X/Y modem communication
+ *
+ * @buf = Data for calculation
+ * @bufLen = Length of data
+ * return: Checksum
+ */
+u_short
+crc16_xy(u_char * __restrict buf, int bufLen)
+{
+	u_short crc, x;
+	register u_short i;
+
+	assert(buf);
+
+	for (crc = 0; bufLen > 0; bufLen--, buf++)
+		for (i = 0x80; i; i >>= 1) {
+			x = crc >> 15;
+			crc <<= 1;
+
+			if (*buf & i)
+				crc++;
+			if (x)
+				crc ^= crc_16poly;
+		}
+
+	for (i = 0; i < 16; i++) {
+		x = crc >> 15;
+		crc <<= 1;
+
+		if (x)
+			crc ^= crc_16poly;
+	}
+
+	return crc;
+}
+
+/*
+ * crc16_ccitt() - Checksum calculation
+ *
+ * @buf = Data for calculation
+ * @bufLen = Length of data
+ * return: Checksum
+ */
+u_short
+crc16_ccitt(u_char * __restrict buf, int bufLen)
+{
+	u_short crc;
+	register u_char i;
+
+	for (crc = 0; bufLen > 0; bufLen--, buf++) {
+		crc ^= (u_short) *buf << 8;
+		for (i = 0x80; i; i >>= 1)
+			if (crc & 0x8000)
+				crc = crc << 1 ^ crc_16poly;
+			else
+				crc <<= 1;
+	}
+
+	return crc;
+}
+
+/*
  * crcIP() - Checksum in IP communication
  *
  * @buf = Data for calculation
  * @bufLen = Length of data
- * return: -1 error, !=-1 Checksum
+ * return: Checksum
  */
-inline u_short
+u_short
 crcIP(u_char * __restrict buf, int bufLen)
 {
 	register u_int sum;
@@ -201,7 +292,7 @@ crcIP(u_char * __restrict buf, int bufLen)
 
 	assert(buf);
 
-	for (sum = 0; bufLen && bufLen > 1; bufLen -= 2)
+	for (sum = 0; bufLen > 1; bufLen -= 2)
 		sum += *nBuf++;
 	if (bufLen == 1) {
 		*(u_char*)(&last) += *(u_char*) nBuf;
@@ -215,13 +306,74 @@ crcIP(u_char * __restrict buf, int bufLen)
 }
 
 /*
+ * crcTCP() - Checksum for TCP v4 communication
+ *
+ * @buf = Data for calculation
+ * @bufLen = Length of data
+ * @th = TCP header
+ * return: Checksum
+ */
+u_short
+crcTCP(struct in_addr src, struct in_addr dst, u_char * __restrict th)
+{
+	struct psd_tcp {
+		struct in_addr src;
+		struct in_addr dst;
+		u_char pad;
+		u_char proto;
+		u_short tcp_len;
+		u_char tcp[20];
+	} buf;
+
+	buf.src = src;
+	buf.dst = dst;
+	buf.pad = 0;
+	buf.proto = IPPROTO_TCP;
+	buf.tcp_len = htons(sizeof buf.tcp);
+	memcpy(&buf.tcp, th, sizeof buf.tcp);
+
+	return crcIP((u_char*) &buf, sizeof buf);
+}
+
+/*
+ * crcUDP() - Checksum for UDP v4 communication
+ *
+ * @buf = Data for calculation
+ * @bufLen = Length of data
+ * @uh = UDP header
+ * return: Checksum
+ */
+u_short
+crcUDP(struct in_addr src, struct in_addr dst, u_char * __restrict uh)
+{
+	struct psd_udp {
+		struct in_addr src;
+		struct in_addr dst;
+		u_char pad;
+		u_char proto;
+		u_short udp_len;
+		u_char udp[8];
+	} buf;
+
+	buf.src = src;
+	buf.dst = dst;
+	buf.pad = 0;
+	buf.proto = IPPROTO_UDP;
+	buf.udp_len = htons(sizeof buf.udp);
+	memcpy(&buf.udp, uh, sizeof buf.udp);
+
+	return crcIP((u_char*) &buf, sizeof buf);
+}
+
+
+/*
  * crcFletcher16() - Fletcher-16 Checksum computing
  *
  * @nBuf = Data for calculation
  * @bufLen = Length of data
- * return: -1 error, !=-1 Checksum
+ * return: Checksum
  */
-inline u_short
+u_short
 crcFletcher16(u_short * __restrict nBuf, int bufLen)
 {
 	register u_short s1, s2;
@@ -251,9 +403,9 @@ crcFletcher16(u_short * __restrict nBuf, int bufLen)
  *
  * @nBuf = Data for calculation
  * @bufLen = Length of data
- * return: -1 error, !=-1 Checksum
+ * return: Checksum
  */
-inline u_int
+u_int
 crcFletcher(u_short * __restrict nBuf, int bufLen)
 {
 	register u_int s1, s2, clen;
@@ -282,9 +434,9 @@ crcFletcher(u_short * __restrict nBuf, int bufLen)
  *
  * @psBuf = Data for calculation
  * @bufLen = Length of data
- * return: -1 error, !=-1 Checksum
+ * return: Checksum
  */
-inline u_int
+u_int
 crcAdler(u_char * __restrict psBuf, int bufLen)
 {
 	register u_int s1 = 1, s2 = 0, clen;