Compare commits

...

9 Commits

Author SHA1 Message Date
Hibby 3de6b0150f Update upstream source from tag 'upstream/6.0.24.45'
Update to upstream version '6.0.24.45'
with Debian dir 9a5822f2bb
2024-10-11 15:37:17 +01:00
Hibby eb0d36d3f6 New upstream version 6.0.24.45 2024-10-11 15:37:11 +01:00
Hibby 0d48067b82
Sneak in the 32bit fixes 2024-09-26 23:13:41 +01:00
Hibby b18a579b0c
Updates to .42 2024-09-25 01:37:12 +01:00
Hibby 85da9edc16
Try hardening on for size 2024-08-30 11:46:56 +01:00
Hibby 666c2aabb4
Start tidying up headers 2024-08-30 11:46:04 +01:00
Hibby a47cc11d8a
First build needs 2024-08-30 10:23:16 +01:00
Hibby b26c87817a Update upstream source from tag 'upstream/6.0.24.42'
Update to upstream version '6.0.24.42'
with Debian dir 41e80b6ddf
2024-08-30 10:15:03 +01:00
Hibby 6dfe32758e New upstream version 6.0.24.42 2024-08-30 10:14:56 +01:00
55 changed files with 4543 additions and 5298 deletions

2129
6pack.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -348,7 +348,7 @@ APRSHEARDRECORD MHTABLE[MAXHEARD] = {0};
APRSHEARDRECORD * MHDATA = &MHTABLE[0];
static SOCKET sock = (SOCKET) NULL;
static SOCKET sock = (SOCKET)0;
//Duplicate suppression Code
@ -9154,7 +9154,7 @@ void GetSavedAPRSMessages()
FILE *file;
struct APRSMESSAGE * Message;
struct APRSMESSAGE * ptr;
char Line[256];
char Line[512];
char * Stamp = 0;
char * From = 0;
char * To = 0;

View File

@ -3225,6 +3225,170 @@ char * get_plane(int * Len)
return ptr;
}
char * get_portstats()
{
char Msg[] =
"<!DOCTYPE html>\n"
"<html>\n"
"\n"
"<head>\n"
"<script src=\"https://code.jquery.com/jquery-3.6.0.min.js\"> </script>\n"
"</head>\n"
"\n"
"\n"
"<body>\n"
"<H2 id=\"h1\"> Last hour's stats for Port </h2>\n"
"<p>\n"
"<canvas id=\"myCanvas\" width=\"600\" height=\"250\" style=\"border:1px solid #d3d3d3;\">\n"
"Your browser does not support the HTML canvas tag.</canvas>\n"
"<br>\n"
"<canvas id=\"myCanvas2\" width=\"600\" height=\"250\" style=\"border:1px solid #d3d3d3;\">\n"
"Your browser does not support the HTML canvas tag.</canvas>\n"
"\n"
"<script>\n"
"var c = document.getElementById(\"myCanvas\");\n"
"var ctx = c.getContext(\"2d\");\n"
"\n"
"var port = window.location.search.slice(1);\n"
"\n"
"document.getElementById(\"h1\").innerHTML = \"Last hour's stats for Port \" + port;;\n"
"\n"
"var oReq = new XMLHttpRequest();\n"
"oReq.open(\"GET\", \"/portstats.txt?\" + port, true);\n"
"oReq.responseType = \"arraybuffer\";\n"
"\n"
"oReq.onload = function(oEvent)\n"
" {\n"
" var arrayBuffer = oReq.response;\n"
"\n"
" var byteArray = new Uint8Array(arrayBuffer);\n"
" \n"
" \n"
" // Draw it. Do last hour for testing. Plot each value for 10 pixels\n"
" \n"
"\tctx.strokeStyle = \"green\";\n"
"\tctx.beginPath();\n"
"\t\n"
"\tctx.moveTo(0,200);\n"
"\tvar y = 2880 - 60;\n"
"\tvar val;\n"
"\t\n"
"\tfor (i = 0; i < 600; i+=10)\n"
"\t{\n"
"\t\tval = byteArray[y] * 2;\n"
"\t\t\n"
"\t\tctx.lineTo(i, 200 - val);\n"
"\t\tctx.lineTo(i+10, 200 - val);\n"
"\t\ty++;\n"
"\t}\n"
"\t\n"
"\tctx.stroke();\n"
"\t\n"
"\tctx.strokeStyle = \"gray\";\n"
"\tctx.setLineDash([5, 3]);\n"
"\t\n"
"\tctx.beginPath();\n"
" \tctx.moveTo(0,100);\n"
"\tctx.lineTo(600,100);\n"
" \tctx.moveTo(0,50);\n"
"\tctx.lineTo(600,50);\n"
" \tctx.moveTo(0,150);\n"
"\tctx.lineTo(600,150);\n"
"\tctx.stroke();\n"
"\n"
"\n"
"\t\n"
"\tctx.fillText(\"100%\",0,10);\n"
"\tctx.fillText(\"50%\",0,100);\n"
"\tctx.fillText(\"0%\",0,200);\t\n"
"\tctx.fillText(\"-60 mins\",0,220);\t\n"
"\tctx.fillText(\"-30 mins\",300,220);\t\n"
"\tctx.fillText(\"Now\",580,220);\t\n"
"\n"
"\t\n"
"\t// Do TX\n"
"\t\n"
"\t\n"
"\tc = document.getElementById(\"myCanvas2\");\n"
"\tctx = c.getContext(\"2d\");\n"
"\n"
"\tctx.fillText(\"100%\",0,10);\n"
"\tctx.fillText(\"50%\",0,100);\n"
"\tctx.fillText(\"0%\",0,200);\t\n"
"\tctx.fillText(\"-60 mins\",0,220);\t\n"
"\tctx.fillText(\"-30 mins\",300,220);\t\n"
"\tctx.fillText(\"Now\",580,220);\t\n"
"\n"
"\n"
"\tctx.strokeStyle = \"red\";\n"
"\tctx.beginPath();\n"
"\t\n"
"\tctx.moveTo(0,200);\n"
"\tvar y = 1440 - 60;\n"
"\tvar val;\n"
"\t\n"
"\tfor (i = 0; i < 600; i+=10)\n"
"\t\n"
"\t{\n"
"\t\tval = byteArray[y] * 2;\n"
"\t\t\n"
"\t\tctx.lineTo(i, 200 - val);\n"
"\t\tctx.lineTo(i+10, 200 - val);\n"
"\t\ty++;\n"
"\t}\n"
"\t\n"
"\tctx.stroke();\n"
"\n"
"\tctx.strokeStyle = \"gray\";\n"
"\tctx.setLineDash([5, 3]);\n"
"\t\n"
"\tctx.beginPath();\n"
" \tctx.moveTo(0,100);\n"
"\tctx.lineTo(600,100);\n"
" \tctx.moveTo(0,50);\n"
"\tctx.lineTo(600,50);\n"
" \tctx.moveTo(0,150);\n"
"\tctx.lineTo(600,150);\n"
"\tctx.stroke();\n"
"\n"
"\n"
"};\n"
"\n"
"oReq.send();\n"
"\n"
"\n"
"function draw(Data)\n"
"{\n"
"\n"
"\t// Data has 4 bytes of index to current position the 1440 bytes of load info\n"
"\t\n"
"\n"
"\tview = new Int8Array(Data);\n"
"\t\n"
"alert(view[3]);\n"
"\n"
"ctx.moveTo(0,200);\n"
"var y = 0;\n"
"for (i = 0; i < 720; i+=30)\n"
"{\n"
"\tctx.lineTo(i, 200 - y);\n"
"\tctx.lineTo(i+30, 200 - y);\n"
"\ty += 10;\n"
"}\n"
"\n"
"\n"
"ctx.stroke();\n"
"}\n"
"\n"
"</script>\n"
"\n"
"</body>\n"
"</html>\n"
"\n"
"";
return _strdup(Msg);;
}
char * get_aprs()
{
@ -3638,6 +3802,10 @@ char * GetStandardPage(char * FN, int * Len)
if (_stricmp(FN, "leaflet.rotatedMarker.js") == 0)
return get_rotatedMarker();
if (_stricmp(FN, "PortStats.html") == 0)
return get_portstats();
if (_stricmp(FN, "info_call.html") == 0)
return get_info_call();

54
ARDOP.c
View File

@ -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);
@ -947,7 +958,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
TNC->Streams[0].Connecting ||
TNC->Streams[0].Connected)
{
// discard if TNC not connected or sesison active
// discard if TNC not connected or session active
ReleaseBuffer(buffptr);
continue;
@ -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;
@ -1853,12 +1865,10 @@ VOID ARDOPReleaseTNC(struct TNCINFO * TNC)
ARDOPChangeMYC(TNC, TNC->NodeCall);
ARDOPSendCommand(TNC, "LISTEN TRUE", TRUE);
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
// Start Scanner
ARDOPSendCommand(TNC, "LISTEN TRUE", TRUE);
// Start Scanner
@ -1877,12 +1887,19 @@ VOID ARDOPReleaseTNC(struct TNCINFO * TNC)
VOID ARDOPSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
{
TNC->PortRecord->PORTCONTROL.PortSuspended = TRUE;
ARDOPSendCommand(TNC, "LISTEN FALSE", TRUE);
strcpy(TNC->WEB_TNCSTATE, "Interlocked");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
VOID ARDOPReleasePort(struct TNCINFO * TNC)
{
TNC->PortRecord->PORTCONTROL.PortSuspended = FALSE;
ARDOPSendCommand(TNC, "LISTEN TRUE", TRUE);
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
extern char WebProcTemplate[];
@ -2941,6 +2958,15 @@ VOID ARDOPProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
if (TNC->PTTMode)
Rig_PTT(TNC, TRUE);
TNC->PTTonTime = GetTickCount();
// Cancel Busy timer (stats include ptt on time in port active
if (TNC->BusyonTime)
{
TNC->BusyActivemS += (GetTickCount() - TNC->BusyonTime);
TNC->BusyonTime = 0;
}
return;
}
if (_memicmp(Buffer, "PTT F", 5) == 0)
@ -2949,6 +2975,12 @@ VOID ARDOPProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
if (TNC->PTTMode)
Rig_PTT(TNC, FALSE);
if (TNC->PTTonTime)
{
TNC->PTTActivemS += (GetTickCount() - TNC->PTTonTime);
TNC->PTTonTime = 0;
}
return;
}
@ -2957,6 +2989,8 @@ VOID ARDOPProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
TNC->BusyFlags |= CDBusy;
TNC->Busy = TNC->BusyHold * 10; // BusyHold delay
TNC->BusyonTime = GetTickCount();
MySetWindowText(TNC->xIDC_CHANSTATE, "Busy");
strcpy(TNC->WEB_CHANSTATE, "Busy");
@ -2973,6 +3007,12 @@ VOID ARDOPProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
else
strcpy(TNC->WEB_CHANSTATE, "Clear");
if (TNC->BusyonTime)
{
TNC->BusyActivemS += (GetTickCount() - TNC->BusyonTime);
TNC->BusyonTime = 0;
}
MySetWindowText(TNC->xIDC_CHANSTATE, TNC->WEB_CHANSTATE);
TNC->WinmorRestartCodecTimer = time(NULL);
return;
@ -3840,6 +3880,7 @@ VOID ARDOPProcessDataPacket(struct TNCINFO * TNC, UCHAR * Type, UCHAR * Data, in
char * ptr2;
char c;
int Len = Length;
char Call[10] = "";
Debugprintf(Data);
@ -3912,7 +3953,12 @@ VOID ARDOPProcessDataPacket(struct TNCINFO * TNC, UCHAR * Type, UCHAR * Data, in
buffptr->LENGTH = 16 + MSGHDDRLEN + APLen;
time(&buffptr->Timestamp);
memcpy(Call,ptr1, 9);
strlop(Call, '>');
UpdateMH(TNC, Call, '!', 'I');
BPQTRACE((MESSAGE *)buffptr, TRUE);
}
else
{

View File

@ -124,7 +124,7 @@ void decodeblock( unsigned char in[4], unsigned char out[3]);
int encode_quoted_printable(char *s, char * out, int Len);
int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress);
int APIENTRY ChangeSessionCallsign(int Stream, unsigned char * AXCall);
void SendMessageReadEvent(char * user, struct MsgInfo * Msg);
void SendMessageReadEvent(char * call, struct MsgInfo * Msg);
void SendNewMessageEvent(char * call, struct MsgInfo * Msg);
config_t cfg;
@ -10059,6 +10059,7 @@ BOOL GetConfig(char * ConfigName)
char Size[80];
config_setting_t *setting;
const char * ptr;
char * ptr1;
char FBBString[8192]= "";
FBBFilter f;
config_init(&cfg);
@ -10265,7 +10266,7 @@ BOOL GetConfig(char * ConfigName)
GetStringValue(group, "FBBFilters", FBBString);
ptr = FBBString;
ptr1 = FBBString;
// delete old list
@ -10279,31 +10280,31 @@ BOOL GetConfig(char * ConfigName)
free(Filters);
Filters = NULL;
while (ptr && ptr[0])
while (ptr1 && ptr1[0])
{
FBBFilter * PFilter;
f.Action = ptr[0];
f.Type = ptr[2];
ptr = &ptr[4];
f.Action = ptr1[0];
f.Type = ptr1[2];
ptr1 = &ptr1[4];
memcpy(f.From, ptr, 10);
memcpy(f.From, ptr1, 10);
strlop(f.From, '|');
ptr = strlop(ptr, '|');
ptr1 = strlop(ptr1, '|');
memcpy(f.TO, ptr, 10);
memcpy(f.TO, ptr1, 10);
strlop(f.TO, '|');
ptr = strlop(ptr, '|');
ptr1 = strlop(ptr1, '|');
memcpy(f.AT, ptr, 10);
memcpy(f.AT, ptr1, 10);
strlop(f.AT, '|');
ptr = strlop(ptr, '|');
ptr1 = strlop(ptr1, '|');
memcpy(f.BID, ptr, 10);
memcpy(f.BID, ptr1, 10);
strlop(f.BID, '|');
ptr = strlop(ptr, '|');
ptr1 = strlop(ptr1, '|');
f.MaxLen = atoi(ptr);
f.MaxLen = atoi(ptr1);
// add to list
@ -10325,7 +10326,7 @@ BOOL GetConfig(char * ConfigName)
p->Next = PFilter;
}
ptr = strlop(ptr, '|');
ptr1 = strlop(ptr1, '|');
}
@ -11762,300 +11763,258 @@ BOOL CheckforMIME(SocketConn * sockptr, char * Msg, char ** Body, int * MsgLen);
#include <sys/wait.h>
#include <signal.h>
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) {
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]);
}
(void)close(pdes[1]);
}
setpgid(-pid,pid);
char *args[] = {"sh", "-c", program, NULL};
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, " </dev/null");
if (pgdir)
{
/* remove ';' security reasons */
ptr = strchr(pgdir, ';');
if (ptr)
*ptr = '\0';
sprintf (dir, "cd %s ; ", pgdir);
}
else
*dir = '\0';
*arg = '\0';
if (data)
{
/* remove ';' security reasons */
ptr = strchr(data, ';');
if (ptr)
*ptr = '\0';
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");
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;
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)
switch (pgret)
{
case -1: // ERROR or forced closed
case 0: index=0; // Goodbye/Exit
case 0:
index=0; // Goodbye/Exit
conn->InputMode=0;
SendPrompt(conn, user);
break;
case 1: index++; // inc & keep in PG
case 1:
index++; // inc & keep in PG
break;
case 2: index=0; // disconnect
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);
case 3:
Debugprintf("data->BBS & end");
break;
case 4:
Debugprintf("data->BBS and inc %d", pindex++);
break;
case 5:
Debugprintf("call no inc %d", pgret);
break;
default:
BBSputs(conn, "PG unexexpected response\r");
user->Temp->PG_INDEX = 0;
conn->InputMode=0;
SendPrompt(conn, user);
return;
}
user->Temp->PG_INDEX = index;
// printf("runpg return index = %d\n", index);
}
/*---- G7TAJ END ----- */
#else
@ -12076,7 +12035,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 +12210,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:

