From 5d125856cd0d9d216f615386c2d187384fb6513c Mon Sep 17 00:00:00 2001 From: Mike Quin Date: Tue, 2 Jul 2024 19:48:28 +0100 Subject: [PATCH 01/12] bpq32.cfg: Set SECURETELNET on Telnet port The SECURETELNET option restricts outbound telnet connections from the node to users who have authenticated. --- debian/bpq32.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/bpq32.cfg b/debian/bpq32.cfg index 458ce81..08d1091 100644 --- a/debian/bpq32.cfg +++ b/debian/bpq32.cfg @@ -34,6 +34,7 @@ PORT LOGGING=1 CMS=1 DisconnectOnClose=1 + SECURETELNET=1 TCPPORT=8010 FBBPORT=8011 HTTPPORT=8008 From d37331205e79e74c511fb308da256fdedffcc83d Mon Sep 17 00:00:00 2001 From: Tom Fanning Date: Wed, 3 Jul 2024 10:02:44 +0100 Subject: [PATCH 02/12] Create secure-by-default.patch --- debian/patches/secure-by-default.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 debian/patches/secure-by-default.patch diff --git a/debian/patches/secure-by-default.patch b/debian/patches/secure-by-default.patch new file mode 100644 index 0000000..e7a3912 --- /dev/null +++ b/debian/patches/secure-by-default.patch @@ -0,0 +1,12 @@ +diff --git a/TelnetV6.c b/TelnetV6.c +index b139fad..4a68108 100644 +--- a/TelnetV6.c ++++ b/TelnetV6.c +@@ -428,6 +428,7 @@ int ProcessLine(char * buf, int Port) + TNC->Hardware = H_TELNET; + TCP->IPV4 = TRUE; + strcpy(TCP->CMSServer, "cms.winlink.org"); ++ TCP->SecureTelnet = 1; + } + + TNC = TNCInfo[Port]; From d122a87dd1598428509fdad64dacf64f1cc1f4dd Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Fri, 5 Jul 2024 08:34:18 +0100 Subject: [PATCH 03/12] New patch to run secure-by-default until upstream patch --- .gitignore | 1 + debian/changelog | 6 ++++++ debian/patches/secure-by-default.patch | 18 ++++++++---------- debian/patches/series | 1 + 4 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..224e7f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.pc/ diff --git a/debian/changelog b/debian/changelog index 6cdcd7d..6cd7c70 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +linbpq (6.0.24.38-2) UNRELEASED; urgency=medium + + * Secure by default patch + + -- Dave Hibberd Fri, 05 Jul 2024 08:34:44 +0100 + linbpq (6.0.24.38-1) unstable; urgency=medium * New Upstream diff --git a/debian/patches/secure-by-default.patch b/debian/patches/secure-by-default.patch index e7a3912..38550cd 100644 --- a/debian/patches/secure-by-default.patch +++ b/debian/patches/secure-by-default.patch @@ -1,12 +1,10 @@ -diff --git a/TelnetV6.c b/TelnetV6.c -index b139fad..4a68108 100644 --- a/TelnetV6.c +++ b/TelnetV6.c -@@ -428,6 +428,7 @@ int ProcessLine(char * buf, int Port) - TNC->Hardware = H_TELNET; - TCP->IPV4 = TRUE; - strcpy(TCP->CMSServer, "cms.winlink.org"); -+ TCP->SecureTelnet = 1; - } - - TNC = TNCInfo[Port]; +@@ -428,6 +428,7 @@ + TNC->Hardware = H_TELNET; + TCP->IPV4 = TRUE; + strcpy(TCP->CMSServer, "cms.winlink.org"); ++ TCP->SecureTelnet = 1; + } + + TNC = TNCInfo[Port]; diff --git a/debian/patches/series b/debian/patches/series index 5d2b07a..6953e90 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1,3 @@ spelling-errors.patch makefile +secure-by-default.patch From 766bbe358d961346b239ffe868d1477567046f41 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sun, 7 Jul 2024 16:06:08 +0100 Subject: [PATCH 04/12] New upstream version 6.0.24.40 --- BBSHTMLConfig.c | 4 + BBSUtilities.c | 39 +- BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - BPQChat.vcproj.NOTTSDESKTOP.John.user | 65 - BPQChat.vcproj.SKIGACER.johnw.user | 65 - BPQMail.aps | Bin 91752 -> 91908 bytes BPQMail.c | 7 + BPQMail.rc | 11 +- BPQMail.sln | 20 + BPQMail.vcproj.NOTTSDESKTOP.John.user | 65 - BPQMail.vcproj.SKIGACER.johnw.user | 65 - BPQMail.vcxproj.user | 4 - BPQMailConfig.c | 2 + BPQMailrc.h | 1 + BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - BPQWinAPP.vcproj.NOTTSDESKTOP.John.user | 65 - Bpq32.c | 3 + CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - ...32.vcproj.NOTTSDESKTOP.John-notpi4-64.user | 65 - CBPQ32.vcproj.NOTTSDESKTOP.John.user | 65 - CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user | 65 - CBPQ32.vcproj.SKIGACER.johnw.user | 65 - ConfigWinRPR.vcxproj.user | 4 - MailNode.vcproj.NOTTSDESKTOP.John.user | 65 - MailNode.vcproj.SKIGACER.johnw.user | 65 - MailNode.vcxproj.user | 8 - MailRouting.c | 1194 +++++++++-------- Versions.h | 4 +- WinRPRHelper.vcproj.NOTTSDESKTOP.John.user | 65 - ...rControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 - WinmorControl.vcproj.NOTTSDESKTOP.John.user | 65 - bpqmail.h | 2 +- templatedefs.c | 16 +- 33 files changed, 699 insertions(+), 1725 deletions(-) delete mode 100644 BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 BPQChat.vcproj.NOTTSDESKTOP.John.user delete mode 100644 BPQChat.vcproj.SKIGACER.johnw.user create mode 100644 BPQMail.sln delete mode 100644 BPQMail.vcproj.NOTTSDESKTOP.John.user delete mode 100644 BPQMail.vcproj.SKIGACER.johnw.user delete mode 100644 BPQMail.vcxproj.user delete mode 100644 BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 BPQWinAPP.vcproj.NOTTSDESKTOP.John.user delete mode 100644 CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 CBPQ32.vcproj.NOTTSDESKTOP.John-notpi4-64.user delete mode 100644 CBPQ32.vcproj.NOTTSDESKTOP.John.user delete mode 100644 CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user delete mode 100644 CBPQ32.vcproj.SKIGACER.johnw.user delete mode 100644 ConfigWinRPR.vcxproj.user delete mode 100644 MailNode.vcproj.NOTTSDESKTOP.John.user delete mode 100644 MailNode.vcproj.SKIGACER.johnw.user delete mode 100644 MailNode.vcxproj.user delete mode 100644 WinRPRHelper.vcproj.NOTTSDESKTOP.John.user delete mode 100644 WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user delete mode 100644 WinmorControl.vcproj.NOTTSDESKTOP.John.user diff --git a/BBSHTMLConfig.c b/BBSHTMLConfig.c index 80f2bca..c37533c 100644 --- a/BBSHTMLConfig.c +++ b/BBSHTMLConfig.c @@ -158,6 +158,7 @@ char MailPage[] = "%s's BBS Web Server" "Welcome Msgs & Prompts" "Housekeeping" "WP Update" + "WebMail" "Node Menu" ""; @@ -178,6 +179,7 @@ char RefreshMainPage[] = "" "Welcome Msgs & Prompts" "Housekeeping" "WP Update" + "WebMail" "Node Menu" ""; @@ -1887,6 +1889,7 @@ VOID SaveFwdCommon(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Re GetCheckBox(input, "WarnNoRoute=", &WarnNoRoute); GetCheckBox(input, "LocalTime=", &Localtime); GetCheckBox(input, "SendPtoMultiple=", &SendPtoMultiple); + GetCheckBox(input, "FourCharCont=", &FOURCHARCONT); // Reinitialise Aliases @@ -2716,6 +2719,7 @@ VOID SendFwdMainPage(char * Reply, int * RLen, char * Key) (WarnNoRoute) ? CHKD : UNC, (Localtime) ? CHKD : UNC, (SendPtoMultiple) ? CHKD : UNC, + (FOURCHARCONT) ? CHKD : UNC, ALIASES); } diff --git a/BBSUtilities.c b/BBSUtilities.c index 6c542ba..d62b3c5 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -213,6 +213,7 @@ BOOL UserCantKillT = FALSE; typedef int (WINAPI FAR *FARPROCX)(); FARPROCX pRunEventProgram; +FARPROCX pGetPortFrequency; int RunEventProgram(char * Program, char * Param); @@ -9680,6 +9681,7 @@ VOID SaveConfig(char * ConfigName) SaveIntValue(group, "WarnNoRoute", WarnNoRoute); SaveIntValue(group, "Localtime", Localtime); SaveIntValue(group, "SendPtoMultiple", SendPtoMultiple); + SaveIntValue(group, "FOURCHARCONT", FOURCHARCONT); SaveMultiStringValue(group, "FWDAliases", AliasText); @@ -10116,6 +10118,8 @@ BOOL GetConfig(char * ConfigName) ReaddressReceived = GetIntValue(group, "ReaddressReceived"); WarnNoRoute = GetIntValue(group, "WarnNoRoute"); SendPtoMultiple = GetIntValue(group, "SendPtoMultiple"); + FOURCHARCONT = GetIntValue(group, "FOURCHARCONT"); + Localtime = GetIntValue(group, "Localtime"); AliasText = GetMultiStringValue(group, "FWDAliases"); GetStringValue(group, "BBSName", BBSName); @@ -10588,8 +10592,24 @@ int Connected(int Stream) if (SendNewUserMessage) { + int64_t LongFreq = Freq; + char * MailBuffer = malloc(100); - Length += sprintf(MailBuffer, "New User %s Connected to Mailbox on Port %d Freq %d Mode %d\r\n", callsign, port, Freq, Mode); + + if (Freq == 0 && port) + { + // Get Port Freq if available + + char FreqString[256]; + +#ifdef WIN32 + if (pGetPortFrequency) + LongFreq = pGetPortFrequency(port, FreqString); +#else + LongFreq = GetPortFrequency(port, FreqString); +#endif + } + Length += sprintf(MailBuffer, "New User %s Connected to Mailbox on Port %d Freq %d Mode %ld\r\n", callsign, port, LongFreq, Mode); sprintf(Title, "New User %s", callsign); @@ -11754,9 +11774,8 @@ typedef struct _POPENRET */ void run_pgTimeoutThread( pid_t process ) { - - printf("watchdog thread: PID of subprocess: %d\n", process); - fflush(stdout); +// printf("watchdog thread: PID of subprocess: %d\n", process); +// fflush(stdout); Sleep(5000); // if still running PID (?) then kill. if ( getpgid(process) >= 0 ) @@ -11768,10 +11787,8 @@ void run_pgTimeoutThread( pid_t process ) Debugprintf("Failed to kill PG watchdog Process %d", process); } - - Debugprintf("watchdog thread: PID=%d Exit", process); - fflush(stdout); - //return; +// Debugprintf("watchdog thread: PID=%d Exit", process); +// fflush(stdout); } @@ -12638,7 +12655,6 @@ VOID ProcessLine(CIRCUIT * conn, struct UserInfo * user, char* Buffer, int len) #endif return; } - if (_memicmp(Cmd, "Node", 4) == 0) { ExpandAndSendMessage(conn, SignoffMsg, LOG_BBS); @@ -15757,8 +15773,10 @@ VOID GetPGConfig() strcat(FN, "PG/PGList.txt"); if ((file = fopen(FN, "r")) == NULL) + { return; - + } + while(fgets(buf, 255, file) != NULL) { if ( buf[0] == '#') @@ -15785,6 +15803,7 @@ VOID GetPGConfig() break; } + NUM_SERVERS = n; fclose(file); diff --git a/BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index 0cd9a72..0000000 --- a/BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQChat.vcproj.NOTTSDESKTOP.John.user b/BPQChat.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/BPQChat.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQChat.vcproj.SKIGACER.johnw.user b/BPQChat.vcproj.SKIGACER.johnw.user deleted file mode 100644 index b5b0536..0000000 --- a/BPQChat.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQMail.aps b/BPQMail.aps index 694b39f7766dad71d538e1d41d602f2a116248da..8e698f3d85c0ee070383c9430a923a9e0fc10b7e 100644 GIT binary patch delta 2016 zcmYk6e{2**6vyA&z3a6=p+LFzuF$(upwQBCzuLRwhp>0IZI|9J?)KVJO0V<>1p>6t zB9ce|!yiOMS|&1(NNFM(Oi(0;fe=*wz=*Mu7|~#YsL?1yMgP#m1mZcfdk{C-o%j8` zH*aR%%@R(=N!%=|=8$gDEGYn)X1xt^=B^hk~5c-3>5B*HJa81$bfVGmzp5ec+v@ zld#&Dh($Q_L*Y}T#u#uqVER)asT??A29mLp#jA>*WeaichM61$(-EmXl5Aqg<%C%} z3Miql(kQD+MCRNDvrm{ULNSt=v>4|QhqY|N>pV-q{3DQa6>V=l1iETsfv(MF|-e0a))c2ZX| zZ%&2oX-+iDVLiGY=9BJ{(s`A+KJk#G%E4wyjYxWc7ZxCqPFoHvtSgw>Gn;-TeQ#ysMS$0981b=N;DK}(;Qx?%Vmyh+6T+H z4yKb*tIP_=C+PRq3(!Y4TIN>!5d!gbeC&j*kKu>q2yAPEQk0!mZ48$K zRv_7b)+(-K`6_mmxL7`RSXb!-E0K6Cp;f}=hUYj-N7%tof>Kha9$1Z}XkxB;4R^AO zz`bmyPL>5EB*#zNg(f6_oV8&y*>AO>Le5y{;@ZqL>qTF^n_WG?me&5=!y~)5?i_&m z4Rww>m#5C{?{v(E>3|i$9{&9?%PscoC1;W^;-ZXIJ!QauGnw{rQ5Zqu-0sU9?fgr? zd*onxBmR`RpZ>*ApomH+)&gv4&h0X>_Y@L)|69UFF>|YbH42AB^4@@%*ak+CTPN@g zxwLgQY2EUxa9PX*w-%u=DU#H-A>nH=^U1bqLqYCucD{_|vy%8g9uWs`3WEkM&v%1= z3VFuN7en2maL!1^N6h5+7iN>rku}2GT)u?xhJB9#uab&=mH2l?-lwp;m^uF1^(mFS zc8#%Ag58P)yHTnVm7}b}tc-3DkS$;uka3$O(>JkaY3APK-8$?b??0|WZ|2*_5fR@c zHQB22E6@w;01esfA-z^mX~%YM8rXl33}qY9lDU#yl24bKFki}p6EFbzP&1Lu9)uJO zLqFKT!`>ilflaVmvj$-&jKEg*?bj^s9fUrnhOc~M!l|uBF$r*C?3m5Cw*ue}E$qTd z9HLIv2#cR5_xF?=ud;|Cx{s6Q&*^vQ6<(I-xUDv z(H)!6h8O5D-dv~euts>rL2qxua^Z-RKH_cIL#Ow!<=mmQJ_9rT0~eZ#m~-U@qyru3H?al7K_-@UVlDl?4-MiC xU6oOxAI;+7PR&Xrv$A7^1ittLXWDEM*&^*$=pVm)kA)ghn=F*?$ac`-1=g delta 1794 zcmYk6X>3$g6vxlGGt*6$Vms5$beYnHwv3&gs5r!V##>#du`<<^UgcJ|NotP z@45HQ%irs6&FIE_1)SVHj# z2R19LTmtU605(`fFX;7~RxcOx3G9G;0lcY@yE_!?;K*)+H7fE*zMvHF$EA>8a63GR z)Xa*H7A(CXh2u+NGZd;c80onGr54buJQ4Fp?-!h4SQb1sXmhnXp-3fBzuV`F`eU(R z#On?UsTGRG4Aabh0RmR3Ux*v{7Fz%+XZHA5Pdr6}}HONGDDkYSsxQloD--K{FrK2DK^*Bz+37 zLmgdHtUp?>;$+m_758_?6|EW8FH*iJDcqG%aSJpo);Q4j)LzBugbgb41|uEm{O6~%S$i1nUdz+tkLd>ZRnvgz!rm)VcT77;`qC+VB_}Em$_t)c5R$#M( zo!%@iFgTVKZzn%&!rlzcG|yN^TKI{X(4&)XHP&D&9Wj>bT?n48N5!B~zgoKu+UVQH zg0hE1os?*EDiRJ#VZYLGUXCBhjdadv#&-Ibv7qQ-#TQBh)>2tB7QhSfJ5>^4O1%8S9 zuNm95{^hhPO4r=9zo_T_!^kixmJ}dv7`dv#x zgkB%WkUk>+GPoJZON5r~c@GJ_wC4nQgV651_sBUSC->zexk%`~{Uc0Ev+G{u{cLAnr?549{whEwqob)GjdW@* zUw48_ldL|C8!^rX(`Y6$*XZqQ7TqZwfR=rkMhBU`#qOrD9IM&NK5VMVTLEzGU!@E$ zby;i{So3pplm~u$LOig(J~UU2@xNI<8vk8U)cb9nT7VHVvKwY>WIyzwR&%Ec+0JTg z)SctK+rn~pqZ#vAy$BUd;(`3x#P;vTa?KqpvSAwytI$3W&TF7@>*|B~u=dh3a(TgWVaI)(|n9HmKsO5`n89=jUdKz>% diff --git a/BPQMail.c b/BPQMail.c index 2ca2985..e528f98 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1133,6 +1133,10 @@ // Fix possible failure to update last listed count when user disconnects without using B command // Add short random delay (<30 secs) when forward new Messages immediately is enabled (35) // Fix Connect Script IDLETIME (38) +// Add "Mail Mgmt" to Webmail menu bar and "WebMail" to Mail Mgmt Menu (39) +// Improve "New User" frequency determination (39) +// Allow selection of 2 or 4 character country codes for forward processing (39) +// Fix Send P to multiple BBS's when routing on HR (40) #include "bpqmail.h" #include "winstdint.h" @@ -1150,6 +1154,7 @@ FARPROCX pDllBPQTRACE; FARPROCZ pGetLOC; FARPROCX pRefreshWebMailIndex; FARPROCX pRunEventProgram; +FARPROCX pGetPortFrequency; BOOL WINE = FALSE; @@ -1924,6 +1929,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) pGetLOC = GetProcAddress(ExtDriver,"_GetLOC@0"); pRefreshWebMailIndex = GetProcAddress(ExtDriver,"_RefreshWebMailIndex@0"); pRunEventProgram = GetProcAddress(ExtDriver,"_RunEventProgram@8"); + pGetPortFrequency = GetProcAddress(ExtDriver,"_GetPortFrequency@8"); + if (pGetLOC) { diff --git a/BPQMail.rc b/BPQMail.rc index 75ae17f..440945c 100644 --- a/BPQMail.rc +++ b/BPQMail.rc @@ -387,16 +387,16 @@ BEGIN CONTROL "Warn if no route for P or T",IDC_WARNNOROUTE,"Button", BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | WS_TABSTOP,5,101,103,8 - LTEXT "Aliases",IDC_STATIC,5,144,57,13 - EDITTEXT IDC_ALIAS,4,162,99,81,ES_MULTILINE | ES_UPPERCASE | + LTEXT "Aliases",IDC_STATIC,5,165,57,13 + EDITTEXT IDC_ALIAS,4,183,99,81,ES_MULTILINE | ES_UPPERCASE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL CONTROL "Readdress Locally Input",IDC_READDRESSLOCAL,"Button", BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | - WS_DISABLED | WS_TABSTOP,4,246,97,8 + WS_DISABLED | WS_TABSTOP,4,267,97,8 CONTROL "Readdress Received",IDC_READDRESSRXED,"Button", BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | - WS_DISABLED | WS_TABSTOP,4,260,97,8 + WS_DISABLED | WS_TABSTOP,4,281,97,8 GROUPBOX "Per-BBS Params",IDC_STATIC,121,33,326,263 LTEXT "BBS",IDC_STATIC,128,46,57,10 COMBOBOX IDC_BBS,122,59,50,60,CBS_SIMPLE | CBS_OEMCONVERT | @@ -471,6 +471,9 @@ BEGIN WS_TABSTOP,5,130,103,8 LTEXT "Incoming Connect Timeout",IDC_STATIC,125,278,95,12 EDITTEXT IDC_CONTIMEOUT,219,276,22,12,ES_AUTOHSCROLL + CONTROL "Use 4 Char Continent Codes",IDC_FOURCHARCONTINENT, + "Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | + WS_TABSTOP,6,146,103,8 END IDD_USERADDED_BOX DIALOG DISCARDABLE 176, 132, 129, 68 diff --git a/BPQMail.sln b/BPQMail.sln new file mode 100644 index 0000000..8861280 --- /dev/null +++ b/BPQMail.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQMail", "BPQMail.vcproj", "{3766AA10-C777-4ED8-A83D-F1452DE9B665}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.ActiveCfg = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.Build.0 = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BPQMail.vcproj.NOTTSDESKTOP.John.user b/BPQMail.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/BPQMail.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQMail.vcproj.SKIGACER.johnw.user b/BPQMail.vcproj.SKIGACER.johnw.user deleted file mode 100644 index b5b0536..0000000 --- a/BPQMail.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQMail.vcxproj.user b/BPQMail.vcxproj.user deleted file mode 100644 index 6e2aec7..0000000 --- a/BPQMail.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/BPQMailConfig.c b/BPQMailConfig.c index 594881a..06aec1d 100644 --- a/BPQMailConfig.c +++ b/BPQMailConfig.c @@ -1867,6 +1867,7 @@ VOID SaveFWDConfig(HWND hDlg) MaxRXSize = GetDlgItemInt(hDlg, IDC_MAXRECV, &OK, FALSE); MaxAge = GetDlgItemInt(hDlg, IDC_MAXAGE, &OK, FALSE); SendPtoMultiple = IsDlgButtonChecked(hDlg, IDC_MULTIP); + FOURCHARCONT = IsDlgButtonChecked(hDlg, IDC_FOURCHARCONTINENT); // Reinitialise Aliases @@ -3249,6 +3250,7 @@ INT_PTR CALLBACK FwdEditDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARA CheckDlgButton(hDlg, IDC_WARNNOROUTE, WarnNoRoute); CheckDlgButton(hDlg, IDC_USELOCALTIME, Localtime); CheckDlgButton(hDlg, IDC_MULTIP, SendPtoMultiple); + CheckDlgButton(hDlg, IDC_FOURCHARCONTINENT, FOURCHARCONT); CurrentBBS = NULL; diff --git a/BPQMailrc.h b/BPQMailrc.h index 750d898..8b29d46 100644 --- a/BPQMailrc.h +++ b/BPQMailrc.h @@ -319,6 +319,7 @@ #define ID_MULTICAST 40024 #define IDC_DEFAULTNOWINLINK 41001 #define IDC_MULTIP 41002 +#define IDC_FOURCHARCONTINENT 41003 // Next default values for new objects // diff --git a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index 0cd9a72..0000000 --- a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/Bpq32.c b/Bpq32.c index d333e5a..7059a56 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1217,6 +1217,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Fix potential buffer overflow in Telnet login (36) // Allow longer serial device names (37) // Fix ICF8101 Mode setting (37) +// Kill link if we are getting repeated RR(F) after timeout +// (Indicating other station is seeing our RR(P) but not the resent I frame) (40) + #define CKernel diff --git a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index ddedde2..0000000 --- a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.NOTTSDESKTOP.John-notpi4-64.user b/CBPQ32.vcproj.NOTTSDESKTOP.John-notpi4-64.user deleted file mode 100644 index f4ba73a..0000000 --- a/CBPQ32.vcproj.NOTTSDESKTOP.John-notpi4-64.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.NOTTSDESKTOP.John.user b/CBPQ32.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index 270b67b..0000000 --- a/CBPQ32.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user b/CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user deleted file mode 100644 index 03fb73a..0000000 --- a/CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.SKIGACER.johnw.user b/CBPQ32.vcproj.SKIGACER.johnw.user deleted file mode 100644 index 03fb73a..0000000 --- a/CBPQ32.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/ConfigWinRPR.vcxproj.user b/ConfigWinRPR.vcxproj.user deleted file mode 100644 index 6e2aec7..0000000 --- a/ConfigWinRPR.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MailNode.vcproj.NOTTSDESKTOP.John.user b/MailNode.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index 34131b7..0000000 --- a/MailNode.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/MailNode.vcproj.SKIGACER.johnw.user b/MailNode.vcproj.SKIGACER.johnw.user deleted file mode 100644 index b5b0536..0000000 --- a/MailNode.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/MailNode.vcxproj.user b/MailNode.vcxproj.user deleted file mode 100644 index 3ea46b0..0000000 --- a/MailNode.vcxproj.user +++ /dev/null @@ -1,8 +0,0 @@ - - - - c:\linbpq\linbpq.exe - c:\linbpq - WindowsLocalDebugger - - \ No newline at end of file diff --git a/MailRouting.c b/MailRouting.c index 6916f2c..ff6feca 100644 --- a/MailRouting.c +++ b/MailRouting.c @@ -29,9 +29,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Bulls should not be distributed outside their designated area. -// Use 4 char continent codes if this isn't defined +// Use 4 char continent codes if this is set -#define TWOCHARCONT +int FOURCHARCONT = 0; #include "bpqmail.h" @@ -71,266 +71,266 @@ struct Country struct Continent Continents[] = { - "EURO", "EU", // Europe - "MEDR", "EU", // Mediterranean - "ASIA", "AS", // The Orient - "INDI", "AS", // Indian Ocean including the Indian subcontinent - "MDLE", "AS", // Middle East - "SEAS", "AS", // South-East Asia - "NOAM", "NA", // North America (Canada, USA, Mexico) - "CEAM", "NA", // Central America - "CARB", "NA", // Caribbean - "SOAM", "SA", // South America - "AUNZ", "OC", // Australia/New Zealand - "EPAC", "OC", // Eastern Pacific - "NPAC", "OC", // Northern Pacific - "SPAC", "OC", // Southern Pacific - "WPAC", "OC", // Western Pacific - "NAFR", "AF", // Northern Africa - "CAFR", "AF", // Central Africa - "SAFR", "AF", // Southern Africa - "ANTR", "OC", // Antarctica - "MARS", "MARS", // Special for MARS network + "EURO", "EU", // Europe + "MEDR", "EU", // Mediterranean + "ASIA", "AS", // The Orient + "INDI", "AS", // Indian Ocean including the Indian subcontinent + "MDLE", "AS", // Middle East + "SEAS", "AS", // South-East Asia + "NOAM", "NA", // North America (Canada, USA, Mexico) + "CEAM", "NA", // Central America + "CARB", "NA", // Caribbean + "SOAM", "SA", // South America + "AUNZ", "OC", // Australia/New Zealand + "EPAC", "OC", // Eastern Pacific + "NPAC", "OC", // Northern Pacific + "SPAC", "OC", // Southern Pacific + "WPAC", "OC", // Western Pacific + "NAFR", "AF", // Northern Africa + "CAFR", "AF", // Central Africa + "SAFR", "AF", // Southern Africa + "ANTR", "OC", // Antarctica + "MARS", "MARS", // Special for MARS network }; struct Country Countries[] = { - "AFG", "****", "AS", // Afghanistan - "ALA", "EURO", "EU", // Åland Islands - "ALB", "EURO", "EU", // Albania - "DZA", "NAFR", "AF", // Algeria - "ASM", "****", "AS", // American Samoa - "AND", "EURO", "EU", // Andorra - "AGO", "CAFR", "AF", // Angola - "AIA", "CARB", "NA", // Anguilla - "ATG", "CARB", "NA", // Antigua and Barbuda - "ARG", "SOAM", "SA", // Argentina - "ARM", "****", "AS", // Armenia - "ABW", "CARB", "NA", // Aruba - "AUS", "AUNZ", "OC", // Australia - "AUT", "EURO", "EU", // Austria - "AZE", "****", "AS", // Azerbaijan - "BHS", "CARB", "NA", // Bahamas - "BHR", "MDLE", "AS", // Bahrain - "BGD", "INDE", "AS", // Bangladesh - "BRB", "CARB", "NA", // Barbados - "BLR", "EURO", "EU", // Belarus - "BEL", "EURO", "EU", // Belgium - "BLZ", "CEAM", "NA", // Belize - "BEN", "CAFR", "AF", // Benin - "BMU", "CARB", "NA", // Bermuda - "BTN", "ASIA", "AS", // Bhutan - "BOL", "SOAM", "SA", // Bolivia (Plurinational State of) - "BIH", "EURO", "EU", // Bosnia and Herzegovina - "BWA", "****", "AF", // Botswana - "BRA", "SOAM", "SA", // Brazil - "VGB", "CARB", "NA", // British Virgin Islands - "BRN", "ASIA", "AS", // Brunei Darussalam - "BGR", "EURO", "EU", // Bulgaria - "BFA", "CAFR", "AF", // Burkina Faso - "BDI", "CAFR", "AF", // Burundi - "KHM", "****", "AS", // Cambodia - "CMR", "CAFR", "AF", // Cameroon - "CAN", "NOAM", "NA", // Canada - "CPV", "NAFR", "AF", // Cape Verde - "CYM", "CARB", "NA", // Cayman Islands - "CAF", "CAFR", "AF", // Central African Republic - "TCD", "CAFR", "AF", // Chad - "CHL", "SOAM", "SA", // Chile - "CHN", "****", "AS", // China - "HKG", "****", "AS", // Hong Kong Special Administrative Region of China - "MAC", "****", "AS", // Macao Special Administrative Region of China - "COL", "****", "SA", // Colombia - "COM", "SAFR", "AF", // Comoros - "COG", "****", "AF", // Congo - "COK", "SPAC", "OC", // Cook Islands - "CRI", "CEAM", "NA", // Costa Rica - "CIV", "CAFR", "AF", // Côte d'Ivoire - "HRV", "EURO", "EU", // Croatia - "CUB", "CARB", "NA", // Cuba - "CYP", "EURO", "EU", // Cyprus - "CZE", "EURO", "EU", // Czech Republic - "PRK", "****", "AS", // Democratic People's Republic of Korea - "COD", "****", "AF", // Democratic Republic of the Congo - "DNK", "EURO", "EU", // Denmark - "DJI", "NAFR", "AF", // Djibouti - "DMA", "CARB", "NA", // Dominica - "DOM", "CARB", "NA", // Dominican Republic - "ECU", "SOAM", "SA", // Ecuador - "EGY", "MDLE", "AF", // Egypt - "SLV", "CEAM", "NA", // El Salvador - "GNQ", "CAFR", "AF", // Equatorial Guinea - "ERI", "****", "AF", // Eritrea - "EST", "EURO", "EU", // Estonia - "ETH", "****", "AF", // Ethiopia - "FRO", "EURO", "EU", // Faeroe Islands - "FLK", "SOAM", "SA", // Falkland Islands (Malvinas) - "FJI", "SPAC", "OC", // Fiji - "FIN", "EURO", "EU", // Finland - "FRA", "EURO", "EU", // France - "GUF", "SOAM", "SA", // French Guiana - "PYF", "SPAC", "OC", // French Polynesia - "GAB", "CAFR", "AF", // Gabon - "GMB", "CAFR", "AF", // Gambia - "GEO", "ASIA", "AS", // Georgia - "DEU", "EURO", "EU", // Germany - "GHA", "CAFR", "AF", // Ghana - "GIB", "EURO", "EU", // Gibraltar - "GRC", "EURO", "EU", // Greece - "GRL", "EURO", "EU", // Greenland - "GRD", "CARB", "NA", // Grenada - "GLP", "CARB", "NA", // Guadeloupe - "GUM", "SPAC", "OC", // Guam - "GTM", "CEAM", "NA", // Guatemala - "GGY", "EURO", "EU", // Guernsey - "GIN", "CAFR", "AF", // Guinea - "GNB", "CAFR", "AF", // Guinea-Bissau - "GUY", "SOAM", "SA", // Guyana - "HTI", "CARB", "NA", // Haiti - "VAT", "EURO", "EU", // Holy See - "HND", "CEAM", "NA", // Honduras - "HUN", "EURO", "EU", // Hungary - "ISL", "EURO", "EU", // Iceland - "IND", "INDI", "AS", // India - "IDN", "****", "AS", // Indonesia - "IRN", "MDLE", "AS", // Iran (Islamic Republic of) - "IRQ", "MDLE", "AS", // Iraq - "IRL", "EURO", "EU", // Ireland - "IMN", "EURO", "EU", // Isle of Man - "ISR", "MDLE", "AS", // Israel - "ITA", "EURO", "EU", // Italy - "JAM", "CEAM", "NA", // Jamaica - "JPN", "****", "AS", // Japan - "JEY", "EURO", "EU", // Jersey - "JOR", "MDLE", "AS", // Jordan - "KAZ", "****", "AS", // Kazakhstan - "KEN", "****", "AF", // Kenya - "KIR", "EPAC", "OC", // Kiribati - "KWT", "MDLE", "AS", // Kuwait - "KGZ", "ASIA", "AS", // Kyrgyzstan - "LAO", "ASIA", "AS", // Lao People's Democratic Republic - "LVA", "EURO", "EU", // Latvia - "LBN", "MDLE", "AS", // Lebanon - "LSO", "SAFR", "AF", // Lesotho - "LBR", "CAFR", "AF", // Liberia - "LBY", "MDLE", "AS", // Libyan Arab Jamahiriya - "LIE", "EURO", "EU", // Liechtenstein - "LTU", "EURO", "EU", // Lithuania - "LUX", "EURO", "EU", // Luxembourg - "MDG", "SAFR", "AF", // Madagascar - "MWI", "SAFR", "AF", // Malawi - "MYS", "ASIA", "AS", // Malaysia - "MDV", "INDI", "AS", // Maldives - "MLI", "CAFR", "AF", // Mali - "MLT", "EURO", "EU", // Malta - "MHL", "WPAC", "OC", // Marshall Islands - "MTQ", "CARB", "NA", // Martinique - "MRT", "NAFR", "AF", // Mauritania - "MUS", "SAFR", "AF", // Mauritius - "MYT", "SAFR", "AF", // Mayotte - "MEX", "****", "NA", // Mexico - "FSM", "WPAC", "OC", // Micronesia (Federated States of) - "MCO", "EURO", "EU", // Monaco - "MNG", "****", "AS", // Mongolia - "MNE", "EURO", "EU", // Montenegro - "MSR", "CARB", "NA", // Montserrat - "MAR", "NAFR", "AF", // Morocco - "MOZ", "SAFR", "AF", // Mozambique - "MMR", "ASIA", "AS", // Myanmar - "NAM", "****", "AF", // Namibia - "NRU", "WPAC", "OC", // Nauru - "NPL", "****", "AS", // Nepal - "NLD", "EURO", "EU", // Netherlands - "ANT", "CARB", "NA", // Netherlands Antilles - "NCL", "SPAC", "OC", // New Caledonia - "NZL", "AUNZ", "OC", // New Zealand - "NIC", "****", "SA", // Nicaragua - "NER", "NAFR", "AF", // Niger - "NGA", "****", "AF", // Nigeria - "NIU", "SPAC", "OC", // Niue - "NFK", "SPAC", "OC", // Norfolk Island - "MNP", "WPAC", "OC", // Northern Mariana Islands - "NOR", "EURO", "EU", // Norway - "PSE", "MDLE", "AS", // Occupied Palestinian Territory - "OMN", "MDLE", "AS", // Oman - "PAK", "INDI", "AS", // Pakistan - "PLW", "SPAC", "OC", // Palau - "PAN", "CEAM", "SA", // Panama - "PNG", "SPAC", "OC", // Papua New Guinea - "PRY", "SOAM", "SA", // Paraguay - "PER", "SOAM", "SA", // Peru - "PHL", "ASIA", "AS", // Philippines - "PCN", "SPAC", "OC", // Pitcairn - "POL", "EURO", "EU", // Poland - "PRT", "EURO", "EU", // Portugal - "PRI", "CARB", "NA", // Puerto Rico - "QAT", "MDLE", "AS", // Qatar - "KOR", "ASIA", "AS", // Republic of Korea - "MDA", "EURO", "EU", // Republic of Moldova - "REU", "SAFR", "AF", // Réunion - "ROU", "EURO", "EU", // Romania - "RUS", "ASIA", "AS", // Russian Federation - "RWA", "****", "AF", // Rwanda - "BLM", "CARB", "NA", // Saint-Barthélemy - "SHN", "SOAM", "SA", // Saint Helena - "KNA", "CARB", "NA", // Saint Kitts and Nevis - "LCA", "CARB", "NA", // Saint Lucia - "MAF", "CARB", "NA", // Saint-Martin (French part) - "SPM", "NOAM", "NA", // Saint Pierre and Miquelon - "VCT", "CARB", "NA", // Saint Vincent and the Grenadines - "WSM", "SPAC", "OC", // Samoa - "SMR", "EURO", "EU", // San Marino - "STP", "CAFR", "AF", // Sao Tome and Principe - "SAU", "MDLE", "AS", // Saudi Arabia - "SEN", "CAFR", "AF", // Senegal - "SRB", "EURO", "EU", // Serbia - "SYC", "SAFR", "AF", // Seychelles - "SLE", "****", "AF", // Sierra Leone - "SGP", "****", "AS", // Singapore - "SVK", "EURO", "EU", // Slovakia - "SVN", "EURO", "EU", // Slovenia - "SLB", "SPAC", "OC", // Solomon Islands - "SOM", "****", "AF", // Somalia - "ZAF", "SAFR", "AF", // South Africa - "ESP", "EURO", "EU", // Spain - "LKA", "INDE", "AS", // Sri Lanka - "SDN", "****", "AF", // Sudan - "SUR", "SOAM", "SA", // Suriname - "SJM", "EURO", "EU", // Svalbard and Jan Mayen Islands - "SWZ", "****", "AF", // Swaziland - "SWE", "EURO", "EU", // Sweden - "CHE", "EURO", "EU", // Switzerland - "SYR", "MDLE", "AS", // Syrian Arab Republic - "TJK", "ASIA", "AS", // Tajikistan - "THA", "****", "AS", // Thailand - "MKD", "EURO", "EU", // The former Yugoslav Republic of Macedonia - "TLS", "ASIA", "AS", // Timor-Leste - "TGO", "CAFR", "AF", // Togo - "TKL", "AUNZ", "OC", // Tokelau - "TON", "SPAC", "OC", // Tonga - "TTO", "CARB", "NA", // Trinidad and Tobago - "TUN", "****", "AF", // Tunisia - "TUR", "EURO", "EU", // Turkey - "TKM", "****", "AS", // Turkmenistan - "TCA", "CARB", "NA", // Turks and Caicos Islands - "TUV", "SPAC", "OC", // Tuvalu - "UGA", "****", "AF", // Uganda - "UKR", "EURO", "EU", // Ukraine - "ARE", "MDLE", "AS", // United Arab Emirates - "GBR", "EURO", "EU", // United Kingdom of Great Britain and Northern Ireland - "TZA", "****", "AF", // United Republic of Tanzania - "USA", "NOAM", "NA", // United States of America - "VIR", "CARB", "NA", // United States Virgin Islands - "URY", "SOAM", "SA", // Uruguay - "UZB", "ASIA", "AS", // Uzbekistan - "VUT", "SPAC", "OC", // Vanuatu - "VEN", "SOAM", "SA", // Venezuela (Bolivarian Republic of) - "VNM", "****", "AS", // Viet Nam - "WLF", "SPAC", "OC", // Wallis and Futuna Islands - "ESH", "****", "AF", // Western Sahara - "YEM", "****", "AF", // Yemen - "ZMB", "SAFR", "AF", // Zambia - "ZWE", "SAFR", "AF" // Zimbabwe + "AFG", "ASIA", "AS", // Afghanistan + "ALA", "EURO", "EU", // Åland Islands + "ALB", "EURO", "EU", // Albania + "DZA", "NAFR", "AF", // Algeria + "ASM", "ASIA", "AS", // American Samoa + "AND", "EURO", "EU", // Andorra + "AGO", "CAFR", "AF", // Angola + "AIA", "CARB", "NA", // Anguilla + "ATG", "CARB", "NA", // Antigua and Barbuda + "ARG", "SOAM", "SA", // Argentina + "ARM", "ASIA", "AS", // Armenia + "ABW", "CARB", "NA", // Aruba + "AUS", "AUNZ", "OC", // Australia + "AUT", "EURO", "EU", // Austria + "AZE", "ASIA", "AS", // Azerbaijan + "BHS", "CARB", "NA", // Bahamas + "BHR", "MDLE", "AS", // Bahrain + "BGD", "INDE", "AS", // Bangladesh + "BRB", "CARB", "NA", // Barbados + "BLR", "EURO", "EU", // Belarus + "BEL", "EURO", "EU", // Belgium + "BLZ", "CEAM", "NA", // Belize + "BEN", "CAFR", "AF", // Benin + "BMU", "CARB", "NA", // Bermuda + "BTN", "ASIA", "AS", // Bhutan + "BOL", "SOAM", "SA", // Bolivia (Plurinational State of) + "BIH", "EURO", "EU", // Bosnia and Herzegovina + "BWA", "SAFR", "AF", // Botswana + "BRA", "SOAM", "SA", // Brazil + "VGB", "CARB", "NA", // British Virgin Islands + "BRN", "ASIA", "AS", // Brunei Darussalam + "BGR", "EURO", "EU", // Bulgaria + "BFA", "CAFR", "AF", // Burkina Faso + "BDI", "CAFR", "AF", // Burundi + "KHM", "ASIA", "AS", // Cambodia + "CMR", "CAFR", "AF", // Cameroon + "CAN", "NOAM", "NA", // Canada + "CPV", "NAFR", "AF", // Cape Verde + "CYM", "CARB", "NA", // Cayman Islands + "CAF", "CAFR", "AF", // Central African Republic + "TCD", "CAFR", "AF", // Chad + "CHL", "SOAM", "SA", // Chile + "CHN", "ASIA", "AS", // China + "HKG", "ASIA", "AS", // Hong Kong Special Administrative Region of China + "MAC", "ASIA", "AS", // Macao Special Administrative Region of China + "COL", "ASIA", "SA", // Colombia + "COM", "SAFR", "AF", // Comoros + "COG", "CAFR", "AF", // Congo + "COK", "SPAC", "OC", // Cook Islands + "CRI", "CEAM", "NA", // Costa Rica + "CIV", "CAFR", "AF", // Côte d'Ivoire + "HRV", "EURO", "EU", // Croatia + "CUB", "CARB", "NA", // Cuba + "CYP", "EURO", "EU", // Cyprus + "CZE", "EURO", "EU", // Czech Republic + "PRK", "ASIA", "AS", // Democratic People's Republic of Korea + "COD", "CAFR", "AF", // Democratic Republic of the Congo + "DNK", "EURO", "EU", // Denmark + "DJI", "NAFR", "AF", // Djibouti + "DMA", "CARB", "NA", // Dominica + "DOM", "CARB", "NA", // Dominican Republic + "ECU", "SOAM", "SA", // Ecuador + "EGY", "MDLE", "AF", // Egypt + "SLV", "CEAM", "NA", // El Salvador + "GNQ", "CAFR", "AF", // Equatorial Guinea + "ERI", "NAFR", "AF", // Eritrea + "EST", "EURO", "EU", // Estonia + "ETH", "NAFR", "AF", // Ethiopia + "FRO", "EURO", "EU", // Faeroe Islands + "FLK", "SOAM", "SA", // Falkland Islands (Malvinas) + "FJI", "SPAC", "OC", // Fiji + "FIN", "EURO", "EU", // Finland + "FRA", "EURO", "EU", // France + "GUF", "SOAM", "SA", // French Guiana + "PYF", "SPAC", "OC", // French Polynesia + "GAB", "CAFR", "AF", // Gabon + "GMB", "CAFR", "AF", // Gambia + "GEO", "ASIA", "AS", // Georgia + "DEU", "EURO", "EU", // Germany + "GHA", "CAFR", "AF", // Ghana + "GIB", "EURO", "EU", // Gibraltar + "GRC", "EURO", "EU", // Greece + "GRL", "EURO", "EU", // Greenland + "GRD", "CARB", "NA", // Grenada + "GLP", "CARB", "NA", // Guadeloupe + "GUM", "SPAC", "OC", // Guam + "GTM", "CEAM", "NA", // Guatemala + "GGY", "EURO", "EU", // Guernsey + "GIN", "CAFR", "AF", // Guinea + "GNB", "CAFR", "AF", // Guinea-Bissau + "GUY", "SOAM", "SA", // Guyana + "HTI", "CARB", "NA", // Haiti + "VAT", "EURO", "EU", // Holy See + "HND", "CEAM", "NA", // Honduras + "HUN", "EURO", "EU", // Hungary + "ISL", "EURO", "EU", // Iceland + "IND", "INDI", "AS", // India + "IDN", "ASIA", "AS", // Indonesia + "IRN", "MDLE", "AS", // Iran (Islamic Republic of) + "IRQ", "MDLE", "AS", // Iraq + "IRL", "EURO", "EU", // Ireland + "IMN", "EURO", "EU", // Isle of Man + "ISR", "MDLE", "AS", // Israel + "ITA", "EURO", "EU", // Italy + "JAM", "CEAM", "NA", // Jamaica + "JPN", "ASIA", "AS", // Japan + "JEY", "EURO", "EU", // Jersey + "JOR", "MDLE", "AS", // Jordan + "KAZ", "ASIA", "AS", // Kazakhstan + "KEN", "CAFR", "AF", // Kenya + "KIR", "EPAC", "OC", // Kiribati + "KWT", "MDLE", "AS", // Kuwait + "KGZ", "ASIA", "AS", // Kyrgyzstan + "LAO", "ASIA", "AS", // Lao People's Democratic Republic + "LVA", "EURO", "EU", // Latvia + "LBN", "MDLE", "AS", // Lebanon + "LSO", "SAFR", "AF", // Lesotho + "LBR", "CAFR", "AF", // Liberia + "LBY", "MDLE", "AS", // Libyan Arab Jamahiriya + "LIE", "EURO", "EU", // Liechtenstein + "LTU", "EURO", "EU", // Lithuania + "LUX", "EURO", "EU", // Luxembourg + "MDG", "SAFR", "AF", // Madagascar + "MWI", "SAFR", "AF", // Malawi + "MYS", "ASIA", "AS", // Malaysia + "MDV", "INDI", "AS", // Maldives + "MLI", "CAFR", "AF", // Mali + "MLT", "EURO", "EU", // Malta + "MHL", "WPAC", "OC", // Marshall Islands + "MTQ", "CARB", "NA", // Martinique + "MRT", "NAFR", "AF", // Mauritania + "MUS", "SAFR", "AF", // Mauritius + "MYT", "SAFR", "AF", // Mayotte + "MEX", "NOAM", "NA", // Mexico + "FSM", "WPAC", "OC", // Micronesia (Federated States of) + "MCO", "EURO", "EU", // Monaco + "MNG", "ASIA", "AS", // Mongolia + "MNE", "EURO", "EU", // Montenegro + "MSR", "CARB", "NA", // Montserrat + "MAR", "NAFR", "AF", // Morocco + "MOZ", "SAFR", "AF", // Mozambique + "MMR", "ASIA", "AS", // Myanmar + "NAM", "SAFR", "AF", // Namibia + "NRU", "WPAC", "OC", // Nauru + "NPL", "ASIA", "AS", // Nepal + "NLD", "EURO", "EU", // Netherlands + "ANT", "CARB", "NA", // Netherlands Antilles + "NCL", "SPAC", "OC", // New Caledonia + "NZL", "AUNZ", "OC", // New Zealand + "NIC", "CEAM", "SA", // Nicaragua + "NER", "NAFR", "AF", // Niger + "NGA", "CAFR", "AF", // Nigeria + "NIU", "SPAC", "OC", // Niue + "NFK", "SPAC", "OC", // Norfolk Island + "MNP", "WPAC", "OC", // Northern Mariana Islands + "NOR", "EURO", "EU", // Norway + "PSE", "MDLE", "AS", // Occupied Palestinian Territory + "OMN", "MDLE", "AS", // Oman + "PAK", "INDI", "AS", // Pakistan + "PLW", "SPAC", "OC", // Palau + "PAN", "CEAM", "SA", // Panama + "PNG", "SPAC", "OC", // Papua New Guinea + "PRY", "SOAM", "SA", // Paraguay + "PER", "SOAM", "SA", // Peru + "PHL", "ASIA", "AS", // Philippines + "PCN", "SPAC", "OC", // Pitcairn + "POL", "EURO", "EU", // Poland + "PRT", "EURO", "EU", // Portugal + "PRI", "CARB", "NA", // Puerto Rico + "QAT", "MDLE", "AS", // Qatar + "KOR", "ASIA", "AS", // Republic of Korea + "MDA", "EURO", "EU", // Republic of Moldova + "REU", "SAFR", "AF", // Réunion + "ROU", "EURO", "EU", // Romania + "RUS", "ASIA", "AS", // Russian Federation + "RWA", "CAFR", "AF", // Rwanda + "BLM", "CARB", "NA", // Saint-Barthélemy + "SHN", "SOAM", "SA", // Saint Helena + "KNA", "CARB", "NA", // Saint Kitts and Nevis + "LCA", "CARB", "NA", // Saint Lucia + "MAF", "CARB", "NA", // Saint-Martin (French part) + "SPM", "NOAM", "NA", // Saint Pierre and Miquelon + "VCT", "CARB", "NA", // Saint Vincent and the Grenadines + "WSM", "SPAC", "OC", // Samoa + "SMR", "EURO", "EU", // San Marino + "STP", "CAFR", "AF", // Sao Tome and Principe + "SAU", "MDLE", "AS", // Saudi Arabia + "SEN", "CAFR", "AF", // Senegal + "SRB", "EURO", "EU", // Serbia + "SYC", "SAFR", "AF", // Seychelles + "SLE", "NAFR", "AF", // Sierra Leone + "SGP", "ASIA", "AS", // Singapore + "SVK", "EURO", "EU", // Slovakia + "SVN", "EURO", "EU", // Slovenia + "SLB", "SPAC", "OC", // Solomon Islands + "SOM", "NAFR", "AF", // Somalia + "ZAF", "SAFR", "AF", // South Africa + "ESP", "EURO", "EU", // Spain + "LKA", "INDE", "AS", // Sri Lanka + "SDN", "NAFR", "AF", // Sudan + "SUR", "SOAM", "SA", // Suriname + "SJM", "EURO", "EU", // Svalbard and Jan Mayen Islands + "SWZ", "SAFR", "AF", // Swaziland + "SWE", "EURO", "EU", // Sweden + "CHE", "EURO", "EU", // Switzerland + "SYR", "MDLE", "AS", // Syrian Arab Republic + "TJK", "ASIA", "AS", // Tajikistan + "THA", "ASIA", "AS", // Thailand + "MKD", "EURO", "EU", // The former Yugoslav Republic of Macedonia + "TLS", "ASIA", "AS", // Timor-Leste + "TGO", "CAFR", "AF", // Togo + "TKL", "AUNZ", "OC", // Tokelau + "TON", "SPAC", "OC", // Tonga + "TTO", "CARB", "NA", // Trinidad and Tobago + "TUN", "NAFR", "AF", // Tunisia + "TUR", "EURO", "EU", // Turkey + "TKM", "ASIA", "AS", // Turkmenistan + "TCA", "CARB", "NA", // Turks and Caicos Islands + "TUV", "SPAC", "OC", // Tuvalu + "UGA", "SAFR", "AF", // Uganda + "UKR", "EURO", "EU", // Ukraine + "ARE", "MDLE", "AS", // United Arab Emirates + "GBR", "EURO", "EU", // United Kingdom of Great Britain and Northern Ireland + "TZA", "SAFR", "AF", // United Republic of Tanzania + "USA", "NOAM", "NA", // United States of America + "VIR", "CARB", "NA", // United States Virgin Islands + "URY", "SOAM", "SA", // Uruguay + "UZB", "ASIA", "AS", // Uzbekistan + "VUT", "SPAC", "OC", // Vanuatu + "VEN", "SOAM", "SA", // Venezuela (Bolivarian Republic of) + "VNM", "ASIA", "AS", // Viet Nam + "WLF", "SPAC", "OC", // Wallis and Futuna Islands + "ESH", "CAFR", "AF", // Western Sahara + "YEM", "NAFR", "AF", // Yemen + "ZMB", "SAFR", "AF", // Zambia + "ZWE", "SAFR", "AF" // Zimbabwe }; char ** AliasText; struct ALIAS ** Aliases; @@ -339,9 +339,9 @@ struct ALIAS ** NTSAliases = NULL; /*struct ALIAS Aliases[] = { - "AMSAT", "WW", - "USBBS", "USA", - "ALLUS", "USA"}; +"AMSAT", "WW", +"USBBS", "USA", +"ALLUS", "USA"}; */ int NumberofContinents = sizeof(Continents)/sizeof(Continents[1]); @@ -355,7 +355,7 @@ struct Continent * FindContinent(char * Name) for(i=0; i< NumberofContinents; i++) { Cont = &Continents[i]; - + if ((_stricmp(Name, Cont->FourCharCode) == 0) || (_stricmp(Name, Cont->TwoCharCode) == 0)) return Cont; } @@ -371,7 +371,7 @@ struct Country * FindCountry(char * Name) for(i=0; i< NumberofCountries; i++) { Cont = &Countries[i]; - + if (_stricmp(Name, Cont->Country) == 0) return Cont; } @@ -389,7 +389,7 @@ struct ALIAS * FindAlias(char * Name) { if (_stricmp(Name, Alias[0]->Dest) == 0) return Alias[0]; - + Alias++; } @@ -403,7 +403,7 @@ VOID SetupMyHA() struct Continent * Continent; strcpy(MyRouteElements, HRoute); - + // Split it up ptr2 = MyRouteElements + strlen(MyRouteElements) - 1; @@ -418,7 +418,7 @@ VOID SetupMyHA() if (ptr2 == MyRouteElements) { // End - + MyElements[Elements++] = _strdup(ptr2); break; } @@ -435,29 +435,32 @@ VOID SetupMyHA() if (MyElements[1]) { -#ifdef TWOCHARCONT - if (strlen(MyElements[1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(MyElements[1]); - if (Continent) + if (strlen(MyElements[1]) == 4) { - free(MyElements[1]); - MyElements[1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(MyElements[1]); + if (Continent) + { + free(MyElements[1]); + MyElements[1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(MyElements[1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(MyElements[1]); - if (Continent) + if (strlen(MyElements[1]) == 2) { - free(MyElements[1]); - MyElements[1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(MyElements[1]); + if (Continent) + { + free(MyElements[1]); + MyElements[1] = _strdup(Continent->FourCharCode); + } } } -#endif } } @@ -556,7 +559,7 @@ VOID SetupHAElements(struct BBSForwardingInfo * ForwardingInfo) do { ForwardingInfo->BBSHAElements = realloc(ForwardingInfo->BBSHAElements, (Elements+2) * sizeof(void *)); - + while ((*ptr2 != '.') && (ptr2 > SaveHText)) { ptr2 --; @@ -565,13 +568,13 @@ VOID SetupHAElements(struct BBSForwardingInfo * ForwardingInfo) if (ptr2 == SaveHText) { // End - + ForwardingInfo->BBSHAElements[Elements++] = _strdup(ptr2); break; } - ForwardingInfo->BBSHAElements[Elements++] = _strdup(ptr2+1); - *ptr2 = 0; + ForwardingInfo->BBSHAElements[Elements++] = _strdup(ptr2+1); + *ptr2 = 0; } while(TRUE); @@ -579,30 +582,32 @@ VOID SetupHAElements(struct BBSForwardingInfo * ForwardingInfo) if (ForwardingInfo->BBSHAElements[1]) { -#ifdef TWOCHARCONT - if (strlen(ForwardingInfo->BBSHAElements[1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); - if (Continent) + if (strlen(ForwardingInfo->BBSHAElements[1]) == 4) { - free(ForwardingInfo->BBSHAElements[1]); - ForwardingInfo->BBSHAElements[1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); + if (Continent) + { + free(ForwardingInfo->BBSHAElements[1]); + ForwardingInfo->BBSHAElements[1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(ForwardingInfo->BBSHAElements[1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); - if (Continent) + if (strlen(ForwardingInfo->BBSHAElements[1]) == 2) { - free(ForwardingInfo->BBSHAElements[1]); - ForwardingInfo->BBSHAElements[1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); + if (Continent) + { + free(ForwardingInfo->BBSHAElements[1]); + ForwardingInfo->BBSHAElements[1] = _strdup(Continent->FourCharCode); + } } } -#endif - } free(SaveHText); @@ -614,7 +619,7 @@ VOID SetupHAddreses(struct BBSForwardingInfo * ForwardingInfo) int Count=0; char ** HText = ForwardingInfo->Haddresses; char * SaveHText, * ptr2; -// char * TopElement; + // char * TopElement; char * Num; struct Continent * Continent; @@ -626,7 +631,7 @@ VOID SetupHAddreses(struct BBSForwardingInfo * ForwardingInfo) int Elements = 1; ForwardingInfo->HADDRS = realloc(ForwardingInfo->HADDRS, (Count+2) * sizeof(void *)); ForwardingInfo->HADDROffet = realloc(ForwardingInfo->HADDROffet, (Count+2) * sizeof(void *)); - + ForwardingInfo->HADDRS[Count] = zalloc(8); // Always at lesat WWW and NULL SaveHText = _strdup(HText[0]); @@ -671,53 +676,56 @@ VOID SetupHAddreses(struct BBSForwardingInfo * ForwardingInfo) // Far simpler to config it, but can users cope?? // Will config for testing. HA, N -/* + /* TopElement=ForwardingInfo->HADDRS[Count][0]; if (strcmp(TopElement, MyElements[0]) == 0) - goto FullHR; + goto FullHR; if (FindContinent(TopElement)) - goto FullHR; - + goto FullHR; + // Need to add stuff from our HR Elements--; if (Elements < MyElementCount) - break; + break; -FullHR: -*/ + FullHR: + */ ForwardingInfo->HADDROffet[Count] = (Num)? atoi(Num): 0; if (ForwardingInfo->HADDRS[Count][1]) { -#ifdef TWOCHARCONT - if (strlen(ForwardingInfo->HADDRS[Count][1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); - if (Continent) - { - free(ForwardingInfo->HADDRS[Count][1]); - ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->TwoCharCode); - } - } -#else - if (strlen(ForwardingInfo->HADDRS[Count][1]) == 2) - { - // Convert to 4 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); - if (Continent) - { - free(ForwardingInfo->HADDRS[Count][1]); - ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->FourCharCode); - } - } -#endif + if (strlen(ForwardingInfo->HADDRS[Count][1]) == 4) + { + // Convert to 2 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRS[Count][1]); + ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->TwoCharCode); + } + } + } + else + { + if (strlen(ForwardingInfo->HADDRS[Count][1]) == 2) + { + // Convert to 4 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRS[Count][1]); + ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->FourCharCode); + } + } + } } free(SaveHText); HText++; @@ -732,7 +740,7 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) int Count=0; char ** HText = ForwardingInfo->HaddressesP; char * SaveHText, * ptr2; -// char * TopElement; + // char * TopElement; char * Num; struct Continent * Continent; @@ -742,7 +750,7 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) { int Elements = 1; ForwardingInfo->HADDRSP = realloc(ForwardingInfo->HADDRSP, (Count+2) * sizeof(void *)); - + ForwardingInfo->HADDRSP[Count] = zalloc(2 * sizeof(void *)); // Always at lesat WWW and NULL SaveHText = _strdup(HText[0]); @@ -781,29 +789,33 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) if (ForwardingInfo->HADDRSP[Count][1]) { -#ifdef TWOCHARCONT - if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); - if (Continent) + + if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 4) { - free(ForwardingInfo->HADDRSP[Count][1]); - ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRSP[Count][1]); + ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); - if (Continent) + if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 2) { - free(ForwardingInfo->HADDRSP[Count][1]); - ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRSP[Count][1]); + ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->FourCharCode); + } } } -#endif } free(SaveHText); HText++; @@ -816,7 +828,7 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) VOID CheckAndSend(struct MsgInfo * Msg, CIRCUIT * conn, struct UserInfo * bbs) { struct BBSForwardingInfo * ForwardingInfo = bbs->ForwardingInfo; - + if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Don't forward to ourself - already here! (unless ForwardToMe set) { if ((conn == NULL) || (!(conn->BBSFlags & BBS) || (_stricmp(conn->UserPointer->Call, bbs->Call) != 0))) // Dont send back @@ -841,9 +853,9 @@ VOID CheckAndSend(struct MsgInfo * Msg, CIRCUIT * conn, struct UserInfo * bbs) { CheckAndSend(Msg, conn, user); } - + Logprintf(LOG_BBS, conn, '?', "Message matches this BBS and RMS Redirect set - fwd to RMS"); - + } else Logprintf(LOG_BBS, conn, '?', "Message matches this BBS and ForwardToMe not set - not queuing message"); @@ -857,7 +869,7 @@ VOID UpdateB2Dest(struct MsgInfo * Msg, char * Alias) FILE * hFile; char * MsgBytes; struct stat STAT; - + sprintf_s(MsgFile, sizeof(MsgFile), "%s/m_%06d.mes", MailDir, Msg->number); if (stat(MsgFile, &STAT) == -1) @@ -1032,7 +1044,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (strlen(toCall) > 6) toCall[6] = 0; - + strcpy(Msg->to, toCall); strcpy(Msg->via, via); Logprintf(LOG_BBS, conn, '?', "Routing Trace at %s is for us. Leave Here", AMPRDomain); @@ -1048,7 +1060,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (bbs) { // We have bbs AMPR - + if (_stricmp(Msg->to, "RMS") == 0 || Msg->to[0] == 0) { // Was set to go via RMS or ISP - change it @@ -1057,7 +1069,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) } Logprintf(LOG_BBS, conn, '?', "Routing Trace to ampr.org Matches BBS AMPR"); - + set_fwd_bit(Msg->fbbs, bbs->BBSNumber); bbs->ForwardingInfo->MsgCount++; if (bbs->ForwardingInfo->SendNew) @@ -1070,12 +1082,12 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) } } -// See if sending @ winlink.org + // See if sending @ winlink.org if (_stricmp(Msg->to, "RMS") == 0) { // If a user of this bbs with Poll RMS set, leave it here - no point in sending to winlink - + // To = RMS could come from RMS:EMAIL Address. If so, we only check user if @winlink.org, or // we will hold g8bpq@g8bpq.org.uk @@ -1103,7 +1115,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (user->flags & F_BBS) // User is also a BBS, so set FWD bit so he can get it set_fwd_bit(Msg->fbbs, user->BBSNumber); - + return 1; } } @@ -1118,7 +1130,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (RMS) { Logprintf(LOG_BBS, conn, '?', "Routing Trace to RMS Matches BBS RMS"); - + set_fwd_bit(Msg->fbbs, RMS->BBSNumber); RMS->ForwardingInfo->MsgCount++; if (RMS->ForwardingInfo->SendNew) @@ -1140,20 +1152,20 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (user->flags & F_POLLRMS) { Logprintf(LOG_BBS, conn, '?', "Routing Trace @ winlink.org, but local RMS user - leave here"); - + if (user->flags & F_BBS) // User is also a BBS, so set FWD bit so he can get it set_fwd_bit(Msg->fbbs, user->BBSNumber); return 1; // Route found } } - + RMS = FindRMS(); if (RMS) { Logprintf(LOG_BBS, conn, '?', "Routing Trace @ winlink.org Matches BBS RMS"); - + set_fwd_bit(Msg->fbbs, RMS->BBSNumber); RMS->ForwardingInfo->MsgCount++; if (RMS->ForwardingInfo->SendNew) @@ -1169,7 +1181,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) // See if a well-known alias Alias = FindAlias(RouteElements); - + if (Alias) { Logprintf(LOG_BBS, conn, '?', "Routing Trace Alias Substitution %s > %s", @@ -1219,15 +1231,15 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) } Country = FindCountry(ptr2); - + if (Country) { // Just need to add Continent and WW -#ifdef TWOCHARCONT - sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent2); -#else - sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent4); -#endif + if (FOURCHARCONT == 0) + sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent2); + else + sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent4); + goto FULLHA; } @@ -1261,7 +1273,7 @@ FULLHA: if (ptr2 != FullRoute) *ptr2++ = 0; - + HElements[Elements++] = ptr2; @@ -1270,29 +1282,32 @@ FULLHA: if (HElements[1]) { -#ifdef TWOCHARCONT - if (strlen(HElements[1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(HElements[1]); - if (Continent) + if (strlen(HElements[1]) == 4) { -// free(MyElements[1]); - HElements[1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(HElements[1]); + if (Continent) + { + // free(MyElements[1]); + HElements[1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(HElements[1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(HElements[1]); - if (Continent) + if (strlen(HElements[1]) == 2) { -// free(MyElements[1]); - HElements[1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(HElements[1]); + if (Continent) + { + // free(MyElements[1]); + HElements[1] = _strdup(Continent->FourCharCode); + } } } -#endif } @@ -1301,7 +1316,7 @@ FULLHA: if (Msg->type == 'B') { int i = 0; - + // All elements of Helements must match Myelements while (MyElements[i] && HElements[i]) // Until one set runs out @@ -1345,7 +1360,7 @@ NOHA: if (depth > -1) { Logprintf(LOG_BBS, conn, '?', "Routing Trace NTS Matches TO BBS %s Length %d", bbs->Call, depth); - + if (depth > bestmatch) { bestmatch = depth; @@ -1386,7 +1401,63 @@ NOHA: goto CheckWildCardedAT; } + // First check P message to multiple destinations + // We should choose the BBS with most matching elements (ie match on #23.GBR better that GBR) + // If SendPtoMultiple is set I think we send to any with same match level + + // So if SendPtoMultiple is set I think I need to find the best depth then send to all with the same depth + // If none are found on HA match drop through. + + if (SendPtoMultiple && Msg->type == 'P') + { + struct UserInfo * bestbbs = NULL; + int bestmatch = 0; + int depth; + int Matched = 0; + int MultiPDepth = 0; + + Count = 0; + + Logprintf(LOG_BBS, conn, '?', "SendPtoMultiple is set. Checking for best match level"); + + for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) + { + ForwardingInfo = bbs->ForwardingInfo; + + depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); + + if (depth) + { + if (depth > MultiPDepth) + { + MultiPDepth = depth; + bestbbs = bbs; + } + } + } + + if (MultiPDepth) + { + for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) + { + ForwardingInfo = bbs->ForwardingInfo; + + depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); + + if (depth == MultiPDepth) + { + Logprintf(LOG_BBS, conn, '?', "Routing Trace HR Matches BBS %s Depth %d", bbs->Call, depth); + CheckAndSend(Msg, conn, bbs); + Count++; + } + } + return Count; + } + else + Logprintf(LOG_BBS, conn, '?', "SendPtoMultiple is set but no match on HA"); + } + if (Msg->type == 'P' || Flood == 0) { // P messages are only sent to one BBS, but check the TO and AT of all BBSs before routing on HA, @@ -1406,7 +1477,7 @@ NOHA: if (ForwardingInfo->PersonalOnly && (Msg->type != 'P') && (Msg->type != 'T')) continue; - + if (CheckBBSToList(Msg, bbs, ForwardingInfo)) { Logprintf(LOG_BBS, conn, '?', "Routing Trace TO %s Matches BBS %s", Msg->to, bbs->Call); @@ -1433,9 +1504,9 @@ NOHA: if ((strcmp(ATBBS, bbs->Call) == 0)) // @BBS = BBS { Logprintf(LOG_BBS, conn, '?', "Routing Trace %s Matches implied AT %s", ATBBS, bbs->Call); - + CheckAndSend(Msg, conn, bbs); - + Matched++; if (SendPtoMultiple && Msg->type == 'P') continue; @@ -1467,50 +1538,7 @@ NOHA: return 1; } - // We should choose the BBS with most matching elements (ie match on #23.GBR better that GBR) - // If SendPtoMultiple is set I think we send to any with same match level - - // So if SendPtoMultiple is set I think I need to find the best depth then send to all with the same depth - - - if (SendPtoMultiple && Msg->type == 'P') - { - Logprintf(LOG_BBS, conn, '?', "SendPtoMultiple is set. Checking for best match level"); - - for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) - { - ForwardingInfo = bbs->ForwardingInfo; - - depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); - - if (depth) - { - if (depth > MultiPDepth) - { - MultiPDepth = depth; - bestbbs = bbs; - } - } - - if (MultiPDepth) - { - for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) - { - ForwardingInfo = bbs->ForwardingInfo; - - depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); - - if (depth == MultiPDepth) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace HR Matches BBS %s Depth %d", bbs->Call, depth); - CheckAndSend(Msg, conn, bbs); - } - } - - return 1; - } - } - } + // Normal HA match (not SendPToMultiple) for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) { @@ -1586,182 +1614,182 @@ CheckWildCardedAT: Logprintf(LOG_BBS, conn, '?', "Routing Trace - No Match"); return FALSE; // No match - } - - // Flood Bulls go to all matching BBSs in the flood area, so the order of checking doesn't matter - - // For now I will only route on AT (for non-hierarchical addresses) and HA - - // Ver 1.0.4.2 - Try including TO - - for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) - { - ForwardingInfo = bbs->ForwardingInfo; - - if (ForwardingInfo->PersonalOnly) - continue; - - if (CheckBBSToList(Msg, bbs, ForwardingInfo)) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace TO %s Matches BBS %s", Msg->to, bbs->Call); - - if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Dont forward to ourself - already here! (unless ForwardToMe set) - { - set_fwd_bit(Msg->fbbs, bbs->BBSNumber); - ForwardingInfo->MsgCount++; - } - Count++; - continue; - } - - if ((strcmp(ATBBS, bbs->Call) == 0) || // @BBS = BBS - CheckBBSAtList(Msg, ForwardingInfo, ATBBS)) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace AT %s Matches BBS %s", Msg->to, bbs->Call); - CheckAndSend(Msg, conn, bbs); - - Count++; - continue; - } - - - if (CheckBBSHElementsFlood(Msg, bbs, ForwardingInfo, Msg->via, &HElements[0])) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace HR %s %s %s %s %s Matches BBS %s", - HElements[0], HElements[1], HElements[2], - HElements[3], HElements[4], bbs->Call); - - CheckAndSend(Msg, conn, bbs); - - Count++; - } - - } - - if (Count == 0) - goto CheckWildCardedAT; - - Logprintf(LOG_BBS, conn, '?', "Routing Trace - No Match"); - - return Count; } - BOOL CheckBBSToList(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo) - { - char ** Calls; + // Flood Bulls go to all matching BBSs in the flood area, so the order of checking doesn't matter - // Check TO distributions + // For now I will only route on AT (for non-hierarchical addresses) and HA - if (ForwardingInfo->TOCalls) + // Ver 1.0.4.2 - Try including TO + + for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) + { + ForwardingInfo = bbs->ForwardingInfo; + + if (ForwardingInfo->PersonalOnly) + continue; + + if (CheckBBSToList(Msg, bbs, ForwardingInfo)) { - Calls = ForwardingInfo->TOCalls; + Logprintf(LOG_BBS, conn, '?', "Routing Trace TO %s Matches BBS %s", Msg->to, bbs->Call); - while(Calls[0]) + if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Dont forward to ourself - already here! (unless ForwardToMe set) { - if (strcmp(Calls[0], Msg->to) == 0) - return TRUE; - - Calls++; + set_fwd_bit(Msg->fbbs, bbs->BBSNumber); + ForwardingInfo->MsgCount++; } + Count++; + continue; } - return FALSE; + + if ((strcmp(ATBBS, bbs->Call) == 0) || // @BBS = BBS + CheckBBSAtList(Msg, ForwardingInfo, ATBBS)) + { + Logprintf(LOG_BBS, conn, '?', "Routing Trace AT %s Matches BBS %s", Msg->to, bbs->Call); + CheckAndSend(Msg, conn, bbs); + + Count++; + continue; + } + + + if (CheckBBSHElementsFlood(Msg, bbs, ForwardingInfo, Msg->via, &HElements[0])) + { + Logprintf(LOG_BBS, conn, '?', "Routing Trace HR %s %s %s %s %s Matches BBS %s", + HElements[0], HElements[1], HElements[2], + HElements[3], HElements[4], bbs->Call); + + CheckAndSend(Msg, conn, bbs); + + Count++; + } + } - BOOL CheckBBSAtList(struct MsgInfo * Msg, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS) + if (Count == 0) + goto CheckWildCardedAT; + + Logprintf(LOG_BBS, conn, '?', "Routing Trace - No Match"); + + return Count; +} + +BOOL CheckBBSToList(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo) +{ + char ** Calls; + + // Check TO distributions + + if (ForwardingInfo->TOCalls) { - char ** Calls; + Calls = ForwardingInfo->TOCalls; - // Check AT distributions - - // if (strcmp(ATBBS, bbs->Call) == 0) // @BBS = BBS - // return TRUE; - - if (ForwardingInfo->ATCalls) + while(Calls[0]) { - Calls = ForwardingInfo->ATCalls; + if (strcmp(Calls[0], Msg->to) == 0) + return TRUE; - while(Calls[0]) - { - if (strcmp(Calls[0], ATBBS) == 0) - return TRUE; - - Calls++; - } + Calls++; } - return FALSE; } + return FALSE; +} - int CheckBBSHElements(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) +BOOL CheckBBSAtList(struct MsgInfo * Msg, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS) +{ + char ** Calls; + + // Check AT distributions + + // if (strcmp(ATBBS, bbs->Call) == 0) // @BBS = BBS + // return TRUE; + + if (ForwardingInfo->ATCalls) { - // Used for Personal Messages, and Bulls not yot at their target area + Calls = ForwardingInfo->ATCalls; - char *** HRoutes; - int i = 0, j, k = 0; - int bestmatch = 0; - - if (ForwardingInfo->HADDRSP) + while(Calls[0]) { - // Match on Routes + if (strcmp(Calls[0], ATBBS) == 0) + return TRUE; - HRoutes = ForwardingInfo->HADDRSP; - k=0; - - while(HRoutes[k]) - { - i = j = 0; - - while (HRoutes[k][i] && HElements[j]) // Until one set runs out - { - if (strcmp(HRoutes[k][i], HElements[j]) != 0) - break; - i++; - j++; - } - - // Only send if all BBS elements match - - if (HRoutes[k][i] == 0) - { - if (i > bestmatch) - bestmatch = i; - } - k++; - } + Calls++; } - return bestmatch; } + return FALSE; +} +int CheckBBSHElements(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) +{ + // Used for Personal Messages, and Bulls not yot at their target area - int CheckBBSHElementsFlood(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) + char *** HRoutes; + int i = 0, j, k = 0; + int bestmatch = 0; + + if (ForwardingInfo->HADDRSP) { - char *** HRoutes; - char ** BBSHA; + // Match on Routes - int i = 0, j, k = 0; - int bestmatch = 0; + HRoutes = ForwardingInfo->HADDRSP; + k=0; - if (ForwardingInfo->HADDRS) + while(HRoutes[k]) { - // Match on Routes - - // Message must be in right area (all elements of message match BBS Location HA) - - BBSHA = ForwardingInfo->BBSHAElements; - - if (BBSHA == NULL) - return 0; // Not safe to flood - i = j = 0; - while (BBSHA[i] && HElements[j]) // Until one set runs out + while (HRoutes[k][i] && HElements[j]) // Until one set runs out { - if (strcmp(BBSHA[i], HElements[j]) != 0) + if (strcmp(HRoutes[k][i], HElements[j]) != 0) break; i++; j++; } - if (HElements[j] != 0) + // Only send if all BBS elements match + + if (HRoutes[k][i] == 0) + { + if (i > bestmatch) + bestmatch = i; + } + k++; + } + } + return bestmatch; +} + + +int CheckBBSHElementsFlood(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) +{ + char *** HRoutes; + char ** BBSHA; + + int i = 0, j, k = 0; + int bestmatch = 0; + + if (ForwardingInfo->HADDRS) + { + // Match on Routes + + // Message must be in right area (all elements of message match BBS Location HA) + + BBSHA = ForwardingInfo->BBSHAElements; + + if (BBSHA == NULL) + return 0; // Not safe to flood + + i = j = 0; + + while (BBSHA[i] && HElements[j]) // Until one set runs out + { + if (strcmp(BBSHA[i], HElements[j]) != 0) + break; + i++; + j++; + } + + if (HElements[j] != 0) return 0; // Message is not for BBS's area HRoutes = ForwardingInfo->HADDRS; @@ -1770,7 +1798,7 @@ CheckWildCardedAT: while(HRoutes[k]) { i = j = 0; - + while (HRoutes[k][i] && HElements[j]) // Until one set runs out { if (strcmp(HRoutes[k][i], HElements[j]) != 0) @@ -1778,11 +1806,11 @@ CheckWildCardedAT: i++; j++; } - + if (i > bestmatch) { // As Flooding, only match if all elements match, and elements matching > offset - + // As Flooding, only match if all elements from BBS are matched // ie if BBS has #23.gbr.eu, and msg gbr.eu, don't match // if BBS has gbr.eu, and msg #23.gbr.eu, ok (so long as bbs in in #23, checked above. @@ -1807,7 +1835,7 @@ int CheckBBSToForNTS(struct MsgInfo * Msg, struct BBSForwardingInfo * Forwarding int MatchLen = 0; // Look for Matches on TO using Wildcarded Addresses. Intended for use with NTS traffic, with TO = ZIPCode - + // We forward to the BBS with the most specific match - ie minimum *'s in match if (ForwardingInfo->TOCalls) @@ -1848,7 +1876,7 @@ int CheckBBSToForNTS(struct MsgInfo * Msg, struct BBSForwardingInfo * Forwarding else { //no star - just do a normal compare - + if (strcmp(Msg->to, Call) == 0) { if (Invert) @@ -1877,7 +1905,7 @@ int CheckBBSATListWildCarded(struct MsgInfo * Msg, struct BBSForwardingInfo * Fo // Look for Matches on AT using Wildcarded Addresses. Only applied after all other checks fail. Intended mainly // for setting a default route, but could have other uses - + // We forward to the BBS with the most specific match - ie minimum *'s in match if (ForwardingInfo->ATCalls) @@ -1890,7 +1918,7 @@ int CheckBBSATListWildCarded(struct MsgInfo * Msg, struct BBSForwardingInfo * Fo ptr = strchr(Call, '*'); // only look if * present - we have already tried routing on the full AT - + if (ptr) { MatchLen = ptr - Call; @@ -1930,7 +1958,7 @@ struct ALIAS * CheckForNTSAlias(struct MsgInfo * Msg, char * ATFirstElement) break; ptr = strchr(Call, '*'); - + if (ptr) { MatchLen = ptr - Call; @@ -1941,7 +1969,7 @@ struct ALIAS * CheckForNTSAlias(struct MsgInfo * Msg, char * ATFirstElement) else { //no star - just do a normal compare - + if (strcmp(Msg->to, Call) == 0) return(Alias[0]); } @@ -2016,7 +2044,7 @@ VOID ReRouteMessages() if (check_fwd_bit(Msg->fbbs, user->BBSNumber)) // for this BBS? { if (check_fwd_bit(Msg->forw, user->BBSNumber)) // Already sent? - clear_fwd_bit(Msg->fbbs, user->BBSNumber); + clear_fwd_bit(Msg->fbbs, user->BBSNumber); } } diff --git a/Versions.h b/Versions.h index 38a03fb..2fd8eb3 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,8 @@ #endif -#define KVers 6,0,24,38 -#define KVerstring "6.0.24.38\0" +#define KVers 6,0,24,40 +#define KVerstring "6.0.24.40\0" #ifdef CKernel diff --git a/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index 0cd9a72..0000000 --- a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/WinmorControl.vcproj.NOTTSDESKTOP.John.user b/WinmorControl.vcproj.NOTTSDESKTOP.John.user deleted file mode 100644 index fa82c00..0000000 --- a/WinmorControl.vcproj.NOTTSDESKTOP.John.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/bpqmail.h b/bpqmail.h index 0071261..7b72ea4 100644 --- a/bpqmail.h +++ b/bpqmail.h @@ -43,7 +43,7 @@ #define NEWROUTING - +extern int FOURCHARCONT; // Standard __except handler for try/except diff --git a/templatedefs.c b/templatedefs.c index 94f69e8..b532031 100644 --- a/templatedefs.c +++ b/templatedefs.c @@ -101,7 +101,7 @@ char * FwdPagetxt() "{" "position: absolute;" "width:290px;" - "height:510px;" + "height:550px;" "border:0px solid;" "overflow: auto;" "}" @@ -109,7 +109,7 @@ char * FwdPagetxt() "{" "position: absolute;" "width:180px;" - "height:500px;" + "height:540px;" "border:2px solid;" "overflow: auto;" "}" @@ -118,7 +118,7 @@ char * FwdPagetxt() "position: absolute;" "width:95px;" "left:190px;" - "height:500px;" + "height:540px;" "border:2px solid;" "overflow: auto;" "}" @@ -255,6 +255,7 @@ char * FwdPagetxt() " Welcome Msgs & Prompts" " Housekeeping" " WP Update" + "WebMail" " Node Menu" " " " " @@ -279,7 +280,8 @@ char * FwdPagetxt() "
" "Send P Msgs to more than one BBS 
" "
" - + "Use 4 Char Continent Codes 
" + "
" "Aliases
" "
" "

" @@ -400,6 +402,7 @@ char * WebMailPagetxt() "Auto Refresh\r\n" "Send Message\r\n" "Logout\r\n" + "Mail Mgmt\r\n" "Node Menu\r\n" "
\r\n" "
\r\n" @@ -452,6 +455,7 @@ char * MainConfigtxt() " Welcome Msgs & Prompts\r\n" " Housekeeping\r\n" " WP Update\r\n" + "WebMail" " Node Menu\r\n" "\r\n" "
\r\n" @@ -701,6 +705,7 @@ char * MsgPagetxt() " Welcome Msgs & Prompts\r\n" " Housekeeping\r\n" " WP Update\r\n" + "WebMail" " Node Menu\r\n" " \r\n" " \r\n" @@ -1060,6 +1065,7 @@ char * UserPagetxt() "Welcome Msgs & Prompts\r\n" "Housekeeping\r\n" "WP Update\r\n" + "WebMail" "Node Menu\r\n" "
\r\n" "
\r\n" @@ -1116,6 +1122,7 @@ char * Housekeepingtxt() "Welcome Msgs & Prompts\r\n" "Housekeeping\r\n" "WP Update\r\n" + "WebMail" "Node Menu\r\n" "
\r\n" "
Housekeeping
\r\n" @@ -1364,6 +1371,7 @@ char * WPtxt() " Welcome Msgs & Prompts\r\n" " Housekeeping\r\n" " WP Update\r\n" + "WebMail" " Node Menu\r\n" " \r\n" " \r\n" From fc0275b90325addebfdb93a00fefc8511b1b4e98 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sun, 7 Jul 2024 16:08:01 +0100 Subject: [PATCH 05/12] Upstream revision --- debian/changelog | 6 ++++-- debian/patches/spelling-errors.patch | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/debian/changelog b/debian/changelog index 6cd7c70..509c2e7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,10 @@ -linbpq (6.0.24.38-2) UNRELEASED; urgency=medium +linbpq (6.0.24.40-1) UNRELEASED; urgency=medium + * Fresh upstream release + - Patches refreshed * Secure by default patch - -- Dave Hibberd Fri, 05 Jul 2024 08:34:44 +0100 + -- Dave Hibberd Sun, 07 Jul 2024 16:06:22 +0100 linbpq (6.0.24.38-1) unstable; urgency=medium diff --git a/debian/patches/spelling-errors.patch b/debian/patches/spelling-errors.patch index 78f5260..35eca8c 100644 --- a/debian/patches/spelling-errors.patch +++ b/debian/patches/spelling-errors.patch @@ -22,7 +22,7 @@ --- a/BPQMail.rc +++ b/BPQMail.rc -@@ -1042,7 +1042,7 @@ +@@ -1045,7 +1045,7 @@ CONTROL "Delete Log and Message Files to Recycle Bin", IDC_DELETETORECYCLE,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | WS_TABSTOP,5,142,115,20 @@ -108,7 +108,7 @@ goto SeeifMore; // SEE IF ANYTHING ELSE --- a/templatedefs.c +++ b/templatedefs.c -@@ -1158,7 +1158,7 @@ +@@ -1165,7 +1165,7 @@ "Send Non-delivery Notifications
\r\n" "for P and T messages
\r\n" "
\r\n" @@ -117,7 +117,7 @@ "Housekeeping Result

\r\n" "Generate Traffic Report

\r\n" "
\r\n" -@@ -1446,7 +1446,7 @@ +@@ -1454,7 +1454,7 @@ "
The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " "connections may be accepted. The format is ALIAS:CALL, eg BPQCHT:G8BPQ-4. If the node is not directly " "connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands " From 9dacd97014132dfb6fafd22ad75b06a0e4cad6a0 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sun, 7 Jul 2024 16:09:46 +0100 Subject: [PATCH 06/12] Release --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 509c2e7..2584e82 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,10 @@ -linbpq (6.0.24.40-1) UNRELEASED; urgency=medium +linbpq (6.0.24.40-1) unstable; urgency=medium * Fresh upstream release - Patches refreshed * Secure by default patch - -- Dave Hibberd Sun, 07 Jul 2024 16:06:22 +0100 + -- Dave Hibberd Sun, 07 Jul 2024 16:09:28 +0100 linbpq (6.0.24.38-1) unstable; urgency=medium From 60585818de254e8921fca42f55c175aa52e77e1e Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sun, 18 Aug 2024 01:44:28 +0100 Subject: [PATCH 07/12] Move config back to /etc on install --- debian/changelog | 6 ++++++ debian/install | 1 + 2 files changed, 7 insertions(+) create mode 100644 debian/install diff --git a/debian/changelog b/debian/changelog index 2584e82..5d6d692 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +linbpq (6.0.24.40-2) UNRELEASED; urgency=medium + + * Install config to /etc + + -- Dave Hibberd Sat, 17 Aug 2024 17:41:25 +0100 + linbpq (6.0.24.40-1) unstable; urgency=medium * Fresh upstream release diff --git a/debian/install b/debian/install new file mode 100644 index 0000000..d1aded2 --- /dev/null +++ b/debian/install @@ -0,0 +1 @@ +debian/bpq32.cfg etc/ From 6dfe32758e1a995b1241af8c981798c22cd70439 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Fri, 30 Aug 2024 10:14:56 +0100 Subject: [PATCH 08/12] New upstream version 6.0.24.42 --- 6pack.c | 2129 ++++++++ ARDOP.c | 12 + BBSUtilities.c | 456 +- BPQChat.vcproj.NOTTSDESKTOP.John.user | 65 + BPQMail.c | 1 + BPQMail.vcproj.NOTTSDESKTOP.John.user | 65 + BPQMail.vcproj.SKIGACER.johnw.user | 65 + BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 + BPQWinAPP.vcproj.NOTTSDESKTOP.John.user | 65 + Bpq32.c | 7 + CBPQ32.vcproj | 6 +- CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 + CBPQ32.vcproj.NOTTSDESKTOP.John.user | 65 + CBPQ32.vcproj.SKIGACER.johnw.user | 65 + CommonCode.c | 16 +- HFCommon.c | 2 + HTTPcode.c | 19 +- LinBPQ.c | 323 +- MHSave.txt | 0 MailNode.vcproj.NOTTSDESKTOP.John.user | 65 + MailNode.vcproj.SKIGACER.johnw.user | 65 + Moncode.c | 7 +- SCSPactor.c.bak | 4322 ----------------- SerialPort.c | 3 +- TelnetV6.c | 1 + VARA.c | 2 +- Versions.h | 6 +- WinRPRHelper.vcproj.NOTTSDESKTOP.John.user | 65 + ...rControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user | 65 + WinmorControl.vcproj.NOTTSDESKTOP.John.user | 65 + bpqchat.c | 3 +- bpqmail.h | 3 +- tncinfo.h | 11 +- upnp.c | 9 + 34 files changed, 3429 insertions(+), 4754 deletions(-) create mode 100644 6pack.c create mode 100644 BPQChat.vcproj.NOTTSDESKTOP.John.user create mode 100644 BPQMail.vcproj.NOTTSDESKTOP.John.user create mode 100644 BPQMail.vcproj.SKIGACER.johnw.user create mode 100644 BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user create mode 100644 BPQWinAPP.vcproj.NOTTSDESKTOP.John.user create mode 100644 CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user create mode 100644 CBPQ32.vcproj.NOTTSDESKTOP.John.user create mode 100644 CBPQ32.vcproj.SKIGACER.johnw.user create mode 100644 MHSave.txt create mode 100644 MailNode.vcproj.NOTTSDESKTOP.John.user create mode 100644 MailNode.vcproj.SKIGACER.johnw.user delete mode 100644 SCSPactor.c.bak create mode 100644 WinRPRHelper.vcproj.NOTTSDESKTOP.John.user create mode 100644 WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user create mode 100644 WinmorControl.vcproj.NOTTSDESKTOP.John.user diff --git a/6pack.c b/6pack.c new file mode 100644 index 0000000..ba7bd07 --- /dev/null +++ b/6pack.c @@ -0,0 +1,2129 @@ +/* +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 +*/ + +/* + +Using code from 6pack Linux Kernel driver with the following licence and credits + + * 6pack driver version 0.4.2, 1999/08/22 + * + * This module: + * This module 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 + * 2 of the License, or (at your option) any later version. + * + * This module implements the AX.25 protocol for kernel-based + * devices like TTYs. It interfaces between a raw TTY, and the + * kernel's AX.25 protocol layers, just like slip.c. + * AX.25 needs to be separated from slip.c while slip.c is no + * longer a static kernel device since it is a module. + * + * Author: Andreas Könsgen + * + * Lots of stuff has been taken from mkiss.c, written by + * Hans Alblas + * + * with the fixes from + * + * Jonathan (G4KLX) Fixed to match Linux networking changes - 2.1.15. + * Matthias (DG2FEF) Fixed bug in ax25_close(): dev_lock_wait() was + * called twice, causing a deadlock. + */ + + +// 6pack needs fast response to received characters, and I want to be able to operate over TCP links as well as serial. +// So I think the character level stuff may need to run in a separate thread, probably using select. +// +// I also need to support multiple 6pack ports. + +// ?? Do we add this as a backend to KISS driver or a separate Driver. KISS Driver is already quite messy. Not decided yet. + +// ?? If using serial/real TNC we need to be able to interleave control and data bytes, but I think with TCP/QtSM it won't be necessary +// ?? Also a don't see any point in running multiple copies of QtSM on one port, but maybe should treat the QtSM channels as +// multidropped ports for scheduling (?? only if on same radio ??) + +// ?? I think it needs to look like a KISS (L2) driver but will need a transmit scheduler level to do DCD/CSMA/PTT processing, +// ideally with an interlock to other drivers on same port. This needs some thought with QtSM KISS with multiple modems on one channel + + + + + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#define _CRT_SECURE_NO_DEPRECATE + +#include "compatbits.h" +#include +#include "CHeaders.h" + +#include "bpq32.h" + +#include "tncinfo.h" + +#ifndef WIN32 + +#define APIENTRY +#define DllExport +#define VOID void + +#else +#include +#endif + +/**************************************************************************** + * Defines for the 6pack driver. + ****************************************************************************/ + +/* + provisoric define +*/ +#define SIXP_MAJOR MKISS_MAJOR +/* end of provisoric defines */ + + +#define TRUE 1 +#define FALSE 0 + +#define AX25_MAXDEV 16 /* MAX number of AX25 channels; + This can be overridden with + insmod -oax25_maxdev=nnn */ +#define AX_MTU 236 + +/* 6pack protocol bytes/masks. */ +#define SIXP_INIT_CMD 0xE8 +#define SIXP_TNC_FOUND 0xE9 +#define SIXP_CMD_MASK 0xC0 +#define SIXP_PRIO_CMD_MASK 0x80 +#define SIXP_PRIO_DATA_MASK 0x38 +#define SIXP_STD_CMD_MASK 0x40 +#define SIXP_DCD_MASK 0x08 +#define SIXP_RX_DCD_MASK 0x18 +#define SIXP_CHN_MASK 0x07 +#define SIXP_TX_MASK 0x20 +#define SIXP_CON_LED_ON 0x68 +#define SIXP_STA_LED_ON 0x70 +#define SIXP_LED_OFF 0x60 + +/* checksum for a valid 6pack encapsulated packet */ +#define SIXP_CHKSUM 0xFF + +/* priority commands */ +#define SIXP_SEOF 0x40 /* TX underrun */ +#define SIXP_TX_URUN 0x48 /* TX underrun */ +#define SIXP_RX_ORUN 0x50 /* RX overrun */ +#define SIXP_RX_BUF_OVL 0x58 /* RX overrun */ + +struct sixPackTNCInfo +{ + // info for each TNC in chain + + int magic; + + char * name; + + /* These are pointers to the malloc()ed frame buffers. */ + unsigned char *rbuff; /* receiver buffer */ + int rcount; /* received chars counter */ + unsigned char *xbuff; /* transmitter buffer */ + unsigned char *xhead; /* pointer to next byte to XMIT */ + int xleft; /* bytes left in XMIT queue */ + + /* SLIP interface statistics. */ + unsigned long rx_packets; /* inbound frames counter */ + unsigned long tx_packets; /* outbound frames counter */ + unsigned long rx_errors; /* Parity, etc. errors */ + unsigned long tx_errors; /* Planned stuff */ + unsigned long rx_dropped; /* No memory for skb */ + unsigned long tx_dropped; /* When MTU change */ + unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */ + + /* Detailed SLIP statistics. */ + int mtu; /* Our mtu (to spot changes!) */ + int buffsize; /* Max buffers sizes */ + + + unsigned char flags; /* Flag values/ mode etc */ +#define AXF_INUSE 0 /* Channel in use */ +#define AXF_ESCAPE 1 /* ESC received */ +#define AXF_ERROR 2 /* Parity, etc. error */ +#define AXF_KEEPTEST 3 /* Keepalive test flag */ +#define AXF_OUTWAIT 4 /* is outpacket was flag */ + + int mode; + + + /* variables for the state machine */ + + unsigned char tnc_ok; + unsigned char status; + unsigned char status1; + unsigned char status2; + + unsigned char duplex; + unsigned char led_state; + unsigned char tx_enable; + + unsigned char raw_buf[4]; /* receive buffer */ + unsigned char cooked_buf[400]; /* receive buffer after 6pack decoding */ + + unsigned int rx_count; /* counter for receive buffer */ + unsigned int rx_count_cooked; /* counter for receive buffer after 6pack decoding */ + + unsigned char tx_delay; + unsigned char persistance; + unsigned char slottime; + +}; + + +struct sixPackPortInfo +{ + // Per port (chain of TNC's) + + unsigned int linkOK; // Set if response is received + unsigned int reinitTimer; + + struct sixPackTNCInfo * TNCS[8]; // Max TNCs in chain Not sure if real 6pack uses o or 1 for first +}; + + +#define AX25_MAGIC 0x5316 +#define SIXP_DRIVER_MAGIC 0x5304 + +#define SIXP_INIT_RESYNC_TIMEOUT 150 /* in 10 ms */ +#define SIXP_RESYNC_TIMEOUT 500 /* in 10 ms */ + +/* default radio channel access parameters */ +#define SIXP_TXDELAY 25 /* in 10 ms */ +#define SIXP_PERSIST 50 +#define SIXP_SLOTTIME 10 /* in 10 ms */ + +static int sixpack_encaps(unsigned char *tx_buf, unsigned char *tx_buf_raw, int length, unsigned char tx_delay); +static void sixpack_decaps(struct sixPackPortInfo *, unsigned char); + +static void decode_prio_command(unsigned char, struct sixPackTNCInfo *); +static void decode_std_command(unsigned char, struct sixPackTNCInfo *); +static void decode_data(unsigned char, struct sixPackTNCInfo *); +static void resync_tnc(unsigned long); +static void xmit_on_air(struct sixPackTNCInfo *ax); +static void start_tx_timer(struct sixPackTNCInfo *ax); +int Connectto6Pack(int port); + +VOID __cdecl Debugprintf(const char * format, ...); + +/* Set the "sending" flag. This must be atomic, hence the ASM. */ + +static void ax_lock(struct sixPackTNCInfo *ax) +{ +// if (test_and_set_bit(0, (void *)&ax->dev->tbusy)) +// printk(KERN_ERR "6pack: %s: trying to lock already locked device!\n", ax->dev->name); +} + + +/* Clear the "sending" flag. This must be atomic, hence the ASM. */ +static void ax_unlock(struct sixPackTNCInfo *ax) +{ +// if (!test_and_clear_bit(0, (void *)&ax->dev->tbusy)) +// printk(KERN_ERR "6pack: %s: trying to unlock already unlocked device!\n", ax->dev->name); +} +/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */ +static void ax_bump(struct sixPackTNCInfo *ax) +{ +} + +VOID SixPackProcessReceivedPacket(struct TNCINFO * TNC) +{ + int InputLen, MsgLen; + unsigned char * ptr; + char Buffer[4096]; + + if (TNC->InputLen > 8000) // Shouldnt have packets longer than this + TNC->InputLen=0; + + InputLen = recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8192 - TNC->InputLen, 0); + + if (InputLen == 0 || InputLen == SOCKET_ERROR) + { + // Does this mean closed? + + int err = GetLastError(); + + closesocket(TNC->TCPSock); + + TNC->TCPSock = 0; + + TNC->CONNECTED = FALSE; + TNC->Streams[0].ReportDISC = TRUE; + + sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + return; + } + + TNC->InputLen += InputLen; + + // Process Bytes + +} + + + +static int sixpack_encaps(unsigned char *tx_buf, unsigned char *tx_buf_raw, int length, unsigned char tx_delay) +{ + int count = 0; + unsigned char checksum = 0, buf[400]; + int raw_count = 0; + + tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK; + tx_buf_raw[raw_count++] = SIXP_SEOF; + + buf[0] = tx_delay; + for(count = 1; count < length; count++) + buf[count] = tx_buf[count]; + + for(count = 0; count < length; count++) + checksum += buf[count]; + buf[length] = (unsigned char)0xff - checksum; + + for(count = 0; count <= length; count++) { + if((count % 3) == 0) { + tx_buf_raw[raw_count++] = (buf[count] & 0x3f); + tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30); + } + else if((count % 3) == 1) { + tx_buf_raw[raw_count++] |= (buf[count] & 0x0f); + tx_buf_raw[raw_count] = + ((buf[count] >> 2) & 0x3c); + } else { + tx_buf_raw[raw_count++] |= (buf[count] & 0x03); + tx_buf_raw[raw_count++] = + (buf[count] >> 2); + } /* else */ + } /* for */ + if ((length % 3) != 2) + raw_count++; + tx_buf_raw[raw_count++] = SIXP_SEOF; + return(raw_count); +} + + +static void sixpack_decaps(struct sixPackPortInfo *ax, unsigned char inbyte) +{ + // if (inbyte == SIXP_TNC_FOUND) { + // This is wrong. It will only work with one TNC in the chain. Should look for E8 in top bits. Bottome 3 bits are number in chain + + if ((inbyte & SIXP_INIT_CMD) == 0) + { + int Count = inbyte & SIXP_CHN_MASK; + struct sixPackTNCInfo * sixTNC; + + int i; + + Debugprintf("6pack: %d TNCs found. ", Count); + + // clear existing TNC strucs and allocate new ones if needed + + for (i = 0; i < Count; i++) + { + sixTNC = ax->TNCS[i]; + + if (sixTNC) + memset(sixTNC, 0, sizeof(struct sixPackTNCInfo)); + else + sixTNC = ax->TNCS[i] = zalloc(sizeof(struct sixPackTNCInfo)); + + sixTNC->tnc_ok = 1; + } + + ax->linkOK = TRUE; + + } +/* +if((inbyte & SIXP_PRIO_CMD_MASK) != 0) + decode_prio_command(inbyte, ax); + else if((inbyte & SIXP_STD_CMD_MASK) != 0) + decode_std_command(inbyte, ax); + else { + if ((ax->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK) + decode_data(inbyte, ax); + } +*/ +} + +/* identify and execute a 6pack priority command byte */ + +void decode_prio_command(unsigned char cmd, struct sixPackTNCInfo *ax) +{ + unsigned char channel; + + channel = cmd & SIXP_CHN_MASK; + if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */ + + /* RX and DCD flags can only be set in the same prio command, + if the DCD flag has been set without the RX flag in the previous + prio command. If DCD has not been set before, something in the + transmission has gone wrong. In this case, RX and DCD are + cleared in order to prevent the decode_data routine from + reading further data that might be corrupt. */ + + if (((ax->status & SIXP_DCD_MASK) == 0) && + ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) { + if (ax->status != 1) + Debugprintf("6pack: protocol violation\n"); + else + ax->status = 0; + cmd &= !SIXP_RX_DCD_MASK; + } + ax->status = cmd & SIXP_PRIO_DATA_MASK; + } /* if */ + + + /* if the state byte has been received, the TNC is present, + so the resync timer can be reset. */ + + if (ax->tnc_ok == 1) { +// del_timer(&(ax->resync_t)); +// ax->resync_t.data = (unsigned long) ax; +// ax->resync_t.function = resync_tnc; +// ax->resync_t.expires = jiffies + SIXP_INIT_RESYNC_TIMEOUT; +// add_timer(&(ax->resync_t)); + } + + ax->status1 = cmd & SIXP_PRIO_DATA_MASK; +} + +/* try to resync the TNC. Called by the resync timer defined in + decode_prio_command */ + +static void resync_tnc(unsigned long channel) +{ + static char resync_cmd = SIXP_INIT_CMD; + struct sixPackTNCInfo *ax = (struct sixPackTNCInfo *) channel; + + Debugprintf("6pack: resyncing TNC\n"); + + /* clear any data that might have been received */ + + ax->rx_count = 0; + ax->rx_count_cooked = 0; + + /* reset state machine */ + + ax->status = 1; + ax->status1 = 1; + ax->status2 = 0; + ax->tnc_ok = 0; + + /* resync the TNC */ + + ax->led_state = SIXP_LED_OFF; +// ax->tty->driver.write(ax->tty, 0, &(ax->led_state), 1); +// ax->tty->driver.write(ax->tty, 0, &resync_cmd, 1); + + + /* Start resync timer again -- the TNC might be still absent */ + +// del_timer(&(ax->resync_t)); +// ax->resync_t.data = (unsigned long) ax; +// ax->resync_t.function = resync_tnc; +// ax->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT; +// add_timer(&(ax->resync_t)); +} + + + +/* identify and execute a standard 6pack command byte */ + +void decode_std_command(unsigned char cmd, struct sixPackTNCInfo *ax) +{ + unsigned char checksum = 0, channel; + unsigned int i; + + channel = cmd & SIXP_CHN_MASK; + switch(cmd & SIXP_CMD_MASK) { /* normal command */ + case SIXP_SEOF: + if ((ax->rx_count == 0) && (ax->rx_count_cooked == 0)) { + if ((ax->status & SIXP_RX_DCD_MASK) == + SIXP_RX_DCD_MASK) { + ax->led_state = SIXP_CON_LED_ON; +// ax->tty->driver.write(ax->tty, 0, &(ax->led_state), 1); + } /* if */ + } else { + ax->led_state = SIXP_LED_OFF; +// ax->tty->driver.write(ax->tty, 0, &(ax->led_state), 1); + /* fill trailing bytes with zeroes */ + if (ax->rx_count == 2) { + decode_data(0, ax); + decode_data(0, ax); + ax->rx_count_cooked -= 2; + } + else if (ax->rx_count == 3) { + decode_data(0, ax); + ax->rx_count_cooked -= 1; + } + for (i=0; i< ax->rx_count_cooked; i++) + checksum += ax->cooked_buf[i]; + if (checksum != SIXP_CHKSUM) { + Debugprintf("6pack: bad checksum %2.2x\n", checksum); + } else { + ax->rcount = ax->rx_count_cooked-1; + ax_bump(ax); + } /* else */ + ax->rx_count_cooked = 0; + } /* else */ + break; + case SIXP_TX_URUN: + Debugprintf("6pack: TX underrun\n"); + break; + case SIXP_RX_ORUN: + Debugprintf("6pack: RX overrun\n"); + break; + case SIXP_RX_BUF_OVL: + Debugprintf("6pack: RX buffer overflow\n"); + } /* switch */ +} /* function */ + +/* decode 4 sixpack-encoded bytes into 3 data bytes */ + +void decode_data(unsigned char inbyte, struct sixPackTNCInfo *ax) +{ + + unsigned char *buf; + + if (ax->rx_count != 3) + ax->raw_buf[ax->rx_count++] = inbyte; + else { + buf = ax->raw_buf; + ax->cooked_buf[ax->rx_count_cooked++] = + buf[0] | ((buf[1] << 2) & 0xc0); + ax->cooked_buf[ax->rx_count_cooked++] = + (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0); + ax->cooked_buf[ax->rx_count_cooked++] = + (buf[2] & 0x03) | (inbyte << 2); + ax->rx_count = 0; + } +} + +// This takes a packet from the KISS driver and converts to 6pack format + +static void ax_encaps(struct sixPackTNCInfo *ax, unsigned char *icp, int len) +{ + unsigned char *p; + int count; + struct sixPackTNCInfo *tmp_ax; + + if (len > ax->mtu) { /* Sigh, shouldn't occur BUT ... */ + len = ax->mtu; + Debugprintf("6pack: %s: truncating oversized transmit packet!\n", ax->name); + ax->tx_dropped++; + ax_unlock(ax); + return; + } + + p = icp; + + if (p[0] > 5) + { + Debugprintf("%s: invalid KISS command -- dropped\n", ax->name); + ax_unlock(ax); + return; + } + + if ((p[0] != 0) && (len > 2)) + { + Debugprintf("%s: KISS command packet too long -- dropped\n", ax->name); + ax_unlock(ax); + return; + } + + if ((p[0] == 0) && (len < 15)) + { + Debugprintf("%s: bad AX.25 packet to transmit -- dropped\n", ax->name); + ax->tx_dropped++; + ax_unlock(ax); + return; + } + + switch(p[0]) + { + case 1: tmp_ax->tx_delay = p[1]; break; + case 2: tmp_ax->persistance = p[1]; break; + case 3: tmp_ax->slottime = p[1]; break; + case 4: Debugprintf("6pack: got KISS command 4 -- ignored\n"); + break; + case 5: tmp_ax->duplex = p[1]; break; + } + + // How do we handle ACKMODE ?? + + if (p[0] != 0) { + ax_unlock(ax); + return; + } + + count = sixpack_encaps(p, (unsigned char *) tmp_ax->xbuff, len, tmp_ax->tx_delay); + tmp_ax->xleft = count; + tmp_ax->status2 = count; + tmp_ax->xhead = tmp_ax->xbuff; + + /* in case of DAMA or fullduplex operation, we don't take care + about the state of the DCD or of any timers, as the determination + of the correct time to send is the job of the AX.25 layer. We send + immediately after data has arrived. */ + + if (tmp_ax->duplex == 1) { /* DAMA / fullduplex */ + xmit_on_air(tmp_ax); + } else { /* CSMA */ + start_tx_timer(tmp_ax); + } /* if ax->duplex */ +} /* ax_encaps */ + +// This starts sending a packet to a TNC. TNC will immediately send (after TXD) + +/* the next two functions perform the persistence/slottime algorithm for CSMA access. + If the persistence check was successful, write the data to the serial driver. + Note that in case of DAMA operation, the data is not sent here. */ + +/* set timer to time out slottime */ +static void start_tx_timer(struct sixPackTNCInfo *ax) +{ +// del_timer(&(ax->tx_t)); +// ax->tx_t.data = (unsigned long) ax; +// ax->tx_t.function = tx_schedule; +// ax->tx_t.expires = jiffies + (((ax->slottime)+1)*HZ)/100; +// add_timer(&(ax->tx_t)); +} + +/* compute random number and check if it is ok to send */ +static void tx_schedule(unsigned long channel) +{ + struct sixPackTNCInfo *ax = (struct sixPackTNCInfo *) channel; + static unsigned char random; + + random = random * 17 + 41; + + if (((ax->status1 & SIXP_DCD_MASK) == 0) && (random < ax->persistance)) + xmit_on_air(ax); + else + start_tx_timer(ax); +} + + +static void xmit_on_air(struct sixPackTNCInfo *ax) +{ + int actual; + +// ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); + ax->led_state = SIXP_STA_LED_ON; +// ax->tty->driver.write(ax->tty, 0, &(ax->led_state), 1); + ax->tx_enable = 1; +// actual = ax->tty->driver.write(ax->tty, 0, ax->xbuff, ax->status2); + ax->tx_packets++; +// ax->dev->trans_start = jiffies; + ax->xleft -= actual; + ax->xhead = ax->xbuff + actual; + ax->led_state = SIXP_LED_OFF; +// ax->tty->driver.write(ax->tty, 0, &(ax->led_state), 1); +} /* xmit_on_air */ + + +// BPQ Driver Module Interface + + +extern int (WINAPI FAR *GetModuleFileNameExPtr)(); +extern int (WINAPI FAR *EnumProcessesPtr)(); + +static int Socket_Data(int sock, int error, int eventcode); + +VOID MoveWindows(struct TNCINFO * TNC); +static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen); +int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error); +BOOL SerialWriteCommBlock(struct TNCINFO * TNC); +void SerialCheckRX(struct TNCINFO * TNC); +int SerialSendData(struct TNCINFO * TNC, UCHAR * data, int txlen); +int SerialSendCommand(struct TNCINFO * TNC, UCHAR * data); +int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); +VOID SendInitScript(struct TNCINFO * TNC); +int SIXPACKGetLine(char * buf); +int ProcessEscape(UCHAR * TXMsg); +VOID SIXPACKProcessReceivedPacket(struct TNCINFO * TNC); +static int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); +int ConnecttoKISS(int port); +TRANSPORTENTRY * SetupNewSession(TRANSPORTENTRY * Session, char * Bufferptr); +BOOL DecodeCallString(char * Calls, BOOL * Stay, BOOL * Spy, UCHAR * AXCalls); +BOOL FindLink(UCHAR * LinkCall, UCHAR * OurCall, int Port, struct _LINKTABLE ** REQLINK); +VOID RESET2(struct _LINKTABLE * LINK); +VOID L2SENDXID(struct _LINKTABLE * LINK); +VOID SENDSABM(struct _LINKTABLE * LINK); + +static char ClassName[]="KISSSTATUS"; +static char WindowTitle[] = "SIXPACK"; +static int RigControlRow = 165; + +#ifndef LINBPQ +#include +#endif + +extern int SemHeldByAPI; + +static RECT Rect; + +static int ProcessLine(char * buf, int Port); + +VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); + +#define FEND 0xC0 // KISS CONTROL CODES +#define FESC 0xDB +#define TFEND 0xDC +#define TFESC 0xDD + +static int ProcessLine(char * buf, int Port) +{ + UCHAR * ptr,* p_cmd; + char * p_ipad = 0; + char * p_port = 0; + unsigned short WINMORport = 0; + int BPQport; + int len=510; + struct TNCINFO * TNC; + char errbuf[256]; + + strcpy(errbuf, buf); + + ptr = strtok(buf, " \t\n\r"); + + if(ptr == NULL) return (TRUE); + + if(*ptr =='#') return (TRUE); // comment + + if(*ptr ==';') return (TRUE); // comment + + if (_stricmp(buf, "ADDR")) + return FALSE; // Must start with ADDR + + ptr = strtok(NULL, " \t\n\r"); + + BPQport = Port; + p_ipad = ptr; + + TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); + memset(TNC, 0, sizeof(struct TNCINFO)); + + TNC->DefaultMode = TNC->WL2KMode = 0; // Packet 1200 + + TNC->InitScript = malloc(1000); + TNC->InitScript[0] = 0; + + if (p_ipad == NULL) + p_ipad = strtok(NULL, " \t\n\r"); + + if (p_ipad == NULL) return (FALSE); + + p_port = strtok(NULL, " \t\n\r"); + + if (p_port == NULL) return (FALSE); + + WINMORport = atoi(p_port); + + TNC->destaddr.sin_family = AF_INET; + TNC->destaddr.sin_port = htons(WINMORport); + + TNC->HostName = malloc(strlen(p_ipad)+1); + + if (TNC->HostName == NULL) return TRUE; + + strcpy(TNC->HostName,p_ipad); + + ptr = strtok(NULL, " \t\n\r"); + + if (ptr) + { + if (_stricmp(ptr, "PTT") == 0) + { + 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); + } + } + + // 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, "UPDATEMAP", 9) == 0) + TNC->PktUpdateMap = TRUE; + else if (standardParams(TNC, buf) == FALSE) + strcat(TNC->InitScript, buf); + } + return (TRUE); +} + +char * Config; +static char * ptr1, * ptr2; + +int SIXPACKGetLine(char * buf) +{ +loop: + + if (ptr2 == NULL) + return 0; + + memcpy(buf, ptr1, ptr2 - ptr1 + 2); + buf[ptr2 - ptr1 + 2] = 0; + ptr1 = ptr2 + 2; + ptr2 = strchr(ptr1, 13); + + if (buf[0] < 0x20) goto loop; + if (buf[0] == '#') goto loop; + if (buf[0] == ';') goto loop; + + if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; + if (buf[strlen(buf)-1] < 0x20) buf[strlen(buf)-1] = 0; + buf[strlen(buf)] = 13; + + return 1; +} + +VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); +VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); +VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); + +static time_t ltime; + +static VOID SendToTNC(struct TNCINFO * TNC, int Stream, UCHAR * Encoded, int EncLen) +{ + if (TNC->hDevice) + { + // Serial mode. Queue to Hostmode driver + + PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); + + if (buffptr == 0) return; // No buffers, so ignore + + buffptr->Len = EncLen; + memcpy(&buffptr->Data[0], Encoded, EncLen); + + C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); + TNC->Streams[Stream].FramesQueued++; + + return; + } +} + + +static SOCKADDR_IN sinx; +static SOCKADDR_IN rxaddr; + +static int addrlen=sizeof(sinx); + + +static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) +{ + int datalen; + PMSGWITHLEN buffptr; + char txbuff[500]; + unsigned int bytes,txlen = 0; + UCHAR * TXMsg; + + size_t Param; + int Stream = 0; + HKEY hKey=0; + struct TNCINFO * TNC = TNCInfo[port]; + struct STREAMINFO * STREAM = &TNC->Streams[0]; + struct ScanEntry * Scan; + + if (TNC == NULL) + return 0; // Port not defined + + if (TNC->CONNECTED == 0 && TNC->CONNECTING == 0) + { + // Try to reopen every 30 secs + + if (fn > 3 && fn < 7) + goto ok; + + TNC->ReopenTimer++; + + if (TNC->ReopenTimer < 150) + return 0; + + TNC->ReopenTimer = 0; + + Connectto6Pack(TNC->Port); + + return 0; + + SendInitScript(TNC); + + } +ok: + + switch (fn) + { + case 7: + + // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances + + SerialCheckRX(TNC); + return 0; + + case 1: // poll + + STREAM = &TNC->Streams[0]; + + if (STREAM->NeedDisc) + { + STREAM->NeedDisc--; + + if (STREAM->NeedDisc == 0) + { + // Send the DISCONNECT + + SerialSendCommand(TNC, "DISCONNECT\r"); + } + } + + if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && STREAM->Attached == 0) + { + // New Attach + + int calllen; + char Msg[80]; + + STREAM->Attached = TRUE; + + calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, TNC->Streams[Stream].MyCall); + TNC->Streams[Stream].MyCall[calllen] = 0; + + + // Stop other ports in same group + + SuspendOtherPorts(TNC); + + sprintf(TNC->WEB_TNCSTATE, "In Use by %s", TNC->Streams[0].MyCall); + MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); + + // Stop Scanning + + sprintf(Msg, "%d SCANSTOP", TNC->Port); + + Rig_Command( (TRANSPORTENTRY *) -1, Msg); + } + + if (STREAM->Attached) + CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete); + + // See if any frames for this port + + STREAM = &TNC->Streams[0]; + + if (STREAM->BPQtoPACTOR_Q) + { + PMSGWITHLEN buffptr = (PMSGWITHLEN)Q_REM(&STREAM->BPQtoPACTOR_Q); + UCHAR * data = &buffptr->Data[0]; + STREAM->FramesQueued--; + txlen = (int)buffptr->Len; + STREAM->BytesTXed += txlen; + + bytes=SerialSendData(TNC, data, txlen); + WritetoTrace(TNC, data, txlen); + } + + if (STREAM->PACTORtoBPQ_Q != 0) + { + buffptr = (PMSGWITHLEN)Q_REM(&STREAM->PACTORtoBPQ_Q); + + datalen = (int)buffptr->Len; + + buff->PORT = Stream; // Compatibility with Kam Driver + buff->PID = 0xf0; + memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte + datalen += sizeof(void *) + 4; + + PutLengthinBuffer(buff, datalen); + + ReleaseBuffer(buffptr); + + return (1); + } + + if (STREAM->ReportDISC) // May need a delay so treat as a counter + { + STREAM->ReportDISC--; + + if (STREAM->ReportDISC == 0) + { + buff->PORT = Stream; + return -1; + } + } + + return (0); + + case 2: // send + + Stream = 0; + + if (!TNC->CONNECTED) + return 0; // Don't try if not connected + + STREAM = &TNC->Streams[0]; + + if (TNC->SwallowSignon) + { + TNC->SwallowSignon = FALSE; // Discard *** connected + return 0; + } + + // We may get KISS packets (UI or session related) or text commands such as RADIO, CONNECT + + txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN); + + TXMsg = &buff->L2DATA[0]; + + if (buff->PID != 240) // ax.25 address + { + txlen = KissEncode(&buff->PID, txbuff, txlen); + txlen = send(TNC->TCPSock, txbuff, txlen, 0); + return 1; + } + + TXMsg[txlen - 1] = 0; + strcpy(txbuff, TXMsg); + + if (STREAM->Attached == 0) + return 0; + + if (STREAM->Connected) + { + PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); + + if (buffptr == 0) return 1; // No buffers, so ignore + + buffptr->Len = txlen; + memcpy((UCHAR *)&buffptr->Data[0], &buff->L2DATA[0], txlen); + C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); + + // connected data + + return 1; + } + + // Process as Text Command + + if (_memicmp(txbuff, "D\r", 2) == 0 || _memicmp(txbuff, "BYE\r", 4) == 0) + { + STREAM->ReportDISC = TRUE; // Tell Node + return 0; + } + + if (_memicmp(txbuff, "RADIO ", 6) == 0) + { + sprintf(&buff->L2DATA[0], "%d %s", TNC->Port, &txbuff[6]); + + if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK, &buff->L2DATA[0])) + { + } + else + { + PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); + + if (buffptr == 0) return 1; // No buffers, so ignore + + buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "%s", &buff->L2DATA[0]); + C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); + } + return 1; + } + + + if (_memicmp(txbuff, "OVERRIDEBUSY", 12) == 0) + { + PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); + + TNC->OverrideBusy = TRUE; + + if (buffptr) + { + buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "SIXPACK} OK\r"); + C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); + } + + return 0; + + } + + if (_memicmp(&buff->L2DATA[0], "SessionTimeLimit", 16) == 0) + { + if (buff->L2DATA[16] != 13) + { + PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); + + TNC->SessionTimeLimit = atoi(&buff->L2DATA[16]) * 60; + + if (buffptr) + { + buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "SIXPACK} OK\r"); + C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); + } + return 0; + } + } + + if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect + { + // Connect Command. Pass to L2 code to start session + + char * ptr = strchr(&buff->L2DATA[2], 13); + TRANSPORTENTRY * NewSess = L4TABLE; + struct _LINKTABLE * LINK; + TRANSPORTENTRY * Session = TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK; + struct PORTCONTROL * PORT = &TNC->PortRecord->PORTCONTROL; + + UCHAR axcalls[64]; + UCHAR ourcall[7]; // Call we are using (may have SSID bits inverted + int Stay = 0, Spy = 0, CQFLAG = 0, n; + + if (ptr) + *ptr = 0; + + _strupr(&buff->L2DATA[2]); + + if (DecodeCallString(&buff->L2DATA[2], &Stay, &Spy, &axcalls[0]) == 0) + { + PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); + if (buffptr) + { + buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "SIXPACK} Invalid Call\r"); + C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); + } + return 0; + } + + // Code copied from cmdc00 + + // Get Session Entry for Downlink + + NewSess = SetupNewSession(Session, NULL); + + if (NewSess == NULL) + return 0; + + NewSess->L4CIRCUITTYPE = L2LINK + DOWNLINK; + + // FORMAT LINK TABLE ENTRY FOR THIS CONNECTION + + memcpy(Session->L4USER, NewSess->L4USER, 7); + memcpy(ourcall, NewSess->L4USER, 7); + + // SSID SWAP TEST - LEAVE ALONE FOR HOST or Pactor like (unless UZ7HO) + + if ((Session->L4CIRCUITTYPE & BPQHOST))// host + goto noFlip3; + + if ((Session->L4CIRCUITTYPE & PACTOR)) + { + // incoming is Pactorlike - see if UZ7HO + + if (memcmp(Session->L4TARGET.EXTPORT->PORT_DLL_NAME, "UZ7HO", 5) != 0) + goto noFlip3; + + if (Session->L4TARGET.EXTPORT->MAXHOSTMODESESSIONS < 2) // Not multisession + goto noFlip3; + + ourcall[6] ^= 0x1e; // UZ7HO Uplink - flip + } + else + + // Must be L2 uplink - flip + + ourcall[6] ^= 0x1e; // Flip SSID + +noFlip3: + + // SET UP NEW SESSION (OR RESET EXISTING ONE) + + FindLink(axcalls, ourcall, TNC->Port, &LINK); + + if (LINK == NULL) + { + PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); + if (buffptr) + { + buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "SIXPACK} Sorry - System Tables Full\r"); + C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); + } + return 0; + } + + memcpy(LINK->LINKCALL, axcalls, 7); + memcpy(LINK->OURCALL, ourcall, 7); + + LINK->LINKPORT = PORT; + + LINK->L2TIME = PORT->PORTT1; + + // Copy Digis + + n = 7; + ptr = &LINK->DIGIS[0]; + + while (axcalls[n]) + { + memcpy(ptr, &axcalls[n], 7); + n += 7; + ptr += 7; + + LINK->L2TIME += 2 * PORT->PORTT1; // ADJUST TIMER VALUE FOR 1 DIGI + } + + LINK->LINKTYPE = 2; // DOWNLINK + LINK->LINKWINDOW = PORT->PORTWINDOW; + + RESET2(LINK); // RESET ALL FLAGS + +// if (CMD->String[0] == 'N' && SUPPORT2point2) +// LINK->L2STATE = 1; // New (2.2) send XID +// else + LINK->L2STATE = 2; // Send SABM + + LINK->CIRCUITPOINTER = NewSess; + + NewSess->L4TARGET.LINK = LINK; + + if (PORT->PORTPACLEN) + NewSess->SESSPACLEN = Session->SESSPACLEN = PORT->PORTPACLEN; + + STREAM->Connecting = TRUE; + + if (CQFLAG == 0) // if a CQ CALL DONT SEND SABM + { + if (LINK->L2STATE == 1) + L2SENDXID(LINK); + else + SENDSABM(LINK); + } + return 0; + } + + return 0; + + case 3: + + // CHECK IF OK TO SEND (And check TNC Status) + + return ((TNC->CONNECTED) << 8 | TNC->Streams[0].Disconnecting << 15); // OK + + case 4: // reinit7 + + return 0; + + case 5: // Close + + return 0; + + case 6: // Scan Stop Interface + + Param = (size_t)buff; + + if (Param == 2) // Check Permission (Shouldn't happen) + { + Debugprintf("Scan Check Permission called on SIXPACK"); + return 1; // OK to change + } + + if (Param == 1) // Request Permission + { + if (!TNC->CONNECTED) + return 0; // No connection so no interlock + + if (TNC->ConnectPending == 0 && TNC->PTTState == 0) + { + SerialSendCommand(TNC, "CONOK OFF"); + TNC->GavePermission = TRUE; + return 0; // OK to Change + } + + if (TNC->ConnectPending) + TNC->ConnectPending--; // Time out if set too long + + return TRUE; + } + + if (Param == 3) // Release Permission + { + if (TNC->GavePermission) + { + TNC->GavePermission = FALSE; + if (TNC->ARDOPCurrentMode[0] != 'S') // Skip + SerialSendCommand(TNC, "CONOK ON"); + } + return 0; + } + + // Param is Address of a struct ScanEntry + + Scan = (struct ScanEntry *)buff; + return 0; + } + return 0; +} + +VOID SIXPACKReleaseTNC(struct TNCINFO * TNC) +{ + // Set mycall back to Node or Port Call, and Start Scanner + + UCHAR TXMsg[64]; + + // Start Scanner + + sprintf(TXMsg, "%d SCANSTART 15", TNC->Port); + Rig_Command( (TRANSPORTENTRY *) -1, TXMsg); + + strcpy(TNC->WEB_TNCSTATE, "Free"); + MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); + + ReleaseOtherPorts(TNC); +} + +VOID SIXPACKSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC) +{ +} + +VOID SIXPACKReleasePort(struct TNCINFO * TNC) +{ +} + +static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) +{ + int Len = sprintf(Buff, "" + "" + "VARA Status" + "

