diff --git a/APRSCode.c b/APRSCode.c
index fea004a..a9af47a 100644
--- a/APRSCode.c
+++ b/APRSCode.c
@@ -1581,9 +1581,9 @@ OK:
// Copy frame to a DIGIMessage Struct
- memcpy(&Msg, monbuff, 21 + (7 * Digis)); // Header, Dest, Source, Addresses and Digis
+ memcpy(&Msg, monbuff, MSGHDDRLEN + 14 + (7 * Digis)); // Header, Dest, Source, Addresses and Digis
- len = Msg.LENGTH - 21 - (7 * Digis); // Payload Length (including CTL and PID
+ len = Msg.LENGTH - (MSGHDDRLEN + 14) - (7 * Digis); // Payload Length (including CTL and PID
memcpy(&Msg.CTL, &AdjBuff->CTL, len);
diff --git a/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user b/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user
new file mode 100644
index 0000000..40182c4
--- /dev/null
+++ b/BPQMail.vcproj.DESKTOP-TGEL8RC.John.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user b/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user
new file mode 100644
index 0000000..40182c4
--- /dev/null
+++ b/BPQWinAPP.vcproj.DESKTOP-TGEL8RC.John.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bpq32.c b/Bpq32.c
index 9d87e34..1df9d34 100644
--- a/Bpq32.c
+++ b/Bpq32.c
@@ -1195,7 +1195,9 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
// Allow zero resptime (send RR immediately) (13)
// Make sure CMD bit is set on UI frames
// Add setting Modem Flags in QtSM AGW mode
-// If FT847 om PTC Port send a "Cat On" command (16)
+// If FT847 om PTC Port send a "Cat On" command (17)
+// Fix some 63 port bugs in RigCOntrol (17)
+// Fix 63 port bug in Bridging (18)
#define CKernel
diff --git a/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user b/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user
new file mode 100644
index 0000000..fdd7820
--- /dev/null
+++ b/CBPQ32.vcproj.DESKTOP-TGEL8RC.John.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/IPCode.c b/IPCode.c
index 8013b61..efc4d91 100644
--- a/IPCode.c
+++ b/IPCode.c
@@ -233,7 +233,7 @@ UCHAR ourMACAddr[6] = {02,'B','P','Q',1,1};
UCHAR RealMacAddress[6];
-int IPPortMask = 0;
+uint64_t IPPortMask = 0;
IPSTATS IPStats = {0};
@@ -1548,7 +1548,8 @@ VOID ProcessEthIPMsg(PETHMSG Buffer)
VOID ProcessEthARPMsg(PETHARP arpptr, BOOL FromTAP)
{
- int i=0, Mask=IPPortMask;
+ int i=0;
+ uint64_t Mask=IPPortMask;
PARPDATA Arp;
PROUTEENTRY Route;
BOOL Found;
@@ -1748,12 +1749,12 @@ ProxyARPReply:
memset(AXARPREQMSG.TARGETHWADDR, 0, 7);
AXARPREQMSG.ARPOPCODE = 0x0100;
- for (i=1; i<=NUMBEROFPORTS; i++)
+ for (i = 1; i <= MaxBPQPortNo; i++)
{
if (Mask & 1)
Send_AX_Datagram((PMESSAGE)&AXARPREQMSG, 46, i, QST);
- Mask>>=1;
+ Mask >>= 1;
}
break;
@@ -1847,7 +1848,8 @@ SendBack:
VOID ProcessAXARPMsg(PAXARP arpptr)
{
- int i=0, Mask=IPPortMask;
+ int i=0;
+ uint64_t Mask=IPPortMask;
PARPDATA Arp;
PROUTEENTRY Route;
@@ -1954,13 +1956,13 @@ AXProxyARPReply:
AXARPREQMSG.TARGETIPADDR = arpptr->TARGETIPADDR;
AXARPREQMSG.SENDIPADDR = arpptr->SENDIPADDR;
- for (i=1; i<=NUMBEROFPORTS; i++)
+ for (i=1; i<=MaxBPQPortNo; i++)
{
if (i != arpptr->MSGHDDR.PORT)
if (Mask & 1)
Send_AX_Datagram((PMESSAGE)&AXARPREQMSG, 46, i, QST);
- Mask>>=1;
+ Mask >>= 1;
}
memset(ETHARPREQMSG.MSGHDDR.DEST, 0xff, 6);
@@ -3281,7 +3283,7 @@ static BOOL ReadConfigFile()
static int ProcessLine(char * buf)
{
- char * ptr, * p_value, * p_origport, * p_host, * p_port;
+ char * ptr, * p_value, * p_origport, * p_host;
int port, mappedport, ipad, mappedipad;
BOOL NATTAP = FALSE;
int i;
@@ -3447,16 +3449,28 @@ static int ProcessLine(char * buf)
if (_stricmp(ptr,"IPPorts") == 0)
{
- p_port = strtok(p_value, " ,\t\n\r");
-
- while (p_port != NULL)
+ struct _EXTPORTDATA * PORTVEC;
+
+ while (p_value != NULL)
{
- i=atoi(p_port);
+ i=atoi(p_value);
if (i == 0) return FALSE;
- if (i > NUMBEROFPORTS) return FALSE;
- IPPortMask |= 1 << (i-1);
- p_port = strtok(NULL, " ,\t\n\r");
+ PORTVEC = (struct _EXTPORTDATA * )GetPortTableEntryFromPortNum(i);
+
+ if (PORTVEC == NULL)
+ return FALSE;
+
+ // if not KISS, make sure it can send UI frames
+
+ if (PORTVEC->PORTCONTROL.PORTTYPE == 16) // EXTERNAL
+ if (PORTVEC->PORTCONTROL.PROTOCOL == 10) // Pactor/WINMOR
+ if (PORTVEC->PORTCONTROL.UICAPABLE == 0)
+ return FALSE;
+
+
+ IPPortMask |= (uint64_t)1 << (i-1);
+ p_value = strlop(p_value, ',');
}
return (TRUE);
}
diff --git a/MailNode.vcproj.DESKTOP-TGEL8RC.John.user b/MailNode.vcproj.DESKTOP-TGEL8RC.John.user
new file mode 100644
index 0000000..40182c4
--- /dev/null
+++ b/MailNode.vcproj.DESKTOP-TGEL8RC.John.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RigControl.c b/RigControl.c
index 77b1ffe..4167cd4 100644
--- a/RigControl.c
+++ b/RigControl.c
@@ -202,7 +202,7 @@ char * RigWebPage = 0;
int RigWebPageLen = 0;
-struct RIGPORTINFO * PORTInfo[34] = {NULL}; // Records are Malloc'd
+struct RIGPORTINFO * PORTInfo[MAXBPQPORTS + 2] = {NULL}; // Records are Malloc'd
struct RIGINFO * DLLRIG = NULL; // Rig record for dll PTT interface (currently only for UZ7HO);
@@ -782,7 +782,7 @@ int Rig_Command(TRANSPORTENTRY * Session, char * Command)
{
RIG = &PORT->Rigs[i];
- if (RIG->BPQPort & (1 << Port))
+ if (RIG->BPQPort & ((uint64_t)1 << Port))
goto portok;
}
}
@@ -2201,12 +2201,12 @@ DllExport BOOL APIENTRY Rig_Init()
NumberofPorts = 0;
- for (port = 0; port < 32; port++)
+ for (port = 0; port < MAXBPQPORTS; port++)
PORTInfo[port] = NULL;
// See if any rigcontrol defined (either RADIO or RIGCONTROL lines)
- for (port = 0; port < 32; port++)
+ for (port = 0; port < MAXBPQPORTS; port++)
{
if (RadioConfigMsg[port])
NeedRig++;
@@ -2362,15 +2362,6 @@ DllExport BOOL APIENTRY Rig_Init()
}
else
PORT->hPTTDevice = PORT->hDevice; // Use same port for PTT
-
-
- // Looks like FT847 Needa a "Cat On" Command. If PTC port need to send it here
-
- if (PORT->PTC && strcmp(PORT->Rigs[0].RigName, "FT847") == 0)
- {
- UCHAR CATON[6] = {0,0,0,0,0};
- SendPTCRadioCommand(PORT->PTC, CATON, 5);
- }
}
for (p = 0; p < NumberofPorts; p++)
@@ -2381,7 +2372,7 @@ DllExport BOOL APIENTRY Rig_Init()
{
int j;
int k = 0;
- int BitMask;
+ uint64_t BitMask;
struct _EXTPORTDATA * PortEntry;
RIG = &PORT->Rigs[i];
@@ -2395,7 +2386,7 @@ DllExport BOOL APIENTRY Rig_Init()
// then those with neither
BitMask = RIG->BPQPort;
- for (j = 0; j < 32; j++)
+ for (j = 0; j < MAXBPQPORTS; j++)
{
if (BitMask & 1)
{
@@ -2408,7 +2399,7 @@ DllExport BOOL APIENTRY Rig_Init()
}
BitMask = RIG->BPQPort;
- for (j = 0; j < 32; j++)
+ for (j = 0; j < MAXBPQPORTS; j++)
{
if (BitMask & 1)
{
@@ -2421,7 +2412,7 @@ DllExport BOOL APIENTRY Rig_Init()
}
BitMask = RIG->BPQPort;
- for (j = 0; j < 32; j++)
+ for (j = 0; j < MAXBPQPORTS; j++)
{
if (BitMask & 1)
{
@@ -3266,7 +3257,7 @@ CheckOtherPorts:
{
PortRecord = RIG->PortRecord[i];
- if (PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 1))
+ if (PortRecord->PORT_EXT_ADDR && PortRecord->PORT_EXT_ADDR(6, PortRecord->PORTCONTROL.PORTNUMBER, 1))
{
// 1 means can't change - release all
@@ -7330,7 +7321,7 @@ VOID SetupScanInterLockGroups(struct RIGINFO *RIG)
if (TNC->RXRadio == Interlock)
{
int p = PortRecord->PORTNUMBER;
- RIG->BPQPort |= (1 << p);
+ RIG->BPQPort |= ((uint64_t)1 << p);
sprintf(PortString, "%s,%d", PortString, p);
TNC->RIG = RIG;
@@ -7340,7 +7331,7 @@ VOID SetupScanInterLockGroups(struct RIGINFO *RIG)
if (TNC->TXRadio == Interlock && TNC->TXRadio != TNC->RXRadio)
{
int p = PortRecord->PORTNUMBER;
- RIG->BPQPort |= (1 << p);
+ RIG->BPQPort |= ((uint64_t)1 << p);
sprintf(TxPortString, "%s,%d", TxPortString, p);
TNC->TXRIG = RIG;
@@ -9912,7 +9903,7 @@ void ProcessSDRANGELFrame(struct RIGPORTINFO * PORT)
// As we mess with the message, save a copy and restore for each Rig
- save = strdup(ptr3);
+ save = _strdup(ptr3);
for (i = 0; i < PORT->ConfiguredRigs; i++)
{
diff --git a/SCSPactor.c b/SCSPactor.c
index eff5512..4ae57be 100644
--- a/SCSPactor.c
+++ b/SCSPactor.c
@@ -122,6 +122,7 @@ 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
@@ -3179,10 +3180,23 @@ VOID ProcessDEDFrame(struct TNCINFO * TNC, UCHAR * Msg, int framelen)
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
+
+ PORT = TNC->RIG->PORT;
+
+ if (PORT->PTC && strcmp(PORT->Rigs[0].RigName, "FT847") == 0)
+ {
+ UCHAR CATON[6] = {0,0,0,0,0};
+ SendPTCRadioCommand(PORT->PTC, CATON, 5);
+ }
+
}
Stream = RealStream = Msg[2];
diff --git a/Versions.h b/Versions.h
index 411efe1..7619958 100644
--- a/Versions.h
+++ b/Versions.h
@@ -10,8 +10,8 @@
#endif
-#define KVers 6,0,24,16
-#define KVerstring "6.0.24.16\0"
+#define KVers 6,0,24,18
+#define KVerstring "6.0.24.18\0"
#ifdef CKernel
diff --git a/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user
new file mode 100644
index 0000000..d4a1f25
--- /dev/null
+++ b/WinRPRHelper.vcproj.DESKTOP-TGEL8RC.John.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user b/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user
new file mode 100644
index 0000000..40182c4
--- /dev/null
+++ b/WinmorControl.vcproj.DESKTOP-TGEL8RC.John.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cMain.c b/cMain.c
index abab877..7ca9e2e 100644
--- a/cMain.c
+++ b/cMain.c
@@ -2213,7 +2213,7 @@ L2Packet:
// Bridge if requested
- for (toPort = 1; toPort <= NUMBEROFPORTS; toPort++)
+ for (toPort = 1; toPort <= MaxBPQPortNo; toPort++)
{
if (BridgeMap[CURRENTPORT][toPort])
{
diff --git a/configstructs.h b/configstructs.h
index 67a6fbf..9dae4fb 100644
--- a/configstructs.h
+++ b/configstructs.h
@@ -158,7 +158,7 @@ struct CONFIGTABLE
char C_IDMSG[512];
char C_CTEXT[512];
char C_INFOMSG[2048];
- UCHAR CfgBridgeMap[MaxBPQPortNo][MaxBPQPortNo];
+ UCHAR CfgBridgeMap[MaxBPQPortNo + 1][MaxBPQPortNo + 1];
struct ROUTECONFIG C_ROUTE[MaxLockedRoutes];
struct APPLCONFIG C_APPL[NumberofAppls];
struct PORTCONFIG C_PORT[MaxBPQPortNo + 4];
diff --git a/rigcontrol.h b/rigcontrol.h
index 2868704..13e0218 100644
--- a/rigcontrol.h
+++ b/rigcontrol.h
@@ -67,7 +67,7 @@ struct RIGINFO
void * BPQtoRADIO_Q; // Frames from switch for radio
- UINT BPQPort; // Port this radio is attached to. Bit Map, as may be more than one port controlling radio
+ uint64_t BPQPort; // Port this radio is attached to. Bit Map, as may be more than one port controlling radio
// int PortNum; // Number of port that defined this rig
int Interlock; // Interlock group for this Radio
int IC735; // Old ICOM with shorter freq message
diff --git a/upnp-DESKTOP-TGEL8RC.c b/upnp-DESKTOP-TGEL8RC.c
new file mode 100644
index 0000000..70a8081
--- /dev/null
+++ b/upnp-DESKTOP-TGEL8RC.c
@@ -0,0 +1,187 @@
+// Includes code from MiniUPnPc, used subject to the following conditions:
+
+/*
+
+MiniUPnPc
+Copyright (c) 2005-2020, Thomas BERNARD
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#define MINIUPNP_STATICLIB
+
+#include
+#ifdef _WIN32
+#include "upnpcommands.h"
+#include "miniupnpc.h"
+#include "upnperrors.h"
+#include
+#else
+#include
+#include
+#include
+#include
+#endif
+
+int AddMap(char * controlURL, char * eport, char * iport, char * proto);
+int DeleteMap(char * controlURL, char * eport, char * iport, char * proto);
+
+void Consoleprintf(const char * format, ...);
+
+struct UPNP
+{
+ struct UPNP * Next;
+ char * Protocol;
+ char * LANport;
+ char * WANPort;
+};
+
+extern struct UPNP * UPNPConfig;
+
+char * controlURL = 0;
+char * servicetype = 0;
+char iaddr[] = "IP";
+char * inClient = NULL;
+#ifdef LINBPQ
+char desc[] = "LinBPQ ";
+#else
+char desc[] = "BPQ32 ";
+#endif
+char * remoteHost = NULL;
+char * leaseDuration = NULL;
+
+struct UPNPDev * devlist = 0;
+char lanaddr[64] = "unset"; /* my ip address on the LAN */
+struct UPNPUrls urls;
+struct IGDdatas data;
+
+int i;
+const char * rootdescurl = 0;
+const char * multicastif = 0;
+const char * minissdpdpath = 0;
+int localport = UPNP_LOCAL_PORT_ANY;
+int retcode = 0;
+int error = 0;
+int ipv6 = 0;
+int ignore = 0;
+unsigned char ttl = 2;
+
+
+int upnpInit()
+{
+ struct UPNP * Config = UPNPConfig;
+ int i;
+#ifdef WIN32
+ WSADATA wsaData;
+ int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+ if(nResult != NO_ERROR)
+ {
+ fprintf(stderr, "WSAStartup() failed.\n");
+ return -1;
+ }
+#endif
+
+ while (Config)
+ {
+ if (devlist == NULL)
+ {
+ devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
+
+ if (devlist == NULL)
+ {
+ Consoleprintf("Failed to find a UPNP device");
+ return 0;
+ }
+
+ i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
+ }
+
+ AddMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
+ Config = Config->Next;
+ }
+
+ return 0;
+}
+
+int upnpClose()
+{
+ struct UPNP * Config = UPNPConfig;
+ int i;
+
+ while (Config)
+ {
+ if (devlist == NULL)
+ {
+ devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
+
+ if (devlist == NULL)
+ {
+ Consoleprintf("Failed to find a UPNP device");
+ return 0;
+ }
+
+ i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
+ }
+
+ DeleteMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
+ Config = Config->Next;
+ }
+
+ return 0;
+}
+
+int AddMap(char * controlURL, char * eport, char * iport, char * proto)
+{
+ int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
+ eport, iport, lanaddr, desc,
+ proto, remoteHost, leaseDuration);
+
+ if (r != UPNPCOMMAND_SUCCESS)
+ {
+ Consoleprintf("UPNP AddPortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
+ return -2;
+ }
+ Consoleprintf("UPNP AddPortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
+ return 0;
+}
+
+int DeleteMap(char * controlURL, char * eport, char * iport, char * proto)
+{
+ int r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport, proto, remoteHost);
+
+ if(r != UPNPCOMMAND_SUCCESS)
+ {
+ Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
+ return -2;
+ }
+ Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
+
+ return 0;
+}
+
+
+
+
diff --git a/upnp.c b/upnp.c
index cdc68a4..6299446 100644
--- a/upnp.c
+++ b/upnp.c
@@ -39,13 +39,21 @@ POSSIBILITY OF SUCH DAMAGE.
#include "miniupnpc.h"
#include "upnperrors.h"
#include
-#else
+#endif
+#ifdef LINBPQ
+#ifndef MACBPQ
#include
#include
#include
#include
#endif
-
+#endif
+#ifdef MACBPQ
+#include
+#include
+#include
+#include
+#endif
int AddMap(char * controlURL, char * eport, char * iport, char * proto);
int DeleteMap(char * controlURL, char * eport, char * iport, char * proto);
diff --git a/upnp.c.bak b/upnp.c.bak
new file mode 100644
index 0000000..cdc68a4
--- /dev/null
+++ b/upnp.c.bak
@@ -0,0 +1,187 @@
+// Includes code from MiniUPnPc, used subject to the following conditions:
+
+/*
+
+MiniUPnPc
+Copyright (c) 2005-2020, Thomas BERNARD
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#define MINIUPNP_STATICLIB
+
+#include
+#ifdef _WIN32
+#include "upnpcommands.h"
+#include "miniupnpc.h"
+#include "upnperrors.h"
+#include
+#else
+#include
+#include
+#include
+#include
+#endif
+
+int AddMap(char * controlURL, char * eport, char * iport, char * proto);
+int DeleteMap(char * controlURL, char * eport, char * iport, char * proto);
+
+void Consoleprintf(const char * format, ...);
+
+struct UPNP
+{
+ struct UPNP * Next;
+ char * Protocol;
+ char * LANport;
+ char * WANPort;
+};
+
+extern struct UPNP * UPNPConfig;
+
+char * controlURL = 0;
+char * servicetype = 0;
+char iaddr[] = "IP";
+char * inClient = NULL;
+#ifdef LINBPQ
+char desc[] = "LinBPQ ";
+#else
+char desc[] = "BPQ32 ";
+#endif
+char * remoteHost = NULL;
+char * leaseDuration = NULL;
+
+struct UPNPDev * devlist = 0;
+char lanaddr[64] = "unset"; /* my ip address on the LAN */
+struct UPNPUrls urls;
+struct IGDdatas data;
+
+int i;
+const char * rootdescurl = 0;
+const char * multicastif = 0;
+const char * minissdpdpath = 0;
+int localport = UPNP_LOCAL_PORT_ANY;
+int retcode = 0;
+int error = 0;
+int ipv6 = 0;
+int ignore = 0;
+unsigned char ttl = 2;
+
+
+int upnpInit()
+{
+ struct UPNP * Config = UPNPConfig;
+ int i;
+#ifdef WIN32
+ WSADATA wsaData;
+ int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+ if(nResult != NO_ERROR)
+ {
+ fprintf(stderr, "WSAStartup() failed.\n");
+ return -1;
+ }
+#endif
+
+ while (Config)
+ {
+ if (devlist == NULL)
+ {
+ devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
+
+ if (devlist == NULL)
+ {
+ Consoleprintf("Failed to find a UPNP device");
+ return 0;
+ }
+
+ i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
+ }
+
+ AddMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
+ Config = Config->Next;
+ }
+
+ return 0;
+}
+
+int upnpClose()
+{
+ struct UPNP * Config = UPNPConfig;
+ int i;
+
+ while (Config)
+ {
+ if (devlist == NULL)
+ {
+ devlist = upnpDiscover(2000, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
+
+ if (devlist == NULL)
+ {
+ Consoleprintf("Failed to find a UPNP device");
+ return 0;
+ }
+
+ i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
+ }
+
+ DeleteMap(devlist->descURL, Config->LANport, Config->WANPort, Config->Protocol);
+ Config = Config->Next;
+ }
+
+ return 0;
+}
+
+int AddMap(char * controlURL, char * eport, char * iport, char * proto)
+{
+ int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
+ eport, iport, lanaddr, desc,
+ proto, remoteHost, leaseDuration);
+
+ if (r != UPNPCOMMAND_SUCCESS)
+ {
+ Consoleprintf("UPNP AddPortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
+ return -2;
+ }
+ Consoleprintf("UPNP AddPortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
+ return 0;
+}
+
+int DeleteMap(char * controlURL, char * eport, char * iport, char * proto)
+{
+ int r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport, proto, remoteHost);
+
+ if(r != UPNPCOMMAND_SUCCESS)
+ {
+ Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) failed with code %d (%s)", eport, iport, lanaddr, r, strupnperror(r));
+ return -2;
+ }
+ Consoleprintf("UPNP DeletePortMapping(%s, %s, %s) Succeeded", eport, iport, lanaddr, r);
+
+ return 0;
+}
+
+
+
+