Binary file not shown.

Binary file not shown.

View File

@ -1137,6 +1137,9 @@
// 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)
// Fix SendPToMultiple not stopping at Implied AT match (45)
// Log Our HA when checking for flood bulls (45)
#include "bpqmail.h"
#include "winstdint.h"

View File

@ -1,20 +0,0 @@

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

14
Bpq32.c
View File

@ -1212,13 +1212,21 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
// Add NodeAPI call sendLinks and remove get from other calls (32)
// Improve validation of Web Beacon Config (33)
// Support SNMP via host ip stack as well as IPGateway (34)
// Switch APRS Map to OSM tile servers (36)
// 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)
// Change default of SECURETELNET to 1 (41)
// Add optional ATTACH time limit for ARDOP (42)
// Fix buffer overflow risk in HTTP Terminal(42)
// Fix KISSHF Interlock (43)
// Support other than channel A on HFKISS (43)
// Support additional port info reporting for M0LTE Map (44)
// Allow interlocking of KISS and Session mode ports (eg ARDOP and VARA) (45)
// Add ARDOP UI Packets to MH (45)
// Add support for Qtsm Mgmt Interface (45)
@ -1313,6 +1321,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 +3959,9 @@ VOID * InitializeExtDriver(PEXTPORTDATA PORTVEC)
if (strstr(Value, "FREEDATA"))
return FreeDataExtInit;
if (strstr(Value, "6PACK"))
return SIXPACKExtInit;
ExtDriver = LoadLibrary(Value);
if (ExtDriver == NULL)

Binary file not shown.

View File

@ -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}"
>
<File
RelativePath=".\6pack.c"
>
</File>
<File
RelativePath="..\CommonSource\adif.c"
>

130
Cmd.c
View File

@ -10,7 +10,7 @@ the Free Software Foundation, either version 3 of the License, or
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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. S"paclenee the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
@ -66,6 +66,10 @@ VOID SaveMH();
BOOL RestartTNC(struct TNCINFO * TNC);
void GetPortCTEXT(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD);
VOID WriteMiniDump();
int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive);
int seeifInterlockneeded(struct PORTCONTROL * PORT);
extern VOID KISSTX();
char COMMANDBUFFER[81] = ""; // Command Hander input buffer
char OrigCmdBuffer[81] = ""; // Command Hander input buffer before toupper
@ -171,7 +175,8 @@ VOID APRSCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX *
VOID RECONFIGTELNET (TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD);
VOID HELPCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD);
VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD);
VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * UserCMD);
void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
@ -1196,7 +1201,8 @@ VOID CMDSTATS(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX *
Bufferptr = Cmdprintf(Session, Bufferptr, "\r");
PORT = STARTPORT;
Bufferptr = Cmdprintf(Session, Bufferptr, "Link Active %% ");
// Bufferptr = Cmdprintf(Session, Bufferptr, "Link Active %% ");
Bufferptr = Cmdprintf(Session, Bufferptr, "Active(TX/Busy) %%");
for (i = 0; i < cols; i++)
{
@ -2295,8 +2301,8 @@ VOID CMDC00(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * C
int TextCallLen;
char PortString[10];
char cmdCopy[256];
struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT;;
struct _EXTPORTDATA * EXTPORT = (struct _EXTPORTDATA *)PORT;
char toCall[12], fromCall[12];
#ifdef EXCLUDEBITS
@ -2738,6 +2744,16 @@ noFlip:
return;
}
ret = CheckKissInterlock(PORT, TRUE);
if (ret)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry, Interlocked port %d is in use\r", ret);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
if (Session->L4USER[6] == 0x42 || Session->L4USER[6] == 0x44)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Sorry - Can't make ax.25 calls with SSID of T or R\r");
@ -2822,6 +2838,12 @@ noFlip3:
RESET2(LINK); // RESET ALL FLAGS
toCall[ConvFromAX25(LINK->LINKCALL, toCall)] = 0;
fromCall[ConvFromAX25(LINK->OURCALL, fromCall)] = 0;
hookL2SessionAttempt(CONNECTPORT, fromCall, toCall, LINK);
if (CMD->String[0] == 'N' && SUPPORT2point2)
LINK->L2STATE = 1; // New (2.2) send XID
else
@ -2836,6 +2858,8 @@ noFlip3:
if (CQFLAG == 0) // if a CQ CALL DONT SEND SABM
{
seeifInterlockneeded(PORT);
if (LINK->L2STATE == 1)
L2SENDXID(LINK);
else
@ -4166,7 +4190,7 @@ VOID ATTACHCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX
if (EXTPORT->ATTACHEDSESSIONS[sess])
if (EXTPORT->ATTACHEDSESSIONS[sess] || PORT->PortSuspended)
{
// In use
@ -4434,6 +4458,7 @@ CMDX COMMANDS[] =
"NAT ",3,SHOWNAT,0,
"IPROUTE ",3,SHOWIPROUTE,0,
"UZ7HO ",5,UZ7HOCMD,0,
"QTSM ",4,QTSMCMD,0,
"..FLMSG ",7,FLMSG,0
};
@ -4897,15 +4922,65 @@ VOID DoTheCommand(TRANSPORTENTRY * Session)
VOID StatsTimer()
{
struct PORTCONTROL * PORT = PORTTABLE;
int sum;
uint64_t sum, sum2;
// Interval is 60 secs
while(PORT)
{
int index = PORT->StatsPointer++;
if (index == 1439)
PORT->StatsPointer = 0; // Cyclic through 24 hours (1440 Mins)
if (PORT->TNC)
{
struct TNCINFO * TNC = PORT->TNC;
if (TNC->Hardware == H_ARDOP || TNC->Hardware == H_VARA)
{
sum = TNC->PTTActivemS / 600; // ms but want %
PORT->AVSENDING = (UCHAR)sum;
TNC->PTTActivemS = 0;
sum2 = TNC->BusyActivemS / 600; // ms but want %
PORT->AVACTIVE = (UCHAR)(sum + sum2);
TNC->BusyActivemS = 0;
}
}
else
{
// if KISS port using QtSM Average is already updated
struct KISSINFO * KISS = (struct KISSINFO *)PORT;
if (PORT->PORTNUMBER == 17)
{
int x = 17;
}
if (PORT->PORTTXROUTINE == KISSTX && (KISS->QtSMStats || KISS->FIRSTPORT->PORT.QtSMPort)) // KISS Port QtSM Stats
{
}
else
{
sum = PORT->SENDING / 11;
PORT->AVSENDING = sum;
PORT->AVSENDING = (UCHAR)sum;
sum = (PORT->SENDING + PORT->ACTIVE) /11;
PORT->AVACTIVE = sum;
PORT->AVACTIVE = (UCHAR)sum;
}
}
if (PORT->TX == NULL && PORT->AVACTIVE)
{
PORT->TX = zalloc(1440); // Keep 1 day history
PORT->BUSY = zalloc(1440);
}
if (PORT->TX)
{
PORT->TX[index] = PORT->AVSENDING;
PORT->BUSY[index] = PORT->AVACTIVE;
}
PORT->SENDING = 0;
PORT->ACTIVE = 0;
@ -5865,6 +5940,43 @@ VOID UZ7HOCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX *
return;
}
VOID QTSMCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, CMDX * CMD)
{
int port;
struct PORTCONTROL * PORT;
struct KISSINFO * KISS;
CmdTail = CmdTail + (OrigCmdBuffer - COMMANDBUFFER); // Replace with original case version
port = atoi(CmdTail);
PORT = GetPortTableEntryFromPortNum(port);
if (PORT == NULL || PORT->PORTTXROUTINE != KISSTX) // Must be a kiss like port
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port %d is not a KISS port\r", port);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
KISS = (struct KISSINFO *)PORT;
if (KISS->QtSMModem == 0)
{
Bufferptr = Cmdprintf(Session, Bufferptr, "Error - Port %d has no QtSM information\r", port);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}
Bufferptr = Cmdprintf(Session, Bufferptr, "Modem %s Centre frequency %d\r",
(KISS->QtSMModem) ? KISS->QtSMModem : "Not Available", KISS->QtSMFreq);
SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER));
return;
}

View File

@ -73,6 +73,7 @@ void SendDataToPktMap(char *Msg);
extern BOOL LogAllConnects;
extern BOOL M0LTEMap;
char * stristr (char *ch1, char *ch2);
extern VOID * ENDBUFFERPOOL;
@ -547,6 +548,7 @@ VOID * _GetBuff(char * File, int Line)
Msg->Process = (short)GetCurrentProcessId();
Msg->Linkptr = NULL;
Msg->Padding[0] = 0; // Used for modem status info
}
else
Debugprintf("Warning - Getbuff returned NULL");
@ -1669,7 +1671,7 @@ DllExport time_t APIENTRY GetRaw(int stream, char * msg, int * len, int * count)
Stamp = MSG->Timestamp;
memcpy(msg, MSG, Msglen);
memcpy(msg, MSG, BUFFLEN - sizeof(void *)); // To c
*len = Msglen;
@ -2454,8 +2456,8 @@ HANDLE OpenCOMPort(VOID * pPort, int speed, BOOL SetDTR, BOOL SetRTS, BOOL Quiet
struct termios term;
struct speed_struct *s;
if ((UINT)pPort < 256)
sprintf(Port, "%s/com%d", BPQDirectory, (int)pPort);
if ((uintptr_t)pPort < 256)
sprintf(Port, "%s/com%d", BPQDirectory, (int)(uintptr_t)pPort);
else
strcpy(Port, pPort);
@ -3688,7 +3690,7 @@ VOID OpenReportingSockets()
{
// Enable Node Map Reports
ReportTimer = 60;
ReportTimer = 1200; // 2 mins - Give Rigcontrol time to start
ReportSocket = socket(AF_INET,SOCK_DGRAM,0);
@ -4859,7 +4861,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 +5090,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 +5113,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 +5135,7 @@ void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT)
Normcall, PORT->PORTNUMBER, MH->MHCOUNT, MHTIME);
strcat( MHJSON, mhstr );
skipit:
MH++;
}
}
@ -5150,6 +5162,7 @@ void SendDataToPktMap(char *Msg)
char * Use;
char * Type;
char * Modulation;
char * Usage;
char locked[] = " ! ";
int Percent = 0;
@ -5254,6 +5267,10 @@ void SendDataToPktMap(char *Msg)
Type = "RF";
Bitrate = 0;
Modulation = "FSK";
Usage = "Access";
if (PORT->PortFreq)
Freq = PORT->PortFreq;
if (PORT->PORTTYPE == 0)
{
@ -5311,7 +5328,7 @@ void SendDataToPktMap(char *Msg)
continue;
}
if (TNC->RIG)
if (Freq == 0 && TNC->RIG)
Freq = TNC->RIG->RigFreq * 1000000;
switch (TNC->Hardware) // Hardware Type
@ -5377,6 +5394,15 @@ void SendDataToPktMap(char *Msg)
break;
case H_KISSHF:
// Try to get mode from ID then drop through
if (stristr(PORT->PORTDESCRIPTION, "BPSK"))
{
Modulation = "BPSK";
}
case H_WINMOR:
case H_V4:
@ -5385,7 +5411,7 @@ void SendDataToPktMap(char *Msg)
case H_UIARQ:
case H_ARDOP:
case H_VARA:
case H_KISSHF:
case H_FREEDATA:
// TCP
@ -5421,12 +5447,58 @@ void SendDataToPktMap(char *Msg)
while (*(ptr2) == ' ' && ptr2 != ID)
*(ptr2--) = 0;
if (PORT->M0LTEMapInfo)
{
// Override with user configured values - RF,7.045,BPSK,300,300,Access
char param[256];
char *p1, *p2, *p3, *p4, *p5;
strcpy(param, PORT->M0LTEMapInfo);
p1 = strlop(param, ',');
p2 = strlop(p1, ',');
p3 = strlop(p2, ',');
p4 = strlop(p3, ',');
p5 = strlop(p4, ',');
// int n = sscanf(PORT->M0LTEMapInfo, "%s,%s,%s,%s,%s,%s", &p1, &p2, &p3, &p4, &p5, &p6);
if (p5)
{
if (param[0]) Type = param;
if (p1[0])
{
// if set to DIAL+=n and frequency set from config or rigcontrol modify it
uint64_t offset = 0;
if (_memicmp(p1, "DIAL+", 5) == 0)
offset = atoi(&p1[5]);
else if (_memicmp(p1, "DIAL-", 5) == 0)
offset = -atoi(&p1[5]);
else
Freq = atof(p1) * 1000000;
if (Freq != 0)
Freq += offset;
}
if (p2[0]) Modulation = p2;
if (p3[0]) Baud = atoi(p3);
if (p4[0]) Bitrate = atoi(p4);
if (p5[0]) Usage = p5;
}
}
ptr += sprintf(ptr, "{\"id\": \"%d\",\"linkType\": \"%s\","
"\"freq\": \"%lld\",\"mode\": \"%s\",\"modulation\": \"%s\","
"\"baud\": \"%d\",\"bitrate\": \"%d\",\"usage\": \"%s\",\"comment\": \"%s\"},\r\n",
PortNo, Type,
Freq, Mode, Modulation,
Baud, Bitrate, "Access", ID);
Baud, Bitrate, Usage, ID);
// G7TAJ //
// make MH list to be added later

