--- libelwix/src/crc.c	2013/01/17 10:05:35	1.1
+++ libelwix/src/crc.c	2019/12/30 18:11:16	1.6
@@ -3,7 +3,7 @@
 *  by Michael Pounov <misho@openbsd-bg.org>
 *
 * $Author: misho $
-* $Id: crc.c,v 1.1 2013/01/17 10:05:35 misho Exp $
+* $Id: crc.c,v 1.6 2019/12/30 18:11:16 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 - 2019
 	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;
 
@@ -73,14 +76,14 @@ 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, rev;
+	register u_int i, j = 1, rev = 0;
 
-	for (i = (u_int) 1 << (crcBits - 1), j = 1, rev ^= rev; i; i >>= 1, j <<= 1)
+	for (i = (u_int) 1 << (crcBits - 1); i; i >>= 1, j <<= 1)
 		if (crcNum & i)
 			rev |= j;
 	return rev;
@@ -95,9 +98,9 @@ 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;
@@ -187,13 +190,75 @@ crcCalc(u_char * __restrict psBuf, u_int bufLen, u_cha
 
 
 /*
+ * crc16_ext() - Checksum ver.2 calculation in X/Y modem communication
+ *
+ * @buf = Data for calculation
+ * @bufLen = Length of data
+ * return: Checksum
+ */
+u_short
+crc16_ext(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() - Checksum calculation in X/Y modem communication
+ *
+ * @buf = Data for calculation
+ * @bufLen = Length of data
+ * return: Checksum
+ */
+u_short
+crc16(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 +266,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 +280,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 +377,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,17 +408,15 @@ 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, s2, clen;
+	register u_int s1 = 1, s2 = 0, clen;
 
 	assert(psBuf);
 
-	s1 = 1L;
-	s2 ^= s2;
 	while (bufLen) {
 		clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
 		bufLen -= clen;