SIXPACK Status" + "

", + TNC->Port); + + + Len += sprintf(&Buff[Len], ""); + + Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); + Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); +// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); + Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); + + Len += sprintf(&Buff[Len], "", TNC->WebBuffer); + Len = DoScanLine(TNC, Buff, Len); + + return Len; +} + + + +VOID * SIXPACKExtInit(EXTPORTDATA * PortEntry) +{ + int port; + char Msg[255]; + char * ptr; + struct TNCINFO * TNC; + char * TempScript; + struct PORTCONTROL * PORT = &PortEntry->PORTCONTROL; + + port = PORT->PORTNUMBER; + + if (TNCInfo[port]) // If restarting, free old config + free(TNCInfo[port]); + + TNC = TNCInfo[port] = malloc(sizeof(struct TNCINFO)); + memset(TNC, 0, sizeof(struct TNCINFO)); + + TNC->InitScript = malloc(1000); + TNC->InitScript[0] = 0; + + if (PortConfig[port]) // May not have config + ReadConfigFile(port, ProcessLine); + + TNC = TNCInfo[port]; + + if (TNC == NULL) + { + // Not defined in Config file + + sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); + WritetoConsole(Msg); + + return ExtProc; + } + + TNC->sixPack = zalloc(sizeof(struct sixPackTNCInfo)); + + TNC->Port = port; + TNC->Hardware = H_SIXPACK; + TNC->ARDOPBuffer = malloc(8192); + + TNC->PortRecord = PortEntry; + + if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) + memcpy(TNC->NodeCall, MYNODECALL, 10); + else + ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); + + if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) + TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; + + PortEntry->PORTCONTROL.PROTOCOL = 10; + PortEntry->PORTCONTROL.PORTQUALITY = 0; + PortEntry->PORTCONTROL.USERS = 1; // Max 1 Session + + TNC->PacketChannels = 0; + + PortEntry->MAXHOSTMODESESSIONS = 1; + + PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only + PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream + + PortEntry->PORTCONTROL.UICAPABLE = TRUE; + + if (PortEntry->PORTCONTROL.PORTPACLEN == 0) + PortEntry->PORTCONTROL.PORTPACLEN = 236; + + TNC->SuspendPortProc = SIXPACKSuspendPort; + TNC->ReleasePortProc = SIXPACKReleasePort; + +// PortEntry->PORTCONTROL.PORTSTARTCODE = KISSStartPort; +// PortEntry->PORTCONTROL.PORTSTOPCODE = KISSStopPort; + + ptr=strchr(TNC->NodeCall, ' '); + if (ptr) *(ptr) = 0; // Null Terminate + + // Set Essential Params and MYCALL + + // Put overridable ones on front, essential ones on end + + TempScript = zalloc(1000); + + // cant think of any yet + + if (TNC->InitScript) + { + strcat(TempScript, TNC->InitScript); + free(TNC->InitScript); + } + + TNC->InitScript = TempScript; + + if (TNC->WL2K == NULL) + if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Alrerady decoded + TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; + + PortEntry->PORTCONTROL.TNC = TNC; + + TNC->WebWindowProc = WebProc; + TNC->WebWinX = 520; + TNC->WebWinY = 500; + TNC->WebBuffer = zalloc(5000); + + TNC->WEB_COMMSSTATE = zalloc(100); + TNC->WEB_TNCSTATE = zalloc(100); + TNC->WEB_CHANSTATE = zalloc(100); + TNC->WEB_BUFFERS = zalloc(100); + TNC->WEB_PROTOSTATE = zalloc(100); + TNC->WEB_RESTARTTIME = zalloc(100); + TNC->WEB_RESTARTS = zalloc(100); + + TNC->WEB_MODE = zalloc(20); + TNC->WEB_TRAFFIC = zalloc(100); + + +#ifndef LINBPQ + + CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 700, 450, ForcedClose); + + CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,116,80,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,116,374,20 , TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,138,100,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,138,40,20 , TNC->hDlg, NULL, hInstance, NULL); + CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,138,100,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,138,200,20, TNC->hDlg, NULL, hInstance, NULL); + + TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | + LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, + 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); + + TNC->ClientHeight = 450; + TNC->ClientWidth = 500; + + TNC->hMenu = CreatePopupMenu(); + + AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill TNC"); + AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart TNC"); + AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); + CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); + AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); + + MoveWindows(TNC); +#endif + Consoleprintf("SIXPACK Host %s %d", TNC->HostName, htons(TNC->destaddr.sin_port)); + + Connectto6Pack(port); + + time(&TNC->lasttime); // Get initial time value + + return ExtProc; +} + + +VOID TidyClose(struct TNCINFO * TNC, int Stream) +{ + // If all acked, send disc + + if (TNC->Streams[Stream].BytesOutstanding == 0) + SerialSendCommand(TNC, "DISCONNECT\r"); +} + +VOID ForcedClose(struct TNCINFO * TNC, int Stream) +{ + SerialSendCommand(TNC, "DISCONNECT\r"); +} + +VOID CloseComplete(struct TNCINFO * TNC, int Stream) +{ + if (Stream == 0) + { + SIXPACKReleaseTNC(TNC); + } +} + + +static int KissDecode(UCHAR * inbuff, UCHAR * outbuff, int len) +{ + int i,txptr=0; + UCHAR c; + + for (i=0;iInputLen > 8000) // Shouldnt have packets longer than this + TNC->InputLen=0; + + InputLen = recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8192 - TNC->InputLen, 0); + + if (InputLen == 0 || InputLen == SOCKET_ERROR) + { + // Does this mean closed? + + int err = GetLastError(); + + closesocket(TNC->TCPSock); + + TNC->TCPSock = 0; + + TNC->CONNECTED = FALSE; + TNC->Streams[0].ReportDISC = TRUE; + + sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + return; + } + + TNC->InputLen += InputLen; + + // Extract and decode KISS frames + + ptr = memchr(TNC->ARDOPBuffer + 1, FEND, TNC->InputLen - 1); // Ignore leading FEND + + while (ptr) // FEND in buffer + { + ptr++; + + MsgLen = ptr - TNC->ARDOPBuffer; + + if (MsgLen > 360) + { + TNC->InputLen = 0; + return; + } + + TNC->InputLen -= MsgLen; + + if (MsgLen > 1) + { + PMESSAGE Buff = GetBuff(); + + MsgLen = KissDecode(TNC->ARDOPBuffer, Buffer, MsgLen); + + // we dont need the FENDS or control byte + + MsgLen -= 3; + + if (Buff) + { + memcpy(&Buff->DEST, &Buffer[2], MsgLen); + MsgLen += (3 + sizeof(void *)); + + PutLengthinBuffer((PDATAMESSAGE)Buff, MsgLen); // Needed for arm5 portability + + C_Q_ADD(&TNC->PortRecord->PORTCONTROL.PORTRX_Q, (UINT *)Buff); + } + } + + if (TNC->InputLen == 0) + return; + + memmove(TNC->ARDOPBuffer, ptr, TNC->InputLen); + ptr = memchr(TNC->ARDOPBuffer + 1, FEND, TNC->InputLen - 1); // Ignore leading FEND + } + +} + + + +/* + +// we dont need the control byte + +len --; + +if (Buffer) +{ +memcpy(&Buffer->DEST, &Port->RXMSG[1], len); +len += (3 + sizeof(void *)); + +PutLengthinBuffer((PDATAMESSAGE)Buffer, len); // Needed for arm5 portability + +C_Q_ADD(TNC->PortRecord->PORTCONTROL.PORTRX_Q, (UINT *)Buffer); +} + +*/ + +// TNC->InputLen -= MsgLen; +// goto loop; + + + + +void AttachSIXPACK(struct PORTCONTROL * PORT, MESSAGE * Buffer) +{ + // SABM on HFKISS port. L2 code will accepr call and connect to appl if necessary, but + // need to attach the port + + char Call[16] = ""; + char OrigCall[16] = ""; + struct TNCINFO * TNC = PORT->TNC; + struct WL2KInfo * WL2K = TNC->WL2K; + + if (TNC->PortRecord->ATTACHEDSESSIONS[0] == 0) + { + TRANSPORTENTRY * SESS; + struct TNCINFO * TNC = PORT->TNC; + + // Incoming Connect + + Call[ConvFromAX25(Buffer->DEST, Call)] = 0; + OrigCall[ConvFromAX25(Buffer->ORIGIN, OrigCall)] = 0; + + // Stop other ports in same group + + SuspendOtherPorts(TNC); + + TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit + + ProcessIncommingConnectEx(TNC, Call, 0, FALSE, FALSE); + + SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; + + SESS->Mode = TNC->WL2KMode; + + TNC->ConnectPending = FALSE; + + if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", OrigCall, Call, TNC->RIG->Valchar); + SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq + if (SESS->Frequency == 1500) + { + // try to get from WL2K record + + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + } + } + SESS->Mode = TNC->WL2KMode; + } + else + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", OrigCall, Call); + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + SESS->Mode = WL2K->mode; + } + } + + if (WL2K) + strcpy(SESS->RMSCall, WL2K->RMSCall); + + MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); + } +} + +void DetachSIXPACK(struct PORTCONTROL * PORT) +{ + // L2 Link Closed. Detach. + + struct TNCINFO * TNC = PORT->TNC; + struct STREAMINFO * STREAM = &TNC->Streams[0]; + + if (STREAM->Attached) + STREAM->ReportDISC = TRUE; // Tell Node + + STREAM->Connecting = FALSE; + STREAM->Connected = FALSE; + +} + +void SIXPACKConnected(struct PORTCONTROL * PORT, struct _LINKTABLE * LINK) +{ + // UA received when connecting + + struct TNCINFO * TNC = PORT->TNC; + struct STREAMINFO * STREAM = &TNC->Streams[0]; + struct WL2KInfo * WL2K = TNC->WL2K; + + TRANSPORTENTRY * SESS; + char Call[16] = ""; + char OrigCall[16] = ""; + + + if (STREAM->Connecting) + { + STREAM->Connecting = FALSE; + STREAM->Connected = TRUE; + + Call[ConvFromAX25(LINK->LINKCALL, Call)] = 0; + OrigCall[ConvFromAX25(LINK->OURCALL, OrigCall)] = 0; + + TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit + + SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; + SESS->Mode = TNC->WL2KMode; + + if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound Freq %s", OrigCall, Call, TNC->RIG->Valchar); + SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq + + if (SESS->Frequency == 1500) + { + // try to get from WL2K record + + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + } + } + SESS->Mode = TNC->WL2KMode; + } + else + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", OrigCall, Call); + + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + SESS->Mode = WL2K->mode; + } + } + + if (WL2K) + strcpy(SESS->RMSCall, WL2K->RMSCall); + + MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); + } +} + + + +VOID x6PackThead(void * portptr); + +int Connectto6Pack(int port) +{ + _beginthread(x6PackThead, 0, (void *)(size_t)port); + + return 0; +} + +VOID x6PackThead(void * portptr) +{ + // 6pack over TNC thread + + // Opens socket and looks for data + + int port = (int)(size_t)portptr; + char Msg[255]; + int err, i, ret; + u_long param=1; + BOOL bcopt=TRUE; + struct hostent * HostEnt; + struct TNCINFO * TNC = TNCInfo[port]; + fd_set readfs; + fd_set errorfs; + struct timeval timeout; + char * ptr1; + char * ptr2; + UINT * buffptr; + int reinitTimer = 0; + int linkactive = 0; + + struct sixPackPortInfo * sixPack = TNC->sixPack; + + if (sixPack == NULL || TNC->HostName == NULL) + return; + + TNC->BusyFlags = 0; + + TNC->CONNECTING = TRUE; + + Sleep(3000); // Allow init to complete + +#ifdef WIN32 + if (strcmp(TNC->HostName, "127.0.0.1") == 0) + { + // can only check if running on local host + + TNC->PID = GetListeningPortsPID(TNC->destaddr.sin_port); + if (TNC->PID == 0) + { + TNC->CONNECTING = FALSE; + return; // Not listening so no point trying to connect + } + + // Get the File Name in case we want to restart it. + + if (TNC->ProgramPath == NULL) + { + if (GetModuleFileNameExPtr) + { + HANDLE hProc; + char ExeName[256] = ""; + + hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); + + if (hProc) + { + GetModuleFileNameExPtr(hProc, 0, ExeName, 255); + CloseHandle(hProc); + + TNC->ProgramPath = _strdup(ExeName); + } + } + } + } +#endif + +// // If we started the TNC make sure it is still running. + +// if (!IsProcess(TNC->PID)) +// { +// RestartTNC(TNC); +// Sleep(3000); +// } + + + TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); + + if (TNC->destaddr.sin_addr.s_addr == INADDR_NONE) + { + // Resolve name to address + + HostEnt = gethostbyname (TNC->HostName); + + if (!HostEnt) + { + TNC->CONNECTING = FALSE; + return; // Resolve failed + } + memcpy(&TNC->destaddr.sin_addr.s_addr,HostEnt->h_addr,4); + memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); + } + +// closesocket(TNC->TCPSock); + + TNC->TCPSock=socket(AF_INET,SOCK_STREAM,0); + + if (TNC->TCPSock == INVALID_SOCKET) + { + i=sprintf(Msg, "Socket Failed for 6Pack socket - error code = %d\r\n", WSAGetLastError()); + WritetoConsole(Msg); + + TNC->CONNECTING = FALSE; + return; + } + + setsockopt(TNC->TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); + + sinx.sin_family = AF_INET; + sinx.sin_addr.s_addr = INADDR_ANY; + sinx.sin_port = 0; + + if (connect(TNC->TCPSock,(LPSOCKADDR) &TNC->destaddr,sizeof(TNC->destaddr)) == 0) + { + // + // Connected successful + // + } + else + { + if (TNC->Alerted == FALSE) + { + err=WSAGetLastError(); + i=sprintf(Msg, "Connect Failed for 6Pack socket - error code = %d\r\n", err); + WritetoConsole(Msg); + sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + TNC->Alerted = TRUE; + } + + closesocket(TNC->TCPSock); + TNC->TCPSock = 0; + TNC->CONNECTING = FALSE; + return; + } + + Sleep(1000); + + TNC->LastFreq = 0; // so V4 display will be updated + + TNC->CONNECTING = FALSE; + TNC->CONNECTED = TRUE; + TNC->BusyFlags = 0; + TNC->InputLen = 0; + + TNC->Alerted = TRUE; + + sprintf(TNC->WEB_COMMSSTATE, "Connected to TNC"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + FreeSemaphore(&Semaphore); + + sprintf(Msg, "Connected to TNC Port %d\r\n", TNC->Port); + WritetoConsole(Msg); + + while (TNC->CONNECTED) + { + FD_ZERO(&readfs); + FD_ZERO(&errorfs); + + FD_SET(TNC->TCPSock,&readfs); + FD_SET(TNC->TCPSock,&errorfs); + + timeout.tv_sec = 1; + timeout.tv_usec = 0; // We use this to run timeouts + + ret = select((int)TNC->TCPSock + 1, &readfs, NULL, &errorfs, &timeout); + + if (ret == SOCKET_ERROR) + { + Debugprintf("6Pack Select failed %d ", WSAGetLastError()); + goto Lost; + } + if (ret > 0) + { + // See what happened + + if (FD_ISSET(TNC->TCPSock, &readfs)) + { + GetSemaphore(&Semaphore, 52); + SixPackProcessReceivedPacket(TNC); + FreeSemaphore(&Semaphore); + } + + if (FD_ISSET(TNC->TCPSock, &errorfs)) + { +Lost: + sprintf(Msg, "6Pack Connection lost for Port %d\r\n", TNC->Port); + WritetoConsole(Msg); + + sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + TNC->CONNECTED = FALSE; + TNC->Alerted = FALSE; + + if (TNC->PTTMode) + Rig_PTT(TNC, FALSE); // Make sure PTT is down + + if (TNC->Streams[0].Attached) + TNC->Streams[0].ReportDISC = TRUE; + + TNC->TCPSock = 0; + return; + } + } + else + { + // Timeout. See if we need to reinit tnc chain + + if (sixPack->linkOK == 0) + { + sixPack->reinitTimer++; + if (sixPack->reinitTimer > 30) + { + // send SIXP_INIT_CMD which should rescan the tnc chain + + unsigned char Msg = SIXP_INIT_CMD; + int txlen = send(TNC->TCPSock, &Msg, 1, 0); + sixPack->reinitTimer = 0; + } + } + } + + } + sprintf(Msg, "6Pack Thread Terminated Port %d\r\n", TNC->Port); + WritetoConsole(Msg); +} + + + + + + diff --git a/ARDOP.c b/ARDOP.c index 01ee591..61fab6b 100644 --- a/ARDOP.c +++ b/ARDOP.c @@ -880,6 +880,17 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) } } + // Check ATTACH time limit + + if (STREAM->Attached) + { + if (STREAM->AttachTime && TNC->AttachTimeLimit && time(NULL) > (TNC->AttachTimeLimit + STREAM->AttachTime)) + { + STREAM->ReportDISC = 1; + STREAM->AttachTime = 0; + } + } + if (TNC->ARDOPCommsMode != 'T') // S I or E { ARDOPSCSCheckRX(TNC); @@ -1190,6 +1201,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) Debugprintf("ARDOP New Attach Stream %d DEDStream %d", Stream, STREAM->DEDStream); STREAM->Attached = TRUE; + STREAM->AttachTime = time(NULL); calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, TNC->Streams[Stream].MyCall); TNC->Streams[Stream].MyCall[calllen] = 0; diff --git a/BBSUtilities.c b/BBSUtilities.c index d62b3c5..a3b9bd8 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -11762,300 +11762,258 @@ BOOL CheckforMIME(SocketConn * sockptr, char * Msg, char ** Body, int * MsgLen); #include #include -typedef struct _POPENRET -{ - FILE * fp; - pid_t pid; -} POPENRET; +// G8BPQ Version of Steve G7TAJ's code -/* -* Check if the PG is still running after 5 sec -* if so, kill it +int pgret = 9999; +int pindex = 0; + +void sigchild_handler(int sig , siginfo_t * siginfo, void * ucontext) +{ +/* • SIGCHLD fills in si_pid, si_uid, si_status, si_utime, and + si_stime, providing information about the child. The si_pid + field is the process ID of the child; si_uid is the child's + real user ID. The si_status field contains the exit status of + the child (if si_code is CLD_EXITED), or the signal number + that caused the process to change state. */ -void run_pgTimeoutThread( pid_t process ) -{ -// printf("watchdog thread: PID of subprocess: %d\n", process); -// fflush(stdout); - Sleep(5000); - // if still running PID (?) then kill. - if ( getpgid(process) >= 0 ) - { - Debugprintf("watchdog thread: Still running, so killing %d ... ", process); - if ( kill( -process, SIGKILL ) == 0 ) - Debugprintf("Killed PG watchdog Process %d", process); - else - Debugprintf("Failed to kill PG watchdog Process %d", process); - } - -// Debugprintf("watchdog thread: PID=%d Exit", process); -// fflush(stdout); +// printf("SIGCHLD PID %d Code %d status %d\n", siginfo->si_pid, siginfo->si_code, siginfo->si_status); + pgret = siginfo->si_status; } -//https://sources.debian.org/src/cron/3.0pl1-45/popen.c/ - -POPENRET my_popen(char *program, char *type, CIRCUIT *conn) +void run_pg(CIRCUIT * conn, struct UserInfo * user) { register char *cp; FILE *iop; int argc, pdes[2]; pid_t pid; - POPENRET PRET; - if (*type != 'r' && *type != 'w' || type[1]) - return(PRET); - if (pipe(pdes) < 0) - return(PRET); + pgret = 9999; + + int index = user->Temp->PG_INDEX; iop = NULL; - switch(pid = fork()) { + + conn->InputBuffer[conn->InputLen] = 0; + strlop(conn->InputBuffer, 13); + conn->InputLen = 0; + + if (!user->Temp->RUNPGPARAMS) + user->Temp->RUNPGPARAMS = (RUNPGARGS_PTR) zalloc(sizeof(RUNPGARGS)); + + user->Temp->RUNPGPARAMS->user = user; + user->Temp->RUNPGPARAMS->conn = conn; + strncpy(user->Temp->RUNPGPARAMS->InputBuffer, conn->InputBuffer, 80); // needs to be length of actual input! + user->Temp->RUNPGPARAMS->Len = conn->InputLen; + + if (conn == 0 || user == 0) + { + Debugprintf("run_pg conn or user null"); + return; + } + + // Build command line. Parmas are: + + // - Callsign (format as F6FBB-8). + // - Level number (0 is the first time, up to 99). + // - Flags of the user (binary number as user`s mask of INIT.SRV). + // - Record number of the user in INF.SYS. + // - Received data (each word is a new argument). + + // BPQ doesn't support params 3 and 4 (but may supply copy of user record later) + + char cmd[20]; + char *ptr = cmd; + char pg_dir[MAX_PATH]; + char log_file[50] = "pg.log"; + char call[10]; + char data[80]; + char line[80]; + size_t bufsize = 80; + + strcpy(pg_dir, BaseDir); + strcat(pg_dir, "/PG/"); + sprintf(cmd, "./%s", SERVERLIST[user->Temp->PG_SERVER][1] ); + + sprintf(line, "%s%s", pg_dir, SERVERLIST[user->Temp->PG_SERVER][1]); +// printf("PG Prog %s%s\n", pg_dir, SERVERLIST[user->Temp->PG_SERVER][1]); + + // check file exists and is executable + + if (access(line, F_OK) == -1 || access(line, X_OK) == -1) + { + Debugprintf("%s FileNotFound || not executable", line); + BBSputs(conn, "Error running PG Server\r"); + conn->InputMode=0; + SendPrompt(conn, user); + return; + } + + strcpy(call, conn->UserPointer->Call); + index = user->Temp->PG_INDEX; + + // remove ';' from input for security reasons + + ptr = strchr(user->Temp->RUNPGPARAMS->InputBuffer, ';'); + if (ptr) + *ptr = '\0'; + + sprintf(data, "%s %d 0 0 %s", call, index, user->Temp->RUNPGPARAMS->InputBuffer); +// printf("PG Params %s\n", data); + + conn->InputBufferLen = 0; + + char buf[256]; + + sprintf (buf, "%s %s", line, data); // buf is command to exec +// printf ("PG exec cmd %s\n", buf); + + // Create pipe for reading PG program STDOUT + + if (pipe(pdes) < 0) + { + Debugprintf("run_pg pipe failed"); + BBSputs(conn, "Error running PG Server (pipe() failed)\r"); + conn->InputMode=0; + SendPrompt(conn, user); + return; + } + + // We will just fork and execute program. For now don't create a new thread + + // Trap sigchild so we can tell when it exits and get return code + + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); + act.sa_flags = SA_RESETHAND | SA_SIGINFO; // Restore default handler when called + act.sa_sigaction = sigchild_handler; + sigaction(SIGCHLD, &act, NULL); + + switch(pid = fork()) + { case -1: /* error */ (void)close(pdes[0]); (void)close(pdes[1]); - return PRET; + Debugprintf("run_pg fork failed"); + BBSputs(conn, "Error running PG Server (fork() failed)\r"); + conn->InputMode=0; + SendPrompt(conn, user); + + return; + case 0: /* child */ - if (*type == 'r') { - if (pdes[1] != 1) { - dup2(pdes[1], 1); - dup2(pdes[1], 2); - (void)close(pdes[1]); - } - (void)close(pdes[0]); - } else { - if (pdes[0] != 0) { - dup2(pdes[0], 0); - (void)close(pdes[0]); - } + + if (pdes[1] != 1) + { + dup2(pdes[1], 1); + dup2(pdes[1], 2); (void)close(pdes[1]); } - setpgid(-pid,pid); - char *args[] = {"sh", "-c", program, NULL}; - execve("/bin/sh", args, NULL); + (void)close(pdes[0]); + + setpgid(0, pid); + + char *args[] = {"sh", "-c", buf, NULL}; + execve("/bin/sh", args, NULL); + _exit(1); } /* parent */ - _beginthread((void (*)(void *))run_pgTimeoutThread, 0, (VOID *) pid ); +// printf("child PID %d\n", pid); - if (*type == 'r') { - iop = fdopen(pdes[0], type); - (void)close(pdes[1]); - } else { - iop = fdopen(pdes[1], type); - (void)close(pdes[0]); + struct timespec duration; + duration.tv_sec = 5; + duration.tv_nsec = 0; + + nanosleep(&duration, &duration); // Will be interrupted by SIGCHLD + +// printf("PG retcode %d\n", pgret); + + if (pgret == 9999) // Process still running + { + BBSputs(conn, "PG Program Looping\r"); + kill(pid, SIGKILL); + user->Temp->PG_INDEX = 0; + conn->InputMode=0; + SendPrompt(conn, user); + return; } + if (pgret > 127) + { + // Probably killed by signal + + int err = pgret - 128; + char errmsg[256]; + + sprintf(errmsg, "PG Signal %s received\n", strsignal(err)); + + BBSputs(conn, errmsg); + user->Temp->PG_INDEX = 0; + conn->InputMode=0; + SendPrompt(conn, user); + return; + } + + // Send STDOUT from PG program to BBS user + + iop = fdopen(pdes[0], "r"); + (void)close(pdes[1]); + char buffer[128]; while (fgets(buffer, sizeof(buffer), iop) != NULL) { BBSputs(conn, buffer); buffer[0] = '\0'; } - PRET.fp = iop; - PRET.pid= pid; - return(PRET); -} - -int -my_pclose( POPENRET pret ) -{ - register int fdes; - sigset_t omask, mask; - int stat_loc; - pid_t pid; - FILE * iop = pret.fp; - - fdes = fileno(iop); - (void)fclose(iop); - - sigemptyset(&mask); - sigaddset(&mask, SIGQUIT); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &omask); - pid = waitpid(pret.pid, &stat_loc, 0); - sigprocmask(SIG_SETMASK, &omask, NULL); - if (pid == -1 || !WIFEXITED(stat_loc)) - return -1; - return stat_loc; -} - - -int run_server (char **cmd, int nb_cmd, int mode, char *log, char *pgdir, char *data, CIRCUIT * conn) -{ - int i; - int ret = 0; - FILE *fp; - POPENRET PRET; - pid_t pid; - char *ptr; - char file[256]; - char buf[256]; - char dir[256]; - char arg[256]; - - if (mode) - // sprintf (file, " >>%s", log); - // sprintf (file, " | tee -a %s", log); - sprintf(file, "" ); - else - sprintf (file, " InputMode=0; + SendPrompt(conn, user); + break; + case 1: + index++; // inc & keep in PG + break; - sprintf (dir, "cd %s ; ", pgdir); - } - else - *dir = '\0'; + case 2: + + index=0; // disconnect + conn->InputMode=0; + Disconnect(conn->BPQStream); + break; - *arg = '\0'; + case 3: + Debugprintf("data->BBS & end"); + break; - if (data) - { - /* remove ';' security reasons */ - ptr = strchr(data, ';'); - if (ptr) - *ptr = '\0'; + case 4: + Debugprintf("data->BBS and inc %d", pindex++); + break; + case 5: + Debugprintf("call no inc %d", pgret); + break; - sprintf (arg, " %s ", data); - } - - - for (i = 0; i < nb_cmd; i++) - { - /* remove ';' security reasons */ - ptr = strchr(cmd[i], ';'); - if (ptr) - *ptr = '\0'; - - sprintf (buf, "%s%s%s%s", dir, cmd[i], arg, file); - - PRET = my_popen (buf, "r", conn); - - if (PRET.fp == NULL) - Debugprintf ("Failed to run PG command %s\n", cmd[i] ); - - ret = my_pclose( PRET ); - ret = ret >> 8; - - if (verbose) { - Debugprintf ("Debug: command = {%s}\n", buf); - Debugprintf ("Debug: exit code = %d\n", ret); - } - - /* fail-safe bypass if executable isn't found (exit code 127) (was ret ==127)*/ - if (ret > 5) // should never be more than 5 - ret = 0; - } - return ( ret ); -} - - -void run_pg( CIRCUIT * conn, struct UserInfo * user ) -{ - - if (!user->Temp->RUNPGPARAMS) { - user->Temp->RUNPGPARAMS = (RUNPGARGS_PTR) zalloc(sizeof(RUNPGARGS)); - } - - user->Temp->RUNPGPARAMS->user = user; - user->Temp->RUNPGPARAMS->conn = conn; - strncpy(user->Temp->RUNPGPARAMS->InputBuffer, conn->InputBuffer, 80); // needs to be length of actual input! - user->Temp->RUNPGPARAMS->Len = conn->InputLen; - - if ( conn == 0 || user == 0 ) { - Debugprintf("run_pg null err"); - return; - } - - _beginthread((void (*)(void *))startrun_pgThread, 0, user->Temp->RUNPGPARAMS ); - - return; -} - - -void startrun_pgThread( RUNPGARGS_PTR Args ) { - - CIRCUIT * conn = Args->conn; - struct UserInfo * user = Args->user; - - char cmd[20]; - sprintf( cmd, "./%s", SERVERLIST[user->Temp->PG_SERVER][1] ); - char *ptr = cmd; - char pg_dir[MAX_PATH]; - char log_file[50] = "pg.log"; - char call[6]; - char data[80]; - char line[80]; - char *line_ptr = line; - int index; - char *data_ptr = data; - size_t bufsize = 80; - - strcpy(pg_dir, BaseDir); - strcat(pg_dir, "/PG/"); - - sprintf(line, "%s%s", pg_dir, SERVERLIST[user->Temp->PG_SERVER][1]); - - // check file exists and is executable - if (access(line, F_OK) == -1 || access(line, X_OK) == -1) { - Debugprintf("%s FileNotFound || Not EXE", line); - BBSputs(conn, "Error running PG Server\r"); + default: + BBSputs(conn, "PG unexexpected response\r"); + user->Temp->PG_INDEX = 0; conn->InputMode=0; SendPrompt(conn, user); return; } - strcpy( call, conn->UserPointer->Call); - // sprintf( log_file, "%s-%d.log", call, conn); - index = user->Temp->PG_INDEX; + user->Temp->PG_INDEX = index; - line[0] = '\0'; - int Len = Args->Len; - UCHAR * Msg = Args->InputBuffer; - strncpy( line, Msg, Len); - line[ Len - 1 ] = 0; //remove LF - - sprintf( data, "%s %d 0 0 %s", call, index, line); - - // clear the input queue - conn->InputLen = 0; - conn->InputBufferLen = 0; - - int ret = run_server (&ptr, 1, 1, log_file, pg_dir, data_ptr, conn); - - switch (ret) - { - case -1: // ERROR or forced closed - case 0: index=0; // Goodbye/Exit - conn->InputMode=0; - SendPrompt(conn, user); - break; - case 1: index++; // inc & keep in PG - break; - case 2: index=0; // disconnect - conn->InputMode=0; - Disconnect(conn->BPQStream); - break; - case 3: Debugprintf("data->BBS & end"); - break; - case 4: Debugprintf("data->BBS and inc %d", index++); - break; - case 5: Debugprintf("call no inc %d", ret); - break; - - } - - user->Temp->PG_INDEX=index; +// printf("runpg return index = %d\n", index); } + + /*---- G7TAJ END ----- */ #else @@ -12076,7 +12034,7 @@ void ReadFromPipe(void); void run_pg( CIRCUIT * conn, struct UserInfo * user ) { - // Run PG program, rend anything from program's stdout to the user + // Run PG program, read anything from program's stdout to the user int retcode = -1; SECURITY_ATTRIBUTES saAttr; @@ -12251,7 +12209,7 @@ void run_pg( CIRCUIT * conn, struct UserInfo * user ) case 4: - // Send Output to BBS - was down above + // Send Output to BBS - was done above break; case 5: diff --git a/BPQChat.vcproj.NOTTSDESKTOP.John.user b/BPQChat.vcproj.NOTTSDESKTOP.John.user new file mode 100644 index 0000000..fa82c00 --- /dev/null +++ b/BPQChat.vcproj.NOTTSDESKTOP.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/BPQMail.c b/BPQMail.c index e528f98..402d87f 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1137,6 +1137,7 @@ // Improve "New User" frequency determination (39) // Allow selection of 2 or 4 character country codes for forward processing (39) // Fix Send P to multiple BBS's when routing on HR (40) +// Rewrite PG server code on Lunux (41) #include "bpqmail.h" #include "winstdint.h" diff --git a/BPQMail.vcproj.NOTTSDESKTOP.John.user b/BPQMail.vcproj.NOTTSDESKTOP.John.user new file mode 100644 index 0000000..fa82c00 --- /dev/null +++ b/BPQMail.vcproj.NOTTSDESKTOP.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/BPQMail.vcproj.SKIGACER.johnw.user b/BPQMail.vcproj.SKIGACER.johnw.user new file mode 100644 index 0000000..b5b0536 --- /dev/null +++ b/BPQMail.vcproj.SKIGACER.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user new file mode 100644 index 0000000..0cd9a72 --- /dev/null +++ b/BPQWinAPP.vcproj.LAPTOP-Q6S4RP5Q.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user new file mode 100644 index 0000000..fa82c00 --- /dev/null +++ b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/Bpq32.c b/Bpq32.c index 7059a56..d98b6ea 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1219,6 +1219,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Fix ICF8101 Mode setting (37) // Kill link if we are getting repeated RR(F) after timeout // (Indicating other station is seeing our RR(P) but not the resent I frame) (40) +// Change default of SECURETELNET to 1 (41) +// Add optional ATTACH time limit for ARDOP (42) +// Fix buffer overflow risk in HTTP Terminal(42) @@ -1313,6 +1316,7 @@ void * KISSHFExtInit(EXTPORTDATA * PortEntry); void * WinRPRExtInit(EXTPORTDATA * PortEntry); void * HSMODEMExtInit(EXTPORTDATA * PortEntry); void * FreeDataExtInit(EXTPORTDATA * PortEntry); +void * SIXPACKExtInit(EXTPORTDATA * PortEntry); extern char * ConfigBuffer; // Config Area VOID REMOVENODE(dest_list * DEST); @@ -3950,6 +3954,9 @@ VOID * InitializeExtDriver(PEXTPORTDATA PORTVEC) if (strstr(Value, "FREEDATA")) return FreeDataExtInit; + if (strstr(Value, "6PACK")) + return SIXPACKExtInit; + ExtDriver = LoadLibrary(Value); if (ExtDriver == NULL) diff --git a/CBPQ32.vcproj b/CBPQ32.vcproj index 0648ae6..a580f7a 100644 --- a/CBPQ32.vcproj +++ b/CBPQ32.vcproj @@ -57,7 +57,7 @@ UsePrecompiledHeader="0" AssemblerOutput="2" AssemblerListingLocation="c:\devprogs\bpq32\listings\debug\" - BrowseInformation="0" + BrowseInformation="1" WarningLevel="3" Detect64BitPortabilityProblems="false" DebugInformationFormat="4" @@ -234,6 +234,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + diff --git a/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user new file mode 100644 index 0000000..ddedde2 --- /dev/null +++ b/CBPQ32.vcproj.LAPTOP-Q6S4RP5Q.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/CBPQ32.vcproj.NOTTSDESKTOP.John.user b/CBPQ32.vcproj.NOTTSDESKTOP.John.user new file mode 100644 index 0000000..270b67b --- /dev/null +++ b/CBPQ32.vcproj.NOTTSDESKTOP.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/CBPQ32.vcproj.SKIGACER.johnw.user b/CBPQ32.vcproj.SKIGACER.johnw.user new file mode 100644 index 0000000..f8a6101 --- /dev/null +++ b/CBPQ32.vcproj.SKIGACER.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/CommonCode.c b/CommonCode.c index 3b7fb70..48a253d 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -4859,7 +4859,6 @@ DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqString) struct TNCINFO * TNC; struct RIGINFO * RIG = 0; - int RigPort; if (PORT->RIGPort) TNC = TNCInfo[PORT->RIGPort]; @@ -5089,6 +5088,8 @@ void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) int len; char * ptr; char mhstr[400]; + int i; + char c; if (MH == NULL) return; @@ -5110,7 +5111,16 @@ void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) continue; } - Normcall[len++] = 0; + // validate call to prevent corruption of json + + for (i=0; i < len; i++) + { + c = Normcall[i]; + + if (!isalnum(c) && !(c == '#') && !(c == ' ') && !(c == '-')) + goto skipit; + } + //format TIME @@ -5123,7 +5133,7 @@ void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) Normcall, PORT->PORTNUMBER, MH->MHCOUNT, MHTIME); strcat( MHJSON, mhstr ); - +skipit: MH++; } } diff --git a/HFCommon.c b/HFCommon.c index 00af093..c5f639a 100644 --- a/HFCommon.c +++ b/HFCommon.c @@ -1876,6 +1876,8 @@ int standardParams(struct TNCINFO * TNC, char * buf) TNC->WL2K = DecodeWL2KReportLine(buf); else if (_memicmp(buf, "SESSIONTIMELIMIT", 16) == 0) TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit = atoi(&buf[17]) * 60; + else if (_memicmp(buf, "ATTACHTIMELIMIT", 15) == 0) + TNC->AttachTimeLimit = atoi(&buf[16]) * 60; else if (_memicmp(buf, "BUSYHOLD", 8) == 0) // Hold Time for Busy Detect TNC->BusyHold = atoi(&buf[8]); else if (_memicmp(buf, "BUSYWAIT", 8) == 0) // Wait time before failing connect if busy diff --git a/HTTPcode.c b/HTTPcode.c index 367146d..e1ddfbe 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -600,7 +600,8 @@ VOID HTTPTimer() for (n = Last;;) { - strcat(_REPLYBUFFER, Session->ScreenLines[n]); + if ((strlen(Session->ScreenLines[n]) + strlen(_REPLYBUFFER)) < 99999) + strcat(_REPLYBUFFER, Session->ScreenLines[n]); if (n == 99) n = -1; @@ -680,13 +681,15 @@ struct HTTPConnectionInfo * FindSession(char * Key) void ProcessTermInput(SOCKET sock, char * MsgPtr, int MsgLen, char * Key) { - char _REPLYBUFFER[1024]; + char _REPLYBUFFER[2048]; int ReplyLen; char Header[256]; int HeaderLen; int State; struct HTTPConnectionInfo * Session = FindSession(Key); int Stream; + int maxlen = 1000; + if (Session == NULL) { @@ -701,12 +704,24 @@ void ProcessTermInput(SOCKET sock, char * MsgPtr, int MsgLen, char * Key) char c; UCHAR hex; + int msglen = end - input; + struct TNCINFO * TNC = Session->TNC; struct TCPINFO * TCP = 0; if (TNC) TCP = TNC->TCPInfo; + if (TCP && TCP->WebTermCSS) + maxlen -= strlen(TCP->WebTermCSS); + + if (MsgLen > maxlen) + { + Session->KillTimer = 99999; // close session + return; + } + + if (TCP && TCP->WebTermCSS) ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, TCP->WebTermCSS); else diff --git a/LinBPQ.c b/LinBPQ.c index 6146500..27dc550 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -1077,216 +1077,211 @@ int main(int argc, char * argv[]) BBSApplMask = 1<<(BBSApplNum-1); - // See if we need to warn of possible problem with BaseDir moved by installer + // See if we need to warn of possible problem with BaseDir moved by installer - sprintf(BaseDir, "%s", BPQDirectory); + sprintf(BaseDir, "%s", BPQDirectory); - // Set up file and directory names + // Set up file and directory names - strcpy(UserDatabasePath, BaseDir); - strcat(UserDatabasePath, "/"); - strcat(UserDatabasePath, UserDatabaseName); + strcpy(UserDatabasePath, BaseDir); + strcat(UserDatabasePath, "/"); + strcat(UserDatabasePath, UserDatabaseName); - strcpy(MsgDatabasePath, BaseDir); - strcat(MsgDatabasePath, "/"); - strcat(MsgDatabasePath, MsgDatabaseName); + strcpy(MsgDatabasePath, BaseDir); + strcat(MsgDatabasePath, "/"); + strcat(MsgDatabasePath, MsgDatabaseName); - strcpy(BIDDatabasePath, BaseDir); - strcat(BIDDatabasePath, "/"); - strcat(BIDDatabasePath, BIDDatabaseName); + strcpy(BIDDatabasePath, BaseDir); + strcat(BIDDatabasePath, "/"); + strcat(BIDDatabasePath, BIDDatabaseName); - strcpy(WPDatabasePath, BaseDir); - strcat(WPDatabasePath, "/"); - strcat(WPDatabasePath, WPDatabaseName); + strcpy(WPDatabasePath, BaseDir); + strcat(WPDatabasePath, "/"); + strcat(WPDatabasePath, WPDatabaseName); - strcpy(BadWordsPath, BaseDir); - strcat(BadWordsPath, "/"); - strcat(BadWordsPath, BadWordsName); + strcpy(BadWordsPath, BaseDir); + strcat(BadWordsPath, "/"); + strcat(BadWordsPath, BadWordsName); - strcpy(NTSAliasesPath, BaseDir); - strcat(NTSAliasesPath, "/"); - strcat(NTSAliasesPath, NTSAliasesName); + strcpy(NTSAliasesPath, BaseDir); + strcat(NTSAliasesPath, "/"); + strcat(NTSAliasesPath, NTSAliasesName); - strcpy(MailDir, BaseDir); - strcat(MailDir, "/"); - strcat(MailDir, "Mail"); + strcpy(MailDir, BaseDir); + strcat(MailDir, "/"); + strcat(MailDir, "Mail"); #ifdef WIN32 - CreateDirectory(MailDir, NULL); // Just in case + CreateDirectory(MailDir, NULL); // Just in case #else - mkdir(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); - chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); + mkdir(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); + chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); #endif - // Make backup copies of Databases + // Make backup copies of Databases -// CopyConfigFile(ConfigName); + // CopyConfigFile(ConfigName); - CopyBIDDatabase(); - CopyMessageDatabase(); - CopyUserDatabase(); - CopyWPDatabase(); + CopyBIDDatabase(); + CopyMessageDatabase(); + CopyUserDatabase(); + CopyWPDatabase(); - SetupMyHA(); - SetupFwdAliases(); - SetupNTSAliases(NTSAliasesPath); + SetupMyHA(); + SetupFwdAliases(); + SetupNTSAliases(NTSAliasesPath); - GetWPDatabase(); + GetWPDatabase(); - GetMessageDatabase(); - GetUserDatabase(); - GetBIDDatabase(); - GetBadWordFile(); - GetHTMLForms(); - GetPGConfig(); + GetMessageDatabase(); + GetUserDatabase(); + GetBIDDatabase(); + GetBadWordFile(); + GetHTMLForms(); + GetPGConfig(); - // Make sure there is a user record for the BBS, with BBS bit set. + // Make sure there is a user record for the BBS, with BBS bit set. - user = LookupCall(BBSName); + user = LookupCall(BBSName); - if (user == NULL) - { - user = AllocateUserRecord(BBSName); - user->Temp = zalloc(sizeof (struct TempUserInfo)); - } - - if ((user->flags & F_BBS) == 0) - { - // Not Defined as a BBS - - if(SetupNewBBS(user)) - user->flags |= F_BBS; - } - - // if forwarding AMPR mail make sure User/BBS AMPR exists - - if (SendAMPRDirect) - { - BOOL NeedSave = FALSE; - - user = LookupCall("AMPR"); - if (user == NULL) { - user = AllocateUserRecord("AMPR"); + user = AllocateUserRecord(BBSName); user->Temp = zalloc(sizeof (struct TempUserInfo)); - NeedSave = TRUE; } if ((user->flags & F_BBS) == 0) { // Not Defined as a BBS - if (SetupNewBBS(user)) + if(SetupNewBBS(user)) user->flags |= F_BBS; - NeedSave = TRUE; } - if (NeedSave) - SaveUserDatabase(); - } + // if forwarding AMPR mail make sure User/BBS AMPR exists - - // Make sure SYSOPCALL is set - - if (SYSOPCall[0] == 0) - strcpy(SYSOPCall, BBSName); - - // See if just want to add user (mainly for setup scripts) - - if (argc == 5 && _stricmp(argv[1], "--adduser") == 0) - { - BOOL isBBS = FALSE; - char * response; - - if (_stricmp(argv[4], "TRUE") == 0) - isBBS = TRUE; - - printf("Adding User %s\r\n", argv[2]); - response = AddUser(argv[2], argv[3], isBBS); - printf("%s", response); - exit(0); - } - // Allocate Streams - - strcpy(pgm, "BBS"); - - for (i=0; i < MaxStreams; i++) - { - conn = &Connections[i]; - conn->BPQStream = FindFreeStream(); - - if (conn->BPQStream == 255) break; - - NumberofStreams++; - -// BPQSetHandle(conn->BPQStream, hWnd); - - SetAppl(conn->BPQStream, (i == 0 && EnableUI) ? 0x82 : 2, BBSApplMask); - Disconnect(conn->BPQStream); - } - - strcpy(pgm, "LINBPQ"); - - Debugprintf("POP3 Debug Before Init TCP Timer = %d", POP3Timer); - - InitialiseTCP(); - Debugprintf("POP3 Debug Before Init NNTP Timer = %d", POP3Timer); - InitialiseNNTP(); - - SetupListenSet(); // Master set of listening sockets - - if (EnableUI || MailForInterval) - SetupUIInterface(); - - if (MailForInterval) - _beginthread(SendMailForThread, 0, 0); - - - // Calulate time to run Housekeeping - { - struct tm *tm; - time_t now; - - now = time(NULL); - - tm = gmtime(&now); - - tm->tm_hour = MaintTime / 100; - tm->tm_min = MaintTime % 100; - tm->tm_sec = 0; - - MaintClock = mktime(tm) - (time_t)_MYTIMEZONE; - - while (MaintClock < now) - MaintClock += MaintInterval * 3600; - - Debugprintf("Maint Clock %lld NOW %lld Time to HouseKeeping %lld", (long long)MaintClock, (long long)now, (long long)(MaintClock - now)); - - if (LastHouseKeepingTime) + if (SendAMPRDirect) { - if ((now - LastHouseKeepingTime) > MaintInterval * 3600) + BOOL NeedSave = FALSE; + + user = LookupCall("AMPR"); + + if (user == NULL) { - DoHouseKeeping(FALSE); + user = AllocateUserRecord("AMPR"); + user->Temp = zalloc(sizeof (struct TempUserInfo)); + NeedSave = TRUE; } + + if ((user->flags & F_BBS) == 0) + { + // Not Defined as a BBS + + if (SetupNewBBS(user)) + user->flags |= F_BBS; + NeedSave = TRUE; + } + + if (NeedSave) + SaveUserDatabase(); } - for (i = optind; i < argc; i++) + + + // Make sure SYSOPCALL is set + + if (SYSOPCall[0] == 0) + strcpy(SYSOPCall, BBSName); + + // See if just want to add user (mainly for setup scripts) + + if (argc == 5 && _stricmp(argv[1], "--adduser") == 0) { - if (_stricmp(argv[i], "tidymail") == 0) - DeleteRedundantMessages(); + BOOL isBBS = FALSE; + char * response; - if (_stricmp(argv[i], "nohomebbs") == 0) - DontNeedHomeBBS = TRUE; + if (_stricmp(argv[4], "TRUE") == 0) + isBBS = TRUE; + + printf("Adding User %s\r\n", argv[2]); + response = AddUser(argv[2], argv[3], isBBS); + printf("%s", response); + exit(0); + } + // Allocate Streams + + strcpy(pgm, "BBS"); + + for (i=0; i < MaxStreams; i++) + { + conn = &Connections[i]; + conn->BPQStream = FindFreeStream(); + + if (conn->BPQStream == 255) break; + + NumberofStreams++; + + // BPQSetHandle(conn->BPQStream, hWnd); + + SetAppl(conn->BPQStream, (i == 0 && EnableUI) ? 0x82 : 2, BBSApplMask); + Disconnect(conn->BPQStream); } - printf("Mail Started\n"); - Logprintf(LOG_BBS, NULL, '!', "Mail Starting"); + strcpy(pgm, "LINBPQ"); - } - } + InitialiseTCP(); + InitialiseNNTP(); - Debugprintf("POP3 Debug After Mail Init Timer = %d", POP3Timer); + SetupListenSet(); // Master set of listening sockets + + if (EnableUI || MailForInterval) + SetupUIInterface(); + + if (MailForInterval) + _beginthread(SendMailForThread, 0, 0); + + + // Calulate time to run Housekeeping + { + struct tm *tm; + time_t now; + + now = time(NULL); + + tm = gmtime(&now); + + tm->tm_hour = MaintTime / 100; + tm->tm_min = MaintTime % 100; + tm->tm_sec = 0; + + MaintClock = mktime(tm) - (time_t)_MYTIMEZONE; + + while (MaintClock < now) + MaintClock += MaintInterval * 3600; + + Debugprintf("Maint Clock %lld NOW %lld Time to HouseKeeping %lld", (long long)MaintClock, (long long)now, (long long)(MaintClock - now)); + + if (LastHouseKeepingTime) + { + if ((now - LastHouseKeepingTime) > MaintInterval * 3600) + { + DoHouseKeeping(FALSE); + } + } + for (i = optind; i < argc; i++) + { + if (_stricmp(argv[i], "tidymail") == 0) + DeleteRedundantMessages(); + + if (_stricmp(argv[i], "nohomebbs") == 0) + DontNeedHomeBBS = TRUE; + } + + printf("Mail Started\n"); + Logprintf(LOG_BBS, NULL, '!', "Mail Starting"); + + } + } if (NUMBEROFTNCPORTS) InitializeTNCEmulator(); diff --git a/MHSave.txt b/MHSave.txt new file mode 100644 index 0000000..e69de29 diff --git a/MailNode.vcproj.NOTTSDESKTOP.John.user b/MailNode.vcproj.NOTTSDESKTOP.John.user new file mode 100644 index 0000000..34131b7 --- /dev/null +++ b/MailNode.vcproj.NOTTSDESKTOP.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/MailNode.vcproj.SKIGACER.johnw.user b/MailNode.vcproj.SKIGACER.johnw.user new file mode 100644 index 0000000..b5b0536 --- /dev/null +++ b/MailNode.vcproj.SKIGACER.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/Moncode.c b/Moncode.c index aa1c0bd..6463b14 100644 --- a/Moncode.c +++ b/Moncode.c @@ -195,6 +195,9 @@ KC6OAR*>ID: // Check Port Port = msg->PORT; + + if (Port == 40) + Port = Port; if (Port & 0x80) { @@ -250,10 +253,8 @@ KC6OAR*>ID: ptr += 7; n--; - if (n == 0) - { + if (n < 0) return 0; // Corrupt - no end of address bit - } } // Reached End of digis diff --git a/SCSPactor.c.bak b/SCSPactor.c.bak deleted file mode 100644 index 78f96db..0000000 --- a/SCSPactor.c.bak +++ /dev/null @@ -1,4322 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// DLL to inteface SCS TNC in Pactor Mode to BPQ32 switch -// -// Uses BPQ EXTERNAL interface - - -// Dec 29 2009 - -// Add Scan Control using %W Hostmode Command -// Map Rig control port to a Virtual Serial Port. -// Add Support for packet port(s). - -// July 2010 - -// Support up to 32 BPQ Ports - -// Version 1.1.1.14 August 2010 - -// Drop RTS as well as DTR on close - -// Version 1.2.1.1 August 2010 - -// Save Minimized State - -// Version 1.2.1.2 August 2010 - -// Implement scan bandwidth change - -// Version 1.2.1.3 September 2010 - -// Don't connect if channel is busy -// Add WL2K reporting -// Add PACKETCHANNELS config command -// And Port Selector (P1 or P2) for Packet Ports - -// Version 1.2.1.4 September 2010 - -// Fix Freq Display after Node reconfig -// Only use AutoConnect APPL for Pactor Connects - -// Version 1.2.2.1 September 2010 - -// Add option to get config from bpq32.cfg - -// October 2011 - -// Changes for P4Dragon - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_DEPRECATE - - -#include -#include -#include "time.h" - -//#include -//#include - -#define MaxStreams 10 // First is used for Pactor, even though Pactor uses channel 31 - -#include "CHeaders.h" -#include "tncinfo.h" - -#include "bpq32.h" - -#ifndef WIN32 -#ifndef MACBPQ -#ifndef FREEBSD - -#include -#include -#endif -#endif -#endif - -static char ClassName[]="PACTORSTATUS"; -static char WindowTitle[] = "SCS Pactor"; -static int RigControlRow = 185; - - -#define NARROWMODE 12 // PI/II -#define WIDEMODE 16 // PIII only - -extern UCHAR LogDirectory[]; - -static RECT Rect; - -VOID __cdecl Debugprintf(const char * format, ...); - -char NodeCall[11]; // Nodecall, Null Terminated - -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); - -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); - -VOID PTCSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC); -VOID PTCReleasePort(struct TNCINFO * TNC); -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -int CheckMode(struct TNCINFO * TNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); -void SCSTryToSendDATA(struct TNCINFO * TNC, int Stream); -VOID UpdateMHwithDigis(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction); -int standardParams(struct TNCINFO * TNC, char * buf); -int SendPTCRadioCommand(struct TNCINFO * TNC, char * Block, int Length); - -#define FEND 0xC0 // KISS CONTROL CODES -#define FESC 0xDB -#define TFEND 0xDC -#define TFESC 0xDD - -static FILE * LogHandle[32] = {0}; - -//char * Logs[4] = {"1", "2", "3", "4"}; - -static char BaseDir[MAX_PATH]="c:\\"; - -static BOOL WRITELOG = FALSE; - -BOOL SCSStopPort(struct PORTCONTROL * PORT) -{ - // Disable Port - close TCP Sockets or Serial Port - - struct TNCINFO * TNC = PORT->TNC; - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - if (TNC->hDevice) - { - CloseCOMPort(TNC->hDevice); - TNC->hDevice = 0; - } - - TNC->HostMode = FALSE; - - sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Stopped"); - MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE); - - return TRUE; -} - -BOOL SCSStartPort(struct PORTCONTROL * PORT) -{ - // Restart Port - Open Sockets or Serial Port - - struct TNCINFO * TNC = PORT->TNC; - - TNC->ReopenTimer = 999; // Reopen immediately - - sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Restarted"); - MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE); - - return TRUE; -} - - - -static VOID CloseLogFile(int Flags) -{ - if (WRITELOG) - { - fclose(LogHandle[Flags]); - LogHandle[Flags] = NULL; - } -} - -static BOOL OpenLogFile(int Flags) -{ - if (WRITELOG) - { - UCHAR FN[MAX_PATH]; - - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(FN,"%s/logs/SCSLog_%02d%02d_%d.txt", LogDirectory, tm->tm_mon + 1, tm->tm_mday, Flags); - - LogHandle[Flags] = fopen(FN, "ab"); - - return (LogHandle[Flags] != NULL); - } - return 0; -} - -static void WriteLogLine(int Flags, char * Msg, int MsgLen) -{ - if (WRITELOG) - { - if (LogHandle[Flags]) - { - fwrite(Msg, 1, MsgLen, LogHandle[Flags]); - fwrite("\r\n", 1, 2, LogHandle[Flags]); - } - } -} - - -static int DontAddPDUPLEX = 0; - - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC; - char errbuf[256]; - - BPQport = Port; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - goto ConfigLine; - - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; -ConfigLine: - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "DEBUGLOG", 8) == 0) // Write Debug Log - WRITELOG = atoi(&buf[9]); - else - if (_memicmp(buf, "APPL", 4) == 0) - { - p_cmd = strtok(&buf[5], " \t\n\r"); - - if (p_cmd && p_cmd[0] != ';' && p_cmd[0] != '#') - TNC->ApplCmd=_strdup(_strupr(p_cmd)); - } - else - if (_memicmp(buf, "PACKETCHANNELS", 14) == 0) // Packet Channels - TNC->PacketChannels = atoi(&buf[14]); - - else - if (_memicmp(buf, "SCANFORROBUSTPACKET", 19) == 0) - { - // Spend a percentage of scan time in Robust Packet Mode - - double Robust = atof(&buf[20]); - #pragma warning(push) - #pragma warning(disable : 4244) - TNC->RobustTime = Robust * 10; - #pragma warning(pop) - } - else - if (_memicmp(buf, "USEAPPLCALLS", 12) == 0 && buf[12] != 'F' && buf[12] != 'f') - TNC->UseAPPLCalls = TRUE; - else - if (_memicmp(buf, "USEAPPLCALLSFORPACTOR", 21) == 0) - TNC->UseAPPLCallsforPactor = TRUE; - else - if (_memicmp(buf, "DRAGON", 6) == 0) - { - TNC->Dragon = TRUE; - if (_memicmp(&buf[7], "SINGLE", 6) == 0) - TNC->DragonSingle = TRUE; - - if (_memicmp(&buf[7], "KISS", 4) == 0) - TNC->DragonKISS = TRUE; - } - else - if (_memicmp(buf, "DEFAULT ROBUST", 14) == 0) - TNC->RobustDefault = TRUE; - else - if (_memicmp(buf, "DontAddPDUPLEX", 14) == 0) - DontAddPDUPLEX = TRUE; - else - if (_memicmp(buf, "FORCE ROBUST", 12) == 0) - TNC->ForceRobust = TNC->RobustDefault = TRUE; - else - if (_memicmp(buf, "MAXLEVEL", 8) == 0) // Maximum Pactor Level to use. - TNC->MaxLevel = atoi(&buf[8]); - else - if (_memicmp(buf, "DATE", 4) == 0) - { - char Cmd[32]; - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(Cmd,"DATE %02d%02d%02d\r", tm->tm_mday, tm->tm_mon + 1, tm->tm_year - 100); - - strcat (TNC->InitScript, Cmd); - } - else if (_memicmp(buf, "TIME", 4) == 0) - { - char Cmd[32]; - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(Cmd,"TIME %02d%02d%02d\r", tm->tm_hour, tm->tm_min, tm->tm_sec); - - strcat (TNC->InitScript, Cmd); - } - else if (standardParams(TNC, buf) == FALSE) - strcat (TNC->InitScript, buf); - } - - return (TRUE); - -} - -struct TNCINFO * CreateTTYInfo(int port, int speed); - -BOOL CloseConnection(struct TNCINFO * conn); -BOOL WriteCommBlock(struct TNCINFO * TNC); -BOOL DestroyTTYInfo(int port); -void SCSCheckRX(struct TNCINFO * TNC); -VOID SCSPoll(int Port); -VOID CRCStuffAndSend(struct TNCINFO * TNC, UCHAR * Msg, int Len); -unsigned short int compute_crc(unsigned char *buf,int len); -int Unstuff(UCHAR * MsgIn, UCHAR * MsgOut, int len); -VOID ProcessDEDFrame(struct TNCINFO * TNC, UCHAR * rxbuff, int len); -VOID ProcessTermModeResponse(struct TNCINFO * TNC); -static VOID ExitHost(struct TNCINFO * TNC); -static VOID DoTNCReinit(struct TNCINFO * TNC); -static VOID DoTermModeTimeout(struct TNCINFO * TNC); -static VOID DoMonitor(struct TNCINFO * TNC, UCHAR * Msg, int Len); -int Switchmode(struct TNCINFO * TNC, int Mode); -VOID SwitchToPactor(struct TNCINFO * TNC); -VOID SwitchToPacket(struct TNCINFO * TNC); - - -char status[8][8] = {"ERROR", "REQUEST", "TRAFFIC", "IDLE", "OVER", "PHASE", "SYNCH", ""}; - -char ModeText[8][14] = {"STANDBY", "AMTOR-ARQ", "PACTOR-ARQ", "AMTOR-FEC", "PACTOR-FEC", "RTTY / CW", "LISTEN", "Channel-Busy"}; - -char PactorLevelText[5][14] = {"Not Connected", "PACTOR-I", "PACTOR-II", "PACTOR-III", "PACTOR-IV"}; - -char PleveltoMode[5] = {30, 11, 14, 16, 20}; // WL2K Reporting Modes - RP, P1, P2, P3, P4 - - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int txlen = 0; - PMSGWITHLEN buffptr; - struct TNCINFO * TNC = TNCInfo[port]; - size_t Param; - int Stream = 0; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - char PLevel; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; - - if (TNC->hDevice == 0) - { - // Clear anything from UI_Q - - while (TNC->PortRecord->UI_Q) - { - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - // Try to reopen every 30 secs - - if (fn > 3 && fn < 7) - goto ok; - - TNC->ReopenTimer++; - - if (TNC->ReopenTimer < 300) - return 0; - - TNC->ReopenTimer = 0; - - if (TNC->PortRecord->PORTCONTROL.PortStopped == 0) - OpenCOMMPort(TNC, TNC->PortRecord->PORTCONTROL.SerialPortName, TNC->PortRecord->PORTCONTROL.BAUDRATE, TRUE); - - if (TNC->hDevice == 0) - return 0; - -#ifndef WIN32 -#ifndef MACBPQ -#ifndef FREEBSD - - if (TNC->Dragon) - { - struct serial_struct sstruct; - - // Need to set custom baud rate - - if (ioctl(TNC->hDevice, TIOCGSERIAL, &sstruct) < 0) - { - Debugprintf("Error: Dragon could not get comm ioctl\n"); - } - else - { - // set custom divisor to get 829440 baud - - sstruct.custom_divisor = 29; - sstruct.flags |= ASYNC_SPD_CUST; - - // set serial_struct - - if (ioctl(TNC->hDevice, TIOCSSERIAL, &sstruct) < 0) - Debugprintf("Error: Dragon could not set custom comm baud divisor\n"); - else - Debugprintf("Dragon custom baud rate set\n"); - } - } -#endif -#endif -#endif - - } -ok: - switch (fn) - { - case 7: - - // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - // G7TAJ's code to record activity for stats display - - if ( TNC->BusyFlags && CDBusy ) - TNC->PortRecord->PORTCONTROL.ACTIVE += 2; - - if ( TNC->PTTState ) - TNC->PortRecord->PORTCONTROL.SENDING += 2; - - SCSCheckRX(TNC); - SCSPoll(port); - - return 0; - - case 1: // poll - - // Check session limit timer - - if ((STREAM->Connecting || STREAM->Connected) && !STREAM->Disconnecting) - { - if (TNC->SessionTimeLimit && STREAM->ConnectTime && time(NULL) > (TNC->SessionTimeLimit + STREAM->ConnectTime)) - { - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - sprintf(STREAM->CmdSet, "D\r"); - STREAM->Disconnecting = TRUE; - } - } - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->Streams[Stream].ReportDISC) - { - TNC->Streams[Stream].ReportDISC = FALSE; - buff->PORT = Stream; - - return -1; - } - } - - if (TNC->EnterExit) - return 0; // Switching to Term mode to change bandwidth - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->Streams[Stream].PACTORtoBPQ_Q !=0) - { - int datalen; - - buffptr = Q_REM(&TNC->Streams[Stream].PACTORtoBPQ_Q); - datalen = (int)buffptr->Len; - - buff->PORT = Stream; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte - datalen += sizeof(void *) + 4; - - PutLengthinBuffer(buff, datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - } - - return 0; - - case 2: // send - - buffptr = GetBuff(); - - if (buffptr == 0) return 0; // No buffers, so ignore - - Stream = buff->PORT; - - if (!TNC->TNCOK) - { - // Send Error Response - - buffptr->Len = sprintf(buffptr->Data, "No Connection to PACTOR TNC\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - - if (txlen == 1 && buff->L2DATA[0] == 0) // Keepalive Packet - { - ReleaseBuffer(buffptr); - return 0; - } - - buffptr->Len = txlen; - memcpy(buffptr->Data, buff->L2DATA, txlen); - - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - - TNC->Streams[Stream].FramesOutstanding++; - - // See if possible to send immediately - - SCSTryToSendDATA(TNC, Stream); - - return 0; - - case 3: // CHECK IF OK TO SEND. Also used to check if TNC is responding - - Stream = (int)(size_t)buff; - - STREAM = &TNC->Streams[Stream]; - - if (Stream == 0) - { - if (TNC->Dragon) - { - if (STREAM->FramesOutstanding > 25) - return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15); - } - else - { - if (STREAM->FramesOutstanding > 10) - return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15); - } - } - else - { - if (STREAM->FramesOutstanding > 3 || TNC->Buffers < 200) - return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15); } - - return TNC->HostMode << 8 | STREAM->Disconnecting << 15; // OK, but lock attach if disconnecting - - - case 4: // reinit - - // Ensure in Pactor - - TNC->TXBuffer[2] = 31; - TNC->TXBuffer[3] = 0x1; - TNC->TXBuffer[4] = 0x1; - memcpy(&TNC->TXBuffer[5], "PT", 2); - - CRCStuffAndSend(TNC, TNC->TXBuffer, 7); - - Sleep(25); - ExitHost(TNC); - Sleep(50); - CloseCOMPort(TNC->hDevice); - TNC->hDevice =(HANDLE)0; - TNC->ReopenTimer = 250; - TNC->HostMode = FALSE; - - return (0); - - case 5: // Close - - // Ensure in Pactor - - TNC->TXBuffer[2] = 31; - TNC->TXBuffer[3] = 0x1; - TNC->TXBuffer[4] = 0x1; - memcpy(&TNC->TXBuffer[5], "PT", 2); - - CRCStuffAndSend(TNC, TNC->TXBuffer, 7); - - Sleep(25); - - ExitHost(TNC); - - Sleep(25); - - CloseCOMPort(TNCInfo[port]->hDevice); - - return (0); - - case 6: // Scan Interface - - Param = (size_t)buff; - - switch (Param) - { - case 1: // Request Permission - - if (TNC->TNCOK) - { - // If been in Sync a long time, or if using applcalls and - // Scan had been locked too long just let it change - - if (TNC->UseAPPLCallsforPactor) - { - if (TNC->PTCStatus == 6) // Sync - { - int insync = (int)(time(NULL) - TNC->TimeEnteredSYNCMode); - if (insync > 4) - { - Debugprintf("SCS Scan - in SYNC for %d Secs - allow change regardless", insync); - return 0; - } - } - else if (TNC->TimeScanLocked) - { - time_t timeLocked = time(NULL) - TNC->TimeScanLocked; - if (timeLocked > 4) - { - Debugprintf("SCS Scan - Scan Locked for %d Secs - allow change regardless", timeLocked); - TNC->TimeScanLocked = 0; - return 0; - } - } - } - - TNC->WantToChangeFreq = TRUE; - TNC->OKToChangeFreq = FALSE; - return TRUE; - } - return 0; // Don't lock scan if TNC isn't responding - - - case 2: // Check Permission - return TNC->OKToChangeFreq; - - case 3: // Release Permission - - TNC->WantToChangeFreq = FALSE; - - if (TNC->DontReleasePermission) // Disable connects during this interval? - { - TNC->DontReleasePermission = FALSE; - if (TNC->SyncSupported == FALSE) - TNC->TimeScanLocked = time(NULL) + 100; // Make sure doesnt time out - return 0; - } - - TNC->DontWantToChangeFreq = TRUE; - return 0; - - default: // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - - PLevel = Scan->PMaxLevel; - - if (PLevel == 0 && (Scan->HFPacketMode || Scan->RPacketMode)) - { - // Switch to Packet for this Interval - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("SCS Switching to Packet, %d", TNC->HFPacket); - - if (TNC->HFPacket == FALSE) - SwitchToPacket(TNC); - - return 0; - } - - if (PLevel > '0' && PLevel < '5') // 1 - 4 - { - if (TNC->Bandwidth != PLevel || TNC->MinLevel != (Scan->PMinLevel - '0')) - { - TNC->Bandwidth = PLevel; - TNC->MinLevel = Scan->PMinLevel - '0'; - Switchmode(TNC, PLevel - '0'); - } - - if (TNC->UseAPPLCallsforPactor && Scan->APPLCALL[0]) - { - // Switch callsign - - STREAM = &TNC->Streams[0]; - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - - strcpy(STREAM->MyCall, Scan->APPLCALL); - - sprintf(STREAM->CmdSet, "I%s\rI\r", STREAM->MyCall); - if (TNC->RIG->RIG_DEBUG) - Debugprintf("SCS Pactor APPLCALL Set to %s", STREAM->MyCall); - } - - else - { - if (TNC->HFPacket) - SwitchToPactor(TNC); - } - } - - if (Scan->RPacketMode) - if (TNC->RobustTime) - SwitchToPacket(TNC); // Always start in packet, switch to pactor after RobustTime ticks - - if (PLevel == '0') - TNC->DontReleasePermission = TRUE; // Dont allow connects in this interval - else - TNC->DontReleasePermission = FALSE; - - return 0; - } - } - return 0; -} - -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len) -{ - struct RIGINFO * RIG = TNC->RIG; - - if (RIG && RIG->WEB_Label) - { - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], "", RIG->WEB_Label); - Len += sprintf(&Buff[Len], "", RIG->WEB_FREQ); - Len += sprintf(&Buff[Len], "", RIG->WEB_MODE); - Len += sprintf(&Buff[Len], "", RIG->WEB_SCAN); - Len += sprintf(&Buff[Len], "", RIG->WEB_PTT); - - - if (TNC->TXRIG && TNC->TXRIG != TNC->RIG) - { - struct RIGINFO * RIG = TNC->TXRIG; - - Len += sprintf(&Buff[Len], "", RIG->WEB_Label); - Len += sprintf(&Buff[Len], "", RIG->WEB_FREQ); - Len += sprintf(&Buff[Len], "", RIG->WEB_MODE); - Len += sprintf(&Buff[Len], "", RIG->WEB_SCAN); - Len += sprintf(&Buff[Len], "
%s%s%s%c%c
%s%s%s%c%c
", RIG->WEB_PTT); - } - Len += sprintf(&Buff[Len], ""); - } - return Len; -} - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "SCS Pactor Status

SCS Pactor Status

"); - - Len += sprintf(&Buff[Len], ""); - - Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); - Len += sprintf(&Buff[Len], "", TNC->WEB_STATE); - Len += sprintf(&Buff[Len], "", TNC->WEB_TXRX); - Len += sprintf(&Buff[Len], "", TNC->WEB_BUFFERS); - Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); - Len += sprintf(&Buff[Len], "", TNC->WEB_PACTORLEVEL); - Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Status%s
TX/RX State%s
Buffers%s
Traffic%s
Mode%s
"); - - Len += sprintf(&Buff[Len], "", TNC->WebBuffer); - Len = DoScanLine(TNC, Buff, Len); - - return Len; -} - -void * SCSExtInit(EXTPORTDATA * PortEntry) -{ - char msg[500]; - struct TNCINFO * TNC; - int port; - char * ptr; - int Stream = 0; - char * TempScript; - - // - // Will be called once for each Pactor Port - // The COM port number is in IOBASE - // - - DontAddPDUPLEX = 0; - - sprintf(msg,"SCS Pactor %s", PortEntry->PORTCONTROL.SerialPortName); - WritetoConsole(msg); - - port=PortEntry->PORTCONTROL.PORTNUMBER; - - ReadConfigFile(port, ProcessLine); - - TNC = TNCInfo[port]; - - if (TNC == NULL) - { - // Not defined in Config file - - sprintf(msg," ** Error - no info in BPQ32.cfg for this port\n"); - WritetoConsole(msg); - - return ExtProc; - } - - TNC->Port = port; - TNC->Hardware = H_SCS; - - OpenLogFile(TNC->Port); - CloseLogFile(TNC->Port); - - - if (TNC->BusyHold == 0) - TNC->BusyHold = 3; - - if (TNC->BusyWait == 0) - TNC->BusyWait = 10; - - if (TNC->MaxLevel == 0) - TNC->MaxLevel = 3; - - // Set up DED addresses for streams (first stream (Pactor) = DED 31 - - TNC->Streams[0].DEDStream = 31; - - for (Stream = 1; Stream <= MaxStreams; Stream++) - { - TNC->Streams[Stream].DEDStream = Stream; - } - - if (TNC->PacketChannels > MaxStreams) - TNC->PacketChannels = MaxStreams; - - PortEntry->MAXHOSTMODESESSIONS = TNC->PacketChannels + 1; - PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream - PortEntry->SCANCAPABILITIES = CONLOCK; // Scan Control 3 stage/conlock - - TNC->PortRecord = PortEntry; - - if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) - TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; - - if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) - memcpy(TNC->NodeCall, MYNODECALL, 10); - else - ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); - - PortEntry->PORTCONTROL.PROTOCOL = 10; - PortEntry->PORTCONTROL.PORTQUALITY = 0; - - if (PortEntry->PORTCONTROL.PORTPACLEN == 0) - PortEntry->PORTCONTROL.PORTPACLEN = 100; - - TNC->SuspendPortProc = PTCSuspendPort; - TNC->ReleasePortProc = PTCReleasePort; - - PortEntry->PORTCONTROL.PORTSTARTCODE = SCSStartPort; - PortEntry->PORTCONTROL.PORTSTOPCODE = SCSStopPort; - - PortEntry->PORTCONTROL.UICAPABLE = TRUE; - - ptr=strchr(TNC->NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - // get NODECALL for RP tests - - memcpy(NodeCall, MYNODECALL, 10); - - ptr=strchr(NodeCall, ' '); - if (ptr) *(ptr) = 0; // Null Terminate - - - // Set TONES to 4 - - TempScript = malloc(1000); - - strcpy(TempScript, "QUIT\r"); // In case in pac: mode - strcat(TempScript, "TONES 4\r"); // Tones may be changed but I want this as standard - strcat(TempScript, "MAXERR 30\r"); // Max retries - strcat(TempScript, "MODE 0\r"); // ASCII mode, no PTC II compression (Forwarding will use FBB Compression) - strcat(TempScript, "MAXSUM 20\r"); // Max count for memory ARQ - strcat(TempScript, "CWID 0 2\r"); // CW ID disabled - strcat(TempScript, "PTCC 0\r"); // Dragon out of PTC Compatibility Mode - strcat(TempScript, "VER\r"); // Try to determine Controller Type - - sprintf(msg, "MYLEVEL %d\r", TNC->MaxLevel); - strcat(TempScript, msg); // Default Level to MAXLEVEL - - strcat(TempScript, TNC->InitScript); - - free(TNC->InitScript); - TNC->InitScript = TempScript; - - // Others go on end so they can't be overriden - - strcat(TNC->InitScript, "ADDLF 0\r"); // Auto Line Feed disabled - strcat(TNC->InitScript, "ARX 0\r"); // Amtor Phasing disabled - strcat(TNC->InitScript, "BELL 0\r"); // Disable Bell - strcat(TNC->InitScript, "BC 0\r"); // FEC reception is disabled - strcat(TNC->InitScript, "BKCHR 2\r"); // Breakin Char = 2 - strcat(TNC->InitScript, "CHOBELL 0\r"); // Changeover Bell off - strcat(TNC->InitScript, "CMSG 0\r"); // Connect Message Off - strcat(TNC->InitScript, "LFIGNORE 0\r"); // No insertion of Line feed - strcat(TNC->InitScript, "LISTEN 0\r"); // Pactor Listen disabled - strcat(TNC->InitScript, "MAIL 0\r"); // Disable internal mailbox reporting - strcat(TNC->InitScript, "REMOTE 0\r"); // Disable remote control - strcat(TNC->InitScript, "PAC CBELL 0\r"); // - strcat(TNC->InitScript, "PAC CMSG 0\r"); // - strcat(TNC->InitScript, "PAC PRBOX 0\r"); // Turn off Packet Radio Mailbox - - // Automatic Status must be enabled for BPQ32 - // Pactor must use Host Mode Chanel 31 - // PDuplex must be set. The Node code relies on automatic IRS/ISS changeover - // 5 second duplex timer - - strcat(TNC->InitScript, "STATUS 2\rPTCHN 31\rPDTIMER 5\r"); - - if (DontAddPDUPLEX == 0) - strcat(TNC->InitScript, "PDUPLEX 1\r"); - - sprintf(msg, "MYCALL %s\rPAC MYCALL %s\r", TNC->NodeCall, TNC->NodeCall); - strcat(TNC->InitScript, msg); - - PortEntry->PORTCONTROL.TNC = TNC; - - TNC->WebWindowProc = WebProc; - TNC->WebWinX = 510; - TNC->WebWinY = 280; - - TNC->WEB_COMMSSTATE = zalloc(100); - TNC->WEB_TNCSTATE = zalloc(100); - strcpy(TNC->WEB_TNCSTATE, "Free"); - TNC->WEB_MODE = zalloc(100); - TNC->WEB_TRAFFIC = zalloc(100); - TNC->WEB_BUFFERS = zalloc(100); - TNC->WEB_STATE = zalloc(100); - TNC->WEB_TXRX = zalloc(100); - TNC->WEB_PACTORLEVEL = zalloc(100); - TNC->WebBuffer = zalloc(5000); - - -#ifndef LINBPQ - - CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 500, ForcedClose); - - CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Status", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_STATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "TX/RX State", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TXRX = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Buffers", WS_CHILD | WS_VISIBLE,10,116,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_BUFFERS = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,116,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,138,80,20, TNC->hDlg, NULL, hInstance, NULL); - TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "RX 0 TX 0 ACKED 0", WS_CHILD | WS_VISIBLE,116,138,374,20 , TNC->hDlg, NULL, hInstance, NULL); - - TNC->xIDC_PACTORLEVEL = CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE,10,160,430,20, TNC->hDlg, NULL, hInstance, NULL); - - TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | - LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, - 0,RigControlRow + 44,250,300, TNC->hDlg, NULL, hInstance, NULL); - - TNC->ClientHeight = 500; - TNC->ClientWidth = 500; - - sprintf(TNC->WEB_BUFFERS, "%05d Queued %05d", TNC->Buffers, TNC->Streams[0].FramesOutstanding); - SetWindowText(TNC->xIDC_BUFFERS, TNC->WEB_BUFFERS); - - - MoveWindows(TNC); -#endif - OpenCOMMPort(TNC, PortEntry->PORTCONTROL.SerialPortName, PortEntry->PORTCONTROL.BAUDRATE, FALSE); - -#ifndef WIN32 -#ifndef MACBPQ -#ifndef FREEBSD - - if (TNC->Dragon) - { - struct serial_struct sstruct; - - // Need to set custom baud rate - - if (ioctl(TNC->hDevice, TIOCGSERIAL, &sstruct) < 0) - { - printf("Error: Dragon could not get comm ioctl\n"); - } - else - { - // set custom divisor to get 829440 baud - - sstruct.custom_divisor = 29; - sstruct.flags |= ASYNC_SPD_CUST; - - // set serial_struct - - if (ioctl(TNC->hDevice, TIOCSSERIAL, &sstruct) < 0) - Debugprintf("Error: Dragon could not set custom comm baud divisor\n"); - else - Debugprintf("Dragon custom baud rate set\n"); - } - } -#endif -#endif -#endif - if (TNC->RobustDefault) - SwitchToPacket(TNC); - - WritetoConsole("\n"); - - return ExtProc; -} - -void SCSCheckRX(struct TNCINFO * TNC) -{ - int Length, Len; - unsigned short crc; - char UnstuffBuffer[500]; - - if (TNC->RXLen == 500) - TNC->RXLen = 0; - - Len = ReadCOMBlock(TNC->hDevice, &TNC->RXBuffer[TNC->RXLen], 500 - TNC->RXLen); - - if (Len == 0) - return; - - TNC->RXLen += Len; - - Length = TNC->RXLen; - - // DED mode doesn't have an end of frame delimiter. We need to know if we have a full frame - - // Fortunately this is a polled protocol, so we only get one frame at a time - - // If first char != 170, then probably a Terminal Mode Frame. Wait for CR on end - - // If first char is 170, we could check rhe length field, but that could be corrupt, as - // we haen't checked CRC. All I can think of is to check the CRC and if it is ok, assume frame is - // complete. If CRC is duff, we will eventually time out and get a retry. The retry code - // can clear the RC buffer - - if (TNC->UsingTermMode) - { - // Send response to Host if connected - - PMSGWITHLEN buffptr; - int Len = TNC->RXLen; - int Posn = 0; - - // First message is probably ACK of JHO4T - AA AA 1F 00 1E 19 - - if (TNC->RXBuffer[0] == 0xaa && Len > 6) - { - memmove(TNC->RXBuffer, &TNC->RXBuffer[6], Len - 6); - Len -= 6; - } - - // TNC seems to send 1e f7 or 1e 87 regularly - - while (TNC->RXBuffer[0] == 0x1e && Len > 1) - { - memmove(TNC->RXBuffer, &TNC->RXBuffer[2], Len - 2); - Len -= 2; - } - - if (Len == 0) - { - TNC->RXLen = 0; // Ready for next frame - return; - } - - while (Len > 250) - { - buffptr = GetBuff(); - buffptr->Len = 250; - memcpy(buffptr->Data, &TNC->RXBuffer[Posn], 250); - C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr); - Len -= 250; - Posn += 250; - } - - buffptr = GetBuff(); - buffptr->Len = Len; - memcpy(buffptr->Data, &TNC->RXBuffer[Posn], Len); - C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr); - - TNC->RXLen = 0; // Ready for next frame - return; - } - - - if (TNC->RXBuffer[0] != 170) - { - // Char Mode Frame I think we need to see cmd: on end - - // If we think we are in host mode, then to could be noise - just discard. - - if (TNC->HostMode) - { - TNC->RXLen = 0; // Ready for next frame - return; - } - - TNC->RXBuffer[TNC->RXLen] = 0; - -// if (TNC->Streams[Stream].RXBuffer[TNC->Streams[Stream].RXLen-2] != ':') - - if (strlen(TNC->RXBuffer) < TNC->RXLen) - TNC->RXLen = 0; - - if ((strstr(TNC->RXBuffer, "cmd: ") == 0) && (strstr(TNC->RXBuffer, "pac: ") == 0)) - - return; // Wait for rest of frame - - // Complete Char Mode Frame - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, TNC->RXBuffer, (int)strlen(TNC->RXBuffer)); - CloseLogFile(TNC->Port); - - TNC->RXLen = 0; // Ready for next frame - - if (TNC->HostMode == 0) - { - // We think TNC is in Terminal Mode - ProcessTermModeResponse(TNC); - return; - } - // We thought it was in Host Mode, but are wrong. - - TNC->HostMode = FALSE; - return; - } - - // Receiving a Host Mode frame - - if (Length < 6) // Minimum Frame Sise - return; - - if (TNC->RXBuffer[2] == 170) - { - // Retransmit Request - - TNC->RXLen = 0; - return; // Ignore for now - } - - // Can't unstuff into same buffer - fails if partial msg received, and we unstuff twice - - - Length = Unstuff(&TNC->RXBuffer[2], &UnstuffBuffer[2], Length - 2); - - if (Length == -1) - { - // Unstuff returned an errors (170 not followed by 0) - - TNC->RXLen = 0; - return; // Ignore for now - } - crc = compute_crc(&UnstuffBuffer[2], Length); - - if (crc == 0xf0b8) // Good CRC - { - TNC->RXLen = 0; // Ready for next frame - ProcessDEDFrame(TNC, UnstuffBuffer, Length); - - // If there are more channels to poll (more than 1 entry in general poll response, - // and link is not active, poll the next one - - if (TNC->Timeout == 0) - { - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->NexttoPoll[0]) - { - UCHAR Chan = TNC->NexttoPoll[0] - 1; - - memmove(&TNC->NexttoPoll[0], &TNC->NexttoPoll[1], 19); - - Poll[2] = Chan; // Channel - Poll[3] = 0x1; // Command - - if (Chan == 254) // Status - Send Extended Status (G3) - { - Poll[4] = 1; // Len-1 - Poll[5] = 'G'; // Extended Status Poll - Poll[6] = '3'; - } - else - { - Poll[4] = 0; // Len-1 - Poll[5] = 'G'; // Poll - } - - CRCStuffAndSend(TNC, Poll, Poll[4] + 6); - TNC->InternalCmd = FALSE; - - return; - } - else - { - // if last message wasn't a general poll, send one now - - if (TNC->PollSent) - return; - - TNC->PollSent = TRUE; - - // Use General Poll (255) - - Poll[2] = 255 ; // Channel - Poll[3] = 0x1; // Command - - Poll[4] = 0; // Len-1 - Poll[5] = 'G'; // Poll - - CRCStuffAndSend(TNC, Poll, 6); - TNC->InternalCmd = FALSE; - } - } - return; - } - - // Bad CRC - assume incomplete frame, and wait for rest. If it was a full bad frame, timeout and retry will recover link. - - return; -} - -BOOL WriteCommBlock(struct TNCINFO * TNC) -{ - BOOL ret = WriteCOMBlock(TNC, TNC->TXBuffer, TNC->TXLen); - - TNC->Timeout = 20; // 2 secs - return ret; -} - -VOID SCSPoll(int Port) -{ - struct TNCINFO * TNC = TNCInfo[Port]; - UCHAR * Poll = TNC->TXBuffer; - char Status[80]; - int Stream = 0; - int nn; - struct STREAMINFO * STREAM; - - if (TNC->UsingTermMode) - { - if (TNC->Streams[Stream].BPQtoPACTOR_Q) - { - PMSGWITHLEN buffptr = Q_REM(&TNC->Streams[Stream].BPQtoPACTOR_Q); - - // See if enter host mode command - - if (_memicmp(buffptr->Data, "ENTERHOST\r", buffptr->Len) == 0) - { - TNC->UsingTermMode = FALSE; - - memcpy(Poll, "JHOST4\r", 7); - TNC->TXLen = 7; - WriteCommBlock(TNC); - - // No response expected - - Sleep(10); - - Poll[2] = 255; // Channel - TNC->Toggle = 0; - Poll[3] = 0x41; - Poll[4] = 0; // Len-1 - Poll[5] = 'G'; // Poll - - CRCStuffAndSend(TNC, Poll, 6); - TNC->InternalCmd = FALSE; - TNC->Timeout = 5; // 1/2 sec - In case missed - - - } - else - { - // Send to TNC - - memcpy(&Poll[0], buffptr->Data, buffptr->Len); - TNC->TXLen = buffptr->Len;; - WriteCommBlock(TNC); - } - ReleaseBuffer(buffptr); - } - return; - } - - if (TNC->MinLevelTimer) - { - TNC->MinLevelTimer--; - - if (TNC->MinLevelTimer == 0) - { - // Failed to reach min level in 15 secs - - STREAM = &TNC->Streams[0]; - - if (STREAM->Connected) - { - PMSGWITHLEN buffptr; - - Debugprintf("Required Min Level not reached - disconnecting"); - - // Discard Queued Data, Send a Message, then a disconnect - - while (STREAM->BPQtoPACTOR_Q) - ReleaseBuffer(Q_REM(&STREAM->BPQtoPACTOR_Q)); - - STREAM->NeedDisc = 15; // 1 secs - - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, - "This port only allows Pactor Level %d or above - Disconnecting\r\n", TNC->MinLevel); - - C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr); - } - } - } - - if (TNC->SwitchToPactor) - { - TNC->SwitchToPactor--; - - if (TNC->SwitchToPactor == 0) - SwitchToPactor(TNC); - } - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && TNC->Streams[Stream].Attached == 0) - { - // New Attach - - // If Pactor, stop scanning and take out of listen mode. - - // Set call to connecting user's call - - // If Stream 0 Put in Pactor Mode so Busy Detect will work - - int calllen=0; - - STREAM = &TNC->Streams[Stream]; - Debugprintf("SCS New Attach Stream %d DEDStream %d", Stream, STREAM->DEDStream); - - if (Stream == 0) - STREAM->DEDStream = 31; // Pactor - - STREAM->Attached = TRUE; - - calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, STREAM->MyCall); - - STREAM->MyCall[calllen] = 0; - - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - - if (Stream == 0) - { - // Release Scan Lock if it is held - - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit - - if (TNC->DontReleasePermission) - { - TNC->DontReleasePermission = FALSE; - TNC->DontWantToChangeFreq = TRUE; - } - - sprintf(STREAM->CmdSet, "I%s\r", "SCSPTC"); - - Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet); - - SuspendOtherPorts(TNC); // Prevent connects on other ports in same scan gruop - - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - // Stop Scanner - - sprintf(Status, "%d SCANSTOP", TNC->Port); - TNC->SwitchToPactor = 0; // Cancel any RP to Pactor switch - - Rig_Command((TRANSPORTENTRY *) -1, Status); - } - else - { - sprintf(STREAM->CmdSet, "I%s\r", STREAM->MyCall); - Debugprintf("SCS Pactor Attach CMDSet = %s", STREAM->CmdSet); - } - } - } - - if (TNC->Timeout) - { - TNC->Timeout--; - - if (TNC->Timeout) // Still waiting - return; - - TNC->Retries--; - - if(TNC->Retries) - { - WriteCommBlock(TNC); // Retransmit Block - return; - } - - // Retried out. - - if (TNC->HostMode == 0) - { - DoTermModeTimeout(TNC); - return; - } - - // Retried out in host mode - Clear any connection and reinit the TNC - - Debugprintf("PACTOR - Link to TNC Lost"); - TNC->TNCOK = FALSE; - - sprintf(TNC->WEB_COMMSSTATE,"%s Open but TNC not responding", TNC->PortRecord->PORTCONTROL.SerialPortName); - SetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - // Clear anything from UI_Q - - while (TNC->PortRecord->UI_Q) - { - UINT * buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - - TNC->HostMode = 0; - TNC->ReinitState = 0; - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream]) // Connected - { - TNC->Streams[Stream].Connected = FALSE; // Back to Command Mode - TNC->Streams[Stream].ReportDISC = TRUE; // Tell Node - } - } - } - - // We delay clearing busy for BusyHold secs - - if (TNC->Busy) - if (TNC->Mode != 7) - TNC->Busy--; - - if (TNC->BusyDelay) // Waiting to send connect - { - // Still Busy? - - if (InterlockedCheckBusy(TNC) == 0) - { - // No, so send - - TNC->Streams[0].CmdSet = TNC->ConnectCmd; - TNC->Streams[0].Connecting = TRUE; - TNC->Streams[0].ConnectTime = time(NULL); - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - Debugprintf("SCS Pactor CMDSet = %s", TNC->Streams[0].CmdSet); - - TNC->BusyDelay = 0; - return; - } - else - { - // Wait Longer - - TNC->BusyDelay--; - - if (TNC->BusyDelay == 0) - { - // Timed out - Send Error Response - - PMSGWITHLEN buffptr = GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = 39; - memcpy(buffptr->Data,"Sorry, Can't Connect - Channel is busy\r", 39); - - C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr); - - free(TNC->ConnectCmd); - - } - } - } - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - STREAM = &TNC->Streams[Stream]; - - if (STREAM->Attached) - CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete); - - if (STREAM->NeedDisc) - { - STREAM->NeedDisc--; - - if (STREAM->NeedDisc == 0) - STREAM->ReportDISC = TRUE; - - } - - if (TNC->Timeout) - return; // We've sent something - } - - // if we have just restarted or TNC appears to be in terminal mode, run Initialisation Sequence - - if (!TNC->HostMode) - { - DoTNCReinit(TNC); - return; - } - - TNC->PollSent = FALSE; - - //If sending internal command list, send next element - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->Streams[Stream].CmdSet) - { - unsigned char * start, * end; - int len; - - start = TNC->Streams[Stream].CmdSet; - - if (*(start) == 250) // 2nd part of long KISS packet - { - len = start[1]; - - Poll[2] = 250; // KISS Channel - Poll[3] = 0; // Data - Poll[4] = len - 1; - memcpy(&Poll[5], &start[2], len); - - CRCStuffAndSend(TNC, Poll, len + 5); - - free(TNC->Streams[Stream].CmdSave); - TNC->Streams[Stream].CmdSet = NULL; - return; - } - - if (*(start) == 0) // End of Script - { - free(TNC->Streams[Stream].CmdSave); - TNC->Streams[Stream].CmdSet = NULL; - } - else - { - end = strchr(start, 13); - len = (int)(++end - start - 1); // exclude cr - TNC->Streams[Stream].CmdSet = end; - - if (*(start) == 1) - { - // This is UI data, not a command. Send it to channel 0 - - len --; - - Poll[2] = 0; // UI Channel - Poll[3] = 0; // Data - Poll[4] = len - 1; - memcpy(&Poll[5], &start[1], len); - - CRCStuffAndSend(TNC, Poll, len + 5); - - return; - } - - if (*(start) == 2) - { - // This is a UI command Send it to channel 0 - - len--; - - Poll[2] = 0; // UI Channel - Poll[3] = 1; // Command - Poll[4] = len - 1; - memcpy(&Poll[5], &start[1], len); - - CRCStuffAndSend(TNC, Poll, len + 5); - - return; - } - - Poll[2] = TNC->Streams[Stream].DEDStream; // Channel - Poll[3] = 1; // Command - Poll[4] = len - 1; - memcpy(&Poll[5], start, len); - - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, &Poll[5], len); - CloseLogFile(TNC->Port); - - CRCStuffAndSend(TNC, Poll, len + 5); - - return; - } - } - } - // if Freq Change needed, check if ok to do it. - - if (TNC->TNCOK) - { - if (TNC->WantToChangeFreq) - { - Poll[2] = 31; // Command - Poll[3] = 1; // Command - Poll[4] = 2; // Len -1 - Poll[5] = '%'; - Poll[6] = 'W'; - Poll[7] = '0'; - - CRCStuffAndSend(TNC, Poll, 8); - - TNC->InternalCmd = TRUE; - TNC->WantToChangeFreq = FALSE; - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("Scan Debug SCS Pactor Requesting permission from TNC"); - - return; - } - - if (TNC->DontWantToChangeFreq) - { - Poll[2] = 31; // Command - Poll[3] = 1; // Command - Poll[4] = 2; // Len -1 - Poll[5] = '%'; - Poll[6] = 'W'; - Poll[7] = '1'; - - CRCStuffAndSend(TNC, Poll, 8); - - TNC->InternalCmd = TRUE; - TNC->DontWantToChangeFreq = FALSE; - TNC->OKToChangeFreq = FALSE; - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("Scan Debug SCS Pactor Release Scan Lock sent to TNC"); - - return; - } - } - - // Send Radio Command if avail - - if (TNC->TNCOK && TNC->BPQtoRadio_Q) - { - int datalen; - PMSGWITHLEN buffptr; - - buffptr = Q_REM(&TNC->BPQtoRadio_Q); - - datalen = (int)buffptr->Len; - - Poll[2] = 253; // Radio Channel - Poll[3] = 0; // Data? - Poll[4] = datalen - 1; - - memcpy(&Poll[5], buffptr->Data, datalen); - - ReleaseBuffer(buffptr); - - CRCStuffAndSend(TNC, Poll, datalen + 5); - - if (TNC->RIG->RIG_DEBUG) - { - Debugprintf("SCS Rig Command Queued, Len = %d", datalen ); - Debugprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - Poll[5], Poll[6], Poll[7], Poll[8], Poll[9], Poll[10], Poll[11], Poll[12], - Poll[13], Poll[14], Poll[15], Poll[16], Poll[17], Poll[18], Poll[19], Poll[20]); - } - - // Debugprintf("SCS Sending Rig Command"); - - return; - } - - if (TNC->TNCOK && TNC->PortRecord->UI_Q) - { - int datalen; - char * Buffer; - char ICall[16]; - char CCMD[80] = "C"; - char Call[12] = " "; - struct _MESSAGE * buffptr; - - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - - datalen = buffptr->LENGTH - MSGHDDRLEN; - Buffer = &buffptr->DEST[0]; // Raw Frame - - Buffer[datalen] = 0; - - // If a Dragon with KISS over Hostmade we can just send it - - if (TNC->DragonKISS) - { - int EncLen; - - Poll[2] = 250; // KISS Channel - Poll[3] = 0; // CMD - Poll[4] = datalen + 2; // 3 extrac chars, but need Len - 1 - - Buffer--; - *(Buffer) = 0; // KISS Control on front - EncLen = KissEncode(Buffer, &Poll[5], datalen + 1); - - // We can only send 256 bytes in HostMode, so if longer will - // have to fragemt - - if (EncLen > 256) - { - //We have to wait for response before sending rest, so use CmdSet - - // We need to save the extra first, as CRC will overwrite the first two bytes - - UCHAR * ptr = TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = zalloc(400); - - (*ptr++) = 250; // KISS Channel - (*ptr++) = EncLen - 256; - memcpy(ptr, &Poll[5 + 256], EncLen - 256); - - // Send first 256 - - Poll[4] = 255; //need Len - 1 - CRCStuffAndSend(TNC, Poll, 261); - } - else - { - Poll[4] = EncLen - 1; //need Len - 1 - CRCStuffAndSend(TNC, Poll, EncLen + 5); - } - - ReleaseBuffer((UINT *)buffptr); - return; - } - - // Not dragon KISS - - // Buffer has an ax.25 header, which we need to pick out and set as channel 0 Connect address - // before sending the beacon - - // We also need to set Chan 0 Mycall so digi'ing can work, and put - // it back after so incoming calls will work - - // But we cant set digipeated bit in call, so if we find one, skip message - - // This doesn't seem to work - - - ConvFromAX25(Buffer + 7, ICall); // Origin - strlop(ICall, ' '); - - ConvFromAX25(Buffer, &Call[1]); // Dest - strlop(&Call[1], ' '); - strcat(CCMD, Call); - Buffer += 14; // Skip Origin - datalen -= 7; - - while ((Buffer[-1] & 1) == 0) - { - if (Buffer[6] & 0x80) // Digied bit set? - { - ReleaseBuffer((UINT *)buffptr); - return; - } - - ConvFromAX25(Buffer, &Call[1]); - strlop(&Call[1], ' '); - strcat(CCMD, Call); - Buffer += 7; // End of addr - datalen -= 7; - } - - if (Buffer[0] == 3) // UI - { - Buffer += 2; - datalen -= 2; - - Poll[2] = 0; // UI Channel - Poll[3] = 1; // CMD - Poll[4] = (int)strlen(CCMD) - 1; - strcpy(&Poll[5], CCMD); - CRCStuffAndSend(TNC, Poll, Poll[4] + 6); // Set Dest and Path - - TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = zalloc(400); - sprintf(TNC->Streams[0].CmdSet, "%cI%s\r%c%s\r%cI%s\r", - 2, ICall, // Flag as Chan 0 Command - 1, Buffer, // Flag CmdSet as Data - 2, TNC->NodeCall); // Flag as Chan 0 Command - } - - ReleaseBuffer((UINT *)buffptr); - return; - } - - - // Check status Periodically - - if (TNC->TNCOK) - { - if (TNC->IntCmdDelay == 6) - { - Poll[2] = 254; // Channel - Poll[3] = 0x1; // Command - Poll[4] = 1; // Len-1 - Poll[5] = 'G'; // Extended Status Poll - Poll[6] = '3'; - - CRCStuffAndSend(TNC, Poll, 7); - - TNC->InternalCmd = TRUE; - TNC->IntCmdDelay--; - - return; - } - - if (TNC->IntCmdDelay == 4) - { - Poll[2] = 31; // Channel - Poll[3] = 0x1; // Command - Poll[4] = 1; // Len-1 - Poll[5] = '%'; // Bytes acked Status - Poll[6] = 'T'; - - CRCStuffAndSend(TNC, Poll, 7); - - TNC->InternalCmd = TRUE; - TNC->IntCmdDelay--; - - return; - } - - if (TNC->IntCmdDelay <=0) - { - Poll[2] = 31; // Channel - Poll[3] = 0x1; // Command - Poll[4] = 1; // Len-1 - Poll[5] = '@'; // Buffer Status - Poll[6] = 'B'; - - CRCStuffAndSend(TNC, Poll, 7); - - TNC->InternalCmd = TRUE; - TNC->IntCmdDelay = 20; // Every 2 secs - - return; - } - else - TNC->IntCmdDelay--; - } - - // If busy, send status poll, send Data if avail - - // We need to start where we last left off, or a busy stream will lock out the others - - for (nn = 0; nn <= MaxStreams; nn++) - { - Stream = TNC->LastStream++; - - if (TNC->LastStream > MaxStreams) - TNC->LastStream = 0; - - if (TNC->TNCOK && TNC->Streams[Stream].BPQtoPACTOR_Q) - { - int datalen; - PMSGWITHLEN buffptr; - char * Buffer; - - // Dont send to Pactor if waiting for Min Level to be reached - - if (TNC->MinLevelTimer && Stream == 0) - continue; - - buffptr = Q_REM(&TNC->Streams[Stream].BPQtoPACTOR_Q); - - datalen = (int)buffptr->Len; - Buffer = buffptr->Data; // Data portion of frame - - Poll[2] = TNC->Streams[Stream].DEDStream; // Channel - - if (TNC->Streams[Stream].Connected) - { - if (TNC->SwallowSignon && Stream == 0) - { - TNC->SwallowSignon = FALSE; - if (strstr(Buffer, "Connected")) // Discard *** connected - { - ReleaseBuffer(buffptr); - return; - } - } - - Poll[3] = 0; // Data? - TNC->Streams[Stream].BytesTXed += datalen; - - Poll[4] = datalen - 1; - memcpy(&Poll[5], Buffer, datalen); - - WritetoTrace(TNC, Buffer, datalen); - - ReleaseBuffer(buffptr); - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, &Poll[5], datalen); - CloseLogFile(TNC->Port); - - CRCStuffAndSend(TNC, Poll, datalen + 5); - - TNC->Streams[Stream].InternalCmd = TNC->Streams[Stream].Connected; - - if (STREAM->Disconnecting && TNC->Streams[Stream].BPQtoPACTOR_Q == 0) - TidyClose(TNC, 0); - - return; - } - - // Command. Do some sanity checking and look for things to process locally - - Poll[3] = 1; // Command - datalen--; // Exclude CR - Buffer[datalen] = 0; // Null Terminate - _strupr(Buffer); - - if (_memicmp(Buffer, "DD", 2) == 0) - { - // Send DD (Dirty Disconnect) - - // Uses "Hidden" feature where you can send any normal mode command - // in host mode by preceeding with a # - - Poll[2] = 31; - Poll[3] = 0x1; - Poll[4] = 2; - sprintf(&Poll[5], "#DD\r"); - CRCStuffAndSend(TNC, Poll, 8); - - // It looks like there isn't a response - - TNC->Timeout = 0; - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, &Poll[5], 4); - CloseLogFile(TNC->Port); - - ReleaseBuffer(buffptr); - return; - } - - if (_memicmp(Buffer, "D", 1) == 0) - { - TNC->Streams[Stream].ReportDISC = TRUE; // Tell Node - ReleaseBuffer(buffptr); - return; - } - - if (memcmp(Buffer, "RADIO ", 6) == 0) - { - sprintf(&Buffer[40], "%d %s", TNC->Port, &Buffer[6]); - - if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK, &Buffer[40])) - { - ReleaseBuffer(buffptr); - } - else - { - buffptr->Len = sprintf(buffptr->Data, "%s", &Buffer[40]); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return; - } - - if (_memicmp(Buffer, "SessionTimeLimit", 16) == 0) - { - if (Buffer[16] != 13) - { - PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff(); - - TNC->SessionTimeLimit = atoi(&Buffer[16]) * 60; - - if (buffptr) - { - buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "SCS} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - } - return; - } - } - - if (memcmp(Buffer, "MYLEVEL ", 8) == 0) - { - Switchmode(TNC, Buffer[8] - '0'); - TNC->Bandwidth = Buffer[8]; // so scanner knows where we are - - buffptr->Len = sprintf(buffptr->Data, "Ok\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return; - } - - if (memcmp(Buffer, "CHECKLEVEL", 10) == 0) - { - CheckMode(TNC); - - buffptr->Len = sprintf(buffptr->Data, "%s\r", &TNC->RXBuffer[2]); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return; - } - - if (_memicmp(Buffer, "OVERRIDEBUSY", 12) == 0) - { - TNC->OverrideBusy = TRUE; - - buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return; - } - - if ((Stream == 0) && memcmp(Buffer, "RPACKET", 7) == 0) - { - TNC->HFPacket = TRUE; - buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r"); - C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr); - return; - } - - if ((Stream == 0) && memcmp(Buffer, "PACTOR", 6) == 0) - { - TNC->HFPacket = FALSE; - buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r"); - C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr); - return; - } - - - if ((Stream == 0) && memcmp(Buffer, "EXITHOST", 8) == 0) - { - UCHAR * Poll = TNC->TXBuffer; - - TNC->UsingTermMode = 1; - - ExitHost(TNC); - - // Send CR to get prompt from TNC - - Poll[0] = 13; - TNC->TXLen = 1; - WriteCommBlock(TNC); - - ReleaseBuffer(buffptr); - return; - } - if (Stream == 0 && Buffer[0] == 'C' && datalen > 2) // Pactor Connect - Poll[2] = TNC->Streams[0].DEDStream = 31; // Pactor Channel - - if (Stream == 0 && Buffer[0] == 'R' && Buffer[1] == 'C') // Robust Packet Connect - { - Poll[2] = TNC->Streams[0].DEDStream = 30; // Last Packet Channel - memmove(Buffer, &Buffer[1], datalen--); - } - - if (Buffer[0] == 'C' && datalen > 2) // Connect - { - if (*(++Buffer) == ' ') Buffer++; // Space isn't needed - - if ((memcmp(Buffer, "P1 ", 3) == 0) ||(memcmp(Buffer, "P2 ", 3) == 0)) - { - // Port Selector for Packet Connect convert to 2:CALL - - Buffer[0] = Buffer[1]; - Buffer[1] = ':'; - memmove(&Buffer[2], &Buffer[3], datalen--); - //Buffer += 2; - } - - memcpy(TNC->Streams[Stream].RemoteCall, Buffer, 9); - - TNC->Streams[Stream].Connecting = TRUE; - - if (Stream == 0) - { - // Send Call, Mode Command followed by connect - - TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = malloc(100); - - if (TNC->Dragon) - sprintf(TNC->Streams[0].CmdSet, "I%s\r%s\r", TNC->Streams[0].MyCall, buffptr->Data); - else - { - if (TNC->Streams[0].DEDStream == 31) - sprintf(TNC->Streams[0].CmdSet, "I%s\rPT\r%s\r", TNC->Streams[0].MyCall, buffptr->Data); - else - sprintf(TNC->Streams[0].CmdSet, "I%s\rPR\r%s\r", TNC->Streams[0].MyCall, buffptr->Data); - } - - ReleaseBuffer(buffptr); - - // See if Busy - - if (InterlockedCheckBusy(TNC)) - { - // Channel Busy. Unless override set, wait - - if (TNC->OverrideBusy == 0) - { - // Send Mode Command now, save command, and wait up to 10 secs - // No, leave in Pactor, or Busy Detect won't work. Queue the whole conect sequence - - TNC->ConnectCmd = TNC->Streams[0].CmdSet; - TNC->Streams[0].CmdSet = NULL; - - sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel"); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - TNC->BusyDelay = TNC->BusyWait * 10; - TNC->Streams[Stream].Connecting = FALSE; // Not connecting Yet - - return; - } - } - - TNC->OverrideBusy = FALSE; - - sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[Stream].MyCall, TNC->Streams[Stream].RemoteCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - Debugprintf("SCS Pactor CMDSet = %s", TNC->Streams[Stream].CmdSet); - - TNC->Streams[0].InternalCmd = FALSE; - return; - } - } - - - Poll[4] = datalen - 1; - memcpy(&Poll[5], buffptr->Data, datalen); - - // if it starts with # the tnc won't respond, so send OK now. - - if (Buffer[0] == '#') - { - TNC->HFPacket = TRUE; - buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r"); - C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr); - } - else - ReleaseBuffer(buffptr); - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, &Poll[5], datalen); - CloseLogFile(TNC->Port); - - CRCStuffAndSend(TNC, Poll, datalen + 5); - - TNC->Streams[Stream].InternalCmd = TNC->Streams[Stream].Connected; - - return; - } - - // if frames outstanding, issue a poll - - if (TNC->Streams[Stream].FramesOutstanding) - { - Poll[2] = TNC->Streams[Stream].DEDStream; - Poll[3] = 0x1; // Command - Poll[4] = 0; // Len-1 - Poll[5] = 'L'; // Status - - CRCStuffAndSend(TNC, Poll, 6); - - TNC->InternalCmd = TRUE; - TNC->IntCmdDelay--; - return; - } - - } - - TNC->PollSent = TRUE; - - // Use General Poll (255) - - Poll[2] = 255 ; // Channel - Poll[3] = 0x1; // Command - - if (TNC->ReinitState == 3) - { - TNC->ReinitState = 0; - Poll[3] = 0x41; - } - - Poll[4] = 0; // Len-1 - Poll[5] = 'G'; // Poll - - CRCStuffAndSend(TNC, Poll, 6); - TNC->InternalCmd = FALSE; - - return; - -} - -void SCSTryToSendDATA(struct TNCINFO * TNC, int Stream) -{ - // Used after queuing data to see if it can be sent immediately - - struct STREAMINFO * STREAM = &TNC->Streams[Stream]; - int datalen; - PMSGWITHLEN buffptr; - char * Buffer; - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->TNCOK == 0 || STREAM->BPQtoPACTOR_Q == 0 || STREAM->Connected == 0) - return; - - - // Dont send to Pactor if waiting for Min Level to be reached - - if (TNC->MinLevelTimer && Stream == 0) - return;; - - Sleep(10); // Give TNC time to respond - - SCSCheckRX(TNC); // See if anything received - - if (TNC->Timeout) - return; // Link busy - - buffptr = Q_REM(&STREAM->BPQtoPACTOR_Q); - - datalen = (int)buffptr->Len; - Buffer = buffptr->Data; // Data portion of frame - - Poll[2] = STREAM->DEDStream; // Channel - - if (TNC->SwallowSignon && Stream == 0) - { - TNC->SwallowSignon = FALSE; - - if (strstr(Buffer, "Connected")) // Discard *** connected - { - ReleaseBuffer(buffptr); - return; - } - } - - Poll[3] = 0; // Data - STREAM->BytesTXed += datalen; - - Poll[4] = datalen - 1; - memcpy(&Poll[5], Buffer, datalen); - - WritetoTrace(TNC, Buffer, datalen); - - ReleaseBuffer(buffptr); - OpenLogFile(TNC->Port); - - WriteLogLine(TNC->Port, &Poll[5], datalen); - CloseLogFile(TNC->Port); - - CRCStuffAndSend(TNC, Poll, datalen + 5); - - if (STREAM->Disconnecting && STREAM->BPQtoPACTOR_Q == 0) - TidyClose(TNC, Stream); - - return; -} - - -VOID DoTNCReinit(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->ReinitState == 0) - { - // Just Starting - Send a TNC Mode Command to see if in Terminal or Host Mode - - TNC->TNCOK = FALSE; - sprintf(TNC->WEB_COMMSSTATE,"%s Initialising TNC", TNC->PortRecord->PORTCONTROL.SerialPortName); - SetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - Poll[0] = 13; - Poll[1] = 0x1B; - TNC->TXLen = 2; - - if (WriteCommBlock(TNC) == FALSE) - { - CloseCOMPort(TNC->hDevice); - OpenCOMMPort(TNC, TNC->PortRecord->PORTCONTROL.SerialPortName, TNC->PortRecord->PORTCONTROL.BAUDRATE, TRUE); - } - - TNC->Retries = 1; - } - - if (TNC->ReinitState == 1) // Forcing back to Term - TNC->ReinitState = 0; - - if (TNC->ReinitState == 2) // In Term State, Sending Initialisation Commands - { - char * start, * end; - int len; - - start = TNC->InitPtr; - - if (*(start) == 0) // End of Script - { - // Put into Host Mode - - Debugprintf("DOTNCReinit Complete - Entering Hostmode"); - - TNC->TXBuffer[2] = 0; - TNC->Toggle = 0; - - memcpy(Poll, "JHOST4\r", 7); - - TNC->TXLen = 7; - WriteCommBlock(TNC); - - // Timeout will enter host mode - - TNC->Timeout = 1; - TNC->Retries = 1; - TNC->Toggle = 0; - TNC->ReinitState = 3; // Set toggle force bit - TNC->OKToChangeFreq = 1; // In case failed whilst waiting for permission - - return; - } - - end = strchr(start, 13); - len = (int)(++end - start); - TNC->InitPtr = end; - memcpy(Poll, start, len); - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, Poll, len); - CloseLogFile(TNC->Port); - - TNC->TXLen = len; - WriteCommBlock(TNC); - - TNC->Retries = 2; - } -} - -static VOID DoTermModeTimeout(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->ReinitState == 0) - { - //Checking if in Terminal Mode - Try to set back to Term Mode - - TNC->ReinitState = 1; - ExitHost(TNC); - TNC->Retries = 1; - - return; - } - - if (TNC->ReinitState == 1) - { - // Forcing back to Term Mode - - TNC->ReinitState = 0; - DoTNCReinit(TNC); // See if worked - return; - } - - if (TNC->ReinitState == 3) - { - // Entering Host Mode - - // Assume ok - - TNC->HostMode = TRUE; - TNC->IntCmdDelay = 10; - - return; - } -} - -BOOL CheckRXText(struct TNCINFO * TNC) -{ - int Length; - - // only try to read number of bytes in queue - - if (TNC->RXLen == 500) - TNC->RXLen = 0; - - Length = ReadCOMBlock(TNC->hDevice, &TNC->RXBuffer[TNC->RXLen], 500 - TNC->RXLen); - - if (Length == 0) - return FALSE; // Nothing doing - - TNC->RXLen += Length; - - Length = TNC->RXLen; - - TNC->RXBuffer[TNC->RXLen] = 0; - - if (strlen(TNC->RXBuffer) < TNC->RXLen) - TNC->RXLen = 0; - - if ((strstr(TNC->RXBuffer, "cmd: ") == 0) && (strstr(TNC->RXBuffer, "pac: ") == 0)) - return 0; // Wait for rest of frame - - // Complete Char Mode Frame - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, TNC->RXBuffer, TNC->RXLen); - CloseLogFile(TNC->Port); - - TNC->RXBuffer[TNC->RXLen] = 0; - - if (TNC->RIG->RIG_DEBUG) - Debugprintf(TNC->RXBuffer); - - TNC->RXLen = 0; // Ready for next frame - - return TRUE; -} - -BOOL CheckRXHost(struct TNCINFO * TNC, char * UnstuffBuffer) -{ - int Length; - unsigned short crc; - - // only try to read number of bytes in queue - - if (TNC->RXLen == 500) - TNC->RXLen = 0; - - Length = ReadCOMBlock(TNC->hDevice, &TNC->RXBuffer[TNC->RXLen], 500 - TNC->RXLen); - - if (Length == 0) - return FALSE; // Nothing doing - - TNC->RXLen += Length; - - Length = TNC->RXLen; - - if (Length < 6) // Minimum Frame Sise - return FALSE; - - if (TNC->RXBuffer[2] == 170) - { - // Retransmit Request - - TNC->RXLen = 0; - return FALSE; // Ignore for now - } - - // Can't unstuff into same buffer - fails if partial msg received, and we unstuff twice - - Length = Unstuff(&TNC->RXBuffer[2], &UnstuffBuffer[2], Length - 2); - - if (Length == -1) - { - // Unstuff returned an errors (170 not followed by 0) - - TNC->RXLen = 0; - return FALSE; // Ignore for now - } - - crc = compute_crc(&UnstuffBuffer[2], Length); - - if (crc == 0xf0b8) // Good CRC - { - TNC->RXLen = 0; // Ready for next frame - return TRUE; - } - - // Bad CRC - assume incomplete frame, and wait for rest. If it was a full bad frame, timeout and retry will recover link. - - return FALSE; -} - - -//#include "Mmsystem.h" - -int Sleeptime = 250; - -int CheckMode(struct TNCINFO * TNC) -{ - int n; - char UnstuffBuffer[500]; - - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->HostMode == 0) - return 0; // Don't try if initialising - - TNC->EnterExit = TRUE; - - Poll[2] = 31; - Poll[3] = 0x41; - Poll[4] = 0x5; - memcpy(&Poll[5], "JHOST0", 6); - - CRCStuffAndSend(TNC, Poll, 11); - - n = 0; - - while (CheckRXHost(TNC, UnstuffBuffer) == FALSE) - { - Sleep(5); - n++; - - if (n > 100) break; - } - - - sprintf(Poll, "MYL\r"); - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, Poll, 3); - CloseLogFile(TNC->Port); - - TNC->TXLen = 4; - WriteCommBlock(TNC); - - n = 0; - - while (CheckRXText(TNC) == FALSE) - { - Sleep(5); - n++; - if (n > 100) break; - } - - memcpy(Poll, "JHOST4\r", 7); - - TNC->TXLen = 7; - WriteCommBlock(TNC); - - // No response expected - - Sleep(10); - - Poll[2] = 255; // Channel - TNC->Toggle = 0; - Poll[3] = 0x41; - Poll[4] = 0; // Len-1 - Poll[5] = 'G'; // Poll - - CRCStuffAndSend(TNC, Poll, 6); - TNC->InternalCmd = FALSE; - TNC->Timeout = 5; // 1/2 sec - In case missed - - TNC->EnterExit = FALSE; - return 0; -} - - -int Switchmode(struct TNCINFO * TNC, int Mode) -{ - int n; - char UnstuffBuffer[500]; - - UCHAR * Poll = TNC->TXBuffer; - - if (TNC->HostMode == 0) - return 0; // Don't try if initialising - - if (TNC->HFPacket) - { - Poll[2] = 31; - Poll[3] = 0x1; - Poll[4] = 0x1; - memcpy(&Poll[5], "PT", 2); - CRCStuffAndSend(TNC, Poll, 7); - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, "SwitchModes - Setting Pactor", 28); - CloseLogFile(TNC->Port); - - TNC->HFPacket = FALSE; - TNC->Streams[0].DEDStream = 31; // Pactor Channel - - n = 0; - while (CheckRXHost(TNC, UnstuffBuffer) == FALSE) - { - Sleep(5); - n++; - if (n > 100) break; - } - -// Debugprintf("Set Pactor ACK received in %d mS, Sleeping for %d", 5 * n, Sleeptime); - Sleep(Sleeptime); - } - - // Uses "Hidden" feature where you can send any normal mode command - // in host mode by preceeding with a # - - Poll[2] = 31; - Poll[3] = 0x1; - Poll[4] = 5; - sprintf(&Poll[5], "#MYL %d\r", Mode); - CRCStuffAndSend(TNC, Poll, 11); - - // It looks like there isn't a response - - TNC->Timeout = 0; - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, &Poll[5], 6); - CloseLogFile(TNC->Port); - - return 0; -} - -VOID SwitchToPactor(struct TNCINFO * TNC) -{ - if (TNC->ForceRobust) - return; - - TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = malloc(100); - sprintf(TNC->Streams[0].CmdSet, "PT\r"); - - TNC->HFPacket = FALSE; - TNC->Streams[0].DEDStream = 31; // Pactor Channel - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("BPQ32 Scan - switch to Pactor"); -} - -VOID SwitchToPacket(struct TNCINFO * TNC) -{ - TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = malloc(100); - sprintf(TNC->Streams[0].CmdSet, "PR\r"); - - TNC->HFPacket = TRUE; - TNC->Streams[0].DEDStream = 30; // Packet Channel - - TNC->SwitchToPactor = TNC->RobustTime; - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("BPQ32 Scan - switch to Packet"); -} - -VOID ExitHost(struct TNCINFO * TNC) -{ - UCHAR * Poll = TNC->TXBuffer; - - // Try to exit Host Mode - - TNC->TXBuffer[2] = 31; - TNC->TXBuffer[3] = 0x41; - TNC->TXBuffer[4] = 0x5; - memcpy(&TNC->TXBuffer[5], "JHOST0", 6); - - CRCStuffAndSend(TNC, Poll, 11); - return; -} - -VOID CRCStuffAndSend(struct TNCINFO * TNC, UCHAR * Msg, int Len) -{ - unsigned short int crc; - UCHAR StuffedMsg[500]; - int i, j; - - Msg[3] |= TNC->Toggle; - TNC->Toggle ^= 0x80; - - crc = compute_crc(&Msg[2], Len-2); - crc ^= 0xffff; - - Msg[Len++] = (crc&0xff); - Msg[Len++] = (crc>>8); - - for (i = j = 2; i < Len; i++) - { - StuffedMsg[j++] = Msg[i]; - if (Msg[i] == 170) - { - StuffedMsg[j++] = 0; - } - } - - if (j != i) - { - Len = j; - memcpy(Msg, StuffedMsg, j); - } - - TNC->TXLen = Len; - - Msg[0] = 170; - Msg[1] = 170; - - WriteCommBlock(TNC); - - TNC->Retries = 5; -} - -int Unstuff(UCHAR * MsgIn, UCHAR * MsgOut, int len) -{ - int i, j=0; - - for (i=0; iTXBuffer; - - if (TNC->ReinitState == 0) - { - // Testing if in Term Mode. It is, so can now send Init Commands - - TNC->InitPtr = TNC->InitScript; - TNC->ReinitState = 2; - - // Send Restart to make sure PTC is in a known state - - strcpy(Poll, "RESTART\r"); - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, Poll, 7); - CloseLogFile(TNC->Port); - - TNC->TXLen = 8; - WriteCommBlock(TNC); - - TNC->Timeout = 60; // 6 secs - - return; - } - if (TNC->ReinitState == 2) - { - // Sending Init Commands - - if (strstr(TNC->RXBuffer, "SCS P4dragon")) - { - TNC->Dragon = TRUE; - Debugprintf("SCSPactor in P4dragon mode"); - } - - DoTNCReinit(TNC); // Send Next Command - return; - } -} - -VOID ProcessIncomingCall(struct TNCINFO * TNC, struct STREAMINFO * STREAM, int Stream) -{ - APPLCALLS * APPL; - char * ApplPtr = APPLS; - int App; - char Appl[10]; - char FreqAppl[10] = ""; // Frequecy-specific application - char DestCall[10]; - TRANSPORTENTRY * SESS; - struct WL2KInfo * WL2K = TNC->WL2K; - UCHAR * ptr; - UCHAR Buffer[80]; - PMSGWITHLEN buffptr; - BOOL PactorCall = FALSE; - - char * Call = STREAM->RemoteCall; - - if (Stream > 0 && Stream < 30) - ProcessIncommingConnectEx(TNC, Call, Stream, FALSE, TRUE); // No CTEXT - else - ProcessIncommingConnectEx(TNC, Call, Stream, TRUE, TRUE); - - SESS = TNC->PortRecord->ATTACHEDSESSIONS[Stream]; - - if (SESS == NULL) - return; // Cant do much without one - - if (Stream > 0 && Stream < 30) - { - // Packet Connect. Much safer to process here, even though it means - // duplicating some code, or the Pactor/RP mode tests get very complicated - - int Len = 0; - struct PORTCONTROL * PORT = &TNC->PortRecord->PORTCONTROL; - - strcpy(DestCall, STREAM->MyCall); - Debugprintf("PTC Packet Incoming Call - MYCALL = *%s*", DestCall); - - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(DestCall, Appl) == 0) - break; - } - - if (App < 32) - { - char AppName[13]; - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // Make sure app is available - - Debugprintf("Connect is to APPL %s", AppName); - - if (CheckAppl(TNC, AppName)) - { - int MsgLen = sprintf(Buffer, "%s\r", AppName); - - buffptr = GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = MsgLen; - - memcpy(buffptr->Data, Buffer, MsgLen); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - else - { - char Msg[] = "Application not available\r\n"; - - // Send a Message, then a disconenct - - buffptr = GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = (int)strlen(Msg); - memcpy(buffptr->Data, Msg, strlen(Msg)); - C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr); - - STREAM->NeedDisc = 100; // 10 secs - } - return; - } - - // Not to a known appl - drop through to Node - - if (PORT->CTEXT) - { - Len = strlen(PORT->CTEXT); - ptr = PORT->CTEXT; - } - else if (CTEXTLEN) - { - Len = CTEXTLEN; - ptr = CTEXTMSG; - } - else - return; - - while (Len > 0) - { - int sendLen = TNC->PortRecord->ATTACHEDSESSIONS[Stream]->SESSPACLEN; - - if (sendLen == 0) - sendLen = 80; - - if (Len < sendLen) - sendLen = Len; - - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sendLen; - memcpy(buffptr->Data, ptr, sendLen); - C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr); - - ptr += sendLen; - Len -= sendLen; - } - return; - } - - //Connect on HF port. May be Pactor or RP on some models - - if (STREAM->DEDStream == 31) - PactorCall = TRUE; - - if (TNC->RIG && TNC->RIG != &TNC->DummyRig) - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", STREAM->RemoteCall, TNC->NodeCall, TNC->RIG->Valchar); - SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq - - // If Scan Entry has a Appl, save it - - if (PactorCall && TNC->RIG->FreqPtr && TNC->RIG->FreqPtr[0]->APPL[0]) - strcpy(FreqAppl, &TNC->RIG->FreqPtr[0]->APPL[0]); - } - else - { - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", STREAM->RemoteCall, TNC->NodeCall); - if (WL2K) - SESS->Frequency = WL2K->Freq; - } - - if (WL2K) - strcpy(SESS->RMSCall, WL2K->RMSCall); - - SESS->Mode = PleveltoMode[TNC->Streams[Stream].PTCStatus1]; - - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - if (PactorCall && TNC->MinLevel > 1) - TNC->MinLevelTimer = 150; // Check we have reached right level - - // See which application the connect is for - - strcpy(DestCall, STREAM->MyCall); - - if (PactorCall) - Debugprintf("Pactor Incoming Call - MYCALL = *%s*", DestCall); - else - Debugprintf("HF Packet/RP Incoming Call - MYCALL = *%s*", DestCall); - - if ((PactorCall && TNC->UseAPPLCallsforPactor) || (PactorCall == 0 && TNC->UseAPPLCalls)) - // Test for Richard - Should drop through to Node if not to an APPLCALL - //&& strcmp(DestCall, TNC->NodeCall) != 0) // Not Connect to Node Call - { - for (App = 0; App < 32; App++) - { - APPL=&APPLCALLTABLE[App]; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) - *ptr = 0; - - if (_stricmp(DestCall, Appl) == 0) - break; - } - - if (App < 32) - { - char AppName[13]; - - memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12); - AppName[12] = 0; - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(AppName, "RELAY "); - - // Make sure app is available - - Debugprintf("Connect is to APPL %s", AppName); - - if (CheckAppl(TNC, AppName)) - { - int MsgLen = sprintf(Buffer, "%s\r", AppName); - buffptr = GetBuff(); - - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = MsgLen; - memcpy(buffptr->Data, Buffer, MsgLen); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - } - else - { - char Msg[] = "Application not available\r\n"; - - // Send a Message, then a disconenct - - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = strlen(Msg); - memcpy(buffptr->Data, Msg, strlen(Msg)); - C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr); - - STREAM->NeedDisc = 100; // 10 secs - } - return; - } - - // Not to a known appl - drop through to Node - } - - if (!PactorCall && TNC->UseAPPLCalls) - goto DontUseAPPLCmd; // Don't use APPL= for Packet Calls - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && strcmp(FreqAppl, "RMS") == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - strcpy(FreqAppl, "RELAY"); - - Debugprintf("Pactor Call is %s Freq Specific Appl is %s Freq is %s", - DestCall, FreqAppl, TNC->RIG->Valchar); - - if (FreqAppl[0]) // Frequency specific APPL overrides TNC APPL - { - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - Debugprintf("Using Freq Specific Appl %s", FreqAppl); - - buffptr->Len = sprintf(buffptr->Data, "%s\r", FreqAppl); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - return; - } - - // If an autoconnect APPL is defined, send it - - if (TNC->ApplCmd) - { - char App[16]; - - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - strcpy(App, TNC->ApplCmd); - - Debugprintf("Using Default Appl *%s*, connecting call is %s", App, Call); - - // if SendTandRtoRelay set and Appl is RMS change to RELAY - - if (TNC->SendTandRtoRelay && memcmp(App, "RMS", 3) == 0 - && (strstr(Call, "-T" ) || strstr(Call, "-R"))) - { - strcpy(App, "RELAY"); - Debugprintf("Radio Only Call - Connecting to RELAY"); - } - - buffptr->Len = sprintf(buffptr->Data, "%s\r", App); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - TNC->SwallowSignon = TRUE; - return; - } - -DontUseAPPLCmd: - - if (FULL_CTEXT && CTEXTLEN && HFCTEXTLEN == 0) - { - int Len = CTEXTLEN, CTPaclen = 100; - int Next = 0; - - while (Len > CTPaclen) // CTEXT Paclen - { - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = CTPaclen; - memcpy(buffptr->Data, &CTEXTMSG[Next], CTPaclen); - C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr); - - Next += CTPaclen; - Len -= CTPaclen; - } - - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = Len; - memcpy(buffptr->Data, &CTEXTMSG[Next], Len); - C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr); - } -} - -VOID ProcessDEDFrame(struct TNCINFO * TNC, UCHAR * Msg, int framelen) -{ - PMSGWITHLEN buffptr; - UCHAR * Buffer; // Data portion of frame - char Status[80]; - unsigned int Stream = 0, RealStream; - - if (TNC->HostMode == 0) - return; - - // Any valid frame is an ACK - - TNC->Timeout = 0; - - if (TNC->TNCOK == FALSE) - { - // Just come up - - struct RIGPORTINFO * PORT; - - TNC->TNCOK = TRUE; - sprintf(TNC->WEB_COMMSSTATE,"%s TNC link OK", TNC->PortRecord->PORTCONTROL.SerialPortName); - SetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); - - // If using an FT847 on PTC Port it needa a "Cat On" Command. Send it here - - if (TNC->RIG->PORT && TNC->RIG->PORT->PTC) - { - PORT = TNC->RIG->PORT; - - if (strcmp(PORT->Rigs[0].RigName, "FT847") == 0) - { - UCHAR CATON[6] = {0,0,0,0,0}; - SendPTCRadioCommand(PORT->PTC, CATON, 5); - } - } - } - - Stream = RealStream = Msg[2]; - - if (Stream > 29) - Stream = 0; // 31 = Pactor or 30 = Robust Packet Outgoing - - // if in Dragon Single Mode (Pactor and Packet on Same Port) - // we only use stream 0, so if a packet frame, set DEDStream - - // Im not convinced this is the bast place to do this, but let's try - - if (TNC->DragonSingle && RealStream && RealStream < 31) // Not a Pactor or control frame - { - // must be packet - - TNC->Streams[0].DEDStream = RealStream; // Packet Channel - Stream = 0; - } - - if (TNC->TXBuffer[5] == '#') // Shouldnt happen! - return; - - - // See if Poll Reply or Data - - if (Msg[3] == 0) - { - // Success - Nothing Follows - - if (Stream < 32) - if (TNC->Streams[Stream].CmdSet) - return; // Response to Command Set - - if ((TNC->TXBuffer[3] & 1) == 0) // Data - return; - - // If the response to a Command, then we should convert to a text "Ok" for forward scripts, etc - - if (TNC->TXBuffer[5] == 'G') // Poll - return; - - if (TNC->TXBuffer[5] == 'C') // Connect - reply we need is async - return; - - if (TNC->TXBuffer[5] == 'L') // Shouldnt happen! - return; - - if (TNC->TXBuffer[5] == '#') // Shouldnt happen! - return; - - if (TNC->TXBuffer[5] == '%' && TNC->TXBuffer[6] == 'W') // Scan Control - Response to W1 - if (TNC->InternalCmd) - return; // Just Ignore - - if (TNC->TXBuffer[5] == 'J') // JHOST - { - if (TNC->TXBuffer[10] == '0') // JHOST0 - { - TNC->Timeout = 1; // - return; - } - } - - if (TNC->Streams[Stream].Connected) - return; - - buffptr = GetBuff(); - - if (buffptr == NULL) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data,"Pactor} Ok\r"); - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, buffptr->Data, (int)buffptr->Len); - CloseLogFile(TNC->Port); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - return; - } - - if (Msg[3] > 0 && Msg[3] < 6) - { - // Success with message - null terminated - - UCHAR * ptr; - int len; - - if (Msg[2] == 0xff) // General Poll Response - { - UCHAR * Poll = TNC->TXBuffer; - UCHAR Chan = Msg[4] - 1; - - if (Chan == 255) // Nothing doing - return; - - if (Msg[5] != 0) - { - // More than one to poll - save the list of channels to poll - - strcpy(TNC->NexttoPoll, &Msg[5]); - } - - // Poll the channel that had data - - Poll[2] = Chan; // Channel - Poll[3] = 0x1; // Command - - if (Chan == 254) // Status - Send Extended Status (G3) - { - Poll[4] = 1; // Len-1 - Poll[5] = 'G'; // Extended Status Poll - Poll[6] = '3'; - } - else - { - Poll[4] = 0; // Len-1 - Poll[5] = 'G'; // Poll - } - - CRCStuffAndSend(TNC, Poll, Poll[4] + 6); - TNC->InternalCmd = FALSE; - - return; - } - - Buffer = &Msg[4]; - - ptr = strchr(Buffer, 0); - - if (ptr == 0) - return; - - *(ptr++) = 13; - *(ptr) = 0; - - len = (int)(ptr - Buffer); - - if (len > 256) - return; - - // See if we need to process locally (Response to our command, Incoming Call, Disconencted, etc - - if (Msg[3] < 3) // 1 or 2 - Success or Fail - { - char LastCmd = TNC->TXBuffer[5]; - struct STREAMINFO * STREAM = &TNC->Streams[Stream]; - - // See if a response to internal command - - if (TNC->RIG->RIG_DEBUG) - if (LastCmd == 'I') - Debugprintf("SCS I Cmd Response %s", Buffer); - - if (LastCmd == 'I' && STREAM->CheckingCall == TRUE) - { - // We've received a connect and are checking MYCALL - - Debugprintf("SCS Incoming Call I Cmd Response %s Stream %d DED Stream %d", Buffer, Stream, RealStream); - - strlop(Buffer, 13); - strcpy(STREAM->MyCall, Buffer); - - ProcessIncomingCall(TNC, STREAM, Stream); - STREAM->CheckingCall = FALSE; - return; - } - - if (TNC->InternalCmd) - { - // Process it - - if (LastCmd == 'L') // Status - { - int s1, s2, s3, s4, s5, s6, num; - - num = sscanf(Buffer, "%d %d %d %d %d %d", &s1, &s2, &s3, &s4, &s5, &s6); - - TNC->Streams[Stream].FramesOutstanding = s3; - - // flow control debug - - sprintf(TNC->WEB_BUFFERS, "%d Q %d", TNC->Buffers, TNC->Streams[0].FramesOutstanding); - SetWindowText(TNC->xIDC_BUFFERS, TNC->WEB_BUFFERS); - - return; - } - - if (LastCmd == '@') // @ Commands - { - if (TNC->TXBuffer[6]== 'B') // Buffer Status - { - TNC->Buffers = atoi(Buffer); - sprintf(TNC->WEB_BUFFERS, "%d Q %d", TNC->Buffers, TNC->Streams[0].FramesOutstanding); - SetWindowText(TNC->xIDC_BUFFERS, TNC->WEB_BUFFERS); - return; - } - } - - if (LastCmd == '%') // % Commands - { - if (TNC->TXBuffer[6]== 'T') // TX count Status - { - sprintf(TNC->WEB_TRAFFIC, "RX %d TX %d ACKED %s", TNC->Streams[Stream].BytesRXed, TNC->Streams[Stream].BytesTXed, Buffer); - SetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC); - return; - } - - if (TNC->TXBuffer[6] == 'W') // Scan Control - { - if (Msg[4] == '1') // Ok to Change - { - TNC->OKToChangeFreq = 1; - TNC->TimeScanLocked = 0; - if (TNC->RIG->RIG_DEBUG) - Debugprintf("Scan Debug SCS Pactor TNC gave permission"); - } - else - { - TNC->OKToChangeFreq = -1; - if (TNC->SyncSupported == FALSE && TNC->UseAPPLCallsforPactor && TNC->TimeScanLocked == 0) - TNC->TimeScanLocked = time(NULL); - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("Scan Debug SCS Pactor TNC refused permission"); - - } - } - } - return; - } - } - - if (Msg[3] == 3) // Status - { - struct STREAMINFO * STREAM = &TNC->Streams[Stream]; - - if (strstr(Buffer, "DISCONNECTED") || strstr(Buffer, "LINK FAILURE")) - { - if ((STREAM->Connecting | STREAM->Connected) == 0) - return; - - if (STREAM->Connecting && STREAM->Disconnecting == FALSE) - { - // Connect Failed - - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Failure with %s\r", TNC->Streams[Stream].RemoteCall); - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - - STREAM->Connecting = FALSE; - STREAM->Connected = FALSE; // In case! - STREAM->FramesOutstanding = 0; - - if (Stream == 0) - { - sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall); - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - } - - STREAM->ReportDISC = TRUE; // Tell Node - return; - } - - // Must Have been connected or disconnecting - Release Session - - STREAM->Connecting = FALSE; - STREAM->Connected = FALSE; // Back to Command Mode - STREAM->FramesOutstanding = 0; - - if (STREAM->Disconnecting == FALSE) - STREAM->ReportDISC = TRUE; // Tell Node - - STREAM->Disconnecting = FALSE; - return; - } - - if (strstr(Buffer, "CONNECTED")) - { - char * Call = strstr(Buffer, " to "); - char * ptr; - char MHCall[30]; - - // Do we need to protect against 2nd call in Dragon Single Mode??? - - Call += 4; - - if (Call[1] == ':') - Call +=2; - - ptr = strchr(Call, ' '); - if (ptr) *ptr = 0; - - ptr = strchr(Call, 13); - if (ptr) *ptr = 0; - - STREAM->Connected = TRUE; // Subsequent data to data channel - STREAM->Connecting = FALSE; - STREAM->ConnectTime = time(NULL); - STREAM->BytesRXed = STREAM->BytesTXed = 0; - - // Stop Scanner - - if (Stream == 0 || TNC->HFPacket) - { - TNC->SwitchToPactor = 0; // Cancel any RP to Pactor switch - - sprintf(Status, "%d SCANSTOP", TNC->Port); - Rig_Command((TRANSPORTENTRY *) -1, Status); - - SuspendOtherPorts(TNC); // Prevent connects on other ports in same scan gruop - - memcpy(MHCall, Call, 9); - MHCall[9] = 0; - } - - if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] == 0) - { - // Incoming Connect - - TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit - - // Check for ExcludeList - - if (ExcludeList[0]) - { - UCHAR AXCALL[7]; - - ConvToAX25(MHCall, AXCALL); //Permitted calls are stored in ax.25 format - - if (CheckExcludeList(AXCALL) == FALSE) - { - TidyClose(TNC, Stream); - sprintf(Status, "%d SCANSTART 15", TNC->Port); - Rig_Command((TRANSPORTENTRY *) -1, Status); - Debugprintf("SCS Call from %s rejected", MHCall); - return; - } - } - - // IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT - - if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS) - { - UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS; - UCHAR AXCALL[7]; - - ConvToAX25(MHCall, AXCALL); //Permitted calls are stored in ax.25 format - - while (TRUE) - { - if (memcmp(AXCALL, ptr, 6) == 0) // Ignore SSID - break; - - ptr += 7; - - if ((*ptr) == 0) // Not in list - { - char Status[64]; - - TidyClose(TNC, 0); - sprintf(Status, "%d SCANSTART 15", TNC->Port); - Rig_Command((TRANSPORTENTRY *) -1, Status); - Debugprintf("Pactor Call from %s not in ValidCalls - rejected", Call); - return; - } - } - } - - // Check that we think we are in the right mode - - if (Stream == 0 && TNC->Dragon == 0) // Dragon runs both at the same time - { - if (TNC->HFPacket && RealStream == 31) - { - Debugprintf("Incoming Pactor Call while in Packet Mode"); - TNC->HFPacket = FALSE; - STREAM->DEDStream = 31; - } - else - if (TNC->HFPacket == 0 && RealStream == 30) - { - Debugprintf("Incoming Packet Call while in Pactor Mode"); - TNC->HFPacket = TRUE; - STREAM->DEDStream = 30; - } - } - - if (TNC->HFPacket) - { - char Save = TNC->RIG->CurrentBandWidth; - TNC->RIG->CurrentBandWidth = 'R'; - UpdateMH(TNC, MHCall, '+', 'I'); - TNC->RIG->CurrentBandWidth = Save; - } - - memcpy(STREAM->RemoteCall, Call, 9); // Save Text Callsign - - // We need to check what MYCALL is set to, either in case - // Appl Scan has failed to change the callsign or if a - // Packet Call to MYALIAS - - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - sprintf(STREAM->CmdSet, "I\r"); - - STREAM->CheckingCall = TRUE; - return; - } - else - { - // Connect Complete - - buffptr = GetBuff(); - if (buffptr == 0) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data, "*** Connected to %s\r", Call);; - - C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); - - if (Stream == 0) - { - if (TNC->RIG) - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound Freq %s", STREAM->MyCall, STREAM->RemoteCall, TNC->RIG->Valchar); - else - sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", STREAM->MyCall, STREAM->RemoteCall); - - SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); - - if (STREAM->DEDStream == 30) // Robust Mode - { - char Save = TNC->RIG->CurrentBandWidth; - TNC->RIG->CurrentBandWidth = 'R'; - UpdateMH(TNC, Call, '+', 'O'); - TNC->RIG->CurrentBandWidth = Save; - } - else - { - UpdateMH(TNC, Call, '+', 'O'); - } - } - return; - } - } - return; - } - - if (Msg[3] == 4 || Msg[3] == 5) - { - struct STREAMINFO * STREAM = &TNC->Streams[1]; // RP Stream - - // Monitor - - if ((TNC->HFPacket || TNC->DragonSingle) && TNC->UseAPPLCalls && strstr(&Msg[4], "SABM") && STREAM->Connected == FALSE) - { - // See if a call to Nodecall or one of our APPLCALLS - if so, stop scan and switch MYCALL - - char DestCall[10] = "NOCALL "; - char * ptr1 = strstr(&Msg[7], "to "); - int i; - APPLCALLS * APPL; - char Appl[11]; - char Status[80]; - - if (ptr1) memcpy(DestCall, &ptr1[3], 10); - - ptr1 = strchr(DestCall, ' '); - if (ptr1) *(ptr1) = 0; // Null Terminate - - Debugprintf("RP SABM Received for %s" , DestCall); - - if (strcmp(TNC->NodeCall, DestCall) != 0) - { - // Not Calling NodeCall/Portcall - - if (strcmp(NodeCall, DestCall) == 0) - goto SetThisCall; - - // See if to one of our ApplCalls - - for (i = 0; i < 32; i++) - { - APPL=&APPLCALLTABLE[i]; - - if (APPL->APPLCALL_TEXT[0] > ' ') - { - char * ptr; - memcpy(Appl, APPL->APPLCALL_TEXT, 10); - ptr=strchr(Appl, ' '); - - if (ptr) *ptr = 0; - - if (strcmp(Appl, DestCall) == 0) - { - SetThisCall: - Debugprintf("RP SABM is for NODECALL or one of our APPLCalls - setting MYCALL to %s and pausing scan", DestCall); - - sprintf(Status, "%d SCANSTART 30", TNC->Port); - Rig_Command((TRANSPORTENTRY *) -1, Status); - TNC->SwitchToPactor = 0; // Stay in RP - - strcpy(STREAM->MyCall, DestCall); - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - sprintf(STREAM->CmdSet, "I%s\r", DestCall); - TNC->InternalCmd = TRUE; - - break; - } - } - } - } - } - - DoMonitor(TNC, &Msg[3], framelen - 3); - return; - - } - - // 1, 2, 4, 5 - pass to Appl - - buffptr = GetBuff(); - - if (buffptr == NULL) return; // No buffers, so ignore - - buffptr->Len = sprintf(buffptr->Data,"Pactor} %s", &Msg[4]); - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, &Msg[4], (int)strlen(&Msg[4])); - CloseLogFile(TNC->Port); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return; - } - - if (Msg[3] == 6) - { - // Monitor Data With length) - - DoMonitor(TNC, &Msg[3], framelen - 3); - return; - } - - if (Msg[3] == 7) - { - char StatusMsg[60]; - int Status, ISS, Offset; - - if (Msg[2] == 0xfe) // Status Poll Response - { - int PactorLevel = Msg[6] & 7; // Pactor Level 1-4 - - if (TNC->MinLevelTimer) - { - if (PactorLevel >= TNC->MinLevel) - { - Debugprintf("Reached MIN Pactor Level"); - TNC->MinLevelTimer = 0; - } - else - Debugprintf("Still waiting for Min Level Now %d Need %d", PactorLevel, TNC->MinLevel); - } - - Status = Msg[5]; - - TNC->Streams[0].PTCStatus0 = Status; - TNC->Streams[0].PTCStatus1 = PactorLevel; // Pactor Level 1-4 - TNC->Streams[0].PTCStatus2 = Msg[7]; // Speed Level - Offset = Msg[8]; - - if (Offset > 128) - Offset -= 128; - - TNC->Streams[0].PTCStatus3 = Offset; - - TNC->Mode = (Status >> 4) & 7; - ISS = Status & 8; - Status &= 7; - - if (TNC->PTCStatus != Status) // Changed - { - Debugprintf("SCS status changed, now %s", status[Status]); - - if (Status == 6) // SYNCH - { - // New Sync - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("SCS New SYNC Detected"); - - TNC->TimeEnteredSYNCMode = time(NULL); - TNC->SyncSupported = TRUE; - } - else - { - if (TNC->PTCStatus == 6) - { - if (TNC->RIG->RIG_DEBUG) - Debugprintf("SCS left SYNC, now %s", status[Status]); - - TNC->TimeEnteredSYNCMode = 0; - } - } - TNC->PTCStatus = Status; - } - sprintf(StatusMsg, "%x %x %x %x", TNC->Streams[0].PTCStatus0, - TNC->Streams[0].PTCStatus1, TNC->Streams[0].PTCStatus2, TNC->Streams[0].PTCStatus3); - - if (ISS) - { - SetWindowText(TNC->xIDC_TXRX, "Sender"); - strcpy(TNC->WEB_TXRX, "Sender"); - } - else - { - SetWindowText(TNC->xIDC_TXRX, "Receiver"); - strcpy(TNC->WEB_TXRX, "Receiver"); - } - - SetWindowText(TNC->xIDC_STATE, status[Status]); - strcpy(TNC->WEB_STATE, status[Status]); - SetWindowText(TNC->xIDC_MODE, ModeText[TNC->Mode]); - strcpy(TNC->WEB_MODE, ModeText[TNC->Mode]); - - if (TNC->Mode == 7) - TNC->Busy = TNC->BusyHold * 10; // BusyHold delay - - if (Offset == 128) // Undefined - sprintf(StatusMsg, "Mode %s Speed Level %d Freq Offset Unknown", - PactorLevelText[TNC->Streams[0].PTCStatus1], Msg[7]); - else - sprintf(StatusMsg, "Mode %s Speed Level %d Freq Offset %d", - PactorLevelText[TNC->Streams[0].PTCStatus1], Msg[7], Offset); - - strcpy(TNC->WEB_PACTORLEVEL, StatusMsg); - SetWindowText(TNC->xIDC_PACTORLEVEL, StatusMsg); - - return; - } - - if (Msg[2] == 248) // Log Message - { - // Monitor Data - Length format - // first 4 bytes contain a 32 bits long timestamp. - // That timestamp holds the number of seconds that elapsed since date 01.01.2000 at 00:00:00. - // The MS byte is sent first. The timestamp can be corrected to the usual C timestamp (seconds - //since 01.01.1970, 00:00:00) simply by adding 946684800 (seconds) to it. - // Teminated with LF - - int datalen = Msg[4] + 1; - unsigned int timestamp = (Msg[5] << 24) + (Msg[6] << 16) - + (Msg[6] << 8) + Msg[7] + 946684800; - - Msg[5 + datalen] = 0; - Debugprintf("SCS Debug %s", &Msg[9]); - return; - } - - if (Msg[2] == 253) // Rig Port Response - { - // Queue for Rig Control Driver - - int datalen = Msg[4] + 1; - PMSGWITHLEN buffptr; - - // if not configured to use PTC Rig Control, Ignore - - if (TNC->RIG->PORT == NULL || TNC->RIG->PORT->PTC == NULL) - return; - - buffptr = GetBuff(); - - if (buffptr) - { - buffptr->Len = datalen; - memcpy(buffptr->Data, &Msg[5], datalen); - C_Q_ADD(&TNC->RadiotoBPQ_Q, buffptr); - if (TNC->RIG->RIG_DEBUG) - { - Debugprintf("SCS RIG frame received, len %d", datalen); - Debugprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - Msg[5], Msg[6], Msg[7], Msg[8], Msg[9], Msg[10], Msg[11], Msg[12], - Msg[13], Msg[14], Msg[15], Msg[16], Msg[17], Msg[18], Msg[19], Msg[20]); - - } - } - return; - } - - // Connected Data - - buffptr = GetBuff(); - - if (buffptr == NULL) return; // No buffers, so ignore - - buffptr->Len = Msg[4] + 1; // Length - TNC->Streams[Stream].BytesRXed += (int)buffptr->Len; - memcpy(buffptr->Data, &Msg[5], buffptr->Len); - - WritetoTrace(TNC, &Msg[5], (int)buffptr->Len); - - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return; - } -} - -int GetPTCRadioCommand(struct TNCINFO * TNC, char * Block) -{ - PMSGWITHLEN buffptr; - int Length; - - if (TNC->RadiotoBPQ_Q == 0) - return 0; - - buffptr = Q_REM(&TNC->RadiotoBPQ_Q); - - Length = (int)buffptr->Len; - - memcpy(Block, buffptr->Data, Length); - - ReleaseBuffer(buffptr); - -// Debugprintf("SCS Rig Command Queued"); - - return Length;; -} - -int SendPTCRadioCommand(struct TNCINFO * TNC, char * Block, int Length) -{ - PMSGWITHLEN buffptr; - - if (TNC->TNCOK || (TNC->Hardware == H_ARDOP && TNC->ARDOPCommsMode == 'T')) - { - } - else - return 0; - - // Queue for TNC - - buffptr = GetBuff(); - - if (buffptr == 0) return (0); // No buffers, so ignore - - buffptr->Len = Length; - - memcpy(buffptr->Data, Block, Length); - - C_Q_ADD(&TNC->BPQtoRadio_Q, buffptr); - - return 0; - -} - -static MESSAGE Monframe; // I frames come in two parts. - -#define TIMESTAMP 352 - -MESSAGE * AdjMsg = &Monframe; // Adjusted for digis - -static VOID DoMonitor(struct TNCINFO * TNC, UCHAR * Msg, int Len) -{ - // Convert to ax.25 form and pass to monitor - - UCHAR * ptr, * starptr; - char * context; - char * MHCall = Monframe.ORIGIN; - - - if (Msg[0] == 6) // Second part of I or UI - { - int len = Msg[1] +1; - - memcpy(AdjMsg->L2DATA, &Msg[2], len); - Monframe.LENGTH += len; - - time(&Monframe.Timestamp); - - BPQTRACE((MESSAGE *)&Monframe, TRUE); - return; - } - - Monframe.LENGTH = MSGHDDRLEN + 16; // Control Frame - - Monframe.PORT = TNC->Port; - - AdjMsg = &Monframe; // Adjusted for digis - ptr = strstr(Msg, "fm "); - - ConvToAX25(&ptr[3], Monframe.ORIGIN); - - ptr = strstr(ptr, "to "); - - ConvToAX25(&ptr[3], Monframe.DEST); - - ptr = strstr(ptr, "via "); - - if (ptr) - { - // We have digis - - char Save[100]; - char * fiddle; - - memcpy(Save, &ptr[4], 60); - - ptr = strtok_s(Save, " ", &context); -DigiLoop: - fiddle = (char *)AdjMsg; - fiddle += 7; - AdjMsg = (MESSAGE *)fiddle; - - Monframe.LENGTH += 7; - - starptr = strchr(ptr, '*'); - if (starptr) - *(starptr) = 0; - - ConvToAX25(ptr, AdjMsg->ORIGIN); - - if (starptr) - AdjMsg->ORIGIN[6] |= 0x80; // Set end of address - - ptr = strtok_s(NULL, " ", &context); - - if (memcmp(ptr, "ctl", 3)) - goto DigiLoop; - } - - AdjMsg->ORIGIN[6] |= 1; // Set end of address - - ptr = strstr(Msg, "ctl "); - - if (memcmp(&ptr[4], "SABM", 4) == 0) - { - AdjMsg->CTL = 0x2f; - UpdateMHwithDigis(TNC, MHCall, '.', 0); - } - else - if (memcmp(&ptr[4], "DISC", 4) == 0) - AdjMsg->CTL = 0x43; - else - if (memcmp(&ptr[4], "UA", 2) == 0) - { - AdjMsg->CTL = 0x63; - UpdateMHwithDigis(TNC, MHCall, '.', 0); - } - else - if (memcmp(&ptr[4], "DM", 2) == 0) - AdjMsg->CTL = 0x0f; - else - if (memcmp(&ptr[4], "UI", 2) == 0) - { - AdjMsg->CTL = 0x03; - UpdateMHwithDigis(TNC, MHCall, '.', 0); - } - else - if (memcmp(&ptr[4], "RR", 2) == 0) - AdjMsg->CTL = 0x1 | (ptr[6] << 5); - else - if (memcmp(&ptr[4], "RNR", 3) == 0) - AdjMsg->CTL = 0x5 | (ptr[7] << 5); - else - if (memcmp(&ptr[4], "REJ", 3) == 0) - AdjMsg->CTL = 0x9 | (ptr[7] << 5); - else - if (memcmp(&ptr[4], "FRMR", 4) == 0) - AdjMsg->CTL = 0x87; - else - if (ptr[4] == 'I') - { - AdjMsg->CTL = (ptr[5] << 5) | (ptr[6] & 7) << 1 ; - } - - if (strchr(&ptr[4], '+')) - { - AdjMsg->CTL |= 0x10; - Monframe.DEST[6] |= 0x80; // SET COMMAND - } - - if (strchr(&ptr[4], '-')) - { - AdjMsg->CTL |= 0x10; - Monframe.ORIGIN[6] |= 0x80; // SET COMMAND - } - - if (Msg[0] == 5) // More to come - { - ptr = strstr(ptr, "pid "); - sscanf(&ptr[3], "%x", (int *)&AdjMsg->PID); - return; - } - - time(&Monframe.Timestamp); - - BPQTRACE((MESSAGE *)&Monframe, TRUE); - -} -//1:fm G8BPQ to KD6PGI-1 ctl I11^ pid F0 -//fm KD6PGI-1 to G8BPQ ctl DISC+ - -VOID TidyClose(struct TNCINFO * TNC, int Stream) -{ - // Queue it as we may have just sent data - - TNC->Streams[Stream].CmdSet = TNC->Streams[Stream].CmdSave = malloc(100); - sprintf(TNC->Streams[Stream].CmdSet, "D\r"); -} - - -VOID ForcedClose(struct TNCINFO * TNC, int Stream) -{ - // Sending D twice should do a "Dirty Disconnect" - - // Try thst first. If it still doesn't disconnect maybe try restart - - unsigned char Resp[500] = ""; - char * Poll = &TNC->TXBuffer[0]; - - Debugprintf("Failed to disconnect TNC - trying a forced disconnect"); - - // Try Normal Mode DD (Dirty Disconnect) - - // Uses "Hidden" feature where you can send any normal mode command - // in host mode by preceeding with a # - - Poll[2] = 31; - Poll[3] = 0x1; - Poll[4] = 2; - sprintf(&Poll[5], "#DD\r"); // Node \r isn't sent but is there for log - CRCStuffAndSend(TNC, Poll, 8); - - // It looks like there isn't a response - - TNC->Timeout = 0; - - OpenLogFile(TNC->Port); - WriteLogLine(TNC->Port, &Poll[5], 4); - CloseLogFile(TNC->Port); - -/* - Poll[2] = 31; - Poll[3] = 1; - Poll[4] = 0; - Poll[5] = 'D'; - - CRCStuffAndSend(TNC, Poll, 6); - - // Wait for response before sending another - - n = 0; - while (CheckRXHost(TNC, Resp) == FALSE) - { - Sleep(5); - n++; - if (n > 100) break; - } - - Poll[2] = 31; - Poll[3] = 1; - Poll[4] = 0; - Poll[5] = 'D'; - - CRCStuffAndSend(TNC, Poll, 6); - - n = 0; - while (CheckRXHost(TNC, Resp) == FALSE) - { - Sleep(5); - n++; - if (n > 100) break; - } - - // See if it worked - - Poll[2] = 254; // Channel - Poll[3] = 0x1; // Command - Poll[4] = 1; // Len-1 - Poll[5] = 'G'; // Extended Status Poll - Poll[6] = '3'; - - CRCStuffAndSend(TNC, Poll, 7); - - n = 0; - while (CheckRXHost(TNC, Resp) == FALSE) - { - Sleep(5); - n++; - if (n > 100) break; - } - - Debugprintf("PTC Status Now %x %x %x %x %x %x %x %x", - Resp[0], Resp[1], Resp[2], Resp[3], Resp[4], Resp[5], Resp[6], Resp[7]); - - TNC->Timeout = 0; - - return; - - // Maybe best just to restart the TNC - - if (TNC->PacketChannels == 0) // Not using packet - { - Debugprintf("Forced Disconnect Failed - restarting TNC"); - - // Ensure in Pactor - - if(TNC->Dragon == 0) - { - TNC->TXBuffer[2] = 31; - TNC->TXBuffer[3] = 0x1; - TNC->TXBuffer[4] = 0x1; - memcpy(&TNC->TXBuffer[5], "PT", 2); - - CRCStuffAndSend(TNC, TNC->TXBuffer, 7); - - n = 0; - while (CheckRXHost(TNC, Resp) == FALSE) - { - Sleep(5); - n++; - if (n > 100) break; - } - } - - Sleep(50); - ExitHost(TNC); - Sleep(50); - - n = 0; - while (CheckRXHost(TNC, Resp) == FALSE) - { - Sleep(5); - n++; - if (n > 100) break; - } - - TNC->Timeout = 0; - TNC->HostMode = FALSE; - TNC->ReinitState = 0; - - return; - } -*/ -} - -VOID CloseComplete(struct TNCINFO * TNC, int Stream) -{ - char Status[80]; - struct STREAMINFO * STREAM = &TNC->Streams[Stream]; - - Debugprintf("SCS Pactor Close Complete - Stream = %d", Stream); - - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - - strcpy(STREAM->MyCall, TNC->NodeCall); - - if (Stream == 0 || TNC->HFPacket) - { - SetWindowText(TNC->xIDC_TNCSTATE, "Free"); - strcpy(TNC->WEB_TNCSTATE, "Free"); - sprintf(Status, "%d SCANSTART 15", TNC->Port); - Rig_Command((TRANSPORTENTRY *) -1, Status); - - if (TNC->Dragon) - { - sprintf(STREAM->CmdSet, "I%s\r", TNC->NodeCall); - TNC->Streams[0].DEDStream = 31; // Pactor Channel - } - else - { - if (TNC->HFPacket) - { - sprintf(STREAM->CmdSet, "I%s\rPR\r", TNC->NodeCall); - TNC->Streams[0].DEDStream = 30; // Packet Channel - Debugprintf("BPQ32 Session Closed - switch to Packet"); - } - else - { - sprintf(STREAM->CmdSet, "I%s\rPT\r", TNC->NodeCall); - TNC->Streams[0].DEDStream = 31; // Pactor Channel - Debugprintf("BPQ32 Session Closed - switch to Pactor"); - } - } - ReleaseOtherPorts(TNC); - } - else - sprintf(STREAM->CmdSet, "I%s\r", TNC->NodeCall); - - Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet); - -} - -VOID PTCSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - STREAM->CmdSet = STREAM->CmdSave = zalloc(100); - sprintf(STREAM->CmdSet, "I%s\r", "SCSPTC"); // Should prevent connects - - Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet); -} - -VOID PTCReleasePort(struct TNCINFO * TNC) -{ - struct STREAMINFO * STREAM = &TNC->Streams[0]; - - STREAM->CmdSet = STREAM->CmdSave = zalloc(100); - - if (TNC->UseAPPLCallsforPactor && TNC->RIG && TNC->RIG != &TNC->DummyRig - && TNC->RIG->FreqPtr[0]->APPLCALL[0]) - sprintf(STREAM->CmdSet, "I%s\r", TNC->RIG->FreqPtr[0]->APPLCALL); - else - sprintf(STREAM->CmdSet, "I%s\r", TNC->NodeCall); - - Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet); -} - - - diff --git a/SerialPort.c b/SerialPort.c index 59ab627..9886be7 100644 --- a/SerialPort.c +++ b/SerialPort.c @@ -452,8 +452,7 @@ ok: if (buffptr == 0) return (0); // No buffers, so ignore - buffptr->Len = 36; - memcpy(&buffptr->Data[0], "No Connection to TNC\r", 36); + buffptr->Len = sprintf(&buffptr->Data[0], "No Connection to TNC\r"); C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); diff --git a/TelnetV6.c b/TelnetV6.c index b139fad..eb8f9a1 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -427,6 +427,7 @@ int ProcessLine(char * buf, int Port) TCP->MaxSessions = 10; // Default Values TNC->Hardware = H_TELNET; TCP->IPV4 = TRUE; + TCP->SecureTelnet = 1; strcpy(TCP->CMSServer, "cms.winlink.org"); } diff --git a/VARA.c b/VARA.c index 6d1ec68..f83adb1 100644 --- a/VARA.c +++ b/VARA.c @@ -2586,7 +2586,7 @@ VOID VARAProcessDataPacket(struct TNCINFO * TNC, UCHAR * Data, int Length) STREAM->BytesRXed += Length; Data[Length] = 0; - Debugprintf("VARA: RXD %d bytes", Length); +// Debugprintf("VARA: RXD %d bytes", Length); sprintf(TNC->WEB_TRAFFIC, "Sent %d RXed %d Queued %d", STREAM->BytesTXed, STREAM->BytesRXed,STREAM->BytesOutstanding); diff --git a/Versions.h b/Versions.h index 2fd8eb3..332f2ea 100644 --- a/Versions.h +++ b/Versions.h @@ -10,14 +10,14 @@ #endif -#define KVers 6,0,24,40 -#define KVerstring "6.0.24.40\0" +#define KVers 6,0,24,42 +#define KVerstring "6.0.24.42\0" #ifdef CKernel #define Vers KVers #define Verstring KVerstring -#define Datestring "January 2024" +#define Datestring "August 2024" #define VerComments "G8BPQ Packet Switch (C Version)" KVerstring #define VerCopyright "Copyright © 2001-2024 John Wiseman G8BPQ\0" #define VerDesc "BPQ32 Switch\0" diff --git a/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user new file mode 100644 index 0000000..fa82c00 --- /dev/null +++ b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user new file mode 100644 index 0000000..0cd9a72 --- /dev/null +++ b/WinmorControl.vcproj.LAPTOP-Q6S4RP5Q.johnw.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/WinmorControl.vcproj.NOTTSDESKTOP.John.user b/WinmorControl.vcproj.NOTTSDESKTOP.John.user new file mode 100644 index 0000000..fa82c00 --- /dev/null +++ b/WinmorControl.vcproj.NOTTSDESKTOP.John.user @@ -0,0 +1,65 @@ + + + + + + + + + + + diff --git a/bpqchat.c b/bpqchat.c index 06fb369..35f62c9 100644 --- a/bpqchat.c +++ b/bpqchat.c @@ -70,8 +70,9 @@ // Allow /History to be shortened to /Hi (45) // Fix extra r charater in Chat Config Web Page +//.25 -// Increase sise of status display buffers (7) +// Increase size of status display buffers (7) #include "BPQChat.h" #include "Dbghelp.h" diff --git a/bpqmail.h b/bpqmail.h index 7b72ea4..48270a1 100644 --- a/bpqmail.h +++ b/bpqmail.h @@ -1194,8 +1194,7 @@ int CountMessagestoForward(struct UserInfo * user); VOID * GetMultiLineDialogParam(HWND hDialog, int DLGItem); -#define LIBCONFIG_STATIC -#include "libconfig.h" + VOID * GetMultiStringValue(config_setting_t * hKey, char * ValueName); VOID * RegGetMultiStringValue(HKEY hKey, char * ValueName); diff --git a/tncinfo.h b/tncinfo.h index fa8f4c9..bd0639e 100644 --- a/tncinfo.h +++ b/tncinfo.h @@ -225,6 +225,8 @@ struct STREAMINFO char AGWKey[21]; // Session Key for AGW Session Based Drivers time_t ConnectTime; // Time connection made + time_t AttachTime; + int BytesTXed; int BytesAcked; int BytesRXed; @@ -258,6 +260,7 @@ struct STREAMINFO HWND xIDC_DIRN; int RelaySyncStream; + int VaraACMode; }; typedef struct AGWINFO @@ -409,7 +412,7 @@ struct FreeDataINFO char * SSIDS[16]; }; - +struct sixPackInfo; typedef struct TNCINFO { @@ -427,6 +430,9 @@ typedef struct TNCINFO time_t SessionTimeLimit; // Optional limit to total session time time_t DefaultSessionTimeLimit; // Configured value + time_t AttachTimeLimit; // to trap port left attached for a long time without other activity + time_t AttachTime; + int Hardware; // Hardware Type #define H_WINMOR 1 @@ -449,6 +455,7 @@ typedef struct TNCINFO #define H_WINRPR 17 #define H_HSMODEM 18 #define H_FREEDATA 19 +#define H_SIXPACK 20 int Port; // BPQ Port Number @@ -839,6 +846,8 @@ typedef struct TNCINFO char * NRNeighbour; int NRCloseTimer; struct _LINKTABLE * DummyLink; // Simulated link to simplify interface to ax,25 netrom code + struct sixPackPortInfo * sixPack; + int VaraACMode; } *PTNCINFO; diff --git a/upnp.c b/upnp.c index dbc7c8d..96cb9d3 100644 --- a/upnp.c +++ b/upnp.c @@ -85,6 +85,7 @@ char * leaseDuration = NULL; struct UPNPDev * devlist = 0; char lanaddr[64] = "unset"; /* my ip address on the LAN */ +char wanaddr[64] = "unset"; /* my ip address on the LAN */ struct UPNPUrls urls; struct IGDdatas data; @@ -126,7 +127,11 @@ int upnpInit() return 0; } +#if MINIUPNPC_API_VERSION == 18 + i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr)); +#else i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); +#endif } AddMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol); @@ -153,7 +158,11 @@ int upnpClose() return 0; } +#if MINIUPNPC_API_VERSION == 18 + i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr)); +#else i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); +#endif } DeleteMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol); From a47cc11d8ada25cbc54a7078152e19591a1da87b Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Fri, 30 Aug 2024 10:16:14 +0100 Subject: [PATCH 09/12] First build needs --- debian/changelog | 5 +++-- debian/patches/ftbfs-gcc14.patch | 11 +++++++++++ debian/patches/secure-by-default.patch | 4 ++-- debian/patches/series | 1 + 4 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 debian/patches/ftbfs-gcc14.patch diff --git a/debian/changelog b/debian/changelog index 5d6d692..f482e14 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ -linbpq (6.0.24.40-2) UNRELEASED; urgency=medium +linbpq (6.0.24.42-1) UNRELEASED; urgency=medium * Install config to /etc + * New upstream update - -- Dave Hibberd Sat, 17 Aug 2024 17:41:25 +0100 + -- Dave Hibberd Fri, 30 Aug 2024 10:15:11 +0100 linbpq (6.0.24.40-1) unstable; urgency=medium diff --git a/debian/patches/ftbfs-gcc14.patch b/debian/patches/ftbfs-gcc14.patch new file mode 100644 index 0000000..096769c --- /dev/null +++ b/debian/patches/ftbfs-gcc14.patch @@ -0,0 +1,11 @@ +--- a/Multicast.c ++++ b/Multicast.c +@@ -620,7 +620,7 @@ + int r; + + UINT rlen; +- UINT outlen; ++ long outlen; + + memcpy(&rlen, &Decoded[5], 4); + diff --git a/debian/patches/secure-by-default.patch b/debian/patches/secure-by-default.patch index 38550cd..9d371bf 100644 --- a/debian/patches/secure-by-default.patch +++ b/debian/patches/secure-by-default.patch @@ -1,8 +1,8 @@ --- a/TelnetV6.c +++ b/TelnetV6.c -@@ -428,6 +428,7 @@ - TNC->Hardware = H_TELNET; +@@ -429,6 +429,7 @@ TCP->IPV4 = TRUE; + TCP->SecureTelnet = 1; strcpy(TCP->CMSServer, "cms.winlink.org"); + TCP->SecureTelnet = 1; } diff --git a/debian/patches/series b/debian/patches/series index 6953e90..d2549aa 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,4 @@ +ftbfs-gcc14.patch spelling-errors.patch makefile secure-by-default.patch From 666c2aabb4fa81e856ff58d4d4bb47760da34978 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Fri, 30 Aug 2024 10:35:36 +0100 Subject: [PATCH 10/12] Start tidying up headers --- debian/patches/ftbfs-gcc14.patch | 55 +++++++ debian/patches/headers.patch | 258 +++++++++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 314 insertions(+) create mode 100644 debian/patches/headers.patch diff --git a/debian/patches/ftbfs-gcc14.patch b/debian/patches/ftbfs-gcc14.patch index 096769c..38a656c 100644 --- a/debian/patches/ftbfs-gcc14.patch +++ b/debian/patches/ftbfs-gcc14.patch @@ -9,3 +9,58 @@ memcpy(&rlen, &Decoded[5], 4); +--- a/MBLRoutines.c ++++ b/MBLRoutines.c +@@ -23,7 +23,7 @@ + + #include "bpqmail.h" + +-void SendMessageReadEvent(struct UserInfo * user, struct MsgInfo * Msg); ++void SendMessageReadEvent(char * Call, struct MsgInfo * Msg); + + + VOID ProcessMBLLine(CIRCUIT * conn, struct UserInfo * user, UCHAR* Buffer, int len) +--- a/bpqmail.h ++++ b/bpqmail.h +@@ -695,8 +695,8 @@ + unsigned char Type; + unsigned char changed; + unsigned short seen; +- long long last_modif; +- long long last_seen; ++ time_t last_modif; ++ time_t last_seen; + char first_homebbs[41]; + char secnd_homebbs[41]; + char first_zip[9]; +--- a/AGWAPI.c ++++ b/AGWAPI.c +@@ -128,7 +128,7 @@ + int AGWGetSessionKey(char * key, struct AGWSocketConnectionInfo * sockptr); + int ProcessAGWCommand(struct AGWSocketConnectionInfo * sockptr); + int SendDataToAppl(int Stream, byte * Buffer, int Length); +-int InternalAGWDecodeFrame(char * msg, char * buffer, int Stamp, int * FrameType, int useLocalTime, int doNodes); ++int InternalAGWDecodeFrame(char * msg, char * buffer, time_t Stamp, int * FrameType, int useLocalTime, int doNodes); + int AGWDataSocket_Disconnect( struct AGWSocketConnectionInfo * sockptr); + int SendRawPacket(struct AGWSocketConnectionInfo * sockptr, char *txmsg, int Length); + int ShowApps(); +--- a/AGWMoncode.c ++++ b/AGWMoncode.c +@@ -68,7 +68,7 @@ + static UCHAR * DISPLAYARPDATAGRAM(UCHAR * Datagram, UCHAR * Output); + + +-int InternalAGWDecodeFrame(MESSAGE * msg, char * buffer, int Stamp, int * FrameType, int useLocalTime, int DoNodes) ++int InternalAGWDecodeFrame(MESSAGE * msg, char * buffer, time_t Stamp, int * FrameType, int useLocalTime, int DoNodes) + { + UCHAR * ptr; + int n; +@@ -364,7 +364,7 @@ + } + + if (Output == NULL) +- return NULL; ++ return 0; + + if (Output[-1] != 13) + Output += sprintf((char *)Output, "\r"); diff --git a/debian/patches/headers.patch b/debian/patches/headers.patch new file mode 100644 index 0000000..e6fc079 --- /dev/null +++ b/debian/patches/headers.patch @@ -0,0 +1,258 @@ +--- /dev/null ++++ b/bpqheaders.h +@@ -0,0 +1,8 @@ ++//Header for an easier build under debian GCC-14 ++#include ++#include ++#include ++ ++int CanPortDigi(int Port); ++ ++int KissEncode(unsigned char * inbuff, unsigned char * outbuff, int len); +--- a/cMain.c ++++ b/cMain.c +@@ -29,9 +29,10 @@ + //#include "windows.h" + //#include "winerror.h" + +-#include "time.h" +-#include "stdio.h" ++#include ++#include + #include ++#include "bpqheaders.h" + + #include "kernelresource.h" + #include "CHeaders.h" +--- a/CHeaders.h ++++ b/CHeaders.h +@@ -93,7 +93,7 @@ + char * MOVEANDCHECK(TRANSPORTENTRY * Session, char * Bufferptr, char * Source, int Len); + VOID DISPLAYCIRCUIT(TRANSPORTENTRY * L4, char * Buffer); + char * FormatUptime(int Uptime); +-char * strlop(char * buf, char delim); ++char * strlop(const char * buf, char delim); + BOOL CompareCalls(UCHAR * c1, UCHAR * c2); + + VOID PostDataAvailable(TRANSPORTENTRY * Session); +@@ -427,4 +427,4 @@ + extern int MinCounter[MaxBPQPortNo + 1]; // Interval Countdown + extern BOOL SendFromFile[MaxBPQPortNo + 1]; + +-DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqStringMhz); +\ No newline at end of file ++DllExport uint64_t APIENTRY GetPortFrequency(int PortNo, char * FreqStringMhz); +--- a/WinRPR.c ++++ b/WinRPR.c +@@ -63,7 +63,6 @@ + static RECT Rect; + + VOID __cdecl Debugprintf(const char * format, ...); +-char * strlop(char * buf, char delim); + + char NodeCall[11]; // Nodecall, Null Terminated + +--- a/bpqmail.h ++++ b/bpqmail.h +@@ -877,7 +877,6 @@ + }; + + VOID __cdecl nprintf(CIRCUIT * conn, const char * format, ...); +-char * strlop(char * buf, char delim); + int rt_cmd(CIRCUIT *circuit, char * Buffer); + CIRCUIT *circuit_new(CIRCUIT *circuit, int flags); + VOID BBSputs(CIRCUIT * conn, char * buf); +--- a/APRSCode.c ++++ b/APRSCode.c +@@ -63,7 +63,6 @@ + VOID __cdecl Consoleprintf(const char * format, ...); + BOOL APIENTRY Send_AX(PMESSAGE Block, DWORD Len, UCHAR Port); + VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); +-char * strlop(char * buf, char delim); + int APRSDecodeFrame(char * msg, char * buffer, time_t Stamp, uint64_t Mask); // Unsemaphored DecodeFrame + APRSHEARDRECORD * UpdateHeard(UCHAR * Call, int Port); + BOOL CheckforDups(char * Call, char * Msg, int Len); +--- a/FLDigi.c ++++ b/FLDigi.c +@@ -101,8 +101,6 @@ + VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); + VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); + +-char * strlop(char * buf, char delim); +- + extern UCHAR BPQDirectory[]; + + #define MAXMPSKPORTS 16 +--- a/MULTIPSK.c ++++ b/MULTIPSK.c +@@ -71,8 +71,6 @@ + static VOID DoMonitorHddr(struct TNCINFO * TNC, struct AGWHEADER * RXHeader, UCHAR * Msg); + VOID SendRPBeacon(struct TNCINFO * TNC); + +-char * strlop(char * buf, char delim); +- + extern UCHAR BPQDirectory[]; + + #define MAXMPSKPORTS 16 +--- a/AGWMoncode.c ++++ b/AGWMoncode.c +@@ -61,7 +61,6 @@ + + #define NODES_SIG 0xFF + +-char * strlop(char * buf, char delim); + UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, int msglen); + + static UCHAR * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen, int DoNodes); +--- a/Bpq32.c ++++ b/Bpq32.c +@@ -1406,7 +1406,6 @@ + VOID FindLostBuffers(); + BOOL InitializeTNCEmulator(); + VOID TNCTimer(); +-char * strlop(char * buf, char delim); + + DllExport int APIENTRY Get_APPLMASK(int Stream); + DllExport int APIENTRY GetStreamPID(int Stream); +--- a/CMSAuth.c ++++ b/CMSAuth.c +@@ -31,7 +31,7 @@ + #include + #endif + +-char * strlop(char * buf, char delim); ++char * strlop(const char * buf, char delim); + + VOID APIENTRY md5 (char *arg, unsigned char * checksum); + +--- a/FLDigi64.c ++++ b/FLDigi64.c +@@ -102,8 +102,6 @@ + VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); + VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); + +-char * strlop(char * buf, char delim); +- + extern UCHAR BPQDirectory[]; + + #define MAXBPQPORTS 32 +--- a/HTTPcode.c ++++ b/HTTPcode.c +@@ -102,7 +102,6 @@ + + extern UCHAR ConfigDirectory[260]; + +-char * strlop(char * buf, char delim); + VOID sendandcheck(SOCKET sock, const char * Buffer, int Len); + int CompareNode(const void *a, const void *b); + int CompareAlias(const void *a, const void *b); +--- a/MULTIPSK64.c ++++ b/MULTIPSK64.c +@@ -74,8 +74,6 @@ + static VOID DoMonitorHddr(struct TNCINFO * TNC, struct AGWHEADER * RXHeader, UCHAR * Msg); + VOID SendRPBeacon(struct TNCINFO * TNC); + +-char * strlop(char * buf, char delim); +- + extern UCHAR BPQDirectory[]; + + #define MAXBPQPORTS 32 +--- a/Moncode.c ++++ b/Moncode.c +@@ -59,7 +59,6 @@ + + #define NODES_SIG 0xFF + +-char * strlop(char * buf, char delim); + UCHAR * DisplayINP3RIF(UCHAR * ptr1, UCHAR * ptr2, unsigned int msglen); + + char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen); +--- a/NodeMapTest.c ++++ b/NodeMapTest.c +@@ -201,7 +201,6 @@ + int ConvFromAX25(unsigned char * incall, char * outcall); + void GenerateOutputFiles(time_t Now); + void UpdateHeardData(struct NodeData * Node, struct NodeData * Call, char * Freq, char * LOC, char * Flags); +-char * strlop(char * buf, char delim); + void ProcessChatUpdate(char * From, char * Msg); + void ProcessNodeUpdate(char * From, char * Msg); + +--- a/SCSTracker.c ++++ b/SCSTracker.c +@@ -52,7 +52,6 @@ + static RECT Rect; + + VOID __cdecl Debugprintf(const char * format, ...); +-char * strlop(char * buf, char delim); + + char NodeCall[11]; // Nodecall, Null Terminated + +--- a/TelnetV6.c ++++ b/TelnetV6.c +@@ -127,8 +127,6 @@ + + static int ProcessLine(char * buf, int Port); + VOID __cdecl Debugprintf(const char * format, ...); +-char * strlop(char * buf, char delim); +- + + int DisplaySessions(struct TNCINFO * TNC); + int DoStateChange(int Stream); +--- a/UIARQ.c ++++ b/UIARQ.c +@@ -78,7 +78,6 @@ + VOID Send_AX_Datagram(PDIGIMESSAGE Block, DWORD Len, UCHAR Port); + int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); + VOID ProcessARQPacket(struct PORTCONTROL * PORT, MESSAGE * Buffer); +-char * strlop(char * buf, char delim); + + extern UCHAR BPQDirectory[]; + extern char MYALIASLOPPED[10]; +--- a/bpqchat.h ++++ b/bpqchat.h +@@ -603,7 +603,6 @@ + VOID nputs(ChatCIRCUIT * conn, char * buf); + #endif + BOOL matchi(char * p1, char * p2); +-char * strlop(char * buf, char delim); + int rt_cmd(ChatCIRCUIT *circuit, char * Buffer); + ChatCIRCUIT *circuit_new(ChatCIRCUIT *circuit, int flags); + void makelinks(void); +@@ -775,4 +774,4 @@ + + struct ConsoleInfo * ConsHeader[2]; + +-extern BOOL LogCHAT; +\ No newline at end of file ++extern BOOL LogCHAT; +--- a/SCSTrackeMulti.c ++++ b/SCSTrackeMulti.c +@@ -48,7 +48,6 @@ + static RECT Rect; + + VOID __cdecl Debugprintf(const char * format, ...); +-char * strlop(char * buf, char delim); + BOOL KAMStartPort(struct PORTCONTROL * PORT); + BOOL KAMStopPort(struct PORTCONTROL * PORT); + +--- a/SCSTrackeMulti64.c ++++ b/SCSTrackeMulti64.c +@@ -52,7 +52,6 @@ + struct TNCINFO * TNCInfo[34]; // Records are Malloc'd + + VOID __cdecl Debugprintf(const char * format, ...); +-char * strlop(char * buf, char delim); + BOOL KAMStartPort(struct PORTCONTROL * PORT); + BOOL KAMStopPort(struct PORTCONTROL * PORT); + +--- a/CommonCode.c ++++ b/CommonCode.c +@@ -568,7 +568,7 @@ + return ptr; + } + +-char * strlop(char * buf, char delim) ++char * strlop(const char * buf, char delim) + { + // Terminate buf at delim, and return rest of string + diff --git a/debian/patches/series b/debian/patches/series index d2549aa..8e599fc 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,4 @@ +headers.patch ftbfs-gcc14.patch spelling-errors.patch makefile From 85da9edc164b92933d92aeca16be430a8274e992 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Fri, 30 Aug 2024 11:46:56 +0100 Subject: [PATCH 11/12] Try hardening on for size --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index b802fff..acc4edb 100755 --- a/debian/rules +++ b/debian/rules @@ -1,6 +1,6 @@ #!/usr/bin/make -f -#export DEB_BUILD_MAINT_OPTIONS=hardening=+all +export DEB_BUILD_MAINT_OPTIONS=hardening=+all CFLAGS = $(shell dpkg-buildflags --get CFLAGS) CFLAGS += -fcommon From b18a579b0c56cbf065714972a48c19d1662180e8 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Wed, 25 Sep 2024 01:37:12 +0100 Subject: [PATCH 12/12] Updates to .42 --- debian/changelog | 5 +++-- debian/control | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index f482e14..1efabd0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,10 @@ -linbpq (6.0.24.42-1) UNRELEASED; urgency=medium +linbpq (6.0.24.42-1) unstable; urgency=medium * Install config to /etc * New upstream update + * Add in new repo for continued updates - -- Dave Hibberd Fri, 30 Aug 2024 10:15:11 +0100 + -- Dave Hibberd Wed, 25 Sep 2024 01:36:59 +0100 linbpq (6.0.24.40-1) unstable; urgency=medium diff --git a/debian/control b/debian/control index e879a32..6c598e2 100644 --- a/debian/control +++ b/debian/control @@ -11,7 +11,7 @@ Rules-Requires-Root: no Package: linbpq Architecture: linux-any -Depends: ${shlibs:Depends}, ${misc:Depends}, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, adduser, hibbian-archive-keyring Description: Packet node and ax25 stack LINBPQ is a Linux version of the BPQ32 Node, BBS and Chat Server components. It is actively developed by John G8BPQ and contains a complete, independent