#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2004-11-12 13:27 CET by <dl9sau@db0tud.ampr.org>.
# Source directory was `/tmp'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    803 -rw------- kissparms.diff
#  10581 -rw------- mkiss.c.diff
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$2 "$8"'
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh04819; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= kissparms.diff ==============
if test -f 'kissparms.diff' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'kissparms.diff' '(file already exists)'
else
  $echo 'x -' extracting 'kissparms.diff' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'kissparms.diff' &&
40,41c40
< #define USAGE "usage: kissparms -p <port> [-f y|n] [-h hw] [-l txtail] \
< 	[-r pers ] [-s slot] [-t txd] [-e feclevel] [-v] [-x]\n"
---
> #define USAGE "usage: kissparms [-c crc-type] -p <port> [-f y|n] [-h hw] [-l txtail]\n                 [-r pers ] [-s slot] [-t txd] [-e feclevel] [-v] [-x]\n"
55a55
> 	int crcmode = -1;
66c66
< 	while ((s = getopt(argc, argv, "e:f:h:l:p:r:s:t:X:vx")) != -1) {
---
> 	while ((s = getopt(argc, argv, "c:e:f:h:l:p:r:s:t:X:vx")) != -1) {
67a68,70
> 			case 'c':
> 				crcmode  = atoi(optarg);
> 				break;
240a244,253
> 			buflen    = 2;
> 			if (sendto(s, buffer, buflen, 0, &sa, sizeof(struct sockaddr)) == -1) {
> 				perror("kissparms: sendto");
> 				return 1;
> 			}
> 		}
> 
> 		if (crcmode != -1) {
> 			buffer[0] = 0x85;
> 			buffer[1] = crcmode;
SHAR_EOF
  (set 20 04 11 12 13 17 56 'kissparms.diff'; eval "$shar_touch") &&
  chmod 0600 'kissparms.diff' ||
  $echo 'restore of' 'kissparms.diff' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'kissparms.diff:' 'MD5 check failed'
2080b529ecc8762ac51c5264cd6ce916  kissparms.diff
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'kissparms.diff'`"
    test 803 -eq "$shar_count" ||
    $echo 'kissparms.diff:' 'original size' '803,' 'current size' "$shar_count!"
  fi
fi
# ============= mkiss.c.diff ==============
if test -f 'mkiss.c.diff' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'mkiss.c.diff' '(file already exists)'
else
  $echo 'x -' extracting 'mkiss.c.diff' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'mkiss.c.diff' &&
--- mkiss.c.orig	Mon Aug 25 13:44:42 2003
+++ mkiss.c	Mon Oct 25 00:21:08 2004
@@ -74,6 +74,8 @@
X 
X int ax25_maxdev = AX25_MAXDEV;		/* Can be overridden with insmod! */
X 
+int crc_force = 0;		        /* Can be overridden with insmod! */
+
X static struct tty_ldisc	ax_ldisc;
X 
X static int ax25_init(struct net_device *);
@@ -149,6 +151,74 @@
X }
X 
X /*---------------------------------------------------------------------------*/
+/* used by smack */
+
+static const unsigned short Crc_16_table[] = {
+  0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
+  0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
+  0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
+  0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
+  0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
+  0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
+  0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
+  0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
+  0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
+  0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
+  0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
+  0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
+  0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
+  0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
+  0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
+  0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
+  0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
+  0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
+  0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
+  0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
+  0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
+  0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
+  0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
+  0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
+  0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
+  0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
+  0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
+  0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
+  0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
+  0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
+  0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
+  0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
+};
+
+/*---------------------------------------------------------------------------*/
+
+static unsigned short calc_crc_16(unsigned char *cp, int size)
+{
+    unsigned short crc = 0x0000;
+    
+    while (size--)
+    	crc = (crc >> 8) ^ Crc_16_table[(crc ^ *cp++) & 0xff];
+
+    return (((crc >> 8) & 0x00ff) | ((crc << 8) & 0xff00));
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int check_crc_16(unsigned char *cp, int size)
+{
+  unsigned short crc = 0x0000;
+
+  if (size < 3)
+      return -1;
+
+  while (size--)
+      crc = (crc >> 8) ^ Crc_16_table[(crc ^ *cp++) & 0xff];
+
+  if (crc != 0x0000)
+      return -1;
+
+  return 0;
+}
+
+/*---------------------------------------------------------------------------*/
X 
X /* Find a free channel, and link in this `tty' line. */
X static inline struct ax_disp *ax_alloc(void)
@@ -245,7 +315,7 @@
X 
X 	if (xbuff == NULL || rbuff == NULL)  {
X 		printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, MTU change cancelled.\n",
-		       ax->dev->name);
+				ax->dev->name);
X 		dev->mtu = ax->mtu;
X 		if (xbuff != NULL)
X 			kfree(xbuff);
@@ -316,28 +386,47 @@
X 	struct mkiss_channel *mkiss;
X 	int count;
X 
-        tmp_ax = ax;
+	tmp_ax = ax;
X 
X 	if (ax->rbuff[0] > 0x0f) {
X 		if (ax->mkiss != NULL) {
X 			mkiss= ax->mkiss->tty->driver_data;
X 			if (mkiss->magic == MKISS_DRIVER_MAGIC)
X 				tmp_ax = ax->mkiss;
-		} else if (ax->rbuff[0] & 0x20) {
-		        ax->crcmode = CRC_MODE_FLEX;
-			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
-			        ax->rx_errors++;
-				return;
+		} else {
+			if (ax->rbuff[0] & 0x80) {
+				if (check_crc_16(ax->rbuff, ax->rcount) < 0) {
+					ax->rx_errors++;
+					return;
+				}
+				if (ax->crcmode != CRC_MODE_SMACK && ax->crcauto) {
+					printk(KERN_INFO "mkiss: %s: Switchting to crc-smack\n", ax->dev->name);
+					ax->crcmode = CRC_MODE_SMACK;
+				}
+				ax->rcount -= 2;
+				*ax->rbuff &= ~0x80;
+			} else if (ax->rbuff[0] & 0x20)  {
+				if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
+					ax->rx_errors++;
+					return;
+				}
+				if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) {
+					printk(KERN_INFO "mkiss: %s: Switchting to crc-flexnet\n", ax->dev->name);
+					ax->crcmode = CRC_MODE_FLEX;
+				}
+				ax->rcount -= 2;
+
+				/* dl9sau bugfix: the trailling two
+				 * bytes flexnet crc will not be passed
+				 * to the kernel. thus we have to
+				 * correct the kissparm signature,
+				 * because it indicates a crc but
+				 * there's none
+		 		 */
+				*ax->rbuff &= ~0x20;
X 			}
-			ax->rcount -= 2;
-                        /* dl9sau bugfix: the trailling two bytes flexnet crc
-                         * will not be passed to the kernel. thus we have
-                         * to correct the kissparm signature, because it
-                         * indicates a crc but there's none
-			 */
-                        *ax->rbuff &= ~0x20;
X 		}
- 	}
+	}
X 
X 	count = ax->rcount;
X 
@@ -377,18 +466,66 @@
X 	p = icp;
X 
X 	if (mkiss->magic  != MKISS_DRIVER_MAGIC) {
-	        switch (ax->crcmode) {
-		         unsigned short crc;
-
-		case CRC_MODE_FLEX:
-		         *p |= 0x20;
-		         crc = calc_crc_flex(p, len);
-			 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
-			 break;
+		if ((*p & 0x0f) != 0) {
+			/* Configuration Command (kissparms(1).
+			 * Protocol spec says: never append CRC.
+			 * This fixes a very old bug in the linux
+			 * kiss driver. -- dl9sau */
+			switch (*p & 0xff) {
+			case 0x85:
+				/* command from userspace especially for us,
+				 * not for delivery to the tnc */
+				if (len > 1) {
+					int cmd = (p[1] & 0xff);
+					switch(cmd) {
+					case 3:
+					  ax->crcmode = CRC_MODE_SMACK;
+					  break;
+					case 2:
+					  ax->crcmode = CRC_MODE_FLEX;
+					  break;
+					case 1:
+					  ax->crcmode = CRC_MODE_NONE;
+					  break;
+					case 0:
+					default:
+					  ax->crcmode = CRC_MODE_SMACK_TEST;
+					  cmd = 0;
+					}
+					ax->crcauto = (cmd ? 0 : 1);
+					printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd);
+				}
+				ax_unlock(ax);
+				return;
+				break;
+			default:
+				count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+			}
+		} else {
+			unsigned short crc;
+			switch (ax->crcmode) {
+			case CRC_MODE_SMACK_TEST:
+				ax->crcmode  = CRC_MODE_FLEX_TEST;
+				printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name);
+				// fall through
+			case CRC_MODE_SMACK:
+				*p |= 0x80;
+				crc = calc_crc_16(p, len);
+				count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+				break;
+			case CRC_MODE_FLEX_TEST:
+				ax->crcmode = CRC_MODE_NONE;
+				printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name);
+				// fall through
+			case CRC_MODE_FLEX:
+				*p |= 0x20;
+				crc = calc_crc_flex(p, len);
+				count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+				break;
X 
-		default:
-		         count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
-			 break;
+			default:
+				count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+			}
X 		}
X 		ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
X 		actual = ax->tty->driver.write(ax->tty, 0, ax->xbuff, count);
@@ -432,7 +569,7 @@
X 			mkiss= ax->mkiss->tty->driver_data;
X 			if (mkiss->magic  == MKISS_DRIVER_MAGIC)
X 				ax_unlock(ax->mkiss);
-	        }
+		}
X 
X 		netif_wake_queue(ax->dev);
X 		return;
@@ -471,7 +608,7 @@
X 		if (netif_queue_stopped(dev)) {
X 			printk(KERN_ERR "mkiss: dev busy while serial dev is free\n");
X 			ax_unlock(ax);
-	        }
+		}
X 
X 	if (netif_queue_stopped(dev)) {
X 		/*
@@ -484,8 +621,8 @@
X 		}
X 
X 		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
-		       (ax->tty->driver.chars_in_buffer(ax->tty) || ax->xleft) ?
-		       "bad line quality" : "driver error");
+				(ax->tty->driver.chars_in_buffer(ax->tty) || ax->xleft) ?
+				"bad line quality" : "driver error");
X 
X 		ax->xleft = 0;
X 		ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
@@ -508,7 +645,7 @@
X 
X /* Return the frame type ID */
X static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
-	  void *daddr, void *saddr, unsigned len)
+		void *daddr, void *saddr, unsigned len)
X {
X #ifdef CONFIG_INET
X 	if (type != htons(ETH_P_AX25))
@@ -564,6 +701,27 @@
X 	ax->buffsize = len;
X 	ax->rcount   = 0;
X 	ax->xleft    = 0;
+	switch(crc_force) {
+	case 3:
+	  ax->crcmode  = CRC_MODE_SMACK;
+	  printk(KERN_INFO "mkiss: %s: crc mode smack forced.\n", ax->dev->name);
+	  break;
+	case 2:
+	  ax->crcmode  = CRC_MODE_FLEX;
+	  printk(KERN_INFO "mkiss: %s: crc mode flexnet forced.\n", ax->dev->name);
+	  break;
+	case 1:
+	  ax->crcmode  = CRC_MODE_NONE;
+	  printk(KERN_INFO "mkiss: %s: crc mode disabled.\n", ax->dev->name);
+	  break;
+	case 0:
+	  // fall through
+	default:
+	  crc_force = 0; // just 2b sure
+	  printk(KERN_INFO "mkiss: %s: crc mode is auto.\n", ax->dev->name);
+	  ax->crcmode  = CRC_MODE_SMACK_TEST;
+	}
+	ax->crcauto = (crc_force ? 0 : 1);
X 
X 	ax->flags   &= (1 << AXF_INUSE);      /* Clear ESCAPE & ERROR flags */
X 
@@ -1018,7 +1176,9 @@
X MODULE_AUTHOR("Hans Albas PE1AYX <hans@esrac.ele.tue.nl>");
X MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
X MODULE_PARM(ax25_maxdev, "i");
+MODULE_PARM(crc_force, "i");
X MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
+MODULE_PARM_DESC(crc_force, "crc [0 = auto | 1 = none | 2 = flexnet | 3 = smack]");
X MODULE_LICENSE("GPL");
X 
X module_init(mkiss_init_driver);
--- mkiss.h.orig	Sat Aug  3 02:39:44 2002
+++ mkiss.h	Mon Oct 25 00:38:00 2004
@@ -54,9 +54,12 @@
X 
X 	int                 mode;
X         int                 crcmode;    /* MW: for FlexNet, SMACK etc.  */ 
+        int                 crcauto;    /* crc auto mode */ 
X #define CRC_MODE_NONE   0
X #define CRC_MODE_FLEX   1
X #define CRC_MODE_SMACK  2
+#define CRC_MODE_FLEX_TEST   3
+#define CRC_MODE_SMACK_TEST  4
X };
X 
X #define AX25_MAGIC		0x5316
SHAR_EOF
  (set 20 04 11 12 13 18 03 'mkiss.c.diff'; eval "$shar_touch") &&
  chmod 0600 'mkiss.c.diff' ||
  $echo 'restore of' 'mkiss.c.diff' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'mkiss.c.diff:' 'MD5 check failed'
0daa7265f233166d64c4878a3beab469  mkiss.c.diff
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'mkiss.c.diff'`"
    test 10581 -eq "$shar_count" ||
    $echo 'mkiss.c.diff:' 'original size' '10581,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh04819
exit 0
