Compare commits

...

4 commits

Author SHA1 Message Date
Hibby e569b24f9a Changelog! 2025-10-24 00:48:59 +01:00
Hibby 272c31f62b Refresh patches with gbp pq! 2025-10-24 00:40:43 +01:00
Hibby f99a060918 Update upstream source from tag 'upstream/6.0.25.8+repack'
Update to upstream version '6.0.25.8+repack'
with Debian dir 34f11488df
2025-10-24 00:36:53 +01:00
Hibby 453f162d22 New upstream version 6.0.25.8+repack 2025-10-24 00:36:48 +01:00
34 changed files with 2550 additions and 450 deletions

View file

@ -62,6 +62,12 @@ int (WINAPI FAR *EnumProcessesPtr)();
#include "tncinfo.h"
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
#define WSA_ACCEPT WM_USER + 1
#define WSA_DATA WM_USER + 2
#define WSA_CONNECT WM_USER + 3

View file

@ -42,11 +42,19 @@ extern int DEBUGINP3;
VOID SendNegativeInfo();
VOID SortRoutes(struct DEST_LIST * Dest);
VOID SendRTTMsg(struct ROUTE * Route);
VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame);
static VOID SendNetFrame(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame)
{
// INP3 should only ever send over an active link, so just queue the message
if (Route->TCPPort) // NETROM over TCP
{
TCPNETROMSend(Route, Frame);
ReleaseBuffer(Frame);
return;
}
if (Route->NEIGHBOUR_LINK)
C_Q_ADD(&Route->NEIGHBOUR_LINK->TX_Q, Frame);
else
@ -127,10 +135,11 @@ VOID TellINP3LinkGone(struct ROUTE * Route)
if (Route->NEIGHBOUR_LINK)
Debugprintf("BPQ32 Neighbour_Link not cleared");
// Link can have both NETROM and INP3 links
if (Route->INP3Node == 0)
// if (Route->INP3Node == 0)
DecayNETROMRoutes(Route);
else
// else
DeleteINP3Routes(Route);
}
@ -882,9 +891,11 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len
int Dummy;
char * ptr;
struct _RTTMSG * RTTMsg = (struct _RTTMSG *)&Buff->L4DATA[0];
char Normcall[10];
if (Route->NEIGHBOUR_LINK == 0)
return;
Normcall[ConvFromAX25(Route->NEIGHBOUR_LINK->LINKCALL, Normcall)] = 0;
// See if a reply to our message, or a new request
@ -896,7 +907,7 @@ VOID ProcessRTTMsg(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Buff, int Len
return;
}
if (Route->NEIGHBOUR_LINK->LINKPORT->ALLOWINP3 || Route->NEIGHBOUR_LINK->LINKPORT->ENABLEINP3)
if (Route->NEIGHBOUR_LINK->LINKPORT && (Route->NEIGHBOUR_LINK->LINKPORT->ALLOWINP3 || Route->NEIGHBOUR_LINK->LINKPORT->ENABLEINP3))
Route->INP3Node = 1;
if (Route->INP3Node == 0)
@ -1168,11 +1179,16 @@ int SendRIPTimer()
// Delay more if Locked - they could be retrying for a long time
if ((Route->NEIGHBOUR_FLAG)) // LOCKED ROUTE
INP3Delay = 1200;
if (Route->ConnectionAttempts < 5)
INP3Delay = 30;
else
INP3Delay = 600;
{
if ((Route->NEIGHBOUR_FLAG)) // LOCKED ROUTE
INP3Delay = 300;
else
INP3Delay = 120;
}
if (Route->LastConnectAttempt && (REALTIMETICKS - Route->LastConnectAttempt) < INP3Delay)
{
Route++;
@ -1181,6 +1197,8 @@ int SendRIPTimer()
// Try to activate link
Route->ConnectionAttempts++;
if (Route->INP3Node)
{
Normcall[ConvFromAX25(Route->NEIGHBOUR_CALL, Normcall)] = 0;
@ -1618,7 +1636,7 @@ VOID INP3TIMER()
}
UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen)
UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, int msglen)
{
char call[10];
int calllen;

View file

@ -45,7 +45,7 @@ extern VOID Q_ADD();
VOID __cdecl Debugprintf(const char * format, ...);
TRANSPORTENTRY * NRRSession;
time_t NRRTime;
int NRRID = 1; // Id to correlate requests and responses
/*
@ -77,8 +77,9 @@ VOID NRRecordRoute(UCHAR * Buff, int Len)
{
UCHAR * BUFFER = GetBuff();
UCHAR * ptr1;
struct _MESSAGE * Msg;
struct _MESSAGE * Msg1;
time_t Now = time(NULL);
int ID = (Msg->L4TXNO << 8) | Msg->L4RXNO;
if (BUFFER == NULL)
return;
@ -87,7 +88,18 @@ VOID NRRecordRoute(UCHAR * Buff, int Len)
*ptr1++ = 0xf0; // PID
ptr1 += sprintf(ptr1, "NRR Response in (probably) %d Secs :", (int)(Now - NRRTime));
if (BUFFER == NULL)
return;
ptr1 = &BUFFER[MSGHDDRLEN];
*ptr1++ = 0xf0; // PID
if (ID == NRRSession->NRRID)
ptr1 += sprintf(ptr1, "NRR Response in %d Secs:", (int)(Now - NRRSession->NRRTime));
else
ptr1 += sprintf(ptr1, "NRR Response:", (int)(Now - NRRSession->NRRTime));
Buff += 21 + MSGHDDRLEN;
Len -= (21 + MSGHDDRLEN);
@ -100,7 +112,7 @@ VOID NRRecordRoute(UCHAR * Buff, int Len)
if ((Buff[7] & 0x80) == 0x80) // Check turnround bit
*ptr1++ = '*';
Buff+=8;
Buff += 8;
Len -= 8;
}
@ -114,11 +126,11 @@ VOID NRRecordRoute(UCHAR * Buff, int Len)
Len = (int)(ptr1 - BUFFER);
Msg = (struct _MESSAGE *)BUFFER;
Msg1 = (struct _MESSAGE *)BUFFER;
Msg->LENGTH = Len;
Msg1->LENGTH = Len;
Msg->CHAIN = NULL;
Msg1->CHAIN = NULL;
C_Q_ADD(&NRRSession->L4TX_Q, (UINT *)BUFFER);
@ -175,7 +187,6 @@ VOID SendNRRecordRoute(struct DEST_LIST * DEST, TRANSPORTENTRY * Session)
return;
NRRSession = Session; // Save Session Pointer for reply
NRRTime = time(NULL);
Msg->Port = 0;
Msg->L3PID = NRPID;
@ -187,11 +198,16 @@ VOID SendNRRecordRoute(struct DEST_LIST * DEST, TRANSPORTENTRY * Session)
Msg->L4ID = 1;
Msg->L4INDEX = 0;
Msg->L4FLAGS = 0;
Msg->L4TXNO = NRRID << 8;
Msg->L4RXNO = NRRID & 0xff;
memcpy(Msg->L4DATA, MYCALL, 7);
Msg->L4DATA[7] = Stream + 28;
Msg->LENGTH = 8 + 21 + MSGHDDRLEN;
Session->NRRTime = time(NULL);
Session->NRRID = NRRID++;
C_Q_ADD(&DEST->DEST_Q, Msg);
}

77
Bpq32.c
View file

@ -1292,6 +1292,12 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
// Improvments to INP3 (4, 5)
// Add Node API /api/tcpqueues (5)
// Add sending link events to OARC API (disabled by default) (6)
// Fix possible program error in Telnet_Connected (7)
// Close links when program is closed down (7)
// Fix possible problem with deleting routes when using both NODES and INP3 routing on same link (7)
// Add Paula's Netromx (allows connects to different applications using Node call) (8)
// Add Netrom over TCP (8)
// Fix FRMR caused by sending SREJ when no frames outstanding (8)
#define CKernel
@ -1387,6 +1393,8 @@ void * HSMODEMExtInit(EXTPORTDATA * PortEntry);
void * FreeDataExtInit(EXTPORTDATA * PortEntry);
void * SIXPACKExtInit(EXTPORTDATA * PortEntry);
VOID RealCloseAllPrograms();
extern char * ConfigBuffer; // Config Area
VOID REMOVENODE(dest_list * DEST);
DllExport int ConvFromAX25(unsigned char * incall,unsigned char * outcall);
@ -1396,6 +1404,8 @@ VOID ADIFWriteFreqList();
void SaveAIS();
void initAIS();
void initADSB();
int CloseAllSessions();
int CloseAllLinks();
extern BOOL ADIFLogEnabled;
@ -1643,6 +1653,8 @@ BOOL IGateEnabled = TRUE;
extern int ISDelayTimer; // Time before trying to reopen APRS-IS link
extern int ISPort;
int CLOSING = 0;
UINT * WINMORTraceQ = NULL;
UINT * SetWindowTextQ = NULL;
@ -1698,6 +1710,8 @@ BOOL ReconfigFlag = FALSE;
BOOL RigReconfigFlag = FALSE;
BOOL APRSReconfigFlag = FALSE;
BOOL CloseAllNeeded = FALSE;
int CloseAllTimer = 0;
BOOL NeedWebMailRefresh = FALSE;
int AttachedPIDList[100] = {0};
@ -2379,6 +2393,52 @@ VOID TimerProcX()
CheckGuardZone();
if (CloseAllTimer == 50) // First entry
{
if (CloseAllSessions() == 0)
{
if (CloseAllLinks() == 0) // No sessions closed so close links now
CloseAllTimer = 0; // No Links so close now
else
CloseAllTimer = 39; // ~4 secs for links to close
}
}
if (CloseAllTimer == 40) // First entry
CloseAllLinks(); // No sessions closed so close links now
if (CloseAllTimer)
{
// See if any links left
struct _LINKTABLE * LINK = LINKS;
int i = MAXLINKS;
if (CloseAllTimer == 0)
RealCloseAllPrograms();
while (i--)
{
if (LINK->LINKCALL[0])
{
break;
}
if (i == 0)
{
CloseAllTimer = 0;
RealCloseAllPrograms();
return;
}
LINK++;
continue;
}
CloseAllTimer--;
if(CloseAllTimer == 0)
RealCloseAllPrograms();
}
return;
}
@ -5905,13 +5965,24 @@ DllExport VOID APIENTRY CreateNewTrayIcon()
trayMenu = NULL;
}
void hookNodeClosing(char * Reason);
DllExport VOID APIENTRY CloseAllPrograms()
{
// HANDLE hProc;
CLOSING = TRUE;
// Close all attached BPQ32 programs
// Tell BG to shut when all links are gone or after 5 secs
Closing = TRUE;
CloseAllTimer = 50;
}
VOID RealCloseAllPrograms()
{
hookNodeClosing("Shutdown");
Sleep(500);
Closing = 1;
ShowWindow(FrameWnd, SW_RESTORE);

272
Cmd.c
View file

@ -17,9 +17,7 @@ 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
@ -44,8 +42,6 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#include "tncinfo.h"
#include "telnetserver.h"
//#include "GetVersion.h"
//#define DllImport __declspec( dllimport )
@ -74,6 +70,7 @@ int CompareNode(const void *a, const void *b);
int CompareAlias(const void *a, const void *b);
int CompareRoutes(const void * a, const void * b);
void SendVARANetromNodes(struct TNCINFO * TNC, MESSAGE *Buffer);
VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest, BOOL Spy, int Service);
extern VOID KISSTX(struct KISSINFO * KISS, PMESSAGE Buffer);
@ -190,6 +187,54 @@ VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct
void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
/* Paula's NetROMX includes a service number in a CREQX message which allows a node to host lots of applications without
filling the Nodes table with SSID's
I could make these (or some of them) BPQ Commands but some will clash (eg INFO) or match an existing APPL (eg BBS)
I could use C APPL@CALL for an extended call to a node
Maybe I can detect APPL NODE so Paula's syntax will work
or both??
Standard Services are:
*/
struct NETROMX SERVICES[] = {
{0, "CMD"}, // Normal connection to Node's command line
{1, "INFO"}, // Standard Information server
{2, "PMS"}, // Personal Message System
{3, "BBS"}, // (reserved for Bulletin Board System)
{4, "DX"}, // (reserved for DX cluster/dx-spot feed)
{5, "TPP"}, // (reserved for "Tampa Ping-Pong" chat)
{7, "ECHO"}, // Echoes data back to sender
{8, "XRCHAT"}, // XRChat server
{9, "DISCARD"}, // Data sink
{10, "RMS"}, // (reserved for winlink RMS}
{11, "CHAT"}, // (reserved for BPQ chat server)
{13, "DAYTIME"}, // Local date/time (similar to RFC867)
{14, "APRS"}, // APRS Server
{15, "CUSTINF"},// (reserved for custom information file server)
{16, "WX"}, // Local weather information
{17, "TELEM"}, // (reserved for Telemetry server)
{18, "SMS"}, // Short Message System server
{19, "CHARGEN"},// Generates a test pattern
{20, "NDATA"}, // (reserved for NFTP extension)
{21, "NFTP"}, // Netrom File Transfer Protocol
{22, "NSSH"}, // (reserved for secure login - if legal?)
{23, "TELNET"}, // Normal L4 login (same as 0)
{25, "SMTP"}, // (reserved for Simple Mail Transfer Protocol)
{26, "MHEARD"}, // MHEARD server (shows MH lists)
{27, "DXLIST"}, // DX List server (shows DX lists)
{79, "FINGER"}, // Finger server
{80, "HTTP"}, // NetromWeb (HTTP over Netrom) server
{87, "NTTY"}, // Netrom TTY - Keyboard to keyboard chat
{1883, "MQTT"} // MQTT server
};
int NUMBEROFSSERVICES = sizeof(SERVICES)/sizeof(struct NETROMX);
char * __cdecl Cmdprintf(TRANSPORTENTRY * Session, char * Bufferptr, const char * format, ...)
{
@ -791,6 +836,104 @@ BOOL cATTACHTOBBS(TRANSPORTENTRY * Session, UINT Mask, int Paclen, int * AnySess
return FALSE;
}
void ConnecttoService(TRANSPORTENTRY * Session, char * Bufferptr, int ServiceIndex, char * Node, int Stay)
{
struct DEST_LIST * Dest = DESTS;
int n = MAXDESTS;
int gotDest = 0;
unsigned char axcall[7];
int Service = -1;
// Make Sure Node is Known
strcat(Node, " "); // Node table has 6 byte Aliases
while (n--)
{
if (memcmp(Dest->DEST_ALIAS, Node, 6) == 0)
{
gotDest = 1;
break;
}
Dest++;
}
if (gotDest == 0)
{
Dest = DESTS;
n = MAXDESTS;
ConvToAX25(Node, axcall);
while (n--)
{
if (CompareCalls(Dest->DEST_CALL, axcall))
{
gotDest = 1;
break;
}
Dest++;
}
}
strlop(Node, ' ');
if (gotDest == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Node %s not found\r", Node);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Session->STAYFLAG = Stay;
Service = SERVICES[ServiceIndex].ServiceNo;
Bufferptr = Cmdprintf(Session, Bufferptr, "Connecting to Service %s on Node %s \r", SERVICES[ServiceIndex].ServiceName, Node);
DoNetromConnect(Session, Bufferptr, Dest, 0, Service);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
int checkifService(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
char APPName[13];
int n = 12;
BOOL Stay = FALSE;
char * ptr, *Context;
int i;
ptr = strtok_s(CmdTail, " ", &Context);
// see if any param. if longer than two chars treat as remote node
if (ptr == 0 || strlen(ptr) < 3)
return 0;
memcpy(APPName, CMD->String, 13);
strlop(APPName, ' ');
if (Context && Context[0] == 'S')
Session->STAYFLAG = Stay;
// See if APPL is one of Paula's service
for (i = 0; i < NUMBEROFSSERVICES; i++)
{
if (strcmp(APPName, SERVICES[i].ServiceName) == 0)
{
ConnecttoService(Session, Bufferptr, i, ptr, Stay);
return 1;
}
}
return 0;
}
VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
BOOL CONFAILED = 0;
@ -799,6 +942,7 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct
char * ptr1, *ptr2;
int n = 12;
BOOL Stay = FALSE;
char * ptr, *Context;
// Copy Appl and Null Terminate
@ -817,12 +961,43 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct
return;
}
ptr = strtok_s(CmdTail, " ", &Context);
if (CmdTail[0] == 'S')
Stay = TRUE;
Session->STAYFLAG = Stay;
// ptr is first param. Context is rest of string;
if (ptr)
{
// could be Node for NETROMX connect or S flag
int i;
if (strlen(ptr) > 1)
{
if (Context && Context[0] == 'S')
Session->STAYFLAG = Stay;
// See if APPL is one of Paula's service
for (i = 0; i < NUMBEROFSSERVICES; i++)
{
if (strcmp(APPName, SERVICES[i].ServiceName) == 0)
{
ConnecttoService(Session, Bufferptr, i, ptr, Stay);
return;
}
}
// Not a service that can be accessed remotely
Bufferptr = Cmdprintf(Session, Bufferptr, "Connection to %s on a remote node is not possible\r", APPName);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
else if (ptr[0] == 'S')
Session->STAYFLAG = Stay;
}
memcpy(Session->APPL, CMD->String, 12);
// SEE IF THERE IS AN ALIAS DEFINDED FOR THIS COMMAND
@ -904,6 +1079,9 @@ VOID APPLCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct
VOID CMDI00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD)
{
if (checkifService(Session, Bufferptr, CmdTail, CMD)) // See can be used remotely
return;
Bufferptr = Cmdprintf(Session, Bufferptr, "%s", INFOMSG);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
}
@ -2229,7 +2407,7 @@ TRANSPORTENTRY * SetupNewSession(TRANSPORTENTRY * Session, char * Bufferptr)
}
VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest, BOOL Spy)
VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIST * Dest, BOOL Spy, int Service)
{
TRANSPORTENTRY * NewSess;
@ -2238,6 +2416,8 @@ VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIS
if (NewSess == NULL)
return; // Tables Full
NewSess->Service = Service;
NewSess->L4CIRCUITTYPE = SESSION + DOWNLINK;
NewSess->L4TARGET.DEST = Dest;
@ -2245,12 +2425,12 @@ VOID DoNetromConnect(TRANSPORTENTRY * Session, char * Bufferptr, struct DEST_LIS
NewSess->SPYFLAG = Spy;
ReleaseBuffer((UINT *)REPLYBUFFER);
if (Service == -1)
ReleaseBuffer((UINT *)REPLYBUFFER);
SENDL4CONNECT(NewSess);
SENDL4CONNECT(NewSess, Service);
L4CONNECTSOUT++;
return;
}
@ -2336,6 +2516,9 @@ VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C
char PortString[10];
char cmdCopy[256];
struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT;
int Service = -1;
int haveService = 0;
int i = 0;
#ifdef EXCLUDEBITS
@ -2482,7 +2665,7 @@ NoPort:
// SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED
if (axcalls[7] == 0)
if (axcalls[7] == 0 && axcalls[9] )
{
// If this connect is as a result of a command alias, don't check appls or we will loop
@ -2533,9 +2716,30 @@ NoPort:
}
}
if (axcalls[7] == 0)
// if no digis see if connect to known node. But now could have a single numeric param as a service number (Paula's Netromx)
// cmdCopy is command tail (after call)
// Make sure field is numeric
i = 0;
while (cmdCopy[i] >= '0' && cmdCopy[i]<= '9')
i++;
if (cmdCopy[i] != ' ')
goto Downlink;
else
{
// SEE IF CALL TO ANOTHER NODE
if (i > 0) // Some digits
{
haveService = 1;
Service = atoi(cmdCopy);
}
}
if (axcalls[7] == 0 || haveService)
{
// SEE IF CALL TO ANOTHER NODE
struct DEST_LIST * Dest = DESTS;
int n = MAXDESTS;
@ -2546,7 +2750,7 @@ NoPort:
{
if (memcmp(Dest->DEST_ALIAS, TextCall, 6) == 0)
{
DoNetromConnect(Session, Bufferptr, Dest, Spy);
DoNetromConnect(Session, Bufferptr, Dest, Spy, Service);
return;
}
Dest++;
@ -2560,7 +2764,7 @@ NoPort:
{
if (CompareCalls(Dest->DEST_CALL, axcalls))
{
DoNetromConnect(Session, Bufferptr, Dest, Spy);
DoNetromConnect(Session, Bufferptr, Dest, Spy, Service);
return;
}
Dest++;
@ -3723,6 +3927,8 @@ VOID MHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CM
int len;
char Digi = 0;
if (checkifService(Session, Bufferptr, CmdTail, CMD)) // See can be used remotely
return;
// Note that the MHDIGIS field may contain rubbish. You have to check End of Address bit to find
// how many digis there are
@ -4435,6 +4641,7 @@ struct CMDX COMMANDS[] =
"MAXHOPS ",7,SWITCHVAL,(size_t)&MaxHops,
"PREFERINP3 ",10,SWITCHVAL,(size_t)&PREFERINP3ROUTES,
"MAXRTT ",6,SWITCHVALW,(size_t)&MAXRTT,
"MAXTT ",6,SWITCHVALW,(size_t)&MAXRTT,
"PASSWORD ", 8, PWDCMD, 0,
"************", 12, APPLCMD, 0,
@ -4468,7 +4675,7 @@ struct CMDX COMMANDS[] =
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0,
"************", 12, APPLCMD, 0, // Apppl 32 is internal Terminal
"************", 12, APPLCMD, 0, // Apppl 32 is internal Terminal on Windows
"*** LINKED ",10,LINKCMD,0,
"CQ ",2,CQCMD,0,
"CONNECT ",1,CMDC00,0,
@ -4861,6 +5068,8 @@ VOID DoTheCommand(TRANSPORTENTRY * Session)
struct DATAMESSAGE * Buffer = REPLYBUFFER;
char * ptr1, * ptr2;
int n;
int i, Service = -1;
char * Cmd, *Node, *Context;
ptr1 = &COMMANDBUFFER[0]; //
@ -4952,6 +5161,31 @@ VOID DoTheCommand(TRANSPORTENTRY * Session)
CMD++;
}
// See if a NETROMX Service
Cmd = strtok_s(ptr1, " ", &Context);
Node = strtok_s(NULL, " ", &Context);
for (i = 0; i < NUMBEROFSSERVICES; i++)
{
if (strcmp(Cmd, SERVICES[i].ServiceName) == 0)
{
int Stay = 0;
if (Context && Context[0] == 'S')
Session->STAYFLAG = Stay;
if (Node)
{
ConnecttoService(Session, ReplyPointer, i, Node, Stay);
return;
}
// Connecting to service on local node - msy be possible sometime
}
}
Session->BADCOMMANDS++;
if (Session->BADCOMMANDS > 6) // TOO MANY ERRORS

View file

@ -49,6 +49,12 @@ extern struct CONFIGTABLE xxcfg;
#endif
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
struct TNCINFO * TNCInfo[71]; // Records are Malloc'd
extern int ReportTimer;
@ -3679,6 +3685,12 @@ char NodeAPIServer[80] = "node-api.packet.oarc.uk";
int NodeAPIPort = 13579;
int nodeStartedSent = 0;
extern time_t LastNodeStatus;
void hookNodeStarted();
VOID ResolveUpdateThread(void * Unused)
{
struct hostent * HostEnt1;
@ -3717,15 +3729,23 @@ VOID ResolveUpdateThread(void * Unused)
HostEnt3 = gethostbyname(NodeAPIServer);
if (HostEnt3)
{
memcpy(&UDPreportdest.sin_addr.s_addr,HostEnt3->h_addr,4);
if (nodeStartedSent == 0)
{
hookNodeStarted();
nodeStartedSent = 1;
LastNodeStatus = time(NULL);
}
}
if (HostEnt1 && HostEnt2)
{
Sleep(1000 * 60 * 30);
{
Sleep(1000 * 60 * 30);
continue;
}
Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net");
Sleep(1000 * 60 * 5);
}
@ -3759,13 +3779,6 @@ VOID OpenReportingSockets()
reportdest.sin_port = htons(81);
ConvToAX25("DUMMY-1", ReportDest);
}
UDPreportdest.sin_family = AF_INET;
UDPreportdest.sin_port = htons(NodeAPIPort);
if (EnableOARCAPI)
NodeAPISocket = socket(AF_INET, SOCK_DGRAM, 0);
// Set up Chat Report even if no LOCATOR reportdest.sin_family = AF_INET;
// Socket must be opened in MailChat Process

928
Events.c
View file

@ -25,6 +25,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#include <string.h>
#include "asmstrucs.h"
#include "tncinfo.h"
#include "cheaders.h"
VOID __cdecl Debugprintf(const char * format, ...);
@ -41,9 +42,9 @@ VOID __cdecl Debugprintf(const char * format, ...);
extern BOOL EventsEnabled;
void MQTTReportSession(char * Msg);
extern int MQTT;
extern time_t TimeLoaded;
int UDPSeq = 0;
int UDPSeq = 1;
extern SOCKET NodeAPISocket;
extern SOCKADDR_IN UDPreportdest;
@ -51,9 +52,23 @@ extern SOCKADDR_IN UDPreportdest;
extern char Modenames[19][10];
extern char NODECALLLOPPED[10];
extern char MYALIASLOPPED[10];
extern char LOC[7];
extern char VersionString[50];
extern double LatFromLOC;
extern double LonFromLOC;
void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Direction);
int ConvFromAX25(unsigned char * incall, unsigned char * outcall);
int COUNT_AT_L2(struct _LINKTABLE * LINK);
int CountFramesQueuedOnSession(TRANSPORTENTRY * Session);
int decodeNETROMUIMsg(unsigned char * Msg, int iLen, char * Buffer, int BufferLen);
int decodeNETROMIFrame(unsigned char * Msg, int iLen, char * Buffer, int BufferLen);
int decodeINP3RIF(unsigned char * Msg, int iLen, char * Buffer, int BufferLen);
int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen);
// Runs use specified routine on certain event
#ifndef WIN32
void RunEventProgram(char * Program, char * Param)
@ -130,9 +145,8 @@ void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _
char UDPMsg[1024];
int udplen;
LINK->ConnectTime = time(NULL);
LINK->bytesTXed = LINK->bytesRXed = 0;
LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0;
strcpy(LINK->callingCall, remotecall);
strcpy(LINK->receivingCall, ourcall);
@ -140,12 +154,14 @@ void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _
if (NodeAPISocket)
{
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
LINK->lastStatusSentTime = time(NULL);
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
@ -170,8 +186,6 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK)
double avBytesRXed = LINK->bytesRXed / (sessionTime / 60.0);
time_t Now = time(NULL);
struct tm * TM = localtime(&Now);
char UDPMsg[1024];
int udplen;
sprintf(timestamp, "%02d:%02d:%02d", TM->tm_hour, TM->tm_min, TM->tm_sec);
@ -190,36 +204,21 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK)
if (MQTT)
MQTTReportSession(Msg);
if (NodeAPISocket)
{
if (strcmp(LINK->Direction, "Out") == 0)
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall);
else
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
LINK->ConnectTime = 0;
}
LINK->ConnectTime = 0;
}
if (LINK->Sent && LINK->Received && (LINK->SentAfterCompression || LINK->ReceivedAfterExpansion))
Debugprintf("L2 Compression Stats %s %s TX %d %d %d%% RX %d %d %d%%", LINK->callingCall, LINK->receivingCall,
if (LINK->Sent && LINK->Received && (LINK->SentAfterCompression || LINK->ReceivedAfterExpansion))
Debugprintf("L2 Compression Stats %s %s TX %d %d %d%% RX %d %d %d%%", LINK->callingCall, LINK->receivingCall,
LINK->Sent, LINK->SentAfterCompression, ((LINK->Sent - LINK->SentAfterCompression) * 100) / LINK->Sent,
LINK->Received, LINK->ReceivedAfterExpansion, ((LINK->ReceivedAfterExpansion - LINK->Received) * 100) / LINK->Received);
}
}
void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK)
{
LINK->ConnectTime = time(NULL);
LINK->bytesTXed = LINK->bytesRXed = 0;
LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0;
strcpy(LINK->callingCall, ourcall);
strcpy(LINK->receivingCall, remotecall);
@ -234,13 +233,72 @@ void hookL2SessionConnected(struct _LINKTABLE * LINK)
int udplen;
if (NodeAPISocket)
{
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
{
LINK->lastStatusSentTime = time(NULL);
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Direction)
{
// Link closed. Could be normal, ie disc send/received or restried out etc
char UDPMsg[1024];
int udplen;
if (NodeAPISocket)
{
if (LINK->receivingCall[0] == 0 || LINK->callingCall[0] == 0)
return;
if (strcmp(Direction, "Out") == 0)
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\","
"\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d, \"reason\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall,
LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason);
else
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\","
"\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d, \"reason\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall,
LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void hookL2SessionStatus(struct _LINKTABLE * LINK)
{
// Send at regular intervals on open links
char UDPMsg[1024];
int udplen;
if (NodeAPISocket)
{
LINK->lastStatusSentTime = time(NULL);
if (strcmp(LINK->Direction, "Out") == 0)
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\","
"\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall,
LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, 0, LINK->framesResent);
else
udplen = sprintf(UDPMsg, "{\"@type\":\"LinkStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\","
"\"bytesSent\": %d, \"bytesRcvd\": %d, \"frmsSent\": %d, \"frmsRcvd\": %d, \"frmsQueued\": %d, \"frmsResent\": %d}",
NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall,
LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
@ -316,3 +374,795 @@ void hookL4SessionDeleted(struct TNCINFO * TNC, struct STREAMINFO * STREAM)
}
void hookNodeStarted()
{
char UDPMsg[1024];
int udplen;
#ifdef LINBPQ
char Software[80] = "LinBPQ";
if (sizeof(void *) == 4)
strcat(Software, "(32 bit)");
#else
char Software[80] = "BPQ32";
#endif
if (NodeAPISocket)
{
int ret;
udplen = sprintf(UDPMsg, "{\"@type\": \"NodeUpEvent\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"locator\": \"%s\","
"\"latitude\": %f, \"longitude\": %f, \"software\": \"%s\", \"version\": \"%s\"}",
NODECALLLOPPED, MYALIASLOPPED, LOC, LatFromLOC, LonFromLOC, Software, VersionString);
ret = sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
if (ret != udplen)
Debugprintf("%d %d %s", ret, WSAGetLastError(), UDPMsg);
}
}
void hookNodeClosing(char * Reason)
{
char UDPMsg[1024];
int udplen;
if (NodeAPISocket)
{
udplen = sprintf(UDPMsg, "{\"@type\": \"NodeDownEvent\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"reason\": \"%s\"}",
NODECALLLOPPED, MYALIASLOPPED, Reason);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void hookNodeRunning()
{
char UDPMsg[1024];
int udplen;
#ifdef LINBPQ
char Software[80] = "LinBPQ";
if (sizeof(void *) == 4)
strcat(Software, "(32 bit)");
#else
char Software[80] = "BPQ32";
#endif
if (NodeAPISocket)
{
udplen = sprintf(UDPMsg, "{\"@type\": \"NodeStatus\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"locator\": \"%s\","
"\"latitude\": %f, \"longitude\": %f, \"software\": \"%s\", \"version\": \"%s\", \"uptimeSecs\": %d}",
NODECALLLOPPED, MYALIASLOPPED, LOC, LatFromLOC, LonFromLOC, Software, VersionString, time(NULL) - TimeLoaded);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void IncomingL4ConnectionEvent(TRANSPORTENTRY * L4)
{
char UDPMsg[1024];
int udplen;
char remotecall[64];
char ourcall[64];
char circuitinfo[32];
// CACK sent to CREQ
if (NodeAPISocket)
{
remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0;
// remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0;
ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0;
sprintf(circuitinfo, ":%02x%02x", L4->FARINDEX, L4->FARID);
strcat(remotecall, circuitinfo);
sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITINDEX, L4->CIRCUITID);
strcat(ourcall, circuitinfo);
udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\","
"\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, L4->Service, remotecall, ourcall);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void OutgoingL4ConnectionEvent(TRANSPORTENTRY * L4)
{
char UDPMsg[1024];
int udplen;
char remotecall[64];
char ourcall[64];
char circuitinfo[32];
// CACK received
if (NodeAPISocket)
{
remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0;
// remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0;
ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0;
sprintf(circuitinfo, ":%02x%02x", L4->FARID, L4->FARINDEX);
strcat(remotecall, circuitinfo);
sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITID, L4->CIRCUITINDEX);
strcat(ourcall, circuitinfo);
udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\","
"\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, L4->Service, remotecall, ourcall);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
/*
{
"@type": "CircuitUpEvent",
"node": "G8PZT"
"id": 1,
"direction": "incoming",
"service": 0,
"remote": "G8PZT@G8PZT:14c0",
"local": "G8PZT-4:0001"
}
"segsSent": 5,
"segsRcvd": 27,
"segsResent": 0,
"segsQueued": 0,
"reason": "rcvd DREQ"
*/
void L4DisconnectEvent(TRANSPORTENTRY * L4, char * Direction, char * Reason)
{
char UDPMsg[1024];
int udplen;
char remotecall[64];
char ourcall[64];
char circuitinfo[32];
int Count;
// CACK received
if (NodeAPISocket)
{
remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0;
// remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0;
ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0;
sprintf(circuitinfo, ":%02x%02x", L4->FARINDEX, L4->FARID);
strcat(remotecall, circuitinfo);
sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITINDEX, L4->CIRCUITID);
strcat(ourcall, circuitinfo);
if (L4->L4CROSSLINK) // CONNECTED?
Count = CountFramesQueuedOnSession(L4->L4CROSSLINK);
else
Count = CountFramesQueuedOnSession(L4);
udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitDownEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"%s\","
"\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\", \"segsSent\": %d, \"segsRcvd\": %d, \"segsResent\": %d, \"segsQueued\": %d, \"reason\": \"%s\"}",
NODECALLLOPPED, UDPSeq++, Direction, 0, remotecall, ourcall,L4->segsSent, L4->segsRcvd, L4->segsResent, Count, Reason);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
void L4StatusSeport(TRANSPORTENTRY * L4)
{
char UDPMsg[1024];
int udplen;
char remotecall[64];
char ourcall[64];
char nodecall[16];
char circuitinfo[32];
int Count;
// CACK received
if (NodeAPISocket)
{
nodecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, nodecall)] = 0;
remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0;
ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0;
sprintf(circuitinfo, ":%02x%02x", L4->FARINDEX, L4->FARID);
strcat(remotecall, circuitinfo);
sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITINDEX, L4->CIRCUITID);
strcat(ourcall, circuitinfo);
if (L4->L4CROSSLINK) // CONNECTED?
Count = CountFramesQueuedOnSession(L4->L4CROSSLINK);
else
Count = CountFramesQueuedOnSession(L4);
udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\","
"\"service\": %d, \"remote\": %s, \"local\": \"%s\", \"segsSent\": %d, \"segsRcvd\": %d, \"segsResent\": %d, \"segsQueued\": %d}",
NODECALLLOPPED, UDPSeq++, 0, remotecall, ourcall,L4->segsSent, L4->segsRcvd, L4->segsResent, Count);
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
}
// L2/3/4 Tracing
#define PFBIT 0x10 // POLL/FINAL BIT IN CONTROL BYTE
#define NETROM_PID 0xCF
#define IP_PID 0xCC
#define ARP_PID 0xCD
char * PIDtoText(int PID)
{
switch (PID)
{
case 240:
return "DATA";
case NETROM_PID:
return "NET/ROM";
case IP_PID:
return "IP";
case ARP_PID:
return "ARP";
}
return "?";
}
void APIL2Trace(struct _MESSAGE * Message, char Dirn)
{
char UDPMsg[2048];
int udplen;
char srcecall[64];
char destcall[16];
char CR[3] = "";
char PF[2] = "";
int iLen = 0;
int CTL = Message->CTL;
char Type[16] = "Unknown";
int UIFlag = 0;
int IFlag = 0;
int UFlag = 0;
int NS;
int NR;
if ((Message->ORIGIN[6] & 1) == 0) // Digis
return;
destcall[ConvFromAX25(Message->DEST, destcall)] = 0;
srcecall[ConvFromAX25(Message->ORIGIN, srcecall)] = 0;
// See if any Digis
if ((Message->ORIGIN[6] & 1) == 0) // Digis - ignore for now
return;
if ((Message->DEST[6] & 0x80) == 0 && (Message->ORIGIN[6] & 0x80) == 0)
strcpy(CR, "V1");
else if ((Message->DEST[6] & 0x80))
strcpy(CR, "C");
else if (Message->ORIGIN[6] & 0x80)
strcpy(CR, "R");
else
strcpy(CR, "V1");
if (CTL & PFBIT)
{
if (CR[0] == 'C')
PF[0] = 'P';
else if (CR[0] == 'R')
PF[0] = 'F';
}
CTL &= ~PFBIT;
if ((CTL & 1) == 0) // I frame
{
NS = (CTL >> 1) & 7; // ISOLATE RECEIVED N(S)
NR = (CTL >> 5) & 7;
IFlag = 1;
iLen = Message->LENGTH - (MSGHDDRLEN + 16); // Dest origin ctl pid
strcpy(Type, "I");
}
else if (CTL == 3)
{
// Un-numbered Information Frame
strcpy(Type, "UI");
UIFlag = 1;
iLen = Message->LENGTH - (MSGHDDRLEN + 16); // Dest origin ctl pid
}
if (CTL & 2)
{
// UnNumbered
UFlag = 1;
switch (CTL)
{
case SABM:
strcpy(Type, "C");
break;
case SABME:
strcpy(Type, "SABME");
break;
case XID:
strcpy(Type, "XID");
break;
case TEST:
strcpy(Type, "TEST");
break;
case DISC:
strcpy(Type, "D");
break;
case DM:
strcpy(Type, "DM");
break;
case UA:
strcpy(Type, "UA");
break;
case FRMR:
strcpy(Type, "FRMR");
break;
}
}
else
{
// Super
NR = (CTL >> 5) & 7;
NS = (CTL >> 1) & 7; // ISOLATE RECEIVED N(S)
switch (CTL & 0x0F)
{
case RR:
strcpy(Type, "RR");
break;
case RNR:
strcpy(Type, "RNR");
break;
case REJ:
strcpy(Type, "REJ");
break;
case SREJ:
strcpy(Type, "SREJ");
break;
}
}
// Common to all frame types
udplen = snprintf(UDPMsg, 2048,
"{\"@type\": \"L2Trace\", \"reportFrom\": \"%s\", \"port\": \"%d\", \"srce\": \"%s\", \"dest\": \"%s\", \"ctrl\": %d,"
"\"l2type\": \"%s\", \"modulo\": 8, \"cr\": \"%s\"",
NODECALLLOPPED, Message->PORT, srcecall, destcall, Message->CTL, Type, CR);
if (UIFlag)
{
udplen += snprintf(&UDPMsg[udplen], 2048 - udplen,
", \"ilen\": %d, \"pid\": %d, \"ptcl\": \"%s\"", iLen, Message->PID, PIDtoText(Message->PID));
if (Message->PID == NETROM_PID)
{
udplen += decodeNETROMUIMsg(Message->L2DATA, iLen, &UDPMsg[udplen], 2048 - udplen);
}
}
else if (IFlag)
{
if (PF[0])
udplen += snprintf(&UDPMsg[udplen], 2048 - udplen,
", \"ilen\": %d, \"pid\": %d, \"ptcl\": \"%s\", \"pf\": \"%s\", \"rseq\": %d, \"tseq\": %d",
iLen, Message->PID, PIDtoText(Message->PID), PF, NR, NS);
else
udplen += snprintf(&UDPMsg[udplen], 2048 - udplen,
", \"ilen\": %d, \"pid\": %d, \"ptcl\": \"%s\", \"rseq\": %d, \"tseq\": %d",
iLen, Message->PID, PIDtoText(Message->PID), NR, NS);
if (Message->PID == NETROM_PID)
{
int n = decodeNETROMIFrame(Message->L2DATA, iLen, &UDPMsg[udplen], 2048 - udplen);
if (n == 0)
return; // Can't decode so don't trace anything;
udplen += n;
}
}
else if (UFlag)
{
if (PF[0])
udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"pf\": \"%s\"", PF);
}
else
{
// supervisory
if (PF[0])
udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"pf\": \"%s\", \"rseq\": %d, \"tseq\": %d", PF, NR, NS);
else
udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, ", \"rseq\": %d, \"tseq\": %d", NR, NS);
}
UDPMsg[udplen++] = '}';
UDPMsg[udplen] = 0;
// Debugprintf(UDPMsg);
sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest));
}
int decodeNETROMUIMsg(unsigned char * Msg, int iLen, char * Buffer, int BufferLen)
{
int Len = 0;
// UI with NETROM PID are assumed to by NODES broadcast (INP3 routes are sent in I frames)
// But check first byte is 0xff to be sure, or 0xfe for Paula's char Alias[7]= "";
char Dest[10];
char Node[10];
char Alias[10] = "";
memcpy(Alias, &Msg[1], 6);
strlop(Alias, ' ');
if (Msg[0] == 0xfe) // Paula's Nodes Poll
{
Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"Routing info\", \"type\": \"Routing poll\"");
return Len;
}
if (Msg[0] != 0xff)
return 0;
Msg += 7; // to first field
Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"Routing info\", \"type\": \"NODES\", \"nodes\": [");
iLen -= 7; //Header, mnemonic and signature length
if (iLen < 21) // No Entries
{
Buffer[Len++] = ']';
return Len;
}
while(iLen > 20) // Entries are 21 bytes
{
Dest[ConvFromAX25(Msg, Dest)] = 0;
Msg +=7;
memcpy(Alias, Msg, 6);
Msg +=6;
strlop(Alias, ' ');
Node[ConvFromAX25(Msg, Node)] = 0;
Msg +=7;
Len += snprintf(&Buffer[Len], BufferLen - Len, "{\"call\": \"%s\", \"alias\": \"%s\", \"via\": \"%s\", \"qual\": %d},", Dest, Alias, Node, Msg[0]);
Msg++;
iLen -= 21;
}
// Have to replace trailing , with ]
Buffer[Len - 1] = ']';
return Len;
}
int decodeNETROMIFrame(unsigned char * Msg, int iLen, char * Buffer, int BufferLen)
{
int Len = 0;
L3MESSAGE * L3MSG = (L3MESSAGE *)Msg;
char srcecall[64];
char destcall[16];
char srcUser[16];
char srcNode[16];
int Opcode;
int netromx = 0;
int service = 0;
if (Msg[0] == 0xff) // RIF?
return decodeINP3RIF(&Msg[1], iLen - 1, Buffer, BufferLen);
// Netrom L3 /4 frame. Do standard L3 header
destcall[ConvFromAX25(L3MSG->L3DEST, destcall)] = 0;
srcecall[ConvFromAX25(L3MSG->L3SRCE, srcecall)] = 0;
if (strcmp(destcall, "KEEPLI") == 0)
return 0;
Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"NetRom\", \"l3src\": \"%s\", \"l3dst\": \"%s\", \"ttl\": %d", srcecall, destcall, L3MSG->L3TTL);
// L4 Stuff
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. Ignore for now
// 00 01 Seesm to be Netrom Record Route
if (L3MSG->L4ID == 1 && L3MSG->L4INDEX == 0)
{
Len += decodeRecordRoute(L3MSG, iLen, &Buffer[Len], BufferLen - Len);
return Len;
}
case L4CREQX:
netromx = 1;
service = (L3MSG->L4RXNO << 8) | L3MSG->L4TXNO;
case L4CREQ:
srcUser[ConvFromAX25(&L3MSG->L4DATA[1], srcUser)] = 0;
srcNode[ConvFromAX25(&L3MSG->L4DATA[8], srcNode)] = 0;
if (netromx)
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN REQX\", \"fromCct\": %d, \"srcUser\": \"%s\", \"srcNode\": \"%s\", \"window\": %d, \"service\": %d",
(L3MSG->L4INDEX << 8) | L3MSG->L4ID, srcUser, srcNode, L3MSG->L4DATA[0], service);
else
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN REQ\", \"fromCct\": %d, \"srcUser\": \"%s\", \"srcNode\": \"%s\", \"window\": %d",
(L3MSG->L4INDEX << 8) | L3MSG->L4ID, srcUser, srcNode, L3MSG->L4DATA[0]);
return Len;
case L4CACK:
// Can be ACK or NACK depending on Choke flag
if (L3MSG->L4FLAGS & L4BUSY)
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN NACK\", \"toCct\": %d",
(L3MSG->L4INDEX << 8) | L3MSG->L4ID);
else
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"CONN ACK\", \"toCct\": %d, \"fromCct\": %d, \"accWin\": %d",
(L3MSG->L4INDEX << 8) | L3MSG->L4ID, (L3MSG->L4TXNO << 8) | L3MSG->L4RXNO, L3MSG->L4DATA[0]);
return Len;
case L4INFO:
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"INFO\", \"toCct\": %d, \"txSeq\": %d, \"rxSeq\": %d, \"paylen\": %d",
(L3MSG->L4INDEX << 8) | L3MSG->L4ID, L3MSG->L4TXNO, L3MSG->L4RXNO, iLen - 20);
return Len;
case L4IACK:
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"INFO ACK\", \"toCct\": %d, \"rxSeq\": %d",
(L3MSG->L4INDEX << 8) | L3MSG->L4ID, L3MSG->L4RXNO);
return Len;
case L4DREQ:
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"DISC REQ\", \"toCct\": %d", (L3MSG->L4INDEX << 8) | L3MSG->L4ID);
return Len;
case L4DACK:
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"DISC ACK\", \"toCct\": %d", (L3MSG->L4INDEX << 8) | L3MSG->L4ID);
return Len;
case L4RESET:
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"RSET\", \"fromCct\": %d", (L3MSG->L4INDEX << 8) | L3MSG->L4ID);
return Len;
/*
"NRR Request" Netrom Record Route Request
"NRR Reply" Netrom Record Route Reply
"CONN REQ" Connect Request
"CONN REQX" Extended Connect Request
"CONN ACK" Connection Acknowledgement
"CONN NAK" Connection Negative Ack (refusal)
"DISC REQ" Disconnect request
"DISC ACK" Disconnect Acknowledgement
"INFO" Information-bearing frame
"INFO ACK" Acknowledgement for an INFO frame.
"RSET" Circuit Reset (kill)
"PROT EXT" Protocol Extension (e.g. IP, NCMP etc)
"unknown" Unrecognised type (shouldn't happen)
"l4type": "CONN ACK",
"fromCct": 10,
"toCct": 23809,
"accWin": 4,
*/
}
return Len;
}
int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen)
{
int Len = 0;
char callList[512];
char * ptr1 = callList;
unsigned char * ptr = L3->L4DATA;
char call[16];
int Response = 0;
iLen -= 20;
while (iLen > 0)
{
call[ConvFromAX25(ptr, call)] = 0;
ptr1 += sprintf(ptr1, " %s", call);
if ((ptr[7] & 0x80) == 0x80) // Check turnround bit
{
*ptr1++ = '*';
Response = 1;
}
ptr += 8;
iLen -= 8;
}
*ptr1 = 0;
if (Response)
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"NRR Reply\", \"nrrId\": %d, \"nrrRoute\": \"%s\"",
(L3->L4TXNO << 8) | L3->L4RXNO, callList);
else
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"l4Type\": \"NRR Request\", \"nrrId\": %d, \"nrrRoute\": \"%s\"",
(L3->L4TXNO << 8) | L3->L4RXNO, callList);
Debugprintf(Buffer);
return Len;
}
int decodeINP3RIF(unsigned char * Msg, int iLen, char * Buffer, int BufferLen)
{
char call[10];
int calllen;
int hops;
unsigned short rtt;
unsigned int len;
unsigned int opcode;
char alias[10] = "";
UCHAR IP[6];
int i;
int Len = 0;
Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"Routing info\", \"type\": \"INP3\", \"nodes\": [");
if (iLen < 10) // No Entries
{
Buffer[Len++] = ']';
return Len;
}
while (iLen > 1)
{
calllen = ConvFromAX25(Msg, call);
call[calllen] = 0;
// Validate the call
for (i = 0; i < calllen; i++)
{
if (!isupper(call[i]) && !isdigit(call[i]) && call[i] != '-')
return 0;
}
Msg+=7;
hops = *Msg++;
rtt = (*Msg++ << 8);
rtt += *Msg++;
IP[0] = 0;
strcpy(alias, " ");
iLen -= 10;
// Process optional fields
while (*Msg && iLen > 0) // Have an option
{
len = *Msg;
opcode = *(Msg+1);
if (len < 2 || len > iLen)
return 0;
if (opcode == 0 && len < 9)
{
memcpy(alias, Msg+2, len-2);
}
else if (opcode == 1 && len < 8)
{
memcpy(IP, Msg+2, len-2);
}
Msg += len;
iLen -= len;
}
Len += snprintf(&Buffer[Len], BufferLen - Len, "{\"call\": \"%s\", \"hops\": %d, \"tt\": %d", call, hops, rtt);
if (alias[0] > ' ')
Len += snprintf(&Buffer[Len], BufferLen - Len, ", \"alias\": \"%s\"", alias);
Buffer[Len++] = '}';
Buffer[Len++] = ',';
Msg++;
iLen--; // Over EOP
}
// Have to replace trailing , with ]
Buffer[Len - 1] = ']';
return Len;
}

