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

SIXPACK Status" + "

", + TNC->Port); + + + Len += sprintf(&Buff[Len], ""); + + Len += sprintf(&Buff[Len], "", TNC->WEB_COMMSSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_TNCSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_MODE); + Len += sprintf(&Buff[Len], "", TNC->WEB_CHANSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_PROTOSTATE); + Len += sprintf(&Buff[Len], "", TNC->WEB_TRAFFIC); +// Len += sprintf(&Buff[Len], "", TNC->WEB_RESTARTS); + Len += sprintf(&Buff[Len], "
Comms State%s
TNC State%s
Mode%s
Channel State%s
Proto State%s
Traffic%s
TNC Restarts
"); + + Len += sprintf(&Buff[Len], "", TNC->WebBuffer); + Len = DoScanLine(TNC, Buff, Len); + + return Len; +} + + + +VOID * SIXPACKExtInit(EXTPORTDATA * PortEntry) +{ + int port; + char Msg[255]; + char * ptr; + struct TNCINFO * TNC; + char * TempScript; + struct PORTCONTROL * PORT = &PortEntry->PORTCONTROL; + + port = PORT->PORTNUMBER; + + if (TNCInfo[port]) // If restarting, free old config + free(TNCInfo[port]); + + TNC = TNCInfo[port] = malloc(sizeof(struct TNCINFO)); + memset(TNC, 0, sizeof(struct TNCINFO)); + + TNC->InitScript = malloc(1000); + TNC->InitScript[0] = 0; + + if (PortConfig[port]) // May not have config + ReadConfigFile(port, ProcessLine); + + TNC = TNCInfo[port]; + + if (TNC == NULL) + { + // Not defined in Config file + + sprintf(Msg," ** Error - no info in BPQ32.cfg for this port\n"); + WritetoConsole(Msg); + + return ExtProc; + } + + TNC->sixPack = zalloc(sizeof(struct sixPackTNCInfo)); + + TNC->Port = port; + TNC->Hardware = H_SIXPACK; + TNC->ARDOPBuffer = malloc(8192); + + TNC->PortRecord = PortEntry; + + if (PortEntry->PORTCONTROL.PORTCALL[0] == 0) + memcpy(TNC->NodeCall, MYNODECALL, 10); + else + ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall); + + if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0) + TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK; + + PortEntry->PORTCONTROL.PROTOCOL = 10; + PortEntry->PORTCONTROL.PORTQUALITY = 0; + PortEntry->PORTCONTROL.USERS = 1; // Max 1 Session + + TNC->PacketChannels = 0; + + PortEntry->MAXHOSTMODESESSIONS = 1; + + PortEntry->SCANCAPABILITIES = SIMPLE; // Scan Control - pending connect only + PortEntry->PERMITGATEWAY = TRUE; // Can change ax.25 call on each stream + + PortEntry->PORTCONTROL.UICAPABLE = TRUE; + + if (PortEntry->PORTCONTROL.PORTPACLEN == 0) + PortEntry->PORTCONTROL.PORTPACLEN = 236; + + TNC->SuspendPortProc = SIXPACKSuspendPort; + TNC->ReleasePortProc = SIXPACKReleasePort; + +// PortEntry->PORTCONTROL.PORTSTARTCODE = KISSStartPort; +// PortEntry->PORTCONTROL.PORTSTOPCODE = KISSStopPort; + + ptr=strchr(TNC->NodeCall, ' '); + if (ptr) *(ptr) = 0; // Null Terminate + + // Set Essential Params and MYCALL + + // Put overridable ones on front, essential ones on end + + TempScript = zalloc(1000); + + // cant think of any yet + + if (TNC->InitScript) + { + strcat(TempScript, TNC->InitScript); + free(TNC->InitScript); + } + + TNC->InitScript = TempScript; + + if (TNC->WL2K == NULL) + if (PortEntry->PORTCONTROL.WL2KInfo.RMSCall[0]) // Alrerady decoded + TNC->WL2K = &PortEntry->PORTCONTROL.WL2KInfo; + + PortEntry->PORTCONTROL.TNC = TNC; + + TNC->WebWindowProc = WebProc; + TNC->WebWinX = 520; + TNC->WebWinY = 500; + TNC->WebBuffer = zalloc(5000); + + TNC->WEB_COMMSSTATE = zalloc(100); + TNC->WEB_TNCSTATE = zalloc(100); + TNC->WEB_CHANSTATE = zalloc(100); + TNC->WEB_BUFFERS = zalloc(100); + TNC->WEB_PROTOSTATE = zalloc(100); + TNC->WEB_RESTARTTIME = zalloc(100); + TNC->WEB_RESTARTS = zalloc(100); + + TNC->WEB_MODE = zalloc(20); + TNC->WEB_TRAFFIC = zalloc(100); + + +#ifndef LINBPQ + + CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 700, 450, ForcedClose); + + CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Channel State", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_CHANSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Proto State", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_PROTOSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,116,80,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "0 0 0 0", WS_CHILD | WS_VISIBLE,116,116,374,20 , TNC->hDlg, NULL, hInstance, NULL); + + CreateWindowEx(0, "STATIC", "TNC Restarts", WS_CHILD | WS_VISIBLE,10,138,100,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_RESTARTS = CreateWindowEx(0, "STATIC", "0", WS_CHILD | WS_VISIBLE,116,138,40,20 , TNC->hDlg, NULL, hInstance, NULL); + CreateWindowEx(0, "STATIC", "Last Restart", WS_CHILD | WS_VISIBLE,140,138,100,20, TNC->hDlg, NULL, hInstance, NULL); + TNC->xIDC_RESTARTTIME = CreateWindowEx(0, "STATIC", "Never", WS_CHILD | WS_VISIBLE,250,138,200,20, TNC->hDlg, NULL, hInstance, NULL); + + TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOINTEGRALHEIGHT | + LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL, + 0,170,250,300, TNC->hDlg, NULL, hInstance, NULL); + + TNC->ClientHeight = 450; + TNC->ClientWidth = 500; + + TNC->hMenu = CreatePopupMenu(); + + AppendMenu(TNC->hMenu, MF_STRING, WINMOR_KILL, "Kill TNC"); + AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTART, "Kill and Restart TNC"); + AppendMenu(TNC->hMenu, MF_STRING, WINMOR_RESTARTAFTERFAILURE, "Restart TNC after failed Connection"); + CheckMenuItem(TNC->hMenu, WINMOR_RESTARTAFTERFAILURE, (TNC->RestartAfterFailure) ? MF_CHECKED : MF_UNCHECKED); + AppendMenu(TNC->hMenu, MF_STRING, ARDOP_ABORT, "Abort Current Session"); + + MoveWindows(TNC); +#endif + Consoleprintf("SIXPACK Host %s %d", TNC->HostName, htons(TNC->destaddr.sin_port)); + + Connectto6Pack(port); + + time(&TNC->lasttime); // Get initial time value + + return ExtProc; +} + + +VOID TidyClose(struct TNCINFO * TNC, int Stream) +{ + // If all acked, send disc + + if (TNC->Streams[Stream].BytesOutstanding == 0) + SerialSendCommand(TNC, "DISCONNECT\r"); +} + +VOID ForcedClose(struct TNCINFO * TNC, int Stream) +{ + SerialSendCommand(TNC, "DISCONNECT\r"); +} + +VOID CloseComplete(struct TNCINFO * TNC, int Stream) +{ + if (Stream == 0) + { + SIXPACKReleaseTNC(TNC); + } +} + + +static int KissDecode(UCHAR * inbuff, UCHAR * outbuff, int len) +{ + int i,txptr=0; + UCHAR c; + + for (i=0;iInputLen > 8000) // Shouldnt have packets longer than this + TNC->InputLen=0; + + InputLen = recv(TNC->TCPSock, &TNC->ARDOPBuffer[TNC->InputLen], 8192 - TNC->InputLen, 0); + + if (InputLen == 0 || InputLen == SOCKET_ERROR) + { + // Does this mean closed? + + int err = GetLastError(); + + closesocket(TNC->TCPSock); + + TNC->TCPSock = 0; + + TNC->CONNECTED = FALSE; + TNC->Streams[0].ReportDISC = TRUE; + + sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + return; + } + + TNC->InputLen += InputLen; + + // Extract and decode KISS frames + + ptr = memchr(TNC->ARDOPBuffer + 1, FEND, TNC->InputLen - 1); // Ignore leading FEND + + while (ptr) // FEND in buffer + { + ptr++; + + MsgLen = ptr - TNC->ARDOPBuffer; + + if (MsgLen > 360) + { + TNC->InputLen = 0; + return; + } + + TNC->InputLen -= MsgLen; + + if (MsgLen > 1) + { + PMESSAGE Buff = GetBuff(); + + MsgLen = KissDecode(TNC->ARDOPBuffer, Buffer, MsgLen); + + // we dont need the FENDS or control byte + + MsgLen -= 3; + + if (Buff) + { + memcpy(&Buff->DEST, &Buffer[2], MsgLen); + MsgLen += (3 + sizeof(void *)); + + PutLengthinBuffer((PDATAMESSAGE)Buff, MsgLen); // Needed for arm5 portability + + C_Q_ADD(&TNC->PortRecord->PORTCONTROL.PORTRX_Q, (UINT *)Buff); + } + } + + if (TNC->InputLen == 0) + return; + + memmove(TNC->ARDOPBuffer, ptr, TNC->InputLen); + ptr = memchr(TNC->ARDOPBuffer + 1, FEND, TNC->InputLen - 1); // Ignore leading FEND + } + +} + + + +/* + +// we dont need the control byte + +len --; + +if (Buffer) +{ +memcpy(&Buffer->DEST, &Port->RXMSG[1], len); +len += (3 + sizeof(void *)); + +PutLengthinBuffer((PDATAMESSAGE)Buffer, len); // Needed for arm5 portability + +C_Q_ADD(TNC->PortRecord->PORTCONTROL.PORTRX_Q, (UINT *)Buffer); +} + +*/ + +// TNC->InputLen -= MsgLen; +// goto loop; + + + + +void AttachSIXPACK(struct PORTCONTROL * PORT, MESSAGE * Buffer) +{ + // SABM on HFKISS port. L2 code will accepr call and connect to appl if necessary, but + // need to attach the port + + char Call[16] = ""; + char OrigCall[16] = ""; + struct TNCINFO * TNC = PORT->TNC; + struct WL2KInfo * WL2K = TNC->WL2K; + + if (TNC->PortRecord->ATTACHEDSESSIONS[0] == 0) + { + TRANSPORTENTRY * SESS; + struct TNCINFO * TNC = PORT->TNC; + + // Incoming Connect + + Call[ConvFromAX25(Buffer->DEST, Call)] = 0; + OrigCall[ConvFromAX25(Buffer->ORIGIN, OrigCall)] = 0; + + // Stop other ports in same group + + SuspendOtherPorts(TNC); + + TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit + + ProcessIncommingConnectEx(TNC, Call, 0, FALSE, FALSE); + + SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; + + SESS->Mode = TNC->WL2KMode; + + TNC->ConnectPending = FALSE; + + if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", OrigCall, Call, TNC->RIG->Valchar); + SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq + if (SESS->Frequency == 1500) + { + // try to get from WL2K record + + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + } + } + SESS->Mode = TNC->WL2KMode; + } + else + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", OrigCall, Call); + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + SESS->Mode = WL2K->mode; + } + } + + if (WL2K) + strcpy(SESS->RMSCall, WL2K->RMSCall); + + MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); + } +} + +void DetachSIXPACK(struct PORTCONTROL * PORT) +{ + // L2 Link Closed. Detach. + + struct TNCINFO * TNC = PORT->TNC; + struct STREAMINFO * STREAM = &TNC->Streams[0]; + + if (STREAM->Attached) + STREAM->ReportDISC = TRUE; // Tell Node + + STREAM->Connecting = FALSE; + STREAM->Connected = FALSE; + +} + +void SIXPACKConnected(struct PORTCONTROL * PORT, struct _LINKTABLE * LINK) +{ + // UA received when connecting + + struct TNCINFO * TNC = PORT->TNC; + struct STREAMINFO * STREAM = &TNC->Streams[0]; + struct WL2KInfo * WL2K = TNC->WL2K; + + TRANSPORTENTRY * SESS; + char Call[16] = ""; + char OrigCall[16] = ""; + + + if (STREAM->Connecting) + { + STREAM->Connecting = FALSE; + STREAM->Connected = TRUE; + + Call[ConvFromAX25(LINK->LINKCALL, Call)] = 0; + OrigCall[ConvFromAX25(LINK->OURCALL, OrigCall)] = 0; + + TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit; // Reset Limit + + SESS = TNC->PortRecord->ATTACHEDSESSIONS[0]; + SESS->Mode = TNC->WL2KMode; + + if (TNC->RIG && TNC->RIG != &TNC->DummyRig && strcmp(TNC->RIG->RigName, "PTT")) + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound Freq %s", OrigCall, Call, TNC->RIG->Valchar); + SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500; // Convert to Centre Freq + + if (SESS->Frequency == 1500) + { + // try to get from WL2K record + + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + } + } + SESS->Mode = TNC->WL2KMode; + } + else + { + sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", OrigCall, Call); + + if (WL2K) + { + SESS->Frequency = WL2K->Freq; + SESS->Mode = WL2K->mode; + } + } + + if (WL2K) + strcpy(SESS->RMSCall, WL2K->RMSCall); + + MySetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE); + } +} + + + +VOID x6PackThead(void * portptr); + +int Connectto6Pack(int port) +{ + _beginthread(x6PackThead, 0, (void *)(size_t)port); + + return 0; +} + +VOID x6PackThead(void * portptr) +{ + // 6pack over TNC thread + + // Opens socket and looks for data + + int port = (int)(size_t)portptr; + char Msg[255]; + int err, i, ret; + u_long param=1; + BOOL bcopt=TRUE; + struct hostent * HostEnt; + struct TNCINFO * TNC = TNCInfo[port]; + fd_set readfs; + fd_set errorfs; + struct timeval timeout; + char * ptr1; + char * ptr2; + UINT * buffptr; + int reinitTimer = 0; + int linkactive = 0; + + struct sixPackPortInfo * sixPack = TNC->sixPack; + + if (sixPack == NULL || TNC->HostName == NULL) + return; + + TNC->BusyFlags = 0; + + TNC->CONNECTING = TRUE; + + Sleep(3000); // Allow init to complete + +#ifdef WIN32 + if (strcmp(TNC->HostName, "127.0.0.1") == 0) + { + // can only check if running on local host + + TNC->PID = GetListeningPortsPID(TNC->destaddr.sin_port); + if (TNC->PID == 0) + { + TNC->CONNECTING = FALSE; + return; // Not listening so no point trying to connect + } + + // Get the File Name in case we want to restart it. + + if (TNC->ProgramPath == NULL) + { + if (GetModuleFileNameExPtr) + { + HANDLE hProc; + char ExeName[256] = ""; + + hProc = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, TNC->PID); + + if (hProc) + { + GetModuleFileNameExPtr(hProc, 0, ExeName, 255); + CloseHandle(hProc); + + TNC->ProgramPath = _strdup(ExeName); + } + } + } + } +#endif + +// // If we started the TNC make sure it is still running. + +// if (!IsProcess(TNC->PID)) +// { +// RestartTNC(TNC); +// Sleep(3000); +// } + + + TNC->destaddr.sin_addr.s_addr = inet_addr(TNC->HostName); + + if (TNC->destaddr.sin_addr.s_addr == INADDR_NONE) + { + // Resolve name to address + + HostEnt = gethostbyname (TNC->HostName); + + if (!HostEnt) + { + TNC->CONNECTING = FALSE; + return; // Resolve failed + } + memcpy(&TNC->destaddr.sin_addr.s_addr,HostEnt->h_addr,4); + memcpy(&TNC->Datadestaddr.sin_addr.s_addr,HostEnt->h_addr,4); + } + +// closesocket(TNC->TCPSock); + + TNC->TCPSock=socket(AF_INET,SOCK_STREAM,0); + + if (TNC->TCPSock == INVALID_SOCKET) + { + i=sprintf(Msg, "Socket Failed for 6Pack socket - error code = %d\r\n", WSAGetLastError()); + WritetoConsole(Msg); + + TNC->CONNECTING = FALSE; + return; + } + + setsockopt(TNC->TCPSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4); + + sinx.sin_family = AF_INET; + sinx.sin_addr.s_addr = INADDR_ANY; + sinx.sin_port = 0; + + if (connect(TNC->TCPSock,(LPSOCKADDR) &TNC->destaddr,sizeof(TNC->destaddr)) == 0) + { + // + // Connected successful + // + } + else + { + if (TNC->Alerted == FALSE) + { + err=WSAGetLastError(); + i=sprintf(Msg, "Connect Failed for 6Pack socket - error code = %d\r\n", err); + WritetoConsole(Msg); + sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC failed"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + TNC->Alerted = TRUE; + } + + closesocket(TNC->TCPSock); + TNC->TCPSock = 0; + TNC->CONNECTING = FALSE; + return; + } + + Sleep(1000); + + TNC->LastFreq = 0; // so V4 display will be updated + + TNC->CONNECTING = FALSE; + TNC->CONNECTED = TRUE; + TNC->BusyFlags = 0; + TNC->InputLen = 0; + + TNC->Alerted = TRUE; + + sprintf(TNC->WEB_COMMSSTATE, "Connected to TNC"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + FreeSemaphore(&Semaphore); + + sprintf(Msg, "Connected to TNC Port %d\r\n", TNC->Port); + WritetoConsole(Msg); + + while (TNC->CONNECTED) + { + FD_ZERO(&readfs); + FD_ZERO(&errorfs); + + FD_SET(TNC->TCPSock,&readfs); + FD_SET(TNC->TCPSock,&errorfs); + + timeout.tv_sec = 1; + timeout.tv_usec = 0; // We use this to run timeouts + + ret = select((int)TNC->TCPSock + 1, &readfs, NULL, &errorfs, &timeout); + + if (ret == SOCKET_ERROR) + { + Debugprintf("6Pack Select failed %d ", WSAGetLastError()); + goto Lost; + } + if (ret > 0) + { + // See what happened + + if (FD_ISSET(TNC->TCPSock, &readfs)) + { + GetSemaphore(&Semaphore, 52); + SixPackProcessReceivedPacket(TNC); + FreeSemaphore(&Semaphore); + } + + if (FD_ISSET(TNC->TCPSock, &errorfs)) + { +Lost: + sprintf(Msg, "6Pack Connection lost for Port %d\r\n", TNC->Port); + WritetoConsole(Msg); + + sprintf(TNC->WEB_COMMSSTATE, "Connection to TNC lost"); + MySetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE); + + TNC->CONNECTED = FALSE; + TNC->Alerted = FALSE; + + if (TNC->PTTMode) + Rig_PTT(TNC, FALSE); // Make sure PTT is down + + if (TNC->Streams[0].Attached) + TNC->Streams[0].ReportDISC = TRUE; + + TNC->TCPSock = 0; + return; + } + } + else + { + // Timeout. See if we need to reinit tnc chain + + if (sixPack->linkOK == 0) + { + sixPack->reinitTimer++; + if (sixPack->reinitTimer > 30) + { + // send SIXP_INIT_CMD which should rescan the tnc chain + + unsigned char Msg = SIXP_INIT_CMD; + int txlen = send(TNC->TCPSock, &Msg, 1, 0); + sixPack->reinitTimer = 0; + } + } + } + + } + sprintf(Msg, "6Pack Thread Terminated Port %d\r\n", TNC->Port); + WritetoConsole(Msg); +} + + + + + + diff --git a/ARDOP.c b/ARDOP.c index 01ee591..61fab6b 100644 --- a/ARDOP.c +++ b/ARDOP.c @@ -880,6 +880,17 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) } } + // Check ATTACH time limit + + if (STREAM->Attached) + { + if (STREAM->AttachTime && TNC->AttachTimeLimit && time(NULL) > (TNC->AttachTimeLimit + STREAM->AttachTime)) + { + STREAM->ReportDISC = 1; + STREAM->AttachTime = 0; + } + } + if (TNC->ARDOPCommsMode != 'T') // S I or E { ARDOPSCSCheckRX(TNC); @@ -1190,6 +1201,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) Debugprintf("ARDOP New Attach Stream %d DEDStream %d", Stream, STREAM->DEDStream); STREAM->Attached = TRUE; + STREAM->AttachTime = time(NULL); calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, TNC->Streams[Stream].MyCall); TNC->Streams[Stream].MyCall[calllen] = 0; diff --git a/BBSHTMLConfig.c b/BBSHTMLConfig.c index 80f2bca..c37533c 100644 --- a/BBSHTMLConfig.c +++ b/BBSHTMLConfig.c @@ -158,6 +158,7 @@ char MailPage[] = "%s's BBS Web Server" "Welcome Msgs & Prompts" "Housekeeping" "WP Update" + "WebMail" "Node Menu" ""; @@ -178,6 +179,7 @@ char RefreshMainPage[] = "" "Welcome Msgs & Prompts" "Housekeeping" "WP Update" + "WebMail" "Node Menu" ""; @@ -1887,6 +1889,7 @@ VOID SaveFwdCommon(struct HTTPConnectionInfo * Session, char * MsgPtr, char * Re GetCheckBox(input, "WarnNoRoute=", &WarnNoRoute); GetCheckBox(input, "LocalTime=", &Localtime); GetCheckBox(input, "SendPtoMultiple=", &SendPtoMultiple); + GetCheckBox(input, "FourCharCont=", &FOURCHARCONT); // Reinitialise Aliases @@ -2716,6 +2719,7 @@ VOID SendFwdMainPage(char * Reply, int * RLen, char * Key) (WarnNoRoute) ? CHKD : UNC, (Localtime) ? CHKD : UNC, (SendPtoMultiple) ? CHKD : UNC, + (FOURCHARCONT) ? CHKD : UNC, ALIASES); } diff --git a/BBSUtilities.c b/BBSUtilities.c index 6c542ba..a3b9bd8 100644 --- a/BBSUtilities.c +++ b/BBSUtilities.c @@ -213,6 +213,7 @@ BOOL UserCantKillT = FALSE; typedef int (WINAPI FAR *FARPROCX)(); FARPROCX pRunEventProgram; +FARPROCX pGetPortFrequency; int RunEventProgram(char * Program, char * Param); @@ -9680,6 +9681,7 @@ VOID SaveConfig(char * ConfigName) SaveIntValue(group, "WarnNoRoute", WarnNoRoute); SaveIntValue(group, "Localtime", Localtime); SaveIntValue(group, "SendPtoMultiple", SendPtoMultiple); + SaveIntValue(group, "FOURCHARCONT", FOURCHARCONT); SaveMultiStringValue(group, "FWDAliases", AliasText); @@ -10116,6 +10118,8 @@ BOOL GetConfig(char * ConfigName) ReaddressReceived = GetIntValue(group, "ReaddressReceived"); WarnNoRoute = GetIntValue(group, "WarnNoRoute"); SendPtoMultiple = GetIntValue(group, "SendPtoMultiple"); + FOURCHARCONT = GetIntValue(group, "FOURCHARCONT"); + Localtime = GetIntValue(group, "Localtime"); AliasText = GetMultiStringValue(group, "FWDAliases"); GetStringValue(group, "BBSName", BBSName); @@ -10588,8 +10592,24 @@ int Connected(int Stream) if (SendNewUserMessage) { + int64_t LongFreq = Freq; + char * MailBuffer = malloc(100); - Length += sprintf(MailBuffer, "New User %s Connected to Mailbox on Port %d Freq %d Mode %d\r\n", callsign, port, Freq, Mode); + + if (Freq == 0 && port) + { + // Get Port Freq if available + + char FreqString[256]; + +#ifdef WIN32 + if (pGetPortFrequency) + LongFreq = pGetPortFrequency(port, FreqString); +#else + LongFreq = GetPortFrequency(port, FreqString); +#endif + } + Length += sprintf(MailBuffer, "New User %s Connected to Mailbox on Port %d Freq %d Mode %ld\r\n", callsign, port, LongFreq, Mode); sprintf(Title, "New User %s", callsign); @@ -11742,303 +11762,258 @@ BOOL CheckforMIME(SocketConn * sockptr, char * Msg, char ** Body, int * MsgLen); #include #include -typedef struct _POPENRET -{ - FILE * fp; - pid_t pid; -} POPENRET; +// G8BPQ Version of Steve G7TAJ's code -/* -* Check if the PG is still running after 5 sec -* if so, kill it +int pgret = 9999; +int pindex = 0; + +void sigchild_handler(int sig , siginfo_t * siginfo, void * ucontext) +{ +/* • SIGCHLD fills in si_pid, si_uid, si_status, si_utime, and + si_stime, providing information about the child. The si_pid + field is the process ID of the child; si_uid is the child's + real user ID. The si_status field contains the exit status of + the child (if si_code is CLD_EXITED), or the signal number + that caused the process to change state. */ -void run_pgTimeoutThread( pid_t process ) -{ - - printf("watchdog thread: PID of subprocess: %d\n", process); - fflush(stdout); - Sleep(5000); - // if still running PID (?) then kill. - if ( getpgid(process) >= 0 ) - { - Debugprintf("watchdog thread: Still running, so killing %d ... ", process); - if ( kill( -process, SIGKILL ) == 0 ) - Debugprintf("Killed PG watchdog Process %d", process); - else - Debugprintf("Failed to kill PG watchdog Process %d", process); - } - - - Debugprintf("watchdog thread: PID=%d Exit", process); - fflush(stdout); - //return; +// printf("SIGCHLD PID %d Code %d status %d\n", siginfo->si_pid, siginfo->si_code, siginfo->si_status); + pgret = siginfo->si_status; } -//https://sources.debian.org/src/cron/3.0pl1-45/popen.c/ - -POPENRET my_popen(char *program, char *type, CIRCUIT *conn) +void run_pg(CIRCUIT * conn, struct UserInfo * user) { register char *cp; FILE *iop; int argc, pdes[2]; pid_t pid; - POPENRET PRET; - if (*type != 'r' && *type != 'w' || type[1]) - return(PRET); - if (pipe(pdes) < 0) - return(PRET); + pgret = 9999; + + int index = user->Temp->PG_INDEX; iop = NULL; - switch(pid = fork()) { + + conn->InputBuffer[conn->InputLen] = 0; + strlop(conn->InputBuffer, 13); + conn->InputLen = 0; + + if (!user->Temp->RUNPGPARAMS) + user->Temp->RUNPGPARAMS = (RUNPGARGS_PTR) zalloc(sizeof(RUNPGARGS)); + + user->Temp->RUNPGPARAMS->user = user; + user->Temp->RUNPGPARAMS->conn = conn; + strncpy(user->Temp->RUNPGPARAMS->InputBuffer, conn->InputBuffer, 80); // needs to be length of actual input! + user->Temp->RUNPGPARAMS->Len = conn->InputLen; + + if (conn == 0 || user == 0) + { + Debugprintf("run_pg conn or user null"); + return; + } + + // Build command line. Parmas are: + + // - Callsign (format as F6FBB-8). + // - Level number (0 is the first time, up to 99). + // - Flags of the user (binary number as user`s mask of INIT.SRV). + // - Record number of the user in INF.SYS. + // - Received data (each word is a new argument). + + // BPQ doesn't support params 3 and 4 (but may supply copy of user record later) + + char cmd[20]; + char *ptr = cmd; + char pg_dir[MAX_PATH]; + char log_file[50] = "pg.log"; + char call[10]; + char data[80]; + char line[80]; + size_t bufsize = 80; + + strcpy(pg_dir, BaseDir); + strcat(pg_dir, "/PG/"); + sprintf(cmd, "./%s", SERVERLIST[user->Temp->PG_SERVER][1] ); + + sprintf(line, "%s%s", pg_dir, SERVERLIST[user->Temp->PG_SERVER][1]); +// printf("PG Prog %s%s\n", pg_dir, SERVERLIST[user->Temp->PG_SERVER][1]); + + // check file exists and is executable + + if (access(line, F_OK) == -1 || access(line, X_OK) == -1) + { + Debugprintf("%s FileNotFound || not executable", line); + BBSputs(conn, "Error running PG Server\r"); + conn->InputMode=0; + SendPrompt(conn, user); + return; + } + + strcpy(call, conn->UserPointer->Call); + index = user->Temp->PG_INDEX; + + // remove ';' from input for security reasons + + ptr = strchr(user->Temp->RUNPGPARAMS->InputBuffer, ';'); + if (ptr) + *ptr = '\0'; + + sprintf(data, "%s %d 0 0 %s", call, index, user->Temp->RUNPGPARAMS->InputBuffer); +// printf("PG Params %s\n", data); + + conn->InputBufferLen = 0; + + char buf[256]; + + sprintf (buf, "%s %s", line, data); // buf is command to exec +// printf ("PG exec cmd %s\n", buf); + + // Create pipe for reading PG program STDOUT + + if (pipe(pdes) < 0) + { + Debugprintf("run_pg pipe failed"); + BBSputs(conn, "Error running PG Server (pipe() failed)\r"); + conn->InputMode=0; + SendPrompt(conn, user); + return; + } + + // We will just fork and execute program. For now don't create a new thread + + // Trap sigchild so we can tell when it exits and get return code + + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); + act.sa_flags = SA_RESETHAND | SA_SIGINFO; // Restore default handler when called + act.sa_sigaction = sigchild_handler; + sigaction(SIGCHLD, &act, NULL); + + switch(pid = fork()) + { case -1: /* error */ (void)close(pdes[0]); (void)close(pdes[1]); - return PRET; + Debugprintf("run_pg fork failed"); + BBSputs(conn, "Error running PG Server (fork() failed)\r"); + conn->InputMode=0; + SendPrompt(conn, user); + + return; + case 0: /* child */ - if (*type == 'r') { - if (pdes[1] != 1) { - dup2(pdes[1], 1); - dup2(pdes[1], 2); - (void)close(pdes[1]); - } - (void)close(pdes[0]); - } else { - if (pdes[0] != 0) { - dup2(pdes[0], 0); - (void)close(pdes[0]); - } + + if (pdes[1] != 1) + { + dup2(pdes[1], 1); + dup2(pdes[1], 2); (void)close(pdes[1]); } - setpgid(-pid,pid); - char *args[] = {"sh", "-c", program, NULL}; - execve("/bin/sh", args, NULL); + (void)close(pdes[0]); + + setpgid(0, pid); + + char *args[] = {"sh", "-c", buf, NULL}; + execve("/bin/sh", args, NULL); + _exit(1); } /* parent */ - _beginthread((void (*)(void *))run_pgTimeoutThread, 0, (VOID *) pid ); +// printf("child PID %d\n", pid); - if (*type == 'r') { - iop = fdopen(pdes[0], type); - (void)close(pdes[1]); - } else { - iop = fdopen(pdes[1], type); - (void)close(pdes[0]); + struct timespec duration; + duration.tv_sec = 5; + duration.tv_nsec = 0; + + nanosleep(&duration, &duration); // Will be interrupted by SIGCHLD + +// printf("PG retcode %d\n", pgret); + + if (pgret == 9999) // Process still running + { + BBSputs(conn, "PG Program Looping\r"); + kill(pid, SIGKILL); + user->Temp->PG_INDEX = 0; + conn->InputMode=0; + SendPrompt(conn, user); + return; } + if (pgret > 127) + { + // Probably killed by signal + + int err = pgret - 128; + char errmsg[256]; + + sprintf(errmsg, "PG Signal %s received\n", strsignal(err)); + + BBSputs(conn, errmsg); + user->Temp->PG_INDEX = 0; + conn->InputMode=0; + SendPrompt(conn, user); + return; + } + + // Send STDOUT from PG program to BBS user + + iop = fdopen(pdes[0], "r"); + (void)close(pdes[1]); + char buffer[128]; while (fgets(buffer, sizeof(buffer), iop) != NULL) { BBSputs(conn, buffer); buffer[0] = '\0'; } - PRET.fp = iop; - PRET.pid= pid; - return(PRET); -} - -int -my_pclose( POPENRET pret ) -{ - register int fdes; - sigset_t omask, mask; - int stat_loc; - pid_t pid; - FILE * iop = pret.fp; - - fdes = fileno(iop); - (void)fclose(iop); - - sigemptyset(&mask); - sigaddset(&mask, SIGQUIT); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &omask); - pid = waitpid(pret.pid, &stat_loc, 0); - sigprocmask(SIG_SETMASK, &omask, NULL); - if (pid == -1 || !WIFEXITED(stat_loc)) - return -1; - return stat_loc; -} - - -int run_server (char **cmd, int nb_cmd, int mode, char *log, char *pgdir, char *data, CIRCUIT * conn) -{ - int i; - int ret = 0; - FILE *fp; - POPENRET PRET; - pid_t pid; - char *ptr; - char file[256]; - char buf[256]; - char dir[256]; - char arg[256]; - - if (mode) - // sprintf (file, " >>%s", log); - // sprintf (file, " | tee -a %s", log); - sprintf(file, "" ); - else - sprintf (file, " InputMode=0; + SendPrompt(conn, user); + break; + case 1: + index++; // inc & keep in PG + break; - sprintf (dir, "cd %s ; ", pgdir); - } - else - *dir = '\0'; + case 2: + + index=0; // disconnect + conn->InputMode=0; + Disconnect(conn->BPQStream); + break; - *arg = '\0'; + case 3: + Debugprintf("data->BBS & end"); + break; - if (data) - { - /* remove ';' security reasons */ - ptr = strchr(data, ';'); - if (ptr) - *ptr = '\0'; + case 4: + Debugprintf("data->BBS and inc %d", pindex++); + break; + case 5: + Debugprintf("call no inc %d", pgret); + break; - sprintf (arg, " %s ", data); - } - - - for (i = 0; i < nb_cmd; i++) - { - /* remove ';' security reasons */ - ptr = strchr(cmd[i], ';'); - if (ptr) - *ptr = '\0'; - - sprintf (buf, "%s%s%s%s", dir, cmd[i], arg, file); - - PRET = my_popen (buf, "r", conn); - - if (PRET.fp == NULL) - Debugprintf ("Failed to run PG command %s\n", cmd[i] ); - - ret = my_pclose( PRET ); - ret = ret >> 8; - - if (verbose) { - Debugprintf ("Debug: command = {%s}\n", buf); - Debugprintf ("Debug: exit code = %d\n", ret); - } - - /* fail-safe bypass if executable isn't found (exit code 127) (was ret ==127)*/ - if (ret > 5) // should never be more than 5 - ret = 0; - } - return ( ret ); -} - - -void run_pg( CIRCUIT * conn, struct UserInfo * user ) -{ - - if (!user->Temp->RUNPGPARAMS) { - user->Temp->RUNPGPARAMS = (RUNPGARGS_PTR) zalloc(sizeof(RUNPGARGS)); - } - - user->Temp->RUNPGPARAMS->user = user; - user->Temp->RUNPGPARAMS->conn = conn; - strncpy(user->Temp->RUNPGPARAMS->InputBuffer, conn->InputBuffer, 80); // needs to be length of actual input! - user->Temp->RUNPGPARAMS->Len = conn->InputLen; - - if ( conn == 0 || user == 0 ) { - Debugprintf("run_pg null err"); - return; - } - - _beginthread((void (*)(void *))startrun_pgThread, 0, user->Temp->RUNPGPARAMS ); - - return; -} - - -void startrun_pgThread( RUNPGARGS_PTR Args ) { - - CIRCUIT * conn = Args->conn; - struct UserInfo * user = Args->user; - - char cmd[20]; - sprintf( cmd, "./%s", SERVERLIST[user->Temp->PG_SERVER][1] ); - char *ptr = cmd; - char pg_dir[MAX_PATH]; - char log_file[50] = "pg.log"; - char call[6]; - char data[80]; - char line[80]; - char *line_ptr = line; - int index; - char *data_ptr = data; - size_t bufsize = 80; - - strcpy(pg_dir, BaseDir); - strcat(pg_dir, "/PG/"); - - sprintf(line, "%s%s", pg_dir, SERVERLIST[user->Temp->PG_SERVER][1]); - - // check file exists and is executable - if (access(line, F_OK) == -1 || access(line, X_OK) == -1) { - Debugprintf("%s FileNotFound || Not EXE", line); - BBSputs(conn, "Error running PG Server\r"); + default: + BBSputs(conn, "PG unexexpected response\r"); + user->Temp->PG_INDEX = 0; conn->InputMode=0; SendPrompt(conn, user); return; } - strcpy( call, conn->UserPointer->Call); - // sprintf( log_file, "%s-%d.log", call, conn); - index = user->Temp->PG_INDEX; + user->Temp->PG_INDEX = index; - line[0] = '\0'; - int Len = Args->Len; - UCHAR * Msg = Args->InputBuffer; - strncpy( line, Msg, Len); - line[ Len - 1 ] = 0; //remove LF - - sprintf( data, "%s %d 0 0 %s", call, index, line); - - // clear the input queue - conn->InputLen = 0; - conn->InputBufferLen = 0; - - int ret = run_server (&ptr, 1, 1, log_file, pg_dir, data_ptr, conn); - - switch (ret) - { - case -1: // ERROR or forced closed - case 0: index=0; // Goodbye/Exit - conn->InputMode=0; - SendPrompt(conn, user); - break; - case 1: index++; // inc & keep in PG - break; - case 2: index=0; // disconnect - conn->InputMode=0; - Disconnect(conn->BPQStream); - break; - case 3: Debugprintf("data->BBS & end"); - break; - case 4: Debugprintf("data->BBS and inc %d", index++); - break; - case 5: Debugprintf("call no inc %d", ret); - break; - - } - - user->Temp->PG_INDEX=index; +// printf("runpg return index = %d\n", index); } + + /*---- G7TAJ END ----- */ #else @@ -12059,7 +12034,7 @@ void ReadFromPipe(void); void run_pg( CIRCUIT * conn, struct UserInfo * user ) { - // Run PG program, rend anything from program's stdout to the user + // Run PG program, read anything from program's stdout to the user int retcode = -1; SECURITY_ATTRIBUTES saAttr; @@ -12234,7 +12209,7 @@ void run_pg( CIRCUIT * conn, struct UserInfo * user ) case 4: - // Send Output to BBS - was down above + // Send Output to BBS - was done above break; case 5: @@ -12638,7 +12613,6 @@ VOID ProcessLine(CIRCUIT * conn, struct UserInfo * user, char* Buffer, int len) #endif return; } - if (_memicmp(Cmd, "Node", 4) == 0) { ExpandAndSendMessage(conn, SignoffMsg, LOG_BBS); @@ -15757,8 +15731,10 @@ VOID GetPGConfig() strcat(FN, "PG/PGList.txt"); if ((file = fopen(FN, "r")) == NULL) + { return; - + } + while(fgets(buf, 255, file) != NULL) { if ( buf[0] == '#') @@ -15785,6 +15761,7 @@ VOID GetPGConfig() break; } + NUM_SERVERS = n; fclose(file); diff --git a/BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user b/BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user deleted file mode 100644 index 0cd9a72..0000000 --- a/BPQChat.vcproj.LAPTOP-Q6S4RP5Q.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQChat.vcproj.SKIGACER.johnw.user b/BPQChat.vcproj.SKIGACER.johnw.user deleted file mode 100644 index b5b0536..0000000 --- a/BPQChat.vcproj.SKIGACER.johnw.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/BPQMail.aps b/BPQMail.aps index 694b39f..8e698f3 100644 Binary files a/BPQMail.aps and b/BPQMail.aps differ diff --git a/BPQMail.c b/BPQMail.c index 2ca2985..402d87f 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1133,6 +1133,11 @@ // Fix possible failure to update last listed count when user disconnects without using B command // Add short random delay (<30 secs) when forward new Messages immediately is enabled (35) // Fix Connect Script IDLETIME (38) +// Add "Mail Mgmt" to Webmail menu bar and "WebMail" to Mail Mgmt Menu (39) +// Improve "New User" frequency determination (39) +// Allow selection of 2 or 4 character country codes for forward processing (39) +// Fix Send P to multiple BBS's when routing on HR (40) +// Rewrite PG server code on Lunux (41) #include "bpqmail.h" #include "winstdint.h" @@ -1150,6 +1155,7 @@ FARPROCX pDllBPQTRACE; FARPROCZ pGetLOC; FARPROCX pRefreshWebMailIndex; FARPROCX pRunEventProgram; +FARPROCX pGetPortFrequency; BOOL WINE = FALSE; @@ -1924,6 +1930,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) pGetLOC = GetProcAddress(ExtDriver,"_GetLOC@0"); pRefreshWebMailIndex = GetProcAddress(ExtDriver,"_RefreshWebMailIndex@0"); pRunEventProgram = GetProcAddress(ExtDriver,"_RunEventProgram@8"); + pGetPortFrequency = GetProcAddress(ExtDriver,"_GetPortFrequency@8"); + if (pGetLOC) { diff --git a/BPQMail.rc b/BPQMail.rc index 75ae17f..440945c 100644 --- a/BPQMail.rc +++ b/BPQMail.rc @@ -387,16 +387,16 @@ BEGIN CONTROL "Warn if no route for P or T",IDC_WARNNOROUTE,"Button", BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | WS_TABSTOP,5,101,103,8 - LTEXT "Aliases",IDC_STATIC,5,144,57,13 - EDITTEXT IDC_ALIAS,4,162,99,81,ES_MULTILINE | ES_UPPERCASE | + LTEXT "Aliases",IDC_STATIC,5,165,57,13 + EDITTEXT IDC_ALIAS,4,183,99,81,ES_MULTILINE | ES_UPPERCASE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL CONTROL "Readdress Locally Input",IDC_READDRESSLOCAL,"Button", BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | - WS_DISABLED | WS_TABSTOP,4,246,97,8 + WS_DISABLED | WS_TABSTOP,4,267,97,8 CONTROL "Readdress Received",IDC_READDRESSRXED,"Button", BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | - WS_DISABLED | WS_TABSTOP,4,260,97,8 + WS_DISABLED | WS_TABSTOP,4,281,97,8 GROUPBOX "Per-BBS Params",IDC_STATIC,121,33,326,263 LTEXT "BBS",IDC_STATIC,128,46,57,10 COMBOBOX IDC_BBS,122,59,50,60,CBS_SIMPLE | CBS_OEMCONVERT | @@ -471,6 +471,9 @@ BEGIN WS_TABSTOP,5,130,103,8 LTEXT "Incoming Connect Timeout",IDC_STATIC,125,278,95,12 EDITTEXT IDC_CONTIMEOUT,219,276,22,12,ES_AUTOHSCROLL + CONTROL "Use 4 Char Continent Codes",IDC_FOURCHARCONTINENT, + "Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_MULTILINE | + WS_TABSTOP,6,146,103,8 END IDD_USERADDED_BOX DIALOG DISCARDABLE 176, 132, 129, 68 diff --git a/BPQMail.sln b/BPQMail.sln new file mode 100644 index 0000000..8861280 --- /dev/null +++ b/BPQMail.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQMail", "BPQMail.vcproj", "{3766AA10-C777-4ED8-A83D-F1452DE9B665}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.ActiveCfg = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.Build.0 = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BPQMail.vcxproj.user b/BPQMail.vcxproj.user deleted file mode 100644 index 6e2aec7..0000000 --- a/BPQMail.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/BPQMailConfig.c b/BPQMailConfig.c index 594881a..06aec1d 100644 --- a/BPQMailConfig.c +++ b/BPQMailConfig.c @@ -1867,6 +1867,7 @@ VOID SaveFWDConfig(HWND hDlg) MaxRXSize = GetDlgItemInt(hDlg, IDC_MAXRECV, &OK, FALSE); MaxAge = GetDlgItemInt(hDlg, IDC_MAXAGE, &OK, FALSE); SendPtoMultiple = IsDlgButtonChecked(hDlg, IDC_MULTIP); + FOURCHARCONT = IsDlgButtonChecked(hDlg, IDC_FOURCHARCONTINENT); // Reinitialise Aliases @@ -3249,6 +3250,7 @@ INT_PTR CALLBACK FwdEditDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARA CheckDlgButton(hDlg, IDC_WARNNOROUTE, WarnNoRoute); CheckDlgButton(hDlg, IDC_USELOCALTIME, Localtime); CheckDlgButton(hDlg, IDC_MULTIP, SendPtoMultiple); + CheckDlgButton(hDlg, IDC_FOURCHARCONTINENT, FOURCHARCONT); CurrentBBS = NULL; diff --git a/BPQMailrc.h b/BPQMailrc.h index 750d898..8b29d46 100644 --- a/BPQMailrc.h +++ b/BPQMailrc.h @@ -319,6 +319,7 @@ #define ID_MULTICAST 40024 #define IDC_DEFAULTNOWINLINK 41001 #define IDC_MULTIP 41002 +#define IDC_FOURCHARCONTINENT 41003 // Next default values for new objects // diff --git a/Bpq32.c b/Bpq32.c index d333e5a..d98b6ea 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1217,6 +1217,12 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Fix potential buffer overflow in Telnet login (36) // Allow longer serial device names (37) // Fix ICF8101 Mode setting (37) +// Kill link if we are getting repeated RR(F) after timeout +// (Indicating other station is seeing our RR(P) but not the resent I frame) (40) +// Change default of SECURETELNET to 1 (41) +// Add optional ATTACH time limit for ARDOP (42) +// Fix buffer overflow risk in HTTP Terminal(42) + #define CKernel @@ -1310,6 +1316,7 @@ void * KISSHFExtInit(EXTPORTDATA * PortEntry); void * WinRPRExtInit(EXTPORTDATA * PortEntry); void * HSMODEMExtInit(EXTPORTDATA * PortEntry); void * FreeDataExtInit(EXTPORTDATA * PortEntry); +void * SIXPACKExtInit(EXTPORTDATA * PortEntry); extern char * ConfigBuffer; // Config Area VOID REMOVENODE(dest_list * DEST); @@ -3947,6 +3954,9 @@ VOID * InitializeExtDriver(PEXTPORTDATA PORTVEC) if (strstr(Value, "FREEDATA")) return FreeDataExtInit; + if (strstr(Value, "6PACK")) + return SIXPACKExtInit; + ExtDriver = LoadLibrary(Value); if (ExtDriver == NULL) diff --git a/CBPQ32.vcproj b/CBPQ32.vcproj index 0648ae6..a580f7a 100644 --- a/CBPQ32.vcproj +++ b/CBPQ32.vcproj @@ -57,7 +57,7 @@ UsePrecompiledHeader="0" AssemblerOutput="2" AssemblerListingLocation="c:\devprogs\bpq32\listings\debug\" - BrowseInformation="0" + BrowseInformation="1" WarningLevel="3" Detect64BitPortabilityProblems="false" DebugInformationFormat="4" @@ -234,6 +234,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + diff --git a/CBPQ32.vcproj.NOTTSDESKTOP.John-notpi4-64.user b/CBPQ32.vcproj.NOTTSDESKTOP.John-notpi4-64.user deleted file mode 100644 index f4ba73a..0000000 --- a/CBPQ32.vcproj.NOTTSDESKTOP.John-notpi4-64.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user b/CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user deleted file mode 100644 index 03fb73a..0000000 --- a/CBPQ32.vcproj.SKIGACER.johnw-notpi4-64.user +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - diff --git a/CBPQ32.vcproj.SKIGACER.johnw.user b/CBPQ32.vcproj.SKIGACER.johnw.user index 03fb73a..f8a6101 100644 --- a/CBPQ32.vcproj.SKIGACER.johnw.user +++ b/CBPQ32.vcproj.SKIGACER.johnw.user @@ -37,7 +37,7 @@ Name="Release|Win32" > RIGPort) TNC = TNCInfo[PORT->RIGPort]; @@ -5089,6 +5088,8 @@ void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) int len; char * ptr; char mhstr[400]; + int i; + char c; if (MH == NULL) return; @@ -5110,7 +5111,16 @@ void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) continue; } - Normcall[len++] = 0; + // validate call to prevent corruption of json + + for (i=0; i < len; i++) + { + c = Normcall[i]; + + if (!isalnum(c) && !(c == '#') && !(c == ' ') && !(c == '-')) + goto skipit; + } + //format TIME @@ -5123,7 +5133,7 @@ void BuildPortMH(char * MHJSON, struct PORTCONTROL * PORT) Normcall, PORT->PORTNUMBER, MH->MHCOUNT, MHTIME); strcat( MHJSON, mhstr ); - +skipit: MH++; } } diff --git a/ConfigWinRPR.vcxproj.user b/ConfigWinRPR.vcxproj.user deleted file mode 100644 index 6e2aec7..0000000 --- a/ConfigWinRPR.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/HFCommon.c b/HFCommon.c index 00af093..c5f639a 100644 --- a/HFCommon.c +++ b/HFCommon.c @@ -1876,6 +1876,8 @@ int standardParams(struct TNCINFO * TNC, char * buf) TNC->WL2K = DecodeWL2KReportLine(buf); else if (_memicmp(buf, "SESSIONTIMELIMIT", 16) == 0) TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit = atoi(&buf[17]) * 60; + else if (_memicmp(buf, "ATTACHTIMELIMIT", 15) == 0) + TNC->AttachTimeLimit = atoi(&buf[16]) * 60; else if (_memicmp(buf, "BUSYHOLD", 8) == 0) // Hold Time for Busy Detect TNC->BusyHold = atoi(&buf[8]); else if (_memicmp(buf, "BUSYWAIT", 8) == 0) // Wait time before failing connect if busy diff --git a/HTTPcode.c b/HTTPcode.c index 367146d..e1ddfbe 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -600,7 +600,8 @@ VOID HTTPTimer() for (n = Last;;) { - strcat(_REPLYBUFFER, Session->ScreenLines[n]); + if ((strlen(Session->ScreenLines[n]) + strlen(_REPLYBUFFER)) < 99999) + strcat(_REPLYBUFFER, Session->ScreenLines[n]); if (n == 99) n = -1; @@ -680,13 +681,15 @@ struct HTTPConnectionInfo * FindSession(char * Key) void ProcessTermInput(SOCKET sock, char * MsgPtr, int MsgLen, char * Key) { - char _REPLYBUFFER[1024]; + char _REPLYBUFFER[2048]; int ReplyLen; char Header[256]; int HeaderLen; int State; struct HTTPConnectionInfo * Session = FindSession(Key); int Stream; + int maxlen = 1000; + if (Session == NULL) { @@ -701,12 +704,24 @@ void ProcessTermInput(SOCKET sock, char * MsgPtr, int MsgLen, char * Key) char c; UCHAR hex; + int msglen = end - input; + struct TNCINFO * TNC = Session->TNC; struct TCPINFO * TCP = 0; if (TNC) TCP = TNC->TCPInfo; + if (TCP && TCP->WebTermCSS) + maxlen -= strlen(TCP->WebTermCSS); + + if (MsgLen > maxlen) + { + Session->KillTimer = 99999; // close session + return; + } + + if (TCP && TCP->WebTermCSS) ReplyLen = sprintf(_REPLYBUFFER, InputLine, Key, TCP->WebTermCSS); else diff --git a/LinBPQ.c b/LinBPQ.c index 6146500..27dc550 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -1077,216 +1077,211 @@ int main(int argc, char * argv[]) BBSApplMask = 1<<(BBSApplNum-1); - // See if we need to warn of possible problem with BaseDir moved by installer + // See if we need to warn of possible problem with BaseDir moved by installer - sprintf(BaseDir, "%s", BPQDirectory); + sprintf(BaseDir, "%s", BPQDirectory); - // Set up file and directory names + // Set up file and directory names - strcpy(UserDatabasePath, BaseDir); - strcat(UserDatabasePath, "/"); - strcat(UserDatabasePath, UserDatabaseName); + strcpy(UserDatabasePath, BaseDir); + strcat(UserDatabasePath, "/"); + strcat(UserDatabasePath, UserDatabaseName); - strcpy(MsgDatabasePath, BaseDir); - strcat(MsgDatabasePath, "/"); - strcat(MsgDatabasePath, MsgDatabaseName); + strcpy(MsgDatabasePath, BaseDir); + strcat(MsgDatabasePath, "/"); + strcat(MsgDatabasePath, MsgDatabaseName); - strcpy(BIDDatabasePath, BaseDir); - strcat(BIDDatabasePath, "/"); - strcat(BIDDatabasePath, BIDDatabaseName); + strcpy(BIDDatabasePath, BaseDir); + strcat(BIDDatabasePath, "/"); + strcat(BIDDatabasePath, BIDDatabaseName); - strcpy(WPDatabasePath, BaseDir); - strcat(WPDatabasePath, "/"); - strcat(WPDatabasePath, WPDatabaseName); + strcpy(WPDatabasePath, BaseDir); + strcat(WPDatabasePath, "/"); + strcat(WPDatabasePath, WPDatabaseName); - strcpy(BadWordsPath, BaseDir); - strcat(BadWordsPath, "/"); - strcat(BadWordsPath, BadWordsName); + strcpy(BadWordsPath, BaseDir); + strcat(BadWordsPath, "/"); + strcat(BadWordsPath, BadWordsName); - strcpy(NTSAliasesPath, BaseDir); - strcat(NTSAliasesPath, "/"); - strcat(NTSAliasesPath, NTSAliasesName); + strcpy(NTSAliasesPath, BaseDir); + strcat(NTSAliasesPath, "/"); + strcat(NTSAliasesPath, NTSAliasesName); - strcpy(MailDir, BaseDir); - strcat(MailDir, "/"); - strcat(MailDir, "Mail"); + strcpy(MailDir, BaseDir); + strcat(MailDir, "/"); + strcat(MailDir, "Mail"); #ifdef WIN32 - CreateDirectory(MailDir, NULL); // Just in case + CreateDirectory(MailDir, NULL); // Just in case #else - mkdir(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); - chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); + mkdir(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); + chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO); #endif - // Make backup copies of Databases + // Make backup copies of Databases -// CopyConfigFile(ConfigName); + // CopyConfigFile(ConfigName); - CopyBIDDatabase(); - CopyMessageDatabase(); - CopyUserDatabase(); - CopyWPDatabase(); + CopyBIDDatabase(); + CopyMessageDatabase(); + CopyUserDatabase(); + CopyWPDatabase(); - SetupMyHA(); - SetupFwdAliases(); - SetupNTSAliases(NTSAliasesPath); + SetupMyHA(); + SetupFwdAliases(); + SetupNTSAliases(NTSAliasesPath); - GetWPDatabase(); + GetWPDatabase(); - GetMessageDatabase(); - GetUserDatabase(); - GetBIDDatabase(); - GetBadWordFile(); - GetHTMLForms(); - GetPGConfig(); + GetMessageDatabase(); + GetUserDatabase(); + GetBIDDatabase(); + GetBadWordFile(); + GetHTMLForms(); + GetPGConfig(); - // Make sure there is a user record for the BBS, with BBS bit set. + // Make sure there is a user record for the BBS, with BBS bit set. - user = LookupCall(BBSName); + user = LookupCall(BBSName); - if (user == NULL) - { - user = AllocateUserRecord(BBSName); - user->Temp = zalloc(sizeof (struct TempUserInfo)); - } - - if ((user->flags & F_BBS) == 0) - { - // Not Defined as a BBS - - if(SetupNewBBS(user)) - user->flags |= F_BBS; - } - - // if forwarding AMPR mail make sure User/BBS AMPR exists - - if (SendAMPRDirect) - { - BOOL NeedSave = FALSE; - - user = LookupCall("AMPR"); - if (user == NULL) { - user = AllocateUserRecord("AMPR"); + user = AllocateUserRecord(BBSName); user->Temp = zalloc(sizeof (struct TempUserInfo)); - NeedSave = TRUE; } if ((user->flags & F_BBS) == 0) { // Not Defined as a BBS - if (SetupNewBBS(user)) + if(SetupNewBBS(user)) user->flags |= F_BBS; - NeedSave = TRUE; } - if (NeedSave) - SaveUserDatabase(); - } + // if forwarding AMPR mail make sure User/BBS AMPR exists - - // Make sure SYSOPCALL is set - - if (SYSOPCall[0] == 0) - strcpy(SYSOPCall, BBSName); - - // See if just want to add user (mainly for setup scripts) - - if (argc == 5 && _stricmp(argv[1], "--adduser") == 0) - { - BOOL isBBS = FALSE; - char * response; - - if (_stricmp(argv[4], "TRUE") == 0) - isBBS = TRUE; - - printf("Adding User %s\r\n", argv[2]); - response = AddUser(argv[2], argv[3], isBBS); - printf("%s", response); - exit(0); - } - // Allocate Streams - - strcpy(pgm, "BBS"); - - for (i=0; i < MaxStreams; i++) - { - conn = &Connections[i]; - conn->BPQStream = FindFreeStream(); - - if (conn->BPQStream == 255) break; - - NumberofStreams++; - -// BPQSetHandle(conn->BPQStream, hWnd); - - SetAppl(conn->BPQStream, (i == 0 && EnableUI) ? 0x82 : 2, BBSApplMask); - Disconnect(conn->BPQStream); - } - - strcpy(pgm, "LINBPQ"); - - Debugprintf("POP3 Debug Before Init TCP Timer = %d", POP3Timer); - - InitialiseTCP(); - Debugprintf("POP3 Debug Before Init NNTP Timer = %d", POP3Timer); - InitialiseNNTP(); - - SetupListenSet(); // Master set of listening sockets - - if (EnableUI || MailForInterval) - SetupUIInterface(); - - if (MailForInterval) - _beginthread(SendMailForThread, 0, 0); - - - // Calulate time to run Housekeeping - { - struct tm *tm; - time_t now; - - now = time(NULL); - - tm = gmtime(&now); - - tm->tm_hour = MaintTime / 100; - tm->tm_min = MaintTime % 100; - tm->tm_sec = 0; - - MaintClock = mktime(tm) - (time_t)_MYTIMEZONE; - - while (MaintClock < now) - MaintClock += MaintInterval * 3600; - - Debugprintf("Maint Clock %lld NOW %lld Time to HouseKeeping %lld", (long long)MaintClock, (long long)now, (long long)(MaintClock - now)); - - if (LastHouseKeepingTime) + if (SendAMPRDirect) { - if ((now - LastHouseKeepingTime) > MaintInterval * 3600) + BOOL NeedSave = FALSE; + + user = LookupCall("AMPR"); + + if (user == NULL) { - DoHouseKeeping(FALSE); + user = AllocateUserRecord("AMPR"); + user->Temp = zalloc(sizeof (struct TempUserInfo)); + NeedSave = TRUE; } + + if ((user->flags & F_BBS) == 0) + { + // Not Defined as a BBS + + if (SetupNewBBS(user)) + user->flags |= F_BBS; + NeedSave = TRUE; + } + + if (NeedSave) + SaveUserDatabase(); } - for (i = optind; i < argc; i++) + + + // Make sure SYSOPCALL is set + + if (SYSOPCall[0] == 0) + strcpy(SYSOPCall, BBSName); + + // See if just want to add user (mainly for setup scripts) + + if (argc == 5 && _stricmp(argv[1], "--adduser") == 0) { - if (_stricmp(argv[i], "tidymail") == 0) - DeleteRedundantMessages(); + BOOL isBBS = FALSE; + char * response; - if (_stricmp(argv[i], "nohomebbs") == 0) - DontNeedHomeBBS = TRUE; + if (_stricmp(argv[4], "TRUE") == 0) + isBBS = TRUE; + + printf("Adding User %s\r\n", argv[2]); + response = AddUser(argv[2], argv[3], isBBS); + printf("%s", response); + exit(0); + } + // Allocate Streams + + strcpy(pgm, "BBS"); + + for (i=0; i < MaxStreams; i++) + { + conn = &Connections[i]; + conn->BPQStream = FindFreeStream(); + + if (conn->BPQStream == 255) break; + + NumberofStreams++; + + // BPQSetHandle(conn->BPQStream, hWnd); + + SetAppl(conn->BPQStream, (i == 0 && EnableUI) ? 0x82 : 2, BBSApplMask); + Disconnect(conn->BPQStream); } - printf("Mail Started\n"); - Logprintf(LOG_BBS, NULL, '!', "Mail Starting"); + strcpy(pgm, "LINBPQ"); - } - } + InitialiseTCP(); + InitialiseNNTP(); - Debugprintf("POP3 Debug After Mail Init Timer = %d", POP3Timer); + SetupListenSet(); // Master set of listening sockets + + if (EnableUI || MailForInterval) + SetupUIInterface(); + + if (MailForInterval) + _beginthread(SendMailForThread, 0, 0); + + + // Calulate time to run Housekeeping + { + struct tm *tm; + time_t now; + + now = time(NULL); + + tm = gmtime(&now); + + tm->tm_hour = MaintTime / 100; + tm->tm_min = MaintTime % 100; + tm->tm_sec = 0; + + MaintClock = mktime(tm) - (time_t)_MYTIMEZONE; + + while (MaintClock < now) + MaintClock += MaintInterval * 3600; + + Debugprintf("Maint Clock %lld NOW %lld Time to HouseKeeping %lld", (long long)MaintClock, (long long)now, (long long)(MaintClock - now)); + + if (LastHouseKeepingTime) + { + if ((now - LastHouseKeepingTime) > MaintInterval * 3600) + { + DoHouseKeeping(FALSE); + } + } + for (i = optind; i < argc; i++) + { + if (_stricmp(argv[i], "tidymail") == 0) + DeleteRedundantMessages(); + + if (_stricmp(argv[i], "nohomebbs") == 0) + DontNeedHomeBBS = TRUE; + } + + printf("Mail Started\n"); + Logprintf(LOG_BBS, NULL, '!', "Mail Starting"); + + } + } if (NUMBEROFTNCPORTS) InitializeTNCEmulator(); diff --git a/MHSave.txt b/MHSave.txt new file mode 100644 index 0000000..e69de29 diff --git a/MailNode.vcxproj.user b/MailNode.vcxproj.user deleted file mode 100644 index 3ea46b0..0000000 --- a/MailNode.vcxproj.user +++ /dev/null @@ -1,8 +0,0 @@ - - - - c:\linbpq\linbpq.exe - c:\linbpq - WindowsLocalDebugger - - \ No newline at end of file diff --git a/MailRouting.c b/MailRouting.c index 6916f2c..ff6feca 100644 --- a/MailRouting.c +++ b/MailRouting.c @@ -29,9 +29,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Bulls should not be distributed outside their designated area. -// Use 4 char continent codes if this isn't defined +// Use 4 char continent codes if this is set -#define TWOCHARCONT +int FOURCHARCONT = 0; #include "bpqmail.h" @@ -71,266 +71,266 @@ struct Country struct Continent Continents[] = { - "EURO", "EU", // Europe - "MEDR", "EU", // Mediterranean - "ASIA", "AS", // The Orient - "INDI", "AS", // Indian Ocean including the Indian subcontinent - "MDLE", "AS", // Middle East - "SEAS", "AS", // South-East Asia - "NOAM", "NA", // North America (Canada, USA, Mexico) - "CEAM", "NA", // Central America - "CARB", "NA", // Caribbean - "SOAM", "SA", // South America - "AUNZ", "OC", // Australia/New Zealand - "EPAC", "OC", // Eastern Pacific - "NPAC", "OC", // Northern Pacific - "SPAC", "OC", // Southern Pacific - "WPAC", "OC", // Western Pacific - "NAFR", "AF", // Northern Africa - "CAFR", "AF", // Central Africa - "SAFR", "AF", // Southern Africa - "ANTR", "OC", // Antarctica - "MARS", "MARS", // Special for MARS network + "EURO", "EU", // Europe + "MEDR", "EU", // Mediterranean + "ASIA", "AS", // The Orient + "INDI", "AS", // Indian Ocean including the Indian subcontinent + "MDLE", "AS", // Middle East + "SEAS", "AS", // South-East Asia + "NOAM", "NA", // North America (Canada, USA, Mexico) + "CEAM", "NA", // Central America + "CARB", "NA", // Caribbean + "SOAM", "SA", // South America + "AUNZ", "OC", // Australia/New Zealand + "EPAC", "OC", // Eastern Pacific + "NPAC", "OC", // Northern Pacific + "SPAC", "OC", // Southern Pacific + "WPAC", "OC", // Western Pacific + "NAFR", "AF", // Northern Africa + "CAFR", "AF", // Central Africa + "SAFR", "AF", // Southern Africa + "ANTR", "OC", // Antarctica + "MARS", "MARS", // Special for MARS network }; struct Country Countries[] = { - "AFG", "****", "AS", // Afghanistan - "ALA", "EURO", "EU", // Åland Islands - "ALB", "EURO", "EU", // Albania - "DZA", "NAFR", "AF", // Algeria - "ASM", "****", "AS", // American Samoa - "AND", "EURO", "EU", // Andorra - "AGO", "CAFR", "AF", // Angola - "AIA", "CARB", "NA", // Anguilla - "ATG", "CARB", "NA", // Antigua and Barbuda - "ARG", "SOAM", "SA", // Argentina - "ARM", "****", "AS", // Armenia - "ABW", "CARB", "NA", // Aruba - "AUS", "AUNZ", "OC", // Australia - "AUT", "EURO", "EU", // Austria - "AZE", "****", "AS", // Azerbaijan - "BHS", "CARB", "NA", // Bahamas - "BHR", "MDLE", "AS", // Bahrain - "BGD", "INDE", "AS", // Bangladesh - "BRB", "CARB", "NA", // Barbados - "BLR", "EURO", "EU", // Belarus - "BEL", "EURO", "EU", // Belgium - "BLZ", "CEAM", "NA", // Belize - "BEN", "CAFR", "AF", // Benin - "BMU", "CARB", "NA", // Bermuda - "BTN", "ASIA", "AS", // Bhutan - "BOL", "SOAM", "SA", // Bolivia (Plurinational State of) - "BIH", "EURO", "EU", // Bosnia and Herzegovina - "BWA", "****", "AF", // Botswana - "BRA", "SOAM", "SA", // Brazil - "VGB", "CARB", "NA", // British Virgin Islands - "BRN", "ASIA", "AS", // Brunei Darussalam - "BGR", "EURO", "EU", // Bulgaria - "BFA", "CAFR", "AF", // Burkina Faso - "BDI", "CAFR", "AF", // Burundi - "KHM", "****", "AS", // Cambodia - "CMR", "CAFR", "AF", // Cameroon - "CAN", "NOAM", "NA", // Canada - "CPV", "NAFR", "AF", // Cape Verde - "CYM", "CARB", "NA", // Cayman Islands - "CAF", "CAFR", "AF", // Central African Republic - "TCD", "CAFR", "AF", // Chad - "CHL", "SOAM", "SA", // Chile - "CHN", "****", "AS", // China - "HKG", "****", "AS", // Hong Kong Special Administrative Region of China - "MAC", "****", "AS", // Macao Special Administrative Region of China - "COL", "****", "SA", // Colombia - "COM", "SAFR", "AF", // Comoros - "COG", "****", "AF", // Congo - "COK", "SPAC", "OC", // Cook Islands - "CRI", "CEAM", "NA", // Costa Rica - "CIV", "CAFR", "AF", // Côte d'Ivoire - "HRV", "EURO", "EU", // Croatia - "CUB", "CARB", "NA", // Cuba - "CYP", "EURO", "EU", // Cyprus - "CZE", "EURO", "EU", // Czech Republic - "PRK", "****", "AS", // Democratic People's Republic of Korea - "COD", "****", "AF", // Democratic Republic of the Congo - "DNK", "EURO", "EU", // Denmark - "DJI", "NAFR", "AF", // Djibouti - "DMA", "CARB", "NA", // Dominica - "DOM", "CARB", "NA", // Dominican Republic - "ECU", "SOAM", "SA", // Ecuador - "EGY", "MDLE", "AF", // Egypt - "SLV", "CEAM", "NA", // El Salvador - "GNQ", "CAFR", "AF", // Equatorial Guinea - "ERI", "****", "AF", // Eritrea - "EST", "EURO", "EU", // Estonia - "ETH", "****", "AF", // Ethiopia - "FRO", "EURO", "EU", // Faeroe Islands - "FLK", "SOAM", "SA", // Falkland Islands (Malvinas) - "FJI", "SPAC", "OC", // Fiji - "FIN", "EURO", "EU", // Finland - "FRA", "EURO", "EU", // France - "GUF", "SOAM", "SA", // French Guiana - "PYF", "SPAC", "OC", // French Polynesia - "GAB", "CAFR", "AF", // Gabon - "GMB", "CAFR", "AF", // Gambia - "GEO", "ASIA", "AS", // Georgia - "DEU", "EURO", "EU", // Germany - "GHA", "CAFR", "AF", // Ghana - "GIB", "EURO", "EU", // Gibraltar - "GRC", "EURO", "EU", // Greece - "GRL", "EURO", "EU", // Greenland - "GRD", "CARB", "NA", // Grenada - "GLP", "CARB", "NA", // Guadeloupe - "GUM", "SPAC", "OC", // Guam - "GTM", "CEAM", "NA", // Guatemala - "GGY", "EURO", "EU", // Guernsey - "GIN", "CAFR", "AF", // Guinea - "GNB", "CAFR", "AF", // Guinea-Bissau - "GUY", "SOAM", "SA", // Guyana - "HTI", "CARB", "NA", // Haiti - "VAT", "EURO", "EU", // Holy See - "HND", "CEAM", "NA", // Honduras - "HUN", "EURO", "EU", // Hungary - "ISL", "EURO", "EU", // Iceland - "IND", "INDI", "AS", // India - "IDN", "****", "AS", // Indonesia - "IRN", "MDLE", "AS", // Iran (Islamic Republic of) - "IRQ", "MDLE", "AS", // Iraq - "IRL", "EURO", "EU", // Ireland - "IMN", "EURO", "EU", // Isle of Man - "ISR", "MDLE", "AS", // Israel - "ITA", "EURO", "EU", // Italy - "JAM", "CEAM", "NA", // Jamaica - "JPN", "****", "AS", // Japan - "JEY", "EURO", "EU", // Jersey - "JOR", "MDLE", "AS", // Jordan - "KAZ", "****", "AS", // Kazakhstan - "KEN", "****", "AF", // Kenya - "KIR", "EPAC", "OC", // Kiribati - "KWT", "MDLE", "AS", // Kuwait - "KGZ", "ASIA", "AS", // Kyrgyzstan - "LAO", "ASIA", "AS", // Lao People's Democratic Republic - "LVA", "EURO", "EU", // Latvia - "LBN", "MDLE", "AS", // Lebanon - "LSO", "SAFR", "AF", // Lesotho - "LBR", "CAFR", "AF", // Liberia - "LBY", "MDLE", "AS", // Libyan Arab Jamahiriya - "LIE", "EURO", "EU", // Liechtenstein - "LTU", "EURO", "EU", // Lithuania - "LUX", "EURO", "EU", // Luxembourg - "MDG", "SAFR", "AF", // Madagascar - "MWI", "SAFR", "AF", // Malawi - "MYS", "ASIA", "AS", // Malaysia - "MDV", "INDI", "AS", // Maldives - "MLI", "CAFR", "AF", // Mali - "MLT", "EURO", "EU", // Malta - "MHL", "WPAC", "OC", // Marshall Islands - "MTQ", "CARB", "NA", // Martinique - "MRT", "NAFR", "AF", // Mauritania - "MUS", "SAFR", "AF", // Mauritius - "MYT", "SAFR", "AF", // Mayotte - "MEX", "****", "NA", // Mexico - "FSM", "WPAC", "OC", // Micronesia (Federated States of) - "MCO", "EURO", "EU", // Monaco - "MNG", "****", "AS", // Mongolia - "MNE", "EURO", "EU", // Montenegro - "MSR", "CARB", "NA", // Montserrat - "MAR", "NAFR", "AF", // Morocco - "MOZ", "SAFR", "AF", // Mozambique - "MMR", "ASIA", "AS", // Myanmar - "NAM", "****", "AF", // Namibia - "NRU", "WPAC", "OC", // Nauru - "NPL", "****", "AS", // Nepal - "NLD", "EURO", "EU", // Netherlands - "ANT", "CARB", "NA", // Netherlands Antilles - "NCL", "SPAC", "OC", // New Caledonia - "NZL", "AUNZ", "OC", // New Zealand - "NIC", "****", "SA", // Nicaragua - "NER", "NAFR", "AF", // Niger - "NGA", "****", "AF", // Nigeria - "NIU", "SPAC", "OC", // Niue - "NFK", "SPAC", "OC", // Norfolk Island - "MNP", "WPAC", "OC", // Northern Mariana Islands - "NOR", "EURO", "EU", // Norway - "PSE", "MDLE", "AS", // Occupied Palestinian Territory - "OMN", "MDLE", "AS", // Oman - "PAK", "INDI", "AS", // Pakistan - "PLW", "SPAC", "OC", // Palau - "PAN", "CEAM", "SA", // Panama - "PNG", "SPAC", "OC", // Papua New Guinea - "PRY", "SOAM", "SA", // Paraguay - "PER", "SOAM", "SA", // Peru - "PHL", "ASIA", "AS", // Philippines - "PCN", "SPAC", "OC", // Pitcairn - "POL", "EURO", "EU", // Poland - "PRT", "EURO", "EU", // Portugal - "PRI", "CARB", "NA", // Puerto Rico - "QAT", "MDLE", "AS", // Qatar - "KOR", "ASIA", "AS", // Republic of Korea - "MDA", "EURO", "EU", // Republic of Moldova - "REU", "SAFR", "AF", // Réunion - "ROU", "EURO", "EU", // Romania - "RUS", "ASIA", "AS", // Russian Federation - "RWA", "****", "AF", // Rwanda - "BLM", "CARB", "NA", // Saint-Barthélemy - "SHN", "SOAM", "SA", // Saint Helena - "KNA", "CARB", "NA", // Saint Kitts and Nevis - "LCA", "CARB", "NA", // Saint Lucia - "MAF", "CARB", "NA", // Saint-Martin (French part) - "SPM", "NOAM", "NA", // Saint Pierre and Miquelon - "VCT", "CARB", "NA", // Saint Vincent and the Grenadines - "WSM", "SPAC", "OC", // Samoa - "SMR", "EURO", "EU", // San Marino - "STP", "CAFR", "AF", // Sao Tome and Principe - "SAU", "MDLE", "AS", // Saudi Arabia - "SEN", "CAFR", "AF", // Senegal - "SRB", "EURO", "EU", // Serbia - "SYC", "SAFR", "AF", // Seychelles - "SLE", "****", "AF", // Sierra Leone - "SGP", "****", "AS", // Singapore - "SVK", "EURO", "EU", // Slovakia - "SVN", "EURO", "EU", // Slovenia - "SLB", "SPAC", "OC", // Solomon Islands - "SOM", "****", "AF", // Somalia - "ZAF", "SAFR", "AF", // South Africa - "ESP", "EURO", "EU", // Spain - "LKA", "INDE", "AS", // Sri Lanka - "SDN", "****", "AF", // Sudan - "SUR", "SOAM", "SA", // Suriname - "SJM", "EURO", "EU", // Svalbard and Jan Mayen Islands - "SWZ", "****", "AF", // Swaziland - "SWE", "EURO", "EU", // Sweden - "CHE", "EURO", "EU", // Switzerland - "SYR", "MDLE", "AS", // Syrian Arab Republic - "TJK", "ASIA", "AS", // Tajikistan - "THA", "****", "AS", // Thailand - "MKD", "EURO", "EU", // The former Yugoslav Republic of Macedonia - "TLS", "ASIA", "AS", // Timor-Leste - "TGO", "CAFR", "AF", // Togo - "TKL", "AUNZ", "OC", // Tokelau - "TON", "SPAC", "OC", // Tonga - "TTO", "CARB", "NA", // Trinidad and Tobago - "TUN", "****", "AF", // Tunisia - "TUR", "EURO", "EU", // Turkey - "TKM", "****", "AS", // Turkmenistan - "TCA", "CARB", "NA", // Turks and Caicos Islands - "TUV", "SPAC", "OC", // Tuvalu - "UGA", "****", "AF", // Uganda - "UKR", "EURO", "EU", // Ukraine - "ARE", "MDLE", "AS", // United Arab Emirates - "GBR", "EURO", "EU", // United Kingdom of Great Britain and Northern Ireland - "TZA", "****", "AF", // United Republic of Tanzania - "USA", "NOAM", "NA", // United States of America - "VIR", "CARB", "NA", // United States Virgin Islands - "URY", "SOAM", "SA", // Uruguay - "UZB", "ASIA", "AS", // Uzbekistan - "VUT", "SPAC", "OC", // Vanuatu - "VEN", "SOAM", "SA", // Venezuela (Bolivarian Republic of) - "VNM", "****", "AS", // Viet Nam - "WLF", "SPAC", "OC", // Wallis and Futuna Islands - "ESH", "****", "AF", // Western Sahara - "YEM", "****", "AF", // Yemen - "ZMB", "SAFR", "AF", // Zambia - "ZWE", "SAFR", "AF" // Zimbabwe + "AFG", "ASIA", "AS", // Afghanistan + "ALA", "EURO", "EU", // Åland Islands + "ALB", "EURO", "EU", // Albania + "DZA", "NAFR", "AF", // Algeria + "ASM", "ASIA", "AS", // American Samoa + "AND", "EURO", "EU", // Andorra + "AGO", "CAFR", "AF", // Angola + "AIA", "CARB", "NA", // Anguilla + "ATG", "CARB", "NA", // Antigua and Barbuda + "ARG", "SOAM", "SA", // Argentina + "ARM", "ASIA", "AS", // Armenia + "ABW", "CARB", "NA", // Aruba + "AUS", "AUNZ", "OC", // Australia + "AUT", "EURO", "EU", // Austria + "AZE", "ASIA", "AS", // Azerbaijan + "BHS", "CARB", "NA", // Bahamas + "BHR", "MDLE", "AS", // Bahrain + "BGD", "INDE", "AS", // Bangladesh + "BRB", "CARB", "NA", // Barbados + "BLR", "EURO", "EU", // Belarus + "BEL", "EURO", "EU", // Belgium + "BLZ", "CEAM", "NA", // Belize + "BEN", "CAFR", "AF", // Benin + "BMU", "CARB", "NA", // Bermuda + "BTN", "ASIA", "AS", // Bhutan + "BOL", "SOAM", "SA", // Bolivia (Plurinational State of) + "BIH", "EURO", "EU", // Bosnia and Herzegovina + "BWA", "SAFR", "AF", // Botswana + "BRA", "SOAM", "SA", // Brazil + "VGB", "CARB", "NA", // British Virgin Islands + "BRN", "ASIA", "AS", // Brunei Darussalam + "BGR", "EURO", "EU", // Bulgaria + "BFA", "CAFR", "AF", // Burkina Faso + "BDI", "CAFR", "AF", // Burundi + "KHM", "ASIA", "AS", // Cambodia + "CMR", "CAFR", "AF", // Cameroon + "CAN", "NOAM", "NA", // Canada + "CPV", "NAFR", "AF", // Cape Verde + "CYM", "CARB", "NA", // Cayman Islands + "CAF", "CAFR", "AF", // Central African Republic + "TCD", "CAFR", "AF", // Chad + "CHL", "SOAM", "SA", // Chile + "CHN", "ASIA", "AS", // China + "HKG", "ASIA", "AS", // Hong Kong Special Administrative Region of China + "MAC", "ASIA", "AS", // Macao Special Administrative Region of China + "COL", "ASIA", "SA", // Colombia + "COM", "SAFR", "AF", // Comoros + "COG", "CAFR", "AF", // Congo + "COK", "SPAC", "OC", // Cook Islands + "CRI", "CEAM", "NA", // Costa Rica + "CIV", "CAFR", "AF", // Côte d'Ivoire + "HRV", "EURO", "EU", // Croatia + "CUB", "CARB", "NA", // Cuba + "CYP", "EURO", "EU", // Cyprus + "CZE", "EURO", "EU", // Czech Republic + "PRK", "ASIA", "AS", // Democratic People's Republic of Korea + "COD", "CAFR", "AF", // Democratic Republic of the Congo + "DNK", "EURO", "EU", // Denmark + "DJI", "NAFR", "AF", // Djibouti + "DMA", "CARB", "NA", // Dominica + "DOM", "CARB", "NA", // Dominican Republic + "ECU", "SOAM", "SA", // Ecuador + "EGY", "MDLE", "AF", // Egypt + "SLV", "CEAM", "NA", // El Salvador + "GNQ", "CAFR", "AF", // Equatorial Guinea + "ERI", "NAFR", "AF", // Eritrea + "EST", "EURO", "EU", // Estonia + "ETH", "NAFR", "AF", // Ethiopia + "FRO", "EURO", "EU", // Faeroe Islands + "FLK", "SOAM", "SA", // Falkland Islands (Malvinas) + "FJI", "SPAC", "OC", // Fiji + "FIN", "EURO", "EU", // Finland + "FRA", "EURO", "EU", // France + "GUF", "SOAM", "SA", // French Guiana + "PYF", "SPAC", "OC", // French Polynesia + "GAB", "CAFR", "AF", // Gabon + "GMB", "CAFR", "AF", // Gambia + "GEO", "ASIA", "AS", // Georgia + "DEU", "EURO", "EU", // Germany + "GHA", "CAFR", "AF", // Ghana + "GIB", "EURO", "EU", // Gibraltar + "GRC", "EURO", "EU", // Greece + "GRL", "EURO", "EU", // Greenland + "GRD", "CARB", "NA", // Grenada + "GLP", "CARB", "NA", // Guadeloupe + "GUM", "SPAC", "OC", // Guam + "GTM", "CEAM", "NA", // Guatemala + "GGY", "EURO", "EU", // Guernsey + "GIN", "CAFR", "AF", // Guinea + "GNB", "CAFR", "AF", // Guinea-Bissau + "GUY", "SOAM", "SA", // Guyana + "HTI", "CARB", "NA", // Haiti + "VAT", "EURO", "EU", // Holy See + "HND", "CEAM", "NA", // Honduras + "HUN", "EURO", "EU", // Hungary + "ISL", "EURO", "EU", // Iceland + "IND", "INDI", "AS", // India + "IDN", "ASIA", "AS", // Indonesia + "IRN", "MDLE", "AS", // Iran (Islamic Republic of) + "IRQ", "MDLE", "AS", // Iraq + "IRL", "EURO", "EU", // Ireland + "IMN", "EURO", "EU", // Isle of Man + "ISR", "MDLE", "AS", // Israel + "ITA", "EURO", "EU", // Italy + "JAM", "CEAM", "NA", // Jamaica + "JPN", "ASIA", "AS", // Japan + "JEY", "EURO", "EU", // Jersey + "JOR", "MDLE", "AS", // Jordan + "KAZ", "ASIA", "AS", // Kazakhstan + "KEN", "CAFR", "AF", // Kenya + "KIR", "EPAC", "OC", // Kiribati + "KWT", "MDLE", "AS", // Kuwait + "KGZ", "ASIA", "AS", // Kyrgyzstan + "LAO", "ASIA", "AS", // Lao People's Democratic Republic + "LVA", "EURO", "EU", // Latvia + "LBN", "MDLE", "AS", // Lebanon + "LSO", "SAFR", "AF", // Lesotho + "LBR", "CAFR", "AF", // Liberia + "LBY", "MDLE", "AS", // Libyan Arab Jamahiriya + "LIE", "EURO", "EU", // Liechtenstein + "LTU", "EURO", "EU", // Lithuania + "LUX", "EURO", "EU", // Luxembourg + "MDG", "SAFR", "AF", // Madagascar + "MWI", "SAFR", "AF", // Malawi + "MYS", "ASIA", "AS", // Malaysia + "MDV", "INDI", "AS", // Maldives + "MLI", "CAFR", "AF", // Mali + "MLT", "EURO", "EU", // Malta + "MHL", "WPAC", "OC", // Marshall Islands + "MTQ", "CARB", "NA", // Martinique + "MRT", "NAFR", "AF", // Mauritania + "MUS", "SAFR", "AF", // Mauritius + "MYT", "SAFR", "AF", // Mayotte + "MEX", "NOAM", "NA", // Mexico + "FSM", "WPAC", "OC", // Micronesia (Federated States of) + "MCO", "EURO", "EU", // Monaco + "MNG", "ASIA", "AS", // Mongolia + "MNE", "EURO", "EU", // Montenegro + "MSR", "CARB", "NA", // Montserrat + "MAR", "NAFR", "AF", // Morocco + "MOZ", "SAFR", "AF", // Mozambique + "MMR", "ASIA", "AS", // Myanmar + "NAM", "SAFR", "AF", // Namibia + "NRU", "WPAC", "OC", // Nauru + "NPL", "ASIA", "AS", // Nepal + "NLD", "EURO", "EU", // Netherlands + "ANT", "CARB", "NA", // Netherlands Antilles + "NCL", "SPAC", "OC", // New Caledonia + "NZL", "AUNZ", "OC", // New Zealand + "NIC", "CEAM", "SA", // Nicaragua + "NER", "NAFR", "AF", // Niger + "NGA", "CAFR", "AF", // Nigeria + "NIU", "SPAC", "OC", // Niue + "NFK", "SPAC", "OC", // Norfolk Island + "MNP", "WPAC", "OC", // Northern Mariana Islands + "NOR", "EURO", "EU", // Norway + "PSE", "MDLE", "AS", // Occupied Palestinian Territory + "OMN", "MDLE", "AS", // Oman + "PAK", "INDI", "AS", // Pakistan + "PLW", "SPAC", "OC", // Palau + "PAN", "CEAM", "SA", // Panama + "PNG", "SPAC", "OC", // Papua New Guinea + "PRY", "SOAM", "SA", // Paraguay + "PER", "SOAM", "SA", // Peru + "PHL", "ASIA", "AS", // Philippines + "PCN", "SPAC", "OC", // Pitcairn + "POL", "EURO", "EU", // Poland + "PRT", "EURO", "EU", // Portugal + "PRI", "CARB", "NA", // Puerto Rico + "QAT", "MDLE", "AS", // Qatar + "KOR", "ASIA", "AS", // Republic of Korea + "MDA", "EURO", "EU", // Republic of Moldova + "REU", "SAFR", "AF", // Réunion + "ROU", "EURO", "EU", // Romania + "RUS", "ASIA", "AS", // Russian Federation + "RWA", "CAFR", "AF", // Rwanda + "BLM", "CARB", "NA", // Saint-Barthélemy + "SHN", "SOAM", "SA", // Saint Helena + "KNA", "CARB", "NA", // Saint Kitts and Nevis + "LCA", "CARB", "NA", // Saint Lucia + "MAF", "CARB", "NA", // Saint-Martin (French part) + "SPM", "NOAM", "NA", // Saint Pierre and Miquelon + "VCT", "CARB", "NA", // Saint Vincent and the Grenadines + "WSM", "SPAC", "OC", // Samoa + "SMR", "EURO", "EU", // San Marino + "STP", "CAFR", "AF", // Sao Tome and Principe + "SAU", "MDLE", "AS", // Saudi Arabia + "SEN", "CAFR", "AF", // Senegal + "SRB", "EURO", "EU", // Serbia + "SYC", "SAFR", "AF", // Seychelles + "SLE", "NAFR", "AF", // Sierra Leone + "SGP", "ASIA", "AS", // Singapore + "SVK", "EURO", "EU", // Slovakia + "SVN", "EURO", "EU", // Slovenia + "SLB", "SPAC", "OC", // Solomon Islands + "SOM", "NAFR", "AF", // Somalia + "ZAF", "SAFR", "AF", // South Africa + "ESP", "EURO", "EU", // Spain + "LKA", "INDE", "AS", // Sri Lanka + "SDN", "NAFR", "AF", // Sudan + "SUR", "SOAM", "SA", // Suriname + "SJM", "EURO", "EU", // Svalbard and Jan Mayen Islands + "SWZ", "SAFR", "AF", // Swaziland + "SWE", "EURO", "EU", // Sweden + "CHE", "EURO", "EU", // Switzerland + "SYR", "MDLE", "AS", // Syrian Arab Republic + "TJK", "ASIA", "AS", // Tajikistan + "THA", "ASIA", "AS", // Thailand + "MKD", "EURO", "EU", // The former Yugoslav Republic of Macedonia + "TLS", "ASIA", "AS", // Timor-Leste + "TGO", "CAFR", "AF", // Togo + "TKL", "AUNZ", "OC", // Tokelau + "TON", "SPAC", "OC", // Tonga + "TTO", "CARB", "NA", // Trinidad and Tobago + "TUN", "NAFR", "AF", // Tunisia + "TUR", "EURO", "EU", // Turkey + "TKM", "ASIA", "AS", // Turkmenistan + "TCA", "CARB", "NA", // Turks and Caicos Islands + "TUV", "SPAC", "OC", // Tuvalu + "UGA", "SAFR", "AF", // Uganda + "UKR", "EURO", "EU", // Ukraine + "ARE", "MDLE", "AS", // United Arab Emirates + "GBR", "EURO", "EU", // United Kingdom of Great Britain and Northern Ireland + "TZA", "SAFR", "AF", // United Republic of Tanzania + "USA", "NOAM", "NA", // United States of America + "VIR", "CARB", "NA", // United States Virgin Islands + "URY", "SOAM", "SA", // Uruguay + "UZB", "ASIA", "AS", // Uzbekistan + "VUT", "SPAC", "OC", // Vanuatu + "VEN", "SOAM", "SA", // Venezuela (Bolivarian Republic of) + "VNM", "ASIA", "AS", // Viet Nam + "WLF", "SPAC", "OC", // Wallis and Futuna Islands + "ESH", "CAFR", "AF", // Western Sahara + "YEM", "NAFR", "AF", // Yemen + "ZMB", "SAFR", "AF", // Zambia + "ZWE", "SAFR", "AF" // Zimbabwe }; char ** AliasText; struct ALIAS ** Aliases; @@ -339,9 +339,9 @@ struct ALIAS ** NTSAliases = NULL; /*struct ALIAS Aliases[] = { - "AMSAT", "WW", - "USBBS", "USA", - "ALLUS", "USA"}; +"AMSAT", "WW", +"USBBS", "USA", +"ALLUS", "USA"}; */ int NumberofContinents = sizeof(Continents)/sizeof(Continents[1]); @@ -355,7 +355,7 @@ struct Continent * FindContinent(char * Name) for(i=0; i< NumberofContinents; i++) { Cont = &Continents[i]; - + if ((_stricmp(Name, Cont->FourCharCode) == 0) || (_stricmp(Name, Cont->TwoCharCode) == 0)) return Cont; } @@ -371,7 +371,7 @@ struct Country * FindCountry(char * Name) for(i=0; i< NumberofCountries; i++) { Cont = &Countries[i]; - + if (_stricmp(Name, Cont->Country) == 0) return Cont; } @@ -389,7 +389,7 @@ struct ALIAS * FindAlias(char * Name) { if (_stricmp(Name, Alias[0]->Dest) == 0) return Alias[0]; - + Alias++; } @@ -403,7 +403,7 @@ VOID SetupMyHA() struct Continent * Continent; strcpy(MyRouteElements, HRoute); - + // Split it up ptr2 = MyRouteElements + strlen(MyRouteElements) - 1; @@ -418,7 +418,7 @@ VOID SetupMyHA() if (ptr2 == MyRouteElements) { // End - + MyElements[Elements++] = _strdup(ptr2); break; } @@ -435,29 +435,32 @@ VOID SetupMyHA() if (MyElements[1]) { -#ifdef TWOCHARCONT - if (strlen(MyElements[1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(MyElements[1]); - if (Continent) + if (strlen(MyElements[1]) == 4) { - free(MyElements[1]); - MyElements[1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(MyElements[1]); + if (Continent) + { + free(MyElements[1]); + MyElements[1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(MyElements[1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(MyElements[1]); - if (Continent) + if (strlen(MyElements[1]) == 2) { - free(MyElements[1]); - MyElements[1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(MyElements[1]); + if (Continent) + { + free(MyElements[1]); + MyElements[1] = _strdup(Continent->FourCharCode); + } } } -#endif } } @@ -556,7 +559,7 @@ VOID SetupHAElements(struct BBSForwardingInfo * ForwardingInfo) do { ForwardingInfo->BBSHAElements = realloc(ForwardingInfo->BBSHAElements, (Elements+2) * sizeof(void *)); - + while ((*ptr2 != '.') && (ptr2 > SaveHText)) { ptr2 --; @@ -565,13 +568,13 @@ VOID SetupHAElements(struct BBSForwardingInfo * ForwardingInfo) if (ptr2 == SaveHText) { // End - + ForwardingInfo->BBSHAElements[Elements++] = _strdup(ptr2); break; } - ForwardingInfo->BBSHAElements[Elements++] = _strdup(ptr2+1); - *ptr2 = 0; + ForwardingInfo->BBSHAElements[Elements++] = _strdup(ptr2+1); + *ptr2 = 0; } while(TRUE); @@ -579,30 +582,32 @@ VOID SetupHAElements(struct BBSForwardingInfo * ForwardingInfo) if (ForwardingInfo->BBSHAElements[1]) { -#ifdef TWOCHARCONT - if (strlen(ForwardingInfo->BBSHAElements[1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); - if (Continent) + if (strlen(ForwardingInfo->BBSHAElements[1]) == 4) { - free(ForwardingInfo->BBSHAElements[1]); - ForwardingInfo->BBSHAElements[1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); + if (Continent) + { + free(ForwardingInfo->BBSHAElements[1]); + ForwardingInfo->BBSHAElements[1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(ForwardingInfo->BBSHAElements[1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); - if (Continent) + if (strlen(ForwardingInfo->BBSHAElements[1]) == 2) { - free(ForwardingInfo->BBSHAElements[1]); - ForwardingInfo->BBSHAElements[1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(ForwardingInfo->BBSHAElements[1]); + if (Continent) + { + free(ForwardingInfo->BBSHAElements[1]); + ForwardingInfo->BBSHAElements[1] = _strdup(Continent->FourCharCode); + } } } -#endif - } free(SaveHText); @@ -614,7 +619,7 @@ VOID SetupHAddreses(struct BBSForwardingInfo * ForwardingInfo) int Count=0; char ** HText = ForwardingInfo->Haddresses; char * SaveHText, * ptr2; -// char * TopElement; + // char * TopElement; char * Num; struct Continent * Continent; @@ -626,7 +631,7 @@ VOID SetupHAddreses(struct BBSForwardingInfo * ForwardingInfo) int Elements = 1; ForwardingInfo->HADDRS = realloc(ForwardingInfo->HADDRS, (Count+2) * sizeof(void *)); ForwardingInfo->HADDROffet = realloc(ForwardingInfo->HADDROffet, (Count+2) * sizeof(void *)); - + ForwardingInfo->HADDRS[Count] = zalloc(8); // Always at lesat WWW and NULL SaveHText = _strdup(HText[0]); @@ -671,53 +676,56 @@ VOID SetupHAddreses(struct BBSForwardingInfo * ForwardingInfo) // Far simpler to config it, but can users cope?? // Will config for testing. HA, N -/* + /* TopElement=ForwardingInfo->HADDRS[Count][0]; if (strcmp(TopElement, MyElements[0]) == 0) - goto FullHR; + goto FullHR; if (FindContinent(TopElement)) - goto FullHR; - + goto FullHR; + // Need to add stuff from our HR Elements--; if (Elements < MyElementCount) - break; + break; -FullHR: -*/ + FullHR: + */ ForwardingInfo->HADDROffet[Count] = (Num)? atoi(Num): 0; if (ForwardingInfo->HADDRS[Count][1]) { -#ifdef TWOCHARCONT - if (strlen(ForwardingInfo->HADDRS[Count][1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); - if (Continent) - { - free(ForwardingInfo->HADDRS[Count][1]); - ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->TwoCharCode); - } - } -#else - if (strlen(ForwardingInfo->HADDRS[Count][1]) == 2) - { - // Convert to 4 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); - if (Continent) - { - free(ForwardingInfo->HADDRS[Count][1]); - ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->FourCharCode); - } - } -#endif + if (strlen(ForwardingInfo->HADDRS[Count][1]) == 4) + { + // Convert to 2 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRS[Count][1]); + ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->TwoCharCode); + } + } + } + else + { + if (strlen(ForwardingInfo->HADDRS[Count][1]) == 2) + { + // Convert to 4 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRS[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRS[Count][1]); + ForwardingInfo->HADDRS[Count][1] = _strdup(Continent->FourCharCode); + } + } + } } free(SaveHText); HText++; @@ -732,7 +740,7 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) int Count=0; char ** HText = ForwardingInfo->HaddressesP; char * SaveHText, * ptr2; -// char * TopElement; + // char * TopElement; char * Num; struct Continent * Continent; @@ -742,7 +750,7 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) { int Elements = 1; ForwardingInfo->HADDRSP = realloc(ForwardingInfo->HADDRSP, (Count+2) * sizeof(void *)); - + ForwardingInfo->HADDRSP[Count] = zalloc(2 * sizeof(void *)); // Always at lesat WWW and NULL SaveHText = _strdup(HText[0]); @@ -781,29 +789,33 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) if (ForwardingInfo->HADDRSP[Count][1]) { -#ifdef TWOCHARCONT - if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); - if (Continent) + + if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 4) { - free(ForwardingInfo->HADDRSP[Count][1]); - ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRSP[Count][1]); + ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); - if (Continent) + if (strlen(ForwardingInfo->HADDRSP[Count][1]) == 2) { - free(ForwardingInfo->HADDRSP[Count][1]); - ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(ForwardingInfo->HADDRSP[Count][1]); + if (Continent) + { + free(ForwardingInfo->HADDRSP[Count][1]); + ForwardingInfo->HADDRSP[Count][1] = _strdup(Continent->FourCharCode); + } } } -#endif } free(SaveHText); HText++; @@ -816,7 +828,7 @@ VOID SetupHAddresesP(struct BBSForwardingInfo * ForwardingInfo) VOID CheckAndSend(struct MsgInfo * Msg, CIRCUIT * conn, struct UserInfo * bbs) { struct BBSForwardingInfo * ForwardingInfo = bbs->ForwardingInfo; - + if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Don't forward to ourself - already here! (unless ForwardToMe set) { if ((conn == NULL) || (!(conn->BBSFlags & BBS) || (_stricmp(conn->UserPointer->Call, bbs->Call) != 0))) // Dont send back @@ -841,9 +853,9 @@ VOID CheckAndSend(struct MsgInfo * Msg, CIRCUIT * conn, struct UserInfo * bbs) { CheckAndSend(Msg, conn, user); } - + Logprintf(LOG_BBS, conn, '?', "Message matches this BBS and RMS Redirect set - fwd to RMS"); - + } else Logprintf(LOG_BBS, conn, '?', "Message matches this BBS and ForwardToMe not set - not queuing message"); @@ -857,7 +869,7 @@ VOID UpdateB2Dest(struct MsgInfo * Msg, char * Alias) FILE * hFile; char * MsgBytes; struct stat STAT; - + sprintf_s(MsgFile, sizeof(MsgFile), "%s/m_%06d.mes", MailDir, Msg->number); if (stat(MsgFile, &STAT) == -1) @@ -1032,7 +1044,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (strlen(toCall) > 6) toCall[6] = 0; - + strcpy(Msg->to, toCall); strcpy(Msg->via, via); Logprintf(LOG_BBS, conn, '?', "Routing Trace at %s is for us. Leave Here", AMPRDomain); @@ -1048,7 +1060,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (bbs) { // We have bbs AMPR - + if (_stricmp(Msg->to, "RMS") == 0 || Msg->to[0] == 0) { // Was set to go via RMS or ISP - change it @@ -1057,7 +1069,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) } Logprintf(LOG_BBS, conn, '?', "Routing Trace to ampr.org Matches BBS AMPR"); - + set_fwd_bit(Msg->fbbs, bbs->BBSNumber); bbs->ForwardingInfo->MsgCount++; if (bbs->ForwardingInfo->SendNew) @@ -1070,12 +1082,12 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) } } -// See if sending @ winlink.org + // See if sending @ winlink.org if (_stricmp(Msg->to, "RMS") == 0) { // If a user of this bbs with Poll RMS set, leave it here - no point in sending to winlink - + // To = RMS could come from RMS:EMAIL Address. If so, we only check user if @winlink.org, or // we will hold g8bpq@g8bpq.org.uk @@ -1103,7 +1115,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (user->flags & F_BBS) // User is also a BBS, so set FWD bit so he can get it set_fwd_bit(Msg->fbbs, user->BBSNumber); - + return 1; } } @@ -1118,7 +1130,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (RMS) { Logprintf(LOG_BBS, conn, '?', "Routing Trace to RMS Matches BBS RMS"); - + set_fwd_bit(Msg->fbbs, RMS->BBSNumber); RMS->ForwardingInfo->MsgCount++; if (RMS->ForwardingInfo->SendNew) @@ -1140,20 +1152,20 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) if (user->flags & F_POLLRMS) { Logprintf(LOG_BBS, conn, '?', "Routing Trace @ winlink.org, but local RMS user - leave here"); - + if (user->flags & F_BBS) // User is also a BBS, so set FWD bit so he can get it set_fwd_bit(Msg->fbbs, user->BBSNumber); return 1; // Route found } } - + RMS = FindRMS(); if (RMS) { Logprintf(LOG_BBS, conn, '?', "Routing Trace @ winlink.org Matches BBS RMS"); - + set_fwd_bit(Msg->fbbs, RMS->BBSNumber); RMS->ForwardingInfo->MsgCount++; if (RMS->ForwardingInfo->SendNew) @@ -1169,7 +1181,7 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) // See if a well-known alias Alias = FindAlias(RouteElements); - + if (Alias) { Logprintf(LOG_BBS, conn, '?', "Routing Trace Alias Substitution %s > %s", @@ -1219,15 +1231,15 @@ int MatchMessagetoBBSList(struct MsgInfo * Msg, CIRCUIT * conn) } Country = FindCountry(ptr2); - + if (Country) { // Just need to add Continent and WW -#ifdef TWOCHARCONT - sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent2); -#else - sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent4); -#endif + if (FOURCHARCONT == 0) + sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent2); + else + sprintf_s(FullRoute, sizeof(FullRoute),"%s.%s.WW", RouteElements, Country->Continent4); + goto FULLHA; } @@ -1261,7 +1273,7 @@ FULLHA: if (ptr2 != FullRoute) *ptr2++ = 0; - + HElements[Elements++] = ptr2; @@ -1270,29 +1282,32 @@ FULLHA: if (HElements[1]) { -#ifdef TWOCHARCONT - if (strlen(HElements[1]) == 4) + if (FOURCHARCONT == 0) { - // Convert to 2 char Continent; - Continent = FindContinent(HElements[1]); - if (Continent) + if (strlen(HElements[1]) == 4) { -// free(MyElements[1]); - HElements[1] = _strdup(Continent->TwoCharCode); + // Convert to 2 char Continent; + Continent = FindContinent(HElements[1]); + if (Continent) + { + // free(MyElements[1]); + HElements[1] = _strdup(Continent->TwoCharCode); + } } } -#else - if (strlen(HElements[1]) == 2) + else { - // Convert to 4 char Continent; - Continent = FindContinent(HElements[1]); - if (Continent) + if (strlen(HElements[1]) == 2) { -// free(MyElements[1]); - HElements[1] = _strdup(Continent->FourCharCode); + // Convert to 4 char Continent; + Continent = FindContinent(HElements[1]); + if (Continent) + { + // free(MyElements[1]); + HElements[1] = _strdup(Continent->FourCharCode); + } } } -#endif } @@ -1301,7 +1316,7 @@ FULLHA: if (Msg->type == 'B') { int i = 0; - + // All elements of Helements must match Myelements while (MyElements[i] && HElements[i]) // Until one set runs out @@ -1345,7 +1360,7 @@ NOHA: if (depth > -1) { Logprintf(LOG_BBS, conn, '?', "Routing Trace NTS Matches TO BBS %s Length %d", bbs->Call, depth); - + if (depth > bestmatch) { bestmatch = depth; @@ -1386,7 +1401,63 @@ NOHA: goto CheckWildCardedAT; } + // First check P message to multiple destinations + // We should choose the BBS with most matching elements (ie match on #23.GBR better that GBR) + // If SendPtoMultiple is set I think we send to any with same match level + + // So if SendPtoMultiple is set I think I need to find the best depth then send to all with the same depth + // If none are found on HA match drop through. + + if (SendPtoMultiple && Msg->type == 'P') + { + struct UserInfo * bestbbs = NULL; + int bestmatch = 0; + int depth; + int Matched = 0; + int MultiPDepth = 0; + + Count = 0; + + Logprintf(LOG_BBS, conn, '?', "SendPtoMultiple is set. Checking for best match level"); + + for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) + { + ForwardingInfo = bbs->ForwardingInfo; + + depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); + + if (depth) + { + if (depth > MultiPDepth) + { + MultiPDepth = depth; + bestbbs = bbs; + } + } + } + + if (MultiPDepth) + { + for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) + { + ForwardingInfo = bbs->ForwardingInfo; + + depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); + + if (depth == MultiPDepth) + { + Logprintf(LOG_BBS, conn, '?', "Routing Trace HR Matches BBS %s Depth %d", bbs->Call, depth); + CheckAndSend(Msg, conn, bbs); + Count++; + } + } + return Count; + } + else + Logprintf(LOG_BBS, conn, '?', "SendPtoMultiple is set but no match on HA"); + } + if (Msg->type == 'P' || Flood == 0) { // P messages are only sent to one BBS, but check the TO and AT of all BBSs before routing on HA, @@ -1406,7 +1477,7 @@ NOHA: if (ForwardingInfo->PersonalOnly && (Msg->type != 'P') && (Msg->type != 'T')) continue; - + if (CheckBBSToList(Msg, bbs, ForwardingInfo)) { Logprintf(LOG_BBS, conn, '?', "Routing Trace TO %s Matches BBS %s", Msg->to, bbs->Call); @@ -1433,9 +1504,9 @@ NOHA: if ((strcmp(ATBBS, bbs->Call) == 0)) // @BBS = BBS { Logprintf(LOG_BBS, conn, '?', "Routing Trace %s Matches implied AT %s", ATBBS, bbs->Call); - + CheckAndSend(Msg, conn, bbs); - + Matched++; if (SendPtoMultiple && Msg->type == 'P') continue; @@ -1467,50 +1538,7 @@ NOHA: return 1; } - // We should choose the BBS with most matching elements (ie match on #23.GBR better that GBR) - // If SendPtoMultiple is set I think we send to any with same match level - - // So if SendPtoMultiple is set I think I need to find the best depth then send to all with the same depth - - - if (SendPtoMultiple && Msg->type == 'P') - { - Logprintf(LOG_BBS, conn, '?', "SendPtoMultiple is set. Checking for best match level"); - - for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) - { - ForwardingInfo = bbs->ForwardingInfo; - - depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); - - if (depth) - { - if (depth > MultiPDepth) - { - MultiPDepth = depth; - bestbbs = bbs; - } - } - - if (MultiPDepth) - { - for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) - { - ForwardingInfo = bbs->ForwardingInfo; - - depth = CheckBBSHElements(Msg, bbs, ForwardingInfo, ATBBS, &HElements[0]); - - if (depth == MultiPDepth) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace HR Matches BBS %s Depth %d", bbs->Call, depth); - CheckAndSend(Msg, conn, bbs); - } - } - - return 1; - } - } - } + // Normal HA match (not SendPToMultiple) for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) { @@ -1586,182 +1614,182 @@ CheckWildCardedAT: Logprintf(LOG_BBS, conn, '?', "Routing Trace - No Match"); return FALSE; // No match - } - - // Flood Bulls go to all matching BBSs in the flood area, so the order of checking doesn't matter - - // For now I will only route on AT (for non-hierarchical addresses) and HA - - // Ver 1.0.4.2 - Try including TO - - for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) - { - ForwardingInfo = bbs->ForwardingInfo; - - if (ForwardingInfo->PersonalOnly) - continue; - - if (CheckBBSToList(Msg, bbs, ForwardingInfo)) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace TO %s Matches BBS %s", Msg->to, bbs->Call); - - if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Dont forward to ourself - already here! (unless ForwardToMe set) - { - set_fwd_bit(Msg->fbbs, bbs->BBSNumber); - ForwardingInfo->MsgCount++; - } - Count++; - continue; - } - - if ((strcmp(ATBBS, bbs->Call) == 0) || // @BBS = BBS - CheckBBSAtList(Msg, ForwardingInfo, ATBBS)) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace AT %s Matches BBS %s", Msg->to, bbs->Call); - CheckAndSend(Msg, conn, bbs); - - Count++; - continue; - } - - - if (CheckBBSHElementsFlood(Msg, bbs, ForwardingInfo, Msg->via, &HElements[0])) - { - Logprintf(LOG_BBS, conn, '?', "Routing Trace HR %s %s %s %s %s Matches BBS %s", - HElements[0], HElements[1], HElements[2], - HElements[3], HElements[4], bbs->Call); - - CheckAndSend(Msg, conn, bbs); - - Count++; - } - - } - - if (Count == 0) - goto CheckWildCardedAT; - - Logprintf(LOG_BBS, conn, '?', "Routing Trace - No Match"); - - return Count; } - BOOL CheckBBSToList(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo) - { - char ** Calls; + // Flood Bulls go to all matching BBSs in the flood area, so the order of checking doesn't matter - // Check TO distributions + // For now I will only route on AT (for non-hierarchical addresses) and HA - if (ForwardingInfo->TOCalls) + // Ver 1.0.4.2 - Try including TO + + for (bbs = BBSChain; bbs; bbs = bbs->BBSNext) + { + ForwardingInfo = bbs->ForwardingInfo; + + if (ForwardingInfo->PersonalOnly) + continue; + + if (CheckBBSToList(Msg, bbs, ForwardingInfo)) { - Calls = ForwardingInfo->TOCalls; + Logprintf(LOG_BBS, conn, '?', "Routing Trace TO %s Matches BBS %s", Msg->to, bbs->Call); - while(Calls[0]) + if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Dont forward to ourself - already here! (unless ForwardToMe set) { - if (strcmp(Calls[0], Msg->to) == 0) - return TRUE; - - Calls++; + set_fwd_bit(Msg->fbbs, bbs->BBSNumber); + ForwardingInfo->MsgCount++; } + Count++; + continue; } - return FALSE; + + if ((strcmp(ATBBS, bbs->Call) == 0) || // @BBS = BBS + CheckBBSAtList(Msg, ForwardingInfo, ATBBS)) + { + Logprintf(LOG_BBS, conn, '?', "Routing Trace AT %s Matches BBS %s", Msg->to, bbs->Call); + CheckAndSend(Msg, conn, bbs); + + Count++; + continue; + } + + + if (CheckBBSHElementsFlood(Msg, bbs, ForwardingInfo, Msg->via, &HElements[0])) + { + Logprintf(LOG_BBS, conn, '?', "Routing Trace HR %s %s %s %s %s Matches BBS %s", + HElements[0], HElements[1], HElements[2], + HElements[3], HElements[4], bbs->Call); + + CheckAndSend(Msg, conn, bbs); + + Count++; + } + } - BOOL CheckBBSAtList(struct MsgInfo * Msg, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS) + if (Count == 0) + goto CheckWildCardedAT; + + Logprintf(LOG_BBS, conn, '?', "Routing Trace - No Match"); + + return Count; +} + +BOOL CheckBBSToList(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo) +{ + char ** Calls; + + // Check TO distributions + + if (ForwardingInfo->TOCalls) { - char ** Calls; + Calls = ForwardingInfo->TOCalls; - // Check AT distributions - - // if (strcmp(ATBBS, bbs->Call) == 0) // @BBS = BBS - // return TRUE; - - if (ForwardingInfo->ATCalls) + while(Calls[0]) { - Calls = ForwardingInfo->ATCalls; + if (strcmp(Calls[0], Msg->to) == 0) + return TRUE; - while(Calls[0]) - { - if (strcmp(Calls[0], ATBBS) == 0) - return TRUE; - - Calls++; - } + Calls++; } - return FALSE; } + return FALSE; +} - int CheckBBSHElements(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) +BOOL CheckBBSAtList(struct MsgInfo * Msg, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS) +{ + char ** Calls; + + // Check AT distributions + + // if (strcmp(ATBBS, bbs->Call) == 0) // @BBS = BBS + // return TRUE; + + if (ForwardingInfo->ATCalls) { - // Used for Personal Messages, and Bulls not yot at their target area + Calls = ForwardingInfo->ATCalls; - char *** HRoutes; - int i = 0, j, k = 0; - int bestmatch = 0; - - if (ForwardingInfo->HADDRSP) + while(Calls[0]) { - // Match on Routes + if (strcmp(Calls[0], ATBBS) == 0) + return TRUE; - HRoutes = ForwardingInfo->HADDRSP; - k=0; - - while(HRoutes[k]) - { - i = j = 0; - - while (HRoutes[k][i] && HElements[j]) // Until one set runs out - { - if (strcmp(HRoutes[k][i], HElements[j]) != 0) - break; - i++; - j++; - } - - // Only send if all BBS elements match - - if (HRoutes[k][i] == 0) - { - if (i > bestmatch) - bestmatch = i; - } - k++; - } + Calls++; } - return bestmatch; } + return FALSE; +} +int CheckBBSHElements(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) +{ + // Used for Personal Messages, and Bulls not yot at their target area - int CheckBBSHElementsFlood(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) + char *** HRoutes; + int i = 0, j, k = 0; + int bestmatch = 0; + + if (ForwardingInfo->HADDRSP) { - char *** HRoutes; - char ** BBSHA; + // Match on Routes - int i = 0, j, k = 0; - int bestmatch = 0; + HRoutes = ForwardingInfo->HADDRSP; + k=0; - if (ForwardingInfo->HADDRS) + while(HRoutes[k]) { - // Match on Routes - - // Message must be in right area (all elements of message match BBS Location HA) - - BBSHA = ForwardingInfo->BBSHAElements; - - if (BBSHA == NULL) - return 0; // Not safe to flood - i = j = 0; - while (BBSHA[i] && HElements[j]) // Until one set runs out + while (HRoutes[k][i] && HElements[j]) // Until one set runs out { - if (strcmp(BBSHA[i], HElements[j]) != 0) + if (strcmp(HRoutes[k][i], HElements[j]) != 0) break; i++; j++; } - if (HElements[j] != 0) + // Only send if all BBS elements match + + if (HRoutes[k][i] == 0) + { + if (i > bestmatch) + bestmatch = i; + } + k++; + } + } + return bestmatch; +} + + +int CheckBBSHElementsFlood(struct MsgInfo * Msg, struct UserInfo * bbs, struct BBSForwardingInfo * ForwardingInfo, char * ATBBS, char ** HElements) +{ + char *** HRoutes; + char ** BBSHA; + + int i = 0, j, k = 0; + int bestmatch = 0; + + if (ForwardingInfo->HADDRS) + { + // Match on Routes + + // Message must be in right area (all elements of message match BBS Location HA) + + BBSHA = ForwardingInfo->BBSHAElements; + + if (BBSHA == NULL) + return 0; // Not safe to flood + + i = j = 0; + + while (BBSHA[i] && HElements[j]) // Until one set runs out + { + if (strcmp(BBSHA[i], HElements[j]) != 0) + break; + i++; + j++; + } + + if (HElements[j] != 0) return 0; // Message is not for BBS's area HRoutes = ForwardingInfo->HADDRS; @@ -1770,7 +1798,7 @@ CheckWildCardedAT: while(HRoutes[k]) { i = j = 0; - + while (HRoutes[k][i] && HElements[j]) // Until one set runs out { if (strcmp(HRoutes[k][i], HElements[j]) != 0) @@ -1778,11 +1806,11 @@ CheckWildCardedAT: i++; j++; } - + if (i > bestmatch) { // As Flooding, only match if all elements match, and elements matching > offset - + // As Flooding, only match if all elements from BBS are matched // ie if BBS has #23.gbr.eu, and msg gbr.eu, don't match // if BBS has gbr.eu, and msg #23.gbr.eu, ok (so long as bbs in in #23, checked above. @@ -1807,7 +1835,7 @@ int CheckBBSToForNTS(struct MsgInfo * Msg, struct BBSForwardingInfo * Forwarding int MatchLen = 0; // Look for Matches on TO using Wildcarded Addresses. Intended for use with NTS traffic, with TO = ZIPCode - + // We forward to the BBS with the most specific match - ie minimum *'s in match if (ForwardingInfo->TOCalls) @@ -1848,7 +1876,7 @@ int CheckBBSToForNTS(struct MsgInfo * Msg, struct BBSForwardingInfo * Forwarding else { //no star - just do a normal compare - + if (strcmp(Msg->to, Call) == 0) { if (Invert) @@ -1877,7 +1905,7 @@ int CheckBBSATListWildCarded(struct MsgInfo * Msg, struct BBSForwardingInfo * Fo // Look for Matches on AT using Wildcarded Addresses. Only applied after all other checks fail. Intended mainly // for setting a default route, but could have other uses - + // We forward to the BBS with the most specific match - ie minimum *'s in match if (ForwardingInfo->ATCalls) @@ -1890,7 +1918,7 @@ int CheckBBSATListWildCarded(struct MsgInfo * Msg, struct BBSForwardingInfo * Fo ptr = strchr(Call, '*'); // only look if * present - we have already tried routing on the full AT - + if (ptr) { MatchLen = ptr - Call; @@ -1930,7 +1958,7 @@ struct ALIAS * CheckForNTSAlias(struct MsgInfo * Msg, char * ATFirstElement) break; ptr = strchr(Call, '*'); - + if (ptr) { MatchLen = ptr - Call; @@ -1941,7 +1969,7 @@ struct ALIAS * CheckForNTSAlias(struct MsgInfo * Msg, char * ATFirstElement) else { //no star - just do a normal compare - + if (strcmp(Msg->to, Call) == 0) return(Alias[0]); } @@ -2016,7 +2044,7 @@ VOID ReRouteMessages() if (check_fwd_bit(Msg->fbbs, user->BBSNumber)) // for this BBS? { if (check_fwd_bit(Msg->forw, user->BBSNumber)) // Already sent? - clear_fwd_bit(Msg->fbbs, user->BBSNumber); + clear_fwd_bit(Msg->fbbs, user->BBSNumber); } } diff --git a/Moncode.c b/Moncode.c index aa1c0bd..6463b14 100644 --- a/Moncode.c +++ b/Moncode.c @@ -195,6 +195,9 @@ KC6OAR*>ID: // Check Port Port = msg->PORT; + + if (Port == 40) + Port = Port; if (Port & 0x80) { @@ -250,10 +253,8 @@ KC6OAR*>ID: ptr += 7; n--; - if (n == 0) - { + if (n < 0) return 0; // Corrupt - no end of address bit - } } // Reached End of digis diff --git a/SCSPactor.c.bak b/SCSPactor.c.bak deleted file mode 100644 index 78f96db..0000000 --- a/SCSPactor.c.bak +++ /dev/null @@ -1,4322 +0,0 @@ -/* -Copyright 2001-2022 John Wiseman G8BPQ - -This file is part of LinBPQ/BPQ32. - -LinBPQ/BPQ32 is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -LinBPQ/BPQ32 is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses -*/ - -// -// DLL to inteface SCS TNC in Pactor Mode to BPQ32 switch -// -// Uses BPQ EXTERNAL interface - - -// Dec 29 2009 - -// Add Scan Control using %W Hostmode Command -// Map Rig control port to a Virtual Serial Port. -// Add Support for packet port(s). - -// July 2010 - -// Support up to 32 BPQ Ports - -// Version 1.1.1.14 August 2010 - -// Drop RTS as well as DTR on close - -// Version 1.2.1.1 August 2010 - -// Save Minimized State - -// Version 1.2.1.2 August 2010 - -// Implement scan bandwidth change - -// Version 1.2.1.3 September 2010 - -// Don't connect if channel is busy -// Add WL2K reporting -// Add PACKETCHANNELS config command -// And Port Selector (P1 or P2) for Packet Ports - -// Version 1.2.1.4 September 2010 - -// Fix Freq Display after Node reconfig -// Only use AutoConnect APPL for Pactor Connects - -// Version 1.2.2.1 September 2010 - -// Add option to get config from bpq32.cfg - -// October 2011 - -// Changes for P4Dragon - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_DEPRECATE - - -#include -#include -#include "time.h" - -//#include -//#include - -#define MaxStreams 10 // First is used for Pactor, even though Pactor uses channel 31 - -#include "CHeaders.h" -#include "tncinfo.h" - -#include "bpq32.h" - -#ifndef WIN32 -#ifndef MACBPQ -#ifndef FREEBSD - -#include -#include -#endif -#endif -#endif - -static char ClassName[]="PACTORSTATUS"; -static char WindowTitle[] = "SCS Pactor"; -static int RigControlRow = 185; - - -#define NARROWMODE 12 // PI/II -#define WIDEMODE 16 // PIII only - -extern UCHAR LogDirectory[]; - -static RECT Rect; - -VOID __cdecl Debugprintf(const char * format, ...); - -char NodeCall[11]; // Nodecall, Null Terminated - -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len); - -VOID SuspendOtherPorts(struct TNCINFO * ThisTNC); -VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC); - -VOID PTCSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC); -VOID PTCReleasePort(struct TNCINFO * TNC); -int KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len); -int CheckMode(struct TNCINFO * TNC); -VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len); -void SCSTryToSendDATA(struct TNCINFO * TNC, int Stream); -VOID UpdateMHwithDigis(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction); -int standardParams(struct TNCINFO * TNC, char * buf); -int SendPTCRadioCommand(struct TNCINFO * TNC, char * Block, int Length); - -#define FEND 0xC0 // KISS CONTROL CODES -#define FESC 0xDB -#define TFEND 0xDC -#define TFESC 0xDD - -static FILE * LogHandle[32] = {0}; - -//char * Logs[4] = {"1", "2", "3", "4"}; - -static char BaseDir[MAX_PATH]="c:\\"; - -static BOOL WRITELOG = FALSE; - -BOOL SCSStopPort(struct PORTCONTROL * PORT) -{ - // Disable Port - close TCP Sockets or Serial Port - - struct TNCINFO * TNC = PORT->TNC; - - TNC->CONNECTED = FALSE; - TNC->Alerted = FALSE; - - if (TNC->Streams[0].Attached) - TNC->Streams[0].ReportDISC = TRUE; - - if (TNC->hDevice) - { - CloseCOMPort(TNC->hDevice); - TNC->hDevice = 0; - } - - TNC->HostMode = FALSE; - - sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Stopped"); - MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE); - - return TRUE; -} - -BOOL SCSStartPort(struct PORTCONTROL * PORT) -{ - // Restart Port - Open Sockets or Serial Port - - struct TNCINFO * TNC = PORT->TNC; - - TNC->ReopenTimer = 999; // Reopen immediately - - sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Restarted"); - MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE); - - return TRUE; -} - - - -static VOID CloseLogFile(int Flags) -{ - if (WRITELOG) - { - fclose(LogHandle[Flags]); - LogHandle[Flags] = NULL; - } -} - -static BOOL OpenLogFile(int Flags) -{ - if (WRITELOG) - { - UCHAR FN[MAX_PATH]; - - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(FN,"%s/logs/SCSLog_%02d%02d_%d.txt", LogDirectory, tm->tm_mon + 1, tm->tm_mday, Flags); - - LogHandle[Flags] = fopen(FN, "ab"); - - return (LogHandle[Flags] != NULL); - } - return 0; -} - -static void WriteLogLine(int Flags, char * Msg, int MsgLen) -{ - if (WRITELOG) - { - if (LogHandle[Flags]) - { - fwrite(Msg, 1, MsgLen, LogHandle[Flags]); - fwrite("\r\n", 1, 2, LogHandle[Flags]); - } - } -} - - -static int DontAddPDUPLEX = 0; - - -static int ProcessLine(char * buf, int Port) -{ - UCHAR * ptr,* p_cmd; - char * p_ipad = 0; - char * p_port = 0; - unsigned short WINMORport = 0; - int BPQport; - int len=510; - struct TNCINFO * TNC; - char errbuf[256]; - - BPQport = Port; - - TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO)); - memset(TNC, 0, sizeof(struct TNCINFO)); - - TNC->InitScript = malloc(1000); - TNC->InitScript[0] = 0; - - goto ConfigLine; - - - // Read Initialisation lines - - while(TRUE) - { - if (GetLine(buf) == 0) - return TRUE; -ConfigLine: - - strcpy(errbuf, buf); - - if (memcmp(buf, "****", 4) == 0) - return TRUE; - - ptr = strchr(buf, ';'); - if (ptr) - { - *ptr++ = 13; - *ptr = 0; - } - - if (_memicmp(buf, "DEBUGLOG", 8) == 0) // Write Debug Log - WRITELOG = atoi(&buf[9]); - else - if (_memicmp(buf, "APPL", 4) == 0) - { - p_cmd = strtok(&buf[5], " \t\n\r"); - - if (p_cmd && p_cmd[0] != ';' && p_cmd[0] != '#') - TNC->ApplCmd=_strdup(_strupr(p_cmd)); - } - else - if (_memicmp(buf, "PACKETCHANNELS", 14) == 0) // Packet Channels - TNC->PacketChannels = atoi(&buf[14]); - - else - if (_memicmp(buf, "SCANFORROBUSTPACKET", 19) == 0) - { - // Spend a percentage of scan time in Robust Packet Mode - - double Robust = atof(&buf[20]); - #pragma warning(push) - #pragma warning(disable : 4244) - TNC->RobustTime = Robust * 10; - #pragma warning(pop) - } - else - if (_memicmp(buf, "USEAPPLCALLS", 12) == 0 && buf[12] != 'F' && buf[12] != 'f') - TNC->UseAPPLCalls = TRUE; - else - if (_memicmp(buf, "USEAPPLCALLSFORPACTOR", 21) == 0) - TNC->UseAPPLCallsforPactor = TRUE; - else - if (_memicmp(buf, "DRAGON", 6) == 0) - { - TNC->Dragon = TRUE; - if (_memicmp(&buf[7], "SINGLE", 6) == 0) - TNC->DragonSingle = TRUE; - - if (_memicmp(&buf[7], "KISS", 4) == 0) - TNC->DragonKISS = TRUE; - } - else - if (_memicmp(buf, "DEFAULT ROBUST", 14) == 0) - TNC->RobustDefault = TRUE; - else - if (_memicmp(buf, "DontAddPDUPLEX", 14) == 0) - DontAddPDUPLEX = TRUE; - else - if (_memicmp(buf, "FORCE ROBUST", 12) == 0) - TNC->ForceRobust = TNC->RobustDefault = TRUE; - else - if (_memicmp(buf, "MAXLEVEL", 8) == 0) // Maximum Pactor Level to use. - TNC->MaxLevel = atoi(&buf[8]); - else - if (_memicmp(buf, "DATE", 4) == 0) - { - char Cmd[32]; - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(Cmd,"DATE %02d%02d%02d\r", tm->tm_mday, tm->tm_mon + 1, tm->tm_year - 100); - - strcat (TNC->InitScript, Cmd); - } - else if (_memicmp(buf, "TIME", 4) == 0) - { - char Cmd[32]; - time_t T; - struct tm * tm; - - T = time(NULL); - tm = gmtime(&T); - - sprintf(Cmd,"TIME %02d%02d%02d\r", tm->tm_hour, tm->tm_min, tm->tm_sec); - - strcat (TNC->InitScript, Cmd); - } - else if (standardParams(TNC, buf) == FALSE) - strcat (TNC->InitScript, buf); - } - - return (TRUE); - -} - -struct TNCINFO * CreateTTYInfo(int port, int speed); - -BOOL CloseConnection(struct TNCINFO * conn); -BOOL WriteCommBlock(struct TNCINFO * TNC); -BOOL DestroyTTYInfo(int port); -void SCSCheckRX(struct TNCINFO * TNC); -VOID SCSPoll(int Port); -VOID CRCStuffAndSend(struct TNCINFO * TNC, UCHAR * Msg, int Len); -unsigned short int compute_crc(unsigned char *buf,int len); -int Unstuff(UCHAR * MsgIn, UCHAR * MsgOut, int len); -VOID ProcessDEDFrame(struct TNCINFO * TNC, UCHAR * rxbuff, int len); -VOID ProcessTermModeResponse(struct TNCINFO * TNC); -static VOID ExitHost(struct TNCINFO * TNC); -static VOID DoTNCReinit(struct TNCINFO * TNC); -static VOID DoTermModeTimeout(struct TNCINFO * TNC); -static VOID DoMonitor(struct TNCINFO * TNC, UCHAR * Msg, int Len); -int Switchmode(struct TNCINFO * TNC, int Mode); -VOID SwitchToPactor(struct TNCINFO * TNC); -VOID SwitchToPacket(struct TNCINFO * TNC); - - -char status[8][8] = {"ERROR", "REQUEST", "TRAFFIC", "IDLE", "OVER", "PHASE", "SYNCH", ""}; - -char ModeText[8][14] = {"STANDBY", "AMTOR-ARQ", "PACTOR-ARQ", "AMTOR-FEC", "PACTOR-FEC", "RTTY / CW", "LISTEN", "Channel-Busy"}; - -char PactorLevelText[5][14] = {"Not Connected", "PACTOR-I", "PACTOR-II", "PACTOR-III", "PACTOR-IV"}; - -char PleveltoMode[5] = {30, 11, 14, 16, 20}; // WL2K Reporting Modes - RP, P1, P2, P3, P4 - - -static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) -{ - int txlen = 0; - PMSGWITHLEN buffptr; - struct TNCINFO * TNC = TNCInfo[port]; - size_t Param; - int Stream = 0; - struct STREAMINFO * STREAM = &TNC->Streams[0]; - char PLevel; - struct ScanEntry * Scan; - - if (TNC == NULL) - return 0; - - if (TNC->hDevice == 0) - { - // Clear anything from UI_Q - - while (TNC->PortRecord->UI_Q) - { - buffptr = Q_REM(&TNC->PortRecord->UI_Q); - ReleaseBuffer(buffptr); - } - - // Try to reopen every 30 secs - - if (fn > 3 && fn < 7) - goto ok; - - TNC->ReopenTimer++; - - if (TNC->ReopenTimer < 300) - return 0; - - TNC->ReopenTimer = 0; - - if (TNC->PortRecord->PORTCONTROL.PortStopped == 0) - OpenCOMMPort(TNC, TNC->PortRecord->PORTCONTROL.SerialPortName, TNC->PortRecord->PORTCONTROL.BAUDRATE, TRUE); - - if (TNC->hDevice == 0) - return 0; - -#ifndef WIN32 -#ifndef MACBPQ -#ifndef FREEBSD - - if (TNC->Dragon) - { - struct serial_struct sstruct; - - // Need to set custom baud rate - - if (ioctl(TNC->hDevice, TIOCGSERIAL, &sstruct) < 0) - { - Debugprintf("Error: Dragon could not get comm ioctl\n"); - } - else - { - // set custom divisor to get 829440 baud - - sstruct.custom_divisor = 29; - sstruct.flags |= ASYNC_SPD_CUST; - - // set serial_struct - - if (ioctl(TNC->hDevice, TIOCSSERIAL, &sstruct) < 0) - Debugprintf("Error: Dragon could not set custom comm baud divisor\n"); - else - Debugprintf("Dragon custom baud rate set\n"); - } - } -#endif -#endif -#endif - - } -ok: - switch (fn) - { - case 7: - - // 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances - - // G7TAJ's code to record activity for stats display - - if ( TNC->BusyFlags && CDBusy ) - TNC->PortRecord->PORTCONTROL.ACTIVE += 2; - - if ( TNC->PTTState ) - TNC->PortRecord->PORTCONTROL.SENDING += 2; - - SCSCheckRX(TNC); - SCSPoll(port); - - return 0; - - case 1: // poll - - // Check session limit timer - - if ((STREAM->Connecting || STREAM->Connected) && !STREAM->Disconnecting) - { - if (TNC->SessionTimeLimit && STREAM->ConnectTime && time(NULL) > (TNC->SessionTimeLimit + STREAM->ConnectTime)) - { - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - sprintf(STREAM->CmdSet, "D\r"); - STREAM->Disconnecting = TRUE; - } - } - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->Streams[Stream].ReportDISC) - { - TNC->Streams[Stream].ReportDISC = FALSE; - buff->PORT = Stream; - - return -1; - } - } - - if (TNC->EnterExit) - return 0; // Switching to Term mode to change bandwidth - - for (Stream = 0; Stream <= MaxStreams; Stream++) - { - if (TNC->Streams[Stream].PACTORtoBPQ_Q !=0) - { - int datalen; - - buffptr = Q_REM(&TNC->Streams[Stream].PACTORtoBPQ_Q); - datalen = (int)buffptr->Len; - - buff->PORT = Stream; // Compatibility with Kam Driver - buff->PID = 0xf0; - memcpy(&buff->L2DATA, &buffptr->Data[0], datalen); // Data goes to + 7, but we have an extra byte - datalen += sizeof(void *) + 4; - - PutLengthinBuffer(buff, datalen); - - ReleaseBuffer(buffptr); - - return (1); - } - } - - return 0; - - case 2: // send - - buffptr = GetBuff(); - - if (buffptr == 0) return 0; // No buffers, so ignore - - Stream = buff->PORT; - - if (!TNC->TNCOK) - { - // Send Error Response - - buffptr->Len = sprintf(buffptr->Data, "No Connection to PACTOR TNC\r"); - C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); - - return 0; - } - - txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1); // 1 as no PID - - if (txlen == 1 && buff->L2DATA[0] == 0) // Keepalive Packet - { - ReleaseBuffer(buffptr); - return 0; - } - - buffptr->Len = txlen; - memcpy(buffptr->Data, buff->L2DATA, txlen); - - C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr); - - TNC->Streams[Stream].FramesOutstanding++; - - // See if possible to send immediately - - SCSTryToSendDATA(TNC, Stream); - - return 0; - - case 3: // CHECK IF OK TO SEND. Also used to check if TNC is responding - - Stream = (int)(size_t)buff; - - STREAM = &TNC->Streams[Stream]; - - if (Stream == 0) - { - if (TNC->Dragon) - { - if (STREAM->FramesOutstanding > 25) - return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15); - } - else - { - if (STREAM->FramesOutstanding > 10) - return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15); - } - } - else - { - if (STREAM->FramesOutstanding > 3 || TNC->Buffers < 200) - return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15); } - - return TNC->HostMode << 8 | STREAM->Disconnecting << 15; // OK, but lock attach if disconnecting - - - case 4: // reinit - - // Ensure in Pactor - - TNC->TXBuffer[2] = 31; - TNC->TXBuffer[3] = 0x1; - TNC->TXBuffer[4] = 0x1; - memcpy(&TNC->TXBuffer[5], "PT", 2); - - CRCStuffAndSend(TNC, TNC->TXBuffer, 7); - - Sleep(25); - ExitHost(TNC); - Sleep(50); - CloseCOMPort(TNC->hDevice); - TNC->hDevice =(HANDLE)0; - TNC->ReopenTimer = 250; - TNC->HostMode = FALSE; - - return (0); - - case 5: // Close - - // Ensure in Pactor - - TNC->TXBuffer[2] = 31; - TNC->TXBuffer[3] = 0x1; - TNC->TXBuffer[4] = 0x1; - memcpy(&TNC->TXBuffer[5], "PT", 2); - - CRCStuffAndSend(TNC, TNC->TXBuffer, 7); - - Sleep(25); - - ExitHost(TNC); - - Sleep(25); - - CloseCOMPort(TNCInfo[port]->hDevice); - - return (0); - - case 6: // Scan Interface - - Param = (size_t)buff; - - switch (Param) - { - case 1: // Request Permission - - if (TNC->TNCOK) - { - // If been in Sync a long time, or if using applcalls and - // Scan had been locked too long just let it change - - if (TNC->UseAPPLCallsforPactor) - { - if (TNC->PTCStatus == 6) // Sync - { - int insync = (int)(time(NULL) - TNC->TimeEnteredSYNCMode); - if (insync > 4) - { - Debugprintf("SCS Scan - in SYNC for %d Secs - allow change regardless", insync); - return 0; - } - } - else if (TNC->TimeScanLocked) - { - time_t timeLocked = time(NULL) - TNC->TimeScanLocked; - if (timeLocked > 4) - { - Debugprintf("SCS Scan - Scan Locked for %d Secs - allow change regardless", timeLocked); - TNC->TimeScanLocked = 0; - return 0; - } - } - } - - TNC->WantToChangeFreq = TRUE; - TNC->OKToChangeFreq = FALSE; - return TRUE; - } - return 0; // Don't lock scan if TNC isn't responding - - - case 2: // Check Permission - return TNC->OKToChangeFreq; - - case 3: // Release Permission - - TNC->WantToChangeFreq = FALSE; - - if (TNC->DontReleasePermission) // Disable connects during this interval? - { - TNC->DontReleasePermission = FALSE; - if (TNC->SyncSupported == FALSE) - TNC->TimeScanLocked = time(NULL) + 100; // Make sure doesnt time out - return 0; - } - - TNC->DontWantToChangeFreq = TRUE; - return 0; - - default: // Param is Address of a struct ScanEntry - - Scan = (struct ScanEntry *)buff; - - PLevel = Scan->PMaxLevel; - - if (PLevel == 0 && (Scan->HFPacketMode || Scan->RPacketMode)) - { - // Switch to Packet for this Interval - - if (TNC->RIG->RIG_DEBUG) - Debugprintf("SCS Switching to Packet, %d", TNC->HFPacket); - - if (TNC->HFPacket == FALSE) - SwitchToPacket(TNC); - - return 0; - } - - if (PLevel > '0' && PLevel < '5') // 1 - 4 - { - if (TNC->Bandwidth != PLevel || TNC->MinLevel != (Scan->PMinLevel - '0')) - { - TNC->Bandwidth = PLevel; - TNC->MinLevel = Scan->PMinLevel - '0'; - Switchmode(TNC, PLevel - '0'); - } - - if (TNC->UseAPPLCallsforPactor && Scan->APPLCALL[0]) - { - // Switch callsign - - STREAM = &TNC->Streams[0]; - STREAM->CmdSet = STREAM->CmdSave = malloc(100); - - strcpy(STREAM->MyCall, Scan->APPLCALL); - - sprintf(STREAM->CmdSet, "I%s\rI\r", STREAM->MyCall); - if (TNC->RIG->RIG_DEBUG) - Debugprintf("SCS Pactor APPLCALL Set to %s", STREAM->MyCall); - } - - else - { - if (TNC->HFPacket) - SwitchToPactor(TNC); - } - } - - if (Scan->RPacketMode) - if (TNC->RobustTime) - SwitchToPacket(TNC); // Always start in packet, switch to pactor after RobustTime ticks - - if (PLevel == '0') - TNC->DontReleasePermission = TRUE; // Dont allow connects in this interval - else - TNC->DontReleasePermission = FALSE; - - return 0; - } - } - return 0; -} - -int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len) -{ - struct RIGINFO * RIG = TNC->RIG; - - if (RIG && RIG->WEB_Label) - { - Len += sprintf(&Buff[Len], ""); - Len += sprintf(&Buff[Len], "", RIG->WEB_Label); - Len += sprintf(&Buff[Len], "", RIG->WEB_FREQ); - Len += sprintf(&Buff[Len], "", RIG->WEB_MODE); - Len += sprintf(&Buff[Len], "", RIG->WEB_SCAN); - Len += sprintf(&Buff[Len], "", RIG->WEB_PTT); - - - if (TNC->TXRIG && TNC->TXRIG != TNC->RIG) - { - struct RIGINFO * RIG = TNC->TXRIG; - - Len += sprintf(&Buff[Len], "", RIG->WEB_Label); - Len += sprintf(&Buff[Len], "", RIG->WEB_FREQ); - Len += sprintf(&Buff[Len], "", RIG->WEB_MODE); - Len += sprintf(&Buff[Len], "", RIG->WEB_SCAN); - Len += sprintf(&Buff[Len], "
%s%s%s%c%c
%s%s%s%c%c
", RIG->WEB_PTT); - } - Len += sprintf(&Buff[Len], ""); - } - return Len; -} - -static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL) -{ - int Len = sprintf(Buff, "" - "SCS Pactor Status

SCS Pactor Status

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

\r\n" "Generate Traffic Report

\r\n" "
\r\n" -@@ -1446,7 +1446,7 @@ +@@ -1454,7 +1454,7 @@ "
The Nodes to link to box defines which other Chat Nodes should be connected to, or from which " "connections may be accepted. The format is ALIAS:CALL, eg BPQCHT:G8BPQ-4. If the node is not directly " "connectable (ie is not in your NODES table) you can add a connect script. This consists of a series of commands " diff --git a/debian/rules b/debian/rules index b802fff..acc4edb 100755 --- a/debian/rules +++ b/debian/rules @@ -1,6 +1,6 @@ #!/usr/bin/make -f -#export DEB_BUILD_MAINT_OPTIONS=hardening=+all +export DEB_BUILD_MAINT_OPTIONS=hardening=+all CFLAGS = $(shell dpkg-buildflags --get CFLAGS) CFLAGS += -fcommon diff --git a/templatedefs.c b/templatedefs.c index 94f69e8..b532031 100644 --- a/templatedefs.c +++ b/templatedefs.c @@ -101,7 +101,7 @@ char * FwdPagetxt() "{" "position: absolute;" "width:290px;" - "height:510px;" + "height:550px;" "border:0px solid;" "overflow: auto;" "}" @@ -109,7 +109,7 @@ char * FwdPagetxt() "{" "position: absolute;" "width:180px;" - "height:500px;" + "height:540px;" "border:2px solid;" "overflow: auto;" "}" @@ -118,7 +118,7 @@ char * FwdPagetxt() "position: absolute;" "width:95px;" "left:190px;" - "height:500px;" + "height:540px;" "border:2px solid;" "overflow: auto;" "}" @@ -255,6 +255,7 @@ char * FwdPagetxt() " Welcome Msgs & Prompts" " Housekeeping" " WP Update" + "WebMail" " Node Menu" " " " " @@ -279,7 +280,8 @@ char * FwdPagetxt() "
" "Send P Msgs to more than one BBS 
" "
" - + "Use 4 Char Continent Codes 
" + "
" "Aliases
" "
" "

