From 9aad97786d945165530dcac2216c5b75e4632f82 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 11 Nov 2025 21:42:35 +0000 Subject: [PATCH 1/2] 6.0.25.9 --- APRSCode.c | 30 +- ARDOP.c | 170 +++++----- BBSUtilities.c | 8 +- BPQINP3.c | 3 + Bpq32.c | 115 +++++++ Cmd.c | 51 +++ CommonCode.c | 22 ++ DRATS.c | 21 +- Events.c | 862 +++++++++++++++++++++++++++++++++++++++++++++++ KernelScript1.rc | 13 + L2Code.c | 25 ++ L3Code.c | 13 +- L4Code.c | 14 +- LinBPQ.c | 9 + MailTCP.c | 23 +- NETROMTCP.c | 589 ++++++++++++++++++++++++++++++++ TelnetV6.c | 43 +-- UZ7HODrv.c | 116 +++---- VARA.c | 3 +- Versions.h | 8 + WINMOR.c | 2 + WebMail.c | 4 +- asmstrucs.h | 19 ++ bpqaxip.c | 4 +- cMain.c | 27 +- config.c | 7 + lzhuf32.c | 152 ++++----- pngwutil.c | 5 +- 28 files changed, 2064 insertions(+), 294 deletions(-) diff --git a/APRSCode.c b/APRSCode.c index 2ee3b5f..6e65001 100644 --- a/APRSCode.c +++ b/APRSCode.c @@ -7693,7 +7693,7 @@ VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE) while (ptr) { char ToLopped[11] = ""; - + if (ptr->Acked) strcpy(Retries, "A"); else if (ptr->Retries == 0) @@ -7701,26 +7701,26 @@ VOID APRSProcessHTTPMessage(SOCKET sock, char * MsgPtr, BOOL LOCAL, BOOL COOKIE) else sprintf(Retries, "%d", ptr->Retries); - memcpy(ToLopped, ptr->ToCall, 10); - strlop(ToLopped, ' '); + memcpy(ToLopped, ptr->ToCall, 10); + strlop(ToLopped, ' '); - OutputLen += sprintf(&OutBuffer[OutputLen], WebTXLine, - ptr->ToCall, ptr->Seq, ptr->Time, Retries, ptr->Text); - ptr = ptr->Next; + OutputLen += sprintf(&OutBuffer[OutputLen], WebTXLine, + ptr->ToCall, ptr->Seq, ptr->Time, Retries, ptr->Text); + ptr = ptr->Next; - if (OutputLen > 99000) - break; + if (OutputLen > 99000) + break; - } + } - OutputLen += sprintf(&OutBuffer[OutputLen], "%s", WebTrailer); + OutputLen += sprintf(&OutBuffer[OutputLen], "%s", WebTrailer); - HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); - sendandcheck(sock, Header, HeaderLen); - sendandcheck(sock, OutBuffer, OutputLen); + HeaderLen = sprintf(Header, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n", OutputLen); + sendandcheck(sock, Header, HeaderLen); + sendandcheck(sock, OutBuffer, OutputLen); + + return; - return; - } diff --git a/ARDOP.c b/ARDOP.c index 5832c44..ef92fad 100644 --- a/ARDOP.c +++ b/ARDOP.c @@ -466,107 +466,107 @@ static int ProcessLine(char * buf, int Port) else return FALSE; // Must start with ADDR - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; + TNC->InitScript = malloc(1000); + TNC->InitScript[0] = 0; - ptr = strtok(NULL, " \t\n\r"); + ptr = strtok(NULL, " \t\n\r"); - if (ptr) + if (ptr) + { + if (_stricmp(ptr, "PTT") == 0) { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); + ptr = strtok(NULL, " \t\n\r"); - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - } - - if (ptr) - { - if (_memicmp(ptr, "PATH", 4) == 0) - { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); - } - } - - TNC->MaxConReq = 10; // Default - TNC->OldMode = FALSE; // Default - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); if (ptr) { - *ptr++ = 13; - *ptr = 0; + DecodePTTString(TNC, ptr); + ptr = strtok(NULL, " \t\n\r"); } - - if ((_memicmp(buf, "CAPTURE", 7) == 0) || (_memicmp(buf, "PLAYBACK", 8) == 0)) - {} // Ignore - else -/* + } + } + + if (ptr) + { + if (_memicmp(ptr, "PATH", 4) == 0) + { + p_cmd = strtok(NULL, "\n\r"); + if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); + } + } + + TNC->MaxConReq = 10; // Default + TNC->OldMode = FALSE; // Default + + // Read Initialisation lines + + while(TRUE) + { + if (GetLine(buf) == 0) + return TRUE; + + strcpy(errbuf, buf); + + if (memcmp(buf, "****", 4) == 0) + return TRUE; + + ptr = strchr(buf, ';'); + if (ptr) + { + *ptr++ = 13; + *ptr = 0; + } + + if ((_memicmp(buf, "CAPTURE", 7) == 0) || (_memicmp(buf, "PLAYBACK", 8) == 0)) + {} // Ignore + else + /* if (_memicmp(buf, "PATH", 4) == 0) { - char * Context; - p_cmd = strtok_s(&buf[5], "\n\r", &Context); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); + char * Context; + p_cmd = strtok_s(&buf[5], "\n\r", &Context); + if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); } else -*/ + */ if (_memicmp(buf, "PACKETCHANNELS", 14) == 0) // Packet Channels TNC->PacketChannels = atoi(&buf[14]); else - if (_memicmp(buf, "MAXCONREQ", 9) == 0) // Hold Time for Busy Detect - TNC->MaxConReq = atoi(&buf[9]); + if (_memicmp(buf, "MAXCONREQ", 9) == 0) // Hold Time for Busy Detect + TNC->MaxConReq = atoi(&buf[9]); - else - if (_memicmp(buf, "STARTINROBUST", 13) == 0) - TNC->StartInRobust = TRUE; - - else - if (_memicmp(buf, "ROBUST", 6) == 0) - { - if (_memicmp(&buf[7], "TRUE", 4) == 0) - TNC->Robust = TRUE; - - strcat (TNC->InitScript, buf); - } - else - if (_memicmp(buf, "LOGDIR ", 7) == 0) - TNC->LogPath = _strdup(&buf[7]); - else - if (_memicmp(buf, "ENABLEPACKET", 12) == 0) - { - if (TNC->PacketChannels == 0) - TNC->PacketChannels = 5; - // AddVirtualKISSPort(TNC, Port, buf); - } + else + if (_memicmp(buf, "STARTINROBUST", 13) == 0) + TNC->StartInRobust = TRUE; -// else if (_memicmp(buf, "PAC ", 4) == 0 && _memicmp(buf, "PAC MODE", 8) != 0) -// { - // PAC MODE goes to TNC, others are parsed locally -// -// ConfigVirtualKISSPort(TNC, buf); -// } - else if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - } + else + if (_memicmp(buf, "ROBUST", 6) == 0) + { + if (_memicmp(&buf[7], "TRUE", 4) == 0) + TNC->Robust = TRUE; + + strcat (TNC->InitScript, buf); + } + else + if (_memicmp(buf, "LOGDIR ", 7) == 0) + TNC->LogPath = _strdup(&buf[7]); + else + if (_memicmp(buf, "ENABLEPACKET", 12) == 0) + { + if (TNC->PacketChannels == 0) + TNC->PacketChannels = 5; + // AddVirtualKISSPort(TNC, Port, buf); + } + + // else if (_memicmp(buf, "PAC ", 4) == 0 && _memicmp(buf, "PAC MODE", 8) != 0) + // { + // PAC MODE goes to TNC, others are parsed locally + // + // ConfigVirtualKISSPort(TNC, buf); + // } + else if (standardParams(TNC, buf) == FALSE) + strcat(TNC->InitScript, buf); + } return (TRUE); @@ -1041,8 +1041,10 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) { TNC->Busy--; if (TNC->Busy == 0) + { MySetWindowText(TNC->xIDC_CHANSTATE, "Clear"); strcpy(TNC->WEB_CHANSTATE, "Clear"); + } } } diff --git a/BBSUtilities.c b/BBSUtilities.c index e803500..e6f7ade 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -3701,10 +3701,10 @@ void DoKillCommand(CIRCUIT * conn, struct UserInfo * user, char * Cmd, char * Ar if (conn->sysop) { if (Arg1) - if (KillMessagesFrom(conn, user, Arg1) == 0); + if (KillMessagesFrom(conn, user, Arg1) == 0) BBSputs(conn, "No Messages found\r"); - return; + return; } } @@ -6556,7 +6556,7 @@ nextline: { char APRS[128]; char Call[16]; - int SSID = user->flags >> 28; + int SSID = (user->flags >> 28) & 15; // on some platforms this is treated as signed ?? if (SSID) sprintf(Call, "%s-%d", Msg->to, SSID); @@ -13395,7 +13395,7 @@ int DeleteRedundantMessages() { while(n--) { - if (stat(namelist[n]->d_name, &STAT) == 0); + if (stat(namelist[n]->d_name, &STAT) == 0) { Msgno = atoi(&namelist[n]->d_name[2]); diff --git a/BPQINP3.c b/BPQINP3.c index 872496b..de4bf76 100644 --- a/BPQINP3.c +++ b/BPQINP3.c @@ -747,6 +747,9 @@ VOID SortRoutes(struct DEST_LIST * Dest) { char Call1[10], Call2[10], Call3[10]; + // force route re-evaluation + + Dest->DEST_ROUTE = 0; // May now be out of order diff --git a/Bpq32.c b/Bpq32.c index 41d4e64..3c5801f 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1406,6 +1406,11 @@ void initAIS(); void initADSB(); int CloseAllSessions(); int CloseAllLinks(); +<<<<<<< Updated upstream +||||||| Stash base +======= +void NETROMTCPResolve(); +>>>>>>> Stashed changes extern BOOL ADIFLogEnabled; @@ -1413,6 +1418,8 @@ int CloseOnError = 0; char UIClassName[]="UIMAINWINDOW"; // the main window class name +char ClosingClassName[]="CLOSING"; // the main window class name + HWND UIhWnd; extern char AUTOSAVE; @@ -2216,6 +2223,8 @@ VOID TimerProcX() Start(); + NETROMTCPResolve(); + INITIALISEPORTS(); // Restart Ports SetApplPorts(); @@ -2398,7 +2407,12 @@ VOID TimerProcX() if (CloseAllSessions() == 0) { if (CloseAllLinks() == 0) // No sessions closed so close links now +<<<<<<< Updated upstream CloseAllTimer = 0; // No Links so close now +||||||| Stash base +======= + CloseAllTimer = 1; // No Links so close now +>>>>>>> Stashed changes else CloseAllTimer = 39; // ~4 secs for links to close } @@ -2632,6 +2646,7 @@ Check_Timer() WSAStartup(MAKEWORD(2, 0), &WsaData); + // Load Psapi.dll if possible ExtDriver = LoadLibrary("Psapi.dll"); @@ -2646,6 +2661,8 @@ Check_Timer() Start(); + NETROMTCPResolve(); + INITIALISEPORTS(); OpenReportingSockets(); @@ -2969,6 +2986,8 @@ BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReser } else { + NETROMTCPResolve(); + SetApplPorts(); GetUIConfig(); @@ -5967,14 +5986,110 @@ DllExport VOID APIENTRY CreateNewTrayIcon() void hookNodeClosing(char * Reason); +<<<<<<< Updated upstream +||||||| Stash base +======= +BOOL CALLBACK ClosaAllProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + + switch (message) + { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_CTLCOLORDLG: + return (LONG)bgBrush; + + case WM_CTLCOLORSTATIC: + { + HDC hdcStatic = (HDC)wParam; + SetTextColor(hdcStatic, RGB(0, 0, 0)); + SetBkMode(hdcStatic, TRANSPARENT); + + return (LONG)bgBrush; + } + + case WM_COMMAND: + + return 0; + + case WM_SYSCOMMAND: + + wmId = LOWORD(wParam); // Remember, these are... + wmEvent = HIWORD(wParam); // ...different for Win32! + + switch (wmId) + { + case SC_RESTORE: + + return (DefWindowProc(hWnd, message, wParam, lParam)); + + case SC_MINIMIZE: + + if (MinimizetoTray) + return ShowWindow(hWnd, SW_HIDE); + else + return (DefWindowProc(hWnd, message, wParam, lParam)); + + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + + case WM_CLOSE: + return(DestroyWindow(hWnd)); + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + + } + + return (0); +} + + +HWND hwndClosing = NULL; // Window handle of dialog box + +>>>>>>> Stashed changes DllExport VOID APIENTRY CloseAllPrograms() { +<<<<<<< Updated upstream +||||||| Stash base +// HANDLE hProc; +======= + WNDCLASS wc; +>>>>>>> Stashed changes CLOSING = TRUE; // Tell BG to shut when all links are gone or after 5 secs CloseAllTimer = 50; +<<<<<<< Updated upstream +||||||| Stash base + Closing = TRUE; +======= + + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = ClosaAllProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = DLGWINDOWEXTRA; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON) ); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = bgBrush; + + wc.lpszMenuName = NULL; + wc.lpszClassName = ClosingClassName; + + RegisterClass(&wc); + + hwndClosing = CreateDialog(hInstance, ClosingClassName, NULL, (DLGPROC)ClosaAllProc); + ShowWindow(hwndClosing, SW_SHOW); +>>>>>>> Stashed changes } VOID RealCloseAllPrograms() diff --git a/Cmd.c b/Cmd.c index 605ccd1..7eb6061 100644 --- a/Cmd.c +++ b/Cmd.c @@ -130,6 +130,8 @@ int NOBUFFCOUNT = 0; int BUFFERWAITS = 0; int MAXDESTS = 0; int NUMBEROFNODES = 0; +int L2CONNECTSOUT = 0; +int L2CONNECTSIN = 0; int L4CONNECTSOUT = 0; int L4CONNECTSIN = 0; int L4FRAMESTX = 0; @@ -903,8 +905,18 @@ int checkifService(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, s BOOL Stay = FALSE; char * ptr, *Context; int i; +<<<<<<< Updated upstream ptr = strtok_s(CmdTail, " ", &Context); +||||||| Stash base +======= + char TailCopy[256]; + + strcpy(TailCopy, CmdTail); + + + ptr = strtok_s(TailCopy, " ", &Context); +>>>>>>> Stashed changes // see if any param. if longer than two chars treat as remote node @@ -2665,7 +2677,14 @@ NoPort: // SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED +<<<<<<< Updated upstream if (axcalls[7] == 0 && axcalls[9] ) +||||||| Stash base + if (axcalls[7] == 0) +======= +// if (axcalls[7] == 0 && axcalls[9]) + if (axcalls[7] == 0) +>>>>>>> Stashed changes { // If this connect is as a result of a command alias, don't check appls or we will loop @@ -2716,6 +2735,7 @@ NoPort: } } +<<<<<<< Updated upstream // 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) @@ -2729,11 +2749,42 @@ NoPort: if (cmdCopy[i] != ' ') goto Downlink; else +||||||| Stash base + 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 + + if (cmdCopy[0] != ' ') +>>>>>>> Stashed changes { +<<<<<<< Updated upstream if (i > 0) // Some digits { haveService = 1; Service = atoi(cmdCopy); +||||||| Stash base + // SEE IF CALL TO ANOTHER NODE +======= + i = 0; + + while (cmdCopy[i] >= '0' && cmdCopy[i]<= '9') + i++; + + if (cmdCopy[i] != ' ') + goto Downlink; + else + { + if (i > 0) // Some digits + { + haveService = 1; + Service = atoi(cmdCopy); + } +>>>>>>> Stashed changes } } diff --git a/CommonCode.c b/CommonCode.c index cffbdb7..09690ae 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -75,6 +75,7 @@ void printStack(void); char * FormatMH(PMHSTRUC MH, char Format); void WriteConnectLog(char * fromCall, char * toCall, UCHAR * Mode); void SendDataToPktMap(); +void NETROMTCPResolve(); extern BOOL LogAllConnects; extern BOOL M0LTEMap; @@ -3738,16 +3739,37 @@ VOID ResolveUpdateThread(void * Unused) nodeStartedSent = 1; LastNodeStatus = time(NULL); } +<<<<<<< Updated upstream } if (HostEnt1 && HostEnt2) { Sleep(1000 * 60 * 30); continue; +||||||| Stash base + Sleep(1000 * 60 * 30); + continue; +======= +>>>>>>> Stashed changes } +<<<<<<< Updated upstream Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); Sleep(1000 * 60 * 5); +||||||| Stash base + + Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); + Sleep(1000 * 60 * 5); +======= + + NETROMTCPResolve(); + + if (HostEnt1 && HostEnt2) + { + Sleep(1000 * 60 * 15); + continue; + } +>>>>>>> Stashed changes } } diff --git a/DRATS.c b/DRATS.c index c7b6b83..7fd85cf 100644 --- a/DRATS.c +++ b/DRATS.c @@ -568,18 +568,19 @@ void DRATSConnectionLost(struct ConnectionInfo * sockptr) int doinflate(unsigned char * source, unsigned char * dest, int Len, int destlen, int * outLen) { - int ret; - z_stream strm; + int ret; + z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; - ret = inflateInit(&strm); - if (ret != Z_OK) - return ret; + ret = inflateInit(&strm); + + if (ret != Z_OK) + return ret; strm.avail_in = Len; strm.next_in = source; diff --git a/Events.c b/Events.c index 2030929..1a64b3b 100644 --- a/Events.c +++ b/Events.c @@ -57,6 +57,7 @@ extern char LOC[7]; extern char VersionString[50]; extern double LatFromLOC; extern double LonFromLOC; +<<<<<<< Updated upstream void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Direction); int ConvFromAX25(unsigned char * incall, unsigned char * outcall); @@ -66,6 +67,21 @@ int decodeNETROMUIMsg(unsigned char * Msg, int iLen, char * Buffer, int BufferLe 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); +||||||| Stash base +======= +extern int NUMBEROFNODES, MAXDESTS, L4CONNECTSOUT, L4CONNECTSIN, L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES; +extern int L2CONNECTSOUT, L2CONNECTSIN; + +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); +char * byte_base64_encode(char *str, int len); +>>>>>>> Stashed changes // Runs use specified routine on certain event @@ -141,13 +157,31 @@ DllExport void APIENTRY RunEventProgram(char * Program, char * Param) void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK) { // Incoming SABM accepted +<<<<<<< Updated upstream char UDPMsg[1024]; int udplen; +||||||| Stash base + // Incoming SABM +======= +>>>>>>> Stashed changes +<<<<<<< Updated upstream LINK->ConnectTime = time(NULL); LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; +||||||| Stash base + LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = 0; +======= + char UDPMsg[1024]; + int udplen; +>>>>>>> Stashed changes + L2CONNECTSIN++; + + LINK->lastStatusSentTime = LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; + LINK->LastStatusbytesTXed = LINK->LastStatusbytesRXed = 0; strcpy(LINK->callingCall, remotecall); strcpy(LINK->receivingCall, ourcall); strcpy(LINK->Direction, "In"); @@ -217,9 +251,19 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK) void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK) { +<<<<<<< Updated upstream LINK->ConnectTime = time(NULL); LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; +||||||| Stash base + LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = 0; + +======= + LINK->lastStatusSentTime = LINK->ConnectTime = time(NULL); + LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; + LINK->LastStatusbytesTXed = LINK->LastStatusbytesRXed = 0; +>>>>>>> Stashed changes strcpy(LINK->callingCall, ourcall); strcpy(LINK->receivingCall, remotecall); strcpy(LINK->Direction, "Out"); @@ -232,6 +276,7 @@ void hookL2SessionConnected(struct _LINKTABLE * LINK) char UDPMsg[1024]; int udplen; +<<<<<<< Updated upstream if (NodeAPISocket) { LINK->lastStatusSentTime = time(NULL); @@ -297,6 +342,96 @@ void hookL2SessionStatus(struct _LINKTABLE * LINK) LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent); // Debugprintf(UDPMsg); +||||||| Stash base +======= + L2CONNECTSOUT++; + + if (NodeAPISocket) + { + 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; + time_t Now = time(NULL); + + 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\"," + " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, + LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason, + (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued); + 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\"," + " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, + LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason, + (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued); + + + 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; + time_t Now = time(NULL); + int bpsTx, bpsRx, interval; + + if (NodeAPISocket) + { + interval = Now - (int)LINK->lastStatusSentTime; + bpsTx = (LINK->bytesTXed - LINK->LastStatusbytesTXed) / interval; + bpsRx = (LINK->bytesRXed - LINK->LastStatusbytesRXed) / interval; + + LINK->lastStatusSentTime = Now; + LINK->LastStatusbytesTXed = LINK->bytesTXed; + LINK->LastStatusbytesRXed = LINK->bytesRXed; + + 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," + "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, + LINK->bytesTXed, LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, 0, LINK->framesResent, + (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT); + 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," + "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d}", + NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, + LINK->bytesTXed, LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, 0, LINK->framesResent, + (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT); + + LINK->intervalMaxQueued = 0; + + Debugprintf(UDPMsg); +>>>>>>> Stashed changes sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); } @@ -412,6 +547,7 @@ void hookNodeClosing(char * Reason) if (NodeAPISocket) { +<<<<<<< Updated upstream udplen = sprintf(UDPMsg, "{\"@type\": \"NodeDownEvent\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"reason\": \"%s\"}", NODECALLLOPPED, MYALIASLOPPED, Reason); @@ -1074,6 +1210,732 @@ int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen) (L3->L4TXNO << 8) | L3->L4RXNO, callList); Debugprintf(Buffer); +||||||| Stash base +======= + udplen = sprintf(UDPMsg, "{\"@type\": \"NodeDownEvent\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"reason\": \"%s\", \"uptimeSecs\": %d," + "\"linksIn\": %d, \"linksOut\": %d, \"cctsIn\": %d, \"cctsOut\": %d, \"l3Relayed\": %d}", + NODECALLLOPPED, MYALIASLOPPED, Reason, time(NULL) - TimeLoaded, L2CONNECTSIN, L2CONNECTSOUT, L4CONNECTSIN, L4CONNECTSOUT, L3FRAMES); + +// 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," + "\"linksIn\": %d, \"linksOut\": %d, \"cctsIn\": %d, \"cctsOut\": %d, \"l3Relayed\": %d}", + NODECALLLOPPED, MYALIASLOPPED, LOC, LatFromLOC, LonFromLOC, Software, VersionString, time(NULL) - TimeLoaded, + L2CONNECTSIN, L2CONNECTSOUT, L4CONNECTSIN, L4CONNECTSOUT, L3FRAMES); + +// 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 dumpDuffPacket(char * call, char * Buffer, int Len) +{ + // log to syslog in base64 + + char * Base64; + + Base64 = byte_base64_encode(Buffer, Len); + + Debugprintf("Trace Error %s %s", call, Base64); + free(Base64); +} + +int checkCall(char * call, unsigned char * Buffer, int Len) +{ + char c; + int i; + + // Validate source and dest calls - if duff, dump packet + + for (i = 0; i < strlen(call); i++) + { + c = call[i]; + + if (isalnum(c) || c == '-' || c == '@') + continue; + + dumpDuffPacket(call, Buffer, Len); + return 0; + } + + return 1; +} + + + +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; + + // Validate source and dest calls - if duff, dump packet + + if (!checkCall(destcall,(char *) Message, Message->LENGTH)) + return; + + if (!checkCall(srcecall, (char *) Message, Message->LENGTH)) + return; + + // 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\", \"dirn\": \"%s\", \"reportFrom\": \"%s\", \"port\": \"%d\", \"srce\": \"%s\", \"dest\": \"%s\", \"ctrl\": %d," + "\"l2Type\": \"%s\", \"modulo\": 8, \"cr\": \"%s\"", + Dirn, 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 (!checkCall(destcall, Msg, iLen)) + return 0; + + if (!checkCall(srcecall, Msg, iLen)) + return 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 (!checkCall(srcUser, Msg, iLen)) + return 0; + + + if (!checkCall(srcNode, Msg, iLen)) + return 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 NAK\", \"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); +>>>>>>> Stashed changes return Len; } diff --git a/KernelScript1.rc b/KernelScript1.rc index 4eef3b5..b230ace 100644 --- a/KernelScript1.rc +++ b/KernelScript1.rc @@ -50,6 +50,19 @@ BEGIN LTEXT "Enable IGate",IDC_STATIC,5,2,49,10 END +CLOSING DIALOG DISCARDABLE 300, 300, 200, 50 +STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | + WS_THICKFRAME +CAPTION "BPQ32 Close All" +CLASS "CLOSING" +FONT 8, "Fixedsys" +BEGIN + LTEXT "Closing Links - Please wait....",IDC_BACKGROUND,22,20,337,273 + +END + + + CONFIG DIALOGEX 249, 200, 160, 118 STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION EXSTYLE WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE diff --git a/L2Code.c b/L2Code.c index 8171d49..44015e1 100644 --- a/L2Code.c +++ b/L2Code.c @@ -2346,6 +2346,9 @@ VOID SFRAME(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, UCHAR CTL, UCHA LINK->L2TIMER = ONEMINUTE; // (RE)SET TIMER + + LINK->framesResent++; + PORT = LINK->LINKPORT; if (PORT) @@ -2452,6 +2455,20 @@ treatasRR: LINK->L2FLAGS &= ~POLLSENT; // CLEAR I(P) or RR(P) SET + // ?? is this the place to do RTT? + + if (LINK->lastPSent) + { + int RTT = GetTickCount() - LINK->lastPSent; + + if (LINK->RTT) + LINK->RTT = ((LINK->RTT * 90) / 100) + RTT /10; // Smooth - 90% of old + 10% of new + else + LINK->RTT = RTT; + + LINK->lastPSent = 0; + } + if ((CTL & 0xf) == RNR) { // Dont Clear timer on receipt of RNR(F), spec says should poll for clearing of busy, @@ -2927,6 +2944,8 @@ VOID RESETNS(struct _LINKTABLE * LINK, UCHAR NS) { int Resent = (LINK->LINKNS - NS) & 7; // FRAMES TO RESEND + LINK->framesResent += Resent; + LINK->LINKNS = NS; // RESET N(S) if (LINK->LINKTYPE == 3) // mode-Node @@ -3150,6 +3169,11 @@ VOID SDETX(struct _LINKTABLE * LINK) LINK->LASTFRAMESENT = time(NULL); LINK->LASTSENTQCOUNT = COUNT_AT_L2(LINK); + if (LINK->LASTSENTQCOUNT > LINK->maxQueued) + LINK->maxQueued = LINK->LASTSENTQCOUNT; + + if (LINK->LASTSENTQCOUNT > LINK->intervalMaxQueued) + LINK->intervalMaxQueued = LINK->LASTSENTQCOUNT; if (LINK->AllowCompress && Msg->LENGTH > 20 && LINK->TX_Q && Msg->PID == 240) // if short and no more not worth trying compression { @@ -3352,6 +3376,7 @@ VOID SDETX(struct _LINKTABLE * LINK) // FLAG BUFFER TO CAUSE TIMER TO BE RESET AFTER SEND (or ACK if ACKMODE) Buffer->Linkptr = LINK; + LINK->lastPSent = GetTickCount(); } } diff --git a/L3Code.c b/L3Code.c index c25df5b..0aafe67 100644 --- a/L3Code.c +++ b/L3Code.c @@ -236,7 +236,7 @@ BOOL ACTIVATE_DEST(struct DEST_LIST * DEST) return L2SETUPCROSSLINK(ROUTE); } - // We umst be waiting for link to come up + // We must be waiting for link to come up return TRUE; @@ -627,9 +627,6 @@ VOID PROCROUTES(struct DEST_LIST * DEST, struct ROUTE * ROUTE, int Qual) if (Index == 0) { // THIS IS A REFRESH OF BEST - IF THIS ISNT ACTIVE ROUTE, MAKE IT ACTIVE - - if (DEST->DEST_ROUTE > 1) // LEAVE IT IF NOT SELECTED OR ALREADY USING BEST - DEST->DEST_ROUTE = 1; } goto UpdatateThisEntry; @@ -728,6 +725,8 @@ SORTROUTES: goto SORTROUTES; // 1 AND 2 MAY NOW BE WRONG! } + + DEST->DEST_ROUTE = 0; // OForce re-evaluation. } int COUNTNODES(struct ROUTE * ROUTE) @@ -1042,7 +1041,8 @@ VOID L3TimerProc() LINK = LINKS; i = MAXLINKS; - while (i--); + + while (i--) { if (LINK->LINKTYPE == 3) // Only if Internode { @@ -1310,6 +1310,9 @@ VOID REMOVENODE(dest_list * DEST) while (DEST->DEST_Q) ReleaseBuffer(Q_REM(&DEST->DEST_Q)); + if (DEST->DEST_STATE & 0x80) // LOCKED DESTINATION + return; + // MAY NEED TO CHECK FOR L4 CIRCUITS USING DEST, BUT PROBABLY NOT, // AS THEY SHOULD HAVE TIMED OUT LONG AGO diff --git a/L4Code.c b/L4Code.c index ecfd5f0..4bb6e18 100644 --- a/L4Code.c +++ b/L4Code.c @@ -1601,7 +1601,13 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl int Index; char APPLCMD[13] = ""; +<<<<<<< Updated upstream memcpy(APPLCMD, APPL->APPLCMD, 13); +||||||| Stash base +======= + if (APPL) + memcpy(APPLCMD, APPL->APPLCMD, 13); +>>>>>>> Stashed changes memcpy(BPQPARAMS, &L4T1, 2); // SET DEFAULT T1 IN CASE NOT FROM ANOTHER BPQ NODE @@ -1674,6 +1680,12 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl { // At the moment I only handle connects to appls. May support other node commands later. +<<<<<<< Updated upstream +||||||| Stash base +======= + memcpy(APPLCMD, CMD->String, 13); + +>>>>>>> Stashed changes if (n < APPL1 + NumberofAppls) goto doAPPLConnect; } @@ -2028,7 +2040,7 @@ TryAgain: while (n--) { - if (DEST->DEST_COUNT == 0 && DEST->DEST_RTT == 0) // Not used and not INP3 + if (DEST->DEST_COUNT == 0 && DEST->DEST_RTT == 0 && (DEST->DEST_STATE & 0x80) == 0) // Not used and not INP3 and not Appl { if (DEST->NRROUTE[0].ROUT_QUALITY < WorstQual) { diff --git a/LinBPQ.c b/LinBPQ.c index 1c16ef4..0000e1c 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -85,6 +85,11 @@ VOID GetPGConfig(); void SendBBSDataToPktMap(); void CloseAllLinks(); void hookNodeClosing(char * Reason); +<<<<<<< Updated upstream +||||||| Stash base +======= +void NETROMTCPResolve(); +>>>>>>> Stashed changes extern uint64_t INP3timeLoadedMS; @@ -1015,6 +1020,8 @@ int main(int argc, char * argv[]) return (0); } + NETROMTCPResolve(); + for (i=0;PWTEXT[i] > 0x20;i++); //Scan for cr or null PWLen=i; @@ -1546,6 +1553,8 @@ int main(int argc, char * argv[]) Consoleprintf(VerCopyright); Start(); + + NETROMTCPResolve(); INITIALISEPORTS(); diff --git a/MailTCP.c b/MailTCP.c index 289fb62..37c7cf9 100644 --- a/MailTCP.c +++ b/MailTCP.c @@ -2092,20 +2092,19 @@ int CreateSMTPMessage(SocketConn * sockptr, int i, char * MsgTitle, time_t Date, struct tm * tm; tm = gmtime(&Date); - + sprintf(DateString, "%04d/%02d/%02d %02d:%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); if (strcmp(Msg->to, "RMS") == 0) // Address is in via - strcpy(B2To, Msg->via); - else - if (Msg->via[0]) - sprintf(B2To, "%s@%s", Msg->to, Msg->via); + strcpy(B2To, Msg->via); else - strcpy(B2To, Msg->to); + if (Msg->via[0]) + sprintf(B2To, "%s@%s", Msg->to, Msg->via); + else + strcpy(B2To, Msg->to); - Msg->B2Flags = B2Msg | Attachments; if (Msg->type == 'P') @@ -3934,12 +3933,12 @@ int CreatePOP3Message(char * From, char * To, char * MsgTitle, time_t Date, char if (strcmp(Msg->to, "RMS") == 0) // Address is in via - strcpy(B2To, Msg->via); - else - if (Msg->via[0]) - sprintf(B2To, "%s@%s", Msg->to, Msg->via); + strcpy(B2To, Msg->via); else - strcpy(B2To, Msg->to); + if (Msg->via[0]) + sprintf(B2To, "%s@%s", Msg->to, Msg->via); + else + strcpy(B2To, Msg->to); Msg->B2Flags = B2Msg | Attachments; diff --git a/NETROMTCP.c b/NETROMTCP.c index 79f186b..2041937 100644 --- a/NETROMTCP.c +++ b/NETROMTCP.c @@ -1,3 +1,4 @@ +<<<<<<< Updated upstream /* Copyright 2001-2022 John Wiseman G8BPQ @@ -549,3 +550,591 @@ void NETROMConnectionLost(struct ConnectionInfo * sockptr) memset(sockptr, 0, sizeof(struct ConnectionInfo)); } +||||||| Stash base +======= +/* +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 +//#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); + +} + +void NETROMTCPResolve() +{ + struct ROUTE * Route = NEIGHBOURS; + int n = MAXNEIGHBOURS; + struct addrinfo hints, *res = 0; + char PortString[20]; + int err; + + while (n--) + { + if (Route->TCPAddress) + { + // try to resolve host + + sprintf(PortString, "%d", Route->TCPPort); + + 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); + + err = WSAGetLastError(); + + if (res) + { + Route->TCPAddress->ai_family = res->ai_family; + Route->TCPAddress->ai_socktype = res->ai_socktype; + Route->TCPAddress->ai_protocol = res->ai_protocol; + Route->TCPAddress->ai_addrlen = res->ai_addrlen; + memcpy(Route->TCPAddress->ai_addr, res->ai_addr, sizeof(struct sockaddr)); + freeaddrinfo(res); + } + } + + Route++; + } +} + +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 * res = Route->TCPAddress; + int Port = Route->TCPPort; + + sprintf(PortString, "%d", Port); + + // get host info, make socket, and connect it + + if (res->ai_family == 0) + { +// err = WSAGetLastError(); +// Debugprintf("Resolve HostName %s Failed - Error %d", Route->TCPHost, err); + return FALSE; // Resolve failed + } + + 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, ¶m); + + 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; + return TRUE; + } + else + { + 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. + + Debugprintf("New NRTCP Connection from %s", Msg->Call); + + memcpy(Info->Call, Msg->Call, 10); + + ConvToAX25(Msg->Call, axCall); + + if (FindNeighbour(axCall, portNo, &Route)) + { + Info->Route = Route; + Route->NEIGHBOUR_LINK = Info->LINK; + Route->NEIGHBOUR_PORT = portNo; + Info->LINK->NEIGHBOUR = Route; + Info->LINK->LINKPORT = GetPortTableEntryFromPortNum(portNo); + Route->TCPSession = Info; + Info->LINK->L2STATE = 5; + + if (Info->Route->INP3Node) + SendRTTMsg(Info->Route); + } + else + { + Debugprintf("Neighbour %s port %d not found - closing connection", Msg->Call, portNo); + closesocket(sockptr->socket); + sockptr->SocketActive = FALSE; + memset(sockptr, 0, sizeof(struct ConnectionInfo)); + Info->Call[0] = 0; + return 0; + } + } + + + 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 = portNo; + 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); + + if (Route) + Route->TCPSession = 0; + + Info->Call[0] = 0; + } + + sockptr->SocketActive = FALSE; + + memset(sockptr, 0, sizeof(struct ConnectionInfo)); +} + +>>>>>>> Stashed changes diff --git a/TelnetV6.c b/TelnetV6.c index 0761363..590186c 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -3874,12 +3874,14 @@ MsgLoop: LFPtr=memchr(MsgPtr, 10, InputLen); if (LFPtr == 0) + { if (CRPtr) { LFPtr = ++CRPtr; InputLen++; } - if (LFPtr == 0) + } + if (LFPtr == 0) { // Check Paclen @@ -3895,7 +3897,7 @@ MsgLoop: } // Send to Node - + // Line could be up to 500 chars if coming from a program rather than an interative user // Limit send to node to 255 @@ -3907,16 +3909,16 @@ MsgLoop: memmove(MsgPtr,MsgPtr+255,InputLen); } - + SendtoNode(TNC, sockptr->Number, MsgPtr, InputLen); sockptr->InputLen = 0; - + } // PACLEN return 0; // No CR } - + // Got a LF // Process data up to the cr @@ -3929,7 +3931,7 @@ MsgLoop: case 2: // Normal Data State - + STREAM->bytesRXed += MsgLen; SendIndex = 0; @@ -3944,7 +3946,7 @@ MsgLoop: } SendtoNode(TNC, sockptr->Number, MsgPtr + SendIndex, MsgLen); - + MsgLen += SendIndex; // If anything left, copy down buffer, and go back @@ -3963,20 +3965,20 @@ MsgLoop: return 0; case 0: - - // Check Username - // + + // Check Username + // *(LFPtr-1)=0; // remove cr - - // send(sock, NLMsg, 2, 0); - if (LogEnabled) + // send(sock, NLMsg, 2, 0); + + if (LogEnabled) { char Addr[256]; - + Tel_Format_Addr(sockptr, Addr); - + if (strlen(MsgPtr) > 64) { MsgPtr[64] = 0; @@ -4571,7 +4573,8 @@ MsgLoop: if (P8 == 1) SendPortsForMonitor(sock, sockptr->UserPointer->Secure); - sockptr->InputLen = 0; + + sockptr->InputLen = 0; return 0; } } @@ -6386,10 +6389,10 @@ VOID SaveCMSHostInfo(int port, struct TCPINFO * TCP, int CMSNo) char ip[256]; int n; - if (sizeof(time_t) == 4) - n = sscanf(buf,"%s %d %s", addr, (int *)&t, ip); - else - n = sscanf(buf, "%s %lld %s", addr, &t, ip); + if (sizeof(time_t) == 4) + n = sscanf(buf,"%s %d %s", addr, (int *)&t, ip); + else + n = sscanf(buf, "%s %lld %s", addr, &t, ip); if (n == 3) { diff --git a/UZ7HODrv.c b/UZ7HODrv.c index e166b36..2adfe12 100644 --- a/UZ7HODrv.c +++ b/UZ7HODrv.c @@ -1586,81 +1586,81 @@ static int ProcessLine(char * buf, int Port) if (TNC->TCPPort == 0) TNC->TCPPort = 8000; - TNC->destaddr.sin_family = AF_INET; - TNC->destaddr.sin_port = htons(TNC->TCPPort); - TNC->HostName = malloc(strlen(p_ipad)+1); + TNC->destaddr.sin_family = AF_INET; + TNC->destaddr.sin_port = htons(TNC->TCPPort); + TNC->HostName = malloc(strlen(p_ipad)+1); - if (TNC->HostName == NULL) return TRUE; + if (TNC->HostName == NULL) return TRUE; - strcpy(TNC->HostName,p_ipad); + strcpy(TNC->HostName,p_ipad); - ptr = strtok(NULL, " \t\n\r"); + ptr = strtok(NULL, " \t\n\r"); - if (ptr) + if (ptr) + { + if (_stricmp(ptr, "PTT") == 0) { - if (_stricmp(ptr, "PTT") == 0) - { - ptr = strtok(NULL, " \t\n\r"); + ptr = strtok(NULL, " \t\n\r"); - if (ptr) - { - DecodePTTString(TNC, ptr); - ptr = strtok(NULL, " \t\n\r"); - } - } - - if (ptr &&_memicmp(ptr, "PATH", 4) == 0) + if (ptr) { - p_cmd = strtok(NULL, "\n\r"); - if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); + DecodePTTString(TNC, ptr); + ptr = strtok(NULL, " \t\n\r"); } } - // Read Initialisation lines - - while(TRUE) + if (ptr &&_memicmp(ptr, "PATH", 4) == 0) { - if (GetLine(buf) == 0) - return TRUE; + p_cmd = strtok(NULL, "\n\r"); + if (p_cmd) TNC->ProgramPath = _strdup(p_cmd); + } + } - strcpy(errbuf, buf); + // Read Initialisation lines - if (memcmp(buf, "****", 4) == 0) - return TRUE; + while(TRUE) + { + if (GetLine(buf) == 0) + return TRUE; - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "MAXSESSIONS", 11) == 0) - { - AGW->MaxSessions = atoi(&buf[12]); - if (AGW->MaxSessions > 26 ) AGW->MaxSessions = 26; - } - if (_memicmp(buf, "CONTIMEOUT", 10) == 0) - AGW->ConnTimeOut = atoi(&buf[11]) * 10; - else + strcpy(errbuf, buf); + + if (memcmp(buf, "****", 4) == 0) + return TRUE; + + ptr = strchr(buf, ';'); + if (ptr) + { + *ptr++ = 13; + *ptr = 0; + } + + if (_memicmp(buf, "MAXSESSIONS", 11) == 0) + { + AGW->MaxSessions = atoi(&buf[12]); + if (AGW->MaxSessions > 26 ) AGW->MaxSessions = 26; + } + if (_memicmp(buf, "CONTIMEOUT", 10) == 0) + AGW->ConnTimeOut = atoi(&buf[11]) * 10; + else if (_memicmp(buf, "UPDATEMAP", 9) == 0) TNC->PktUpdateMap = TRUE; else - if (_memicmp(buf, "BEACONAFTERSESSION", 18) == 0) // Send Beacon after each session - TNC->RPBEACON = TRUE; - else - if (_memicmp(buf, "WINDOW", 6) == 0) - TNC->Window = atoi(&buf[7]); - else - if (_memicmp(buf, "DEFAULTMODEM", 12) == 0) - TNC->AGWInfo->Modem = atoi(&buf[13]); - else - if (_memicmp(buf, "MODEMCENTER", 11) == 0 || _memicmp(buf, "MODEMCENTRE", 11) == 0) - TNC->AGWInfo->CenterFreq = atoi(&buf[12]); - else - if (standardParams(TNC, buf) == FALSE) - strcat(TNC->InitScript, buf); - } + if (_memicmp(buf, "BEACONAFTERSESSION", 18) == 0) // Send Beacon after each session + TNC->RPBEACON = TRUE; + else + if (_memicmp(buf, "WINDOW", 6) == 0) + TNC->Window = atoi(&buf[7]); + else + if (_memicmp(buf, "DEFAULTMODEM", 12) == 0) + TNC->AGWInfo->Modem = atoi(&buf[13]); + else + if (_memicmp(buf, "MODEMCENTER", 11) == 0 || _memicmp(buf, "MODEMCENTRE", 11) == 0) + TNC->AGWInfo->CenterFreq = atoi(&buf[12]); + else + if (standardParams(TNC, buf) == FALSE) + strcat(TNC->InitScript, buf); + } return (TRUE); diff --git a/VARA.c b/VARA.c index 70f7461..f913fe8 100644 --- a/VARA.c +++ b/VARA.c @@ -423,8 +423,9 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) { TNC->Busy--; if (TNC->Busy == 0) - SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); + { SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); strcpy(TNC->WEB_CHANSTATE, "Clear"); + } } } diff --git a/Versions.h b/Versions.h index be8a65e..dfad8ec 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,16 @@ #endif +<<<<<<< Updated upstream #define KVers 6,0,25,8 #define KVerstring "6.0.25.8\0" +||||||| Stash base +#define KVers 6,0,25,1 +#define KVerstring "6.0.25.1\0" +======= +#define KVers 6,0,25,9 +#define KVerstring "6.0.25.9\0" +>>>>>>> Stashed changes #ifdef CKernel diff --git a/WINMOR.c b/WINMOR.c index 836a070..94630b3 100644 --- a/WINMOR.c +++ b/WINMOR.c @@ -618,8 +618,10 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) { TNC->Busy--; if (TNC->Busy == 0) + { SetWindowText(TNC->xIDC_CHANSTATE, "Clear"); strcpy(TNC->WEB_CHANSTATE, "Clear"); + } } } diff --git a/WebMail.c b/WebMail.c index 63bfd6e..a97b9bf 100644 --- a/WebMail.c +++ b/WebMail.c @@ -3311,7 +3311,7 @@ char * xxReadTemplate(char * FormSet, char * DirName, char *FileName) while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_DIR) - continue; + continue; if (stristr(entry->d_name, FileName)) { @@ -5609,7 +5609,7 @@ char * CheckFile(struct HtmlFormDir * Dir, char * FN) while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_DIR) - continue; + continue; if (stricmp(entry->d_name, FN) == 0) { diff --git a/asmstrucs.h b/asmstrucs.h index 3ac464b..8b11d45 100644 --- a/asmstrucs.h +++ b/asmstrucs.h @@ -250,7 +250,13 @@ typedef struct ROUTE char * TCPHost; // For NETROM over TCP int TCPPort; +<<<<<<< Updated upstream struct NRTCPSTRUCT * TCPSession; +||||||| Stash base +======= + struct NRTCPSTRUCT * TCPSession; + struct addrinfo * TCPAddress; // Resolved Address +>>>>>>> Stashed changes } *PROUTE; @@ -977,6 +983,19 @@ typedef struct _LINKTABLE int framesRXed; int framesTXed; int framesResent; +<<<<<<< Updated upstream +||||||| Stash base +======= + time_t LastStatusTime; + int LastStatusbytesRXed; + int LastStatusbytesTXed; + int maxQueued; + int intervalMaxQueued; + + uint64_t lastPSent; // Time last I frame with P bit sent in mS (for RTT Measurements) + int RTT; + +>>>>>>> Stashed changes // Now support compressing L2 Sessions. // We collect as much data as possible before compressing and re-packetizing diff --git a/bpqaxip.c b/bpqaxip.c index 3491bbd..71f0ce1 100644 --- a/bpqaxip.c +++ b/bpqaxip.c @@ -444,7 +444,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff) From[ConvFromAX25(call, &From[1]) + 1] = 0; if (strstr(CantReplyList, From) == 0) { - if (strlen(CantReplyList) < 500); + if (strlen(CantReplyList) < 500) strcat(CantReplyList, From); Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); } @@ -557,7 +557,7 @@ static size_t ExtProc(int fn, int port, PMESSAGE buff) From[ConvFromAX25(call, &From[1]) + 1] = 0; if (strstr(CantReplyList, From) == 0) { - if (strlen(CantReplyList) < 500); + if (strlen(CantReplyList) < 500) strcat(CantReplyList, From); Debugprintf("AXIP Packet from %s dropped - can't reply", &From[1]); } diff --git a/cMain.c b/cMain.c index 74b6bc6..bcd24b0 100644 --- a/cMain.c +++ b/cMain.c @@ -57,7 +57,13 @@ VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD); void WritePacketLogThread(void * param); void hookNodeStarted(); void hookNodeRunning(); +<<<<<<< Updated upstream void APIL2Trace(struct _MESSAGE * Message, char Dirn); +||||||| Stash base + +======= +void APIL2Trace(struct _MESSAGE * Message, char * Dirn); +>>>>>>> Stashed changes #include "configstructs.h" @@ -1416,12 +1422,19 @@ BOOL Start() { ROUTE->TCPHost = Rcfg->tcphost; ROUTE->TCPPort = Rcfg->tcpport; +<<<<<<< Updated upstream +||||||| Stash base +======= + + ROUTE->TCPAddress = (struct addrinfo *)zalloc(sizeof(struct addrinfo)); + ROUTE->TCPAddress->ai_addr = (struct sockaddr *) zalloc(sizeof(struct sockaddr)); +>>>>>>> Stashed changes } Rcfg++; ROUTE++; } - + // SET UP INFO MESSAGE ptr2 = &cfg->C_INFOMSG[0]; @@ -2028,7 +2041,7 @@ VOID ReadNodes() ptr = strtok_s(NULL, seps, &Context); // INP3 if (ptr == NULL) continue; - if (ROUTE->NEIGHBOUR_FLAG == 0 || ROUTE->OtherendLocked == 0); // Not LOCKED ROUTE + if (ROUTE->NEIGHBOUR_FLAG == 0 || ROUTE->OtherendLocked == 0) // Not LOCKED ROUTE ROUTE->OtherendsRouteQual = atoi(ptr); ptr = strtok_s(NULL, seps, &Context); // INP3 @@ -2279,7 +2292,12 @@ VOID TIMERINTERRUPT() Message = (struct _MESSAGE *)Buffer; if(NodeAPISocket) +<<<<<<< Updated upstream APIL2Trace(Message, 'T'); +||||||| Stash base +======= + APIL2Trace(Message, "sent"); +>>>>>>> Stashed changes Message->PORT |= 0x80; // Set TX Bit @@ -2394,7 +2412,12 @@ L2Packet: MQTTKISSRX(Buffer); if(NodeAPISocket &&PORT->PROTOCOL == 0) +<<<<<<< Updated upstream APIL2Trace(Message, 'R'); +||||||| Stash base +======= + APIL2Trace(Message, "rcvd"); +>>>>>>> Stashed changes // Bridge if requested diff --git a/config.c b/config.c index bb0b2f2..d90ba74 100644 --- a/config.c +++ b/config.c @@ -635,6 +635,13 @@ BOOL ProcessConfig() paramok[93]=1; // ONLYVer2point0 paramok[94]=1; // DEBUGINP3 paramok[95]=1; // EnableOARCAPI +<<<<<<< Updated upstream +||||||| Stash base + paramok[93]=1; // C_ONLYVer2point0 +======= + paramok[96]=1; // OARCAPI + +>>>>>>> Stashed changes for (i=0; i < PARAMLIM; i++) { diff --git a/lzhuf32.c b/lzhuf32.c index c1aea82..961c624 100644 --- a/lzhuf32.c +++ b/lzhuf32.c @@ -487,124 +487,124 @@ static void reconst(void) static void update(int c) { - int i, j, l; + int i, j, l; unsigned int k; - if (freq[R] == MAX_FREQ) { - reconst(); - } - c = prnt[c + T]; - do { - k = ++freq[c]; + if (freq[R] == MAX_FREQ) { + reconst(); + } + c = prnt[c + T]; + do { + k = ++freq[c]; - /* if the order is disturbed, exchange nodes */ + /* if the order is disturbed, exchange nodes */ + + l = c + 1; - l = c + 1; - if ((unsigned)k > freq[l]) { - while ((unsigned)k > freq[++l]); - l--; - freq[c] = freq[l]; - freq[l] = k; + while ((unsigned)k > freq[++l]); + l--; + freq[c] = freq[l]; + freq[l] = k; - i = son[c]; - prnt[i] = l; - if (i < T) prnt[i + 1] = l; + i = son[c]; + prnt[i] = l; + if (i < T) prnt[i + 1] = l; - j = son[l]; - son[l] = i; + j = son[l]; + son[l] = i; - prnt[j] = c; - if (j < T) prnt[j + 1] = c; - son[c] = j; + prnt[j] = c; + if (j < T) prnt[j + 1] = c; + son[c] = j; - c = l; - } - } while ((c = prnt[c]) != 0); /* repeat up to root */ + c = l; + } + } while ((c = prnt[c]) != 0); /* repeat up to root */ } unsigned code, len; static void EncodeChar(unsigned int c) { - unsigned int i; - int j, k; + unsigned int i; + int j, k; - i = 0; - j = 0; - k = prnt[c + T]; + i = 0; + j = 0; + k = prnt[c + T]; - /* travel from leaf to root */ - do { - i >>= 1; + /* travel from leaf to root */ + do { + i >>= 1; - /* if node's address is odd-numbered, choose bigger brother node */ - if (k & 1) i += 0x8000; + /* if node's address is odd-numbered, choose bigger brother node */ + if (k & 1) i += 0x8000; - j++; - } while ((k = prnt[k]) != R); - Putcode(j, i); - code = i; - len = j; - update(c); + j++; + } while ((k = prnt[k]) != R); + Putcode(j, i); + code = i; + len = j; + update(c); } static void EncodePosition(unsigned int c) { - unsigned int i; + unsigned int i; - /* output upper 6 bits by table lookup */ - i = c >> 6; - Putcode(p_len[i], (unsigned)p_code[i] << 8); + /* output upper 6 bits by table lookup */ + i = c >> 6; + Putcode(p_len[i], (unsigned)p_code[i] << 8); - /* output lower 6 bits verbatim */ - Putcode(6, (c & 0x3f) << 10); + /* output lower 6 bits verbatim */ + Putcode(6, (c & 0x3f) << 10); } static void EncodeEnd(void) { - if (putlen) { - if (crc_fputc(putbuf >> 8) == EOF) { - Error(wterr); - } - codesize++; - } + if (putlen) { + if (crc_fputc(putbuf >> 8) == EOF) { + Error(wterr); + } + codesize++; + } } int DecodeChar(void) { - unsigned int c; + unsigned int c; - c = son[R]; + c = son[R]; - /* travel from root to leaf, */ - /* choosing the smaller child node (son[]) if the read bit is 0, */ - /* the bigger (son[]+1} if 1 */ - while (c < T) { - c += GetBit(); - c = son[c]; - } - c -= T; - update(c); - return (int)c; + /* travel from root to leaf, */ + /* choosing the smaller child node (son[]) if the read bit is 0, */ + /* the bigger (son[]+1} if 1 */ + while (c < T) { + c += GetBit(); + c = son[c]; + } + c -= T; + update(c); + return (int)c; } int DecodePosition(void) { - unsigned int i, j, c; + unsigned int i, j, c; - /* recover upper 6 bits from table */ - i = GetByte(); - c = (unsigned)d_code[i] << 6; - j = d_len[i]; + /* recover upper 6 bits from table */ + i = GetByte(); + c = (unsigned)d_code[i] << 6; + j = d_len[i]; - /* read lower 6 bits verbatim */ - j -= 2; - while (j--) { - i = (i << 1) + GetBit(); - } - return (int)(c | (i & 0x3f)); + /* read lower 6 bits verbatim */ + j -= 2; + while (j--) { + i = (i << 1) + GetBit(); + } + return (int)(c | (i & 0x3f)); } /* compression */ diff --git a/pngwutil.c b/pngwutil.c index dd7b150..2f42e07 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -350,10 +350,11 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) comp->output_ptr[i]=NULL; } if (comp->max_output_ptr != 0) - png_free(png_ptr, comp->output_ptr); - comp->output_ptr=NULL; + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; /* write anything left in zbuf */ if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); From 85f200a46cf5e002e59e36b11ab4fba2f0422b33 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 11 Nov 2025 21:50:47 +0000 Subject: [PATCH 2/2] New upstream version 6.0.25.11+repack --- Bpq32.c | 25 +- Cmd.c | 41 +-- CommonCode.c | 22 -- Events.c | 929 +++++++----------------------------------------- L4Code.c | 27 +- LinBPQ.c | 4 - NETROMTCP.c | 578 ++---------------------------- Versions.h | 12 +- asmstrucs.h | 17 +- cMain.c | 86 +++-- config.c | 15 +- configstructs.h | 1 + 12 files changed, 243 insertions(+), 1514 deletions(-) diff --git a/Bpq32.c b/Bpq32.c index 3c5801f..e49bd8b 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1298,6 +1298,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // 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) +// Fix some issues with NetromX connects and Route Selection when running INP3 and NODES routing (9) +// Fix connecting to a netrom node with c p node command (10) #define CKernel @@ -1406,11 +1408,7 @@ void initAIS(); void initADSB(); int CloseAllSessions(); int CloseAllLinks(); -<<<<<<< Updated upstream -||||||| Stash base -======= void NETROMTCPResolve(); ->>>>>>> Stashed changes extern BOOL ADIFLogEnabled; @@ -2407,12 +2405,7 @@ VOID TimerProcX() if (CloseAllSessions() == 0) { if (CloseAllLinks() == 0) // No sessions closed so close links now -<<<<<<< Updated upstream - CloseAllTimer = 0; // No Links so close now -||||||| Stash base -======= CloseAllTimer = 1; // No Links so close now ->>>>>>> Stashed changes else CloseAllTimer = 39; // ~4 secs for links to close } @@ -5986,9 +5979,6 @@ DllExport VOID APIENTRY CreateNewTrayIcon() void hookNodeClosing(char * Reason); -<<<<<<< Updated upstream -||||||| Stash base -======= BOOL CALLBACK ClosaAllProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; @@ -6052,25 +6042,15 @@ BOOL CALLBACK ClosaAllProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam HWND hwndClosing = NULL; // Window handle of dialog box ->>>>>>> Stashed changes DllExport VOID APIENTRY CloseAllPrograms() { -<<<<<<< Updated upstream -||||||| Stash base -// HANDLE hProc; -======= WNDCLASS wc; ->>>>>>> Stashed changes CLOSING = TRUE; // Tell BG to shut when all links are gone or after 5 secs CloseAllTimer = 50; -<<<<<<< Updated upstream -||||||| Stash base - Closing = TRUE; -======= wc.style = CS_HREDRAW | CS_VREDRAW; @@ -6089,7 +6069,6 @@ DllExport VOID APIENTRY CloseAllPrograms() hwndClosing = CreateDialog(hInstance, ClosingClassName, NULL, (DLGPROC)ClosaAllProc); ShowWindow(hwndClosing, SW_SHOW); ->>>>>>> Stashed changes } VOID RealCloseAllPrograms() diff --git a/Cmd.c b/Cmd.c index 7eb6061..42869d5 100644 --- a/Cmd.c +++ b/Cmd.c @@ -905,18 +905,12 @@ int checkifService(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, s BOOL Stay = FALSE; char * ptr, *Context; int i; -<<<<<<< Updated upstream - - ptr = strtok_s(CmdTail, " ", &Context); -||||||| Stash base -======= char TailCopy[256]; strcpy(TailCopy, CmdTail); ptr = strtok_s(TailCopy, " ", &Context); ->>>>>>> Stashed changes // see if any param. if longer than two chars treat as remote node @@ -2677,14 +2671,8 @@ NoPort: // SEE IF CALL TO ANY OF OUR HOST SESSIONS - UNLESS DIGIS SPECIFIED -<<<<<<< Updated upstream - if (axcalls[7] == 0 && axcalls[9] ) -||||||| Stash base - if (axcalls[7] == 0) -======= // if (axcalls[7] == 0 && axcalls[9]) if (axcalls[7] == 0) ->>>>>>> Stashed changes { // If this connect is as a result of a command alias, don't check appls or we will loop @@ -2735,23 +2723,6 @@ NoPort: } } -<<<<<<< Updated upstream - // 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 -||||||| Stash base - 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) @@ -2760,22 +2731,13 @@ NoPort: // Make sure field is numeric if (cmdCopy[0] != ' ') ->>>>>>> Stashed changes { -<<<<<<< Updated upstream - if (i > 0) // Some digits - { - haveService = 1; - Service = atoi(cmdCopy); -||||||| Stash base - // SEE IF CALL TO ANOTHER NODE -======= i = 0; while (cmdCopy[i] >= '0' && cmdCopy[i]<= '9') i++; - if (cmdCopy[i] != ' ') + if (i && cmdCopy[i] != ' ') // have an all digit param = probably a service goto Downlink; else { @@ -2784,7 +2746,6 @@ NoPort: haveService = 1; Service = atoi(cmdCopy); } ->>>>>>> Stashed changes } } diff --git a/CommonCode.c b/CommonCode.c index 09690ae..9e8b37a 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -3739,28 +3739,7 @@ VOID ResolveUpdateThread(void * Unused) nodeStartedSent = 1; LastNodeStatus = time(NULL); } -<<<<<<< Updated upstream } - - if (HostEnt1 && HostEnt2) - { - Sleep(1000 * 60 * 30); - continue; -||||||| Stash base - Sleep(1000 * 60 * 30); - continue; -======= ->>>>>>> Stashed changes - } -<<<<<<< Updated upstream - - Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); - Sleep(1000 * 60 * 5); -||||||| Stash base - - Debugprintf("Resolve Failed for update.g8bpq.net or chatmap.g8bpq.net"); - Sleep(1000 * 60 * 5); -======= NETROMTCPResolve(); @@ -3769,7 +3748,6 @@ VOID ResolveUpdateThread(void * Unused) Sleep(1000 * 60 * 15); continue; } ->>>>>>> Stashed changes } } diff --git a/Events.c b/Events.c index 1a64b3b..bb2a8ef 100644 --- a/Events.c +++ b/Events.c @@ -26,6 +26,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "asmstrucs.h" #include "tncinfo.h" #include "cheaders.h" +#include "kiss.h" VOID __cdecl Debugprintf(const char * format, ...); @@ -44,7 +45,9 @@ void MQTTReportSession(char * Msg); extern int MQTT; extern time_t TimeLoaded; -int UDPSeq = 1; +uint16_t UDPSeq = 1; +int linkSeq = 1; +int cctSeq = 1; extern SOCKET NodeAPISocket; extern SOCKADDR_IN UDPreportdest; @@ -57,18 +60,6 @@ extern char LOC[7]; extern char VersionString[50]; extern double LatFromLOC; extern double LonFromLOC; -<<<<<<< Updated upstream - -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); -||||||| Stash base -======= extern int NUMBEROFNODES, MAXDESTS, L4CONNECTSOUT, L4CONNECTSIN, L4FRAMESTX, L4FRAMESRX, L4FRAMESRETRIED, OLDFRAMES; extern int L2CONNECTSOUT, L2CONNECTSIN; @@ -81,7 +72,6 @@ int decodeNETROMIFrame(unsigned char * Msg, int iLen, char * Buffer, int BufferL int decodeINP3RIF(unsigned char * Msg, int iLen, char * Buffer, int BufferLen); int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen); char * byte_base64_encode(char *str, int len); ->>>>>>> Stashed changes // Runs use specified routine on certain event @@ -157,27 +147,12 @@ DllExport void APIENTRY RunEventProgram(char * Program, char * Param) void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK) { // Incoming SABM accepted -<<<<<<< Updated upstream char UDPMsg[1024]; int udplen; -||||||| Stash base - // Incoming SABM -======= ->>>>>>> Stashed changes - -<<<<<<< Updated upstream - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; -||||||| Stash base - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = 0; -======= - char UDPMsg[1024]; - int udplen; ->>>>>>> Stashed changes L2CONNECTSIN++; + LINK->apiSeq = linkSeq++; LINK->lastStatusSentTime = LINK->ConnectTime = time(NULL); LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; @@ -190,8 +165,8 @@ void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _ { 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); + udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\", \"isRF\": %s}", + NODECALLLOPPED, LINK->apiSeq, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, (LINK->LINKPORT->isRF)?"true":"false"); // Debugprintf(UDPMsg); @@ -251,19 +226,9 @@ void hookL2SessionDeleted(struct _LINKTABLE * LINK) void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK) { -<<<<<<< Updated upstream - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; - -||||||| Stash base - LINK->ConnectTime = time(NULL); - LINK->bytesTXed = LINK->bytesRXed = 0; - -======= LINK->lastStatusSentTime = LINK->ConnectTime = time(NULL); LINK->bytesTXed = LINK->bytesRXed = LINK->framesResent = LINK->framesRXed = LINK->framesTXed = 0; LINK->LastStatusbytesTXed = LINK->LastStatusbytesRXed = 0; ->>>>>>> Stashed changes strcpy(LINK->callingCall, ourcall); strcpy(LINK->receivingCall, remotecall); strcpy(LINK->Direction, "Out"); @@ -276,82 +241,15 @@ void hookL2SessionConnected(struct _LINKTABLE * LINK) char UDPMsg[1024]; int udplen; -<<<<<<< Updated upstream - if (NodeAPISocket) - { - 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); -||||||| Stash base -======= L2CONNECTSOUT++; + LINK->apiSeq = linkSeq++; if (NodeAPISocket) { 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); + udplen = sprintf(UDPMsg, "{\"@type\":\"LinkUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", \"port\": \"%d\", \"remote\": \"%s\", \"local\": \"%s\", \"isRF\": %s}", + NODECALLLOPPED, LINK->apiSeq, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, (LINK->LINKPORT->isRF)?"true":"false"); // Debugprintf(UDPMsg); @@ -375,20 +273,19 @@ void hookL2SessionClosed(struct _LINKTABLE * LINK, char * Reason, char * Directi 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\"," - " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d}", - NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, + " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d, \"isRF\": %s}", + NODECALLLOPPED, LINK->apiSeq, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason, - (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued); + (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued, (LINK->LINKPORT->isRF)?"true":"false"); 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\"," - " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d}", - NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, + " \"time\": %d, \"upForSecs\": %d, \"frmsQdPeak\": %d, \"isRF\": %s}", + NODECALLLOPPED, LINK->apiSeq, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, LINK->bytesTXed , LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, COUNT_AT_L2(LINK), LINK->framesResent, Reason, - (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued); + (int)Now, (int)Now - LINK->ConnectTime, LINK->maxQueued, (LINK->LINKPORT->isRF)?"true":"false"); - - Debugprintf(UDPMsg); +// Debugprintf(UDPMsg); sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); } @@ -416,23 +313,21 @@ void hookL2SessionStatus(struct _LINKTABLE * LINK) 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," - "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d}", - NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, + "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d, \"isRF\": %s}", + NODECALLLOPPED, LINK->apiSeq, LINK->LINKPORT->PORTNUMBER, LINK->receivingCall, LINK->callingCall, LINK->bytesTXed, LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, 0, LINK->framesResent, - (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT); + (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT, (LINK->LINKPORT->isRF)?"true":"false"); 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," - "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d}", - NODECALLLOPPED, UDPSeq++, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, + "\"upForSecs\": %d, \"frmsQdPeak\": %d, \"bpsTxMean\": %d, \"bpsRxMean\": %d, \"frmQMax\": %d, \"l2rttMs\": %d, \"isRF\": %s}", + NODECALLLOPPED, LINK->apiSeq, LINK->LINKPORT->PORTNUMBER, LINK->callingCall, LINK->receivingCall, LINK->bytesTXed, LINK->bytesRXed, LINK->framesTXed, LINK->framesRXed, 0, LINK->framesResent, - (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT); + (int)Now - LINK->ConnectTime, LINK->maxQueued, bpsTx, bpsRx, LINK->intervalMaxQueued, LINK->RTT, (LINK->LINKPORT->isRF)?"true":"false"); LINK->intervalMaxQueued = 0; - Debugprintf(UDPMsg); ->>>>>>> Stashed changes - +// Debugprintf(UDPMsg); sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); } } @@ -547,671 +442,6 @@ void hookNodeClosing(char * Reason) if (NodeAPISocket) { -<<<<<<< Updated upstream - 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); -||||||| Stash base -======= udplen = sprintf(UDPMsg, "{\"@type\": \"NodeDownEvent\", \"nodeCall\": \"%s\", \"nodeAlias\": \"%s\", \"reason\": \"%s\", \"uptimeSecs\": %d," "\"linksIn\": %d, \"linksOut\": %d, \"cctsIn\": %d, \"cctsOut\": %d, \"l3Relayed\": %d}", NODECALLLOPPED, MYALIASLOPPED, Reason, time(NULL) - TimeLoaded, L2CONNECTSIN, L2CONNECTSOUT, L4CONNECTSIN, L4CONNECTSOUT, L3FRAMES); @@ -1258,11 +488,17 @@ void IncomingL4ConnectionEvent(TRANSPORTENTRY * L4) char remotecall[64]; char ourcall[64]; char circuitinfo[32]; + int Service = L4->Service; // CACK sent to CREQ + L4->apiSeq = cctSeq++; + strcpy(L4->Direction, "incoming"); + if (NodeAPISocket) { + L4->lastStatusSentTime = time(NULL); + remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0; // remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0; ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0; @@ -1272,10 +508,16 @@ void IncomingL4ConnectionEvent(TRANSPORTENTRY * L4) sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITINDEX, L4->CIRCUITID); strcat(ourcall, circuitinfo); - - udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\"," + + if (Service == -1) + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", " + "\"remote\": \"%s\", \"local\": \"%s\"}", + NODECALLLOPPED, L4->apiSeq, remotecall, ourcall); + else + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"incoming\", " "\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\"}", - NODECALLLOPPED, UDPSeq++, L4->Service, remotecall, ourcall); + NODECALLLOPPED, L4->apiSeq, Service, remotecall, ourcall); + // Debugprintf(UDPMsg); sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); @@ -1290,11 +532,18 @@ void OutgoingL4ConnectionEvent(TRANSPORTENTRY * L4) char remotecall[64]; char ourcall[64]; char circuitinfo[32]; + int Service = L4->Service; // CACK received + strcpy(L4->Direction, "outgoing"); + + L4->apiSeq = cctSeq++; + if (NodeAPISocket) { + L4->lastStatusSentTime = time(NULL); + remotecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, remotecall)] = 0; // remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0; ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0; @@ -1305,9 +554,14 @@ void OutgoingL4ConnectionEvent(TRANSPORTENTRY * L4) sprintf(circuitinfo, ":%02x%02x", L4->CIRCUITID, L4->CIRCUITINDEX); strcat(ourcall, circuitinfo); - udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\"," + if (Service == -1) + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", " + "\"remote\": \"%s\", \"local\": \"%s\"}", + NODECALLLOPPED, L4->apiSeq, remotecall, ourcall); + else + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitUpEvent\", \"node\": \"%s\", \"id\": %d, \"direction\": \"outgoing\", " "\"service\": %d, \"remote\": \"%s\", \"local\": \"%s\"}", - NODECALLLOPPED, UDPSeq++, L4->Service, remotecall, ourcall); + NODECALLLOPPED, L4->apiSeq, Service, remotecall, ourcall); // Debugprintf(UDPMsg); sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); @@ -1365,7 +619,7 @@ void L4DisconnectEvent(TRANSPORTENTRY * L4, char * Direction, char * Reason) 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); + NODECALLLOPPED, L4->apiSeq, Direction, 0, remotecall, ourcall,L4->segsSent, L4->segsRcvd, L4->segsResent, Count, Reason); // Debugprintf(UDPMsg); sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); @@ -1381,11 +635,16 @@ void L4StatusSeport(TRANSPORTENTRY * L4) char nodecall[16]; char circuitinfo[32]; int Count; + time_t Now = time(NULL); + int Service = L4->Service; - // CACK received + + + // Regular Status reports if (NodeAPISocket) { + L4->lastStatusSentTime = Now; nodecall[ConvFromAX25(L4->L4TARGET.DEST->DEST_CALL, nodecall)] = 0; remotecall[ConvFromAX25(L4->L4USER, remotecall)] = 0; ourcall[ConvFromAX25(L4->L4MYCALL, ourcall)] = 0; @@ -1401,10 +660,15 @@ void L4StatusSeport(TRANSPORTENTRY * L4) 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); + + if (Service == -1) + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"%s\"," + "\"upForSecs\": %d,\"remote\": \"%s\", \"local\": \"%s\", \"segsSent\": %d, \"segsRcvd\": %d, \"segsResent\": %d, \"segsQueued\": %d}", + NODECALLLOPPED, L4->apiSeq, L4->Direction, Now - L4->ConnectTime, remotecall, ourcall,L4->segsSent, L4->segsRcvd, L4->segsResent, Count); + else + udplen = sprintf(UDPMsg, "{\"@type\": \"CircuitStatus\", \"node\": \"%s\", \"id\": %d, \"direction\": \"%s\"," + "\"upForSecs\": %d, \"service\": %d, \"remote\": \"%s\", \"local\": \"%s\", \"segsSent\": %d, \"segsRcvd\": %d, \"segsResent\": %d, \"segsQueued\": %d}", + NODECALLLOPPED, L4->apiSeq, L4->Direction, Now - L4->ConnectTime, Service, remotecall, ourcall,L4->segsSent, L4->segsRcvd, L4->segsResent, Count); // Debugprintf(UDPMsg); sendto(NodeAPISocket, UDPMsg, udplen, 0, (struct sockaddr *)&UDPreportdest, sizeof(UDPreportdest)); @@ -1486,8 +750,13 @@ void APIL2Trace(struct _MESSAGE * Message, char * Dirn) int UFlag = 0; int NS; int NR; + struct PORTCONTROL * PORT = GetPortTableEntryFromPortNum(Message->PORT); + time_t Now = time(NULL); + if (PORT == 0) + return; + if ((Message->ORIGIN[6] & 1) == 0) // Digis return; @@ -1507,7 +776,6 @@ void APIL2Trace(struct _MESSAGE * Message, char * Dirn) 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)) @@ -1630,9 +898,9 @@ void APIL2Trace(struct _MESSAGE * Message, char * Dirn) // Common to all frame types udplen = snprintf(UDPMsg, 2048, - "{\"@type\": \"L2Trace\", \"dirn\": \"%s\", \"reportFrom\": \"%s\", \"port\": \"%d\", \"srce\": \"%s\", \"dest\": \"%s\", \"ctrl\": %d," + "{\"@type\": \"L2Trace\", \"serial\": %d, \"time\": %d, \"dirn\": \"%s\", \"isRF\": %s, \"reportFrom\": \"%s\", \"port\": \"%d\", \"srce\": \"%s\", \"dest\": \"%s\", \"ctrl\": %d," "\"l2Type\": \"%s\", \"modulo\": 8, \"cr\": \"%s\"", - Dirn, NODECALLLOPPED, Message->PORT, srcecall, destcall, Message->CTL, Type, CR); + UDPSeq++, (int)Now, Dirn, (PORT->isRF)?"true":"false", NODECALLLOPPED, Message->PORT, srcecall, destcall, Message->CTL, Type, CR); if (UIFlag) { @@ -1690,6 +958,48 @@ void APIL2Trace(struct _MESSAGE * Message, char * Dirn) } + //"@type" = @L3Trace, reportFrom, time, dirn, + +void NetromTCPTrace(struct _MESSAGE * Message, char * Dirn) +{ + char UDPMsg[2048]; + int udplen; + time_t Now = time(NULL); + int iLen = Message->LENGTH - (15 + MSGHDDRLEN); + int isRF = 0; + + + udplen = snprintf(UDPMsg, 2048, + "{\"@type\": \"L3Trace\", \"serial\": %d, \"time\": %d, \"dirn\": \"%s\", \"isRF\": %s, \"reportFrom\": \"%s\", \"port\": %d", + UDPSeq++, (int)Now, Dirn, (isRF)?"true":"false", NODECALLLOPPED, Message->PORT); + + + udplen += snprintf(&UDPMsg[udplen], 2048 - udplen, + ", \"ilen\": %d, \"pid\": %d, \"ptcl\": \"%s\"", + iLen, Message->PID, PIDtoText(Message->PID)); + + 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; + } + + + + 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; @@ -1716,7 +1026,7 @@ int decodeNETROMUIMsg(unsigned char * Msg, int iLen, char * Buffer, int BufferLe Msg += 7; // to first field - Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"Routing info\", \"type\": \"NODES\", \"nodes\": ["); + Len = snprintf(Buffer, BufferLen, ", \"l3Type\": \"Routing info\", \"type\": \"NODES\", \"fromAlias\": \"%s\", \"nodes\": [", Alias); iLen -= 7; //Header, mnemonic and signature length @@ -1935,7 +1245,6 @@ int decodeRecordRoute(L3MESSAGE * L3, int iLen, char * Buffer, int BufferLen) (L3->L4TXNO << 8) | L3->L4RXNO, callList); // Debugprintf(Buffer); ->>>>>>> Stashed changes return Len; } diff --git a/L4Code.c b/L4Code.c index 4bb6e18..a319504 100644 --- a/L4Code.c +++ b/L4Code.c @@ -73,6 +73,7 @@ void OutgoingL4ConnectionEvent(TRANSPORTENTRY * L4); void IncomingL4ConnectionEvent(TRANSPORTENTRY * L4); void L4DisconnectEvent(TRANSPORTENTRY * L4, char * Direction, char * Reason); VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame); +void L4StatusSeport(TRANSPORTENTRY * L4); static UINT APPLMASK; @@ -89,6 +90,8 @@ extern int L2Compress; extern int L2CompMaxframe; extern int L2CompPaclen; +int sessionStatusInterval = 300; // 5 mins + // L4 Flags Values #define DISCPENDING 8 // SEND DISC WHEN ALL DATA ACK'ED @@ -1128,6 +1131,7 @@ VOID L4TimerProc() TRANSPORTENTRY * L4 = L4TABLE; TRANSPORTENTRY * Partner; int MaxLinks = MAXLINKS; + time_t Now = time(NULL); while (n--) { @@ -1136,6 +1140,12 @@ VOID L4TimerProc() L4++; continue; } + + // Check for Status report time + + if (L4->lastStatusSentTime && (Now - L4->lastStatusSentTime) > sessionStatusInterval) + L4StatusSeport(L4); + // CHECK FOR L4BUSY SET AND NO LONGER BUSY @@ -1601,13 +1611,8 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl int Index; char APPLCMD[13] = ""; -<<<<<<< Updated upstream - memcpy(APPLCMD, APPL->APPLCMD, 13); -||||||| Stash base -======= if (APPL) memcpy(APPLCMD, APPL->APPLCMD, 13); ->>>>>>> Stashed changes memcpy(BPQPARAMS, &L4T1, 2); // SET DEFAULT T1 IN CASE NOT FROM ANOTHER BPQ NODE @@ -1680,12 +1685,8 @@ VOID CONNECTREQUEST(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, UINT Appl { // At the moment I only handle connects to appls. May support other node commands later. -<<<<<<< Updated upstream -||||||| Stash base -======= memcpy(APPLCMD, CMD->String, 13); ->>>>>>> Stashed changes if (n < APPL1 + NumberofAppls) goto doAPPLConnect; } @@ -2270,6 +2271,14 @@ VOID FRAMEFORUS(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG, int ApplMask, return; } + // if connect to service don't send connected to node messsage as service will send own message + +// if (L4->Service) +// { +// ReleaseBuffer(L3MSG); +// return; +// } + Msg = (PDATAMESSAGE)L3MSG; // reuse input buffer Msg->PID = 0xf0; diff --git a/LinBPQ.c b/LinBPQ.c index 0000e1c..ad749d0 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -85,11 +85,7 @@ VOID GetPGConfig(); void SendBBSDataToPktMap(); void CloseAllLinks(); void hookNodeClosing(char * Reason); -<<<<<<< Updated upstream -||||||| Stash base -======= void NETROMTCPResolve(); ->>>>>>> Stashed changes extern uint64_t INP3timeLoadedMS; diff --git a/NETROMTCP.c b/NETROMTCP.c index 2041937..f756621 100644 --- a/NETROMTCP.c +++ b/NETROMTCP.c @@ -1,557 +1,3 @@ -<<<<<<< Updated upstream -/* -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 -//#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, ¶m); - - 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)); -} - -||||||| Stash base -======= /* Copyright 2001-2022 John Wiseman G8BPQ @@ -613,6 +59,9 @@ 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); +void NetromTCPTrace(struct _MESSAGE * Message, char * Dirn); + +extern SOCKET NodeAPISocket; struct NRTCPMsg { @@ -764,8 +213,11 @@ int NETROMOpenConnection(struct ROUTE * Route) { struct NRTCPSTRUCT * Info; struct ConnectionInfo * sockptr; + char farCall[10]; - Debugprintf("Opening NRTCP Connection"); + farCall[ConvFromAX25(Route->NEIGHBOUR_CALL, farCall)] = 0; + + Debugprintf("Opening NRTCP Connection to %s", farCall); if (Route->TCPSession) { @@ -786,7 +238,7 @@ int NETROMOpenConnection(struct ROUTE * Route) return 0; Info = Route->TCPSession = NRTCPInfo[sockptr->Number]; - memcpy(Info->Call, MYNETROMCALL, 10); + memcpy(Info->Call, farCall, 10); Route->NEIGHBOUR_LINK = Info->LINK; Info->Route = Route; @@ -1009,6 +461,7 @@ checkLen: if (memcmp(Info->Call, Msg->Call, 10) != 0) { + Debugprintf("Mismatch"); // something wrong - maybe connection reused } @@ -1045,6 +498,10 @@ checkLen: time(&Buffer->Timestamp); BPQTRACE(Buffer, FALSE); + + if(NodeAPISocket) + NetromTCPTrace(Buffer, "rcvd"); + ReleaseBuffer(Buffer); } @@ -1089,7 +546,7 @@ VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame) { Buffer->CHAIN = 0; Buffer->CTL = 0; - Buffer->PORT = Route->NEIGHBOUR_PORT | 128; // TX Flag + Buffer->PORT = Route->NEIGHBOUR_PORT; ConvToAX25(Route->TCPSession->Call, Buffer->DEST); ConvToAX25(MYNETROMCALL, Buffer->ORIGIN); @@ -1100,7 +557,13 @@ VOID TCPNETROMSend(struct ROUTE * Route, struct _L3MESSAGEBUFFER * Frame) Buffer->LENGTH = DataLen + 15 + MSGHDDRLEN; time(&Buffer->Timestamp); + if(NodeAPISocket) + NetromTCPTrace(Buffer, "sent"); + + Buffer->PORT = Route->NEIGHBOUR_PORT | 128; // TX Flag BPQTRACE(Buffer, FALSE); + + ReleaseBuffer(Buffer); } @@ -1137,4 +600,3 @@ void NETROMConnectionLost(struct ConnectionInfo * sockptr) memset(sockptr, 0, sizeof(struct ConnectionInfo)); } ->>>>>>> Stashed changes diff --git a/Versions.h b/Versions.h index dfad8ec..a988953 100644 --- a/Versions.h +++ b/Versions.h @@ -10,16 +10,8 @@ #endif -<<<<<<< Updated upstream -#define KVers 6,0,25,8 -#define KVerstring "6.0.25.8\0" -||||||| Stash base -#define KVers 6,0,25,1 -#define KVerstring "6.0.25.1\0" -======= -#define KVers 6,0,25,9 -#define KVerstring "6.0.25.9\0" ->>>>>>> Stashed changes +#define KVers 6,0,25,11 +#define KVerstring "6.0.25.11\0" #ifdef CKernel diff --git a/asmstrucs.h b/asmstrucs.h index 8b11d45..439b6f9 100644 --- a/asmstrucs.h +++ b/asmstrucs.h @@ -184,7 +184,13 @@ typedef struct _TRANSPORTENTRY int NRRID; time_t NRRTime; + time_t ConnectTime; + char Direction[16]; // In or Out + int Service; // For Paula's Connnect to Service + int apiSeq; // for OARC event reporting + time_t lastStatusSentTime; + } TRANSPORTENTRY; @@ -250,13 +256,8 @@ typedef struct ROUTE char * TCPHost; // For NETROM over TCP int TCPPort; -<<<<<<< Updated upstream - struct NRTCPSTRUCT * TCPSession; -||||||| Stash base -======= struct NRTCPSTRUCT * TCPSession; struct addrinfo * TCPAddress; // Resolved Address ->>>>>>> Stashed changes } *PROUTE; @@ -742,6 +743,7 @@ typedef struct PORTCONTROL UCHAR * BUSY; // % Active (Normally DCD active or TX) int Hardware; // TNC H_TYPE. Copied here for access from application context + int isRF; // For API reporting. -1 is unspecified } PORTCONTROLX, *PPORTCONTROL; @@ -983,9 +985,6 @@ typedef struct _LINKTABLE int framesRXed; int framesTXed; int framesResent; -<<<<<<< Updated upstream -||||||| Stash base -======= time_t LastStatusTime; int LastStatusbytesRXed; int LastStatusbytesTXed; @@ -995,7 +994,6 @@ typedef struct _LINKTABLE uint64_t lastPSent; // Time last I frame with P bit sent in mS (for RTT Measurements) int RTT; ->>>>>>> Stashed changes // Now support compressing L2 Sessions. // We collect as much data as possible before compressing and re-packetizing @@ -1013,6 +1011,7 @@ typedef struct _LINKTABLE char ApplName[16]; time_t lastStatusSentTime; + int apiSeq; // for OARC event reporting } LINKTABLE; diff --git a/cMain.c b/cMain.c index bcd24b0..d592ecb 100644 --- a/cMain.c +++ b/cMain.c @@ -38,6 +38,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "cheaders.h" #include "tncinfo.h" #include "mqtt.h" +#include "kiss.h" VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer); VOID ProcessIframe(struct _LINKTABLE * LINK, PDATAMESSAGE Buffer); @@ -57,13 +58,7 @@ VOID L2SENDCOMMAND(struct _LINKTABLE * LINK, int CMD); void WritePacketLogThread(void * param); void hookNodeStarted(); void hookNodeRunning(); -<<<<<<< Updated upstream -void APIL2Trace(struct _MESSAGE * Message, char Dirn); -||||||| Stash base - -======= void APIL2Trace(struct _MESSAGE * Message, char * Dirn); ->>>>>>> Stashed changes #include "configstructs.h" @@ -1023,6 +1018,7 @@ BOOL Start() PORT->INP3ONLY = PortRec->INP3ONLY; PORT->ALLOWINP3 = PortRec->AllowINP3; PORT->ENABLEINP3 = PortRec->EnableINP3; + PORT->isRF = PortRec->isRF; PORT->PORTWINDOW = (UCHAR)PortRec->MAXFRAME; @@ -1422,13 +1418,9 @@ BOOL Start() { ROUTE->TCPHost = Rcfg->tcphost; ROUTE->TCPPort = Rcfg->tcpport; -<<<<<<< Updated upstream -||||||| Stash base -======= ROUTE->TCPAddress = (struct addrinfo *)zalloc(sizeof(struct addrinfo)); ROUTE->TCPAddress->ai_addr = (struct sockaddr *) zalloc(sizeof(struct sockaddr)); ->>>>>>> Stashed changes } Rcfg++; @@ -2292,12 +2284,7 @@ VOID TIMERINTERRUPT() Message = (struct _MESSAGE *)Buffer; if(NodeAPISocket) -<<<<<<< Updated upstream - APIL2Trace(Message, 'T'); -||||||| Stash base -======= APIL2Trace(Message, "sent"); ->>>>>>> Stashed changes Message->PORT |= 0x80; // Set TX Bit @@ -2412,12 +2399,7 @@ L2Packet: MQTTKISSRX(Buffer); if(NodeAPISocket &&PORT->PROTOCOL == 0) -<<<<<<< Updated upstream - APIL2Trace(Message, 'R'); -||||||| Stash base -======= APIL2Trace(Message, "rcvd"); ->>>>>>> Stashed changes // Bridge if requested @@ -2788,6 +2770,7 @@ VOID INITIALISEPORTS() { char INITMSG[80]; struct PORTCONTROL * PORT = PORTTABLE; + struct PORTCONTROL * SAVEPORT; while (PORT) { @@ -2795,7 +2778,68 @@ VOID INITIALISEPORTS() WritetoConsoleLocal(INITMSG); PORT->PORTINITCODE(PORT); - PORT = PORT->PORTPOINTER; + SAVEPORT=PORT; + + // See if it is an RF port + + if (PORT->isRF == -1) // Not set + { + // Try to determine if RF + + if (PORT->PORTTYPE == 0) + { + struct KISSINFO * KISS = (struct KISSINFO *)PORT; + NPASYINFO Port; + + if (KISS->FIRSTPORT && KISS->FIRSTPORT != KISS) + { + // Not first port on device + + PORT = (struct PORTCONTROL *)KISS->FIRSTPORT; + } + + Port = KISSInfo[PORT->PORTNUMBER]; + + if (Port) + { + // KISS like + + if (PORT->PORTIPADDR.s_addr || PORT->KISSSLAVE) + { + // KISS over UDP or TCP + + if (PORT->KISSTCP) + PORT->isRF = 1; // Assume TCP is RF (software modem) + else + PORT->isRF = 0; // Assuem UDP is Internet + } + else + PORT->isRF = 1; // Serial port + } + } + else if (PORT->PORTTYPE == 14) // Loopback + PORT->isRF = 0; + + else if (PORT->PORTTYPE == 16) // External + { + if (PORT->PROTOCOL == 10) // 'HF' Port + { + struct TNCINFO * TNC = TNCInfo[PORT->PORTNUMBER]; + + if (TNC && TNC->Hardware == H_TELNET) + PORT->isRF = 0; + else + PORT->isRF = 1; // ARDOP etc + } + else + { + // External but not HF - AXIP, BPQETHER VKISS, ?? + + PORT->isRF = 0; + } + } + } + PORT = SAVEPORT->PORTPOINTER; } } diff --git a/config.c b/config.c index d90ba74..b41e0e8 100644 --- a/config.c +++ b/config.c @@ -379,7 +379,8 @@ static char *pkeywords[] = "BCALL", "DIGIMASK", "NOKEEPALIVES", "COMPORT", "DRIVER", "WL2KREPORT", "UIONLY", "UDPPORT", "IPADDR", "I2CBUS", "I2CDEVICE", "UDPTXPORT", "UDPRXPORT", "NONORMALIZE", "IGNOREUNLOCKEDROUTES", "INP3ONLY", "TCPPORT", "RIGPORT", "PERMITTEDAPPLS", "HIDE", -"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort", "ALLOWINP3", "ENABLEINP3"}; /* parameter keywords */ +"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort", +"ALLOWINP3", "ENABLEINP3", "isRF"}; /* parameter keywords */ static void * poffset[] = { @@ -393,7 +394,8 @@ static void * poffset[] = &xxp.BCALL, &xxp.DIGIMASK, &xxp.DefaultNoKeepAlives, &xxp.IOADDR, &xxp.DLLNAME, &xxp.WL2K, &xxp.UIONLY, &xxp.IOADDR, &xxp.IPADDR, &xxp.INTLEVEL, &xxp.IOADDR, &xxp.IOADDR, &xxp.ListenPort, &xxp.NoNormalize, &xxp.IGNOREUNLOCKED, &xxp.INP3ONLY, &xxp.TCPPORT, &xxp.RIGPORT, &xxp.PERMITTEDAPPLS, &xxp.Hide, -&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq, &xxp.M0LTEMapInfo, &xxp.QtSMPort, &xxp.AllowINP3, &xxp.EnableINP3}; /* offset for corresponding data in config file */ +&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq, &xxp.M0LTEMapInfo, &xxp.QtSMPort, +&xxp.AllowINP3, &xxp.EnableINP3, &xxp.isRF}; /* offset for corresponding data in config file */ static int proutine[] = { @@ -407,7 +409,8 @@ static int proutine[] = 0, 1, 2, 18, 15, 16, 2, 1, 17, 1, 1, 1, 1, 2, 2, 2, 1, 1, 19, 2, -1, 20, 1, 21, 22, 1, 1, 1}; /* routine to process parameter */ +1, 20, 1, 21, 22, 1, +1, 1, 1}; /* routine to process parameter */ int PPARAMLIM = sizeof(proutine)/sizeof(int); @@ -635,13 +638,8 @@ BOOL ProcessConfig() paramok[93]=1; // ONLYVer2point0 paramok[94]=1; // DEBUGINP3 paramok[95]=1; // EnableOARCAPI -<<<<<<< Updated upstream -||||||| Stash base - paramok[93]=1; // C_ONLYVer2point0 -======= paramok[96]=1; // OARCAPI ->>>>>>> Stashed changes for (i=0; i < PARAMLIM; i++) { @@ -1825,6 +1823,7 @@ int ports(int i) } xxp.SendtoM0LTEMap = 1; // Default to enabled + xxp.isRF = -1; // Default to undefined while (endport == 0 && !feof(fp1)) { diff --git a/configstructs.h b/configstructs.h index 013d725..fae9d30 100644 --- a/configstructs.h +++ b/configstructs.h @@ -83,6 +83,7 @@ struct PORTCONFIG int QtSMPort; int AllowINP3; int EnableINP3; + short isRF; }; struct ROUTECONFIG