View file

@ -36,6 +36,12 @@ extern int (WINAPI FAR *EnumProcessesPtr)();
#include "bpq32.h"
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
#define VERSION_MAJOR 2
#define VERSION_MINOR 0
@ -819,7 +825,7 @@ pollloop:
char outbuff[1000];
int newlen;
buff->L2DATA[-1] = 6; // KISS Control
buff->PID = 6; // KISS Control (PID is just before Data)
newlen = KissEncode(&buff->L2DATA[-1], outbuff, txlen);
sendto(TNC->TCPDataSock, outbuff, newlen, 0, (struct sockaddr *)&TNC->Datadestaddr, sizeof(struct sockaddr));

View file

@ -43,6 +43,11 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
int KillTNC(struct TNCINFO * TNC);
static int RestartTNC(struct TNCINFO * TNC);
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
extern int (WINAPI FAR *GetModuleFileNameExPtr)();
extern int (WINAPI FAR *EnumProcessesPtr)();
static int Socket_Data(int sock, int error, int eventcode);

104
L2Code.c
View file

@ -125,9 +125,14 @@ void hookL2SessionConnected(struct _LINKTABLE * LINK);
int L2Compressit(unsigned char * Out, int OutSize, unsigned char * In, int Len);
VOID DeleteINP3Routes(struct ROUTE * Route);
VOID SendRTTMsg(struct ROUTE * Route);
void hookL2SessionStatus(struct _LINKTABLE * LINK);
void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Direction);
int NETROMOpenConnection(struct ROUTE * Route);
extern int REALTIMETICKS;
int linkStatusInterval = 300; // 5 mins
// MSGFLAG contains CMD/RESPONSE BITS
#define CMDBIT 4 // CURRENT MESSAGE IS A COMMAND
@ -142,6 +147,7 @@ extern int REALTIMETICKS;
extern int L2Compress;
extern int L2CompMaxframe;
extern int L2CompPaclen;
extern BOOL CLOSING;
UCHAR NO_CTEXT = 0;
UCHAR ALIASMSG = 0;
@ -1081,6 +1087,7 @@ VOID L2LINKACTIVE(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
if (CTLlessPF == DISC)
{
InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END
hookL2SessionClosed(LINK, "Normal", "In");
CLEAROUTLINK(LINK);
L2SENDUA(PORT, Buffer, ADJBUFFER);
@ -1276,9 +1283,13 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
int CONERROR;
struct ROUTE * ROUTE = NULL;
char toCall[12], fromCall[12];
if (CLOSING)
{
L2SENDDM(PORT, Buffer, ADJBUFFER);
return;
}
if (LINK == 0) // NO LINK ENTRIES - SEND DM RESPONSE
{
@ -1839,6 +1850,16 @@ BOOL InternalL2SETUPCROSSLINK(PROUTE ROUTE, int Retries)
struct PORTCONTROL * PORT;
int FRACK;
// If it is NETROM Over TCP then check for existing connection
if (ROUTE->TCPPort)
{
if (strcmp(ROUTE->TCPHost, "0.0.0.0") == 0) // listening connection so wait for other end to connect
return FALSE;
return NETROMOpenConnection(ROUTE);
}
if (FindLink(ROUTE->NEIGHBOUR_CALL, NETROMCALL, ROUTE->NEIGHBOUR_PORT, &LINK))
{
// SESSION ALREADY EXISTS
@ -2050,6 +2071,8 @@ VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * B
if (FindNeighbour(Buffer->ORIGIN, PORT->PORTNUMBER, &ROUTE))
{
ROUTE->ConnectionAttempts = 0; // Reset counter
if (ROUTE->INP3Node)
{
Debugprintf("INP3 Route to %s connected", fromCall);
@ -2093,6 +2116,8 @@ VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * B
if (LINK->L2STATE == 4) // DISCONNECTING?
{
InformPartner(LINK, NORMALCLOSE); // SEND DISC TO OTHER END
hookL2SessionClosed(LINK, "Normal", "Out");
CLEAROUTLINK(LINK);
if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF)
@ -2255,6 +2280,13 @@ VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHA
MESSAGE * Msg;
MESSAGE * Buffer;
// it shouldn't be possible to get srej when all are acked (NS = Link->NS) but just in case...
if (NS == LINK->LINKNS)
{
Debugprintf ("SREJ for our NS");
goto treatasRR;
}
LINK->L2FLAGS &= ~POLLSENT; // CLEAR I(P) or RR(P) SET
Msg = LINK->FRAMES[NS]; // is frame available?
@ -2332,6 +2364,9 @@ VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHA
return;
}
treatasRR:
// VALID RR/RNR RECEIVED
LINK->L2FLAGS &= ~RNRSET; //CLEAR RNR
@ -2664,6 +2699,7 @@ VOID PROC_I_FRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE *
LINK->bytesRXed += Length;
LINK->Received += Length - 1; // Exclude PID
LINK->framesRXed++;
// Adjust for DIGIS
@ -3239,6 +3275,10 @@ VOID SDETX(struct _LINKTABLE * LINK)
LINK->FRAMES[LINK->SDTSLOT] = Msg;
LINK->SDTSLOT ++;
LINK->SDTSLOT &= 7;
LINK->framesTXed++;
LINK->bytesTXed += sendLen;
compdata += sendLen;
complen -= sendLen;
@ -3252,6 +3292,9 @@ VOID SDETX(struct _LINKTABLE * LINK)
LINK->FRAMES[LINK->SDTSLOT] = Msg;
LINK->SDTSLOT ++;
LINK->SDTSLOT &= 7;
LINK->framesTXed++;
LINK->bytesTXed += (Msg->LENGTH - (MSGHDDRLEN + 1));
}
}
@ -3350,6 +3393,7 @@ VOID L2TimerProc()
int i = MAXLINKS;
struct _LINKTABLE * LINK = LINKS;
struct PORTCONTROL * PORT = PORTTABLE;
time_t Now = time(NULL);
while (i--)
{
@ -3357,8 +3401,14 @@ VOID L2TimerProc()
{
LINK++;
continue;
}
}
// Check for Status report time
if (LINK->lastStatusSentTime && (Now - LINK->lastStatusSentTime) > linkStatusInterval)
hookL2SessionStatus(LINK);
// CHECK FOR TIMER EXPIRY OR BUSY CLEARED
PORT = LINK->LINKPORT;
@ -3721,6 +3771,8 @@ VOID L2TIMEOUT(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT)
{
// RETRIED N TIMES SEND A COUPLE OF DISCS AND THEN CLOSE
hookL2SessionClosed(LINK, "Retried Out", "Out");
InformPartner(LINK, RETRIEDOUT); // TELL OTHER END ITS GONE
LINK->L2RETRIES -= 1; // Just send one DISC
@ -4100,20 +4152,21 @@ stayinREJ2:
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 we support SREJ send that instesd or REJ
// Dont send SREJ if clearing RNR - causes FRMR
// Dont send SREJ if clearing RNR - causes FRMR
// Latest Spec says shouldn't send SREJ as Command
// Latest Spec says shouldn't send SREJ as Command
if (SaveRNRSent || CMD == 1)
return REJ;
if (SaveRNRSent || CMD == 1)
return REJ;
if (LINK->Ver2point2) // We only allow 2.2 with SREJ Multi
return SREJ;
else
return REJ;
if (LINK->Ver2point2) // We only allow 2.2 with SREJ Multi
return SREJ;
else
return REJ;
}
}
return RR;
@ -4708,5 +4761,32 @@ int L2Compressit(unsigned char * Out, int OutSize, unsigned char * In, int Len)
}
int CloseAllLinks()
{
struct _LINKTABLE * LINK = LINKS;
int i = MAXLINKS;
int Closed = 0;
while (i--)
{
if (LINK->LINKCALL[0] == 0 || LINK->L2STATE !=5 )
{
LINK++;
continue;
}
// Close Link
InformPartner(LINK, NORMALCLOSE); // TELL OTHER END ITS GONE
LINK->L2RETRIES -= 1; // Just send one DISC
LINK->L2STATE = 4; // CLOSING
L2SENDCOMMAND(LINK, DISC | PFBIT);
Closed++;
}
return Closed;
}

View file

@ -61,9 +61,11 @@ VOID SendNETROMRoute(struct PORTCONTROL * PORT, unsigned char * axcall);
void SendVARANetromNodes(struct TNCINFO * TNC, MESSAGE *Buffer);
void SendVARANetromMsg(struct TNCINFO * TNC,L3MESSAGEBUFFER * Buffer);
VOID SENDNODESMSG(int Portnum);
VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame);
extern int NODESINPROGRESS;
extern int NODESToOnePort;
extern int CLOSING;
extern BOOL NODESINPROGRESS ;;
PPORTCONTROL L3CURRENTPORT;
@ -98,7 +100,15 @@ VOID L3BG()
{
ROUTE = DEST->NRROUTE[ActiveRoute - 1].ROUT_NEIGHBOUR;
// if NetROM over VARA pass direct to the driver
// if NetROM over VARA or NetROM over TCP pass direct to the driver
if (ROUTE && ROUTE->TCPPort)
{
PL3MESSAGEBUFFER Frame = (PL3MESSAGEBUFFER)Q_REM(&DEST->DEST_Q);
TCPNETROMSend(ROUTE, Frame);
ReleaseBuffer(Frame);
continue;
}
if (ROUTE)
{
@ -990,7 +1000,9 @@ VOID CLEARACTIVEROUTE(struct ROUTE * ROUTE, int Reason)
dest_list * DEST;
int n;
if (Reason != NORMALCLOSE || ROUTE->INP3Node)
// If a link restarts and is no longer inp3 we must still clear any inp3 routes
// if (Reason != NORMALCLOSE || ROUTE->INP3Node)
TellINP3LinkGone(ROUTE);
DEST = DESTS;
@ -1121,6 +1133,11 @@ VOID L3FastTimer()
MESSAGE * Msg;
struct PORTCONTROL * PORT = PORTTABLE;
// Not if Node is closing
if (CLOSING)
return;
INP3TIMER();
// Send Node faster if VARA

424
L4Code.c
View file

@ -49,7 +49,7 @@ BOOL FINDCIRCUIT(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY ** REQL4, int * NewInde
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);
TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE, int Service);
extern char * ALIASPTR;
void SendConACK(struct _LINKTABLE * LINK, TRANSPORTENTRY * L4, L3MESSAGEBUFFER * L3MSG, BOOL BPQNODE, UINT Applmask, UCHAR * ApplCall);
void L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG);
@ -69,6 +69,11 @@ void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode);
void SendVARANetromMsg(struct TNCINFO * TNC, PL3MESSAGEBUFFER MSG);
int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen);
int L2Compressit(unsigned char * Out, int OutSize, unsigned char * In, int Len);
void OutgoingL4ConnectionEvent(TRANSPORTENTRY * L4);
void IncomingL4ConnectionEvent(TRANSPORTENTRY * L4);
void L4DisconnectEvent(TRANSPORTENTRY * L4, char * Direction, char * Reason);
VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame);
static UINT APPLMASK;
extern BOOL LogL4Connects;
@ -131,6 +136,14 @@ VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG)
return;
}
// IS IT INP3 (L3RTT)
if (CompareCalls(L3MSG->L3DEST, L3RTT))
{
ProcessRTTMsg(LINK->NEIGHBOUR, L3MSG, L3MSG->LENGTH, L3MSG->Port);
return;
}
APPLMASK = 0; // NOT APPLICATION
if (NODE) // _NODE SUPPORT INCLUDED?
@ -167,14 +180,6 @@ VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG)
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)
@ -455,7 +460,7 @@ VOID Q_IP_MSG(MESSAGE * Buffer)
ReleaseBuffer(Buffer);
}
VOID SENDL4CONNECT(TRANSPORTENTRY * Session)
VOID SENDL4CONNECT(TRANSPORTENTRY * Session, int Service)
{
PL3MESSAGEBUFFER MSG = (PL3MESSAGEBUFFER)GetBuff();
struct DEST_LIST * DEST = Session->L4TARGET.DEST;
@ -479,12 +484,21 @@ VOID SENDL4CONNECT(TRANSPORTENTRY * Session)
MSG->L4INDEX = Session->CIRCUITINDEX;
MSG->L4ID = Session->CIRCUITID;
MSG->L4TXNO = 0;
MSG->L4RXNO = 0;
MSG->L4FLAGS = L4CREQ;
if (Service == -1) // Normal CREQ
{
MSG->L4RXNO = 0;
MSG->L4FLAGS = L4CREQ;
}
else
{
MSG->L4RXNO = Service << 8; // Paula's extended connect
MSG->L4TXNO = (Service & 0xff);
MSG->L4FLAGS = L4CREQX;
}
MSG->L4DATA[0] = L4DEFAULTWINDOW; // PROPOSED WINDOW
memcpy(&MSG->L4DATA[1], Session->L4USER, 7); // ORIG CALL
memcpy(&MSG->L4DATA[8], Session->L4MYCALL, 7);
@ -858,8 +872,6 @@ VOID L4BG()
Msglen = Msg->LENGTH - (MSGHDDRLEN + 1); //Dont include PID
LINK->bytesTXed += Msglen;
Paclen = L4->SESSPACLEN;
if (Paclen == 0)
@ -1223,7 +1235,7 @@ VOID L4TIMEOUT(TRANSPORTENTRY * L4)
Debugprintf("Retrying L4 Connect Request");
SENDL4CONNECT(L4); // Resend connect
SENDL4CONNECT(L4, L4->Service); // Resend connect
return;
}
@ -1258,10 +1270,13 @@ VOID L4TIMEOUT(TRANSPORTENTRY * L4)
// if compressed session display stats
L4DisconnectEvent(L4, "outgoing", "Retried Out");
CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT)
return;
}
// RESEND ALL OUTSTANDING FRAMES
L4->FLAGS &= 0x7F; // CLEAR CHOKED
@ -1568,19 +1583,25 @@ void WriteL4LogLine(UCHAR * mycall, UCHAR * call, UCHAR * node)
fclose(L4LogHandle);
}
VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT ApplMask, UCHAR * ApplCall)
extern struct CMDX COMMANDS[];
extern int NUMBEROFCOMMANDS;
VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT ApplMask, UCHAR * ApplCall, int Service)
{
// CONNECT REQUEST - SEE IF EXISTING SESSION
// IF NOT, GET AND FORMAT SESSION TABLE ENTRY
// SEND CONNECT ACK
// EDI = _BUFFER, EBX = LINK
// Service is for Paula's CREQX - Connect to Service
TRANSPORTENTRY * L4;
int BPQNODE = 0; // NOT ONE OF MINE
char BPQPARAMS[10]; // Extended Connect Params from BPQ Node
int CONERROR;
int Index;
char APPLCMD[13] = "";
memcpy(APPLCMD, APPL->APPLCMD, 13);
memcpy(BPQPARAMS, &L4T1, 2); // SET DEFAULT T1 IN CASE NOT FROM ANOTHER BPQ NODE
@ -1608,8 +1629,9 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl
}
L4->CIRCUITINDEX = Index;
L4->Service = Service;
SETUPNEWCIRCUIT(LINK, L3MSG, L4, BPQPARAMS, ApplMask, &BPQNODE);
SETUPNEWCIRCUIT(LINK, L3MSG, L4, BPQPARAMS, ApplMask, &BPQNODE, Service);
if (L4->L4TARGET.DEST == 0)
{
@ -1619,6 +1641,58 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl
SendConNAK(LINK, L3MSG);
return;
}
// Check for NetromX Service
if (Service > 0 && Service != 23) // 0 is CMD Hander 23 is TELNET which also connects to node
{
int i;
for (i = 0; i < NUMBEROFSSERVICES; i++)
{
if (SERVICES[i].ServiceNo == Service)
{
// Check if we have this application
struct CMDX * CMD = NULL;
int n;
char * APP = &SERVICES[i].ServiceName[0];
int APPlen = strlen(APP);
for (n = PASSCMD; n < NUMBEROFCOMMANDS; n++) // Don't allow SYSOP Commands
{
CMD = &COMMANDS[n];
if (n == APPL1) // First APPL command
{
ApplMask = 1; // FOR APPLICATION ATTACH REQUESTS
ALIASPTR = &CMDALIAS[0][0];
}
// ptr1 is input command
if (memcmp(CMD->String, APP, APPlen) == 0)
{
// At the moment I only handle connects to appls. May support other node commands later.
if (n < APPL1 + NumberofAppls)
goto doAPPLConnect;
}
ApplMask <<= 1;
ALIASPTR += ALIASLEN;
}
}
}
// Not one of our applications - refuse connect
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
@ -1630,6 +1704,7 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl
// IF APPL CONNECT, SEE IF APPL HAS AN ALIAS
doAPPLConnect:
if (ALIASPTR[0] > ' ')
{
@ -1644,7 +1719,7 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl
if (Msg)
{
Msg->PID = 0xf0;
memcpy(Msg->L2DATA, APPL->APPLCMD, 12);
memcpy(Msg->L2DATA, APPLCMD, 12);
Msg->L2DATA[12] = 13;
Msg->LENGTH = MSGHDDRLEN + 12 + 2; // 2 for PID and CR
@ -1747,10 +1822,17 @@ VOID SendConACK(struct _LINKTABLE * LINK, TRANSPORTENTRY * L4, L3MESSAGEBUFFER *
TNC = LINK->LINKPORT->TNC;
if (TNC && TNC->NetRomMode)
if (LINK->NEIGHBOUR && LINK->NEIGHBOUR->TCPPort)
{
TCPNETROMSend(LINK->NEIGHBOUR, L3MSG);
ReleaseBuffer(L3MSG);
}
else if (TNC && TNC->NetRomMode)
SendVARANetromMsg(TNC, L3MSG);
else
C_Q_ADD(&LINK->TX_Q, L3MSG);
IncomingL4ConnectionEvent(L4);
}
int FINDCIRCUIT(L3MESSAGEBUFFER * L3MSG, TRANSPORTENTRY ** REQL4, int * NewIndex)
@ -1827,7 +1909,7 @@ void L3SWAPADDRESSES(L3MESSAGEBUFFER * L3MSG)
memcpy(L3MSG->L3SRCE, L3MSG->L3DEST, 7);
memcpy(L3MSG->L3DEST, Temp, 7);
L3MSG->L3DEST[6] &= 0x1E; // Mack EOA and CMD
L3MSG->L3DEST[6] &= 0x1E; // Mask EOA and CMD
L3MSG->L3SRCE[6] &= 0x1E;
L3MSG->L3SRCE[6] |= 1; // Set Last Call
}
@ -1847,6 +1929,9 @@ VOID SendL4RESET(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG)
{
// Paula's extension
L3MSG->L4RXNO = L3MSG->L4ID;
L3MSG->L4TXNO = L3MSG->L4INDEX;
L3MSG->L4FLAGS = L4RESET;
L3SWAPADDRESSES(L3MSG);
@ -1863,7 +1948,7 @@ VOID SendL4RESET(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG)
VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG,
TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE)
TRANSPORTENTRY * L4, char * BPQPARAMS, int ApplMask, int * BPQNODE, int Service)
{
struct DEST_LIST * DEST;
int Maxtries = 2; // Just in case
@ -1882,10 +1967,10 @@ VOID SETUPNEWCIRCUIT(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG,
L4->SESSIONT1 = L4T1;
L4->L4WINDOW = (UCHAR)L4DEFAULTWINDOW;
L4->L4WINDOW = L3MSG->L4DATA[0];
if (L3MSG->L4DATA[0] > L4DEFAULTWINDOW)
L4->L4WINDOW = L3MSG->L4DATA[0];
L4->L4WINDOW = L4DEFAULTWINDOW;
memcpy(L4->L4USER, &L3MSG->L4DATA[1], 7); // Originator's call from Call Request
@ -2020,6 +2105,8 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask,
char Call[10];
struct TNCINFO * TNC;
int Service = -1; // Paula's connect to service
L4FRAMESRX++;
Opcode = L3MSG->L4FLAGS & 15;
@ -2048,9 +2135,13 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask,
ReleaseBuffer(L3MSG);
return;
case L4CREQX: // Paula's connect to service
Service = (L3MSG->L4RXNO << 8) | L3MSG->L4TXNO;
case L4CREQ:
CONNECTREQUEST(LINK, L3MSG, ApplMask, ApplCall);
CONNECTREQUEST(LINK, L3MSG, ApplMask, ApplCall, Service);
return;
}
@ -2067,7 +2158,8 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask,
while (n--)
{
if (L4->L4USER[0] && L4->FARID == L3MSG->L4ID && L4->FARINDEX == L3MSG->L4INDEX)
if ((L4->L4USER[0] && L4->FARID == L3MSG->L4RXNO && L4->FARINDEX == L3MSG->L4TXNO) || // Paula returns session in RX/TXNO, I sent in ID/INDEX
(L4->L4USER[0] && L4->FARID == L3MSG->L4ID && L4->FARINDEX == L3MSG->L4INDEX))
{
// Check L3 source call to be sure (should that be L4 source call??
@ -2075,10 +2167,9 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask,
if (memcmp(L3MSG->L3SRCE, L4->L4TARGET.DEST->DEST_CALL, 7) == 0)
{
L4DisconnectEvent(L4, "incoming", "RESET Received");
CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT)
}
ReleaseBuffer(L3MSG);
return;
}
L4++;
}
@ -2156,6 +2247,9 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask,
L4->L4WINDOW = L3MSG->L4DATA[0];
strcpy(ReplyText, "Connected to");
OutgoingL4ConnectionEvent(L4);
}
if (Partner == 0)
@ -2194,16 +2288,25 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask,
TNC = LINK->LINKPORT->TNC;
if (TNC && TNC->NetRomMode)
if (LINK->NEIGHBOUR && LINK->NEIGHBOUR->TCPPort)
{
TCPNETROMSend(LINK->NEIGHBOUR, L3MSG);
ReleaseBuffer(L3MSG);
}
else if (TNC && TNC->NetRomMode)
SendVARANetromMsg(TNC, L3MSG);
else
C_Q_ADD(&LINK->TX_Q, L3MSG);
L4DisconnectEvent(L4, "incoming", "DREQ Received");
CloseSessionPartner(L4); // SEND CLOSE TO PARTNER (IF PRESENT)
return;
case L4DACK:
L4DisconnectEvent(L4, "outgoing", "DACK Received");
CLEARSESSIONENTRY(L4);
ReleaseBuffer(L3MSG);
return;
@ -2640,241 +2743,32 @@ VOID SENDL4IACK(TRANSPORTENTRY * Session)
}
int CloseAllSessions()
{
int n = MAXCIRCUITS;
TRANSPORTENTRY * L4 = L4TABLE;
TRANSPORTENTRY * Partner;
int MaxLinks = MAXLINKS;
int Closed = 0;
while (n--)
{
if (L4->L4USER[0] == 0)
{
L4++;
continue;
}
/*
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
Closed++;
POP ECX
POP ESI
POP EBX
RET
Partner = L4->L4CROSSLINK;
PUBLIC xxx
xxx:
POP ECX
POP ESI
REP MOVSB
CLOSECURRENTSESSION(L4);
if (Partner)
CLOSECURRENTSESSION(Partner); // CLOSE THIS ONE
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
*/
L4++;
}
return Closed;
}

