2389 lines
80 KiB
C
Executable file
2389 lines
80 KiB
C
Executable file
/************************************************************************/
|
|
/* */
|
|
/* ***** ***** */
|
|
/* ***** ***** */
|
|
/* ***** ***** */
|
|
/* ***** ***** */
|
|
/* *************** *************** */
|
|
/* ***************** ***************** */
|
|
/* *************** *************** */
|
|
/* ***** ***** TheNetNode */
|
|
/* ***** ***** Portable */
|
|
/* ***** ***** Network */
|
|
/* ***** ***** Software */
|
|
/* */
|
|
/* File os/win32/l1win32.c (maintained by: DF6LN) */
|
|
/* */
|
|
/* This file is part of "TheNetNode" - Software Package */
|
|
/* */
|
|
/* Copyright (C) 1998 - 2008 NORD><LINK e.V. Braunschweig */
|
|
/* */
|
|
/* This program is free software; you can redistribute it and/or modify */
|
|
/* it under the terms of the NORD><LINK ALAS (Allgemeine Lizenz fuer */
|
|
/* Amateurfunk Software) as published by Hans Georg Giese (DF2AU) */
|
|
/* on 13/Oct/1992; either version 1, or (at your option) any later */
|
|
/* version. */
|
|
/* */
|
|
/* This program is distributed WITHOUT ANY WARRANTY only for further */
|
|
/* development and learning purposes. See the ALAS (Allgemeine Lizenz */
|
|
/* fuer Amateurfunk Software). */
|
|
/* */
|
|
/* You should have received a copy of the NORD><LINK ALAS (Allgemeine */
|
|
/* Lizenz fuer Amateurfunk Software) along with this program; if not, */
|
|
/* write to NORD><LINK e.V., Hinter dem Berge 5, D-38108 Braunschweig */
|
|
/* */
|
|
/* Dieses Programm ist PUBLIC DOMAIN, mit den Einschraenkungen durch */
|
|
/* die ALAS (Allgemeine Lizenz fuer Amateurfunk Software), entweder */
|
|
/* Version 1, veroeffentlicht von Hans Georg Giese (DF2AU), */
|
|
/* am 13.Oct.1992, oder (wenn gewuenscht) jede spaetere Version. */
|
|
/* */
|
|
/* Dieses Programm wird unter Haftungsausschluss vertrieben, aus- */
|
|
/* schliesslich fuer Weiterentwicklungs- und Lehrzwecke. Naeheres */
|
|
/* koennen Sie der ALAS (Allgemeine Lizenz fuer Amateurfunk Software) */
|
|
/* entnehmen. */
|
|
/* */
|
|
/* Sollte dieser Software keine ALAS (Allgemeine Lizenz fuer Amateur- */
|
|
/* funk Software) beigelegen haben, wenden Sie sich bitte an */
|
|
/* NORD><LINK e.V., Hinter dem Berge 5, D-38108 Braunschweig */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#include "tnn.h"
|
|
|
|
UWORD wd_timer[L2PNUM]; /* Wenn dieser Timer gegen 0 geht, wird */
|
|
/* der Port zurueckgesetzt. */
|
|
#define WATCHDOG_TIMEOUT 18000 /* Nach 3 Minuten ohne RX Port reset */
|
|
|
|
|
|
static void config_tnc(int);
|
|
static void kissframe_to_tnc(int, BOOLEAN);
|
|
static void append_crc_16(char *, int *);
|
|
static int check_crc_16(char *, int *);
|
|
static void append_crc_rmnc(char *, int *);
|
|
#ifdef LOOPBACK
|
|
static void loopback(void);
|
|
#endif
|
|
|
|
static UWORD tic1m = 0;
|
|
#ifndef ATTACH
|
|
static BOOLEAN tokenflag;
|
|
#endif /* ATTACH */
|
|
static ULONG recovery_count;
|
|
static LONG lost_token = 0;
|
|
static LONG token_pro_sec = 0L; /* Anzahl Token/Sekunde */
|
|
static LONG token_max_sec = 0L; /* Maximale Anzahl */
|
|
static LONG token_min_sec = 0L; /* Minimale Anzahl */
|
|
static LONG token_count = 0L; /* Zaehler fuer Token */
|
|
LONG rounds_pro_sec = 0L; /* Anzahl Rounds/Sekunde */
|
|
LONG rounds_max_sec = 0L; /* Maximale Anzahl */
|
|
LONG rounds_min_sec = 0L; /* Minimale Anzahl */
|
|
LONG rounds_count = 0L; /* Zaehler fuer Rounds */
|
|
|
|
int tkcom = -1;
|
|
UWORD tkbaud = 0;
|
|
|
|
static ULONG cd_timer[L2PNUM]; /* 0 = Frame wurde gesendet.. */
|
|
/* != 0 Frame an TNC uebergeben, wird */
|
|
/* bearbeitet bzw. Sendung laeuft. */
|
|
#define CD_TIMEOUT 3000 /* 30 s Timeout, falls Bestaetigung */
|
|
/* verloren gegangen ist (Tokenring?) */
|
|
static const int Crc_16_table[256];
|
|
static const int Crc_rmnc_table[256];
|
|
static int check_crc_rmnc(char *, int *);
|
|
#ifndef ATTACH
|
|
static void tf_set_kiss(DEVICE *);
|
|
#endif /* ATTACH */
|
|
|
|
ULONG tnn_buffers;
|
|
char tnn_initfile[MAXPATH];
|
|
char tnn_dir[MAXPATH];
|
|
char tnn_errfile[MAXPATH];
|
|
BOOLEAN kiss_active;
|
|
DEVICE l1port[L1PNUM];
|
|
WORD max_device;
|
|
WORD used_l1ports;
|
|
WORD l1ptab[L2PNUM];
|
|
WORD l2ptab[L1PNUM];
|
|
|
|
#ifdef VANESSA
|
|
extern BOOLEAN van_test(int);
|
|
WORD found_vanessa;
|
|
static BOOLEAN check_van = FALSE;
|
|
#endif
|
|
|
|
#ifdef KERNELIF
|
|
extern void ifip_clearstat(void);
|
|
#endif
|
|
|
|
static ULONG token_sent = 0L;
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Initialisierung der Variablen */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void
|
|
l1init(void)
|
|
{
|
|
register WORD i;
|
|
|
|
/* alle Ports initialisieren */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
portpar[i].speed = 12;
|
|
portpar[i].major = NO_MAJOR;
|
|
portstat[i].reset_count = 0L;
|
|
portpar[i].reset_port = FALSE;
|
|
cd_timer[i] = 0;
|
|
kick[i] = FALSE; /* kein TNC sendet */
|
|
testflag[i] = FALSE;
|
|
commandflag[i] = TRUE;
|
|
wd_timer[i] = WATCHDOG_TIMEOUT;
|
|
}
|
|
|
|
/* Zaehler ruecksetzen */
|
|
for (i = 0; i < L1PNUM; ++i)
|
|
l1port[i].bad_frames = 0L;
|
|
|
|
show_recovery = TRUE;
|
|
recovery_count = 0L;
|
|
tic1m = 0;
|
|
|
|
#ifdef VANESSA
|
|
/* Vanessen suchen und einrichten */
|
|
if (check_van)
|
|
{
|
|
found_vanessa = 0;
|
|
vanessa_l1init();
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (kissmode(i) == KISS_VAN)
|
|
{
|
|
if (!van_test(i))
|
|
l1port[l1ptab[i]].kisstype = KISS_NIX;
|
|
else
|
|
{
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
++found_vanessa;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef AX_IPX
|
|
/* IPX-Port einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (kissmode(i) == KISS_IPX)
|
|
{
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
break; /* nur 1 IPX-Port */
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef AX25IP
|
|
/* AXIP23-Port einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (kissmode(i) == KISS_AXIP)
|
|
{
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
break; /* nur 1 AX25IP-Port */
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef KERNELIF
|
|
/* Kernel-AX.25-Ports einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
if ( (kissmode(i) == KISS_KAX25)
|
|
|| (kissmode(i) == KISS_KAX25KJD))
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
#endif
|
|
#ifdef SIXPACK
|
|
/* 6PACK-Ring einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
if (kissmode(i) == KISS_6PACK)
|
|
{
|
|
Sixpack_l1init();
|
|
break;
|
|
}
|
|
#endif
|
|
#ifdef L1TELNET
|
|
/* TELNET-Port einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (kissmode(i) == KISS_TELNET)
|
|
{
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
break; /* nur 1 TELNET-Port */
|
|
}
|
|
}
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
/* TELNET-Port einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (kissmode(i) == KISS_HTTPD)
|
|
{
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
break; /* nur 1 HTTPD-Port */
|
|
}
|
|
}
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
/* IPCONV-Port einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (kissmode(i) == KISS_IPCONV)
|
|
{
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
break; /* nur 1 IPCONV-Port */
|
|
}
|
|
}
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
/* IRC-Port einrichten */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (kissmode(i) == KISS_IRC)
|
|
{
|
|
l1port[l1ptab[i]].port_active = TRUE;
|
|
break; /* nur 1 IPCONV-Port */
|
|
}
|
|
}
|
|
#endif /* L1IRC */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Serielle Schnittstellen initialisieren */
|
|
/* ( KISS, SMACK, Tokenring, teilweise 6PACK ) */
|
|
/************************************************************************/
|
|
|
|
BOOLEAN
|
|
init_kisslink(void)
|
|
{
|
|
WORD i;
|
|
UWORD fehler;
|
|
DEVICE *l1pp;
|
|
|
|
fehler = 0; /* Merker fuer Fortschritt der Initialisierung */
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Lockfiles schreiben und Kiss-Ports initialisieren. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
/* alle L1-ports durch gehen */
|
|
for (i = 0; i < L1PNUM; ++i)
|
|
{
|
|
l1pp = &l1port[i];
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn Vanessa, naechsten Port. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#ifdef VANESSA
|
|
if (stricmp("VANESSA", l1pp->device) == 0)
|
|
{
|
|
check_van = TRUE;
|
|
l1pp->kisstype = KISS_VAN; /* falls Kisstype nicht angegeben */
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn IPX, auch naechsten Port. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#ifdef AX_IPX
|
|
if (stricmp("IPX", l1pp->device) == 0)
|
|
{
|
|
l1pp->kisstype = KISS_IPX; /* falls Kisstype nicht angegeben */
|
|
l1pp->port_active = TRUE;
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn AX25IP, auch naechsten Port. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#ifdef AX25IP
|
|
if (stricmp("AX25IP", l1pp->device) == 0)
|
|
{
|
|
l1pp->kisstype = KISS_AXIP; /* falls Kisstype nicht angegeben */
|
|
l1pp->port_active = TRUE;
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Kernel-AX25 hat hier auch nix zu suchen */
|
|
/* */
|
|
/************************************************************************/
|
|
#ifdef KERNELIF
|
|
if ( (l1pp->kisstype == KISS_KAX25)
|
|
|| (l1pp->kisstype == KISS_KAX25KJD))
|
|
{
|
|
l1pp->port_active = TRUE;
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* 6PACK hat hier auch nix zu suchen */
|
|
/* */
|
|
/************************************************************************/
|
|
#ifdef SIXPACK
|
|
if (l1pp->kisstype == KISS_6PACK)
|
|
{
|
|
l1pp->port_active = TRUE;
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
#ifdef L1TELNET
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn TELNET, auch naechsten Port. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (l1pp->kisstype == KISS_TELNET)
|
|
{
|
|
int TCPPort = atoi(l1pp->device);
|
|
|
|
if ( (TCPPort < 1)
|
|
||(TCPPort > 65536))
|
|
{
|
|
printf("Warnung: Alte Syntax device %s ungueltig!!!\n"
|
|
" Neue Syntax device 1..65535.\n"
|
|
"TCP-Port wird auf default 10023 gesetzt.\n"
|
|
"Aenderung in der TNN.INI vornehmen!\n", l1pp->device);
|
|
strncpy(l1pp->device, "10023", MAXPATH);
|
|
Break();
|
|
}
|
|
else
|
|
{
|
|
l1pp->port_active = TRUE;
|
|
}
|
|
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif /* L1TELNET */
|
|
|
|
#ifdef L1HTTPD
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn HTTPD, auch naechsten Port. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (l1pp->kisstype == KISS_HTTPD)
|
|
{
|
|
int TCPPort = atoi(l1pp->device);
|
|
|
|
if ( (TCPPort < 1)
|
|
||(TCPPort > 65536))
|
|
{
|
|
printf("Warnung: Alte Syntax device %s ungueltig!!!\n"
|
|
" Neue Syntax device 1..65535.\n"
|
|
"TCP-Port wird auf default 18080 gesetzt.\n"
|
|
"Aenderung in der TNN.INI vornehmen!\n", l1pp->device);
|
|
strncpy(l1pp->device, "18080", MAXPATH);
|
|
Break();
|
|
}
|
|
else
|
|
l1pp->port_active = TRUE;
|
|
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif /* L1HTTPD */
|
|
|
|
#ifdef L1IPCONV
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn IPCONV, auch naechsten Port. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (l1pp->kisstype == KISS_IPCONV)
|
|
{
|
|
int TCPPort = atoi(l1pp->device);
|
|
|
|
if ( (TCPPort < 1)
|
|
||(TCPPort > 65536))
|
|
{
|
|
printf("Warnung: Alte Syntax device %s ungueltig!!!\n"
|
|
" Neue Syntax device 1..65535.\n"
|
|
"TCP-Port wird auf default 13600 gesetzt.\n"
|
|
"Aenderung in der TNN.INI vornehmen!\n", l1pp->device);
|
|
strncpy(l1pp->device, "13600", MAXPATH);
|
|
Break();
|
|
}
|
|
else
|
|
l1pp->port_active = TRUE;
|
|
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif /* L1IPCONV */
|
|
|
|
#ifdef L1IRC
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn IRC, auch naechsten Port. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (l1pp->kisstype == KISS_IRC)
|
|
{
|
|
int TCPPort = atoi(l1pp->device);
|
|
|
|
if ( (TCPPort < 1)
|
|
||(TCPPort > 65536))
|
|
{
|
|
printf("Warnung: Alte Syntax device %s ungueltig!!!\n"
|
|
" Neue Syntax device 1..65535.\n"
|
|
"TCP-Port wird auf default 13601 gesetzt.\n"
|
|
"Aenderung in der TNN.INI vornehmen!\n", l1pp->device);
|
|
strncpy(l1pp->device, "13601", MAXPATH);
|
|
Break();
|
|
}
|
|
else
|
|
l1pp->port_active = TRUE;
|
|
|
|
if (i == max_device)
|
|
break;
|
|
else
|
|
continue;
|
|
}
|
|
#endif /* L1IRC */
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Port oeffnen. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (fehler == 0) /* nur wenn Lock-File geschrieben */
|
|
{ /* wurde oder nicht gefordert war */
|
|
l1pp->kisslink = open_win(l1pp->device, l1pp->speed);
|
|
|
|
if (l1pp->kisslink == -1)
|
|
{
|
|
fehler = 2;
|
|
printf("Error: can't open device %s\n", l1pp->device);
|
|
printf(" (%s)\n", strerror(errno));
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Serielle Schnittstelle auf neue Parameter einstellen, KISS-Empfang */
|
|
/* initialisieren */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (fehler == 0)
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->rx_port = 0;
|
|
l1pp->tx_port = 0;
|
|
l1pp->port_active = TRUE;
|
|
|
|
if (l1pp->kisstype == KISS_TF)
|
|
tf_set_kiss(l1pp);
|
|
}
|
|
else
|
|
break;
|
|
if (i == max_device)
|
|
break;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn kein Fehler aufgetreten ist, dann fuer gewisse Interfaces die */
|
|
/* ersten Aktionen ausfuehren. */
|
|
/* */
|
|
/* Tokenring : Token senden */
|
|
/* 6PACK : TNC-Zaehlung anstossen */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (fehler == 0)
|
|
{
|
|
/* Tokenring */
|
|
if (l1port[0].kisstype == KISS_TOK)
|
|
{
|
|
send_kisscmd(0xff, CMD_TOKEN, 0); /* Token senden */
|
|
token_sent = tic10; /* Zeitpunkt der Sendung */
|
|
tokenflag = FALSE; /* Token unterwegs */
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Wenn bei einem Teil der Initialisierung ein Fehler aufgetreten ist, */
|
|
/* muessen alle bisher vorgenommenen Parameteraenderungen der seriellen */
|
|
/* Schnittstellen rueckgaengig gemacht werden. Ausserdem muessen alle */
|
|
/* geoeffneten Files wieder geschlossen werden. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
do
|
|
{
|
|
/* Port war schon offen, aber noch nicht veraendert, nur schliessen */
|
|
if ((fehler > 2) && (l1port[i].kisslink != -1))
|
|
{
|
|
CloseHandle((void *)l1port[i].kisslink);
|
|
l1port[i].kisslink = -1;
|
|
}
|
|
|
|
fehler = 4; /* beim naechsten Durchgang alles restaurieren */
|
|
} while (--i >= 0);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Serielle Schnittstellen wieder freigeben (fuer Programmende) */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void exit_kisslink(void)
|
|
{
|
|
register WORD i;
|
|
char buffer[] = { (char)FEND, (char)0xFF };
|
|
|
|
for (i = 0; i < L1PNUM; ++i)
|
|
{
|
|
/* abgeschaltete Ports */
|
|
if (!l1port[i].port_active)
|
|
continue;
|
|
#ifdef AX_IPX
|
|
/* AX_IPX */
|
|
if (l1port[i].kisstype > KISS_IPX)
|
|
continue;
|
|
#endif
|
|
#ifdef KERNELIF
|
|
/* Kernel-AX.25 */
|
|
if ( (l1port[i].kisstype == KISS_KAX25)
|
|
|| (l1port[i].kisstype == KISS_KAX25KJD))
|
|
continue;
|
|
#endif
|
|
#ifdef AX25IP
|
|
/* AX25IP */
|
|
if (l1port[i].kisstype == KISS_AXIP)
|
|
continue;
|
|
#endif
|
|
#ifdef VANESSA
|
|
if (l1port[i].kisstype == KISS_VAN)
|
|
continue;
|
|
#endif
|
|
#ifdef SIXPACK
|
|
/* 6PACK */
|
|
if (l1port[i].kisstype == KISS_6PACK)
|
|
continue;
|
|
#endif
|
|
#ifdef L1TELNET
|
|
/* TELNET-Server */
|
|
if (l1port[i].kisstype == KISS_TELNET)
|
|
continue;
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
/* HTTPD-Server */
|
|
if (l1port[i].kisstype == KISS_HTTPD)
|
|
continue;
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
/* IPCONV-Server */
|
|
if (l1port[i].kisstype == KISS_IPCONV)
|
|
continue;
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
/* IRC-Server */
|
|
if (l1port[i].kisstype == KISS_IRC)
|
|
continue;
|
|
#endif /* L1IRC */
|
|
|
|
/* TNC mit TheFirmware */
|
|
if (l1port[i].kisstype == KISS_TF)
|
|
{
|
|
/* KISS-Kommando senden (TNC-Reset) */
|
|
write(l1port[i].kisslink, buffer, 2);
|
|
sleep(1);
|
|
}
|
|
|
|
CloseHandle((void *)l1port[i].kisslink);
|
|
/* Lockfile loeschen */
|
|
if (*(l1port[i].tnn_lockfile) != '\0')
|
|
unlink(l1port[i].tnn_lockfile);
|
|
/* alle Devices bearbeitet ? */
|
|
if (i == max_device)
|
|
break;
|
|
}
|
|
kiss_active = FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Level1 Ende, Ports schliessen und aufraeumen */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1exit(void)
|
|
{
|
|
#ifdef KERNELIF
|
|
/* Kernel-AX.25 */
|
|
register unsigned int i;
|
|
|
|
for (i = 0;i < L1PNUM; ++i)
|
|
if ( (l1port[i].kisstype == KISS_KAX25)
|
|
|| (l1port[i].kisstype == KISS_KAX25KJD))
|
|
ifax_close(&(l1port[i]));
|
|
#endif
|
|
/* KISS-Schnittstellen */
|
|
if (kiss_active)
|
|
exit_kisslink();
|
|
#ifdef VANESSA
|
|
/* Vanessa */
|
|
vanessa_l1exit();
|
|
#endif
|
|
#ifdef AX_IPX
|
|
/* AX25IPX */
|
|
axipx_l1exit();
|
|
#endif
|
|
#ifdef AX25IP
|
|
/* AX25IP */
|
|
ax25ip_l1exit();
|
|
#endif
|
|
#ifdef SIXPACK
|
|
/* 6PACK */
|
|
Sixpack_l1exit();
|
|
#endif
|
|
#ifdef L1TELNET
|
|
/* TCPIP-Interface schliessen. */
|
|
L1ExitTCP(KISS_TELNET);
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
/* TCPIP-Interface schliessen. */
|
|
L1ExitTCP(KISS_HTTPD);
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
/* TCPIP-Interface schliessen. */
|
|
L1ExitTCP(KISS_IPCONV);
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
/* TCPIP-Interface schliessen. */
|
|
L1ExitTCP(KISS_IRC);
|
|
#endif /* L1IRC */
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Level1 Timer */
|
|
/* Watchdog-Timer fuer die einzelnen L2-Ports */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1timr(UWORD ticks)
|
|
{
|
|
register unsigned int i;
|
|
|
|
if ((tic1m += ticks) > 6000) /* alle Minute */
|
|
{
|
|
tic1m -= 6000;
|
|
/* Statistik fuer den Tokenring */
|
|
token_pro_sec = (token_count / 60L);
|
|
|
|
if ( (token_max_sec != 0)
|
|
&& (token_min_sec != 0))
|
|
{
|
|
token_max_sec = max(token_pro_sec, token_max_sec);
|
|
token_min_sec = min(token_pro_sec, token_min_sec);
|
|
}
|
|
else
|
|
token_min_sec = token_max_sec = token_pro_sec;
|
|
|
|
token_count = 0L;
|
|
}
|
|
|
|
/* DCD (TX) fuer die Tokenring-Ports checken */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
if (wd_timer[i] < ticks)
|
|
{
|
|
wd_timer[i] = WATCHDOG_TIMEOUT;
|
|
portpar[i].reset_port = TRUE;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Level1 RX/TX */
|
|
/* wird staendig in der main() Hauptschleife aufgerufen. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1rxtx(void)
|
|
{
|
|
register UBYTE i;
|
|
DEVICE *l1pp;
|
|
|
|
#ifdef VANESSA
|
|
if (found_vanessa != 0)
|
|
vanessa();
|
|
#endif
|
|
#ifdef AX_IPX
|
|
axipx();
|
|
#endif
|
|
#ifdef AX25IP
|
|
ax25ip();
|
|
#endif
|
|
#ifdef KERNELIF
|
|
ifax_housekeeping();
|
|
#endif
|
|
#ifdef SIXPACK
|
|
Sixpack_Housekeeping();
|
|
#endif
|
|
|
|
++rounds_count; /* Anzahl der Hauptschleifendurchlaeufe */
|
|
#ifdef LOOPBACK
|
|
/* Loopback-Funktionalitaet */
|
|
loopback();
|
|
#endif
|
|
|
|
/* alle Ports durchgehen */
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
/* uninitialisierter Port */
|
|
if (l1ptab[i] == -1)
|
|
continue;
|
|
/* deaktivierter Port */
|
|
if (!portenabled(i))
|
|
continue;
|
|
l1pp = &l1port[l1ptab[i]];
|
|
/* Tokenring darf nur senden, wenn wir das Token haben */
|
|
if ( (l1pp->kisstype == KISS_TOK) /* Wenn Token noch unterwegs, */
|
|
&& (tokenflag == FALSE)) /* nicht senden! */
|
|
continue;
|
|
|
|
#ifdef AX_IPX
|
|
if (l1pp->kisstype == KISS_IPX)
|
|
continue;
|
|
#endif
|
|
#ifdef AX25IP
|
|
if (l1pp->kisstype == KISS_AXIP)
|
|
continue;
|
|
#endif
|
|
#ifdef VANESSA
|
|
if (l1pp->kisstype == KISS_VAN)
|
|
continue;
|
|
#endif
|
|
#ifdef KERNELIF
|
|
if ( (l1pp->kisstype == KISS_KAX25)
|
|
|| (l1pp->kisstype == KISS_KAX25KJD))
|
|
continue;
|
|
#endif
|
|
#ifdef SIXPACK
|
|
if (l1pp->kisstype == KISS_6PACK)
|
|
continue;
|
|
#endif
|
|
#ifdef L1TELNET
|
|
if (l1pp->kisstype == KISS_TELNET)
|
|
continue;
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
if (l1pp->kisstype == KISS_HTTPD)
|
|
continue;
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
if (l1pp->kisstype == KISS_IPCONV)
|
|
continue;
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
if (l1pp->kisstype == KISS_IRC)
|
|
continue;
|
|
#endif /* L1IRC */
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Nicht-Tokenring-TNCs konfigurieren, falls notwendig */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (commandflag[i]) /* TNC konfigurieren */
|
|
config_tnc(i);
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Tokenring ist frei - oder SMACK-/KISS-Link */
|
|
/* */
|
|
/************************************************************************/
|
|
if (kick[i]) /* Es soll auf diesem Port gesendet werden */
|
|
{
|
|
kissframe_to_tnc(i, FALSE); /* Alles fuer diesen Port senden */
|
|
cd_timer[i] = tic10; /* Wir senden, Belegt-Timer starten */
|
|
}
|
|
}
|
|
if (l1port[0].kisstype != KISS_TOK) /* kein Tokenring da? */
|
|
return;
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Tokenring ueberwachen - wenn Token empfangen, ggf. neue Daten senden */
|
|
/* oder TNC(s) resetten bzw. konfigurieren. Wenn zu lange kein Token */
|
|
/* angekommen, Verlust des Token annehmen und neues Token generieren. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (tokenflag == FALSE) /* nichts gekommen? */
|
|
{
|
|
if (tic10 > (token_sent + TOKENTIMEOUT)) /* noch einmal warten.. */
|
|
{
|
|
if (++lost_token >= 150) /* zu viele Token-Recoveries */
|
|
HALT("Tokenring");
|
|
|
|
l1port[0].rx_state = ST_BEGIN; /* auf FEND warten */
|
|
send_kisscmd(0xff, CMD_TOKEN, 0); /* Token senden */
|
|
token_sent = tic10; /* nix gekommen... */
|
|
++recovery_count; /* fuer die Statistik */
|
|
|
|
for (i = 0; i < L2PNUM; ++i) /* ggf neue Parameter an TNC */
|
|
{
|
|
if ( portenabled(i)
|
|
&& (kissmode(i) == KISS_TOK))
|
|
{
|
|
commandflag[i] = TRUE; /* Portparameter neu einstellen */
|
|
kissframe_to_tnc(i, TRUE); /* zur Sicherheit bei Recovery */
|
|
} /* Restframes loeschen */
|
|
}
|
|
|
|
if (show_recovery == TRUE)
|
|
{
|
|
notify(1, "*** Token-Recovery (%lu)", lost_token);
|
|
if (!blicnt)
|
|
xprintf("*** Token-Recovery (%lu)\n", lost_token);
|
|
}
|
|
}
|
|
}
|
|
else /* Token ist angekommen */
|
|
{
|
|
for (i = 0; i < L2PNUM; ++i)
|
|
{
|
|
if (l1ptab[i] == -1) /* Port uninitialisiert */
|
|
continue;
|
|
if (!portenabled(i)) /* Port ist aus */
|
|
continue;
|
|
l1pp = &l1port[l1ptab[i]];
|
|
if (l1pp->kisstype != KISS_TOK) /* nicht Tokenring */
|
|
continue;
|
|
if (portpar[i].reset_port == TRUE) /* diesen Port resetten?*/
|
|
{
|
|
send_kisscmd(i, CMD_TNCRES, 0);
|
|
portpar[i].reset_port = FALSE;
|
|
commandflag[i] = TRUE; /* nach Reset TNC konfigurieren */
|
|
break; /* nur 1 RESET/Token, mehr */
|
|
} /* kommt evtl. nicht durch, da */
|
|
} /* TNC taub ist nach RESET */
|
|
|
|
send_kisscmd(0xff, CMD_TOKEN, 0); /* Token senden */
|
|
token_sent = tic10;
|
|
tokenflag = FALSE;
|
|
lost_token = 0;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Loopback-Ports bearbeiten */
|
|
/* */
|
|
/************************************************************************/
|
|
#ifdef LOOPBACK
|
|
static void loopback(void)
|
|
{
|
|
LHEAD *l2flp;
|
|
MBHEAD *txfhd;
|
|
MBHEAD *rxfhd;
|
|
register int port;
|
|
int rxport;
|
|
|
|
l2flp = txl2fl;
|
|
|
|
for (port = 0; port < L2PNUM; l2flp++, port++)/* jeden Port durchlaufen */
|
|
{
|
|
if (kissmode(port) == KISS_LOOP)
|
|
{
|
|
/* wenn zwei L2-Ports mit aufeinanderfolgender Nummer (um genau zu sein */
|
|
/* ein Port mit gerader Nummer und der mit der naechsthoeheren Nummer) */
|
|
/* auf LOOP gesetzt sind, auf den Nachbarport senden; andernfalls auf */
|
|
/* Sendeport */
|
|
rxport = port ^ 1;
|
|
if ( !portenabled(rxport)
|
|
|| (kissmode(rxport) != KISS_LOOP))
|
|
rxport = port;
|
|
|
|
while (kick[port]) /* was zum senden... */
|
|
{
|
|
ulink((LEHEAD *)(txfhd = (MBHEAD *) l2flp->head));
|
|
rxfhd = (MBHEAD *) allocb(ALLOC_MBHEAD);
|
|
|
|
rxfhd->l2port = rxport;
|
|
while (txfhd->mbpc > txfhd->mbgc)
|
|
putchr(getchr(txfhd), rxfhd);
|
|
relink((LEHEAD *)rxfhd, (LEHEAD *)rxfl.tail); /* in Rx-Liste */
|
|
relink((LEHEAD *)txfhd, (LEHEAD *)stfl.tail); /* Frame gesendet */
|
|
kick[port] = ((LHEAD *)l2flp->head != l2flp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* TNC gemaess Port-Parametern konfigurieren */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
static void config_tnc(int l2port)
|
|
{
|
|
PORTINFO *ppp;
|
|
DEVICE *l1pp;
|
|
|
|
l1pp = &l1port[l1ptab[l2port]];
|
|
ppp = &portpar[l2port];
|
|
|
|
if ( (l1pp->kisstype != KISS_TOK) /* DAMA geht nur mit Tokenring */
|
|
&& (l1pp->kisstype != KISS_VAN)) /* oder Vanessa */
|
|
ppp->l2mode &= ~MODE_a;
|
|
|
|
if ( (l1pp->kisstype == KISS_TOK) /* Tokenring aber Token noch */
|
|
&& (tokenflag == FALSE)) /* unterwegs? -> beim naechsten */
|
|
return; /* Durchgang nochmal probieren */
|
|
|
|
send_kisscmd(l2port, CMD_TXDELAY, ppp->txdelay);
|
|
|
|
/* Persistance je nach DAMA einstellen */
|
|
if (dama(l2port))
|
|
send_kisscmd(l2port, CMD_PERSIST, 255);
|
|
else
|
|
send_kisscmd(l2port, CMD_PERSIST, ppp->persistance);
|
|
|
|
send_kisscmd(l2port, CMD_SLOTTIME, ppp->slottime);
|
|
send_kisscmd(l2port, CMD_TXTAIL, TAILTIME);
|
|
send_kisscmd(l2port, CMD_FULLDUP, fullduplex(l2port) ? 1 : 0);
|
|
send_kisscmd(l2port, CMD_DAMA, (dama(l2port)) ? 1 : 0);
|
|
commandflag[l2port] = FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Level1 Control */
|
|
/* eine Aktion fuer einen Hardware-Port anfordern */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1ctl(int req, int port)
|
|
{
|
|
/* je nach Request die notwendigen Aktionen bestimmen */
|
|
switch (req)
|
|
{
|
|
/* Port resetten */
|
|
case L1CRES: portpar[port].reset_port = TRUE;
|
|
break;
|
|
/* Parameter zum Port bringen */
|
|
case L1CCMD: commandflag[port] = TRUE;
|
|
break;
|
|
/* Testsignal senden */
|
|
case L1CTST: testflag[port] = TRUE;
|
|
kick[port] = TRUE;
|
|
break;
|
|
/* sonstiges */
|
|
default: break;
|
|
}
|
|
#ifdef VANESSA
|
|
if (found_vanessa != 0)
|
|
vanessa_l1ctl(req);
|
|
#endif
|
|
#ifdef AX_IPX
|
|
axipx_l1ctl(req, port);
|
|
#endif
|
|
#ifdef AX25IP
|
|
ax25ip_l1ctl(req, port);
|
|
#endif
|
|
#ifdef KERNELIF
|
|
ifax_l1ctl(req);
|
|
#endif
|
|
#ifdef SIXPACK
|
|
Sixpack_l1ctl(req, (UWORD)port);
|
|
#endif
|
|
#ifdef L1TCPIP
|
|
L1ctlTCP(req, port);
|
|
#endif /* L1TCPIP */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Kommando fuer TNC-Parameter an KISS-Link senden */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void send_kisscmd(int l2prt, int cmd, int value)
|
|
{
|
|
UBYTE tx_buffer[10]; /* Buffer fuer KISS-Frame - 10 Zeichen reicht! */
|
|
UBYTE *tx_bufptr;
|
|
unsigned len;
|
|
UBYTE val2;
|
|
DEVICE *l1pp;
|
|
|
|
/* ohne KISS geht es hier nicht weiter */
|
|
if (!kiss_active)
|
|
return;
|
|
|
|
if (l2prt != 0xff) /* wenn nicht Token */
|
|
l1pp = &l1port[l1ptab[l2prt]];
|
|
else
|
|
l1pp = l1port; /* Token = Tokenring = 1. Device */
|
|
|
|
switch (l1pp->kisstype) /* pruefen, ob Kommando zum */
|
|
{ /* Kiss-Modus passt */
|
|
case KISS_RMNC:
|
|
case KISS_SCC:
|
|
return;
|
|
break;
|
|
case KISS_TOK:
|
|
if (cmd < CMD_TXDELAY) return;
|
|
if ((cmd > CMD_TOKEN) && (cmd != CMD_TNCRES)) return;
|
|
break;
|
|
default:
|
|
if ((cmd < CMD_TXDELAY) || (cmd > CMD_FULLDUP)) return;
|
|
break;
|
|
}
|
|
|
|
tx_bufptr = tx_buffer; /* KISS-Frame in Puffer schreiben */
|
|
*tx_bufptr++ = (char)FEND;
|
|
len = 1;
|
|
|
|
if (l1pp->kisstype == KISS_TOK) /* Port-Nummer nur bei Token- */
|
|
{ /* ring */
|
|
*tx_bufptr++ = l2prt;
|
|
len++;
|
|
}
|
|
|
|
*tx_bufptr++ = (char)cmd;
|
|
++len;
|
|
|
|
if ((l2prt != 0xff) && (cmd != CMD_TNCRES)) /* Parameter folgt */
|
|
{
|
|
val2 = (char)(value & 0xFF); /* Parameter nur 0 - 255 */
|
|
switch (val2) /* ggf. Sonderbehandlung */
|
|
{
|
|
case FEND: /* FEND -> FESC - TFEND */
|
|
*tx_bufptr++ = (char)FESC;
|
|
*tx_bufptr++ = (char)TFEND;
|
|
len += 2;
|
|
break;
|
|
case FESC: /* FESC -> FESC - TFESC */
|
|
*tx_bufptr++ = (char)FESC;
|
|
*tx_bufptr++ = (char)TFESC;
|
|
len += 2;
|
|
break;
|
|
default: /* keine Sonderbehandlung */
|
|
*tx_bufptr++ = val2;
|
|
len++;
|
|
break;
|
|
}
|
|
}
|
|
*tx_bufptr++ = (char)FEND; /* Ende Kommando-Frame */
|
|
++len;
|
|
|
|
write(l1pp->kisslink, tx_buffer, len);/* Kommando-Frame absenden */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* send all frames in txbuffer over kisslink */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
static void kissframe_to_tnc(int l2prt, BOOLEAN recovery)
|
|
{
|
|
UBYTE tx_buffer[2*MAXKISSLEN];
|
|
UBYTE *tx_bufptr;
|
|
unsigned len;
|
|
unsigned short ch1;
|
|
int i;
|
|
UBYTE tmp_buffer[MAXKISSLEN];
|
|
UBYTE *tmp_bufptr;
|
|
int tmp_buflen;
|
|
DEVICE *l1pp;
|
|
MBHEAD *txfhdl;
|
|
LHEAD *l2flp;
|
|
ULONG count = 0L;
|
|
|
|
/* Testsignal senden ? */
|
|
if (testflag[l2prt] == TRUE)
|
|
{
|
|
count = (portpar[l2prt].speed * 1000) / 8; /* 10 sec lang */
|
|
if (count < 1024) /* min. 1kB */
|
|
count = 1024;
|
|
}
|
|
|
|
l1pp = &l1port[l1ptab[l2prt]];
|
|
kick[l2prt] = FALSE; /* alles senden */
|
|
l2flp = (LHEAD *) &txl2fl[l2prt];
|
|
|
|
while ( (l2flp->head != l2flp) /* solange Frames vorhanden */
|
|
|| (testflag[l2prt] == TRUE)) /* oder TEST gefordert */
|
|
{
|
|
if (l2flp->head != l2flp) /* erst Info, danach erst TEST */
|
|
{
|
|
txfhdl = (MBHEAD *) l2flp->head;
|
|
ulink((LEHEAD *) txfhdl);
|
|
tmp_bufptr = tmp_buffer; /* Zwischenpuffer auf Anfang */
|
|
*tmp_bufptr++ = (char)0x00; /* fuer KISS-Befehl "Daten */
|
|
tmp_buflen = 1; /* folgen" */
|
|
|
|
while (txfhdl->mbgc < txfhdl->mbpc) /* noch Zeichen im Frame */
|
|
{
|
|
ch1 = getchr(txfhdl); /* 1 Zeichen aus Frame holen */
|
|
*tmp_bufptr++ = (char)(ch1 & 0xFF);/* Zeichen in Zwischenpuffer */
|
|
++tmp_buflen;
|
|
}
|
|
|
|
relink((LEHEAD *) txfhdl, (LEHEAD *) stfl.tail);
|
|
}
|
|
else /* TEST */
|
|
{
|
|
tmp_bufptr = tmp_buffer; /* Zwischenpuffer auf Anfang */
|
|
*tmp_bufptr++ = 0x00; /* fuer KISS-Befehl "Daten */
|
|
tmp_buflen = 1; /* folgen" */
|
|
while (count > 0) /* noch Zeichen fuer Test */
|
|
{
|
|
if (tmp_buflen == MAXKISSLEN-3) /* Buffer voll? */
|
|
break;
|
|
*tmp_bufptr++ = 0; /* Zeichen in Zwischenpuffer */
|
|
++tmp_buflen;
|
|
if (--count == 0) /* fertig? */
|
|
testflag[l2prt] = FALSE;
|
|
}
|
|
}
|
|
if (!portenabled(l2prt)) /* Port aus -> Frame ist abgeholt, auf */
|
|
continue; /* zum naechsten .. */
|
|
if (recovery) /* bei Token-Recovery */
|
|
continue; /* zum naechsten .. */
|
|
tx_bufptr = tx_buffer; /* Sendepuffer auf Anfang */
|
|
*tx_bufptr++ = (char)FEND; /* KISS-Frame beginnt mit FEND */
|
|
len = 1;
|
|
switch (l1pp->kisstype) /* KISS-Befehl "Daten folgen" abhaengig */
|
|
{ /* vom KISS-Modus */
|
|
case KISS_NORMAL: /* KISS einfach */
|
|
case KISS_SCC:
|
|
*tmp_buffer = 0x00;
|
|
break;
|
|
|
|
case KISS_SMACK: /* SMACK */
|
|
case KISS_TF: /* TheFirmware */
|
|
*tmp_buffer = 0x80;
|
|
append_crc_16(tmp_buffer, &tmp_buflen); /* CRC ueber gesamtes */
|
|
break; /* Frame anhaengen */
|
|
|
|
case KISS_RMNC: /* RMNC-KISS */
|
|
*tmp_buffer = 0x20;
|
|
append_crc_rmnc(tmp_buffer, &tmp_buflen);/* CRC ueber gesamtes */
|
|
break; /* Frame anhaengen */
|
|
|
|
case KISS_TOK: /* Tokenring-KISS */
|
|
*tmp_buffer = 0x00;
|
|
*tx_bufptr++ = l2prt; /* L2-Port vorweg */
|
|
++len;
|
|
break;
|
|
}
|
|
tmp_bufptr = tmp_buffer; /* Zwischenpuffer auf Anfang */
|
|
|
|
for (i = 0; i < tmp_buflen; ++i) /* Zwischenpuffer -> Sendepuffer */
|
|
{ /* kopieren */
|
|
switch (*tmp_bufptr)
|
|
{
|
|
case FEND: /* FEND -> FESC / TFEND */
|
|
*tx_bufptr++ = (char)FESC;
|
|
*tx_bufptr++ = (char)TFEND;
|
|
len += 2;
|
|
break;
|
|
|
|
case FESC: /* FESC -> FESC / TFESC */
|
|
*tx_bufptr++ = (char)FESC;
|
|
*tx_bufptr++ = (char)TFESC;
|
|
len += 2;
|
|
break;
|
|
|
|
default: /* keine Sonderbehandlung */
|
|
*tx_bufptr++ = *tmp_bufptr;
|
|
++len;
|
|
break;
|
|
}
|
|
++tmp_bufptr;
|
|
}
|
|
*tx_bufptr++ = (char)FEND; /* Frameende = FEND */
|
|
++len;
|
|
|
|
write(l1pp->kisslink, tx_buffer, len); /* Frame -> TNC */
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Empfangsframe in TNN-Puffer schreiben - CRC ist ggf. schon geprueft */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
static void frame_to_l1(WORD port, char *buffer, int len)
|
|
{
|
|
static MBHEAD *rxfrhd;
|
|
register int i;
|
|
|
|
rxfrhd = (MBHEAD *) allocb(ALLOC_MBHEAD);
|
|
rxfrhd->l2port = port;
|
|
|
|
for (i = 0; i < len; ++i)
|
|
putchr(buffer[i], rxfrhd);
|
|
|
|
relink((LEHEAD *) rxfrhd, (LEHEAD *)rxfl.tail);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Frame auf Gueltigkeit pruefen (Laenge, CRC) und gueltige Frames */
|
|
/* weiterreichen */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
static void frame_valid(WORD port, char *buffer, int len, int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case KISS_NORMAL: /* KISS einfach, Tokenring oder SCC: */
|
|
case KISS_TOK: /* nur Framelaenge kann geprueft werden */
|
|
case KISS_SCC:
|
|
if (len <= MAXFRAMELEN)
|
|
frame_to_l1(port, buffer+1, len-1);
|
|
break;
|
|
case KISS_SMACK: /* SMACK: CRC und Framelaenge */
|
|
case KISS_TF: /* TF auch mit SMACK */
|
|
if (!check_crc_16(buffer, &len)) /* pruefen */
|
|
if (len <= MAXFRAMELEN)
|
|
frame_to_l1(port, buffer+1, len-1);
|
|
break;
|
|
case KISS_RMNC: /* RMNC-KISS: CRC und Frame- */
|
|
if (!check_crc_rmnc(buffer, &len))/* laenge pruefen */
|
|
if (len <= MAXFRAMELEN)
|
|
frame_to_l1(port, buffer+1, len-1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* put data received over kisslink in rxbuffer */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void framedata_to_queue(int dev, char *buffer, int len)
|
|
{
|
|
UBYTE *bufptr;
|
|
register int i;
|
|
UBYTE ch;
|
|
DEVICE *l1pp;
|
|
static WORD k;
|
|
|
|
l1pp = &l1port[dev];
|
|
|
|
if (l1pp->kisstype == KISS_TOK) /* Waehrend Empfang kein Token- */
|
|
token_sent = tic10; /* recovery */
|
|
|
|
for (bufptr = buffer, i = 0; i < len; ++i, bufptr++)
|
|
{
|
|
ch = *bufptr; /* 1 Zeichen aus Puffer holen */
|
|
switch (l1pp->rx_state)
|
|
{
|
|
case ST_BEGIN: /* Frameanfang suchen */
|
|
if (ch == FEND) /* alles ausser FEND ignorieren */
|
|
l1pp->rx_state = ST_PORT;
|
|
break;
|
|
case ST_PORT: /* Portnummer folgt */
|
|
if (ch != FEND) /* zusaetzliche FEND ignorieren */
|
|
{
|
|
switch (l1pp->kisstype)
|
|
{
|
|
case KISS_NORMAL:
|
|
case KISS_SCC:
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* KISS einfach: Die Portnummer ist als Bit 4-7 kodiert. Daher sind */
|
|
/* eigentlich 16 Ports moeglich. Dies wird von dieser Software aber */
|
|
/* (noch?) nicht unterstuetzt. Gibt es ueberhaupt TNC-Software, die */
|
|
/* normalen KISS-Modus mit mehreren Ports unterstuetzt? Wer kann das */
|
|
/* einbauen und testen? */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if ((ch & 0x8F) == 0x00)
|
|
l1pp->rx_port = (ch & 0x70) >> 4;
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
case KISS_SMACK:
|
|
case KISS_TF:
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* SMACK: Die Portnummer ist als Bit 4-6 kodiert. Daher sind eigentlich */
|
|
/* 8 Ports moeglich. Dies wird von dieser Software aber (noch?) nicht */
|
|
/* unterstuetzt. Gibt es ueberhaupt TNC-Software, die den SMACK-Modus */
|
|
/* mit mehreren Ports unterstuetzt? Wer kann das einbauen und testen? */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if ((ch & 0x8F) == 0x80)
|
|
l1pp->rx_port = (ch & 0x70) >> 4;
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
case KISS_RMNC:
|
|
if ((ch & 0xFF) == 0x20)
|
|
l1pp->rx_port = 0;
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
case KISS_TOK:
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Tokenring: Die Portnummer ist als einzelnes Byte definiert. Daher */
|
|
/* sind eigentlich 255 Ports moeglich. TNN unterstuetzt aber nur die */
|
|
/* Ports 0 - 15. Ausserdem wird Port 255 fuer das Token verwendet. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
l1pp->rx_port = ch;
|
|
if ( (ch != 0xff) /* nicht Token-Port? */
|
|
&& ((ch >= L2PNUM) /* gueltige Portnummer? */
|
|
|| (l1ptab[(WORD) ch] != 0))) /* Port definiert? */
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
else
|
|
l1pp->rx_state = ST_TOKCMD;
|
|
break;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Die Portnummer wird jetzt ueberprueft. Ausser beim Tokenring MUSS es */
|
|
/* 0 sein. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
if (l1pp->kisstype != KISS_TOK)
|
|
{
|
|
if (l1pp->rx_state != ST_BEGIN)
|
|
{
|
|
if (l1pp->rx_port != 0x00)
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_DATA;
|
|
l1pp->rx_bufptr = l1pp->rx_buffer;
|
|
*l1pp->rx_bufptr++ = ch;
|
|
l1pp->rx_buflen = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case ST_DATA: /* Daten kommen */
|
|
switch (ch)
|
|
{
|
|
case FEND: /* Frameende? */
|
|
if (l1pp->kisstype != KISS_TOK) /* ggf. Portnummer aus */
|
|
l1pp->rx_port = l2ptab[dev]; /* Tabelle holen */
|
|
frame_valid(l1pp->rx_port, /* Frame pruefen und */
|
|
l1pp->rx_buffer, /* an L2 weitergeben */
|
|
l1pp->rx_buflen,
|
|
l1pp->kisstype);
|
|
l1pp->rx_state = ST_PORT; /* naechstes Frame kann */
|
|
break; /* kommen */
|
|
case FESC: /* FESC -> Sonderfall */
|
|
l1pp->rx_state = ST_ESC;
|
|
break;
|
|
default: /* normales Zeichen */
|
|
*l1pp->rx_bufptr = ch;
|
|
l1pp->rx_bufptr++;
|
|
l1pp->rx_buflen++;
|
|
if (l1pp->rx_buflen > MAXKISSLEN) /* Frame zu lang? */
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case ST_ESC: /* zuletzt FESC empfangen */
|
|
switch (ch)
|
|
{
|
|
case TFEND: /* FESC / TFEND -> FEND */
|
|
*l1pp->rx_bufptr = (char)FEND;
|
|
l1pp->rx_bufptr++;
|
|
l1pp->rx_buflen++;
|
|
if (l1pp->rx_buflen > MAXKISSLEN) /* Frame zu lang? */
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
else
|
|
l1pp->rx_state = ST_DATA;
|
|
break;
|
|
case TFESC: /* FESC / TFESC -> FESC */
|
|
*l1pp->rx_bufptr = (char)FESC;
|
|
l1pp->rx_bufptr++;
|
|
l1pp->rx_buflen++;
|
|
if (l1pp->rx_buflen > MAXKISSLEN) /* Frame zu lang? */
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
else
|
|
l1pp->rx_state = ST_DATA;
|
|
break;
|
|
default:
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
break;
|
|
}
|
|
break;
|
|
case ST_TOKCMD: /* Tokenring nach Port */
|
|
switch (ch & 0xff) /* kommt Kommando */
|
|
{
|
|
case 0: /* Kommando: "Daten */
|
|
l1pp->rx_state = ST_DATA; /* folgen" */
|
|
l1pp->rx_bufptr = l1pp->rx_buffer;
|
|
*l1pp->rx_bufptr++ = ch;
|
|
l1pp->rx_buflen = 1;
|
|
break;
|
|
case CMD_TOKEN: /* Kommando: "Token" */
|
|
if (l1pp->rx_port == 0xff)
|
|
l1pp->rx_state = ST_TOKEN;
|
|
else
|
|
l1pp->rx_state = ST_BEGIN;
|
|
break;
|
|
case MSG_TNCRES: /* Kommando: "TNC- */
|
|
if (l1pp->rx_port != 0xff) /* Meldung - Reset" */
|
|
{
|
|
k = 0;
|
|
l1pp->rx_state = ST_TNCRES;
|
|
}
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
case MSG_SENTDAMA: /* Kommando: "TNC- */
|
|
if (l1pp->rx_port != 0xff) /* Meldung: DAMA-Frames */
|
|
l1pp->rx_state = ST_DAMA; /* gesendet" */
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
default: /* unbekanntes Kommando */
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
break;
|
|
}
|
|
break;
|
|
case ST_TOKEN: /* nach Token kommt FEND */
|
|
if (ch == FEND)
|
|
{
|
|
tokenflag = TRUE;
|
|
l1pp->rx_state = ST_PORT;
|
|
++token_count;
|
|
}
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
case ST_TNCRES: /* nach TNC-Meldung kommt FEND */
|
|
if (ch == FEND)
|
|
{
|
|
commandflag[l1pp->rx_port] = TRUE;
|
|
portstat[l1pp->rx_port].reset_count++;
|
|
l1pp->rx_state = ST_PORT;
|
|
printf("TNC-Reset - Port %d\r\n", l1pp->rx_port);
|
|
}
|
|
else
|
|
{
|
|
if (++k > 6)
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
}
|
|
break;
|
|
case ST_DAMA: /* nach TNC-Meldung kommt FEND */
|
|
if (ch == FEND)
|
|
{
|
|
cd_timer[l1pp->rx_port] = 0; /* Kanal frei: Timer stoppen */
|
|
l1pp->rx_state = ST_PORT;
|
|
}
|
|
else
|
|
{
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
}
|
|
break;
|
|
default:
|
|
l1pp->rx_state = ST_BEGIN;
|
|
l1pp->bad_frames++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Markieren, dass fuer TNC #port Frames zum Senden vorliegen */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void kicktx(int port)
|
|
{
|
|
kick[port] = TRUE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* iscd(): Carrier Detect Wichtig fuer DAMA !!! */
|
|
/* */
|
|
/* Return: abhaengig von der Hardware des Ports - nur KISS wird */
|
|
/* direkt behandelt. PTTFLAG = auf DAMA-Port noch nicht */
|
|
/* alles gesendet, 0 sonst. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
WORD iscd(int l2port)
|
|
{
|
|
switch (kissmode(l2port))
|
|
{
|
|
#ifdef VANESSA
|
|
case KISS_VAN : return (vanessa_dcd(l2port)); break;
|
|
#endif
|
|
#ifdef AX_IPX
|
|
case KISS_IPX : return (axipx_dcd(l2port)); break;
|
|
#endif
|
|
#ifdef AX25IP
|
|
case KISS_AXIP : return (ax25ip_dcd(l2port)); break;
|
|
#endif
|
|
#if defined(KERNELIF) && (defined(PCISCC4_KAX25) || defined(HDLC_DCDPTTSTAT) || defined(SCC_DCDPTTSTAT))
|
|
case KISS_KAX25 : return (ifax_dcd(l2port)); break;
|
|
#endif
|
|
#ifdef SIXPACK
|
|
case KISS_6PACK : return (Sixpack_DCD((UWORD)l2port)); break;
|
|
#endif
|
|
#ifdef L1TELNET
|
|
case KISS_TELNET: return (TcpDCD(l2port)); break;
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
case KISS_HTTPD: return (TcpDCD(l2port)); break;
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
case KISS_IPCONV: return (TcpDCD(l2port)); break;
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
case KISS_IRC: return (TcpDCD(l2port)); break;
|
|
#endif /* L1IRC */
|
|
|
|
default : break;
|
|
}
|
|
|
|
/* DCD fuer Tokenring */
|
|
if ( dama(l2port) /* Nur DAMA-Ports und belegt.. */
|
|
&& cd_timer[l2port])
|
|
{
|
|
if ((tic10 - cd_timer[l2port]) > CD_TIMEOUT) /* Timeout abgelaufen? */
|
|
cd_timer[l2port] = 0; /* Timer stoppen */
|
|
|
|
if (cd_timer[l2port]) /* Timer laeuft: Port ist belegt */
|
|
return(PTTFLAG); /* Einen belegten Port gefunden! */
|
|
}/*Nur DAMA*/
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Aufzaehlen der vorhandenen Layer 1 Geraete. Dies sind nicht die */
|
|
/* tatsaechlich installierten sondern die compilierten. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1enum(MBHEAD *mbp)
|
|
{
|
|
#ifdef LOOPBACK
|
|
putstr(" * KISS-Protocols: TOKENRING KISS SMACK RKISS TF LOOP\r", mbp);
|
|
#else
|
|
putstr(" * KISS-Protocols: TOKENRING KISS SMACK RKISS TF\r", mbp);
|
|
#endif
|
|
#ifdef SIXPACK
|
|
putstr(" * 6PACK\r", mbp);
|
|
#endif
|
|
#ifdef VANESSA
|
|
putstr(" * VANESSA\r", mbp);
|
|
#endif
|
|
#ifdef AX_IPX
|
|
putstr(" * IPX\r", mbp);
|
|
#endif
|
|
#ifdef AX25IP
|
|
putstr(" * AX25IP\r", mbp);
|
|
#endif
|
|
#ifdef KERNELIF
|
|
putstr(" * Kernel-AX.25\r", mbp);
|
|
putstr(" * IP-Tunnel\r", mbp);
|
|
#endif
|
|
#ifdef L1TELNET
|
|
putstr(" * TELNET-Server\r", mbp);
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
putstr(" * HTTPD-Server\r", mbp);
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
putstr(" * IPCONVERS-Server\r", mbp);
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
putstr(" * IRC-Server\r", mbp);
|
|
#endif /* L1IRC */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* L1-Statistik loeschen (alle Ports) */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1sclr(const char *str)
|
|
{
|
|
register unsigned int i;
|
|
|
|
token_pro_sec = 0;
|
|
token_max_sec = 0;
|
|
token_min_sec = 0;
|
|
token_count = 0;
|
|
recovery_count = 0L;
|
|
|
|
for (i = 0; i < L1PNUM; ++i)
|
|
l1port[i].bad_frames = 0L;
|
|
|
|
#ifdef KERNELIF
|
|
ifip_clearstat();
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* L1-Statistik (Tokenring) anzeigen */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1stat(const char *name, MBHEAD *mbp)
|
|
{
|
|
int i;
|
|
BOOLEAN flag = FALSE;
|
|
|
|
if (tkcom >= 0)
|
|
{
|
|
putprintf(mbp, "\rTokens/sec - min.: %u; last: %u; max.: %u\r", token_min_sec, token_pro_sec, token_max_sec);
|
|
|
|
if (token_max_sec != 0) /* nicht vor 1. Messung */
|
|
putprintf(mbp, "TOKENRING load: %u%%\r", 100-(((ULONG)token_pro_sec)*100L) / ((ULONG)token_max_sec));
|
|
|
|
if (recovery_count != 0)
|
|
putprintf(mbp, "\rToken-Recoveries: %lu\r", recovery_count);
|
|
}
|
|
|
|
for (i = 0; i < L1PNUM; ++i)
|
|
{
|
|
if (l1port[i].bad_frames != 0)
|
|
{
|
|
if (!flag)
|
|
{
|
|
flag = TRUE;
|
|
putstr("\rBad frames:\r", mbp);
|
|
}
|
|
putprintf(mbp, "Device %s = %lu\r", l1port[i].device, l1port[i].bad_frames);
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* L1 beenden */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1detach(int l2prt)
|
|
{
|
|
portpar[l2prt].major = NO_MAJOR;
|
|
#ifdef AX_IPX
|
|
if (kissmode(l2prt) == KISS_IPX)
|
|
axipx_l1exit();
|
|
#endif
|
|
#ifdef AX25IP
|
|
if (kissmode(l2prt) == KISS_AXIP)
|
|
ax25ip_l1exit();
|
|
#endif
|
|
#ifdef KERNELIF
|
|
if ( (kissmode(l2prt) == KISS_KAX25)
|
|
|| (kissmode(l2prt) == KISS_KAX25KJD))
|
|
ifax_close(&(l1port[l1ptab[l2prt]]));
|
|
#endif
|
|
#ifdef L1TELNET
|
|
if (kissmode(l2prt) == KISS_TELNET)
|
|
L1ExitTCP(kissmode(l2prt));
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
if (kissmode(l2prt) == KISS_HTTPD)
|
|
L1ExitTCP(kissmode(l2prt));
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
if (kissmode(l2prt) == KISS_IPCONV)
|
|
L1ExitTCP(kissmode(l2prt));
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
if (kissmode(l2prt) == KISS_IRC)
|
|
L1ExitTCP(kissmode(l2prt));
|
|
#endif /* L1IRC */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* L1 starten */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
int l1attach(int l2prt, char *buf)
|
|
{
|
|
if (l1port[l1ptab[l2prt]].port_active == FALSE)
|
|
/* Port undefiniert in tnn.ini - der Port kann auf LOOP gesetzt werden */
|
|
{
|
|
if (strnicmp("LOOP", buf, min(4, strlen(buf))) == 0)
|
|
{
|
|
kissmode(l2prt) = KISS_LOOP;
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
if (strnicmp("TOKENRING", buf, min(9, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_TOK)
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
#ifdef SIXPACK
|
|
if (strnicmp("6PACK", buf, min(5, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_6PACK)
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (strnicmp("KISS", buf, min(4, strlen(buf))) == 0)
|
|
{
|
|
if ((kissmode(l2prt) != KISS_NIX) && (kissmode(l2prt) != KISS_VAN))
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
if (strnicmp("SMACK", buf, min(5, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_SMACK)
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
if (strnicmp("TF", buf, 2) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_TF)
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
if (strnicmp("RKISS", buf, min(5, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_RMNC)
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
#ifdef VANESSA
|
|
if (strnicmp("VANESSA", buf, min(7, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_VAN)
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef AX_IPX
|
|
if (strnicmp("IPX", buf, min(3, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_IPX)
|
|
{
|
|
if (!axipx_l1init(l2prt))
|
|
return(0);
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef AX25IP
|
|
if (strnicmp("AX25IP", buf, min(6, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_AXIP)
|
|
{
|
|
if (!ax25ip_l1init(l2prt))
|
|
return(0);
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef KERNELIF
|
|
if (strnicmp("KERNEL", buf, min(6, strlen(buf))) == 0)
|
|
{
|
|
if ( (kissmode(l2prt) == KISS_KAX25)
|
|
|| (kissmode(l2prt) == KISS_KAX25KJD))
|
|
{
|
|
if (!ifax_setup(&(l1port[l1ptab[l2prt]])))
|
|
return(0);
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef L1TELNET
|
|
if (strnicmp("TELNET", buf, min(6, strlen(buf))) == FALSE)
|
|
{
|
|
if (kissmode(l2prt) == KISS_TELNET)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
|
|
portpar[l2prt].major = TRUE;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
if (strnicmp("HTTPD", buf, min(6, strlen(buf))) == FALSE)
|
|
{
|
|
if (kissmode(l2prt) == KISS_HTTPD)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
|
|
portpar[l2prt].major = TRUE;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
if (strnicmp("IPCONV", buf, min(6, strlen(buf))) == FALSE)
|
|
{
|
|
if (kissmode(l2prt) == KISS_IPCONV)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
|
|
portpar[l2prt].major = TRUE;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
if (strnicmp("IRC", buf, min(3, strlen(buf))) == FALSE)
|
|
{
|
|
if (kissmode(l2prt) == KISS_IRC)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
|
|
portpar[l2prt].major = TRUE;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
#endif /* L1IRC */
|
|
if (strnicmp("SSC", buf, min(3, strlen(buf))) == 0)
|
|
{
|
|
if (kissmode(l2prt) == KISS_SCC)
|
|
{
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
if (stricmp("ON", buf) == 0)
|
|
{
|
|
if (kissmode(l2prt) != KISS_NIX)
|
|
{
|
|
#ifdef AX_IPX
|
|
if (kissmode(l2prt) == KISS_IPX)
|
|
{
|
|
if (!axipx_l1init(l2prt))
|
|
return(0);
|
|
}
|
|
#endif
|
|
#ifdef AX25IP
|
|
if (kissmode(l2prt) == KISS_AXIP)
|
|
{
|
|
if (!ax25ip_l1init(l2prt))
|
|
return(0);
|
|
}
|
|
#endif
|
|
#ifdef KERNELIF
|
|
if ( (kissmode(l2prt) == KISS_KAX25)
|
|
|| (kissmode(l2prt) == KISS_KAX25KJD))
|
|
{
|
|
if (!ifax_setup(&(l1port[l1ptab[l2prt]])))
|
|
return(0);
|
|
}
|
|
#endif
|
|
#ifdef L1TELNET
|
|
if (kissmode(l2prt) == KISS_TELNET)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
}
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
if (kissmode(l2prt) == KISS_HTTPD)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
}
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
if (kissmode(l2prt) == KISS_IPCONV)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
}
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
if (kissmode(l2prt) == KISS_IRC)
|
|
{
|
|
if (!L1InitTCP(kissmode(l2prt), l2prt, htons((unsigned short)atoi(l1port[l1ptab[l2prt]].device))))
|
|
return(FALSE);
|
|
}
|
|
#endif /* L1IRC */
|
|
|
|
portpar[l2prt].major = 1;
|
|
return(1);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Infostring fuer den Port-Befehl zusammenbauen. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1hwstr(int l2prt, MBHEAD *mbp)
|
|
{
|
|
l1hwcfg(l2prt, mbp);
|
|
if ((kissmode(l2prt) != KISS_VAN) && (kissmode(l2prt) < KISS_IPX))
|
|
{
|
|
putchr(' ', mbp);
|
|
putstr(l1port[l1ptab[l2prt]].device, mbp);
|
|
}
|
|
else
|
|
{
|
|
#ifdef VANESSA
|
|
if (kissmode(l2prt) == KISS_VAN)
|
|
van_hwstr(l2prt, mbp);
|
|
#endif
|
|
#ifdef AX_IPX
|
|
if (kissmode(l2prt) == KISS_IPX)
|
|
axipx_hwstr(l2prt, mbp);
|
|
#endif
|
|
#ifdef AX25IP
|
|
if (kissmode(l2prt) == KISS_AXIP)
|
|
ax25ip_hwstr(l2prt, mbp);
|
|
#endif
|
|
#ifdef KERNELIF
|
|
if ( (kissmode(l2prt) == KISS_KAX25)
|
|
|| (kissmode(l2prt) == KISS_KAX25KJD))
|
|
ifax_hwstr(l2prt, mbp);
|
|
#endif
|
|
#ifdef L1TELNET
|
|
if (kissmode(l2prt) == KISS_TELNET)
|
|
HwstrTCP(KISS_TELNET, l2prt, mbp);
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
if (kissmode(l2prt) == KISS_HTTPD)
|
|
HwstrTCP(KISS_HTTPD, l2prt, mbp);
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
if (kissmode(l2prt) == KISS_IPCONV)
|
|
HwstrTCP(KISS_IPCONV, l2prt, mbp);
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
if (kissmode(l2prt) == KISS_IRC)
|
|
HwstrTCP(KISS_IRC, l2prt, mbp);
|
|
#endif /* L1IRC */
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Infostring fuer SAVEPARM zusammenbauen. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
void l1hwcfg(int l2prt, MBHEAD *mbp)
|
|
{
|
|
if (!portenabled(l2prt))
|
|
putstr("OFF", mbp);
|
|
else
|
|
{
|
|
switch (kissmode(l2prt))
|
|
{
|
|
case KISS_SMACK: putstr("SMACK", mbp);
|
|
break;
|
|
case KISS_TF: putstr("TF", mbp);
|
|
break;
|
|
case KISS_TOK: putstr("TOKENRING", mbp);
|
|
break;
|
|
#ifdef LOOPBACK
|
|
case KISS_LOOP: putstr("LOOP", mbp);
|
|
break;
|
|
#endif
|
|
case KISS_RMNC: putstr("RKISS", mbp);
|
|
break;
|
|
#ifdef VANESSA
|
|
case KISS_VAN: putstr("VANESSA", mbp);
|
|
break;
|
|
#endif
|
|
#ifdef AX_IPX
|
|
case KISS_IPX: putstr("IPX", mbp);
|
|
break;
|
|
#endif
|
|
#ifdef AX25IP
|
|
case KISS_AXIP: putstr("AX25IP", mbp);
|
|
break;
|
|
#endif
|
|
#ifdef KERNELIF
|
|
case KISS_KAX25:
|
|
case KISS_KAX25KJD: putstr("KERNEL", mbp);
|
|
break;
|
|
#endif
|
|
#ifdef SIXPACK
|
|
case KISS_6PACK: putstr("6PACK", mbp);
|
|
break;
|
|
#endif
|
|
#ifdef L1TELNET
|
|
case KISS_TELNET: putstr("TELNET", mbp);
|
|
break;
|
|
#endif /* L1TELNET */
|
|
#ifdef L1HTTPD
|
|
case KISS_HTTPD: putstr("HTTPD ", mbp);
|
|
break;
|
|
#endif /* L1HTTPD */
|
|
#ifdef L1IPCONV
|
|
case KISS_IPCONV: putstr("IPCONV", mbp);
|
|
break;
|
|
#endif /* L1IPCONV */
|
|
#ifdef L1IRC
|
|
case KISS_IRC: putstr("IRC ", mbp);
|
|
break;
|
|
#endif /* L1IRC */
|
|
|
|
default: putstr("KISS", mbp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Blocktransferroutinen fuer den Level 1
|
|
* Message-Buffer koennen Blockweise in einen linearen Buffer umgewandelt
|
|
* werden und wieder zurueck. Dies darf aber so ohne weiteres nur im
|
|
* Level 1 erfolgen, da der Buffer zurueckgespult wird.
|
|
*/
|
|
|
|
/* Message-Buffer -> linearen Buffer */
|
|
int cpymbflat(char *buf, MBHEAD *fbp) {
|
|
MB *bp;
|
|
LHEAD *llp = &fbp->mbl; /* Zeiger auf den Listenkopf */
|
|
int i = fbp->mbpc; /* Anzahl der Bytes im Frame */
|
|
|
|
for (bp = (MB *)llp->head; bp != (MB *)llp;
|
|
bp = bp->nextmb, i -= sizeof_MBDATA, buf += sizeof_MBDATA)
|
|
memcpy(buf, bp->data, sizeof_MBDATA);
|
|
return(fbp->mbpc);
|
|
}
|
|
|
|
/* linearer Buffer -> Message-Buffer */
|
|
MBHEAD *cpyflatmb(char *buf, int size) {
|
|
MBHEAD *mbhd;
|
|
MB *bp;
|
|
LHEAD *llp;
|
|
|
|
mbhd = (MBHEAD *)allocb(ALLOC_MBHEAD); /* einen Buffer fuer den Kopf */
|
|
mbhd->mbpc = size; /* soviel wird mal drinstehen */
|
|
llp = &mbhd->mbl; /* Zeiger auf den Listenkopf */
|
|
for ( ; size > 0; size -= sizeof_MBDATA, buf += sizeof_MBDATA) {
|
|
memcpy((bp = (MB *)allocb(ALLOC_MB))->data, buf, sizeof_MBDATA);
|
|
relink((LEHEAD *)bp, (LEHEAD *)llp->tail);
|
|
}
|
|
rwndmb(mbhd); /* mbbp richtig setzen */
|
|
return(mbhd);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* TNC mit TheFirmware in KISS-Modus schalten */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#ifndef ATTACH
|
|
static void tf_set_kiss(DEVICE *l1pp)
|
|
#else
|
|
void tf_set_kiss(DEVICE *l1pp)
|
|
#endif /* ATTACH */
|
|
{
|
|
char buffer1[] = {0x18, 0x12, 0x18, ESC, '@', 'K', CR};
|
|
char buffer2[] = {(char)FESC, (char)FEND, (char)FEND, (char)0x80, 0, 0, (char)FEND};
|
|
|
|
write(l1pp->kisslink, buffer1, 7);
|
|
sleep(5);
|
|
write(l1pp->kisslink, buffer2, 7);
|
|
}
|
|
|
|
/* tfkiss: TNC-emulation for Win32
|
|
Copyright (C) 1995-96 by Mark Wahl
|
|
CRC calculation (crc.c)
|
|
created: Mark Wahl DL4YBG 95/10/08
|
|
updated: Mark Wahl DL4YBG 96/01/31
|
|
*/
|
|
|
|
/* CRC-table for SMACK */
|
|
static const int
|
|
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
|
|
};
|
|
|
|
/* CRC-table for RMNC-KISS */
|
|
static const int
|
|
Crc_rmnc_table[] = {
|
|
0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,
|
|
0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,
|
|
0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,
|
|
0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,
|
|
0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,
|
|
0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,
|
|
0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,
|
|
0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,
|
|
0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,
|
|
0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,
|
|
0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,
|
|
0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,
|
|
0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,
|
|
0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,
|
|
0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,
|
|
0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,
|
|
0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,
|
|
0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,
|
|
0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,
|
|
0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,
|
|
0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,
|
|
0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,
|
|
0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,
|
|
0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,
|
|
0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,
|
|
0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,
|
|
0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,
|
|
0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,
|
|
0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,
|
|
0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,
|
|
0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,
|
|
0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff
|
|
};
|
|
|
|
static void append_crc_16(char *buffer, int *len)
|
|
{
|
|
register int i;
|
|
int crc_16 = 0;
|
|
UBYTE *bufptr = buffer;
|
|
|
|
for (i = 0; i < *len; ++i)
|
|
crc_16 = (crc_16 >> 8) ^ Crc_16_table[(crc_16 ^ *bufptr++) & 0xff];
|
|
|
|
*bufptr++ = crc_16;
|
|
*bufptr++ = (crc_16 >> 8);
|
|
*len += 2;
|
|
}
|
|
|
|
static int check_crc_16(char *buffer, int *len)
|
|
{
|
|
register int i;
|
|
int crc_16 = 0;
|
|
UBYTE *bufptr = buffer;
|
|
|
|
if (*len < 3)
|
|
return(1);
|
|
|
|
for (i = 0; i < *len; ++i)
|
|
crc_16 = (crc_16 >> 8) ^ Crc_16_table[(crc_16 ^ *bufptr++) & 0xff];
|
|
|
|
if (crc_16)
|
|
return(1);
|
|
|
|
*len -= 2;
|
|
return(0);
|
|
}
|
|
|
|
static void append_crc_rmnc(char *buffer, int *len)
|
|
{
|
|
register int i;
|
|
int crc_rmnc = 0xFFFF;
|
|
UBYTE *bufptr = buffer;
|
|
|
|
for (i = 0; i < *len; ++i)
|
|
crc_rmnc = (crc_rmnc << 8) ^ Crc_rmnc_table[((crc_rmnc >> 8) ^ *bufptr++) & 0xff];
|
|
|
|
*bufptr++ = (crc_rmnc >> 8);
|
|
*bufptr++ = crc_rmnc;
|
|
*len += 2;
|
|
}
|
|
|
|
static int check_crc_rmnc(char *buffer, int *len)
|
|
{
|
|
register int i;
|
|
int crc_rmnc = 0xFFFF;
|
|
UBYTE *bufptr = buffer;
|
|
|
|
if (*len < 3)
|
|
return(1);
|
|
|
|
for (i = 0; i < *len; ++i)
|
|
crc_rmnc = (crc_rmnc << 8) ^ Crc_rmnc_table[((crc_rmnc >> 8) ^ *bufptr++) & 0xff];
|
|
|
|
if ((crc_rmnc & 0xFFFF) != 0x7070)
|
|
return(1);
|
|
|
|
*len -= 2;
|
|
return(0);
|
|
}
|
|
|
|
/* End of os/win32/l1win32.c */
|