View File

@ -107,3 +107,16 @@ DllExport void APIENTRY RunEventProgram(char * Program, char * Param)
return;
}
void hookL2SessionAccepted(int Port, char * remotecall, char * ourcall, struct _LINKTABLE * LINK)
{
}
void hookL2SessionDeleted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK)
{
}
void hookL2SessionAttempt(int Port, char * ourcall, char * remotecall, struct _LINKTABLE * LINK)
{
}

View File

@ -686,8 +686,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
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);
@ -3215,7 +3214,7 @@ void ProcessTNCJSON(struct TNCINFO * TNC, char * Msg, int Len)
}
}
else if (memcmp(ptr, "close", 12) == 0)
else if (memcmp(ptr, "close", 5) == 0)
{
if (TNC->FreeDataInfo->arqstate != 4)
{

View File

@ -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

View File

@ -600,6 +600,7 @@ VOID HTTPTimer()
for (n = Last;;)
{
if ((strlen(Session->ScreenLines[n]) + strlen(_REPLYBUFFER)) < 99999)
strcat(_REPLYBUFFER, Session->ScreenLines[n]);
if (n == 99)
@ -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
@ -1608,23 +1623,23 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn)
char * WebSock = 0;
char PortsHddr[] = "<h2 align=center>Ports</h2><table align=center border=2 bgcolor=white>"
"<tr><th>Port</th><th>Driver</th><th>ID</th><th>Beacons</th><th>Driver Window</th></tr>";
"<tr><th>Port</th><th>Driver</th><th>ID</th><th>Beacons</th><th>Driver Window</th><th>Stats Graph</th></tr>";
char PortLine[] = "<tr><td>%d</td><td><a href=PortStats?%d&%s>&nbsp;%s</a></td><td>%s</td></tr>";
// char PortLine[] = "<tr><td>%d</td><td><a href=PortStats?%d&%s>&nbsp;%s</a></td><td>%s</td></tr>";
char PortLineWithBeacon[] = "<tr><td>%d</td><td><a href=PortStats?%d&%s>&nbsp;%s</a></td><td>%s</td>"
"<td><a href=PortBeacons?%d>&nbsp;Beacons</a><td> </td></td></tr>\r\n";
"<td><a href=PortBeacons?%d>&nbsp;Beacons</a><td> </td></td><td>%s</td></tr>\r\n";
char SessionPortLine[] = "<tr><td>%d</td><td>%s</td><td>%s</td><td> </td>"
"<td> </td></tr>\r\n";
"<td> </td><td>%s</td></tr>\r\n";
char PortLineWithDriver[] = "<tr><td>%d</td><td>%s</td><td>%s</td><td> </td>"
"<td><a href=\"javascript:dev_win('/Node/Port?%d',%d,%d,%d,%d);\">Driver Window</a></td></tr>\r\n";
"<td><a href=\"javascript:dev_win('/Node/Port?%d',%d,%d,%d,%d);\">Driver Window</a></td><td>%s</td></tr>\r\n";
char PortLineWithBeaconAndDriver[] = "<tr><td>%d</td><td>%s</td><td>%s</td>"
"<td><a href=PortBeacons?%d>&nbsp;Beacons</a></td>"
"<td><a href=\"javascript:dev_win('/Node/Port?%d',%d,%d,%d,%d);\">Driver Window</a></td></tr>\r\n";
"<td><a href=\"javascript:dev_win('/Node/Port?%d',%d,%d,%d,%d);\">Driver Window</a></td><td>%s</td></tr>\r\n";
char RigControlLine[] = "<tr><td>%d</td><td>%s</td><td>%s</td><td> </td>"
"<td><a href=\"javascript:dev_win('/Node/RigControl.html',%d,%d,%d,%d);\">Rig Control</a></td></tr>\r\n";
@ -2692,6 +2707,53 @@ doHeader:
return 0;
}
else if (_memicmp(NodeURL, "/portstats.txt", 15) == 0)
{
char * Compressed;
char * ptr;
int port;
struct PORTCONTROL * PORT;
ptr = &NodeURL[15];
port = atoi(ptr);
PORT = GetPortTableEntryFromPortNum(port);
ReplyLen = 0;
if (PORT && PORT->TX)
{
// We send the last 24 hours worth of data. Buffer is cyclic so oldest byte is at StatsPointer
int first = PORT->StatsPointer;
int firstlen = 1440 - first;
memcpy(&_REPLYBUFFER[0], &PORT->TX[first], firstlen);
memcpy(&_REPLYBUFFER[firstlen], PORT->TX, first);
memcpy(&_REPLYBUFFER[1440], &PORT->BUSY[first], firstlen);
memcpy(&_REPLYBUFFER[1440 + firstlen], PORT->BUSY, first);
ReplyLen = 2880;
}
if (allowDeflate)
Compressed = Compressit(_REPLYBUFFER, ReplyLen, &ReplyLen);
else
Compressed = _REPLYBUFFER;
HeaderLen = sprintf(Header, "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: %d\r\nContent-Type: Text\r\n%s\r\n", ReplyLen, Encoding);
sendandcheck(sock, Header, HeaderLen);
sendandcheck(sock, Compressed, ReplyLen);
if (allowDeflate)
free (Compressed);
return 0;
}
else if (_memicmp(NodeURL, "/Icon", 5) == 0 && _memicmp(&NodeURL[10], ".png", 4) == 0)
{
// APRS internal Icon
@ -2865,7 +2927,7 @@ doHeader:
" {"
" // The browser doesn't support WebSocket\r\n"
" const div = document.getElementById('div');\r\n"
" div.innerHTML = 'WebSocket not supported by your Browser - RigControl Page not availble'\r\n"
" div.innerHTML = 'WebSocket not supported by your Browser - RigControl Page not availible'\r\n"
" }"
"}"
"function PTT(p)"
@ -3220,6 +3282,7 @@ doHeader:
int count;
char DLL[20];
char StatsURL[64];
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], "%s", PortsHddr);
@ -3228,6 +3291,13 @@ doHeader:
Port = GetPortTableEntryFromSlot(count);
ExtPort = (struct _EXTPORTDATA *)Port;
// see if has a stats page
if (Port->AVACTIVE)
sprintf(StatsURL, "<a href=/PortStats.html?%d>&nbsp;Stats Graph</a>", Port->PORTNUMBER);
else
StatsURL[0] = 0;
if (Port->PORTTYPE == 0x10)
{
strcpy(DLL, ExtPort->PORT_DLL_NAME);
@ -3250,20 +3320,20 @@ doHeader:
{
if (Port->UICAPABLE)
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithBeaconAndDriver, Port->PORTNUMBER, DLL,
Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200);
Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200, StatsURL);
else
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithDriver, Port->PORTNUMBER, DLL,
Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200);
Port->PORTDESCRIPTION, Port->PORTNUMBER, Port->TNC->WebWinX, Port->TNC->WebWinY, 200, 200, StatsURL);
continue;
}
if (Port->PORTTYPE == 16 && Port->PROTOCOL == 10 && Port->UICAPABLE == 0) // EXTERNAL, Pactor/WINMO
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], SessionPortLine, Port->PORTNUMBER, DLL,
Port->PORTDESCRIPTION, Port->PORTNUMBER);
Port->PORTDESCRIPTION, Port->PORTNUMBER, StatsURL);
else
ReplyLen += sprintf(&_REPLYBUFFER[ReplyLen], PortLineWithBeacon, Port->PORTNUMBER, Port->PORTNUMBER,
DLL, DLL, Port->PORTDESCRIPTION, Port->PORTNUMBER);
DLL, DLL, Port->PORTDESCRIPTION, Port->PORTNUMBER, StatsURL);
}
if (RigActive)

View File