View file

@ -83,6 +83,8 @@ void RHPPoll();
VOID GetPGConfig();
void SendBBSDataToPktMap();
void CloseAllLinks();
void hookNodeClosing(char * Reason);
extern uint64_t INP3timeLoadedMS;
@ -262,9 +264,9 @@ extern char MailDir[MAX_PATH];
extern time_t MaintClock; // Time to run housekeeping
#ifdef WIN32
BOOL KEEPGOING = 30; // 5 secs to shut down
int KEEPGOING = 30; // 5 secs to shut down
#else
BOOL KEEPGOING = 50; // 5 secs to shut down
int KEEPGOING = 50; // 5 secs to shut down
#endif
BOOL Restarting = FALSE;
BOOL CLOSING = FALSE;
@ -337,6 +339,7 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
// Handle the CTRL-C signal.
case CTRL_C_EVENT:
printf( "Ctrl-C event\n\n" );
CloseAllLinks();
CLOSING = TRUE;
Beep( 750, 300 );
return( TRUE );
@ -344,7 +347,8 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
// CTRL-CLOSE: confirm that the user wants to exit.
case CTRL_CLOSE_EVENT:
CLOSING = TRUE;
CloseAllLinks();
CLOSING = TRUE;
printf( "Ctrl-Close event\n\n" );
Sleep(20000);
Beep( 750, 300 );
@ -354,7 +358,8 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
case CTRL_BREAK_EVENT:
Beep( 900, 200 );
printf( "Ctrl-Break event\n\n" );
CLOSING = TRUE;
CloseAllLinks();
CLOSING = TRUE;
Beep( 750, 300 );
return FALSE;
@ -366,7 +371,8 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
case CTRL_SHUTDOWN_EVENT:
Beep( 750, 500 );
printf( "Ctrl-Shutdown event\n\n" );
CLOSING = TRUE;
CloseAllLinks();
CLOSING = TRUE;
Beep( 750, 300 );
return FALSE;
@ -399,6 +405,9 @@ static void segvhandler(int sig)
write(STDOUT_FILENO, msg, strlen(msg));
backtrace_symbols_fd(array, size, STDOUT_FILENO);
hookNodeClosing("sigsegv");
Sleep(500);
exit(1);
}
@ -419,6 +428,9 @@ static void abrthandler(int sig)
write(STDOUT_FILENO, msg, strlen(msg));
backtrace_symbols_fd(array, size, STDOUT_FILENO);
hookNodeClosing("sigabrt");
Sleep(500);
exit(1);
}
@ -427,12 +439,14 @@ static void sigterm_handler(int sig)
{
syslog(LOG_INFO, "terminating on SIGTERM\n");
CLOSING = TRUE;
CloseAllLinks();
}
static void sigint_handler(int sig)
{
printf("terminating on SIGINT\n");
CLOSING = TRUE;
CloseAllLinks();
}
@ -1682,6 +1696,9 @@ int main(int argc, char * argv[])
Slowtimer = 0;
}
hookNodeClosing("Shutdown");
Sleep(500);
printf("Closing Ports\n");
CloseTNCEmulator();

