From @nic.funet.fi:[email protected] Sat Jun 18 00:00:19 1994
Received: from ucsd.edu ([132.239.254.201]) by nic.funet.fi with SMTP id <92228-3>; Sat, 18 Jun 1994 00:00:16 +0300
Received: by ucsd.edu; id NAA20506
       sendmail 8.6.9/UCSD-2.2-sun
       Fri, 17 Jun 1994 13:30:50 -0700 for ham-bsd-list
Received: from nothing.ucsd.edu by ucsd.edu; id NAA20502
       sendmail 8.6.9/UCSD-2.2-sun via ESMTP
       Fri, 17 Jun 1994 13:30:48 -0700 for <[email protected]>
Received: from localhost by nothing.ucsd.edu (8.6.3/UCSDGENERIC.4)
       id NAA06577 to [email protected]; Fri, 17 Jun 1994 13:30:48 -0700
Date:   Fri, 17 Jun 1994 23:30:48 +0300
From:   [email protected] (Brian Kantor)
Message-Id: <[email protected]>
To:     [email protected]
Subject: kissmon.c
Status: RO

/*
* a simple program that expects to find a KISS TNC at 9600 bps serial
* speed on /dev/tty01 (COM2) of your BSDI 1.1 system.  Displays common
* packet formats on the screen.  Does not transmit.
*
* Brian Kantor June 1994
*/
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>

#define DEBUG 1

#define FR_END          0xc0
#define FR_ESC          0xdb
#define T_FR_END        0xdc
#define T_FR_ESC        0xdd

int trace = 0xff;

int tnc;
char tncdev[32];

unsigned char tncbuf[1024];
int plen;
int errcnt;

extern int errno;

main()
       {
       int c;
       int escaped, framed;

       escaped = 0;
       framed = 0;

       plen = 0;

       strcpy(tncdev, "/dev/tty01");

       opendev();

       while ( (c = gettncchar()) != -1 )
               {
               if (c == FR_END)
                       {
                       if ( (trace & 1) && (plen > 0) )
                               {
                               printf("\nKISS len=%d\n", plen);
                               }

                       /* protocol upcall */
                       if (plen > 0 && tncbuf[0] == 0x00)
                               ax25in(tncbuf+1, plen-1);

                       framed = !framed;
                       plen = 0;
                       errcnt = 0;
                       continue;
                       }

               if (!framed)
                       continue;

               if (c == FR_ESC)
                       {
                       escaped = 1;
                       continue;
                       }

               /* escaped chars */
               if (escaped)
                       {
                       escaped = 0;
                       if (c == T_FR_END)
                               {
                               tncbuf[plen++] = FR_END;
                               continue;
                               }
                       if (c == T_FR_ESC)
                               {
                               tncbuf[plen++] = FR_ESC;
                               continue;
                               }

                       /* bad frame, flush it */
                       plen = 0;
                       continue;
                       }
               tncbuf[plen++] = c;
               }
       }

/*
* read a character from the tnc.  If there is an I/O error,
* return -1.  If it times out, return 0.  Else return the char
* timeout is in seconds; 0 = poll
*/
int
gettncchar()
       {
       unsigned char c[2];

       /* so get the char already */
       if (read(tnc, c, 1) != 1)
               {
               perror("tnc read");
               return(-1);
               }

       c[0] &= 0x00FF;         /* trim to 8 bits */

       return((int) c[0]);
       }