@ -343,12 +343,12 @@ VOID ExpireMessages()
Killed = 0;
PRLimit = now - PR*86400;
PURLimit = now - PUR*86400;
PFLimit = now - PF*86400;
PNFLimit = now - PNF*86400;
BFLimit = now - BF*86400;
BNFLimit = now - BNF*86400;
PRLimit = now - (time_t)PR*86400;
PURLimit = now -(time_t)PUR*86400;
PFLimit = now - (time_t)PF*86400;
PNFLimit = now - (time_t)PNF*86400;
BFLimit = now - (time_t)BF*86400;
BNFLimit = now -(time_t) BNF*86400;
if (NTSU == 0)
{
@ -391,7 +391,7 @@ VOID ExpireMessages()
if (Msg->datecreated < PURLimit)
{
if (SendNonDeliveryMsgs)
SendNonDeliveryMessage(Msg, TRUE, PUR);
SendNonDeliveryMessage(Msg, TRUE, (int)PUR);
KillMsg(Msg);
}
@ -401,7 +401,7 @@ VOID ExpireMessages()
if (Msg->datecreated < PNFLimit)
{
if (SendNonDeliveryMsgs)
SendNonDeliveryMessage(Msg, FALSE, PNF);
SendNonDeliveryMessage(Msg, FALSE, (int)PNF);
KillMsg(Msg);
}

113
KISSHF.c
View File

@ -50,8 +50,8 @@ int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len);
VOID SendInitScript(struct TNCINFO * TNC);
int KISSHFGetLine(char * buf);
int ProcessEscape(UCHAR * TXMsg);
VOID KISSHFProcessReceivedPacket(struct TNCINFO * TNC);
static int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len);
VOID KISSHFProcessReceivedPacket(struct TNCINFO * TNC, int Channel);
static int KissEncode(struct TNCINFO * TNC, UCHAR * inbuff, UCHAR * outbuff, int len, int Channel);
int ConnecttoKISS(int port);
TRANSPORTENTRY * SetupNewSession(TRANSPORTENTRY * Session, char * Bufferptr);
BOOL DecodeCallString(char * Calls, BOOL * Stay, BOOL * Spy, UCHAR * AXCalls);
@ -265,6 +265,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
struct TNCINFO * TNC = TNCInfo[port];
struct STREAMINFO * STREAM = &TNC->Streams[0];
struct ScanEntry * Scan;
int Channel = ((TNC->PortRecord->PORTCONTROL.CHANNELNUM - 1) & 15) << 4;
if (TNC == NULL)
return 0; // Port not defined
@ -417,7 +418,10 @@ ok:
if (buff->PID != 240) // ax.25 address
{
txlen = KissEncode(&buff->PID, txbuff, txlen);
txlen = KissEncode(TNC, &buff->PID, txbuff, txlen, Channel);
// We need to che check for ackmode
txlen = send(TNC->TCPSock, txbuff, txlen, 0);
return 1;
}
@ -504,7 +508,8 @@ ok:
}
}
if (toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect
if ((toupper(buff->L2DATA[0]) == 'C' && buff->L2DATA[1] == ' ' && txlen > 2) // Connect
|| (toupper(buff->L2DATA[0]) == 'N' && buff->L2DATA[1] == ' ' && txlen > 2)) // Connect
{
// Connect Command. Pass to L2 code to start session
@ -616,9 +621,9 @@ noFlip3:
RESET2(LINK); // RESET ALL FLAGS
// if (CMD->String[0] == 'N' && SUPPORT2point2)
// LINK->L2STATE = 1; // New (2.2) send XID
// else
if (toupper(buff->L2DATA[0]) == 'N' && SUPPORT2point2)
LINK->L2STATE = 1; // New (2.2) send XID
else
LINK->L2STATE = 2; // Send SABM
LINK->CIRCUITPOINTER = NewSess;
@ -722,10 +727,16 @@ VOID KISSHFReleaseTNC(struct TNCINFO * TNC)
VOID KISSHFSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
{
TNC->PortRecord->PORTCONTROL.PortSuspended = 1;
strcpy(TNC->WEB_TNCSTATE, "Interlocked");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
VOID KISSHFReleasePort(struct TNCINFO * TNC)
{
TNC->PortRecord->PORTCONTROL.PortSuspended = 0;
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL)
@ -735,9 +746,9 @@ static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL)
"function ScrollOutput()\r\n"
"{var textarea = document.getElementById('textarea');"
"textarea.scrollTop = textarea.scrollHeight;}</script>"
"</head><title>VARA Status</title></head><body id=Text onload=\"ScrollOutput()\">"
"</head><title>KISSHF Status</title></head><body id=Text onload=\"ScrollOutput()\">"
"<h2><form method=post target=\"POPUPW\" onsubmit=\"POPUPW = window.open('about:blank','POPUPW',"
"'width=440,height=150');\" action=ARDOPAbort?%d>KISSHF Status"
"'width=440,height=50');\" action=ARDOPAbort?%d>KISSHF Status"
"<input name=Save value=\"Abort Session\" type=submit style=\"position: absolute; right: 20;\"></form></h2>",
TNC->Port);
@ -746,14 +757,14 @@ static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL)
Len += sprintf(&Buff[Len], "<tr><td width=110px>Comms State</td><td>%s</td></tr>", TNC->WEB_COMMSSTATE);
Len += sprintf(&Buff[Len], "<tr><td>TNC State</td><td>%s</td></tr>", TNC->WEB_TNCSTATE);
Len += sprintf(&Buff[Len], "<tr><td>Mode</td><td>%s</td></tr>", TNC->WEB_MODE);
Len += sprintf(&Buff[Len], "<tr><td>Channel State</td><td>%s</td></tr>", TNC->WEB_CHANSTATE);
Len += sprintf(&Buff[Len], "<tr><td>Proto State</td><td>%s</td></tr>", TNC->WEB_PROTOSTATE);
Len += sprintf(&Buff[Len], "<tr><td>Traffic</td><td>%s</td></tr>", TNC->WEB_TRAFFIC);
// Len += sprintf(&Buff[Len], "<tr><td>Mode</td><td>%s</td></tr>", TNC->WEB_MODE);
// Len += sprintf(&Buff[Len], "<tr><td>Channel State</td><td>%s</td></tr>", TNC->WEB_CHANSTATE);
// Len += sprintf(&Buff[Len], "<tr><td>Proto State</td><td>%s</td></tr>", TNC->WEB_PROTOSTATE);
// Len += sprintf(&Buff[Len], "<tr><td>Traffic</td><td>%s</td></tr>", TNC->WEB_TRAFFIC);
// Len += sprintf(&Buff[Len], "<tr><td>TNC Restarts</td><td></td></tr>", TNC->WEB_RESTARTS);
Len += sprintf(&Buff[Len], "</table>");
Len += sprintf(&Buff[Len], "<textarea rows=10 style=\"width:500px; height:250px;\" id=textarea >%s</textarea>", TNC->WebBuffer);
Len += sprintf(&Buff[Len], "<textarea rows=2 style=\"width:500px; height:50px;\" id=textarea >%s</textarea>", TNC->WebBuffer);
Len = DoScanLine(TNC, Buff, Len);
return Len;
@ -976,6 +987,7 @@ VOID KISSThread(void * portptr)
char * ptr1;
char * ptr2;
UINT * buffptr;
int Channel = ((TNC->PortRecord->PORTCONTROL.CHANNELNUM - 1) & 15) << 4;
if (TNC->HostName == NULL)
return;
@ -1184,7 +1196,7 @@ VOID KISSThread(void * portptr)
if (FD_ISSET(TNC->TCPSock, &readfs))
{
GetSemaphore(&Semaphore, 52);
KISSHFProcessReceivedPacket(TNC);
KISSHFProcessReceivedPacket(TNC, Channel);
FreeSemaphore(&Semaphore);
}
@ -1243,16 +1255,43 @@ static int KissDecode(UCHAR * inbuff, UCHAR * outbuff, int len)
}
#define ACKMODE 4 // CAN USE ACK REQURED FRAMES
#define MSGHDDRLEN (USHORT)(sizeof(VOID *) + sizeof(UCHAR) + sizeof(USHORT))
#define ONEMINUTE 60*3
static int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len)
static int KissEncode(struct TNCINFO * TNC, UCHAR * inbuff, UCHAR * outbuff, int len, int Channel)
{
int i,txptr=0;
UCHAR c;
outbuff[0] = FEND;
outbuff[1]=0;
outbuff[1] = Channel;
txptr=2;
// See if we need ackmode
if (TNC->PortRecord->PORTCONTROL.KISSFLAGS & ACKMODE)
{
UCHAR * ptr = inbuff - MSGHDDRLEN;
PMESSAGE Buffer = (PMESSAGE)ptr;
if (Buffer->Linkptr) // Frame Needs ACK
{
UINT ACKWORD = (UINT)(Buffer->Linkptr - LINKS);
outbuff[1] |= 0x0c; // ACK OPCODE
outbuff[2] = ACKWORD & 0xff;
outbuff[3] = (ACKWORD >> 8) &0xff;
Buffer->Linkptr->L2TIMER = ONEMINUTE; // Extend timeout
txptr = 4;
// have to reset flag so trace doesnt clear it
Buffer->Linkptr = 0;
}
}
for (i=0;i<len;i++)
{
c=inbuff[i];
@ -1283,7 +1322,7 @@ static int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len)
}
VOID KISSHFProcessReceivedPacket(struct TNCINFO * TNC)
VOID KISSHFProcessReceivedPacket(struct TNCINFO * TNC, int Channel)
{
int InputLen, MsgLen;
unsigned char * ptr;
@ -1335,10 +1374,42 @@ VOID KISSHFProcessReceivedPacket(struct TNCINFO * TNC)
if (MsgLen > 1)
{
PMESSAGE Buff = GetBuff();
PMESSAGE Buff;
if ((TNC->ARDOPBuffer[1] & 0xf0) != Channel)
goto ignoreit;
Buff = GetBuff();
MsgLen = KissDecode(TNC->ARDOPBuffer, Buffer, MsgLen);
// See if ACKMODE ACK
if ((Buffer[1] & 0xf) == 12)
{
//Ackmode
struct _LINKTABLE * LINK;
int ACKWORD = Buffer[2] | Buffer[3] << 8;
if (ACKWORD < MAXLINKS)
{
LINK = LINKS + ACKWORD;
if (LINK->L2TIMER)
LINK->L2TIMER = LINK->L2TIME;
}
ReleaseBuffer(Buff);
goto ignoreit;
}
if ((Buffer[1] & 0xf) != 0)
{
ReleaseBuffer(Buff);
goto ignoreit; // Not data
}
// we dont need the FENDS or control byte
MsgLen -= 3;
@ -1354,6 +1425,8 @@ VOID KISSHFProcessReceivedPacket(struct TNCINFO * TNC)
}
}
ignoreit:
if (TNC->InputLen == 0)
return;
@ -1463,7 +1536,7 @@ void DetachKISSHF(struct PORTCONTROL * PORT)
struct STREAMINFO * STREAM = &TNC->Streams[0];
if (STREAM->Attached)
STREAM->ReportDISC = TRUE; // Tell Node
STREAM->ReportDISC = 10; // Tell Node but give time for error message to display
STREAM->Connecting = FALSE;
STREAM->Connected = FALSE;

183
L2Code.c
View File