View file

@ -59,7 +59,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#define NODES_SIG 0xFF
UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen);
UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, int msglen);
char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen);
UCHAR * DISPLAYIPDATAGRAM(IPMSG * IP, UCHAR * Output, int MsgLen);
@ -655,12 +655,13 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen)
char Node[10];
UCHAR TTL, Index, ID, TXNO, RXNO, OpCode, Flags, Window;
UCHAR * ptr = &ADJBUFFER->L2DATA[0];
int service = 0;
int netromx = 0; // Set if Paula's connect to service
if (ADJBUFFER->L2DATA[0] == NODES_SIG)
{
// Display NODES
// If an INP3 RIF (type <> UI) decode as such
if (ADJBUFFER->CTL != 3) // UI
@ -722,6 +723,12 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen)
switch (OpCode)
{
case L4CREQX: // Paula's connect to service
netromx = 1;
service = (RXNO << 8) | TXNO;
case L4CREQ:
Window = *(ptr++);
@ -730,7 +737,10 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen)
Node[ConvFromAX25(ptr, Node)] = 0;
ptr +=7;
Output += sprintf((char *)Output, "<CON REQ> w=%d %s at %s", Window, Dest, Node);
if (netromx)
Output += sprintf((char *)Output, "<CON REQX> w=%d %d@%s at %s", Window, service, Dest, Node);
else
Output += sprintf((char *)Output, "<CON REQ> w=%d %s at %s", Window, Dest, Node);
if (MsgLen > 38) // BPQ Extended Params
{
@ -745,7 +755,7 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen)
if (Flags & L4BUSY) // BUSY RETURNED
return Output + sprintf((char *)Output, " <CON NAK> - BUSY");
return Output + sprintf((char *)Output, " <CON ACK> w=%d my cct=%02X%02X", ptr[1], TXNO, RXNO);
return Output + sprintf((char *)Output, " <CON ACK> w=%d my cct=%02X%02X", ptr[0], TXNO, RXNO);
case L4DREQ:

