/libretroshare/src/upnp/upnputil.c
C | 589 lines | 451 code | 33 blank | 105 comment | 65 complexity | bc023cd5b519c5592cf400b17685bb2b MD5 | raw file
Possible License(s): 0BSD, GPL-2.0, AGPL-1.0
- //this file uses miniupnp
- //From https://github.com/miniupnp/miniupnp/blob/master/miniupnpc/upnpc.c
- #include "upnp/upnputil.h"
- #if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18
- #include <time.h>
- #endif
- /* protofix() checks if protocol is "UDP" or "TCP"
- * returns NULL if not */
- const char * protofix(const char * proto)
- {
- static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
- static const char proto_udp[4] = { 'U', 'D', 'P', 0};
- int i, b;
- for(i=0, b=1; i<4; i++)
- b = b && ( (proto[i] == proto_tcp[i])
- || (proto[i] == (proto_tcp[i] | 32)) );
- if(b)
- return proto_tcp;
- for(i=0, b=1; i<4; i++)
- b = b && ( (proto[i] == proto_udp[i])
- || (proto[i] == (proto_udp[i] | 32)) );
- if(b)
- return proto_udp;
- return 0;
- }
- void DisplayInfos(struct UPNPUrls * urls,
- struct IGDdatas * data)
- {
- char externalIPAddress[40];
- char connectionType[64];
- char status[64];
- char lastconnerr[64];
- unsigned int uptime;
- unsigned int brUp, brDown;
- time_t timenow, timestarted;
- int r;
- #if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
- const char * servicetype = data->first.servicetype;
- const char * servicetype_CIF = data->CIF.servicetype;
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- const char * servicetype = data->servicetype;
- const char * servicetype_CIF = data->servicetype_CIF;
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif//>=-7
- #endif//>=-2
- #if MINIUPNPC_API_VERSION >= -3//1.0 2009/04/17
- if(UPNP_GetConnectionTypeInfo(urls->controlURL,
- servicetype,
- connectionType) != UPNPCOMMAND_SUCCESS)
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- UPNP_GetConnectionTypeInfo(urls->controlURL, servicetype,
- connectionType);
- if(connectionType[0])
- #endif//>=-7
- #endif//>=-3
- printf("GetConnectionTypeInfo failed.\n");
- else
- printf("Connection Type : %s\n", connectionType);
- #if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18
- if(UPNP_GetStatusInfo(urls->controlURL, servicetype,
- status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
- printf("GetStatusInfo failed.\n");
- else
- printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
- status, uptime, lastconnerr);
- timenow = time(NULL);
- timestarted = timenow - uptime;
- printf(" Time started : %s", ctime(×tarted));
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- UPNP_GetStatusInfo(urls->controlURL, servicetype,
- status, &uptime, lastconnerr);
- printf("Status : %s, uptime=%u, LastConnectionError : %s\n",
- status, uptime, lastconnerr);
- #endif//>=-7
- #endif//>=-4
- #if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18
- if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, servicetype_CIF,
- &brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
- printf("GetLinkLayerMaxBitRates failed.\n");
- } else {
- printf("MaxBitRateDown : %u bps", brDown);
- if(brDown >= 1000000) {
- printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
- } else if(brDown >= 1000) {
- printf(" (%u Kbps)", brDown / 1000);
- }
- printf(" MaxBitRateUp %u bps", brUp);
- if(brUp >= 1000000) {
- printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
- } else if(brUp >= 1000) {
- printf(" (%u Kbps)", brUp / 1000);
- }
- printf("\n");
- }
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF,
- servicetype_CIF,
- &brDown, &brUp);
- printf("MaxBitRateDown : %u bps MaxBitRateUp %u bps\n", brDown, brUp);
- #endif//>=-7
- #endif//>=-4
- #if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19
- r = UPNP_GetExternalIPAddress(urls->controlURL,
- servicetype,
- externalIPAddress);
- if(r != UPNPCOMMAND_SUCCESS) {
- printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
- } else {
- printf("ExternalIPAddress = %s\n", externalIPAddress);
- }
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- UPNP_GetExternalIPAddress(urls->controlURL,
- servicetype,
- externalIPAddress);
- if(externalIPAddress[0])
- printf("ExternalIPAddress = %s\n", externalIPAddress);
- else
- printf("GetExternalIPAddress failed.\n");
- #endif//>=-7
- #endif//>=-4
- }
- void GetConnectionStatus(struct UPNPUrls * urls,
- struct IGDdatas * data)
- {
- unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
- #if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
- const char * servicetype_CIF = data->CIF.servicetype;
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- const char * servicetype_CIF = data->servicetype_CIF;
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif//>=-7
- #endif//>=-2
- DisplayInfos(urls, data);
- bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, servicetype_CIF);
- bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, servicetype_CIF);
- packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, servicetype_CIF);
- packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, servicetype_CIF);
- printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
- printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
- }
- void ListRedirections(struct UPNPUrls * urls,
- struct IGDdatas * data)
- {
- int r;
- int i = 0;
- char index[6];
- char intClient[40];
- char intPort[6];
- char extPort[6];
- char protocol[4];
- char desc[80];
- char enabled[6];
- char rHost[64];
- char duration[16];
- #if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
- const char * servicetype = data->first.servicetype;
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- const char * servicetype = data->servicetype;
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif//>=-7
- #endif//>=-2
- /*unsigned int num=0;
- UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
- printf("PortMappingNumberOfEntries : %u\n", num);*/
- do {
- snprintf(index, 6, "%d", i);
- rHost[0] = '\0'; enabled[0] = '\0';
- duration[0] = '\0'; desc[0] = '\0';
- extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
- r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
- servicetype,
- index,
- extPort, intClient, intPort,
- protocol, desc, enabled,
- rHost, duration);
- if(r==0)
- printf("%02d - %s %5s->%s:%-5s"
- "\tenabled=%s leaseDuration=%s\n"
- " desc='%s' rHost='%s'\n",
- i, protocol, extPort, intClient, intPort,
- enabled, duration,
- desc, rHost);
- else
- printf("GetGenericPortMappingEntry() returned %d (%s)\n",
- r, strupnperror(r));
- i++;
- } while(r==0);
- }
- /* Test function
- * 1 - get connection type
- * 2 - get extenal ip address
- * 3 - Add port mapping
- * 4 - get this port mapping from the IGD */
- int SetRedirectAndTest(struct UPNPUrls * urls,
- struct IGDdatas * data,
- const char * iaddr,
- const char * iport,
- const char * eport,
- const char * proto,
- const char * leaseDuration,
- const char * description,
- int addAny)
- {
- char externalIPAddress[40];
- char intClient[40];
- char intPort[6];
- char reservedPort[6];
- char duration[16];
- int r;
- int ok = 1;
- #if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
- const char * servicetype = data->first.servicetype;
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- const char * servicetype = data->servicetype;
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif
- #endif
- if(!iaddr || !iport || !eport || !proto)
- {
- fprintf(stderr, "Wrong arguments\n");
- return 0;
- }
- proto = protofix(proto);
- if(!proto)
- {
- fprintf(stderr, "invalid protocol\n");
- return 0;
- }
- #if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19
- r = UPNP_GetExternalIPAddress(urls->controlURL,
- servicetype,
- externalIPAddress);
- if(r != UPNPCOMMAND_SUCCESS)
- printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
- else
- printf("ExternalIPAddress = %s\n", externalIPAddress);
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- UPNP_GetExternalIPAddress(urls->controlURL,
- servicetype,
- externalIPAddress);
- if(externalIPAddress[0])
- printf("ExternalIPAddress = %s\n", externalIPAddress);
- else
- printf("GetExternalIPAddress failed.\n");
- #endif//>=-7
- #endif//>=-4
- #if MINIUPNPC_API_VERSION >= 11
- if (addAny) {
- r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
- eport, iport, iaddr, description,
- proto, 0, leaseDuration, reservedPort);
- if(r==UPNPCOMMAND_SUCCESS)
- eport = reservedPort;
- else
- printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
- eport, iport, iaddr, r, strupnperror(r));
- } else
- #endif
- {
- #if MINIUPNPC_API_VERSION >= -1
- /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */
- //UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
- // const char * extPort,
- // const char * inPort,
- // const char * inClient,
- // const char * desc,
- // const char * proto,
- // const char * remoteHost,
- // const char * leaseDuration);
- r = UPNP_AddPortMapping(urls->controlURL, servicetype,
- eport, iport, iaddr, NULL, proto, NULL, NULL);
- #else
- #if MINIUPNPC_API_VERSION >= -3 //1.0 2009/04/17
- /* $Id: upnpcommands.h,v 1.18 2010/06/09 10:59:09 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */
- //UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
- // const char * extPort,
- // const char * inPort,
- // const char * inClient,
- // const char * desc,
- // const char * proto,
- // const char * remoteHost);
- r = UPNP_AddPortMapping(urls->controlURL, servicetype,
- eport, iport, iaddr, NULL, proto, NULL);
- #else
- #if MINIUPNPC_API_VERSION >= -7//Before 1.0
- /* $Id: upnpcommands.h,v 1.14 2008/09/25 18:02:50 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */
- //UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
- // const char * extPort,
- // const char * inPort,
- // const char * inClient,
- // const char * desc,
- // const char * proto);
- r = UPNP_AddPortMapping(urls->controlURL, servicetype,
- eport, iport, iaddr, NULL, proto);
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif//>=-7
- #endif//>=-3
- #endif//>=-1
- #if MINIUPNPC_API_VERSION >= -5//2007/12/19
- if(r!=UPNPCOMMAND_SUCCESS){
- #else
- #if MINIUPNPC_API_VERSION >= -7//Before 1.0
- if(r==0){
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif//>=-7
- #endif//>=-5
- printf("AddPortMapping(%s, %s, %s) failed and returns %d\n", eport, iport, iaddr, r);
- //this seems to trigger for unknown reasons sometimes.
- //rely on Checking it afterwards...
- //should check IP address then!
- ok = 0;
- }
- }
- #if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04
- /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */
- //UPNP_GetSpecificPortMappingEntry(const char * controlURL,
- // const char * servicetype,
- // const char * extPort,
- // const char * proto,
- // const char * remoteHost,
- // char * intClient,
- // char * intPort,
- // char * desc,
- // char * enabled,
- // char * leaseDuration);
- r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
- data->first.servicetype,
- eport, proto, NULL/*remoteHost*/,
- intClient, intPort, NULL/*desc*/,
- NULL/*enabled*/, duration);
- #else
- #if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04
- /* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */
- //UPNP_GetSpecificPortMappingEntry(const char * controlURL,
- // const char * servicetype,
- // const char * extPort,
- // const char * proto,
- // char * intClient,
- // char * intPort,
- // char * desc,
- // char * enabled,
- // char * leaseDuration);
- r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
- data->first.servicetype,
- eport, proto,
- intClient, intPort, NULL/*desc*/,
- NULL/*enabled*/, duration);
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */
- //UPNP_GetSpecificPortMappingEntry(const char * controlURL,
- // const char * servicetype,
- // const char * extPort,
- // const char * proto,
- // char * intClient,
- // char * intPort);
- UPNP_GetSpecificPortMappingEntry(urls->controlURL,
- servicetype,
- eport,
- proto,
- intClient,
- intPort);
- if(intClient[0]) r = UPNPCOMMAND_SUCCESS;
- #endif//>=-7
- #endif//>=6
- #endif//>=10
- if(r!=UPNPCOMMAND_SUCCESS) {
- printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
- r, strupnperror(r));
- ok = 0;
- } else if(intClient[0]) {
- printf("InternalIP:Port = %s:%s\n", intClient, intPort);
- printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
- externalIPAddress, eport, proto, intClient, intPort, duration);
- }
- if ((strcmp(iaddr, intClient) != 0) || (strcmp(iport, intPort) != 0))
- {
- printf("PortMappingEntry to wrong location! FAILED\n");
- printf("IP1:\"%s\"\n", iaddr);
- printf("IP2:\"%s\"\n", intClient);
- printf("PORT1:\"%s\"\n", iport);
- printf("PORT2:\"%s\"\n", intPort);
- ok = 0;
- }
- if (ok)
- {
- printf("uPnP Forward/Mapping Succeeded\n");
- }
- else
- {
- printf("uPnP Forward/Mapping Failed\n");
- }
- return ok;
- }
- int TestRedirect(struct UPNPUrls * urls,
- struct IGDdatas * data,
- const char * iaddr,
- const char * iport,
- const char * eport,
- const char * proto)
- {
- char externalIPAddress[40];
- char intClient[40];
- char intPort[6];
- char duration[16];
- int r = 0;
- int ok = 1;
- if(!iaddr || !iport || !eport || !proto)
- {
- fprintf(stderr, "Wrong arguments\n");
- return 0;
- }
- proto = protofix(proto);
- if(!proto)
- {
- fprintf(stderr, "invalid protocol\n");
- return 0;
- }
- #if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
- const char * servicetype = data->first.servicetype;
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- const char * servicetype = data->servicetype;
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif
- #endif
- #if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04
- /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */
- //UPNP_GetSpecificPortMappingEntry(const char * controlURL,
- // const char * servicetype,
- // const char * extPort,
- // const char * proto,
- // const char * remoteHost,
- // char * intClient,
- // char * intPort,
- // char * desc,
- // char * enabled,
- // char * leaseDuration);
- r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
- servicetype,
- eport, proto, NULL/*remoteHost*/,
- intClient, intPort, NULL/*desc*/,
- NULL/*enabled*/, duration);
- #else
- #if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04
- /* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */
- //UPNP_GetSpecificPortMappingEntry(const char * controlURL,
- // const char * servicetype,
- // const char * extPort,
- // const char * proto,
- // char * intClient,
- // char * intPort,
- // char * desc,
- // char * enabled,
- // char * leaseDuration);
- r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
- servicetype,
- eport, proto,
- intClient, intPort, NULL/*desc*/,
- NULL/*enabled*/, duration);
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */
- /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */
- //UPNP_GetSpecificPortMappingEntry(const char * controlURL,
- // const char * servicetype,
- // const char * extPort,
- // const char * proto,
- // char * intClient,
- // char * intPort);
- UPNP_GetSpecificPortMappingEntry(urls->controlURL,
- servicetype,
- eport,
- proto,
- intClient,
- intPort);
- if(intClient[0]) r = UPNPCOMMAND_SUCCESS;
- #endif//>=-7
- #endif//>=6
- #endif//>=10
- if(r!=UPNPCOMMAND_SUCCESS) {
- printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
- r, strupnperror(r));
- ok = 0;
- } else if(intClient[0]) {
- printf("uPnP Check: InternalIP:Port = %s:%s\n", intClient, intPort);
- printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
- externalIPAddress, eport, proto, intClient, intPort, duration);
- }
- if (ok)
- {
- printf("uPnP Check: uPnP Forward/Mapping still Active\n");
- }
- else
- {
- printf("uPnP Check: Forward/Mapping has been Dropped\n");
- }
- return ok;
- }
- int
- RemoveRedirect(struct UPNPUrls * urls,
- struct IGDdatas * data,
- const char * eport,
- const char * proto)
- {
- if(!proto || !eport)
- {
- fprintf(stderr, "invalid arguments\n");
- return 0;
- }
- proto = protofix(proto);
- if(!proto)
- {
- fprintf(stderr, "protocol invalid\n");
- return 0;
- }
- #if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09
- UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, NULL);
- #else
- #if MINIUPNPC_API_VERSION >= -3//1.3 2009/04/17
- UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto, NULL);
- #else
- #if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04
- UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto);
- #else
- #error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version
- #endif//>= -7
- #endif//>= -3
- #endif//>= -2
- return 1;
- }
- /* EOF */