@ -106,6 +106,13 @@ void AttachKISSHF(struct PORTCONTROL * PORT, MESSAGE * Buffer);
void DetachKISSHF(struct PORTCONTROL * PORT);
void KISSHFConnected(struct PORTCONTROL * PORT, struct _LINKTABLE * LINK);
void WriteConnectLog(char * fromcall, char * tocall, UCHAR * Mode);
int seeifInterlockneeded(struct PORTCONTROL * PORT);
int seeifUnlockneeded(struct _LINKTABLE * LINK);
int CheckKissInterlock(struct PORTCONTROL * MYPORT, int Exclusive);
void hookL2SessionAccepted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
void hookL2SessionDeleted(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
void hookL2SessionAttempt(int Port, char * fromCall, char * toCall, struct _LINKTABLE * LINK);
extern int REALTIMETICKS;
@ -789,6 +796,14 @@ VOID ProcessXIDCommand(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESS
UCHAR TEMPDIGI[57];
int n;
// Check Interlock - should we also check exclude etc?. No, checked in L2FORUS
if (CheckKissInterlock(PORT, TRUE)) // Interlock with ARDOP/VARA etc
{
L2SENDDM(PORT, Buffer, ADJBUFFER);
return;
}
if (*ptr++ == 0x82 && *ptr++ == 0x80)
{
int Type;
@ -1101,12 +1116,21 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
TRANSPORTENTRY * Session;
int CONERROR;
char toCall[12], fromCall[12];
if (LINK == 0) // NO LINK ENTRIES - SEND DM RESPONSE
{
L2SENDDM(PORT, Buffer, ADJBUFFER);
return;
}
if (CheckKissInterlock(PORT, TRUE)) // Interlock with ARDOP/VARA etc
{
L2SENDDM(PORT, Buffer, ADJBUFFER);
return;
}
SETUPNEWL2SESSION(LINK, PORT, Buffer, MSGFLAG);
if (LINK->L2STATE != 5) // Setup OK?
@ -1115,6 +1139,14 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
return;
}
// See if need to Interlock non-sharable modes, eg ARDOP and VARA
seeifInterlockneeded(PORT);
toCall[ConvFromAX25(ADJBUFFER->DEST, toCall)] = 0;
fromCall[ConvFromAX25(ADJBUFFER->ORIGIN, fromCall)] = 0;
// IF CONNECT TO APPL ADDRESS, SET UP APPL SESSION
if (APPLMASK == 0)
@ -1137,6 +1169,8 @@ VOID L2SABM(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * Buffe
WriteConnectLog(fromCall, toCall, "AX.25");
}
hookL2SessionAccepted(PORT->PORTNUMBER, fromCall, toCall, LINK);
L2SENDUA(PORT, Buffer, ADJBUFFER);
if (PORT->TNC && PORT->TNC->Hardware == H_KISSHF)
@ -3226,6 +3260,15 @@ VOID SENDFRMR(struct _LINKTABLE * LINK)
VOID CLEAROUTLINK(struct _LINKTABLE * LINK)
{
char toCall[12], fromCall[12];
toCall[ConvFromAX25(LINK->LINKCALL, toCall)] = 0;
fromCall[ConvFromAX25(LINK->OURCALL, fromCall)] = 0;
hookL2SessionDeleted(LINK->LINKPORT->PORTNUMBER, fromCall, toCall, LINK);
seeifUnlockneeded(LINK);
CLEARL2QUEUES(LINK); // TO RELEASE ANY BUFFERS
memset(LINK, 0, sizeof(struct _LINKTABLE));
@ -3593,7 +3636,7 @@ VOID ConnectFailedOrRefused(struct _LINKTABLE * LINK, char * Msg)
Buffer->LENGTH = (int)(ptr1 - (UCHAR *)Buffer);
Session = LINK->CIRCUITPOINTER; // GET CIRCUIT TABLE ENTRY
InSession = Session->L4CROSSLINK; // TO INCOMMONG SESSION
InSession = Session->L4CROSSLINK; // TO INCOMMING SESSION
CLEARSESSIONENTRY(Session);
@ -3960,3 +4003,141 @@ BOOL CheckForListeningSession(struct PORTCONTROL * PORT, MESSAGE * Msg)
}
return FALSE;
}
int COUNTLINKS(int Port);
VOID SuspendOtherPorts(struct TNCINFO * ThisTNC);
VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC);
int CheckKissInterlock(struct PORTCONTROL * PORT, int Exclusive)
{
// This checks for interlocked kiss and other ports. Returns 1 if attach/connect not allowed
// If Exclusive is not set allow connects on specified port up to l2limit,
// If Exclusive is set also don't allow any connects on specified port.
// Generally use Exclusive if locking a port that doesn't allow shared access, eg ARDOP, VARAus
// Maybe only Exclusive is needed, and just check session mode ports. Sharing of KISS ports is controlled by USERS
int Interlock = PORT->PORTINTERLOCK;
if (Interlock == 0)
return 0; // No locking
PORT = PORTTABLE;
if (Exclusive)
{
while(PORT)
{
if (PORT->TNC)
{
struct TNCINFO * TNC = PORT->TNC;
if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group
{
// See if port in use
int n;
for (n = 0; n <= 26; n++)
{
if (TNC->PortRecord->ATTACHEDSESSIONS[n])
{
return TNC->Port; ; // Refuse Connect
}
}
}
}
PORT = PORT->PORTPOINTER;
}
}
return 0; // ok to connect
}
int seeifInterlockneeded(struct PORTCONTROL * PORT)
{
// Can we just call SuspendOtherPorts - it won't do any harm if already suspended
// No, at that needs a TNC Record, so duplicate code here
int i;
int Interlock = PORT->PORTINTERLOCK;
struct TNCINFO * TNC;
if (Interlock == 0)
return 0; // No locking
for (i = 1; i <= MAXBPQPORTS; i++)
{
TNC = TNCInfo[i];
if (TNC)
if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group
if (TNC->SuspendPortProc && TNC->PortRecord->PORTCONTROL.PortSuspended == FALSE)
TNC->SuspendPortProc(TNC, TNC);
}
return 0;
}
int seeifUnlockneeded(struct _LINKTABLE * LINK)
{
// We need to see if any other links are active on any interlocked KISS ports. If not, release the lock
int i;
int links = 0;
int Interlock;
struct TNCINFO * TNC;
struct PORTCONTROL * PORT = LINK->LINKPORT;
if (PORT == NULL)
return 0;
// Should only be called for KISS links, but just in case
if (PORT->PORTTYPE > 12) // INTERNAL or EXTERNAL?
return 0; // Not KISS Port
Interlock = PORT->PORTINTERLOCK;
if (Interlock == 0)
return 0; // No locking
// Count all L2 links on interlocked KISS ports
PORT = PORTTABLE;
while(PORT)
{
if (PORT->PORTTYPE <= 12) // INTERNAL or EXTERNAL?
if (Interlock == PORT->PORTINTERLOCK)
links += COUNTLINKS(PORT->PORTNUMBER);
PORT = PORT->PORTPOINTER;
}
if (links > 1) // must be the one we are closing
return 0; // Keep lock
for (i = 1; i <= MAXBPQPORTS; i++)
{
TNC = TNCInfo[i];
if (TNC)
if (Interlock == TNC->RXRadio || Interlock == TNC->TXRadio) // Same Group
if (TNC->ReleasePortProc && TNC->PortRecord->PORTCONTROL.PortSuspended == TRUE)
TNC->ReleasePortProc(TNC, TNC);
}
return 0;
}

View File

@ -1229,10 +1229,7 @@ int main(int argc, char * argv[])
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
@ -1286,8 +1283,6 @@ int main(int argc, char * argv[])
}
}
Debugprintf("POP3 Debug After Mail Init Timer = %d", POP3Timer);
if (NUMBEROFTNCPORTS)
InitializeTNCEmulator();

View File

@ -23,7 +23,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
#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)

0
MHSave.txt Normal file
View File

View File

@ -1317,6 +1317,10 @@ FULLHA:
{
int i = 0;
// Log My HA for debugging
Logprintf(LOG_BBS, conn, '?', "Routing Trace. Check if reached correct area My HA is %s", HRoute);
// All elements of Helements must match Myelements
while (MyElements[i] && HElements[i]) // Until one set runs out
@ -1409,6 +1413,9 @@ NOHA:
// 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.
// But this means a message at the @BBS call will be forwarded without checking the Implied AT. So do that first
if (SendPtoMultiple && Msg->type == 'P')
{
struct UserInfo * bestbbs = NULL;
@ -1425,6 +1432,16 @@ NOHA:
{
ForwardingInfo = bbs->ForwardingInfo;
// Check Implied AT
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);
return 1;
}
depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]);
if (depth)

View File

@ -196,6 +196,9 @@ KC6OAR*>ID:
Port = msg->PORT;
if (Port == 40)
Port = Port;
if (Port & 0x80)
{
if ((MTX & 1) == 0)
@ -207,7 +210,12 @@ KC6OAR*>ID:
Port &= 0x7F;
if ((((uint64_t)1 << (Port - 1)) & Mask) == 0) // Check MMASK
{
if (msg->Padding[0] == '[')
msg->Padding[0] = 0;
return 0;
}
// We now pass Text format monitoring from non-ax25 drivers through this code
@ -250,11 +258,9 @@ KC6OAR*>ID:
ptr += 7;
n--;
if (n == 0)
{
if (n < 0)
return 0; // Corrupt - no end of address bit
}
}
// Reached End of digis
@ -534,6 +540,12 @@ KC6OAR*>ID:
}
}
}
if (msg->Padding[0] == '[')
Output += sprintf((char *)Output, " %s", msg->Padding);
msg->Padding[0] = 0;
if (Info)
{
// We have an info frame

View File

@ -4297,16 +4297,22 @@ VOID PTCSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
{
struct STREAMINFO * STREAM = &TNC->Streams[0];
strcpy(TNC->WEB_TNCSTATE, "Interlocked");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
STREAM->CmdSet = STREAM->CmdSave = zalloc(100);
sprintf(STREAM->CmdSet, "I%s\r", "SCSPTC"); // Should prevent connects
Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
// Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
}
VOID PTCReleasePort(struct TNCINFO * TNC)
{
struct STREAMINFO * STREAM = &TNC->Streams[0];
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
STREAM->CmdSet = STREAM->CmdSave = zalloc(100);
if (TNC->UseAPPLCallsforPactor && TNC->RIG && TNC->RIG != &TNC->DummyRig
@ -4315,7 +4321,7 @@ VOID PTCReleasePort(struct TNCINFO * TNC)
else
sprintf(STREAM->CmdSet, "I%s\r", TNC->NodeCall);
Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
// Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
}

File diff suppressed because it is too large Load Diff

View File

@ -109,6 +109,9 @@ VOID TRKSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
{
struct STREAMINFO * STREAM = &TNC->Streams[0];
strcpy(TNC->WEB_TNCSTATE, "Interlocked");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
STREAM->CmdSet = STREAM->CmdSave = zalloc(100);
sprintf(STREAM->CmdSet, "\1\1\1IDSPTNC");
}
@ -117,6 +120,9 @@ VOID TRKReleasePort(struct TNCINFO * TNC)
{
struct STREAMINFO * STREAM = &TNC->Streams[0];
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
STREAM->CmdSet = STREAM->CmdSave = zalloc(100);
sprintf(STREAM->CmdSet, "\1\1\1I%s", TNC->NodeCall);
}

View File

@ -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);

View File

@ -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");
}

View File

@ -350,12 +350,17 @@ VOID UZ7HOSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
return;
TNC->PortRecord->PORTCONTROL.PortSuspended = TRUE;
strcpy(TNC->WEB_TNCSTATE, "Interlocked");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
RegisterAPPLCalls(TNC, TRUE);
}
VOID UZ7HOReleasePort(struct TNCINFO * TNC)
{
TNC->PortRecord->PORTCONTROL.PortSuspended = FALSE;
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
RegisterAPPLCalls(TNC, FALSE);
}

210
VARA.c
View File