551
NETROMTCP.c Normal file
View file

@ -0,0 +1,551 @@
/*
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
*/
/*
Netrom over TCP Support
This is intended for operation over radio links with an IP interface, eg New Packet Radio or possibly microwave links
To simplify interface to the rest of the oode dummy LINK and PORT records are created
Packet Format is Length (2 byte little endian) Call (10 bytes ASCII) NETROM L3/4 Packet, starting 0xcf (to detect framing errors).
A TCP message can contain multiple packets and/or partial packets
It uses the Telnet Server, with port defined in NETROMPORT
ROUTE definitions have an extra field, the TCP Port Number
*/
//#pragma data_seg("_BPQDATA")
#define _CRT_SECURE_NO_DEPRECATE
#include "time.h"
#include "stdio.h"
#include <fcntl.h>
//#include "vmm.h"
#include "cheaders.h"
#include "asmstrucs.h"
#include "telnetserver.h"
#define NETROM_PID 0xCF
void NETROMConnectionLost(struct ConnectionInfo * sockptr);
int DataSocket_ReadNETROM(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info, int portNo);
int NETROMTCPConnect(struct ROUTE * Route, struct ConnectionInfo * sockptr);
void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info);
VOID SendRTTMsg(struct ROUTE * Route);
BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE);
VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG);
int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS);
VOID L3LINKCLOSED(struct _LINKTABLE * LINK, int Reason);
struct NRTCPMsg
{
short Length;
char Call[10];
unsigned char PID;
char Packet[1024];
};
struct NRTCPSTRUCT
{
struct ConnectionInfo * sockptr;
struct _LINKTABLE * LINK; // Dummy Link Record for this ROUTE
struct ROUTE * Route; // May need backlink
char Call[10];
};
struct NRTCPSTRUCT * NRTCPInfo[256] = {0};
// Do we want to use normal TCP server connections, which are limited, or our own. Let's try our own for now
struct ConnectionInfo * AllocateNRTCPRec()
{
struct ConnectionInfo * sockptr = 0;
struct NRTCPSTRUCT * Info;
int i;
for (i = 0; i < 255; i++)
{
if (NRTCPInfo[i] == 0)
{
// only allocate as many as needed
Info = NRTCPInfo[i] = (struct NRTCPSTRUCT *)zalloc(sizeof(struct NRTCPSTRUCT));
Info->sockptr = (struct ConnectionInfo *)zalloc(sizeof(struct ConnectionInfo));
Info->LINK = (struct _LINKTABLE *)zalloc(sizeof(struct _LINKTABLE));
Info->sockptr->Number = i;
}
else
Info = NRTCPInfo[i];
sockptr = Info->sockptr;
if (sockptr->SocketActive == FALSE)
{
sockptr->SocketActive = TRUE;
sockptr->ConnectTime = sockptr->LastSendTime = time(NULL);
Debugprintf("NRTCP Allocated %d", i);
return sockptr;
}
}
return 0;
}
void checkNRTCPSockets(int portNo)
{
SOCKET sock;
int Active = 0;
SOCKET maxsock;
int retval;
int i;
struct timeval timeout;
fd_set readfd, writefd, exceptfd;
struct ConnectionInfo * sockptr;
timeout.tv_sec = 0;
timeout.tv_usec = 0; // poll
maxsock = 0;
FD_ZERO(&readfd);
FD_ZERO(&writefd);
FD_ZERO(&exceptfd);
for (i = 0; i < 255; i++)
{
if (NRTCPInfo[i] == 0)
break; // only as many as have been used
sockptr = NRTCPInfo[i]->sockptr;
if (sockptr->SocketActive == 0)
continue;
if (sockptr->Connecting)
{
// look for complete or failed
FD_SET(sockptr->socket, &writefd);
FD_SET(sockptr->socket, &exceptfd);
}
else
{
FD_SET(sockptr->socket, &readfd);
FD_SET(sockptr->socket, &exceptfd);
}
Active++;
if (sockptr->socket > maxsock)
maxsock = sockptr->socket;
}
if (Active)
{
retval = select((int)maxsock + 1, &readfd, &writefd, &exceptfd, &timeout);
if (retval == -1)
{
perror("data select");
Debugprintf("NRTCP Select Error %d Active %d", WSAGetLastError(), Active);
}
else
{
if (retval)
{
// see who has data
for (i = 0; i < 255; i++)
{
if (NRTCPInfo[i] == 0)
break;
sockptr = NRTCPInfo[i]->sockptr;
if (sockptr->SocketActive == 0)
continue;
sock = sockptr->socket;
if (FD_ISSET(sock, &writefd))
NETROMConnected(sockptr, sock, NRTCPInfo[i]);
if (FD_ISSET(sock, &readfd))
DataSocket_ReadNETROM(sockptr, sock, NRTCPInfo[i], portNo);
if (FD_ISSET(sock, &exceptfd))
NETROMConnectionLost(sockptr);
}
}
}
}
}
int NETROMOpenConnection(struct ROUTE * Route)
{
struct NRTCPSTRUCT * Info;
struct ConnectionInfo * sockptr;
Debugprintf("Opening NRTCP Connection");
if (Route->TCPSession)
{
// SESSION ALREADY EXISTS
sockptr = Route->TCPSession->sockptr;
if (sockptr->Connected || sockptr->Connecting)
return TRUE;
// previous connect failed
}
else
{
sockptr = AllocateNRTCPRec();
if (sockptr == NULL)
return 0;
Info = Route->TCPSession = NRTCPInfo[sockptr->Number];
memcpy(Info->Call, MYNETROMCALL, 10);
Route->NEIGHBOUR_LINK = Info->LINK;
Info->Route = Route;
Info->LINK->NEIGHBOUR = Route;
Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(Route->NEIGHBOUR_PORT);
}
return NETROMTCPConnect(Route, sockptr);
}
int NETROMTCPConnect(struct ROUTE * Route, struct ConnectionInfo * sockptr)
{
int err;
u_long param=1;
BOOL bcopt=TRUE;
SOCKET sock;
struct sockaddr_in sinx;
int addrlen=sizeof(sinx);
char PortString[20];
struct addrinfo hints, *res = 0, *saveres;
int Port = Route->TCPPort;
sprintf(PortString, "%d", Port);
// get host info, make socket, and connect it
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
getaddrinfo(Route->TCPHost, PortString, &hints, &res);
if (!res)
{
err = WSAGetLastError();
Debugprintf("Resolve HostName %s Failed - Error %d", Route->TCPHost, err);
return FALSE; // Resolve failed
}
// Step thorough the list of hosts
saveres = res; // Save for free
sock = sockptr->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock == INVALID_SOCKET)
{
Debugprintf, ("Netrom over TCP Create Socket Failed");
return FALSE;
}
ioctl(sock, FIONBIO, &param);
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4);
if (connect(sock, res->ai_addr, (int)res->ai_addrlen) == 0)
{
//
// Connected successful
//
sockptr->Connected = TRUE;
freeaddrinfo(saveres);
return TRUE;
}
else
{
freeaddrinfo(saveres);
err=WSAGetLastError();
if (err == 10035 || err == 115 || err == 36) //EWOULDBLOCK
{
// Connect in Progress
sockptr->Connecting = TRUE;
return TRUE;
}
else
{
// Connect failed
closesocket(sockptr->socket);
return FALSE;
}
}
return FALSE;
}
void NETROMConnectionAccepted(struct ConnectionInfo * sockptr)
{
// Not sure we can do much here until first message arrives with callsign
sockptr->Connected = TRUE;
Debugprintf("NRTCP Connection Accepted");
}
void NETROMConnected(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info)
{
// Connection Complete
Debugprintf("NRTCP Connected");
sockptr->Connecting = FALSE;
sockptr->Connected = TRUE;
Info->LINK->L2STATE = 5;
if (Info->Route->INP3Node)
SendRTTMsg(Info->Route);
}
int DataSocket_ReadNETROM(struct ConnectionInfo * sockptr, SOCKET sock, struct NRTCPSTRUCT * Info, int portNo)
{
int len=0, maxlen;
struct NRTCPMsg * Msg;
struct _L3MESSAGEBUFFER * L3Msg;
struct ROUTE * Route;
UCHAR axCall[7];
PMESSAGE Buffer;
ioctl(sock,FIONREAD,&len);
maxlen = InputBufferLen - sockptr->InputLen;
if (len > maxlen) len = maxlen;
len = recv(sock, &sockptr->InputBuffer[sockptr->InputLen], len, 0);
if (len == SOCKET_ERROR || len == 0)
{
// Failed or closed - clear connection
NETROMConnectionLost(sockptr);
return 0;
}
sockptr->InputLen += len;
// Process data
checkLen:
// See if we have a whole packet
Msg = (struct NRTCPMsg *)&sockptr->InputBuffer[0];
if (Msg->Length > sockptr->InputLen) // if not got whole frame wait
return 0;
if (Info->Call[0] == 0)
{
// first packet - do we need to do anything?
// This must be an incoming connection as Call is set before calling so need to find route record and set things up.
memcpy(Info->Call, Msg->Call, 10);
ConvToAX25(Msg->Call, axCall);
if (FindNeighbour(axCall, portNo, &Route))
{
Info->Route = Route;
Route->NEIGHBOUR_LINK = Info->LINK;
Info->LINK->NEIGHBOUR = Route;
Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(Route->NEIGHBOUR_PORT);
Route->TCPSession = Info;
Info->LINK->L2STATE = 5;
if (Info->Route->INP3Node)
SendRTTMsg(Info->Route);
}
else
goto seeifMore; // Should we kill connection?
}
if (memcmp(Info->Call, Msg->Call, 10) != 0)
{
// something wrong - maybe connection reused
}
// Format as if come from an ax.25 link
L3Msg = GetBuff();
if (L3Msg == 0)
goto seeifMore;
L3Msg->LENGTH = (Msg->Length - 12) + MSGHDDRLEN;
L3Msg->Next = 0;
L3Msg->Port = 0;
L3Msg->L3PID = NETROM_PID;
memcpy(&L3Msg->L3SRCE, Msg->Packet, Msg->Length - 13);
// Create a dummy L2 message so we can trace it
Buffer = GetBuff();
if (Buffer)
{
Buffer->CHAIN = 0;
Buffer->CTL = 0;
Buffer->PORT = portNo;
ConvToAX25(Info->Call, Buffer->ORIGIN);
ConvToAX25(MYNETROMCALL, Buffer->DEST);
memcpy(Buffer->L2DATA, &L3Msg->L3SRCE[0], Msg->Length - 13);
Buffer->ORIGIN[6] |= 1; // Set end of calls
Buffer->PID = NETROM_PID;
Buffer->LENGTH = Msg->Length + 10;
time(&Buffer->Timestamp);
BPQTRACE(Buffer, FALSE);
ReleaseBuffer(Buffer);
}
NETROMMSG(Info->LINK, L3Msg);
seeifMore:
sockptr->InputLen -= Msg->Length;
if (sockptr->InputLen > 0)
{
memmove(sockptr->InputBuffer, &sockptr->InputBuffer[Msg->Length], sockptr->InputLen);
goto checkLen;
}
return 0;
}
VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame)
{
struct NRTCPMsg Msg;
unsigned char * Data = (unsigned char *)&Frame->L3SRCE[0];
int DataLen = Frame->LENGTH - (MSGHDDRLEN + 1); // Not including PID
int Ret;
PMESSAGE Buffer;
Msg.Length = DataLen + 13; // include PID
memcpy(Msg.Call, MYNETROMCALL, 10);
Msg.PID = NETROM_PID;
memcpy(Msg.Packet, Data, DataLen);
if (Route->TCPSession == 0)
return;
Ret = send(Route->TCPSession->sockptr->socket, (char *)&Msg, DataLen + 13, 0);
// Create a dummy L2 message so we can trace it
Buffer = GetBuff();
if (Buffer)
{
Buffer->CHAIN = 0;
Buffer->CTL = 0;
Buffer->PORT = Route->NEIGHBOUR_PORT | 128; // TX Flag
ConvToAX25(Route->TCPSession->Call, Buffer->DEST);
ConvToAX25(MYNETROMCALL, Buffer->ORIGIN);
memcpy(Buffer->L2DATA, &Frame->L3SRCE[0], DataLen);
Buffer->ORIGIN[6] |= 1; // Set end of calls
Buffer->PID = NETROM_PID;
Buffer->LENGTH = DataLen + 15 + MSGHDDRLEN;
time(&Buffer->Timestamp);
BPQTRACE(Buffer, FALSE);
ReleaseBuffer(Buffer);
}
}
void NETROMConnectionLost(struct ConnectionInfo * sockptr)
{
struct NRTCPSTRUCT * Info = NRTCPInfo[sockptr->Number];
struct ROUTE * Route;
closesocket(sockptr->socket);
// If there is an attached route (there should be) clear all connections
if (Info)
{
Route = Info->Route;
if (sockptr->Connected)
L3LINKCLOSED(Info->LINK, LINKLOST);
if (sockptr->Connecting)
L3LINKCLOSED(Info->LINK, SETUPFAILED);
Route->TCPSession = 0;
Info->Call[0] = 0;
}
sockptr->SocketActive = FALSE;
memset(sockptr, 0, sizeof(struct ConnectionInfo));
}