/* open the tnc */
int
opendev()
       {
       struct termios  ti;
       int err;

       tnc = open(tncdev, (O_RDWR|O_EXCL), 0);
       if (tnc < 0)
               {
               perror(tncdev);
               return(errno);
               }

       if (DEBUG)
               printf("%s is open on fd %d\n", tncdev, tnc);

       /* get current port settings */
       err = tcgetattr(tnc, &ti);
       if (err < 0)
               {
               perror(tncdev);
               return(errno);
               }
       /*
        * set tty params to 9600 no parity
        * this is for BSDI 1.1  God help you on other systems.
        */
       cfmakeraw(&ti);

       cfsetspeed(&ti, 9600);

       ti.c_iflag |= IGNBRK;   /* ignore breaks */

       ti.c_cflag &= ~CSIZE;   /* 8-bit bytes */
       ti.c_cflag |= CS8;
       ti.c_cflag &= ~CSTOPB;  /* one stop bit */
       ti.c_cflag &= ~PARENB;  /* no parity */

       ti.c_cc[VMIN] = 1;      /* read() can return 1 byte */
       ti.c_cc[VTIME] = 0;     /* no time out */

       errno = 0;
       err = tcsetattr(tnc, TCSANOW, &ti);
       if (err < 0)
               {
               perror(tncdev);
               return(errno);
               }
       return 0;
       }

ax25in(p,l)
unsigned char *p;
int l;
       {
       int i;
       int addrend;
       char v;
       unsigned char op;
       unsigned char pid;
       char ps[16];

       /* long enough to be meaningful? */
       if (l < 15)
               return;

       if (trace & 2)
               {
               v = '1';
               if ( (*(p+6) & 0x80 == 1) && (*(p+12) & 0x80 == 0) )
                       v = 'C';
               if ( (*(p+6) & 0x80 == 0) && (*(p+12) & 0x80 == 1) )
                       v = 'R';
               printf("AX.25 %c len=%d: ", v, l);
               addrend = printaxaddr(p+7, 0);  /* source addr */
               printf("-> ");
               printaxaddr(p, 0);      /* dest addr */

               if (!addrend)
                       printf("via ");

               p += 14;
               l -= 14;

               /* print variable number of digipeater addresses */
               while (!addrend)
                       {
                       addrend = printaxaddr(p, 1);
                       p += 7;
                       l -= 7;
                       }

               op = *p++ & 0x00FF;
               l -= 2;

               switch (pid = *p++ & 0x00FF)
                       {
       default:        sprintf(ps, "%02x", pid); break;
       case 0xCC:      strcpy(ps, "IP"); break;
       case 0xCD:      strcpy(ps, "ARP"); break;
       case 0xCF:      strcpy(ps, "NR"); break;
       case 0xF0:      strcpy(ps, "text"); break;
                       }

               /* interpret the opcode */
               if ((op & 1) == 0)
                       {
                       printf("<I> R=%d S=%d P=%d dlen=%d pid=%s\n",
                               (op & 0xE0) >> 5, (op & 0x0E) >> 1,
                               (op & 0x10) >> 4, l, ps);
                       }
               else if ((op & 0xEF) == 0x03)
                       {
                       printf("<UI> P=%d dlen=%d pid=%s\n",
                               (op & 0x10) >> 4, l, ps);
                       }
               else if ((op & 0xEF) == 0x2F)
                       {
                       printf("<SABM> P=%d\n", (op & 0x10) >> 4);
                       }
               else if ((op & 0xEF) == 0x43)
                       {
                       printf("<DISC> P=%d\n", (op & 0x10) >> 4);
                       }
               else if ((op & 0xEF) == 0x0F)
                       {
                       printf("<DM> P=%d\n", (op & 0x10) >> 4);
                       }
               else if ((op & 0xEF) == 0x63)
                       {
                       printf("<UA> P=%d\n", (op & 0x10) >> 4);
                       }
               else if ((op & 0xEF) == 0x87)
                       {
                       printf("<FRMR> P=%d\n", (op & 0x10) >> 4);
                       hexout(p+2, 3);
                       }
               else if ((op & 0x0F) == 0x01)
                       {
                       printf("<RR> R=%d PF=%d\n",
                               (op & 0xE0) >> 5, (op & 0x10) >> 4);
                       }
               else if ((op & 0x0F) == 0x05)
                       {
                       printf("<RNR> R=%d PF=%d\n",
                               (op & 0xE0) >> 5, (op & 0x10) >> 4);
                       }
               else if ((op & 0x0F) == 0x09)
                       {
                       printf("<REJ> R=%d PF=%d\n",
                               (op & 0xE0) >> 5, (op & 0x10) >> 4);
                       }
               else
                       {
                       printf("unknown %02x\n", *p);
                       }
               fflush(stdout);
               }

       /* I or UI, call the appropriate embedded protocol handler */
       if ((op & 1) == 0 || (op & 0xEF) == 0x03)
               {
               switch(pid)
                       {
       default:        break;

       case 0xCC:      ipin(p, l);
                       break;

       case 0xCD:      arpin(p, l);
                       break;

       case 0xCF:      nrin(p, l);
                       break;

       case 0xF0:      if (trace & 3)
                               hexout(p, l);
                       break;
                       }
               }
       }