@ -258,6 +258,9 @@ static int ProcessLine(char * buf, int Port)
*ptr = 0;
}
else if (_memicmp(buf, "VARAAC", 6) == 0)
TNC->VaraACAllowed = atoi(&buf[7]);
else if (_memicmp(buf, "BW2300", 6) == 0)
{
TNC->ARDOPCurrentMode[0] = 'W'; // Save current state for scanning
@ -282,6 +285,7 @@ static int ProcessLine(char * buf, int Port)
TNC->DefaultMode = TNC->WL2KMode = 52;
else if (standardParams(TNC, buf) == FALSE)
strcat(TNC->InitScript, buf);
}
return (TRUE);
@ -304,12 +308,31 @@ static SOCKADDR_IN rxaddr;
static int addrlen=sizeof(sinx);
void doVarACSend(struct TNCINFO * TNC)
{
int hdrlen;
int txlen = strlen(TNC->VARACMsg);
char txbuff[64];
txlen--; // remove cr
hdrlen = sprintf(txbuff, "%d ", txlen);
send(TNC->TCPDataSock, txbuff, hdrlen, 0); // send length
send(TNC->TCPDataSock, TNC->VARACMsg, txlen, 0);
free (TNC->VARACMsg);
TNC->VARACMsg = 0;
TNC->VARACSize = 0;
TNC->VarACTimer = 0;
return ;
}
static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
{
size_t datalen;
PMSGWITHLEN buffptr;
char txbuff[500];
unsigned int bytes,txlen=0;
unsigned int bytes;
size_t txlen=0;
size_t Param;
HKEY hKey=0;
struct TNCINFO * TNC = TNCInfo[port];
@ -342,6 +365,14 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
// approx 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances
if (TNC->VarACTimer)
{
TNC->VarACTimer--;
if (TNC->VarACTimer == 0)
doVarACSend(TNC);
}
// G7TAJ's code to record activity for stats display
if ( TNC->BusyFlags && CDBusy )
@ -528,7 +559,45 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
{
PMSGWITHLEN buffptr = Q_REM(&TNC->Streams[0].BPQtoPACTOR_Q);
txlen = (int)buffptr->Len;
if(TNC->VaraACMode || TNC->VaraModeSet == 0)
{
// Send in varac format -
// 5 Hello, 15 de G8 BPQ
buffptr->Data[txlen] = 0; // Null terminate
STREAM->BytesTXed += txlen;
WritetoTrace(TNC, buffptr->Data, txlen);
// Always add to stored data and set timer. If it expires send message
if (TNC->VARACMsg == 0)
{
TNC->VARACMsg = zalloc(4096);
TNC->VARACSize = 4096;
}
else
{
if (strlen(TNC->VARACMsg) + txlen >= (TNC->VARACSize - 10))
{
TNC->VARACSize += 4096;
TNC->VARACMsg = realloc(TNC->VARACMsg, TNC->VARACSize);
}
}
strcat(TNC->VARACMsg, buffptr->Data);
TNC->VarACTimer = 10; // One second
return 0;
}
else
memcpy(txbuff, buffptr->Data, txlen);
bytes = VARASendData(TNC, &txbuff[0], txlen);
STREAM->BytesTXed += bytes;
ReleaseBuffer(buffptr);
@ -565,8 +634,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
if (buffptr == 0) return (0); // No buffers, so ignore
buffptr->Len=36;
memcpy(buffptr->Data,"No Connection to VARA TNC\r", 36);
buffptr->Len = sprintf(buffptr->Data,"No Connection to VARA TNC\r");
C_Q_ADD(&TNC->WINMORtoBPQ_Q, buffptr);
@ -595,11 +663,56 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
if (TNC->Streams[0].Connected)
{
unsigned char txbuff[512];
STREAM->PacketsSent++;
bytes=send(TNC->TCPDataSock, buff->L2DATA, txlen, 0);
if(TNC->VaraACMode == 0 && TNC->VaraModeSet == 1)
{
// Normal Send
memcpy(txbuff, buff->L2DATA, txlen);
bytes=send(TNC->TCPDataSock, txbuff, txlen, 0);
STREAM->BytesTXed += bytes;
WritetoTrace(TNC, buff->L2DATA, txlen);
return 0;
}
// Send in varac format - len space data. No cr on end, but is implied
// 5 Hello
// I think we have to send a whole message (something terminated with a new line)
// may need to combine packets. Also I think we need to combine seqential sends
// (eg CTEXT and SID)
buff->L2DATA[txlen] = 0; // Null terminate
STREAM->BytesTXed += txlen;
WritetoTrace(TNC, buff->L2DATA, txlen);
// Always add to stored data and set timer. If it expires send message
if (TNC->VARACMsg == 0)
{
TNC->VARACMsg = zalloc(4096);
TNC->VARACSize = 4096;
}
else
{
if (strlen(TNC->VARACMsg) + txlen >= (TNC->VARACSize - 10))
{
TNC->VARACSize += 4096;
TNC->VARACMsg = realloc(TNC->VARACMsg, TNC->VARACSize);
}
}
strcat(TNC->VARACMsg, buff->L2DATA);
TNC->VarACTimer = 10; // One second
return 0;
}
else
{
@ -979,12 +1092,19 @@ static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL)
VOID VARASuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
{
TNC->PortRecord->PORTCONTROL.PortSuspended = TRUE;
VARASendCommand(TNC, "LISTEN OFF\r", TRUE);
strcpy(TNC->WEB_TNCSTATE, "Interlocked");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
VOID VARAReleasePort(struct TNCINFO * TNC)
{
TNC->PortRecord->PORTCONTROL.PortSuspended = FALSE;
VARASendCommand(TNC, "LISTEN ON\r", TRUE);
strcpy(TNC->WEB_TNCSTATE, "Free");
MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
}
@ -1730,6 +1850,15 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
TNC->Busy = TNC->BusyHold * 10; // BusyHold delay
TNC->PTTonTime = GetTickCount();
// Cancel Busy timer (stats include ptt on time in port active)
if (TNC->BusyonTime)
{
TNC->BusyActivemS += (GetTickCount() - TNC->BusyonTime);
TNC->BusyonTime = 0;
}
if (TNC->PTTMode)
Rig_PTT(TNC, TRUE);
@ -1740,6 +1869,12 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
{
// Debugprintf("PTT Off");
if (TNC->PTTonTime)
{
TNC->PTTActivemS += (GetTickCount() - TNC->PTTonTime);
TNC->PTTonTime = 0;
}
if (TNC->PTTMode)
Rig_PTT(TNC, FALSE);
@ -1760,6 +1895,8 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
TNC->BusyFlags |= CDBusy;
TNC->Busy = TNC->BusyHold * 10; // BusyHold delay
TNC->BusyonTime = GetTickCount();
MySetWindowText(TNC->xIDC_CHANSTATE, "Busy");
strcpy(TNC->WEB_CHANSTATE, "Busy");
@ -1775,6 +1912,13 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
else
strcpy(TNC->WEB_CHANSTATE, "Clear");
if (TNC->BusyonTime)
{
TNC->BusyActivemS += (GetTickCount() - TNC->BusyonTime);
TNC->BusyonTime = 0;
}
MySetWindowText(TNC->xIDC_CHANSTATE, TNC->WEB_CHANSTATE);
TNC->WinmorRestartCodecTimer = time(NULL);
return;
@ -1879,6 +2023,17 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
STREAM->ConnectTime = time(NULL);
STREAM->BytesRXed = STREAM->BytesTXed = STREAM->PacketsSent = 0;
if (TNC->VARACMsg)
free(TNC->VARACMsg);
TNC->VaraACMode = 0;
TNC->VARACMsg = 0;
TNC->VARACSize = 0;
if (TNC->VaraACAllowed == 0)
TNC->VaraModeSet = 1; // definitly not varaac
else
TNC->VaraModeSet = 0; // Don't know yet
strcpy(TNC->WEB_MODE, "");
if (strstr(Buffer, "2300"))
@ -1937,6 +2092,8 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit
// Only allow VarAC mode for incomming sessions
ProcessIncommingConnectEx(TNC, Call, 0, (TNC->NetRomMode == 0), TRUE);
SESS = TNC->PortRecord->ATTACHEDSESSIONS[0];
@ -2125,7 +2282,6 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
if (TNC->NetRomTxLen)
{
STREAM->PacketsSent++;
bytes = send(TNC->TCPDataSock, TNC->NetRomTxBuffer, TNC->NetRomTxLen, 0);
@ -2137,6 +2293,9 @@ VOID VARAProcessResponse(struct TNCINFO * TNC, UCHAR * Buffer, int MsgLen)
}
else
{
TNC->VaraACMode = 0;
TNC->VaraModeSet = 1; // Don't allow connect to VaraAC
buffptr = GetBuff();
if (buffptr == 0)
@ -2586,12 +2745,51 @@ 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);
MySetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC);
// if VARAAC Mode, remove byte count from front and add cr
// could possibly be longer than buffer size
if (TNC->VaraModeSet == 0) // Could be normal or VaraAC
{
unsigned char *ptr = memchr(Data, ' ', Length); // contains a space
if (ptr)
{
int ACLen = atoi(Data);
int lenLen = (ptr - Data) + 1;
if (ACLen == (Length - lenLen))
TNC->VaraACMode = 1; // AC Mode
}
TNC->VaraModeSet = 1; // Know which mode
}
if (TNC->VaraACMode)
{
char * lenp;
char * msg;
int len;
lenp = Data;
msg = strlop(lenp, ' ');
len = atoi(lenp);
if (len != strlen(msg))
return;
msg[len++] = 13;
msg[len] = 0;
Length = len;
memmove(Data, msg, len + 1);
}
// May need to fragment
while (Length)

View File

@ -10,14 +10,14 @@
#endif
#define KVers 6,0,24,40
#define KVerstring "6.0.24.40\0"
#define KVers 6,0,24,45
#define KVerstring "6.0.24.45\0"
#ifdef CKernel
#define Vers KVers
#define Verstring KVerstring
#define Datestring "January 2024"
#define Datestring "October 2024"
#define VerComments "G8BPQ Packet Switch (C Version)" KVerstring
#define VerCopyright "Copyright © 2001-2024 John Wiseman G8BPQ\0"
#define VerDesc "BPQ32 Switch\0"

View File

@ -600,6 +600,8 @@ typedef struct PORTCONTROL
UCHAR AVSENDING; // LAST MINUTE
UCHAR AVACTIVE;
char PktFlags[64]; // Decode stts rom QtSM
char PORTTYPE; // H/W TYPE
// 0 = ASYNC, 2 = PC120, 4 = DRSI
// 6 = TOSH, 8 = QUAD, 10 = RLC100
@ -691,6 +693,13 @@ typedef struct PORTCONTROL
time_t SmartIDInterval; // Smart ID Interval (Secs)
int SendtoM0LTEMap;
uint64_t PortFreq; // Configured freq
char * M0LTEMapInfo;
int QtSMPort;
BOOL QtSMConnected;
int StatsPointer;
UCHAR * TX; // % Sending
UCHAR * BUSY; // % Active (Normally DCD active or TX)
} PORTCONTROLX, *PPORTCONTROL;
@ -735,6 +744,19 @@ typedef struct KISSINFO
UCHAR * KISSCMD; // Commands to be sent when port opened
int KISSCMDLEN;
int PTTMode; // PTT Mode Flags
int PTTState; // Current State
uint64_t PTTActivemS; // For Stats
uint64_t PTTonTime; //
uint64_t BusyActivemS; // For channel busy stats
uint64_t BusyonTime;
char * QtSMModem;
int QtSMFreq;
int QtSMStats; // Set if stats received as KISS Command
// UCHAR WIN32INFO[16]; // FOR WINDOWS DRIVER
} *PKISSINFO;

View File

@ -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"

View File

@ -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);

View File

@ -46,6 +46,8 @@ int upnpInit();
void AISTimer();
void ADSBTimer();
VOID SendSmartID(struct PORTCONTROL * PORT);
int CanPortDigi(int Port);
int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len);
#include "configstructs.h"
@ -368,6 +370,7 @@ VOID EXTTX(PEXTPORTDATA PORTVEC, MESSAGE * Buffer)
if (LINK->L2TIMER)
LINK->L2TIMER = LINK->L2TIME;
if (PORT->TNC == 0 || PORT->TNC->Hardware != H_KISSHF)
Buffer->Linkptr = 0; // CLEAR FLAG FROM BUFFER
}
@ -1081,6 +1084,10 @@ BOOL Start()
PORT->SendtoM0LTEMap = PortRec->SendtoM0LTEMap;
PORT->PortFreq = PortRec->PortFreq;
PORT->M0LTEMapInfo = PortRec->M0LTEMapInfo;
PORT->QtSMPort = PortRec->QtSMPort;
if (PortRec->BBSFLAG) // Appl 1 not permitted - BBSFLAG=NOBBS
PORT->PERMITTEDAPPLS &= 0xfffffffe; // Clear bottom bit

View File