View file

@ -2217,7 +2217,7 @@ int BittoInt(UINT BitMask)
return i;
}
extern char * RadioConfigMsg[36];
extern char * RadioConfigMsg[70];
struct TNCINFO RIGTNC; // Dummy TNC Record for Rigcontrol without a corresponding TNC

View file

@ -90,7 +90,7 @@ void RHPThread(void * Params);
void ProcessRHPWebSockClosed(SOCKET socket);
int ProcessSNMPPayload(UCHAR * Msg, int Len, UCHAR * Reply, int * OffPtr);
int RHPProcessHTTPMessage(struct ConnectionInfo * conn, char * response, char * Method, char * URL, char * request, BOOL LOCAL, BOOL COOKIE);
void checkNRTCPSockets(int portNo);
#ifndef LINBPQ
extern HKEY REGTREE;
@ -172,12 +172,14 @@ VOID Tel_Format_Addr(struct ConnectionInfo * sockptr, char * dst);
VOID ProcessTrimodeCommand(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, char * MsgPtr);
VOID ProcessTrimodeResponse(struct TNCINFO * TNC, struct STREAMINFO * STREAM, unsigned char * MsgPtr, int Msglen);
VOID ProcessTriModeDataMessage(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCKET sock, struct STREAMINFO * STREAM);
void processNETROMFrame(unsigned char * Message, int Len, struct ConnectionInfo * sockptr);
void NETROMConnectionLost(struct ConnectionInfo * sockptr);
void NETROMConnectionAccepted(struct ConnectionInfo * sockptr);
struct ConnectionInfo * AllocateNRTCPRec();
static int LogAge = 13;
#ifdef WIN32
int DeleteLogFile(char * Log);
@ -542,6 +544,9 @@ int ProcessLine(char * buf, int Port)
else if (_stricmp(param,"HTTPPORT") == 0)
HTTPPort = TCP->HTTPPort = atoi(value);
else if (_stricmp(param,"NETROMPORT") == 0)
TCP->NETROMPort = atoi(value);
else if (_stricmp(param,"APIPORT") == 0)
TCP->APIPort = atoi(value);
@ -1139,7 +1144,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
shutdown(TCP->FBBsock[n++], SD_BOTH);
shutdown(TCP->Relaysock, SD_BOTH);
shutdown(TCP->HTTPsock, SD_BOTH);
shutdown(TCP->HTTPSock, SD_BOTH);
shutdown(TCP->HTTPsock6, SD_BOTH);
@ -1163,7 +1168,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
closesocket(TCP->Relaysock);
closesocket(TCP->Relaysock6);
closesocket(TCP->HTTPsock);
closesocket(TCP->HTTPSock);
closesocket(TCP->HTTPsock6);
// Save info from old TNC record
@ -1248,7 +1253,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
shutdown(TCP->FBBsock[n++], SD_BOTH);
shutdown(TCP->Relaysock, SD_BOTH);
shutdown(TCP->HTTPsock, SD_BOTH);
shutdown(TCP->HTTPSock, SD_BOTH);
shutdown(TCP->HTTPsock6, SD_BOTH);
shutdown(TCP->sock6, SD_BOTH);
@ -1275,7 +1280,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
closesocket(TCP->FBBsock6[n++]);
closesocket(TCP->Relaysock6);
closesocket(TCP->HTTPsock);
closesocket(TCP->HTTPSock);
closesocket(TCP->HTTPsock6);
return (0);
@ -1713,11 +1718,14 @@ BOOL OpenSockets(struct TNCINFO * TNC)
}
if (TCP->HTTPPort)
TCP->HTTPsock = OpenSocket4(TNC, TCP->HTTPPort);
TCP->HTTPSock = OpenSocket4(TNC, TCP->HTTPPort);
if (TCP->APIPort)
TCP->APIsock = OpenSocket4(TNC, TCP->APIPort);
if (TCP->NETROMPort)
TCP->NETROMSock = OpenSocket4(TNC, TCP->NETROMPort);
if (TCP->SyncPort)
TCP->Syncsock = OpenSocket4(TNC, TCP->SyncPort);
@ -1836,6 +1844,9 @@ BOOL OpenSockets6(struct TNCINFO * TNC)
if (TCP->APIPort)
TCP->APIsock6 = OpenSocket6(TNC, TCP->APIPort);
if (TCP->NETROMPort)
TCP->NETROMSock6 = OpenSocket6(TNC, TCP->NETROMPort);
if (TCP->SyncPort)
TCP->Syncsock6 = OpenSocket6(TNC, TCP->SyncPort);
@ -1888,7 +1899,7 @@ static VOID SetupListenSet(struct TNCINFO * TNC)
maxsock = sock;
}
sock = TCP->HTTPsock;
sock = TCP->HTTPSock;
if (sock)
{
FD_SET(sock, readfd);
@ -1904,6 +1915,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC)
maxsock = sock;
}
sock = TCP->NETROMSock;
if (sock)
{
FD_SET(sock, readfd);
if (sock > maxsock)
maxsock = sock;
}
sock = TCP->Syncsock;
if (sock)
{
@ -1979,6 +1998,14 @@ static VOID SetupListenSet(struct TNCINFO * TNC)
maxsock = sock;
}
sock = TCP->NETROMSock6;
if (sock)
{
FD_SET(sock, readfd);
if (sock > maxsock)
maxsock = sock;
}
sock = TCP->DRATSsock6;
if (sock)
@ -2066,13 +2093,20 @@ VOID TelnetPoll(int Port)
Socket_Accept(TNC, sock, TCP->RelayPort);
}
sock = TCP->HTTPsock;
sock = TCP->HTTPSock;
if (sock)
{
if (FD_ISSET(sock, &readfd))
Socket_Accept(TNC, sock, TCP->HTTPPort);
}
sock = TCP->NETROMSock;
if (sock)
{
if (FD_ISSET(sock, &readfd))
Socket_Accept(TNC, sock, TCP->NETROMPort);
}
sock = TCP->DRATSsock;
if (sock)
{
@ -2120,6 +2154,14 @@ VOID TelnetPoll(int Port)
Socket_Accept(TNC, sock, TCP->HTTPPort);
}
sock = TCP->NETROMSock6;
if (sock)
{
if (FD_ISSET(sock, &readfd))
Socket_Accept(TNC, sock, TCP->NETROMPort);
}
sock = TCP->DRATSsock6;
if (sock)
{
@ -2247,9 +2289,12 @@ VOID TelnetPoll(int Port)
}
}
nosocks:
// Poll TCPNR
checkNRTCPSockets(Port);
// Try SNMP
if (TCP->SNMPsock)
@ -3062,7 +3107,7 @@ LRESULT CALLBACK TelWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara
shutdown(TCP->FBBsock[n++], SD_BOTH);
shutdown(TCP->Relaysock, SD_BOTH);
shutdown(TCP->HTTPsock, SD_BOTH);
shutdown(TCP->HTTPSock, SD_BOTH);
shutdown(TCP->HTTPsock6, SD_BOTH);
@ -3087,7 +3132,7 @@ LRESULT CALLBACK TelWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPara
closesocket(TCP->Relaysock);
closesocket(TCP->Relaysock6);
closesocket(TCP->HTTPsock);
closesocket(TCP->HTTPSock);
closesocket(TCP->HTTPsock6);
// Save info from old TNC record
@ -3256,6 +3301,35 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port)
return 0;
}
// Netrom Over TCP uses its own Connection Entries
if (SocketId == TCP->NETROMSock || SocketId == TCP->NETROMSock6)
{
sockptr = AllocateNRTCPRec();
if (sockptr == 0)
{
// No entries - accept and close
sock = accept(SocketId, (struct sockaddr *)&sin6, &addrlen);
send(sock,"No Free Sessions\r\n", 18,0);
Debugprintf("No Free Netrom Telnet Sessions");
Sleep (500);
closesocket(sock);
return 0;
}
sock = accept(SocketId, (struct sockaddr *)&sockptr->sin, &addrlen);
sockptr->socket = sock;
ioctl(sock, FIONBIO, &param);
sockptr->NETROMMode = TRUE;
NETROMConnectionAccepted(sockptr);
return 0;
}
// Find a free Session
for (n = 1; n <= TCP->MaxSessions; n++)
@ -3307,7 +3381,8 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port)
TNC->Streams[n].FramesQueued = 0;
sockptr->HTTPMode = FALSE;
sockptr->APIMode = FALSE;
sockptr->APIMode = FALSE;
sockptr->NETROMMode = FALSE;
sockptr->SyncMode = FALSE;
sockptr->DRATSMode = FALSE;
sockptr->FBBMode = FALSE;
@ -3322,9 +3397,12 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port)
memset(sockptr->ADIF, 0, sizeof(struct ADIF));
if (SocketId == TCP->HTTPsock || SocketId == TCP->HTTPsock6)
if (SocketId == TCP->HTTPSock || SocketId == TCP->HTTPsock6)
sockptr->HTTPMode = TRUE;
if (SocketId == TCP->NETROMSock || SocketId == TCP->NETROMSock6)
sockptr->NETROMMode = TRUE;
if (SocketId == TCP->APIsock || SocketId == TCP->APIsock6)
{
sockptr->HTTPMode = TRUE; // API is a type of HTTP socket
@ -3358,7 +3436,7 @@ int Socket_Accept(struct TNCINFO * TNC, SOCKET SocketId, int Port)
if (sockptr->HTTPMode)
return 0;
if (sockptr->DRATSMode)
{
send(sock, "100 Authentication not required\n", 33, 0);
@ -5271,6 +5349,7 @@ int DataSocket_ReadDRATS(struct TNCINFO * TNC, struct ConnectionInfo * sockptr,
}
int DataSocket_Disconnect(struct TNCINFO * TNC, struct ConnectionInfo * sockptr)
{
int n;
@ -5685,7 +5764,9 @@ int Telnet_Connected(struct TNCINFO * TNC, struct ConnectionInfo * sockptr, SOCK
}
else
{
if (TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4CROSSLINK->APPL[0])
struct _TRANSPORTENTRY * CROSSLINK = TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4CROSSLINK;
if (CROSSLINK && CROSSLINK->APPL[0])
buffptr->Len = sprintf(&buffptr->Data[0], "*** Connected to %s\r",
TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4CROSSLINK->APPL);
else

View file

@ -80,6 +80,11 @@ int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len);
VOID ProcessARQPacket(struct PORTCONTROL * PORT, MESSAGE * Buffer);
char * strlop(char * buf, char delim);
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
extern UCHAR BPQDirectory[];
extern char MYALIASLOPPED[10];

View file

@ -78,6 +78,11 @@ VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC);
int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len);
int standardParams(struct TNCINFO * TNC, char * buf);
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
extern UCHAR BPQDirectory[];
#define MAXUZ7HOPORTS 16

5
VARA.c
View file

@ -73,6 +73,11 @@ int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len);
VOID PROCESSNODEMESSAGE(MESSAGE * Msg, struct PORTCONTROL * PORT);
VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG);
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
#ifndef LINBPQ
BOOL CALLBACK EnumVARAWindowsProc(HWND hwnd, LPARAM lParam);
#endif

