From 93a10a982d3fcab0c469e2805b2034bba4e59a55 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sat, 30 Nov 2024 11:27:28 +0000 Subject: [PATCH] New upstream version 6.0.24.51.3+repack+really50 --- AGWAPI.c | 125 +- APRSCode.c | 3 +- BBSUtilities.c | 80 +- BPQMail.c | 18 +- Bpq32.c | 18 +- CHeaders.h | 1 - Cmd-skigdebian.c | 5989 ------------------------------------------- CommonCode.c | 33 +- L2Code-skigdebian.c | 4143 ------------------------------ L4Code-skigdebian.c | 2416 ----------------- LinBPQ.c | 12 - MailDataDefs.c | 1 - MailTCP.c | 3 +- Versions.h | 6 +- adif.c | 1 + bpqmail.h | 3 - cMain.c | 17 +- config.c | 17 +- datadefs.c | 4 - lzhuf32.c | 3 - mailapi.c | 402 +-- 21 files changed, 89 insertions(+), 13206 deletions(-) delete mode 100644 Cmd-skigdebian.c delete mode 100644 L2Code-skigdebian.c delete mode 100644 L4Code-skigdebian.c diff --git a/AGWAPI.c b/AGWAPI.c index 80c1ce4..0f2d86c 100644 --- a/AGWAPI.c +++ b/AGWAPI.c @@ -1017,7 +1017,6 @@ int AGWDataSocket_Read(struct AGWSocketConnectionInfo * sockptr, SOCKET sock) { int i; int DataLength; - struct AGWHeader * AGW = &sockptr->AGWRXHeader; ioctlsocket(sock,FIONREAD,&DataLength); @@ -1029,83 +1028,18 @@ int AGWDataSocket_Read(struct AGWSocketConnectionInfo * sockptr, SOCKET sock) return 0; } - if (DataLength < 36) // A header - { - // If we don't get a header within a few ms assume a rogue connection and close it - int n = 50; - - while (n--) - { - Sleep(10); - ioctlsocket(sock,FIONREAD,&DataLength); - - if (DataLength >= 36) - break; - } - - if (n < 1) - { - Debugprintf("Corrupt AGW Packet Received"); - AGWDataSocket_Disconnect(sockptr); - return 0; - } - } - - // Have a header - - i=recv(sock,(char *)&sockptr->AGWRXHeader, 36, 0); - - if (i == SOCKET_ERROR) - { - i=WSAGetLastError(); - AGWDataSocket_Disconnect(sockptr); - } - - sockptr->MsgDataLength = sockptr->AGWRXHeader.DataLength; - - // Validate packet to protect against accidental (or malicious!) connects from a non-agw application - - if (AGW->Port > 64 || AGW->filler2 != 0 || AGW->filler3 != 0 || AGW->DataLength > 400) - { - Debugprintf("Corrupt AGW Packet Received"); - AGWDataSocket_Disconnect(sockptr); - return 0; - } - - if (sockptr->MsgDataLength == 0) - ProcessAGWCommand (sockptr); - else - sockptr->GotHeader = TRUE; // Wait for data - - ioctlsocket(sock,FIONREAD,&DataLength); // See if more data - if (sockptr->GotHeader) { // Received a header, without sufficient data bytes if (DataLength < sockptr->MsgDataLength) { - // Fiddle - seem to be problems somtimes with un-Neagled hosts so wait a few ms - // if we don't get a full packet assume a rogue connection and close it + // Fiddle - seem to be problems somtimes with un-Neagled hosts + + Sleep(500); - int n = 50; - - while (n--) - { - Sleep(10); - ioctlsocket(sock,FIONREAD,&DataLength); - - if (DataLength >= sockptr->MsgDataLength) - break; - } - - if (n < 1) - { - Debugprintf("Corrupt AGW Packet Received"); - AGWDataSocket_Disconnect(sockptr); - return 0; - } + ioctlsocket(sock,FIONREAD,&DataLength); } if (DataLength >= sockptr->MsgDataLength) @@ -1118,9 +1052,60 @@ int AGWDataSocket_Read(struct AGWSocketConnectionInfo * sockptr, SOCKET sock) ProcessAGWCommand (sockptr); free(sockptr->MsgData); + sockptr->GotHeader = FALSE; } + + // Not Enough Data - wait + } + else // Not got header + { + if (DataLength > 35)// A header + { + struct AGWHeader * AGW = &sockptr->AGWRXHeader; + + i=recv(sock,(char *)&sockptr->AGWRXHeader, 36, 0); + + if (i == SOCKET_ERROR) + { + i=WSAGetLastError(); + + AGWDataSocket_Disconnect(sockptr); + } + + + sockptr->MsgDataLength = sockptr->AGWRXHeader.DataLength; + + // Validate packet to protect against accidental (or malicious!) connects from a non-agw application + + + if (AGW->Port > 64 || AGW->filler2 != 0 || AGW->filler3 != 0 || AGW->DataLength > 400) + { + Debugprintf("Corrupt AGW Packet Received"); + AGWDataSocket_Disconnect(sockptr); + return 0; + } + + if (sockptr->MsgDataLength > 500) + OutputDebugString("Corrupt AGW message"); + + + if (sockptr->MsgDataLength == 0) + { + ProcessAGWCommand (sockptr); + } + else + { + sockptr->GotHeader = TRUE; // Wait for data + } + + } + + // not got 36 bytes + + } + return 0; } diff --git a/APRSCode.c b/APRSCode.c index b8f02f0..ff1e322 100644 --- a/APRSCode.c +++ b/APRSCode.c @@ -88,7 +88,7 @@ double myDistance(double laa, double loa, BOOL KM); struct STATIONRECORD * FindStation(char * Call, BOOL AddIfNotFound); int DecodeAPRSPayload(char * Payload, struct STATIONRECORD * Station); BOOL KillOldTNC(char * Path); - +int FromLOC(char * Locator, double * pLat, double * pLon); BOOL ToLOC(double Lat, double Lon , char * Locator); BOOL InternalSendAPRSMessage(char * Text, char * Call); void UndoTransparency(char * input); @@ -104,7 +104,6 @@ void ClearSavedMessages(); void GetSavedAPRSMessages(); static VOID GPSDConnect(void * unused); int CanPortDigi(int Port); -int FromLOC(char * Locator, double * pLat, double * pLon); extern int SemHeldByAPI; extern int APRSMONDECODE(); diff --git a/BBSUtilities.c b/BBSUtilities.c index 56e08a0..82344bd 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -5566,19 +5566,14 @@ BOOL CreateMessage(CIRCUIT * conn, char * From, char * ToCall, char * ATBBS, cha { if (_memicmp(ToCall, "rms:", 4) == 0) { - // Could be ampr.org message - - if (!isAMPRMsg(ToCall)) + if (!FindRMS()) { - if (!FindRMS()) - { - nodeprintf(conn, "*** Error - Forwarding via RMS is not configured on this BBS\r"); - return FALSE; - } + nodeprintf(conn, "*** Error - Forwarding via RMS is not configured on this BBS\r"); + return FALSE; } + via=strlop(ToCall, ':'); _strupr(ToCall); - } else if (_memicmp(ToCall, "rms/", 4) == 0) { @@ -6882,7 +6877,7 @@ int CountMessagestoForward (struct UserInfo * user) if ((Msg->status != 'H') && (Msg->status != 'D') && Msg->type && check_fwd_bit(Msg->fbbs, BBSNumber)) { n++; - continue; // So we dont count twice if Flag set and NTS MPS + continue; // So we dont count twice in Flag set and NTS MPS } // if an NTS MPS, also check for any matches @@ -6923,66 +6918,6 @@ int CountMessagestoForward (struct UserInfo * user) return n; } -int CountBytestoForward (struct UserInfo * user) -{ - // See if any messages are queued for this BBS. If so return total bytes queued - - int m, n=0; - struct MsgInfo * Msg; - int BBSNumber = user->BBSNumber; - int FirstMessage = FirstMessageIndextoForward; - - if ((user->flags & F_NTSMPS)) - FirstMessage = 1; - - for (m = FirstMessage; m <= NumberofMessages; m++) - { - Msg=MsgHddrPtr[m]; - - if ((Msg->status != 'H') && (Msg->status != 'D') && Msg->type && check_fwd_bit(Msg->fbbs, BBSNumber)) - { - n += Msg->length; - continue; // So we dont count twice if Flag set and NTS MPS - } - - // if an NTS MPS, also check for any matches - - if (Msg->type == 'T' && (user->flags & F_NTSMPS)) - { - struct BBSForwardingInfo * ForwardingInfo = user->ForwardingInfo; - int depth; - - if (Msg->status == 'N' && ForwardingInfo) - { - depth = CheckBBSToForNTS(Msg, ForwardingInfo); - - if (depth > -1 && Msg->Locked == 0) - { - n += Msg->length; - continue; - } - depth = CheckBBSAtList(Msg, ForwardingInfo, Msg->via); - - if (depth && Msg->Locked == 0) - { - n += Msg->length; - continue; - } - - depth = CheckBBSATListWildCarded(Msg, ForwardingInfo, Msg->via); - - if (depth > -1 && Msg->Locked == 0) - { - n += Msg->length; - continue; - } - } - } - } - - return n; -} - int ListMessagestoForward(CIRCUIT * conn, struct UserInfo * user) { // See if any messages are queued for this BBS @@ -15888,11 +15823,6 @@ void SendMessageReadEvent(char * call, struct MsgInfo * Msg) } } -void SendMessageForwardedToM0LTE(char * call, struct MsgInfo * Msg) -{ -} - - void SendNewMessageEvent(char * call, struct MsgInfo * Msg) { if (reportMailEvents) diff --git a/BPQMail.c b/BPQMail.c index 5d26cd5..08d5818 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1143,8 +1143,6 @@ // Semaphore calls to SaveConfig // Include SERVIC as valid from call (for Winlink Service messages) (49) // Attempt to detect line draw characters in Webmail (50) -// Fix sending ampr.org mail when RMS is not enabled (51) -// Send forwarding info tp packetnodes.spots.radio database (51) #include "bpqmail.h" #include "winstdint.h" @@ -1163,8 +1161,6 @@ FARPROCZ pGetLOC; FARPROCX pRefreshWebMailIndex; FARPROCX pRunEventProgram; FARPROCX pGetPortFrequency; -FARPROCX pSendWebRequest; -FARPROCX pGetLatLon; BOOL WINE = FALSE; @@ -1389,7 +1385,6 @@ char * CheckToAddress(CIRCUIT * conn, char * Addr); BOOL CheckifPacket(char * Via); int GetHTMLForms(); VOID GetPGConfig(); -void SendBBSDataToPktMap(); struct _EXCEPTION_POINTERS exinfox; @@ -1941,8 +1936,6 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) pRefreshWebMailIndex = GetProcAddress(ExtDriver,"_RefreshWebMailIndex@0"); pRunEventProgram = GetProcAddress(ExtDriver,"_RunEventProgram@8"); pGetPortFrequency = GetProcAddress(ExtDriver,"_GetPortFrequency@8"); - pSendWebRequest = GetProcAddress(ExtDriver,"_SendWebRequest@16"); - pGetLatLon = GetProcAddress(ExtDriver,"_GetLatLon@8"); if (pGetLOC) @@ -2190,13 +2183,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) Debugprintf("|Enter HouseKeeping"); DoHouseKeeping(FALSE); } - - if (APIClock < NOW) - { - SendBBSDataToPktMap(); - APIClock = NOW + 7200; // Every 2 hours - } - tm = gmtime(&NOW); if (tm->tm_wday == 0) // Sunday @@ -3071,6 +3057,7 @@ static PSOCKADDR_IN psin; SOCKET sock; + BOOL Initialise() { int i, len; @@ -3396,9 +3383,6 @@ BOOL Initialise() CreatePipeThread(); GetPGConfig(); - - APIClock = 0; - return TRUE; } diff --git a/Bpq32.c b/Bpq32.c index 1125b31..f7e1f59 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1086,7 +1086,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Add ? and * wildcards to NODES command (74) // Add Port RADIO config parameter (74) -// Version 6.0.24.1 August 2023 +// Version 6.0.24.1 August 2024 // Apply NODES command wildcard to alias as well a call (2) // Add STOPPORT/STARTPORT to VARA Driver (2) @@ -1234,7 +1234,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Add optional ATTACH time limit for VARA (48) // API format fixes (48) // AGWAPI Add protection against accidental connects from a non-agw application (50) -// Save MH and NODES every hour (51) #define CKernel @@ -1375,9 +1374,6 @@ extern struct _LINKTABLE * LINKS; extern int LINK_TABLE_LEN; extern int MAXLINKS; -extern double LatFromLOC; -extern double LonFromLOC; - extern int BPQHOSTAPI(); extern int INITIALISEPORTS(); @@ -3072,7 +3068,7 @@ SkipInit: if (AttachedProcesses < 2) { - if (AUTOSAVE) + if (AUTOSAVE == 1) SaveNodes(); if (AUTOSAVEMH) SaveMH(); @@ -6625,19 +6621,11 @@ int GetListeningPortsPID(int Port) return 0; // Not found } -DllExport char * APIENTRY GetLOC() +DllExport char * APIENTRY GetLOC() { return LOC; } -DllExport void APIENTRY GetLatLon(double * lat, double * lon) -{ - *lat = LatFromLOC; - *lon = LonFromLOC; - return; -} - - // UZ7HO Dll PTT interface // 1 ext_PTT_info diff --git a/CHeaders.h b/CHeaders.h index aeef69c..13cb99d 100644 --- a/CHeaders.h +++ b/CHeaders.h @@ -398,7 +398,6 @@ extern int REALTIMETICKS; extern time_t CurrentSecs; extern time_t lastSlowSecs; -extern time_t lastSaveSecs; // SNMP Variables diff --git a/Cmd-skigdebian.c b/Cmd-skigdebian.c deleted file mode 100644 index 88189b1..0000000 --- a/Cmd-skigdebian.c +++ /dev/null @@ -1,5989 +0,0 @@ -/* -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 -//#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, CMDX * CMD); -VOID WriteMiniDump(); -int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive); -int seeifInterlockneeded(struct PORTCONTROL * PORT); - -extern VOID KISSTX(); - -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(); -VOID RESET2(); - -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; - -CMDX COMMANDS[]; - -int CMDXLEN = sizeof (CMDX); - -VOID SENDNODESMSG(); -VOID KISSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STOPCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STARTCMS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STOPPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID STARTPORT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID FINDBUFFS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID WL2KSYSOP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID AXRESOLVER(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID AXMHEARD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWTELNET(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWAGW(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWARP(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWNAT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID PING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID SHOWIPROUTE(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID FLMSG(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); -void ListExcludedCalls(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD); -VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD); -VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, 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, 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, CMDX * CMD) -{ - SaveMH(); - - strcpy(Bufferptr, OKMSG); - Bufferptr += (int)strlen(OKMSG); - - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID SAVENODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, 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, 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, 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, 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, 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, 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, CMDX * CMD); - -VOID VALNODES(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - VALNODESFLAG = 1; - PORTVAL(Session, Bufferptr, CmdTail, CMD); -} - -VOID EXTPORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD) -{ - EXTONLY = 1; - PORTVAL(Session, Bufferptr, CmdTail, CMD); -} -VOID PORTVAL(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, 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, 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, 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, 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, CMDX * CMD) -{ - Bufferptr = Cmdprintf(Session, Bufferptr, "%s", INFOMSG); - SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); -} - -VOID CMDV00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, 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, CMDX * CMD) -{ - CLOSECURRENTSESSION(Session); // Kills any crosslink, plus local link - ReleaseBuffer((UINT *)REPLYBUFFER); - return; -} - -VOID CMDPAC(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, CMDX * UserCMD); - -VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, 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; - char toCall[12], fromCall[12]; - -#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 - - toCall[ConvFromAX25(LINK->LINKCALL, toCall)] = 0; - fromCall[ConvFromAX25(LINK->OURCALL, fromCall)] = 0; - - hookL2SessionAttempt(CONNECTPORT, fromCall, toCall, LINK); - - - 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, 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, 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; countNRROUTE[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, CMDX * UserCMD) -{ - // DISPLAY AVAILABLE COMMANDS - - int n; - char * ptr; - char ApplList[2048]; - char * out = ApplList; - - 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, 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, 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, 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, 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 - -CMDX COMMANDS[] = -{ - "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 -}; - -CMDX * CMD = NULL; - -int NUMBEROFCOMMANDS = sizeof(COMMANDS)/sizeof(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 (PORT->PORTTXROUTINE == 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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 || PORT->PORTTXROUTINE != 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; -} - - - - - - - - - - - - - diff --git a/CommonCode.c b/CommonCode.c index e3504d1..a392b17 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -4912,7 +4912,7 @@ SOCKET OpenHTTPSock(char * Host) { err = WSAGetLastError(); - Debugprintf("Resolve Failed for %s %d %x", Host, err, err); + Debugprintf("Resolve Failed for %s %d %x", "api.winlink.org", err, err); return 0 ; // Resolve failed } @@ -4945,7 +4945,7 @@ SOCKET OpenHTTPSock(char * Host) } static char HeaderTemplate[] = "POST %s HTTP/1.1\r\n" - "Accept: app N B lication/json\r\n" + "Accept: application/json\r\n" // "Accept-Encoding: gzip,deflate,gzip, deflate\r\n" "Content-Type: application/json\r\n" "Host: %s:%d\r\n" @@ -4955,24 +4955,14 @@ static char HeaderTemplate[] = "POST %s HTTP/1.1\r\n" "\r\n"; -DllExport VOID WINAPI SendWebRequest(char * Host, char * Request, char * Params, char * Return) +VOID SendWebRequest(SOCKET sock, char * Host, char * Request, char * Params, int Len, char * Return) { - SOCKET sock; int InputLen = 0; int inptr = 0; char Buffer[4096]; char Header[256]; char * ptr, * ptr1; int Sent; - int Len = strlen(Params); - - if (M0LTEMap == 0) - return; - - sock = OpenHTTPSock(Host); - - if (sock == 0) - return; #ifdef LINBPQ sprintf(Header, HeaderTemplate, Request, Host, 80, Len, "linbpq/", VersionString, Params); @@ -4986,7 +4976,6 @@ DllExport VOID WINAPI SendWebRequest(char * Host, char * Request, char * Params, { int Err = WSAGetLastError(); Debugprintf("Error %d from Web Update send()", Err); - closesocket(sock); return; } @@ -4998,10 +4987,12 @@ DllExport VOID WINAPI SendWebRequest(char * Host, char * Request, char * Params, { int Err = WSAGetLastError(); Debugprintf("Error %d from Web Update recv()", Err); - closesocket(sock); return; } + // As we are using a persistant connection, can't look for close. Check + // for complete message + inptr += InputLen; Buffer[inptr] = 0; @@ -5044,7 +5035,6 @@ DllExport VOID WINAPI SendWebRequest(char * Host, char * Request, char * Params, Debugprintf("Map Update failed - %s", Buffer); } - closesocket(sock); return; } } @@ -5056,7 +5046,6 @@ DllExport VOID WINAPI SendWebRequest(char * Host, char * Request, char * Params, { // Just accept anything until I've sorted things with Lee Debugprintf("%s", ptr1); - closesocket(sock); Debugprintf("Web Database update ok"); return; } @@ -5595,11 +5584,19 @@ void SendDataToPktMap(char *Msg) } ], + + */ // "contact": "string", // "neighbours": [{"node": "G7TAJ","port": "30"}] - SendWebRequest("packetnodes.spots.radio", Request, Params, Return); + sock = OpenHTTPSock("packetnodes.spots.radio"); + + if (sock == 0) + return; + + SendWebRequest(sock, "packetnodes.spots.radio", Request, Params, strlen(Params), Return); + closesocket(sock); } // ="{\"neighbours\": [{\"node\": \"G7TAJ\",\"port\": \"30\"}]}"; diff --git a/L2Code-skigdebian.c b/L2Code-skigdebian.c deleted file mode 100644 index a36854d..0000000 --- a/L2Code-skigdebian.c +++ /dev/null @@ -1,4143 +0,0 @@ -/* -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. See 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 L2Code.asm -// -#define Kernel - -#define _CRT_SECURE_NO_DEPRECATE - - -#pragma data_seg("_BPQDATA") - -#include "time.h" -#include "stdio.h" - -#include "CHeaders.h" -#include "tncinfo.h" - -#define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE - -#define REJSENT 1 // SET WHEN FIRST REJ IS SENT IN REPLY - // TO AN I(P) -#define RNRSET 0x2 // RNR RECEIVED FROM OTHER END -#define DISCPENDING 8 // SEND DISC WHEN ALL DATA ACK'ED -#define RNRSENT 0x10 // WE HAVE SEND RNR -#define POLLSENT 0x20 // POLL BIT OUTSTANDING - -#define ONEMINUTE 60*3 -#define TENSECS 10*3 -#define THREESECS 3*3 - - -VOID L2SENDCOMMAND(); -VOID L2ROUTINE(); -MESSAGE * SETUPL2MESSAGE(struct _LINKTABLE * LINK, UCHAR CMD); -VOID SendSupervisCmd(struct _LINKTABLE * LINK); -void SEND_RR_RESP(struct _LINKTABLE * LINK, UCHAR PF); -VOID L2SENDRESPONSE(struct _LINKTABLE * LINK, int CMD); -VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD); -VOID ACKMSG(struct _LINKTABLE * LINK); -VOID InformPartner(struct _LINKTABLE * LINK, int Reason); -UINT RR_OR_RNR(struct _LINKTABLE * LINK); -VOID L2TIMEOUT(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT); -VOID CLEAROUTLINK(struct _LINKTABLE * LINK); -VOID SENDFRMR(struct _LINKTABLE * LINK); -char * SetupNodeHeader(struct DATAMESSAGE * Buffer); -VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session); -VOID SDFRMR(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT); -VOID SDNRCHK(struct _LINKTABLE * LINK, UCHAR CTL); -VOID RESETNS(struct _LINKTABLE * LINK, UCHAR NS); -VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer); -VOID RESET2X(struct _LINKTABLE * LINK); -VOID RESET2(struct _LINKTABLE * LINK); -VOID CONNECTREFUSED(struct _LINKTABLE * LINK); -VOID SDUFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL); -VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHAR MSGFLAG); -VOID SDIFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG); -VOID SENDCONNECTREPLY(struct _LINKTABLE * LINK); -VOID SETUPNEWL2SESSION(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR MSGFLAG); -BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE); -VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR MSGFLAG); -VOID L2SENDUA(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER); -VOID L2SENDDM(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER); -VOID L2SENDRESP(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL); -int COUNTLINKS(int Port); -VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG); -TRANSPORTENTRY * SetupSessionForL2(struct _LINKTABLE * LINK); -BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySessions); -VOID PUT_ON_PORT_Q(struct PORTCONTROL * PORT, MESSAGE * Buffer); -VOID L2SWAPADDRESSES(MESSAGE * Buffer); -BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK); -VOID SENDSABM(struct _LINKTABLE * LINK); -VOID L2SENDXID(struct _LINKTABLE * LINK); -VOID __cdecl Debugprintf(const char * format, ...); -VOID Q_IP_MSG(MESSAGE * Buffer); -VOID PROCESSNODEMESSAGE(MESSAGE * Msg, struct PORTCONTROL * PORT); -VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG); -BOOL CompareAliases(UCHAR * c1, UCHAR * c2); -VOID L2FORUS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG); -VOID Digipeat(struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR * OurCall, int toPort, int UIOnly); -VOID DigiToMultiplePorts(struct PORTCONTROL * PORTVEC, PMESSAGE Msg); -VOID MHPROC(struct PORTCONTROL * PORT, MESSAGE * Buffer); -BOOL CheckForListeningSession(struct PORTCONTROL * PORT, MESSAGE * Msg); -VOID L2SENDINVALIDCTRL(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL); -UCHAR * SETUPADDRESSES(struct _LINKTABLE * LINK, PMESSAGE Msg); -VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG); -int CountBits(uint32_t in); -void AttachKISSHF(struct PORTCONTROL * PORT, MESSAGE * Buffer); -void DetachKISSHF(struct PORTCONTROL * PORT); -void KISSHFConnected(struct PORTCONTROL * PORT, struct _LINKTABLE * LINK); -void WriteConnectLog(char * fromcall, char * tocall, UCHAR * Mode); -int seeifInterlockneeded(struct PORTCONTROL * PORT); -int seeifUnlockneeded(struct _LINKTABLE * LINK); -int CheckKissInterlock(struct PORTCONTROL * MYPORT, int Exclusive); -void hookL2SessionAccepted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); -void hookL2SessionDeleted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); -void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK); - - -extern int REALTIMETICKS; - -// MSGFLAG contains CMD/RESPONSE BITS - -#define CMDBIT 4 // CURRENT MESSAGE IS A COMMAND -#define RESP 2 // CURRENT MSG IS RESPONSE -#define VER1 1 // CURRENT MSG IS VERSION 1 - -// FRMR REJECT FLAGS - -#define SDINVC 1 // INVALID COMMAND -#define SDNRER 8 // INVALID N(R) - - - -UCHAR NO_CTEXT = 0; -UCHAR ALIASMSG = 0; -extern UINT APPLMASK; -static UCHAR ISNETROMMSG = 0; -UCHAR MSGFLAG = 0; -extern char * ALIASPTR; - -UCHAR QSTCALL[7] = {'Q'+'Q','S'+'S','T'+'T',0x40,0x40,0x40,0xe0}; // QST IN AX25 -UCHAR NODECALL[7] = {0x9C, 0x9E, 0x88, 0x8A, 0xA6, 0x40, 0xE0}; // 'NODES' IN AX25 FORMAT - -extern BOOL LogAllConnects; - -APPLCALLS * APPL; - -VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer) -{ - // LEVEL 2 PROCESSING - - MESSAGE * ADJBUFFER; - struct _LINKTABLE * LINK; - UCHAR * ptr; - int n; - UCHAR CTL; - uintptr_t Work; - UCHAR c; - - // Check for invalid length (< 22 7Header + 7Addr + 7Addr + CTL - - if (Buffer->LENGTH < (18 + sizeof(void *))) - { - Debugprintf("BPQ32 Bad L2 Msg Port %d Len %d", PORT->PORTNUMBER, Buffer->LENGTH); - ReleaseBuffer(Buffer); - return; - } - - PORT->L2FRAMES++; - - ALIASMSG = 0; - APPLMASK = 0; - ISNETROMMSG = 0; - - MSGFLAG = 0; // CMD/RESP UNDEFINED - - // Check for Corrupted Callsign in Origin (to keep MH list clean) - - ptr = &Buffer->ORIGIN[0]; - n = 6; - - c = *(ptr) >> 1; - - if (c == ' ') // Blank Call - { - Debugprintf("BPQ32 Blank Call Port %d", PORT->PORTNUMBER); - ReleaseBuffer(Buffer); - return; - } - - while(n--) - { - // Try a bit harder to detect corruption - - c = *(ptr++); - - if (c & 1) - { - ReleaseBuffer(Buffer); - return; - } - - c = c >> 1; - - if (!isalnum(c) && !(c == '#') && !(c == ' ')) - { - ReleaseBuffer(Buffer); - return; - } - } - - // Check Digis if present - - if ((Buffer->ORIGIN[6] & 1) == 0) // Digis - { - ptr = &Buffer->CTL; - n = 6; - - while(n--) - { - c = *(ptr++); - - if (c & 1) - { - ReleaseBuffer(Buffer); - return; - } - - c = c >> 1; - - if (!isalnum(c) && !(c == '#') && !(c == ' ')) - { - ReleaseBuffer(Buffer); - return; - } - } - } - - BPQTRACE(Buffer, TRUE); // TRACE - RX frames to APRS - - if (PORT->PORTMHEARD) - MHPROC(PORT, Buffer); - - /// TAJ added 07/12/2020 for 'all RX traffic as IfinOctects - - InOctets[PORT->PORTNUMBER] += Buffer->LENGTH - MSGHDDRLEN; - - // CHECK THAT ALL DIGIS HAVE BEEN ACTIONED, - // AND ADJUST FOR DIGIPEATERS IF PRESENT - - n = 8; // MAX DIGIS - ptr = &Buffer->ORIGIN[6]; // End of Address bit - - while ((*ptr & 1) == 0) - { - // MORE TO COME - - ptr += 7; - - if ((*ptr & 0x80) == 0) // Digi'd bit - { - // FRAME HAS NOT BEEN REPEATED THROUGH CURRENT DIGI - - // SEE IF WE ARE MEANT TO DIGI IT - - struct XDIGI * XDigi = PORT->XDIGIS; // Cross port digi setup - - ptr -= 6; // To start of Call - - if (CompareCalls(ptr, MYCALL) || CompareAliases(ptr, MYALIAS) || - CompareCalls(ptr, PORT->PORTALIAS) || CompareCalls(ptr, PORT->PORTALIAS2)) - { - Digipeat(PORT, Buffer, ptr, 0, 0); // Digi it (if enabled) - return; - } - - while (XDigi) - { - if (CompareCalls(ptr, XDigi->Call)) - { - Digipeat(PORT, Buffer, ptr, XDigi->Port, XDigi->UIOnly); // Digi it (if enabled) - return; - } - XDigi = XDigi->Next; - } - - ReleaseBuffer(Buffer); - return; // not complete and not for us - } - n--; - - if (n == 0) - { - ReleaseBuffer(Buffer); - return; // Corrupt - no end of address bit - } - } - - // Reached End of digis, and all actioned, so can process it - - Work = (uintptr_t)&Buffer->ORIGIN[6]; - ptr -= Work; // ptr is now length of digis - - Work = (uintptr_t)Buffer; - ptr += Work; - - ADJBUFFER = (MESSAGE * )ptr; // ADJBUFFER points to CTL, etc. allowing for digis - - // GET CMD/RESP BITS - - if (Buffer->DEST[6] & 0x80) - { - if (Buffer->ORIGIN[6] & 0x80) // Both set, assume V1 - MSGFLAG |= VER1; - else - MSGFLAG |= CMDBIT; - } - else - { - if (Buffer->ORIGIN[6] & 0x80) // Only Dest Set - MSGFLAG |= RESP; - else - MSGFLAG |= VER1; // Neither, assume V1 - } - - // SEE IF FOR AN ACTIVE LINK SESSION - - CTL = ADJBUFFER->CTL; - - // IF A UI, THERE IS NO SESSION - - if (FindLink(Buffer->ORIGIN, Buffer->DEST, PORT->PORTNUMBER, &LINK)) - { - L2LINKACTIVE(LINK, PORT, Buffer,ADJBUFFER, CTL, MSGFLAG); - return; - } - - // NOT FOR ACTIVE LINK - SEE IF ADDRESSED TO OUR ADDRESSES - - // FIRST TRY PORT ADDR/ALIAS - - if(PORT->PORTBBSFLAG == 1) - goto PORTCALLISBBS; // PORT CALL/ALIAS ARE FOR BBS - - if (NODE) - goto USING_NODE; - -PORTCALLISBBS: - - // NODE IS NOT ACTIVE, SO PASS CALLS TO PORTCALL/ALIAS TO BBS - - APPLMASK = 1; - - if (CompareCalls(Buffer->DEST, NETROMCALL)) - { - ISNETROMMSG = 1; - goto FORUS; - } - if (PORT->PORTL3FLAG) // L3 Only Port? - goto NOTFORUS; // If L3ONLY, only accept calls to NETROMCALL - - ISNETROMMSG = 0; - -USING_NODE: - - if (CompareCalls(Buffer->DEST, PORT->PORTCALL)) - goto FORUS; - - ALIASMSG = 1; - - if (CompareAliases(Buffer->DEST, PORT->PORTALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - - if (NODE == 0) - goto TRYBBS; // NOT USING NODE SYSTEM - - ALIASMSG = 0; - - if (CompareCalls(Buffer->DEST, MYCALL)) - goto FORUS; - - ALIASMSG = 1; - - if (CompareAliases(Buffer->DEST, MYALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - -TRYBBS: - - if (BBS == 0) - goto NOWTRY_NODES; // NOT USING BBS CALLS - - // TRY APPLICATION CALLSIGNS/ALIASES - - - APPLMASK = 1; - ALIASPTR = &CMDALIAS[0][0]; - - n = NumberofAppls; - - APPL = APPLCALLTABLE; - - while (n--) - { - if (APPL->APPLCALL[0] > 0x40) // Valid ax.25 addr - { - // WE MAY NOT BE ALLOWED TO USE THE BBS CALL ON SOME BANDS DUE TO - // THE RATHER ODD UK LICENCING RULES! - // For backward compatibility only apply to appl 1 - - if ((PORT->PERMITTEDAPPLS & APPLMASK) != 0) - { - ALIASMSG = 0; - - if (CompareCalls(Buffer->DEST, APPL->APPLCALL)) - goto FORUS; - - ALIASMSG = 1; - - if (CompareAliases(Buffer->DEST, APPL->APPLALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - - if (CompareAliases(Buffer->DEST, APPL->L2ALIAS)) // only compare 6 bits - allow any ssid - goto FORUS; - } - } - APPLMASK <<= 1; - ALIASPTR += ALIASLEN; - APPL++; - } - - // NOT FOR US - SEE IF 'NODES' OR IP/ARP BROADCAST MESSAGE - -NOWTRY_NODES: - - if (CompareCalls(Buffer->DEST, QSTCALL)) - { - Q_IP_MSG(Buffer); // IP BROADCAST - return; - } - - if (ADJBUFFER->PID != 0xCF) // NETROM MSG? - goto NOTFORUS; // NO - - if (CompareCalls(Buffer->DEST, NODECALL)) - { - if (Buffer->L2DATA[0] == 0xff) // Valid NODES Broadcast - { - PROCESSNODEMESSAGE(Buffer, PORT); - } - } - - ReleaseBuffer(Buffer); - return; - -NOTFORUS: - // - // MAY JUST BE A REPLY TO A 'PRIMED' CQ CALL - // - if ((CTL & ~PFBIT) == SABM) - if (CheckForListeningSession(PORT, Buffer)) - return; // Used buffer to send UA - - ReleaseBuffer(Buffer); - return; - -FORUS: - - // if a UI frame and UIHook Specified, call it - - if (PORT->UIHook && CTL == 3) - PORT->UIHook(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); - - L2FORUS(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); -} - - -VOID MHPROC(struct PORTCONTROL * PORT, MESSAGE * Buffer) -{ - PMHSTRUC MH = PORT->PORTMHEARD; - PMHSTRUC MHBASE = MH; - int i; - int OldCount = 0; - char Freq[64] = ""; - char DIGI = '*'; - double ReportFreq = 0; - - // if port has a freq associated with it use it - - GetPortFrequency(PORT->PORTNUMBER, Freq); - - // if (Buffer->ORIGIN[6] & 1) - DIGI = 0; // DOn't think we want to do this - - // See if in list - - for (i = 0; i < MHENTRIES; i++) - { - if ((MH->MHCALL[0] == 0) || (CompareCalls(Buffer->ORIGIN, MH->MHCALL) && MH->MHDIGI == DIGI)) // Spare or our entry - { - OldCount = MH->MHCOUNT; - goto DoMove; - } - MH++; - } - - // TABLE FULL AND ENTRY NOT FOUND - MOVE DOWN ONE, AND ADD TO TOP - - i = MHENTRIES - 1; - - // Move others down and add at front -DoMove: - if (i != 0) // First - memmove(MHBASE + 1, MHBASE, i * sizeof(MHSTRUC)); - - memcpy (MHBASE->MHCALL, Buffer->ORIGIN, 7 * 9); // Save Digis - MHBASE->MHDIGI = DIGI; - MHBASE->MHTIME = time(NULL); - MHBASE->MHCOUNT = ++OldCount; - strcpy(MHBASE->MHFreq, Freq); - MHBASE->MHLocator[0] = 0; - - return; -} - - -int CountFramesQueuedOnSession(TRANSPORTENTRY * Session) -{ - // COUNT NUMBER OF FRAMES QUEUED ON A SESSION - - if (Session == 0) - return 0; - - if (Session->L4CIRCUITTYPE & BPQHOST) - { - return C_Q_COUNT(&Session->L4TX_Q); - } - - if (Session->L4CIRCUITTYPE & SESSION) - { - // L4 SESSION - GET NUMBER UNACKED, AND ADD NUMBER ON TX QUEUE - - int Count = C_Q_COUNT(&Session->L4TX_Q); - UCHAR Unacked = Session->TXSEQNO - Session->L4WS; - - return Count + Unacked; - } - - if (Session->L4CIRCUITTYPE & PACTOR) - { - // PACTOR Type - Frames are queued on the Port Entry - - struct PORTCONTROL * PORT = Session->L4TARGET.PORT; - EXTPORTDATA * EXT = (EXTPORTDATA *)PORT; - - int ret = EXT->FramesQueued; - - // Check L4 Queue as messages can stay there briefly - - ret += C_Q_COUNT(&Session->L4RX_Q); - - return ret + C_Q_COUNT(&PORT->PORTTX_Q); - } - - // L2 CIRCUIT - - { - int SessCount = C_Q_COUNT(&Session->L4TX_Q); - struct _LINKTABLE * LINK = Session->L4TARGET.LINK; - int L2 = COUNT_AT_L2(LINK); - - return SessCount + L2; - } -} - -int CHECKIFBUSYL2(TRANSPORTENTRY * Session) -{ - // RETURN TOP BIT OF AL SET IF SESSION PARTNER IS BUSY - - if (Session->L4CROSSLINK) // CONNECTED? - { - Session = Session->L4CROSSLINK; - - if (CountFramesQueuedOnSession(Session) > 10) - return L4BUSY;; - } - return 0; -} - -VOID L2FORUS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG) -{ - // MESSAGE ADDRESSED TO OUR CALL OR ALIAS, BUT NOT FOR AN ACTIVE SESSION - - // LINK points to an empty link table entry - - struct ROUTE * ROUTE; - int CTLlessPF = CTL & ~PFBIT; - - PORT->L2FRAMESFORUS++; - - NO_CTEXT = 0; - - // ONLY SABM or UI ALLOWED IF NO SESSION - // Plus XID/TEST/SABME if V2.2 support enabled - - if (CTLlessPF == 3) // UI - { - // A UI ADDRESSED TO US - SHOULD ONLY BE FOR IP, or possibly addressed NODES - - switch(ADJBUFFER->PID) - { - case 0xcf: // Netrom - - if (Buffer->L2DATA[0] == 0xff) // NODES - PROCESSNODEMESSAGE(Buffer, PORT); - - break; - - case 0xcc: // TCP - case 0xcd: // ARP - case 0x08: // NOS FRAGMENTED AX25 TCP/IP - - Q_IP_MSG( Buffer); - return; - } - - ReleaseBuffer(Buffer); - return; - } - - if (PORT->PortUIONLY) // Port is for UI only - { - ReleaseBuffer(Buffer); - return; - } - - if (CTLlessPF == SABME) - { - // Although some say V2.2 requires SABME I don't agree! - - // Reject until we support Mod 128 - - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - return; - } - - if (CTLlessPF == SREJ) // Used to see if other end supports SREJ on 2.0 - { - // Send FRMR if dont support SREJ - // Send DM if we do - - if (SUPPORT2point2) - L2SENDRESP(PORT, Buffer, ADJBUFFER, DM); - else - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - - return; - } - - if (CTLlessPF == XID) - { - // Send FRMR if we only support V 2.0 - - if (SUPPORT2point2 == FALSE) - { - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - return; - } - // if Support 2.2 drop through - } - - if (CTLlessPF == TEST) - { - // I can't see amy harm in replying to TEST - - L2SENDRESP(PORT, Buffer, ADJBUFFER, TEST); - return; - } - - -// if (CTLlessPF != SABM && CTLlessPF != SABME) - if (CTLlessPF != SABM && CTLlessPF != XID) - { - if ((MSGFLAG & CMDBIT) && (CTL & PFBIT)) // Command with P? - L2SENDDM(PORT, Buffer, ADJBUFFER); - else - ReleaseBuffer(Buffer); // Ignore if not - - return; - } - - // Exclude and limit tests are done for XID and SABM - - if (NODE == 0 && BBS == 0) // Don't want any calls - { - ReleaseBuffer(Buffer); - return; - } - -#ifdef EXCLUDEBITS - - // CHECK ExcludeList - - if (CheckExcludeList(Buffer->ORIGIN) == 0) - { - ReleaseBuffer(Buffer); - return; - } -#endif - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (PORT->PERMITTEDCALLS) - { - UCHAR * ptr = PORT->PERMITTEDCALLS; - - while (TRUE) - { - if (memcmp(Buffer->ORIGIN, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - ReleaseBuffer(Buffer); - return; - } - } - } - - // IF CALL REQUEST IS FROM A LOCKED NODE WITH QUALITY ZERO, IGNORE IT - - if (FindNeighbour(Buffer->ORIGIN, PORT->PORTNUMBER, &ROUTE)) - { - // From a known node - - NO_CTEXT = 1; - - if (ROUTE->NEIGHBOUR_FLAG == 1 && ROUTE->NEIGHBOUR_QUAL == 0) // Locked, qual 0 - { - ReleaseBuffer(Buffer); - return; - } - } - - // CHECK PORT CONNECT LIMITS - - if (PORT->USERS) - { - if (COUNTLINKS(PORT->PORTNUMBER) >= PORT->USERS) - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - } - - // if KISSHF, check if attached. If so, reject. If not, attach. - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - { - struct TNCINFO * TNC = PORT->TNC; - - if (TNC->PortRecord->ATTACHEDSESSIONS[0]) - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - } - - // OK to accept SABM or XID - - if (CTLlessPF == XID) - { - ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); - return; - } - - // Not XID, so must be SABM - - L2SABM(LINK, PORT, Buffer, ADJBUFFER, MSGFLAG); // Process the SABM -} - - -VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG) -{ - // I think it is fairly safe to accept XID as soon as we - // can process SREJ, but only accept Mod 8 and 256 Byte frames - - // I think the only way to run 2.2 Mod 8 is to preceed a - // SABM with XID, but others don't seem to agree! - - // Run through XID fields, changing any we don't like, - // then return an XID response - - // Decode and process XID - - UCHAR * ptr = &ADJBUFFER->PID; - UCHAR * ptr1, * ptr2; - UCHAR TEMPDIGI[57]; - int n; - - // Check Interlock - should we also check exclude etc?. No, checked in L2FORUS - - if (CheckKissInterlock(PORT, TRUE)) // Interlock with ARDOP/VARA etc - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - if (*ptr++ == 0x82 && *ptr++ == 0x80) - { - int Type; - int Len; - unsigned int value; - int xidlen = *(ptr++) << 8; - xidlen += *ptr++; - - // XID is set of Type, Len, Value n-tuples - - while (xidlen > 0) - { - Type = *ptr++; - Len = *ptr++; - - value = 0; - xidlen -= (Len + 2); - - while (Len--) - { - value <<=8; - value += *ptr++; - } - switch(Type) - { - case 2: //Bin fields - - break; - - case 3: - - if ((value & OPMustHave) != OPMustHave) - goto BadXID; - - if ((value & OPMod8) == 0) - goto BadXID; - - if ((value & OPSREJMult) == 0) - goto BadXID; - - - // Reply Mod 8 SREJMULTI - - value = OPMustHave | OPSREJMult | OPMod8; - ptr -=3; - *ptr++ = value >> 16; - *ptr++ = value >> 8; - *ptr++ = value; - - - break; - - case 6: //RX Size - - break; - - case 8: //RX Window - - break; - } - } - - // Send back as XID response - - LINK->L2STATE = 1; // XID received - LINK->Ver2point2 = TRUE; // Must support 2.2 if sent XID - LINK->L2TIME = PORT->PORTT1; - - LINK->LINKPORT = PORT; - - // save calls so we can match up SABM when it comes - - memcpy(LINK->LINKCALL, Buffer->ORIGIN, 7); - LINK->LINKCALL[6] &= 0x1e; // Mask SSID - - memcpy(LINK->OURCALL, Buffer->DEST, 7); - - LINK->OURCALL[6] &= 0x1e; // Mask SSID - - memset(LINK->DIGIS, 0, 56); // CLEAR DIGI FIELD IN CASE RECONNECT - - if ((Buffer->ORIGIN[6] & 1) == 0) // End of Address - { - // THERE ARE DIGIS TO PROCESS - COPY TO WORK AREA reversed, THEN COPY BACK - - memset(TEMPDIGI, 0, 57); // CLEAR DIGI FIELD IN CASE RECONNECT - - ptr1 = &Buffer->ORIGIN[6]; // End of add - ptr2 = &TEMPDIGI[7 * 7]; // Last Temp Digi - - while((*ptr1 & 1) == 0) // End of address bit - { - ptr1++; - memcpy(ptr2, ptr1, 7); - ptr2[6] &= 0x1e; // Mask Repeated and Last bits - ptr2 -= 7; - ptr1 += 6; - } - - // LIST OF DIGI CALLS COMPLETE - COPY TO LINK CONTROL ENTRY - - n = PORT->PORTMAXDIGIS; - - ptr1 = ptr2 + 7; // First in TEMPDIGIS - ptr2 = &LINK->DIGIS[0]; - - while (*ptr1) - { - if (n == 0) - { - // Too many for us - - CLEAROUTLINK(LINK); - ReleaseBuffer(Buffer); - return; - } - - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - n--; - } - } - - ADJBUFFER->CTL = CTL | PFBIT; - - // Buffer->LENGTH = (UCHAR *)ADJBUFFER - (UCHAR *)Buffer + MSGHDDRLEN + 15; // SET UP BYTE COUNT - - L2SWAPADDRESSES(Buffer); // SWAP ADDRESSES AND SET RESP BITS - - // We need to save APPLMASK and ALIASPTR so following SABM connects to application - - LINK->APPLMASK = APPLMASK; - LINK->ALIASPTR = ALIASPTR; - - PUT_ON_PORT_Q(PORT, Buffer); - return; - } -BadXID: - L2SENDINVALIDCTRL(PORT, Buffer, ADJBUFFER, CTL); - return; -} - - - -int COUNTLINKS(int Port) -{ - //COUNT LINKS ON PORT - - int i = MAXLINKS, n = 0; - struct _LINKTABLE * LINK = LINKS; - - while (i--) - { - if (LINK->LINKPORT && LINK->LINKPORT->PORTNUMBER == Port) - n++; - - LINK++; - } - - return n; -} - - -VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL, UCHAR MSGFLAG) -{ - // MESSAGE ON AN ACTIVE LINK - - int CTLlessPF = CTL & ~PFBIT; - - PORT->L2FRAMESFORUS++; - - // ONLY SABM or UI ALLOWED IF NO SESSION - - if (CTLlessPF == 3) // UI - { - // A UI ADDRESSED TO US - SHOULD ONLY BE FOR IP, or possibly addressed NODES - - switch(ADJBUFFER->PID) - { - case 0xcf: // Netrom - - if (Buffer->L2DATA[0] == 0xff) // NODES - PROCESSNODEMESSAGE(Buffer, PORT); - - break; - - case 0xcc: // TCP - case 0xcd: // ARP - case 0x08: // NOS FRAGMENTED AX25 TCP/IP - - Q_IP_MSG( Buffer); - return; - } - - ReleaseBuffer(Buffer); - return; - } - - if (CTLlessPF == DISC) - { - InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - return; - } - - - if (LINK->L2STATE == 1) - { - // XID State. Should be XID response if 2.2 ok or DM/FRMR if not - - if (MSGFLAG & RESP) - { - if (CTLlessPF == DM || CTLlessPF == FRMR) - { - // Doesn't support XID - Send SABM - - LINK->L2STATE = 2; - LINK->Ver2point2 = FALSE; - LINK->L2TIMER = 1; // USe retry to send SABM - } - else if (CTLlessPF == XID) - { - // Process response to make sure ok, Send SABM or DISC - - LINK->L2STATE = 2; - LINK->Ver2point2 = TRUE;// Must support 2.2 if responded to XID - LINK->L2TIMER = 1; // USe retry to send SABM - } - - ReleaseBuffer(Buffer); - return; - } - - // Command on existing session. Could be due to other end missing - // the XID response, so if XID just resend response - - } - - if (CTLlessPF == XID && (MSGFLAG & CMDBIT)) - { - // XID Command on active session. Other end may be restarting. Send Response - - ProcessXIDCommand(LINK, PORT, Buffer, ADJBUFFER, CTL, MSGFLAG); - return; - } - - - if (CTLlessPF == SABM) - { - // SABM ON EXISTING SESSION - IF DISCONNECTING, REJECT - - if (LINK->L2STATE == 1) // Sent XID? - { - APPLMASK = LINK->APPLMASK; - ALIASPTR = LINK->ALIASPTR; - - L2SABM(LINK, PORT, Buffer, ADJBUFFER, MSGFLAG); // Process the SABM - return; - } - - if (LINK->L2STATE == 4) // DISCONNECTING? - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - // THIS IS A SABM ON AN EXISTING SESSION - - // THERE ARE SEVERAL POSSIBILITIES: - - // 1. RECONNECT COMMAND TO TNC - // 2. OTHER END THINKS LINK HAS DIED - // 3. RECOVERY FROM FRMR CONDITION - // 4. REPEAT OF ORIGINAL SABM COS OTHER END MISSED UA - - // FOR 1-3 IT IS REASONABLE TO FULLY RESET THE CIRCUIT, BUT IN 4 - // SUCH ACTION WILL LOSE THE INITIAL SIGNON MSG IF CONNECTING TO A - // BBS. THE PROBLEM IS TELLING THE DIFFERENCE. I'M GOING TO SET A FLAG - // WHEN FIRST INFO RECEIVED - IF SABM REPEATED BEFORE THIS, I'LL ASSUME - // CONDITION 4, AND JUST RESEND THE UA - - - if (LINK->SESSACTIVE == 0) // RESET OF ACTIVE CIRCUIT? - { - L2SENDUA(PORT, Buffer, ADJBUFFER); // No, so repeat UA - return; - } - - InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END - LINK->CIRCUITPOINTER = 0; - - L2SABM(LINK, PORT, Buffer, ADJBUFFER, MSGFLAG); // Process the SABM - return; - } - - L2_PROCESS(LINK, PORT, Buffer, CTL, MSGFLAG); -} - - -VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR MSGFLAG) -{ - // SET UP NEW SESSION (OR RESET EXISTING ONE) - - TRANSPORTENTRY * Session; - int CONERROR; - - char toCall[12], fromCall[12]; - - - if (LINK == 0) // NO LINK ENTRIES - SEND DM RESPONSE - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - if (CheckKissInterlock(PORT, TRUE)) // Interlock with ARDOP/VARA etc - { - L2SENDDM(PORT, Buffer, ADJBUFFER); - return; - } - - SETUPNEWL2SESSION(LINK, PORT, Buffer, MSGFLAG); - - if (LINK->L2STATE != 5) // Setup OK? - { - L2SENDDM(PORT, Buffer, ADJBUFFER); // Failed - return; - } - - // See if need to Interlock non-sharable modes, eg ARDOP and VARA - - seeifInterlockneeded(PORT); - - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - - - // IF CONNECT TO APPL ADDRESS, SET UP APPL SESSION - - if (APPLMASK == 0) - { - // Not ATTACH TO APPL - - // Send CTEXT if connect to NODE/Port Alias, or NODE/Port Call, and FULL_CTEXT set - // Dont sent to known NODEs, or appl connects - - struct DATAMESSAGE * Msg; - int Totallen = 0; - int Paclen= PORT->PORTPACLEN; - UCHAR * ptr; - - if (LogAllConnects) - { - char toCall[12], fromCall[12]; - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - WriteConnectLog(fromCall, toCall, "AX.25"); - } - - hookL2SessionAccepted(PORT->PORTNUMBER, fromCall, toCall, LINK); - - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - AttachKISSHF(PORT, Buffer); - - if (NO_CTEXT == 1) - return; - - if (FULL_CTEXT == 0 && !ALIASMSG) // Any connect, or call to alias - return; - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (CTEXTLEN) - { - Totallen = CTEXTLEN; - ptr = CTEXTMSG; - } - else - return; - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&LINK->TX_Q, Msg); - - ptr += Paclen; - Totallen -= Paclen; - } - return; - } - - - // Connnect to APPL - - if (LINK->LINKTYPE != 1) - { - L2SENDUA(PORT, Buffer, ADJBUFFER); // RESET OF DOWN/CROSSLINK - return; - } - - if (LINK->CIRCUITPOINTER) - { - L2SENDUA(PORT, Buffer, ADJBUFFER); // ALREADY SET UP - MUST BE REPEAT OF SABM OR LINK RESET - return; - } - - // IF RUNNING ONLY BBS (NODE=0), THIS MAY BE EITHER A USER OR NODE - // TRYING TO SET UP A L4 CIRCUIT - WE DONT WANT TO ATTACH A NODE TO - // THE BBS! - - if (NODE == 0) - { - // NOW THINGS GET DIFICULT - WE MUST EITHER WAIT TO SEE IF A PID CF MSG - // ARRIVES, OR ASSUME ALL NODES ARE IN NEIGHBOURS - I'LL TRY THE LATTER - // AND SEE HOW IT GOES. tHIS MEANS THAT YOU MUST DEFINE ALL ROUTES - // IN CONFIG FILE - - struct ROUTE * ROUTE; - - if (FindNeighbour(Buffer->ORIGIN, PORT->PORTNUMBER, &ROUTE)) - { - // It's a node - - L2SENDUA(PORT, Buffer, ADJBUFFER); // ALREADY SET UP - MUST BE REPEAT OF SABM OR LINK RESET - return; - } - } - - - Session = SetupSessionForL2(LINK); // CREATE INCOMING L4 SESSION - - if (Session == NULL) - { - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - L2SENDDM(PORT, Buffer, ADJBUFFER); - - return; - } - - // NOW TRY A BBS CONNECT - // IF APPL CONNECT, SEE IF APPL HAS AN ALIAS - - if (ALIASPTR[0] > ' ') - { - struct DATAMESSAGE * Msg; - - // ACCEPT THE CONNECT, THEN INVOKE THE ALIAS - - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - { - struct DATAMESSAGE * Msg; - int Totallen = 0; - int Paclen= PORT->PORTPACLEN; - UCHAR * ptr; - - AttachKISSHF(PORT, Buffer); - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (HFCTEXTLEN) - { - Totallen = HFCTEXTLEN; - ptr = HFCTEXT; - } - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&LINK->TX_Q, Msg); - - ptr += Paclen; - Totallen -= Paclen; - } - - } - - if (LogAllConnects) - { - char toCall[12], fromCall[12]; - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - WriteConnectLog(fromCall, toCall, "AX.25"); - } - - Msg = GetBuff(); - - if (Msg) - { - Msg->PID = 0xf0; - - memcpy(Msg->L2DATA, ALIASPTR, 12); - Msg->L2DATA[12] = 13; - - Msg->LENGTH = MSGHDDRLEN + 12 + 2; // 2 for PID and CR - - C_Q_ADD(&LINK->RX_Q, Msg); - } - - return; - } - - if (cATTACHTOBBS(Session, APPLMASK, PORT->PORTPACLEN, &CONERROR) == 0) - { - // NO BBS AVAILABLE - - CLEARSESSIONENTRY(Session); - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - L2SENDDM(PORT, Buffer, ADJBUFFER); - - return; - } - - if (LogAllConnects) - { - char toCall[12], fromCall[12]; - toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0; - fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0; - WriteConnectLog(fromCall, toCall, "AX.25"); - } - - L2SENDUA(PORT, Buffer, ADJBUFFER); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - { - struct DATAMESSAGE * Msg; - int Totallen = 0; - int Paclen= PORT->PORTPACLEN; - UCHAR * ptr; - - AttachKISSHF(PORT, Buffer); - - // if Port CTEXT defined, use it - - if (PORT->CTEXT) - { - Totallen = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (HFCTEXTLEN) - { - Totallen = HFCTEXTLEN; - ptr = HFCTEXT; - } - else - return; - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&LINK->TX_Q, Msg); - - ptr += Paclen; - Totallen -= Paclen; - } - return; - } -} - -VOID SETUPNEWL2SESSION(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR MSGFLAG) -{ - // COPY ADDRESS INFO TO LINK TABLE - - UCHAR * ptr1, * ptr2; - UCHAR TEMPDIGI[57]; - int n; - - memcpy(LINK->LINKCALL, Buffer->ORIGIN, 7); - LINK->LINKCALL[6] &= 0x1e; // Mask SSID - - memcpy(LINK->OURCALL, Buffer->DEST, 7); - LINK->OURCALL[6] &= 0x1e; // Mask SSID - - memset(LINK->DIGIS, 0, 56); // CLEAR DIGI FIELD IN CASE RECONNECT - - LINK->L2TIME = PORT->PORTT1; // Set tomeoiut for no digis - - if ((Buffer->ORIGIN[6] & 1) == 0) // End of Address - { - // THERE ARE DIGIS TO PROCESS - COPY TO WORK AREA reversed, THEN COPY BACK - - memset(TEMPDIGI, 0, 57); // CLEAR DIGI FIELD IN CASE RECONNECT - - ptr1 = &Buffer->ORIGIN[6]; // End of add - ptr2 = &TEMPDIGI[7 * 7]; // Last Temp Digi - - while((*ptr1 & 1) == 0) // End of address bit - { - ptr1++; - memcpy(ptr2, ptr1, 7); - ptr2[6] &= 0x1e; // Mask Repeated and Last bits - ptr2 -= 7; - ptr1 += 6; - } - - // LIST OF DIGI CALLS COMPLETE - COPY TO LINK CONTROL ENTRY - - n = PORT->PORTMAXDIGIS; - - ptr1 = ptr2 + 7; // First in TEMPDIGIS - ptr2 = &LINK->DIGIS[0]; - - while (*ptr1) - { - if (n == 0) - { - // Too many for us - - CLEAROUTLINK(LINK); - return; - } - - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - n--; - - LINK->L2TIME += PORT->PORTT1; // Adjust timeout for digis - } - } - - // THIS MAY BE RESETTING A LINK - BEWARE OF CONVERTING A CROSSLINK TO - // AN UPLINK AND CONFUSING EVERYTHING - - LINK->LINKPORT = PORT; - - if (LINK->LINKTYPE == 0) - { - if (ISNETROMMSG && NODE == 0) // Only allow crosslink if node = 0 - LINK->LINKTYPE = 3; // Crosslink - else - LINK->LINKTYPE = 1; // Uplink - } - LINK->L2TIMER = 0; // CANCEL TIMER - - LINK->L2SLOTIM = T3; // SET FRAME SENT RECENTLY - - LINK->LINKWINDOW = PORT->PORTWINDOW; - - RESET2(LINK); // RESET ALL FLAGS - - LINK->L2STATE = 5; - - // IF VERSION 1 MSG, SET FLAG - - if (MSGFLAG & VER1) - LINK->VER1FLAG |= 1; - -} - -VOID L2SENDUA(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER) -{ - L2SENDRESP(PORT, Buffer, ADJBUFFER, UA); -} - -VOID L2SENDDM(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER) -{ - if (CheckExcludeList(Buffer->ORIGIN) == 0) // if in exclude, don't send DM - { - ReleaseBuffer(Buffer); // not sure that this is the right place for releasing? - return; - } - - L2SENDRESP(PORT, Buffer, ADJBUFFER, DM); -} - -VOID L2SENDRESP(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL) -{ - // QUEUE RESPONSE TO PORT CONTROL - MAY NOT HAVE A LINK ENTRY - - // SET APPROPRIATE P/F BIT - - ADJBUFFER->CTL = CTL | PFBIT; - - Buffer->LENGTH = (int)((UCHAR *)ADJBUFFER - (UCHAR *)Buffer) + MSGHDDRLEN + 15; // SET UP BYTE COUNT - - L2SWAPADDRESSES(Buffer); // SWAP ADDRESSES AND SET RESP BITS - - PUT_ON_PORT_Q(PORT, Buffer); - - return; -} - - -VOID L2SENDINVALIDCTRL(struct PORTCONTROL * PORT, MESSAGE * Buffer, MESSAGE * ADJBUFFER, UCHAR CTL) -{ - // Send FRMR Invalid Control field - - // QUEUE RESPONSE TO PORT CONTROL - MAY NOT HAVE A LINK ENTRY - - // SET APPROPRIATE P/F BIT - - UCHAR * ptr; - - ADJBUFFER->CTL = FRMR | PFBIT; - - ptr = &ADJBUFFER->PID; - - *(ptr++) = CTL; // MOVE REJECT C-BYTE - *(ptr++) = 0; - *(ptr++) = SDINVC; // MOVE REJECT FLAGS - - Buffer->LENGTH = (int)((UCHAR *)ADJBUFFER - (UCHAR *)Buffer) + MSGHDDRLEN + 18; // SET UP BYTE COUNT - - L2SWAPADDRESSES(Buffer); // SWAP ADDRESSES AND SET RESP BITS - - PUT_ON_PORT_Q(PORT, Buffer); - - return; -} - -VOID L2SWAPADDRESSES(MESSAGE * Buffer) -{ - // EXCHANGE ORIGIN AND DEST, AND REVERSE DIGIS (IF PRESENT) - - char TEMPFIELD[7]; - UCHAR * ptr1, * ptr2; - UCHAR TEMPDIGI[57]; - - memcpy(TEMPFIELD, Buffer->ORIGIN, 7); - memcpy(Buffer->ORIGIN, Buffer->DEST, 7); - memcpy(Buffer->DEST, TEMPFIELD, 7); - - Buffer->ORIGIN[6] &= 0x1e; // Mask SSID - Buffer->ORIGIN[6] |= 0xe0; // Reserved and Response - - Buffer->DEST[6] &= 0x1e; // Mask SSID - Buffer->DEST[6] |= 0x60; // Reserved - - if ((TEMPFIELD[6] & 1) == 0) - { - // THERE ARE DIGIS TO PROCESS - COPY TO WORK AREA reversed, THEN COPY BACK - - memset(TEMPDIGI, 0, 57); // CLEAR DIGI FIELD IN CASE RECONNECT - - ptr1 = &Buffer->ORIGIN[6]; // End of add - ptr2 = &TEMPDIGI[7 * 7]; // Last Temp Digi - - while((*ptr1 & 1) == 0) // End of address bit - { - ptr1++; - memcpy(ptr2, ptr1, 7); - ptr2[6] &= 0x1e; // Mask Repeated and Last bits - ptr2 -= 7; - ptr1 += 6; - } - - // LIST OF DIGI CALLS COMPLETE - copy back - - ptr1 = ptr2 + 7; // First in TEMPDIGIS - ptr2 = &Buffer->CTL; - - while (*ptr1) - { - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - } - - *(ptr2 - 1) |= 1; // End of addresses - } - else - { - Buffer->ORIGIN[6] |= 1; // End of address - } -} - -BOOL InternalL2SETUPCROSSLINK(PROUTE ROUTE, int Retries) -{ - // ROUTE POINTS TO A NEIGHBOUR - FIND AN L2 SESSION FROM US TO IT, OR INITIATE A NEW ONE - - struct _LINKTABLE * LINK; - struct PORTCONTROL * PORT; - int FRACK; - - if (FindLink(ROUTE->NEIGHBOUR_CALL, NETROMCALL, ROUTE->NEIGHBOUR_PORT, &LINK)) - { - // SESSION ALREADY EXISTS - - LINK->LINKTYPE = 3; // MAKE SURE IT KNOWS ITS A CROSSLINK - ROUTE->NEIGHBOUR_LINK = LINK; - LINK->NEIGHBOUR = ROUTE; - - return TRUE; - } - - // SET UP NEW SESSION (OR RESET EXISTING ONE) - - if (LINK == NULL) - return FALSE; // No free links - - - ROUTE->NEIGHBOUR_LINK = LINK; - LINK->NEIGHBOUR = ROUTE; - - LINK->LINKPORT = PORT = GetPortTableEntryFromPortNum(ROUTE->NEIGHBOUR_PORT); - - if (PORT == NULL) - return FALSE; // maybe port has been deleted - - // IF ROUTE HAS A FRACK, SET IT - - if (ROUTE->NBOUR_FRACK) - FRACK = ROUTE->NBOUR_FRACK; - else - FRACK = PORT->PORTT1; - - LINK->L2TIME = FRACK; // SET TIMER VALUE - - // IF ROUTE HAS A WINDOW, SET IT - - if (ROUTE->NBOUR_MAXFRAME) - LINK->LINKWINDOW = ROUTE->NBOUR_MAXFRAME; - else - LINK->LINKWINDOW = PORT->PORTWINDOW; - -// if (SUPPORT2point2) -// LINK->L2STATE = 1; // Send XID -// else - LINK->L2STATE = 2; - - memcpy(LINK->LINKCALL, ROUTE->NEIGHBOUR_CALL, 7); - memcpy(LINK->OURCALL, NETROMCALL, 7); - - if (ROUTE->NEIGHBOUR_DIGI1[0]) - { - memcpy(LINK->DIGIS, ROUTE->NEIGHBOUR_DIGI1, 7); - LINK->L2TIME += FRACK; - } - - if (ROUTE->NEIGHBOUR_DIGI2[0]) - { - memcpy(&LINK->DIGIS[7], ROUTE->NEIGHBOUR_DIGI1, 7); - LINK->L2TIME += FRACK; - } - - LINK->LINKTYPE = 3; // CROSSLINK - - if (Retries) - LINK->L2RETRIES = PORT->PORTN2 - Retries; - - if (LINK->L2STATE == 1) - L2SENDXID(LINK); - else - SENDSABM(LINK); - - return TRUE; -} - - - -BOOL L2SETUPCROSSLINKEX(PROUTE ROUTE, int Retries) -{ - // Allows caller to specify number of times SABM should be sent - - return InternalL2SETUPCROSSLINK(ROUTE, Retries); -} - -BOOL L2SETUPCROSSLINK(PROUTE ROUTE) -{ - return InternalL2SETUPCROSSLINK(ROUTE, 0); -} - -VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG) -{ - // PROCESS LEVEL 2 PROTOCOL STUFF - - // SEE IF COMMAND OR RESPONSE - - if ((MSGFLAG & CMDBIT) == 0) - { - - // RESPONSE OR VERSION 1 - - // IF RETRYING, MUST ONLY ACCEPT RESPONSES WITH F SET (UNLESS RUNNING V1) - - if ((CTL & PFBIT) || LINK->VER1FLAG == 1) - { - // F SET or V1 - CAN CANCEL TIMER - - LINK->L2TIMER = 0; // CANCEL LINK TIMER - } - } - - if (LINK->L2STATE == 3) - { - - // FRMR STATE - IF C(P) SEND FRMR, ELSE IGNORE - - if (CTL & PFBIT) - { - if (CTL == (FRMR | PFBIT)) // if both ends in FRMR state, reset link - { - RESET2(LINK); - - LINK->L2STATE = 2; // INITIALISING - LINK->L2ACKREQ = 0; // DONT SEND ANYTHING ELSE - LINK->L2RETRIES = 0; // ALLOW FULL RETRY COUNT FOR SABM - - L2SENDCOMMAND(LINK, SABM | PFBIT); - } - } - - if (MSGFLAG & CMDBIT) - { - // SEND FRMR AGAIN - - SENDFRMR(LINK); - } - - ReleaseBuffer(Buffer); - return; - } - - if (LINK->L2STATE >= 5) - { - // LINK IN STATE 5 OR ABOVE - LINK RUNNING - - if ((CTL & 1) == 0) // I frame - { - SDIFRM(LINK, PORT, Buffer, CTL, MSGFLAG); // consumes buffer - return; - } - - if ((CTL & 2)) // U frame - { - SDUFRM(LINK, PORT, Buffer, CTL); //consumes buffer - return; - } - - // ELSE SUPERVISORY, MASK OFF N(R) AND P-BIT - - switch (CTL & 0x0f) - { - // is there any harm in accepting SREJ even if we don't - // otherwise support 2.2? - - case REJ: - case SREJ: - - PORT->L2REJCOUNT++; - - case RR: - case RNR: - - SFRAME(LINK, PORT, CTL, MSGFLAG); - break; - - default: - - // UNRECOGNISABLE COMMAND - - LINK->SDRBYTE = CTL; // SAVE FOR FRMR RESPONSE - LINK->SDREJF |= SDINVC; // SET INVALID COMMAND REJECT - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - } - - ReleaseBuffer(Buffer); - return; - } - - // NORMAL DISCONNECT MODE - - // COULD BE UA, DM - SABM AND DISC HANDLED ABOVE - - switch (CTL & ~PFBIT) - { - case UA: - - // UA RECEIVED - - if (LINK->L2STATE == 2) - { - // RESPONSE TO SABM - SET LINK UP - - RESET2X(LINK); // LEAVE QUEUED STUFF - - LINK->L2STATE = 5; - LINK->L2TIMER = 0; // CANCEL TIMER - LINK->L2RETRIES = 0; - LINK->L2SLOTIM, T3; // SET FRAME SENT RECENTLY - - // IF VERSION 1 MSG, SET FLAG - - if (MSGFLAG & VER1) - LINK->VER1FLAG |= 1; - - // TELL PARTNER CONNECTION IS ESTABLISHED - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - KISSHFConnected(PORT, LINK); - - SENDCONNECTREPLY(LINK); - ReleaseBuffer(Buffer); - return; - } - - if (LINK->L2STATE == 4) // DISCONNECTING? - { - InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - } - - // UA, BUT NOT IN STATE 2 OR 4 - IGNORE - - ReleaseBuffer(Buffer); - return; - - case DM: - - // DM RESPONSE - IF TO SABM, SEND BUSY MSG - - if (LINK->L2STATE == 2) - { - CONNECTREFUSED(LINK); // SEND MESSAGE IF DOWNLINK - return; - } - - // DM RESP TO DISC RECEIVED - OTHER END HAS LOST SESSION - - // CLEAR OUT TABLE ENTRY - IF INTERNAL TNC, SHOULD SEND *** DISCONNECTED - - InformPartner(LINK, LINKLOST); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - ReleaseBuffer(Buffer); - return; - - case FRMR: - - // FRAME REJECT RECEIVED - LOG IT AND RESET LINK - - RESET2(LINK); - - LINK->L2STATE = 2; // INITIALISING - LINK->L2ACKREQ = 0; // DONT SEND ANYTHING ELSE - LINK->L2RETRIES = 0; // ALLOW FULL RETRY COUNT FOR SABM - - PORT->L2FRMRRX++; - - L2SENDCOMMAND(LINK, SABM | PFBIT); - return; - - default: - - // ANY OTHER - IGNORE - - ReleaseBuffer(Buffer); - } -} - -VOID SDUFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL) -{ - // PROCESS AN UNSEQUENCED COMMAND (IN LINK UP STATES) - - switch (CTL & ~PFBIT) - { - case UA: - - // DISCARD - PROBABLY REPEAT OF ACK OF SABM - - break; - - case FRMR: - - // FRAME REJECT RECEIVED - LOG IT AND RESET LINK - - RESET2(LINK); - - LINK->L2STATE = 2; // INITIALISING - LINK->L2ACKREQ = 0; // DONT SEND ANYTHING ELSE - LINK->L2RETRIES = 0; // ALLOW FULL RETRY COUNT FOR SABM - - PORT->L2FRMRRX++; - - L2SENDCOMMAND(LINK, SABM | PFBIT); - break; - - case DM: - - // DM RESPONSE - SESSION MUST HAVE GONE - - // SEE IF CROSSLINK ACTIVE - - InformPartner(LINK, LINKLOST); // SEND DISC TO OTHER END - CLEAROUTLINK(LINK); - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - break; - - default: - - // UNDEFINED COMMAND - - LINK->SDRBYTE = CTL; // SAVE FOR FRMR RESPONSE - LINK->SDREJF |= SDINVC; - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - - } - - ReleaseBuffer(Buffer); -} - - -VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHAR MSGFLAG) -{ - // CHECK COUNTS, AND IF RNR INDICATE _BUFFER SHORTAGE AT OTHER END - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - return; - } - - SDNRCHK(LINK, CTL); // CHECK RECEIVED N(R) - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET NOW? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - return; - } - - if ((CTL & 0xf) == SREJ) - { - // Probably safer to handle SREJ completely separately - - // Can we get SREJ Command with P??(Yes) - - // Can we just resend missing frame ?? (Think so!) - - // We support MultiSREJ (can gave additional missing frame - // numbers in the Info field - - // I don't see the point of Multi unless we wait fot an F bit, - // bur maybe not safe to assume others do the same - - // So if I get SREJ(F) I can send missing frame(s) - - if (MSGFLAG & RESP) - { - // SREJ Response - - if (CTL & PFBIT) - { - // SREJ(F). Send Frames() - - UCHAR NS = (CTL >> 5) & 7; // Frame to resend - - struct PORTCONTROL * PORT; - UCHAR * ptr1, * ptr2; - UCHAR CTL; - int count; - MESSAGE * Msg; - MESSAGE * Buffer; - - Msg = LINK->FRAMES[NS]; // is frame available? - - if (Msg == NULL) - return; // Wot!! - - // send the frame - - // GET BUFFER FOR COPY OF MESSAGE - HAVE TO KEEP ORIGINAL FOR RETRIES - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - ptr2 = SETUPADDRESSES(LINK, Buffer); // copy addresses - - // ptr2 NOW POINTS TO COMMAND BYTE - - // GOING TO SEND I FRAME - WILL ACK ANY RECEIVED FRAMES - - LINK->L2ACKREQ = 0; // CLEAR ACK NEEDED - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - LINK->KILLTIMER = 0; // RESET IDLE CIRCUIT TIMER - - CTL = LINK->LINKNR << 5; // GET CURRENT N(R), SHIFT IT TO TOP 3 BITS - CTL |= NS << 1; // BITS 1-3 OF CONTROL BYTE - - // SET P BIT IF NO MORE TO SEND (only more if Multi SREJ) - - if (LINK->VER1FLAG == 0) // NO POLL BIT IF V1 - { - CTL |= PFBIT; - LINK->L2FLAGS |= POLLSENT; - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND (or ACK if ACKMODE) - - Buffer->Linkptr = LINK; - } - - *(ptr2++) = CTL; // TO DATA (STARTING WITH PID) - - count = Msg->LENGTH - MSGHDDRLEN; - - if (count > 0) // SHOULD ALWAYS BE A PID, BUT BETTER SAFE THAN SORRY - { - ptr1 = (UCHAR *)Msg; - ptr1 += MSGHDDRLEN; - memcpy(ptr2, ptr1, count); - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - Buffer->LENGTH = (int)(ptr2 - (UCHAR *)Buffer) + count; // SET NEW LENGTH - - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } - } - } - - return; - } - - // VALID RR/RNR RECEIVED - - LINK->L2FLAGS &= ~RNRSET; //CLEAR RNR - - if ((CTL & 0xf) == RNR) - LINK->L2FLAGS |= RNRSET; //Set RNR - - if (MSGFLAG & CMDBIT) - { - // ALWAYS REPLY TO RR/RNR/REJ COMMAND (even if no P bit ??) - - // FIRST PROCESS RESEQ QUEUE - - //; CALL PROCESS_RESEQ - - // IGNORE IF AN 'F' HAS BEEN SENT RECENTLY - - if (LINK->LAST_F_TIME + 15 > REALTIMETICKS) - return; // DISCARD - - CTL = RR_OR_RNR(LINK); - - CTL |= LINK->LINKNR << 5; // SHIFT N(R) TO TOP 3 BITS - CTL |= PFBIT; - - L2SENDRESPONSE(LINK, CTL); - - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - - LINK->L2ACKREQ = 0; // CANCEL DELAYED ACKL2 - - // SAVE TIME IF 'F' SENT' - - LINK->LAST_F_TIME = REALTIMETICKS; - - return; - } - - // Response - - if ((CTL & PFBIT) == 0 && LINK->VER1FLAG == 0) - { - // RESPONSE WITHOUT P/F DONT RESET N(S) (UNLESS V1) - - return; - - } - - // RESPONSE WITH P/F - MUST BE REPLY TO POLL FOLLOWING TIMEOUT OR I(P) - - // THERE IS A PROBLEM WITH REPEATED RR(F), SAY CAUSED BY DELAY AT L1 - - // AS FAR AS I CAN SEE, WE SHOULD ONLY RESET N(S) IF AN RR(F) FOLLOWS - // AN RR(P) AFTER A TIMEOUT - AN RR(F) FOLLOWING AN I(P) CANT POSSIBLY - // INDICATE A LOST FRAME. ON THE OTHER HAND, A REJ(F) MUST INDICATE - // A LOST FRAME. So dont reset NS if not retrying, unless REJ - - - // someone (probably WLE KISS Driver) is sending REJ followed by RR(F) - // after lost frame and i(p) - -/* -1:Fm W4DHW-10 To W4DHW [17:08:03R] [+++] -úJƒÑZKÀ)x@DÖBÉrNôÝ4XÔ;i‹#CäM³,ïнҼüÕrÞùOË N¿XæâïÀÄ5Ð(È|©¸ì#íÿÈUþïÒcYÞÍl—çûž)Àú璘oÑȼö>©Ï9¨*ÎG²£ëðû(6À5C‹!áL±Ÿîßì÷³ÙQð»pƒËIH”Š;ØÚi¯Ò>â9p¶B¬õ<ÌcŠEPž«<ŸÊ{0aŽ(’­YÕ–´M¢†—N£+<ÇIÐ[–áÛPw–[^]6ƒ2\ù¿9äÆov{‹¥Å¸mm [17:08:03T] -1:Fm W4DHW To W4DHW-10 [17:08:03T] -1:Fm W4DHW To W4DHW-10 [17:08:03T] - - is there a problem with restting on RR(F) following I(P)? - - I think the problem is restting NS twice if you get delayed responses to - I or RR (P). So lets try only resetting NS once for each P sent - -*/ -// if ((CTL & 0xf) == REJ || LINK->L2RETRIES) - if ((LINK->L2FLAGS & POLLSENT)) - { - RESETNS(LINK, (CTL >> 5) & 7); // RESET N(S) AND COUNT RETRIED FRAMES - - LINK->L2RETRIES = 0; - LINK->L2TIMER = 0; // WILL RESTART TIMER WHEN RETRY SENT - } - - LINK->L2FLAGS &= ~POLLSENT; // CLEAR I(P) or RR(P) SET - - if ((CTL & 0xf) == RNR) - { - // Dont Clear timer on receipt of RNR(F), spec says should poll for clearing of busy, - // and loss of subsequent RR will cause hang. Perhaps should set slightly longer time?? - // Timer may have been cleared earlier, so restart it - - LINK->L2TIMER = LINK->L2TIME; - } -} - -//*** PROCESS AN INFORMATION FRAME - -VOID SDIFRM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR CTL, UCHAR MSGFLAG) -{ - int NS; - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - ReleaseBuffer(Buffer); - return; - } - - SDNRCHK(LINK, CTL); // CHECK RECEIVED N(R) - - if (LINK->SDREJF) // ARE ANY REJECT FLAGS SET NOW? - { - SDFRMR(LINK, PORT); // PROCESS FRAME REJECT CONDITION - ReleaseBuffer(Buffer); - return; - } - - LINK->SESSACTIVE = 1; // SESSION IS DEFINITELY SET UP - - NS = (CTL >> 1) & 7; // ISOLATE RECEIVED N(S) - - // IPOLL (sending an I(P) frame following timeout instead of RR(P)) - // is a problem. We need to send REJ(F), but shouldn't add to collector. - // We also need to handle repeated I(P), so shouldn't set REJSENT in - // this state. - - if ((((NS + 1) & 7) == LINK->LINKNR) && (CTL & PFBIT)) - { - // Previous Frame and P set - Assume IPOLL - - PORT->L2OUTOFSEQ++; - LINK->L2STATE = 6; - - LINK->L2ACKREQ = 0; // CANCEL RR NEEDED - - // We need to protect against sending multiple REJ(F) if channel - // delays mean we get two I(P) close together (how close is close ??) - // SM has default IPOLL limit of 30 bytes or about a second at 300 - // ACKMODE should avoid this anyway, and resptime of under 3 secs - // is unlikely so say 2.5 secs ?? - - if (LINK->LAST_F_TIME + 25 > REALTIMETICKS) - { - ReleaseBuffer(Buffer); - return; - } - - SEND_RR_RESP(LINK, PFBIT); - LINK->LAST_F_TIME = REALTIMETICKS; - - ReleaseBuffer(Buffer); - return; - } - -CheckNSLoop: - - if (NS != LINK->LINKNR) // EQUAL TO OUR N(R)? - { - // There is a frame missing. - // if we have just sent a REJ we have at least one out - // of sequence frame in RXFRAMES - - // so if we have frame LINK->LINKNR we can process it - // and remove it from RXFRAMES. If we are then back - // in sequence we just carry on. - - if (LINK->RXFRAMES[LINK->LINKNR]) - { - // We have the first missing frame. Process it. - - MESSAGE * OldBuffer = Q_REM(&LINK->RXFRAMES[LINK->LINKNR]); - - Debugprintf("L2 process saved Frame %d", LINK->LINKNR); - PROC_I_FRAME(LINK, PORT, OldBuffer); // Passes on or releases Buffer - - // NR has been updated. - - goto CheckNSLoop; // See if OK or we have another saved frame - } - - // BAD FRAME, SEND REJ (AFTER RESPTIME - OR WE MAY SEND LOTS!) - - // ALSO SAVE THE FRAME - NEXT TIME WE MAY GET A DIFFERENT SUBSET - // AND SOON WE WILL HANDLE SREJ - - PORT->L2OUTOFSEQ++; - - LINK->L2STATE = 6; - - // IF RUNNING VER1, AND OTHER END MISSES THIS REJ, LINK WILL FAIL - // SO TIME OUT REJ SENT STATE (MUST KEEP IT FOR A WHILE TO AVOID - // 'MULTIPLE REJ' PROBLEM) - - if (LINK->VER1FLAG == 1) - LINK->REJTIMER = TENSECS; - - // SET ACK REQUIRED TIMER - REJ WILL BE SENT WHEN IT EXPIRES - - // if configured RESPTIME is longer than 3 secs use it (may be longer on HF) - - if (PORT->PORTT2 > THREESECS) - LINK->L2ACKREQ = PORT->PORTT2; - else - LINK->L2ACKREQ = THREESECS; // EXTRA LONG RESPTIME, AS SENDING TOO MANY REJ'S IS SERIOUS - - if (LINK->RXFRAMES[NS]) - { - // Already have a copy, so discard old and keep this - - Debugprintf ("Frame %d out of seq but already have copy - release it", NS); - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[NS])); - } - else - { - Debugprintf ("Frame %d out of seq - save", NS); - } - - Buffer->CHAIN = 0; - LINK->RXFRAMES[NS] = Buffer; - goto CheckPF; - } - - // IN SEQUENCE FRAME - - // Remove any stored frame with this seq - - if (LINK->RXFRAMES[NS]) - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[NS])); - - if (LINK->L2STATE == 6) // REJ? - { - // If using REJ we can cancel REJ state. - // If using SREJ we only cancel REJ if we have no stored frames - - if (LINK->Ver2point2) - { - // see if any frames saved. - - int i; - - for (i = 0; i < 8; i++) - { - if (LINK->RXFRAMES[i]) - goto stayinREJ; - } - // Drop through if no stored frames - } - - // CANCEL REJ - - LINK->L2STATE = 5; - LINK->L2FLAGS &= ~REJSENT; - } - -stayinREJ: - - PROC_I_FRAME(LINK, PORT, Buffer); // Passes on or releases Buffer - - -CheckPF: - - if (LINK->Ver2point2 == 0) // Unless using SREJ - { - if (LINK->L2FLAGS & REJSENT) - { - return; // DONT SEND ANOTHER TILL REJ IS CANCELLED - } - } - - if (CTL & PFBIT) - { - if (LINK->L2STATE == 6) - LINK->L2FLAGS |= REJSENT; // Set "REJ Sent" - else - { - // we have all frames. Clear anything in RXFRAMES - - int n = 0; - - while (n < 8) - { - if (LINK->RXFRAMES[n]) - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[n])); - - n++; - } - } - LINK->L2ACKREQ = 0; // CANCEL RR NEEDED - - SEND_RR_RESP(LINK, PFBIT); - - // RECORD TIME - - LINK->LAST_F_TIME = REALTIMETICKS; - } - else - if (LINK->L2ACKREQ == 0) // Resptime is zero so send RR now - SEND_RR_RESP(LINK, 0); - -} - - -VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffer) -{ - int Length; - char * Info; - UCHAR PID; - struct DATAMESSAGE * Msg = (struct DATAMESSAGE *)Buffer; - UCHAR * EOA; - int n = 8; // Max Digis - - LINK->LINKNR++; // INCREMENT OUR N(R) - LINK->LINKNR &= 7; // MODULO 8 - - // ATTACH I FRAMES TO LINK TABLE RX QUEUE - ONLY DATA IS ADDED (NOT ADDRESSES) - - // IF DISC PENDING SET, IGNORE FRAME - - if (LINK->L2FLAGS & DISCPENDING) - { - ReleaseBuffer(Buffer); - return; - } - - // Copy data down the buffer so PID comes after Header (DATAMESSAGE format) - - Length = Buffer->LENGTH - (MSGHDDRLEN + 15); // Buffer Header + addrs + CTL - Info = &Buffer->PID; - - // Adjust for DIGIS - - EOA = &Buffer->ORIGIN[6]; // End of address Bit - - while (((*EOA & 1) == 0) && n--) - { - Length -= 7; - Info += 7; - EOA += 7; - } - - PID = EOA[2]; - - switch(PID) - { - case 0xcc: - case 0xcd: - - // IP Message - - if (n < 8) // If digis, move data back down buffer - { - memmove(&Buffer->PID, &EOA[2], Length); - Buffer->LENGTH -= (int)(&EOA[2] - &Buffer->PID); - } - - Q_IP_MSG( Buffer); - break; - - case 8: - - // NOS FRAGMENTED IP - - if (n < 8) // If digis, move data back down buffer - { - memmove(&Buffer->PID, &EOA[2], Length); - Buffer->LENGTH -= (int)(&EOA[2] - &Buffer->PID); - } - - C_Q_ADD(&LINK->L2FRAG_Q, Buffer); - - if (Buffer->L2DATA[0] == 0) - { - // THERE IS A WHOLE MESSAGE ON FRAG_Q - PASS TO IP - - while(LINK->L2FRAG_Q) - { - Buffer = Q_REM(&LINK->L2FRAG_Q); - Q_IP_MSG( Buffer); - } - } - break; - - default: - - if (Length < 1 || Length > 257) - { - ReleaseBuffer(Buffer); - return; - } - - // Copy Data back over - - memmove(&Msg->PID, Info, Length); - - Buffer->LENGTH = Length + MSGHDDRLEN; - - C_Q_ADD(&LINK->RX_Q, Buffer); - } - - LINK->L2ACKREQ = PORT->PORTT2; // SET RR NEEDED - LINK->KILLTIMER = 0; // RESET IDLE LINK TIMER -} - -//*** CHECK RECEIVED N(R) COUNT - -VOID SDNRCHK(struct _LINKTABLE * LINK, UCHAR CTL) -{ - UCHAR NR = (CTL >> 5) & 7; - - if (NR >= LINK->LINKWS) // N(R) >= WINDOW START? - { - // N(R) ABOVE OR EQUAL TO WINDOW START - OK IF NOT ABOVE N(S), OR N(S) BELOW WS - - if (NR > LINK->LINKNS) // N(R) <= WINDOW END? - { - // N(R) ABOVE N(S) - DOES COUNT WRAP? - - if (LINK->LINKNS >= LINK->LINKWS) // Doesnt wrap - goto BadNR; - } - -GoodNR: - - if ((CTL & 0x0f) == SREJ) - if ((CTL & PFBIT) == 0) - return; // SREJ without F doesn't ACK anything - - LINK->LINKWS = NR; // NEW WINDOW START = RECEIVED N(R) - ACKMSG(LINK); // Remove any acked messages - return; - } - - // N(R) LESS THAN WINDOW START - ONLY OK IF WINDOW WRAPS - - if (NR <= LINK->LINKNS) // N(R) <= WINDOW END? - goto GoodNR; - -BadNR: - - // RECEIVED N(R) IS INVALID - - LINK->SDREJF |= SDNRER; // FLAG A REJECT CONDITION - LINK->SDRBYTE = CTL; // SAVE FOR FRMR RESPONSE -} - -VOID RESETNS(struct _LINKTABLE * LINK, UCHAR NS) -{ - int Resent = (LINK->LINKNS - NS) & 7; // FRAMES TO RESEND - - LINK->LINKNS = NS; // RESET N(S) - - if (LINK->LINKTYPE == 3) // mode-Node - { - if (LINK->NEIGHBOUR) - LINK->NEIGHBOUR->NBOUR_RETRIES += Resent; - } -} - -int COUNT_AT_L2(struct _LINKTABLE * LINK) -{ - // COUNTS FRAMES QUEUED ON AN L2 SESSION (IN BX) - - int count = 0, abovelink = 0; - int n = 0; - - if (LINK == NULL) - return 0; - - abovelink = C_Q_COUNT((UINT *)&LINK->TX_Q); - - // COUNT FRAMES IN TSLOTS - - while (n < 8) - { - if (LINK->FRAMES[n]) - count++; - n++; - } - -// ADD AL,AH ; TOTAL IN AL, NUMBER ABOVE LINK IN AH - - return abovelink + count; -} - -//*** RESET HDLC AND PURGE ALL QUEUES ETC. - -VOID RESET2X(struct _LINKTABLE * LINK) -{ - LINK->SDREJF = 0; // CLEAR FRAME REJECT FLAGS - LINK->LINKWS = 0; // CLEAR WINDOW POINTERS - LINK->LINKOWS = 0; - LINK->LINKNR = 0; // CLEAR N(R) - LINK->LINKNS = 0; // CLEAR N(S) - LINK->SDTSLOT= 0; - LINK->L2STATE = 5; // RESET STATE - LINK->L2FLAGS = 0; -} - - -VOID CLEARL2QUEUES(struct _LINKTABLE * LINK) -{ - // GET RID OF ALL FRAMES THAT ARE QUEUED - - int n = 0; - - while (n < 8) - { - while (LINK->FRAMES[n]) - ReleaseBuffer(Q_REM(&LINK->FRAMES[n])); - while (LINK->RXFRAMES[n]) - ReleaseBuffer(Q_REM(&LINK->RXFRAMES[n])); - n++; - } - - // GET RID OF ALL FRAMES THAT ARE - // QUEUED ON THE TX HOLDING QUEUE, RX QUEUE AND LEVEL 3 QUEUE - - - while (LINK->TX_Q) - ReleaseBuffer(Q_REM(&LINK->TX_Q)); - - while (LINK->RX_Q) - ReleaseBuffer(Q_REM(&LINK->RX_Q)); - -} - -VOID RESET2(struct _LINKTABLE * LINK) -{ - CLEARL2QUEUES(LINK); - RESET2X(LINK); -} - -VOID SENDSABM(struct _LINKTABLE * LINK) -{ - L2SENDCOMMAND(LINK, SABM | PFBIT); -} - - -VOID PUT_ON_PORT_Q(struct PORTCONTROL * PORT, MESSAGE * Buffer) -{ - // TIME STAMP IT - - time(&Buffer->Timestamp); - - if (PORT->TXPORT) - { - Buffer->PORT = PORT->TXPORT; // update port no in header - - PORT = GetPortTableEntryFromPortNum(PORT->TXPORT); - - if (PORT == NULL) - { - ReleaseBuffer(Buffer); - return; - } - } - C_Q_ADD(&PORT->PORTTX_Q, (UINT *)Buffer); -} - - -UCHAR * SETUPADDRESSES(struct _LINKTABLE * LINK, PMESSAGE Msg) -{ - // COPY ADDRESSES FROM LINK TABLE TO MESSAGE _BUFFER - - UCHAR * ptr1 = &LINK->DIGIS[0]; - UCHAR * ptr2 = &Msg->CTL; - int Digis = 8; - - memcpy(&Msg->DEST[0], &LINK->LINKCALL[0], 14); // COPY DEST AND ORIGIN - - Msg->DEST[6] |= 0x60; - Msg->ORIGIN[6] |= 0x60; - - while (Digis) - { - if (*(ptr1)) // any more to copy? - { - memcpy(ptr2, ptr1, 7); - ptr1 += 7; - ptr2 += 7; - Digis--; - } - else - break; - } - - *(ptr2 - 1) |= 1; // SET END OF ADDRESSES - - return ptr2; // Pointer to CTL -} - -VOID SDETX(struct _LINKTABLE * LINK) -{ - // Start sending frsmes if possible - - struct PORTCONTROL * PORT; - int Outstanding; - UCHAR * ptr1, * ptr2; - UCHAR CTL; - int count; - MESSAGE * Msg; - MESSAGE * Buffer; - - // DONT SEND IF RESEQUENCING RECEIVED FRAMES - CAN CAUSE FRMR PROBLEMS - -// if (LINK->L2RESEQ_Q) -// return; - - if (LINK->LINKPORT->PORTNUMBER == 19) - { - int i = 0; - } - - Outstanding = LINK->LINKNS - LINK->LINKOWS; // Was WS not NS - - if (Outstanding < 0) - Outstanding += 8; // allow for wrap - - if (Outstanding >= LINK->LINKWINDOW) // LIMIT - return; - - // See if we can load any more frames into the frame holding q - - while (LINK->TX_Q && LINK->FRAMES[LINK->SDTSLOT] == NULL) - { - Msg = Q_REM(&LINK->TX_Q); - Msg->CHAIN = NULL; - LINK->FRAMES[LINK->SDTSLOT] = Msg; - LINK->SDTSLOT ++; - LINK->SDTSLOT &= 7; - } - - // dont send while poll outstanding - - while ((LINK->L2FLAGS & POLLSENT) == 0) - { - Msg = LINK->FRAMES[LINK->LINKNS]; // is next frame available? - - if (Msg == NULL) - return; - - // send the frame - - // GET BUFFER FOR COPY OF MESSAGE - HAVE TO KEEP ORIGINAL FOR RETRIES - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - ptr2 = SETUPADDRESSES(LINK, Buffer); // copy addresses - - // ptr2 NOW POINTS TO COMMAND BYTE - - // GOING TO SEND I FRAME - WILL ACK ANY RECEIVED FRAMES - - LINK->L2ACKREQ = 0; // CLEAR ACK NEEDED - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - LINK->KILLTIMER = 0; // RESET IDLE CIRCUIT TIMER - - CTL = LINK->LINKNR << 5; // GET CURRENT N(R), SHIFT IT TO TOP 3 BITS - CTL |= LINK->LINKNS << 1; // BITS 1-3 OF CONTROL BYTE - - LINK->LINKNS++; // INCREMENT NS - LINK->LINKNS &= 7; // mod 8 - - // SET P BIT IF END OF WINDOW OR NO MORE TO SEND - - if (LINK->VER1FLAG == 0) // NO POLL BIT IF V1 - { - Outstanding = LINK->LINKNS - LINK->LINKOWS; - - if (Outstanding < 0) - Outstanding += 8; // allow for wrap - - // if at limit, or no more to send, set P) - - if (Outstanding >= LINK->LINKWINDOW || LINK->FRAMES[LINK->LINKNS] == NULL) - { - CTL |= PFBIT; - LINK->L2FLAGS |= POLLSENT; - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND (or ACK if ACKMODE) - - Buffer->Linkptr = LINK; - } - } - - *(ptr2++) = CTL; // TO DATA (STARTING WITH PID) - - count = Msg->LENGTH - MSGHDDRLEN; - - if (count > 0) // SHOULD ALWAYS BE A PID, BUT BETTER SAFE THAN SORRY - { - ptr1 = (UCHAR *)Msg; - ptr1 += MSGHDDRLEN; - memcpy(ptr2, ptr1, count); - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - Buffer->LENGTH = (int)(ptr2 - (UCHAR *)Buffer) + count; // SET NEW LENGTH - - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } - - } -} - -VOID L2TimerProc() -{ - int i = MAXLINKS; - struct _LINKTABLE * LINK = LINKS; - struct PORTCONTROL * PORT = PORTTABLE; - - while (i--) - { - if (LINK->LINKCALL[0] == 0) - { - LINK++; - continue; - } - - // CHECK FOR TIMER EXPIRY OR BUSY CLEARED - - PORT = LINK->LINKPORT; - - if (PORT == NULL) - { - LINK++; - continue; // just ion case!! - } - - if (LINK->L2TIMER) - { - LINK->L2TIMER--; - if (LINK->L2TIMER == 0) - { - L2TIMEOUT(LINK, PORT); - LINK++; - continue; - } - } - else - { - // TIMER NOT RUNNING - MAKE SURE STATE NOT BELOW 5 - IF - // IT IS, SOMETHING HAS GONE WRONG, AND LINK WILL HANG FOREVER - - if (LINK->L2STATE < 5 && LINK->L2STATE != 2 && LINK->L2STATE != 1) // 2 = CONNECT - PROBABLY TO CQ - LINK->L2TIMER = 2; // ARBITRARY VALUE - } - - // TEST FOR RNR SENT, AND NOT STILL BUSY - - if (LINK->L2FLAGS & RNRSENT) - { - // Was busy - - if (RR_OR_RNR(LINK) != RNR) // SEE IF STILL BUSY - { - // Not still busy - tell other end - - // Just sending RR will hause a hang of RR is missed, and other end does not poll on Busy - // Try sending RR CP, so we will retry if not acked - - LINK->L2ACKREQ = 0; // CLEAR ANY DELAYED ACK TIMER - - if (LINK->L2RETRIES == 0) // IF RR(P) OUTSTANDING WILl REPORT ANYWAY - { - SendSupervisCmd(LINK); - LINK++; - continue; - } - } - } - else - { - // NOT BUSY - - if (LINK->L2ACKREQ) // DELAYED ACK TIMER - { - if (LINK->L2RETRIES == 0) // DONT SEND RR RESPONSE WHILEST RR(P) OUTSTANDING - { - LINK->L2ACKREQ--; - if (LINK->L2ACKREQ == 0) - { - SEND_RR_RESP(LINK, 0); // NO F BIT - LINK++; - continue; - } - } - } - } - - // CHECK FOR REJ TIMEOUT - - if (LINK->REJTIMER) - { - LINK->REJTIMER--; - if (LINK->REJTIMER == 0) // {REJ HAS TIMED OUT (THIS MUST BE A VERSION 1 SESSION) - { - // CANCEL REJ STATE - - if (LINK->L2STATE == 6) // REJ? - LINK->L2STATE = 5; // CLEAR REJ - } - } - - // See if time for link validation poll - - if (LINK->L2SLOTIM) - { - LINK->L2SLOTIM--; - if (LINK->L2SLOTIM == 0) // Time to poll - { - SendSupervisCmd(LINK); - LINK++; - continue; - } - } - - // See if idle too long - - LINK->KILLTIMER++; - - if (L2KILLTIME && LINK->KILLTIMER > L2KILLTIME) - { - // CIRCUIT HAS BEEN IDLE TOO LONG - SHUT IT DOWN - - LINK->KILLTIMER = 0; - LINK->L2TIMER = 1; // TO FORCE DISC - LINK->L2STATE = 4; // DISCONNECTING - - // TELL OTHER LEVELS - - InformPartner(LINK, NORMALCLOSE); - } - LINK++; - } -} - -VOID SendSupervisCmd(struct _LINKTABLE * LINK) -{ - // Send Super Command RR/RNR/REJ(P) - - UCHAR CTL; - - if (LINK->VER1FLAG == 1) - { - // VERSION 1 TIMEOUT - - // RESET TO RESEND I FRAMES - - LINK->LINKNS = LINK->LINKOWS; - - SDETX(LINK); // PREVENT FRMR (I HOPE) - } - - // SEND RR COMMAND - EITHER AS LINK VALIDATION POLL OR FOLLOWING TIMEOUT - - LINK->L2ACKREQ = 0; // CLEAR ACK NEEDED - - CTL = RR_OR_RNR(LINK); - -// MOV L2STATE[EBX],5 ; CANCEL REJ - ACTUALLY GOING TO 'PENDING ACK' - - CTL |= LINK->LINKNR << 5; // SHIFT N(R) TO TOP 3 BITS - CTL |= PFBIT; - - LINK->L2FLAGS |= POLLSENT; - - L2SENDCOMMAND(LINK, CTL); - - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY -} - -void SEND_RR_RESP(struct _LINKTABLE * LINK, UCHAR PF) -{ - UCHAR CTL; - - CTL = RR_OR_RNR(LINK); - -// MOV L2STATE[EBX],5 ; CANCEL REJ - ACTUALLY GOING TO 'PENDING ACK' - - CTL |= LINK->LINKNR << 5; // SHIFT N(R) TO TOP 3 BITS - CTL |= PF; - - L2SENDRESPONSE(LINK, CTL); - - ACKMSG(LINK); // SEE IF STILL WAITING FOR ACK -} - -VOID ACKMSG(struct _LINKTABLE * LINK) -{ - // RELEASE ANY ACKNOWLEDGED FRAMES - - while (LINK->LINKOWS != LINK->LINKWS) // is OLD WINDOW START EQUAL TO NEW WINDOW START? - { - // No, so frames to ack - - if (LINK->FRAMES[LINK->LINKOWS]) - ReleaseBuffer(Q_REM(&LINK->FRAMES[LINK->LINKOWS])); - else - { - char Call1[12], Call2[12]; - - Call1[ConvFromAX25(LINK->LINKCALL, Call1)] = 0; - Call2[ConvFromAX25(LINK->OURCALL, Call2)] = 0; - - Debugprintf("Missing frame to ack Seq %d Calls %s %s", LINK->LINKOWS, Call1, Call2); - } - - LINK->IFrameRetryCounter = 0; - - LINK->LINKOWS++; // INCREMENT OLD WINDOW START - LINK->LINKOWS &= 7; // MODULO 8 - - // SOMETHING HAS BEEN ACKED - RESET RETRY COUNTER - - if (LINK->L2RETRIES) - LINK->L2RETRIES = 1; // MUSTN'T SET TO ZERO - COULD CAUSE PREMATURE RETRANSMIT - - } - - if (LINK->LINKWS != LINK->LINKNS) // IS N(S) = NEW WINDOW START? - { - // NOT ALL I-FRAMES HAVE BEEN ACK'ED - RESTART TIMER - - // Need to kill link if we are getting repeated RR(F) after timeout - // (Indicating other station is seeing our RR(P) but not the resent I frame) - - if (LINK->IFrameRetryCounter++ > LINK->LINKPORT->PORTN2) - { - Debugprintf("Too many repeats of same I frame - closing connection"); - LINK->L2TIMER = 1; // USE TIMER TO SEND DISC - LINK->L2STATE = 4; // DISCONNECTING - return; - } - - - LINK->L2TIMER = LINK->L2TIME; - return; - } - - // ALL FRAMES HAVE BEEN ACKED - CANCEL TIMER UNLESS RETRYING - // IF RETRYING, MUST ONLY CANCEL WHEN RR(F) RECEIVED - - if (LINK->VER1FLAG == 1 || LINK->L2RETRIES == 0) // STOP TIMER IF LEVEL 1 or not retrying - { - LINK->L2TIMER = 0; - LINK->L2FLAGS &= ~POLLSENT; // CLEAR I(P) SET (IN CASE TALKING TO OLD BPQ!) - } - - // IF DISCONNECT REQUEST OUTSTANDING, AND NO FRAMES ON TX QUEUE, SEND DISC - - if ((LINK->L2FLAGS & DISCPENDING) && LINK->TX_Q == 0) - { - LINK->L2FLAGS &= ~DISCPENDING; - - LINK->L2TIMER = 1; // USE TIMER TO SEND DISC - LINK->L2STATE = 4; // DISCONNECTING - } -} - -VOID CONNECTFAILED(); - -VOID L2TIMEOUT(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT) -{ - // TIMER EXPIRED - - // IF LINK UP (STATE 5 OR ABOVE) SEND RR/RNR AS REQUIRED - // IF S2, REPEAT SABM - // IF S3, REPEAT FRMR - // IF S4, REPEAT DISC - - - PORT->L2TIMEOUTS++; // FOR STATS - - if (LINK->L2STATE == 0) - return; - - if (LINK->L2STATE == 1) - { - // XID - - LINK->L2RETRIES++; - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - Give up - - CONNECTFAILED(LINK); // TELL LEVEL 4 IT FAILED - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - CLEAROUTLINK(LINK); - return; - } - - L2SENDXID(LINK); - return; - } - - - if (LINK->L2STATE == 2) - { - // CONNECTING - - LINK->L2RETRIES++; - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - Give up - - CONNECTFAILED(LINK); // TELL LEVEL 4 IT FAILED - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - CLEAROUTLINK(LINK); - return; - } - - SENDSABM(LINK); - return; - } - - if (LINK->L2STATE == 4) - { - // DISCONNECTING - - LINK->L2RETRIES++; - - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - JUST CLEAR OUT LINK - - if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) - DetachKISSHF(PORT); - - CLEAROUTLINK(LINK); - return; - } - - L2SENDCOMMAND(LINK, DISC | PFBIT); - return; - } - - if (LINK->L2STATE == 3) - { - // FRMR - - LINK->L2RETRIES++; - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N2 TIMES - RESET LINK - - LINK->L2RETRIES = 0; - LINK->L2STATE = 2; - SENDSABM(LINK); - return; - } - } - - // STATE 5 OR ABOVE - - // SEND RR(P) UP TO N2 TIMES - - LINK->L2RETRIES++; - - if (LINK->L2RETRIES >= PORT->PORTN2) - { - // RETRIED N TIMES SEND A COUPLE OF DISCS AND THEN CLOSE - - InformPartner(LINK, RETRIEDOUT); // TELL OTHER END ITS GONE - - LINK->L2RETRIES -= 1; // Just send one DISC - LINK->L2STATE = 4; // CLOSING - - L2SENDCOMMAND(LINK, DISC | PFBIT); - return; - } - - SendSupervisCmd(LINK); -} - -VOID SDFRMR(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT) -{ - PORT->L2FRMRTX++; - - LINK->L2STATE = 3; // ENTER FRMR STATE - - LINK->L2TIMER = LINK->L2TIME; //SET TIMER - - SENDFRMR(LINK); -} - -VOID SENDFRMR(struct _LINKTABLE * LINK) -{ - // RESEND FRMR - - struct PORTCONTROL * PORT; - MESSAGE * Buffer; - UCHAR * ptr; - - Buffer = SETUPL2MESSAGE(LINK, FRMR); - - if (Buffer == NULL) - return; - - Buffer->ORIGIN[6] |= 0x80; // SET RESPONSE - - ptr = &Buffer->PID; - - *(ptr++) = LINK->SDRBYTE; // MOVE REJECT C-BYTE - - *(ptr++) = LINK->LINKNR << 5 | LINK->LINKNS << 1; - - *(ptr++) = LINK->SDREJF; // MOVE REJECT FLAGS - - Buffer->LENGTH += 3; - - PORT = LINK->LINKPORT; - Buffer->PORT = PORT->PORTNUMBER; - - if (PORT) - PUT_ON_PORT_Q(PORT, Buffer); - else - ReleaseBuffer(Buffer); - - return; -} - -VOID CLEAROUTLINK(struct _LINKTABLE * LINK) -{ - char toCall[12], fromCall[12]; - - toCall[ConvFromAX25(LINK->LINKCALL, toCall)] = 0; - fromCall[ConvFromAX25(LINK->OURCALL, fromCall)] = 0; - - hookL2SessionDeleted(LINK->LINKPORT->PORTNUMBER, fromCall, toCall, LINK); - - seeifUnlockneeded(LINK); - - CLEARL2QUEUES(LINK); // TO RELEASE ANY BUFFERS - - memset(LINK, 0, sizeof(struct _LINKTABLE)); -} - -VOID L2SENDXID(struct _LINKTABLE * LINK) -{ - // Set up and send XID - - struct PORTCONTROL * PORT; - UCHAR * ptr; - unsigned int xidval; - MESSAGE * Buffer; - - if (LINK->LINKPORT == 0) - return; //??? has been zapped - - Buffer = SETUPL2MESSAGE(LINK, XID | PFBIT); - - if (Buffer == NULL) - { - // NO BUFFERS - SET TIMER TO FORCE RETRY - - LINK->L2TIMER = 10*3; // SET TIMER - return; - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - ptr = &Buffer->PID; - - // Set up default XID Mod 8 - - *ptr++ = 0x82; // FI - *ptr++ = 0x80; // GI - *ptr++ = 0x0; - *ptr++ = 0x10; // Length 16 - - *ptr++ = 0x02; // Classes of Procedures - *ptr++ = 0x02; // Length - *ptr++ = 0x00; // - *ptr++ = 0x21; // ABM Half Duplex - - // We offer REJ, SREJ and SREJ Multiframe - - *ptr++ = 0x03; // Optional Functions - *ptr++ = 0x03; // Len - - // Sync TX, SREJ Multiframe 16 bit FCS, Mod 8, TEST, - // Extended Addressing, REJ, SREJ - - xidval = OPMustHave | OPSREJ | OPSREJMult | OPREJ | OPMod8; - *ptr++ = xidval >> 16; - *ptr++ = xidval >> 8; - *ptr++ = xidval; - - - *ptr++ = 0x06; // RX Packet Len - *ptr++ = 0x02; // Len - *ptr++ = 0x08; // - *ptr++ = 0x00; // 2K bits (256) Bytes - - *ptr++ = 0x08; // RX Window - *ptr++ = 0x01; // Len - *ptr++ = 0x07; // 7 - - Buffer->LENGTH = (int)(ptr - (UCHAR *)Buffer); // SET LENGTH - - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND - - Buffer->Linkptr = LINK; - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } -} - - - - - - -VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD) -{ - // SEND COMMAND IN CMD - - struct PORTCONTROL * PORT; - MESSAGE * Buffer; - - if (LINK->LINKPORT == 0) - return; //??? has been zapped - - Buffer = SETUPL2MESSAGE(LINK, CMD); - - if (Buffer == NULL) - { - // NO BUFFERS - SET TIMER TO FORCE RETRY - - if (CMD & PFBIT) // RESPONSE EXPECTED? - LINK->L2TIMER = 10*3; // SET TIMER - - return; - } - - Buffer->DEST[6] |= 0x80; // SET COMMAND - - if (CMD & PFBIT) // RESPONSE EXPECTED? - { - LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER - - // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND - - Buffer->Linkptr = LINK; - } - - PORT = LINK->LINKPORT; - - if (PORT) - { - Buffer->PORT = PORT->PORTNUMBER; - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - Buffer->Linkptr = 0; - ReleaseBuffer(Buffer); - } -} - - - - - - -VOID L2SENDRESPONSE(struct _LINKTABLE * LINK, int CMD) -{ - // SEND Response IN CMD - - struct PORTCONTROL * PORT; - MESSAGE * Buffer; - - Buffer = SETUPL2MESSAGE(LINK, CMD); - - if (Buffer == NULL) - { - // NO BUFFERS - SET TIMER TO FORCE RETRY - - if (CMD & PFBIT) // RESPONSE EXPECTED? - LINK->L2TIMER = 10*3; // SET TIMER - - return; - } - - Buffer->ORIGIN[6] |= 0x80; // SET RESPONSE - - LINK->L2SLOTIM = T3 + rand() % 15; // SET FRAME SENT RECENTLY - - PORT = LINK->LINKPORT; - Buffer->PORT = PORT->PORTNUMBER; - - if (PORT) - PUT_ON_PORT_Q(PORT, Buffer); - else - ReleaseBuffer(Buffer); - -} - - -MESSAGE * SETUPL2MESSAGE(struct _LINKTABLE * LINK, UCHAR CMD) -{ - MESSAGE * Buffer; - UCHAR * ptr; - - Buffer = GetBuff(); - - if (Buffer == NULL) - return NULL; - - ptr = SETUPADDRESSES(LINK, Buffer); // copy addresses - - // ptr NOW POINTS TO COMMAND BYTE - - *(ptr)++ = CMD; - - Buffer->LENGTH = (int)(ptr - (UCHAR *)Buffer); // SET LENGTH - - return Buffer; -} - - -VOID L3LINKCLOSED(struct _LINKTABLE * LINK, int Reason); - -VOID InformPartner(struct _LINKTABLE * LINK, int Reason) -{ - // LINK IS DISCONNECTING - IF THERE IS A CROSSLINK, SEND DISC TO IT - - if (LINK->LINKTYPE == 3) - { - L3LINKCLOSED(LINK, Reason); - return; - } - - if (LINK->CIRCUITPOINTER) - { - CloseSessionPartner(LINK->CIRCUITPOINTER); - CLEARSESSIONENTRY(LINK->CIRCUITPOINTER); - } -} - - -UINT RR_OR_RNR(struct _LINKTABLE * LINK) -{ - UCHAR Temp; - TRANSPORTENTRY * Session; - - LINK->L2FLAGS &= ~RNRSENT; - - // SET UP APPROPRIATE SUPER COMMAND - - if (LINK->LINKTYPE == 3) - - // Node to Node - only busy if short of buffers - - goto CHKBUFFS; - -// UP OR DOWN LINK - SEE IF SESSION IS BUSY - - if (LINK->CIRCUITPOINTER == 0) - goto CHKBUFFS; // NOT CONNECTED - - Session = LINK->CIRCUITPOINTER; // TO CIRCUIT ENTRY - - Temp = CHECKIFBUSYL2(Session); //TARGET SESSION BUSY? - - if (Temp & L4BUSY) - goto SENDRNR; // BUSY - -CHKBUFFS: - - if (QCOUNT < 20) - goto SENDRNR; // NOT ENOUGH - - // SEND REJ IF IN REJ STATE - - if (LINK->L2STATE == 6) - { - - // We may have the needed frame in RXFRAMES - -CheckNSLoop2: - - if (LINK->RXFRAMES[LINK->LINKNR]) - { - // We have the first missing frame. Process it. - - struct PORTCONTROL * PORT = LINK->LINKPORT; - MESSAGE * OldBuffer = Q_REM(&LINK->RXFRAMES[LINK->LINKNR]); - - Debugprintf("L2 about to send REJ - process saved Frame %d", LINK->LINKNR); - PROC_I_FRAME(LINK, PORT, OldBuffer); // Passes on or releases Buffer - - // NR has been updated. - - // Clear REJ if we have no more saved - - if (LINK->Ver2point2) // Using SREJ? - { - // see if any frames saved. - - int i; - - for (i = 0; i < 8; i++) - { - if (LINK->RXFRAMES[i]) - goto stayinREJ2; - } - // Drop through if no stored frames - } - - LINK->L2STATE = 5; - LINK->L2FLAGS &= ~REJSENT; -stayinREJ2: - LINK->L2ACKREQ = 0; // Cancel Resptime (Set by PROC_I_FRAME) - - goto CheckNSLoop2; // See if OK or we have another saved frame - } - if (LINK->L2STATE == 6) - - // if we support SREJ send that instesd or REJ - - if (LINK->Ver2point2) // We only allow 2.2 with SREJ Multi - return SREJ; - else - return REJ; - } - return RR; - -SENDRNR: - - LINK->L2FLAGS |= RNRSENT; // REMEMBER - - return RNR; -} - - -VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg); - -VOID CONNECTFAILED(struct _LINKTABLE * LINK) -{ - ConnectFailedOrRefused(LINK, "Failure with"); -} -VOID CONNECTREFUSED(struct _LINKTABLE * LINK) -{ - ConnectFailedOrRefused(LINK, "Busy from"); -} - -VOID L3CONNECTFAILED(); - -VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg) -{ - // IF DOWNLINK, TELL PARTNER - // IF CROSSLINK, TELL ROUTE CONTROL - - struct DATAMESSAGE * Buffer; - UCHAR * ptr1; - char Normcall[10]; - TRANSPORTENTRY * Session; - TRANSPORTENTRY * InSession; - - if (LINK->LINKTYPE == 3) - { - L3CONNECTFAILED(LINK); // REPORT TO LEVEL 3 - return; - } - - if (LINK->CIRCUITPOINTER == 0) // No crosslink?? - return; - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - // SET UP HEADER - - Buffer->PID = 0xf0; - - ptr1 = SetupNodeHeader(Buffer); - - Normcall[ConvFromAX25(LINK->LINKCALL, Normcall)] = 0; - - ptr1 += sprintf(ptr1, "%s %s\r", Msg, Normcall); - - Buffer->LENGTH = (int)(ptr1 - (UCHAR *)Buffer); - - Session = LINK->CIRCUITPOINTER; // GET CIRCUIT TABLE ENTRY - InSession = Session->L4CROSSLINK; // TO INCOMMING SESSION - - CLEARSESSIONENTRY(Session); - - if (InSession) - { - InSession->L4CROSSLINK = NULL; // CLEAR REVERSE LINK - C_Q_ADD(&InSession->L4TX_Q, Buffer); - PostDataAvailable(InSession); - } - else - ReleaseBuffer(Buffer); -} - -VOID SENDCONNECTREPLY(struct _LINKTABLE * LINK) -{ - // LINK SETUP COMPLETE - - struct DATAMESSAGE * Buffer; - UCHAR * ptr1; - char Normcall[10]; - TRANSPORTENTRY * Session; - TRANSPORTENTRY * InSession; - - if (LINK->LINKTYPE == 3) - return; - - // UP/DOWN LINK - - if (LINK->CIRCUITPOINTER == 0) // No crosslink?? - return; - - Buffer = GetBuff(); - - if (Buffer == NULL) - return; - - // SET UP HEADER - - Buffer->PID = 0xf0; - - ptr1 = SetupNodeHeader(Buffer); - - Normcall[ConvFromAX25(LINK->LINKCALL, Normcall)] = 0; - - ptr1 += sprintf(ptr1, "Connected to %s\r", Normcall); - - Buffer->LENGTH = (int)(ptr1 - (UCHAR *)Buffer); - - Session = LINK->CIRCUITPOINTER; // GET CIRCUIT TABLE ENTRY - Session->L4STATE = 5; - InSession = Session->L4CROSSLINK; // TO INCOMMONG SESSION - - if (InSession) - { - C_Q_ADD(&InSession->L4TX_Q, Buffer); - PostDataAvailable(InSession); - } -} - - -TRANSPORTENTRY * SetupSessionForL2(struct _LINKTABLE * LINK) -{ - TRANSPORTENTRY * NewSess = L4TABLE; - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (NewSess->L4USER[0] == 0) - { - // Got One - - LINK->CIRCUITPOINTER = NewSess; // SETUP LINK-CIRCUIT CONNECTION - - memcpy(NewSess->L4USER, LINK->LINKCALL, 7); - memcpy(NewSess->L4MYCALL, MYCALL, 7); // ALWAYS USE _NODE CALL - - NewSess->CIRCUITINDEX = Index; //OUR INDEX - NewSess->CIRCUITID = NEXTID; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - NewSess->L4TARGET.LINK = LINK; - - NewSess->L4CIRCUITTYPE = L2LINK | UPLINK; - - NewSess->L4STATE = 5; // SET LINK ACTIVE - - NewSess->SESSPACLEN = LINK->LINKPORT->PORTPACLEN; - - - NewSess->SESSIONT1 = L4T1; // Default - NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - - return NewSess; - } - Index++; - NewSess++; - } - - return NULL; -} - - -VOID Digipeat(struct PORTCONTROL * PORT, MESSAGE * Buffer, UCHAR * OurCall, int toPort, int UIOnly) // Digi it (if enabled) -{ - // WE MAY HAVE DISABLED DIGIPEAT ALTOGETHER, (DIGIFLAG=0), - // OR ALLOW ALLOW ONLY UI FRAMES TO BE DIGIED (DIGIFLAG=-1) - - // toPort and UIOnly are used for Cross Port digi feature - - int n; - - if (PORT->DIGIFLAG == 0 && toPort == 0) - { - ReleaseBuffer(Buffer); - return; - } - - OurCall[6] |= 0x80; // SET HAS BEEN REPEATED - - // SEE IF UI FRAME - scan forward for end of address bit - - n = 8; - - while ((OurCall[6] & 1) == 0) - { - OurCall += 7; - - if ((OurCall - &Buffer->CTL) > 56) - { - // Run off end before findin end of address - - ReleaseBuffer(Buffer); - return; - } - } - - if (toPort) // Cross port digi - { - if (((OurCall[7] & ~PFBIT) == 3) || UIOnly == 0) - { - // UI or Digi all - - Buffer->PORT = toPort; // update port no in header - PORT = GetPortTableEntryFromPortNum(toPort); - - if (PORT == NULL) - ReleaseBuffer(Buffer); - else - PUT_ON_PORT_Q(PORT, Buffer); - return; - } - else - { - ReleaseBuffer(Buffer); - return; - } - } - - if ((OurCall[7] & ~PFBIT) == 3) - { - // UI - - // UI FRAME. IF DIGIMASK IS NON-ZERO, SEND TO ALL PORTS SET, OTHERWISE SEND TO DIGIPORT - - PORT->L2DIGIED++; - - if (toPort) - { - // Cross port digi - - PORT = GetPortTableEntryFromPortNum(toPort); - Buffer->PORT = PORT->DIGIPORT; // update port no in header - - if (PORT == NULL) - ReleaseBuffer(Buffer); - else - PUT_ON_PORT_Q(PORT, Buffer); - - return; - } - - if (PORT->DIGIMASK == 0) - { - if (PORT->DIGIPORT) // Cross Band Digi? - { - Buffer->PORT = PORT->DIGIPORT; // update port no in header - - PORT = GetPortTableEntryFromPortNum(PORT->DIGIPORT); - - if (PORT == NULL) - { - ReleaseBuffer(Buffer); - return; - } - } - PUT_ON_PORT_Q(PORT, Buffer); - } - else - { - DigiToMultiplePorts(PORT, Buffer); - ReleaseBuffer(Buffer); - } - return; - } - - // Not UI - Only Digi if Digiflag not -1 - - if (PORT->DIGIFLAG == -1) - { - ReleaseBuffer(Buffer); - return; - } - - PORT->L2DIGIED++; - - if (PORT->DIGIPORT) // Cross Band Digi? - { - Buffer->PORT = PORT->DIGIPORT; // update port no in header - - PORT = GetPortTableEntryFromPortNum(PORT->DIGIPORT); - - if (PORT == NULL) - { - ReleaseBuffer(Buffer); - return; - } - } - PUT_ON_PORT_Q(PORT, Buffer); -} - -BOOL CheckForListeningSession(struct PORTCONTROL * PORT, MESSAGE * Msg) -{ - TRANSPORTENTRY * L4 = L4TABLE; - struct DATAMESSAGE * Buffer; - int i = MAXCIRCUITS; - UCHAR * ptr; - - while (i--) - { - if ((CountBits64(L4->LISTEN) == 1) && ((1 << ((Msg->PORT & 0x7f) - 1) && L4->LISTEN))) - { - // See if he is calling our call - - UCHAR ourcall[7]; // Call we are using (may have SSID bits inverted - memcpy(ourcall, L4->L4USER, 7); - ourcall[6] ^= 0x1e; // Flip SSID - - if (CompareCalls(Msg->DEST, ourcall)) - { - // Get Session Entry for Downlink - - TRANSPORTENTRY * NewSess = L4TABLE; - struct _LINKTABLE * LINK; - char Normcall[10]; - - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (NewSess->L4USER[0] == 0) - { - // Got One - - L4->L4CROSSLINK = NewSess; - NewSess->L4CROSSLINK = L4; - - memcpy(NewSess->L4USER, L4->L4USER, 7); - memcpy(NewSess->L4MYCALL, L4->L4USER, 7); - - NewSess->CIRCUITINDEX = Index; //OUR INDEX - NewSess->CIRCUITID = NEXTID; - NewSess->L4STATE = 5; - NewSess->L4CIRCUITTYPE = L2LINK+UPLINK; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - NewSess->SESSIONT1 = L4->SESSIONT1; - NewSess->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - - // SET UP NEW SESSION (OR RESET EXISTING ONE) - - FindLink(Msg->ORIGIN, ourcall, PORT->PORTNUMBER, &LINK); - - if (LINK == NULL) - return FALSE; - - memcpy(LINK->LINKCALL, Msg->ORIGIN, 7); - LINK->LINKCALL[6] &= 0xFE; - 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 - - LINK->L2STATE = 5; // CONNECTED - - LINK->CIRCUITPOINTER = NewSess; - - NewSess->L4TARGET.LINK = LINK; - - if (PORT->PORTPACLEN) - NewSess->SESSPACLEN = L4->SESSPACLEN = PORT->PORTPACLEN; - - L2SENDUA(PORT, Msg, Msg); // RESET OF DOWN/CROSSLINK - - L4->LISTEN = FALSE; // Take out of listen mode - - // Tell User - - Buffer = GetBuff(); - - if (Buffer == NULL) - return TRUE; - - // SET UP HEADER - - Buffer->PID = 0xf0; - - ptr = &Buffer->L2DATA[0]; - - Normcall[ConvFromAX25(LINK->LINKCALL, Normcall)] = 0; - - ptr += sprintf(ptr, "Incoming call from %s\r", Normcall); - - Buffer->LENGTH = (int)(ptr - (UCHAR *)Buffer); - - C_Q_ADD(&L4->L4TX_Q, Buffer); - PostDataAvailable(L4); - - return TRUE; - - } - Index++; - NewSess++; - } - return FALSE; - } - } - L4++; - } - return FALSE; -} - - -int COUNTLINKS(int Port); -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); - - -int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive) -{ - // This checks for interlocked kiss and other ports. Returns 1 if attach/connect not allowed - - // If Exclusive is not set allow connects on specified port up to l2limit, - - // If Exclusive is set also don't allow any connects on specified port. - - // Generally use Exclusive if locking a port that doesn't allow shared access, eg ARDOP, VARAus - - // Maybe only Exclusive is needed, and just check session mode ports. Sharing of KISS ports is controlled by USERS - - int Interlock = PORT->PORTINTERLOCK; - - if (Interlock == 0) - return 0; // No locking - - PORT = PORTTABLE; - - if (Exclusive) - { - while(PORT) - { - if (PORT->TNC) - { - struct TNCINFO * TNC = PORT->TNC; - - if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group - { - // See if port in use - - int n; - - for (n = 0; n <= 26; n++) - { - if (TNC->PortRecord->ATTACHEDSESSIONS[n]) - { - return TNC->Port; ; // Refuse Connect - } - } - } - } - PORT = PORT->PORTPOINTER; - } - } - return 0; // ok to connect -} - -int seeifInterlockneeded(struct PORTCONTROL * PORT) -{ - // Can we just call SuspendOtherPorts - it won't do any harm if already suspended - // No, at that needs a TNC Record, so duplicate code here - - int i; - int Interlock = PORT->PORTINTERLOCK; - struct TNCINFO * TNC; - - if (Interlock == 0) - return 0; // No locking - - for (i = 1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - - if (TNC) - if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group - if (TNC->SuspendPortProc && TNC->PortRecord->PORTCONTROL.PortSuspended == FALSE) - TNC->SuspendPortProc(TNC, TNC); - } - - return 0; -} - -int seeifUnlockneeded(struct _LINKTABLE * LINK) -{ - // We need to see if any other links are active on any interlocked KISS ports. If not, release the lock - - int i; - int links = 0; - - int Interlock; - struct TNCINFO * TNC; - struct PORTCONTROL * PORT = LINK->LINKPORT; - - if (PORT == NULL) - return 0; - - // Should only be called for KISS links, but just in case - - if (PORT->PORTTYPE > 12) // INTERNAL or EXTERNAL? - return 0; // Not KISS Port - - Interlock = PORT->PORTINTERLOCK; - - if (Interlock == 0) - return 0; // No locking - - - // Count all L2 links on interlocked KISS ports - - PORT = PORTTABLE; - - while(PORT) - { - if (PORT->PORTTYPE <= 12) // INTERNAL or EXTERNAL? - if (Interlock == PORT->PORTINTERLOCK) - links += COUNTLINKS(PORT->PORTNUMBER); - - PORT = PORT->PORTPOINTER; - } - - if (links > 1) // must be the one we are closing - return 0; // Keep lock - - - for (i = 1; i <= MAXBPQPORTS; i++) - { - TNC = TNCInfo[i]; - - if (TNC) - if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group - if (TNC->ReleasePortProc && TNC->PortRecord->PORTCONTROL.PortSuspended == TRUE) - TNC->ReleasePortProc(TNC, TNC); - } - - return 0; -} - - - - diff --git a/L4Code-skigdebian.c b/L4Code-skigdebian.c deleted file mode 100644 index 59fc0e2..0000000 --- a/L4Code-skigdebian.c +++ /dev/null @@ -1,2416 +0,0 @@ -/* -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. See 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 L4Code.asm -// -#define Kernel - -#define _CRT_SECURE_NO_DEPRECATE - - -#pragma data_seg("_BPQDATA") - -#include "time.h" -#include "stdio.h" -#include - -#include "CHeaders.h" -#include "tncinfo.h" - -extern BPQVECSTRUC BPQHOSTVECTOR[]; -#define BPQHOSTSTREAMS 64 -#define IPHOSTVECTOR BPQHOSTVECTOR[BPQHOSTSTREAMS + 3] - -VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session); -VOID SENDL4DISC(TRANSPORTENTRY * Session); -int C_Q_COUNT(VOID * Q); -TRANSPORTENTRY * SetupSessionForL2(struct _LINKTABLE * LINK); -VOID InformPartner(struct _LINKTABLE * LINK, int Reason); -VOID IFRM150(TRANSPORTENTRY * Session, PDATAMESSAGE Buffer); -VOID SendConNAK(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG); -BOOL FINDCIRCUIT(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY ** REQL4, int * NewIndex); -int GETBUSYBIT(TRANSPORTENTRY * L4); -BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySessions); -VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, - TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE); -extern char * ALIASPTR; -VOID SendConACK(struct _LINKTABLE * LINK, TRANSPORTENTRY * L4, L3MESSAGEBUFFER * L3MSG, BOOL BPQNODE, UINT Applmask, UCHAR * ApplCall); -VOID L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG); -VOID L4TIMEOUT(TRANSPORTENTRY * L4); -struct DEST_LIST * CHECKL3TABLES(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * Msg); -int CHECKIFBUSYL4(TRANSPORTENTRY * L4); -VOID AUTOTIMER(); -VOID NRRecordRoute(UCHAR * Buff, int Len); -VOID REFRESHROUTE(TRANSPORTENTRY * Session); -VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR); -VOID SENDL4IACK(TRANSPORTENTRY * Session); -VOID CHECKNEIGHBOUR(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * Msg); -VOID ProcessINP3RIF(struct ROUTE * Route, UCHAR * ptr1, int msglen, int Port); -VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len, int Port); -VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, UCHAR * ApplCall); -void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode); -void SendVARANetromMsg(struct TNCINFO * TNC, PL3MESSAGEBUFFER MSG); - -extern UINT APPLMASK; - -extern BOOL LogL4Connects; -extern BOOL LogAllConnects; - -// L4 Flags Values - -#define DISCPENDING 8 // SEND DISC WHEN ALL DATA ACK'ED - -extern APPLCALLS * APPL; - -VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) -{ - // MAKE SURE PID IS 0CF - IN CASE SOMEONE IS SENDING L2 STUFF ON WHAT - // WE THINK IS A _NODE-_NODE LINK - - struct DEST_LIST * DEST; - - int n; - - if (L3MSG->L3PID != 0xCF) - { - ReleaseBuffer(L3MSG); - return; - } - - if (LINK->NEIGHBOUR == 0) - { - // NO ROUTE ASSOCIATED WITH THIS CIRCUIT - SET ONE UP - - CHECKNEIGHBOUR(LINK, L3MSG); - - if (LINK->NEIGHBOUR == 0) - { - // COULDNT SET UP NEIGHBOUR - CAN ONLY THROW IT AWAY - - ReleaseBuffer(L3MSG); - return; - } - } - - // See if a INP3 RIF (first Byte 0xFF) - - if (L3MSG->L3SRCE[0] == 0xff) - { - // INP3 - - ProcessINP3RIF(LINK->NEIGHBOUR, &L3MSG->L3SRCE[1], L3MSG->LENGTH - (MSGHDDRLEN + 2), L3MSG->Port); // = 2 = PID + FF Flag - ReleaseBuffer(L3MSG); - return; - } - - APPLMASK = 0; // NOT APPLICATION - - if (NODE) // _NODE SUPPORT INCLUDED? - { - - if (CompareCalls(L3MSG->L3DEST, MYCALL)) - { - FRAMEFORUS(LINK, L3MSG, APPLMASK, MYCALL); - return; - } - } - - // CHECK ALL L4 CALLS - - APPLMASK = 1; - ALIASPTR = &CMDALIAS[0][0]; - - n = NumberofAppls; - - APPL = APPLCALLTABLE; - - while (n--) - { - if (APPL->APPLCALL[0] > 0x40) // Valid ax.25 addr - { - if (CompareCalls(L3MSG->L3DEST, APPL->APPLCALL)) - { - FRAMEFORUS(LINK, L3MSG, APPLMASK, APPL->APPLCALL); - return; - } - } - APPLMASK <<= 1; - ALIASPTR += ALIASLEN; - APPL++; - } - - // IS IT INP3 (L3RTT) - - if (CompareCalls(L3MSG->L3DEST, L3RTT)) - { - ProcessRTTMsg(LINK->NEIGHBOUR, L3MSG, L3MSG->LENGTH, L3MSG->Port); - return; - } - - L3MSG->L3TTL--; - - if (L3MSG->L3TTL == 0) - { - ReleaseBuffer(L3MSG); - return; - } - - // If it is a record route frame we should add our call to the list before sending on - - if (L3MSG->L4FLAGS == 0 && L3MSG->L4ID == 1 && L3MSG->L4INDEX == 0) - { - // Add our call on end, and increase count - - int Len = L3MSG->LENGTH; - int Count; - - UCHAR * ptr = (UCHAR *)L3MSG; - - if (Len < 248) - { - ptr += (Len - 1); - - Count = (*(ptr++)) & 0x7F; // Mask End of Route - - memcpy(ptr, MYCALL, 7); - - ptr += 7; - - Count--; - *(ptr) = Count; - - if (Count) - L3MSG->LENGTH += 8; - } - } - - if (L3MSG->L3TTL > L3LIVES) - L3MSG->L3TTL = L3LIVES; // ENFORCE LIMIT ON ALL FRAMES SENT - - if (FindDestination(L3MSG->L3DEST, &DEST) == 0) - { - ReleaseBuffer(L3MSG); // CANT FIND DESTINATION - return; - } - - // IF MESSAGE ORIGINTED HERE, THERE MUST BE A ROUTING LOOP - - // THERE IS LITTLE POINT SENDING IT OVER THE SAME ROUTE AGAIN, - // SO SET ANOTHER ROUTE ACTIVE IF POSSIBLE - - if (CompareCalls(L3MSG->L3SRCE, MYCALL) || CompareCalls(L3MSG->L3SRCE, APPLCALLTABLE->APPLCALL)) - { - // MESSAGE HAS COME BACK TO ITS STARTING POINT - ACTIVATE ANOTHER ROUTE, - // UNLESS THERE IS ONLY ONE, IN WHICH CASE DISCARD IT - - if (DEST->NRROUTE[1].ROUT_NEIGHBOUR == 0) // No more routes - { - ReleaseBuffer(L3MSG); - return; - } - - DEST->DEST_ROUTE++; - - if (DEST->DEST_ROUTE == 4) // TO NEXT - DEST->DEST_ROUTE = 1; // TRY TO ACTIVATE FIRST - } - - // IF CURRENT ROUTE IS BACK THE WAY WE CAME, THEN ACTIVATE - //ANOTHER (IF POSSIBLE). - - if (DEST->DEST_ROUTE) - { - if (DEST->NRROUTE[DEST->DEST_ROUTE -1].ROUT_NEIGHBOUR == LINK->NEIGHBOUR) - { - // Current ROUTE IS BACK THE WAY WE CAME - ACTIVATE ANOTHER IF POSSIBLE - - DEST->DEST_ROUTE++; - if (DEST->DEST_ROUTE == 4) - DEST->DEST_ROUTE =1; - } - goto NO_PROBLEM; - } - else - { - // DONT HAVE AN ACTIVE ROUTE - - if (DEST->NRROUTE[0].ROUT_NEIGHBOUR == LINK->NEIGHBOUR) - { - // FIRST ROUTE IS BACK THE WAY WE CAME - ACTIVATE ANOTHER IF POSSIBLE - - DEST->DEST_ROUTE = 2; // WILL BE RESET BY L3 CODE IF THERE IS NOT OTHER ROUTE - } - } - -NO_PROBLEM: - - CHECKL3TABLES(LINK, L3MSG); - -// EVEN IF WE CANT PUT ORIGINATING NODE INTO OUR TABLES, PASS MSG ON -// ANYWAY - THE FINAL TARGET MAY HAVE ANOTHER WAY BACK - - - C_Q_ADD(&DEST->DEST_Q, L3MSG); - - L3FRAMES++; -} - -VOID SENDL4MESSAGE(TRANSPORTENTRY * L4, struct DATAMESSAGE * Msg) -{ - L3MESSAGEBUFFER * L3MSG; - struct DEST_LIST * DEST; - struct DATAMESSAGE * Copy; - int FRAGFLAG = 0; - int Len; - - // These make it simpler to understand code - -#define NullPKTLen 4 + sizeof(void *) // 4 is Port, Len, PID -#define MaxL4Len 236 + 4 + sizeof(void *) // Max NETROM Size - - - if (Msg->LENGTH == NullPKTLen) - { - // NO DATA - DISCARD IT - - ReleaseBuffer(Msg); - return; - } - - L3MSG = GetBuff(); - - if (L3MSG == 0) - { - // DONT THINK WE SHOULD GET HERE, UNLESS _QCOUNT IS CORRUPT, - // BUT IF WE DO, SHOULD RETURN MSG TO FREE Q - START TIMER, AND - // DROP THROUGH TO RELBUFF - - L4->L4TIMER = L4->SESSIONT1; - - ReleaseBuffer(Msg); - return; - } - - L3MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(L3MSG->L3SRCE, L4->L4MYCALL, 7); - - DEST = L4->L4TARGET.DEST; - memcpy(L3MSG->L3DEST, DEST->DEST_CALL, 7); - - L3MSG->L3TTL = L3LIVES; - - L3MSG->L4ID = L4->FARID; - L3MSG->L4INDEX = L4->FARINDEX; - - L3MSG->L4TXNO = L4->TXSEQNO; - - // SET UP RTT TIMER - - if (L4->RTT_TIMER == 0) - { - L4->RTT_SEQ = L4->TXSEQNO; - - L4->RTT_TIMER = GetTickCount(); - } - - L4->TXSEQNO++; - - - L4->L4LASTACKED = L3MSG->L4RXNO = L4->RXSEQNO; // SAVE LAST NUMBER ACKED - - // SEE IF CROSSSESSION IS BUSY - - GETBUSYBIT(L4); // Sets BUSY in NAKBITS if Busy - - L3MSG->L4FLAGS = L4INFO | L4->NAKBITS; - - L4->L4TIMER = L4->SESSIONT1; // SET TIMER - L4->L4ACKREQ = 0; // CANCEL ACK NEEDED - - Len = Msg->LENGTH; - - if (Len > MaxL4Len) // 236 DATA + 8 HEADER - { - // MUST FRAGMENT MESSAGE - - L3MSG->L4FLAGS |= L4MORE; - FRAGFLAG = 1; - - Len = MaxL4Len; - } - - Len += 20; // L3/4 Header - - L3MSG->LENGTH = Len; - - Len -= (20 + NullPKTLen); // Actual Data - - memcpy(L3MSG->L4DATA, Msg->L2DATA, Len); - - // CREATE COPY FOR POSSIBLE RETRY - - Copy = GetBuff(); - - if (Copy == 0) - { - // SHOULD NEVER HAPPEN - - ReleaseBuffer(Msg); - return; - } - - memcpy(Copy, L3MSG, L3MSG->LENGTH); - - // If we have fragmented, we should adjust length, or retry will send too much - // (bug in .asm code) - - if (FRAGFLAG) - Copy->LENGTH = MaxL4Len; - - C_Q_ADD(&L4->L4HOLD_Q, Copy); - - C_Q_ADD(&DEST->DEST_Q, L3MSG); - - DEST->DEST_COUNT++; // COUNT THEM - - L4FRAMESTX++; - - if (FRAGFLAG) - { - // MESSAGE WAS TOO BIG - ADJUST IT AND LOOP BACK - - Msg->LENGTH -= 236; - - memmove(Msg->L2DATA, &Msg->L2DATA[236], Msg->LENGTH - NullPKTLen); - - SENDL4MESSAGE(L4, Msg); - } -} - - -int GETBUSYBIT(TRANSPORTENTRY * L4) -{ - // SEE IF CROSSSESSION IS BUSY - - L4->NAKBITS &= ~L4BUSY; // Clear busy - - L4->NAKBITS |= CHECKIFBUSYL4(L4); // RETURNS AL WITH BUSY BIT SET IF CROSSSESSION IS BUSY - - return L4->NAKBITS; -} - -VOID Q_IP_MSG(MESSAGE * Buffer) -{ - if (IPHOSTVECTOR.HOSTAPPLFLAGS & 0x80) - { - // CHECK WE ARENT USING TOO MANY BUFFERS - - if (C_Q_COUNT(&IPHOSTVECTOR.HOSTTRACEQ) > 20) - ReleaseBuffer(Q_REM((void *)&IPHOSTVECTOR.HOSTTRACEQ)); - - C_Q_ADD(&IPHOSTVECTOR.HOSTTRACEQ, Buffer); - return; - } - - ReleaseBuffer(Buffer); -} - -VOID SENDL4CONNECT(TRANSPORTENTRY * Session) -{ - PL3MESSAGEBUFFER MSG = (PL3MESSAGEBUFFER)GetBuff(); - struct DEST_LIST * DEST = Session->L4TARGET.DEST; - - if (MSG == NULL) - return; - - if (DEST->DEST_CALL[0] == 0) - { - Debugprintf("Trying to send L4CREQ to NULL Destination"); - ReleaseBuffer(MSG); - return; - } - - MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(MSG->L3SRCE, Session->L4MYCALL, 7); - memcpy(MSG->L3DEST, DEST->DEST_CALL, 7); - - MSG->L3TTL = L3LIVES; - - MSG->L4INDEX = Session->CIRCUITINDEX; - MSG->L4ID = Session->CIRCUITID; - MSG->L4TXNO = 0; - MSG->L4RXNO = 0; - MSG->L4FLAGS = L4CREQ; - - MSG->L4DATA[0] = L4DEFAULTWINDOW; // PROPOSED WINDOW - - memcpy(&MSG->L4DATA[1], Session->L4USER, 7); // ORIG CALL - memcpy(&MSG->L4DATA[8], Session->L4MYCALL, 7); - - Session->L4TIMER = Session->SESSIONT1; // START TIMER - memcpy(&MSG->L4DATA[15], &Session->SESSIONT1, 2); // AND PUT IN MSG - - MSG->LENGTH = (int)(&MSG->L4DATA[17] - (UCHAR *)MSG); - - if (Session->SPYFLAG) - { - MSG->L4DATA[17] = 'Z'; // ADD SPY ON BBS FLAG - MSG->LENGTH++; - } - C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); -} - -void RETURNEDTONODE(TRANSPORTENTRY * Session) -{ - // SEND RETURNED TO ALIAS:CALL - - struct DATAMESSAGE * Msg = (struct DATAMESSAGE *)GetBuff(); - char Nodename[20]; - - if (Msg) - { - Msg->PID = 0xf0; - - Nodename[DecodeNodeName(MYCALLWITHALIAS, Nodename)] = 0; // null terminate - - Msg->LENGTH = (USHORT)sprintf(&Msg->L2DATA[0], "Returned to Node %s\r", Nodename) + 4 + sizeof(void *); - C_Q_ADD(&Session->L4TX_Q, (UINT *)Msg); - PostDataAvailable(Session); - } -} - - -extern void * BUFFER; - -VOID L4BG() -{ - // PROCESS DATA QUEUED ON SESSIONS - - int n = MAXCIRCUITS; - TRANSPORTENTRY * L4 = L4TABLE; - int MaxLinks = MAXLINKS; - UCHAR Outstanding; - struct DATAMESSAGE * Msg; - struct PORTCONTROL * PORT; - struct _LINKTABLE * LINK; - int Msglen, Paclen; - - while (n--) - { - if (L4->L4USER[0] == 0) - { - L4++; - continue; - } - while (L4->L4TX_Q) - { - if (L4->L4CIRCUITTYPE & BPQHOST) - break; // Leave on TXQ - - // SEE IF BUSY - NEED DIFFERENT TESTS FOR EACH SESSION TYPE - - if (L4->L4CIRCUITTYPE & SESSION) - { - // L4 SESSION - WILL NEED BUFFERS FOR SAVING COPY, - // AND POSSIBLY FRAGMENTATION - - if (QCOUNT < 15) - break; - - if (L4->FLAGS & L4BUSY) - { - // CHOKED - MAKE SURE TIMER IS RUNNING - - if (L4->L4TIMER == 0) - L4->L4TIMER = L4->SESSIONT1; - - break; - } - - // CHECK WINDOW - - Outstanding = L4->TXSEQNO - L4->L4WS; // LAST FRAME ACKED - GIVES NUMBER OUTSTANING - - // MOD 256, SO SHOULD HANDLE WRAP?? - - if (Outstanding > L4->L4WINDOW) - break; - - } - else if (L4->L4CIRCUITTYPE & L2LINK) - { - // L2 LINK - - LINK = L4->L4TARGET.LINK; - - if (COUNT_AT_L2(LINK) > 8) - break; - } - - // Not busy, so continue - - L4->L4KILLTIMER = 0; //RESET SESSION TIMEOUTS - - if(L4->L4CROSSLINK) - L4->L4CROSSLINK->L4KILLTIMER = 0; - - Msg = Q_REM((void *)&L4->L4TX_Q); - - if (L4->L4CIRCUITTYPE & PACTOR) - { - // PACTOR-like - queue to Port - - // Stream Number is in KAMSESSION - - Msg->PORT = L4->KAMSESSION; - PORT = L4->L4TARGET.PORT; - - C_Q_ADD(&PORT->PORTTX_Q, Msg); - - continue; - } - // non-pactor - - // IF CROSSLINK, QUEUE TO NEIGHBOUR, ELSE QUEUE ON LINK ENTRY - - if (L4->L4CIRCUITTYPE & SESSION) - { - SENDL4MESSAGE(L4, Msg); - ReleaseBuffer(Msg); - continue; - } - - LINK = L4->L4TARGET.LINK; - - // If we want to enforce PACLEN this may be a good place to do it - - Msglen = Msg->LENGTH - (MSGHDDRLEN + 1); //Dont include PID - Paclen = L4->SESSPACLEN; - - if (Paclen == 0) - Paclen = 256; - - if (Msglen > Paclen) - { - // Fragment it. - // Is it best to send Paclen packets then short or equal length? - // I think equal length; - - int Fragments = (Msglen + Paclen - 1) / Paclen; - int Fraglen = Msglen / Fragments; - - if ((Msglen & 1)) // Odd - Fraglen ++; - - while (Msglen > Fraglen) - { - PDATAMESSAGE Fragment = GetBuff(); - - if (Fragment == NULL) - break; // Cant do much else - - Fragment->PORT = Msg->PORT; - Fragment->PID = Msg->PID; - Fragment->LENGTH = Fraglen + (MSGHDDRLEN + 1); - - memcpy(Fragment->L2DATA, Msg->L2DATA, Fraglen); - - C_Q_ADD(&LINK->TX_Q, Fragment); - - memcpy(Msg->L2DATA, &Msg->L2DATA[Fraglen], Msglen - Fraglen); - Msglen -= Fraglen; - Msg->LENGTH -= Fraglen; - } - - // Drop through to send last bit - - } - - C_Q_ADD(&LINK->TX_Q, Msg); - } - - // if nothing on TX Queue If there is stuff on hold queue, timer must be running - -// if (L4->L4TX_Q == 0 && L4->L4HOLD_Q) - if (L4->L4HOLD_Q) - { - if (L4->L4TIMER == 0) - { - L4->L4TIMER = L4->SESSIONT1; - } - } - - // now check for rxed frames - - while(L4->L4RX_Q) - { - Msg = Q_REM((void *)&L4->L4RX_Q); - - IFRM150(L4, Msg); - - if (L4->L4USER[0] == 0) // HAVE JUST CLOSED SESSION! - goto NextSess; - } - - // IF ACK IS PENDING, AND WE ARE AT RX WINDOW, SEND ACK NOW - - Outstanding = L4->RXSEQNO - L4->L4LASTACKED; - if (Outstanding >= L4->L4WINDOW) - SENDL4IACK(L4); -NextSess: - L4++; - } -} - -VOID CLEARSESSIONENTRY(TRANSPORTENTRY * Session) -{ - - // RETURN ANY QUEUED BUFFERS TO FREE QUEUE - - while (Session->L4TX_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4TX_Q)); - - while (Session->L4RX_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4RX_Q)); - - while (Session->L4HOLD_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4HOLD_Q)); - - if (C_Q_COUNT(&Session->L4RESEQ_Q) > Session->L4WINDOW) - { - Debugprintf("Corrupt RESEQ_Q Q Len %d Free Buffs %d", C_Q_COUNT(&Session->L4RESEQ_Q), QCOUNT); - Session->L4RESEQ_Q = 0; - } - - while (Session->L4RESEQ_Q) - ReleaseBuffer(Q_REM((void *)&Session->L4RESEQ_Q)); - - if (Session->PARTCMDBUFFER) - ReleaseBuffer(Session->PARTCMDBUFFER); - - memset(Session, 0, sizeof(TRANSPORTENTRY)); -} - -VOID CloseSessionPartner(TRANSPORTENTRY * Session) -{ - // SEND CLOSE TO CROSSLINKED SESSION AND CLEAR LOCAL SESSION - - if (Session == NULL) - return; - - if (Session->L4CROSSLINK) - CLOSECURRENTSESSION(Session->L4CROSSLINK); - - CLEARSESSIONENTRY(Session); -} - - -VOID CLOSECURRENTSESSION(TRANSPORTENTRY * Session) -{ - MESSAGE * Buffer; - struct _LINKTABLE * LINK; - -// SHUT DOWN SESSION AND UNLINK IF CROSSLINKED - - if (Session == NULL) - return; - - Session->L4CROSSLINK = NULL; - - // IF STAY FLAG SET, KEEP SESSION, AND SEND MESSAGE - - if (Session->STAYFLAG) - { - RETURNEDTONODE(Session); - Session->STAYFLAG = 0; // Only do it once - return; - } - - if (Session->L4CIRCUITTYPE & BPQHOST) - { - // BPQ HOST MODE SESSION - INDICATE STATUS CHANGE - - PBPQVECSTRUC HOST = Session->L4TARGET.HOST; - HOST->HOSTSESSION = 0; - HOST->HOSTFLAGS |= 3; /// State Change - - PostStateChange(Session); - CLEARSESSIONENTRY(Session); - return; - } - - if (Session->L4CIRCUITTYPE & PACTOR) - { - // PACTOR-type (Session linked to Port) - - struct _EXTPORTDATA * EXTPORT = Session->L4TARGET.EXTPORT; - - // If any data is queued, move it to the port entry, so it can be sent before the disconnect - - while (Session->L4TX_Q) - { - Buffer = Q_REM((void *)&Session->L4TX_Q); - EXTPORT->PORTCONTROL.PORTTXROUTINE(EXTPORT, Buffer); - } - - EXTPORT->ATTACHEDSESSIONS[Session->KAMSESSION] = NULL; - - CLEARSESSIONENTRY(Session); - return; - } - - if (Session->L4CIRCUITTYPE & SESSION) - { - // L4 SESSION TO CLOSE - - if (Session->L4HOLD_Q || Session->L4TX_Q) // WAITING FOR ACK or MORE TO SEND - SEND DISC LATER - { - Session->FLAGS |= DISCPENDING; // SEND DISC WHEN ALL DATA ACKED - return; - } - - SENDL4DISC(Session); - return; - } - - // Must be LEVEL 2 SESSION TO CLOSE - - // COPY ANY PENDING DATA TO L2 TX Q, THEN GET RID OF SESSION - - LINK = Session->L4TARGET.LINK; - - if (LINK == NULL) // just in case! - { - CLEARSESSIONENTRY(Session); - return; - } - - while (Session->L4TX_Q) - { - Buffer = Q_REM((void *)&Session->L4TX_Q); - C_Q_ADD(&LINK->TX_Q, Buffer); - } - - // NOTHING LEFT AT SESSION LEVEL - - LINK->CIRCUITPOINTER = NULL; // CLEAR REVERSE LINK - - if ((LINK->LINKWS != LINK->LINKNS) || LINK->TX_Q) - { - // STILL MORE TO SEND - SEND DISC LATER - - LINK->L2FLAGS |= DISCPENDING; // SEND DISC WHEN ALL DATA ACKED - } - else - { - // NOTHING QUEUED - CAN SEND DISC NOW - - LINK->L2STATE = 4; // DISCONNECTING - LINK->L2TIMER = 1; // USE TIMER TO KICK OFF DISC - } - - CLEARSESSIONENTRY(Session); - -} - -VOID L4TimerProc() -{ - // CHECK FOR TIMER EXPIRY - - int n = MAXCIRCUITS; - TRANSPORTENTRY * L4 = L4TABLE; - TRANSPORTENTRY * Partner; - int MaxLinks = MAXLINKS; - - while (n--) - { - if (L4->L4USER[0] == 0) - { - L4++; - continue; - } - - // CHECK FOR L4BUSY SET AND NO LONGER BUSY - - if (L4->NAKBITS & L4BUSY) - { - if ((CHECKIFBUSYL4(L4) & L4BUSY) == 0) - { - // no longer busy - - L4->NAKBITS &= ~L4BUSY; // Clear busy - L4->L4ACKREQ = 1; // SEND ACK - } - } - - if (L4->L4TIMER) // Timer Running? - { - L4->L4TIMER--; - if (L4->L4TIMER == 0) // Expired - L4TIMEOUT(L4); - } - - if (L4->L4ACKREQ) // DELAYED ACK Timer Running? - { - L4->L4ACKREQ--; - if (L4->L4ACKREQ == 0) // Expired - SENDL4IACK(L4); - } - - L4->L4KILLTIMER++; - - // IF BIT 6 OF APPLFLAGS SET, SEND MSG EVERY 11 MINS TO KEEP SESSION OPEN - - if (L4->L4CROSSLINK) // CONNECTED? - if (L4->SESS_APPLFLAGS & 0x40) - if (L4->L4KILLTIMER > 11 * 60) - AUTOTIMER(L4); - - if (L4->L4LIMIT == 0) - L4->L4LIMIT = L4LIMIT; - else - { - if (L4->L4KILLTIMER > L4->L4LIMIT) - { - L4->L4KILLTIMER = 0; - - // CLOSE THIS SESSION, AND ITS PARTNER (IF ANY) - - L4->STAYFLAG = 0; - - Partner = L4->L4CROSSLINK; - CLOSECURRENTSESSION(L4); - - if (Partner) - { - Partner->L4KILLTIMER = 0; //ITS TIMES IS ALSO ABOUT TO EXPIRE - CLOSECURRENTSESSION(Partner); // CLOSE THIS ONE - } - } - } - L4++; - } -} - -VOID L4TIMEOUT(TRANSPORTENTRY * L4) -{ - // TIMER EXPIRED - - // IF LINK UP REPEAT TEXT - // IF S2, REPEAT CONNECT REQUEST - // IF S4, REPEAT DISCONNECT REQUEST - - struct DATAMESSAGE * Msg; - struct DATAMESSAGE * Copy; - struct DEST_LIST * DEST; - - if (L4->L4STATE < 2) - return; - - if (L4->L4STATE == 2) - { - // RETRY CONNECT - - L4->L4RETRIES++; - - if (L4->L4RETRIES > L4N2) - { - // RETRIED N2 TIMES - FAIL LINK - - L4CONNECTFAILED(L4); // TELL OTHER PARTNER IT FAILED - CLEARSESSIONENTRY(L4); - return; - } - - Debugprintf("Retrying L4 Connect Request"); - - SENDL4CONNECT(L4); // Resend connect - return; - } - - if (L4->L4STATE == 4) - { - // RETRY DISCONNECT - - L4->L4RETRIES++; - - if (L4->L4RETRIES > L4N2) - { - // RETRIED N2 TIMES - FAIL LINK - - - CLEARSESSIONENTRY(L4); - return; - } - - SENDL4DISC(L4); // Resend connect - return; - } - // STATE 5 OR ABOVE - RETRY INFO - - - L4->FLAGS &= ~L4BUSY; // CANCEL CHOKE - - L4->L4RETRIES++; - - if (L4->L4RETRIES > L4N2) - { - // RETRIED N2 TIMES - FAIL LINK - - CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) - return; - } - - // RESEND ALL OUTSTANDING FRAMES - - L4->FLAGS &= 0x7F; // CLEAR CHOKED - - Msg = L4->L4HOLD_Q; - - while (Msg) - { - Copy = GetBuff(); - - if (Copy == 0) - return; - - memcpy(Copy, Msg, Msg->LENGTH); - - DEST = L4->L4TARGET.DEST; - - C_Q_ADD(&DEST->DEST_Q, Copy); - - L4FRAMESRETRIED++; - - Msg = Msg->CHAIN; - } -} - -VOID AUTOTIMER(TRANSPORTENTRY * L4) -{ - // SEND MESSAGE TO USER TO KEEP CIRCUIT OPEN - - struct DATAMESSAGE * Msg = GetBuff(); - - if (Msg == 0) - return; - - Msg->PID = 0xf0; - Msg->L2DATA[0] = 0; - Msg->L2DATA[1] = 0; - - Msg->LENGTH = MSGHDDRLEN + 3; - - C_Q_ADD(&L4->L4TX_Q, Msg); - - PostDataAvailable(L4); - - L4->L4KILLTIMER = 0; - - if (L4->L4CROSSLINK) - L4->L4CROSSLINK->L4KILLTIMER = 0; -} - -VOID L4CONNECTFAILED(TRANSPORTENTRY * L4) -{ - // CONNECT HAS TIMED OUT - SEND MESSAGE TO OTHER END - - struct DATAMESSAGE * Msg; - TRANSPORTENTRY * Partner; - UCHAR * ptr1; - char Nodename[20]; - struct DEST_LIST * DEST; - - Partner = L4->L4CROSSLINK; - - if (Partner == 0) - return; - - Msg = GetBuff(); - - if (Msg == 0) - return; - - Msg->PID = 0xf0; - - ptr1 = SetupNodeHeader(Msg); - - DEST = L4->L4TARGET.DEST; - Nodename[DecodeNodeName(DEST->DEST_CALL, Nodename)] = 0; // null terminate - - ptr1 += sprintf(ptr1, "Failure with %s\r", Nodename); - - Msg->LENGTH = (int)(ptr1 - (UCHAR *)Msg); - - C_Q_ADD(&Partner->L4TX_Q, Msg); - - PostDataAvailable(Partner); - - Partner->L4CROSSLINK = 0; // Back to command lewel -} - - -VOID ProcessIframe(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer) -{ - // IF UP/DOWN LINK, AND CIRCUIT ESTABLISHED, ADD LEVEL 3/4 HEADERS - // (FRAGMENTING IF NECESSARY), AND PASS TO TRANSPORT CONTROL - // FOR ESTABLISHED ROUTE - - // IF INTERNODE MESSAGE, PASS TO ROUTE CONTROL - - // IF UP/DOWN, AND NO CIRCUIT, PASS TO COMMAND HANDLER - - TRANSPORTENTRY * Session; - - // IT IS POSSIBLE TO MULTIPLEX NETROM AND IP STUFF ON THE SAME LINK - - if (Buffer->PID == 0xCC || Buffer->PID == 0xCD) - { - Q_IP_MSG((MESSAGE *)Buffer); - return; - } - - if (Buffer->PID == 0xCF) - { - // INTERNODE frame - - // IF LINKTYPE IS NOT 3, MUST CHECK IF WE HAVE ACCIDENTALLY ATTACHED A BBS PORT TO THE NODE - - if (LINK->LINKTYPE != 3) - { - if (LINK->CIRCUITPOINTER) - { - // MUST KILL SESSION - - InformPartner(LINK, NORMALCLOSE); // CLOSE IT - LINK->CIRCUITPOINTER = NULL; // AND UNHOOK - } - LINK->LINKTYPE = 3; // NOW WE KNOW ITS A CROSSLINK - } - - NETROMMSG(LINK, (L3MESSAGEBUFFER *)Buffer); - return; - } - - if (LINK->LINKTYPE == 3) - { - // Weve receved a non- netrom frame on an inernode link - - ReleaseBuffer(Buffer); - return; - } - - if (LINK->CIRCUITPOINTER) - { - // Pass to Session - - IFRM150(LINK->CIRCUITPOINTER, Buffer); - return; - } - - // UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE - - Session = SetupSessionForL2(LINK); - - if (Session == NULL) - return; - - CommandHandler(Session, Buffer); - return; -} - - -VOID IFRM100(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer) -{ - TRANSPORTENTRY * Session; - - if (LINK->CIRCUITPOINTER) - { - // Pass to Session - - IFRM150(LINK->CIRCUITPOINTER, Buffer); - return; - } - - // UPLINK MESSAGE WITHOUT LEVEL 4 ENTRY - CREATE ONE - - Session = SetupSessionForL2(LINK); - - if (Session == NULL) - return; - - CommandHandler(Session, Buffer); - return; -} - - -VOID IFRM150(TRANSPORTENTRY * Session, PDATAMESSAGE Buffer) -{ - TRANSPORTENTRY * Partner; - struct _LINKTABLE * LINK; - - Session->L4KILLTIMER = 0; // RESET SESSION TIMEOUT - - if (Session->L4CROSSLINK == NULL) // CONNECTED? - { - // NO, SO PASS TO COMMAND HANDLER - - CommandHandler(Session, Buffer); - return; - } - - Partner = Session->L4CROSSLINK; // TO SESSION PARTNER - - if (Partner->L4STATE == 5) - { - C_Q_ADD(&Partner->L4TX_Q, Buffer); - PostDataAvailable(Partner); - return; - } - - - - // MESSAGE RECEIVED BEFORE SESSION IS UP - CANCEL SESSION - // AND PASS MESSAGE TO COMMAND HANDLER - - if (Partner->L4CIRCUITTYPE & L2LINK) // L2 SESSION? - { - // MUST CANCEL L2 SESSION - - LINK = Partner->L4TARGET.LINK; - LINK->CIRCUITPOINTER = NULL; // CLEAR REVERSE LINK - - LINK->L2STATE = 4; // DISCONNECTING - LINK->L2TIMER = 1; // USE TIMER TO KICK OFF DISC - - LINK->L2RETRIES = LINK->LINKPORT->PORTN2 - 2; //ONLY SEND DISC ONCE - } - - CLEARSESSIONENTRY(Partner); - - Session->L4CROSSLINK = 0; // CLEAR CROSS LINK - CommandHandler(Session, Buffer); - return; -} - - -VOID SENDL4DISC(TRANSPORTENTRY * Session) -{ - L3MESSAGEBUFFER * MSG; - struct DEST_LIST * DEST = Session->L4TARGET.DEST; - - if (Session->L4STATE < 4) - { - // CIRCUIT NOT UP OR CLOSING - PROBABLY NOT YET SET UP - JUST ZAP IT - - CLEARSESSIONENTRY(Session); - return; - } - - Session->L4TIMER = Session->SESSIONT1; // START TIMER - Session->L4STATE = 4; // SET DISCONNECTING - Session->L4ACKREQ = 0; // CANCEL ACK NEEDED - - MSG = GetBuff(); - - if (MSG == NULL) - return; - - MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(MSG->L3SRCE, Session->L4MYCALL, 7); - memcpy(MSG->L3DEST, DEST->DEST_CALL, 7); - MSG->L3TTL = L3LIVES; - MSG->L4INDEX = Session->FARINDEX; - MSG->L4ID = Session->FARID; - MSG->L4TXNO = 0; - MSG->L4FLAGS = L4DREQ; - - MSG->LENGTH = (int)(&MSG->L4DATA[0] - (UCHAR *)MSG); - - C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); -} - - -void WriteL4LogLine(UCHAR * mycall, UCHAR * call, UCHAR * node) -{ - UCHAR FN[MAX_PATH]; - FILE * L4LogHandle; - time_t T; - struct tm * tm; - - char Call1[12], Call2[12], Call3[12]; - - char LogMsg[256]; - int MsgLen; - - Call1[ConvFromAX25(mycall, Call1)] = 0; - Call2[ConvFromAX25(call, Call2)] = 0; - Call3[ConvFromAX25(node, Call3)] = 0; - - - T = time(NULL); - tm = gmtime(&T); - - sprintf(FN,"%s/L4Log_%02d%02d.txt", BPQDirectory, tm->tm_mon + 1, tm->tm_mday); - - L4LogHandle = fopen(FN, "ab"); - - if (L4LogHandle == NULL) - return; - - MsgLen = sprintf(LogMsg, "%02d:%02d:%02d Call to %s from %s at Node %s\r\n", tm->tm_hour, tm->tm_min, tm->tm_sec, Call1, Call2, Call3); - - fwrite(LogMsg , 1, MsgLen, L4LogHandle); - - fclose(L4LogHandle); -} - -VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT ApplMask, UCHAR * ApplCall) -{ - // CONNECT REQUEST - SEE IF EXISTING SESSION - // IF NOT, GET AND FORMAT SESSION TABLE ENTRY - // SEND CONNECT ACK - - // EDI = _BUFFER, EBX = LINK - - TRANSPORTENTRY * L4; - int BPQNODE = 0; // NOT ONE OF MINE - char BPQPARAMS[10]; // Extended Connect Params from BPQ Node - int CONERROR; - int Index; - - memcpy(BPQPARAMS, &L4T1, 2); // SET DEFAULT T1 IN CASE NOT FROM ANOTHER BPQ NODE - - BPQPARAMS[2] = 0; // 'SPY' NOT SET - - if (CheckExcludeList(&L3MSG->L4DATA[1]) == 0) - { - SendConNAK(LINK, L3MSG); - return; - } - - if (FINDCIRCUIT(L3MSG, &L4, &Index)) - { - // SESSION EXISTS - ASSUME RETRY AND SEND ACK - - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - return; - } - - - if (L4 == 0) - { - SendConNAK(LINK, L3MSG); - return; - } - - L4->CIRCUITINDEX = Index; - - SETUPNEWCIRCUIT(LINK, L3MSG, L4, BPQPARAMS, ApplMask, &BPQNODE); - - if (L4->L4TARGET.DEST == 0) - { - // NODE NOT IN TABLE, AND TABLE FULL - CANCEL IT - - memset(L4, 0, sizeof (TRANSPORTENTRY)); - SendConNAK(LINK, L3MSG); - return; - } - // IF CONNECT TO APPL, ALLOCATE BBS PORT - - if (ApplMask == 0 || BPQPARAMS[2] == 'Z') // Z is "Spy" Connect - { - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - - return; - } - - // IF APPL CONNECT, SEE IF APPL HAS AN ALIAS - - - if (ALIASPTR[0] > ' ') - { - struct DATAMESSAGE * Msg; - - // ACCEPT THE CONNECT, THEN INVOKE THE ALIAS - - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - - Msg = GetBuff(); - - if (Msg) - { - Msg->PID = 0xf0; - memcpy(Msg->L2DATA, APPL->APPLCMD, 12); - Msg->L2DATA[12] = 13; - Msg->LENGTH = MSGHDDRLEN + 12 + 2; // 2 for PID and CR - - C_Q_ADD(&L4->L4RX_Q, Msg); - return; - } - } - - if (cATTACHTOBBS(L4, ApplMask, PACLEN, &CONERROR)) - { - SendConACK(LINK, L4, L3MSG, BPQNODE, ApplMask, ApplCall); - return; - } - - // NO BBS AVAILABLE - - CLEARSESSIONENTRY(L4); - SendConNAK(LINK, L3MSG); - return; -} - -VOID SendConACK(struct _LINKTABLE * LINK, TRANSPORTENTRY * L4, L3MESSAGEBUFFER * L3MSG, BOOL BPQNODE, UINT Applmask, UCHAR * ApplCall) -{ - // SEND CONNECT ACK - - struct TNCINFO * TNC; - - L4CONNECTSIN++; - - L3MSG->L4TXNO = L4->CIRCUITINDEX; - L3MSG->L4RXNO = L4->CIRCUITID; - - L3MSG->L4DATA[0] = L4->L4WINDOW; //WINDOW - - L3MSG->L4FLAGS = L4CACK; - - if (LogL4Connects) - WriteL4LogLine(ApplCall, L4->L4USER, L3MSG->L3SRCE); - - if (LogAllConnects) - { - char From[64]; - char toCall[12], fromCall[12], atCall[12]; - - toCall[ConvFromAX25(ApplCall, toCall)] = 0; - fromCall[ConvFromAX25(L4->L4USER, fromCall)] = 0; - atCall[ConvFromAX25(L3MSG->L3SRCE, atCall)] = 0; - - sprintf(From, "%s at Node %s", fromCall, atCall); - WriteConnectLog(From, toCall, "NETROM"); - } - - - if (CTEXTLEN && Applmask == 0) // Connects to Node (not application) - { - struct DATAMESSAGE * Msg; - int Totallen = CTEXTLEN; - int Paclen= PACLEN; - UCHAR * ptr = CTEXTMSG; - - if (Paclen == 0) - Paclen = PACLEN; - - while(Totallen) - { - Msg = GetBuff(); - - if (Msg == NULL) - break; // No Buffers - - Msg->PID = 0xf0; - - if (Paclen > Totallen) - Paclen = Totallen; - - memcpy(Msg->L2DATA, ptr, Paclen); - Msg->LENGTH = Paclen + MSGHDDRLEN + 1; - - C_Q_ADD(&L4->L4TX_Q, Msg); // SEND MESSAGE TO CALLER - PostDataAvailable(L4); - ptr += Paclen; - Totallen -= Paclen; - } - } - - L3SWAPADDRESSES(L3MSG); - - L3MSG->L3TTL = L3LIVES; - - L3MSG->LENGTH = MSGHDDRLEN + 22; // CTL 20 BYTE Header Window - - if (BPQNODE) - { - L3MSG->L4DATA[1] = L3LIVES; // Our TTL - L3MSG->LENGTH++; - } - - TNC = LINK->LINKPORT->TNC; - - if (TNC && TNC->NetRomMode) - SendVARANetromMsg(TNC, L3MSG); - else - C_Q_ADD(&LINK->TX_Q, L3MSG); -} - -int FINDCIRCUIT(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY ** REQL4, int * NewIndex) -{ - // FIND CIRCUIT FOR AN INCOMING MESSAGE - - TRANSPORTENTRY * L4 = L4TABLE; - TRANSPORTENTRY * FIRSTSPARE = NULL; - struct DEST_LIST * DEST; - - int Index = 0; - - while (Index < MAXCIRCUITS) - { - if (L4->L4USER[0] == 0) // Spare - { - if (FIRSTSPARE == NULL) - { - FIRSTSPARE = L4; - *NewIndex = Index; - } - - L4++; - Index++; - continue; - } - - DEST = L4->L4TARGET.DEST; - - if (DEST == NULL) - { - // L4 entry without a Dest shouldn't happen. (I don't think!) - - char Call1[12], Call2[12]; - - Call1[ConvFromAX25(L4->L4USER, Call1)] = 0; - Call2[ConvFromAX25(L4->L4MYCALL, Call2)] = 0; - - Debugprintf("L4 entry without Target. Type = %02x Calls %s %s", - L4->L4CIRCUITTYPE, Call1, Call2); - - L4++; - Index++; - continue; - } - - if (CompareCalls(L3MSG->L3SRCE, DEST->DEST_CALL)) - { - if (L4->FARID == L3MSG->L4ID && L4->FARINDEX == L3MSG->L4INDEX) - { - // Found it - - *REQL4 = L4; - return TRUE; - } - } - L4++; - Index++; - } - - // ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL - - *REQL4 = FIRSTSPARE; - return FALSE; -} - -VOID L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG) -{ - // EXCHANGE ORIGIN AND DEST - - char Temp[7]; - - memcpy(Temp, L3MSG->L3SRCE, 7); - memcpy(L3MSG->L3SRCE, L3MSG->L3DEST, 7); - memcpy(L3MSG->L3DEST, Temp, 7); - - L3MSG->L3DEST[6] &= 0x1E; // Mack EOA and CMD - L3MSG->L3SRCE[6] &= 0x1E; - L3MSG->L3SRCE[6] |= 1; // Set Last Call -} - -VOID SendConNAK(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) -{ - L3MSG->L4FLAGS = L4CACK | L4BUSY; // REJECT - L3MSG->L4DATA[0] = 0; // WINDOW - - L3SWAPADDRESSES(L3MSG); - L3MSG->L3TTL = L3LIVES; - - C_Q_ADD(&LINK->TX_Q, L3MSG); -} - -VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, - TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE) -{ - struct DEST_LIST * DEST; - int Maxtries = 2; // Just in case - - L4->FARINDEX = L3MSG->L4INDEX; - L4->FARID = L3MSG->L4ID; - - // Index set by caller - - L4->CIRCUITID = NEXTID; - - NEXTID++; - if (NEXTID == 0) - NEXTID++; // kEEP nON-ZERO - - L4->SESSIONT1 = L4T1; - - L4->L4WINDOW = (UCHAR)L4DEFAULTWINDOW; - - if (L3MSG->L4DATA[0] > L4DEFAULTWINDOW) - L4->L4WINDOW = L3MSG->L4DATA[0]; - - memcpy(L4->L4USER, &L3MSG->L4DATA[1], 7); // Originator's call from Call Request - - if (ApplMask) - { - // Should get APPLCALL if set ( maybe ??????????????? - } - -// MOV ESI,APPLCALLTABLEPTR -// LEA ESI,APPLCALL[ESI] - - memcpy(L4->L4MYCALL, MYCALL, 7); - - // GET BPQ EXTENDED CONNECT PARAMS IF PRESENT - - if (L3MSG->LENGTH == MSGHDDRLEN + 38 || L3MSG->LENGTH == MSGHDDRLEN + 39) - { - *BPQNODE = 1; - memcpy(BPQPARAMS, &L3MSG->L4DATA[15],L3MSG->LENGTH - (MSGHDDRLEN + 36)); - } - - L4->L4CIRCUITTYPE = SESSION | UPLINK; - L4->L4STATE = 5; - -TryAgain: - - DEST = CHECKL3TABLES(LINK, L3MSG); - - L4->L4TARGET.DEST = DEST; - - if (DEST == 0) - { - int WorstQual = 256; - struct DEST_LIST * WorstDest = NULL; - int n = MAXDESTS; - - // Node not it table and table full - - // Replace worst quality node with session counts of zero - - // But could have been excluded, so check - - if (CheckExcludeList(L3MSG->L3SRCE) == 0) - return; - - DEST = DESTS; - - while (n--) - { - if (DEST->DEST_COUNT == 0 && DEST->DEST_RTT == 0) // Not used and not INP3 - { - if (DEST->NRROUTE[0].ROUT_QUALITY < WorstQual) - { - WorstQual = DEST->NRROUTE[0].ROUT_QUALITY; - WorstDest = DEST; - } - } - DEST++; - } - - if (WorstDest) - { - REMOVENODE(WorstDest); - if (Maxtries--) - goto TryAgain; // We now have a spare (but protect against loop if something amiss) - } - - // Nothing to delete, so just ignore connect - - return; - } - - if (*BPQNODE) - { - SHORT T1; - - DEST->DEST_STATE |= 0x40; // SET BPQ _NODE BIT - memcpy((char *)&T1, BPQPARAMS, 2); - - if (T1 > 300) - L4->SESSIONT1 = L4T1; - else - L4->SESSIONT1 = T1; - } - else - L4->SESSIONT1 = L4T1; // DEFAULT TIMEOUT - - L4->SESSPACLEN = PACLEN; // DEFAULT -} - - -int CHECKIFBUSYL4(TRANSPORTENTRY * L4) -{ - // RETURN TOP BIT OF AL SET IF SESSION PARTNER IS BUSY - - int Count; - - if (L4->L4CROSSLINK) // CONNECTED? - Count = CountFramesQueuedOnSession(L4->L4CROSSLINK); - else - Count = CountFramesQueuedOnSession(L4); - - if (Count < L4->L4WINDOW) - return 0; - else - return L4BUSY; -} - -VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, UCHAR * ApplCall) -{ - // INTERNODE LINK - - TRANSPORTENTRY * L4; - struct DEST_LIST * DEST; - int Opcode; - char Nodename[20]; - char ReplyText[20]; - struct DATAMESSAGE * Msg; - TRANSPORTENTRY * Partner; - UCHAR * ptr1; - int FramesMissing; - L3MESSAGEBUFFER * Saved; - L3MESSAGEBUFFER ** Prev; - char Call[10]; - struct TNCINFO * TNC; - - L4FRAMESRX++; - - Opcode = L3MSG->L4FLAGS & 15; - - switch (Opcode) - { - case 0: - - // OPCODE 0 is used for a variety of functions, using L4INDEX and L4ID as qualifiers - // 0c0c is used for IP - - if (L3MSG->L4ID == 0x0C && L3MSG->L4INDEX == 0x0C) - { - Q_IP_MSG((MESSAGE *)L3MSG); - return; - } - - // 00 01 Seesm to be Netrom Record Route - - if (L3MSG->L4ID == 1 && L3MSG->L4INDEX == 0) - { - NRRecordRoute((UCHAR *)L3MSG, L3MSG->LENGTH); - return; - } - - ReleaseBuffer(L3MSG); - return; - - case L4CREQ: - - CONNECTREQUEST(LINK, L3MSG, ApplMask, ApplCall); - return; - } - - // OTHERS NEED A SESSION - - L4 = &L4TABLE[L3MSG->L4INDEX]; - - if (L4->CIRCUITID!= L3MSG->L4ID) - { - ReleaseBuffer(L3MSG); - return; - } - - if ((L4->L4CIRCUITTYPE & SESSION) == 0) - { - // Not an L4 Session - must be an old connection - - ReleaseBuffer(L3MSG); - return; - } - - // HAVE FOUND CORRECT SESSION ENTRY - - switch (Opcode) - { - case L4CACK: - - // CONNECT ACK - - DEST = L4->L4TARGET.DEST; - - // EXTRACT EXTENDED PARAMS IF PRESENT - - if (L3MSG->LENGTH > MSGHDDRLEN + 22) // Standard Msg - { - DEST->DEST_STATE &= 0x80; - DEST->DEST_STATE |= (L3MSG->L4DATA[1] - L3MSG->L3TTL) + 0x41; // Hops to dest + x40 - } - - Partner = L4->L4CROSSLINK; - - if (L3MSG->L4FLAGS & L4BUSY) - { - // Refused - - CLEARSESSIONENTRY(L4); - if (Partner) - Partner->L4CROSSLINK = NULL; // CLEAR CROSSLINK - - strcpy(ReplyText, "Busy from"); - } - else - { - // Connect OK - - if (L4->L4STATE == 5) - { - // MUST BE REPEAT MSG - DISCARD - - ReleaseBuffer(L3MSG); - return; - } - - L4->FARINDEX = L3MSG->L4TXNO; - L4->FARID = L3MSG->L4RXNO; - - L4->L4STATE = 5; // ACTIVE - L4->L4TIMER = 0; - L4->L4RETRIES = 0; - - L4->L4WINDOW = L3MSG->L4DATA[0]; - - strcpy(ReplyText, "Connected to"); - } - - if (Partner == 0) - { - ReleaseBuffer(L3MSG); - return; - } - - Msg = (PDATAMESSAGE)L3MSG; // reuse input buffer - - Msg->PID = 0xf0; - ptr1 = SetupNodeHeader(Msg); - - Nodename[DecodeNodeName(DEST->DEST_CALL, Nodename)] = 0; // null terminate - - ptr1 += sprintf(ptr1, "%s %s\r", ReplyText, Nodename); - - Msg->LENGTH = (int)(ptr1 - (UCHAR *)Msg); - - C_Q_ADD(&Partner->L4TX_Q, Msg); - - PostDataAvailable(Partner); - return; - - case L4DREQ: - - // DISCONNECT REQUEST - - L3MSG->L4INDEX = L4->FARINDEX; - L3MSG->L4ID = L4->FARID; - - L3MSG->L4FLAGS = L4DACK; - - L3SWAPADDRESSES(L3MSG); // EXCHANGE SOURCE AND DEST - L3MSG->L3TTL = L3LIVES; - - TNC = LINK->LINKPORT->TNC; - - if (TNC && TNC->NetRomMode) - SendVARANetromMsg(TNC, L3MSG); - else - C_Q_ADD(&LINK->TX_Q, L3MSG); - - CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT) - return; - - case L4DACK: - - CLEARSESSIONENTRY(L4); - ReleaseBuffer(L3MSG); - return; - - case L4INFO: - - //MAKE SURE SESSION IS UP - FIRST I FRAME COULD ARRIVE BEFORE CONNECT ACK - - if (L4->L4STATE == 2) - { - ReleaseBuffer(L3MSG); // SHOULD SAVE - WILL AVOID NEED TO RETRANSMIT - return; - } - - ACKFRAMES(L3MSG, L4, L3MSG->L4RXNO); - - // If DISCPENDING or STATE IS 4, THEN SESSION IS CLOSING - IGNORE ANY I FRAMES - - if ((L4->FLAGS & DISCPENDING) || L4->L4STATE == 4) - { - ReleaseBuffer(L3MSG); - return; - } - - // CHECK RECEIVED SEQUENCE - - FramesMissing = L3MSG->L4TXNO - L4->RXSEQNO; // WHAT WE GOT - WHAT WE WANT - - if (FramesMissing > 128) - FramesMissing -= 256; - - // if NUMBER OF FRAMES MISSING is -VE, THEN IN FACT IT INDICATES A REPEAT - - if (FramesMissing < 0) - { - // FRAME IS A REPEAT - - Call[ConvFromAX25(L3MSG->L3SRCE, Call)] = 0; - Debugprintf("Discarding repeated frame seq %d from %s", L3MSG->L4TXNO, Call); - - L4->L4ACKREQ = 1; - ReleaseBuffer(L3MSG); - return; - } - - if (FramesMissing > 0) - { - // EXPECTED FRAME HAS BEEN MISSED - ASK FOR IT AGAIN, - // AND KEEP THIS FRAME UNTIL MISSING ONE ARRIVES - - L4->NAKBITS |= L4NAK; // SET NAK REQUIRED - - SENDL4IACK(L4); // SEND DATA ACK COMMAND TO ACK OUTSTANDING FRAMES - - // SEE IF WE ALREADY HAVE A COPY OF THIS ONE -/* - Saved = L4->L4RESEQ_Q; - - Call[ConvFromAX25(L3MSG->L3SRCE, Call)] = 0; - Debugprintf("saving seq %d from %s", L3MSG->L4TXNO, Call); - - while (Saved) - { - if (Saved->L4TXNO == L3MSG->L4TXNO) - { - // ALREADY HAVE A COPY - DISCARD IT - - Debugprintf("Already have seq %d - discarding", L3MSG->L4TXNO); - ReleaseBuffer(L3MSG); - return; - } - - Saved = Saved->Next; - } - - C_Q_ADD(&L4->L4RESEQ_Q, L3MSG); // ADD TO CHAIN - return; -*/ - } - - // Frame is OK - -L4INFO_OK: - - if (L3MSG == 0) - { - Debugprintf("Trying to Process NULL L3 Message"); - return; - } - - L4->NAKBITS &= ~L4NAK; // CLEAR MESSAGE LOST STATE - - L4->RXSEQNO++; - - // REMOVE HEADERS, AND QUEUE INFO - - L3MSG->LENGTH -= 20; // L3/L4 Header - - if (L3MSG->LENGTH < (4 + sizeof(void *))) // No PID - { - ReleaseBuffer(L3MSG); - return; - } - - L3MSG->L3PID = 0xF0; // Normal Data PID - - memmove(L3MSG->L3SRCE, L3MSG->L4DATA, L3MSG->LENGTH - (4 + sizeof(void *))); - - REFRESHROUTE(L4); - - L4->L4ACKREQ = L4DELAY; // SEND INFO ACK AFTER L4DELAY (UNLESS I FRAME SENT) - - IFRM150(L4, (PDATAMESSAGE)L3MSG); // CHECK IF SETTING UP AND PASS ON - - // See if anything on reseq Q to process - - if (L4->L4RESEQ_Q == 0) - return; - - Prev = &L4->L4RESEQ_Q; - Saved = L4->L4RESEQ_Q; - - while (Saved) - { - if (Saved->L4TXNO == L4->RXSEQNO) // The one we want - { - // REMOVE IT FROM QUEUE,AND PROCESS IT - - *Prev = Saved->Next; // CHAIN NEXT IN CHAIN TO PREVIOUS - - OLDFRAMES++; // COUNT FOR STATS - - L3MSG = Saved; - Debugprintf("Processing Saved Message %d Address %x", L4->RXSEQNO, L3MSG); - goto L4INFO_OK; - } - - Debugprintf("Message %d %x still on Reseq Queue", Saved->L4TXNO, Saved); - - Prev = &Saved; - Saved = Saved->Next; - } - - return; - - case L4IACK: - - ACKFRAMES(L3MSG, L4, L3MSG->L4RXNO); - REFRESHROUTE(L4); - - // Drop Through - } - - // Unrecognised - Ignore - - ReleaseBuffer(L3MSG); - return; -} - - -VOID ACKFRAMES(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY * L4, int NR) -{ - // SEE HOW MANY FRAMES ARE ACKED - IF NEGATIVE, THAN THIS MUST BE A - // DELAYED REPEAT OF AN ACK ALREADY PROCESSED - - int Count = NR - L4->L4WS; - L3MESSAGEBUFFER * Saved; - struct DEST_LIST * DEST; - struct DATAMESSAGE * Msg; - struct DATAMESSAGE * Copy; - int RTT; - - - if (Count < -128) - Count += 256; - - if (Count < 0) - { - // THIS MAY BE A DELAYED REPEAT OF AN ACK ALREADY PROCESSED - - return; // IGNORE COMPLETELY - } - - while (Count > 0) - { - // new ACK - - // FRAME L4WS HAS BEED ACKED - IT SHOULD BE FIRST ON HOLD QUEUE - - Saved = Q_REM((void *)&L4->L4HOLD_Q); - - if (Saved) - ReleaseBuffer(Saved); - - // CHECK RTT SEQUENCE - - if (L4->L4WS == L4->RTT_SEQ) - { - if (L4->RTT_TIMER) - { - // FRAME BEING TIMED HAS BEEN ACKED - UPDATE DEST RTT TIMER - - DEST = L4->L4TARGET.DEST; - - RTT = GetTickCount() - L4->RTT_TIMER; - - if (DEST->DEST_RTT == 0) - DEST->DEST_RTT = RTT; - else - DEST->DEST_RTT = ((DEST->DEST_RTT * 9) + RTT) /10; // 90% Old + New - } - } - - L4->L4WS++; - Count--; - } - - L4->L4TIMER = 0; - L4->L4RETRIES = 0; - - if (NR != L4->TXSEQNO) - { - // Not all Acked - - L4->L4TIMER = L4->SESSIONT1; // RESTART TIMER - } - else - { - if ((L4->FLAGS & DISCPENDING) && L4->L4TX_Q == 0) - { - // All Acked and DISC Pending, so send it - - SENDL4DISC(L4); - return; - } - } - - // SEE IF CHOKE SET - - L4->FLAGS &= ~L4BUSY; - - if (L3MSG->L4FLAGS & L4BUSY) - { - L4->FLAGS |= L3MSG->L4FLAGS & L4BUSY; // Get Busy flag from message - - if ((L3MSG->L4FLAGS & L4NAK) == 0) - return; // Dont send while biust unless NAC received - } - - if (L3MSG->L4FLAGS & L4NAK) - { - // RETRANSMIT REQUESTED MESSAGE - WILL BE FIRST ON HOLD QUEUE - - Msg = L4->L4HOLD_Q; - - if (Msg == 0) - return; - - Copy = GetBuff(); - - if (Copy == 0) - return; - - memcpy(Copy, Msg, Msg->LENGTH); - - DEST = L4->L4TARGET.DEST; - - C_Q_ADD(&DEST->DEST_Q, Copy); - } -} - - - - - - - - - - - - - - - -VOID SENDL4IACK(TRANSPORTENTRY * Session) -{ - // SEND INFO ACK - - PL3MESSAGEBUFFER MSG = (PL3MESSAGEBUFFER)GetBuff(); - struct DEST_LIST * DEST = Session->L4TARGET.DEST; - - if (MSG == NULL) - return; - - MSG->L3PID = 0xCF; // NET MESSAGE - - memcpy(MSG->L3SRCE, Session->L4MYCALL, 7); - memcpy(MSG->L3DEST, DEST->DEST_CALL, 7); - - MSG->L3TTL = L3LIVES; - - MSG->L4INDEX = Session->FARINDEX; - MSG->L4ID = Session->FARID; - - MSG->L4TXNO = 0; - - - MSG->L4RXNO = Session->RXSEQNO; - Session->L4LASTACKED = Session->RXSEQNO; // SAVE LAST NUMBER ACKED - - MSG->L4FLAGS = L4IACK | GETBUSYBIT(Session) | Session->NAKBITS; - - MSG->LENGTH = MSGHDDRLEN + 22; - - C_Q_ADD(&DEST->DEST_Q, (UINT *)MSG); -} - - - - -/* - PUBLIC KILLSESSION -KILLSESSION: - - pushad - push ebx - CALL _CLEARSESSIONENTRY - pop ebx - popad - - JMP L4CONN90 ; REJECT - - PUBLIC CONNECTACK -CONNECTACK: -; -; EXTRACT EXTENDED PARAMS IF PRESENT -; - - CMP BYTE PTR MSGLENGTH[EDI],L4DATA+1 - JE SHORT NOTBPQ - - MOV AL,L4DATA+1[EDI] - SUB AL,L3MONR[EDI] - ADD AL,41H ; HOPS TO DEST + 40H - - MOV ESI,L4TARGET[EBX] - AND DEST_STATE[ESI],80H - OR DEST_STATE[ESI],AL ; SAVE - - PUBLIC NOTBPQ -NOTBPQ: -; -; SEE IF SUCCESS OR FAIL -; - PUSH EDI - - MOV ESI,L4TARGET[EBX] ; ADDR OF LINK/DEST ENTRY - LEA ESI,DEST_CALL[ESI] - - CALL DECODENODENAME ; CONVERT TO ALIAS:CALL - - MOV EDI,OFFSET32 CONACKCALL - MOV ECX,17 - REP MOVSB - - - POP EDI - - TEST L4FLAGS[EDI],L4BUSY - JNZ SHORT L4CONNFAILED - - CMP L4STATE[EBX],5 - JE SHORT CONNACK05 ; MUST BE REPEAT MSG - DISCARD - - MOV AX,WORD PTR L4TXNO[EDI] ; HIS INDEX - MOV WORD PTR FARINDEX[EBX],AX - - MOV L4STATE[EBX],5 ; ACTIVE - MOV L4TIMER[EBX],0 ; CANCEL TIMER - MOV L4RETRIES[EBX],0 ; CLEAR RETRY COUNT - - MOV AL,L4DATA[EDI] ; WINDOW - MOV L4WINDOW[EBX],AL ; SET WINDOW - - MOV EDX,L4CROSSLINK[EBX] ; POINT TO PARTNER -; - MOV ESI,OFFSET32 CONNECTEDMSG - MOV ECX,LCONNECTEDMSG - - JMP SHORT L4CONNCOMM - - PUBLIC L4CONNFAILED -L4CONNFAILED: -; - MOV EDX,L4CROSSLINK[EBX] ; SAVE PARTNER - pushad - push ebx - CALL _CLEARSESSIONENTRY - pop ebx - popad - - PUSH EBX - - MOV EBX,EDX - MOV L4CROSSLINK[EBX],0 ; CLEAR CROSSLINK - POP EBX - - MOV ESI,OFFSET32 BUSYMSG ; ?? BUSY - MOV ECX,LBUSYMSG - - PUBLIC L4CONNCOMM -L4CONNCOMM: - - OR EDX,EDX - JNZ SHORT L4CONNOK10 -; -; CROSSLINK HAS GONE?? - JUST CHUCK MESSAGE -; - PUBLIC CONNACK05 -CONNACK05: - - JMP L4DISCARD - - PUBLIC L4CONNOK10 -L4CONNOK10: - - PUSH EBX - PUSH ESI - PUSH ECX - - MOV EDI,_BUFFER - - ADD EDI,7 - MOV AL,0F0H - STOSB ; PID - - CALL _SETUPNODEHEADER ; PUT IN _NODE ID - - - POP ECX - POP ESI - REP MOVSB - - MOV ESI,OFFSET32 CONACKCALL - MOV ECX,17 ; MAX LENGTH ALIAS:CALL - REP MOVSB - - MOV AL,0DH - STOSB - - MOV ECX,EDI - MOV EDI,_BUFFER - SUB ECX,EDI - - MOV MSGLENGTH[EDI],CX - - MOV EBX,EDX ; CALLER'S SESSION - - LEA ESI,L4TX_Q[EBX] - CALL _Q_ADD ; SEND MESSAGE TO CALLER - - CALL _POSTDATAAVAIL - - POP EBX ; ORIGINAL CIRCUIT TABLE - RET - - - PUBLIC SENDCONNECTREPLY -SENDCONNECTREPLY: -; -; LINK SETUP COMPLETE - EBX = LINK, EDI = _BUFFER -; - CMP LINKTYPE[EBX],3 - JNE SHORT CONNECTED00 -; -; _NODE - _NODE SESSION SET UP - DONT NEED TO DO ANYTHING (I THINK!) -; - CALL RELBUFF - RET - -; -; UP/DOWN LINK -; - PUBLIC CONNECTED00 -CONNECTED00: - CMP CIRCUITPOINTER[EBX],0 - JNE SHORT CONNECTED01 - - CALL RELBUFF ; UP/DOWN WITH NO SESSION - NOONE TO TELL - RET ; NO CROSS LINK - PUBLIC CONNECTED01 -CONNECTED01: - MOV _BUFFER,EDI - PUSH EBX - PUSH ESI - PUSH ECX - - ADD EDI,7 - MOV AL,0F0H - STOSB ; PID - - CALL _SETUPNODEHEADER ; PUT IN _NODE ID - - LEA ESI,LINKCALL[EBX] - - PUSH EDI - CALL CONVFROMAX25 ; ADDR OF CALLED STATION - POP EDI - - MOV EBX,CIRCUITPOINTER[EBX] - - MOV L4STATE[EBX],5 ; SET LINK UP - - MOV EBX,L4CROSSLINK[EBX] ; TO INCOMING LINK - cmp ebx,0 - jne xxx -; -; NO LINK ??? -; - MOV EDI,_BUFFER - CALL RELBUFF - - POP ECX - POP ESI - POP EBX - - RET - - PUBLIC xxx -xxx: - - POP ECX - POP ESI - REP MOVSB - - MOV ESI,OFFSET32 _NORMCALL - MOVZX ECX,_NORMLEN - REP MOVSB - - MOV AL,0DH - STOSB - - MOV ECX,EDI - MOV EDI,_BUFFER - SUB ECX,EDI - - MOV MSGLENGTH[EDI],CX - - LEA ESI,L4TX_Q[EBX] - CALL _Q_ADD ; SEND MESSAGE TO CALLER - - CALL _POSTDATAAVAIL - - POP EBX - RET -*/ \ No newline at end of file diff --git a/LinBPQ.c b/LinBPQ.c index d25dfb7..eba6b31 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -76,7 +76,6 @@ void SaveAIS(); void initAIS(); void DRATSPoll(); VOID GetPGConfig(); -void SendBBSDataToPktMap(); extern uint64_t timeLoadedMS; @@ -1282,10 +1281,6 @@ int main(int argc, char * argv[]) printf("Mail Started\n"); Logprintf(LOG_BBS, NULL, '!', "Mail Starting"); - APIClock = 0; - - SendBBSDataToPktMap(); - } } @@ -1584,13 +1579,6 @@ int main(int argc, char * argv[]) DoHouseKeeping(FALSE); } - if (APIClock < NOW) - { - SendBBSDataToPktMap(); - APIClock = NOW + 7200; // Every 2 hours - } - - tm = gmtime(&NOW); if (tm->tm_wday == 0) // Sunday diff --git a/MailDataDefs.c b/MailDataDefs.c index abfbac2..883963a 100644 --- a/MailDataDefs.c +++ b/MailDataDefs.c @@ -205,7 +205,6 @@ int MailForInterval = 0; char zeros[NBMASK]; // For forward bitmask tests time_t MaintClock; // Time to run housekeeping -time_t APIClock; // Time to sent to MOLTE's Database struct MsgInfo * MsgnotoMsg[100000]; // Message Number to Message Slot List. diff --git a/MailTCP.c b/MailTCP.c index 91ddc3f..49478e1 100644 --- a/MailTCP.c +++ b/MailTCP.c @@ -2897,8 +2897,6 @@ SocketConn * SMTPConnect(char * Host, int Port, BOOL AMPR, struct MsgInfo * Msg, sinx.sin_addr.s_addr = INADDR_ANY; sinx.sin_port = 0; - sockptr->Timeout = 0; - if (bind(sockptr->socket, (LPSOCKADDR) &sinx, addrlen) != 0 ) { // @@ -3592,6 +3590,7 @@ VOID ProcessPOP3ClientMessage(SocketConn * sockptr, char * Buffer, int Len) if (sockptr->POP3MsgCount > sockptr->POP3MsgNum++) { sockprintf(sockptr, "RETR %d", sockptr->POP3MsgNum); + sockptr->State = WaitingForRETRResponse; } else diff --git a/Versions.h b/Versions.h index df74f46..5f0f730 100644 --- a/Versions.h +++ b/Versions.h @@ -10,14 +10,14 @@ #endif -#define KVers 6,0,24,51 -#define KVerstring "6.0.24.51\0" +#define KVers 6,0,24,50 +#define KVerstring "6.0.24.50\0" #ifdef CKernel #define Vers KVers #define Verstring KVerstring -#define Datestring "November 2024" +#define Datestring "October 2024" #define VerComments "G8BPQ Packet Switch (C Version)" KVerstring #define VerCopyright "Copyright © 2001-2024 John Wiseman G8BPQ\0" #define VerDesc "BPQ32 Switch\0" diff --git a/adif.c b/adif.c index 040942e..4e221e6 100644 --- a/adif.c +++ b/adif.c @@ -609,6 +609,7 @@ VOID ADIFWriteFreqList() fprintf(Handle, "[Channels]\r\n"); + for (i = 0; i < freqCount; i++) fprintf(Handle, "Frequency %d=%lld\r\n" , i + 1, Freqs[i]); diff --git a/bpqmail.h b/bpqmail.h index 78a1831..4ee6628 100644 --- a/bpqmail.h +++ b/bpqmail.h @@ -1191,7 +1191,6 @@ BOOL FBBDoForward(CIRCUIT * conn); BOOL FindMessagestoForward(CIRCUIT * conn); BOOL SeeifMessagestoForward(int BBSNumber, CIRCUIT * Conn); int CountMessagestoForward(struct UserInfo * user); -int CountBytestoForward(struct UserInfo * user); VOID * GetMultiLineDialogParam(HWND hDialog, int DLGItem); @@ -1634,8 +1633,6 @@ extern char ** SendWPAddrs; // Replacers WP To and VIA extern BOOL DontCheckFromCall; -extern time_t APIClock;; - // YAPP stuff #define SOH 1 diff --git a/cMain.c b/cMain.c index 4f9dc9b..b63a69c 100644 --- a/cMain.c +++ b/cMain.c @@ -50,7 +50,6 @@ VOID SendSmartID(struct PORTCONTROL * PORT); int CanPortDigi(int Port); int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); void MQTTTimer(); -void SaveMH(); #include "configstructs.h" @@ -1508,7 +1507,7 @@ BOOL Start() upnpInit(); - lastSaveSecs = CurrentSecs = lastSlowSecs = time(NULL); + CurrentSecs = lastSlowSecs = time(NULL); return 0; } @@ -2106,19 +2105,7 @@ VOID TIMERINTERRUPT() } */ } - - // Check Autosave Nodes and MH timer - - if (CurrentSecs - lastSaveSecs >= 3600) // 1 per hour - { - lastSaveSecs = CurrentSecs; - - if (AUTOSAVE == 1) - SaveNodes(); - if (AUTOSAVEMH == 1) - SaveMH(); - } - + if (L4TIMERFLAG >= 10) // 1 PER SEC { L4TIMERFLAG -= 10; diff --git a/config.c b/config.c index 818e24d..6408e25 100644 --- a/config.c +++ b/config.c @@ -174,16 +174,11 @@ extern BOOL Loopflag; extern char NodeMapServer[80]; extern char ChatMapServer[80]; -double LatFromLOC; -double LonFromLOC; - - VOID * zalloc(int len); int WritetoConsoleLocal(char * buff); char * stristr (char *ch1, char *ch2); -int FromLOC(char * Locator, double * pLat, double * pLon); VOID Consoleprintf(const char * format, ...) { @@ -347,7 +342,7 @@ static int routine[] = 14, 14, 14, 14, 14, 14 ,14, 14, 15, 0, 2, 9, 9, -2, 2, 1, 2, 2, 2, +2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 20, 20} ; // Routine to process param int PARAMLIM = sizeof(routine)/sizeof(int); @@ -929,21 +924,11 @@ NextAPRS: strcat(LOCATOR, ":"); strcat(LOCATOR, ptr2); ToLOC(atof(ptr1), atof(ptr2), LOC); - LatFromLOC = atof(ptr1); - LonFromLOC = atof(ptr2); - } else { if (strlen(ptr1) == 6) - { strcpy(LOC, ptr1); - FromLOC(LOC, &LatFromLOC, &LonFromLOC); - // Randomise in square - LatFromLOC += ((rand() / 24.0) / RAND_MAX); - LonFromLOC += ((rand() / 12.0) / RAND_MAX); - - } } } return 0; diff --git a/datadefs.c b/datadefs.c index f68c1c4..44d1fd0 100644 --- a/datadefs.c +++ b/datadefs.c @@ -49,9 +49,6 @@ char MAPCOMMENT[250] = ""; char LOC[7] = ""; // Must be in shared mem// Maidenhead Locator for Reporting char ReportDest[7]; -double LatFromLOC = 0; -double LonFromLOC = 0; - UCHAR BPQDirectory[260] = "."; UCHAR ConfigDirectory[260] = "."; UCHAR LogDirectory[260] = ""; @@ -65,7 +62,6 @@ UCHAR L3KEEP[7] = {'K'+'K','E'+'E','E'+'E','P'+'P','L'+'L','I'+'I', 0xe0}; // K time_t CurrentSecs; time_t lastSlowSecs; -time_t lastSaveSecs; char WL2KCall[10] = ""; char WL2KLoc[7] = ""; diff --git a/lzhuf32.c b/lzhuf32.c index a6828ca..3482b30 100644 --- a/lzhuf32.c +++ b/lzhuf32.c @@ -768,9 +768,6 @@ BOOL CheckifPacket(char * Via) if (FindContinent(ptr1)) return TRUE; // Packet - if (FindCountry(ptr1)) - return TRUE; // Packet - if ((_stricmp(ptr1, "MARS") == 0) || (_stricmp(ptr1, "USA") == 0)) // MARS used both return TRUE; // Packet diff --git a/mailapi.c b/mailapi.c index c1f60d8..f447e7b 100644 --- a/mailapi.c +++ b/mailapi.c @@ -705,404 +705,4 @@ packetmail_queue_length{partner="GB7NOT"} 0 1729090716916 packetmail_queue_length{partner="GB7NWL"} 0 1729090716916 packetmail_queue_length{partner="GM8BPQ"} 0 1729090716916 -*/ - - -// Stuff send to packetnodes.spots.radio/api/bbsdata/{bbsCall} -//https://nodes.ukpacketradio.network/swagger/index.html - - -/* -BbsData{ -callsign* [...] -time* [...] -hroute* [...] -peers [...] -software* [...] -version* [...] -mailQueues [...] -messages [...] -latitude [...] -longitude [...] -locator [...] -location [...] -unroutable [...] -} - -[ - -{ - "callsign": "GE8PZT", - "time": "2024-11-25T10:07:41+00:00", - "hroute": ".#24.GBR.EU", - "peers": [ - "GB7BBS", - "VE2PKT", - "GB7NXT", - "VA2OM" - ], - "software": "XrLin", - "version": "504a", - "mailQueues": [], - "messages": [ - { - "to": "TECH@WW", - "mid": "20539_GB7CIP", - "rcvd": "2024-11-24T09:27:59+00:00", - "routing": [ - "R:241124/0927Z @:GE8PZT.#24.GBR.EU [Lamanva] #:2315 XrLin504a", - - - { - "to": "TNC@WW", - "mid": "37_PA2SNK", - "rcvd": "2024-11-18T21:56:55+00:00", - "routing": [ - "R:241118/2156Z @:GE8PZT.#24.GBR.EU [] #:2215 XrLin504a", - "R:241118/2156Z 12456@VE2PKT.#TRV.QC.CAN.NOAM BPQ6.0.24", - "R:241118/2130Z 51539@VE3KPG.#ECON.ON.CAN.NOAM BPQK6.0.23", - "R:241118/2130Z 26087@VE3CGR.#SCON.ON.CAN.NOAM LinBPQ6.0.24", - "R:241118/2130Z 37521@PA8F.#ZH1.NLD.EURO LinBPQ6.0.24", - "R:241118/2129Z 48377@PI8LAP.#ZLD.NLD.EURO LinBPQ6.0.24", - "R:241118/2129Z @:PD0LPM.FRL.EURO.NLD #:33044 [Joure] $:37_PA2SNK" - ] - } - ], - "latitude": 50.145832, - "longitude": -5.125, - "locator": "IO70KD", - "location": "Lamanva", - "unroutable": [ - { - "type": "P", - "at": "WW" - }, - { - "type": "P", - "at": "G8PZT-2" - }, - { - "type": "P", - "at": "g8pzt._24.gbr.eu" - }, - { - "type": "P", - "at": "G8PZT.#24.GBR.EU" - }, - { - "type": "P", - "at": "GE8PZT.#24.GBR.EU" - }, - { - "type": "P", - "at": "G8PZT.#24.GBR.EURO" - } - ] - }, - -*/ - - -// https://packetnodes.spots.radio/swagger/index.html - -// "unroutable": [{"type": "P","at": "WW"}, {"type": "P", "at": "G8PZT.#24.GBR.EURO"}] - -char * ViaList[100000]; // Pointers to the Message Header field -char TypeList[100000]; - -int unroutableCount = 0; - - -void CheckifRoutable(struct MsgInfo * Msg) -{ - char NextBBS[64]; - int n; - - if (Msg->status == 'K') - return; - - if (Msg->via[0] == 0) // No routing - return; - - strcpy(NextBBS, Msg->via); - strlop(NextBBS, '.'); - - if (strcmp(NextBBS, BBSName) == 0) // via this BBS - return; - - if ((memcmp(Msg->fbbs, zeros, NBMASK) != 0) || (memcmp(Msg->forw, zeros, NBMASK) != 0)) // Has Forwarding Info - return; - - // See if we already have it - - for (n = 0; n < unroutableCount; n++) - { - if ((TypeList[n] == Msg->type) && strcmp(ViaList[n], Msg->via) == 0) - return; - - } - - // Add to list - - TypeList[unroutableCount] = Msg->type; - ViaList[unroutableCount] = Msg->via; - - unroutableCount++; -} - - -extern char LOC[7]; - - -DllExport VOID WINAPI SendWebRequest(char * Host, char * Request, char * Params, char * Return); - -#ifdef LINBPQ -extern double LatFromLOC; -extern double LonFromLOC; -#else -typedef int (WINAPI FAR *FARPROCX)(); -extern FARPROCX pSendWebRequest; -extern FARPROCX pGetLatLon; -double LatFromLOC = 0; -double LonFromLOC = 0; -#endif - -void SendBBSDataToPktMap() -{ - char Return[4096]; - char Request[64]; - char * Params; - char * ptr; - int paramLen; - struct MsgInfo * Msg; - - struct UserInfo * ourBBSRec = LookupCall(BBSName); - struct UserInfo * USER; - char Time[64]; - struct tm * tm; - time_t Date = time(NULL); - char Peers[2048] = "[]"; - char MsgQueues[16000] = "[]"; - char * Messages = malloc(1000000); - char * Unroutables; - int m; - char * MsgBytes; - char * Rlineptr; - char * Rlineend; - char * RLines; - char * ptr1, * ptr2; - int n; - -#ifndef LINBPQ - if (pSendWebRequest == 0) - return; // Old Version of bpq32.dll - - pGetLatLon(&LatFromLOC, &LonFromLOC); - -#endif - if (ourBBSRec == 0) - return; // Wot!! - - // Get peers and Mail Queues - - ptr = &Peers[1]; - ptr1 = &MsgQueues[1]; - - for (USER = BBSChain; USER; USER = USER->BBSNext) - { - if (strcmp(USER->Call, BBSName) != 0) - { - int Bytes; - - int Count = CountMessagestoForward(USER); - - ptr += sprintf(ptr, "\"%s\",", USER->Call); - - if (Count) - { - Bytes = CountBytestoForward(USER); - - ptr1 += sprintf(ptr1, "{\"peerCall\": \"%s\", \"numQueued\": %d, \"bytesQueued\": %d},", - USER->Call, Count, Bytes); - } - } - } - - if ((*ptr) != ']') // Have some entries - { - ptr--; // over trailing comms - *(ptr++) = ']'; - *(ptr) = 0; - } - - if ((*ptr1) != ']') // Have some entries - { - ptr1--; // over trailing comms - *(ptr1++) = ']'; - *(ptr1) = 0; - } - - // Get Messages - - strcpy(Messages, "[]"); - ptr = &Messages[1]; - - for (m = LatestMsg; m >= 1; m--) - { - if (ptr > &Messages[999000]) - break; // protect buffer - - Msg = GetMsgFromNumber(m); - - if (Msg == 0 || Msg->type == 0 || Msg->status == 0) - continue; // Protect against corrupt messages - - // Paula suggests including H and K but limit it to the last 30 days or the last 100 messages, whichever is the smaller. - -// if (Msg->status == 'K' || Msg->status == 'H') -// continue; - - if ((Date - Msg->datereceived) > 30 * 86400) // Too old - continue; - - CheckifRoutable(Msg); - - tm = gmtime(&Msg->datereceived); - - sprintf(Time, "%04d-%02d-%02dT%02d:%02d:%02d+00:00", - tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - // Get Routing - - MsgBytes = ReadMessageFile(Msg->number); - RLines = malloc(Msg->length * 2); // Very unlikely to need so much but better safe.. - - strcpy(RLines, "[]"); - - ptr2 = &RLines[1]; - - // Need to skip B2 header if B2 Message - - Rlineptr = MsgBytes; - - // If it is a B2 Message, Must Skip B2 Header - - if (Msg->B2Flags & B2Msg) - { - Rlineptr = strstr(Rlineptr, "\r\n\r\n"); - if (Rlineptr) - Rlineptr += 4; - else - Rlineptr = MsgBytes; - } - - // We have to process R: lines one at a time as we need to send each one as a separate string - - while (memcmp(Rlineptr, "R:", 2) == 0) - { - // Have R Lines - - Rlineend = strstr(Rlineptr, "\r\n"); - Rlineend[0] = 0; - ptr2 += sprintf(ptr2, "\"%s\",", Rlineptr); - - Rlineptr = Rlineend + 2; // over crlf - } - - if ((*ptr2) == ']') // no entries - continue; - - ptr2--; // over trailing comms - *(ptr2++) = ']'; - *(ptr2) = 0; - - ptr += sprintf(ptr, "{\"to\": \"%s\", \"mid\": \"%s\", \"rcvd\": \"%s\", \"routing\": %s},", - Msg->to, Msg->bid, Time, RLines); - - free(MsgBytes); - free(RLines); - - } - - if ((*ptr) != ']') // Have some entries? - { - ptr--; // over trailing comms - *(ptr++) = ']'; - *(ptr) = 0; - } - - // Get unroutables - - Unroutables = malloc((unroutableCount + 1) * 100); - - strcpy(Unroutables, "[]"); - ptr = &Unroutables[1]; - - - for (n = 0; n < unroutableCount; n++) - { - ptr += sprintf(ptr, "{\"type\": \"%c\",\"at\": \"%s\"},", TypeList[n], ViaList[n]); - } - - if ((*ptr) != ']') // Have some entries? - { - ptr--; // over trailing comms - *(ptr++) = ']'; - *(ptr) = 0; - } - - - - /* -char * ViaList[100000]; // Pointers to the Message Header field -char TypeList[100000]; - -int unroutableCount = 0; - "unroutable": [{"type": "P","at": "WW"}, {"type": "P", "at": "G8PZT.#24.GBR.EURO"}] - */ - - - tm = gmtime(&Date); - - sprintf(Time, "%04d-%02d-%02dT%02d:%02d:%02d+00:00", - tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - - - paramLen = strlen(Peers) + strlen(MsgQueues) + strlen(Messages) + strlen(Unroutables); - - Params = malloc(paramLen + 1000); - - if (Params == 0) - { - free(Messages); - free(Unroutables); - return; - } - - ptr = Params; - - sprintf(Request, "/api/bbsdata/%s", BBSName); - - ptr += sprintf(ptr, "{\"callsign\": \"%s\",\r\n", BBSName); - ptr += sprintf(ptr, "\"time\": \"%s\",\r\n", Time); - ptr += sprintf(ptr, "\"hroute\": \"%s\",\r\n", HRoute); - ptr += sprintf(ptr, "\"peers\": %s,\r\n", Peers); -#ifdef LINBPQ - ptr += sprintf(ptr, "\"software\": \"%s\",\r\n", "linbpq"); -#else - ptr += sprintf(ptr, "\"software\": \"%s\",\r\n", "BPQMail"); -#endif - ptr += sprintf(ptr, "\"version\": \"%s\",\r\n", VersionString); - ptr += sprintf(ptr, "\"mailQueues\": %s,\r\n", MsgQueues); - ptr += sprintf(ptr, "\"messages\": %s,\r\n", Messages); - ptr += sprintf(ptr, "\"latitude\": %1.6f,\r\n", LatFromLOC); - ptr += sprintf(ptr, "\"longitude\": %.6f,\r\n", LonFromLOC); - ptr += sprintf(ptr, "\"locator\": \"%s\",\r\n", LOC); - ptr += sprintf(ptr, "\"location\": \"%s\",\r\n", ourBBSRec->Address); - ptr += sprintf(ptr, "\"unroutable\": %s\r\n}\r\n", Unroutables); - - SendWebRequest("packetnodes.spots.radio", Request, Params, Return); - free(Messages); - free(Unroutables); - free(Params); -} +*/ \ No newline at end of file