@ -365,7 +365,7 @@ static char *pkeywords[] =
"BCALL", "DIGIMASK", "NOKEEPALIVES", "COMPORT", "DRIVER", "WL2KREPORT", "UIONLY",
"UDPPORT", "IPADDR", "I2CBUS", "I2CDEVICE", "UDPTXPORT", "UDPRXPORT", "NONORMALIZE",
"IGNOREUNLOCKEDROUTES", "INP3ONLY", "TCPPORT", "RIGPORT", "PERMITTEDAPPLS", "HIDE",
"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq"}; /* parameter keywords */
"SMARTID", "KISSCOMMAND", "SendtoM0LTEMap", "PortFreq", "M0LTEMapInfo", "QTSMPort"}; /* parameter keywords */
static void * poffset[] =
{
@ -379,7 +379,7 @@ static void * poffset[] =
&xxp.BCALL, &xxp.DIGIMASK, &xxp.DefaultNoKeepAlives, &xxp.IOADDR, &xxp.DLLNAME, &xxp.WL2K, &xxp.UIONLY,
&xxp.IOADDR, &xxp.IPADDR, &xxp.INTLEVEL, &xxp.IOADDR, &xxp.IOADDR, &xxp.ListenPort, &xxp.NoNormalize,
&xxp.IGNOREUNLOCKED, &xxp.INP3ONLY, &xxp.TCPPORT, &xxp.RIGPORT, &xxp.PERMITTEDAPPLS, &xxp.Hide,
&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq}; /* offset for corresponding data in config file */
&xxp.SmartID, &xxp.KissParams, &xxp.SendtoM0LTEMap, &xxp.PortFreq, &xxp.M0LTEMapInfo, &xxp.QtSMPort}; /* offset for corresponding data in config file */
static int proutine[] =
{
@ -393,7 +393,7 @@ static int proutine[] =
0, 1, 2, 18, 15, 16, 2,
1, 17, 1, 1, 1, 1, 2,
2, 2, 1, 1, 19, 2,
1, 20, 1, 21}; /* routine to process parameter */
1, 20, 1, 21, 22, 1}; /* routine to process parameter */
int PPARAMLIM = sizeof(proutine)/sizeof(int);
@ -2237,7 +2237,10 @@ int decode_port_rec(char * rec)
cn = int64_value(poffset[i], value, rec); /* INTEGER VALUES */
break;
case 22:
xxp.M0LTEMapInfo = _strdup(value);
cn = 1;
break;
case 9:

View File

@ -1,40 +0,0 @@
[NETWORK]
#network settings
tncport = 3004
[STATION]
#station settings
mycall = GM8BPQ-2
mygrid = IO68VL
[AUDIO]
#audio settings
rx = 8
tx = 16
txaudiolevel = 125
[RADIO]
#radio settings
radiocontrol = disabled
devicename = RIG_MODEL_NETRIGCTL
deviceport = COM99
serialspeed = 19200
pttprotocol = USB
pttport = COM99
data_bits = 8
stop_bits = 1
handshake = None
rigctld_ip = 127.0.0.1
rigctld_port = 0
[TNC]
#tnc settings
scatter = False
fft = False
narrowband = True
fmin = -50.0
fmax = 50.0
qrv = True
rxbuffersize = 16
explorer = False

View File

@ -79,6 +79,8 @@ struct PORTCONFIG
unsigned char * KissParams;
int SendtoM0LTEMap;
uint64_t PortFreq;
char * M0LTEMapInfo;
int QtSMPort;
};
struct ROUTECONFIG

6
debian/changelog vendored
View File

@ -1,8 +1,10 @@
linbpq (6.0.24.40-2) 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 <hibby@debian.org> Sat, 17 Aug 2024 17:41:25 +0100
-- Dave Hibberd <hibby@debian.org> Wed, 25 Sep 2024 01:36:59 +0100
linbpq (6.0.24.40-1) unstable; urgency=medium

2
debian/control vendored
View File

@ -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

66
debian/patches/ftbfs-gcc14.patch vendored Normal file
View File

@ -0,0 +1,66 @@
--- a/Multicast.c
+++ b/Multicast.c
@@ -620,7 +620,7 @@
int r;
UINT rlen;
- UINT outlen;
+ size_t outlen;
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");

258
debian/patches/headers.patch vendored Normal file
View File

@ -0,0 +1,258 @@
--- /dev/null
+++ b/bpqheaders.h
@@ -0,0 +1,8 @@
+//Header for an easier build under debian GCC-14
+#include <stdio.h>
+#include <time.h>
+#include <fcntl.h>
+
+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 <time.h>
+#include <stdio.h>
#include <fcntl.h>
+#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 <windows.h>
#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

View File

@ -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;
}

View File

@ -1,3 +1,5 @@
headers.patch
ftbfs-gcc14.patch
spelling-errors.patch
makefile
secure-by-default.patch

2
debian/rules vendored
View File

@ -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

354
kiss.c
View File