" @@ -400,6 +402,7 @@ char * WebMailPagetxt() "Auto Refresh\r\n" "Send Message\r\n" "Logout\r\n" + "Mail Mgmt\r\n" "Node Menu\r\n" "
\r\n" "
\r\n" @@ -452,6 +455,7 @@ char * MainConfigtxt() " Welcome Msgs & Prompts\r\n" " Housekeeping\r\n" " WP Update\r\n" + "WebMail" " Node Menu\r\n" "\r\n" "
\r\n" @@ -701,6 +705,7 @@ char * MsgPagetxt() " Welcome Msgs & Prompts\r\n" " Housekeeping\r\n" " WP Update\r\n" + "WebMail" " Node Menu\r\n" " \r\n" " \r\n" @@ -1060,6 +1065,7 @@ char * UserPagetxt() "Welcome Msgs & Prompts\r\n" "Housekeeping\r\n" "WP Update\r\n" + "WebMail" "Node Menu\r\n" "
\r\n" "
\r\n" @@ -1116,6 +1122,7 @@ char * Housekeepingtxt() "Welcome Msgs & Prompts\r\n" "Housekeeping\r\n" "WP Update\r\n" + "WebMail" "Node Menu\r\n" "
\r\n" "
Housekeeping
\r\n" @@ -1364,6 +1371,7 @@ char * WPtxt() " Welcome Msgs & Prompts\r\n" " Housekeeping\r\n" " WP Update\r\n" + "WebMail" " Node Menu\r\n" " \r\n" " \r\n" diff --git a/tncinfo.h b/tncinfo.h index fa8f4c9..bd0639e 100644 --- a/tncinfo.h +++ b/tncinfo.h @@ -225,6 +225,8 @@ struct STREAMINFO char AGWKey[21]; // Session Key for AGW Session Based Drivers time_t ConnectTime; // Time connection made + time_t AttachTime; + int BytesTXed; int BytesAcked; int BytesRXed; @@ -258,6 +260,7 @@ struct STREAMINFO HWND xIDC_DIRN; int RelaySyncStream; + int VaraACMode; }; typedef struct AGWINFO @@ -409,7 +412,7 @@ struct FreeDataINFO char * SSIDS[16]; }; - +struct sixPackInfo; typedef struct TNCINFO { @@ -427,6 +430,9 @@ typedef struct TNCINFO time_t SessionTimeLimit; // Optional limit to total session time time_t DefaultSessionTimeLimit; // Configured value + time_t AttachTimeLimit; // to trap port left attached for a long time without other activity + time_t AttachTime; + int Hardware; // Hardware Type #define H_WINMOR 1 @@ -449,6 +455,7 @@ typedef struct TNCINFO #define H_WINRPR 17 #define H_HSMODEM 18 #define H_FREEDATA 19 +#define H_SIXPACK 20 int Port; // BPQ Port Number @@ -839,6 +846,8 @@ typedef struct TNCINFO char * NRNeighbour; int NRCloseTimer; struct _LINKTABLE * DummyLink; // Simulated link to simplify interface to ax,25 netrom code + struct sixPackPortInfo * sixPack; + int VaraACMode; } *PTNCINFO; diff --git a/upnp.c b/upnp.c index dbc7c8d..96cb9d3 100644 --- a/upnp.c +++ b/upnp.c @@ -85,6 +85,7 @@ char * leaseDuration = NULL; struct UPNPDev * devlist = 0; char lanaddr[64] = "unset"; /* my ip address on the LAN */ +char wanaddr[64] = "unset"; /* my ip address on the LAN */ struct UPNPUrls urls; struct IGDdatas data; @@ -126,7 +127,11 @@ int upnpInit() return 0; } +#if MINIUPNPC_API_VERSION == 18 + i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr)); +#else i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); +#endif } AddMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol); @@ -153,7 +158,11 @@ int upnpClose() return 0; } +#if MINIUPNPC_API_VERSION == 18 + i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), wanaddr, sizeof(wanaddr)); +#else i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); +#endif } DeleteMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);