linbpq/Cmd.c

5989 lines
139 KiB
C

/*
Copyright 2001-2022 John Wiseman G8BPQ
This file is part of LinBPQ/BPQ32.
LinBPQ/BPQ32 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LinBPQ/BPQ32 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. S"paclenee the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
*/
//
// C replacement for cmd.asm
//
#define Kernel
#define _CRT_SECURE_NO_DEPRECATE
#pragma data_seg("_BPQDATA")
//#include "windows.h"
//#include "winerror.h"
#include "time.h"
#include "stdio.h"
#include <fcntl.h>
//#include "vmm.h"
//#include "SHELLAPI.H"
#include "CHeaders.h"
#include "bpqaprs.h"
#include "kiss.h"
#pragma pack()
#include "tncinfo.h"
#include "telnetserver.h"
//#include "GetVersion.h"
//#define DllImport __declspec( dllimport )
//#define DllExport __declspec( dllexport )
BOOL DecodeCallString(char * Calls, BOOL * Stay, BOOL * Spy, UCHAR *AXCalls);
VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port);
int APIENTRY ClearNodes();
VOID GetJSONValue(char * _REPLYBUFFER, char * Name, char * Value);
VOID SendHTTPRequest(SOCKET sock, char * Host, int Port, char * Request, char * Params, int Len, char * Return);
SOCKET OpenWL2KHTTPSock();
VOID FormatTime3(char * Time, time_t cTime);
VOID Format_Addr(unsigned char * Addr, char * Output, BOOL IPV6);
VOID Tel_Format_Addr(struct ConnectionInfo * sockptr, char * dst);
VOID FindLostBuffers();
BOOL CheckCMS(struct TNCINFO * TNC);
VOID L2SENDXID(struct _LINKTABLE * LINK);
int CountBits(unsigned long in);
VOID SaveMH();
BOOL RestartTNC(struct TNCINFO * TNC);
void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID WriteMiniDump();
int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive);
int seeifInterlockneeded(struct PORTCONTROL * PORT);
extern VOID KISSTX(struct KISSINFO * KISS, PMESSAGE Buffer);
char COMMANDBUFFER[81] = ""; // Command Hander input buffer
char OrigCmdBuffer[81] = ""; // Command Hander input buffer before toupper
struct DATAMESSAGE * REPLYBUFFER = NULL;
UINT APPLMASK = 0;
UCHAR SAVEDAPPLFLAGS = 0;
UCHAR ALIASINVOKED = 0;
VOID * CMDPTR = 0;
short CMDPACLEN = 0;
char OKMSG[] = "Ok\r";
char CMDERRMSG[] = "Invalid command - Enter ? for command list\r";
#define CMDERRLEN sizeof(CMDERRMSG) - 1
char PASSWORDMSG[] = "Command requires SYSOP status - enter password\r";
#define LPASSMSG sizeof(PASSWORDMSG) - 1
char CMDLIST[] = "CONNECT BYE INFO NODES PORTS ROUTES USERS MHEARD";
#define CMDLISTLEN sizeof(CMDLIST) - 1
char BADMSG[] = "Bad Parameter\r";
char BADPORT[] = "Invalid Port Number\r";
char NOTEXTPORT[] = "Only valid on EXT ports\r";
char NOVALCALLS[] = "No Valid Calls defined on this port\r";
char BADVALUEMSG[] = "Invalid parameter\r";
char BADCONFIGMSG[] = "Configuration File check falled - will continue with old config\r";
#ifdef LINBPQ
char REBOOTOK[] = "Rebooting\r";
#else
char REBOOTOK[] = "Rebooting in 20 secs\r";
#endif
char REBOOTFAILED[] = "Shutdown failed\r";
char RESTARTOK[] = "Restarting\r";
char RESTARTFAILED[] = "Restart failed\r";
UCHAR ARDOP[7] = {'A'+'A','R'+'R','D'+'D','O'+'O','P'+'P',' '+' '}; // ARDOP IN AX25
UCHAR VARA[7] = {'V'+'V','A'+'A','R'+'R','A'+'A',' '+' ',' '+' '}; // VARA IN AX25
int STATSTIME = 0;
int MAXBUFFS = 0;
int QCOUNT = 0;
int MINBUFFCOUNT = 65535;
int NOBUFFCOUNT = 0;
int BUFFERWAITS = 0;
int MAXDESTS = 0;
int NUMBEROFNODES = 0;
int L4CONNECTSOUT = 0;
int L4CONNECTSIN = 0;
int L4FRAMESTX = 0;
int L4FRAMESRX = 0;
int L4FRAMESRETRIED = 0;
int OLDFRAMES = 0;
int L3FRAMES = 0;
VOID SENDSABM(struct _LINKTABLE * LINK);
VOID RESET2(struct _LINKTABLE * LINK);
int APPL1 = 0;
int PASSCMD = 0;
#pragma pack(1)
struct _EXTPORTDATA DP; // Only way I can think of to get offets to port data into cmd table
char CMDALIAS[ALIASLEN][NumberofAppls] = {0};
char * ALIASPTR = &CMDALIAS[0][0];
extern int RigReconfigFlag;
struct CMDX COMMANDS[];
int CMDXLEN = sizeof (struct CMDX);
VOID SENDNODESMSG();
VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID SHOWAGW(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID SHOWNAT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD);
void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD);
VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD);
void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...)
{
// Send Command response checking PACLEN
char Mess[4096];
va_list(arglist);
int OldLen;
int MsgLen;
struct DATAMESSAGE * Buffer;
char * Messptr = Mess;
int Paclen = Session->SESSPACLEN;
if (Paclen == 0)
Paclen = 255;
va_start(arglist, format);
MsgLen = vsprintf(Mess, format, arglist);
OldLen = (int)(Bufferptr - (char *)REPLYBUFFER->L2DATA);
while ((OldLen + MsgLen) > Paclen)
{
// Have to send Paclen then get a new buffer
int ThisBit = Paclen - OldLen; // What we can send this time
if (ThisBit < 0)
ThisBit = 0; // How can this happen??
memcpy(Bufferptr, Messptr, ThisBit);
Messptr += ThisBit;
MsgLen -= ThisBit;
// QUEUE IT AND GET ANOTHER BUFFER
Buffer = (struct DATAMESSAGE *)GetBuff();
if (Buffer == NULL)
// No buffers, so just reuse the old one (better than crashing !!)
Buffer = REPLYBUFFER;
else
SendCommandReply(Session, REPLYBUFFER, Paclen + (4 + sizeof(void *)));
REPLYBUFFER = Buffer;
Buffer->PID = 0xf0;
Bufferptr = &Buffer->L2DATA[0];
OldLen = 0;
}
// Add last bit to buffer
memcpy(Bufferptr, Messptr, MsgLen);
return Bufferptr + MsgLen;
}
VOID SENDNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
SENDNODESMSG();
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID SAVEMHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
SaveMH();
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID SAVENODES(struct _TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
SaveNodes();
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID DUMPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
WriteMiniDump();
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID RIGRECONFIG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
if (!ProcessConfig())
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Configuration File check falled - will continue with old config");
}
else
{
RigReconfigFlag = TRUE;
Bufferptr = Cmdprintf(Session, Bufferptr, "Rigcontrol Reconfig requested");
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID REBOOT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
if (Reboot())
{
strcpy(Bufferptr, REBOOTOK);
Bufferptr += (int)strlen(REBOOTOK);
}
else
{
strcpy(Bufferptr, REBOOTFAILED);
Bufferptr += (int)strlen(REBOOTFAILED);
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID RESTART(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
if (Restart())
{
strcpy(Bufferptr, RESTARTOK);
Bufferptr += (int)strlen(RESTARTOK);
}
else
{
strcpy(Bufferptr, RESTARTFAILED);
Bufferptr += (int)strlen(RESTARTFAILED);
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID RESTARTTNC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char * ptr, *Context;
int portno;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
portno = atoi (ptr);
if (portno && portno < 33)
{
struct TNCINFO * TNC = TNCInfo[portno];
if (TNC == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
}
else
{
if (TNC->ProgramPath)
{
if (RestartTNC(TNC))
Bufferptr = Cmdprintf(Session, Bufferptr, "Restart %s Ok\r", TNC->ProgramPath);
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Restart %s Failed\r", TNC->ProgramPath);
}
else
{
Bufferptr = Cmdprintf(Session, Bufferptr, "PATH not defined so can't restart TNC\r");
}
}
}
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
UCHAR VALNODESFLAG = 0, EXTONLY = 0;
VOID PORTVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD);
VOID VALNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
VALNODESFLAG = 1;
PORTVAL(Session, Bufferptr, CmdTail, CMD);
}
VOID EXTPORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
EXTONLY = 1;
PORTVAL(Session, Bufferptr, CmdTail, CMD);
}
VOID PORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS PORT VALUE COMMANDS
char * ptr, *Context, * ptr1;
int portno;
UCHAR oldvalue, newvalue;
struct PORTCONTROL * PORT = PORTTABLE;
int n = NUMBEROFPORTS;
UCHAR * valueptr;
// Get port number
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
portno = atoi (ptr);
if (portno)
{
while (n--)
{
if (PORT->PORTNUMBER == portno)
{
if (VALNODESFLAG)
{
char * VNPtr = PORT->PERMITTEDCALLS;
char Normcall[10];
VALNODESFLAG = 0;
if (VNPtr)
{
while (VNPtr[0])
{
Normcall[ConvFromAX25(VNPtr, Normcall)] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%s ", Normcall);
VNPtr += 7;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
}
else
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", NOVALCALLS);
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (EXTONLY)
{
// Make sure an Extenal Port
EXTONLY = 0;
if (PORT->PORTTYPE != 0x10)
{
strcpy(Bufferptr, NOTEXTPORT);
Bufferptr += (int)strlen(NOTEXTPORT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
valueptr = (UCHAR *)PORT + CMD->CMDFLAG;
oldvalue = *valueptr;
// Display Param Namee
ptr1 = &CMD->String[0];
n = 12;
while (*(ptr1) != ' ' && n--)
*(Bufferptr++) = *(ptr1++);
// See if another param - if not, just display current value
ptr = strtok_s(NULL, " ", &Context);
if (ptr && ptr[0])
{
// Get new value
newvalue = atoi(ptr);
*valueptr = newvalue;
Bufferptr = Cmdprintf(Session, Bufferptr, " was %d now %d\r", oldvalue, newvalue);
}
else
Bufferptr = Cmdprintf(Session, Bufferptr, " %d\r", oldvalue);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
PORT = PORT->PORTPOINTER;
}
}
}
// Bad port
strcpy(Bufferptr, BADPORT);
Bufferptr += (int)strlen(BADPORT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID SWITCHVAL (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// Update switch 8 bit value
char * ptr, *Context, * ptr1;
UCHAR oldvalue, newvalue;
int n;
UCHAR * valueptr;
valueptr = (UCHAR *)CMD->CMDFLAG;
oldvalue = *valueptr;
// Display Param Name
ptr1 = &CMD->String[0];
n = 12;
while (*(ptr1) != ' ' && n--)
*(Bufferptr++) = *(ptr1++);
// See if a param - if not, just display current value
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && ptr[0])
{
// Get new value
newvalue = atoi(ptr);
*valueptr = newvalue;
Bufferptr = Cmdprintf(Session, Bufferptr, " was %d now %d\r", oldvalue, newvalue);
if (memcmp(CMD->String, "NODESINT ", 8) == 0)
L3TIMER = L3INTERVAL;
}
else
Bufferptr = Cmdprintf(Session, Bufferptr, " %d\r", oldvalue);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID SWITCHVALW (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// Update switch 16 bit value
char * ptr, *Context, * ptr1;
USHORT oldvalue, newvalue;
int n;
USHORT * valueptr;
valueptr = (USHORT *)CMD->CMDFLAG;
oldvalue = (USHORT)*valueptr;
// Display Param Name
ptr1 = &CMD->String[0];
n = 12;
while (*(ptr1) != ' ' && n--)
*(Bufferptr++) = *(ptr1++);
// See if a param - if not, just display current value
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && ptr[0])
{
// Get new value
newvalue = atoi(ptr);
*valueptr = newvalue;
Bufferptr = Cmdprintf(Session, Bufferptr, " was %d now %d\r", oldvalue, newvalue);
}
else
Bufferptr = Cmdprintf(Session, Bufferptr, " %d\r", oldvalue);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
TRANSPORTENTRY * SetupSessionFromSession(TRANSPORTENTRY * Session, PBPQVECSTRUC HOSTSESS, UINT APPLMASK)
{
// Create a Transport (L4) session linked to an incoming Session
TRANSPORTENTRY * NewSess = L4TABLE;
int Index = 0;
while (Index < MAXCIRCUITS)
{
if (NewSess->L4USER[0] == 0)
{
// Got One
UCHAR * ourcall = &MYCALL[0];
Session->L4CROSSLINK = NewSess;
NewSess->L4CROSSLINK = Session;
if (APPLMASK)
{
// Circuit for APPL - look for an APPLCALL
APPLCALLS * APPL = APPLCALLTABLE;
while ((APPLMASK & 1) == 0)
{
APPLMASK >>= 1;
APPL++;
}
if (APPL->APPLCALL[0] > 0x40) // We have an applcall
ourcall = &APPL->APPLCALL[0];
}
memcpy(NewSess->L4USER, ourcall, 7);
memcpy(NewSess->L4MYCALL, Session->L4MYCALL, 7);
NewSess->CIRCUITINDEX = Index; //OUR INDEX
NewSess->CIRCUITID = NEXTID;
NEXTID++;
if (NEXTID == 0)
NEXTID++; // kEEP nON-ZERO
NewSess->SESSIONT1 = Session->SESSIONT1;
NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW;
NewSess->SESSPACLEN = PACLEN; // Default;
NewSess->L4TARGET.HOST = HOSTSESS;
NewSess->L4STATE = 5;
return NewSess;
}
Index++;
NewSess++;
}
return NULL;
}
extern int GETCONNECTIONINFO();
BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySessions)
{
PBPQVECSTRUC HOSTSESS = BPQHOSTVECTOR;
TRANSPORTENTRY * NewSess;
int ApplNum;
int n = BPQHOSTSTREAMS;
int ConfigedPorts = 0;
// LOOK FOR A FREE HOST SESSION
while (n--)
{
if (HOSTSESS->HOSTAPPLMASK & Mask)
{
// Right appl
ConfigedPorts++;
if (HOSTSESS->HOSTSESSION == NULL && (HOSTSESS->HOSTFLAGS & 3) == 0) // Not attached and no report outstanding
{
// WEVE GOT A FREE BPQ HOST PORT - USE IT
NewSess = SetupSessionFromSession(Session, HOSTSESS, Mask);
if (NewSess == NULL)
return FALSE; // Appl not available
HOSTSESS->HOSTSESSION = NewSess;
// Convert APPLMASK to APPLNUM
ApplNum = 1;
while (APPLMASK && (APPLMASK & 1) == 0)
{
ApplNum++;
APPLMASK >>= 1;
}
HOSTSESS->HOSTAPPLNUM = ApplNum;
HOSTSESS->HOSTFLAGS |= 2; // Indicate State Change
NewSess->L4CIRCUITTYPE = BPQHOST | DOWNLINK;
PostStateChange(NewSess);
NewSess->SESS_APPLFLAGS = HOSTSESS->HOSTAPPLFLAGS;
NewSess->SESSPACLEN = Paclen;
return TRUE;
}
}
HOSTSESS++;
}
*AnySessions = ConfigedPorts; // to distinguish between none and all in use
return FALSE;
}
VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
BOOL CONFAILED = 0;
UINT CONERROR ;
char APPName[13];
char * ptr1, *ptr2;
int n = 12;
BOOL Stay = FALSE;
// Copy Appl and Null Terminate
ptr1 = &CMD->String[0];
ptr2 = APPName;
while (*(ptr1) != ' ' && n--)
*(ptr2++) = *(ptr1++);
*(ptr2) = 0;
if (Session->LISTEN)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Can't use %s while listening\r", APPName);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (CmdTail[0] == 'S')
Stay = TRUE;
Session->STAYFLAG = Stay;
memcpy(Session->APPL, CMD->String, 12);
// SEE IF THERE IS AN ALIAS DEFINDED FOR THIS COMMAND
if (ALIASPTR[0] > ' ')
{
// COPY ALIAS TO COMMAND BUFFER, THEN REENTER COMMAND HANDLER
int SaveSecure = Session->Secure_Session;
memcpy(COMMANDBUFFER, ALIASPTR, ALIASLEN);
_strupr(COMMANDBUFFER);
memcpy(OrigCmdBuffer, ALIASPTR, ALIASLEN); // In case original case version needed
ALIASINVOKED = 1; // To prevent Alias Loops
// Set secure session for application alias in case telnet outward connect
Session->Secure_Session = 1;
DoTheCommand(Session);
Session->Secure_Session = SaveSecure;
return;
}
if (cATTACHTOBBS(Session, APPLMASK, CMDPACLEN, &CONERROR) == 0)
{
// No Streams
if (CONERROR)
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, All %s Ports are in use - Please try later\r", APPName);
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, Application %s is not running - Please try later\r", APPName);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// IF CMD_TO_APPL SET IN APPLFLAGS, SEND INPUT MSG TO APPL
if (Session->L4CROSSLINK->SESS_APPLFLAGS & CMD_TO_APPL)
{
struct DATAMESSAGE * Msg = (struct DATAMESSAGE *)GetBuff();
TRANSPORTENTRY * XSession = Session->L4CROSSLINK;
if (Msg)
{
COMMANDBUFFER[72] = 13;
memcpy(Msg->L2DATA, COMMANDBUFFER, 73);
Msg->LENGTH = 73 + 4 + sizeof(void *);
Msg->PID = 0xf0;
C_Q_ADD(&XSession->L4TX_Q, (UINT *)Msg);
PostDataAvailable(XSession);
}
}
if (Stay)
Session->L4CROSSLINK->L4TARGET.HOST->HOSTFLAGS |= 0x20;
// IF MSG_TO_USER SET, SEND 'CONNECTED' MESSAGE TO USER
Session->SESS_APPLFLAGS = Session->L4CROSSLINK->SESS_APPLFLAGS;
if (Session->L4CROSSLINK->SESS_APPLFLAGS & MSG_TO_USER)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Connected to %s\r", APPName);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// DONT NEED BUFFER ANY MORE
ReleaseBuffer((UINT *)REPLYBUFFER);
return;
}
VOID CMDI00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", INFOMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID CMDV00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
if (sizeof(void *) == 4)
Bufferptr = Cmdprintf(Session, Bufferptr, "Version %s\r", VersionString);
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Version %s (64 bit)\r", VersionString);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID BYECMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
CLOSECURRENTSESSION(Session); // Kills any crosslink, plus local link
ReleaseBuffer((UINT *)REPLYBUFFER);
return;
}
VOID CMDPAC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// SET PACLEN FOR THIS SESSION
char * ptr, *Context;
int newvalue;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && ptr[0])
{
// Get new value
newvalue = atoi(ptr);
if (newvalue > 29 && newvalue < 256)
Session->SESSPACLEN = newvalue & 0xff;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "PACLEN - %d\r", Session->SESSPACLEN);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID CMDIDLE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// SET IDLETIME FOR THIS SESSION
char * ptr, *Context;
int newvalue;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && ptr[0])
{
// Get new value
newvalue = atoi(ptr);
if (newvalue > 59 && newvalue < 901)
Session->L4LIMIT = newvalue;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "IDLETIME - %d\r", Session->L4LIMIT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID CMDT00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// SET L4 TIMEOUT FOR CONNECTS ON THIS SESSION
char * ptr, *Context;
int newvalue;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && ptr[0])
{
// Get new value
newvalue = atoi(ptr);
if (newvalue > 20)
Session->SESSIONT1 = newvalue;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "L4TIMEOUT - %d\r", Session->SESSIONT1);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
UCHAR PWLen;
char PWTEXT[80];
VOID PWDCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char * ptr, *Context;
USHORT pwsum = 0;
int n = 5, p1, p2, p3, p4, p5;
if (Session->Secure_Session) // HOST - SET AUTHORISED REGARDLESS
{
Session->PASSWORD = 0xFFFF; // SET AUTHORISED
Session->Secure_Session = 1;
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && ptr[0])
{
// Check Password
n = 5;
while (n--)
pwsum += *(ptr++);
if (Session->PASSWORD == pwsum)
{
Session->PASSWORD = 0xFFFF; // SET AUTHORISED
Session->Secure_Session = 1;
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
ReleaseBuffer((UINT *)REPLYBUFFER);
return;
}
// SEND PASSWORD PROMPT
if (PWLen == 0)
PWLen = 1;
p1 = rand() % PWLen;
pwsum += PWTEXT[p1++];
p2 = rand() % PWLen;
pwsum += PWTEXT[p2++];
p3 = rand() % PWLen;
pwsum += PWTEXT[p3++];
p4 = rand() % PWLen;
pwsum += PWTEXT[p4++];
p5 = rand() % PWLen;
pwsum += PWTEXT[p5++];
Session->PASSWORD = pwsum;
Bufferptr = Cmdprintf(Session, Bufferptr, "%d %d %d %d %d\r", p1, p2, p3, p4, p5);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID CMDSTATS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char * ptr, *Context;
int Port = 0, cols = NUMBEROFPORTS, i;
char * uptime;
struct PORTCONTROL * PORT = PORTTABLE;
struct PORTCONTROL * STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
// SEE IF ANY PARAM
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && ptr[0])
Port = atoi(ptr);
// IF ASKING FOR PORT STATS, DONT DO SYSTEM ONES
if (Port == 0)
{
uptime = FormatUptime(STATSTIME);
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", uptime);
Bufferptr = Cmdprintf(Session, Bufferptr, "Semaphore Get-Rel/Clashes %9d%9d\r",
Semaphore.Gets - Semaphore.Rels, Semaphore.Clashes);
Bufferptr = Cmdprintf(Session, Bufferptr, "Buffers:Max/Cur/Min/Out/Wait%9d%9d%9d%9d%9d\r",
MAXBUFFS, QCOUNT, MINBUFFCOUNT, NOBUFFCOUNT, BUFFERWAITS);
Bufferptr = Cmdprintf(Session, Bufferptr, "Known Nodes/Max Nodes %9d%9d\r",
NUMBEROFNODES, MAXDESTS);
Bufferptr = Cmdprintf(Session, Bufferptr, "L4 Connects Sent/Rxed %9d%9d\r",
L4CONNECTSOUT, L4CONNECTSIN);
Bufferptr = Cmdprintf(Session, Bufferptr, "L4 Frames TX/RX/Resent/Reseq%9d%9d%9d%9d\r",
L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES);
Bufferptr = Cmdprintf(Session, Bufferptr, "L3 Frames Relayed %9d\r", L3FRAMES);
if (ptr && ptr[0] == 'S')
{
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
// POSITION TO REQUESTED PORT
if (Port)
{
while (PORT && PORT->PORTNUMBER != Port)
{
PORT = PORT->PORTPOINTER;
cols--;
}
}
if (PORT == NULL) // REQUESTED PORT NOT FOUND
{
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
STARTPORT = PORT;
if (cols > 7)
cols = 7;
Bufferptr = Cmdprintf(Session, Bufferptr, " ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Port %02d ", PORT->PORTNUMBER);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Digied");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2DIGIED);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Heard ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRAMES);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Rxed ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRAMESFORUS);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Frames Sent ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRAMESSENT);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Timeouts ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2TIMEOUTS);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "REJ Frames Rxed ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2REJCOUNT);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "RX out of Seq ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2OUTOFSEQ);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "L2 Resequenced ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2RESEQ);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "Undrun/Poll T/o ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2URUNC);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "RX Overruns ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2ORUNC);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "RX CRC Errors ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->RXERRORS);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "FRMRs Sent ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRMRTX);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "FRMRs Received ");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L2FRMRRX);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "Frames abandoned");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%9d", PORT->L1DISCARD);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
// Bufferptr = Cmdprintf(Session, Bufferptr, "Link Active %% ");
Bufferptr = Cmdprintf(Session, Bufferptr, "Active(TX/Busy) %%");
for (i = 0; i < cols; i++)
{
Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %3d ", PORT->AVSENDING, PORT->AVACTIVE);
PORT = PORT->PORTPOINTER;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID CMDL00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS 'LINKS' MESSAGE
struct _LINKTABLE * LINK = LINKS;
int n = MAXLINKS;
int len;
char Normcall[11] = "";
Bufferptr = Cmdprintf(Session, Bufferptr, "Links\r");
while (n--)
{
if (LINK->LINKCALL[0])
{
len = ConvFromAX25(LINK->LINKCALL, Normcall);
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Normcall);
len = ConvFromAX25(LINK->OURCALL, Normcall);
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Normcall);
if (LINK->Ver2point2)
Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=2.2\r",
LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE);
else
Bufferptr = Cmdprintf(Session, Bufferptr, " S=%d P=%d T=%d V=%d\r",
LINK->L2STATE, LINK->LINKPORT->PORTNUMBER, LINK->LINKTYPE, 2 - LINK->VER1FLAG);
}
LINK++;
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID CMDS00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS 'USERS'
int n = MAXCIRCUITS;
TRANSPORTENTRY * L4 = L4TABLE;
TRANSPORTENTRY * Partner;
int MaxLinks = MAXLINKS;
char State[12] = "", Type[12] = "Uplink";
char LHS[50] = "", MID[10] = "", RHS[50] = "";
char Line[100];
Bufferptr = Cmdprintf(Session, Bufferptr, "%s%d)\r", SESSIONHDDR, QCOUNT);
while (n--)
{
if (L4->L4USER[0])
{
RHS[0] = MID[0] = 0;
if ((L4->L4CIRCUITTYPE & UPLINK) == 0) //SHORT CMDS10A ; YES
{
// IF DOWNLINK, ONLY DISPLAY IF NO CROSSLINK
if (L4->L4CROSSLINK == 0) //jne CMDS60 ; WILL PROCESS FROM OTHER END
{
// ITS A DOWNLINK WITH NO PARTNER - MUST BE A CLOSING SESSION
// DISPLAY TO THE RIGHT FOR NOW
strcpy(LHS, "(Closing) ");
DISPLAYCIRCUIT(L4, RHS);
goto CMDS50;
}
else
goto CMDS60; // WILL PROCESS FROM OTHER END
}
if (L4->L4CROSSLINK == 0)
{
// Single Entry
DISPLAYCIRCUIT(L4, LHS);
}
else
{
DISPLAYCIRCUIT(L4, LHS);
Partner = L4->L4CROSSLINK;
if (Partner->L4STATE == 5)
strcpy(MID, "<-->");
else
strcpy(MID, "<~~>");
DISPLAYCIRCUIT(Partner, RHS);
}
CMDS50:
memset(Line, 32, 100);
memcpy(Line, LHS, (int)strlen(LHS));
memcpy(&Line[35], MID, (int)strlen(MID));
strcpy(&Line[40], RHS);
strcat(&Line[40], "\r");
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Line);
}
CMDS60:
L4++;
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
extern int MasterPort[MAXBPQPORTS+1]; // Pointer to first BPQ port for a specific MPSK or UZ7HO host
VOID CMDP00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// Process PORTS Message
// If extended show state of TNC (Open, Active, etc)
struct PORTCONTROL * PORT = PORTTABLE;
char Extended = CmdTail[0];
struct PORTCONTROL * SAVEPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "Ports\r");
while (PORT)
{
char Status[32] = "???????";
int Portno = PORT->PORTNUMBER;
if (PORT->Hide)
{
PORT = PORT->PORTPOINTER;
continue;
}
if (Extended != 'E')
{
Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %s\r", PORT->PORTNUMBER, PORT->PORTDESCRIPTION);
PORT = PORT->PORTPOINTER;
continue;
}
// Try to get port status - may not be possible with some
if (PORT->PortStopped)
{
strcpy(Status, "Stopped");
Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %-7s %s\r", PORT->PORTNUMBER, Status, PORT->PORTDESCRIPTION);
PORT = PORT->PORTPOINTER;
continue;
}
if (PORT->PORTTYPE == 0)
{
struct KISSINFO * KISS = (struct KISSINFO *)PORT;
NPASYINFO Port;
SAVEPORT = PORT;
if (KISS->FIRSTPORT && KISS->FIRSTPORT != KISS)
{
// Not first port on device
PORT = (struct PORTCONTROL *)KISS->FIRSTPORT;
Port = KISSInfo[Portno];
}
Port = KISSInfo[PORT->PORTNUMBER];
if (Port)
{
// KISS like - see if connected
if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE)
{
// KISS over UDP or TCP
if (PORT->KISSTCP)
{
if (Port->Connected)
strcpy(Status, "Open ");
else
if (PORT->KISSSLAVE)
strcpy(Status, "Listen");
else
strcpy(Status, "Closed");
}
else
strcpy(Status, "UDP");
}
else
if (Port->idComDev) // Serial port Open
strcpy(Status, "Open ");
else
strcpy(Status, "Closed");
PORT = SAVEPORT;
}
}
else if (PORT->PORTTYPE == 14) // Loopback
strcpy(Status, "Open ");
else if (PORT->PORTTYPE == 16) // External
{
if (PORT->PROTOCOL == 10) // 'HF' Port
{
struct TNCINFO * TNC = TNCInfo[Portno];
if (TNC == NULL)
{
PORT = PORT->PORTPOINTER;
continue;
}
switch (TNC->Hardware) // Hardware Type
{
case H_SCS:
case H_KAM:
case H_AEA:
case H_HAL:
case H_TRK:
case H_SERIAL:
// Serial
if (TNC->hDevice)
strcpy(Status, "Open ");
else
strcpy(Status, "Closed");
break;
case H_UZ7HO:
if (TNCInfo[MasterPort[Portno]]->CONNECTED)
strcpy(Status, "Open ");
else
strcpy(Status, "Closed");
break;
case H_WINMOR:
case H_V4:
case H_MPSK:
case H_FLDIGI:
case H_UIARQ:
case H_ARDOP:
case H_VARA:
case H_KISSHF:
case H_WINRPR:
case H_FREEDATA:
// TCP
if (TNC->CONNECTED)
{
if (TNC->Streams[0].Attached)
strcpy(Status, "In Use");
else
strcpy(Status, "Open ");
}
else
strcpy(Status, "Closed");
break;
case H_TELNET:
strcpy(Status, "Open ");
}
}
else
{
// External but not HF - AXIP, BPQETHER VKISS, ??
struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT;
strcpy(Status, "Open ");
}
}
Bufferptr = Cmdprintf(Session, Bufferptr, " %2d %-7s %s\r", PORT->PORTNUMBER, Status, PORT->PORTDESCRIPTION);
PORT = PORT->PORTPOINTER;
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
char * DisplayRoute(TRANSPORTENTRY * Session, char * Bufferptr, struct ROUTE * Routes, char Verbose)
{
char Normcall[10];
char locked[] = " ! ";
int NodeCount;
int Percent = 0;
char PercentString[20];
int Iframes, Retries;
char Active[10];
int Queued;
int Port = 0;
int len = ConvFromAX25(Routes->NEIGHBOUR_CALL, Normcall);
Normcall[9]=0;
if ((Routes->NEIGHBOUR_FLAG & 1) == 1)
strcpy(locked, "!");
else
strcpy(locked, " ");
NodeCount = COUNTNODES(Routes);
if (Routes->NEIGHBOUR_LINK && Routes->NEIGHBOUR_LINK->L2STATE >= 5)
strcpy(Active, ">");
else
strcpy(Active, " ");
if (Verbose)
{
if (Routes->NEIGHBOUR_LINK)
Queued = COUNT_AT_L2(Routes->NEIGHBOUR_LINK); // SEE HOW MANY QUEUED
else
Queued = 0;
Iframes = Routes->NBOUR_IFRAMES;
Retries = Routes->NBOUR_RETRIES;
if (Iframes)
{
Percent = (Retries * 100) / Iframes;
sprintf(PercentString, "%3d%%", Percent);
}
else
strcpy(PercentString, " ");
Bufferptr = Cmdprintf(Session, Bufferptr, "%s%2d %s %3d %3d%s%4d %4d %s %d %d %02d:%02d %d %d",
Active, Routes->NEIGHBOUR_PORT, Normcall,
Routes->NEIGHBOUR_QUAL, NodeCount, locked, Iframes, Retries, PercentString, Routes->NBOUR_MAXFRAME, Routes->NBOUR_FRACK,
Routes->NEIGHBOUR_TIME >> 8, (Routes->NEIGHBOUR_TIME) & 0xff, Queued, Routes->OtherendsRouteQual);
// IF INP3 DISPLAY SRTT
if (Routes->INP3Node) // INP3 Enabled?
{
double srtt = Routes->SRTT/1000.0;
double nsrtt = Routes->NeighbourSRTT/1000.0;
Bufferptr = Cmdprintf(Session, Bufferptr, " %4.2fs %4.2fs", srtt, nsrtt);
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
}
else
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s %d %s %d %d%s\r",
Active, Routes->NEIGHBOUR_PORT, Normcall, Routes->NEIGHBOUR_QUAL, NodeCount, locked);
}
return Bufferptr;
}
VOID CMDR00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
struct ROUTE * Routes = NEIGHBOURS;
int MaxRoutes = MAXNEIGHBOURS;
char locked[] = " ! ";
int Percent = 0;
char * ptr, * Context;
char Verbose = 0;
int Port = 0;
char AXCALL[7];
BOOL Found;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr && (int)strlen(ptr) > 1)
{
// Route Update
goto ROUTEUPDATE;
}
if (ptr)
{
Verbose = ptr[0];
ptr = strtok_s(NULL, " ", &Context);
if (ptr)
Port = atoi(ptr);
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Routes\r");
while (MaxRoutes--)
{
if (Routes->NEIGHBOUR_CALL[0] != 0)
if (Port == 0 || Port == Routes->NEIGHBOUR_PORT)
Bufferptr = DisplayRoute(Session, Bufferptr, Routes, Verbose);
Routes++;
}
goto SendReply;
ROUTEUPDATE:
if (Session->PASSWORD != 0xFFFF)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG);
goto SendReply;
}
// Line is
// ROUTES G8BPQ-2 2 100 - Set quality to 100
// ROUTES G8BPQ-2 2 ! - Toggle 'Locked Route' flag
// ROUTES G8BPQ-2 2 100 ! - Set quality and toggle 'locked' flag
ConvToAX25(ptr, AXCALL);
ptr = strtok_s(NULL, " ", &Context);
if (ptr)
Port = atoi(ptr);
if (Port == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Number Missing \r");
goto SendReply;
}
Found = FindNeighbour(AXCALL, Port, &Routes);
if (Context && Context[0] > 32)
{
// More Params
ptr = strtok_s(NULL, " ", &Context);
if (ptr)
{
// Adding
memcpy(Routes->NEIGHBOUR_CALL, AXCALL, 7); // In case Add
Routes->NEIGHBOUR_PORT = Port;
Found = TRUE;
}
if (strcmp(ptr, "!") == 0)
{
// Toggle Lock
Routes->NEIGHBOUR_FLAG ^= 1; // FLIP LOCKED BIT
goto Displayit;
}
if (strcmp(ptr, "Z") == 0)
{
// Clear Counts
Routes->NBOUR_IFRAMES = 0;
Routes->NBOUR_RETRIES = 0;
goto Displayit;
}
Routes->NEIGHBOUR_QUAL = atoi(ptr);
if (Context && Context[0] == '!')
{
// Toggle Lock
Routes->NEIGHBOUR_FLAG ^= 1; // FLIP LOCKED BIT
goto Displayit;
}
}
Displayit:
// Just display
if (Found)
Bufferptr = DisplayRoute(Session, Bufferptr, Routes, 1);
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Not Found\r");
/* MOV ROUTEDISP,1
CMP BYTE PTR [ESI],20H
JE SHORT JUSTDISPLAY
MOV ZAPFLAG,0
CMP BYTE PTR [ESI],'Z'
JNE SHORT NOTZAP
MOV ZAPFLAG,1
JMP SHORT JUSTDISPLAY
PUBLIC NOTZAP
NOTZAP:
MOV ROUTEDISP,2 ; LOCK UPDATE
CMP BYTE PTR [ESI],'!'
JE SHORT JUSTDISPLAY
;
; LOOK FOR V FOR ADDING A DIGI
;
CMP WORD PTR [ESI],' V' ; V [SPACE]
JE ADDDIGI
CALL GETVALUE ; GET NUMBER, UP TO SPACE , CR OR OFFH
JC SHORT BADROUTECMD ; INVALID DIGITS
MOV NEWROUTEVAL,AL
MOV ROUTEDISP,0
CALL SCAN ; SEE IF !
MOV AH,[ESI]
PUBLIC JUSTDISPLAY
JUSTDISPLAY:
MOV ESI,OFFSET32 AX25CALL
CALL _FINDNEIGHBOUR
JZ SHORT FOUNDROUTE ; IN LIST - OK
CMP EBX,0
JE SHORT BADROUTECMD ; TABLE FULL??
MOV ECX,7
MOV EDI,EBX
REP MOVSB ; PUT IN CALL
MOV AL,SAVEPORT
MOV NEIGHBOUR_PORT[EBX],AL
JMP SHORT FOUNDROUTE
PUBLIC BADROUTECMD
BADROUTECMD:
POP EDI
JMP PBADVALUE
PUBLIC FOUNDROUTE
FOUNDROUTE:
CMP ZAPFLAG,1
JNE SHORT NOTCLEARCOUNTS
XOR AX,AX
MOV ES:WORD PTR NBOUR_IFRAMES[EDI],AX
MOV ES:WORD PTR NBOUR_IFRAMES+2[EDI],AX
MOV ES:WORD PTR NBOUR_RETRIES[EDI],AX
MOV ES:WORD PTR NBOUR_RETRIES+2[EDI],AX
JMP SHORT NOUPDATE
PUBLIC NOTCLEARCOUNTS
NOTCLEARCOUNTS:
CMP ROUTEDISP,1
JE SHORT NOUPDATE
CMP ROUTEDISP,2
JE SHORT LOCKUPDATE
MOV AL,NEWROUTEVAL
MOV NEIGHBOUR_QUAL[EBX],AL
CMP AH,'!'
JNE SHORT NOUPDATE
PUBLIC LOCKUPDATE
LOCKUPDATE:
XOR NEIGHBOUR_FLAG[EBX],1 ; FLIP LOCKED BIT
PUBLIC NOUPDATE
NOUPDATE:
MOV ESI,EBX
POP EDI
POP EBX
CALL DISPLAYROUTE
JMP SENDCOMMANDREPLY
PUBLIC ADDDIGI
ADDDIGI:
ADD ESI,2
PUSH ESI ; SAVE INPUT BUFFER
MOV ESI,OFFSET32 AX25CALL
CALL _FINDNEIGHBOUR
POP ESI
JZ SHORT ADD_FOUND ; IN LIST - OK
JMP BADROUTECMD
PUBLIC ADD_FOUND
ADD_FOUND:
CALL CONVTOAX25 ; GET DIGI CALLSIGN
PUSH ESI
MOV ESI,OFFSET32 AX25CALL
LEA EDI,NEIGHBOUR_DIGI[EBX]
MOV ECX,7
REP MOVSB
POP ESI ; MSG BUFFER
;
; SEE IF ANOTHER DIGI
;
CMP BYTE PTR [ESI],20H
JE SHORT NOMORE
CALL CONVTOAX25 ; GET DIGI CALLSIGN
MOV ESI,OFFSET32 AX25CALL
LEA EDI,NEIGHBOUR_DIGI+7[EBX]
MOV ECX,7
REP MOVSB
PUBLIC NOMORE
NOMORE:
JMP NOUPDATE
*/
SendReply:
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID LISTENCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS LISTEN COMMAND
// for monitoring a remote ax.25 port
int Port = 0, index =0;
uint64_t ListenMask = 0;
char * ptr, *Context;
struct PORTCONTROL * PORT = NULL;
char ListenPortList[128] = "";
ptr = strtok_s(CmdTail, " ,", &Context);
// Now accepts a list of ports
if (ptr == 0 || memcmp(ptr, "OFF", 3) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Listening disabled\r");
Session->LISTEN = 0;
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
while (ptr)
{
Port = atoi(ptr);
if (Port == 0 && NUMBEROFPORTS == 1)
Port = 1;
ptr = strtok_s(NULL, ", ", &Context); // Get port String
if (Port)
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port %d\r", Port);
continue;
}
if (PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port %d is not an ax.25 port\r", Port);
continue;
}
if (PORT->PORTL3FLAG)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port %d is for internode traffic only\r", Port);
continue;
}
if (Session->L4CIRCUITTYPE == L2LINK + UPLINK)
{
if (Session->L4TARGET.LINK->LINKPORT->PORTNUMBER == Port)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "You can't Listen to the port you are connected on\r");
continue;
}
}
sprintf(ListenPortList, "%s %d", ListenPortList, Port);
ListenMask |= ((uint64_t)1 << (Port - 1));
}
Session->LISTEN = ListenMask;
if (ListenMask)
{
if (CountBits64(ListenMask) == 1)
Bufferptr = Cmdprintf(Session, Bufferptr, "Listening on port%s. Use CQ to send a beacon, LIS to disable\r", ListenPortList);
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Listening on ports%s. Use LIS to disable\r", ListenPortList);
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID UNPROTOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS UNPROTO COMMAND
int Port = 0, index =0;
char * ptr, *Context;
struct PORTCONTROL * PORT = NULL;
UCHAR axcalls[64];
BOOL Stay, Spy;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
Port = atoi(ptr);
if (Port == 0 && NUMBEROFPORTS == 1)
Port = 1;
else
ptr = strtok_s(NULL, " ", &Context); // Get Unproto String
if (Port)
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (ptr == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Destination missing\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
ptr[strlen(ptr)] = ' '; // Put param back together
if (DecodeCallString(ptr, &Stay, &Spy, &axcalls[0]) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is not an ax.25 port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PORTL3FLAG)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is for internode traffic only\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// Copy Address Info to Session Record
Session->UNPROTO = Port;
Session->UAddrLen = (int)strlen(axcalls);
memcpy(Session->UADDRESS, axcalls, 63);
Bufferptr = Cmdprintf(Session, Bufferptr, "Unproto Mode - enter ctrl/z or /ex to exit\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID CALCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS CAL COMMAND
int Port = 0, index = 0, Count = 0;
char * ptr, *Context;
struct PORTCONTROL * PORT = NULL;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
Port = atoi(ptr);
if (Port == 0 && NUMBEROFPORTS == 1)
Port = 1;
else
ptr = strtok_s(NULL, " ", &Context); // Get Unproto String
if (Port)
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PROTOCOL == 10 && PORT->UICAPABLE == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is not an ax.25 port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (ptr == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Count Missing\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Count = atoi(ptr);
ptr = strtok_s(NULL, " ", &Context); // Get Unproto String
Bufferptr = Cmdprintf(Session, Bufferptr, "Ok\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID CQCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// Send a CQ Beacon on a radio port. Must be in LISTEN state
DIGIMESSAGE Msg;
int Port = 0;
int OneBits = 0;
uint64_t MaskCopy = Session->LISTEN;
int Len;
UCHAR CQCALL[7];
char Empty[] = "";
char * ptr1 = &OrigCmdBuffer[3];
UCHAR * axptr = &Msg.DIGIS[0][0];
char * ptr2, *Context;
while (MaskCopy)
{
if (MaskCopy & 1)
OneBits++;
Port++;
MaskCopy = MaskCopy >> 1;
}
if (OneBits == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "You must enter LISTEN before calling CQ\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (OneBits > 1)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "You can't call CQ if LISTENing on more than one port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Len = (int)strlen(OrigCmdBuffer) - 3;
if (Len < 0)
Len = 0;
memset(&Msg, 0, sizeof(Msg));
Msg.PORT = Port;
Msg.CTL = 3; // UI
// see if a Via specified
if (_memicmp(ptr1, "via ", 4) == 0)
{
ptr2 = strtok_s(ptr1 + 4, ",", &Context);
while (ptr2)
{
if (ConvToAX25(ptr2, axptr) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid via string\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
axptr += 7;
if (axptr == &Msg.DIGIS[7][0])
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Too many digis\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
ptr1 = ptr2;
ptr2 = strtok_s(NULL, ",", &Context);
}
// ptr1 is start of last digi call. We need to position to data
ptr1 = strchr(ptr1, ' ');
if (ptr1 == NULL)
ptr1 = Empty;
else
ptr1++ ; // to message
Len = (int)strlen(ptr1);
}
ConvToAX25("CQ", CQCALL);
memcpy(Msg.DEST, CQCALL, 7);
Msg.DEST[6] |= 0x80; // set Command Bit
memcpy(Msg.ORIGIN, Session->L4USER, 7);
Msg.ORIGIN[6] ^= 0x1e; // Flip SSID
Msg.PID = 0xf0; // Data PID
memcpy(&Msg.L2DATA, ptr1, Len);
Send_AX_Datagram(&Msg, Len + 2, Port); // Len is Payload ie CTL, PID and Data
Bufferptr = Cmdprintf(Session, Bufferptr, "CQ sent\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
TRANSPORTENTRY * SetupNewSession(TRANSPORTENTRY * Session, char * Bufferptr)
{
TRANSPORTENTRY * NewSess = L4TABLE;
int Index = 0;
while (Index < MAXCIRCUITS)
{
if (NewSess->L4USER[0] == 0)
{
// Got One
Session->L4CROSSLINK = NewSess;
NewSess->L4CROSSLINK = Session;
memcpy(NewSess->L4USER, Session->L4USER, 7);
memcpy(NewSess->L4MYCALL, Session->L4MYCALL, 7);
NewSess->CIRCUITINDEX = Index; //OUR INDEX
NewSess->CIRCUITID = NEXTID;
NEXTID++;
if (NEXTID == 0)
NEXTID++; // kEEP nON-ZERO
NewSess->SESSIONT1 = Session->SESSIONT1;
NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW;
return NewSess;
}
Index++;
NewSess++;
}
if (Bufferptr)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry - System Tables Full\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
return NULL;
}
VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest, BOOL Spy)
{
TRANSPORTENTRY * NewSess;
NewSess = SetupNewSession(Session, Bufferptr);
if (NewSess == NULL)
return; // Tables Full
NewSess->L4CIRCUITTYPE = SESSION + DOWNLINK;
NewSess->L4TARGET.DEST = Dest;
NewSess->L4STATE = 2; // CONNECTING
NewSess->SPYFLAG = Spy;
ReleaseBuffer((UINT *)REPLYBUFFER);
SENDL4CONNECT(NewSess);
L4CONNECTSOUT++;
return;
}
BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK)
{
struct _LINKTABLE * LINK = LINKS;
struct _LINKTABLE * FIRSTSPARE = NULL;
int n = MAXLINKS;
while (n--)
{
if (LINK->LINKCALL[0] == 0) // Spare
{
if (FIRSTSPARE == NULL)
FIRSTSPARE = LINK;
LINK++;
continue;
}
if ((LINK->LINKPORT->PORTNUMBER == Port) && CompareCalls(LINK->LINKCALL, LinkCall) && CompareCalls(LINK->OURCALL, OurCall))
{
*REQLINK = LINK;
return TRUE;
}
LINK++;
}
// ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL
*REQLINK = FIRSTSPARE;
return FALSE;
}
VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD);
VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS CONNECT COMMAND
TRANSPORTENTRY * NewSess;
int CONNECTPORT, Port;
BOOL CallEvenIfInNodes = FALSE;
char * ptr, *Context;
UCHAR axcalls[64];
UCHAR ourcall[7]; // Call we are using (may have SSID bits inverted
int ret;
struct PORTCONTROL * PORT = PORTTABLE;
struct _LINKTABLE * LINK;
int CQFLAG = 0; // NOT CQ CALL
BOOL Stay, Spy;
int n;
char TextCall[10];
int TextCallLen;
char PortString[10];
char cmdCopy[256];
struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT;
#ifdef EXCLUDEBITS
if (CheckExcludeList(Session->L4USER) == FALSE)
{
// CONNECTS FROM THIS STATION ARE NOT ALLOWED
ReleaseBuffer((UINT *)REPLYBUFFER);
return;
}
#endif
if (Session->LISTEN)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Can't connect while listening\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
CONNECTPORT = 0; // NO PORT SPECIFIED
ptr = strtok_s(CmdTail, " ", &Context);
strcpy(cmdCopy, Context); // Save in case Telnet Connect
if (ptr == 0)
{
// No param
if (CFLAG) // C Command Disabled ?
{
// Convert to HOST (appl 32) command
//MOV _CMDPTR,OFFSET32 _HOSTCMD
//MOV _ALIASPTR,OFFSET32 _HOSTCMD + 32 * 31
//MOV _APPLMASK, 80000000H ; Internal Term
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Port = atoi(ptr);
if (Port)
{
// IF THERE IS NOTHING FOLLOWING THE NUMBER, ASSUME IT IS A
// NUMERIC ALIAS INSTEAD OF A PORT
sprintf(PortString, "%d", Port);
if (strlen(PortString) < (int)strlen(ptr))
goto NoPort;
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
EXTPORT = (struct _EXTPORTDATA *)PORT;
ptr = strtok_s(NULL, " ", &Context);
if (ptr == 0)
{
// No param
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
CONNECTPORT = Port;
if (strcmp(ptr, "CMS") == 0 || strcmp(ptr, "HOST") == 0) // In case someeone has CMS or HOST as an alias
goto Downlink;
}
NoPort:
ptr[strlen(ptr)] = ' '; // Put param back together
if (ptr[0] == '!')
{
CallEvenIfInNodes = TRUE;
ptr++;
}
if (memcmp(ptr, "RELAY ", 5) == 0 || memcmp(ptr, "SYNC ", 5) == 0)
{
// c p relay with extra parms
goto Downlink;
}
// Skip call validation if using a ptc to allow 1:call, 2:call format
if (Port && PORT->PROTOCOL == 10 && memcmp(EXTPORT->PORT_DLL_NAME, "SCSPACTOR", 9) == 0)
{
char * p;
if (p = strstr(cmdCopy, " S "))
{
Stay = TRUE;
p++;
*p = ' ';
}
if (p = strstr(cmdCopy, " Z "))
{
Spy = TRUE;
p++;
*p = ' ';
}
goto Downlink;
}
else
{
if (DecodeCallString(ptr, &Stay, &Spy, &axcalls[0]) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Call\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
Session->STAYFLAG = Stay;
TextCallLen = ConvFromAX25(axcalls, TextCall);
if (CallEvenIfInNodes)
goto Downlink;
// SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED
if (axcalls[7] == 0)
{
// If this connect is as a result of a command alias, don't check appls or we will loop
if (ALIASINVOKED == 0)
{
APPLCALLS * APPL = APPLCALLTABLE;
int n = NumberofAppls;
APPLMASK = 1;
while (n--)
{
if (memcmp(axcalls, APPL->APPLALIAS, 6) == 0 || CompareCalls(axcalls, APPL->APPLCALL))
{
// Call to an appl
// Convert to an APPL command, so any alias is actioned
// SEE IF THERE IS AN ALIAS DEFINDED FOR THIS COMMAND
if (APPL->APPLHASALIAS && APPL->APPLALIASVAL[0] != 0x20)
{
// COPY ALIAS TO COMMAND _BUFFER, THEN REENTER COMMAND HANDLER
memcpy(COMMANDBUFFER, APPL->APPLALIASVAL, ALIASLEN);
COMMANDBUFFER[80] = 0;
_strupr(COMMANDBUFFER);
memcpy(OrigCmdBuffer, APPL->APPLALIASVAL, ALIASLEN); // In case original case version needed
ALIASINVOKED = TRUE; // To prevent Alias Loops
}
else
{
// Copy Appl Command to Command Buffer. Ensure doesn't contain old command
memset(COMMANDBUFFER, ' ', 72);
memcpy(COMMANDBUFFER, APPL->APPLCMD, 12);
}
DoTheCommand(Session);
return;
}
APPL++;
APPLMASK <<= 1;
}
}
}
if (axcalls[7] == 0)
{
// SEE IF CALL TO ANOTHER NODE
struct DEST_LIST * Dest = DESTS;
int n = MAXDESTS;
if (axcalls[6] == 0x60) // if SSID, dont check aliases
{
while (n--)
{
if (memcmp(Dest->DEST_ALIAS, TextCall, 6) == 0)
{
DoNetromConnect(Session, Bufferptr, Dest, Spy);
return;
}
Dest++;
}
}
Dest = DESTS;
n = MAXDESTS;
while (n--)
{
if (CompareCalls(Dest->DEST_CALL, axcalls))
{
DoNetromConnect(Session, Bufferptr, Dest, Spy);
return;
}
Dest++;
}
}
// Must be Downlink Connect
Downlink:
if (CONNECTPORT == 0 && NUMBEROFPORTS > 1)
{
// L2 NEEDS PORT NUMBER
Bufferptr = Cmdprintf(Session, Bufferptr, "Downlink connect needs port number - C P CALLSIGN\r");
// Send Port List
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// ENSURE PORT IS AVAILABLE FOR L2 USE
if (PORT->PROTOCOL >= 10) // Pactor=-style port?
{
int count;
// if Via PACTOR ARDOP WINMOR or VARA, convert to attach and call = Digi's are in AX25STRING (+7)
if (memcmp(&axcalls[7], &WINMOR[0], 6) == 0 ||
memcmp(&axcalls[7], &ARDOP[0], 6) == 0 ||
memcmp(&axcalls[7], &VARA[0], 6) == 0 ||
memcmp(&axcalls[7], &PACTORCALL[0], 6) == 0)
{
char newcmd[80];
TextCall[TextCallLen] = 0;
sprintf(newcmd, "%s %s", CmdTail, TextCall);
ATTACHCMD(Session, Bufferptr, newcmd, NULL);
return;
}
// If on a KAM or SCS with ax.25 on port 2, do an Attach command, then pass on connect
if (EXTPORT->MAXHOSTMODESESSIONS <= 1)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is not an ax.25 port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// Only Allow Attach VHF from Secure Applications or if PERMITGATEWAY is set
if (EXTPORT->PERMITGATEWAY == 0 && Session->Secure_Session == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, you are not allowed to use this port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
count = EXTPORT->MAXHOSTMODESESSIONS;
count--; // First is Pactor Stream, count is now last ax.25 session
while (count)
{
if (EXTPORT->ATTACHEDSESSIONS[count] == 0)
{
int Paclen, PortPaclen;
struct DATAMESSAGE * Buffer;
struct DATAMESSAGE Message = {0};
char Callstring[80];
int len;
// Found a free one - use it
// See if TNC is OK
Message.PORT = count;
ret = PORT->PORTTXCHECKCODE(PORT, Message.PORT);
if ((ret & 0xff00) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - TNC Not Ready\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// GET CIRCUIT TABLE ENTRY FOR OTHER END OF LINK
NewSess = SetupNewSession(Session, Bufferptr);
if (NewSess == NULL)
return;
// if a UZ7HO port, and the uplink is L2 or Uz7HO invert SSID bits
// We only get here if multisession
if (memcmp(EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0)
goto noFlip;
if ((Session->L4CIRCUITTYPE & BPQHOST))// host
goto noFlip;
if ((Session->L4CIRCUITTYPE & PACTOR))
{
// incoming is Pactorlike - see if UZ7HO
if (memcmp(Session->L4TARGET.EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0)
goto noFlip;
else
NewSess->L4USER[6] ^= 0x1e; // UZ7HO Uplink - flip
}
else
// Must be L2 uplink - flip
NewSess->L4USER[6] ^= 0x1e; // Flip SSID
noFlip:
EXTPORT->ATTACHEDSESSIONS[count] = NewSess;
NewSess->KAMSESSION = count;
// Set paclen to lower of incoming and outgoing
Paclen = Session->SESSPACLEN; // Incoming PACLEN
if (Paclen == 0)
Paclen = 256; // 0 = 256
PortPaclen = PORT->PORTPACLEN;
if (PortPaclen == 0)
PortPaclen = 256; // 0 = 256
if (PortPaclen < Paclen)
Paclen = PortPaclen;
NewSess->SESSPACLEN = Paclen;
Session->SESSPACLEN = Paclen;
NewSess->L4STATE = 5;
NewSess->L4CIRCUITTYPE = DOWNLINK + PACTOR;
NewSess->L4TARGET.PORT = PORT;
// Send the connect command to the TNC
Buffer = REPLYBUFFER;
Buffer->PORT = count;
Buffer->PID = 0xf0;
// if on Telnet Port convert use original cmd tail
// Why just on telnet - what not all ports??
if (memcmp(EXTPORT->PORT_DLL_NAME, "TELNET", 6) == 0 || memcmp(EXTPORT->PORT_DLL_NAME, "SCSPACTOR", 9) == 0)
{
NewSess->Secure_Session = Session->Secure_Session;
len = sprintf(Callstring,"C %s", cmdCopy);
}
else
{
TextCall[TextCallLen] = 0;
len = sprintf(Callstring,"C %s", TextCall);
if (axcalls[7])
{
int digi = 7;
// we have digis
len += sprintf(&Callstring[len], " via");
while (axcalls[digi])
{
TextCall[ConvFromAX25(&axcalls[digi], TextCall)] = 0;
len += sprintf(&Callstring[len], " %s", TextCall);
digi += 7;
}
}
}
Callstring[len++] = 13;
Callstring[len] = 0;
Buffer->LENGTH = len + MSGHDDRLEN + 1;
memcpy(Buffer->L2DATA, Callstring, len);
C_Q_ADD(&PORT->PORTTX_Q, (UINT *)Buffer);
return;
}
count--;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - No free streams on this port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if ((Session->L4CIRCUITTYPE & BPQHOST) == 0 && PORT->PORTL3FLAG)
{
//Port only for L3
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is for internode traffic only\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PortUIONLY)
{
//Port only for UI
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, port is for UI traffic only\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
ret = CheckKissInterlock(PORT, TRUE);
if (ret)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, Interlocked port %d is in use\r", ret);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (Session->L4USER[6] == 0x42 || Session->L4USER[6] == 0x44)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry - Can't make ax.25 calls with SSID of T or R\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// Get Session Entry for Downlink
NewSess = SetupNewSession(Session, Bufferptr);
if (NewSess == NULL)
return;
NewSess->L4CIRCUITTYPE = L2LINK + DOWNLINK;
// FORMAT LINK TABLE ENTRY FOR THIS CONNECTION
memcpy(ourcall, NewSess->L4USER, 7);
// SSID SWAP TEST - LEAVE ALONE FOR HOST or Pactor like (unless UZ7HO)
if ((Session->L4CIRCUITTYPE & BPQHOST))// host
goto noFlip3;
if ((Session->L4CIRCUITTYPE & PACTOR))
{
// incoming is Pactorlike - see if UZ7HO
if (memcmp(Session->L4TARGET.EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0)
goto noFlip3;
if (Session->L4TARGET.EXTPORT->MAXHOSTMODESESSIONS < 2) // Not multisession
goto noFlip3;
ourcall[6] ^= 0x1e; // UZ7HO Uplink - flip
}
else
// Must be L2 uplink - flip
ourcall[6] ^= 0x1e; // Flip SSID
noFlip3:
// SET UP NEW SESSION (OR RESET EXISTING ONE)
FindLink(axcalls, ourcall, Port, &LINK);
if (LINK == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry - System Tables Full\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
// Should release NewSess
return;
}
memcpy(LINK->LINKCALL, axcalls, 7);
memcpy(LINK->OURCALL, ourcall, 7);
LINK->LINKPORT = PORT;
LINK->L2TIME = PORT->PORTT1;
// Copy Digis
n = 7;
ptr = &LINK->DIGIS[0];
while (axcalls[n])
{
memcpy(ptr, &axcalls[n], 7);
n += 7;
ptr += 7;
LINK->L2TIME += 2 * PORT->PORTT1; // ADJUST TIMER VALUE FOR 1 DIGI
}
LINK->LINKTYPE = 2; // DOWNLINK
LINK->LINKWINDOW = PORT->PORTWINDOW;
RESET2(LINK); // RESET ALL FLAGS
if (CMD->String[0] == 'N' && SUPPORT2point2)
LINK->L2STATE = 1; // New (2.2) send XID
else
LINK->L2STATE = 2; // Send SABM
LINK->CIRCUITPOINTER = NewSess;
NewSess->L4TARGET.LINK = LINK;
if (PORT->PORTPACLEN)
NewSess->SESSPACLEN = Session->SESSPACLEN = PORT->PORTPACLEN;
if (CQFLAG == 0) // if a CQ CALL DONT SEND SABM
{
seeifInterlockneeded(PORT);
if (LINK->L2STATE == 1)
L2SENDXID(LINK);
else
SENDSABM(LINK);
}
ReleaseBuffer((UINT *)REPLYBUFFER);
return;
}
BOOL DecodeCallString(char * Calls, BOOL * Stay, BOOL * Spy, UCHAR * AXCalls)
{
// CONVERT CALL + OPTIONAL DIGI STRING TO AX25, RETURN
// CONVERTED STRING IN AXCALLS. Return FALSE if invalied
char * axptr = AXCalls;
char * ptr, *Context;
int CQFLAG = 0; // NOT CQ CALL
int n = 8; // Max digis
*Stay = 0;
*Spy = 0;
memset(AXCalls, 0, 64);
ptr = strtok_s(Calls, " ,", &Context);
if (ptr == NULL)
return FALSE;
// First field is Call
if (ConvToAX25(ptr, axptr) == 0)
return FALSE;
axptr += 7;
ptr = strtok_s(NULL, " ,", &Context);
while (ptr && n--)
{
// NEXT FIELD = COULD BE CALLSIGN, VIA, OR S (FOR STAY)
if (strcmp(ptr, "S") == 0)
*Stay = TRUE;
else if (strcmp(ptr, "Z") == 0)
*Spy = TRUE;
else if (memcmp(ptr, "VIA", (int)strlen(ptr)) == 0)
{
} //skip via
else
{
// Convert next digi
if (ConvToAX25(ptr, axptr) == 0)
return FALSE;
axptr += 7;
}
ptr = strtok_s(NULL, " ,", &Context);
}
return TRUE;
}
VOID LINKCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// PROCESS *** LINKED to CALLSIGN
char * ptr, *Context;
UCHAR axcall[7];
int ret;
if (LINKEDFLAG == 'Y' || // UNCONDITIONAL?
(LINKEDFLAG == 'A' &&
((Session->L4CIRCUITTYPE & BPQHOST) || Session->Secure_Session || Session->PASSWORD == 0xffff)))
{
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
ptr = strtok_s(NULL, " ", &Context);
if (ptr)
{
ret = ConvToAX25Ex(ptr, axcall);
if (ret)
{
memcpy(Session->L4USER, axcall, 7);
strcpy(Bufferptr, OKMSG);
Bufferptr += (int)strlen(OKMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
strcpy(Bufferptr, BADMSG);
Bufferptr += (int)strlen(BADMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
memcpy(Bufferptr, PASSWORDMSG, LPASSMSG);
Bufferptr += LPASSMSG;
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
int CompareNode(const void *a, const void *b);
int CompareAlias(const void *a, const void *b);
char * DoOneNode(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest)
{
char Normcall[10];
char Alias[10];
struct NR_DEST_ROUTE_ENTRY * NRRoute;
struct DEST_ROUTE_ENTRY * Route;
struct ROUTE * Neighbour;
int i, Active, len;
Alias[6] = 0;
memcpy(Alias, Dest->DEST_ALIAS, 6);
strlop(Alias, ' ');
Normcall[ConvFromAX25(Dest->DEST_CALL, Normcall)] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "Routes to: %s:%s", Alias, Normcall);
if (Dest->DEST_COUNT)
Bufferptr = Cmdprintf(Session, Bufferptr, " RTT=%4.2f FR=%d %c %.1d\r",
Dest->DEST_RTT /1000.0, Dest->DEST_COUNT,
(Dest->DEST_STATE & 0x40)? 'B':' ', (Dest->DEST_STATE & 63));
else
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
NRRoute = &Dest->NRROUTE[0];
Active = Dest->DEST_ROUTE;
for (i = 1; i < 4; i++)
{
Neighbour = NRRoute->ROUT_NEIGHBOUR;
if (Neighbour)
{
len = ConvFromAX25(Neighbour->NEIGHBOUR_CALL, Normcall);
Normcall[len] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%c %d %d %d %s\r",
(Active == i)?'>':' ',NRRoute->ROUT_QUALITY, NRRoute->ROUT_OBSCOUNT, Neighbour->NEIGHBOUR_PORT, Normcall);
}
NRRoute++;
}
// DISPLAY INP3 ROUTES
Route = &Dest->ROUTE[0];
Active = Dest->DEST_ROUTE;
for (i = 1; i < 4; i++)
{
Neighbour = Route->ROUT_NEIGHBOUR;
if (Neighbour)
{
double srtt = Route->SRTT/1000.0;
len = ConvFromAX25(Neighbour->NEIGHBOUR_CALL, Normcall);
Normcall[len] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%c %d %4.2fs %d %s\r",
(Active == i + 3)?'>':' ',Route->Hops, srtt, Neighbour->NEIGHBOUR_PORT, Normcall);
}
Route++;
}
return Bufferptr;
}
int DoViaEntry(struct DEST_LIST * Dest, int n, char * line, int cursor)
{
char Portcall[10];
int len;
if (Dest->NRROUTE[n].ROUT_NEIGHBOUR != 0 && Dest->NRROUTE[n].ROUT_NEIGHBOUR->INP3Node == 0)
{
len=ConvFromAX25(Dest->NRROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Portcall);
Portcall[len]=0;
len=sprintf(&line[cursor],"%s %d %d ",
Portcall,
Dest->NRROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_PORT,
Dest->NRROUTE[n].ROUT_QUALITY);
cursor+=len;
if (Dest->NRROUTE[n].ROUT_OBSCOUNT > 127)
{
len=sprintf(&line[cursor],"! ");
cursor+=len;
}
}
return cursor;
}
int DoINP3ViaEntry(struct DEST_LIST * Dest, int n, char * line, int cursor)
{
char Portcall[10];
int len;
double srtt;
if (Dest->ROUTE[n].ROUT_NEIGHBOUR != 0)
{
srtt = Dest->ROUTE[n].SRTT/1000.0;
len=ConvFromAX25(Dest->ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, Portcall);
Portcall[len]=0;
len=sprintf(&line[cursor],"%s %d %d %4.2fs ",
Portcall,
Dest->ROUTE[n].ROUT_NEIGHBOUR->NEIGHBOUR_PORT,
Dest->ROUTE[n].Hops, srtt);
cursor+=len;
if (Dest->NRROUTE[n].ROUT_OBSCOUNT > 127)
{
len=sprintf(&line[cursor],"! ");
cursor+=len;
}
}
return cursor;
}
int WildCmp(char * pattern, char * string)
{
// Check if string is at end or not.
if (*pattern == '\0')
return *string == '\0';
// Check for single character missing or match
if (*pattern == '?' || *pattern == *string)
return *string != '\0' && WildCmp(pattern + 1, string + 1);
if (*pattern == '*')
{
// Check for multiple character missing
return WildCmp(pattern + 1, string) || (*string != '\0' && WildCmp(pattern, string + 1));
}
return 0;
}
VOID CMDN00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
struct DEST_LIST * Dest = DESTS;
int count = MAXDESTS, i;
char Normcall[10];
char Alias[10];
int Width = 4;
int x = 0, n = 0;
struct DEST_LIST * List[1000];
char Param = 0;
char * ptr, * param2,* Context;
char Nodeline[21];
char AXCALL[7];
char * Call;
char * Qualptr;
int Qual;
char line[160];
int cursor, len;
UCHAR axcall[7];
int SavedOBSINIT = OBSINIT;
struct ROUTE * ROUTE = NULL;
char Pattern[80] = "";
char * firststar;
int minqual = 0;
ptr = strtok_s(CmdTail, " ", &Context);
param2 = strtok_s(NULL, " ", &Context);
if (ptr)
{
if (strcmp(ptr, "ADD") == 0)
goto NODE_ADD;
if (strcmp(ptr, "DEL") == 0)
goto NODE_DEL;
if (strcmp(ptr, "VIA") == 0)
goto NODE_VIA;
}
if (ptr)
{
// Could be C or a pattern. Accept C pattern or pattern C
if ((int)strlen(ptr) > 1)
{
strcpy(Pattern, ptr);
if (param2 && param2[0] == 'C')
Param = 'C';
}
else
{
Param = ptr[0];
if (param2)
strcpy(Pattern, param2);
}
}
// Pattern >nnn selects nodes with at least that quality
if (Pattern[0] == '>')
{
minqual = atoi(&Pattern[1]);
Pattern[0] = 0;
}
// We need to pick out CALL or CALL* from other patterns (as call use detail display)
firststar = strchr(Pattern, '*');
if ((firststar && *(firststar + 1) != 0)|| strchr(Pattern, '?')) //(* not on end)
// definitely pattern
goto DoNodePattern;
// If it works as CALL*, process, else drop through
if (Pattern[0])
{
UCHAR AXCall[8];
int count;
int paramlen = (int)strlen(ptr);
char parampadded[20];
int n = 0;
Alias[8] = 0;
strcpy(parampadded, Pattern);
strcat(parampadded, " ");
ConvToAX25(Pattern, AXCall);
// if * on end, list all ssids
if (firststar)
{
AXCall[6] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
while (AXCall[6] < 32)
{
Dest = DESTS;
for (count = 0; count < MAXDESTS; count++)
{
if (memcmp(Dest->DEST_ALIAS, parampadded, 6) == 0 || CompareCalls(Dest->DEST_CALL, AXCall))
{
break;
}
Dest++;
}
if (count < MAXDESTS)
{
Bufferptr = DoOneNode(Session, Bufferptr, Dest);
n++;
}
AXCall[6] += 2;
}
if (n) // Found Some
{
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Dest = DESTS; // Reset
// Drop through to try as pattern
}
else
{
// process as just call
for (count = 0; count < MAXDESTS; count++)
{
if (memcmp(Dest->DEST_ALIAS, parampadded, 6) == 0 || CompareCalls(Dest->DEST_CALL, AXCall))
{
break;
}
Dest++;
}
if (count == MAXDESTS)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not found\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Bufferptr = DoOneNode(Session, Bufferptr, Dest);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
DoNodePattern:
Bufferptr = Cmdprintf(Session, Bufferptr, "Nodes\r");
while (count--)
{
if (Dest->DEST_CALL[0] != 0)
{
if (Dest->NRROUTE->ROUT_QUALITY >= minqual)
if (Param != 'T' || Dest->DEST_COUNT)
List[n++] = Dest;
if (n > 999)
break;
}
Dest++;
}
if (Param == 'C')
qsort(List, n, sizeof(void *), CompareNode);
else
qsort(List, n, sizeof(void *), CompareAlias);
for (i = 0; i < n; i++)
{
int len = ConvFromAX25(List[i]->DEST_CALL, Normcall);
Normcall[len]=0;
memcpy(Alias, List[i]->DEST_ALIAS, 6);
Alias[6] = 0;
strlop(Alias, ' ');
if (strlen(Alias))
strcat(Alias, ":");
if (Alias[0] == '#' && HIDENODES == 1 && Param != '*') // Hidden Node and not N * command
continue;
if (Pattern[0])
if (!WildCmp(Pattern, Normcall) && !WildCmp(Pattern, Alias))
continue;
if (Param == 'T')
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s%s RTT=%4.2f Frames = %d %c %.1d\r",
Alias, Normcall, List[i]->DEST_RTT /1000.0, List[i]->DEST_COUNT,
(List[i]->DEST_STATE & 0x40)? 'B':' ', (List[i]->DEST_STATE & 63));
}
else
{
len = sprintf(Nodeline, "%s%s", Alias, Normcall);
memset(&Nodeline[len], ' ', 20 - len);
Nodeline[20] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", Nodeline);
if (++x == Width)
{
x = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
}
}
}
if (x)
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
goto SendReply;
NODE_VIA:
// List Nodes reachable via a neighbour
ptr = param2;
if (ptr == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Call\r");
goto SendReply;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
ConvToAX25(ptr, AXCALL);
Dest = DESTS;
Dest-=1;
for (count=0; count<MAXDESTS; count++)
{
Dest+=1;
if (Dest->NRROUTE[0].ROUT_NEIGHBOUR == 0 && Dest->ROUTE[0].ROUT_NEIGHBOUR == 0)
continue;
if ((Dest->NRROUTE[0].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->NRROUTE[1].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->NRROUTE[2].ROUT_NEIGHBOUR && CompareCalls(Dest->NRROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->ROUTE[0].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[0].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->ROUTE[1].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[1].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL))
|| (Dest->ROUTE[2].ROUT_NEIGHBOUR && CompareCalls(Dest->ROUTE[2].ROUT_NEIGHBOUR->NEIGHBOUR_CALL, AXCALL)))
{
len=ConvFromAX25(Dest->DEST_CALL,Normcall);
Normcall[len]=0;
memcpy(Alias,Dest->DEST_ALIAS,6);
Alias[6]=0;
for (i=0;i<6;i++)
{
if (Alias[i] == ' ')
Alias[i] = 0;
}
cursor=sprintf(line,"%s:%s ", Alias,Normcall);
cursor = DoViaEntry(Dest, 0, line, cursor);
cursor = DoViaEntry(Dest, 1, line, cursor);
cursor = DoViaEntry(Dest, 2, line, cursor);
cursor = DoINP3ViaEntry(Dest, 0, line, cursor);
cursor = DoINP3ViaEntry(Dest, 1, line, cursor);
cursor = DoINP3ViaEntry(Dest, 2, line, cursor);
line[cursor++]='\r';
line[cursor++]=0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", line);
}
}
goto SendReply;
NODE_ADD:
// FORMAT IS NODE ADD ALIAS:CALL QUAL ROUTE PORT
if (Session->PASSWORD != 0xFFFF)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG);
goto SendReply;
}
ptr = param2;
if (ptr == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Alias:Call\r");
goto SendReply;
}
Call = strlop(ptr, ':');
if (Call == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Alias:Call\r");
goto SendReply;
}
ConvToAX25(Call, AXCALL);
Qualptr = strtok_s(NULL, " ", &Context);
if (Qualptr == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Quality missing\r");
goto SendReply;
}
Qual = atoi(Qualptr);
if (Qual < MINQUAL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Quality is below MINQUAL\r");
goto SendReply;
}
if (FindDestination(AXCALL, &Dest))
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Node already in Table\r");
goto SendReply;
}
if (Dest == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Node Table Full\r");
goto SendReply;
}
memcpy(Dest->DEST_CALL, AXCALL, 7);
memcpy(Dest->DEST_ALIAS, ptr, 6);
NUMBEROFNODES++;
ptr = strtok_s(NULL, " ", &Context);
if (ptr == NULL || ptr[0] == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Neighbour missing\r");
goto SendReply;
}
if (ConvToAX25(ptr, axcall) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Neighbour\r");
goto SendReply;
}
else
{
int Port;
ptr = strtok_s(NULL, " ", &Context);
if (ptr == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Port missing\r");
goto SendReply;
}
Port = atoi(ptr);
if (Context[0] == '!')
{
OBSINIT = 255; //; SPECIAL FOR LOCKED
}
if (FindNeighbour(axcall, Port, &ROUTE))
{
PROCROUTES(Dest, ROUTE, Qual);
}
OBSINIT = SavedOBSINIT;
Bufferptr = Cmdprintf(Session, Bufferptr, "Node Added\r");
goto SendReply;
}
/*
PNODE48:
; GET NEIGHBOURS FOR THIS DESTINATION
;
CALL CONVTOAX25
JNZ SHORT BADROUTE
;
CALL GETVALUE
MOV SAVEPORT,AL ; SET PORT FOR _FINDNEIGHBOUR
CALL GETVALUE
MOV ROUTEQUAL,AL
;
MOV ESI,OFFSET32 AX25CALL
PUSH EBX ; SAVE DEST
CALL _FINDNEIGHBOUR
MOV EAX,EBX ; ROUTE TO AX
POP EBX
JZ SHORT NOTBADROUTE
JMP SHORT BADROUTE
NOTBADROUTE:
;
; UPDATE ROUTE LIST FOR THIS DEST
;
MOV ROUT1_NEIGHBOUR[EBX],EAX
MOV AL,ROUTEQUAL
MOV ROUT1_QUALITY[EBX],AL
MOV ROUT1_OBSCOUNT[EBX],255 ; LOCKED
;
POP EDI
POP EBX
INC _NUMBEROFNODES
JMP SENDOK
BADROUTE:
;
; KILL IT
;
MOV ECX,TYPE DEST_LIST
MOV EDI,EBX
MOV AL,0
REP STOSB
JMP BADROUTECMD
*/
goto SendReply;
NODE_DEL:
if (Session->PASSWORD != 0xFFFF)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG);
goto SendReply;
}
ptr = param2;
if (ptr == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Missing Call\r");
goto SendReply;
}
if (strcmp(ptr, "ALL") == 0)
{
struct DEST_LIST * DEST = DESTS;
int n = MAXDESTS;
while (n--)
{
if (DEST->DEST_CALL[0] && ((DEST->DEST_STATE & 0x80) == 0)) // Don't delete appl node
REMOVENODE(DEST);
DEST++;
}
ClearNodes();
Bufferptr = Cmdprintf(Session, Bufferptr, "All Nodes Deleted\r");
goto SendReply;
}
ConvToAX25(ptr, AXCALL);
if (FindDestination(AXCALL, &Dest) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not Found\r");
goto SendReply;
}
if (Dest->DEST_STATE & 0x80)
Bufferptr = Cmdprintf(Session, Bufferptr, "APPL Node - Can't delete\r");
else
{
REMOVENODE(Dest);
Bufferptr = Cmdprintf(Session, Bufferptr, "Node Deleted\r");
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Node Deleted\r");
SendReply:
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID CMDQUERY(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD)
{
// DISPLAY AVAILABLE COMMANDS
int n;
char * ptr;
char ApplList[2048];
char * out = ApplList;
struct CMDX * CMD = &COMMANDS[APPL1];
for (n = 0; n < NumberofAppls; n++)
{
ptr = &CMD->String[0];
if (*(ptr) != '*')
{
while (*ptr != ' ')
{
*(out++) = *(ptr++);
}
*(out++) = ' ';
}
CMD++;
}
*(out) = 0;
n = CMDLISTLEN;
if (NEEDMH == 0)
n -= 7; // Dont show MH
Bufferptr = Cmdprintf(Session, Bufferptr, "%s%s\r", ApplList, CMDLIST);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
char * FormatMH(MHSTRUC * MH, char Format);
VOID MHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// DISPLAY HEARD LIST
int Port = 0, sess = 0;
char * ptr, *Context, *pattern;
struct PORTCONTROL * PORT = NULL;
MHSTRUC * MH;
int count = MHENTRIES;
int n;
char Normcall[20];
char From[10];
char DigiList[100];
char * Output;
int len;
char Digi = 0;
// Note that the MHDIGIS field may contain rubbish. You have to check End of Address bit to find
// how many digis there are
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr == NULL || ptr[0] == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Number needed eg MH 1\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (ptr)
Port = atoi(ptr);
if (Port)
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
pattern = strtok_s(NULL, " ", &Context);
if (pattern)
_strupr(pattern); // Optional filter
MH = PORT->PORTMHEARD;
if (MH == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "MHEARD not enabled on that port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (pattern && strstr(pattern, "CLEAR"))
{
if (Session->Secure_Session)
{
memset(MH, 0, MHENTRIES * sizeof(MHSTRUC));
SaveMH();
Bufferptr = Cmdprintf(Session, Bufferptr, "Heard List for Port %d Cleared\r", Port);
}
else
{
Bufferptr = Cmdprintf(Session, Bufferptr, "MH Clear needs SYSOP status\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
else
{
if (CMD->String[2] == 'V') // MHV
{
Bufferptr = Cmdprintf(Session, Bufferptr, "MHeard List %s for Port %d\r", MYNODECALL, Port);
Bufferptr = Cmdprintf(Session, Bufferptr, "Callsign Last heard Pkts RX via Digi ;) \r");
Bufferptr = Cmdprintf(Session, Bufferptr, "--------- ----------- ------- ------------------------------------------\r");
}
else
if (pattern)
Bufferptr = Cmdprintf(Session, Bufferptr, "Heard List for Port %d filtered by %s\r", Port, pattern);
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Heard List for Port %d\r", Port);
}
while (count--)
{
if (MH->MHCALL[0] == 0)
break;
Digi = 0;
len = ConvFromAX25(MH->MHCALL, Normcall);
Normcall[len++] = MH->MHDIGI;
Normcall[len++] = 0;
if (pattern && strstr(Normcall, pattern) == 0)
{
MH++;
continue;
}
n = 8; // Max number of digi-peaters
ptr = &MH->MHCALL[6]; // End of Address bit
Output = &DigiList[0];
if ((*ptr & 1) == 0)
{
// at least one digi
strcpy(Output, "via ");
Output += 4;
while ((*ptr & 1) == 0)
{
// MORE TO COME
From[ConvFromAX25(ptr + 1, From)] = 0;
Output += sprintf((char *)Output, "%s", From);
ptr += 7;
n--;
if (n == 0)
break;
// See if digi actioned - put a * on last actioned
if (*ptr & 0x80)
{
if (*ptr & 1) // if last address, must need *
{
*(Output++) = '*';
Digi = '*';
}
else
if ((ptr[7] & 0x80) == 0) // Repeased by next?
{
*(Output++) = '*'; // No, so need *
Digi = '*';
}
}
*(Output++) = ',';
}
*(--Output) = 0; // remove last comma
}
else
*(Output) = 0;
// if we used a digi set * on call and display via string
if (Digi)
Normcall[len++] = Digi;
else
DigiList[0] = 0; // Dont show list if not used
Normcall[len++] = 0;
ptr = FormatMH(MH, CMD->String[2]);
if (CMD->String[2] == 'V') // MHV
Bufferptr = Cmdprintf(Session, Bufferptr, "%-10s %-10s %-10d %-30s\r",
Normcall, ptr, MH->MHCOUNT, DigiList);
else
Bufferptr = Cmdprintf(Session, Bufferptr, "%-10s %s %s\r", Normcall, ptr, DigiList);
MH++;
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
int Rig_Command(TRANSPORTENTRY * Session, char * Command);
VOID RADIOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD)
{
char * ptr;
if (Rig_Command(Session, CmdTail))
{
ReleaseBuffer((UINT *)REPLYBUFFER);
return;
}
// Error Message is in buffer
ptr = strchr(CmdTail, 13);
if (ptr)
{
int len = (int)(++ptr - CmdTail);
memcpy(Bufferptr, CmdTail, len);
Bufferptr += len;
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID SendNRRecordRoute(struct DEST_LIST * DEST, TRANSPORTENTRY * Session);
VOID NRRCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD)
{
// PROCESS 'NRR - Netrom Record Route' COMMAND
char * ptr, *Context;
struct DEST_LIST * Dest = DESTS;
int count = MAXDESTS;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
UCHAR AXCall[8];
int count;
ConvToAX25(ptr, AXCall);
strcat(ptr, " ");
for (count = 0; count < MAXDESTS; count++)
{
if (memcmp(Dest->DEST_ALIAS, ptr, 6) == 0 || CompareCalls(Dest->DEST_CALL, AXCall))
{
SendNRRecordRoute(Dest, Session);
memcpy(Bufferptr, OKMSG, 3);
Bufferptr += 3;
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Dest++;
}
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Not found\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
int CHECKINTERLOCK(struct PORTCONTROL * OURPORT)
{
// See if any Interlocked ports are Busy
struct PORTCONTROL * PORT = PORTTABLE;
struct _EXTPORTDATA * EXTPORT;
int n = NUMBEROFPORTS;
int ourgroup = OURPORT->PORTINTERLOCK;
while (PORT)
{
if (PORT != OURPORT)
{
if (PORT->PORTINTERLOCK == ourgroup)
{
// Same Group - is it busy
int i = 0;
EXTPORT = (struct _EXTPORTDATA *)PORT;
while (i < 27)
if (EXTPORT->ATTACHEDSESSIONS[i++])
return PORT->PORTNUMBER;
}
}
PORT = PORT->PORTPOINTER;
}
return 0;
}
VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD)
{
// ATTACH to a PACTOR or similar port
TRANSPORTENTRY * NewSess;
struct _EXTPORTDATA * EXTPORT;
struct TNCINFO * TNC = 0;
int Port = 0, sess = 0;
char * ptr, *Context;
int ret;
struct PORTCONTROL * PORT = NULL;
struct DATAMESSAGE Message = {0};
int Paclen, PortPaclen;
struct DATAMESSAGE * Buffer;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
Port = atoi(ptr);
if (Port)
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL || PORT->PROTOCOL < 10)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// If attach on telnet port, find a free stream
EXTPORT = (struct _EXTPORTDATA *)PORT;
if (strstr(EXTPORT->PORT_DLL_NAME, "TELNET"))
{
int count = EXTPORT->MAXHOSTMODESESSIONS;
count--; // First is Pactor Stream, count is now last ax.25 session
while (count)
{
if (EXTPORT->ATTACHEDSESSIONS[count] == 0)
{
int Paclen, PortPaclen;
struct DATAMESSAGE Message = {0};
// Found a free one - use it
// See if TNC is OK
Message.PORT = count;
ret = PORT->PORTTXCHECKCODE(PORT, Message.PORT);
if ((ret & 0xff00) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - TNC Not Ready\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// GET CIRCUIT TABLE ENTRY FOR OTHER END OF LINK
NewSess = SetupNewSession(Session, Bufferptr);
if (NewSess == NULL)
return;
EXTPORT->ATTACHEDSESSIONS[count] = NewSess;
NewSess->Secure_Session = Session->Secure_Session;
NewSess->KAMSESSION = count;
// Set paclen to lower of incoming and outgoing
Paclen = Session->SESSPACLEN; // Incoming PACLEN
if (Paclen == 0)
Paclen = 256; // 0 = 256
PortPaclen = PORT->PORTPACLEN;
if (PortPaclen == 0)
PortPaclen = 256; // 0 = 256
if (PortPaclen < Paclen)
Paclen = PortPaclen;
NewSess->SESSPACLEN = Paclen;
Session->SESSPACLEN = Paclen;
NewSess->L4STATE = 5;
NewSess->L4CIRCUITTYPE = DOWNLINK + PACTOR;
NewSess->L4TARGET.PORT = PORT;
ptr = strtok_s(NULL, " ", &Context);
sess = count;
// Replace command tail with original (before conversion to upper case
Context = Context + (OrigCmdBuffer - COMMANDBUFFER);
goto checkattachandcall;
memcpy(Bufferptr, OKMSG, 3);
Bufferptr += 3;
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
count--;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - No free streams on this port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Message.PORT = 0;
ret = PORT->PORTTXCHECKCODE(PORT, Message.PORT);
if ((ret & 0xff00) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - TNC Not Ready\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// See if "Attach and Call" (for VHF ports)
ptr = strtok_s(NULL, " ", &Context);
if (ptr && strcmp(ptr, "S") == 0)
{
Session->STAYFLAG = TRUE;
ptr = strtok_s(NULL, " ", &Context);
}
if (ptr)
{
// we have another param
// if it is a single char it is a channel number for vhf attach
if (strlen(ptr) == 1)
{
// Only Allow Attach VHF from Secure Applications or if PERMITGATEWAY is set
if (EXTPORT->PERMITGATEWAY == 0 && Session->Secure_Session == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, you are not allowed to use this port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
sess = ptr[0] - '@';
if (sess < 1 || sess > EXTPORT->MAXHOSTMODESESSIONS)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Invalid Channel\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
ptr = strtok_s(NULL, " ", &Context);
if (ptr && strcmp(ptr, "S") == 0)
{
Session->STAYFLAG = TRUE;
ptr = strtok_s(NULL, " ", &Context);
}
}
}
if (ret & 0x8000) // Disconnecting
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// Check Interlock. Only ports with a TNC record can be interlocked
TNC = PORT->TNC;
if (TNC)
{
// See if any interlocked ports are in use
struct TNCINFO * OtherTNC;
int i;
int rxInterlock = TNC->RXRadio;
int txInterlock = TNC->TXRadio;
if (rxInterlock || txInterlock)
{
for (i=1; i <= MAXBPQPORTS; i++)
{
OtherTNC = TNCInfo[i];
if (OtherTNC == NULL)
continue;
if (OtherTNC == TNC)
continue;
if (rxInterlock && rxInterlock == OtherTNC->RXRadio || txInterlock && txInterlock == OtherTNC->TXRadio) // Same Group
{
int n;
for (n = 0; n <= 26; n++)
{
if (OtherTNC->PortRecord->ATTACHEDSESSIONS[n])
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, interlocked port %d is in use\r", i);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
}
}
}
}
}
if (EXTPORT->ATTACHEDSESSIONS[sess] || PORT->PortSuspended)
{
// In use
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port in use\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// GET CIRCUIT TABLE ENTRY FOR OTHER END OF LINK
NewSess = SetupNewSession(Session, Bufferptr);
if (NewSess == NULL)
return;
// if a UZ7HO port, and the uplink is L2 or Uz7HO and multisession,
// invert SSID bits
if (memcmp(EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0)
goto noFlip1;
if (EXTPORT->MAXHOSTMODESESSIONS < 2) // Not multisession
goto noFlip1;
if ((Session->L4CIRCUITTYPE & BPQHOST)) // host
goto noFlip1;
if ((Session->L4CIRCUITTYPE & PACTOR))
{
// incoming is Pactorlike - see if UZ7HO
if (memcmp(Session->L4TARGET.EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0)
goto noFlip1;
else
NewSess->L4USER[6] ^= 0x1e; // UZ7HO Uplink - flip
}
else
// Must be L2 uplink - flip
NewSess->L4USER[6] ^= 0x1e; // Flip SSID
noFlip1:
EXTPORT->ATTACHEDSESSIONS[sess] = NewSess;
NewSess->KAMSESSION = sess;
// Set paclen to lower of incoming and outgoing
Paclen = Session->SESSPACLEN; // Incoming PACLEN
if (Paclen == 0)
Paclen = 256; // 0 = 256
PortPaclen = PORT->PORTPACLEN;
if (PortPaclen == 0)
PortPaclen = 256; // 0 = 256
if (PortPaclen < Paclen)
Paclen = PortPaclen;
NewSess->SESSPACLEN = Paclen;
Session->SESSPACLEN = Paclen;
NewSess->L4STATE = 5;
NewSess->L4CIRCUITTYPE = DOWNLINK + PACTOR;
NewSess->L4TARGET.PORT = PORT;
checkattachandcall:
// If set freq on attach is defined, do it
if (TNC && TNC->ActiveRXFreq && TNC->RXRadio)
{
char Msg[128];
sprintf(Msg, "R%d %f", TNC->RXRadio, TNC->ActiveRXFreq);
Rig_Command( (TRANSPORTENTRY *) -1, Msg);
}
if (TNC && TNC->ActiveTXFreq && TNC->TXRadio && TNC->TXRadio != TNC->RXRadio)
{
char Msg[128];
sprintf(Msg, "R%d %f", TNC->TXRadio, TNC->ActiveTXFreq);
Rig_Command( (TRANSPORTENTRY *) -1, Msg);
}
if (ptr)
{
// we have a call to connect to
char Callstring[80];
int len;
Buffer = REPLYBUFFER;
Buffer->PORT = sess;
Buffer->PID = 0xf0;
len = sprintf(Callstring,"C %s", ptr);
ptr = strtok_s(NULL, " ", &Context);
while (ptr) // if any other params (such as digis) copy them
{
if (strcmp(ptr, "S") == 0)
{
Session->STAYFLAG = TRUE;
}
else
len += sprintf(&Callstring[len], " %s", ptr);
ptr = strtok_s(NULL, " ", &Context);
}
Callstring[len++] = 13;
Callstring[len] = 0;
Buffer->LENGTH = len + MSGHDDRLEN + 1;
memcpy(Buffer->L2DATA, Callstring, len);
C_Q_ADD(&PORT->PORTTX_Q, (UINT *)Buffer);
return;
}
memcpy(Bufferptr, OKMSG, 3);
Bufferptr += 3;
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// SYSOP COMMANDS
struct CMDX COMMANDS[] =
{
// "SAVENODES ",8, SAVENODES(struct _TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD), 0,
"SAVENODES ",8, &SAVENODES, 0,
"TELRECONFIG ",4, &RECONFIGTELNET, 0,
"SAVEMH ",6, &SAVEMHCMD, 0,
"REBOOT ",6, &REBOOT, 0,
"RIGRECONFIG ",8, &RIGRECONFIG, 0,
"RESTART ",7, &RESTART,0,
"RESTARTTNC ",10,&RESTARTTNC,0,
"SENDNODES ",8, &SENDNODES,0,
"EXTRESTART ",10, EXTPORTVAL, offsetof(EXTPORTDATA, EXTRESTART),
"TXDELAY ",3, PORTVAL, offsetof(PORTCONTROLX, PORTTXDELAY),
"MAXFRAME ",3, PORTVAL, offsetof(PORTCONTROLX, PORTWINDOW),
"RETRIES ",3, PORTVAL, offsetof(PORTCONTROLX, PORTN2),
"FRACK ",3,PORTVAL, offsetof(PORTCONTROLX, PORTT1),
"RESPTIME ",3,PORTVAL, offsetof(PORTCONTROLX, PORTT2),
"PPACLEN ",3,PORTVAL, offsetof(PORTCONTROLX, PORTPACLEN),
"QUALITY ",3,PORTVAL, offsetof(PORTCONTROLX, PORTQUALITY),
"PERSIST ",2,PORTVAL, offsetof(PORTCONTROLX, PORTPERSISTANCE),
"TXTAIL ",3,PORTVAL, offsetof(PORTCONTROLX, PORTTAILTIME),
"XMITOFF ",7,PORTVAL, offsetof(PORTCONTROLX, PORTDISABLED),
"DIGIFLAG ",5,PORTVAL, offsetof(PORTCONTROLX, DIGIFLAG),
"DIGIPORT ",5,PORTVAL, offsetof(PORTCONTROLX, DIGIPORT),
"MAXUSERS ",4,PORTVAL, offsetof(PORTCONTROLX, USERS),
"L3ONLY ",6,PORTVAL, offsetof(PORTCONTROLX, PORTL3FLAG),
"BBSALIAS ",4,PORTVAL, offsetof(PORTCONTROLX, PORTBBSFLAG),
"VALIDCALLS ",5,VALNODES,0,
"WL2KSYSOP ",5,WL2KSYSOP,0,
"STOPPORT ",4,STOPPORT,0,
"STARTPORT ",5,STARTPORT,0,
"STOPCMS ",7,STOPCMS,0,
"STARTCMS ",8,STARTCMS,0,
"FINDBUFFS ",4,FINDBUFFS,0,
"KISS ",4,KISSCMD,0,
"GETPORTCTEXT",9,GetPortCTEXT, 0,
#ifdef EXCLUDEBITS
"EXCLUDE ",4,ListExcludedCalls,0,
#endif
"FULLDUP ",4,PORTVAL, offsetof(PORTCONTROLX, FULLDUPLEX),
"SOFTDCD ",4,PORTVAL, offsetof(PORTCONTROLX, SOFTDCDFLAG),
"OBSINIT ",7,SWITCHVAL,(size_t)&OBSINIT,
"OBSMIN ",6,SWITCHVAL,(size_t)&OBSMIN,
"NODESINT ",8,SWITCHVAL,(size_t)&L3INTERVAL,
"L3TTL ",5,SWITCHVAL,(size_t)&L3LIVES,
"L4RETRIES ",5,SWITCHVAL,(size_t)&L4N2,
"L4TIMEOUT ",5,SWITCHVALW,(size_t)&L4T1,
"T3 ",2,SWITCHVALW,(size_t)&T3,
"NODEIDLETIME",8,SWITCHVALW,(size_t)&L4LIMIT,
"LINKEDFLAG ",10,SWITCHVAL,(size_t)&LINKEDFLAG,
"IDINTERVAL ",5,SWITCHVAL,(size_t)&IDINTERVAL,
"MINQUAL ",7,SWITCHVAL,(size_t)&MINQUAL,
"FULLCTEXT ",6,SWITCHVAL,(size_t)&FULL_CTEXT,
"HIDENODES ",8,SWITCHVAL,(size_t)&HIDENODES,
"L4DELAY ",7,SWITCHVAL,(size_t)&L4DELAY,
"L4WINDOW ",6,SWITCHVAL,(size_t)&L4DEFAULTWINDOW,
"BTINTERVAL ",5,SWITCHVAL,(size_t)&BTINTERVAL,
"PASSWORD ", 8, PWDCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0, // Apppl 32 is internal Terminal
"*** LINKED ",10,LINKCMD,0,
"CQ ",2,CQCMD,0,
"CONNECT ",1,CMDC00,0,
"NC ",2,CMDC00,0,
"BYE ",1,BYECMD,0,
"QUIT ",1,BYECMD,0,
"INFO ",1,CMDI00,0,
"HELP ",1,HELPCMD,0,
"VERSION ",1,CMDV00,0,
"NODES ",1,CMDN00,0,
"LINKS ",1,CMDL00,0,
"LISTEN ",3,LISTENCMD,0,
"L4T1 ",2,CMDT00,0,
"PORTS ",1,CMDP00,0,
"PACLEN ",3,CMDPAC,0,
"IDLETIME ",4,CMDIDLE,0,
"ROUTES ",1,CMDR00,0,
"STATS ",1,CMDSTATS,0,
"USERS ",1,CMDS00,0,
"UNPROTO ",2,UNPROTOCMD,0,
"? ",1,CMDQUERY,0,
"DUMP ",4,DUMPCMD,0,
"MHU ",3,MHCMD,0, // UTC Times
"MHL ",3,MHCMD,0, // Local Times
"MHV ",3,MHCMD,0,
"MHEARD ",1,MHCMD,0,
"APRS ",2,APRSCMD,0,
"ATTACH ",1,ATTACHCMD,0,
"RADIO ",3,RADIOCMD,0,
"AXRESOLVER ",3,AXRESOLVER,0,
"AXMHEARD ",3,AXMHEARD,0,
"TELSTATUS ",3,SHOWTELNET,0,
"NRR ",1,NRRCMD,0,
"PING ",2,PING,0,
"AGWSTATUS ",3,SHOWAGW,0,
"ARP ",3,SHOWARP,0,
"NAT ",3,SHOWNAT,0,
"IPROUTE ",3,SHOWIPROUTE,0,
"UZ7HO ",5,UZ7HOCMD,0,
"QTSM ",4,QTSMCMD,0,
"..FLMSG ",7,FLMSG,0
};
struct CMDX * CMD = NULL;
int NUMBEROFCOMMANDS = sizeof(COMMANDS)/sizeof(struct CMDX);
char * ReplyPointer; // Pointer into reply buffer
int DecodeNodeName(char * NodeName, char * ptr)
{
// NodeName is TABLE ENTRY WITH AX25 CALL AND ALIAS
// Copyies 20 byte 20 DECODED NAME IN FORM ALIAS:CALL to ptr
// Returns significant length of string
int len;
char Normcall[10];
char * alias = &NodeName[7];
int n = 6;
char * start = ptr;
memset(ptr, ' ', 20);
len = ConvFromAX25(NodeName, Normcall);
if (*(alias) > ' ') // Does alias start with a null or a space ?
{
while (*(alias) > ' ' && n--)
{
*ptr++ = *alias++;
}
*ptr++ = ':';
}
memcpy(ptr, Normcall, len);
ptr += len;
return (int)(ptr - start);
}
char * SetupNodeHeader(struct DATAMESSAGE * Buffer)
{
char Header[20];
int len;
char * ptr = &Buffer->L2DATA[0];
len = DecodeNodeName(MYCALLWITHALIAS, Header);
memcpy (ptr, Header, len);
ptr += len;
(*ptr++) = HEADERCHAR;
(*ptr++) = ' ';
return ptr;
}
VOID SendCommandReply(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer, int Len)
{
if (Len == (4 + sizeof(void *))) // Null Packet
{
ReleaseBuffer((UINT *)Buffer);
return;
}
Buffer->LENGTH = Len;
C_Q_ADD(&Session->L4TX_Q, (UINT *)Buffer);
PostDataAvailable(Session);
}
VOID CommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer)
{
// ignore frames with single NULL (Keepalive)
if (Buffer->LENGTH == sizeof(void *) + 5 && Buffer->L2DATA[0] == 0)
{
ReleaseBuffer(Buffer);
return;
}
if (Buffer->LENGTH > 100)
{
// Debugprintf("BPQ32 command too long %s", Buffer->L2DATA);
ReleaseBuffer(Buffer);
return;
}
InnerLoop:
InnerCommandHandler(Session, Buffer);
// See if any more commands in buffer
if (Session->PARTCMDBUFFER)
{
char * ptr1, * ptr2;
int len;
Buffer = Session->PARTCMDBUFFER;
// Check that message has a CR, if not save buffer and exit
len = Buffer->LENGTH - (4 + sizeof(void *));
ptr1 = &Buffer->L2DATA[0];
ptr2 = memchr(ptr1, 13, len);
if (ptr2 == NULL)
return;
Session->PARTCMDBUFFER = NULL;
goto InnerLoop;
}
}
VOID InnerCommandHandler(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer)
{
char * ptr1, * ptr2, *ptr3;
int len, oldlen, newlen, rest, n;
struct DATAMESSAGE * OldBuffer;
struct DATAMESSAGE * SaveBuffer;
char c;
// If a partial command is stored, append this data to it.
if (Session->PARTCMDBUFFER)
{
len = Buffer->LENGTH - (sizeof(void *) + 4);
ptr1 = &Buffer->L2DATA[0];
OldBuffer = Session->PARTCMDBUFFER; // Old Data
if (OldBuffer == Buffer)
{
// something has gone horribly wrong
Session->PARTCMDBUFFER = NULL;
return;
}
oldlen = OldBuffer->LENGTH;
newlen = len + oldlen;
if (newlen > 200)
{
// Command far too long - ignore previous
OldBuffer->LENGTH = oldlen = sizeof(void *) + 4;
}
OldBuffer->LENGTH += len;
memcpy(&OldBuffer->L2DATA[oldlen - (sizeof(void *) + 4)], Buffer->L2DATA, len);
ReleaseBuffer((UINT *)Buffer);
Buffer = OldBuffer;
Session->PARTCMDBUFFER = NULL;
}
// Check that message has a CR, if not save buffer and exit
len = Buffer->LENGTH - (sizeof(void *) + 4);
ptr1 = &Buffer->L2DATA[0];
// Check for sending YAPP to Node
if (len == 2 && ptr1[0] == 5 && ptr1[1] == 1)
{
ptr1[0] = 0x15; // NAK
ptr1[1] = sprintf(&ptr1[2], "Node doesn't support YAPP Transfers");
Buffer->LENGTH += ptr1[1];
C_Q_ADD(&Session->L4TX_Q, (UINT *)Buffer);
PostDataAvailable(Session);
return;
}
ptr2 = memchr(ptr1, ';', len);
if (ptr2 == 0)
{
ptr2 = memchr(ptr1, 13, len);
if (ptr2 == 0)
{
// No newline
Session->PARTCMDBUFFER = Buffer;
return;
}
}
ptr2++;
rest = len - (int)(ptr2 - ptr1);
if (rest)
{
// there are chars beyond the cr in the buffer
// see if LF after CR
if ((*ptr2) == 10) // LF
{
ptr2++;
rest--;
}
if (rest) // May only have had LF
{
// Get a new buffer, and copy extra data to it.
SaveBuffer = (struct DATAMESSAGE *)GetBuff();
if (SaveBuffer) //`Just ignore if no buffers
{
SaveBuffer->LENGTH = rest + MSGHDDRLEN + 1;
SaveBuffer->PID = 0xf0;
memcpy(&SaveBuffer->L2DATA[0], ptr2, rest);
Session->PARTCMDBUFFER = SaveBuffer;
}
}
}
// GET PACLEN FOR THIS CONNECTION
CMDPACLEN = Session->SESSPACLEN;
if (CMDPACLEN == 0)
CMDPACLEN = PACLEN; // Use default if no Session PACLEN
// If sesion is in UNPROTO Mode, send message as a UI message
if (Session->UNPROTO)
{
// char LongMsg[512] =
// "VeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessage"
// "VeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessageVeryLongMessage";
DIGIMESSAGE Msg;
int Port = Session->UNPROTO;
int Len = Buffer->LENGTH - (MSGHDDRLEN -1); // Need PID
// First check for UNPROTO exit - ctrl/z or /ex
if (Buffer->L2DATA[0] == 26 || (Len == 6 && _memicmp(&Buffer->L2DATA[0], "/ex", 3) == 0)) // CTRL/Z or /ex
{
REPLYBUFFER = Buffer;
Session->UNPROTO = 0;
memset(Session->UADDRESS, 0, 64);
// SET UP HEADER
Buffer->PID = 0xf0;
ptr1 = SetupNodeHeader(Buffer);
memcpy(ptr1, OKMSG, 3);
ptr1 += 3;
SendCommandReply(Session, Buffer, (int)(ptr1 - (char *)Buffer));
return;
}
memset(&Msg, 0, sizeof(Msg));
Msg.PORT = Port;
Msg.CTL = 3; // UI
memcpy(Msg.DEST, Session->UADDRESS, 7);
Msg.DEST[6] |= 0x80; // set Command Bit
memcpy(Msg.ORIGIN, Session->L4USER, 7);
memcpy(Msg.DIGIS, &Session->UADDRESS[7], Session->UAddrLen - 7);
memcpy(&Msg.PID, &Buffer->PID, Len);
Send_AX_Datagram(&Msg, Len, Port); // Len is Payload - CTL, PID and Data
// memcpy(&Msg.PID + 1, LongMsg, 260);
// Send_AX_Datagram(&Msg, 241, Port); // Len is Payload - CTL, PID and Data
// SendUIModeFrame(Session, (PMESSAGE)Buffer, Session->UNPROTO);
ReleaseBuffer((UINT *)Buffer); // Not using buffer for reply
// Assume we don't allow multiple lines in buffer with UI
if (Session->PARTCMDBUFFER)
{
Buffer = Session->PARTCMDBUFFER;
ReleaseBuffer((UINT *)Buffer); // Not using buffer for reply
Session->PARTCMDBUFFER = NULL;
}
return;
}
memset(COMMANDBUFFER, 32, 80); // Clear to spaces
ptr1 = &Buffer->L2DATA[0];
ptr2 = &COMMANDBUFFER[0];
ptr3 = &OrigCmdBuffer[0];
memset(OrigCmdBuffer, 0, 80);
n = 80;
while (n--)
{
c = *(ptr1++) & 0x7f; // Mask paritu
if (c == 13 || c == ';')
break; // CR
*(ptr3++) = c; // Original Case
c = toupper(c);
*(ptr2++) = c;
}
// USE INPUT MESSAGE _BUFFER FOR REPLY
REPLYBUFFER = Buffer;
// SET UP HEADER
Buffer->PID = 0xf0;
ptr1 = SetupNodeHeader(Buffer);
ReplyPointer = ptr1;
ALIASINVOKED = 0; // Clear "Invoked by APPL ALIAS flag"
DoTheCommand(Session); // We also call DotheCommand when we need to reprocess - eg for alias handling
}
VOID DoTheCommand(TRANSPORTENTRY * Session)
{
struct DATAMESSAGE * Buffer = REPLYBUFFER;
char * ptr1, * ptr2;
int n;
ptr1 = &COMMANDBUFFER[0]; //
n = 10;
while ((*ptr1 == ' ' || *ptr1 == 0) && n--)
ptr1++; // STRIP LEADING SPACES and nulls (from keepalive)
if (n == -1)
{
// Null command
ReleaseBuffer((UINT *)Buffer);
return;
}
ptr2 = ptr1; // Save
CMD = &COMMANDS[0];
n = 0;
for (n = 0; n < NUMBEROFCOMMANDS; n++)
{
int CL = CMD->CMDLEN;
ptr1 = ptr2;
CMDPTR = CMD;
if (n == APPL1) // First APPL command
{
APPLMASK = 1; // FOR APPLICATION ATTACH REQUESTS
ALIASPTR = &CMDALIAS[0][0];
}
// ptr1 is input command
if (memcmp(CMD->String, ptr1, CL) == 0)
{
// Found match so far - check rest
char * ptr2 = &CMD->String[CL];
ptr1 += CL;
if (*(ptr1) != ' ')
{
while(*(ptr1) == *ptr2 && *(ptr1) != ' ')
{
ptr1++;
ptr2++;
}
}
if (*(ptr1) == ' ')
{
Session->BADCOMMANDS = 0; // RESET ERROR COUNT
// SEE IF SYSOP COMMAND, AND IF SO IF PASSWORD HAS BEEN ENTERED
if (n < PASSCMD)
{
//NEEDS PASSWORD FOR SYSOP COMMANDS
if (Session->PASSWORD != 0xFFFF)
{
ptr1 = ReplyPointer;
memcpy(ptr1, PASSWORDMSG, LPASSMSG);
ptr1 += LPASSMSG;
SendCommandReply(Session, Buffer, (int)(ptr1 - (char *)Buffer));
return;
}
}
// VALNODESFLAG = 0; // NOT VALID NODES COMMAND
ptr1++; // Skip space
CMD->CMDPROC(Session, ReplyPointer, ptr1, CMD);
return;
}
}
APPLMASK <<= 1;
ALIASPTR += ALIASLEN;
CMD++;
}
Session->BADCOMMANDS++;
if (Session->BADCOMMANDS > 6) // TOO MANY ERRORS
{
ReleaseBuffer((UINT *)Buffer);
Session->STAYFLAG = 0;
CLOSECURRENTSESSION(Session);
return;
}
ptr1 = ReplyPointer;
memcpy(ptr1, CMDERRMSG, CMDERRLEN);
ptr1 += CMDERRLEN;
SendCommandReply(Session, Buffer, (int)(ptr1 - (char *)Buffer));
}
VOID StatsTimer()
{
struct PORTCONTROL * PORT = PORTTABLE;
uint64_t sum, sum2;
// Interval is 60 secs
while(PORT)
{
int index = PORT->StatsPointer++;
if (index == 1439)
PORT->StatsPointer = 0; // Cyclic through 24 hours (1440 Mins)
if (PORT->TNC)
{
struct TNCINFO * TNC = PORT->TNC;
if (TNC->Hardware == H_ARDOP || TNC->Hardware == H_VARA)
{
sum = TNC->PTTActivemS / 600; // ms but want %
PORT->AVSENDING = (UCHAR)sum;
TNC->PTTActivemS = 0;
sum2 = TNC->BusyActivemS / 600; // ms but want %
PORT->AVACTIVE = (UCHAR)(sum + sum2);
TNC->BusyActivemS = 0;
}
}
else
{
// if KISS port using QtSM Average is already updated
struct KISSINFO * KISS = (struct KISSINFO *)PORT;
if (PORT->PORTNUMBER == 17)
{
int x = 17;
}
if ((void *)PORT->PORTTXROUTINE == (void *)KISSTX && (KISS->QtSMStats || KISS->FIRSTPORT->PORT.QtSMPort)) // KISS Port QtSM Stats
{
}
else
{
sum = PORT->SENDING / 11;
PORT->AVSENDING = (UCHAR)sum;
sum = (PORT->SENDING + PORT->ACTIVE) /11;
PORT->AVACTIVE = (UCHAR)sum;
}
}
if (PORT->TX == NULL && PORT->AVACTIVE)
{
PORT->TX = zalloc(1440); // Keep 1 day history
PORT->BUSY = zalloc(1440);
}
if (PORT->TX)
{
PORT->TX[index] = PORT->AVSENDING;
PORT->BUSY[index] = PORT->AVACTIVE;
}
PORT->SENDING = 0;
PORT->ACTIVE = 0;
PORT = PORT->PORTPOINTER;
}
}
extern struct AXIPPORTINFO * Portlist[];
#define TCPConnected 4
VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// DISPLAY AXIP Resolver info
int Port = 0, index =0;
char * ptr, *Context;
struct PORTCONTROL * PORT = NULL;
struct AXIPPORTINFO * AXPORT;
char Normcall[11];
char Flags[10];
struct arp_table_entry * arp;
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
Port = atoi(ptr);
if (Port)
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
AXPORT = Portlist[Port];
if (AXPORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not an AXIP port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "AXIP Resolver info for Port %d\r", Port);
while (index < AXPORT->arp_table_len)
{
arp = &AXPORT->arp_table[index];
if (arp->ResolveFlag && arp->error != 0)
{
// resolver error - Display Error Code
sprintf(AXPORT->hostaddr, "Error %d", arp->error);
}
else
{
if (arp->IPv6)
Format_Addr((unsigned char *)&arp->destaddr6.sin6_addr, AXPORT->hostaddr, TRUE);
else
Format_Addr((unsigned char *)&arp->destaddr.sin_addr, AXPORT->hostaddr, FALSE);
}
ConvFromAX25(arp->callsign, Normcall);
Flags[0] = 0;
if (arp->BCFlag)
strcat(Flags, "B ");
if (arp->TCPState == TCPConnected)
strcat(Flags, "C ");
if (arp->AutoAdded)
strcat(Flags, "A");
if (arp->port == arp->SourcePort)
Bufferptr = Cmdprintf(Session, Bufferptr,"%.10s = %.64s %d = %-.42s %s\r",
Normcall,
arp->hostname,
arp->port,
AXPORT->hostaddr,
Flags);
else
Bufferptr = Cmdprintf(Session, Bufferptr,"%.10s = %.64s %d<%d = %-.42s %s\r",
Normcall,
arp->hostname,
arp->port,
arp->SourcePort,
AXPORT->hostaddr,
Flags);
index++;
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
// DISPLAY AXIP Mheard info
int Port = 0, index = 0;
char * ptr, *Context;
struct PORTCONTROL * PORT = NULL;
struct AXIPPORTINFO * AXPORT;
int n = MHENTRIES;
char Normcall[11];
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
Port = atoi(ptr);
if (Port)
PORT = GetPortTableEntryFromPortNum(Port);
if (PORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
AXPORT = Portlist[Port];
if (AXPORT == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not an AXIP port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "AXIP Mheard for Port %d\r", Port);
while (index < MaxMHEntries)
{
if (AXPORT->MHTable[index].proto != 0)
{
char Addr[80];
Format_Addr((unsigned char *)&AXPORT->MHTable[index].ipaddr6, Addr, AXPORT->MHTable[index].IPv6);
Normcall[ConvFromAX25(AXPORT->MHTable[index].callsign, Normcall)] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%-10s%-15s %c %-6d %-25s%c\r", Normcall,
Addr,
AXPORT->MHTable[index].proto,
AXPORT->MHTable[index].port,
asctime(gmtime( &AXPORT->MHTable[index].LastHeard )),
(AXPORT->MHTable[index].Keepalive == 0) ? ' ' : 'K');
Bufferptr[-3] = ' '; // Clear CR returned by asctime
}
index++;
}
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
#pragma pack()
extern char WL2KCall[10];
extern char WL2KLoc[7];
BOOL GetWL2KSYSOPInfo(char * Call, char * _REPLYBUFFER);
BOOL UpdateWL2KSYSOPInfo(char * Call, char * SQL);
VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char _REPLYBUFFER[1000] = "";
char LastUpdated[100];
char Name[100] = "";
char Addr1[100] = "";
char Addr2[100] = "";
char City[100] = "";
char State[100] = "";
char Country[100] = "";
char PostCode[100] = "";
char Email[100] = "";
char Website[100] = "";
char Phone[100] = "";
char Data[100] = "";
char LOC[100] = "";
BOOL Exists = TRUE;
time_t LastUpdateSecs = 0;
char * ptr1, * ptr2;
SOCKET sock;
int Len;
char Message[2048];
if (WL2KCall[0] < 33)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Winlink reporting is not configured\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (GetWL2KSYSOPInfo(WL2KCall, _REPLYBUFFER) == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Failed to connect to WL2K Database\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (strstr(_REPLYBUFFER, "\"ErrorMessage\":"))
Exists = FALSE;
GetJSONValue(_REPLYBUFFER, "\"SysopName\":", Name);
GetJSONValue(_REPLYBUFFER, "\"StreetAddress1\":", Addr1);
GetJSONValue(_REPLYBUFFER, "\"StreetAddress2\":", Addr2);
GetJSONValue(_REPLYBUFFER, "\"City\":", City);
GetJSONValue(_REPLYBUFFER, "\"State\":", State);
GetJSONValue(_REPLYBUFFER, "\"Country\":", Country);
GetJSONValue(_REPLYBUFFER, "\"PostalCode\":", PostCode);
GetJSONValue(_REPLYBUFFER, "\"Email\":", Email);
GetJSONValue(_REPLYBUFFER, "\"Website\":", Website);
GetJSONValue(_REPLYBUFFER, "\"Phones\":", Phone);
GetJSONValue(_REPLYBUFFER, "\"Comments\":", Data);
GetJSONValue(_REPLYBUFFER, "\"GridSquare\":", LOC);
GetJSONValue(_REPLYBUFFER, "\"Timestamp\":", LastUpdated);
ptr1 = strchr(LastUpdated, '(');
if (ptr1)
{
ptr2 = strchr(++ptr1, ')');
if (ptr2)
{
*(ptr2 - 3) = 0; // remove millisecs
LastUpdateSecs = atoi(ptr1);
FormatTime3(LastUpdated, LastUpdateSecs);
}
}
if (_memicmp(CmdTail, "SET ", 4) == 0)
{
if (Exists)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Record already exists in WL2K Database\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// Set New Values. Any other params are values to set, separated by |
// ptr1 = strtok_s(&CmdTail[4], ",", &Context);
// if (ptr1 == NULL)
// goto DoReplace;
// strcpy(Name, ptr1);
//DoReplace:
Len = sprintf(Message,
"\"Callsign\":\"%s\","
"\"GridSquare\":\"%s\","
"\"SysopName\":\"%s\","
"\"StreetAddress1\":\"%s\","
"\"StreetAddress2\":\"%s\","
"\"City\":\"%s\","
"\"State\":\"%s\","
"\"Country\":\"%s\","
"\"PostalCode\":\"%s\","
"\"Email\":\"%s\","
"\"Phones\":\"%s\","
"\"Website\":\"%s\","
"\"Comments\":\"%s\",",
WL2KCall, WL2KLoc, Name, Addr1, Addr2, City, State, Country, PostCode, Email, Phone, Website, Data);
Debugprintf("Sending %s", Message);
sock = OpenWL2KHTTPSock();
if (sock)
SendHTTPRequest(sock, "api.winlink.org", 80,
"/sysop/add", Message, Len, NULL);
closesocket(sock);
Bufferptr = Cmdprintf(Session, Bufferptr, "Database Updated\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (Exists)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "\rWL2K SYSOP Info for %s\r", WL2KCall);
Bufferptr = Cmdprintf(Session, Bufferptr, "Grid Square: %s\r", LOC);
Bufferptr = Cmdprintf(Session, Bufferptr, "Name: %s\r", Name);
Bufferptr = Cmdprintf(Session, Bufferptr, "Addr Line 1: %s\r", Addr1);
Bufferptr = Cmdprintf(Session, Bufferptr, "Addr Line 2: %s\r", Addr2);
Bufferptr = Cmdprintf(Session, Bufferptr, "City: %s\r", City);
Bufferptr = Cmdprintf(Session, Bufferptr, "State: %s\r", State);
Bufferptr = Cmdprintf(Session, Bufferptr, "Country: %s\r", Country);
Bufferptr = Cmdprintf(Session, Bufferptr, "PostCode: %s\r", PostCode);
Bufferptr = Cmdprintf(Session, Bufferptr, "Email Address: %s\r", Email);
Bufferptr = Cmdprintf(Session, Bufferptr, "Website: %s\r", Website);
Bufferptr = Cmdprintf(Session, Bufferptr, "Phone: %s\r", Phone);
Bufferptr = Cmdprintf(Session, Bufferptr, "Additional Data: %s\r", Data);
Bufferptr = Cmdprintf(Session, Bufferptr, "Last Updated: %s\r", LastUpdated);
}
else
Bufferptr = Cmdprintf(Session, Bufferptr, "No SYSOP record for %s\r", WL2KCall);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID CloseKISSPort(struct PORTCONTROL * PortVector);
VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char _REPLYBUFFER[1000] = "";
char * ptr, * Context;
int portno;
struct TNCINFO * TNC;
struct TCPINFO * TCP;
struct PORTCONTROL * PORT = PORTTABLE;
int n = NUMBEROFPORTS;
// Get port number
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
portno = atoi (ptr);
if (portno)
{
while (n--)
{
if (PORT->PORTNUMBER == portno)
{
TNC = TNCInfo[portno];
if (!TNC || !TNC->TCPInfo)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not a Telnet Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
TCP = TNC->TCPInfo;
TCP->CMS = 0;
TCP->CMSOK = FALSE;
#ifndef LINBPQ
CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TCP->CMS<<3);
SetWindowText(TCP->hCMSWnd, "CMS Off");
#endif
Bufferptr = Cmdprintf(Session, Bufferptr, "CMS Server Disabled\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
PORT = PORT->PORTPOINTER;
}
}
}
// Bad port
strcpy(Bufferptr, BADPORT);
Bufferptr += (int)strlen(BADPORT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char _REPLYBUFFER[1000] = "";
char * ptr, * Context;
int portno;
struct TNCINFO * TNC;
struct TCPINFO * TCP;
struct PORTCONTROL * PORT = PORTTABLE;
int n = NUMBEROFPORTS;
// Get port number
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
portno = atoi (ptr);
if (portno)
{
while (n--)
{
if (PORT->PORTNUMBER == portno)
{
TNC = TNCInfo[portno];
if (!TNC || !TNC->TCPInfo)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not a Telnet Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
TCP = TNC->TCPInfo;
TCP->CMS = 1;
#ifndef LINBPQ
CheckMenuItem(TCP->hActionMenu, 3, MF_BYPOSITION | TCP->CMS<<3);
#endif
CheckCMS(TNC);
Bufferptr = Cmdprintf(Session, Bufferptr, "CMS Server Enabled\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
PORT = PORT->PORTPOINTER;
}
}
}
// Bad port
strcpy(Bufferptr, BADPORT);
Bufferptr += (int)strlen(BADPORT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char _REPLYBUFFER[1000] = "";
char * ptr, * Context;
int portno;
struct PORTCONTROL * PORT = PORTTABLE;
int n = NUMBEROFPORTS;
// Get port number
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
portno = atoi (ptr);
if (portno)
{
while (n--)
{
if (PORT->PORTNUMBER == portno)
{
struct KISSINFO * KISS;
if (PORT->PORTSTOPCODE)
{
// Port has Close Routine
PORT->PortStopped = TRUE;
if (PORT->PORTSTOPCODE(PORT))
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Closed\r");
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Close Failed\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PORTTYPE != 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not a KISS Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not a serial port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
KISS = (struct KISSINFO *) PORT;
if (KISS->FIRSTPORT != KISS)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not first port of a Multidrop Set\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
CloseKISSPort(PORT);
PORT->PortStopped = TRUE;
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Closed\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
PORT = PORT->PORTPOINTER;
}
}
}
// Bad port
strcpy(Bufferptr, BADPORT);
Bufferptr += (int)strlen(BADPORT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char _REPLYBUFFER[1000] = "";
char * ptr, * Context;
int portno;
struct PORTCONTROL * PORT = PORTTABLE;
int n = NUMBEROFPORTS;
// Get port number
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
portno = atoi (ptr);
if (portno)
{
while (n--)
{
if (PORT->PORTNUMBER == portno)
{
struct KISSINFO * KISS;
if (PORT->PORTSTARTCODE)
{
// Port has Open Routine
PORT->PortStopped = FALSE;
if (PORT->PORTSTARTCODE(PORT))
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Opened\r");
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Open Failed\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PORTTYPE != 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not a KISS Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not a serial port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
KISS = (struct KISSINFO *) PORT;
if (KISS->FIRSTPORT != KISS)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not first port of a Multidrop Set\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (OpenConnection(PORT))
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Opened\r");
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Port Open Failed\r");
PORT->PortStopped = FALSE;
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
PORT = PORT->PORTPOINTER;
}
}
}
// Bad port
strcpy(Bufferptr, BADPORT);
Bufferptr += (int)strlen(BADPORT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
int ASYSEND(struct PORTCONTROL * PortVector, char * buffer, int count);
int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len);
VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char _REPLYBUFFER[1000] = "";
char * ptr, * Context;
int portno = 0;
struct PORTCONTROL * PORT = PORTTABLE;
int n = NUMBEROFPORTS;
UCHAR KissString[128];
UCHAR ENCBUFF[256];
int KissLen = 0;
unsigned char * Kissptr = KissString;
// Send KISS Command to TNC
// Get port number
ptr = strtok_s(CmdTail, " ", &Context);
if (ptr)
{
portno = atoi (ptr);
ptr = strtok_s(NULL, " ", &Context);
while (ptr && ptr[0] && KissLen < 120)
{
*(Kissptr++) = atoi (ptr);
KissLen++;
ptr = strtok_s(NULL, " ", &Context);
}
}
if (portno == 0 || KissLen == 0)
{
strcpy(Bufferptr, BADMSG);
Bufferptr += (int)strlen(BADMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
while (n--)
{
if (PORT->PORTNUMBER == portno)
{
struct KISSINFO * KISS;
if (PORT->PORTTYPE != 0 && PORT->PORTTYPE != 22)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not a KISS Port\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
KISS = (struct KISSINFO *) PORT;
if (KISS->FIRSTPORT != KISS)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Not first port of a Multidrop Set\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
// Send Command
KissLen = KissEncode(KissString, ENCBUFF, KissLen);
PORT = (struct PORTCONTROL *)KISS->FIRSTPORT; // ALL FRAMES GO ON SAME Q
PORT->Session = Session;
PORT->LastKISSCmdTime = time(NULL);
ASYSEND(PORT, ENCBUFF, KissLen);
Bufferptr = Cmdprintf(Session, Bufferptr, "Command Sent\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
PORT = PORT->PORTPOINTER;
}
// Bad port
strcpy(Bufferptr, BADPORT);
Bufferptr += (int)strlen(BADPORT);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
FindLostBuffers();
#ifdef WIN32
Bufferptr = Cmdprintf(Session, Bufferptr, "Lost buffer info dumped to Debugview\r");
#else
Bufferptr = Cmdprintf(Session, Bufferptr, "Lost buffer info dumped to syslog\r");
#endif
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD)
{
// Telnet Connection from FLMSG
CLOSECURRENTSESSION(Session); // Kills any crosslink, plus local link
ReleaseBuffer((UINT *)REPLYBUFFER);
}
BOOL CheckExcludeList(UCHAR * Call)
{
UCHAR * ptr1 = ExcludeList;
while (*ptr1)
{
if (memcmp(Call, ptr1, 6) == 0)
return FALSE;
ptr1 += 7;
}
return TRUE;
}
void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
UCHAR * ptr = ExcludeList;
char Normcall[10] = "";
UCHAR AXCall[8] = "";
if (*CmdTail == ' ')
goto DISPLIST;
if (*CmdTail == 'Z')
{
// CLEAR LIST
memset(ExcludeList, 0, 70);
goto DISPLIST;
}
ConvToAX25(CmdTail, AXCall);
if (strlen(ExcludeList) < 70)
strcat(ExcludeList, AXCall);
DISPLIST:
while (*ptr)
{
Normcall[ConvFromAX25(ptr, Normcall)] = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%s ", Normcall);
ptr += 7;
}
*(Bufferptr++) = '\r';
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
BOOL isSYSOP(TRANSPORTENTRY * Session, char * Bufferptr)
{
if (Session->PASSWORD != 0xFFFF)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", PASSWORDMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return FALSE;
}
return TRUE;
}
VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
int FileSize;
char MsgFile[MAX_PATH];
FILE * hFile;
char * MsgBytes;
struct stat STAT;
char * ptr1, * ptr, * ptr2;
sprintf_s(MsgFile, sizeof(MsgFile), "%s/%s", BPQDirectory, "NodeHelp.txt");
if (stat(MsgFile, &STAT) == -1)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Help file not found\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
FileSize = STAT.st_size;
hFile = fopen(MsgFile, "rb");
if (hFile == NULL)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Help file not found\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
MsgBytes = malloc(FileSize+1);
fread(MsgBytes, 1, FileSize, hFile);
fclose(hFile);
MsgBytes[FileSize] = 0;
ptr1 = MsgBytes;
// Replace LF or CRLF with CR
// First remove cr from crlf
while(ptr2 = strstr(ptr1, "\r\n"))
{
memmove(ptr2, ptr2 + 1, strlen(ptr2));
}
// Now replace lf with cr
ptr1 = MsgBytes;
while (*ptr1)
{
if (*ptr1 == '\n')
*(ptr1) = '\r';
ptr1++;
}
ptr = ptr1 = MsgBytes;
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
// Read and send a line at a time, converting any line endings into CR
while (*ptr1)
{
if (*ptr1 == '\r')
{
*(ptr1++) = 0;
Bufferptr = Cmdprintf(Session, Bufferptr, "%s\r", ptr);
ptr = ptr1;
}
else
ptr1++;
}
free(MsgBytes);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
int UZ7HOSetFreq(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESSAGE buff, PMSGWITHLEN buffptr);
int UZ7HOSetModem(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESSAGE buff, PMSGWITHLEN buffptr);
int UZ7HOSetFlags(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESSAGE buff, PMSGWITHLEN buffptr);
VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char * Cmd;
int port;
struct TNCINFO * TNC;
struct AGWINFO * AGW = 0;
PDATAMESSAGE buff;
PMSGWITHLEN buffptr;
CmdTail = CmdTail + (OrigCmdBuffer - COMMANDBUFFER); // Replace with original case version
Cmd = strlop(CmdTail, ' ');
port = atoi(CmdTail);
// remove trailing spaces
while(strlen(Cmd) && Cmd[strlen(Cmd) - 1] == ' ')
Cmd[strlen(Cmd) - 1] = 0;
TNC = TNCInfo[port];
if (TNC)
AGW = TNC->AGWInfo;
if (TNC == 0 || AGW == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - %d is not UZ7HO port\r", port);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (_memicmp(Cmd, "FREQ", 4) == 0 || _memicmp(Cmd, "MODEM", 5) == 0 || _memicmp(Cmd, "FLAGS", 5) == 0)
{
// Pass to procesing code in UZ7HO driver. This expects command in a PDATAMESSAGE amd places response in a PMSGWITHLEN buffer
buff = (PDATAMESSAGE)GetBuff();
buffptr = (PMSGWITHLEN)GetBuff();
if (buffptr == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "UZ7HO Command Failed - no buffers\r");
if (buff)
ReleaseBuffer(buff);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
buff->LENGTH = sprintf(buff->L2DATA, "%s\r", Cmd) + MSGHDDRLEN + 1;
if (_memicmp(Cmd, "FREQ", 4) == 0)
UZ7HOSetFreq(port, TNC, AGW, buff, buffptr);
else if (_memicmp(Cmd, "FLAGS", 5) == 0)
UZ7HOSetFlags(port, TNC, AGW, buff, buffptr);
else
UZ7HOSetModem(port, TNC, AGW, buff, buffptr);
Bufferptr = Cmdprintf(Session, Bufferptr, buffptr->Data);
ReleaseBuffer(buff);
ReleaseBuffer(buffptr);
}
else
Bufferptr = Cmdprintf(Session, Bufferptr, "Invalid UZ7HO Command (not Freq Modem or FLAGS)\r");
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
int port;
struct PORTCONTROL * PORT;
struct KISSINFO * KISS;
CmdTail = CmdTail + (OrigCmdBuffer - COMMANDBUFFER); // Replace with original case version
port = atoi(CmdTail);
PORT = GetPortTableEntryFromPortNum(port);
if (PORT == NULL || (void *)PORT->PORTTXROUTINE != (void *)KISSTX) // Must be a kiss like port
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port %d is not a KISS port\r", port);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
KISS = (struct KISSINFO *)PORT;
if (KISS->QtSMModem == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port %d has no QtSM information\r", port);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Modem %s Centre frequency %d\r",
(KISS->QtSMModem) ? KISS->QtSMModem : "Not Available", KISS->QtSMFreq);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}