/* returns 1 if the address printed was flagged as the last one */
int
printaxaddr(p, digi)
unsigned char *p;
int digi;
       {
       char c;
       c = (*p++) >> 1;  if (c > ' ') putchar(c);
       c = (*p++) >> 1;  if (c > ' ') putchar(c);
       c = (*p++) >> 1;  if (c > ' ') putchar(c);
       c = (*p++) >> 1;  if (c > ' ') putchar(c);
       c = (*p++) >> 1;  if (c > ' ') putchar(c);
       c = (*p++) >> 1;  if (c > ' ') putchar(c);
       printf("-%d%c ", ((*p >> 1) & 0x0f), ((digi && (*p&0x80)>>7)?'*':' '));
       return(*p & 1);
       }

/* pretty-print a string in hex */
hexout(s,l)
unsigned char *s;
int l;
       {
       int i, j;
       char buf[17];

       for (i=0; i < l; i++)
               {
               if ( (i % 16) == 0)
                       {
                       if (i > 0)
                               printf("  %s\n", buf);
                       printf("%04d", i);
                       strcpy(buf, "                ");
                       }

               if ( (i % 8) == 0)
                       printf("- ");

               printf("%02x ", *s);
               buf[i%16] = (isprint(*s) ? *s : '_');
               s++;
               }

       j = (i % 16 == 0) ? 0 : (16 - (i % 16));
       if (j > 7)
               printf("  ");
       while (j--)
               printf("   ");
       printf("  %s\n", buf);
       fflush(stdout);
       }

ipin(p, l)
char *p;
int l;
       {
       printf("IP len=%d\n", l);
       hexout(p, l);
       }

arpin(p, l)
char *p;
int l;
       {
       printf("ARP len=%d\n", l);
       hexout(p, l);
       }

nrin(p, l)
unsigned char *p;
int l;
       {
       int op;

       printf("NETROM len=%d ", l);

       /* network header */
       printaxaddr(p, 0); p += 7;
       printf("-> ");
       printaxaddr(p, 0); p += 7;
       printf("ttl=%x ", *p++);

       /* transport header */
       printf("ckt=%x/%x ", *p++, *p++);
       printf("T=%x R=%x ", *p++, *p++);

       /* flags */
       if ((*p) & 0x80)
               printf("CHOKE ");
       if ((*p) & 0x40)
               printf("NAK ");
       if ((*p) & 0x20)
               printf("MORE ");
       if ((*p) & 0x10)
               printf("rsvd ");

       op = (*p++) & 0x0f;
       switch (op)
               {
case 0x01:      printf("ConReq winreq=%x from ", *p++);
               printaxaddr(p, 0); p += 7;
               printf("@ ");
               printaxaddr(p, 0); p += 7;
               puts("");
               break;
case 0x02:      printf("ConAck winack=%x\n", *p++);
               break;
case 0x03:      printf("DiscReq\n");
               break;
case 0x04:      printf("DiscAck\n");
               break;
case 0x05:      printf("Info\n");
               hexout(p, l);
               break;
case 0x06:      printf("InfoAck\n");
               break;
default:        printf("op=%02x ", op);
               break;
               }
       }