View file

@ -10,8 +10,8 @@
#endif
#define KVers 6,0,25,6
#define KVerstring "6.0.25.6\0"
#define KVers 6,0,25,8
#define KVerstring "6.0.25.8\0"
#ifdef CKernel

View file

@ -105,6 +105,11 @@ int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len);
BOOL KillOldTNC(char * Path);
int standardParams(struct TNCINFO * TNC, char * buf);
void hookL4SessionAttempt(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionAccepted(struct STREAMINFO * , char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);
static char ClassName[]="WINMORSTATUS";
static char WindowTitle[] = "WINMOR";
static int RigControlRow = 165;

View file

@ -42,7 +42,7 @@ typedef int (FAR *FARPROCY)();
#define L4INFO 5 // INFORMATION
#define L4IACK 6 // INFORMATION ACK
#define L4RESET 7 // Paula's extension
#define L4CREQX 8 // Paula's extension
extern char MYCALL[]; // 7 chars, ax.25 format
extern char MYALIASTEXT[]; // 6 chars, not null terminated
@ -177,6 +177,14 @@ typedef struct _TRANSPORTENTRY
int Received;
int ReceivedAfterExpansion;
int segsSent;
int segsRcvd;
int segsResent;
int NRRID;
time_t NRRTime;
int Service; // For Paula's Connnect to Service
} TRANSPORTENTRY;
@ -220,6 +228,7 @@ typedef struct ROUTE
BOOL INP3Node;
BOOL NoKeepAlive; // Suppress Keepalive Processing
int LastConnectAttempt; // To stop us trying too often
int ConnectionAttempts;
int Status; //
int OldBPQ; // Set if other end is BPQ sending RIF in mS
@ -239,6 +248,10 @@ typedef struct ROUTE
int RemoteMAXRTT; // For INP3
int RemoteMAXHOPS;
char * TCPHost; // For NETROM over TCP
int TCPPort;
struct NRTCPSTRUCT * TCPSession;
} *PROUTE;
// Status Equates
@ -961,6 +974,9 @@ typedef struct _LINKTABLE
time_t ConnectTime; // For session stats
int bytesRXed; // Info bytes only
int bytesTXed;
int framesRXed;
int framesTXed;
int framesResent;
// Now support compressing L2 Sessions.
// We collect as much data as possible before compressing and re-packetizing
@ -977,7 +993,7 @@ typedef struct _LINKTABLE
int ReceivedAfterExpansion;
char ApplName[16];
time_t lastStatusSentTime;
} LINKTABLE;
@ -1479,6 +1495,15 @@ struct CMDX
};
struct NETROMX
{
int ServiceNo;
char ServiceName[10];
};
extern struct NETROMX SERVICES[];
extern int NUMBEROFSSERVICES;
#define Disconnect(stream) SessionControl(stream,2,0)
#define Connect(stream) SessionControl(stream,1,0)

61
cMain.c
View file

