/* Copyright 2001-2022 John Wiseman G8BPQ This file is part of LinBPQ/BPQ32. LinBPQ/BPQ32 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. LinBPQ/BPQ32 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses */ // // C replacement for Main.asm // #define Kernel #define _CRT_SECURE_NO_DEPRECATE #pragma data_seg("_BPQDATA") //#include "windows.h" //#include "winerror.h" #include "time.h" #include "stdio.h" #include #include "kernelresource.h" #include "CHeaders.h" #include "tncinfo.h" #include "mqtt.h" VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer); VOID ProcessIframe(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer); VOID FindLostBuffers(); VOID ReadMH(); void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * CMD); int upnpInit(); void AISTimer(); void ADSBTimer(); VOID SendSmartID(struct PORTCONTROL * PORT); int CanPortDigi(int Port); int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); void MQTTTimer(); void SaveMH(); #include "configstructs.h" extern struct CONFIGTABLE xxcfg; extern BOOL needAIS; extern int needADSB; struct PORTCONFIG * PortRec; #define RNRSET 0x2 // RNR RECEIVED FROM OTHER END // STATION INFORMATION char DATABASESTART[14] = ""; char xMAJORVERSION = 4; char xMINORVERSION = 9; char FILLER1[16] = ""; struct ROUTE * NEIGHBOURS = NULL; int ROUTE_LEN = sizeof(struct ROUTE); int MAXNEIGHBOURS = 20; struct DEST_LIST * DESTS = NULL; // NODE LIST int DEST_LIST_LEN = sizeof(struct DEST_LIST); struct _LINKTABLE * LINKS = NULL; int LINK_TABLE_LEN = sizeof (struct _LINKTABLE); int MAXLINKS = 30; char MYCALL[7] = ""; // DB 7 DUP (0) ; NODE CALLSIGN (BIT SHIFTED) char MYALIASTEXT[6] = ""; // DB ' ' ; NODE ALIAS (KEEP TOGETHER) char MYALIASLOPPED[10]; char MYCALLLOPPED[10]; UCHAR MYCALLWITHALIAS[13] = ""; UCHAR NETROMCALL[7] = ""; // Call used for NETROM (can be MYCALL) APPLCALLS APPLCALLTABLE[NumberofAppls] = {0}; UCHAR MYNODECALL[10] = ""; // NODE CALLSIGN (ASCII) UCHAR MYNETROMCALL[10] = ""; // NETROM CALLSIGN (ASCII) char NODECALLLOPPED[10]; VOID * FREE_Q = NULL; time_t TimeLoaded = 0; struct PORTCONTROL * PORTTABLE = NULL; int NUMBEROFPORTS = 0; int PORTENTRYLEN = sizeof(struct PORTCONTROL); struct DEST_LIST * ENDDESTLIST = NULL; // ; NODE LIST+1 ; VOID * BUFFERPOOL = NULL; // START OF BUFFER POOL VOID * ENDBUFFERPOOL = NULL; int OBSINIT = 5; // INITIAL OBSOLESCENCE VALUE int OBSMIN = 4; // MINIMUM TO BROADCAST int L3INTERVAL = 60; // 'NODES' INTERVAL IN MINS int IDINTERVAL = 20; // 'ID' BROADCAST INTERVAL int BTINTERVAL = 20; // 'BT' BROADCAST INTERVAL int MINQUAL = 10; // MIN QUALITY FOR AUTOUPDATES int HIDENODES = 0; // N * COMMAND SWITCH int BBSQUAL = 255; // QUALITY OF BBS RELATIVE TO NODE int NUMBEROFBUFFERS = 999; // PACKET BUFFERS int PACLEN = 100; //MAX PACKET SIZE // L2 SYSTEM TIMER RUNS AT 3 HZ int T3 = 3*61*3; // LINK VALIDATION TIMER (3 MINS) (+ a bit to reduce RR collisions) int L2KILLTIME = 16*60*3; // IDLE LINK TIMER (16 MINS) int L3LIVES = 15; // MAX L3 HOPS int L4N2 = 3; // LEVEL 4 RETRY COUNT int L4LIMIT = 60*15; // IDLE SESSION LIMIT - 15 MINS int L4DELAY = 5; // L4 DELAYED ACK TIMER int BBS = 1; // INCLUDE BBS SUPPORT int NODE = 1; // INCLUDE SWITCH SUPPORT int FULL_CTEXT = 1; // CTEXT ON ALL CONNECTS IF NZ BOOL LogL4Connects = FALSE; BOOL LogAllConnects = FALSE; BOOL AUTOSAVEMH = TRUE; extern BOOL ADIFLogEnabled; extern UCHAR LogDirectory[260]; extern BOOL EventsEnabled; extern BOOL SaveAPRSMsgs; BOOL M0LTEMap = FALSE; BOOL MQTT = FALSE; char MQTT_HOST[80] = ""; int MQTT_PORT = 0; char MQTT_USER[80] = ""; char MQTT_PASS[80] = ""; int MQTT_Connecting = 0; int MQTT_Connected = 0; //TNCTABLE DD 0 //NUMBEROFSTREAMS DD 0 extern VOID * ENDPOOL; extern void * APPL_Q; // Queue of frames for APRS Appl extern BOOL APRSActive; #define BPQHOSTSTREAMS 64 // Although externally streams are numbered 1 to 64, internally offsets are 0 - 63 BPQVECSTRUC XDUMMY = {0}; // Needed to force correct order of following BPQVECSTRUC BPQHOSTVECTOR[BPQHOSTSTREAMS + 5] = {0}; BPQVECSTRUC * TELNETMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS]; BPQVECSTRUC * AGWMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 1]; BPQVECSTRUC * APRSMONVECPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 2]; BPQVECSTRUC * IPHOSTVECTORPTR = &BPQHOSTVECTOR[BPQHOSTSTREAMS + 3]; int BPQVECLENGTH = sizeof(BPQVECSTRUC); int NODEORDER = 0; UCHAR LINKEDFLAG = 0; UCHAR UNPROTOCALL[80] = ""; UCHAR ExcludeList[71] = ""; // 10 ENTRIES, 7 BYTES EACH char * INFOMSG = NULL; char * CTEXTMSG = NULL; int CTEXTLEN = 0; UCHAR MYALIAS[7] = ""; // ALIAS IN AX25 FORM UCHAR BBSALIAS[7] = ""; UCHAR AX25CALL[7] = ""; // WORK AREA FOR AX25 <> NORMAL CALL CONVERSION UCHAR NORMCALL[10] = ""; // CALLSIGN IN NORMAL FORMAT int NORMLEN = 0; // LENGTH OF CALL IN NORMCALL int CURRENTPORT = 0; // PORT FOR CURRENT MESSAGE VOID * CURRENTPORTPTR = NULL; // PORT CONTROL TABLE ENTRY FOR CURRENT PORT int SDCBYTE = 0; // CONTROL BYTE FOR CURRENT FRAME VOID * BUFFER = NULL; // GENERAL SAVE AREA FOR BUFFER ADDR VOID * ADJBUFFER = NULL; // BASE ADJUSED FOR DIGIS UCHAR TEMPFIELD[7] = ""; // ADDRESS WORK FILED void * TRACE_Q = NULL; // TRANSMITTED FRAMES TO BE TRACED int RANDOM = 0; // 'RANDOM' NUMBER FOR PERSISTENCE CALCS int L2TIMERFLAG = 0; // INCREMENTED AT 18HZ BY TIMER INTERRUPT int L3TIMERFLAG = 0; // DITTO int L4TIMERFLAG = 0; // DITTO char HEADERCHAR = '}'; // CHAR FOR _NODE HEADER MSGS VOID * LASTPOINTER = NULL; // PERVIOUS _NODE DURING CHAINING int REALTIMETICKS = 0; int BGTIMER = 0; // TO CONTROL BG SCANS VOID * CONFIGPTR = NULL; // Internal Config Get Offset int AUTOSAVE = 0; // AUTO SAVE NODES ON EXIT FLAG int L4APPL = 1; // Application for BBSCALL/ALIAS connects int CFLAG = 0; // C =HOST Command VOID * IDMSG_Q = NULL; // ID/BEACONS WAITING TO BE SENT int NODESINPROGRESS = 0; VOID * CURRENTNODE = NULL; // NEXT _NODE TO SEND VOID * DESTHEADER = NULL; // HEAD OF SORTED NODES CHAIN int L3TIMER = 1; // TIMER FOR 'NODES' MESSAGE int IDTIMER = 0; // TIMER FOR ID MESSAGE int BTTIMER = 0; // TIMER FOR BT MESSAGE UCHAR * NEXTFREEDATA = NULL; // ADDRESS OF NEXT FREE BYTE of shared memory int NEEDMH = 0; struct DATAMESSAGE BTHDDR = {0,0,9,240,13}; struct _MESSAGE IDHDDR = {0,0,23,0,0,3, 240}; VOID * IDMSG = &IDHDDR; //DD 0 ; CHAIN // DB 0 ; PORT int BTLENGTH = 9; // DW 9 ; LENGTH // DB 0F0H ; PID char BTEXTFLD[256] ="\r"; char BridgeMap[MaxBPQPortNo + 1][MaxBPQPortNo + 1] = {0}; // Keep Buffers at end #define DATABYTES 600000 // WAS 320000 UCHAR DATAAREA[DATABYTES] = ""; void ** Bufferlist[1000] = {0}; extern BOOL IPRequired; extern BOOL PMRequired; extern int MaxHops; extern int MAXRTT; extern USHORT CWTABLE[]; extern struct _TRANSPORTENTRY * L4TABLE; extern UCHAR ROUTEQUAL; extern UINT BPQMsg; extern int NUMBEROFTNCPORTS; extern APPLCALLS APPLCALLTABLE[]; // LOOPBACK PORT ROUTINES VOID LINKINIT(PEXTPORTDATA PORTVEC) { WritetoConsoleLocal("Loopback\n"); } VOID LINKTX(PEXTPORTDATA PORTVEC, PMESSAGE Buffer) { // LOOP BACK TO SWITCH struct _LINKTABLE * LINK; LINK = Buffer->Linkptr; if (LINK) { if (LINK->L2TIMER) LINK->L2TIMER = LINK->L2TIME; Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER } C_Q_ADD(&PORTVEC->PORTCONTROL.PORTRX_Q, Buffer); } VOID LINKRX() { } VOID LINKTIMER() { } VOID LINKCLOSE() { } VOID EXTCLOSE() { } BOOL KISSTXCHECK() { return 0; } BOOL LINKTXCHECK() { return 0; } void * Dummy(int fn, int port, PDATAMESSAGE buff) // Dummy for missing EXT Driver { return 0; } VOID EXTINIT(PEXTPORTDATA PORTVEC) { // LOAD DLL - NAME IS IN PORT_DLL_NAME void *(* Startup) (PEXTPORTDATA PORTVEC); // ADDR OF Startup ROUTINE PORTVEC->PORT_EXT_ADDR = Dummy; Startup = InitializeExtDriver(PORTVEC); if (Startup == 0) { WritetoConsoleLocal("Driver installation failed\n"); return; } // CALL THE ROUTINE TO START IT UP // Startup returns address of processing routine PORTVEC->PORT_EXT_ADDR = (void *(__cdecl *)(int,int,PDATAMESSAGE))Startup(PORTVEC);; if (PORTVEC->PORT_EXT_ADDR == 0) { WritetoConsoleLocal("Driver Initialisation failed\n"); return; } } VOID EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer) { struct _LINKTABLE * LINK; struct PORTCONTROL * PORT = (struct PORTCONTROL *)PORTVEC; // RESET TIMER, unless BAYCOM if (PORT->KISSFLAGS == 255) // Used for BAYCOM { PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, (PDATAMESSAGE)Buffer); return; // Baycom driver passes frames to trace once sent } LINK = Buffer->Linkptr; if (LINK) { if (LINK->L2TIMER) LINK->L2TIMER = LINK->L2TIME; if (PORT->TNC == 0 || PORT->TNC->Hardware != H_KISSHF) Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER } PORTVEC->PORT_EXT_ADDR(2, PORT->PORTNUMBER, (PDATAMESSAGE)Buffer); if (PORT->PROTOCOL == 10 && PORT->TNC && PORT->TNC->Hardware != H_KISSHF) { ReleaseBuffer(Buffer); return; } C_Q_ADD(&TRACE_Q, Buffer); return; } VOID EXTRX(PEXTPORTDATA PORTVEC) { struct _MESSAGE * Message; size_t Len; struct PORTCONTROL * PORT = (struct PORTCONTROL *)PORTVEC; Loop: if (QCOUNT < 10) return; Message = GetBuff(); if (Message == NULL) return; Len = (size_t)PORTVEC->PORT_EXT_ADDR(1, PORT->PORTNUMBER, (PDATAMESSAGE)Message); if (Len == 0) { ReleaseBuffer((UINT *)Message); return; } if (PORT->PROTOCOL == 10) { // PACTOR Style Port - Negative values used to report events - for now -1 = Disconnected if (Len == -1) { int Sessno = Message->PORT; TRANSPORTENTRY * Session; ReleaseBuffer((UINT *)Message); // GET RID OF ANY SESSION ENTRIES Session = PORTVEC->ATTACHEDSESSIONS[Sessno]; if (Session) { struct TNCINFO * TNC = PORTVEC->PORTCONTROL.TNC; CloseSessionPartner(Session); // is this the place to run DisconnectScript? if (TNC->DisconnectScript) { int n = 0; struct DATAMESSAGE * Buffer; TRANSPORTENTRY Session = {0}; // = TNC->PortRecord->ATTACHEDSESSIONS[Sessno]; while (TNC->DisconnectScript[n]) { Buffer = GetBuff(); if (Buffer) { Session.Secure_Session = 1; Session.CIRCUITINDEX = -1; Buffer->LENGTH = sprintf(Buffer->L2DATA, "%s\r", TNC->DisconnectScript[n++]) + (sizeof(void *) + 4); CommandHandler(&Session, Buffer); }; } } PORTVEC->ATTACHEDSESSIONS[Sessno] = NULL; } return; } } C_Q_ADD(&PORT->PORTRX_Q, (UINT *)Message); goto Loop; return; } VOID EXTTIMER(PEXTPORTDATA PORTVEC) { // USED TO SEND A RE-INIT IN THE CORRECT PROCESS if (PORTVEC->EXTRESTART) { PORTVEC->EXTRESTART = 0; //CLEAR PORTVEC->PORT_EXT_ADDR(4, PORTVEC->PORTCONTROL.PORTNUMBER, 0); } PORTVEC->PORT_EXT_ADDR(7, PORTVEC->PORTCONTROL.PORTNUMBER, 0); // Timer Routine } VOID EXTSLOWTIMER(PEXTPORTDATA PORTVEC) { PORTVEC->PORT_EXT_ADDR(8, PORTVEC->PORTCONTROL.PORTNUMBER, 0); // Timer Routine } size_t EXTTXCHECK(PEXTPORTDATA PORTVEC, int Chan) { uintptr_t Temp = Chan; return (size_t)PORTVEC->PORT_EXT_ADDR(3, PORTVEC->PORTCONTROL.PORTNUMBER, (void *)Temp); } VOID PostDataAvailable(TRANSPORTENTRY * Session) { #ifndef LINBPQ if (Session->L4CIRCUITTYPE & BPQHOST) { BPQVECSTRUC * HostSess = Session->L4TARGET.HOST; if (HostSess) { if (HostSess->HOSTHANDLE) { PostMessage(HostSess->HOSTHANDLE, BPQMsg, HostSess->HOSTSTREAM, 2); } } } #endif } VOID PostStateChange(TRANSPORTENTRY * Session) { #ifndef LINBPQ if (Session->L4CIRCUITTYPE & BPQHOST) { BPQVECSTRUC * HostSess = Session->L4TARGET.HOST; if (HostSess) { if (HostSess->HOSTHANDLE); { PostMessage(HostSess->HOSTHANDLE, BPQMsg, HostSess->HOSTSTREAM, 4); } } } #endif } #ifdef LINBPQ #define HDLCTX KHDLCTX #define HDLCRX KHDLCRX #define HDLCTIMER KHDLCTIMER #define HDLCCLOSE KHDLCCLOSE #define HDLCTXCHECK KHDLCTXCHECK #define PC120INIT KHDLCINIT #define DRSIINIT KHDLCINIT #define TOSHINIT KHDLCINIT #define RLC100INIT KHDLCINIT #define BAYCOMINIT KHDLCINIT #define PA0INIT KHDLCINIT int KHDLCINIT(PHDLCDATA PORTVEC); void KHDLCTX(struct KISSINFO * KISS, PMESSAGE Buffer); int KHDLCRX(PHDLCDATA PORTVEC); void KHDLCTIMER(PHDLCDATA PORTVEC); void KHDLCCLOSE(PHDLCDATA PORTVEC); BOOL KHDLCTXCHECK(); #else extern VOID PC120INIT(), DRSIINIT(), TOSHINIT(); extern VOID RLC100INIT(), BAYCOMINIT(), PA0INIT(); extern VOID HDLCTX(); extern VOID HDLCRX(); extern VOID HDLCTIMER(); extern VOID HDLCCLOSE(); extern VOID HDLCTXCHECK(); #endif extern VOID KISSINIT(), KISSTX(), KISSRX(), KISSTIMER(), KISSCLOSE(); extern VOID EXTINIT(PEXTPORTDATA PORTVEC), EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer), LINKRX(), EXTRX(PEXTPORTDATA PORTVEC); extern VOID LINKCLOSE(), EXTCLOSE() ,LINKTIMER(), EXTTIMER(PEXTPORTDATA PORTVEC); // VECTORS TO HARDWARE DEPENDENT ROUTINES VOID * INITCODE[12] = {KISSINIT, PC120INIT, DRSIINIT, TOSHINIT, KISSINIT, RLC100INIT, RLC100INIT, LINKINIT, EXTINIT, BAYCOMINIT, PA0INIT, KISSINIT}; VOID * TXCODE[12] = {KISSTX, HDLCTX, HDLCTX, HDLCTX, KISSTX, HDLCTX, HDLCTX, LINKTX, EXTTX, HDLCTX, HDLCTX, KISSTX}; VOID * RXCODE[12] = {KISSRX, HDLCRX, HDLCRX, HDLCRX, KISSRX, HDLCRX, HDLCRX, LINKRX, EXTRX, HDLCRX, HDLCRX, KISSRX}; VOID * TIMERCODE[12] = {KISSTIMER, HDLCTIMER, HDLCTIMER, HDLCTIMER, KISSTIMER, HDLCTIMER, HDLCTIMER, LINKTIMER, EXTTIMER, HDLCTIMER, HDLCTIMER, KISSTIMER}; VOID * CLOSECODE[12] = {KISSCLOSE, HDLCCLOSE, HDLCCLOSE, HDLCCLOSE, KISSCLOSE, HDLCCLOSE, HDLCCLOSE, LINKCLOSE, EXTCLOSE, HDLCCLOSE, HDLCCLOSE, KISSCLOSE}; VOID * TXCHECKCODE[12] = {KISSTXCHECK, HDLCTXCHECK, HDLCTXCHECK, HDLCTXCHECK, KISSTXCHECK, HDLCTXCHECK, HDLCTXCHECK, LINKTXCHECK, EXTTXCHECK, HDLCTXCHECK, HDLCTXCHECK, KISSTXCHECK}; extern int BACKGROUND(); extern int L2TimerProc(); extern int L3TimerProc(); extern int L4TimerProc(); extern int L3FastTimer(); extern int StatsTimer(); extern int COMMANDHANDLER(); VOID SDETX(struct _LINKTABLE * LINK); extern int L4BG(); extern int L3BG(); extern int TNCTimerProc(); extern int PROCESSIFRAME(); int xxxxx = MAXDATA; BOOL Start() { struct CONFIGTABLE * cfg = &xxcfg; struct APPLCONFIG * ptr1; struct PORTCONTROL * PORT; struct FULLPORTDATA * FULLPORT; // Including HW Data struct FULLPORTDATA * NEXTPORT; // Including HW Data struct _EXTPORTDATA * EXTPORT; APPLCALLS * APPL; struct ROUTE * ROUTE; struct DEST_LIST * DEST; struct CMDX * CMD; int PortSlot = 1; uintptr_t int3; unsigned char * ptr2 = 0, * ptr3, * ptr4; USHORT * CWPTR; int i, n; struct ROUTECONFIG * Rcfg; NEXTFREEDATA = &DATAAREA[0]; // For Reinit memset(DATAAREA, 0, DATABYTES); // Reinit everything in case of restart FREE_Q = 0; TRACE_Q = 0; IDMSG_Q = 0; NUMBEROFPORTS = 0; MAXBUFFS = 0; QCOUNT = 0; NUMBEROFNODES = 0; DESTHEADER = 0; NODESINPROGRESS = 0; CURRENTNODE = 0; L3TIMER = 1; // SEND NODES if (cfg->C_NODEALIAS[0] == 0) memset(cfg->C_NODEALIAS, ' ', 10); TimeLoaded = time(NULL); AUTOSAVE = cfg->C_AUTOSAVE; if (cfg->C_L4APPL) L4APPL = cfg->C_L4APPL; CFLAG = cfg->C_C; IPRequired = cfg->C_IP; PMRequired = cfg->C_PM; if (cfg->C_MAXHOPS) MaxHops = cfg->C_MAXHOPS; if (cfg->C_MAXRTT) MAXRTT = cfg->C_MAXRTT * 100; if (cfg->C_NODE == 0 && cfg->C_BBS) { // USE BBS CALL FOR NODE if Set, otherwise find first APPLCALL // Unless BBS also = 0 if (cfg->C_BBSCALL[0]) { memcpy(MYNODECALL, cfg->C_BBSCALL, 10); memcpy(MYALIASTEXT, cfg->C_BBSALIAS, 6); memcpy(MYALIASLOPPED, cfg->C_BBSALIAS, 10); } else { ptr1 = &cfg->C_APPL[0]; for (i = 0; i < NumberofAppls; i++) { if (ptr1->ApplCall[0] != ' ') { memcpy(MYNODECALL, &ptr1->ApplCall[0], 10); memcpy(MYALIASTEXT, &ptr1->ApplAlias, 6); memcpy(MYALIASLOPPED, &ptr1->ApplAlias, 10); break; } ptr1++; } } } else { memcpy(MYNODECALL, cfg->C_NODECALL, 10); memcpy(MYALIASTEXT, cfg->C_NODEALIAS, 6); memcpy(MYALIASLOPPED, cfg->C_NODEALIAS, 10); } strlop(MYALIASLOPPED, ' '); // IF NO BBS, SET BOTH TO _NODE CALLSIGN if (cfg->C_BBS == 0) { memcpy(APPLCALLTABLE[0].APPLCALL_TEXT, cfg->C_NODECALL, 10); memcpy(APPLCALLTABLE[0].APPLALIAS_TEXT, cfg->C_NODEALIAS, 10); } else { memcpy(APPLCALLTABLE[0].APPLCALL_TEXT, cfg->C_BBSCALL, 10); memcpy(APPLCALLTABLE[0].APPLALIAS_TEXT, cfg->C_BBSALIAS, 10 ); } BBSQUAL = cfg->C_BBSQUAL; // copy MYCALL to NETROMCALL memcpy(MYNETROMCALL, MYNODECALL, 10); // if NETROMCALL Defined, use it if (cfg->C_NETROMCALL[0] && cfg->C_NETROMCALL[0] != ' ') memcpy(MYNETROMCALL, cfg->C_NETROMCALL, 10); strlop(MYNETROMCALL, ' '); strlop(MYNODECALL, ' '); memcpy(NODECALLLOPPED, MYNODECALL, 10); strlop(NODECALLLOPPED, ' '); APPLCALLTABLE[0].APPLQUAL = BBSQUAL; if (cfg->C_WASUNPROTO == 0 && cfg->C_BTEXT) { char * ptr1 = &cfg->C_BTEXT[0]; char * ptr2 = BTHDDR.L2DATA; int len = 120; BTHDDR.LENGTH = 1; // PID while ((*ptr1) && len--) { *(ptr2++) = *(ptr1++); BTHDDR.LENGTH ++; } } OBSINIT = cfg->C_OBSINIT; OBSMIN = cfg->C_OBSMIN; L3INTERVAL = cfg->C_NODESINTERVAL; IDINTERVAL = cfg->C_IDINTERVAL; if (IDINTERVAL) IDTIMER = 2; BTINTERVAL = cfg->C_BTINTERVAL; if (BTINTERVAL) BTTIMER = 2; MINQUAL = cfg->C_MINQUAL; FULL_CTEXT = cfg->C_FULLCTEXT; L3LIVES = cfg->C_L3TIMETOLIVE; L4N2 = cfg->C_L4RETRIES; L4DEFAULTWINDOW = cfg->C_L4WINDOW; L4T1 = cfg->C_L4TIMEOUT; // MOV AX,C_BUFFERS // MOV NUMBEROFBUFFERS,AX PACLEN = cfg->C_PACLEN; T3 = cfg->C_T3 * 3; L4LIMIT = cfg->C_IDLETIME; if (L4LIMIT && L4LIMIT < 120) L4LIMIT = 120; // Don't allow stupidly low L2KILLTIME = L4LIMIT * 3; L4DELAY = cfg->C_L4DELAY; BBS = cfg->C_BBS; NODE = cfg->C_NODE; LINKEDFLAG = cfg->C_LINKEDFLAG; MAXLINKS = cfg->C_MAXLINKS; MAXDESTS = cfg->C_MAXDESTS; MAXNEIGHBOURS = cfg->C_MAXNEIGHBOURS; MAXCIRCUITS = cfg->C_MAXCIRCUITS; HIDENODES = cfg->C_HIDENODES; LogL4Connects = cfg->C_LogL4Connects; LogAllConnects = cfg->C_LogAllConnects; AUTOSAVEMH = cfg->C_SaveMH; ADIFLogEnabled = cfg->C_ADIF; EventsEnabled = cfg->C_EVENTS; SaveAPRSMsgs = cfg->C_SaveAPRSMsgs; M0LTEMap = cfg->C_M0LTEMap; MQTT = cfg->C_MQTT; strcpy(MQTT_HOST, cfg->C_MQTT_HOST); MQTT_PORT = cfg->C_MQTT_PORT; strcpy(MQTT_USER, cfg->C_MQTT_USER); strcpy(MQTT_PASS, cfg->C_MQTT_PASS); // Get pointers to PASSWORD and APPL1 commands // int APPL1 = 0; //int PASSCMD = 0; CMD = &COMMANDS[0]; n = 0; for (n = 0; n < NUMBEROFCOMMANDS; n++) { if (APPL1 == 0 && CMD->String[0] == '*') // First appl { APPLS = (char *)CMD; APPL1 = n; } if (PASSCMD == 0 && memcmp(CMD->String, "PASSWORD", 8) == 0) PASSCMD = n; CMD++; } // SET UP APPLICATION LIST memset(&CMDALIAS[0][0], ' ', NumberofAppls * ALIASLEN ); ptr1 = (struct APPLCONFIG *)&xxcfg.C_APPL[0]; ptr3 = &CMDALIAS[0][0]; for (i = 0; i < NumberofAppls; i++) { if (ptr1->Command[0] != ' ') { ptr2 = (char *)&COMMANDS[APPL1 + i]; memcpy(ptr2, ptr1, 12); // See if an Alias if (ptr1->CommandAlias[0] != ' ') memcpy(ptr3, ptr1->CommandAlias, ALIASLEN); // SET LENGTH FIELD *(ptr2 + 12) = 0; // LENGTH ptr4 = ptr2; while (*(ptr4) > 32) { ptr4++; *(ptr2 + 12) = *(ptr2 + 12) + 1; } } ptr1 ++; ptr2 += CMDXLEN; ptr3 += ALIASLEN; } // Set up Exclude List memcpy(ExcludeList, cfg->C_EXCLUDE, 71); // SET UP PORT TABLE PortRec = &cfg->C_PORT[0];// (struct PORTCONFIG *)ptr2; PORTTABLE = (VOID *)NEXTFREEDATA; FULLPORT = (struct FULLPORTDATA *)PORTTABLE; while (PortRec->PORTNUM) { // SET UP NEXT PORT PTR PORT = &FULLPORT->PORTCONTROL; NEXTPORT = FULLPORT; NEXTPORT++; PORT->PORTPOINTER = (struct PORTCONTROL *)NEXTPORT; PORT->PORTNUMBER = (UCHAR)PortRec->PORTNUM; PORT->PortSlot = PortSlot++; memcpy(PORT->PORTDESCRIPTION, PortRec->ID, 30); PORT->PORTTYPE = (char)PortRec->TYPE; PORT->PORTINITCODE = INITCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE PORT->PORTTXROUTINE = TXCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE PORT->PORTRXROUTINE = RXCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE PORT->PORTTIMERCODE = TIMERCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE PORT->PORTCLOSECODE = CLOSECODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE PORT->PORTTXCHECKCODE = TXCHECKCODE[PORT->PORTTYPE / 2]; // ADDR OF INIT ROUTINE PORT->PROTOCOL = (char)PortRec->PROTOCOL; PORT->IOBASE = PortRec->IOADDR; if (PortRec->SerialPortName && PortRec->SerialPortName[0]) PORT->SerialPortName = _strdup(PortRec->SerialPortName); else { if (PORT->IOBASE > 0 && PORT->IOBASE < 256) { char Name[80]; #ifndef WIN32 sprintf(Name, "com%d", PORT->IOBASE); #else sprintf(Name, "COM%d", PORT->IOBASE); #endif PORT->SerialPortName = _strdup(Name); } else PORT->SerialPortName = _strdup("NOPORT"); } PORT->INTLEVEL = (char)PortRec->INTLEVEL; PORT->BAUDRATE = PortRec->SPEED; if (PORT->BAUDRATE == 49664) PORT->BAUDRATE = (int)115200; PORT->CHANNELNUM = (char)PortRec->CHANNEL; PORT->PORTQUALITY = (UCHAR)PortRec->QUALITY; PORT->NormalizeQuality = !PortRec->NoNormalize; PORT->IgnoreUnlocked = PortRec->IGNOREUNLOCKED; PORT->INP3ONLY = PortRec->INP3ONLY; PORT->PORTWINDOW = (UCHAR)PortRec->MAXFRAME; if (PortRec->PROTOCOL == 0 || PORT->PORTTYPE == 22) // KISS or I2C PORT->PORTTXDELAY = PortRec->TXDELAY /10; else PORT->PORTTXDELAY = PortRec->TXDELAY; if (PortRec->PROTOCOL == 0 || PORT->PORTTYPE == 22) // KISS or I2C PORT->PORTSLOTTIME = (UCHAR)PortRec->SLOTTIME / 10; else PORT->PORTSLOTTIME = (UCHAR)PortRec->SLOTTIME; PORT->PORTPERSISTANCE = (UCHAR)PortRec->PERSIST; PORT->FULLDUPLEX = (UCHAR)PortRec->FULLDUP; PORT->SOFTDCDFLAG = (UCHAR)PortRec->SOFTDCD; PORT->PORTT1 = PortRec->FRACK / 333; PORT->PORTT2 = PortRec->RESPTIME /333; PORT->PORTN2 = (UCHAR)PortRec->RETRIES; PORT->PORTPACLEN = (UCHAR)PortRec->PACLEN; PORT->QUAL_ADJUST = (UCHAR)PortRec->QUALADJUST; PORT->DIGIFLAG = PortRec->DIGIFLAG; if (PortRec->DIGIPORT && CanPortDigi(PortRec->DIGIPORT)) PORT->DIGIPORT = PortRec->DIGIPORT; PORT->DIGIMASK = PortRec->DIGIMASK; PORT->USERS = (UCHAR)PortRec->USERS; // PORTTAILTIME - if KISS, set a default, and cnvert to ticks if (PORT->PORTTYPE == 0) { if (PortRec->TXTAIL) PORT->PORTTAILTIME = PortRec->TXTAIL / 10; else PORT->PORTTAILTIME = 3; // 10ths } else //; ON HDLC, TAIL TIMER IS USED TO HOLD RTS FOR 'CONTROLLED FULL DUP' - Val in seconds PORT->PORTTAILTIME = (UCHAR)PortRec->TXTAIL; PORT->PORTBBSFLAG = (char)PortRec->ALIAS_IS_BBS; PORT->PORTL3FLAG = (char)PortRec->L3ONLY; PORT->KISSFLAGS = PortRec->KISSOPTIONS; PORT->PORTINTERLOCK = (UCHAR)PortRec->INTERLOCK; PORT->NODESPACLEN = (UCHAR)PortRec->NODESPACLEN; PORT->TXPORT = (UCHAR)PortRec->TXPORT; PORT->PORTMINQUAL = PortRec->MINQUAL; if (PortRec->MAXDIGIS) PORT->PORTMAXDIGIS = PortRec->MAXDIGIS; else PORT->PORTMAXDIGIS = 8; PORT->PortNoKeepAlive = PortRec->DefaultNoKeepAlives; PORT->PortUIONLY = PortRec->UIONLY; PORT->TXPORT = (UCHAR)PortRec->TXPORT; // SET UP CWID if (PortRec->CWIDTYPE == 'o') PORT->CWTYPE = 'O'; else PORT->CWTYPE = PortRec->CWIDTYPE; ptr2 = &PortRec->CWID[0]; CWPTR = &PORT->CWID[0]; PORT->CWIDTIMER = (29 - PORT->PORTNUMBER) * 600; // TICKSPERMINUTE PORT->CWPOINTER = &PORT->CWID[0]; for (i = 0; i < 8; i++) // MAX ID LENGTH { char c = *(ptr2++); if (c < 32) break; if (c > 'Z') continue; c -= '/'; // Table stats at / c &= 127; *(CWPTR) = CWTABLE[c]; CWPTR++; } // SEE IF LINK CALLSIGN/ALIAS SPECIFIED if (PortRec->PORTCALL[0]) ConvToAX25(PortRec->PORTCALL, PORT->PORTCALL); if (PortRec->PORTALIAS[0]) ConvToAX25(PortRec->PORTALIAS, PORT->PORTALIAS); if (PortRec->PORTALIAS2[0]) ConvToAX25(PortRec->PORTALIAS2, PORT->PORTALIAS2); if (PortRec->DLLNAME[0]) { EXTPORT = (struct _EXTPORTDATA *)PORT; memcpy(EXTPORT->PORT_DLL_NAME, PortRec->DLLNAME, 16); } if (PortRec->BCALL[0]) ConvToAX25(PortRec->BCALL, PORT->PORTBCALL); PORT->XDIGIS = PortRec->XDIGIS; // Crossband digi aliases memcpy(&PORT->PORTIPADDR, &PortRec->IPADDR, 4); PORT->ListenPort = PortRec->ListenPort; if (PortRec->TCPPORT) { PORT->KISSTCP = TRUE; PORT->IOBASE = PortRec->TCPPORT; if (PortRec->IPADDR == 0) PORT->KISSSLAVE = TRUE; } if (PortRec->WL2K) memcpy(&PORT->WL2KInfo, PortRec->WL2K, sizeof(struct WL2KInfo)); PORT->RIGPort = PortRec->RIGPORT; if (PortRec->HavePermittedAppls) PORT->PERMITTEDAPPLS = PortRec->PERMITTEDAPPLS; else PORT->PERMITTEDAPPLS = 0xffffffff; // Default to all PORT->Hide = PortRec->Hide; PORT->SmartIDInterval = PortRec->SmartID; if (PortRec->KissParams && (PORT->PORTTYPE == 0 || PORT->PORTTYPE == 22)) { struct KISSINFO * KISS = (struct KISSINFO *)PORT; UCHAR KissString[128]; int KissLen = 0; unsigned char * Kissptr = KissString; char * ptr; char * Context; ptr = strtok_s(PortRec->KissParams, " ", &Context); while (ptr && ptr[0] && KissLen < 120) { *(Kissptr++) = atoi (ptr); KissLen++; ptr = strtok_s(NULL, " ", &Context); } KISS->KISSCMD = malloc(256); KISS->KISSCMDLEN = KissEncode(KissString, KISS->KISSCMD, KissLen); KISS->KISSCMD = realloc(KISS->KISSCMD, KISS->KISSCMDLEN); } PORT->SendtoM0LTEMap = PortRec->SendtoM0LTEMap; PORT->PortFreq = PortRec->PortFreq; PORT->M0LTEMapInfo = PortRec->M0LTEMapInfo; PORT->QtSMPort = PortRec->QtSMPort; if (PortRec->BBSFLAG) // Appl 1 not permitted - BBSFLAG=NOBBS PORT->PERMITTEDAPPLS &= 0xfffffffe; // Clear bottom bit // SEE IF PERMITTED LINK CALLSIGNS SPECIFIED ptr2 = &PortRec->VALIDCALLS[0]; if (*(ptr2)) { ptr3 = (char *)PORT->PORTPOINTER; // Permitted Calls follows Port Info PORT->PERMITTEDCALLS = ptr3; while (*(ptr2) > 32) { ConvToAX25(ptr2, ptr3); ptr3 += 7; PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; if (strchr(ptr2, ',')) { ptr2 = strchr(ptr2, ','); ptr2++; } else break; } ptr3 ++; // Terminating NULL // Round to word boundary (for ARM5 etc) int3 = (uintptr_t)ptr3; int3 += 7; int3 &= 0xfffffffffffffff8; ptr3 = (UCHAR *)int3; PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; } // SEE IF PORT UNPROTO ADDR SPECIFIED ptr2 = &PortRec->UNPROTO[0]; if (*(ptr2)) { ptr3 = (char *)PORT->PORTPOINTER; // Unproto follows port info PORT->PORTUNPROTO = ptr3; while (*(ptr2) > 32) { ConvToAX25(ptr2, ptr3); ptr3 += 7; PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; if (strchr(ptr2, ',')) { ptr2 = strchr(ptr2, ','); ptr2++; } else break; } ptr3 ++; // Terminating NULL // Round to word boundsaty (for ARM5 etc) int3 = (uintptr_t)ptr3; int3 += 7; int3 &= 0xfffffffffffffff8; ptr3 = (UCHAR *)int3; PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; } // ADD MH AREA IF NEEDED if (PortRec->MHEARD != 'N') { NEEDMH = 1; // Include MH in Command List ptr3 = (char *)PORT->PORTPOINTER; // Permitted Calls follows Port Info PORT->PORTMHEARD = (PMHSTRUC)ptr3; ptr3 += (MHENTRIES + 1)* sizeof(MHSTRUC); // Round to word boundsaty (for ARM5 etc) int3 = (uintptr_t)ptr3; int3 += 7; int3 &= 0xfffffffffffffff8; ptr3 = (UCHAR *)int3; PORT->PORTPOINTER = (struct PORTCONTROL *)ptr3; } PortRec++; NUMBEROFPORTS ++; FULLPORT = (struct FULLPORTDATA *)PORT->PORTPOINTER; } PORT->PORTPOINTER = NULL; // End of list NEXTFREEDATA = (UCHAR *)FULLPORT; // SET UP APPLICATION CALLS AND ALIASES APPL = &APPLCALLTABLE[0]; ptr1 = (struct APPLCONFIG *)&xxcfg.C_APPL[0]; i = NumberofAppls; if (ptr1->ApplCall[0] == ' ') { // APPL1CALL IS NOT SPECIFED - LEAVE VALUES SET FROM BBSCALL APPL++; ptr1++; i--; } while (i) { memcpy(APPL->APPLCALL_TEXT, ptr1->ApplCall, 10); ConvToAX25(APPL->APPLCALL_TEXT, APPL->APPLCALL); memcpy(APPL->APPLALIAS_TEXT, ptr1->ApplAlias, 10); ConvToAX25(APPL->APPLALIAS_TEXT, APPL->APPLALIAS); ConvToAX25(ptr1->L2Alias, APPL->L2ALIAS); memcpy(APPL->APPLCMD, ptr1->Command, 12); APPL->APPLQUAL = ptr1->ApplQual; if (ptr1->CommandAlias[0] != ' ') { APPL->APPLHASALIAS = 1; memcpy(APPL->APPLALIASVAL, &ptr1->CommandAlias[0], 48); } APPL++; ptr1++; i--; } // SET UP VARIOUS CONTROL TABLES LINKS = (VOID *)NEXTFREEDATA; NEXTFREEDATA += MAXLINKS * sizeof(struct _LINKTABLE); DESTS = (VOID *)NEXTFREEDATA; NEXTFREEDATA += MAXDESTS * sizeof(struct DEST_LIST); ENDDESTLIST = (VOID *)NEXTFREEDATA; NEIGHBOURS = (VOID *)NEXTFREEDATA; NEXTFREEDATA += MAXNEIGHBOURS * sizeof(struct ROUTE); L4TABLE = (VOID *)NEXTFREEDATA; NEXTFREEDATA += MAXCIRCUITS * sizeof(TRANSPORTENTRY); // SET UP DEFAULT ROUTES LIST Rcfg = &cfg->C_ROUTE[0]; ROUTE = NEIGHBOURS; while (Rcfg->call[0]) { int FRACK; char * VIA; char axcall[8]; ConvToAX25(Rcfg->call, ROUTE->NEIGHBOUR_CALL); // if VIA convert digis VIA = strstr(Rcfg->call, "VIA"); if (VIA) { VIA += 4; if (ConvToAX25(VIA, axcall)) { memcpy(ROUTE->NEIGHBOUR_DIGI1, axcall, 7); VIA = strchr(VIA, ' '); if (VIA) { VIA++; if (ConvToAX25(VIA, axcall)) memcpy(ROUTE->NEIGHBOUR_DIGI2, axcall, 7); } } } ROUTE->NEIGHBOUR_QUAL = Rcfg->quality; ROUTE->NEIGHBOUR_PORT = Rcfg->port; PORT = GetPortTableEntryFromPortNum(ROUTE->NEIGHBOUR_PORT); if (Rcfg->pwind & 0x40) ROUTE->NoKeepAlive = 1; else if (PORT != NULL) ROUTE->NoKeepAlive = PORT->PortNoKeepAlive; if (Rcfg->pwind & 0x80 || (PORT && PORT->INP3ONLY)) { ROUTE->INP3Node = 1; ROUTE->NoKeepAlive = 0; // Cant have INP3 and NOKEEPALIVES } ROUTE->NBOUR_MAXFRAME = Rcfg->pwind & 0x3f; FRACK = Rcfg->pfrack; ROUTE->NBOUR_FRACK = FRACK / 333; ROUTE->NBOUR_PACLEN = Rcfg->ppacl; ROUTE->OtherendsRouteQual = ROUTE->OtherendLocked = Rcfg->farQual; ROUTE->NEIGHBOUR_FLAG = 1; // Locked Rcfg++; ROUTE++; } // SET UP INFO MESSAGE ptr2 = &cfg->C_INFOMSG[0]; ptr3 = NEXTFREEDATA; INFOMSG = ptr3; while ((*ptr2)) { *(ptr3++) = *(ptr2++); } *ptr3++ = 0; // Null Terminate NEXTFREEDATA = ptr3; // SET UP CTEXT MESSAGE ptr2 = &cfg->C_CTEXT[0]; ptr3 = NEXTFREEDATA; CTEXTMSG = ptr3; while ((*ptr2)) { *(ptr3++) = *(ptr2++); } CTEXTLEN = (int)(ptr3 - (unsigned char *)CTEXTMSG); NEXTFREEDATA = ptr3; // SET UP ID MESSAGE IDHDDR.DEST[0] = 'I'+'I'; IDHDDR.DEST[1] = 'D'+'D'; IDHDDR.DEST[2] = 0x40; IDHDDR.DEST[3] = 0x40; IDHDDR.DEST[4] = 0x40; IDHDDR.DEST[5] = 0x40; IDHDDR.DEST[6] = 0xe0; // ; ID IN AX25 FORM IDHDDR.CTL = 3; IDHDDR.PID = 0xf0; ptr2 = &cfg->C_IDMSG[0]; ptr3 = &IDHDDR.L2DATA[0]; while ((*ptr2)) { *(ptr3++) = *(ptr2++); } IDHDDR.LENGTH = (int)(ptr3 - (unsigned char *)&IDHDDR); int3 = (uintptr_t)NEXTFREEDATA; int3 += 7; int3 &= 0xfffffffffffffff8; NEXTFREEDATA = (UCHAR *)int3; ENDBUFFERPOOL = NEXTFREEDATA + DATABYTES; // So init will work, set to actual end later BUFFERPOOL = NEXTFREEDATA; Consoleprintf("PORTS %p LINKS %p DESTS %p ROUTES %p L4 %p BUFFERS %p\n", PORTTABLE, LINKS, DESTS, NEIGHBOURS, L4TABLE, BUFFERPOOL); Debugprintf("PORTS %p LINKS %p DESTS %p ROUTES %p L4 %p BUFFERS %p END POOL %p", PORTTABLE, LINKS, DESTS, NEIGHBOURS, L4TABLE, BUFFERPOOL, DATAAREA + DATABYTES); i = NUMBEROFBUFFERS; NUMBEROFBUFFERS = 0; while (i-- && NEXTFREEDATA < (DATAAREA + DATABYTES - (512 + 8192))) // Keep 8K free for anything that needs shared memory { Bufferlist[NUMBEROFBUFFERS] = (void **)NEXTFREEDATA; ReleaseBuffer((UINT *)NEXTFREEDATA); NEXTFREEDATA += BUFFALLOC; // was BUFFLEN NUMBEROFBUFFERS++; MAXBUFFS++; } ENDBUFFERPOOL = NEXTFREEDATA; // Copy Bridge Map memcpy(BridgeMap, &cfg->CfgBridgeMap, sizeof(BridgeMap)); // MOV EAX,_NEXTFREEDATA // CALL HEXOUT // SET UP OUR CALLIGN(S) ConvToAX25(MYNETROMCALL, NETROMCALL); ConvToAX25(MYNODECALL, MYCALL); memcpy(&IDHDDR.ORIGIN[0], MYCALL, 7); IDHDDR.ORIGIN[6] |= 0x61; // SET CMD END AND RESERVED BITS ConvToAX25(MYALIASTEXT, MYALIAS); // SET UP INITIAL DEST ENTRY FOR APPLICATIONS (IF BOTH NODE AND BBS NEEDED) // Actually wrong - we need to set up application node entries even if node = 0 DEST = DESTS; // If NODECALL isn't same as NETROMCALL, Add Dest Entry for NODECALL if (memcmp(NETROMCALL, MYCALL, 7) != 0) { memcpy(DEST->DEST_CALL, MYCALL, 7); memcpy(DEST->DEST_ALIAS, MYALIASTEXT, 6); DEST->DEST_STATE = 0x80; // SPECIAL ENTRY DEST->NRROUTE[0].ROUT_QUALITY = 255; DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; DEST++; NUMBEROFNODES++; } if (BBS) { // Add Application Entries APPL = &APPLCALLTABLE[0]; i = NumberofAppls; while (i--) { if (APPL->APPLQUAL) { memcpy(DEST->DEST_CALL, APPL->APPLCALL, 13); DEST->DEST_STATE = 0x80; // SPECIAL ENTRY DEST->NRROUTE[0].ROUT_QUALITY = (UCHAR)APPL->APPLQUAL; DEST->NRROUTE[0].ROUT_OBSCOUNT = 255; APPL->NODEPOINTER = DEST; DEST++; NUMBEROFNODES++; } APPL++; } } // Read Node and MH Recovery Files ReadNodes(); if (AUTOSAVEMH) ReadMH(); // Only if AutoSave configured // set up stream number in BPQHOSTVECTOR for (i = 0; i < 64; i++) { BPQHOSTVECTOR[i].HOSTSTREAM = i + 1; } memcpy(MYCALLWITHALIAS, MYCALL, 7); memcpy(&MYCALLWITHALIAS[7], MYALIASTEXT, 6); // Set random start value for NETROM Session ID NEXTID = (rand() % 254) + 1; GetPortCTEXT(0, 0, 0, 0); upnpInit(); lastSaveSecs = CurrentSecs = lastSlowSecs = time(NULL); return 0; } BOOL CompareCalls(UCHAR * c1, UCHAR * c2) { // COMPARE AX25 CALLSIGNS IGNORING EXTRA BITS IN SSID if (memcmp(c1, c2, 6)) return FALSE; // No Match if ((c1[6] & 0x1e) == (c2[6] & 0x1e)) return TRUE; return FALSE; } BOOL CompareAliases(UCHAR * c1, UCHAR * c2) { // COMPARE first 6 chars of AX25 CALLSIGNS if (memcmp(c1, c2, 6)) return FALSE; // No Match return TRUE; } BOOL FindNeighbour(UCHAR * Call, int Port, struct ROUTE ** REQROUTE) { struct ROUTE * ROUTE = NEIGHBOURS; struct ROUTE * FIRSTSPARE = NULL; int n = MAXNEIGHBOURS; while (n--) { if (ROUTE->NEIGHBOUR_CALL[0] == 0) // Spare if (FIRSTSPARE == NULL) FIRSTSPARE = ROUTE; if (ROUTE->NEIGHBOUR_PORT != Port) { ROUTE++; continue; } if (CompareCalls(ROUTE->NEIGHBOUR_CALL, Call)) { *REQROUTE = ROUTE; return TRUE; } ROUTE++; } // ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL *REQROUTE = FIRSTSPARE; return FALSE; } BOOL FindDestination(UCHAR * Call, struct DEST_LIST ** REQDEST) { struct DEST_LIST * DEST = DESTS; struct DEST_LIST * FIRSTSPARE = NULL; int n = MAXDESTS; while (n--) { if (DEST->DEST_CALL[0] == 0) // Spare { if (FIRSTSPARE == NULL) FIRSTSPARE = DEST; DEST++; continue; } if (CompareCalls(DEST->DEST_CALL, Call)) { *REQDEST = DEST; return TRUE; } DEST++; } // ENTRY NOT FOUND - FIRSTSPARE HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL *REQDEST = FIRSTSPARE; return FALSE; } extern UCHAR BPQDirectory[]; #define LINE_MAX 256 // Reload saved MH file VOID ReadMH() { char FN[260]; FILE *fp; char line[LINE_MAX]; UCHAR axcall[7]; char * ptr, *digi, *locptr, *locend; char * Context, * Context2; char seps[] = " \n"; int Port; struct PORTCONTROL * PORT = NULL; MHSTRUC * MH; int count = MHENTRIES; char * Digiptr; BOOL Digiused; char * HasStar; // Set up pointer to BPQNODES file if (BPQDirectory[0] == 0) { strcpy(FN,"MHSave.txt"); } else { strcpy(FN,BPQDirectory); strcat(FN,"/"); strcat(FN,"MHSave.txt"); } if ((fp = fopen(FN, "r")) == NULL) { return; } while (fgets(line, LINE_MAX, fp) != NULL) { if (memcmp(line, "Port:", 5) == 0) { Port = atoi(&line[5]); PORT = GetPortTableEntryFromPortNum(Port); if (PORT) MH = PORT->PORTMHEARD; else MH = NULL; continue; } // 1548777630 N9LYA-8 Jan 29 16:00:30 if (MH) { ptr = strtok_s(line, seps, &Context); if (ptr == NULL) continue; MH->MHTIME = atoi(ptr); ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; MH->MHCOUNT = atoi(ptr); // Get LOC and Freq First before strtok messes with line locptr = strchr(Context, '|'); if (locptr == NULL) continue; locend = strchr(++locptr, '|'); if (locend == NULL) continue; if ((locend - locptr) == 6) memcpy(MH->MHLocator, locptr, 6); locend++; strlop(locend, '\n'); if (strlen(locend) < 12) strcpy(MH->MHFreq, locend); ptr = strtok_s(NULL, "|\n", &Context); if (ptr == NULL) continue; if (ConvToAX25(ptr, axcall) == FALSE) continue; // Duff memcpy(MH->MHCALL, axcall, 7); if (ptr[10] != ' ') MH->MHDIGI = ptr[10]; // SEE IF ANY DIGIS digi = strstr(ptr, " via "); if (digi) { digi = digi + 5; Digiptr = &MH->MHDIGIS[0][0]; if (strchr(ptr, '*')) Digiused = 1; // At least one digi used else Digiused = 0; digi = strtok_s(digi, ",\n", &Context2); while(digi) { HasStar = strlop(digi, '*'); if (ConvToAX25(digi, axcall) == FALSE) break; memcpy(Digiptr, axcall, 7); if (Digiused) Digiptr[6] |= 0x80; // Set used if (HasStar) Digiused = 0; // Only last used has * Digiptr += 7; digi = strtok_s(NULL, ",/n", &Context2); } *(--Digiptr) |= 1; // Set end of address on last } else { // No Digis MH->MHCALL[6] |= 1; // Set end of address } MH++; } } fclose(fp); return; } VOID ReadNodes() { char FN[260]; FILE *fp; char line[LINE_MAX]; UCHAR axcall[7]; char * ptr; char * Context; char seps[] = " \r"; int Port, Qual; struct PORTCONTROL * PORT; // Set up pointer to BPQNODES file if (BPQDirectory[0] == 0) { strcpy(FN,"BPQNODES.dat"); } else { strcpy(FN,BPQDirectory); strcat(FN,"/"); strcat(FN,"BPQNODES.dat"); } if ((fp = fopen(FN, "r")) == NULL) { WritetoConsoleLocal( "Route/Node recovery file BPQNODES.dat not found - Continuing without it\n"); return; } // Read the saved ROUTES/NODES file while (fgets(line, LINE_MAX, fp) != NULL) { if (memcmp(line, "ROUTE ADD", 9) == 0) { struct ROUTE * ROUTE = NULL; // FORMAT IS ROUTE ADD CALLSIGN PORT QUAL (VIA .... ptr = strtok_s(&line[10], seps, &Context); if (ConvToAX25(ptr, axcall) == FALSE) continue; // DUff ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; Port = atoi(ptr); PORT = GetPortTableEntryFromPortNum(Port); if (PORT == NULL) continue; // Port has gone if (FindNeighbour(axcall, Port, &ROUTE)) continue; // Already added from ROUTES: if (ROUTE == NULL) continue; // Tsble Full memcpy(ROUTE->NEIGHBOUR_CALL, axcall, 7); ROUTE->NEIGHBOUR_PORT = Port; ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; Qual = atoi(ptr); ROUTE->NEIGHBOUR_QUAL = Qual; ptr = strtok_s(NULL, seps, &Context); // MAXFRAME if (ptr == NULL) continue; // I don't thinlk we should load locked flag from save file - only from config // But need to parse it until I stop saving it if (ptr[0] == '!') { // ROUTE->NEIGHBOUR_FLAG = 1; // LOCKED ROUTE ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; } // SEE IF ANY DIGIS if (ptr[0] == 'V') { ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; if (ConvToAX25(ptr, axcall) == FALSE) continue; // DUff memcpy(ROUTE->NEIGHBOUR_DIGI1, axcall, 7); ROUTE->NEIGHBOUR_FLAG = 1; // LOCKED ROUTE - Digi'ed routes must be locked ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; // See if another digi or MAXFRAME if (strlen(ptr) > 2) { if (ConvToAX25(ptr, axcall) == FALSE) continue; // DUff memcpy(ROUTE->NEIGHBOUR_DIGI2, axcall, 7); ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; } } Qual = atoi(ptr); ROUTE->NBOUR_MAXFRAME = Qual; ptr = strtok_s(NULL, seps, &Context); // FRACK if (ptr == NULL) continue; Qual = atoi(ptr); ROUTE->NBOUR_FRACK = Qual; ptr = strtok_s(NULL, seps, &Context); // PACLEN if (ptr == NULL) continue; Qual = atoi(ptr); ROUTE->NBOUR_PACLEN = Qual; ptr = strtok_s(NULL, seps, &Context); // INP3 if (ptr == NULL) continue; Qual = atoi(ptr); // We now take Nokeepalives from the PORT, unless specifically // Requested ROUTE->NoKeepAlive = PORT->PortNoKeepAlive; if (Qual & 4) ROUTE->NoKeepAlive = TRUE; if ((Qual & 1) || PORT->INP3ONLY) { ROUTE->NoKeepAlive = FALSE; ROUTE->INP3Node = TRUE; } ptr = strtok_s(NULL, seps, &Context); // INP3 if (ptr == NULL) continue; if (ROUTE->NEIGHBOUR_FLAG == 0 || ROUTE->OtherendLocked == 0); // Not LOCKED ROUTE ROUTE->OtherendsRouteQual = atoi(ptr); continue; } if (memcmp(line, "NODE ADD", 8) == 0) { // FORMAT IS NODE ADD ALIAS:CALL ROUTE QUAL dest_list * DEST = NULL; struct ROUTE * ROUTE = NULL; char * ALIAS; char FULLALIAS[6] = " "; int SavedOBSINIT = OBSINIT; if (line[9] == ':') { // No alias Context = &line[10]; } else { ALIAS = strtok_s(&line[9], ":", &Context); if (ALIAS == NULL) continue; memcpy(FULLALIAS, ALIAS, (int)strlen(ALIAS)); } ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; if (ConvToAX25(ptr, axcall) == FALSE) continue; // Duff if (CompareCalls(axcall, MYCALL)) continue; // Shoiuldn't happen, but to be safe! if (FindDestination(axcall, &DEST)) continue; if (DEST == NULL) continue; // Tsble Full memcpy(DEST->DEST_CALL, axcall, 7); memcpy(DEST->DEST_ALIAS, FULLALIAS, 6); NUMBEROFNODES++; RouteLoop: // GET NEIGHBOURS FOR THIS DESTINATION - CALL PORT QUAL ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; if (ConvToAX25(ptr, axcall) == FALSE) continue; // DUff ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; Port = atoi(ptr); ptr = strtok_s(NULL, seps, &Context); if (ptr == NULL) continue; Qual = atoi(ptr); if (Context[0] == '!') { OBSINIT = 255; //; SPECIAL FOR LOCKED } if (FindNeighbour(axcall, Port, &ROUTE)) { PROCROUTES(DEST, ROUTE, Qual); } OBSINIT = SavedOBSINIT; goto RouteLoop; } } fclose(fp); // loadedmsg DB cr,lf,lf,'Switch loaded and initialised OK',lf,0 return; } int DelayBuffers = 0; void sendModeReport(); void sendFreqReport(); VOID TIMERINTERRUPT() { // Main Processing loop - CALLED EVERY 100 MS int i; struct PORTCONTROL * PORT = PORTTABLE; PMESSAGE Buffer; struct _LINKTABLE * LINK; struct _MESSAGE * Message; int toPort; CurrentSecs = time(NULL); BGTIMER++; REALTIMETICKS++; L2TIMERFLAG++; // INCREMENT FLAG FOR BG L3TIMERFLAG++; // INCREMENT FLAG FOR BG L4TIMERFLAG++; // INCREMENT FLAG FOR BG // CALL PORT TIMER ROUTINES for (i = 0; i < NUMBEROFPORTS; i++) { PORT->PORTTIMERCODE(PORT); // Check Smart ID timer if (PORT->SmartIDNeeded && PORT->SmartIDNeeded < time(NULL)) SendSmartID(PORT); PORT = PORT->PORTPOINTER; } // CHECK FOR TIMER ACTIVITY if (L2TIMERFLAG >= 3) { L2TIMERFLAG -= 3; L2TimerProc(); // 300 mS } if (CurrentSecs - lastSlowSecs >= 60) // 1 PER MIN { lastSlowSecs = CurrentSecs; L3TimerProc(); if (needAIS) AISTimer(); if (needADSB) ADSBTimer(); if (APRSActive) Debugprintf("BPQ32 Heartbeat Buffers %d APRS Queues %d %d", QCOUNT, C_Q_COUNT(&APRSMONVECPTR->HOSTTRACEQ), C_Q_COUNT(&APPL_Q)); else Debugprintf("BPQ32 Heartbeat Buffers %d", QCOUNT); StatsTimer(); // Call EXT Port Slow Timer PORT = PORTTABLE; for (i = 0; i < NUMBEROFPORTS; i++) { if (PORT->PROTOCOL == 10) { PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; EXTSLOWTIMER(PORTVEC); } PORT = PORT->PORTPOINTER; } // Call Mode Map support routine sendFreqReport(); sendModeReport(); if (MQTT) MQTTTimer(); /* if (QCOUNT < 200) { if (DelayBuffers == 0) { FindLostBuffers(); DelayBuffers = 10; } else { DelayBuffers--; } } */ } // Check Autosave Nodes and MH timer if (CurrentSecs - lastSaveSecs >= 3600) // 1 per hour { lastSaveSecs = CurrentSecs; if (AUTOSAVE == 1) SaveNodes(); if (AUTOSAVEMH == 1) SaveMH(); } if (L4TIMERFLAG >= 10) // 1 PER SEC { L4TIMERFLAG -= 10; L3FastTimer(); L4TimerProc(); } // SEE IF ANY FRAMES TO TRACE Buffer = Q_REM(&TRACE_Q); while (Buffer) { // IF BUFFER HAS A LINK TABLE ENTRY ON END, RESET TIMEOUT LINK = Buffer->Linkptr; if (LINK) { if (LINK->L2TIMER) LINK->L2TIMER = LINK->L2TIME; Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER } Message = (struct _MESSAGE *)Buffer; Message->PORT |= 0x80; // Set TX Bit BPQTRACE(Message, FALSE); // Dont send TX'ed frames to APRS ReleaseBuffer(Buffer); Buffer = Q_REM(&TRACE_Q); } // CHECK FOR MESSAGES RECEIVED FROM COMMS LINKS PORT = PORTTABLE; for (i = 0; i < NUMBEROFPORTS; i++) { int Sent = 0; CURRENTPORT = PORT->PORTNUMBER; // PORT NUMBER CURRENTPORTPTR = PORT; Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); while (Buffer) { Message = (struct _MESSAGE *) Buffer; if (CURRENTPORT == 30) Sent = Sent; if (PORT->PROTOCOL == 10) { int Sessno = Message->PORT; PEXTPORTDATA PORTVEC = (PEXTPORTDATA)PORT; TRANSPORTENTRY * Session; TRANSPORTENTRY * Partner; if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF) { // KISSHF - May be L2 packet or Test Response if (Message->DEST[0] != 240) // Should only be ax.25 address field goto L2Packet; } // PACTOR Style Message InOctets[PORT->PORTNUMBER] += Message->LENGTH - (MSGHDDRLEN + 1); PORT->L2FRAMESFORUS++; Session = PORTVEC->ATTACHEDSESSIONS[Sessno]; if (Session == NULL) { // TNC not attached - discard ReleaseBuffer(Buffer); Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); continue; } Session->L4KILLTIMER = 0; // Reset Idle Timeout Partner = Session->L4CROSSLINK; if (Partner == NULL) { // No Crosslink - pass to command handler CommandHandler(Session, (PDATAMESSAGE)Buffer); break; } if (Partner->L4STATE < 5) { // MESSAGE RECEIVED BEFORE SESSION IS UP - CANCEL SESSION // AND PASS MESSAGE TO COMMAND HANDLER if (Partner->L4CIRCUITTYPE & L2LINK) // L2 SESSION? { // MUST CANCEL L2 SESSION LINK = Partner->L4TARGET.LINK; LINK->CIRCUITPOINTER = NULL; // CLEAR REVERSE LINK LINK->L2STATE = 4; // DISCONNECTING LINK->L2TIMER = 1; // USE TIMER TO KICK OFF DISC LINK->L2RETRIES = LINK->LINKPORT->PORTN2 - 2; //ONLY SEND DISC ONCE } CLEARSESSIONENTRY(Partner); Session->L4CROSSLINK = 0; // CLEAR CROSS LINK CommandHandler(Session, (struct DATAMESSAGE *)Buffer); break; } C_Q_ADD(&Partner->L4TX_Q, Buffer); PostDataAvailable(Partner); Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); continue; } L2Packet: // TIME STAMP IT time(&Message->Timestamp); Message->PORT = CURRENTPORT; if (MQTT && PORT->PROTOCOL == 0) MQTTKISSRX(Buffer); // Bridge if requested for (toPort = 1; toPort <= MaxBPQPortNo; toPort++) { if (BridgeMap[CURRENTPORT][toPort]) { MESSAGE * BBuffer = GetBuff(); struct PORTCONTROL * BPORT; if (BBuffer) { memcpy(BBuffer, Message, Message->LENGTH); BBuffer->PORT = toPort; BPORT = GetPortTableEntryFromPortNum(toPort); if (BPORT) { if (BPORT->SmartIDInterval && BPORT->SmartIDNeeded == 0) { // Using Smart ID, but none scheduled BPORT->SmartIDNeeded = time(NULL) + BPORT->SmartIDInterval; } PUT_ON_PORT_Q(BPORT, BBuffer); } else ReleaseBuffer(BBuffer); } } } L2Routine(PORT, Buffer); Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTRX_Q); continue; } // End of RX_Q Sent = 0; while (PORT->PORTTX_Q && Sent < 5) { int ret; void * PACTORSAVEQ; Buffer = PORT->PORTTX_Q; Message = (struct _MESSAGE *) Buffer; ret = PORT->PORTTXCHECKCODE(PORT, Message->PORT); // Busy but not connected means TNC has gone - clear queue if (ret == 1) { MESSAGE * Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); if (Buffer == 0) break; // WOT!! // Debugprintf("Busy but not connected - discard message %s", Buffer->L2DATA); ReleaseBuffer(Buffer); break; } ret = ret & 0xff; // Only check bottom byte if (ret == 0) // Not busy { MESSAGE * Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); if (Buffer == 0) break; // WOT!! if (PORT->PORTDISABLED) { ReleaseBuffer(Buffer); break; } PORT->L2FRAMESSENT++; OutOctets[PORT->PORTNUMBER] += Buffer->LENGTH - MSGHDDRLEN; PORT->PORTTXROUTINE((struct _EXTPORTDATA *)PORT, Buffer); Sent++; continue; } // If a Pactor Port, some channels could be busy whilst others are not. if (PORT->PROTOCOL != 10) break; // BUSY // Try passing any other messages on the queue to the node. PACTORSAVEQ = 0; PACTORLOOP: Buffer = PORT->PORTTX_Q; if (Buffer == NULL) goto ENDOFLIST; Message = (struct _MESSAGE *) Buffer; ret = PORT->PORTTXCHECKCODE(PORT, Message->PORT); ret = ret & 0xff; // Only check bottom byte if (ret) // Busy { // Save it Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); C_Q_ADD(&PACTORSAVEQ, Buffer); goto PACTORLOOP; } Buffer = (PMESSAGE)Q_REM((void *)&PORT->PORTTX_Q); if (PORT->PORTDISABLED) { ReleaseBuffer(Buffer); goto PACTORLOOP; } PORT->L2FRAMESSENT++; OutOctets[PORT->PORTNUMBER] += Message->LENGTH; PORT->PORTTXROUTINE((struct _EXTPORTDATA *)PORT, Buffer); Sent++; if (Sent < 5) goto PACTORLOOP; // SEE IF MORE ENDOFLIST: // Move the saved frames back onto Port Q PORT->PORTTX_Q = PACTORSAVEQ; break; } PORT->PORTRXROUTINE((struct _EXTPORTDATA *)PORT); // SEE IF MESSAGE RECEIVED PORT = PORT->PORTPOINTER; } /* ; ; CHECK FOR INCOMING MESSAGES ON LINK CONTROL TABLE - ; BY NOW ONLY 'I' FRAMES WILL BE PRESENT - ; LEVEL 2 PROTOCOL HANDLING IS DONE IN MESSAGE RECEIVE CODE ; AND LINK HANDLING INTERRUPT ROUTINES ; */ LINK = LINKS; i = MAXLINKS; while (i--) { if (LINK->LINKCALL[0]) { Buffer = Q_REM(&LINK->RX_Q); while (Buffer) { ProcessIframe(LINK, (PDATAMESSAGE)Buffer); Buffer =(PMESSAGE)Q_REM((void *)&LINK->RX_Q); } // CHECK FOR OUTGOING MSGS if (LINK->L2STATE >= 5) // CANT SEND TEXT TILL CONNECTED { // CMP VER1FLAG[EBX],1 // JE SHORT MAINL35 ; NEED TO RETRY WITH I FRAMES IF VER 1 // CMP L2RETRIES[EBX],0 // JNE SHORT MAINL40 ; CANT SEND TEXT IF RETRYING if ((LINK->L2FLAGS & RNRSET) == 0) SDETX(LINK); } } LINK++; } L4BG(); // DO LEVEL 4 PROCESSING L3BG(); TNCTimerProc(); } VOID DoListenMonitor(TRANSPORTENTRY * L4, MESSAGE * Msg) { uint64_t SaveMMASK = MMASK; BOOL SaveMTX = MTX; BOOL SaveMCOM = MCOM; BOOL SaveMUI = MUIONLY; PDATAMESSAGE Buffer; char MonBuffer[1024]; int len; UCHAR * monchars = (UCHAR *)Msg; if (CountFramesQueuedOnSession(L4) > 10) return; if (monchars[21] == 3 && monchars[22] == 0xcf && monchars[23] == 0xff) // Netrom Nodes return; IntSetTraceOptionsEx(L4->LISTEN, 1, 0, 0); len = IntDecodeFrame(Msg, MonBuffer, Msg->Timestamp, L4->LISTEN, FALSE, TRUE); IntSetTraceOptionsEx(SaveMMASK, SaveMTX, SaveMCOM, SaveMUI); if (len == 0) return; if (len > 256) len = 256; Buffer = GetBuff(); if (Buffer) { char * ptr = &Buffer->L2DATA[0]; Buffer->PID = 0xf0; memcpy(ptr, MonBuffer, len); Buffer->LENGTH = (USHORT)len + 4 + sizeof(void *); C_Q_ADD(&L4->L4TX_Q, Buffer); PostDataAvailable(L4); } } DllExport int APIENTRY DllBPQTRACE(MESSAGE * Msg, BOOL TOAPRS) { int ret; GetSemaphore(&Semaphore, 88); ret = BPQTRACE(Msg, TOAPRS); FreeSemaphore(&Semaphore); return ret; } int BPQTRACE(MESSAGE * Msg, BOOL TOAPRS) { // ATTACH A COPY OF FRAME TO ANY BPQ HOST PORTS WITH MONITORING ENABLED TRANSPORTENTRY * L4 = L4TABLE; MESSAGE * Buffer; int i = BPQHOSTSTREAMS + 2; // Include Telnet and AGW Stream if (TOAPRS) i++; // Include APRS Stream while(i) { i--; if (QCOUNT < 100) return FALSE; if (BPQHOSTVECTOR[i].HOSTAPPLFLAGS & 0x80) // Trace Enabled? { Buffer = GetBuff(); if (Buffer) { memcpy(&Buffer->PORT, &Msg->PORT, BUFFLEN - sizeof(void *)); // Dont copy chain word C_Q_ADD(&BPQHOSTVECTOR[i].HOSTTRACEQ, Buffer); #ifndef LINBPQ if (BPQHOSTVECTOR[i].HOSTHANDLE) PostMessage(BPQHOSTVECTOR[i].HOSTHANDLE, BPQMsg, BPQHOSTVECTOR[i].HOSTSTREAM, 1); #endif } } } // Also pass to any users LISTENING on this port i = MAXCIRCUITS; if (QCOUNT < 300) return FALSE; // Until I add by session flow control while (i--) { if (L4->LISTEN) if ((((uint64_t)1 << ((Msg->PORT & 0x7f) - 1)) & L4->LISTEN)) // if ((Msg->PORT & 0x7f) == L4->LISTEN) DoListenMonitor(L4, Msg); L4++; } return TRUE; } ; VOID INITIALISEPORTS() { char INITMSG[80]; struct PORTCONTROL * PORT = PORTTABLE; while (PORT) { sprintf(INITMSG, "Initialising Port %02d ", PORT->PORTNUMBER); WritetoConsoleLocal(INITMSG); PORT->PORTINITCODE(PORT); PORT = PORT->PORTPOINTER; } } VOID FindLostBuffers() { void ** Buff; int n, i; unsigned int rev; UINT CodeDump[16]; char codeText[65] = ""; unsigned char * codeByte = (unsigned char *) CodeDump; PBPQVECSTRUC HOSTSESS = BPQHOSTVECTOR; struct _TRANSPORTENTRY * L4; // Pointer to Session struct DEST_LIST * DEST = DESTS; struct ROUTE * Routes = NEIGHBOURS; int MaxRoutes = MAXNEIGHBOURS; int Queued; char Call[10]; n = MAXDESTS; Debugprintf("Looking for missing Buffers"); while (n--) { if (DEST->DEST_CALL[0] && DEST->DEST_Q) // Spare { Debugprintf("DEST Queue %s %d", DEST->DEST_ALIAS, C_Q_COUNT(&DEST->DEST_Q)); } DEST++; } n = 0; while (n < BPQHOSTSTREAMS + 4) { // Check Trace Q if (HOSTSESS->HOSTTRACEQ) { int Count = C_Q_COUNT(&HOSTSESS->HOSTTRACEQ); Debugprintf("Trace Buffers Stream %d Count %d", n, Count); L4 = HOSTSESS->HOSTSESSION; if (L4 && (L4->L4TX_Q || L4->L4RX_Q || L4->L4HOLD_Q || L4->L4RESEQ_Q)) Debugprintf("Stream %d %d %d %d %d", n, C_Q_COUNT(&L4->L4TX_Q), C_Q_COUNT(&L4->L4RX_Q), C_Q_COUNT(&L4->L4HOLD_Q), C_Q_COUNT(&L4->L4RESEQ_Q)); } n++; HOSTSESS++; } n = MAXCIRCUITS; L4 = L4TABLE; while (n--) { if (L4->L4USER[0] == 0) { L4++; continue; } if (L4->L4TX_Q || L4->L4RX_Q || L4->L4HOLD_Q || L4->L4RESEQ_Q) Debugprintf("L4 %d TX %d RX %d HOLD %d RESEQ %d", MAXCIRCUITS - n, C_Q_COUNT(&L4->L4TX_Q), C_Q_COUNT(&L4->L4RX_Q), C_Q_COUNT(&L4->L4HOLD_Q), C_Q_COUNT(&L4->L4RESEQ_Q)); L4++; } // Routes while (MaxRoutes--) { if (Routes->NEIGHBOUR_CALL[0] != 0) { Call[ConvFromAX25(Routes->NEIGHBOUR_CALL, Call)] = 0; if (Routes->NEIGHBOUR_LINK) { Queued = COUNT_AT_L2(Routes->NEIGHBOUR_LINK); // SEE HOW MANY QUEUED if (Queued) Debugprintf("Route %s %d", Call, Queued); } } Routes++; } // Build list of buffers, then mark off all on free Q Buff = BUFFERPOOL; n = 0; for (i = 0; i < NUMBEROFBUFFERS; i++) { Bufferlist[n++] = Buff; Buff += (BUFFALLOC / sizeof(void *)); } Buff = FREE_Q; while (Buff) { n = NUMBEROFBUFFERS; while (n--) { if (Bufferlist[n] == Buff) { Bufferlist[n] = 0; break; } } Buff = *Buff; } n = NUMBEROFBUFFERS; while (n--) { if (Bufferlist[n]) { char * fileptr = (char *)Bufferlist[n]; MESSAGE * Msg = (MESSAGE *)Bufferlist[n]; memcpy(CodeDump, Bufferlist[n], 64); for (i = 0; i < 64; i++) { if (codeByte[i] > 0x1f && codeByte[i] < 0x80) codeText[i] = codeByte[i]; else codeText[i] = '.'; } for (i = 0; i < 16; i++) { rev = (CodeDump[i] & 0xff) << 24; rev |= (CodeDump[i] & 0xff00) << 8; rev |= (CodeDump[i] & 0xff0000) >> 8; rev |= (CodeDump[i] & 0xff000000) >> 24; CodeDump[i] = rev; } Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ", Bufferlist[n], CodeDump[0], CodeDump[1], CodeDump[2], CodeDump[3], CodeDump[4], CodeDump[5], CodeDump[6], CodeDump[7]); Debugprintf(" %08x %08x %08x %08x %08x %08x %08x %08x %d", CodeDump[8], CodeDump[9], CodeDump[10], CodeDump[11], CodeDump[12], CodeDump[13], CodeDump[14], CodeDump[15], Msg->Process); Debugprintf(" %s %s", &fileptr[400], codeText); } } // rebuild list for buffer check Buff = BUFFERPOOL; n = 0; for (i = 0; i < NUMBEROFBUFFERS; i++) { Bufferlist[n++] = Buff; Buff += (BUFFALLOC / sizeof(void *)); } } void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode) { UCHAR FN[MAX_PATH]; FILE * LogHandle; time_t T; struct tm * tm; char LogMsg[256]; int MsgLen; T = time(NULL); tm = gmtime(&T); sprintf(FN,"%s/logs/ConnectLog_%02d%02d%02d.log", LogDirectory, tm->tm_year - 100, tm->tm_mon + 1, tm->tm_mday); LogHandle = fopen(FN, "ab"); if (LogHandle == NULL) return; MsgLen = sprintf(LogMsg, "%02d:%02d:%02d Call from %s to %s Mode %s\r\n", tm->tm_hour, tm->tm_min, tm->tm_sec, fromCall, toCall, Mode); fwrite(LogMsg , 1, MsgLen, LogHandle); fclose(LogHandle); }