@ -44,6 +44,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
//#include <netax25/ttyutils.h>
//#include <netax25/daemon.h>
#include <netinet/tcp.h>
#ifdef MACBPQ
#define NOI2C
#endif
@ -84,6 +86,7 @@ int i2cPoll(struct PORTCONTROL * PORT, NPASYINFO npKISSINFO);
#define FESC 0xDB
#define TFEND 0xDC
#define TFESC 0xDD
#define QTSMKISSCMD 7
#define STX 2 // NETROM CONTROL CODES
#define ETX 3
@ -112,7 +115,8 @@ int ConnecttoTCP(NPASYINFO ASY);
int KISSGetTCPMessage(NPASYINFO ASY);
VOID CloseKISSPort(struct PORTCONTROL * PortVector);
int ReadCOMBlockEx(HANDLE fd, char * Block, int MaxLength, BOOL * Error);
void processDRATSFrame(unsigned char * Message, int Len, struct ConnectionInfo * sockptr);
void processDRATSFrame(unsigned char * Message, int Len, void * sockptr);
VOID ConnecttoQtSM(struct PORTCONTROL * PORT);
extern struct PORTCONTROL * PORTTABLE;
extern int NUMBEROFPORTS;
@ -801,11 +805,14 @@ VOID KISSINIT(struct KISSINFO * KISS)
PORTCONTROLX * PORT = (struct PORTCONTROL *)KISS;
struct KISSINFO * FIRSTCHAN = NULL;
PORT->PORTINTERLOCK = 0; // CANT USE INTERLOCK ON KISS
if (PORT->CHANNELNUM == 0)
PORT->CHANNELNUM = 'A';
// As transition aid warn if Interlock is used on kiss port
if (PORT->PORTINTERLOCK)
WritetoConsoleLocal("Interlock defined on KISS port - is this intended? ");
FIRSTCHAN = (struct KISSINFO *)CHECKIOADDR(PORT); // IF ANOTHER ENTRY FOR THIS ADDR
// MAY BE CHANGED IN ANOTHER CHANNEL USED
@ -1510,7 +1517,7 @@ SeeifMore:
// ACK FRAME. WE DONT SUPPORT ACK REQUIRED FRAMES AS A SLAVE - THEY ARE ONLY ACCEPTED BY TNCS
struct _LINKTABLE * LINK;
UINT ACKWORD = Port->RXMSG[1] | Port->RXMSG[2] << 8;
int ACKWORD = Port->RXMSG[1] | Port->RXMSG[2] << 8;
if (ACKWORD < MAXLINKS)
{
@ -1524,6 +1531,66 @@ SeeifMore:
if (Port->RXMSG[0] & 0x0f) // Not Data
{
// See if QTSM Status Packet
if ((Port->RXMSG[0] & 0x0f) == QTSMKISSCMD)
{
unsigned char * Msg = &Port->RXMSG[1];
int Chan = Port->RXMSG[0] & 0xf0;
len--;
Msg[len] = 0;
while (KISS->OURCTRL != Chan)
{
KISS = KISS->SUBCHAIN;
if (KISS == NULL)
goto SeeifMore; // SEE IF ANYTHING ELSE
}
// ok, KISS now points to our port
// Debugprintf("%d %x %s", PORT->PORTNUMBER, Port->RXMSG[0], Msg);
if (memcmp(Msg, "STATS ", 6) == 0)
{
// Save busy
int TX, DCD;
char * Msg1 = strlop(&Msg[6], ' ');
TX = atoi(&Msg[6]);
if (Msg1)
{
DCD = atoi(Msg1);
KISS->PORT.AVSENDING = TX;
KISS->PORT.AVACTIVE = DCD + TX;
KISS->QtSMStats = 1;
}
}
else if (memcmp(Msg, "PKTINFO ", 8) == 0)
{
// Save State
char * Msg1 = &Msg[8];
if (strlen(Msg) > 63)
Msg[63] = 0;
strcpy(PORT->PktFlags, Msg1);
}
else
Debugprintf("Unknown Command %d %x %s", PORT->PORTNUMBER, Port->RXMSG[0], Msg);
// Note status applies to NEXT data packet received
goto SeeifMore;
}
// If a reply to a manual KISS command(Session set and time not too long ago)
// send reponse to terminal
@ -1618,6 +1685,8 @@ SeeifMore:
PORT->RXERRORS++;
Debugprintf("KISS Checksum Error");
PORT->PktFlags[0] = 0;
goto SeeifMore; // SEE IF ANYTHING ELSE
}
len--; // Remove Checksum
@ -1630,8 +1699,13 @@ SeeifMore:
KISS = KISS->SUBCHAIN;
if (KISS == NULL)
{
// Unknown channel - clear any status info
PORT->PktFlags[0] = 0;
goto SeeifMore; // SEE IF ANYTHING ELSE
}
}
// ok, KISS now points to our port
@ -1648,6 +1722,13 @@ SeeifMore:
PutLengthinBuffer((PDATAMESSAGE)Buffer, len); // Needed for arm5 portability
if (PORT->PktFlags[0])
strcpy(Buffer->Padding, PORT->PktFlags);
else
Buffer->Padding[0] = 0;
PORT->PktFlags[0] = 0;
/*
// Randomly drop packets
@ -1893,6 +1974,10 @@ VOID ConnecttoTCPThread(NPASYINFO ASY)
if (KISS && KISS->KISSCMD && KISS->KISSCMDLEN)
send(sock, KISS->KISSCMD, KISS->KISSCMDLEN, 0);
// Try to open Mgmt Port
ConnecttoQtSM(&KISS->PORT);
continue;
}
else
@ -2030,3 +2115,264 @@ int KISSGetTCPMessage(NPASYINFO ASY)
}
return 0;
}
// Interface to QtSM Managmemt Interface
VOID QtSMThread(struct PORTCONTROL * PORT);
VOID ConnecttoQtSM(struct PORTCONTROL * PORT)
{
if (PORT && PORT->QtSMPort)
_beginthread(QtSMThread, 0, (void *)PORT);
return ;
}
VOID QtSMThread(struct PORTCONTROL * PORT)
{
// This is the Managemt Interface in QtSM. It receives PTT ON/OFF msgs from QtSM and allows changing modem mode and freq.
// Also will collect link usage stats
char Msg[255];
int err, i, ret;
u_long param = 1;
BOOL bcopt = TRUE;
fd_set readfs;
fd_set errorfs;
struct timeval timeout;
SOCKET qtsmsock;
struct sockaddr_in qtsmaddr; // For QtSM Management Session
qtsmaddr.sin_family = AF_INET;
memcpy(&qtsmaddr.sin_addr.s_addr, &PORT->PORTIPADDR, 4); // Same as for KISS connection
qtsmaddr.sin_port = htons(PORT->QtSMPort);
qtsmsock = 0;
qtsmsock = socket(AF_INET,SOCK_STREAM,0);
if (qtsmsock == INVALID_SOCKET)
{
i=sprintf(Msg, "Socket Failed for QtSM Mgmt socket - error code = %d\r\n", WSAGetLastError());
WritetoConsoleLocal(Msg);
return;
}
setsockopt(qtsmsock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4);
setsockopt(qtsmsock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4);
if (connect(qtsmsock,(LPSOCKADDR) &qtsmaddr,sizeof(qtsmaddr)) == 0)
{
//
// Connected successful
//
ioctl(qtsmsock, FIONBIO, &param);
PORT->QtSMConnected = TRUE;
}
else
{
err = WSAGetLastError();
sprintf(Msg, "Connect Failed for QtSM Mgmt - error code = %d Port %d\r\n",
err, PORT->QtSMPort);
WritetoConsoleLocal(Msg);
closesocket(qtsmsock);
qtsmsock = 0;
PORT->QtSMConnected = FALSE;
return;
}
PORT->QtSMConnected = TRUE;
while (PORT->QtSMConnected)
{
FD_ZERO(&readfs);
FD_ZERO(&errorfs);
FD_SET(qtsmsock,&readfs);
FD_SET(qtsmsock,&errorfs);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
ret = select((int)qtsmsock + 1, &readfs, NULL, &errorfs, &timeout);
if (ret == SOCKET_ERROR)
{
Debugprintf("QTSM Mgmt Select failed %d ", WSAGetLastError());
goto Lost;
}
if (ret > 0)
{
// See what happened
if (FD_ISSET(qtsmsock, &readfs))
{
char Buffer[512];
char * Line = Buffer;
char * Rest;
int InputLen = recv(qtsmsock, Buffer, 500, 0);
if (InputLen == 0 || InputLen == SOCKET_ERROR)
{
goto Lost;
}
Buffer[InputLen] = 0;
while(Line && Line[0])
{
Rest = strlop(Line, '\r');
// Need to extract lines from data
if (strcmp(Line, "Ok") == 0)
{
}
else if (memcmp(Line, "PTT ", 4) == 0)
{
// PTT 43 OFF
int Port = atoi(&Line[4]);
char * State = strlop(&Line[4], ' ');
struct KISSINFO * KISS = (struct KISSINFO *)GetPortTableEntryFromPortNum(Port);
if (strcmp(State, "ON") == 0)
{
KISS->PTTonTime = GetTickCount();
// Cancel Busy timer (stats include ptt on time in port active)
if (KISS->BusyonTime)
{
KISS->BusyActivemS += (GetTickCount() - KISS->BusyonTime);
KISS->BusyonTime = 0;
}
// if (KISS->PTTMode)
// Rig_PTT(TNC, TRUE);
}
else if (strcmp(State, "OFF") == 0)
{
if (KISS->PTTonTime)
{
KISS->PTTActivemS += (GetTickCount() - KISS->PTTonTime);
KISS->PTTonTime = 0;
}
// if (KISS->PTTMode)
// Rig_PTT(TNC, FALSE);
}
}
else if (strcmp(Line, "Connected to QtSM") == 0)
{
char Msg[64];
int Len;
// We need tp send a QtSMPort message for each Channel sharing thia connection
// Note struct KISSINFO and struct PORTCONTROL are different mappings of the same data
struct KISSINFO * KISS = (struct KISSINFO *)PORT;
while (KISS)
{
Len = sprintf(Msg, "QtSMPort %d %d\r", KISS->PORT.CHANNELNUM - '@', KISS->PORT.PORTNUMBER);
send(qtsmsock, Msg, Len, 0);
Len = sprintf(Msg, "Modem %d\r", KISS->PORT.CHANNELNUM - '@');
send(qtsmsock, Msg, Len, 0);
KISS = KISS->SUBCHAIN;
}
}
else if (memcmp(Line, "Port ", 5) == 0)
{
// Port 1 Freq 1500 Modem BPSK AX.25 300bd
int Port, chan, Freq;
char * Modem;
struct KISSINFO * KISS;
Port = atoi(&Line[5]);
Line = strlop(&Line[9], ' ');
chan = atoi(Line);
Freq = atoi(&Line[6]);
Modem = strlop(&Line[13], ' ');
KISS = (struct KISSINFO *)GetPortTableEntryFromPortNum(Port);
if (KISS->QtSMModem)
free(KISS->QtSMModem);
KISS->QtSMModem = _strdup(Modem);
KISS->QtSMFreq = Freq;
}
else if (memcmp(Line, "XXSTATS ", 6) == 0)
{
// STATS PORT PTT BUSY
int Port, PTT, Busy;
struct PORTCONTROL * MPORT;
Port = atoi(&Line[6]);
Line = strlop(&Line[6], ' ');
PTT = atoi(Line);
Line = strlop(Line, ' ');
Busy = atoi(Line);
MPORT = GetPortTableEntryFromPortNum(Port);
if (MPORT)
{
MPORT->AVACTIVE = Busy + PTT;
MPORT->AVSENDING = PTT;
}
}
else
Debugprintf("Unexpected QtSM Message %s", Line);
Line = Rest;
}
}
if (FD_ISSET(qtsmsock, &errorfs))
{
Lost:
sprintf(Msg, "QtSM Mgmt Connection lost for TCP Port %d Port %d\r\n", PORT->QtSMPort, PORT->PORTNUMBER);
WritetoConsoleLocal(Msg);
PORT->QtSMConnected = FALSE;
closesocket(qtsmsock);
qtsmsock = 0;
return;
}
continue;
}
else
{
}
}
sprintf(Msg, "QtSM Mgmt Thread Terminated TCP Port %d Port %d\r\n", PORT->QtSMPort, PORT->PORTNUMBER);
WritetoConsoleLocal(Msg);
}

View File

@ -67,7 +67,7 @@ static BOOL ReadConfigFile(int Port);
static int ProcessLine(char * buf,int Port, BOOL CheckPort);
int WritetoConsoleLocal(char * buff);
int ExtProc(int fn, int port,unsigned char * buff)
static size_t ExtProc(int fn, int port, PMESSAGE buff)
{
int len,txlen=0,res;
char txbuff[500];
@ -110,9 +110,8 @@ int ExtProc(int fn, int port,unsigned char * buff)
len-=3;
memcpy(&buff[7],&rxbuff[19],len);
len+=5;
memcpy(&buff->DEST, &rxbuff[19], len);
len += (1 + sizeof(void *));
}
else
{
@ -121,14 +120,11 @@ int ExtProc(int fn, int port,unsigned char * buff)
if ((len < 16) || (len > 320)) return 0; // Probably RLI Mode Frame
len-=3;
memcpy(&buff[7],&rxbuff[16],len);
len+=5;
memcpy(&buff->DEST, &rxbuff[16], len);
len += (1 + sizeof(void *));
}
buff[5]=(len & 0xff);
buff[6]=(len >> 8);
PutLengthinBuffer((PDATAMESSAGE)buff, len);
return 1;
@ -140,9 +136,8 @@ int ExtProc(int fn, int port,unsigned char * buff)
// RLI MODE - An extra 3 bytes before len, seem to be 00 00 41
{
txlen=(buff[6]<<8) + buff[5]; // BPQEther is DOS-based - chain word is 2 bytes
txlen-=2;
txlen = GetLengthfromBuffer((PDATAMESSAGE)buff); // 2 for CRC
txlen -= (sizeof(void *) - 2);
txbuff[16]=0x41;
txbuff[17]=(txlen & 0xff);
txbuff[18]=(txlen >> 8);
@ -150,14 +145,14 @@ int ExtProc(int fn, int port,unsigned char * buff)
if (txlen < 1 || txlen > 400)
return 0;
memcpy(&txbuff[19],&buff[7],txlen);
memcpy(&txbuff[19], &buff->DEST[0], txlen);
}
else
{
txlen=(buff[6]<<8) + buff[5]; // BPQEther is DOS-based - chain word is 2 bytes
txlen-=2;
txlen = GetLengthfromBuffer((PDATAMESSAGE)buff); // 2 for CRC
txlen -= (sizeof(void *) - 2);
txbuff[14]=(txlen & 0xff);
txbuff[15]=(txlen >> 8);
@ -166,7 +161,7 @@ int ExtProc(int fn, int port,unsigned char * buff)
return 0;
memcpy(&txbuff[16],&buff[7],txlen);
memcpy(&txbuff[16], &buff->DEST[0], txlen);
}
memcpy(&txbuff[0], &IF->EthDest[0],6);
@ -210,7 +205,7 @@ int ExtProc(int fn, int port,unsigned char * buff)
}
UINT ETHERExtInit(struct PORTCONTROL * PortEntry)
void * ETHERExtInit(struct PORTCONTROL * PortEntry)
{
// Can have multiple ports, each mapping to a different Ethernet Adapter
@ -299,7 +294,7 @@ UINT ETHERExtInit(struct PORTCONTROL * PortEntry)
// n=sprintf(buf,"Using %s Adapter = Interface %d\r", ifr.ifr_ifindex);
// WritetoConsole(buf);
return ((int) ExtProc);
return (ExtProc);
}

View File

@ -158,13 +158,12 @@ int APIProcessHTTPMessage(char * response, char * Method, char * URL, char * req
int request_token(char * response)
{
Token * token = generate_token();
int expires_in = 3600;
char scope[] = "create";
printf("Token generated: %s\n", token->token);
sprintf(response, "{\"access_token\":\"%s\", \"expires_in\":%d, \"scope\":\"create\"}\r\n",
token->token, expires_in);
sprintf(response, "{\"access_token\":\"%s\", \"expires_at\":%ld,\"scope\":\"create\"}\r\n",
token->token, token->expiration_time);
return strlen(response);
}

View File

@ -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
@ -525,6 +532,8 @@ typedef struct TNCINFO
BOOL TNCCONNECTING; // For FreeData
BOOL TNCCONNECTED;
BOOL QtSMConnected;
char NodeCall[10]; // Call we listen for (PORTCALL or NODECALL
char CurrentMYC[10]; // Save current call so we don't change it unnecessarily
char * LISTENCALLS; // Calls TNC will respond to (currently only for VARA)
@ -536,6 +545,11 @@ typedef struct TNCINFO
int PTTMode; // PTT Mode Flags
int PTTState; // Current State
uint64_t PTTActivemS; // For Stats
uint64_t PTTonTime; //
uint64_t BusyActivemS; // For channel busy stats
uint64_t BusyonTime;
char PTTOn[60]; // Port override of RIGCONTROL config
char PTTOff[60];
@ -839,6 +853,13 @@ typedef struct TNCINFO
char * NRNeighbour;
int NRCloseTimer;
struct _LINKTABLE * DummyLink; // Simulated link to simplify interface to ax,25 netrom code
struct sixPackPortInfo * sixPack;
int VaraACAllowed; // Set by config
int VaraACMode; // Set by first message received
int VaraModeSet; // Have decicded if VarAC mode or not
char * VARACMsg; // to build message from packets
int VarACTimer; // delayed send timer
size_t VARACSize; // malloc'ed size
} *PTNCINFO;

9
upnp.c
View File

@ -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);

View File

@ -1,187 +0,0 @@
// Includes code from MiniUPnPc, used subject to the following conditions:
/*
MiniUPnPc
Copyright (c) 2005-2020, Thomas BERNARD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#define MINIUPNP_STATICLIB
#include <stdio.h>
#ifdef _WIN32
#include "upnpcommands.h"
#include "miniupnpc.h"
#include "upnperrors.h"
#include <winsock2.h>
#else
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnperrors.h>
#include <stdio.h>
#endif
int AddMap(char * controlURL, char * eport, char * iport, char * proto);
int DeleteMap(char * controlURL, char * eport, char * iport, char * proto);
void Consoleprintf(const char * format, ...);
struct UPNP
{
struct UPNP * Next;
char * Protocol;
char * LANport;
char * WANPort;
};
extern struct UPNP * UPNPConfig;
char * controlURL = 0;
char * servicetype = 0;
char iaddr[] = "IP";
char * inClient = NULL;
#ifdef LINBPQ
char desc[] = "LinBPQ ";
#else
char desc[] = "BPQ32 ";
#endif
char * remoteHost = NULL;
char * leaseDuration = NULL;
struct UPNPDev * devlist = 0;
char lanaddr[64] = "unset"; /* my ip address on the LAN */
struct UPNPUrls urls;
struct IGDdatas data;
int i;
const char * rootdescurl = 0;
const char * multicastif = 0;
const char * minissdpdpath = 0;
int localport = UPNP_LOCAL_PORT_ANY;
int retcode = 0;
int error = 0;
int ipv6 = 0;
int ignore = 0;
unsigned char ttl = 2;
int upnpInit()
{
struct UPNP * Config = UPNPConfig;
int i;
#ifdef WIN32
WSADATA wsaData;
int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if(nResult != NO_ERROR)
{
fprintf(stderr, "WSAStartup() failed.\n");
return -1;
}
#endif
while (Config)
{
if (devlist == NULL)
{
devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
if (devlist == NULL)
{
Consoleprintf("Failed to find a UPNP device");
return 0;
}
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
}
AddMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
Config = Config->Next;
}
return 0;
}
int upnpClose()
{
struct UPNP * Config = UPNPConfig;
int i;
while (Config)
{
if (devlist == NULL)
{
devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
if (devlist == NULL)
{
Consoleprintf("Failed to find a UPNP device");
return 0;
}
i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
}
DeleteMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
Config = Config->Next;
}
return 0;
}
int AddMap(char * controlURL, char * eport, char * iport, char * proto)
{
int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
eport, iport, lanaddr, desc,
proto, remoteHost, leaseDuration);
if (r != UPNPCOMMAND_SUCCESS)
{
Consoleprintf("UPNP AddPortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
return -2;
}
Consoleprintf("UPNP AddPortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
return 0;
}
int DeleteMap(char * controlURL, char * eport, char * iport, char * proto)
{
int r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport, proto, remoteHost);
if(r != UPNPCOMMAND_SUCCESS)
{
Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
return -2;
}
Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
return 0;
}