@ -55,7 +55,9 @@ void SaveMH();
VOID InformPartner(struct _LINKTABLE * LINK, int Reason);
VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD);
void WritePacketLogThread(void * param);
void hookNodeStarted();
void hookNodeRunning();
void APIL2Trace(struct _MESSAGE * Message, char Dirn);
#include "configstructs.h"
@ -63,6 +65,15 @@ extern struct CONFIGTABLE xxcfg;
extern BOOL needAIS;
extern int needADSB;
extern int EnableOARCAPI;
extern SOCKET NodeAPISocket;
extern int nodeStartedSent;
extern SOCKADDR_IN UDPreportdest;
extern char NodeAPIServer[80];
extern int NodeAPIPort;
time_t LastNodeStatus = 0;
int nodeStatusTimer = 20 * 60; // 20 mins
struct PORTCONFIG * PortRec;
@ -313,8 +324,8 @@ VOID LINKINIT(PEXTPORTDATA PORTVEC)
VOID LINKTX(PEXTPORTDATA PORTVEC, PMESSAGE Buffer)
{
// LOOP BACK TO SWITCH
struct _LINKTABLE * LINK;
LINK = Buffer->Linkptr;
if (LINK)
@ -1380,13 +1391,13 @@ BOOL Start()
PORT = GetPortTableEntryFromPortNum(ROUTE->NEIGHBOUR_PORT);
if (Rcfg->pwind & 0x40)
if (Rcfg->nokeepalives)
ROUTE->NoKeepAlive = 1;
else
if (PORT != NULL)
ROUTE->NoKeepAlive = PORT->PortNoKeepAlive;
if (Rcfg->pwind & 0x80 || (PORT && PORT->INP3ONLY))
if (Rcfg->inp3 || (PORT && PORT->INP3ONLY))
{
ROUTE->INP3Node = 1;
ROUTE->NoKeepAlive = 0; // Cant have INP3 and NOKEEPALIVES
@ -1400,6 +1411,12 @@ BOOL Start()
ROUTE->OtherendsRouteQual = ROUTE->OtherendLocked = Rcfg->farQual;
ROUTE->NEIGHBOUR_FLAG = LOCKEDBYCONFIG; // Locked
if (Rcfg->tcphost)
{
ROUTE->TCPHost = Rcfg->tcphost;
ROUTE->TCPPort = Rcfg->tcpport;
}
Rcfg++;
ROUTE++;
@ -1584,6 +1601,28 @@ BOOL Start()
lastSaveSecs = CurrentSecs = lastSlowSecs = time(NULL);
// if EnableOARCAPI set try to resolve host here so we can send Node up event before anything else
if (EnableOARCAPI)
{
struct hostent * HostEnt3;
HostEnt3 = gethostbyname(NodeAPIServer);
NodeAPISocket = socket(AF_INET, SOCK_DGRAM, 0);
UDPreportdest.sin_family = AF_INET;
UDPreportdest.sin_port = htons(NodeAPIPort);
if (HostEnt3)
{
memcpy(&UDPreportdest.sin_addr.s_addr,HostEnt3->h_addr,4);
hookNodeStarted();
nodeStartedSent = 1;
LastNodeStatus = time(NULL);
}
}
return 0;
}
@ -2177,6 +2216,12 @@ VOID TIMERINTERRUPT()
if (MQTT)
MQTTTimer();
if (LastNodeStatus && (time(NULL) - LastNodeStatus) > nodeStatusTimer)
{
LastNodeStatus = time(NULL);
hookNodeRunning();
}
/*
if (QCOUNT < 200)
{
@ -2232,6 +2277,10 @@ VOID TIMERINTERRUPT()
}
Message = (struct _MESSAGE *)Buffer;
if(NodeAPISocket)
APIL2Trace(Message, 'T');
Message->PORT |= 0x80; // Set TX Bit
BPQTRACE(Message, FALSE); // Dont send TX'ed frames to APRS
@ -2343,6 +2392,9 @@ L2Packet:
if (MQTT && PORT->PROTOCOL == 0)
MQTTKISSRX(Buffer);
if(NodeAPISocket &&PORT->PROTOCOL == 0)
APIL2Trace(Message, 'R');
// Bridge if requested
@ -2695,7 +2747,6 @@ int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS)
// And to the Monitor to File system.
if (MONTOFILEFLAG) // Trace Enabled?
{
Buffer = GetBuff();

View file

@ -108,7 +108,7 @@ VOID SendCommandReply(TRANSPORTENTRY * Session, struct DATAMESSAGE * Buffer, int
DllExport struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum);
int cCOUNT_AT_L2(struct _LINKTABLE * LINK);
VOID SENDL4CONNECT(TRANSPORTENTRY * Session);
VOID SENDL4CONNECT(TRANSPORTENTRY * Session, int Service);
VOID CloseSessionPartner(TRANSPORTENTRY * Session);
int COUNTNODES(struct ROUTE * ROUTE);
@ -445,7 +445,3 @@ DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqStringMhz);
void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK);
void hookL2SessionDeleted(struct _LINKTABLE * LINK);
void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK);
void hookL4SessionAttempt(void * STREAM, char * remotecall, char * ourcall);
void hookL4SessionAccepted(void * STREAM, char * remotecall, char * ourcall);
void hookL4SessionDeleted(struct TNCINFO * TNC, void * STREAM);

185
config.c
View file

@ -305,7 +305,8 @@ static char *keywords[] =
"APPL5ALIAS", "APPL6ALIAS", "APPL7ALIAS", "APPL8ALIAS",
"APPL1QUAL", "APPL2QUAL", "APPL3QUAL", "APPL4QUAL",
"APPL5QUAL", "APPL6QUAL", "APPL7QUAL", "APPL8QUAL",
"BTEXT:", "NETROMCALL", "C_IS_CHAT", "MAXRTT", "MAXHOPS", // IPGATEWAY= no longer allowed
"BTEXT:", "NETROMCALL", "C_IS_CHAT", "MAXRTT", "MAXTT", "MAXHOPS", // IPGATEWAY= no longer allowed
"LogL4Connects", "LogAllConnects", "SAVEMH", "ENABLEADIFLOG", "ENABLEEVENTS", "SAVEAPRSMSGS",
"EnableM0LTEMap", "MQTT", "MQTT_HOST", "MQTT_PORT", "MQTT_USER", "MQTT_PASS",
"L4Compress", "L4CompMaxframe", "L4CompPaclen", "L2Compress", "L2CompMaxframe",
@ -328,7 +329,8 @@ static void * offset[] =
&xxcfg.C_APPL[4].ApplAlias, &xxcfg.C_APPL[5].ApplAlias, &xxcfg.C_APPL[6].ApplAlias, &xxcfg.C_APPL[7].ApplAlias,
&xxcfg.C_APPL[0].ApplQual, &xxcfg.C_APPL[1].ApplQual, &xxcfg.C_APPL[2].ApplQual, &xxcfg.C_APPL[3].ApplQual,
&xxcfg.C_APPL[4].ApplQual, &xxcfg.C_APPL[5].ApplQual, &xxcfg.C_APPL[6].ApplQual, &xxcfg.C_APPL[7].ApplQual,
&xxcfg.C_BTEXT, &xxcfg.C_NETROMCALL, &xxcfg.C_C, &xxcfg.C_MAXRTT, &xxcfg.C_MAXHOPS, // IPGATEWAY= no longer allowed
&xxcfg.C_BTEXT, &xxcfg.C_NETROMCALL, &xxcfg.C_C, &xxcfg.C_MAXRTT, &xxcfg.C_MAXRTT, &xxcfg.C_MAXHOPS, // IPGATEWAY= no longer allowed
&xxcfg.C_LogL4Connects, &xxcfg.C_LogAllConnects, &xxcfg.C_SaveMH, &xxcfg.C_ADIF, &xxcfg.C_EVENTS, &xxcfg.C_SaveAPRSMsgs,
&xxcfg.C_M0LTEMap, &xxcfg.C_MQTT, &xxcfg.C_MQTT_HOST, &xxcfg.C_MQTT_PORT, &xxcfg.C_MQTT_USER, &xxcfg.C_MQTT_PASS,
&xxcfg.C_L4Compress, &xxcfg.C_L4CompMaxframe, &xxcfg.C_L4CompPaclen, &xxcfg.C_L2Compress, &xxcfg.C_L2CompMaxframe,
@ -350,7 +352,8 @@ static int routine[] =
13, 13 ,13, 13,
14, 14, 14, 14,
14, 14 ,14, 14,
15, 0, 2, 9, 9,
15, 0, 2, 9, 9, 9,
2, 2, 1, 2, 2, 2,
2, 2, 0, 1, 20, 20,
1, 1, 1, 1, 1,
@ -1584,32 +1587,160 @@ int routes(int i)
// strtok and sscanf can't handle successive commas, so split up usig strchr
memset(Param, 0, 2048);
strlop(rec, 13);
strlop(rec, ';');
// Now support keyword=value format
ptr1 = rec;
while (ptr1 && *ptr1 && n < 8)
if (strchr(rec, '='))
{
ptr2 = strchr(ptr1, ',');
if (ptr2) *ptr2++ = 0;
// New format
// call quality port window frack paclen farquality inp3 nokeepalives tcp
strcpy(&Param[n++][0], ptr1);
ptr1 = ptr2;
while(ptr1 && *ptr1 && *ptr1 == ' ')
ptr1++;
char * ptr, *context;
char copy[512] = "";
if (strlen(rec) < 512)
strcpy(copy, rec);
_strupr(rec);
ptr = strtok_s(rec, " ,=", &context);
while (ptr)
{
if (strcmp(ptr, "CALL") == 0)
{
char * Call = strtok_s(NULL, ",=", &context);
if (strlen(Call) < 80)
strcpy(Route->call, Call);
}
else if (strcmp(ptr, "PORT") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->port = atoi(val);
}
else if (strcmp(ptr, "QUALITY") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->quality = atoi(val);
}
else if (strcmp(ptr, "FRACK") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->pfrack = atoi(val);
}
else if (strcmp(ptr, "PACLEN") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->pwind = atoi(val);
}
else if (strcmp(ptr, "WINDOW") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->pwind = atoi(val);
}
else if (strcmp(ptr, "FARQUALITY") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->farQual = atoi(val);
}
else if (strcmp(ptr, "INP3") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->inp3 = atoi(val);
}
else if (strcmp(ptr, "NOKEEPALIVES") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
Route->farQual = atoi(val);
}
else if (strcmp(ptr, "TCP") == 0)
{
char * val = strtok_s(NULL, " ,=", &context);
if (val)
{
char * port = strlop(val, ':');
Route->tcphost = _strdup(val);
if (port)
Route->tcpport = atoi(port);
else
Route->tcpport = 53119;
}
}
else
{
Consoleprintf("Bad Route %s\r\n",rec);
err_flag = 1;
break;
}
ptr = strtok_s(NULL, " ,=", &context);
}
}
strcpy(Route->call, &Param[0][0]);
else
{
Route->quality = atoi(Param[1]);
Route->port = atoi(Param[2]);
Route->pwind = atoi(Param[3]);
Route->pfrack = atoi(Param[4]);
Route->ppacl = atoi(Param[5]);
inp3 = atoi(Param[6]);
Route->farQual = atoi(Param[7]);
memset(Param, 0, 2048);
strlop(rec, 13);
strlop(rec, ';');
ptr1 = rec;
while (ptr1 && *ptr1 && n < 8)
{
ptr2 = strchr(ptr1, ',');
if (ptr2) *ptr2++ = 0;
strcpy(&Param[n++][0], ptr1);
ptr1 = ptr2;
while(ptr1 && *ptr1 && *ptr1 == ' ')
ptr1++;
}
strcpy(Route->call, &Param[0][0]);
Route->quality = atoi(Param[1]);
Route->port = atoi(Param[2]);
Route->pwind = atoi(Param[3]);
Route->pfrack = atoi(Param[4]);
Route->ppacl = atoi(Param[5]);
inp3 = atoi(Param[6]);
Route->farQual = atoi(Param[7]);
if (inp3 & 1)
Route->inp3 = 1;
if (inp3 & 2)
Route->nokeepalives = 1;
}
if (Route->farQual < 0 || Route->farQual > 255)
{
@ -1634,14 +1765,6 @@ int routes(int i)
err_flag = 1;
}
// Use top bit of window as INP3 Flag, next as NoKeepAlive
if (inp3 & 1)
Route->pwind |= 0x80;
if (inp3 & 2)
Route->pwind |= 0x40;
if (err_flag == 1)
{
Consoleprintf("%s\r\n",rec);

View file

@ -94,6 +94,10 @@ struct ROUTECONFIG
int pfrack;
int ppacl;
int farQual;
int inp3;
int nokeepalives;
char * tcphost;
int tcpport;
};
struct CONFIGTABLE

7
debian/changelog vendored
View file

@ -1,8 +1,11 @@
linbpq (6.0.25.06+repack-2~hibbian13+1) UNRELEASED; urgency=medium
linbpq (6.0.25.8+repack-1~hibbian13+1) trixie-hibbian-unstable; urgency=medium
* Build on latest gcc standards
* New upstream version 6.0.25.8+repack
* Refresh patches with gbp pq!
* MINI_BUILDD_OPTION: auto-ports=trixie-packetrepo-unstable,bookworm-packetrepo-unstable,bullseye-packetrepo-unstable,noble-packetrepo-unstable,jammy-packetrepo-unstable
-- Dave Hibberd <hibby@debian.org> Fri, 10 Oct 2025 23:55:05 +0100
-- Dave Hibberd <hibby@debian.org> Fri, 24 Oct 2025 00:45:16 +0100
linbpq (6.0.25.06+repack-1~hibbian13+1) trixie-hibbian-unstable; urgency=medium

View file

@ -7,7 +7,7 @@ Subject: makefile
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/makefile b/makefile
index 0152c9a..0730a2a 100644
index 26403e5..0f15cc0 100644
--- a/makefile
+++ b/makefile
@@ -2,8 +2,7 @@

View file

@ -7,10 +7,10 @@ Subject: spelling-fixes
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/UZ7HODrv.c b/UZ7HODrv.c
index ac33278..c7e463f 100644
index e166b36..23b3e27 100644
--- a/UZ7HODrv.c
+++ b/UZ7HODrv.c
@@ -382,7 +382,7 @@ int UZ7HOSetFreq(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESS
@@ -387,7 +387,7 @@ int UZ7HOSetFreq(int port, struct TNCINFO * TNC, struct AGWINFO * AGW, PDATAMESS
if (AGW->CenterFreq == 0)
{

View file

@ -78,6 +78,8 @@ typedef struct _ETHARP
UCHAR TARGETHWADDR[6];
uint32_t TARGETIPADDR;
char Padding[18]; // For min ether send of 60
} ETHARP, *PETHARP;
typedef struct _RIP2HDDR

View file

@ -13,7 +13,7 @@ OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pn
MailCommands.o MailDataDefs.o LinBPQ.o MailRouting.o MailTCP.o MBLRoutines.o md5.o Moncode.o \
NNTPRoutines.o RigControl.o TelnetV6.o WINMOR.o TNCCode.o UZ7HODrv.o WPRoutines.o \
SCSTrackeMulti.o SCSPactor.o SCSTracker.o HanksRT.o UIRoutines.o AGWAPI.o AGWMoncode.o \
DRATS.o FreeDATA.o base64.o Events.o nodeapi.o mailapi.o mqtt.o RHP.o
DRATS.o FreeDATA.o base64.o Events.o nodeapi.o mailapi.o mqtt.o RHP.o NETROMTCP.o
# Configuration:

View file

@ -38,6 +38,7 @@ struct ConnectionInfo
BOOL SyncMode; // RMS Relay Sync
BOOL HTTPMode; // HTTP Server
BOOL APIMode; // REST API Server
BOOL NETROMMode;
BOOL TriMode; // Trimode emulation
BOOL TriModeConnected; // Set when remote session is connected - now send data to DataSock
SOCKET TriModeDataSock; // Data Socket
@ -73,6 +74,9 @@ struct ConnectionInfo
int WebSocks;
char WebURL[32]; // URL for WebSocket Connection
int WebSecure; // Set if secure session
int Connecting; // For outward connect
int Connected;
};

View file

@ -116,6 +116,7 @@ struct TCPINFO
int SNMPPort;
int DRATSPort;
int CMDPort[33];
int NETROMPort;
char RELAYHOST[64];
char CMSServer[64];
BOOL FallbacktoRelay; // Use Relsy if can't connect to CMS
@ -160,13 +161,14 @@ struct TCPINFO
SOCKET TCPSock;
SOCKET FBBsock[100];
SOCKET Relaysock;
SOCKET HTTPsock;
SOCKET HTTPSock;
SOCKET APIsock;
SOCKET TriModeSock;
SOCKET TriModeDataSock;
SOCKET Syncsock;
SOCKET DRATSsock;
SOCKET SNMPsock;
SOCKET NETROMSock;
struct ConnectionInfo * TriModeControlSession;
SOCKET sock6;
@ -176,6 +178,7 @@ struct TCPINFO
SOCKET APIsock6;
SOCKET Syncsock6;
SOCKET DRATSsock6;
SOCKET NETROMSock6;
fd_set ListenSet;
SOCKET maxsock;